1dddfb0d9SAndrew Boyer /* SPDX-License-Identifier: BSD-3-Clause 2dddfb0d9SAndrew Boyer * Copyright 2021-2024 Advanced Micro Devices, Inc. 3dddfb0d9SAndrew Boyer */ 4dddfb0d9SAndrew Boyer 5dddfb0d9SAndrew Boyer #include <rte_cryptodev.h> 6dddfb0d9SAndrew Boyer #include <cryptodev_pmd.h> 7dddfb0d9SAndrew Boyer #include <rte_errno.h> 8dddfb0d9SAndrew Boyer #include <rte_malloc.h> 9dddfb0d9SAndrew Boyer #include <rte_mempool.h> 10dddfb0d9SAndrew Boyer 11dddfb0d9SAndrew Boyer #include "ionic_crypto.h" 12dddfb0d9SAndrew Boyer 13dddfb0d9SAndrew Boyer static int 14dddfb0d9SAndrew Boyer iocpt_op_config(struct rte_cryptodev *cdev, 15dddfb0d9SAndrew Boyer struct rte_cryptodev_config *config __rte_unused) 16dddfb0d9SAndrew Boyer { 17dddfb0d9SAndrew Boyer struct iocpt_dev *dev = cdev->data->dev_private; 18dddfb0d9SAndrew Boyer 19dddfb0d9SAndrew Boyer iocpt_configure(dev); 20dddfb0d9SAndrew Boyer 21dddfb0d9SAndrew Boyer return 0; 22dddfb0d9SAndrew Boyer } 23dddfb0d9SAndrew Boyer 24dddfb0d9SAndrew Boyer static int 25*80518852SAndrew Boyer iocpt_op_start(struct rte_cryptodev *cdev) 26*80518852SAndrew Boyer { 27*80518852SAndrew Boyer struct iocpt_dev *dev = cdev->data->dev_private; 28*80518852SAndrew Boyer 29*80518852SAndrew Boyer return iocpt_start(dev); 30*80518852SAndrew Boyer } 31*80518852SAndrew Boyer 32*80518852SAndrew Boyer static void 33*80518852SAndrew Boyer iocpt_op_stop(struct rte_cryptodev *cdev) 34*80518852SAndrew Boyer { 35*80518852SAndrew Boyer struct iocpt_dev *dev = cdev->data->dev_private; 36*80518852SAndrew Boyer 37*80518852SAndrew Boyer return iocpt_stop(dev); 38*80518852SAndrew Boyer } 39*80518852SAndrew Boyer 40*80518852SAndrew Boyer static int 41dddfb0d9SAndrew Boyer iocpt_op_close(struct rte_cryptodev *cdev) 42dddfb0d9SAndrew Boyer { 43dddfb0d9SAndrew Boyer struct iocpt_dev *dev = cdev->data->dev_private; 44dddfb0d9SAndrew Boyer 45dddfb0d9SAndrew Boyer iocpt_deinit(dev); 46dddfb0d9SAndrew Boyer 47dddfb0d9SAndrew Boyer return 0; 48dddfb0d9SAndrew Boyer } 49dddfb0d9SAndrew Boyer 50dddfb0d9SAndrew Boyer static void 51dddfb0d9SAndrew Boyer iocpt_op_info_get(struct rte_cryptodev *cdev, struct rte_cryptodev_info *info) 52dddfb0d9SAndrew Boyer { 53dddfb0d9SAndrew Boyer struct iocpt_dev *dev = cdev->data->dev_private; 54dddfb0d9SAndrew Boyer 55dddfb0d9SAndrew Boyer if (info == NULL) 56dddfb0d9SAndrew Boyer return; 57dddfb0d9SAndrew Boyer 58dddfb0d9SAndrew Boyer info->max_nb_queue_pairs = dev->max_qps; 59dddfb0d9SAndrew Boyer info->feature_flags = dev->features; 60dddfb0d9SAndrew Boyer info->capabilities = iocpt_get_caps(info->feature_flags); 61dddfb0d9SAndrew Boyer info->sym.max_nb_sessions = dev->max_sessions; 62dddfb0d9SAndrew Boyer info->driver_id = dev->driver_id; 63dddfb0d9SAndrew Boyer info->min_mbuf_headroom_req = 0; 64dddfb0d9SAndrew Boyer info->min_mbuf_tailroom_req = 0; 65dddfb0d9SAndrew Boyer } 66dddfb0d9SAndrew Boyer 67*80518852SAndrew Boyer static int 68*80518852SAndrew Boyer iocpt_op_queue_release(struct rte_cryptodev *cdev, uint16_t queue_id) 69*80518852SAndrew Boyer { 70*80518852SAndrew Boyer struct iocpt_crypto_q *cptq = cdev->data->queue_pairs[queue_id]; 71*80518852SAndrew Boyer 72*80518852SAndrew Boyer IOCPT_PRINT(DEBUG, "queue_id %u", queue_id); 73*80518852SAndrew Boyer 74*80518852SAndrew Boyer assert(!(cptq->flags & IOCPT_Q_F_INITED)); 75*80518852SAndrew Boyer 76*80518852SAndrew Boyer iocpt_cryptoq_free(cptq); 77*80518852SAndrew Boyer 78*80518852SAndrew Boyer cdev->data->queue_pairs[queue_id] = NULL; 79*80518852SAndrew Boyer 80*80518852SAndrew Boyer return 0; 81*80518852SAndrew Boyer } 82*80518852SAndrew Boyer 83*80518852SAndrew Boyer static int 84*80518852SAndrew Boyer iocpt_op_queue_setup(struct rte_cryptodev *cdev, uint16_t queue_id, 85*80518852SAndrew Boyer const struct rte_cryptodev_qp_conf *qp_conf, 86*80518852SAndrew Boyer int socket_id) 87*80518852SAndrew Boyer { 88*80518852SAndrew Boyer struct iocpt_dev *dev = cdev->data->dev_private; 89*80518852SAndrew Boyer int err; 90*80518852SAndrew Boyer 91*80518852SAndrew Boyer if (cdev->data->queue_pairs[queue_id] != NULL) 92*80518852SAndrew Boyer iocpt_op_queue_release(cdev, queue_id); 93*80518852SAndrew Boyer 94*80518852SAndrew Boyer if (qp_conf->nb_descriptors < (1 << IOCPT_QSIZE_MIN_LG2) || 95*80518852SAndrew Boyer qp_conf->nb_descriptors > (1 << IOCPT_QSIZE_MAX_LG2)) { 96*80518852SAndrew Boyer IOCPT_PRINT(ERR, "invalid nb_descriptors %u, use range %u..%u", 97*80518852SAndrew Boyer qp_conf->nb_descriptors, 98*80518852SAndrew Boyer 1 << IOCPT_QSIZE_MIN_LG2, 1 << IOCPT_QSIZE_MAX_LG2); 99*80518852SAndrew Boyer return -ERANGE; 100*80518852SAndrew Boyer } 101*80518852SAndrew Boyer 102*80518852SAndrew Boyer IOCPT_PRINT(DEBUG, "queue_id %u", queue_id); 103*80518852SAndrew Boyer 104*80518852SAndrew Boyer err = iocpt_cryptoq_alloc(dev, socket_id, queue_id, 105*80518852SAndrew Boyer qp_conf->nb_descriptors); 106*80518852SAndrew Boyer if (err != 0) 107*80518852SAndrew Boyer return err; 108*80518852SAndrew Boyer 109*80518852SAndrew Boyer cdev->data->queue_pairs[queue_id] = dev->cryptoqs[queue_id]; 110*80518852SAndrew Boyer 111*80518852SAndrew Boyer return 0; 112*80518852SAndrew Boyer } 113*80518852SAndrew Boyer 1146bc7f2cfSAndrew Boyer static unsigned int 1156bc7f2cfSAndrew Boyer iocpt_op_get_session_size(struct rte_cryptodev *cdev __rte_unused) 1166bc7f2cfSAndrew Boyer { 1176bc7f2cfSAndrew Boyer return iocpt_session_size(); 1186bc7f2cfSAndrew Boyer } 1196bc7f2cfSAndrew Boyer 1206bc7f2cfSAndrew Boyer static inline int 1216bc7f2cfSAndrew Boyer iocpt_is_algo_supported(struct rte_crypto_sym_xform *xform) 1226bc7f2cfSAndrew Boyer { 1236bc7f2cfSAndrew Boyer if (xform->next != NULL) { 1246bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "chaining not supported"); 1256bc7f2cfSAndrew Boyer return -ENOTSUP; 1266bc7f2cfSAndrew Boyer } 1276bc7f2cfSAndrew Boyer 1286bc7f2cfSAndrew Boyer if (xform->type != RTE_CRYPTO_SYM_XFORM_AEAD) { 1296bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "xform->type %d not supported", xform->type); 1306bc7f2cfSAndrew Boyer return -ENOTSUP; 1316bc7f2cfSAndrew Boyer } 1326bc7f2cfSAndrew Boyer 1336bc7f2cfSAndrew Boyer return 0; 1346bc7f2cfSAndrew Boyer } 1356bc7f2cfSAndrew Boyer 1366bc7f2cfSAndrew Boyer static __rte_always_inline int 1376bc7f2cfSAndrew Boyer iocpt_fill_sess_aead(struct rte_crypto_sym_xform *xform, 1386bc7f2cfSAndrew Boyer struct iocpt_session_priv *priv) 1396bc7f2cfSAndrew Boyer { 1406bc7f2cfSAndrew Boyer struct rte_crypto_aead_xform *aead_form = &xform->aead; 1416bc7f2cfSAndrew Boyer 1426bc7f2cfSAndrew Boyer if (aead_form->algo != RTE_CRYPTO_AEAD_AES_GCM) { 1436bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "Unknown algo"); 1446bc7f2cfSAndrew Boyer return -EINVAL; 1456bc7f2cfSAndrew Boyer } 1466bc7f2cfSAndrew Boyer if (aead_form->op == RTE_CRYPTO_AEAD_OP_ENCRYPT) { 1476bc7f2cfSAndrew Boyer priv->op = IOCPT_DESC_OPCODE_GCM_AEAD_ENCRYPT; 1486bc7f2cfSAndrew Boyer } else if (aead_form->op == RTE_CRYPTO_AEAD_OP_DECRYPT) { 1496bc7f2cfSAndrew Boyer priv->op = IOCPT_DESC_OPCODE_GCM_AEAD_DECRYPT; 1506bc7f2cfSAndrew Boyer } else { 1516bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "Unknown cipher operations"); 1526bc7f2cfSAndrew Boyer return -1; 1536bc7f2cfSAndrew Boyer } 1546bc7f2cfSAndrew Boyer 1556bc7f2cfSAndrew Boyer if (aead_form->key.length < IOCPT_SESS_KEY_LEN_MIN || 1566bc7f2cfSAndrew Boyer aead_form->key.length > IOCPT_SESS_KEY_LEN_MAX_SYMM) { 1576bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "Invalid cipher keylen %u", 1586bc7f2cfSAndrew Boyer aead_form->key.length); 1596bc7f2cfSAndrew Boyer return -1; 1606bc7f2cfSAndrew Boyer } 1616bc7f2cfSAndrew Boyer priv->key_len = aead_form->key.length; 1626bc7f2cfSAndrew Boyer memcpy(priv->key, aead_form->key.data, priv->key_len); 1636bc7f2cfSAndrew Boyer 1646bc7f2cfSAndrew Boyer priv->type = IOCPT_SESS_AEAD_AES_GCM; 1656bc7f2cfSAndrew Boyer priv->iv_offset = aead_form->iv.offset; 1666bc7f2cfSAndrew Boyer priv->iv_length = aead_form->iv.length; 1676bc7f2cfSAndrew Boyer priv->digest_length = aead_form->digest_length; 1686bc7f2cfSAndrew Boyer priv->aad_length = aead_form->aad_length; 1696bc7f2cfSAndrew Boyer 1706bc7f2cfSAndrew Boyer return 0; 1716bc7f2cfSAndrew Boyer } 1726bc7f2cfSAndrew Boyer 1736bc7f2cfSAndrew Boyer static int 1746bc7f2cfSAndrew Boyer iocpt_session_cfg(struct iocpt_dev *dev, 1756bc7f2cfSAndrew Boyer struct rte_crypto_sym_xform *xform, 1766bc7f2cfSAndrew Boyer struct rte_cryptodev_sym_session *sess) 1776bc7f2cfSAndrew Boyer { 1786bc7f2cfSAndrew Boyer struct rte_crypto_sym_xform *chain; 1796bc7f2cfSAndrew Boyer struct iocpt_session_priv *priv = NULL; 1806bc7f2cfSAndrew Boyer 1816bc7f2cfSAndrew Boyer if (iocpt_is_algo_supported(xform) < 0) 1826bc7f2cfSAndrew Boyer return -ENOTSUP; 1836bc7f2cfSAndrew Boyer 1846bc7f2cfSAndrew Boyer if (unlikely(sess == NULL)) { 1856bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "invalid session"); 1866bc7f2cfSAndrew Boyer return -EINVAL; 1876bc7f2cfSAndrew Boyer } 1886bc7f2cfSAndrew Boyer 1896bc7f2cfSAndrew Boyer priv = CRYPTODEV_GET_SYM_SESS_PRIV(sess); 1906bc7f2cfSAndrew Boyer priv->dev = dev; 1916bc7f2cfSAndrew Boyer 1926bc7f2cfSAndrew Boyer chain = xform; 1936bc7f2cfSAndrew Boyer while (chain) { 1946bc7f2cfSAndrew Boyer switch (chain->type) { 1956bc7f2cfSAndrew Boyer case RTE_CRYPTO_SYM_XFORM_AEAD: 1966bc7f2cfSAndrew Boyer if (iocpt_fill_sess_aead(chain, priv)) 1976bc7f2cfSAndrew Boyer return -EIO; 1986bc7f2cfSAndrew Boyer break; 1996bc7f2cfSAndrew Boyer default: 2006bc7f2cfSAndrew Boyer IOCPT_PRINT(ERR, "invalid crypto xform type %d", 2016bc7f2cfSAndrew Boyer chain->type); 2026bc7f2cfSAndrew Boyer return -ENOTSUP; 2036bc7f2cfSAndrew Boyer } 2046bc7f2cfSAndrew Boyer chain = chain->next; 2056bc7f2cfSAndrew Boyer } 2066bc7f2cfSAndrew Boyer 2076bc7f2cfSAndrew Boyer return iocpt_session_init(priv); 2086bc7f2cfSAndrew Boyer } 2096bc7f2cfSAndrew Boyer 2106bc7f2cfSAndrew Boyer static int 2116bc7f2cfSAndrew Boyer iocpt_op_session_cfg(struct rte_cryptodev *cdev, 2126bc7f2cfSAndrew Boyer struct rte_crypto_sym_xform *xform, 2136bc7f2cfSAndrew Boyer struct rte_cryptodev_sym_session *sess) 2146bc7f2cfSAndrew Boyer { 2156bc7f2cfSAndrew Boyer struct iocpt_dev *dev = cdev->data->dev_private; 2166bc7f2cfSAndrew Boyer 2176bc7f2cfSAndrew Boyer return iocpt_session_cfg(dev, xform, sess); 2186bc7f2cfSAndrew Boyer } 2196bc7f2cfSAndrew Boyer 2206bc7f2cfSAndrew Boyer static void 2216bc7f2cfSAndrew Boyer iocpt_session_clear(struct rte_cryptodev_sym_session *sess) 2226bc7f2cfSAndrew Boyer { 2236bc7f2cfSAndrew Boyer iocpt_session_deinit(CRYPTODEV_GET_SYM_SESS_PRIV(sess)); 2246bc7f2cfSAndrew Boyer } 2256bc7f2cfSAndrew Boyer 2266bc7f2cfSAndrew Boyer static void 2276bc7f2cfSAndrew Boyer iocpt_op_session_clear(struct rte_cryptodev *cdev __rte_unused, 2286bc7f2cfSAndrew Boyer struct rte_cryptodev_sym_session *sess) 2296bc7f2cfSAndrew Boyer { 2306bc7f2cfSAndrew Boyer iocpt_session_clear(sess); 2316bc7f2cfSAndrew Boyer } 2326bc7f2cfSAndrew Boyer 233*80518852SAndrew Boyer static inline void 234*80518852SAndrew Boyer iocpt_fill_sge(struct iocpt_crypto_sg_elem *arr, uint8_t idx, 235*80518852SAndrew Boyer uint64_t addr, uint16_t len) 236*80518852SAndrew Boyer { 237*80518852SAndrew Boyer arr[idx].addr = rte_cpu_to_le_64(addr); 238*80518852SAndrew Boyer arr[idx].len = rte_cpu_to_le_16(len); 239*80518852SAndrew Boyer } 240*80518852SAndrew Boyer 241*80518852SAndrew Boyer static __rte_always_inline int 242*80518852SAndrew Boyer iocpt_enq_one_aead(struct iocpt_crypto_q *cptq, 243*80518852SAndrew Boyer struct iocpt_session_priv *priv, struct rte_crypto_op *op) 244*80518852SAndrew Boyer { 245*80518852SAndrew Boyer struct rte_crypto_sym_op *sym_op = op->sym; 246*80518852SAndrew Boyer struct iocpt_queue *q = &cptq->q; 247*80518852SAndrew Boyer struct iocpt_crypto_desc *desc, *desc_base = q->base; 248*80518852SAndrew Boyer struct iocpt_crypto_sg_desc *sg_desc, *sg_desc_base = q->sg_base; 249*80518852SAndrew Boyer struct iocpt_crypto_sg_elem *src, *dst; 250*80518852SAndrew Boyer rte_iova_t aad_addr, digest_addr, iv_addr, seg_addr; 251*80518852SAndrew Boyer uint32_t data_len, data_offset, seg_len; 252*80518852SAndrew Boyer uint8_t nsge_src = 0, nsge_dst = 0, flags = 0; 253*80518852SAndrew Boyer struct rte_mbuf *m; 254*80518852SAndrew Boyer 255*80518852SAndrew Boyer desc = &desc_base[q->head_idx]; 256*80518852SAndrew Boyer sg_desc = &sg_desc_base[q->head_idx]; 257*80518852SAndrew Boyer src = sg_desc->src_elems; 258*80518852SAndrew Boyer dst = sg_desc->dst_elems; 259*80518852SAndrew Boyer 260*80518852SAndrew Boyer /* Fill the first SGE with the IV / Nonce */ 261*80518852SAndrew Boyer iv_addr = rte_crypto_op_ctophys_offset(op, priv->iv_offset); 262*80518852SAndrew Boyer iocpt_fill_sge(src, nsge_src++, iv_addr, priv->iv_length); 263*80518852SAndrew Boyer 264*80518852SAndrew Boyer /* Fill the second SGE with the AAD, if applicable */ 265*80518852SAndrew Boyer if (priv->aad_length > 0) { 266*80518852SAndrew Boyer aad_addr = sym_op->aead.aad.phys_addr; 267*80518852SAndrew Boyer iocpt_fill_sge(src, nsge_src++, aad_addr, priv->aad_length); 268*80518852SAndrew Boyer flags |= IOCPT_DESC_F_AAD_VALID; 269*80518852SAndrew Boyer } 270*80518852SAndrew Boyer 271*80518852SAndrew Boyer m = sym_op->m_src; 272*80518852SAndrew Boyer data_len = sym_op->aead.data.length; 273*80518852SAndrew Boyer 274*80518852SAndrew Boyer /* Fast-forward through mbuf chain to account for data offset */ 275*80518852SAndrew Boyer data_offset = sym_op->aead.data.offset; 276*80518852SAndrew Boyer while (m != NULL && data_offset >= m->data_len) { 277*80518852SAndrew Boyer data_offset -= m->data_len; 278*80518852SAndrew Boyer m = m->next; 279*80518852SAndrew Boyer } 280*80518852SAndrew Boyer 281*80518852SAndrew Boyer /* Fill the next SGEs with the payload segments */ 282*80518852SAndrew Boyer while (m != NULL && data_len > 0) { 283*80518852SAndrew Boyer seg_addr = rte_mbuf_data_iova(m) + data_offset; 284*80518852SAndrew Boyer seg_len = RTE_MIN(m->data_len - data_offset, data_len); 285*80518852SAndrew Boyer data_offset = 0; 286*80518852SAndrew Boyer data_len -= seg_len; 287*80518852SAndrew Boyer 288*80518852SAndrew Boyer /* Use -1 to save room for digest */ 289*80518852SAndrew Boyer if (nsge_src >= IOCPT_CRYPTO_MAX_SG_ELEMS - 1) 290*80518852SAndrew Boyer return -ERANGE; 291*80518852SAndrew Boyer 292*80518852SAndrew Boyer iocpt_fill_sge(src, nsge_src++, seg_addr, seg_len); 293*80518852SAndrew Boyer 294*80518852SAndrew Boyer m = m->next; 295*80518852SAndrew Boyer } 296*80518852SAndrew Boyer 297*80518852SAndrew Boyer /* AEAD AES-GCM: digest == authentication tag */ 298*80518852SAndrew Boyer digest_addr = sym_op->aead.digest.phys_addr; 299*80518852SAndrew Boyer iocpt_fill_sge(src, nsge_src++, digest_addr, priv->digest_length); 300*80518852SAndrew Boyer 301*80518852SAndrew Boyer /* Process Out-Of-Place destination SGL */ 302*80518852SAndrew Boyer if (sym_op->m_dst != NULL) { 303*80518852SAndrew Boyer /* Put the AAD here, too */ 304*80518852SAndrew Boyer if (priv->aad_length > 0) 305*80518852SAndrew Boyer iocpt_fill_sge(dst, nsge_dst++, 306*80518852SAndrew Boyer sym_op->aead.aad.phys_addr, priv->aad_length); 307*80518852SAndrew Boyer 308*80518852SAndrew Boyer m = sym_op->m_dst; 309*80518852SAndrew Boyer data_len = sym_op->aead.data.length; 310*80518852SAndrew Boyer 311*80518852SAndrew Boyer /* Fast-forward through chain to account for data offset */ 312*80518852SAndrew Boyer data_offset = sym_op->aead.data.offset; 313*80518852SAndrew Boyer while (m != NULL && data_offset >= m->data_len) { 314*80518852SAndrew Boyer data_offset -= m->data_len; 315*80518852SAndrew Boyer m = m->next; 316*80518852SAndrew Boyer } 317*80518852SAndrew Boyer 318*80518852SAndrew Boyer /* Fill in the SGEs with the payload segments */ 319*80518852SAndrew Boyer while (m != NULL && data_len > 0) { 320*80518852SAndrew Boyer seg_addr = rte_mbuf_data_iova(m) + data_offset; 321*80518852SAndrew Boyer seg_len = RTE_MIN(m->data_len - data_offset, data_len); 322*80518852SAndrew Boyer data_offset = 0; 323*80518852SAndrew Boyer data_len -= seg_len; 324*80518852SAndrew Boyer 325*80518852SAndrew Boyer if (nsge_dst >= IOCPT_CRYPTO_MAX_SG_ELEMS) 326*80518852SAndrew Boyer return -ERANGE; 327*80518852SAndrew Boyer 328*80518852SAndrew Boyer iocpt_fill_sge(dst, nsge_dst++, seg_addr, seg_len); 329*80518852SAndrew Boyer 330*80518852SAndrew Boyer m = m->next; 331*80518852SAndrew Boyer } 332*80518852SAndrew Boyer } 333*80518852SAndrew Boyer 334*80518852SAndrew Boyer desc->opcode = priv->op; 335*80518852SAndrew Boyer desc->flags = flags; 336*80518852SAndrew Boyer desc->num_src_dst_sgs = iocpt_encode_nsge_src_dst(nsge_src, nsge_dst); 337*80518852SAndrew Boyer desc->session_tag = rte_cpu_to_le_32(priv->index); 338*80518852SAndrew Boyer 339*80518852SAndrew Boyer op->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; 340*80518852SAndrew Boyer q->info[q->head_idx] = op; 341*80518852SAndrew Boyer q->head_idx = Q_NEXT_TO_POST(q, 1); 342*80518852SAndrew Boyer 343*80518852SAndrew Boyer return 0; 344*80518852SAndrew Boyer } 345*80518852SAndrew Boyer 346*80518852SAndrew Boyer static uint16_t 347*80518852SAndrew Boyer iocpt_enqueue_sym(void *qp, struct rte_crypto_op **ops, uint16_t nb_ops) 348*80518852SAndrew Boyer { 349*80518852SAndrew Boyer struct iocpt_crypto_q *cptq = qp; 350*80518852SAndrew Boyer struct rte_crypto_op *op; 351*80518852SAndrew Boyer struct iocpt_session_priv *priv; 352*80518852SAndrew Boyer uint16_t avail, count; 353*80518852SAndrew Boyer int err; 354*80518852SAndrew Boyer 355*80518852SAndrew Boyer avail = iocpt_q_space_avail(&cptq->q); 356*80518852SAndrew Boyer if (unlikely(nb_ops > avail)) 357*80518852SAndrew Boyer nb_ops = avail; 358*80518852SAndrew Boyer 359*80518852SAndrew Boyer count = 0; 360*80518852SAndrew Boyer while (likely(count < nb_ops)) { 361*80518852SAndrew Boyer op = ops[count]; 362*80518852SAndrew Boyer 363*80518852SAndrew Boyer if (unlikely(op->sess_type != RTE_CRYPTO_OP_WITH_SESSION)) { 364*80518852SAndrew Boyer op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS; 365*80518852SAndrew Boyer break; 366*80518852SAndrew Boyer } 367*80518852SAndrew Boyer 368*80518852SAndrew Boyer priv = CRYPTODEV_GET_SYM_SESS_PRIV(op->sym->session); 369*80518852SAndrew Boyer if (unlikely(priv == NULL)) { 370*80518852SAndrew Boyer op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION; 371*80518852SAndrew Boyer break; 372*80518852SAndrew Boyer } 373*80518852SAndrew Boyer 374*80518852SAndrew Boyer err = iocpt_enq_one_aead(cptq, priv, op); 375*80518852SAndrew Boyer if (unlikely(err != 0)) { 376*80518852SAndrew Boyer op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS; 377*80518852SAndrew Boyer break; 378*80518852SAndrew Boyer } 379*80518852SAndrew Boyer 380*80518852SAndrew Boyer count++; 381*80518852SAndrew Boyer } 382*80518852SAndrew Boyer 383*80518852SAndrew Boyer if (likely(count > 0)) 384*80518852SAndrew Boyer iocpt_q_flush(&cptq->q); 385*80518852SAndrew Boyer 386*80518852SAndrew Boyer return count; 387*80518852SAndrew Boyer } 388*80518852SAndrew Boyer 389*80518852SAndrew Boyer static uint16_t 390*80518852SAndrew Boyer iocpt_dequeue_sym(void *qp, struct rte_crypto_op **ops, uint16_t nb_ops) 391*80518852SAndrew Boyer { 392*80518852SAndrew Boyer struct iocpt_crypto_q *cptq = qp; 393*80518852SAndrew Boyer struct iocpt_queue *q = &cptq->q; 394*80518852SAndrew Boyer struct iocpt_cq *cq = &cptq->cq; 395*80518852SAndrew Boyer struct rte_crypto_op *op; 396*80518852SAndrew Boyer struct iocpt_crypto_comp *cq_desc_base = cq->base; 397*80518852SAndrew Boyer volatile struct iocpt_crypto_comp *cq_desc; 398*80518852SAndrew Boyer uint16_t count = 0; 399*80518852SAndrew Boyer 400*80518852SAndrew Boyer cq_desc = &cq_desc_base[cq->tail_idx]; 401*80518852SAndrew Boyer 402*80518852SAndrew Boyer /* First walk the CQ to update any completed op's status 403*80518852SAndrew Boyer * NB: These can arrive out of order! 404*80518852SAndrew Boyer */ 405*80518852SAndrew Boyer while ((cq_desc->color & 0x1) == cq->done_color) { 406*80518852SAndrew Boyer cq->tail_idx = Q_NEXT_TO_SRVC(cq, 1); 407*80518852SAndrew Boyer if (unlikely(cq->tail_idx == 0)) 408*80518852SAndrew Boyer cq->done_color = !cq->done_color; 409*80518852SAndrew Boyer 410*80518852SAndrew Boyer op = q->info[rte_le_to_cpu_16(cq_desc->comp_index)]; 411*80518852SAndrew Boyer 412*80518852SAndrew Boyer /* Process returned CQ descriptor status */ 413*80518852SAndrew Boyer if (unlikely(cq_desc->status)) { 414*80518852SAndrew Boyer switch (cq_desc->status) { 415*80518852SAndrew Boyer case IOCPT_COMP_SYMM_AUTH_VERIFY_ERROR: 416*80518852SAndrew Boyer op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED; 417*80518852SAndrew Boyer break; 418*80518852SAndrew Boyer case IOCPT_COMP_INVAL_OPCODE_ERROR: 419*80518852SAndrew Boyer case IOCPT_COMP_UNSUPP_OPCODE_ERROR: 420*80518852SAndrew Boyer case IOCPT_COMP_SYMM_SRC_SG_ERROR: 421*80518852SAndrew Boyer case IOCPT_COMP_SYMM_DST_SG_ERROR: 422*80518852SAndrew Boyer case IOCPT_COMP_SYMM_SRC_DST_LEN_MISMATCH: 423*80518852SAndrew Boyer case IOCPT_COMP_SYMM_KEY_IDX_ERROR: 424*80518852SAndrew Boyer op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS; 425*80518852SAndrew Boyer break; 426*80518852SAndrew Boyer default: 427*80518852SAndrew Boyer op->status = RTE_CRYPTO_OP_STATUS_ERROR; 428*80518852SAndrew Boyer break; 429*80518852SAndrew Boyer } 430*80518852SAndrew Boyer } else 431*80518852SAndrew Boyer op->status = RTE_CRYPTO_OP_STATUS_SUCCESS; 432*80518852SAndrew Boyer 433*80518852SAndrew Boyer cq_desc = &cq_desc_base[cq->tail_idx]; 434*80518852SAndrew Boyer } 435*80518852SAndrew Boyer 436*80518852SAndrew Boyer /* Next walk the SQ to pop off completed ops in-order */ 437*80518852SAndrew Boyer while (count < nb_ops) { 438*80518852SAndrew Boyer op = q->info[q->tail_idx]; 439*80518852SAndrew Boyer 440*80518852SAndrew Boyer /* No more completions */ 441*80518852SAndrew Boyer if (op == NULL || 442*80518852SAndrew Boyer op->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED) 443*80518852SAndrew Boyer break; 444*80518852SAndrew Boyer 445*80518852SAndrew Boyer ops[count] = op; 446*80518852SAndrew Boyer q->info[q->tail_idx] = NULL; 447*80518852SAndrew Boyer 448*80518852SAndrew Boyer q->tail_idx = Q_NEXT_TO_SRVC(q, 1); 449*80518852SAndrew Boyer count++; 450*80518852SAndrew Boyer } 451*80518852SAndrew Boyer 452*80518852SAndrew Boyer return count; 453*80518852SAndrew Boyer } 454*80518852SAndrew Boyer 455dddfb0d9SAndrew Boyer static struct rte_cryptodev_ops iocpt_ops = { 456dddfb0d9SAndrew Boyer .dev_configure = iocpt_op_config, 457*80518852SAndrew Boyer .dev_start = iocpt_op_start, 458*80518852SAndrew Boyer .dev_stop = iocpt_op_stop, 459dddfb0d9SAndrew Boyer .dev_close = iocpt_op_close, 460dddfb0d9SAndrew Boyer .dev_infos_get = iocpt_op_info_get, 4616bc7f2cfSAndrew Boyer 462*80518852SAndrew Boyer .queue_pair_setup = iocpt_op_queue_setup, 463*80518852SAndrew Boyer .queue_pair_release = iocpt_op_queue_release, 464*80518852SAndrew Boyer 4656bc7f2cfSAndrew Boyer .sym_session_get_size = iocpt_op_get_session_size, 4666bc7f2cfSAndrew Boyer .sym_session_configure = iocpt_op_session_cfg, 4676bc7f2cfSAndrew Boyer .sym_session_clear = iocpt_op_session_clear, 468dddfb0d9SAndrew Boyer }; 469dddfb0d9SAndrew Boyer 470dddfb0d9SAndrew Boyer int 471dddfb0d9SAndrew Boyer iocpt_assign_ops(struct rte_cryptodev *cdev) 472dddfb0d9SAndrew Boyer { 473dddfb0d9SAndrew Boyer struct iocpt_dev *dev = cdev->data->dev_private; 474dddfb0d9SAndrew Boyer 475dddfb0d9SAndrew Boyer cdev->dev_ops = &iocpt_ops; 476dddfb0d9SAndrew Boyer cdev->feature_flags = dev->features; 477dddfb0d9SAndrew Boyer 478*80518852SAndrew Boyer if (dev->features & RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO) { 479*80518852SAndrew Boyer cdev->enqueue_burst = iocpt_enqueue_sym; 480*80518852SAndrew Boyer cdev->dequeue_burst = iocpt_dequeue_sym; 481*80518852SAndrew Boyer } 482*80518852SAndrew Boyer 483dddfb0d9SAndrew Boyer return 0; 484dddfb0d9SAndrew Boyer } 485