1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2017 Intel Corporation
4 #include <rte_common.h>
5 #include <rte_hexdump.h>
6 #include <rte_cryptodev.h>
7 #include <rte_cryptodev_pmd.h>
8 #include <rte_bus_vdev.h>
9 #include <rte_malloc.h>
10 #include <rte_cpuflags.h>
11 #include <rte_reorder.h>
13 #include "rte_cryptodev_scheduler.h"
14 #include "scheduler_pmd_private.h"
16 uint8_t cryptodev_driver_id;
18 struct scheduler_init_params {
19 struct rte_cryptodev_pmd_init_params def_p;
21 enum rte_cryptodev_scheduler_mode mode;
22 uint32_t enable_ordering;
24 char slave_names[RTE_CRYPTODEV_SCHEDULER_MAX_NB_SLAVES]
25 [RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN];
28 #define RTE_CRYPTODEV_VDEV_NAME ("name")
29 #define RTE_CRYPTODEV_VDEV_SLAVE ("slave")
30 #define RTE_CRYPTODEV_VDEV_MODE ("mode")
31 #define RTE_CRYPTODEV_VDEV_ORDERING ("ordering")
32 #define RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG ("max_nb_queue_pairs")
33 #define RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG ("max_nb_sessions")
34 #define RTE_CRYPTODEV_VDEV_SOCKET_ID ("socket_id")
35 #define RTE_CRYPTODEV_VDEV_COREMASK ("coremask")
36 #define RTE_CRYPTODEV_VDEV_CORELIST ("corelist")
38 const char *scheduler_valid_params[] = {
39 RTE_CRYPTODEV_VDEV_NAME,
40 RTE_CRYPTODEV_VDEV_SLAVE,
41 RTE_CRYPTODEV_VDEV_MODE,
42 RTE_CRYPTODEV_VDEV_ORDERING,
43 RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
44 RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
45 RTE_CRYPTODEV_VDEV_SOCKET_ID,
46 RTE_CRYPTODEV_VDEV_COREMASK,
47 RTE_CRYPTODEV_VDEV_CORELIST
50 struct scheduler_parse_map {
55 const struct scheduler_parse_map scheduler_mode_map[] = {
56 {RTE_STR(SCHEDULER_MODE_NAME_ROUND_ROBIN),
57 CDEV_SCHED_MODE_ROUNDROBIN},
58 {RTE_STR(SCHEDULER_MODE_NAME_PKT_SIZE_DISTR),
59 CDEV_SCHED_MODE_PKT_SIZE_DISTR},
60 {RTE_STR(SCHEDULER_MODE_NAME_FAIL_OVER),
61 CDEV_SCHED_MODE_FAILOVER},
62 {RTE_STR(SCHEDULER_MODE_NAME_MULTI_CORE),
63 CDEV_SCHED_MODE_MULTICORE}
66 const struct scheduler_parse_map scheduler_ordering_map[] = {
72 cryptodev_scheduler_create(const char *name,
73 struct rte_vdev_device *vdev,
74 struct scheduler_init_params *init_params)
76 struct rte_cryptodev *dev;
77 struct scheduler_ctx *sched_ctx;
81 dev = rte_cryptodev_pmd_create(name, &vdev->device,
84 CS_LOG_ERR("driver %s: failed to create cryptodev vdev",
89 if (init_params->wcmask != 0)
90 RTE_LOG(INFO, PMD, " workers core mask = %"PRIx64"\n",
93 dev->driver_id = cryptodev_driver_id;
94 dev->dev_ops = rte_crypto_scheduler_pmd_ops;
96 sched_ctx = dev->data->dev_private;
97 sched_ctx->max_nb_queue_pairs =
98 init_params->def_p.max_nb_queue_pairs;
100 if (init_params->mode == CDEV_SCHED_MODE_MULTICORE) {
103 sched_ctx->nb_wc = 0;
105 for (i = 0; i < RTE_CRYPTODEV_SCHEDULER_MAX_NB_WORKER_CORES; i++) {
106 if (init_params->wcmask & (1ULL << i)) {
107 sched_ctx->wc_pool[sched_ctx->nb_wc++] = i;
109 " Worker core[%u]=%u added\n",
110 sched_ctx->nb_wc-1, i);
115 if (init_params->mode > CDEV_SCHED_MODE_USERDEFINED &&
116 init_params->mode < CDEV_SCHED_MODE_COUNT) {
117 ret = rte_cryptodev_scheduler_mode_set(dev->data->dev_id,
120 rte_cryptodev_pmd_release_device(dev);
124 for (i = 0; i < RTE_DIM(scheduler_mode_map); i++) {
125 if (scheduler_mode_map[i].val != sched_ctx->mode)
128 RTE_LOG(INFO, PMD, " Scheduling mode = %s\n",
129 scheduler_mode_map[i].name);
134 sched_ctx->reordering_enabled = init_params->enable_ordering;
136 for (i = 0; i < RTE_DIM(scheduler_ordering_map); i++) {
137 if (scheduler_ordering_map[i].val !=
138 sched_ctx->reordering_enabled)
141 RTE_LOG(INFO, PMD, " Packet ordering = %s\n",
142 scheduler_ordering_map[i].name);
147 for (i = 0; i < init_params->nb_slaves; i++) {
148 sched_ctx->init_slave_names[sched_ctx->nb_init_slaves] =
151 RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN, 0,
154 if (!sched_ctx->init_slave_names[
155 sched_ctx->nb_init_slaves]) {
156 CS_LOG_ERR("driver %s: Insufficient memory",
161 strncpy(sched_ctx->init_slave_names[
162 sched_ctx->nb_init_slaves],
163 init_params->slave_names[i],
164 RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN - 1);
166 sched_ctx->nb_init_slaves++;
170 * Initialize capabilities structure as an empty structure,
171 * in case device information is requested when no slaves are attached
173 sched_ctx->capabilities = rte_zmalloc_socket(NULL,
174 sizeof(struct rte_cryptodev_capabilities),
177 if (!sched_ctx->capabilities) {
178 RTE_LOG(ERR, PMD, "Not enough memory for capability "
187 cryptodev_scheduler_remove(struct rte_vdev_device *vdev)
190 struct rte_cryptodev *dev;
191 struct scheduler_ctx *sched_ctx;
196 name = rte_vdev_device_name(vdev);
197 dev = rte_cryptodev_pmd_get_named_dev(name);
201 sched_ctx = dev->data->dev_private;
203 if (sched_ctx->nb_slaves) {
206 for (i = 0; i < sched_ctx->nb_slaves; i++)
207 rte_cryptodev_scheduler_slave_detach(dev->data->dev_id,
208 sched_ctx->slaves[i].dev_id);
211 return rte_cryptodev_pmd_destroy(dev);
214 /** Parse integer from integer argument */
216 parse_integer_arg(const char *key __rte_unused,
217 const char *value, void *extra_args)
219 int *i = (int *) extra_args;
223 CS_LOG_ERR("Argument has to be positive.\n");
230 /** Parse integer from hexadecimal integer argument */
232 parse_coremask_arg(const char *key __rte_unused,
233 const char *value, void *extra_args)
235 struct scheduler_init_params *params = extra_args;
237 params->wcmask = strtoull(value, NULL, 16);
242 /** Parse integer from list of integers argument */
244 parse_corelist_arg(const char *key __rte_unused,
245 const char *value, void *extra_args)
247 struct scheduler_init_params *params = extra_args;
249 params->wcmask = 0ULL;
251 const char *token = value;
253 while (isdigit(token[0])) {
255 unsigned int core = strtoul(token, &rval, 10);
257 params->wcmask |= 1ULL << core;
258 token = (const char *)rval;
259 if (token[0] == '\0')
269 parse_name_arg(const char *key __rte_unused,
270 const char *value, void *extra_args)
272 struct rte_cryptodev_pmd_init_params *params = extra_args;
274 if (strlen(value) >= RTE_CRYPTODEV_NAME_MAX_LEN - 1) {
275 CS_LOG_ERR("Invalid name %s, should be less than "
276 "%u bytes.\n", value,
277 RTE_CRYPTODEV_NAME_MAX_LEN - 1);
281 strncpy(params->name, value, RTE_CRYPTODEV_NAME_MAX_LEN);
288 parse_slave_arg(const char *key __rte_unused,
289 const char *value, void *extra_args)
291 struct scheduler_init_params *param = extra_args;
293 if (param->nb_slaves >= RTE_CRYPTODEV_SCHEDULER_MAX_NB_SLAVES) {
294 CS_LOG_ERR("Too many slaves.\n");
298 strncpy(param->slave_names[param->nb_slaves++], value,
299 RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN - 1);
305 parse_mode_arg(const char *key __rte_unused,
306 const char *value, void *extra_args)
308 struct scheduler_init_params *param = extra_args;
311 for (i = 0; i < RTE_DIM(scheduler_mode_map); i++) {
312 if (strcmp(value, scheduler_mode_map[i].name) == 0) {
313 param->mode = (enum rte_cryptodev_scheduler_mode)
314 scheduler_mode_map[i].val;
319 if (i == RTE_DIM(scheduler_mode_map)) {
320 CS_LOG_ERR("Unrecognized input.\n");
328 parse_ordering_arg(const char *key __rte_unused,
329 const char *value, void *extra_args)
331 struct scheduler_init_params *param = extra_args;
334 for (i = 0; i < RTE_DIM(scheduler_ordering_map); i++) {
335 if (strcmp(value, scheduler_ordering_map[i].name) == 0) {
336 param->enable_ordering =
337 scheduler_ordering_map[i].val;
342 if (i == RTE_DIM(scheduler_ordering_map)) {
343 CS_LOG_ERR("Unrecognized input.\n");
351 scheduler_parse_init_params(struct scheduler_init_params *params,
352 const char *input_args)
354 struct rte_kvargs *kvlist = NULL;
361 kvlist = rte_kvargs_parse(input_args,
362 scheduler_valid_params);
366 ret = rte_kvargs_process(kvlist,
367 RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
369 ¶ms->def_p.max_nb_queue_pairs);
373 ret = rte_kvargs_process(kvlist,
374 RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
376 ¶ms->def_p.max_nb_sessions);
380 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_SOCKET_ID,
382 ¶ms->def_p.socket_id);
386 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_COREMASK,
392 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_CORELIST,
398 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_NAME,
404 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_SLAVE,
405 &parse_slave_arg, params);
409 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_MODE,
410 &parse_mode_arg, params);
414 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_ORDERING,
415 &parse_ordering_arg, params);
421 rte_kvargs_free(kvlist);
426 cryptodev_scheduler_probe(struct rte_vdev_device *vdev)
428 struct scheduler_init_params init_params = {
431 sizeof(struct scheduler_ctx),
433 RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS,
434 RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_SESSIONS
437 .mode = CDEV_SCHED_MODE_NOT_SET,
438 .enable_ordering = 0,
439 .slave_names = { {0} }
443 name = rte_vdev_device_name(vdev);
447 scheduler_parse_init_params(&init_params,
448 rte_vdev_device_args(vdev));
451 return cryptodev_scheduler_create(name,
456 static struct rte_vdev_driver cryptodev_scheduler_pmd_drv = {
457 .probe = cryptodev_scheduler_probe,
458 .remove = cryptodev_scheduler_remove
461 static struct cryptodev_driver scheduler_crypto_drv;
463 RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_SCHEDULER_PMD,
464 cryptodev_scheduler_pmd_drv);
465 RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_SCHEDULER_PMD,
466 "max_nb_queue_pairs=<int> "
467 "max_nb_sessions=<int> "
470 RTE_PMD_REGISTER_CRYPTO_DRIVER(scheduler_crypto_drv,
471 cryptodev_scheduler_pmd_drv.driver,
472 cryptodev_driver_id);