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.
11 #include <linux/dma-mapping.h>
12 #include <linux/spinlock.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
);
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
);
36 rdr
->write
= rdr
->base
;
37 rdr
->base_end
= rdr
->base
+ rdr
->offset
* EIP197_DEFAULT_RING_SIZE
;
38 rdr
->read
= rdr
->base
;
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
;
64 void *safexcel_ring_next_rptr(struct safexcel_crypto_priv
*priv
,
65 struct safexcel_ring
*ring
)
67 void *ptr
= ring
->read
;
70 return ERR_PTR(-ENOENT
);
72 ring
->read
+= ring
->offset
;
73 if (ring
->read
== ring
->base_end
)
74 ring
->read
= ring
->base
;
80 void safexcel_ring_rollback_wptr(struct safexcel_crypto_priv
*priv
,
81 struct safexcel_ring
*ring
)
86 if (ring
->write
== ring
->base
)
87 ring
->write
= ring
->base_end
- ring
->offset
;
89 ring
->write
-= ring
->offset
;
94 struct safexcel_command_desc
*safexcel_add_cdesc(struct safexcel_crypto_priv
*priv
,
96 bool first
, bool last
,
97 dma_addr_t data
, u32 data_len
,
100 struct safexcel_command_desc
*cdesc
;
103 cdesc
= safexcel_ring_next_wptr(priv
, &priv
->ring
[ring_id
].cdr
);
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
]);
137 struct safexcel_result_desc
*safexcel_add_rdesc(struct safexcel_crypto_priv
*priv
,
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
);
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
);