cryptodev: add APIs to assist PMD initialisation
[dpdk.git] / lib / librte_cryptodev / rte_cryptodev_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 the copyright holder 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
33 #include <rte_malloc.h>
34
35 #include "rte_cryptodev_vdev.h"
36 #include "rte_cryptodev_pci.h"
37 #include "rte_cryptodev_pmd.h"
38
39 /**
40  * Parse name from argument
41  */
42 static int
43 rte_cryptodev_pmd_parse_name_arg(const char *key __rte_unused,
44                 const char *value, void *extra_args)
45 {
46         struct rte_cryptodev_pmd_init_params *params = extra_args;
47         int n;
48
49         n = snprintf(params->name, RTE_CRYPTODEV_NAME_MAX_LEN, "%s", value);
50         if (n >= RTE_CRYPTODEV_NAME_MAX_LEN)
51                 return -EINVAL;
52
53         return 0;
54 }
55
56 /**
57  * Parse unsigned integer from argument
58  */
59 static int
60 rte_cryptodev_pmd_parse_uint_arg(const char *key __rte_unused,
61                 const char *value, void *extra_args)
62 {
63         int i;
64         char *end;
65         errno = 0;
66
67         i = strtol(value, &end, 10);
68         if (*end != 0 || errno != 0 || i < 0)
69                 return -EINVAL;
70
71         *((uint32_t *)extra_args) = i;
72         return 0;
73 }
74
75 int
76 rte_cryptodev_pmd_parse_input_args(
77                 struct rte_cryptodev_pmd_init_params *params,
78                 const char *args)
79 {
80         struct rte_kvargs *kvlist = NULL;
81         int ret = 0;
82
83         if (params == NULL)
84                 return -EINVAL;
85
86         if (args) {
87                 kvlist = rte_kvargs_parse(args, cryptodev_pmd_valid_params);
88                 if (kvlist == NULL)
89                         return -EINVAL;
90
91                 ret = rte_kvargs_process(kvlist,
92                                 RTE_CRYPTODEV_PMD_MAX_NB_QP_ARG,
93                                 &rte_cryptodev_pmd_parse_uint_arg,
94                                 &params->max_nb_queue_pairs);
95                 if (ret < 0)
96                         goto free_kvlist;
97
98                 ret = rte_kvargs_process(kvlist,
99                                 RTE_CRYPTODEV_PMD_MAX_NB_SESS_ARG,
100                                 &rte_cryptodev_pmd_parse_uint_arg,
101                                 &params->max_nb_sessions);
102                 if (ret < 0)
103                         goto free_kvlist;
104
105                 ret = rte_kvargs_process(kvlist,
106                                 RTE_CRYPTODEV_PMD_SOCKET_ID_ARG,
107                                 &rte_cryptodev_pmd_parse_uint_arg,
108                                 &params->socket_id);
109                 if (ret < 0)
110                         goto free_kvlist;
111
112                 ret = rte_kvargs_process(kvlist,
113                                 RTE_CRYPTODEV_PMD_NAME_ARG,
114                                 &rte_cryptodev_pmd_parse_name_arg,
115                                 params);
116                 if (ret < 0)
117                         goto free_kvlist;
118         }
119
120 free_kvlist:
121         rte_kvargs_free(kvlist);
122         return ret;
123 }
124
125 struct rte_cryptodev *
126 rte_cryptodev_pmd_create(const char *name,
127                 struct rte_device *device,
128                 struct rte_cryptodev_pmd_init_params *params)
129 {
130         struct rte_cryptodev *cryptodev;
131
132         if (params->name[0] != '\0') {
133                 CDEV_LOG_INFO("[%s] User specified device name = %s\n",
134                                 device->driver->name, params->name);
135                 name = params->name;
136         }
137
138         CDEV_LOG_INFO("[%s] - Creating cryptodev %s\n",
139                         device->driver->name, name);
140
141         CDEV_LOG_INFO("[%s] - Initialisation parameters - name: %s,"
142                         "socket id: %d, max queue pairs: %u, max sessions: %u",
143                         device->driver->name, name,
144                         params->socket_id, params->max_nb_queue_pairs,
145                         params->max_nb_sessions);
146
147         /* allocate device structure */
148         cryptodev = rte_cryptodev_pmd_allocate(name, params->socket_id);
149         if (cryptodev == NULL) {
150                 CDEV_LOG_ERR("[%s] Failed to allocate crypto device for %s",
151                                 device->driver->name, name);
152                 return NULL;
153         }
154
155         /* allocate private device structure */
156         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
157                 cryptodev->data->dev_private =
158                                 rte_zmalloc_socket("cryptodev device private",
159                                                 params->private_data_size,
160                                                 RTE_CACHE_LINE_SIZE,
161                                                 params->socket_id);
162
163                 if (cryptodev->data->dev_private == NULL) {
164                         CDEV_LOG_ERR("[%s] Cannot allocate memory for "
165                                         "cryptodev %s private data",
166                                         device->driver->name, name);
167
168                         rte_cryptodev_pmd_release_device(cryptodev);
169                         return NULL;
170                 }
171         }
172
173         cryptodev->device = device;
174
175         /* initialise user call-back tail queue */
176         TAILQ_INIT(&(cryptodev->link_intr_cbs));
177
178         return cryptodev;
179 }
180
181 int
182 rte_cryptodev_pmd_destroy(struct rte_cryptodev *cryptodev)
183 {
184         int retval;
185
186         CDEV_LOG_INFO("[%s] Closing crypto device %s",
187                         cryptodev->device->driver->name,
188                         cryptodev->device->name);
189
190         /* free crypto device */
191         retval = rte_cryptodev_pmd_release_device(cryptodev);
192         if (retval)
193                 return retval;
194
195         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
196                 rte_free(cryptodev->data->dev_private);
197
198
199         cryptodev->device = NULL;
200         cryptodev->data = NULL;
201
202         return 0;
203 }
204
205 /**
206  * Parse name from argument
207  */
208 static int
209 rte_cryptodev_vdev_parse_name_arg(const char *key __rte_unused,
210                 const char *value, void *extra_args)
211 {
212         struct rte_crypto_vdev_init_params *params = extra_args;
213
214         if (strlen(value) >= RTE_CRYPTODEV_NAME_MAX_LEN - 1) {
215                 CDEV_LOG_ERR("Invalid name %s, should be less than "
216                                 "%u bytes", value,
217                                 RTE_CRYPTODEV_NAME_MAX_LEN - 1);
218                 return -1;
219         }
220
221         strncpy(params->name, value, RTE_CRYPTODEV_NAME_MAX_LEN);
222
223         return 0;
224 }
225
226 /**
227  * Parse integer from argument
228  */
229 static int
230 rte_cryptodev_vdev_parse_integer_arg(const char *key __rte_unused,
231                 const char *value, void *extra_args)
232 {
233         int *i = extra_args;
234
235         *i = atoi(value);
236         if (*i < 0) {
237                 CDEV_LOG_ERR("Argument has to be positive.");
238                 return -1;
239         }
240
241         return 0;
242 }
243
244 struct rte_cryptodev *
245 rte_cryptodev_vdev_pmd_init(const char *name, size_t dev_private_size,
246                 int socket_id, struct rte_vdev_device *vdev)
247 {
248         struct rte_cryptodev *cryptodev;
249
250         /* allocate device structure */
251         cryptodev = rte_cryptodev_pmd_allocate(name, socket_id);
252         if (cryptodev == NULL)
253                 return NULL;
254
255         /* allocate private device structure */
256         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
257                 cryptodev->data->dev_private =
258                                 rte_zmalloc_socket("cryptodev device private",
259                                                 dev_private_size,
260                                                 RTE_CACHE_LINE_SIZE,
261                                                 socket_id);
262
263                 if (cryptodev->data->dev_private == NULL)
264                         rte_panic("Cannot allocate memzone for private device"
265                                         " data");
266         }
267
268         cryptodev->device = &vdev->device;
269
270         return cryptodev;
271 }
272
273 int
274 rte_cryptodev_vdev_parse_init_params(struct rte_crypto_vdev_init_params *params,
275                 const char *input_args)
276 {
277         struct rte_kvargs *kvlist = NULL;
278         int ret = 0;
279
280         if (params == NULL)
281                 return -EINVAL;
282
283         if (input_args) {
284                 kvlist = rte_kvargs_parse(input_args,
285                                 cryptodev_vdev_valid_params);
286                 if (kvlist == NULL)
287                         return -1;
288
289                 ret = rte_kvargs_process(kvlist,
290                                         RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
291                                         &rte_cryptodev_vdev_parse_integer_arg,
292                                         &params->max_nb_queue_pairs);
293                 if (ret < 0)
294                         goto free_kvlist;
295
296                 ret = rte_kvargs_process(kvlist,
297                                         RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
298                                         &rte_cryptodev_vdev_parse_integer_arg,
299                                         &params->max_nb_sessions);
300                 if (ret < 0)
301                         goto free_kvlist;
302
303                 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_SOCKET_ID,
304                                         &rte_cryptodev_vdev_parse_integer_arg,
305                                         &params->socket_id);
306                 if (ret < 0)
307                         goto free_kvlist;
308
309                 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_NAME,
310                                         &rte_cryptodev_vdev_parse_name_arg,
311                                         params);
312                 if (ret < 0)
313                         goto free_kvlist;
314         }
315
316 free_kvlist:
317         rte_kvargs_free(kvlist);
318         return ret;
319 }
320
321 int
322 rte_cryptodev_pci_generic_probe(struct rte_pci_device *pci_dev,
323                         size_t private_data_size,
324                         cryptodev_pci_init_t dev_init)
325 {
326         struct rte_cryptodev *cryptodev;
327
328         char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
329
330         int retval;
331
332         rte_pci_device_name(&pci_dev->addr, cryptodev_name,
333                         sizeof(cryptodev_name));
334
335         cryptodev = rte_cryptodev_pmd_allocate(cryptodev_name, rte_socket_id());
336         if (cryptodev == NULL)
337                 return -ENOMEM;
338
339         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
340                 cryptodev->data->dev_private =
341                                 rte_zmalloc_socket(
342                                                 "cryptodev private structure",
343                                                 private_data_size,
344                                                 RTE_CACHE_LINE_SIZE,
345                                                 rte_socket_id());
346
347                 if (cryptodev->data->dev_private == NULL)
348                         rte_panic("Cannot allocate memzone for private "
349                                         "device data");
350         }
351
352         cryptodev->device = &pci_dev->device;
353
354         /* Invoke PMD device initialization function */
355         RTE_FUNC_PTR_OR_ERR_RET(*dev_init, -EINVAL);
356         retval = dev_init(cryptodev);
357         if (retval == 0)
358                 return 0;
359
360         CDEV_LOG_ERR("driver %s: crypto_dev_init(vendor_id=0x%x device_id=0x%x)"
361                         " failed", pci_dev->device.driver->name,
362                         (unsigned int) pci_dev->id.vendor_id,
363                         (unsigned int) pci_dev->id.device_id);
364
365         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
366                 rte_free(cryptodev->data->dev_private);
367
368         /* free crypto device */
369         rte_cryptodev_pmd_release_device(cryptodev);
370
371         return -ENXIO;
372 }
373
374 int
375 rte_cryptodev_pci_generic_remove(struct rte_pci_device *pci_dev,
376                 cryptodev_pci_uninit_t dev_uninit)
377 {
378         struct rte_cryptodev *cryptodev;
379         char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
380         int ret;
381
382         if (pci_dev == NULL)
383                 return -EINVAL;
384
385         rte_pci_device_name(&pci_dev->addr, cryptodev_name,
386                         sizeof(cryptodev_name));
387
388         cryptodev = rte_cryptodev_pmd_get_named_dev(cryptodev_name);
389         if (cryptodev == NULL)
390                 return -ENODEV;
391
392         /* Invoke PMD device uninit function */
393         if (dev_uninit) {
394                 ret = dev_uninit(cryptodev);
395                 if (ret)
396                         return ret;
397         }
398
399         /* free crypto device */
400         rte_cryptodev_pmd_release_device(cryptodev);
401
402         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
403                 rte_free(cryptodev->data->dev_private);
404
405         cryptodev->device = NULL;
406         cryptodev->data = NULL;
407
408         return 0;
409 }