18769079aSJay Zhou /* SPDX-License-Identifier: BSD-3-Clause 28769079aSJay Zhou * Copyright(c) 2018 HUAWEI TECHNOLOGIES CO., LTD. 38769079aSJay Zhou */ 4*6f0175ffSJay Zhou #include <rte_errno.h> 58769079aSJay Zhou #include <rte_pci.h> 68769079aSJay Zhou #include <rte_bus_pci.h> 725500d4bSJay Zhou #include <rte_cryptodev.h> 88769079aSJay Zhou #include <rte_cryptodev_pmd.h> 925500d4bSJay Zhou #include <rte_eal.h> 108769079aSJay Zhou 118769079aSJay Zhou #include "virtio_cryptodev.h" 1225500d4bSJay Zhou #include "virtqueue.h" 1325500d4bSJay Zhou 1425500d4bSJay Zhou int virtio_crypto_logtype_init; 1525500d4bSJay Zhou int virtio_crypto_logtype_session; 1625500d4bSJay Zhou int virtio_crypto_logtype_rx; 1725500d4bSJay Zhou int virtio_crypto_logtype_tx; 1825500d4bSJay Zhou int virtio_crypto_logtype_driver; 1925500d4bSJay Zhou 20*6f0175ffSJay Zhou static int virtio_crypto_dev_configure(struct rte_cryptodev *dev, 21*6f0175ffSJay Zhou struct rte_cryptodev_config *config); 22*6f0175ffSJay Zhou static int virtio_crypto_dev_start(struct rte_cryptodev *dev); 23*6f0175ffSJay Zhou static void virtio_crypto_dev_stop(struct rte_cryptodev *dev); 24*6f0175ffSJay Zhou static int virtio_crypto_dev_close(struct rte_cryptodev *dev); 25*6f0175ffSJay Zhou static void virtio_crypto_dev_info_get(struct rte_cryptodev *dev, 26*6f0175ffSJay Zhou struct rte_cryptodev_info *dev_info); 27*6f0175ffSJay Zhou static int virtio_crypto_qp_setup(struct rte_cryptodev *dev, 28*6f0175ffSJay Zhou uint16_t queue_pair_id, 29*6f0175ffSJay Zhou const struct rte_cryptodev_qp_conf *qp_conf, 30*6f0175ffSJay Zhou int socket_id, 31*6f0175ffSJay Zhou struct rte_mempool *session_pool); 32*6f0175ffSJay Zhou static int virtio_crypto_qp_release(struct rte_cryptodev *dev, 33*6f0175ffSJay Zhou uint16_t queue_pair_id); 34*6f0175ffSJay Zhou static void virtio_crypto_dev_free_mbufs(struct rte_cryptodev *dev); 35*6f0175ffSJay Zhou 3625500d4bSJay Zhou /* 3725500d4bSJay Zhou * The set of PCI devices this driver supports 3825500d4bSJay Zhou */ 3925500d4bSJay Zhou static const struct rte_pci_id pci_id_virtio_crypto_map[] = { 4025500d4bSJay Zhou { RTE_PCI_DEVICE(VIRTIO_CRYPTO_PCI_VENDORID, 4125500d4bSJay Zhou VIRTIO_CRYPTO_PCI_DEVICEID) }, 4225500d4bSJay Zhou { .vendor_id = 0, /* sentinel */ }, 4325500d4bSJay Zhou }; 448769079aSJay Zhou 458769079aSJay Zhou uint8_t cryptodev_virtio_driver_id; 468769079aSJay Zhou 47*6f0175ffSJay Zhou void 48*6f0175ffSJay Zhou virtio_crypto_queue_release(struct virtqueue *vq) 49*6f0175ffSJay Zhou { 50*6f0175ffSJay Zhou struct virtio_crypto_hw *hw; 51*6f0175ffSJay Zhou 52*6f0175ffSJay Zhou PMD_INIT_FUNC_TRACE(); 53*6f0175ffSJay Zhou 54*6f0175ffSJay Zhou if (vq) { 55*6f0175ffSJay Zhou hw = vq->hw; 56*6f0175ffSJay Zhou /* Select and deactivate the queue */ 57*6f0175ffSJay Zhou VTPCI_OPS(hw)->del_queue(hw, vq); 58*6f0175ffSJay Zhou 59*6f0175ffSJay Zhou rte_memzone_free(vq->mz); 60*6f0175ffSJay Zhou rte_mempool_free(vq->mpool); 61*6f0175ffSJay Zhou rte_free(vq); 62*6f0175ffSJay Zhou } 63*6f0175ffSJay Zhou } 64*6f0175ffSJay Zhou 65*6f0175ffSJay Zhou #define MPOOL_MAX_NAME_SZ 32 66*6f0175ffSJay Zhou 67*6f0175ffSJay Zhou int 68*6f0175ffSJay Zhou virtio_crypto_queue_setup(struct rte_cryptodev *dev, 69*6f0175ffSJay Zhou int queue_type, 70*6f0175ffSJay Zhou uint16_t vtpci_queue_idx, 71*6f0175ffSJay Zhou uint16_t nb_desc, 72*6f0175ffSJay Zhou int socket_id, 73*6f0175ffSJay Zhou struct virtqueue **pvq) 74*6f0175ffSJay Zhou { 75*6f0175ffSJay Zhou char vq_name[VIRTQUEUE_MAX_NAME_SZ]; 76*6f0175ffSJay Zhou char mpool_name[MPOOL_MAX_NAME_SZ]; 77*6f0175ffSJay Zhou const struct rte_memzone *mz; 78*6f0175ffSJay Zhou unsigned int vq_size, size; 79*6f0175ffSJay Zhou struct virtio_crypto_hw *hw = dev->data->dev_private; 80*6f0175ffSJay Zhou struct virtqueue *vq = NULL; 81*6f0175ffSJay Zhou uint32_t i = 0; 82*6f0175ffSJay Zhou uint32_t j; 83*6f0175ffSJay Zhou 84*6f0175ffSJay Zhou PMD_INIT_FUNC_TRACE(); 85*6f0175ffSJay Zhou 86*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("setting up queue: %u", vtpci_queue_idx); 87*6f0175ffSJay Zhou 88*6f0175ffSJay Zhou /* 89*6f0175ffSJay Zhou * Read the virtqueue size from the Queue Size field 90*6f0175ffSJay Zhou * Always power of 2 and if 0 virtqueue does not exist 91*6f0175ffSJay Zhou */ 92*6f0175ffSJay Zhou vq_size = VTPCI_OPS(hw)->get_queue_num(hw, vtpci_queue_idx); 93*6f0175ffSJay Zhou if (vq_size == 0) { 94*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("virtqueue does not exist"); 95*6f0175ffSJay Zhou return -EINVAL; 96*6f0175ffSJay Zhou } 97*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("vq_size: %u", vq_size); 98*6f0175ffSJay Zhou 99*6f0175ffSJay Zhou if (!rte_is_power_of_2(vq_size)) { 100*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("virtqueue size is not powerof 2"); 101*6f0175ffSJay Zhou return -EINVAL; 102*6f0175ffSJay Zhou } 103*6f0175ffSJay Zhou 104*6f0175ffSJay Zhou if (queue_type == VTCRYPTO_DATAQ) { 105*6f0175ffSJay Zhou snprintf(vq_name, sizeof(vq_name), "dev%d_dataqueue%d", 106*6f0175ffSJay Zhou dev->data->dev_id, vtpci_queue_idx); 107*6f0175ffSJay Zhou snprintf(mpool_name, sizeof(mpool_name), 108*6f0175ffSJay Zhou "dev%d_dataqueue%d_mpool", 109*6f0175ffSJay Zhou dev->data->dev_id, vtpci_queue_idx); 110*6f0175ffSJay Zhou } else if (queue_type == VTCRYPTO_CTRLQ) { 111*6f0175ffSJay Zhou snprintf(vq_name, sizeof(vq_name), "dev%d_controlqueue", 112*6f0175ffSJay Zhou dev->data->dev_id); 113*6f0175ffSJay Zhou snprintf(mpool_name, sizeof(mpool_name), 114*6f0175ffSJay Zhou "dev%d_controlqueue_mpool", 115*6f0175ffSJay Zhou dev->data->dev_id); 116*6f0175ffSJay Zhou } 117*6f0175ffSJay Zhou size = RTE_ALIGN_CEIL(sizeof(*vq) + 118*6f0175ffSJay Zhou vq_size * sizeof(struct vq_desc_extra), 119*6f0175ffSJay Zhou RTE_CACHE_LINE_SIZE); 120*6f0175ffSJay Zhou vq = rte_zmalloc_socket(vq_name, size, RTE_CACHE_LINE_SIZE, 121*6f0175ffSJay Zhou socket_id); 122*6f0175ffSJay Zhou if (vq == NULL) { 123*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("Can not allocate virtqueue"); 124*6f0175ffSJay Zhou return -ENOMEM; 125*6f0175ffSJay Zhou } 126*6f0175ffSJay Zhou 127*6f0175ffSJay Zhou if (queue_type == VTCRYPTO_DATAQ) { 128*6f0175ffSJay Zhou /* pre-allocate a mempool and use it in the data plane to 129*6f0175ffSJay Zhou * improve performance 130*6f0175ffSJay Zhou */ 131*6f0175ffSJay Zhou vq->mpool = rte_mempool_lookup(mpool_name); 132*6f0175ffSJay Zhou if (vq->mpool == NULL) 133*6f0175ffSJay Zhou vq->mpool = rte_mempool_create(mpool_name, 134*6f0175ffSJay Zhou vq_size, 135*6f0175ffSJay Zhou sizeof(struct virtio_crypto_op_cookie), 136*6f0175ffSJay Zhou RTE_CACHE_LINE_SIZE, 0, 137*6f0175ffSJay Zhou NULL, NULL, NULL, NULL, socket_id, 138*6f0175ffSJay Zhou 0); 139*6f0175ffSJay Zhou if (!vq->mpool) { 140*6f0175ffSJay Zhou VIRTIO_CRYPTO_DRV_LOG_ERR("Virtio Crypto PMD " 141*6f0175ffSJay Zhou "Cannot create mempool"); 142*6f0175ffSJay Zhou goto mpool_create_err; 143*6f0175ffSJay Zhou } 144*6f0175ffSJay Zhou for (i = 0; i < vq_size; i++) { 145*6f0175ffSJay Zhou vq->vq_descx[i].cookie = 146*6f0175ffSJay Zhou rte_zmalloc("crypto PMD op cookie pointer", 147*6f0175ffSJay Zhou sizeof(struct virtio_crypto_op_cookie), 148*6f0175ffSJay Zhou RTE_CACHE_LINE_SIZE); 149*6f0175ffSJay Zhou if (vq->vq_descx[i].cookie == NULL) { 150*6f0175ffSJay Zhou VIRTIO_CRYPTO_DRV_LOG_ERR("Failed to " 151*6f0175ffSJay Zhou "alloc mem for cookie"); 152*6f0175ffSJay Zhou goto cookie_alloc_err; 153*6f0175ffSJay Zhou } 154*6f0175ffSJay Zhou } 155*6f0175ffSJay Zhou } 156*6f0175ffSJay Zhou 157*6f0175ffSJay Zhou vq->hw = hw; 158*6f0175ffSJay Zhou vq->dev_id = dev->data->dev_id; 159*6f0175ffSJay Zhou vq->vq_queue_index = vtpci_queue_idx; 160*6f0175ffSJay Zhou vq->vq_nentries = vq_size; 161*6f0175ffSJay Zhou 162*6f0175ffSJay Zhou /* 163*6f0175ffSJay Zhou * Using part of the vring entries is permitted, but the maximum 164*6f0175ffSJay Zhou * is vq_size 165*6f0175ffSJay Zhou */ 166*6f0175ffSJay Zhou if (nb_desc == 0 || nb_desc > vq_size) 167*6f0175ffSJay Zhou nb_desc = vq_size; 168*6f0175ffSJay Zhou vq->vq_free_cnt = nb_desc; 169*6f0175ffSJay Zhou 170*6f0175ffSJay Zhou /* 171*6f0175ffSJay Zhou * Reserve a memzone for vring elements 172*6f0175ffSJay Zhou */ 173*6f0175ffSJay Zhou size = vring_size(vq_size, VIRTIO_PCI_VRING_ALIGN); 174*6f0175ffSJay Zhou vq->vq_ring_size = RTE_ALIGN_CEIL(size, VIRTIO_PCI_VRING_ALIGN); 175*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("%s vring_size: %d, rounded_vring_size: %d", 176*6f0175ffSJay Zhou (queue_type == VTCRYPTO_DATAQ) ? "dataq" : "ctrlq", 177*6f0175ffSJay Zhou size, vq->vq_ring_size); 178*6f0175ffSJay Zhou 179*6f0175ffSJay Zhou mz = rte_memzone_reserve_aligned(vq_name, vq->vq_ring_size, 180*6f0175ffSJay Zhou socket_id, 0, VIRTIO_PCI_VRING_ALIGN); 181*6f0175ffSJay Zhou if (mz == NULL) { 182*6f0175ffSJay Zhou if (rte_errno == EEXIST) 183*6f0175ffSJay Zhou mz = rte_memzone_lookup(vq_name); 184*6f0175ffSJay Zhou if (mz == NULL) { 185*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("not enough memory"); 186*6f0175ffSJay Zhou goto mz_reserve_err; 187*6f0175ffSJay Zhou } 188*6f0175ffSJay Zhou } 189*6f0175ffSJay Zhou 190*6f0175ffSJay Zhou /* 191*6f0175ffSJay Zhou * Virtio PCI device VIRTIO_PCI_QUEUE_PF register is 32bit, 192*6f0175ffSJay Zhou * and only accepts 32 bit page frame number. 193*6f0175ffSJay Zhou * Check if the allocated physical memory exceeds 16TB. 194*6f0175ffSJay Zhou */ 195*6f0175ffSJay Zhou if ((mz->phys_addr + vq->vq_ring_size - 1) 196*6f0175ffSJay Zhou >> (VIRTIO_PCI_QUEUE_ADDR_SHIFT + 32)) { 197*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("vring address shouldn't be " 198*6f0175ffSJay Zhou "above 16TB!"); 199*6f0175ffSJay Zhou goto vring_addr_err; 200*6f0175ffSJay Zhou } 201*6f0175ffSJay Zhou 202*6f0175ffSJay Zhou memset(mz->addr, 0, sizeof(mz->len)); 203*6f0175ffSJay Zhou vq->mz = mz; 204*6f0175ffSJay Zhou vq->vq_ring_mem = mz->phys_addr; 205*6f0175ffSJay Zhou vq->vq_ring_virt_mem = mz->addr; 206*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_ring_mem(physical): 0x%"PRIx64, 207*6f0175ffSJay Zhou (uint64_t)mz->phys_addr); 208*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_ring_virt_mem: 0x%"PRIx64, 209*6f0175ffSJay Zhou (uint64_t)(uintptr_t)mz->addr); 210*6f0175ffSJay Zhou 211*6f0175ffSJay Zhou *pvq = vq; 212*6f0175ffSJay Zhou 213*6f0175ffSJay Zhou return 0; 214*6f0175ffSJay Zhou 215*6f0175ffSJay Zhou vring_addr_err: 216*6f0175ffSJay Zhou rte_memzone_free(mz); 217*6f0175ffSJay Zhou mz_reserve_err: 218*6f0175ffSJay Zhou cookie_alloc_err: 219*6f0175ffSJay Zhou rte_mempool_free(vq->mpool); 220*6f0175ffSJay Zhou if (i != 0) { 221*6f0175ffSJay Zhou for (j = 0; j < i; j++) 222*6f0175ffSJay Zhou rte_free(vq->vq_descx[j].cookie); 223*6f0175ffSJay Zhou } 224*6f0175ffSJay Zhou mpool_create_err: 225*6f0175ffSJay Zhou rte_free(vq); 226*6f0175ffSJay Zhou return -ENOMEM; 227*6f0175ffSJay Zhou } 228*6f0175ffSJay Zhou 229*6f0175ffSJay Zhou static int 230*6f0175ffSJay Zhou virtio_crypto_ctrlq_setup(struct rte_cryptodev *dev, uint16_t queue_idx) 231*6f0175ffSJay Zhou { 232*6f0175ffSJay Zhou int ret; 233*6f0175ffSJay Zhou struct virtqueue *vq; 234*6f0175ffSJay Zhou struct virtio_crypto_hw *hw = dev->data->dev_private; 235*6f0175ffSJay Zhou 236*6f0175ffSJay Zhou /* if virtio device has started, do not touch the virtqueues */ 237*6f0175ffSJay Zhou if (dev->data->dev_started) 238*6f0175ffSJay Zhou return 0; 239*6f0175ffSJay Zhou 240*6f0175ffSJay Zhou PMD_INIT_FUNC_TRACE(); 241*6f0175ffSJay Zhou 242*6f0175ffSJay Zhou ret = virtio_crypto_queue_setup(dev, VTCRYPTO_CTRLQ, queue_idx, 243*6f0175ffSJay Zhou 0, SOCKET_ID_ANY, &vq); 244*6f0175ffSJay Zhou if (ret < 0) { 245*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("control vq initialization failed"); 246*6f0175ffSJay Zhou return ret; 247*6f0175ffSJay Zhou } 248*6f0175ffSJay Zhou 249*6f0175ffSJay Zhou hw->cvq = vq; 250*6f0175ffSJay Zhou 251*6f0175ffSJay Zhou return 0; 252*6f0175ffSJay Zhou } 253*6f0175ffSJay Zhou 254*6f0175ffSJay Zhou static void 255*6f0175ffSJay Zhou virtio_crypto_free_queues(struct rte_cryptodev *dev) 256*6f0175ffSJay Zhou { 257*6f0175ffSJay Zhou unsigned int i; 258*6f0175ffSJay Zhou struct virtio_crypto_hw *hw = dev->data->dev_private; 259*6f0175ffSJay Zhou 260*6f0175ffSJay Zhou PMD_INIT_FUNC_TRACE(); 261*6f0175ffSJay Zhou 262*6f0175ffSJay Zhou /* control queue release */ 263*6f0175ffSJay Zhou virtio_crypto_queue_release(hw->cvq); 264*6f0175ffSJay Zhou 265*6f0175ffSJay Zhou /* data queue release */ 266*6f0175ffSJay Zhou for (i = 0; i < hw->max_dataqueues; i++) 267*6f0175ffSJay Zhou virtio_crypto_queue_release(dev->data->queue_pairs[i]); 268*6f0175ffSJay Zhou } 269*6f0175ffSJay Zhou 270*6f0175ffSJay Zhou static int 271*6f0175ffSJay Zhou virtio_crypto_dev_close(struct rte_cryptodev *dev __rte_unused) 272*6f0175ffSJay Zhou { 273*6f0175ffSJay Zhou return 0; 274*6f0175ffSJay Zhou } 275*6f0175ffSJay Zhou 27625500d4bSJay Zhou /* 27725500d4bSJay Zhou * dev_ops for virtio, bare necessities for basic operation 27825500d4bSJay Zhou */ 27925500d4bSJay Zhou static struct rte_cryptodev_ops virtio_crypto_dev_ops = { 28025500d4bSJay Zhou /* Device related operations */ 281*6f0175ffSJay Zhou .dev_configure = virtio_crypto_dev_configure, 282*6f0175ffSJay Zhou .dev_start = virtio_crypto_dev_start, 283*6f0175ffSJay Zhou .dev_stop = virtio_crypto_dev_stop, 284*6f0175ffSJay Zhou .dev_close = virtio_crypto_dev_close, 285*6f0175ffSJay Zhou .dev_infos_get = virtio_crypto_dev_info_get, 28625500d4bSJay Zhou 28725500d4bSJay Zhou .stats_get = NULL, 28825500d4bSJay Zhou .stats_reset = NULL, 28925500d4bSJay Zhou 290*6f0175ffSJay Zhou .queue_pair_setup = virtio_crypto_qp_setup, 291*6f0175ffSJay Zhou .queue_pair_release = virtio_crypto_qp_release, 29225500d4bSJay Zhou .queue_pair_start = NULL, 29325500d4bSJay Zhou .queue_pair_stop = NULL, 29425500d4bSJay Zhou .queue_pair_count = NULL, 29525500d4bSJay Zhou 29625500d4bSJay Zhou /* Crypto related operations */ 29725500d4bSJay Zhou .session_get_size = NULL, 29825500d4bSJay Zhou .session_configure = NULL, 29925500d4bSJay Zhou .session_clear = NULL, 30025500d4bSJay Zhou .qp_attach_session = NULL, 30125500d4bSJay Zhou .qp_detach_session = NULL 30225500d4bSJay Zhou }; 30325500d4bSJay Zhou 30425500d4bSJay Zhou static int 305*6f0175ffSJay Zhou virtio_crypto_qp_setup(struct rte_cryptodev *dev, uint16_t queue_pair_id, 306*6f0175ffSJay Zhou const struct rte_cryptodev_qp_conf *qp_conf, 307*6f0175ffSJay Zhou int socket_id, 308*6f0175ffSJay Zhou struct rte_mempool *session_pool __rte_unused) 309*6f0175ffSJay Zhou { 310*6f0175ffSJay Zhou int ret; 311*6f0175ffSJay Zhou struct virtqueue *vq; 312*6f0175ffSJay Zhou 313*6f0175ffSJay Zhou PMD_INIT_FUNC_TRACE(); 314*6f0175ffSJay Zhou 315*6f0175ffSJay Zhou /* if virtio dev is started, do not touch the virtqueues */ 316*6f0175ffSJay Zhou if (dev->data->dev_started) 317*6f0175ffSJay Zhou return 0; 318*6f0175ffSJay Zhou 319*6f0175ffSJay Zhou ret = virtio_crypto_queue_setup(dev, VTCRYPTO_DATAQ, queue_pair_id, 320*6f0175ffSJay Zhou qp_conf->nb_descriptors, socket_id, &vq); 321*6f0175ffSJay Zhou if (ret < 0) { 322*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR( 323*6f0175ffSJay Zhou "virtio crypto data queue initialization failed\n"); 324*6f0175ffSJay Zhou return ret; 325*6f0175ffSJay Zhou } 326*6f0175ffSJay Zhou 327*6f0175ffSJay Zhou dev->data->queue_pairs[queue_pair_id] = vq; 328*6f0175ffSJay Zhou 329*6f0175ffSJay Zhou return 0; 330*6f0175ffSJay Zhou } 331*6f0175ffSJay Zhou 332*6f0175ffSJay Zhou static int 333*6f0175ffSJay Zhou virtio_crypto_qp_release(struct rte_cryptodev *dev, uint16_t queue_pair_id) 334*6f0175ffSJay Zhou { 335*6f0175ffSJay Zhou struct virtqueue *vq 336*6f0175ffSJay Zhou = (struct virtqueue *)dev->data->queue_pairs[queue_pair_id]; 337*6f0175ffSJay Zhou 338*6f0175ffSJay Zhou PMD_INIT_FUNC_TRACE(); 339*6f0175ffSJay Zhou 340*6f0175ffSJay Zhou if (vq == NULL) { 341*6f0175ffSJay Zhou VIRTIO_CRYPTO_DRV_LOG_DBG("vq already freed"); 342*6f0175ffSJay Zhou return 0; 343*6f0175ffSJay Zhou } 344*6f0175ffSJay Zhou 345*6f0175ffSJay Zhou virtio_crypto_queue_release(vq); 346*6f0175ffSJay Zhou return 0; 347*6f0175ffSJay Zhou } 348*6f0175ffSJay Zhou 349*6f0175ffSJay Zhou static int 35025500d4bSJay Zhou virtio_negotiate_features(struct virtio_crypto_hw *hw, uint64_t req_features) 35125500d4bSJay Zhou { 35225500d4bSJay Zhou uint64_t host_features; 35325500d4bSJay Zhou 35425500d4bSJay Zhou PMD_INIT_FUNC_TRACE(); 35525500d4bSJay Zhou 35625500d4bSJay Zhou /* Prepare guest_features: feature that driver wants to support */ 35725500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("guest_features before negotiate = %" PRIx64, 35825500d4bSJay Zhou req_features); 35925500d4bSJay Zhou 36025500d4bSJay Zhou /* Read device(host) feature bits */ 36125500d4bSJay Zhou host_features = VTPCI_OPS(hw)->get_features(hw); 36225500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("host_features before negotiate = %" PRIx64, 36325500d4bSJay Zhou host_features); 36425500d4bSJay Zhou 36525500d4bSJay Zhou /* 36625500d4bSJay Zhou * Negotiate features: Subset of device feature bits are written back 36725500d4bSJay Zhou * guest feature bits. 36825500d4bSJay Zhou */ 36925500d4bSJay Zhou hw->guest_features = req_features; 37025500d4bSJay Zhou hw->guest_features = vtpci_cryptodev_negotiate_features(hw, 37125500d4bSJay Zhou host_features); 37225500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("features after negotiate = %" PRIx64, 37325500d4bSJay Zhou hw->guest_features); 37425500d4bSJay Zhou 37525500d4bSJay Zhou if (hw->modern) { 37625500d4bSJay Zhou if (!vtpci_with_feature(hw, VIRTIO_F_VERSION_1)) { 37725500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR( 37825500d4bSJay Zhou "VIRTIO_F_VERSION_1 features is not enabled."); 37925500d4bSJay Zhou return -1; 38025500d4bSJay Zhou } 38125500d4bSJay Zhou vtpci_cryptodev_set_status(hw, 38225500d4bSJay Zhou VIRTIO_CONFIG_STATUS_FEATURES_OK); 38325500d4bSJay Zhou if (!(vtpci_cryptodev_get_status(hw) & 38425500d4bSJay Zhou VIRTIO_CONFIG_STATUS_FEATURES_OK)) { 38525500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("failed to set FEATURES_OK " 38625500d4bSJay Zhou "status!"); 38725500d4bSJay Zhou return -1; 38825500d4bSJay Zhou } 38925500d4bSJay Zhou } 39025500d4bSJay Zhou 39125500d4bSJay Zhou hw->req_guest_features = req_features; 39225500d4bSJay Zhou 39325500d4bSJay Zhou return 0; 39425500d4bSJay Zhou } 39525500d4bSJay Zhou 39625500d4bSJay Zhou /* reset device and renegotiate features if needed */ 39725500d4bSJay Zhou static int 39825500d4bSJay Zhou virtio_crypto_init_device(struct rte_cryptodev *cryptodev, 39925500d4bSJay Zhou uint64_t req_features) 40025500d4bSJay Zhou { 40125500d4bSJay Zhou struct virtio_crypto_hw *hw = cryptodev->data->dev_private; 40225500d4bSJay Zhou struct virtio_crypto_config local_config; 40325500d4bSJay Zhou struct virtio_crypto_config *config = &local_config; 40425500d4bSJay Zhou 40525500d4bSJay Zhou PMD_INIT_FUNC_TRACE(); 40625500d4bSJay Zhou 40725500d4bSJay Zhou /* Reset the device although not necessary at startup */ 40825500d4bSJay Zhou vtpci_cryptodev_reset(hw); 40925500d4bSJay Zhou 41025500d4bSJay Zhou /* Tell the host we've noticed this device. */ 41125500d4bSJay Zhou vtpci_cryptodev_set_status(hw, VIRTIO_CONFIG_STATUS_ACK); 41225500d4bSJay Zhou 41325500d4bSJay Zhou /* Tell the host we've known how to drive the device. */ 41425500d4bSJay Zhou vtpci_cryptodev_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER); 41525500d4bSJay Zhou if (virtio_negotiate_features(hw, req_features) < 0) 41625500d4bSJay Zhou return -1; 41725500d4bSJay Zhou 41825500d4bSJay Zhou /* Get status of the device */ 41925500d4bSJay Zhou vtpci_read_cryptodev_config(hw, 42025500d4bSJay Zhou offsetof(struct virtio_crypto_config, status), 42125500d4bSJay Zhou &config->status, sizeof(config->status)); 42225500d4bSJay Zhou if (config->status != VIRTIO_CRYPTO_S_HW_READY) { 42325500d4bSJay Zhou VIRTIO_CRYPTO_DRV_LOG_ERR("accelerator hardware is " 42425500d4bSJay Zhou "not ready"); 42525500d4bSJay Zhou return -1; 42625500d4bSJay Zhou } 42725500d4bSJay Zhou 42825500d4bSJay Zhou /* Get number of data queues */ 42925500d4bSJay Zhou vtpci_read_cryptodev_config(hw, 43025500d4bSJay Zhou offsetof(struct virtio_crypto_config, max_dataqueues), 43125500d4bSJay Zhou &config->max_dataqueues, 43225500d4bSJay Zhou sizeof(config->max_dataqueues)); 43325500d4bSJay Zhou hw->max_dataqueues = config->max_dataqueues; 43425500d4bSJay Zhou 43525500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("hw->max_dataqueues=%d", 43625500d4bSJay Zhou hw->max_dataqueues); 43725500d4bSJay Zhou 43825500d4bSJay Zhou return 0; 43925500d4bSJay Zhou } 44025500d4bSJay Zhou 44125500d4bSJay Zhou /* 44225500d4bSJay Zhou * This function is based on probe() function 44325500d4bSJay Zhou * It returns 0 on success. 44425500d4bSJay Zhou */ 44525500d4bSJay Zhou static int 44625500d4bSJay Zhou crypto_virtio_create(const char *name, struct rte_pci_device *pci_dev, 44725500d4bSJay Zhou struct rte_cryptodev_pmd_init_params *init_params) 44825500d4bSJay Zhou { 44925500d4bSJay Zhou struct rte_cryptodev *cryptodev; 45025500d4bSJay Zhou struct virtio_crypto_hw *hw; 45125500d4bSJay Zhou 45225500d4bSJay Zhou PMD_INIT_FUNC_TRACE(); 45325500d4bSJay Zhou 45425500d4bSJay Zhou cryptodev = rte_cryptodev_pmd_create(name, &pci_dev->device, 45525500d4bSJay Zhou init_params); 45625500d4bSJay Zhou if (cryptodev == NULL) 45725500d4bSJay Zhou return -ENODEV; 45825500d4bSJay Zhou 45925500d4bSJay Zhou cryptodev->driver_id = cryptodev_virtio_driver_id; 46025500d4bSJay Zhou cryptodev->dev_ops = &virtio_crypto_dev_ops; 46125500d4bSJay Zhou 46225500d4bSJay Zhou cryptodev->enqueue_burst = virtio_crypto_pkt_tx_burst; 46325500d4bSJay Zhou cryptodev->dequeue_burst = virtio_crypto_pkt_rx_burst; 46425500d4bSJay Zhou 46525500d4bSJay Zhou cryptodev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO | 46625500d4bSJay Zhou RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING; 46725500d4bSJay Zhou 46825500d4bSJay Zhou hw = cryptodev->data->dev_private; 46925500d4bSJay Zhou hw->dev_id = cryptodev->data->dev_id; 47025500d4bSJay Zhou 47125500d4bSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("dev %d vendorID=0x%x deviceID=0x%x", 47225500d4bSJay Zhou cryptodev->data->dev_id, pci_dev->id.vendor_id, 47325500d4bSJay Zhou pci_dev->id.device_id); 47425500d4bSJay Zhou 47525500d4bSJay Zhou /* pci device init */ 47625500d4bSJay Zhou if (vtpci_cryptodev_init(pci_dev, hw)) 47725500d4bSJay Zhou return -1; 47825500d4bSJay Zhou 47925500d4bSJay Zhou if (virtio_crypto_init_device(cryptodev, 48025500d4bSJay Zhou VIRTIO_CRYPTO_PMD_GUEST_FEATURES) < 0) 48125500d4bSJay Zhou return -1; 48225500d4bSJay Zhou 48325500d4bSJay Zhou return 0; 48425500d4bSJay Zhou } 48525500d4bSJay Zhou 4868769079aSJay Zhou static int 487*6f0175ffSJay Zhou virtio_crypto_dev_uninit(struct rte_cryptodev *cryptodev) 488*6f0175ffSJay Zhou { 489*6f0175ffSJay Zhou struct virtio_crypto_hw *hw = cryptodev->data->dev_private; 490*6f0175ffSJay Zhou 491*6f0175ffSJay Zhou PMD_INIT_FUNC_TRACE(); 492*6f0175ffSJay Zhou 493*6f0175ffSJay Zhou if (rte_eal_process_type() == RTE_PROC_SECONDARY) 494*6f0175ffSJay Zhou return -EPERM; 495*6f0175ffSJay Zhou 496*6f0175ffSJay Zhou if (cryptodev->data->dev_started) { 497*6f0175ffSJay Zhou virtio_crypto_dev_stop(cryptodev); 498*6f0175ffSJay Zhou virtio_crypto_dev_close(cryptodev); 499*6f0175ffSJay Zhou } 500*6f0175ffSJay Zhou 501*6f0175ffSJay Zhou cryptodev->dev_ops = NULL; 502*6f0175ffSJay Zhou cryptodev->enqueue_burst = NULL; 503*6f0175ffSJay Zhou cryptodev->dequeue_burst = NULL; 504*6f0175ffSJay Zhou 505*6f0175ffSJay Zhou /* release control queue */ 506*6f0175ffSJay Zhou virtio_crypto_queue_release(hw->cvq); 507*6f0175ffSJay Zhou 508*6f0175ffSJay Zhou rte_free(cryptodev->data); 509*6f0175ffSJay Zhou cryptodev->data = NULL; 510*6f0175ffSJay Zhou 511*6f0175ffSJay Zhou VIRTIO_CRYPTO_DRV_LOG_INFO("dev_uninit completed"); 512*6f0175ffSJay Zhou 513*6f0175ffSJay Zhou return 0; 514*6f0175ffSJay Zhou } 515*6f0175ffSJay Zhou 516*6f0175ffSJay Zhou static int 517*6f0175ffSJay Zhou virtio_crypto_dev_configure(struct rte_cryptodev *cryptodev, 518*6f0175ffSJay Zhou struct rte_cryptodev_config *config __rte_unused) 519*6f0175ffSJay Zhou { 520*6f0175ffSJay Zhou struct virtio_crypto_hw *hw = cryptodev->data->dev_private; 521*6f0175ffSJay Zhou 522*6f0175ffSJay Zhou PMD_INIT_FUNC_TRACE(); 523*6f0175ffSJay Zhou 524*6f0175ffSJay Zhou if (virtio_crypto_init_device(cryptodev, 525*6f0175ffSJay Zhou VIRTIO_CRYPTO_PMD_GUEST_FEATURES) < 0) 526*6f0175ffSJay Zhou return -1; 527*6f0175ffSJay Zhou 528*6f0175ffSJay Zhou /* setup control queue 529*6f0175ffSJay Zhou * [0, 1, ... ,(config->max_dataqueues - 1)] are data queues 530*6f0175ffSJay Zhou * config->max_dataqueues is the control queue 531*6f0175ffSJay Zhou */ 532*6f0175ffSJay Zhou if (virtio_crypto_ctrlq_setup(cryptodev, hw->max_dataqueues) < 0) { 533*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_ERR("control queue setup error"); 534*6f0175ffSJay Zhou return -1; 535*6f0175ffSJay Zhou } 536*6f0175ffSJay Zhou virtio_crypto_ctrlq_start(cryptodev); 537*6f0175ffSJay Zhou 538*6f0175ffSJay Zhou return 0; 539*6f0175ffSJay Zhou } 540*6f0175ffSJay Zhou 541*6f0175ffSJay Zhou static void 542*6f0175ffSJay Zhou virtio_crypto_dev_stop(struct rte_cryptodev *dev) 543*6f0175ffSJay Zhou { 544*6f0175ffSJay Zhou struct virtio_crypto_hw *hw = dev->data->dev_private; 545*6f0175ffSJay Zhou 546*6f0175ffSJay Zhou PMD_INIT_FUNC_TRACE(); 547*6f0175ffSJay Zhou VIRTIO_CRYPTO_DRV_LOG_DBG("virtio_dev_stop"); 548*6f0175ffSJay Zhou 549*6f0175ffSJay Zhou vtpci_cryptodev_reset(hw); 550*6f0175ffSJay Zhou 551*6f0175ffSJay Zhou virtio_crypto_dev_free_mbufs(dev); 552*6f0175ffSJay Zhou virtio_crypto_free_queues(dev); 553*6f0175ffSJay Zhou 554*6f0175ffSJay Zhou dev->data->dev_started = 0; 555*6f0175ffSJay Zhou } 556*6f0175ffSJay Zhou 557*6f0175ffSJay Zhou static int 558*6f0175ffSJay Zhou virtio_crypto_dev_start(struct rte_cryptodev *dev) 559*6f0175ffSJay Zhou { 560*6f0175ffSJay Zhou struct virtio_crypto_hw *hw = dev->data->dev_private; 561*6f0175ffSJay Zhou 562*6f0175ffSJay Zhou if (dev->data->dev_started) 563*6f0175ffSJay Zhou return 0; 564*6f0175ffSJay Zhou 565*6f0175ffSJay Zhou /* Do final configuration before queue engine starts */ 566*6f0175ffSJay Zhou virtio_crypto_dataq_start(dev); 567*6f0175ffSJay Zhou vtpci_cryptodev_reinit_complete(hw); 568*6f0175ffSJay Zhou 569*6f0175ffSJay Zhou dev->data->dev_started = 1; 570*6f0175ffSJay Zhou 571*6f0175ffSJay Zhou return 0; 572*6f0175ffSJay Zhou } 573*6f0175ffSJay Zhou 574*6f0175ffSJay Zhou static void 575*6f0175ffSJay Zhou virtio_crypto_dev_free_mbufs(struct rte_cryptodev *dev) 576*6f0175ffSJay Zhou { 577*6f0175ffSJay Zhou uint32_t i; 578*6f0175ffSJay Zhou struct virtio_crypto_hw *hw = dev->data->dev_private; 579*6f0175ffSJay Zhou 580*6f0175ffSJay Zhou for (i = 0; i < hw->max_dataqueues; i++) { 581*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("Before freeing dataq[%d] used " 582*6f0175ffSJay Zhou "and unused buf", i); 583*6f0175ffSJay Zhou VIRTQUEUE_DUMP((struct virtqueue *) 584*6f0175ffSJay Zhou dev->data->queue_pairs[i]); 585*6f0175ffSJay Zhou 586*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("queue_pairs[%d]=%p", 587*6f0175ffSJay Zhou i, dev->data->queue_pairs[i]); 588*6f0175ffSJay Zhou 589*6f0175ffSJay Zhou virtqueue_detatch_unused(dev->data->queue_pairs[i]); 590*6f0175ffSJay Zhou 591*6f0175ffSJay Zhou VIRTIO_CRYPTO_INIT_LOG_DBG("After freeing dataq[%d] used and " 592*6f0175ffSJay Zhou "unused buf", i); 593*6f0175ffSJay Zhou VIRTQUEUE_DUMP( 594*6f0175ffSJay Zhou (struct virtqueue *)dev->data->queue_pairs[i]); 595*6f0175ffSJay Zhou } 596*6f0175ffSJay Zhou } 597*6f0175ffSJay Zhou 598*6f0175ffSJay Zhou static void 599*6f0175ffSJay Zhou virtio_crypto_dev_info_get(struct rte_cryptodev *dev, 600*6f0175ffSJay Zhou struct rte_cryptodev_info *info) 601*6f0175ffSJay Zhou { 602*6f0175ffSJay Zhou struct virtio_crypto_hw *hw = dev->data->dev_private; 603*6f0175ffSJay Zhou 604*6f0175ffSJay Zhou PMD_INIT_FUNC_TRACE(); 605*6f0175ffSJay Zhou 606*6f0175ffSJay Zhou if (info != NULL) { 607*6f0175ffSJay Zhou info->driver_id = cryptodev_virtio_driver_id; 608*6f0175ffSJay Zhou info->pci_dev = RTE_DEV_TO_PCI(dev->device); 609*6f0175ffSJay Zhou info->feature_flags = dev->feature_flags; 610*6f0175ffSJay Zhou info->max_nb_queue_pairs = hw->max_dataqueues; 611*6f0175ffSJay Zhou info->sym.max_nb_sessions = 612*6f0175ffSJay Zhou RTE_VIRTIO_CRYPTO_PMD_MAX_NB_SESSIONS; 613*6f0175ffSJay Zhou } 614*6f0175ffSJay Zhou } 615*6f0175ffSJay Zhou 616*6f0175ffSJay Zhou static int 6178769079aSJay Zhou crypto_virtio_pci_probe( 6188769079aSJay Zhou struct rte_pci_driver *pci_drv __rte_unused, 61925500d4bSJay Zhou struct rte_pci_device *pci_dev) 6208769079aSJay Zhou { 62125500d4bSJay Zhou struct rte_cryptodev_pmd_init_params init_params = { 62225500d4bSJay Zhou .name = "", 62325500d4bSJay Zhou .socket_id = rte_socket_id(), 62425500d4bSJay Zhou .private_data_size = sizeof(struct virtio_crypto_hw), 62525500d4bSJay Zhou .max_nb_sessions = RTE_VIRTIO_CRYPTO_PMD_MAX_NB_SESSIONS 62625500d4bSJay Zhou }; 62725500d4bSJay Zhou char name[RTE_CRYPTODEV_NAME_MAX_LEN]; 62825500d4bSJay Zhou 62925500d4bSJay Zhou VIRTIO_CRYPTO_DRV_LOG_DBG("Found Crypto device at %02x:%02x.%x", 63025500d4bSJay Zhou pci_dev->addr.bus, 63125500d4bSJay Zhou pci_dev->addr.devid, 63225500d4bSJay Zhou pci_dev->addr.function); 63325500d4bSJay Zhou 63425500d4bSJay Zhou rte_pci_device_name(&pci_dev->addr, name, sizeof(name)); 63525500d4bSJay Zhou 63625500d4bSJay Zhou return crypto_virtio_create(name, pci_dev, &init_params); 6378769079aSJay Zhou } 6388769079aSJay Zhou 6398769079aSJay Zhou static int 6408769079aSJay Zhou crypto_virtio_pci_remove( 6418769079aSJay Zhou struct rte_pci_device *pci_dev __rte_unused) 6428769079aSJay Zhou { 64325500d4bSJay Zhou struct rte_cryptodev *cryptodev; 64425500d4bSJay Zhou char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN]; 64525500d4bSJay Zhou 64625500d4bSJay Zhou if (pci_dev == NULL) 64725500d4bSJay Zhou return -EINVAL; 64825500d4bSJay Zhou 64925500d4bSJay Zhou rte_pci_device_name(&pci_dev->addr, cryptodev_name, 65025500d4bSJay Zhou sizeof(cryptodev_name)); 65125500d4bSJay Zhou 65225500d4bSJay Zhou cryptodev = rte_cryptodev_pmd_get_named_dev(cryptodev_name); 65325500d4bSJay Zhou if (cryptodev == NULL) 65425500d4bSJay Zhou return -ENODEV; 65525500d4bSJay Zhou 656*6f0175ffSJay Zhou return virtio_crypto_dev_uninit(cryptodev); 6578769079aSJay Zhou } 6588769079aSJay Zhou 6598769079aSJay Zhou static struct rte_pci_driver rte_virtio_crypto_driver = { 66025500d4bSJay Zhou .id_table = pci_id_virtio_crypto_map, 66125500d4bSJay Zhou .drv_flags = 0, 6628769079aSJay Zhou .probe = crypto_virtio_pci_probe, 6638769079aSJay Zhou .remove = crypto_virtio_pci_remove 6648769079aSJay Zhou }; 6658769079aSJay Zhou 6668769079aSJay Zhou static struct cryptodev_driver virtio_crypto_drv; 6678769079aSJay Zhou 6688769079aSJay Zhou RTE_PMD_REGISTER_PCI(CRYPTODEV_NAME_VIRTIO_PMD, rte_virtio_crypto_driver); 6698769079aSJay Zhou RTE_PMD_REGISTER_CRYPTO_DRIVER(virtio_crypto_drv, 6708769079aSJay Zhou rte_virtio_crypto_driver.driver, 6718769079aSJay Zhou cryptodev_virtio_driver_id); 67225500d4bSJay Zhou 67325500d4bSJay Zhou RTE_INIT(virtio_crypto_init_log); 67425500d4bSJay Zhou static void 67525500d4bSJay Zhou virtio_crypto_init_log(void) 67625500d4bSJay Zhou { 67725500d4bSJay Zhou virtio_crypto_logtype_init = rte_log_register("pmd.crypto.virtio.init"); 67825500d4bSJay Zhou if (virtio_crypto_logtype_init >= 0) 67925500d4bSJay Zhou rte_log_set_level(virtio_crypto_logtype_init, RTE_LOG_NOTICE); 68025500d4bSJay Zhou 68125500d4bSJay Zhou virtio_crypto_logtype_session = 68225500d4bSJay Zhou rte_log_register("pmd.crypto.virtio.session"); 68325500d4bSJay Zhou if (virtio_crypto_logtype_session >= 0) 68425500d4bSJay Zhou rte_log_set_level(virtio_crypto_logtype_session, 68525500d4bSJay Zhou RTE_LOG_NOTICE); 68625500d4bSJay Zhou 68725500d4bSJay Zhou virtio_crypto_logtype_rx = rte_log_register("pmd.crypto.virtio.rx"); 68825500d4bSJay Zhou if (virtio_crypto_logtype_rx >= 0) 68925500d4bSJay Zhou rte_log_set_level(virtio_crypto_logtype_rx, RTE_LOG_NOTICE); 69025500d4bSJay Zhou 69125500d4bSJay Zhou virtio_crypto_logtype_tx = rte_log_register("pmd.crypto.virtio.tx"); 69225500d4bSJay Zhou if (virtio_crypto_logtype_tx >= 0) 69325500d4bSJay Zhou rte_log_set_level(virtio_crypto_logtype_tx, RTE_LOG_NOTICE); 69425500d4bSJay Zhou 69525500d4bSJay Zhou virtio_crypto_logtype_driver = 69625500d4bSJay Zhou rte_log_register("pmd.crypto.virtio.driver"); 69725500d4bSJay Zhou if (virtio_crypto_logtype_driver >= 0) 69825500d4bSJay Zhou rte_log_set_level(virtio_crypto_logtype_driver, RTE_LOG_NOTICE); 69925500d4bSJay Zhou } 700