linux_dsm_epyc7002/drivers/crypto/inside-secure/safexcel_ring.c
Ofer Heifetz 9744fec95f crypto: inside-secure - remove request list to improve performance
This patch main goal is to improve driver performance by moving the
crypto request from a list to a RDR ring shadow.

This is possible since there is one producer and one consume for this
RDR request shadow and one ring descriptor is left unused.
Doing this change eliminates the use of spinlock when accessing the
descriptor ring and the need to dynamicaly allocate memory per crypto
request.

The crypto request is placed in the first RDR shadow descriptor only
if there are enough descriptors, when the result handler is invoked,
it fetches the first result descriptor from RDR shadow.

Signed-off-by: Ofer Heifetz <oferh@marvell.com>
Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2018-07-09 00:30:19 +08:00

182 lines
4.6 KiB
C

/*
* Copyright (C) 2017 Marvell
*
* Antoine Tenart <antoine.tenart@free-electrons.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
#include "safexcel.h"
int safexcel_init_ring_descriptors(struct safexcel_crypto_priv *priv,
struct safexcel_desc_ring *cdr,
struct safexcel_desc_ring *rdr)
{
cdr->offset = sizeof(u32) * priv->config.cd_offset;
cdr->base = dmam_alloc_coherent(priv->dev,
cdr->offset * EIP197_DEFAULT_RING_SIZE,
&cdr->base_dma, GFP_KERNEL);
if (!cdr->base)
return -ENOMEM;
cdr->write = cdr->base;
cdr->base_end = cdr->base + cdr->offset * (EIP197_DEFAULT_RING_SIZE - 1);
cdr->read = cdr->base;
rdr->offset = sizeof(u32) * priv->config.rd_offset;
rdr->base = dmam_alloc_coherent(priv->dev,
rdr->offset * EIP197_DEFAULT_RING_SIZE,
&rdr->base_dma, GFP_KERNEL);
if (!rdr->base)
return -ENOMEM;
rdr->write = rdr->base;
rdr->base_end = rdr->base + rdr->offset * (EIP197_DEFAULT_RING_SIZE - 1);
rdr->read = rdr->base;
return 0;
}
inline int safexcel_select_ring(struct safexcel_crypto_priv *priv)
{
return (atomic_inc_return(&priv->ring_used) % priv->config.rings);
}
static void *safexcel_ring_next_wptr(struct safexcel_crypto_priv *priv,
struct safexcel_desc_ring *ring)
{
void *ptr = ring->write;
if ((ring->write == ring->read - ring->offset) ||
(ring->read == ring->base && ring->write == ring->base_end))
return ERR_PTR(-ENOMEM);
if (ring->write == ring->base_end)
ring->write = ring->base;
else
ring->write += ring->offset;
return ptr;
}
void *safexcel_ring_next_rptr(struct safexcel_crypto_priv *priv,
struct safexcel_desc_ring *ring)
{
void *ptr = ring->read;
if (ring->write == ring->read)
return ERR_PTR(-ENOENT);
if (ring->read == ring->base_end)
ring->read = ring->base;
else
ring->read += ring->offset;
return ptr;
}
inline void *safexcel_ring_curr_rptr(struct safexcel_crypto_priv *priv,
int ring)
{
struct safexcel_desc_ring *rdr = &priv->ring[ring].rdr;
return rdr->read;
}
inline int safexcel_ring_first_rdr_index(struct safexcel_crypto_priv *priv,
int ring)
{
struct safexcel_desc_ring *rdr = &priv->ring[ring].rdr;
return (rdr->read - rdr->base) / rdr->offset;
}
inline int safexcel_ring_rdr_rdesc_index(struct safexcel_crypto_priv *priv,
int ring,
struct safexcel_result_desc *rdesc)
{
struct safexcel_desc_ring *rdr = &priv->ring[ring].rdr;
return ((void *)rdesc - rdr->base) / rdr->offset;
}
void safexcel_ring_rollback_wptr(struct safexcel_crypto_priv *priv,
struct safexcel_desc_ring *ring)
{
if (ring->write == ring->read)
return;
if (ring->write == ring->base)
ring->write = ring->base_end;
else
ring->write -= ring->offset;
}
struct safexcel_command_desc *safexcel_add_cdesc(struct safexcel_crypto_priv *priv,
int ring_id,
bool first, bool last,
dma_addr_t data, u32 data_len,
u32 full_data_len,
dma_addr_t context) {
struct safexcel_command_desc *cdesc;
int i;
cdesc = safexcel_ring_next_wptr(priv, &priv->ring[ring_id].cdr);
if (IS_ERR(cdesc))
return cdesc;
memset(cdesc, 0, sizeof(struct safexcel_command_desc));
cdesc->first_seg = first;
cdesc->last_seg = last;
cdesc->particle_size = data_len;
cdesc->data_lo = lower_32_bits(data);
cdesc->data_hi = upper_32_bits(data);
if (first && context) {
struct safexcel_token *token =
(struct safexcel_token *)cdesc->control_data.token;
cdesc->control_data.packet_length = full_data_len;
cdesc->control_data.options = EIP197_OPTION_MAGIC_VALUE |
EIP197_OPTION_64BIT_CTX |
EIP197_OPTION_CTX_CTRL_IN_CMD;
cdesc->control_data.context_lo =
(lower_32_bits(context) & GENMASK(31, 2)) >> 2;
cdesc->control_data.context_hi = upper_32_bits(context);
/* TODO: large xform HMAC with SHA-384/512 uses refresh = 3 */
cdesc->control_data.refresh = 2;
for (i = 0; i < EIP197_MAX_TOKENS; i++)
eip197_noop_token(&token[i]);
}
return cdesc;
}
struct safexcel_result_desc *safexcel_add_rdesc(struct safexcel_crypto_priv *priv,
int ring_id,
bool first, bool last,
dma_addr_t data, u32 len)
{
struct safexcel_result_desc *rdesc;
rdesc = safexcel_ring_next_wptr(priv, &priv->ring[ring_id].rdr);
if (IS_ERR(rdesc))
return rdesc;
memset(rdesc, 0, sizeof(struct safexcel_result_desc));
rdesc->first_seg = first;
rdesc->last_seg = last;
rdesc->particle_size = len;
rdesc->data_lo = lower_32_bits(data);
rdesc->data_hi = upper_32_bits(data);
return rdesc;
}