123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- /*
- * 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_ring *cdr,
- struct safexcel_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;
- 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;
- 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_ring *ring)
- {
- void *ptr = ring->write;
- if (ring->nr == EIP197_DEFAULT_RING_SIZE - 1)
- return ERR_PTR(-ENOMEM);
- ring->write += ring->offset;
- if (ring->write == ring->base_end)
- ring->write = ring->base;
- ring->nr++;
- return ptr;
- }
- void *safexcel_ring_next_rptr(struct safexcel_crypto_priv *priv,
- struct safexcel_ring *ring)
- {
- void *ptr = ring->read;
- if (!ring->nr)
- return ERR_PTR(-ENOENT);
- ring->read += ring->offset;
- if (ring->read == ring->base_end)
- ring->read = ring->base;
- ring->nr--;
- return ptr;
- }
- void safexcel_ring_rollback_wptr(struct safexcel_crypto_priv *priv,
- struct safexcel_ring *ring)
- {
- if (!ring->nr)
- return;
- if (ring->write == ring->base)
- ring->write = ring->base_end - ring->offset;
- else
- ring->write -= ring->offset;
- ring->nr--;
- }
- 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;
- }
|