Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2021-2024 Advanced Micro Devices, Inc.
3 : : */
4 : :
5 : : #include <inttypes.h>
6 : :
7 : : #include <rte_common.h>
8 : : #include <rte_malloc.h>
9 : : #include <rte_bitops.h>
10 : :
11 : : #include "ionic_crypto.h"
12 : :
13 : : static int
14 : 0 : iocpt_cq_init(struct iocpt_cq *cq, uint16_t num_descs)
15 : : {
16 [ # # ]: 0 : if (!rte_is_power_of_2(num_descs) ||
17 [ # # ]: 0 : num_descs < IOCPT_MIN_RING_DESC ||
18 : : num_descs > IOCPT_MAX_RING_DESC) {
19 : 0 : IOCPT_PRINT(ERR, "%u descriptors (min: %u max: %u)",
20 : : num_descs, IOCPT_MIN_RING_DESC, IOCPT_MAX_RING_DESC);
21 : 0 : return -EINVAL;
22 : : }
23 : :
24 : 0 : cq->num_descs = num_descs;
25 : 0 : cq->size_mask = num_descs - 1;
26 : 0 : cq->tail_idx = 0;
27 : 0 : cq->done_color = 1;
28 : :
29 : 0 : return 0;
30 : : }
31 : :
32 : : static void
33 : : iocpt_cq_reset(struct iocpt_cq *cq)
34 : : {
35 : 0 : cq->tail_idx = 0;
36 : 0 : cq->done_color = 1;
37 : :
38 : 0 : memset(cq->base, 0, sizeof(struct iocpt_nop_comp) * cq->num_descs);
39 : : }
40 : :
41 : : static void
42 : : iocpt_cq_map(struct iocpt_cq *cq, void *base, rte_iova_t base_pa)
43 : : {
44 : 0 : cq->base = base;
45 : 0 : cq->base_pa = base_pa;
46 : : }
47 : :
48 : : uint32_t
49 : 0 : iocpt_cq_service(struct iocpt_cq *cq, uint32_t work_to_do,
50 : : iocpt_cq_cb cb, void *cb_arg)
51 : : {
52 : : uint32_t work_done = 0;
53 : :
54 [ # # ]: 0 : if (work_to_do == 0)
55 : : return 0;
56 : :
57 [ # # ]: 0 : while (cb(cq, cq->tail_idx, cb_arg)) {
58 : 0 : cq->tail_idx = Q_NEXT_TO_SRVC(cq, 1);
59 [ # # ]: 0 : if (cq->tail_idx == 0)
60 : 0 : cq->done_color = !cq->done_color;
61 : :
62 [ # # ]: 0 : if (++work_done == work_to_do)
63 : : break;
64 : : }
65 : :
66 : : return work_done;
67 : : }
68 : :
69 : : static int
70 : 0 : iocpt_q_init(struct iocpt_queue *q, uint8_t type, uint32_t index,
71 : : uint16_t num_descs, uint16_t num_segs, uint32_t socket_id)
72 : : {
73 : : uint32_t ring_size;
74 : :
75 [ # # ]: 0 : if (!rte_is_power_of_2(num_descs))
76 : : return -EINVAL;
77 : :
78 : : ring_size = rte_log2_u32(num_descs);
79 [ # # ]: 0 : if (ring_size < 2 || ring_size > 16)
80 : : return -EINVAL;
81 : :
82 : 0 : q->type = type;
83 : 0 : q->index = index;
84 : 0 : q->num_descs = num_descs;
85 : 0 : q->num_segs = num_segs;
86 : 0 : q->size_mask = num_descs - 1;
87 : 0 : q->head_idx = 0;
88 : 0 : q->tail_idx = 0;
89 : :
90 : 0 : q->info = rte_calloc_socket("iocpt",
91 : 0 : (uint64_t)num_descs * num_segs, sizeof(void *),
92 : 0 : rte_mem_page_size(), socket_id);
93 [ # # ]: 0 : if (q->info == NULL) {
94 : 0 : IOCPT_PRINT(ERR, "Cannot allocate queue info");
95 : 0 : return -ENOMEM;
96 : : }
97 : :
98 : : return 0;
99 : : }
100 : :
101 : : static void
102 : : iocpt_q_reset(struct iocpt_queue *q)
103 : : {
104 : 0 : q->head_idx = 0;
105 : 0 : q->tail_idx = 0;
106 : : }
107 : :
108 : : static void
109 : : iocpt_q_map(struct iocpt_queue *q, void *base, rte_iova_t base_pa)
110 : : {
111 : 0 : q->base = base;
112 : 0 : q->base_pa = base_pa;
113 : : }
114 : :
115 : : static void
116 : : iocpt_q_sg_map(struct iocpt_queue *q, void *base, rte_iova_t base_pa)
117 : : {
118 : 0 : q->sg_base = base;
119 : 0 : q->sg_base_pa = base_pa;
120 : 0 : }
121 : :
122 : : static void
123 : : iocpt_q_free(struct iocpt_queue *q)
124 : : {
125 [ # # # # ]: 0 : if (q->info != NULL) {
126 : 0 : rte_free(q->info);
127 : 0 : q->info = NULL;
128 : : }
129 : : }
130 : :
131 : : static void
132 : 0 : iocpt_get_abs_stats(const struct iocpt_dev *dev,
133 : : struct rte_cryptodev_stats *stats)
134 : : {
135 : : uint32_t i;
136 : :
137 : : memset(stats, 0, sizeof(*stats));
138 : :
139 : : /* Sum up the per-queue stats counters */
140 [ # # ]: 0 : for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) {
141 : 0 : struct rte_cryptodev_stats *q_stats = &dev->cryptoqs[i]->stats;
142 : :
143 : 0 : stats->enqueued_count += q_stats->enqueued_count;
144 : 0 : stats->dequeued_count += q_stats->dequeued_count;
145 : 0 : stats->enqueue_err_count += q_stats->enqueue_err_count;
146 : 0 : stats->dequeue_err_count += q_stats->dequeue_err_count;
147 : : }
148 : 0 : }
149 : :
150 : : void
151 : 0 : iocpt_get_stats(const struct iocpt_dev *dev, struct rte_cryptodev_stats *stats)
152 : : {
153 : : /* Retrieve the new absolute stats values */
154 : 0 : iocpt_get_abs_stats(dev, stats);
155 : :
156 : : /* Subtract the base stats values to get relative values */
157 : 0 : stats->enqueued_count -= dev->stats_base.enqueued_count;
158 : 0 : stats->dequeued_count -= dev->stats_base.dequeued_count;
159 : 0 : stats->enqueue_err_count -= dev->stats_base.enqueue_err_count;
160 : 0 : stats->dequeue_err_count -= dev->stats_base.dequeue_err_count;
161 : 0 : }
162 : :
163 : : void
164 : 0 : iocpt_reset_stats(struct iocpt_dev *dev)
165 : : {
166 : : uint32_t i;
167 : :
168 : : /* Erase the per-queue stats counters */
169 [ # # ]: 0 : for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++)
170 : 0 : memset(&dev->cryptoqs[i]->stats, 0,
171 : : sizeof(dev->cryptoqs[i]->stats));
172 : :
173 : : /* Update the base stats values */
174 : 0 : iocpt_get_abs_stats(dev, &dev->stats_base);
175 : 0 : }
176 : :
177 : : static int
178 : 0 : iocpt_session_write(struct iocpt_session_priv *priv,
179 : : enum iocpt_sess_control_oper oper)
180 : : {
181 : 0 : struct iocpt_dev *dev = priv->dev;
182 : 0 : struct iocpt_admin_ctx ctx = {
183 : : .pending_work = true,
184 : : .cmd.sess_control = {
185 : : .opcode = IOCPT_CMD_SESS_CONTROL,
186 : 0 : .type = priv->type,
187 : : .oper = oper,
188 : 0 : .index = rte_cpu_to_le_32(priv->index),
189 : 0 : .key_len = rte_cpu_to_le_16(priv->key_len),
190 : 0 : .key_seg_len = (uint8_t)RTE_MIN(priv->key_len,
191 : : IOCPT_SESS_KEY_SEG_LEN),
192 : : },
193 : : };
194 : : struct iocpt_sess_control_cmd *cmd = &ctx.cmd.sess_control;
195 : : uint16_t key_offset;
196 : : uint8_t key_segs, seg, seg_len;
197 : : int err;
198 : :
199 : 0 : key_segs = ((priv->key_len - 1) >> IOCPT_SESS_KEY_SEG_SHFT) + 1;
200 : :
201 [ # # ]: 0 : for (seg = 0; seg < key_segs; seg++) {
202 : 0 : ctx.pending_work = true;
203 : :
204 : 0 : key_offset = seg * cmd->key_seg_len;
205 : 0 : seg_len = (uint8_t)RTE_MIN(priv->key_len - key_offset,
206 : : IOCPT_SESS_KEY_SEG_LEN);
207 [ # # ]: 0 : memcpy(cmd->key, &priv->key[key_offset], seg_len);
208 : 0 : cmd->key_seg_idx = seg;
209 : :
210 : : /* Mark final segment */
211 [ # # ]: 0 : if (seg + 1 == key_segs)
212 : 0 : cmd->flags |= rte_cpu_to_le_16(IOCPT_SCTL_F_END);
213 : :
214 : 0 : err = iocpt_adminq_post_wait(dev, &ctx);
215 [ # # ]: 0 : if (err != 0)
216 : 0 : return err;
217 : : }
218 : :
219 : : return 0;
220 : : }
221 : :
222 : : static int
223 : 0 : iocpt_session_wdog(struct iocpt_dev *dev)
224 : : {
225 : 0 : struct iocpt_session_priv priv = {
226 : : .dev = dev,
227 : : .index = IOCPT_Q_WDOG_SESS_IDX,
228 : : .type = IOCPT_SESS_AEAD_AES_GCM,
229 : : .key_len = IOCPT_Q_WDOG_KEY_LEN,
230 : : };
231 : :
232 : : /* Reserve session 0 for queue watchdog */
233 : 0 : rte_bitmap_clear(dev->sess_bm, IOCPT_Q_WDOG_SESS_IDX);
234 : :
235 : 0 : return iocpt_session_write(&priv, IOCPT_SESS_INIT);
236 : : }
237 : :
238 : : int
239 : 0 : iocpt_session_init(struct iocpt_session_priv *priv)
240 : : {
241 : 0 : struct iocpt_dev *dev = priv->dev;
242 : 0 : uint64_t bm_slab = 0;
243 : 0 : uint32_t bm_pos = 0;
244 : : int err = 0;
245 : :
246 : 0 : rte_spinlock_lock(&dev->adminq_lock);
247 : :
248 [ # # ]: 0 : if (rte_bitmap_scan(dev->sess_bm, &bm_pos, &bm_slab) > 0) {
249 : 0 : priv->index = bm_pos + rte_ctz64(bm_slab);
250 : 0 : rte_bitmap_clear(dev->sess_bm, priv->index);
251 : : } else
252 : : err = -ENOSPC;
253 : :
254 : : rte_spinlock_unlock(&dev->adminq_lock);
255 : :
256 [ # # ]: 0 : if (err != 0) {
257 : 0 : IOCPT_PRINT(ERR, "session index space exhausted");
258 : 0 : return err;
259 : : }
260 : :
261 : 0 : err = iocpt_session_write(priv, IOCPT_SESS_INIT);
262 [ # # ]: 0 : if (err != 0) {
263 : : rte_spinlock_lock(&dev->adminq_lock);
264 : 0 : rte_bitmap_set(dev->sess_bm, priv->index);
265 : : rte_spinlock_unlock(&dev->adminq_lock);
266 : 0 : return err;
267 : : }
268 : :
269 : 0 : priv->flags |= IOCPT_S_F_INITED;
270 : :
271 : 0 : return 0;
272 : : }
273 : :
274 : : int
275 : 0 : iocpt_session_update(struct iocpt_session_priv *priv)
276 : : {
277 : 0 : return iocpt_session_write(priv, IOCPT_SESS_UPDATE_KEY);
278 : : }
279 : :
280 : : void
281 : 0 : iocpt_session_deinit(struct iocpt_session_priv *priv)
282 : : {
283 : 0 : struct iocpt_dev *dev = priv->dev;
284 : 0 : struct iocpt_admin_ctx ctx = {
285 : : .pending_work = true,
286 : : .cmd.sess_control = {
287 : : .opcode = IOCPT_CMD_SESS_CONTROL,
288 : 0 : .type = priv->type,
289 : : .oper = IOCPT_SESS_DISABLE,
290 : 0 : .index = rte_cpu_to_le_32(priv->index),
291 : 0 : .key_len = rte_cpu_to_le_16(priv->key_len),
292 : : },
293 : : };
294 : :
295 : 0 : (void)iocpt_adminq_post_wait(dev, &ctx);
296 : :
297 : 0 : rte_spinlock_lock(&dev->adminq_lock);
298 : 0 : rte_bitmap_set(dev->sess_bm, priv->index);
299 : : rte_spinlock_unlock(&dev->adminq_lock);
300 : :
301 : 0 : priv->flags &= ~IOCPT_S_F_INITED;
302 : 0 : }
303 : :
304 : : static const struct rte_memzone *
305 : 0 : iocpt_dma_zone_reserve(const char *type_name, uint16_t qid, size_t size,
306 : : unsigned int align, int socket_id)
307 : : {
308 : : char zone_name[RTE_MEMZONE_NAMESIZE];
309 : : const struct rte_memzone *mz;
310 : : int err;
311 : :
312 [ # # ]: 0 : err = snprintf(zone_name, sizeof(zone_name),
313 : : "iocpt_%s_%u", type_name, qid);
314 [ # # ]: 0 : if (err >= RTE_MEMZONE_NAMESIZE) {
315 : 0 : IOCPT_PRINT(ERR, "Name %s too long", type_name);
316 : 0 : return NULL;
317 : : }
318 : :
319 : 0 : mz = rte_memzone_lookup(zone_name);
320 [ # # ]: 0 : if (mz != NULL)
321 : : return mz;
322 : :
323 : 0 : return rte_memzone_reserve_aligned(zone_name, size, socket_id,
324 : : RTE_MEMZONE_IOVA_CONTIG, align);
325 : : }
326 : :
327 : : static int
328 : 0 : iocpt_commonq_alloc(struct iocpt_dev *dev,
329 : : uint8_t type,
330 : : size_t struct_size,
331 : : uint32_t socket_id,
332 : : uint32_t index,
333 : : const char *type_name,
334 : : uint16_t flags,
335 : : uint16_t num_descs,
336 : : uint16_t num_segs,
337 : : uint16_t desc_size,
338 : : uint16_t cq_desc_size,
339 : : uint16_t sg_desc_size,
340 : : struct iocpt_common_q **comq)
341 : : {
342 : : struct iocpt_common_q *new;
343 : : uint32_t q_size, cq_size, sg_size, total_size;
344 : : void *q_base, *cq_base, *sg_base;
345 : : rte_iova_t q_base_pa = 0;
346 : : rte_iova_t cq_base_pa = 0;
347 : : rte_iova_t sg_base_pa = 0;
348 : 0 : size_t page_size = rte_mem_page_size();
349 : : int err;
350 : :
351 : 0 : *comq = NULL;
352 : :
353 : 0 : q_size = num_descs * desc_size;
354 : 0 : cq_size = num_descs * cq_desc_size;
355 : 0 : sg_size = num_descs * sg_desc_size;
356 : :
357 : : /*
358 : : * Note: aligning q_size/cq_size is not enough due to cq_base address
359 : : * aligning as q_base could be not aligned to the page.
360 : : * Adding page_size.
361 : : */
362 : 0 : total_size = RTE_ALIGN(q_size, page_size) +
363 : 0 : RTE_ALIGN(cq_size, page_size) + page_size;
364 [ # # ]: 0 : if (flags & IOCPT_Q_F_SG)
365 : 0 : total_size += RTE_ALIGN(sg_size, page_size) + page_size;
366 : :
367 : 0 : new = rte_zmalloc_socket("iocpt", struct_size,
368 : : RTE_CACHE_LINE_SIZE, socket_id);
369 [ # # ]: 0 : if (new == NULL) {
370 : 0 : IOCPT_PRINT(ERR, "Cannot allocate queue structure");
371 : 0 : return -ENOMEM;
372 : : }
373 : :
374 : 0 : new->dev = dev;
375 : :
376 : 0 : err = iocpt_q_init(&new->q, type, index, num_descs, num_segs,
377 : : socket_id);
378 [ # # ]: 0 : if (err != 0) {
379 : 0 : IOCPT_PRINT(ERR, "Queue initialization failed");
380 : 0 : goto err_free_q;
381 : : }
382 : :
383 : 0 : err = iocpt_cq_init(&new->cq, num_descs);
384 [ # # ]: 0 : if (err != 0) {
385 : 0 : IOCPT_PRINT(ERR, "Completion queue initialization failed");
386 : 0 : goto err_deinit_q;
387 : : }
388 : :
389 : 0 : new->base_z = iocpt_dma_zone_reserve(type_name, index, total_size,
390 : : IONIC_ALIGN, socket_id);
391 [ # # ]: 0 : if (new->base_z == NULL) {
392 : 0 : IOCPT_PRINT(ERR, "Cannot reserve queue DMA memory");
393 : : err = -ENOMEM;
394 : 0 : goto err_deinit_cq;
395 : : }
396 : :
397 : 0 : new->base = new->base_z->addr;
398 : 0 : new->base_pa = new->base_z->iova;
399 : :
400 : : q_base = new->base;
401 : : q_base_pa = new->base_pa;
402 : : iocpt_q_map(&new->q, q_base, q_base_pa);
403 : :
404 : 0 : cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, page_size);
405 : 0 : cq_base_pa = RTE_ALIGN(q_base_pa + q_size, page_size);
406 : : iocpt_cq_map(&new->cq, cq_base, cq_base_pa);
407 : :
408 [ # # ]: 0 : if (flags & IOCPT_Q_F_SG) {
409 : 0 : sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
410 : : page_size);
411 : 0 : sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, page_size);
412 : : iocpt_q_sg_map(&new->q, sg_base, sg_base_pa);
413 : : }
414 : :
415 : 0 : IOCPT_PRINT(DEBUG, "q_base_pa %#jx cq_base_pa %#jx sg_base_pa %#jx",
416 : : q_base_pa, cq_base_pa, sg_base_pa);
417 : :
418 : 0 : *comq = new;
419 : :
420 : 0 : return 0;
421 : :
422 : : err_deinit_cq:
423 [ # # ]: 0 : err_deinit_q:
424 : : iocpt_q_free(&new->q);
425 : 0 : err_free_q:
426 : 0 : rte_free(new);
427 : 0 : return err;
428 : : }
429 : :
430 : : int
431 : 0 : iocpt_cryptoq_alloc(struct iocpt_dev *dev, uint32_t socket_id, uint32_t index,
432 : : uint16_t num_descs)
433 : : {
434 : : struct iocpt_crypto_q *cptq;
435 : : uint16_t flags = 0;
436 : : int err;
437 : :
438 : : /* CryptoQ always supports scatter-gather */
439 : : flags |= IOCPT_Q_F_SG;
440 : :
441 : 0 : IOCPT_PRINT(DEBUG, "cptq %u num_descs %u num_segs %u",
442 : : index, num_descs, 1);
443 : :
444 : 0 : err = iocpt_commonq_alloc(dev,
445 : : IOCPT_QTYPE_CRYPTOQ,
446 : : sizeof(struct iocpt_crypto_q),
447 : : socket_id,
448 : : index,
449 : : "crypto",
450 : : flags,
451 : : num_descs,
452 : : 1,
453 : : sizeof(struct iocpt_crypto_desc),
454 : : sizeof(struct iocpt_crypto_comp),
455 : : sizeof(struct iocpt_crypto_sg_desc),
456 : : (struct iocpt_common_q **)&cptq);
457 [ # # ]: 0 : if (err != 0)
458 : : return err;
459 : :
460 : 0 : cptq->flags = flags;
461 : :
462 : 0 : dev->cryptoqs[index] = cptq;
463 : :
464 : 0 : return 0;
465 : : }
466 : :
467 : : struct ionic_doorbell *
468 : 0 : iocpt_db_map(struct iocpt_dev *dev, struct iocpt_queue *q)
469 : : {
470 : 0 : return dev->db_pages + q->hw_type;
471 : : }
472 : :
473 : : static int
474 : 0 : iocpt_cryptoq_init(struct iocpt_crypto_q *cptq)
475 : : {
476 : 0 : struct iocpt_queue *q = &cptq->q;
477 : 0 : struct iocpt_dev *dev = cptq->dev;
478 : : struct iocpt_cq *cq = &cptq->cq;
479 : 0 : struct iocpt_admin_ctx ctx = {
480 : : .pending_work = true,
481 : : .cmd.q_init = {
482 : : .opcode = IOCPT_CMD_Q_INIT,
483 : : .type = IOCPT_QTYPE_CRYPTOQ,
484 : 0 : .ver = dev->qtype_info[IOCPT_QTYPE_CRYPTOQ].version,
485 : 0 : .index = rte_cpu_to_le_32(q->index),
486 : : .flags = rte_cpu_to_le_16(IOCPT_QINIT_F_ENA |
487 : : IOCPT_QINIT_F_SG),
488 : : .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
489 [ # # ]: 0 : .ring_size = rte_log2_u32(q->num_descs),
490 : 0 : .ring_base = rte_cpu_to_le_64(q->base_pa),
491 : 0 : .cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
492 : 0 : .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
493 : : },
494 : : };
495 : : int err;
496 : :
497 : 0 : IOCPT_PRINT(DEBUG, "cptq_init.index %d", q->index);
498 : 0 : IOCPT_PRINT(DEBUG, "cptq_init.ring_base %#jx", q->base_pa);
499 : 0 : IOCPT_PRINT(DEBUG, "cptq_init.ring_size %d",
500 : : ctx.cmd.q_init.ring_size);
501 : 0 : IOCPT_PRINT(DEBUG, "cptq_init.ver %u", ctx.cmd.q_init.ver);
502 : :
503 : : iocpt_q_reset(q);
504 : : iocpt_cq_reset(cq);
505 : :
506 : 0 : err = iocpt_adminq_post_wait(dev, &ctx);
507 [ # # ]: 0 : if (err != 0)
508 : : return err;
509 : :
510 : 0 : q->hw_type = ctx.comp.q_init.hw_type;
511 : 0 : q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
512 : 0 : q->db = iocpt_db_map(dev, q);
513 : :
514 : 0 : IOCPT_PRINT(DEBUG, "cptq->hw_type %d", q->hw_type);
515 : 0 : IOCPT_PRINT(DEBUG, "cptq->hw_index %d", q->hw_index);
516 : 0 : IOCPT_PRINT(DEBUG, "cptq->db %p", q->db);
517 : :
518 : 0 : cptq->flags |= IOCPT_Q_F_INITED;
519 : :
520 : 0 : return 0;
521 : : }
522 : :
523 : : static void
524 : 0 : iocpt_cryptoq_deinit(struct iocpt_crypto_q *cptq)
525 : : {
526 : 0 : struct iocpt_dev *dev = cptq->dev;
527 : 0 : struct iocpt_admin_ctx ctx = {
528 : : .pending_work = true,
529 : : .cmd.q_control = {
530 : : .opcode = IOCPT_CMD_Q_CONTROL,
531 : : .type = IOCPT_QTYPE_CRYPTOQ,
532 : 0 : .index = rte_cpu_to_le_32(cptq->q.index),
533 : : .oper = IOCPT_Q_DISABLE,
534 : : },
535 : : };
536 : : unsigned long sleep_usec = 100UL * 1000;
537 : : uint32_t sleep_cnt, sleep_max = IOCPT_CRYPTOQ_WAIT;
538 : : int err;
539 : :
540 [ # # ]: 0 : for (sleep_cnt = 0; sleep_cnt < sleep_max; sleep_cnt++) {
541 : 0 : ctx.pending_work = true;
542 : :
543 : 0 : err = iocpt_adminq_post_wait(dev, &ctx);
544 [ # # ]: 0 : if (err != -EAGAIN)
545 : : break;
546 : :
547 : 0 : rte_delay_us_block(sleep_usec);
548 : : }
549 : :
550 [ # # ]: 0 : if (err != 0)
551 : 0 : IOCPT_PRINT(ERR, "Deinit queue %u returned %d after %u ms",
552 : : cptq->q.index, err, sleep_cnt * 100);
553 : : else
554 : 0 : IOCPT_PRINT(DEBUG, "Deinit queue %u returned %d after %u ms",
555 : : cptq->q.index, err, sleep_cnt * 100);
556 : :
557 : 0 : IOCPT_PRINT(DEBUG, "Queue %u watchdog: enq %"PRIu64" deq %"PRIu64,
558 : : cptq->q.index, cptq->enqueued_wdogs, cptq->dequeued_wdogs);
559 : :
560 : 0 : cptq->flags &= ~IOCPT_Q_F_INITED;
561 : 0 : }
562 : :
563 : : void
564 : 0 : iocpt_cryptoq_free(struct iocpt_crypto_q *cptq)
565 : : {
566 [ # # ]: 0 : if (cptq == NULL)
567 : : return;
568 : :
569 [ # # ]: 0 : if (cptq->base_z != NULL) {
570 : 0 : rte_memzone_free(cptq->base_z);
571 : 0 : cptq->base_z = NULL;
572 : 0 : cptq->base = NULL;
573 : 0 : cptq->base_pa = 0;
574 : : }
575 : :
576 : : iocpt_q_free(&cptq->q);
577 : :
578 : 0 : rte_free(cptq);
579 : : }
580 : :
581 : : static int
582 : 0 : iocpt_adminq_alloc(struct iocpt_dev *dev)
583 : : {
584 : : struct iocpt_admin_q *aq;
585 : : uint16_t num_descs = IOCPT_ADMINQ_LENGTH;
586 : : uint16_t flags = 0;
587 : : int err;
588 : :
589 : 0 : err = iocpt_commonq_alloc(dev,
590 : : IOCPT_QTYPE_ADMINQ,
591 : : sizeof(struct iocpt_admin_q),
592 : : rte_socket_id(),
593 : : 0,
594 : : "admin",
595 : : flags,
596 : : num_descs,
597 : : 1,
598 : : sizeof(struct iocpt_admin_cmd),
599 : : sizeof(struct iocpt_admin_comp),
600 : : 0,
601 : : (struct iocpt_common_q **)&aq);
602 [ # # ]: 0 : if (err != 0)
603 : : return err;
604 : :
605 : 0 : aq->flags = flags;
606 : :
607 : 0 : dev->adminq = aq;
608 : :
609 : 0 : return 0;
610 : : }
611 : :
612 : : static int
613 : : iocpt_adminq_init(struct iocpt_dev *dev)
614 : : {
615 : 0 : return iocpt_dev_adminq_init(dev);
616 : : }
617 : :
618 : : static void
619 : : iocpt_adminq_deinit(struct iocpt_dev *dev)
620 : : {
621 : 0 : dev->adminq->flags &= ~IOCPT_Q_F_INITED;
622 : : }
623 : :
624 : : static void
625 : 0 : iocpt_adminq_free(struct iocpt_admin_q *aq)
626 : : {
627 [ # # ]: 0 : if (aq->base_z != NULL) {
628 : 0 : rte_memzone_free(aq->base_z);
629 : 0 : aq->base_z = NULL;
630 : 0 : aq->base = NULL;
631 : 0 : aq->base_pa = 0;
632 : : }
633 : :
634 : : iocpt_q_free(&aq->q);
635 : :
636 : 0 : rte_free(aq);
637 : 0 : }
638 : :
639 : : static int
640 : 0 : iocpt_alloc_objs(struct iocpt_dev *dev)
641 : : {
642 : : uint32_t bmsize, i;
643 : : uint8_t *bm;
644 : : int err;
645 : :
646 : 0 : IOCPT_PRINT(DEBUG, "Crypto: %s", dev->name);
647 : :
648 : 0 : dev->cryptoqs = rte_calloc_socket("iocpt",
649 : 0 : dev->max_qps, sizeof(*dev->cryptoqs),
650 : 0 : RTE_CACHE_LINE_SIZE, dev->socket_id);
651 [ # # ]: 0 : if (dev->cryptoqs == NULL) {
652 : 0 : IOCPT_PRINT(ERR, "Cannot allocate tx queues array");
653 : 0 : return -ENOMEM;
654 : : }
655 : :
656 : : rte_spinlock_init(&dev->adminq_lock);
657 : : rte_spinlock_init(&dev->adminq_service_lock);
658 : :
659 : 0 : err = iocpt_adminq_alloc(dev);
660 [ # # ]: 0 : if (err != 0) {
661 : 0 : IOCPT_PRINT(ERR, "Cannot allocate admin queue");
662 : : err = -ENOMEM;
663 : 0 : goto err_free_cryptoqs;
664 : : }
665 : :
666 : 0 : dev->info_sz = RTE_ALIGN(sizeof(*dev->info), rte_mem_page_size());
667 : 0 : dev->info_z = iocpt_dma_zone_reserve("info", 0, dev->info_sz,
668 : 0 : IONIC_ALIGN, dev->socket_id);
669 [ # # ]: 0 : if (dev->info_z == NULL) {
670 : 0 : IOCPT_PRINT(ERR, "Cannot allocate dev info memory");
671 : : err = -ENOMEM;
672 : 0 : goto err_free_adminq;
673 : : }
674 : :
675 : 0 : dev->info = dev->info_z->addr;
676 : 0 : dev->info_pa = dev->info_z->iova;
677 : :
678 : 0 : bmsize = rte_bitmap_get_memory_footprint(dev->max_sessions);
679 : 0 : bm = rte_malloc_socket("iocpt", bmsize,
680 : 0 : RTE_CACHE_LINE_SIZE, dev->socket_id);
681 [ # # ]: 0 : if (bm == NULL) {
682 : 0 : IOCPT_PRINT(ERR, "Cannot allocate %uB bitmap memory", bmsize);
683 : : err = -ENOMEM;
684 : 0 : goto err_free_dmazone;
685 : : }
686 : :
687 : 0 : dev->sess_bm = rte_bitmap_init(dev->max_sessions, bm, bmsize);
688 [ # # ]: 0 : if (dev->sess_bm == NULL) {
689 : 0 : IOCPT_PRINT(ERR, "Cannot initialize bitmap");
690 : : err = -EFAULT;
691 : 0 : goto err_free_bm;
692 : : }
693 [ # # ]: 0 : for (i = 0; i < dev->max_sessions; i++)
694 : 0 : rte_bitmap_set(dev->sess_bm, i);
695 : :
696 : : return 0;
697 : :
698 : : err_free_bm:
699 : 0 : rte_free(bm);
700 : 0 : err_free_dmazone:
701 : 0 : rte_memzone_free(dev->info_z);
702 : 0 : dev->info_z = NULL;
703 : 0 : dev->info = NULL;
704 : 0 : dev->info_pa = 0;
705 : 0 : err_free_adminq:
706 : 0 : iocpt_adminq_free(dev->adminq);
707 : 0 : dev->adminq = NULL;
708 : 0 : err_free_cryptoqs:
709 : 0 : rte_free(dev->cryptoqs);
710 : 0 : dev->cryptoqs = NULL;
711 : 0 : return err;
712 : : }
713 : :
714 : : static int
715 : 0 : iocpt_init(struct iocpt_dev *dev)
716 : : {
717 : : int err;
718 : :
719 : 0 : memset(&dev->stats_base, 0, sizeof(dev->stats_base));
720 : :
721 : : /* Uses dev_cmds */
722 : 0 : err = iocpt_dev_init(dev, dev->info_pa);
723 [ # # ]: 0 : if (err != 0)
724 : : return err;
725 : :
726 : : err = iocpt_adminq_init(dev);
727 [ # # ]: 0 : if (err != 0)
728 : : return err;
729 : :
730 : : /* Write the queue watchdog key */
731 : 0 : err = iocpt_session_wdog(dev);
732 [ # # ]: 0 : if (err != 0) {
733 : 0 : IOCPT_PRINT(ERR, "Cannot setup watchdog session");
734 : 0 : goto err_out_adminq_deinit;
735 : : }
736 : :
737 : 0 : dev->state |= IOCPT_DEV_F_INITED;
738 : :
739 : 0 : return 0;
740 : :
741 : : err_out_adminq_deinit:
742 : : iocpt_adminq_deinit(dev);
743 : :
744 : 0 : return err;
745 : : }
746 : :
747 : : void
748 : 0 : iocpt_configure(struct iocpt_dev *dev)
749 : : {
750 : : RTE_SET_USED(dev);
751 : 0 : }
752 : :
753 : : int
754 : 0 : iocpt_start(struct iocpt_dev *dev)
755 : : {
756 : : uint32_t i;
757 : : int err;
758 : :
759 : 0 : IOCPT_PRINT(DEBUG, "Starting %u queues",
760 : : dev->crypto_dev->data->nb_queue_pairs);
761 : :
762 [ # # ]: 0 : for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) {
763 : 0 : err = iocpt_cryptoq_init(dev->cryptoqs[i]);
764 [ # # ]: 0 : if (err != 0)
765 : 0 : return err;
766 : : }
767 : :
768 : 0 : dev->state |= IOCPT_DEV_F_UP;
769 : :
770 : 0 : return 0;
771 : : }
772 : :
773 : : void
774 : 0 : iocpt_stop(struct iocpt_dev *dev)
775 : : {
776 : : uint32_t i;
777 : :
778 : 0 : IOCPT_PRINT_CALL();
779 : :
780 : 0 : dev->state &= ~IOCPT_DEV_F_UP;
781 : :
782 [ # # ]: 0 : for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) {
783 : 0 : struct iocpt_crypto_q *cptq = dev->cryptoqs[i];
784 : :
785 [ # # ]: 0 : if (cptq->flags & IOCPT_Q_F_INITED)
786 : 0 : (void)iocpt_cryptoq_deinit(cptq);
787 : : }
788 : 0 : }
789 : :
790 : : void
791 : 0 : iocpt_deinit(struct iocpt_dev *dev)
792 : : {
793 : 0 : IOCPT_PRINT_CALL();
794 : :
795 [ # # ]: 0 : if (!(dev->state & IOCPT_DEV_F_INITED))
796 : : return;
797 : :
798 : : iocpt_adminq_deinit(dev);
799 : :
800 : 0 : dev->state &= ~IOCPT_DEV_F_INITED;
801 : : }
802 : :
803 : : static void
804 : 0 : iocpt_free_objs(struct iocpt_dev *dev)
805 : : {
806 : 0 : void **queue_pairs = dev->crypto_dev->data->queue_pairs;
807 : : uint32_t i;
808 : :
809 : 0 : IOCPT_PRINT_CALL();
810 : :
811 [ # # ]: 0 : for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) {
812 : 0 : iocpt_cryptoq_free(queue_pairs[i]);
813 : 0 : queue_pairs[i] = NULL;
814 : : }
815 : :
816 [ # # ]: 0 : if (dev->sess_bm != NULL) {
817 : : rte_bitmap_free(dev->sess_bm);
818 : 0 : rte_free(dev->sess_bm);
819 : 0 : dev->sess_bm = NULL;
820 : : }
821 : :
822 [ # # ]: 0 : if (dev->adminq != NULL) {
823 : 0 : iocpt_adminq_free(dev->adminq);
824 : 0 : dev->adminq = NULL;
825 : : }
826 : :
827 [ # # ]: 0 : if (dev->cryptoqs != NULL) {
828 : 0 : rte_free(dev->cryptoqs);
829 : 0 : dev->cryptoqs = NULL;
830 : : }
831 : :
832 [ # # ]: 0 : if (dev->info != NULL) {
833 : 0 : rte_memzone_free(dev->info_z);
834 : 0 : dev->info_z = NULL;
835 : 0 : dev->info = NULL;
836 : 0 : dev->info_pa = 0;
837 : : }
838 : 0 : }
839 : :
840 : : static int
841 : : iocpt_devargs(struct rte_devargs *devargs, struct iocpt_dev *dev)
842 : : {
843 : : RTE_SET_USED(devargs);
844 : : RTE_SET_USED(dev);
845 : :
846 : : return 0;
847 : : }
848 : :
849 : : int
850 : 0 : iocpt_probe(void *bus_dev, struct rte_device *rte_dev,
851 : : struct iocpt_dev_bars *bars, const struct iocpt_dev_intf *intf,
852 : : uint8_t driver_id, uint8_t socket_id)
853 : : {
854 : 0 : struct rte_cryptodev_pmd_init_params init_params = {
855 : : "iocpt",
856 : : sizeof(struct iocpt_dev),
857 : : socket_id,
858 : : RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS
859 : : };
860 : : struct rte_cryptodev *cdev;
861 : : struct iocpt_dev *dev;
862 : : uint32_t i, sig;
863 : : int err;
864 : :
865 : : /* Check structs (trigger error at compilation time) */
866 : : iocpt_struct_size_checks();
867 : :
868 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
869 : 0 : IOCPT_PRINT(ERR, "Multi-process not supported");
870 : : err = -EPERM;
871 : 0 : goto err;
872 : : }
873 : :
874 : 0 : cdev = rte_cryptodev_pmd_create(rte_dev->name, rte_dev, &init_params);
875 [ # # ]: 0 : if (cdev == NULL) {
876 : 0 : IOCPT_PRINT(ERR, "Out of memory");
877 : : err = -ENOMEM;
878 : 0 : goto err;
879 : : }
880 : :
881 : 0 : dev = cdev->data->dev_private;
882 : 0 : dev->crypto_dev = cdev;
883 : 0 : dev->bus_dev = bus_dev;
884 : 0 : dev->intf = intf;
885 : 0 : dev->driver_id = driver_id;
886 : 0 : dev->socket_id = socket_id;
887 : :
888 [ # # ]: 0 : for (i = 0; i < bars->num_bars; i++) {
889 : : struct ionic_dev_bar *bar = &bars->bar[i];
890 : :
891 : 0 : IOCPT_PRINT(DEBUG,
892 : : "bar[%u] = { .va = %p, .pa = %#jx, .len = %lu }",
893 : : i, bar->vaddr, bar->bus_addr, bar->len);
894 [ # # ]: 0 : if (bar->vaddr == NULL) {
895 : 0 : IOCPT_PRINT(ERR, "Null bar found, aborting");
896 : : err = -EFAULT;
897 : 0 : goto err_destroy_crypto_dev;
898 : : }
899 : :
900 : 0 : dev->bars.bar[i].vaddr = bar->vaddr;
901 : 0 : dev->bars.bar[i].bus_addr = bar->bus_addr;
902 : 0 : dev->bars.bar[i].len = bar->len;
903 : : }
904 [ # # ]: 0 : dev->bars.num_bars = bars->num_bars;
905 : :
906 : : err = iocpt_devargs(rte_dev->devargs, dev);
907 : : if (err != 0) {
908 : : IOCPT_PRINT(ERR, "Cannot parse device arguments");
909 : : goto err_destroy_crypto_dev;
910 : : }
911 : :
912 : : err = iocpt_setup_bars(dev);
913 [ # # ]: 0 : if (err != 0) {
914 : 0 : IOCPT_PRINT(ERR, "Cannot setup BARs: %d, aborting", err);
915 : 0 : goto err_destroy_crypto_dev;
916 : : }
917 : :
918 : 0 : sig = ioread32(&dev->dev_info->signature);
919 [ # # ]: 0 : if (sig != IOCPT_DEV_INFO_SIGNATURE) {
920 : 0 : IOCPT_PRINT(ERR, "Incompatible firmware signature %#x", sig);
921 : : err = -EFAULT;
922 : 0 : goto err_destroy_crypto_dev;
923 : : }
924 : :
925 [ # # ]: 0 : for (i = 0; i < IOCPT_FWVERS_BUFLEN; i++)
926 : 0 : dev->fw_version[i] = ioread8(&dev->dev_info->fw_version[i]);
927 : 0 : dev->fw_version[IOCPT_FWVERS_BUFLEN - 1] = '\0';
928 : 0 : IOCPT_PRINT(DEBUG, "%s firmware: %s", dev->name, dev->fw_version);
929 : :
930 : 0 : err = iocpt_dev_identify(dev);
931 [ # # ]: 0 : if (err != 0) {
932 : 0 : IOCPT_PRINT(ERR, "Cannot identify device: %d, aborting",
933 : : err);
934 : 0 : goto err_destroy_crypto_dev;
935 : : }
936 : :
937 : 0 : err = iocpt_alloc_objs(dev);
938 [ # # ]: 0 : if (err != 0) {
939 : 0 : IOCPT_PRINT(ERR, "Cannot alloc device objects: %d", err);
940 : 0 : goto err_destroy_crypto_dev;
941 : : }
942 : :
943 : 0 : err = iocpt_init(dev);
944 [ # # ]: 0 : if (err != 0) {
945 : 0 : IOCPT_PRINT(ERR, "Cannot init device: %d, aborting", err);
946 : 0 : goto err_free_objs;
947 : : }
948 : :
949 : 0 : err = iocpt_assign_ops(cdev);
950 [ # # ]: 0 : if (err != 0) {
951 : 0 : IOCPT_PRINT(ERR, "Failed to configure opts");
952 : 0 : goto err_deinit_dev;
953 : : }
954 : :
955 : : return 0;
956 : :
957 : : err_deinit_dev:
958 : 0 : iocpt_deinit(dev);
959 : 0 : err_free_objs:
960 : 0 : iocpt_free_objs(dev);
961 : 0 : err_destroy_crypto_dev:
962 : 0 : rte_cryptodev_pmd_destroy(cdev);
963 : : err:
964 : : return err;
965 : : }
966 : :
967 : : int
968 : 0 : iocpt_remove(struct rte_device *rte_dev)
969 : : {
970 : : struct rte_cryptodev *cdev;
971 : : struct iocpt_dev *dev;
972 : :
973 : 0 : cdev = rte_cryptodev_pmd_get_named_dev(rte_dev->name);
974 [ # # ]: 0 : if (cdev == NULL) {
975 : 0 : IOCPT_PRINT(DEBUG, "Cannot find device %s", rte_dev->name);
976 : 0 : return -ENODEV;
977 : : }
978 : :
979 : 0 : dev = cdev->data->dev_private;
980 : :
981 : 0 : iocpt_deinit(dev);
982 : :
983 : 0 : iocpt_dev_reset(dev);
984 : :
985 : 0 : iocpt_free_objs(dev);
986 : :
987 : 0 : rte_cryptodev_pmd_destroy(cdev);
988 : :
989 : 0 : return 0;
990 : : }
991 : :
992 [ - + ]: 251 : RTE_LOG_REGISTER_DEFAULT(iocpt_logtype, NOTICE);
|