Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cris-mirror.git] / drivers / crypto / inside-secure / safexcel_ring.c
blobc9d2a8716b5b1059c502a0aa7680115e19f6ecff
1 /*
2 * Copyright (C) 2017 Marvell
4 * Antoine Tenart <antoine.tenart@free-electrons.com>
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
11 #include <linux/dma-mapping.h>
12 #include <linux/spinlock.h>
14 #include "safexcel.h"
16 int safexcel_init_ring_descriptors(struct safexcel_crypto_priv *priv,
17 struct safexcel_ring *cdr,
18 struct safexcel_ring *rdr)
20 cdr->offset = sizeof(u32) * priv->config.cd_offset;
21 cdr->base = dmam_alloc_coherent(priv->dev,
22 cdr->offset * EIP197_DEFAULT_RING_SIZE,
23 &cdr->base_dma, GFP_KERNEL);
24 if (!cdr->base)
25 return -ENOMEM;
26 cdr->write = cdr->base;
27 cdr->base_end = cdr->base + cdr->offset * EIP197_DEFAULT_RING_SIZE;
28 cdr->read = cdr->base;
30 rdr->offset = sizeof(u32) * priv->config.rd_offset;
31 rdr->base = dmam_alloc_coherent(priv->dev,
32 rdr->offset * EIP197_DEFAULT_RING_SIZE,
33 &rdr->base_dma, GFP_KERNEL);
34 if (!rdr->base)
35 return -ENOMEM;
36 rdr->write = rdr->base;
37 rdr->base_end = rdr->base + rdr->offset * EIP197_DEFAULT_RING_SIZE;
38 rdr->read = rdr->base;
40 return 0;
43 inline int safexcel_select_ring(struct safexcel_crypto_priv *priv)
45 return (atomic_inc_return(&priv->ring_used) % priv->config.rings);
48 static void *safexcel_ring_next_wptr(struct safexcel_crypto_priv *priv,
49 struct safexcel_ring *ring)
51 void *ptr = ring->write;
53 if (ring->nr == EIP197_DEFAULT_RING_SIZE - 1)
54 return ERR_PTR(-ENOMEM);
56 ring->write += ring->offset;
57 if (ring->write == ring->base_end)
58 ring->write = ring->base;
60 ring->nr++;
61 return ptr;
64 void *safexcel_ring_next_rptr(struct safexcel_crypto_priv *priv,
65 struct safexcel_ring *ring)
67 void *ptr = ring->read;
69 if (!ring->nr)
70 return ERR_PTR(-ENOENT);
72 ring->read += ring->offset;
73 if (ring->read == ring->base_end)
74 ring->read = ring->base;
76 ring->nr--;
77 return ptr;
80 void safexcel_ring_rollback_wptr(struct safexcel_crypto_priv *priv,
81 struct safexcel_ring *ring)
83 if (!ring->nr)
84 return;
86 if (ring->write == ring->base)
87 ring->write = ring->base_end - ring->offset;
88 else
89 ring->write -= ring->offset;
91 ring->nr--;
94 struct safexcel_command_desc *safexcel_add_cdesc(struct safexcel_crypto_priv *priv,
95 int ring_id,
96 bool first, bool last,
97 dma_addr_t data, u32 data_len,
98 u32 full_data_len,
99 dma_addr_t context) {
100 struct safexcel_command_desc *cdesc;
101 int i;
103 cdesc = safexcel_ring_next_wptr(priv, &priv->ring[ring_id].cdr);
104 if (IS_ERR(cdesc))
105 return cdesc;
107 memset(cdesc, 0, sizeof(struct safexcel_command_desc));
109 cdesc->first_seg = first;
110 cdesc->last_seg = last;
111 cdesc->particle_size = data_len;
112 cdesc->data_lo = lower_32_bits(data);
113 cdesc->data_hi = upper_32_bits(data);
115 if (first && context) {
116 struct safexcel_token *token =
117 (struct safexcel_token *)cdesc->control_data.token;
119 cdesc->control_data.packet_length = full_data_len;
120 cdesc->control_data.options = EIP197_OPTION_MAGIC_VALUE |
121 EIP197_OPTION_64BIT_CTX |
122 EIP197_OPTION_CTX_CTRL_IN_CMD;
123 cdesc->control_data.context_lo =
124 (lower_32_bits(context) & GENMASK(31, 2)) >> 2;
125 cdesc->control_data.context_hi = upper_32_bits(context);
127 /* TODO: large xform HMAC with SHA-384/512 uses refresh = 3 */
128 cdesc->control_data.refresh = 2;
130 for (i = 0; i < EIP197_MAX_TOKENS; i++)
131 eip197_noop_token(&token[i]);
134 return cdesc;
137 struct safexcel_result_desc *safexcel_add_rdesc(struct safexcel_crypto_priv *priv,
138 int ring_id,
139 bool first, bool last,
140 dma_addr_t data, u32 len)
142 struct safexcel_result_desc *rdesc;
144 rdesc = safexcel_ring_next_wptr(priv, &priv->ring[ring_id].rdr);
145 if (IS_ERR(rdesc))
146 return rdesc;
148 memset(rdesc, 0, sizeof(struct safexcel_result_desc));
150 rdesc->first_seg = first;
151 rdesc->last_seg = last;
152 rdesc->particle_size = len;
153 rdesc->data_lo = lower_32_bits(data);
154 rdesc->data_hi = upper_32_bits(data);
156 return rdesc;