cryptodev: remove crypto device type enumeration
[dpdk.git] / drivers / crypto / scheduler / scheduler_pmd.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2017 Intel Corporation. All rights reserved.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above copyright
13  *       notice, this list of conditions and the following disclaimer in
14  *       the documentation and/or other materials provided with the
15  *       distribution.
16  *     * Neither the name of Intel Corporation nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 #include <rte_common.h>
33 #include <rte_hexdump.h>
34 #include <rte_cryptodev.h>
35 #include <rte_cryptodev_pmd.h>
36 #include <rte_cryptodev_vdev.h>
37 #include <rte_vdev.h>
38 #include <rte_malloc.h>
39 #include <rte_cpuflags.h>
40 #include <rte_reorder.h>
41
42 #include "rte_cryptodev_scheduler.h"
43 #include "scheduler_pmd_private.h"
44
45 uint8_t cryptodev_driver_id;
46
47 struct scheduler_init_params {
48         struct rte_crypto_vdev_init_params def_p;
49         uint32_t nb_slaves;
50         enum rte_cryptodev_scheduler_mode mode;
51         uint32_t enable_ordering;
52         char slave_names[RTE_CRYPTODEV_SCHEDULER_MAX_NB_SLAVES]
53                         [RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN];
54 };
55
56 #define RTE_CRYPTODEV_VDEV_NAME                 ("name")
57 #define RTE_CRYPTODEV_VDEV_SLAVE                ("slave")
58 #define RTE_CRYPTODEV_VDEV_MODE                 ("mode")
59 #define RTE_CRYPTODEV_VDEV_ORDERING             ("ordering")
60 #define RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG        ("max_nb_queue_pairs")
61 #define RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG      ("max_nb_sessions")
62 #define RTE_CRYPTODEV_VDEV_SOCKET_ID            ("socket_id")
63
64 const char *scheduler_valid_params[] = {
65         RTE_CRYPTODEV_VDEV_NAME,
66         RTE_CRYPTODEV_VDEV_SLAVE,
67         RTE_CRYPTODEV_VDEV_MODE,
68         RTE_CRYPTODEV_VDEV_ORDERING,
69         RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
70         RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
71         RTE_CRYPTODEV_VDEV_SOCKET_ID
72 };
73
74 struct scheduler_parse_map {
75         const char *name;
76         uint32_t val;
77 };
78
79 const struct scheduler_parse_map scheduler_mode_map[] = {
80         {RTE_STR(SCHEDULER_MODE_NAME_ROUND_ROBIN),
81                         CDEV_SCHED_MODE_ROUNDROBIN},
82         {RTE_STR(SCHEDULER_MODE_NAME_PKT_SIZE_DISTR),
83                         CDEV_SCHED_MODE_PKT_SIZE_DISTR},
84         {RTE_STR(SCHEDULER_MODE_NAME_FAIL_OVER),
85                         CDEV_SCHED_MODE_FAILOVER}
86 };
87
88 const struct scheduler_parse_map scheduler_ordering_map[] = {
89                 {"enable", 1},
90                 {"disable", 0}
91 };
92
93 static int
94 cryptodev_scheduler_create(const char *name,
95                 struct rte_vdev_device *vdev,
96                 struct scheduler_init_params *init_params)
97 {
98         struct rte_cryptodev *dev;
99         struct scheduler_ctx *sched_ctx;
100         uint32_t i;
101         int ret;
102
103         if (init_params->def_p.name[0] == '\0')
104                 snprintf(init_params->def_p.name,
105                                 sizeof(init_params->def_p.name),
106                                 "%s", name);
107
108         dev = rte_cryptodev_vdev_pmd_init(init_params->def_p.name,
109                         sizeof(struct scheduler_ctx),
110                         init_params->def_p.socket_id,
111                         vdev);
112         if (dev == NULL) {
113                 CS_LOG_ERR("driver %s: failed to create cryptodev vdev",
114                         name);
115                 return -EFAULT;
116         }
117
118         dev->driver_id = cryptodev_driver_id;
119         dev->dev_ops = rte_crypto_scheduler_pmd_ops;
120
121         sched_ctx = dev->data->dev_private;
122         sched_ctx->max_nb_queue_pairs =
123                         init_params->def_p.max_nb_queue_pairs;
124
125         if (init_params->mode > CDEV_SCHED_MODE_USERDEFINED &&
126                         init_params->mode < CDEV_SCHED_MODE_COUNT) {
127                 ret = rte_cryptodev_scheduler_mode_set(dev->data->dev_id,
128                         init_params->mode);
129                 if (ret < 0) {
130                         rte_cryptodev_pmd_release_device(dev);
131                         return ret;
132                 }
133
134                 for (i = 0; i < RTE_DIM(scheduler_mode_map); i++) {
135                         if (scheduler_mode_map[i].val != sched_ctx->mode)
136                                 continue;
137
138                         RTE_LOG(INFO, PMD, "  Scheduling mode = %s\n",
139                                         scheduler_mode_map[i].name);
140                         break;
141                 }
142         }
143
144         sched_ctx->reordering_enabled = init_params->enable_ordering;
145
146         for (i = 0; i < RTE_DIM(scheduler_ordering_map); i++) {
147                 if (scheduler_ordering_map[i].val !=
148                                 sched_ctx->reordering_enabled)
149                         continue;
150
151                 RTE_LOG(INFO, PMD, "  Packet ordering = %s\n",
152                                 scheduler_ordering_map[i].name);
153
154                 break;
155         }
156
157         for (i = 0; i < init_params->nb_slaves; i++) {
158                 sched_ctx->init_slave_names[sched_ctx->nb_init_slaves] =
159                         rte_zmalloc_socket(
160                                 NULL,
161                                 RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN, 0,
162                                 SOCKET_ID_ANY);
163
164                 if (!sched_ctx->init_slave_names[
165                                 sched_ctx->nb_init_slaves]) {
166                         CS_LOG_ERR("driver %s: Insufficient memory",
167                                         name);
168                         return -ENOMEM;
169                 }
170
171                 strncpy(sched_ctx->init_slave_names[
172                                         sched_ctx->nb_init_slaves],
173                                 init_params->slave_names[i],
174                                 RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN - 1);
175
176                 sched_ctx->nb_init_slaves++;
177         }
178
179         /*
180          * Initialize capabilities structure as an empty structure,
181          * in case device information is requested when no slaves are attached
182          */
183         sched_ctx->capabilities = rte_zmalloc_socket(NULL,
184                         sizeof(struct rte_cryptodev_capabilities),
185                         0, SOCKET_ID_ANY);
186
187         if (!sched_ctx->capabilities) {
188                 RTE_LOG(ERR, PMD, "Not enough memory for capability "
189                                 "information\n");
190                 return -ENOMEM;
191         }
192
193         return 0;
194 }
195
196 static int
197 cryptodev_scheduler_remove(struct rte_vdev_device *vdev)
198 {
199         const char *name;
200         struct rte_cryptodev *dev;
201         struct scheduler_ctx *sched_ctx;
202
203         if (vdev == NULL)
204                 return -EINVAL;
205
206         name = rte_vdev_device_name(vdev);
207         dev = rte_cryptodev_pmd_get_named_dev(name);
208         if (dev == NULL)
209                 return -EINVAL;
210
211         sched_ctx = dev->data->dev_private;
212
213         if (sched_ctx->nb_slaves) {
214                 uint32_t i;
215
216                 for (i = 0; i < sched_ctx->nb_slaves; i++)
217                         rte_cryptodev_scheduler_slave_detach(dev->data->dev_id,
218                                         sched_ctx->slaves[i].dev_id);
219         }
220
221         RTE_LOG(INFO, PMD, "Closing Crypto Scheduler device %s on numa "
222                 "socket %u\n", name, rte_socket_id());
223
224         return 0;
225 }
226
227 /** Parse integer from integer argument */
228 static int
229 parse_integer_arg(const char *key __rte_unused,
230                 const char *value, void *extra_args)
231 {
232         int *i = (int *) extra_args;
233
234         *i = atoi(value);
235         if (*i < 0) {
236                 CS_LOG_ERR("Argument has to be positive.\n");
237                 return -EINVAL;
238         }
239
240         return 0;
241 }
242
243 /** Parse name */
244 static int
245 parse_name_arg(const char *key __rte_unused,
246                 const char *value, void *extra_args)
247 {
248         struct rte_crypto_vdev_init_params *params = extra_args;
249
250         if (strlen(value) >= RTE_CRYPTODEV_NAME_MAX_LEN - 1) {
251                 CS_LOG_ERR("Invalid name %s, should be less than "
252                                 "%u bytes.\n", value,
253                                 RTE_CRYPTODEV_NAME_MAX_LEN - 1);
254                 return -EINVAL;
255         }
256
257         strncpy(params->name, value, RTE_CRYPTODEV_NAME_MAX_LEN);
258
259         return 0;
260 }
261
262 /** Parse slave */
263 static int
264 parse_slave_arg(const char *key __rte_unused,
265                 const char *value, void *extra_args)
266 {
267         struct scheduler_init_params *param = extra_args;
268
269         if (param->nb_slaves >= RTE_CRYPTODEV_SCHEDULER_MAX_NB_SLAVES - 1) {
270                 CS_LOG_ERR("Too many slaves.\n");
271                 return -ENOMEM;
272         }
273
274         strncpy(param->slave_names[param->nb_slaves++], value,
275                         RTE_CRYPTODEV_SCHEDULER_NAME_MAX_LEN - 1);
276
277         return 0;
278 }
279
280 static int
281 parse_mode_arg(const char *key __rte_unused,
282                 const char *value, void *extra_args)
283 {
284         struct scheduler_init_params *param = extra_args;
285         uint32_t i;
286
287         for (i = 0; i < RTE_DIM(scheduler_mode_map); i++) {
288                 if (strcmp(value, scheduler_mode_map[i].name) == 0) {
289                         param->mode = (enum rte_cryptodev_scheduler_mode)
290                                         scheduler_mode_map[i].val;
291                         break;
292                 }
293         }
294
295         if (i == RTE_DIM(scheduler_mode_map)) {
296                 CS_LOG_ERR("Unrecognized input.\n");
297                 return -EINVAL;
298         }
299
300         return 0;
301 }
302
303 static int
304 parse_ordering_arg(const char *key __rte_unused,
305                 const char *value, void *extra_args)
306 {
307         struct scheduler_init_params *param = extra_args;
308         uint32_t i;
309
310         for (i = 0; i < RTE_DIM(scheduler_ordering_map); i++) {
311                 if (strcmp(value, scheduler_ordering_map[i].name) == 0) {
312                         param->enable_ordering =
313                                         scheduler_ordering_map[i].val;
314                         break;
315                 }
316         }
317
318         if (i == RTE_DIM(scheduler_ordering_map)) {
319                 CS_LOG_ERR("Unrecognized input.\n");
320                 return -EINVAL;
321         }
322
323         return 0;
324 }
325
326 static int
327 scheduler_parse_init_params(struct scheduler_init_params *params,
328                 const char *input_args)
329 {
330         struct rte_kvargs *kvlist = NULL;
331         int ret = 0;
332
333         if (params == NULL)
334                 return -EINVAL;
335
336         if (input_args) {
337                 kvlist = rte_kvargs_parse(input_args,
338                                 scheduler_valid_params);
339                 if (kvlist == NULL)
340                         return -1;
341
342                 ret = rte_kvargs_process(kvlist,
343                                 RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
344                                 &parse_integer_arg,
345                                 &params->def_p.max_nb_queue_pairs);
346                 if (ret < 0)
347                         goto free_kvlist;
348
349                 ret = rte_kvargs_process(kvlist,
350                                 RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
351                                 &parse_integer_arg,
352                                 &params->def_p.max_nb_sessions);
353                 if (ret < 0)
354                         goto free_kvlist;
355
356                 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_SOCKET_ID,
357                                 &parse_integer_arg,
358                                 &params->def_p.socket_id);
359                 if (ret < 0)
360                         goto free_kvlist;
361
362                 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_NAME,
363                                 &parse_name_arg,
364                                 &params->def_p);
365                 if (ret < 0)
366                         goto free_kvlist;
367
368                 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_SLAVE,
369                                 &parse_slave_arg, params);
370                 if (ret < 0)
371                         goto free_kvlist;
372
373                 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_MODE,
374                                 &parse_mode_arg, params);
375                 if (ret < 0)
376                         goto free_kvlist;
377
378                 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_ORDERING,
379                                 &parse_ordering_arg, params);
380                 if (ret < 0)
381                         goto free_kvlist;
382         }
383
384 free_kvlist:
385         rte_kvargs_free(kvlist);
386         return ret;
387 }
388
389 static int
390 cryptodev_scheduler_probe(struct rte_vdev_device *vdev)
391 {
392         struct scheduler_init_params init_params = {
393                 .def_p = {
394                         RTE_CRYPTODEV_VDEV_DEFAULT_MAX_NB_QUEUE_PAIRS,
395                         RTE_CRYPTODEV_VDEV_DEFAULT_MAX_NB_SESSIONS,
396                         rte_socket_id(),
397                         ""
398                 },
399                 .nb_slaves = 0,
400                 .mode = CDEV_SCHED_MODE_NOT_SET,
401                 .enable_ordering = 0,
402                 .slave_names = { {0} }
403         };
404         const char *name;
405
406         name = rte_vdev_device_name(vdev);
407         if (name == NULL)
408                 return -EINVAL;
409
410         scheduler_parse_init_params(&init_params,
411                                     rte_vdev_device_args(vdev));
412
413         RTE_LOG(INFO, PMD, "Initialising %s on NUMA node %d\n",
414                         name,
415                         init_params.def_p.socket_id);
416         RTE_LOG(INFO, PMD, "  Max number of queue pairs = %d\n",
417                         init_params.def_p.max_nb_queue_pairs);
418         RTE_LOG(INFO, PMD, "  Max number of sessions = %d\n",
419                         init_params.def_p.max_nb_sessions);
420         if (init_params.def_p.name[0] != '\0')
421                 RTE_LOG(INFO, PMD, "  User defined name = %s\n",
422                         init_params.def_p.name);
423
424         return cryptodev_scheduler_create(name,
425                                         vdev,
426                                         &init_params);
427 }
428
429 static struct rte_vdev_driver cryptodev_scheduler_pmd_drv = {
430         .probe = cryptodev_scheduler_probe,
431         .remove = cryptodev_scheduler_remove
432 };
433
434 RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_SCHEDULER_PMD,
435         cryptodev_scheduler_pmd_drv);
436 RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_SCHEDULER_PMD,
437         "max_nb_queue_pairs=<int> "
438         "max_nb_sessions=<int> "
439         "socket_id=<int> "
440         "slave=<name>");
441 RTE_PMD_REGISTER_CRYPTO_DRIVER(cryptodev_scheduler_pmd_drv,
442                 cryptodev_driver_id);