409c7556bbd1deae619d67ee93839fdb71f5d747
[dpdk.git] / drivers / crypto / ipsec_mb / ipsec_mb_ops.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2021 Intel Corporation
3  */
4
5 #include <string.h>
6
7 #include <rte_common.h>
8 #include <rte_malloc.h>
9
10 #include "ipsec_mb_private.h"
11
12 /** Configure device */
13 int
14 ipsec_mb_config(__rte_unused struct rte_cryptodev *dev,
15                     __rte_unused struct rte_cryptodev_config *config)
16 {
17         return 0;
18 }
19
20 /** Start device */
21 int
22 ipsec_mb_start(__rte_unused struct rte_cryptodev *dev)
23 {
24         return 0;
25 }
26
27 /** Stop device */
28 void
29 ipsec_mb_stop(__rte_unused struct rte_cryptodev *dev)
30 {
31 }
32
33 /** Close device */
34 int
35 ipsec_mb_close(__rte_unused struct rte_cryptodev *dev)
36 {
37         return 0;
38 }
39
40 /** Get device statistics */
41 void
42 ipsec_mb_stats_get(struct rte_cryptodev *dev,
43                 struct rte_cryptodev_stats *stats)
44 {
45         int qp_id;
46
47         for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
48                 struct ipsec_mb_qp *qp = dev->data->queue_pairs[qp_id];
49                 if (qp == NULL) {
50                         IPSEC_MB_LOG(DEBUG, "Uninitialised qp %d", qp_id);
51                         continue;
52                 }
53
54                 stats->enqueued_count += qp->stats.enqueued_count;
55                 stats->dequeued_count += qp->stats.dequeued_count;
56
57                 stats->enqueue_err_count += qp->stats.enqueue_err_count;
58                 stats->dequeue_err_count += qp->stats.dequeue_err_count;
59         }
60 }
61
62 /** Reset device statistics */
63 void
64 ipsec_mb_stats_reset(struct rte_cryptodev *dev)
65 {
66         int qp_id;
67
68         for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
69                 struct ipsec_mb_qp *qp = dev->data->queue_pairs[qp_id];
70
71                 memset(&qp->stats, 0, sizeof(qp->stats));
72         }
73 }
74
75 /** Get device info */
76 void
77 ipsec_mb_info_get(struct rte_cryptodev *dev,
78                 struct rte_cryptodev_info *dev_info)
79 {
80         struct ipsec_mb_dev_private *internals = dev->data->dev_private;
81         struct ipsec_mb_internals *pmd_info =
82                 &ipsec_mb_pmds[internals->pmd_type];
83
84         if (dev_info != NULL) {
85                 dev_info->driver_id = dev->driver_id;
86                 dev_info->feature_flags = dev->feature_flags;
87                 dev_info->capabilities = pmd_info->caps;
88                 dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
89                 /* No limit of number of sessions */
90                 dev_info->sym.max_nb_sessions = 0;
91         }
92 }
93
94 /** Release queue pair */
95 int
96 ipsec_mb_qp_release(struct rte_cryptodev *dev, uint16_t qp_id)
97 {
98         struct ipsec_mb_qp *qp = dev->data->queue_pairs[qp_id];
99         struct rte_ring *r = NULL;
100
101         if (qp != NULL) {
102                 r = rte_ring_lookup(qp->name);
103                 if (r)
104                         rte_ring_free(r);
105                 rte_free(qp);
106                 dev->data->queue_pairs[qp_id] = NULL;
107         }
108         return 0;
109 }
110
111 /** Set a unique name for the queue pair */
112 int
113 ipsec_mb_qp_set_unique_name(struct rte_cryptodev *dev,
114                                            struct ipsec_mb_qp *qp)
115 {
116         uint32_t n =
117             snprintf(qp->name, sizeof(qp->name), "ipsec_mb_pmd_%u_qp_%u",
118                      dev->data->dev_id, qp->id);
119
120         if (n >= sizeof(qp->name))
121                 return -1;
122
123         return 0;
124 }
125
126 /** Create a ring to place processed operations on */
127 static struct rte_ring
128 *ipsec_mb_qp_create_processed_ops_ring(
129         struct ipsec_mb_qp *qp, unsigned int ring_size, int socket_id)
130 {
131         struct rte_ring *r;
132         char ring_name[RTE_CRYPTODEV_NAME_MAX_LEN];
133
134         unsigned int n = rte_strlcpy(ring_name, qp->name, sizeof(ring_name));
135
136         if (n >= sizeof(ring_name))
137                 return NULL;
138
139         r = rte_ring_lookup(ring_name);
140         if (r) {
141                 if (rte_ring_get_size(r) >= ring_size) {
142                         IPSEC_MB_LOG(
143                             INFO, "Reusing existing ring %s for processed ops",
144                             ring_name);
145                         return r;
146                 }
147                 IPSEC_MB_LOG(
148                     ERR, "Unable to reuse existing ring %s for processed ops",
149                     ring_name);
150                 return NULL;
151         }
152
153         return rte_ring_create(ring_name, ring_size, socket_id,
154                                RING_F_SP_ENQ | RING_F_SC_DEQ);
155 }
156
157 /** Setup a queue pair */
158 int
159 ipsec_mb_qp_setup(struct rte_cryptodev *dev, uint16_t qp_id,
160                                 const struct rte_cryptodev_qp_conf *qp_conf,
161                                 int socket_id)
162 {
163         struct ipsec_mb_qp *qp = NULL;
164         struct ipsec_mb_dev_private *internals = dev->data->dev_private;
165         struct ipsec_mb_internals *pmd_data =
166                 &ipsec_mb_pmds[internals->pmd_type];
167         uint32_t qp_size;
168         int ret;
169
170         /* Free memory prior to re-allocation if needed. */
171         if (dev->data->queue_pairs[qp_id] != NULL)
172                 ipsec_mb_qp_release(dev, qp_id);
173
174         qp_size = sizeof(*qp) + pmd_data->qp_priv_size;
175         /* Allocate the queue pair data structure. */
176         qp = rte_zmalloc_socket("IPSEC PMD Queue Pair", qp_size,
177                                 RTE_CACHE_LINE_SIZE, socket_id);
178         if (qp == NULL)
179                 return -ENOMEM;
180
181         qp->id = qp_id;
182         dev->data->queue_pairs[qp_id] = qp;
183         if (ipsec_mb_qp_set_unique_name(dev, qp)) {
184                 ret = -EINVAL;
185                 goto qp_setup_cleanup;
186         }
187
188         qp->pmd_type = internals->pmd_type;
189         qp->sess_mp = qp_conf->mp_session;
190         qp->sess_mp_priv = qp_conf->mp_session_private;
191
192         qp->ingress_queue = ipsec_mb_qp_create_processed_ops_ring(qp,
193                 qp_conf->nb_descriptors, socket_id);
194         if (qp->ingress_queue == NULL) {
195                 ret = -EINVAL;
196                 goto qp_setup_cleanup;
197         }
198
199         qp->mb_mgr = alloc_init_mb_mgr();
200         if (!qp->mb_mgr) {
201                 ret = -ENOMEM;
202                 goto qp_setup_cleanup;
203         }
204
205         memset(&qp->stats, 0, sizeof(qp->stats));
206
207         if (pmd_data->queue_pair_configure) {
208                 ret = pmd_data->queue_pair_configure(qp);
209                 if (ret < 0)
210                         goto qp_setup_cleanup;
211         }
212
213         return 0;
214
215 qp_setup_cleanup:
216         if (qp->mb_mgr)
217                 free_mb_mgr(qp->mb_mgr);
218         if (qp)
219                 rte_free(qp);
220         return ret;
221 }
222
223 /** Return the size of the specific pmd session structure */
224 unsigned
225 ipsec_mb_sym_session_get_size(struct rte_cryptodev *dev)
226 {
227         struct ipsec_mb_dev_private *internals = dev->data->dev_private;
228         struct ipsec_mb_internals *pmd_data =
229                 &ipsec_mb_pmds[internals->pmd_type];
230
231         return pmd_data->session_priv_size;
232 }
233
234 /** Configure pmd specific multi-buffer session from a crypto xform chain */
235 int
236 ipsec_mb_sym_session_configure(
237         struct rte_cryptodev *dev, struct rte_crypto_sym_xform *xform,
238         struct rte_cryptodev_sym_session *sess, struct rte_mempool *mempool)
239 {
240         void *sess_private_data;
241         struct ipsec_mb_dev_private *internals = dev->data->dev_private;
242         struct ipsec_mb_internals *pmd_data =
243                 &ipsec_mb_pmds[internals->pmd_type];
244         IMB_MGR *mb_mgr = alloc_init_mb_mgr();
245         int ret = 0;
246
247         if (!mb_mgr)
248                 return -ENOMEM;
249
250         if (unlikely(sess == NULL)) {
251                 IPSEC_MB_LOG(ERR, "invalid session struct");
252                 free_mb_mgr(mb_mgr);
253                 return -EINVAL;
254         }
255
256         if (rte_mempool_get(mempool, &sess_private_data)) {
257                 IPSEC_MB_LOG(ERR, "Couldn't get object from session mempool");
258                 free_mb_mgr(mb_mgr);
259                 return -ENOMEM;
260         }
261
262         ret = (*pmd_data->session_configure)(mb_mgr, sess_private_data, xform);
263         if (ret != 0) {
264                 IPSEC_MB_LOG(ERR, "failed configure session parameters");
265
266                 /* Return session to mempool */
267                 rte_mempool_put(mempool, sess_private_data);
268                 free_mb_mgr(mb_mgr);
269                 return ret;
270         }
271
272         set_sym_session_private_data(sess, dev->driver_id, sess_private_data);
273
274         return 0;
275 }
276
277 /** Clear the session memory */
278 void
279 ipsec_mb_sym_session_clear(struct rte_cryptodev *dev,
280                                struct rte_cryptodev_sym_session *sess)
281 {
282         uint8_t index = dev->driver_id;
283         void *sess_priv = get_sym_session_private_data(sess, index);
284
285         /* Zero out the whole structure */
286         if (sess_priv) {
287                 memset(sess_priv, 0, ipsec_mb_sym_session_get_size(dev));
288                 struct rte_mempool *sess_mp = rte_mempool_from_obj(sess_priv);
289
290                 set_sym_session_private_data(sess, index, NULL);
291                 rte_mempool_put(sess_mp, sess_priv);
292         }
293 }