a2866892d0957f84e2d21a8dfee3185184b99ead
[dpdk.git] / drivers / crypto / cnxk / cn10k_cryptodev_ops.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include <rte_cryptodev.h>
6 #include <rte_cryptodev_pmd.h>
7 #include <rte_ip.h>
8
9 #include "cn10k_cryptodev.h"
10 #include "cn10k_cryptodev_ops.h"
11 #include "cn10k_ipsec_la_ops.h"
12 #include "cn10k_ipsec.h"
13 #include "cnxk_ae.h"
14 #include "cnxk_cryptodev.h"
15 #include "cnxk_cryptodev_ops.h"
16 #include "cnxk_se.h"
17
18 static inline struct cnxk_se_sess *
19 cn10k_cpt_sym_temp_sess_create(struct cnxk_cpt_qp *qp, struct rte_crypto_op *op)
20 {
21         const int driver_id = cn10k_cryptodev_driver_id;
22         struct rte_crypto_sym_op *sym_op = op->sym;
23         struct rte_cryptodev_sym_session *sess;
24         struct cnxk_se_sess *priv;
25         int ret;
26
27         /* Create temporary session */
28         sess = rte_cryptodev_sym_session_create(qp->sess_mp);
29         if (sess == NULL)
30                 return NULL;
31
32         ret = sym_session_configure(qp->lf.roc_cpt, driver_id, sym_op->xform,
33                                     sess, qp->sess_mp_priv);
34         if (ret)
35                 goto sess_put;
36
37         priv = get_sym_session_private_data(sess, driver_id);
38
39         sym_op->session = sess;
40
41         return priv;
42
43 sess_put:
44         rte_mempool_put(qp->sess_mp, sess);
45         return NULL;
46 }
47
48 static __rte_always_inline int __rte_hot
49 cpt_sec_inst_fill(struct rte_crypto_op *op, struct cn10k_sec_session *sess,
50                   struct cpt_inst_s *inst)
51 {
52         struct rte_crypto_sym_op *sym_op = op->sym;
53         union roc_ot_ipsec_sa_word2 *w2;
54         struct cn10k_ipsec_sa *sa;
55         int ret;
56
57         if (unlikely(sym_op->m_dst && sym_op->m_dst != sym_op->m_src)) {
58                 plt_dp_err("Out of place is not supported");
59                 return -ENOTSUP;
60         }
61
62         if (unlikely(!rte_pktmbuf_is_contiguous(sym_op->m_src))) {
63                 plt_dp_err("Scatter Gather mode is not supported");
64                 return -ENOTSUP;
65         }
66
67         sa = &sess->sa;
68         w2 = (union roc_ot_ipsec_sa_word2 *)&sa->in_sa.w2;
69
70         if (w2->s.dir == ROC_IE_OT_SA_DIR_OUTBOUND)
71                 ret = process_outb_sa(op, sa, inst);
72         else
73                 ret = process_inb_sa(op, sa, inst);
74
75         return ret;
76 }
77
78 static __rte_always_inline int __rte_hot
79 cpt_sym_inst_fill(struct cnxk_cpt_qp *qp, struct rte_crypto_op *op,
80                   struct cnxk_se_sess *sess, struct cpt_inflight_req *infl_req,
81                   struct cpt_inst_s *inst)
82 {
83         uint64_t cpt_op;
84         int ret = -1;
85
86         cpt_op = sess->cpt_op;
87
88         if (cpt_op & ROC_SE_OP_CIPHER_MASK)
89                 ret = fill_fc_params(op, sess, &qp->meta_info, infl_req, inst);
90         else
91                 ret = fill_digest_params(op, sess, &qp->meta_info, infl_req,
92                                          inst);
93
94         return ret;
95 }
96
97 static inline int
98 cn10k_cpt_fill_inst(struct cnxk_cpt_qp *qp, struct rte_crypto_op *ops[],
99                     struct cpt_inst_s inst[], struct cpt_inflight_req *infl_req)
100 {
101         struct cn10k_sec_session *sec_sess;
102         struct rte_crypto_asym_op *asym_op;
103         struct rte_crypto_sym_op *sym_op;
104         struct cnxk_ae_sess *ae_sess;
105         struct cnxk_se_sess *sess;
106         struct rte_crypto_op *op;
107         uint64_t w7;
108         int ret;
109
110         op = ops[0];
111
112         inst[0].w0.u64 = 0;
113         inst[0].w2.u64 = 0;
114         inst[0].w3.u64 = 0;
115
116         sym_op = op->sym;
117
118         if (op->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
119                 if (op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
120                         sec_sess = get_sec_session_private_data(
121                                 sym_op->sec_session);
122                         ret = cpt_sec_inst_fill(op, sec_sess, &inst[0]);
123                         if (unlikely(ret))
124                                 return 0;
125                         w7 = sec_sess->sa.inst.w7;
126                 } else if (op->sess_type == RTE_CRYPTO_OP_WITH_SESSION) {
127                         sess = get_sym_session_private_data(
128                                 sym_op->session, cn10k_cryptodev_driver_id);
129                         ret = cpt_sym_inst_fill(qp, op, sess, infl_req,
130                                                 &inst[0]);
131                         if (unlikely(ret))
132                                 return 0;
133                         w7 = sess->cpt_inst_w7;
134                 } else {
135                         sess = cn10k_cpt_sym_temp_sess_create(qp, op);
136                         if (unlikely(sess == NULL)) {
137                                 plt_dp_err("Could not create temp session");
138                                 return 0;
139                         }
140
141                         ret = cpt_sym_inst_fill(qp, op, sess, infl_req,
142                                                 &inst[0]);
143                         if (unlikely(ret)) {
144                                 sym_session_clear(cn10k_cryptodev_driver_id,
145                                                   op->sym->session);
146                                 rte_mempool_put(qp->sess_mp, op->sym->session);
147                                 return 0;
148                         }
149                         w7 = sess->cpt_inst_w7;
150                 }
151         } else if (op->type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC) {
152
153                 if (op->sess_type == RTE_CRYPTO_OP_WITH_SESSION) {
154                         asym_op = op->asym;
155                         ae_sess = get_asym_session_private_data(
156                                 asym_op->session, cn10k_cryptodev_driver_id);
157                         ret = cnxk_ae_enqueue(qp, op, infl_req, &inst[0],
158                                               ae_sess);
159                         if (unlikely(ret))
160                                 return 0;
161                         w7 = ae_sess->cpt_inst_w7;
162                 } else {
163                         plt_dp_err("Not supported Asym op without session");
164                         return 0;
165                 }
166         } else {
167                 plt_dp_err("Unsupported op type");
168                 return 0;
169         }
170
171         inst[0].res_addr = (uint64_t)&infl_req->res;
172         infl_req->res.cn10k.compcode = CPT_COMP_NOT_DONE;
173         infl_req->cop = op;
174
175         inst[0].w7.u64 = w7;
176
177         return 1;
178 }
179
180 #define PKTS_PER_LOOP   32
181 #define PKTS_PER_STEORL 16
182
183 static uint16_t
184 cn10k_cpt_enqueue_burst(void *qptr, struct rte_crypto_op **ops, uint16_t nb_ops)
185 {
186         uint64_t lmt_base, lmt_arg, io_addr;
187         struct cpt_inflight_req *infl_req;
188         uint16_t nb_allowed, count = 0;
189         struct cnxk_cpt_qp *qp = qptr;
190         struct pending_queue *pend_q;
191         struct cpt_inst_s *inst;
192         uint16_t lmt_id;
193         int ret, i;
194
195         pend_q = &qp->pend_q;
196
197         nb_allowed = qp->lf.nb_desc - pend_q->pending_count;
198         nb_ops = RTE_MIN(nb_ops, nb_allowed);
199
200         if (unlikely(nb_ops == 0))
201                 return 0;
202
203         lmt_base = qp->lmtline.lmt_base;
204         io_addr = qp->lmtline.io_addr;
205
206         ROC_LMT_BASE_ID_GET(lmt_base, lmt_id);
207         inst = (struct cpt_inst_s *)lmt_base;
208
209 again:
210         for (i = 0; i < RTE_MIN(PKTS_PER_LOOP, nb_ops); i++) {
211                 infl_req = &pend_q->req_queue[pend_q->enq_tail];
212                 infl_req->op_flags = 0;
213
214                 ret = cn10k_cpt_fill_inst(qp, ops + i, &inst[2 * i], infl_req);
215                 if (unlikely(ret != 1)) {
216                         plt_dp_err("Could not process op: %p", ops + i);
217                         if (i == 0)
218                                 goto update_pending;
219                         break;
220                 }
221
222                 MOD_INC(pend_q->enq_tail, qp->lf.nb_desc);
223         }
224
225         if (i > PKTS_PER_STEORL) {
226                 lmt_arg = ROC_CN10K_CPT_LMT_ARG | (PKTS_PER_STEORL - 1) << 12 |
227                           (uint64_t)lmt_id;
228                 roc_lmt_submit_steorl(lmt_arg, io_addr);
229                 lmt_arg = ROC_CN10K_CPT_LMT_ARG |
230                           (i - PKTS_PER_STEORL - 1) << 12 |
231                           (uint64_t)(lmt_id + PKTS_PER_STEORL);
232                 roc_lmt_submit_steorl(lmt_arg, io_addr);
233         } else {
234                 lmt_arg = ROC_CN10K_CPT_LMT_ARG | (i - 1) << 12 |
235                           (uint64_t)lmt_id;
236                 roc_lmt_submit_steorl(lmt_arg, io_addr);
237         }
238
239         rte_io_wmb();
240
241         if (nb_ops - i > 0 && i == PKTS_PER_LOOP) {
242                 nb_ops -= i;
243                 ops += i;
244                 count += i;
245                 goto again;
246         }
247
248 update_pending:
249         pend_q->pending_count += count + i;
250
251         pend_q->time_out = rte_get_timer_cycles() +
252                            DEFAULT_COMMAND_TIMEOUT * rte_get_timer_hz();
253
254         return count + i;
255 }
256
257 static inline void
258 cn10k_cpt_sec_post_process(struct rte_crypto_op *cop,
259                            struct cpt_cn10k_res_s *res)
260 {
261         struct rte_mbuf *m = cop->sym->m_src;
262         const uint16_t m_len = res->rlen;
263
264         m->data_len = m_len;
265         m->pkt_len = m_len;
266 }
267
268 static inline void
269 cn10k_cpt_dequeue_post_process(struct cnxk_cpt_qp *qp,
270                                struct rte_crypto_op *cop,
271                                struct cpt_inflight_req *infl_req)
272 {
273         struct cpt_cn10k_res_s *res = (struct cpt_cn10k_res_s *)&infl_req->res;
274         unsigned int sz;
275
276         if (likely(res->compcode == CPT_COMP_GOOD ||
277                    res->compcode == CPT_COMP_WARN)) {
278                 if (unlikely(res->uc_compcode)) {
279                         if (res->uc_compcode == ROC_SE_ERR_GC_ICV_MISCOMPARE)
280                                 cop->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
281                         else
282                                 cop->status = RTE_CRYPTO_OP_STATUS_ERROR;
283
284                         plt_dp_info("Request failed with microcode error");
285                         plt_dp_info("MC completion code 0x%x",
286                                     res->uc_compcode);
287                         goto temp_sess_free;
288                 }
289
290                 cop->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
291                 if (cop->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
292                         if (cop->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
293                                 cn10k_cpt_sec_post_process(cop, res);
294                                 return;
295                         }
296
297                         /* Verify authentication data if required */
298                         if (unlikely(infl_req->op_flags &
299                                      CPT_OP_FLAGS_AUTH_VERIFY)) {
300                                 uintptr_t *rsp = infl_req->mdata;
301                                 compl_auth_verify(cop, (uint8_t *)rsp[0],
302                                                   rsp[1]);
303                         }
304                 } else if (cop->type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC) {
305                         struct rte_crypto_asym_op *op = cop->asym;
306                         uintptr_t *mdata = infl_req->mdata;
307                         struct cnxk_ae_sess *sess;
308
309                         sess = get_asym_session_private_data(
310                                 op->session, cn10k_cryptodev_driver_id);
311
312                         cnxk_ae_post_process(cop, sess, (uint8_t *)mdata[0]);
313                 }
314         } else {
315                 cop->status = RTE_CRYPTO_OP_STATUS_ERROR;
316                 plt_dp_info("HW completion code 0x%x", res->compcode);
317
318                 switch (res->compcode) {
319                 case CPT_COMP_INSTERR:
320                         plt_dp_err("Request failed with instruction error");
321                         break;
322                 case CPT_COMP_FAULT:
323                         plt_dp_err("Request failed with DMA fault");
324                         break;
325                 case CPT_COMP_HWERR:
326                         plt_dp_err("Request failed with hardware error");
327                         break;
328                 default:
329                         plt_dp_err(
330                                 "Request failed with unknown completion code");
331                 }
332         }
333
334 temp_sess_free:
335         if (unlikely(cop->sess_type == RTE_CRYPTO_OP_SESSIONLESS)) {
336                 if (cop->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
337                         sym_session_clear(cn10k_cryptodev_driver_id,
338                                           cop->sym->session);
339                         sz = rte_cryptodev_sym_get_existing_header_session_size(
340                                 cop->sym->session);
341                         memset(cop->sym->session, 0, sz);
342                         rte_mempool_put(qp->sess_mp, cop->sym->session);
343                         cop->sym->session = NULL;
344                 }
345         }
346 }
347
348 static uint16_t
349 cn10k_cpt_dequeue_burst(void *qptr, struct rte_crypto_op **ops, uint16_t nb_ops)
350 {
351         struct cpt_inflight_req *infl_req;
352         struct cnxk_cpt_qp *qp = qptr;
353         struct pending_queue *pend_q;
354         struct cpt_cn10k_res_s *res;
355         struct rte_crypto_op *cop;
356         int i, nb_pending;
357
358         pend_q = &qp->pend_q;
359
360         nb_pending = pend_q->pending_count;
361
362         if (nb_ops > nb_pending)
363                 nb_ops = nb_pending;
364
365         for (i = 0; i < nb_ops; i++) {
366                 infl_req = &pend_q->req_queue[pend_q->deq_head];
367
368                 res = (struct cpt_cn10k_res_s *)&infl_req->res;
369
370                 if (unlikely(res->compcode == CPT_COMP_NOT_DONE)) {
371                         if (unlikely(rte_get_timer_cycles() >
372                                      pend_q->time_out)) {
373                                 plt_err("Request timed out");
374                                 pend_q->time_out = rte_get_timer_cycles() +
375                                                    DEFAULT_COMMAND_TIMEOUT *
376                                                            rte_get_timer_hz();
377                         }
378                         break;
379                 }
380
381                 MOD_INC(pend_q->deq_head, qp->lf.nb_desc);
382
383                 cop = infl_req->cop;
384
385                 ops[i] = cop;
386
387                 cn10k_cpt_dequeue_post_process(qp, cop, infl_req);
388
389                 if (unlikely(infl_req->op_flags & CPT_OP_FLAGS_METABUF))
390                         rte_mempool_put(qp->meta_info.pool, infl_req->mdata);
391         }
392
393         pend_q->pending_count -= i;
394
395         return i;
396 }
397
398 void
399 cn10k_cpt_set_enqdeq_fns(struct rte_cryptodev *dev)
400 {
401         dev->enqueue_burst = cn10k_cpt_enqueue_burst;
402         dev->dequeue_burst = cn10k_cpt_dequeue_burst;
403
404         rte_mb();
405 }
406
407 static void
408 cn10k_cpt_dev_info_get(struct rte_cryptodev *dev,
409                        struct rte_cryptodev_info *info)
410 {
411         if (info != NULL) {
412                 cnxk_cpt_dev_info_get(dev, info);
413                 info->driver_id = cn10k_cryptodev_driver_id;
414         }
415 }
416
417 struct rte_cryptodev_ops cn10k_cpt_ops = {
418         /* Device control ops */
419         .dev_configure = cnxk_cpt_dev_config,
420         .dev_start = cnxk_cpt_dev_start,
421         .dev_stop = cnxk_cpt_dev_stop,
422         .dev_close = cnxk_cpt_dev_close,
423         .dev_infos_get = cn10k_cpt_dev_info_get,
424
425         .stats_get = NULL,
426         .stats_reset = NULL,
427         .queue_pair_setup = cnxk_cpt_queue_pair_setup,
428         .queue_pair_release = cnxk_cpt_queue_pair_release,
429
430         /* Symmetric crypto ops */
431         .sym_session_get_size = cnxk_cpt_sym_session_get_size,
432         .sym_session_configure = cnxk_cpt_sym_session_configure,
433         .sym_session_clear = cnxk_cpt_sym_session_clear,
434
435         /* Asymmetric crypto ops */
436         .asym_session_get_size = cnxk_ae_session_size_get,
437         .asym_session_configure = cnxk_ae_session_cfg,
438         .asym_session_clear = cnxk_ae_session_clear,
439
440 };