15566a3e3SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
25566a3e3SBruce Richardson * Copyright(c) 2017 Intel Corporation
3503e9c5aSFan Zhang */
472b452c5SDmitry Kozlyuk #include <ctype.h>
572b452c5SDmitry Kozlyuk #include <stdlib.h>
672b452c5SDmitry Kozlyuk
7503e9c5aSFan Zhang #include <rte_common.h>
8503e9c5aSFan Zhang #include <rte_hexdump.h>
9503e9c5aSFan Zhang #include <rte_cryptodev.h>
10af668035SAkhil Goyal #include <cryptodev_pmd.h>
11e2af4e40SDavid Coyle #include <rte_security_driver.h>
124851ef2bSDavid Marchand #include <bus_vdev_driver.h>
13503e9c5aSFan Zhang #include <rte_malloc.h>
14503e9c5aSFan Zhang #include <rte_cpuflags.h>
15503e9c5aSFan Zhang #include <rte_reorder.h>
16ee9586ddSFan Zhang #include <rte_string_fns.h>
17503e9c5aSFan Zhang
18b88161beSBruce Richardson #include "rte_cryptodev_scheduler.h"
19503e9c5aSFan Zhang #include "scheduler_pmd_private.h"
20503e9c5aSFan Zhang
21520dd992SFerruh Yigit uint8_t cryptodev_scheduler_driver_id;
227a364faeSSlawomir Mrozowicz
23503e9c5aSFan Zhang struct scheduler_init_params {
24f2f020d2SDeclan Doherty struct rte_cryptodev_pmd_init_params def_p;
2585b00824SAdam Dybkowski uint32_t nb_workers;
26a0e805eeSFan Zhang enum rte_cryptodev_scheduler_mode mode;
27ee9586ddSFan Zhang char mode_param_str[RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN];
28a0e805eeSFan Zhang uint32_t enable_ordering;
291b78e3f2SKirill Rybalchenko uint16_t wc_pool[RTE_MAX_LCORE];
301b78e3f2SKirill Rybalchenko uint16_t nb_wc;
3185b00824SAdam Dybkowski char worker_names[RTE_CRYPTODEV_SCHEDULER_MAX_NB_WORKERS]
3250e14527SFan Zhang [RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN];
33503e9c5aSFan Zhang };
34503e9c5aSFan Zhang
35503e9c5aSFan Zhang #define RTE_CRYPTODEV_VDEV_NAME ("name")
3685b00824SAdam Dybkowski #define RTE_CRYPTODEV_VDEV_WORKER ("worker")
37a0e805eeSFan Zhang #define RTE_CRYPTODEV_VDEV_MODE ("mode")
38ee9586ddSFan Zhang #define RTE_CRYPTODEV_VDEV_MODE_PARAM ("mode_param")
39a0e805eeSFan Zhang #define RTE_CRYPTODEV_VDEV_ORDERING ("ordering")
40503e9c5aSFan Zhang #define RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG ("max_nb_queue_pairs")
41503e9c5aSFan Zhang #define RTE_CRYPTODEV_VDEV_SOCKET_ID ("socket_id")
424c07e055SKirill Rybalchenko #define RTE_CRYPTODEV_VDEV_COREMASK ("coremask")
434c07e055SKirill Rybalchenko #define RTE_CRYPTODEV_VDEV_CORELIST ("corelist")
44503e9c5aSFan Zhang
45b74fd6b8SFerruh Yigit static const char * const scheduler_valid_params[] = {
46503e9c5aSFan Zhang RTE_CRYPTODEV_VDEV_NAME,
4785b00824SAdam Dybkowski RTE_CRYPTODEV_VDEV_WORKER,
48a0e805eeSFan Zhang RTE_CRYPTODEV_VDEV_MODE,
49ee9586ddSFan Zhang RTE_CRYPTODEV_VDEV_MODE_PARAM,
50a0e805eeSFan Zhang RTE_CRYPTODEV_VDEV_ORDERING,
51503e9c5aSFan Zhang RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
524c07e055SKirill Rybalchenko RTE_CRYPTODEV_VDEV_SOCKET_ID,
534c07e055SKirill Rybalchenko RTE_CRYPTODEV_VDEV_COREMASK,
5434019b7bSCiara Power RTE_CRYPTODEV_VDEV_CORELIST,
5534019b7bSCiara Power NULL
56503e9c5aSFan Zhang };
57503e9c5aSFan Zhang
58a0e805eeSFan Zhang struct scheduler_parse_map {
59a0e805eeSFan Zhang const char *name;
60a0e805eeSFan Zhang uint32_t val;
61a0e805eeSFan Zhang };
62a0e805eeSFan Zhang
63a0e805eeSFan Zhang const struct scheduler_parse_map scheduler_mode_map[] = {
64a0e805eeSFan Zhang {RTE_STR(SCHEDULER_MODE_NAME_ROUND_ROBIN),
65a0e805eeSFan Zhang CDEV_SCHED_MODE_ROUNDROBIN},
66a0e805eeSFan Zhang {RTE_STR(SCHEDULER_MODE_NAME_PKT_SIZE_DISTR),
67a0e805eeSFan Zhang CDEV_SCHED_MODE_PKT_SIZE_DISTR},
68a0e805eeSFan Zhang {RTE_STR(SCHEDULER_MODE_NAME_FAIL_OVER),
694c07e055SKirill Rybalchenko CDEV_SCHED_MODE_FAILOVER},
704c07e055SKirill Rybalchenko {RTE_STR(SCHEDULER_MODE_NAME_MULTI_CORE),
714c07e055SKirill Rybalchenko CDEV_SCHED_MODE_MULTICORE}
72a0e805eeSFan Zhang };
73a0e805eeSFan Zhang
74a0e805eeSFan Zhang const struct scheduler_parse_map scheduler_ordering_map[] = {
75a0e805eeSFan Zhang {"enable", 1},
76a0e805eeSFan Zhang {"disable", 0}
77a0e805eeSFan Zhang };
78a0e805eeSFan Zhang
796760463cSFan Zhang #define CDEV_SCHED_MODE_PARAM_SEP_CHAR ':'
806760463cSFan Zhang
81e2af4e40SDavid Coyle static void
free_mem(struct rte_cryptodev * dev)82e2af4e40SDavid Coyle free_mem(struct rte_cryptodev *dev)
83e2af4e40SDavid Coyle {
84e2af4e40SDavid Coyle struct scheduler_ctx *sched_ctx = dev->data->dev_private;
85e2af4e40SDavid Coyle int i;
86e2af4e40SDavid Coyle
87e2af4e40SDavid Coyle for (i = 0; i < sched_ctx->nb_init_workers; i++) {
88e2af4e40SDavid Coyle rte_free(sched_ctx->init_worker_names[i]);
89e2af4e40SDavid Coyle sched_ctx->init_worker_names[i] = NULL;
90e2af4e40SDavid Coyle }
91e2af4e40SDavid Coyle
92e2af4e40SDavid Coyle scheduler_free_capabilities(sched_ctx);
93e2af4e40SDavid Coyle
94e2af4e40SDavid Coyle rte_free(dev->security_ctx);
95e2af4e40SDavid Coyle dev->security_ctx = NULL;
96e2af4e40SDavid Coyle }
97e2af4e40SDavid Coyle
98503e9c5aSFan Zhang static int
cryptodev_scheduler_create(const char * name,struct rte_vdev_device * vdev,struct scheduler_init_params * init_params)99503e9c5aSFan Zhang cryptodev_scheduler_create(const char *name,
100917ac9c4SPablo de Lara struct rte_vdev_device *vdev,
101503e9c5aSFan Zhang struct scheduler_init_params *init_params)
102503e9c5aSFan Zhang {
103503e9c5aSFan Zhang struct rte_cryptodev *dev;
104503e9c5aSFan Zhang struct scheduler_ctx *sched_ctx;
105a0e805eeSFan Zhang uint32_t i;
106a0e805eeSFan Zhang int ret;
107503e9c5aSFan Zhang
108f2f020d2SDeclan Doherty dev = rte_cryptodev_pmd_create(name, &vdev->device,
109f2f020d2SDeclan Doherty &init_params->def_p);
110503e9c5aSFan Zhang if (dev == NULL) {
11185aa6d34SHari Kumar CR_SCHED_LOG(ERR, "driver %s: failed to create cryptodev vdev",
112503e9c5aSFan Zhang name);
113503e9c5aSFan Zhang return -EFAULT;
114503e9c5aSFan Zhang }
115503e9c5aSFan Zhang
116520dd992SFerruh Yigit dev->driver_id = cryptodev_scheduler_driver_id;
117503e9c5aSFan Zhang dev->dev_ops = rte_crypto_scheduler_pmd_ops;
118503e9c5aSFan Zhang
119503e9c5aSFan Zhang sched_ctx = dev->data->dev_private;
120503e9c5aSFan Zhang sched_ctx->max_nb_queue_pairs =
121503e9c5aSFan Zhang init_params->def_p.max_nb_queue_pairs;
122503e9c5aSFan Zhang
1234c07e055SKirill Rybalchenko if (init_params->mode == CDEV_SCHED_MODE_MULTICORE) {
1244c07e055SKirill Rybalchenko uint16_t i;
1254c07e055SKirill Rybalchenko
1261b78e3f2SKirill Rybalchenko sched_ctx->nb_wc = init_params->nb_wc;
1274c07e055SKirill Rybalchenko
1281b78e3f2SKirill Rybalchenko for (i = 0; i < sched_ctx->nb_wc; i++) {
1291b78e3f2SKirill Rybalchenko sched_ctx->wc_pool[i] = init_params->wc_pool[i];
13085aa6d34SHari Kumar CR_SCHED_LOG(INFO, " Worker core[%u]=%u added",
1311b78e3f2SKirill Rybalchenko i, sched_ctx->wc_pool[i]);
1324c07e055SKirill Rybalchenko }
1334c07e055SKirill Rybalchenko }
1344c07e055SKirill Rybalchenko
135a0e805eeSFan Zhang if (init_params->mode > CDEV_SCHED_MODE_USERDEFINED &&
136a0e805eeSFan Zhang init_params->mode < CDEV_SCHED_MODE_COUNT) {
1376760463cSFan Zhang union {
1386760463cSFan Zhang struct rte_cryptodev_scheduler_threshold_option
1396760463cSFan Zhang threshold_option;
1406760463cSFan Zhang } option;
1416760463cSFan Zhang enum rte_cryptodev_schedule_option_type option_type;
1426760463cSFan Zhang char param_name[RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN] = {0};
1436760463cSFan Zhang char param_val[RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN] = {0};
1446760463cSFan Zhang char *s, *end;
1456760463cSFan Zhang
1463fb45fdbSFan Zhang ret = rte_cryptodev_scheduler_mode_set(dev->data->dev_id,
147a0e805eeSFan Zhang init_params->mode);
148a0e805eeSFan Zhang if (ret < 0) {
149a0e805eeSFan Zhang rte_cryptodev_pmd_release_device(dev);
150a0e805eeSFan Zhang return ret;
151a0e805eeSFan Zhang }
152a0e805eeSFan Zhang
153a0e805eeSFan Zhang for (i = 0; i < RTE_DIM(scheduler_mode_map); i++) {
154a0e805eeSFan Zhang if (scheduler_mode_map[i].val != sched_ctx->mode)
155a0e805eeSFan Zhang continue;
156a0e805eeSFan Zhang
15785aa6d34SHari Kumar CR_SCHED_LOG(INFO, " Scheduling mode = %s",
158a0e805eeSFan Zhang scheduler_mode_map[i].name);
159a0e805eeSFan Zhang break;
160a0e805eeSFan Zhang }
1616760463cSFan Zhang
1626760463cSFan Zhang if (strlen(init_params->mode_param_str) > 0) {
1636760463cSFan Zhang s = strchr(init_params->mode_param_str,
1646760463cSFan Zhang CDEV_SCHED_MODE_PARAM_SEP_CHAR);
1656760463cSFan Zhang if (s == NULL) {
1666760463cSFan Zhang CR_SCHED_LOG(ERR, "Invalid mode param");
1676760463cSFan Zhang return -EINVAL;
1686760463cSFan Zhang }
1696760463cSFan Zhang
1706760463cSFan Zhang strlcpy(param_name, init_params->mode_param_str,
1716760463cSFan Zhang s - init_params->mode_param_str + 1);
1726760463cSFan Zhang s++;
1736760463cSFan Zhang strlcpy(param_val, s,
1746760463cSFan Zhang RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN);
1756760463cSFan Zhang
1766760463cSFan Zhang switch (init_params->mode) {
1776760463cSFan Zhang case CDEV_SCHED_MODE_PKT_SIZE_DISTR:
1786760463cSFan Zhang if (strcmp(param_name,
1796760463cSFan Zhang RTE_CRYPTODEV_SCHEDULER_PARAM_THRES)
1806760463cSFan Zhang != 0) {
1816760463cSFan Zhang CR_SCHED_LOG(ERR, "Invalid mode param");
1826760463cSFan Zhang return -EINVAL;
1836760463cSFan Zhang }
1846760463cSFan Zhang option_type = CDEV_SCHED_OPTION_THRESHOLD;
1856760463cSFan Zhang
1866760463cSFan Zhang option.threshold_option.threshold =
1876760463cSFan Zhang strtoul(param_val, &end, 0);
1886760463cSFan Zhang break;
1896760463cSFan Zhang default:
1906760463cSFan Zhang CR_SCHED_LOG(ERR, "Invalid mode param");
1916760463cSFan Zhang return -EINVAL;
1926760463cSFan Zhang }
1936760463cSFan Zhang
1946760463cSFan Zhang if (sched_ctx->ops.option_set(dev, option_type,
1956760463cSFan Zhang (void *)&option) < 0) {
1966760463cSFan Zhang CR_SCHED_LOG(ERR, "Invalid mode param");
1976760463cSFan Zhang return -EINVAL;
1986760463cSFan Zhang }
1996760463cSFan Zhang
200*a247fcd9SStephen Hemminger CR_SCHED_LOG(INFO, " Sched mode param (%s = %s)",
2016760463cSFan Zhang param_name, param_val);
2026760463cSFan Zhang }
203a0e805eeSFan Zhang }
204a0e805eeSFan Zhang
205a0e805eeSFan Zhang sched_ctx->reordering_enabled = init_params->enable_ordering;
206a0e805eeSFan Zhang
207a0e805eeSFan Zhang for (i = 0; i < RTE_DIM(scheduler_ordering_map); i++) {
208a0e805eeSFan Zhang if (scheduler_ordering_map[i].val !=
209a0e805eeSFan Zhang sched_ctx->reordering_enabled)
210a0e805eeSFan Zhang continue;
211a0e805eeSFan Zhang
21285aa6d34SHari Kumar CR_SCHED_LOG(INFO, " Packet ordering = %s",
213a0e805eeSFan Zhang scheduler_ordering_map[i].name);
214a0e805eeSFan Zhang
215a0e805eeSFan Zhang break;
216a0e805eeSFan Zhang }
217a0e805eeSFan Zhang
21885b00824SAdam Dybkowski for (i = 0; i < init_params->nb_workers; i++) {
21985b00824SAdam Dybkowski sched_ctx->init_worker_names[sched_ctx->nb_init_workers] =
22050e14527SFan Zhang rte_zmalloc_socket(
22150e14527SFan Zhang NULL,
22250e14527SFan Zhang RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN, 0,
22350e14527SFan Zhang SOCKET_ID_ANY);
22450e14527SFan Zhang
22585b00824SAdam Dybkowski if (!sched_ctx->init_worker_names[
22685b00824SAdam Dybkowski sched_ctx->nb_init_workers]) {
227e2af4e40SDavid Coyle CR_SCHED_LOG(ERR, "Not enough memory for init worker name");
228e2af4e40SDavid Coyle free_mem(dev);
22950e14527SFan Zhang return -ENOMEM;
23050e14527SFan Zhang }
23150e14527SFan Zhang
23285b00824SAdam Dybkowski strncpy(sched_ctx->init_worker_names[
23385b00824SAdam Dybkowski sched_ctx->nb_init_workers],
23485b00824SAdam Dybkowski init_params->worker_names[i],
23550e14527SFan Zhang RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN - 1);
23650e14527SFan Zhang
23785b00824SAdam Dybkowski sched_ctx->nb_init_workers++;
23850e14527SFan Zhang }
23950e14527SFan Zhang
240c570f262SPablo de Lara /*
241c570f262SPablo de Lara * Initialize capabilities structure as an empty structure,
24285b00824SAdam Dybkowski * in case device information is requested when no workers are attached
243c570f262SPablo de Lara */
244c570f262SPablo de Lara sched_ctx->capabilities = rte_zmalloc_socket(NULL,
245c570f262SPablo de Lara sizeof(struct rte_cryptodev_capabilities),
246c570f262SPablo de Lara 0, SOCKET_ID_ANY);
247c570f262SPablo de Lara
248c570f262SPablo de Lara if (!sched_ctx->capabilities) {
249e2af4e40SDavid Coyle CR_SCHED_LOG(ERR, "Not enough memory for capability information");
250e2af4e40SDavid Coyle free_mem(dev);
251e2af4e40SDavid Coyle return -ENOMEM;
252e2af4e40SDavid Coyle }
253e2af4e40SDavid Coyle
254e2af4e40SDavid Coyle /* Initialize security context */
255e2af4e40SDavid Coyle struct rte_security_ctx *security_instance;
256e2af4e40SDavid Coyle security_instance = rte_zmalloc_socket(NULL,
257e2af4e40SDavid Coyle sizeof(struct rte_security_ctx),
258e2af4e40SDavid Coyle RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
259e2af4e40SDavid Coyle if (!security_instance) {
260e2af4e40SDavid Coyle CR_SCHED_LOG(ERR, "Not enough memory for security context");
261e2af4e40SDavid Coyle free_mem(dev);
262e2af4e40SDavid Coyle return -ENOMEM;
263e2af4e40SDavid Coyle }
264e2af4e40SDavid Coyle
265e2af4e40SDavid Coyle security_instance->device = dev;
266e2af4e40SDavid Coyle security_instance->ops = rte_crypto_scheduler_pmd_sec_ops;
267e2af4e40SDavid Coyle security_instance->sess_cnt = 0;
268e2af4e40SDavid Coyle dev->security_ctx = security_instance;
269e2af4e40SDavid Coyle
270e2af4e40SDavid Coyle /*
271e2af4e40SDavid Coyle * Initialize security capabilities structure as an empty structure,
272e2af4e40SDavid Coyle * in case device information is requested when no workers are attached
273e2af4e40SDavid Coyle */
274e2af4e40SDavid Coyle sched_ctx->sec_capabilities = rte_zmalloc_socket(NULL,
275e2af4e40SDavid Coyle sizeof(struct rte_security_capability),
276e2af4e40SDavid Coyle 0, SOCKET_ID_ANY);
277e2af4e40SDavid Coyle
278e2af4e40SDavid Coyle if (!sched_ctx->sec_capabilities) {
279e2af4e40SDavid Coyle CR_SCHED_LOG(ERR, "Not enough memory for security capability information");
280e2af4e40SDavid Coyle free_mem(dev);
281c570f262SPablo de Lara return -ENOMEM;
282c570f262SPablo de Lara }
283c570f262SPablo de Lara
284d54c72ecSAkhil Goyal rte_cryptodev_pmd_probing_finish(dev);
285d54c72ecSAkhil Goyal
286a0e805eeSFan Zhang return 0;
287503e9c5aSFan Zhang }
288503e9c5aSFan Zhang
289503e9c5aSFan Zhang static int
cryptodev_scheduler_remove(struct rte_vdev_device * vdev)2905d2aa461SJan Blunck cryptodev_scheduler_remove(struct rte_vdev_device *vdev)
291503e9c5aSFan Zhang {
2925d2aa461SJan Blunck const char *name;
293503e9c5aSFan Zhang struct rte_cryptodev *dev;
294503e9c5aSFan Zhang struct scheduler_ctx *sched_ctx;
295503e9c5aSFan Zhang
2965d2aa461SJan Blunck if (vdev == NULL)
297503e9c5aSFan Zhang return -EINVAL;
298503e9c5aSFan Zhang
2995d2aa461SJan Blunck name = rte_vdev_device_name(vdev);
300503e9c5aSFan Zhang dev = rte_cryptodev_pmd_get_named_dev(name);
301503e9c5aSFan Zhang if (dev == NULL)
302503e9c5aSFan Zhang return -EINVAL;
303503e9c5aSFan Zhang
304503e9c5aSFan Zhang sched_ctx = dev->data->dev_private;
305503e9c5aSFan Zhang
30685b00824SAdam Dybkowski if (sched_ctx->nb_workers) {
307503e9c5aSFan Zhang uint32_t i;
308503e9c5aSFan Zhang
30985b00824SAdam Dybkowski for (i = 0; i < sched_ctx->nb_workers; i++)
31085b00824SAdam Dybkowski rte_cryptodev_scheduler_worker_detach(dev->data->dev_id,
31185b00824SAdam Dybkowski sched_ctx->workers[i].dev_id);
312503e9c5aSFan Zhang }
313503e9c5aSFan Zhang
314e2af4e40SDavid Coyle rte_free(dev->security_ctx);
315e2af4e40SDavid Coyle dev->security_ctx = NULL;
316e2af4e40SDavid Coyle
317f2f020d2SDeclan Doherty return rte_cryptodev_pmd_destroy(dev);
318503e9c5aSFan Zhang }
319503e9c5aSFan Zhang
320503e9c5aSFan Zhang /** Parse integer from integer argument */
321503e9c5aSFan Zhang static int
parse_integer_arg(const char * key __rte_unused,const char * value,void * extra_args)322503e9c5aSFan Zhang parse_integer_arg(const char *key __rte_unused,
323503e9c5aSFan Zhang const char *value, void *extra_args)
324503e9c5aSFan Zhang {
325503e9c5aSFan Zhang int *i = (int *) extra_args;
326503e9c5aSFan Zhang
327503e9c5aSFan Zhang *i = atoi(value);
328503e9c5aSFan Zhang if (*i < 0) {
32985aa6d34SHari Kumar CR_SCHED_LOG(ERR, "Argument has to be positive.");
330a0e805eeSFan Zhang return -EINVAL;
331503e9c5aSFan Zhang }
332503e9c5aSFan Zhang
333503e9c5aSFan Zhang return 0;
334503e9c5aSFan Zhang }
335503e9c5aSFan Zhang
3364c07e055SKirill Rybalchenko /** Parse integer from hexadecimal integer argument */
3374c07e055SKirill Rybalchenko static int
parse_coremask_arg(const char * key __rte_unused,const char * value,void * extra_args)3384c07e055SKirill Rybalchenko parse_coremask_arg(const char *key __rte_unused,
3394c07e055SKirill Rybalchenko const char *value, void *extra_args)
3404c07e055SKirill Rybalchenko {
3411b78e3f2SKirill Rybalchenko int i, j, val;
3421b78e3f2SKirill Rybalchenko uint16_t idx = 0;
3431b78e3f2SKirill Rybalchenko char c;
3444c07e055SKirill Rybalchenko struct scheduler_init_params *params = extra_args;
3454c07e055SKirill Rybalchenko
3461b78e3f2SKirill Rybalchenko params->nb_wc = 0;
3471b78e3f2SKirill Rybalchenko
3481b78e3f2SKirill Rybalchenko if (value == NULL)
3491b78e3f2SKirill Rybalchenko return -1;
3501b78e3f2SKirill Rybalchenko /* Remove all blank characters ahead and after .
3511b78e3f2SKirill Rybalchenko * Remove 0x/0X if exists.
3521b78e3f2SKirill Rybalchenko */
3531b78e3f2SKirill Rybalchenko while (isblank(*value))
3541b78e3f2SKirill Rybalchenko value++;
3551b78e3f2SKirill Rybalchenko if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X')))
3561b78e3f2SKirill Rybalchenko value += 2;
3571b78e3f2SKirill Rybalchenko i = strlen(value);
3581b78e3f2SKirill Rybalchenko while ((i > 0) && isblank(value[i - 1]))
3591b78e3f2SKirill Rybalchenko i--;
3601b78e3f2SKirill Rybalchenko
3611b78e3f2SKirill Rybalchenko if (i == 0)
3621b78e3f2SKirill Rybalchenko return -1;
3631b78e3f2SKirill Rybalchenko
3641b78e3f2SKirill Rybalchenko for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) {
3651b78e3f2SKirill Rybalchenko c = value[i];
3661b78e3f2SKirill Rybalchenko if (isxdigit(c) == 0) {
3671b78e3f2SKirill Rybalchenko /* invalid characters */
3681b78e3f2SKirill Rybalchenko return -1;
3691b78e3f2SKirill Rybalchenko }
3701b78e3f2SKirill Rybalchenko if (isdigit(c))
3711b78e3f2SKirill Rybalchenko val = c - '0';
3721b78e3f2SKirill Rybalchenko else if (isupper(c))
3731b78e3f2SKirill Rybalchenko val = c - 'A' + 10;
3741b78e3f2SKirill Rybalchenko else
3751b78e3f2SKirill Rybalchenko val = c - 'a' + 10;
3761b78e3f2SKirill Rybalchenko
3771b78e3f2SKirill Rybalchenko for (j = 0; j < 4 && idx < RTE_MAX_LCORE; j++, idx++) {
3781b78e3f2SKirill Rybalchenko if ((1 << j) & val)
3791b78e3f2SKirill Rybalchenko params->wc_pool[params->nb_wc++] = idx;
3801b78e3f2SKirill Rybalchenko }
3811b78e3f2SKirill Rybalchenko }
3824c07e055SKirill Rybalchenko
3834c07e055SKirill Rybalchenko return 0;
3844c07e055SKirill Rybalchenko }
3854c07e055SKirill Rybalchenko
3864c07e055SKirill Rybalchenko /** Parse integer from list of integers argument */
3874c07e055SKirill Rybalchenko static int
parse_corelist_arg(const char * key __rte_unused,const char * value,void * extra_args)3884c07e055SKirill Rybalchenko parse_corelist_arg(const char *key __rte_unused,
3894c07e055SKirill Rybalchenko const char *value, void *extra_args)
3904c07e055SKirill Rybalchenko {
3914c07e055SKirill Rybalchenko struct scheduler_init_params *params = extra_args;
3924c07e055SKirill Rybalchenko
3931b78e3f2SKirill Rybalchenko params->nb_wc = 0;
3944c07e055SKirill Rybalchenko
3954c07e055SKirill Rybalchenko const char *token = value;
3964c07e055SKirill Rybalchenko
3974c07e055SKirill Rybalchenko while (isdigit(token[0])) {
3984c07e055SKirill Rybalchenko char *rval;
3994c07e055SKirill Rybalchenko unsigned int core = strtoul(token, &rval, 10);
4004c07e055SKirill Rybalchenko
4011b78e3f2SKirill Rybalchenko if (core >= RTE_MAX_LCORE) {
40285aa6d34SHari Kumar CR_SCHED_LOG(ERR, "Invalid worker core %u, should be smaller "
40385aa6d34SHari Kumar "than %u.", core, RTE_MAX_LCORE);
4041b78e3f2SKirill Rybalchenko }
4051b78e3f2SKirill Rybalchenko params->wc_pool[params->nb_wc++] = (uint16_t)core;
4064c07e055SKirill Rybalchenko token = (const char *)rval;
4074c07e055SKirill Rybalchenko if (token[0] == '\0')
4084c07e055SKirill Rybalchenko break;
4094c07e055SKirill Rybalchenko token++;
4104c07e055SKirill Rybalchenko }
4114c07e055SKirill Rybalchenko
4124c07e055SKirill Rybalchenko return 0;
4134c07e055SKirill Rybalchenko }
4144c07e055SKirill Rybalchenko
415503e9c5aSFan Zhang /** Parse name */
416503e9c5aSFan Zhang static int
parse_name_arg(const char * key __rte_unused,const char * value,void * extra_args)417503e9c5aSFan Zhang parse_name_arg(const char *key __rte_unused,
418503e9c5aSFan Zhang const char *value, void *extra_args)
419503e9c5aSFan Zhang {
420f2f020d2SDeclan Doherty struct rte_cryptodev_pmd_init_params *params = extra_args;
421503e9c5aSFan Zhang
422503e9c5aSFan Zhang if (strlen(value) >= RTE_CRYPTODEV_NAME_MAX_LEN - 1) {
42385aa6d34SHari Kumar CR_SCHED_LOG(ERR, "Invalid name %s, should be less than "
42485aa6d34SHari Kumar "%u bytes.", value,
425503e9c5aSFan Zhang RTE_CRYPTODEV_NAME_MAX_LEN - 1);
426a0e805eeSFan Zhang return -EINVAL;
427503e9c5aSFan Zhang }
428503e9c5aSFan Zhang
429e5e193acSJerin Jacob strlcpy(params->name, value, RTE_CRYPTODEV_NAME_MAX_LEN);
430503e9c5aSFan Zhang
431503e9c5aSFan Zhang return 0;
432503e9c5aSFan Zhang }
433503e9c5aSFan Zhang
43485b00824SAdam Dybkowski /** Parse worker */
435503e9c5aSFan Zhang static int
parse_worker_arg(const char * key __rte_unused,const char * value,void * extra_args)43685b00824SAdam Dybkowski parse_worker_arg(const char *key __rte_unused,
437503e9c5aSFan Zhang const char *value, void *extra_args)
438503e9c5aSFan Zhang {
439503e9c5aSFan Zhang struct scheduler_init_params *param = extra_args;
440503e9c5aSFan Zhang
44185b00824SAdam Dybkowski if (param->nb_workers >= RTE_CRYPTODEV_SCHEDULER_MAX_NB_WORKERS) {
44285b00824SAdam Dybkowski CR_SCHED_LOG(ERR, "Too many workers.");
443a0e805eeSFan Zhang return -ENOMEM;
444503e9c5aSFan Zhang }
445503e9c5aSFan Zhang
44685b00824SAdam Dybkowski strncpy(param->worker_names[param->nb_workers++], value,
44750e14527SFan Zhang RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN - 1);
448503e9c5aSFan Zhang
449503e9c5aSFan Zhang return 0;
450503e9c5aSFan Zhang }
451503e9c5aSFan Zhang
452503e9c5aSFan Zhang static int
parse_mode_arg(const char * key __rte_unused,const char * value,void * extra_args)453a0e805eeSFan Zhang parse_mode_arg(const char *key __rte_unused,
454a0e805eeSFan Zhang const char *value, void *extra_args)
455a0e805eeSFan Zhang {
456a0e805eeSFan Zhang struct scheduler_init_params *param = extra_args;
457a0e805eeSFan Zhang uint32_t i;
458a0e805eeSFan Zhang
459a0e805eeSFan Zhang for (i = 0; i < RTE_DIM(scheduler_mode_map); i++) {
460a0e805eeSFan Zhang if (strcmp(value, scheduler_mode_map[i].name) == 0) {
461a0e805eeSFan Zhang param->mode = (enum rte_cryptodev_scheduler_mode)
462a0e805eeSFan Zhang scheduler_mode_map[i].val;
463ee9586ddSFan Zhang
464a0e805eeSFan Zhang break;
465a0e805eeSFan Zhang }
466a0e805eeSFan Zhang }
467a0e805eeSFan Zhang
468a0e805eeSFan Zhang if (i == RTE_DIM(scheduler_mode_map)) {
46985aa6d34SHari Kumar CR_SCHED_LOG(ERR, "Unrecognized input.");
470a0e805eeSFan Zhang return -EINVAL;
471a0e805eeSFan Zhang }
472a0e805eeSFan Zhang
473a0e805eeSFan Zhang return 0;
474a0e805eeSFan Zhang }
475a0e805eeSFan Zhang
476a0e805eeSFan Zhang static int
parse_mode_param_arg(const char * key __rte_unused,const char * value,void * extra_args)477ee9586ddSFan Zhang parse_mode_param_arg(const char *key __rte_unused,
478ee9586ddSFan Zhang const char *value, void *extra_args)
479ee9586ddSFan Zhang {
480ee9586ddSFan Zhang struct scheduler_init_params *param = extra_args;
481ee9586ddSFan Zhang
482ee9586ddSFan Zhang strlcpy(param->mode_param_str, value,
483ee9586ddSFan Zhang RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN);
484ee9586ddSFan Zhang
485ee9586ddSFan Zhang return 0;
486ee9586ddSFan Zhang }
487ee9586ddSFan Zhang
488ee9586ddSFan Zhang static int
parse_ordering_arg(const char * key __rte_unused,const char * value,void * extra_args)489a0e805eeSFan Zhang parse_ordering_arg(const char *key __rte_unused,
490a0e805eeSFan Zhang const char *value, void *extra_args)
491a0e805eeSFan Zhang {
492a0e805eeSFan Zhang struct scheduler_init_params *param = extra_args;
493a0e805eeSFan Zhang uint32_t i;
494a0e805eeSFan Zhang
495a0e805eeSFan Zhang for (i = 0; i < RTE_DIM(scheduler_ordering_map); i++) {
496a0e805eeSFan Zhang if (strcmp(value, scheduler_ordering_map[i].name) == 0) {
497a0e805eeSFan Zhang param->enable_ordering =
498a0e805eeSFan Zhang scheduler_ordering_map[i].val;
499a0e805eeSFan Zhang break;
500a0e805eeSFan Zhang }
501a0e805eeSFan Zhang }
502a0e805eeSFan Zhang
503a0e805eeSFan Zhang if (i == RTE_DIM(scheduler_ordering_map)) {
50485aa6d34SHari Kumar CR_SCHED_LOG(ERR, "Unrecognized input.");
505a0e805eeSFan Zhang return -EINVAL;
506a0e805eeSFan Zhang }
507a0e805eeSFan Zhang
508a0e805eeSFan Zhang return 0;
509a0e805eeSFan Zhang }
510a0e805eeSFan Zhang
511a0e805eeSFan Zhang static int
scheduler_parse_init_params(struct scheduler_init_params * params,const char * input_args)512503e9c5aSFan Zhang scheduler_parse_init_params(struct scheduler_init_params *params,
513503e9c5aSFan Zhang const char *input_args)
514503e9c5aSFan Zhang {
515503e9c5aSFan Zhang struct rte_kvargs *kvlist = NULL;
516503e9c5aSFan Zhang int ret = 0;
517503e9c5aSFan Zhang
518503e9c5aSFan Zhang if (params == NULL)
519503e9c5aSFan Zhang return -EINVAL;
520503e9c5aSFan Zhang
521503e9c5aSFan Zhang if (input_args) {
522503e9c5aSFan Zhang kvlist = rte_kvargs_parse(input_args,
523503e9c5aSFan Zhang scheduler_valid_params);
524503e9c5aSFan Zhang if (kvlist == NULL)
525503e9c5aSFan Zhang return -1;
526503e9c5aSFan Zhang
527503e9c5aSFan Zhang ret = rte_kvargs_process(kvlist,
528503e9c5aSFan Zhang RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
529503e9c5aSFan Zhang &parse_integer_arg,
530503e9c5aSFan Zhang ¶ms->def_p.max_nb_queue_pairs);
531503e9c5aSFan Zhang if (ret < 0)
532503e9c5aSFan Zhang goto free_kvlist;
533503e9c5aSFan Zhang
534503e9c5aSFan Zhang ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_SOCKET_ID,
535503e9c5aSFan Zhang &parse_integer_arg,
536503e9c5aSFan Zhang ¶ms->def_p.socket_id);
537503e9c5aSFan Zhang if (ret < 0)
538503e9c5aSFan Zhang goto free_kvlist;
539503e9c5aSFan Zhang
5404c07e055SKirill Rybalchenko ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_COREMASK,
5414c07e055SKirill Rybalchenko &parse_coremask_arg,
5424c07e055SKirill Rybalchenko params);
5434c07e055SKirill Rybalchenko if (ret < 0)
5444c07e055SKirill Rybalchenko goto free_kvlist;
5454c07e055SKirill Rybalchenko
5464c07e055SKirill Rybalchenko ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_CORELIST,
5474c07e055SKirill Rybalchenko &parse_corelist_arg,
5484c07e055SKirill Rybalchenko params);
5494c07e055SKirill Rybalchenko if (ret < 0)
5504c07e055SKirill Rybalchenko goto free_kvlist;
5514c07e055SKirill Rybalchenko
552503e9c5aSFan Zhang ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_NAME,
553503e9c5aSFan Zhang &parse_name_arg,
554503e9c5aSFan Zhang ¶ms->def_p);
555503e9c5aSFan Zhang if (ret < 0)
556503e9c5aSFan Zhang goto free_kvlist;
557503e9c5aSFan Zhang
55885b00824SAdam Dybkowski ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_WORKER,
55985b00824SAdam Dybkowski &parse_worker_arg, params);
560503e9c5aSFan Zhang if (ret < 0)
561503e9c5aSFan Zhang goto free_kvlist;
562503e9c5aSFan Zhang
563a0e805eeSFan Zhang ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_MODE,
564a0e805eeSFan Zhang &parse_mode_arg, params);
565a0e805eeSFan Zhang if (ret < 0)
566a0e805eeSFan Zhang goto free_kvlist;
567a0e805eeSFan Zhang
568ee9586ddSFan Zhang ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_MODE_PARAM,
569ee9586ddSFan Zhang &parse_mode_param_arg, params);
570ee9586ddSFan Zhang if (ret < 0)
571ee9586ddSFan Zhang goto free_kvlist;
572ee9586ddSFan Zhang
573a0e805eeSFan Zhang ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_ORDERING,
574a0e805eeSFan Zhang &parse_ordering_arg, params);
575a0e805eeSFan Zhang if (ret < 0)
576a0e805eeSFan Zhang goto free_kvlist;
577503e9c5aSFan Zhang }
578503e9c5aSFan Zhang
579503e9c5aSFan Zhang free_kvlist:
580503e9c5aSFan Zhang rte_kvargs_free(kvlist);
581503e9c5aSFan Zhang return ret;
582503e9c5aSFan Zhang }
583503e9c5aSFan Zhang
584503e9c5aSFan Zhang static int
cryptodev_scheduler_probe(struct rte_vdev_device * vdev)5855d2aa461SJan Blunck cryptodev_scheduler_probe(struct rte_vdev_device *vdev)
586503e9c5aSFan Zhang {
587503e9c5aSFan Zhang struct scheduler_init_params init_params = {
588503e9c5aSFan Zhang .def_p = {
589f2f020d2SDeclan Doherty "",
590f2f020d2SDeclan Doherty sizeof(struct scheduler_ctx),
591503e9c5aSFan Zhang rte_socket_id(),
592e1fc5b76SPablo de Lara RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS
593503e9c5aSFan Zhang },
59485b00824SAdam Dybkowski .nb_workers = 0,
595a0e805eeSFan Zhang .mode = CDEV_SCHED_MODE_NOT_SET,
59650e14527SFan Zhang .enable_ordering = 0,
59785b00824SAdam Dybkowski .worker_names = { {0} }
598503e9c5aSFan Zhang };
5997e214771SPablo de Lara const char *name;
6007e214771SPablo de Lara
6017e214771SPablo de Lara name = rte_vdev_device_name(vdev);
6027e214771SPablo de Lara if (name == NULL)
6037e214771SPablo de Lara return -EINVAL;
604503e9c5aSFan Zhang
6055d2aa461SJan Blunck scheduler_parse_init_params(&init_params,
6065d2aa461SJan Blunck rte_vdev_device_args(vdev));
607503e9c5aSFan Zhang
608503e9c5aSFan Zhang
609168b9e76SPablo de Lara return cryptodev_scheduler_create(name,
610917ac9c4SPablo de Lara vdev,
6115d2aa461SJan Blunck &init_params);
612503e9c5aSFan Zhang }
613503e9c5aSFan Zhang
614503e9c5aSFan Zhang static struct rte_vdev_driver cryptodev_scheduler_pmd_drv = {
615503e9c5aSFan Zhang .probe = cryptodev_scheduler_probe,
616503e9c5aSFan Zhang .remove = cryptodev_scheduler_remove
617503e9c5aSFan Zhang };
618503e9c5aSFan Zhang
619effd3b9fSPablo de Lara static struct cryptodev_driver scheduler_crypto_drv;
620effd3b9fSPablo de Lara
621503e9c5aSFan Zhang RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_SCHEDULER_PMD,
622503e9c5aSFan Zhang cryptodev_scheduler_pmd_drv);
623503e9c5aSFan Zhang RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_SCHEDULER_PMD,
624503e9c5aSFan Zhang "max_nb_queue_pairs=<int> "
625503e9c5aSFan Zhang "socket_id=<int> "
62685b00824SAdam Dybkowski "worker=<name>");
627effd3b9fSPablo de Lara RTE_PMD_REGISTER_CRYPTO_DRIVER(scheduler_crypto_drv,
628f737f5ceSFiona Trahe cryptodev_scheduler_pmd_drv.driver,
629520dd992SFerruh Yigit cryptodev_scheduler_driver_id);
630