cryptodev: change queue pair configure structure
[dpdk.git] / drivers / crypto / dpaa2_sec / dpaa2_sec_dpseci.c
index e79c243..82220ac 100644 (file)
@@ -36,6 +36,7 @@ typedef uint64_t      dma_addr_t;
 
 /* RTA header files */
 #include <hw/desc/ipsec.h>
+#include <hw/desc/pdcp.h>
 #include <hw/desc/algo.h>
 
 /* Minimum job descriptor consists of a oneword job descriptor HEADER and
@@ -75,6 +76,9 @@ build_proto_compound_fd(dpaa2_sec_session *sess,
        struct rte_mbuf *dst_mbuf = sym_op->m_dst;
        int retval;
 
+       if (!dst_mbuf)
+               dst_mbuf = src_mbuf;
+
        /* Save the shared descriptor */
        flc = &priv->flc_desc[0].flc;
 
@@ -119,6 +123,15 @@ build_proto_compound_fd(dpaa2_sec_session *sess,
        DPAA2_SET_FD_LEN(fd, ip_fle->length);
        DPAA2_SET_FLE_FIN(ip_fle);
 
+#ifdef ENABLE_HFN_OVERRIDE
+       if (sess->ctxt_type == DPAA2_SEC_PDCP && sess->pdcp.hfn_ovd) {
+               /*enable HFN override override */
+               DPAA2_SET_FLE_INTERNAL_JD(ip_fle, sess->pdcp.hfn_ovd);
+               DPAA2_SET_FLE_INTERNAL_JD(op_fle, sess->pdcp.hfn_ovd);
+               DPAA2_SET_FD_INTERNAL_JD(fd, sess->pdcp.hfn_ovd);
+       }
+#endif
+
        return 0;
 
 }
@@ -1189,6 +1202,9 @@ build_sec_fd(struct rte_crypto_op *op,
                case DPAA2_SEC_IPSEC:
                        ret = build_proto_fd(sess, op, fd, bpid);
                        break;
+               case DPAA2_SEC_PDCP:
+                       ret = build_proto_compound_fd(sess, op, fd, bpid);
+                       break;
                case DPAA2_SEC_HASH_CIPHER:
                default:
                        DPAA2_SEC_ERR("error: Unsupported session");
@@ -1210,6 +1226,7 @@ dpaa2_sec_enqueue_burst(void *qp, struct rte_crypto_op **ops,
        struct dpaa2_sec_qp *dpaa2_qp = (struct dpaa2_sec_qp *)qp;
        struct qbman_swp *swp;
        uint16_t num_tx = 0;
+       uint32_t flags[MAX_TX_RING_SLOTS] = {0};
        /*todo - need to support multiple buffer pools */
        uint16_t bpid;
        struct rte_mempool *mb_pool;
@@ -1241,6 +1258,15 @@ dpaa2_sec_enqueue_burst(void *qp, struct rte_crypto_op **ops,
                        dpaa2_eqcr_size : nb_ops;
 
                for (loop = 0; loop < frames_to_send; loop++) {
+                       if ((*ops)->sym->m_src->seqn) {
+                        uint8_t dqrr_index = (*ops)->sym->m_src->seqn - 1;
+
+                        flags[loop] = QBMAN_ENQUEUE_FLAG_DCA | dqrr_index;
+                        DPAA2_PER_LCORE_DQRR_SIZE--;
+                        DPAA2_PER_LCORE_DQRR_HELD &= ~(1 << dqrr_index);
+                        (*ops)->sym->m_src->seqn = DPAA2_INVALID_MBUF_SEQN;
+                       }
+
                        /*Clear the unused FD fields before sending*/
                        memset(&fd_arr[loop], 0, sizeof(struct qbman_fd));
                        mb_pool = (*ops)->sym->m_src->pool;
@@ -1257,7 +1283,7 @@ dpaa2_sec_enqueue_burst(void *qp, struct rte_crypto_op **ops,
                while (loop < frames_to_send) {
                        loop += qbman_swp_enqueue_multiple(swp, &eqdesc,
                                                        &fd_arr[loop],
-                                                       NULL,
+                                                       &flags[loop],
                                                        frames_to_send - loop);
                }
 
@@ -1282,6 +1308,9 @@ sec_simple_fd_to_mbuf(const struct qbman_fd *fd, __rte_unused uint8_t id)
                DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)),
                rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size);
 
+       diff = len - mbuf->pkt_len;
+       mbuf->pkt_len += diff;
+       mbuf->data_len += diff;
        op = (struct rte_crypto_op *)(size_t)mbuf->buf_iova;
        mbuf->buf_iova = op->sym->aead.digest.phys_addr;
        op->sym->aead.digest.phys_addr = 0L;
@@ -1292,9 +1321,6 @@ sec_simple_fd_to_mbuf(const struct qbman_fd *fd, __rte_unused uint8_t id)
                mbuf->data_off += SEC_FLC_DHR_OUTBOUND;
        else
                mbuf->data_off += SEC_FLC_DHR_INBOUND;
-       diff = len - mbuf->pkt_len;
-       mbuf->pkt_len += diff;
-       mbuf->data_len += diff;
 
        return op;
 }
@@ -1492,8 +1518,7 @@ dpaa2_sec_queue_pair_release(struct rte_cryptodev *dev, uint16_t queue_pair_id)
 static int
 dpaa2_sec_queue_pair_setup(struct rte_cryptodev *dev, uint16_t qp_id,
                __rte_unused const struct rte_cryptodev_qp_conf *qp_conf,
-               __rte_unused int socket_id,
-               __rte_unused struct rte_mempool *session_pool)
+               __rte_unused int socket_id)
 {
        struct dpaa2_sec_dev_private *priv = dev->data->dev_private;
        struct dpaa2_sec_qp *qp;
@@ -2543,6 +2568,244 @@ out:
        return ret;
 }
 
