crypto/dpaa2_sec: add basic operations
[dpdk.git] / drivers / crypto / dpaa2_sec / dpaa2_sec_dpseci.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
5  *   Copyright (c) 2016 NXP. All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of  Freescale Semiconductor, Inc nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <time.h>
35 #include <net/if.h>
36
37 #include <rte_mbuf.h>
38 #include <rte_cryptodev.h>
39 #include <rte_malloc.h>
40 #include <rte_memcpy.h>
41 #include <rte_string_fns.h>
42 #include <rte_cycles.h>
43 #include <rte_kvargs.h>
44 #include <rte_dev.h>
45 #include <rte_cryptodev_pmd.h>
46 #include <rte_common.h>
47 #include <rte_fslmc.h>
48 #include <fslmc_vfio.h>
49 #include <dpaa2_hw_pvt.h>
50 #include <dpaa2_hw_dpio.h>
51 #include <fsl_dpseci.h>
52 #include <fsl_mc_sys.h>
53
54 #include "dpaa2_sec_priv.h"
55 #include "dpaa2_sec_logs.h"
56
57 #define FSL_VENDOR_ID           0x1957
58 #define FSL_DEVICE_ID           0x410
59 #define FSL_SUBSYSTEM_SEC       1
60 #define FSL_MC_DPSECI_DEVID     3
61
62 static int
63 dpaa2_sec_dev_configure(struct rte_cryptodev *dev __rte_unused,
64                         struct rte_cryptodev_config *config __rte_unused)
65 {
66         PMD_INIT_FUNC_TRACE();
67
68         return -ENOTSUP;
69 }
70
71 static int
72 dpaa2_sec_dev_start(struct rte_cryptodev *dev)
73 {
74         struct dpaa2_sec_dev_private *priv = dev->data->dev_private;
75         struct fsl_mc_io *dpseci = (struct fsl_mc_io *)priv->hw;
76         struct dpseci_attr attr;
77         struct dpaa2_queue *dpaa2_q;
78         struct dpaa2_sec_qp **qp = (struct dpaa2_sec_qp **)
79                                         dev->data->queue_pairs;
80         struct dpseci_rx_queue_attr rx_attr;
81         struct dpseci_tx_queue_attr tx_attr;
82         int ret, i;
83
84         PMD_INIT_FUNC_TRACE();
85
86         memset(&attr, 0, sizeof(struct dpseci_attr));
87
88         ret = dpseci_enable(dpseci, CMD_PRI_LOW, priv->token);
89         if (ret) {
90                 PMD_INIT_LOG(ERR, "DPSECI with HW_ID = %d ENABLE FAILED\n",
91                              priv->hw_id);
92                 goto get_attr_failure;
93         }
94         ret = dpseci_get_attributes(dpseci, CMD_PRI_LOW, priv->token, &attr);
95         if (ret) {
96                 PMD_INIT_LOG(ERR,
97                              "DPSEC ATTRIBUTE READ FAILED, disabling DPSEC\n");
98                 goto get_attr_failure;
99         }
100         for (i = 0; i < attr.num_rx_queues && qp[i]; i++) {
101                 dpaa2_q = &qp[i]->rx_vq;
102                 dpseci_get_rx_queue(dpseci, CMD_PRI_LOW, priv->token, i,
103                                     &rx_attr);
104                 dpaa2_q->fqid = rx_attr.fqid;
105                 PMD_INIT_LOG(DEBUG, "rx_fqid: %d", dpaa2_q->fqid);
106         }
107         for (i = 0; i < attr.num_tx_queues && qp[i]; i++) {
108                 dpaa2_q = &qp[i]->tx_vq;
109                 dpseci_get_tx_queue(dpseci, CMD_PRI_LOW, priv->token, i,
110                                     &tx_attr);
111                 dpaa2_q->fqid = tx_attr.fqid;
112                 PMD_INIT_LOG(DEBUG, "tx_fqid: %d", dpaa2_q->fqid);
113         }
114
115         return 0;
116 get_attr_failure:
117         dpseci_disable(dpseci, CMD_PRI_LOW, priv->token);
118         return -1;
119 }
120
121 static void
122 dpaa2_sec_dev_stop(struct rte_cryptodev *dev)
123 {
124         struct dpaa2_sec_dev_private *priv = dev->data->dev_private;
125         struct fsl_mc_io *dpseci = (struct fsl_mc_io *)priv->hw;
126         int ret;
127
128         PMD_INIT_FUNC_TRACE();
129
130         ret = dpseci_disable(dpseci, CMD_PRI_LOW, priv->token);
131         if (ret) {
132                 PMD_INIT_LOG(ERR, "Failure in disabling dpseci %d device",
133                              priv->hw_id);
134                 return;
135         }
136
137         ret = dpseci_reset(dpseci, CMD_PRI_LOW, priv->token);
138         if (ret < 0) {
139                 PMD_INIT_LOG(ERR, "SEC Device cannot be reset:Error = %0x\n",
140                              ret);
141                 return;
142         }
143 }
144
145 static int
146 dpaa2_sec_dev_close(struct rte_cryptodev *dev)
147 {
148         struct dpaa2_sec_dev_private *priv = dev->data->dev_private;
149         struct fsl_mc_io *dpseci = (struct fsl_mc_io *)priv->hw;
150         int ret;
151
152         PMD_INIT_FUNC_TRACE();
153
154         /* Function is reverse of dpaa2_sec_dev_init.
155          * It does the following:
156          * 1. Detach a DPSECI from attached resources i.e. buffer pools, dpbp_id
157          * 2. Close the DPSECI device
158          * 3. Free the allocated resources.
159          */
160
161         /*Close the device at underlying layer*/
162         ret = dpseci_close(dpseci, CMD_PRI_LOW, priv->token);
163         if (ret) {
164                 PMD_INIT_LOG(ERR, "Failure closing dpseci device with"
165                              " error code %d\n", ret);
166                 return -1;
167         }
168
169         /*Free the allocated memory for ethernet private data and dpseci*/
170         priv->hw = NULL;
171         free(dpseci);
172
173         return 0;
174 }
175
176 static void
177 dpaa2_sec_dev_infos_get(struct rte_cryptodev *dev,
178                         struct rte_cryptodev_info *info)
179 {
180         struct dpaa2_sec_dev_private *internals = dev->data->dev_private;
181
182         PMD_INIT_FUNC_TRACE();
183         if (info != NULL) {
184                 info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
185                 info->feature_flags = dev->feature_flags;
186                 info->capabilities = dpaa2_sec_capabilities;
187                 info->sym.max_nb_sessions = internals->max_nb_sessions;
188                 info->dev_type = RTE_CRYPTODEV_DPAA2_SEC_PMD;
189         }
190 }
191
192 static struct rte_cryptodev_ops crypto_ops = {
193         .dev_configure        = dpaa2_sec_dev_configure,
194         .dev_start            = dpaa2_sec_dev_start,
195         .dev_stop             = dpaa2_sec_dev_stop,
196         .dev_close            = dpaa2_sec_dev_close,
197         .dev_infos_get        = dpaa2_sec_dev_infos_get,
198 };
199
200 static int
201 dpaa2_sec_uninit(const struct rte_cryptodev_driver *crypto_drv __rte_unused,
202                  struct rte_cryptodev *dev)
203 {
204         PMD_INIT_LOG(INFO, "Closing DPAA2_SEC device %s on numa socket %u\n",
205                      dev->data->name, rte_socket_id());
206
207         return 0;
208 }
209
210 static int
211 dpaa2_sec_dev_init(struct rte_cryptodev *cryptodev)
212 {
213         struct dpaa2_sec_dev_private *internals;
214         struct rte_device *dev = cryptodev->device;
215         struct rte_dpaa2_device *dpaa2_dev;
216         struct fsl_mc_io *dpseci;
217         uint16_t token;
218         struct dpseci_attr attr;
219         int retcode, hw_id;
220
221         PMD_INIT_FUNC_TRACE();
222         dpaa2_dev = container_of(dev, struct rte_dpaa2_device, device);
223         if (dpaa2_dev == NULL) {
224                 PMD_INIT_LOG(ERR, "dpaa2_device not found\n");
225                 return -1;
226         }
227         hw_id = dpaa2_dev->object_id;
228
229         cryptodev->dev_type = RTE_CRYPTODEV_DPAA2_SEC_PMD;
230         cryptodev->dev_ops = &crypto_ops;
231
232         cryptodev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
233                         RTE_CRYPTODEV_FF_HW_ACCELERATED |
234                         RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
235
236         internals = cryptodev->data->dev_private;
237         internals->max_nb_sessions = RTE_DPAA2_SEC_PMD_MAX_NB_SESSIONS;
238
239         /*
240          * For secondary processes, we don't initialise any further as primary
241          * has already done this work. Only check we don't need a different
242          * RX function
243          */
244         if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
245                 PMD_INIT_LOG(DEBUG, "Device already init by primary process");
246                 return 0;
247         }
248         /*Open the rte device via MC and save the handle for further use*/
249         dpseci = (struct fsl_mc_io *)rte_calloc(NULL, 1,
250                                 sizeof(struct fsl_mc_io), 0);
251         if (!dpseci) {
252                 PMD_INIT_LOG(ERR,
253                              "Error in allocating the memory for dpsec object");
254                 return -1;
255         }
256         dpseci->regs = rte_mcp_ptr_list[0];
257
258         retcode = dpseci_open(dpseci, CMD_PRI_LOW, hw_id, &token);
259         if (retcode != 0) {
260                 PMD_INIT_LOG(ERR, "Cannot open the dpsec device: Error = %x",
261                              retcode);
262                 goto init_error;
263         }
264         retcode = dpseci_get_attributes(dpseci, CMD_PRI_LOW, token, &attr);
265         if (retcode != 0) {
266                 PMD_INIT_LOG(ERR,
267                              "Cannot get dpsec device attributed: Error = %x",
268                              retcode);
269                 goto init_error;
270         }
271         sprintf(cryptodev->data->name, "dpsec-%u", hw_id);
272
273         internals->max_nb_queue_pairs = attr.num_tx_queues;
274         cryptodev->data->nb_queue_pairs = internals->max_nb_queue_pairs;
275         internals->hw = dpseci;
276         internals->token = token;
277
278         PMD_INIT_LOG(DEBUG, "driver %s: created\n", cryptodev->data->name);
279         return 0;
280
281 init_error:
282         PMD_INIT_LOG(ERR, "driver %s: create failed\n", cryptodev->data->name);
283
284         /* dpaa2_sec_uninit(crypto_dev_name); */
285         return -EFAULT;
286 }
287
288 static int
289 cryptodev_dpaa2_sec_probe(struct rte_dpaa2_driver *dpaa2_drv,
290                           struct rte_dpaa2_device *dpaa2_dev)
291 {
292         struct rte_cryptodev *cryptodev;
293         char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
294
295         int retval;
296
297         sprintf(cryptodev_name, "dpsec-%d", dpaa2_dev->object_id);
298
299         cryptodev = rte_cryptodev_pmd_allocate(cryptodev_name, rte_socket_id());
300         if (cryptodev == NULL)
301                 return -ENOMEM;
302
303         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
304                 cryptodev->data->dev_private = rte_zmalloc_socket(
305                                         "cryptodev private structure",
306                                         sizeof(struct dpaa2_sec_dev_private),
307                                         RTE_CACHE_LINE_SIZE,
308                                         rte_socket_id());
309
310                 if (cryptodev->data->dev_private == NULL)
311                         rte_panic("Cannot allocate memzone for private "
312                                         "device data");
313         }
314
315         dpaa2_dev->cryptodev = cryptodev;
316         cryptodev->device = &dpaa2_dev->device;
317         cryptodev->driver = (struct rte_cryptodev_driver *)dpaa2_drv;
318
319         /* init user callbacks */
320         TAILQ_INIT(&(cryptodev->link_intr_cbs));
321
322         /* Invoke PMD device initialization function */
323         retval = dpaa2_sec_dev_init(cryptodev);
324         if (retval == 0)
325                 return 0;
326
327         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
328                 rte_free(cryptodev->data->dev_private);
329
330         cryptodev->attached = RTE_CRYPTODEV_DETACHED;
331
332         return -ENXIO;
333 }
334
335 static int
336 cryptodev_dpaa2_sec_remove(struct rte_dpaa2_device *dpaa2_dev)
337 {
338         struct rte_cryptodev *cryptodev;
339         int ret;
340
341         cryptodev = dpaa2_dev->cryptodev;
342         if (cryptodev == NULL)
343                 return -ENODEV;
344
345         ret = dpaa2_sec_uninit(NULL, cryptodev);
346         if (ret)
347                 return ret;
348
349         /* free crypto device */
350         rte_cryptodev_pmd_release_device(cryptodev);
351
352         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
353                 rte_free(cryptodev->data->dev_private);
354
355         cryptodev->device = NULL;
356         cryptodev->driver = NULL;
357         cryptodev->data = NULL;
358
359         return 0;
360 }
361
362 static struct rte_dpaa2_driver rte_dpaa2_sec_driver = {
363         .drv_type = DPAA2_MC_DPSECI_DEVID,
364         .driver = {
365                 .name = "DPAA2 SEC PMD"
366         },
367         .probe = cryptodev_dpaa2_sec_probe,
368         .remove = cryptodev_dpaa2_sec_remove,
369 };
370
371 RTE_PMD_REGISTER_DPAA2(dpaa2_sec_pmd, rte_dpaa2_sec_driver);