2b8ff7adb3a9cff89a1f990d54e486a8ddd8c93a
[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_pci.h"
36 #include "rte_cryptodev_pmd.h"
37
38 /**
39  * Parse name from argument
40  */
41 static int
42 rte_cryptodev_pmd_parse_name_arg(const char *key __rte_unused,
43                 const char *value, void *extra_args)
44 {
45         struct rte_cryptodev_pmd_init_params *params = extra_args;
46         int n;
47
48         n = snprintf(params->name, RTE_CRYPTODEV_NAME_MAX_LEN, "%s", value);
49         if (n >= RTE_CRYPTODEV_NAME_MAX_LEN)
50                 return -EINVAL;
51
52         return 0;
53 }
54
55 /**
56  * Parse unsigned integer from argument
57  */
58 static int
59 rte_cryptodev_pmd_parse_uint_arg(const char *key __rte_unused,
60                 const char *value, void *extra_args)
61 {
62         int i;
63         char *end;
64         errno = 0;
65
66         i = strtol(value, &end, 10);
67         if (*end != 0 || errno != 0 || i < 0)
68                 return -EINVAL;
69
70         *((uint32_t *)extra_args) = i;
71         return 0;
72 }
73
74 int
75 rte_cryptodev_pmd_parse_input_args(
76                 struct rte_cryptodev_pmd_init_params *params,
77                 const char *args)
78 {
79         struct rte_kvargs *kvlist = NULL;
80         int ret = 0;
81
82         if (params == NULL)
83                 return -EINVAL;
84
85         if (args) {
86                 kvlist = rte_kvargs_parse(args, cryptodev_pmd_valid_params);
87                 if (kvlist == NULL)
88                         return -EINVAL;
89
90                 ret = rte_kvargs_process(kvlist,
91                                 RTE_CRYPTODEV_PMD_MAX_NB_QP_ARG,
92                                 &rte_cryptodev_pmd_parse_uint_arg,
93                                 &params->max_nb_queue_pairs);
94                 if (ret < 0)
95                         goto free_kvlist;
96
97                 ret = rte_kvargs_process(kvlist,
98                                 RTE_CRYPTODEV_PMD_MAX_NB_SESS_ARG,
99                                 &rte_cryptodev_pmd_parse_uint_arg,
100                                 &params->max_nb_sessions);
101                 if (ret < 0)
102                         goto free_kvlist;
103
104                 ret = rte_kvargs_process(kvlist,
105                                 RTE_CRYPTODEV_PMD_SOCKET_ID_ARG,
106                                 &rte_cryptodev_pmd_parse_uint_arg,
107                                 &params->socket_id);
108                 if (ret < 0)
109                         goto free_kvlist;
110
111                 ret = rte_kvargs_process(kvlist,
112                                 RTE_CRYPTODEV_PMD_NAME_ARG,
113                                 &rte_cryptodev_pmd_parse_name_arg,
114                                 params);
115                 if (ret < 0)
116                         goto free_kvlist;
117         }
118
119 free_kvlist:
120         rte_kvargs_free(kvlist);
121         return ret;
122 }
123
124 struct rte_cryptodev *
125 rte_cryptodev_pmd_create(const char *name,
126                 struct rte_device *device,
127                 struct rte_cryptodev_pmd_init_params *params)
128 {
129         struct rte_cryptodev *cryptodev;
130
131         if (params->name[0] != '\0') {
132                 CDEV_LOG_INFO("[%s] User specified device name = %s\n",
133                                 device->driver->name, params->name);
134                 name = params->name;
135         }
136
137         CDEV_LOG_INFO("[%s] - Creating cryptodev %s\n",
138                         device->driver->name, name);
139
140         CDEV_LOG_INFO("[%s] - Initialisation parameters - name: %s,"
141                         "socket id: %d, max queue pairs: %u, max sessions: %u",
142                         device->driver->name, name,
143                         params->socket_id, params->max_nb_queue_pairs,
144                         params->max_nb_sessions);
145
146         /* allocate device structure */
147         cryptodev = rte_cryptodev_pmd_allocate(name, params->socket_id);
148         if (cryptodev == NULL) {
149                 CDEV_LOG_ERR("[%s] Failed to allocate crypto device for %s",
150                                 device->driver->name, name);
151                 return NULL;
152         }
153
154         /* allocate private device structure */
155         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
156                 cryptodev->data->dev_private =
157                                 rte_zmalloc_socket("cryptodev device private",
158                                                 params->private_data_size,
159                                                 RTE_CACHE_LINE_SIZE,
160                                                 params->socket_id);
161
162                 if (cryptodev->data->dev_private == NULL) {
163                         CDEV_LOG_ERR("[%s] Cannot allocate memory for "
164                                         "cryptodev %s private data",
165                                         device->driver->name, name);
166
167                         rte_cryptodev_pmd_release_device(cryptodev);
168                         return NULL;
169                 }
170         }
171
172         cryptodev->device = device;
173
174         /* initialise user call-back tail queue */
175         TAILQ_INIT(&(cryptodev->link_intr_cbs));
176
177         return cryptodev;
178 }
179
180 int
181 rte_cryptodev_pmd_destroy(struct rte_cryptodev *cryptodev)
182 {
183         int retval;
184
185         CDEV_LOG_INFO("[%s] Closing crypto device %s",
186                         cryptodev->device->driver->name,
187                         cryptodev->device->name);
188
189         /* free crypto device */
190         retval = rte_cryptodev_pmd_release_device(cryptodev);
191         if (retval)
192                 return retval;
193
194         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
195                 rte_free(cryptodev->data->dev_private);
196
197
198         cryptodev->device = NULL;
199         cryptodev->data = NULL;
200
201         return 0;
202 }
203
204 int
205 rte_cryptodev_pci_generic_probe(struct rte_pci_device *pci_dev,
206                         size_t private_data_size,
207                         cryptodev_pci_init_t dev_init)
208 {
209         struct rte_cryptodev *cryptodev;
210
211         char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
212
213         int retval;
214
215         rte_pci_device_name(&pci_dev->addr, cryptodev_name,
216                         sizeof(cryptodev_name));
217
218         cryptodev = rte_cryptodev_pmd_allocate(cryptodev_name, rte_socket_id());
219         if (cryptodev == NULL)
220                 return -ENOMEM;
221
222         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
223                 cryptodev->data->dev_private =
224                                 rte_zmalloc_socket(
225                                                 "cryptodev private structure",
226                                                 private_data_size,
227                                                 RTE_CACHE_LINE_SIZE,
228                                                 rte_socket_id());
229
230                 if (cryptodev->data->dev_private == NULL)
231                         rte_panic("Cannot allocate memzone for private "
232                                         "device data");
233         }
234
235         cryptodev->device = &pci_dev->device;
236
237         /* Invoke PMD device initialization function */
238         RTE_FUNC_PTR_OR_ERR_RET(*dev_init, -EINVAL);
239         retval = dev_init(cryptodev);
240         if (retval == 0)
241                 return 0;
242
243         CDEV_LOG_ERR("driver %s: crypto_dev_init(vendor_id=0x%x device_id=0x%x)"
244                         " failed", pci_dev->device.driver->name,
245                         (unsigned int) pci_dev->id.vendor_id,
246                         (unsigned int) pci_dev->id.device_id);
247
248         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
249                 rte_free(cryptodev->data->dev_private);
250
251         /* free crypto device */
252         rte_cryptodev_pmd_release_device(cryptodev);
253
254         return -ENXIO;
255 }
256
257 int
258 rte_cryptodev_pci_generic_remove(struct rte_pci_device *pci_dev,
259                 cryptodev_pci_uninit_t dev_uninit)
260 {
261         struct rte_cryptodev *cryptodev;
262         char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
263         int ret;
264
265         if (pci_dev == NULL)
266                 return -EINVAL;
267
268         rte_pci_device_name(&pci_dev->addr, cryptodev_name,
269                         sizeof(cryptodev_name));
270
271         cryptodev = rte_cryptodev_pmd_get_named_dev(cryptodev_name);
272         if (cryptodev == NULL)
273                 return -ENODEV;
274
275         /* Invoke PMD device uninit function */
276         if (dev_uninit) {
277                 ret = dev_uninit(cryptodev);
278                 if (ret)
279                         return ret;
280         }
281
282         /* free crypto device */
283         rte_cryptodev_pmd_release_device(cryptodev);
284
285         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
286                 rte_free(cryptodev->data->dev_private);
287
288         cryptodev->device = NULL;
289         cryptodev->data = NULL;
290
291         return 0;
292 }