+static int
+dpaa2_sec_set_pdcp_session(struct rte_cryptodev *dev,
+                          struct rte_security_session_conf *conf,
+                          void *sess)
+{
+       struct rte_security_pdcp_xform *pdcp_xform = &conf->pdcp;
+       struct rte_crypto_sym_xform *xform = conf->crypto_xform;
+       struct rte_crypto_auth_xform *auth_xform = NULL;
+       struct rte_crypto_cipher_xform *cipher_xform;
+       dpaa2_sec_session *session = (dpaa2_sec_session *)sess;
+       struct ctxt_priv *priv;
+       struct dpaa2_sec_dev_private *dev_priv = dev->data->dev_private;
+       struct alginfo authdata, cipherdata;
+       int bufsize = -1;
+       struct sec_flow_context *flc;
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+       int swap = true;
+#else
+       int swap = false;
+#endif
+
+       PMD_INIT_FUNC_TRACE();
+
+       memset(session, 0, sizeof(dpaa2_sec_session));
+
+       priv = (struct ctxt_priv *)rte_zmalloc(NULL,
+                               sizeof(struct ctxt_priv) +
+                               sizeof(struct sec_flc_desc),
+                               RTE_CACHE_LINE_SIZE);
+
+       if (priv == NULL) {
+               DPAA2_SEC_ERR("No memory for priv CTXT");
+               return -ENOMEM;
+       }
+
+       priv->fle_pool = dev_priv->fle_pool;
+       flc = &priv->flc_desc[0].flc;
+
+       /* find xfrm types */
+       if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER && xform->next == NULL) {
+               cipher_xform = &xform->cipher;
+       } else if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
+                  xform->next->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
+               session->ext_params.aead_ctxt.auth_cipher_text = true;
+               cipher_xform = &xform->cipher;
+               auth_xform = &xform->next->auth;
+       } else if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH &&
+                  xform->next->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
+               session->ext_params.aead_ctxt.auth_cipher_text = false;
+               cipher_xform = &xform->next->cipher;
+               auth_xform = &xform->auth;
+       } else {
+               DPAA2_SEC_ERR("Invalid crypto type");
+               return -EINVAL;
+       }
+
+       session->ctxt_type = DPAA2_SEC_PDCP;
+       if (cipher_xform) {
+               session->cipher_key.data = rte_zmalloc(NULL,
+                                              cipher_xform->key.length,
+                                              RTE_CACHE_LINE_SIZE);
+               if (session->cipher_key.data == NULL &&
+                               cipher_xform->key.length > 0) {
+                       DPAA2_SEC_ERR("No Memory for cipher key");
+                       rte_free(priv);
+                       return -ENOMEM;
+               }
+               session->cipher_key.length = cipher_xform->key.length;
+               memcpy(session->cipher_key.data, cipher_xform->key.data,
+                       cipher_xform->key.length);
+               session->dir =
+                       (cipher_xform->op == RTE_CRYPTO_CIPHER_OP_ENCRYPT) ?
+                                       DIR_ENC : DIR_DEC;
+               session->cipher_alg = cipher_xform->algo;
+       } else {
+               session->cipher_key.data = NULL;
+               session->cipher_key.length = 0;
+               session->cipher_alg = RTE_CRYPTO_CIPHER_NULL;
+               session->dir = DIR_ENC;
+       }
+
+       session->pdcp.domain = pdcp_xform->domain;
+       session->pdcp.bearer = pdcp_xform->bearer;
+       session->pdcp.pkt_dir = pdcp_xform->pkt_dir;
+       session->pdcp.sn_size = pdcp_xform->sn_size;
+#ifdef ENABLE_HFN_OVERRIDE
+       session->pdcp.hfn_ovd = pdcp_xform->hfn_ovd;
+#endif
+       session->pdcp.hfn = pdcp_xform->hfn;
+       session->pdcp.hfn_threshold = pdcp_xform->hfn_threshold;
+
+       cipherdata.key = (size_t)session->cipher_key.data;
+       cipherdata.keylen = session->cipher_key.length;
+       cipherdata.key_enc_flags = 0;
+       cipherdata.key_type = RTA_DATA_IMM;
+
+       switch (session->cipher_alg) {
+       case RTE_CRYPTO_CIPHER_SNOW3G_UEA2:
+               cipherdata.algtype = PDCP_CIPHER_TYPE_SNOW;
+               break;
+       case RTE_CRYPTO_CIPHER_ZUC_EEA3:
+               cipherdata.algtype = PDCP_CIPHER_TYPE_ZUC;
+               break;
+       case RTE_CRYPTO_CIPHER_AES_CTR:
+               cipherdata.algtype = PDCP_CIPHER_TYPE_AES;
+               break;
+       case RTE_CRYPTO_CIPHER_NULL:
+               cipherdata.algtype = PDCP_CIPHER_TYPE_NULL;
+               break;
+       default:
+               DPAA2_SEC_ERR("Crypto: Undefined Cipher specified %u",
+                             session->cipher_alg);
+               goto out;
+       }
+
+       /* Auth is only applicable for control mode operation. */
+       if (pdcp_xform->domain == RTE_SECURITY_PDCP_MODE_CONTROL) {
+               if (pdcp_xform->sn_size != RTE_SECURITY_PDCP_SN_SIZE_5) {
+                       DPAA2_SEC_ERR(
+                               "PDCP Seq Num size should be 5 bits for cmode");
+                       goto out;
+               }
+               if (auth_xform) {
+                       session->auth_key.data = rte_zmalloc(NULL,
+                                                       auth_xform->key.length,
+                                                       RTE_CACHE_LINE_SIZE);
+                       if (session->auth_key.data == NULL &&
+                                       auth_xform->key.length > 0) {
+                               DPAA2_SEC_ERR("No Memory for auth key");
+                               rte_free(session->cipher_key.data);
+                               rte_free(priv);
+                               return -ENOMEM;
+                       }
+                       session->auth_key.length = auth_xform->key.length;
+                       memcpy(session->auth_key.data, auth_xform->key.data,
+                                       auth_xform->key.length);
+                       session->auth_alg = auth_xform->algo;
+               } else {
+                       session->auth_key.data = NULL;
+                       session->auth_key.length = 0;
+                       session->auth_alg = RTE_CRYPTO_AUTH_NULL;
+               }
+               authdata.key = (size_t)session->auth_key.data;
+               authdata.keylen = session->auth_key.length;
+               authdata.key_enc_flags = 0;
+               authdata.key_type = RTA_DATA_IMM;
+
+               switch (session->auth_alg) {
+               case RTE_CRYPTO_AUTH_SNOW3G_UIA2:
+                       authdata.algtype = PDCP_AUTH_TYPE_SNOW;
+                       break;
+               case RTE_CRYPTO_AUTH_ZUC_EIA3:
+                       authdata.algtype = PDCP_AUTH_TYPE_ZUC;
+                       break;
+               case RTE_CRYPTO_AUTH_AES_CMAC:
+                       authdata.algtype = PDCP_AUTH_TYPE_AES;
+                       break;
+               case RTE_CRYPTO_AUTH_NULL:
+                       authdata.algtype = PDCP_AUTH_TYPE_NULL;
+                       break;
+               default:
+                       DPAA2_SEC_ERR("Crypto: Unsupported auth alg %u",
+                                     session->auth_alg);
+                       goto out;
+               }
+
+               if (session->dir == DIR_ENC)
+                       bufsize = cnstr_shdsc_pdcp_c_plane_encap(
+                                       priv->flc_desc[0].desc, 1, swap,
+                                       pdcp_xform->hfn,
+                                       pdcp_xform->bearer,
+                                       pdcp_xform->pkt_dir,
+                                       pdcp_xform->hfn_threshold,
+                                       &cipherdata, &authdata,
+                                       0);
+               else if (session->dir == DIR_DEC)
+                       bufsize = cnstr_shdsc_pdcp_c_plane_decap(
+                                       priv->flc_desc[0].desc, 1, swap,
+                                       pdcp_xform->hfn,
+                                       pdcp_xform->bearer,
+                                       pdcp_xform->pkt_dir,
+                                       pdcp_xform->hfn_threshold,
+                                       &cipherdata, &authdata,
+                                       0);
+       } else {
+               if (session->dir == DIR_ENC)
+                       bufsize = cnstr_shdsc_pdcp_u_plane_encap(
+                                       priv->flc_desc[0].desc, 1, swap,
+                                       (enum pdcp_sn_size)pdcp_xform->sn_size,
+                                       pdcp_xform->hfn,
+                                       pdcp_xform->bearer,
+                                       pdcp_xform->pkt_dir,
+                                       pdcp_xform->hfn_threshold,
+                                       &cipherdata, 0);
+               else if (session->dir == DIR_DEC)
+                       bufsize = cnstr_shdsc_pdcp_u_plane_decap(
+                                       priv->flc_desc[0].desc, 1, swap,
+                                       (enum pdcp_sn_size)pdcp_xform->sn_size,
+                                       pdcp_xform->hfn,
+                                       pdcp_xform->bearer,
+                                       pdcp_xform->pkt_dir,
+                                       pdcp_xform->hfn_threshold,
+                                       &cipherdata, 0);
+       }
+
+       if (bufsize < 0) {
+               DPAA2_SEC_ERR("Crypto: Invalid buffer length");
+               goto out;
+       }
+
+       /* Enable the stashing control bit */
+       DPAA2_SET_FLC_RSC(flc);
+       flc->word2_rflc_31_0 = lower_32_bits(
+                       (size_t)&(((struct dpaa2_sec_qp *)
+                       dev->data->queue_pairs[0])->rx_vq) | 0x14);
+       flc->word3_rflc_63_32 = upper_32_bits(
+                       (size_t)&(((struct dpaa2_sec_qp *)
+                       dev->data->queue_pairs[0])->rx_vq));
+
+       flc->word1_sdl = (uint8_t)bufsize;
+
+       /* Set EWS bit i.e. enable write-safe */
+       DPAA2_SET_FLC_EWS(flc);
+       /* Set BS = 1 i.e reuse input buffers as output buffers */
+       DPAA2_SET_FLC_REUSE_BS(flc);
+       /* Set FF = 10; reuse input buffers if they provide sufficient space */
+       DPAA2_SET_FLC_REUSE_FF(flc);
+
+       session->ctxt = priv;
+
+       return 0;
+out:
+       rte_free(session->auth_key.data);
+       rte_free(session->cipher_key.data);
+       rte_free(priv);
+       return -1;
+}
+
 static int
 dpaa2_sec_security_session_create(void *dev,
                                  struct rte_security_session_conf *conf,
@@ -2565,6 +2828,10 @@ dpaa2_sec_security_session_create(void *dev,
                break;
        case RTE_SECURITY_PROTOCOL_MACSEC:
                return -ENOTSUP;
+       case RTE_SECURITY_PROTOCOL_PDCP:
+               ret = dpaa2_sec_set_pdcp_session(cdev, conf,
+                               sess_private_data);
+               break;
        default:
                return -EINVAL;
        }
@@ -2880,6 +3147,38 @@ dpaa2_sec_process_parallel_event(struct qbman_swp *swp,
 
        qbman_swp_dqrr_consume(swp, dq);
 }
+static void
+dpaa2_sec_process_atomic_event(struct qbman_swp *swp __attribute__((unused)),
+                                const struct qbman_fd *fd,
+                                const struct qbman_result *dq,
+                                struct dpaa2_queue *rxq,
+                                struct rte_event *ev)
+{
+       uint8_t dqrr_index;
+       struct rte_crypto_op *crypto_op = (struct rte_crypto_op *)ev->event_ptr;
+       /* Prefetching mbuf */
+       rte_prefetch0((void *)(size_t)(DPAA2_GET_FD_ADDR(fd)-
+               rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size));
+
+       /* Prefetching ipsec crypto_op stored in priv data of mbuf */
+       rte_prefetch0((void *)(size_t)(DPAA2_GET_FD_ADDR(fd)-64));
+
+       ev->flow_id = rxq->ev.flow_id;
+       ev->sub_event_type = rxq->ev.sub_event_type;
+       ev->event_type = RTE_EVENT_TYPE_CRYPTODEV;
+       ev->op = RTE_EVENT_OP_NEW;
+       ev->sched_type = rxq->ev.sched_type;
+       ev->queue_id = rxq->ev.queue_id;
+       ev->priority = rxq->ev.priority;
+
+       ev->event_ptr = sec_fd_to_mbuf(fd, ((struct rte_cryptodev *)
+                               (rxq->dev))->driver_id);
+       dqrr_index = qbman_get_dqrr_idx(dq);
+       crypto_op->sym->m_src->seqn = dqrr_index + 1;
+       DPAA2_PER_LCORE_DQRR_SIZE++;
+       DPAA2_PER_LCORE_DQRR_HELD |= 1 << dqrr_index;
+       DPAA2_PER_LCORE_DQRR_MBUF(dqrr_index) = crypto_op->sym->m_src;
+}
 
 int
 dpaa2_sec_eventq_attach(const struct rte_cryptodev *dev,
@@ -2895,6 +3194,8 @@ dpaa2_sec_eventq_attach(const struct rte_cryptodev *dev,
 
        if (event->sched_type == RTE_SCHED_TYPE_PARALLEL)
                qp->rx_vq.cb = dpaa2_sec_process_parallel_event;
+       else if (event->sched_type == RTE_SCHED_TYPE_ATOMIC)
+               qp->rx_vq.cb = dpaa2_sec_process_atomic_event;
        else
                return -EINVAL;
 
@@ -2906,7 +3207,10 @@ dpaa2_sec_eventq_attach(const struct rte_cryptodev *dev,
 
        cfg.options |= DPSECI_QUEUE_OPT_USER_CTX;
        cfg.user_ctx = (size_t)(qp);
-
+       if (event->sched_type == RTE_SCHED_TYPE_ATOMIC) {
+               cfg.options |= DPSECI_QUEUE_OPT_ORDER_PRESERVATION;
+               cfg.order_preservation_en = 1;
+       }
        ret = dpseci_set_rx_queue(dpseci, CMD_PRI_LOW, priv->token,
                                  qp_id, &cfg);
        if (ret) {
@@ -2962,7 +3266,7 @@ dpaa2_sec_capabilities_get(void *device __rte_unused)
        return dpaa2_sec_security_cap;
 }
 
-struct rte_security_ops dpaa2_sec_security_ops = {
+static const struct rte_security_ops dpaa2_sec_security_ops = {
        .session_create = dpaa2_sec_security_session_create,
        .session_update = NULL,
        .session_stats_get = NULL,