xref: /dpdk/drivers/crypto/scheduler/scheduler_pmd.c (revision a0e805ee086a87b2a787a4deb139775a01790c7c)
1503e9c5aSFan Zhang /*-
2503e9c5aSFan Zhang  *   BSD LICENSE
3503e9c5aSFan Zhang  *
4503e9c5aSFan Zhang  *   Copyright(c) 2017 Intel Corporation. All rights reserved.
5503e9c5aSFan Zhang  *
6503e9c5aSFan Zhang  *   Redistribution and use in source and binary forms, with or without
7503e9c5aSFan Zhang  *   modification, are permitted provided that the following conditions
8503e9c5aSFan Zhang  *   are met:
9503e9c5aSFan Zhang  *
10503e9c5aSFan Zhang  *     * Redistributions of source code must retain the above copyright
11503e9c5aSFan Zhang  *       notice, this list of conditions and the following disclaimer.
12503e9c5aSFan Zhang  *     * Redistributions in binary form must reproduce the above copyright
13503e9c5aSFan Zhang  *       notice, this list of conditions and the following disclaimer in
14503e9c5aSFan Zhang  *       the documentation and/or other materials provided with the
15503e9c5aSFan Zhang  *       distribution.
16503e9c5aSFan Zhang  *     * Neither the name of Intel Corporation nor the names of its
17503e9c5aSFan Zhang  *       contributors may be used to endorse or promote products derived
18503e9c5aSFan Zhang  *       from this software without specific prior written permission.
19503e9c5aSFan Zhang  *
20503e9c5aSFan Zhang  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21503e9c5aSFan Zhang  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22503e9c5aSFan Zhang  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23503e9c5aSFan Zhang  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24503e9c5aSFan Zhang  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25503e9c5aSFan Zhang  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26503e9c5aSFan Zhang  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27503e9c5aSFan Zhang  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28503e9c5aSFan Zhang  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29503e9c5aSFan Zhang  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30503e9c5aSFan Zhang  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31503e9c5aSFan Zhang  */
32503e9c5aSFan Zhang #include <rte_common.h>
33503e9c5aSFan Zhang #include <rte_hexdump.h>
34503e9c5aSFan Zhang #include <rte_cryptodev.h>
35503e9c5aSFan Zhang #include <rte_cryptodev_pmd.h>
36503e9c5aSFan Zhang #include <rte_vdev.h>
37503e9c5aSFan Zhang #include <rte_malloc.h>
38503e9c5aSFan Zhang #include <rte_cpuflags.h>
39503e9c5aSFan Zhang #include <rte_reorder.h>
40503e9c5aSFan Zhang 
41b88161beSBruce Richardson #include "rte_cryptodev_scheduler.h"
42503e9c5aSFan Zhang #include "scheduler_pmd_private.h"
43503e9c5aSFan Zhang 
44503e9c5aSFan Zhang struct scheduler_init_params {
45503e9c5aSFan Zhang 	struct rte_crypto_vdev_init_params def_p;
46503e9c5aSFan Zhang 	uint32_t nb_slaves;
47029bb907SFan Zhang 	uint8_t slaves[RTE_CRYPTODEV_SCHEDULER_MAX_NB_SLAVES];
48*a0e805eeSFan Zhang 	enum rte_cryptodev_scheduler_mode mode;
49*a0e805eeSFan Zhang 	uint32_t enable_ordering;
50503e9c5aSFan Zhang };
51503e9c5aSFan Zhang 
52503e9c5aSFan Zhang #define RTE_CRYPTODEV_VDEV_NAME			("name")
53503e9c5aSFan Zhang #define RTE_CRYPTODEV_VDEV_SLAVE		("slave")
54*a0e805eeSFan Zhang #define RTE_CRYPTODEV_VDEV_MODE			("mode")
55*a0e805eeSFan Zhang #define RTE_CRYPTODEV_VDEV_ORDERING		("ordering")
56503e9c5aSFan Zhang #define RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG	("max_nb_queue_pairs")
57503e9c5aSFan Zhang #define RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG	("max_nb_sessions")
58503e9c5aSFan Zhang #define RTE_CRYPTODEV_VDEV_SOCKET_ID		("socket_id")
59503e9c5aSFan Zhang 
60503e9c5aSFan Zhang const char *scheduler_valid_params[] = {
61503e9c5aSFan Zhang 	RTE_CRYPTODEV_VDEV_NAME,
62503e9c5aSFan Zhang 	RTE_CRYPTODEV_VDEV_SLAVE,
63*a0e805eeSFan Zhang 	RTE_CRYPTODEV_VDEV_MODE,
64*a0e805eeSFan Zhang 	RTE_CRYPTODEV_VDEV_ORDERING,
65503e9c5aSFan Zhang 	RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
66503e9c5aSFan Zhang 	RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
67503e9c5aSFan Zhang 	RTE_CRYPTODEV_VDEV_SOCKET_ID
68503e9c5aSFan Zhang };
69503e9c5aSFan Zhang 
70*a0e805eeSFan Zhang struct scheduler_parse_map {
71*a0e805eeSFan Zhang 	const char *name;
72*a0e805eeSFan Zhang 	uint32_t val;
73*a0e805eeSFan Zhang };
74*a0e805eeSFan Zhang 
75*a0e805eeSFan Zhang const struct scheduler_parse_map scheduler_mode_map[] = {
76*a0e805eeSFan Zhang 	{RTE_STR(SCHEDULER_MODE_NAME_ROUND_ROBIN),
77*a0e805eeSFan Zhang 			CDEV_SCHED_MODE_ROUNDROBIN},
78*a0e805eeSFan Zhang 	{RTE_STR(SCHEDULER_MODE_NAME_PKT_SIZE_DISTR),
79*a0e805eeSFan Zhang 			CDEV_SCHED_MODE_PKT_SIZE_DISTR},
80*a0e805eeSFan Zhang 	{RTE_STR(SCHEDULER_MODE_NAME_FAIL_OVER),
81*a0e805eeSFan Zhang 			CDEV_SCHED_MODE_FAILOVER}
82*a0e805eeSFan Zhang };
83*a0e805eeSFan Zhang 
84*a0e805eeSFan Zhang const struct scheduler_parse_map scheduler_ordering_map[] = {
85*a0e805eeSFan Zhang 		{"enable", 1},
86*a0e805eeSFan Zhang 		{"disable", 0}
87*a0e805eeSFan Zhang };
88*a0e805eeSFan Zhang 
89503e9c5aSFan Zhang static int
90503e9c5aSFan Zhang attach_init_slaves(uint8_t scheduler_id,
91503e9c5aSFan Zhang 		const uint8_t *slaves, const uint8_t nb_slaves)
92503e9c5aSFan Zhang {
93503e9c5aSFan Zhang 	uint8_t i;
94503e9c5aSFan Zhang 
95503e9c5aSFan Zhang 	for (i = 0; i < nb_slaves; i++) {
96503e9c5aSFan Zhang 		struct rte_cryptodev *dev =
97503e9c5aSFan Zhang 				rte_cryptodev_pmd_get_dev(slaves[i]);
98503e9c5aSFan Zhang 		int status = rte_cryptodev_scheduler_slave_attach(
99503e9c5aSFan Zhang 				scheduler_id, slaves[i]);
100503e9c5aSFan Zhang 
101503e9c5aSFan Zhang 		if (status < 0 || !dev) {
102503e9c5aSFan Zhang 			CS_LOG_ERR("Failed to attach slave cryptodev "
103503e9c5aSFan Zhang 					"%u.\n", slaves[i]);
104503e9c5aSFan Zhang 			return status;
105503e9c5aSFan Zhang 		}
106503e9c5aSFan Zhang 
107*a0e805eeSFan Zhang 		RTE_LOG(INFO, PMD, "  Attached Slave %s\n", dev->data->name);
108503e9c5aSFan Zhang 	}
109503e9c5aSFan Zhang 
110503e9c5aSFan Zhang 	return 0;
111503e9c5aSFan Zhang }
112503e9c5aSFan Zhang 
113503e9c5aSFan Zhang static int
114503e9c5aSFan Zhang cryptodev_scheduler_create(const char *name,
115503e9c5aSFan Zhang 	struct scheduler_init_params *init_params)
116503e9c5aSFan Zhang {
117503e9c5aSFan Zhang 	char crypto_dev_name[RTE_CRYPTODEV_NAME_MAX_LEN] = {0};
118503e9c5aSFan Zhang 	struct rte_cryptodev *dev;
119503e9c5aSFan Zhang 	struct scheduler_ctx *sched_ctx;
120*a0e805eeSFan Zhang 	uint32_t i;
121*a0e805eeSFan Zhang 	int ret;
122503e9c5aSFan Zhang 
123503e9c5aSFan Zhang 	if (init_params->def_p.name[0] == '\0') {
124*a0e805eeSFan Zhang 		ret = rte_cryptodev_pmd_create_dev_name(
125503e9c5aSFan Zhang 				crypto_dev_name,
126503e9c5aSFan Zhang 				RTE_STR(CRYPTODEV_NAME_SCHEDULER_PMD));
127503e9c5aSFan Zhang 
128503e9c5aSFan Zhang 		if (ret < 0) {
129503e9c5aSFan Zhang 			CS_LOG_ERR("failed to create unique name");
130503e9c5aSFan Zhang 			return ret;
131503e9c5aSFan Zhang 		}
132503e9c5aSFan Zhang 	} else {
133503e9c5aSFan Zhang 		strncpy(crypto_dev_name, init_params->def_p.name,
134503e9c5aSFan Zhang 				RTE_CRYPTODEV_NAME_MAX_LEN - 1);
135503e9c5aSFan Zhang 	}
136503e9c5aSFan Zhang 
137503e9c5aSFan Zhang 	dev = rte_cryptodev_pmd_virtual_dev_init(crypto_dev_name,
138503e9c5aSFan Zhang 			sizeof(struct scheduler_ctx),
139503e9c5aSFan Zhang 			init_params->def_p.socket_id);
140503e9c5aSFan Zhang 	if (dev == NULL) {
141503e9c5aSFan Zhang 		CS_LOG_ERR("driver %s: failed to create cryptodev vdev",
142503e9c5aSFan Zhang 			name);
143503e9c5aSFan Zhang 		return -EFAULT;
144503e9c5aSFan Zhang 	}
145503e9c5aSFan Zhang 
146503e9c5aSFan Zhang 	dev->dev_type = RTE_CRYPTODEV_SCHEDULER_PMD;
147503e9c5aSFan Zhang 	dev->dev_ops = rte_crypto_scheduler_pmd_ops;
148503e9c5aSFan Zhang 
149503e9c5aSFan Zhang 	sched_ctx = dev->data->dev_private;
150503e9c5aSFan Zhang 	sched_ctx->max_nb_queue_pairs =
151503e9c5aSFan Zhang 			init_params->def_p.max_nb_queue_pairs;
152503e9c5aSFan Zhang 
153*a0e805eeSFan Zhang 	ret = attach_init_slaves(dev->data->dev_id, init_params->slaves,
154503e9c5aSFan Zhang 			init_params->nb_slaves);
155*a0e805eeSFan Zhang 	if (ret < 0) {
156*a0e805eeSFan Zhang 		rte_cryptodev_pmd_release_device(dev);
157*a0e805eeSFan Zhang 		return ret;
158*a0e805eeSFan Zhang 	}
159*a0e805eeSFan Zhang 
160*a0e805eeSFan Zhang 	if (init_params->mode > CDEV_SCHED_MODE_USERDEFINED &&
161*a0e805eeSFan Zhang 			init_params->mode < CDEV_SCHED_MODE_COUNT) {
162*a0e805eeSFan Zhang 		ret = rte_crpytodev_scheduler_mode_set(dev->data->dev_id,
163*a0e805eeSFan Zhang 			init_params->mode);
164*a0e805eeSFan Zhang 		if (ret < 0) {
165*a0e805eeSFan Zhang 			rte_cryptodev_pmd_release_device(dev);
166*a0e805eeSFan Zhang 			return ret;
167*a0e805eeSFan Zhang 		}
168*a0e805eeSFan Zhang 
169*a0e805eeSFan Zhang 		for (i = 0; i < RTE_DIM(scheduler_mode_map); i++) {
170*a0e805eeSFan Zhang 			if (scheduler_mode_map[i].val != sched_ctx->mode)
171*a0e805eeSFan Zhang 				continue;
172*a0e805eeSFan Zhang 
173*a0e805eeSFan Zhang 			RTE_LOG(INFO, PMD, "  Scheduling mode = %s\n",
174*a0e805eeSFan Zhang 					scheduler_mode_map[i].name);
175*a0e805eeSFan Zhang 			break;
176*a0e805eeSFan Zhang 		}
177*a0e805eeSFan Zhang 	}
178*a0e805eeSFan Zhang 
179*a0e805eeSFan Zhang 	sched_ctx->reordering_enabled = init_params->enable_ordering;
180*a0e805eeSFan Zhang 
181*a0e805eeSFan Zhang 	for (i = 0; i < RTE_DIM(scheduler_ordering_map); i++) {
182*a0e805eeSFan Zhang 		if (scheduler_ordering_map[i].val !=
183*a0e805eeSFan Zhang 				sched_ctx->reordering_enabled)
184*a0e805eeSFan Zhang 			continue;
185*a0e805eeSFan Zhang 
186*a0e805eeSFan Zhang 		RTE_LOG(INFO, PMD, "  Packet ordering = %s\n",
187*a0e805eeSFan Zhang 				scheduler_ordering_map[i].name);
188*a0e805eeSFan Zhang 
189*a0e805eeSFan Zhang 		break;
190*a0e805eeSFan Zhang 	}
191*a0e805eeSFan Zhang 
192*a0e805eeSFan Zhang 	return 0;
193503e9c5aSFan Zhang }
194503e9c5aSFan Zhang 
195503e9c5aSFan Zhang static int
196503e9c5aSFan Zhang cryptodev_scheduler_remove(const char *name)
197503e9c5aSFan Zhang {
198503e9c5aSFan Zhang 	struct rte_cryptodev *dev;
199503e9c5aSFan Zhang 	struct scheduler_ctx *sched_ctx;
200503e9c5aSFan Zhang 
201503e9c5aSFan Zhang 	if (name == NULL)
202503e9c5aSFan Zhang 		return -EINVAL;
203503e9c5aSFan Zhang 
204503e9c5aSFan Zhang 	dev = rte_cryptodev_pmd_get_named_dev(name);
205503e9c5aSFan Zhang 	if (dev == NULL)
206503e9c5aSFan Zhang 		return -EINVAL;
207503e9c5aSFan Zhang 
208503e9c5aSFan Zhang 	sched_ctx = dev->data->dev_private;
209503e9c5aSFan Zhang 
210503e9c5aSFan Zhang 	if (sched_ctx->nb_slaves) {
211503e9c5aSFan Zhang 		uint32_t i;
212503e9c5aSFan Zhang 
213503e9c5aSFan Zhang 		for (i = 0; i < sched_ctx->nb_slaves; i++)
214503e9c5aSFan Zhang 			rte_cryptodev_scheduler_slave_detach(dev->data->dev_id,
215503e9c5aSFan Zhang 					sched_ctx->slaves[i].dev_id);
216503e9c5aSFan Zhang 	}
217503e9c5aSFan Zhang 
218503e9c5aSFan Zhang 	RTE_LOG(INFO, PMD, "Closing Crypto Scheduler device %s on numa "
219503e9c5aSFan Zhang 		"socket %u\n", name, rte_socket_id());
220503e9c5aSFan Zhang 
221503e9c5aSFan Zhang 	return 0;
222503e9c5aSFan Zhang }
223503e9c5aSFan Zhang 
224503e9c5aSFan Zhang static uint8_t
225503e9c5aSFan Zhang number_of_sockets(void)
226503e9c5aSFan Zhang {
227503e9c5aSFan Zhang 	int sockets = 0;
228503e9c5aSFan Zhang 	int i;
229503e9c5aSFan Zhang 	const struct rte_memseg *ms = rte_eal_get_physmem_layout();
230503e9c5aSFan Zhang 
231503e9c5aSFan Zhang 	for (i = 0; ((i < RTE_MAX_MEMSEG) && (ms[i].addr != NULL)); i++) {
232503e9c5aSFan Zhang 		if (sockets < ms[i].socket_id)
233503e9c5aSFan Zhang 			sockets = ms[i].socket_id;
234503e9c5aSFan Zhang 	}
235503e9c5aSFan Zhang 
236503e9c5aSFan Zhang 	/* Number of sockets = maximum socket_id + 1 */
237503e9c5aSFan Zhang 	return ++sockets;
238503e9c5aSFan Zhang }
239503e9c5aSFan Zhang 
240503e9c5aSFan Zhang /** Parse integer from integer argument */
241503e9c5aSFan Zhang static int
242503e9c5aSFan Zhang parse_integer_arg(const char *key __rte_unused,
243503e9c5aSFan Zhang 		const char *value, void *extra_args)
244503e9c5aSFan Zhang {
245503e9c5aSFan Zhang 	int *i = (int *) extra_args;
246503e9c5aSFan Zhang 
247503e9c5aSFan Zhang 	*i = atoi(value);
248503e9c5aSFan Zhang 	if (*i < 0) {
249503e9c5aSFan Zhang 		CS_LOG_ERR("Argument has to be positive.\n");
250*a0e805eeSFan Zhang 		return -EINVAL;
251503e9c5aSFan Zhang 	}
252503e9c5aSFan Zhang 
253503e9c5aSFan Zhang 	return 0;
254503e9c5aSFan Zhang }
255503e9c5aSFan Zhang 
256503e9c5aSFan Zhang /** Parse name */
257503e9c5aSFan Zhang static int
258503e9c5aSFan Zhang parse_name_arg(const char *key __rte_unused,
259503e9c5aSFan Zhang 		const char *value, void *extra_args)
260503e9c5aSFan Zhang {
261503e9c5aSFan Zhang 	struct rte_crypto_vdev_init_params *params = extra_args;
262503e9c5aSFan Zhang 
263503e9c5aSFan Zhang 	if (strlen(value) >= RTE_CRYPTODEV_NAME_MAX_LEN - 1) {
264503e9c5aSFan Zhang 		CS_LOG_ERR("Invalid name %s, should be less than "
265503e9c5aSFan Zhang 				"%u bytes.\n", value,
266503e9c5aSFan Zhang 				RTE_CRYPTODEV_NAME_MAX_LEN - 1);
267*a0e805eeSFan Zhang 		return -EINVAL;
268503e9c5aSFan Zhang 	}
269503e9c5aSFan Zhang 
270503e9c5aSFan Zhang 	strncpy(params->name, value, RTE_CRYPTODEV_NAME_MAX_LEN);
271503e9c5aSFan Zhang 
272503e9c5aSFan Zhang 	return 0;
273503e9c5aSFan Zhang }
274503e9c5aSFan Zhang 
275503e9c5aSFan Zhang /** Parse slave */
276503e9c5aSFan Zhang static int
277503e9c5aSFan Zhang parse_slave_arg(const char *key __rte_unused,
278503e9c5aSFan Zhang 		const char *value, void *extra_args)
279503e9c5aSFan Zhang {
280503e9c5aSFan Zhang 	struct scheduler_init_params *param = extra_args;
281503e9c5aSFan Zhang 	struct rte_cryptodev *dev =
282503e9c5aSFan Zhang 			rte_cryptodev_pmd_get_named_dev(value);
283503e9c5aSFan Zhang 
284503e9c5aSFan Zhang 	if (!dev) {
285503e9c5aSFan Zhang 		RTE_LOG(ERR, PMD, "Invalid slave name %s.\n", value);
286*a0e805eeSFan Zhang 		return -EINVAL;
287503e9c5aSFan Zhang 	}
288503e9c5aSFan Zhang 
289029bb907SFan Zhang 	if (param->nb_slaves >= RTE_CRYPTODEV_SCHEDULER_MAX_NB_SLAVES - 1) {
290503e9c5aSFan Zhang 		CS_LOG_ERR("Too many slaves.\n");
291*a0e805eeSFan Zhang 		return -ENOMEM;
292503e9c5aSFan Zhang 	}
293503e9c5aSFan Zhang 
294503e9c5aSFan Zhang 	param->slaves[param->nb_slaves] = dev->data->dev_id;
295503e9c5aSFan Zhang 	param->nb_slaves++;
296503e9c5aSFan Zhang 
297503e9c5aSFan Zhang 	return 0;
298503e9c5aSFan Zhang }
299503e9c5aSFan Zhang 
300503e9c5aSFan Zhang static int
301*a0e805eeSFan Zhang parse_mode_arg(const char *key __rte_unused,
302*a0e805eeSFan Zhang 		const char *value, void *extra_args)
303*a0e805eeSFan Zhang {
304*a0e805eeSFan Zhang 	struct scheduler_init_params *param = extra_args;
305*a0e805eeSFan Zhang 	uint32_t i;
306*a0e805eeSFan Zhang 
307*a0e805eeSFan Zhang 	for (i = 0; i < RTE_DIM(scheduler_mode_map); i++) {
308*a0e805eeSFan Zhang 		if (strcmp(value, scheduler_mode_map[i].name) == 0) {
309*a0e805eeSFan Zhang 			param->mode = (enum rte_cryptodev_scheduler_mode)
310*a0e805eeSFan Zhang 					scheduler_mode_map[i].val;
311*a0e805eeSFan Zhang 			break;
312*a0e805eeSFan Zhang 		}
313*a0e805eeSFan Zhang 	}
314*a0e805eeSFan Zhang 
315*a0e805eeSFan Zhang 	if (i == RTE_DIM(scheduler_mode_map)) {
316*a0e805eeSFan Zhang 		CS_LOG_ERR("Unrecognized input.\n");
317*a0e805eeSFan Zhang 		return -EINVAL;
318*a0e805eeSFan Zhang 	}
319*a0e805eeSFan Zhang 
320*a0e805eeSFan Zhang 	return 0;
321*a0e805eeSFan Zhang }
322*a0e805eeSFan Zhang 
323*a0e805eeSFan Zhang static int
324*a0e805eeSFan Zhang parse_ordering_arg(const char *key __rte_unused,
325*a0e805eeSFan Zhang 		const char *value, void *extra_args)
326*a0e805eeSFan Zhang {
327*a0e805eeSFan Zhang 	struct scheduler_init_params *param = extra_args;
328*a0e805eeSFan Zhang 	uint32_t i;
329*a0e805eeSFan Zhang 
330*a0e805eeSFan Zhang 	for (i = 0; i < RTE_DIM(scheduler_ordering_map); i++) {
331*a0e805eeSFan Zhang 		if (strcmp(value, scheduler_ordering_map[i].name) == 0) {
332*a0e805eeSFan Zhang 			param->enable_ordering =
333*a0e805eeSFan Zhang 					scheduler_ordering_map[i].val;
334*a0e805eeSFan Zhang 			break;
335*a0e805eeSFan Zhang 		}
336*a0e805eeSFan Zhang 	}
337*a0e805eeSFan Zhang 
338*a0e805eeSFan Zhang 	if (i == RTE_DIM(scheduler_ordering_map)) {
339*a0e805eeSFan Zhang 		CS_LOG_ERR("Unrecognized input.\n");
340*a0e805eeSFan Zhang 		return -EINVAL;
341*a0e805eeSFan Zhang 	}
342*a0e805eeSFan Zhang 
343*a0e805eeSFan Zhang 	return 0;
344*a0e805eeSFan Zhang }
345*a0e805eeSFan Zhang 
346*a0e805eeSFan Zhang static int
347503e9c5aSFan Zhang scheduler_parse_init_params(struct scheduler_init_params *params,
348503e9c5aSFan Zhang 		const char *input_args)
349503e9c5aSFan Zhang {
350503e9c5aSFan Zhang 	struct rte_kvargs *kvlist = NULL;
351503e9c5aSFan Zhang 	int ret = 0;
352503e9c5aSFan Zhang 
353503e9c5aSFan Zhang 	if (params == NULL)
354503e9c5aSFan Zhang 		return -EINVAL;
355503e9c5aSFan Zhang 
356503e9c5aSFan Zhang 	if (input_args) {
357503e9c5aSFan Zhang 		kvlist = rte_kvargs_parse(input_args,
358503e9c5aSFan Zhang 				scheduler_valid_params);
359503e9c5aSFan Zhang 		if (kvlist == NULL)
360503e9c5aSFan Zhang 			return -1;
361503e9c5aSFan Zhang 
362503e9c5aSFan Zhang 		ret = rte_kvargs_process(kvlist,
363503e9c5aSFan Zhang 				RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
364503e9c5aSFan Zhang 				&parse_integer_arg,
365503e9c5aSFan Zhang 				&params->def_p.max_nb_queue_pairs);
366503e9c5aSFan Zhang 		if (ret < 0)
367503e9c5aSFan Zhang 			goto free_kvlist;
368503e9c5aSFan Zhang 
369503e9c5aSFan Zhang 		ret = rte_kvargs_process(kvlist,
370503e9c5aSFan Zhang 				RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
371503e9c5aSFan Zhang 				&parse_integer_arg,
372503e9c5aSFan Zhang 				&params->def_p.max_nb_sessions);
373503e9c5aSFan Zhang 		if (ret < 0)
374503e9c5aSFan Zhang 			goto free_kvlist;
375503e9c5aSFan Zhang 
376503e9c5aSFan Zhang 		ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_SOCKET_ID,
377503e9c5aSFan Zhang 				&parse_integer_arg,
378503e9c5aSFan Zhang 				&params->def_p.socket_id);
379503e9c5aSFan Zhang 		if (ret < 0)
380503e9c5aSFan Zhang 			goto free_kvlist;
381503e9c5aSFan Zhang 
382503e9c5aSFan Zhang 		ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_NAME,
383503e9c5aSFan Zhang 				&parse_name_arg,
384503e9c5aSFan Zhang 				&params->def_p);
385503e9c5aSFan Zhang 		if (ret < 0)
386503e9c5aSFan Zhang 			goto free_kvlist;
387503e9c5aSFan Zhang 
388503e9c5aSFan Zhang 		ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_SLAVE,
389503e9c5aSFan Zhang 				&parse_slave_arg, params);
390503e9c5aSFan Zhang 		if (ret < 0)
391503e9c5aSFan Zhang 			goto free_kvlist;
392503e9c5aSFan Zhang 
393*a0e805eeSFan Zhang 		ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_MODE,
394*a0e805eeSFan Zhang 				&parse_mode_arg, params);
395*a0e805eeSFan Zhang 		if (ret < 0)
396*a0e805eeSFan Zhang 			goto free_kvlist;
397*a0e805eeSFan Zhang 
398*a0e805eeSFan Zhang 		ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_ORDERING,
399*a0e805eeSFan Zhang 				&parse_ordering_arg, params);
400*a0e805eeSFan Zhang 		if (ret < 0)
401*a0e805eeSFan Zhang 			goto free_kvlist;
402*a0e805eeSFan Zhang 
403503e9c5aSFan Zhang 		if (params->def_p.socket_id >= number_of_sockets()) {
404503e9c5aSFan Zhang 			CDEV_LOG_ERR("Invalid socket id specified to create "
405503e9c5aSFan Zhang 				"the virtual crypto device on");
406503e9c5aSFan Zhang 			goto free_kvlist;
407503e9c5aSFan Zhang 		}
408503e9c5aSFan Zhang 	}
409503e9c5aSFan Zhang 
410503e9c5aSFan Zhang free_kvlist:
411503e9c5aSFan Zhang 	rte_kvargs_free(kvlist);
412503e9c5aSFan Zhang 	return ret;
413503e9c5aSFan Zhang }
414503e9c5aSFan Zhang 
415503e9c5aSFan Zhang static int
416503e9c5aSFan Zhang cryptodev_scheduler_probe(const char *name, const char *input_args)
417503e9c5aSFan Zhang {
418503e9c5aSFan Zhang 	struct scheduler_init_params init_params = {
419503e9c5aSFan Zhang 		.def_p = {
420503e9c5aSFan Zhang 			RTE_CRYPTODEV_VDEV_DEFAULT_MAX_NB_QUEUE_PAIRS,
421503e9c5aSFan Zhang 			RTE_CRYPTODEV_VDEV_DEFAULT_MAX_NB_SESSIONS,
422503e9c5aSFan Zhang 			rte_socket_id(),
423503e9c5aSFan Zhang 			""
424503e9c5aSFan Zhang 		},
425503e9c5aSFan Zhang 		.nb_slaves = 0,
426*a0e805eeSFan Zhang 		.slaves = {0},
427*a0e805eeSFan Zhang 		.mode = CDEV_SCHED_MODE_NOT_SET,
428*a0e805eeSFan Zhang 		.enable_ordering = 0
429503e9c5aSFan Zhang 	};
430503e9c5aSFan Zhang 
431503e9c5aSFan Zhang 	scheduler_parse_init_params(&init_params, input_args);
432503e9c5aSFan Zhang 
433503e9c5aSFan Zhang 	RTE_LOG(INFO, PMD, "Initialising %s on NUMA node %d\n", name,
434503e9c5aSFan Zhang 			init_params.def_p.socket_id);
435503e9c5aSFan Zhang 	RTE_LOG(INFO, PMD, "  Max number of queue pairs = %d\n",
436503e9c5aSFan Zhang 			init_params.def_p.max_nb_queue_pairs);
437503e9c5aSFan Zhang 	RTE_LOG(INFO, PMD, "  Max number of sessions = %d\n",
438503e9c5aSFan Zhang 			init_params.def_p.max_nb_sessions);
439503e9c5aSFan Zhang 	if (init_params.def_p.name[0] != '\0')
440503e9c5aSFan Zhang 		RTE_LOG(INFO, PMD, "  User defined name = %s\n",
441503e9c5aSFan Zhang 			init_params.def_p.name);
442503e9c5aSFan Zhang 
443503e9c5aSFan Zhang 	return cryptodev_scheduler_create(name, &init_params);
444503e9c5aSFan Zhang }
445503e9c5aSFan Zhang 
446503e9c5aSFan Zhang static struct rte_vdev_driver cryptodev_scheduler_pmd_drv = {
447503e9c5aSFan Zhang 	.probe = cryptodev_scheduler_probe,
448503e9c5aSFan Zhang 	.remove = cryptodev_scheduler_remove
449503e9c5aSFan Zhang };
450503e9c5aSFan Zhang 
451503e9c5aSFan Zhang RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_SCHEDULER_PMD,
452503e9c5aSFan Zhang 	cryptodev_scheduler_pmd_drv);
453503e9c5aSFan Zhang RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_SCHEDULER_PMD,
454503e9c5aSFan Zhang 	"max_nb_queue_pairs=<int> "
455503e9c5aSFan Zhang 	"max_nb_sessions=<int> "
456503e9c5aSFan Zhang 	"socket_id=<int> "
457503e9c5aSFan Zhang 	"slave=<name>");
458