cdae2a4fca5a13aa924ca4a0209d9ba747331685
[dpdk.git] / drivers / crypto / caam_jr / caam_jr.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2017-2018 NXP
3  */
4
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <sched.h>
8 #include <net/if.h>
9
10 #include <rte_byteorder.h>
11 #include <rte_common.h>
12 #include <rte_cryptodev_pmd.h>
13 #include <rte_crypto.h>
14 #include <rte_cryptodev.h>
15 #include <rte_bus_vdev.h>
16 #include <rte_malloc.h>
17 #include <rte_security_driver.h>
18 #include <rte_hexdump.h>
19
20 #include <caam_jr_config.h>
21 #include <caam_jr_hw_specific.h>
22 #include <caam_jr_pvt.h>
23 #include <caam_jr_log.h>
24
25 /* RTA header files */
26 #include <hw/desc/common.h>
27 #include <of.h>
28
29 #define CRYPTODEV_NAME_CAAM_JR_PMD      crypto_caam_jr
30 static uint8_t cryptodev_driver_id;
31 int caam_jr_logtype;
32
33 enum rta_sec_era rta_sec_era;
34
35 /* Lists the states possible for the SEC user space driver. */
36 enum sec_driver_state_e {
37         SEC_DRIVER_STATE_IDLE,          /* Driver not initialized */
38         SEC_DRIVER_STATE_STARTED,       /* Driver initialized and can be used*/
39         SEC_DRIVER_STATE_RELEASE,       /* Driver release is in progress */
40 };
41
42 /* Job rings used for communication with SEC HW */
43 static struct sec_job_ring_t g_job_rings[MAX_SEC_JOB_RINGS];
44
45 /* The current state of SEC user space driver */
46 static enum sec_driver_state_e g_driver_state = SEC_DRIVER_STATE_IDLE;
47
48 /* The number of job rings used by SEC user space driver */
49 static int g_job_rings_no;
50 static int g_job_rings_max;
51
52 /* @brief Poll the HW for already processed jobs in the JR
53  * and silently discard the available jobs or notify them to UA
54  * with indicated error code.
55  *
56  * @param [in,out]  job_ring        The job ring to poll.
57  * @param [in]  do_notify           Can be #TRUE or #FALSE. Indicates if
58  *                                  descriptors are to be discarded
59  *                                  or notified to UA with given error_code.
60  * @param [out] notified_descs    Number of notified descriptors. Can be NULL
61  *                                      if do_notify is #FALSE
62  */
63 static void
64 hw_flush_job_ring(struct sec_job_ring_t *job_ring,
65                   uint32_t do_notify,
66                   uint32_t *notified_descs)
67 {
68         int32_t jobs_no_to_discard = 0;
69         int32_t discarded_descs_no = 0;
70
71         PMD_INIT_FUNC_TRACE();
72         CAAM_JR_DEBUG("Jr[%p] pi[%d] ci[%d].Flushing jr notify desc=[%d]",
73                 job_ring, job_ring->pidx, job_ring->cidx, do_notify);
74
75         jobs_no_to_discard = hw_get_no_finished_jobs(job_ring);
76
77         /* Discard all jobs */
78         CAAM_JR_DEBUG("Jr[%p] pi[%d] ci[%d].Discarding %d descs",
79                   job_ring, job_ring->pidx, job_ring->cidx,
80                   jobs_no_to_discard);
81
82         while (jobs_no_to_discard > discarded_descs_no) {
83                 discarded_descs_no++;
84                 /* Now increment the consumer index for the current job ring,
85                  * AFTER saving job in temporary location!
86                  * Increment the consumer index for the current job ring
87                  */
88                 job_ring->cidx = SEC_CIRCULAR_COUNTER(job_ring->cidx,
89                                          SEC_JOB_RING_SIZE);
90
91                 hw_remove_entries(job_ring, 1);
92         }
93
94         if (do_notify == true) {
95                 ASSERT(notified_descs != NULL);
96                 *notified_descs = discarded_descs_no;
97         }
98 }
99
100
101 static int
102 caam_jr_dev_configure(struct rte_cryptodev *dev,
103                        struct rte_cryptodev_config *config __rte_unused)
104 {
105         char str[20];
106         struct sec_job_ring_t *internals;
107
108         PMD_INIT_FUNC_TRACE();
109
110         internals = dev->data->dev_private;
111         sprintf(str, "ctx_pool_%d", dev->data->dev_id);
112         if (!internals->ctx_pool) {
113                 internals->ctx_pool = rte_mempool_create((const char *)str,
114                                                 CTX_POOL_NUM_BUFS,
115                                                 sizeof(struct caam_jr_op_ctx),
116                                                 CTX_POOL_CACHE_SIZE, 0,
117                                                 NULL, NULL, NULL, NULL,
118                                                 SOCKET_ID_ANY, 0);
119                 if (!internals->ctx_pool) {
120                         CAAM_JR_ERR("%s create failed\n", str);
121                         return -ENOMEM;
122                 }
123         } else
124                 CAAM_JR_INFO("mempool already created for dev_id : %d",
125                                 dev->data->dev_id);
126
127         return 0;
128 }
129
130 static int
131 caam_jr_dev_start(struct rte_cryptodev *dev __rte_unused)
132 {
133         PMD_INIT_FUNC_TRACE();
134         return 0;
135 }
136
137 static void
138 caam_jr_dev_stop(struct rte_cryptodev *dev __rte_unused)
139 {
140         PMD_INIT_FUNC_TRACE();
141 }
142
143 static int
144 caam_jr_dev_close(struct rte_cryptodev *dev)
145 {
146         struct sec_job_ring_t *internals;
147
148         PMD_INIT_FUNC_TRACE();
149
150         if (dev == NULL)
151                 return -ENOMEM;
152
153         internals = dev->data->dev_private;
154         rte_mempool_free(internals->ctx_pool);
155         internals->ctx_pool = NULL;
156
157         return 0;
158 }
159
160 static void
161 caam_jr_dev_infos_get(struct rte_cryptodev *dev,
162                        struct rte_cryptodev_info *info)
163 {
164         struct sec_job_ring_t *internals = dev->data->dev_private;
165
166         PMD_INIT_FUNC_TRACE();
167         if (info != NULL) {
168                 info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
169                 info->feature_flags = dev->feature_flags;
170                 info->sym.max_nb_sessions = internals->max_nb_sessions;
171                 info->driver_id = cryptodev_driver_id;
172         }
173 }
174
175 static struct rte_cryptodev_ops caam_jr_ops = {
176         .dev_configure        = caam_jr_dev_configure,
177         .dev_start            = caam_jr_dev_start,
178         .dev_stop             = caam_jr_dev_stop,
179         .dev_close            = caam_jr_dev_close,
180         .dev_infos_get        = caam_jr_dev_infos_get,
181 };
182
183
184 /* @brief Flush job rings of any processed descs.
185  * The processed descs are silently dropped,
186  * WITHOUT being notified to UA.
187  */
188 static void
189 close_job_ring(struct sec_job_ring_t *job_ring)
190 {
191         PMD_INIT_FUNC_TRACE();
192         if (job_ring->irq_fd) {
193                 /* Producer index is frozen. If consumer index is not equal
194                  * with producer index, then we have descs to flush.
195                  */
196                 while (job_ring->pidx != job_ring->cidx)
197                         hw_flush_job_ring(job_ring, false, NULL);
198
199                 /* free the uio job ring */
200                 free_job_ring(job_ring->irq_fd);
201                 job_ring->irq_fd = 0;
202                 caam_jr_dma_free(job_ring->input_ring);
203                 caam_jr_dma_free(job_ring->output_ring);
204                 g_job_rings_no--;
205         }
206 }
207
208 /** @brief Release the software and hardware resources tied to a job ring.
209  * @param [in] job_ring The job ring
210  *
211  * @retval  0 for success
212  * @retval  -1 for error
213  */
214 static int
215 shutdown_job_ring(struct sec_job_ring_t *job_ring)
216 {
217         int ret = 0;
218
219         PMD_INIT_FUNC_TRACE();
220         ASSERT(job_ring != NULL);
221         ret = hw_shutdown_job_ring(job_ring);
222         SEC_ASSERT(ret == 0, ret,
223                 "Failed to shutdown hardware job ring %p",
224                 job_ring);
225
226         if (job_ring->coalescing_en)
227                 hw_job_ring_disable_coalescing(job_ring);
228
229         if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
230                 ret = caam_jr_disable_irqs(job_ring->irq_fd);
231                 SEC_ASSERT(ret == 0, ret,
232                 "Failed to disable irqs for job ring %p",
233                 job_ring);
234         }
235
236         return ret;
237 }
238
239 /*
240  * @brief Release the resources used by the SEC user space driver.
241  *
242  * Reset and release SEC's job rings indicated by the User Application at
243  * init_job_ring() and free any memory allocated internally.
244  * Call once during application tear down.
245  *
246  * @note In case there are any descriptors in-flight (descriptors received by
247  * SEC driver for processing and for which no response was yet provided to UA),
248  * the descriptors are discarded without any notifications to User Application.
249  *
250  * @retval ::0                  is returned for a successful execution
251  * @retval ::-1         is returned if SEC driver release is in progress
252  */
253 static int
254 caam_jr_dev_uninit(struct rte_cryptodev *dev)
255 {
256         struct sec_job_ring_t *internals;
257
258         PMD_INIT_FUNC_TRACE();
259         if (dev == NULL)
260                 return -ENODEV;
261
262         internals = dev->data->dev_private;
263         rte_free(dev->security_ctx);
264
265         /* If any descriptors in flight , poll and wait
266          * until all descriptors are received and silently discarded.
267          */
268         if (internals) {
269                 shutdown_job_ring(internals);
270                 close_job_ring(internals);
271                 rte_mempool_free(internals->ctx_pool);
272         }
273
274         CAAM_JR_INFO("Closing crypto device %s", dev->data->name);
275
276         /* last caam jr instance) */
277         if (g_job_rings_no == 0)
278                 g_driver_state = SEC_DRIVER_STATE_IDLE;
279
280         return SEC_SUCCESS;
281 }
282
283 /* @brief Initialize the software and hardware resources tied to a job ring.
284  * @param [in] jr_mode;         Model to be used by SEC Driver to receive
285  *                              notifications from SEC.  Can be either
286  *                              of the three: #SEC_NOTIFICATION_TYPE_NAPI
287  *                              #SEC_NOTIFICATION_TYPE_IRQ or
288  *                              #SEC_NOTIFICATION_TYPE_POLL
289  * @param [in] NAPI_mode        The NAPI work mode to configure a job ring at
290  *                              startup. Used only when #SEC_NOTIFICATION_TYPE
291  *                              is set to #SEC_NOTIFICATION_TYPE_NAPI.
292  * @param [in] irq_coalescing_timer This value determines the maximum
293  *                                      amount of time after processing a
294  *                                      descriptor before raising an interrupt.
295  * @param [in] irq_coalescing_count This value determines how many
296  *                                      descriptors are completed before
297  *                                      raising an interrupt.
298  * @param [in] reg_base_addr,   The job ring base address register
299  * @param [in] irq_id           The job ring interrupt identification number.
300  * @retval  job_ring_handle for successful job ring configuration
301  * @retval  NULL on error
302  *
303  */
304 static void *
305 init_job_ring(void *reg_base_addr, uint32_t irq_id)
306 {
307         struct sec_job_ring_t *job_ring = NULL;
308         int i, ret = 0;
309         int jr_mode = SEC_NOTIFICATION_TYPE_POLL;
310         int napi_mode = 0;
311         int irq_coalescing_timer = 0;
312         int irq_coalescing_count = 0;
313
314         for (i = 0; i < MAX_SEC_JOB_RINGS; i++) {
315                 if (g_job_rings[i].irq_fd == 0) {
316                         job_ring = &g_job_rings[i];
317                         g_job_rings_no++;
318                         break;
319                 }
320         }
321         if (job_ring == NULL) {
322                 CAAM_JR_ERR("No free job ring\n");
323                 return NULL;
324         }
325
326         job_ring->register_base_addr = reg_base_addr;
327         job_ring->jr_mode = jr_mode;
328         job_ring->napi_mode = 0;
329         job_ring->irq_fd = irq_id;
330
331         /* Allocate mem for input and output ring */
332
333         /* Allocate memory for input ring */
334         job_ring->input_ring = caam_jr_dma_mem_alloc(L1_CACHE_BYTES,
335                                 SEC_DMA_MEM_INPUT_RING_SIZE);
336         memset(job_ring->input_ring, 0, SEC_DMA_MEM_INPUT_RING_SIZE);
337
338         /* Allocate memory for output ring */
339         job_ring->output_ring = caam_jr_dma_mem_alloc(L1_CACHE_BYTES,
340                                 SEC_DMA_MEM_OUTPUT_RING_SIZE);
341         memset(job_ring->output_ring, 0, SEC_DMA_MEM_OUTPUT_RING_SIZE);
342
343         /* Reset job ring in SEC hw and configure job ring registers */
344         ret = hw_reset_job_ring(job_ring);
345         if (ret != 0) {
346                 CAAM_JR_ERR("Failed to reset hardware job ring");
347                 goto cleanup;
348         }
349
350         if (jr_mode == SEC_NOTIFICATION_TYPE_NAPI) {
351         /* When SEC US driver works in NAPI mode, the UA can select
352          * if the driver starts with IRQs on or off.
353          */
354                 if (napi_mode == SEC_STARTUP_INTERRUPT_MODE) {
355                         CAAM_JR_INFO("Enabling DONE IRQ generationon job ring - %p",
356                                 job_ring);
357                         ret = caam_jr_enable_irqs(job_ring->irq_fd);
358                         if (ret != 0) {
359                                 CAAM_JR_ERR("Failed to enable irqs for job ring");
360                                 goto cleanup;
361                         }
362                 }
363         } else if (jr_mode == SEC_NOTIFICATION_TYPE_IRQ) {
364         /* When SEC US driver works in pure interrupt mode,
365          * IRQ's are always enabled.
366          */
367                 CAAM_JR_INFO("Enabling DONE IRQ generation on job ring - %p",
368                          job_ring);
369                 ret = caam_jr_enable_irqs(job_ring->irq_fd);
370                 if (ret != 0) {
371                         CAAM_JR_ERR("Failed to enable irqs for job ring");
372                         goto cleanup;
373                 }
374         }
375         if (irq_coalescing_timer || irq_coalescing_count) {
376                 hw_job_ring_set_coalescing_param(job_ring,
377                          irq_coalescing_timer,
378                          irq_coalescing_count);
379
380                 hw_job_ring_enable_coalescing(job_ring);
381                 job_ring->coalescing_en = 1;
382         }
383
384         job_ring->jr_state = SEC_JOB_RING_STATE_STARTED;
385         job_ring->max_nb_queue_pairs = RTE_CAAM_MAX_NB_SEC_QPS;
386         job_ring->max_nb_sessions = RTE_CAAM_JR_PMD_MAX_NB_SESSIONS;
387
388         return job_ring;
389 cleanup:
390         caam_jr_dma_free(job_ring->output_ring);
391         caam_jr_dma_free(job_ring->input_ring);
392         return NULL;
393 }
394
395
396 static int
397 caam_jr_dev_init(const char *name,
398                  struct rte_vdev_device *vdev,
399                  struct rte_cryptodev_pmd_init_params *init_params)
400 {
401         struct rte_cryptodev *dev;
402         struct uio_job_ring *job_ring;
403         char str[RTE_CRYPTODEV_NAME_MAX_LEN];
404
405         PMD_INIT_FUNC_TRACE();
406
407         /* Validate driver state */
408         if (g_driver_state == SEC_DRIVER_STATE_IDLE) {
409                 g_job_rings_max = sec_configure();
410                 if (!g_job_rings_max) {
411                         CAAM_JR_ERR("No job ring detected on UIO !!!!");
412                         return -1;
413                 }
414                 /* Update driver state */
415                 g_driver_state = SEC_DRIVER_STATE_STARTED;
416         }
417
418         if (g_job_rings_no >= g_job_rings_max) {
419                 CAAM_JR_ERR("No more job rings available max=%d!!!!",
420                                 g_job_rings_max);
421                 return -1;
422         }
423
424         job_ring = config_job_ring();
425         if (job_ring == NULL) {
426                 CAAM_JR_ERR("failed to create job ring");
427                 goto init_error;
428         }
429
430         snprintf(str, sizeof(str), "caam_jr%d", job_ring->jr_id);
431
432         dev = rte_cryptodev_pmd_create(name, &vdev->device, init_params);
433         if (dev == NULL) {
434                 CAAM_JR_ERR("failed to create cryptodev vdev");
435                 goto cleanup;
436         }
437         /*TODO free it during teardown*/
438         dev->data->dev_private = init_job_ring(job_ring->register_base_addr,
439                                                 job_ring->uio_fd);
440
441         if (!dev->data->dev_private) {
442                 CAAM_JR_ERR("Ring memory allocation failed\n");
443                 goto cleanup2;
444         }
445
446         dev->driver_id = cryptodev_driver_id;
447         dev->dev_ops = &caam_jr_ops;
448
449         /* register rx/tx burst functions for data path */
450         dev->dequeue_burst = NULL;
451         dev->enqueue_burst = NULL;
452         dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
453                         RTE_CRYPTODEV_FF_HW_ACCELERATED |
454                         RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
455                         RTE_CRYPTODEV_FF_SECURITY |
456                         RTE_CRYPTODEV_FF_IN_PLACE_SGL |
457                         RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT |
458                         RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT |
459                         RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT |
460                         RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT;
461
462         /* For secondary processes, we don't initialise any further as primary
463          * has already done this work. Only check we don't need a different
464          * RX function
465          */
466         if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
467                 CAAM_JR_WARN("Device already init by primary process");
468                 return 0;
469         }
470
471         RTE_LOG(INFO, PMD, "%s cryptodev init\n", dev->data->name);
472
473         return 0;
474
475 cleanup2:
476         caam_jr_dev_uninit(dev);
477         rte_cryptodev_pmd_release_device(dev);
478 cleanup:
479         free_job_ring(job_ring->uio_fd);
480 init_error:
481         CAAM_JR_ERR("driver %s: cryptodev_caam_jr_create failed",
482                         init_params->name);
483
484         return -ENXIO;
485 }
486
487 /** Initialise CAAM JR crypto device */
488 static int
489 cryptodev_caam_jr_probe(struct rte_vdev_device *vdev)
490 {
491         struct rte_cryptodev_pmd_init_params init_params = {
492                 "",
493                 sizeof(struct sec_job_ring_t),
494                 rte_socket_id(),
495                 RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS
496         };
497         const char *name;
498         const char *input_args;
499
500         name = rte_vdev_device_name(vdev);
501         if (name == NULL)
502                 return -EINVAL;
503
504         input_args = rte_vdev_device_args(vdev);
505         rte_cryptodev_pmd_parse_input_args(&init_params, input_args);
506
507         /* if sec device version is not configured */
508         if (!rta_get_sec_era()) {
509                 const struct device_node *caam_node;
510
511                 for_each_compatible_node(caam_node, NULL, "fsl,sec-v4.0") {
512                         const uint32_t *prop = of_get_property(caam_node,
513                                         "fsl,sec-era",
514                                         NULL);
515                         if (prop) {
516                                 rta_set_sec_era(
517                                         INTL_SEC_ERA(cpu_to_caam32(*prop)));
518                                 break;
519                         }
520                 }
521         }
522 #ifdef RTE_LIBRTE_PMD_CAAM_JR_BE
523         if (rta_get_sec_era() > RTA_SEC_ERA_8) {
524                 RTE_LOG(ERR, PMD,
525                 "CAAM is compiled in BE mode for device with sec era > 8???\n");
526                 return -EINVAL;
527         }
528 #endif
529
530         return caam_jr_dev_init(name, vdev, &init_params);
531 }
532
533 /** Uninitialise CAAM JR crypto device */
534 static int
535 cryptodev_caam_jr_remove(struct rte_vdev_device *vdev)
536 {
537         struct rte_cryptodev *cryptodev;
538         const char *name;
539
540         name = rte_vdev_device_name(vdev);
541         if (name == NULL)
542                 return -EINVAL;
543
544         cryptodev = rte_cryptodev_pmd_get_named_dev(name);
545         if (cryptodev == NULL)
546                 return -ENODEV;
547
548         caam_jr_dev_uninit(cryptodev);
549
550         return rte_cryptodev_pmd_destroy(cryptodev);
551 }
552
553 static struct rte_vdev_driver cryptodev_caam_jr_drv = {
554         .probe = cryptodev_caam_jr_probe,
555         .remove = cryptodev_caam_jr_remove
556 };
557
558 static struct cryptodev_driver caam_jr_crypto_drv;
559
560 RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_CAAM_JR_PMD, cryptodev_caam_jr_drv);
561 RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_CAAM_JR_PMD,
562         "max_nb_queue_pairs=<int>"
563         "socket_id=<int>");
564 RTE_PMD_REGISTER_CRYPTO_DRIVER(caam_jr_crypto_drv, cryptodev_caam_jr_drv.driver,
565                 cryptodev_driver_id);
566
567 RTE_INIT(caam_jr_init_log)
568 {
569         caam_jr_logtype = rte_log_register("pmd.crypto.caam");
570         if (caam_jr_logtype >= 0)
571                 rte_log_set_level(caam_jr_logtype, RTE_LOG_NOTICE);
572 }