10054d84fSRavi Kumar /* SPDX-License-Identifier: BSD-3-Clause 20054d84fSRavi Kumar * Copyright(c) 2018 Advanced Micro Devices, Inc. All rights reserved. 30054d84fSRavi Kumar */ 40054d84fSRavi Kumar 56723c0fcSBruce Richardson #include <rte_string_fns.h> 61f37cb2bSDavid Marchand #include <bus_pci_driver.h> 74851ef2bSDavid Marchand #include <bus_vdev_driver.h> 8ef4b04f8SRavi Kumar #include <rte_common.h> 90054d84fSRavi Kumar #include <rte_cryptodev.h> 10af668035SAkhil Goyal #include <cryptodev_pmd.h> 11ef4b04f8SRavi Kumar #include <rte_pci.h> 121acb7f54SDavid Marchand #include <dev_driver.h> 13ef4b04f8SRavi Kumar #include <rte_malloc.h> 140054d84fSRavi Kumar 1570f0f8a8SRavi Kumar #include "ccp_crypto.h" 16ef4b04f8SRavi Kumar #include "ccp_dev.h" 17ef4b04f8SRavi Kumar #include "ccp_pmd_private.h" 18ef4b04f8SRavi Kumar 19ef4b04f8SRavi Kumar /** 20ef4b04f8SRavi Kumar * Global static parameter used to find if CCP device is already initialized. 21ef4b04f8SRavi Kumar */ 22ef4b04f8SRavi Kumar static unsigned int ccp_pmd_init_done; 230054d84fSRavi Kumar uint8_t ccp_cryptodev_driver_id; 2472775857SAmaranath Somalapuram uint8_t cryptodev_cnt; 250054d84fSRavi Kumar 26e0d88a39SRavi Kumar struct ccp_pmd_init_params { 27e0d88a39SRavi Kumar struct rte_cryptodev_pmd_init_params def_p; 28e0d88a39SRavi Kumar bool auth_opt; 29e0d88a39SRavi Kumar }; 30e0d88a39SRavi Kumar 31e0d88a39SRavi Kumar #define CCP_CRYPTODEV_PARAM_NAME ("name") 32e0d88a39SRavi Kumar #define CCP_CRYPTODEV_PARAM_SOCKET_ID ("socket_id") 33e0d88a39SRavi Kumar #define CCP_CRYPTODEV_PARAM_MAX_NB_QP ("max_nb_queue_pairs") 34e0d88a39SRavi Kumar #define CCP_CRYPTODEV_PARAM_AUTH_OPT ("ccp_auth_opt") 35e0d88a39SRavi Kumar 36e0d88a39SRavi Kumar const char *ccp_pmd_valid_params[] = { 37e0d88a39SRavi Kumar CCP_CRYPTODEV_PARAM_NAME, 38e0d88a39SRavi Kumar CCP_CRYPTODEV_PARAM_SOCKET_ID, 39e0d88a39SRavi Kumar CCP_CRYPTODEV_PARAM_MAX_NB_QP, 40e0d88a39SRavi Kumar CCP_CRYPTODEV_PARAM_AUTH_OPT, 41e0d88a39SRavi Kumar }; 42e0d88a39SRavi Kumar 43e0d88a39SRavi Kumar /** ccp pmd auth option */ 44e0d88a39SRavi Kumar enum ccp_pmd_auth_opt { 45e0d88a39SRavi Kumar CCP_PMD_AUTH_OPT_CCP = 0, 46e0d88a39SRavi Kumar CCP_PMD_AUTH_OPT_CPU, 47e0d88a39SRavi Kumar }; 48e0d88a39SRavi Kumar 4970f0f8a8SRavi Kumar static struct ccp_session * 50ffdace42SRavi Kumar get_ccp_session(struct ccp_qp *qp, struct rte_crypto_op *op) 51ef4b04f8SRavi Kumar { 5270f0f8a8SRavi Kumar struct ccp_session *sess = NULL; 53ef4b04f8SRavi Kumar 5470f0f8a8SRavi Kumar if (op->sess_type == RTE_CRYPTO_OP_WITH_SESSION) { 5570f0f8a8SRavi Kumar if (unlikely(op->sym->session == NULL)) 5670f0f8a8SRavi Kumar return NULL; 5770f0f8a8SRavi Kumar 582a440d6aSAkhil Goyal sess = CRYPTODEV_GET_SYM_SESS_PRIV(op->sym->session); 59ffdace42SRavi Kumar } else if (op->sess_type == RTE_CRYPTO_OP_SESSIONLESS) { 60bdce2564SAkhil Goyal struct rte_cryptodev_sym_session *_sess; 61e0d88a39SRavi Kumar struct ccp_private *internals; 62ffdace42SRavi Kumar 63bdce2564SAkhil Goyal if (rte_mempool_get(qp->sess_mp, (void **)&_sess)) 64ffdace42SRavi Kumar return NULL; 65ffdace42SRavi Kumar 66bdce2564SAkhil Goyal sess = (void *)_sess->driver_priv_data; 67ffdace42SRavi Kumar 68e0d88a39SRavi Kumar internals = (struct ccp_private *)qp->dev->data->dev_private; 69e0d88a39SRavi Kumar if (unlikely(ccp_set_session_parameters(sess, op->sym->xform, 70e0d88a39SRavi Kumar internals) != 0)) { 71ffdace42SRavi Kumar rte_mempool_put(qp->sess_mp, _sess); 72ffdace42SRavi Kumar sess = NULL; 73ffdace42SRavi Kumar } 74bdce2564SAkhil Goyal op->sym->session = _sess; 7570f0f8a8SRavi Kumar } 7670f0f8a8SRavi Kumar 7770f0f8a8SRavi Kumar return sess; 7870f0f8a8SRavi Kumar } 7970f0f8a8SRavi Kumar 8070f0f8a8SRavi Kumar static uint16_t 8170f0f8a8SRavi Kumar ccp_pmd_enqueue_burst(void *queue_pair, struct rte_crypto_op **ops, 8270f0f8a8SRavi Kumar uint16_t nb_ops) 8370f0f8a8SRavi Kumar { 8470f0f8a8SRavi Kumar struct ccp_session *sess = NULL; 8570f0f8a8SRavi Kumar struct ccp_qp *qp = queue_pair; 8670f0f8a8SRavi Kumar struct ccp_queue *cmd_q; 8770f0f8a8SRavi Kumar struct rte_cryptodev *dev = qp->dev; 8870f0f8a8SRavi Kumar uint16_t i, enq_cnt = 0, slots_req = 0; 8972775857SAmaranath Somalapuram uint16_t tmp_ops = nb_ops, b_idx, cur_ops = 0; 9070f0f8a8SRavi Kumar 9170f0f8a8SRavi Kumar if (nb_ops == 0) 9270f0f8a8SRavi Kumar return 0; 9370f0f8a8SRavi Kumar 9470f0f8a8SRavi Kumar if (unlikely(rte_ring_full(qp->processed_pkts) != 0)) 9570f0f8a8SRavi Kumar return 0; 9672775857SAmaranath Somalapuram if (tmp_ops >= cryptodev_cnt) 9772775857SAmaranath Somalapuram cur_ops = nb_ops / cryptodev_cnt + (nb_ops)%cryptodev_cnt; 9872775857SAmaranath Somalapuram else 9972775857SAmaranath Somalapuram cur_ops = tmp_ops; 10072775857SAmaranath Somalapuram while (tmp_ops) { 10172775857SAmaranath Somalapuram b_idx = nb_ops - tmp_ops; 10272775857SAmaranath Somalapuram slots_req = 0; 10372775857SAmaranath Somalapuram if (cur_ops <= tmp_ops) { 10472775857SAmaranath Somalapuram tmp_ops -= cur_ops; 10572775857SAmaranath Somalapuram } else { 10672775857SAmaranath Somalapuram cur_ops = tmp_ops; 10772775857SAmaranath Somalapuram tmp_ops = 0; 10872775857SAmaranath Somalapuram } 10972775857SAmaranath Somalapuram for (i = 0; i < cur_ops; i++) { 11072775857SAmaranath Somalapuram sess = get_ccp_session(qp, ops[i + b_idx]); 11170f0f8a8SRavi Kumar if (unlikely(sess == NULL) && (i == 0)) { 11270f0f8a8SRavi Kumar qp->qp_stats.enqueue_err_count++; 11370f0f8a8SRavi Kumar return 0; 11470f0f8a8SRavi Kumar } else if (sess == NULL) { 11572775857SAmaranath Somalapuram cur_ops = i; 11670f0f8a8SRavi Kumar break; 11770f0f8a8SRavi Kumar } 11870f0f8a8SRavi Kumar slots_req += ccp_compute_slot_count(sess); 11970f0f8a8SRavi Kumar } 12070f0f8a8SRavi Kumar 12170f0f8a8SRavi Kumar cmd_q = ccp_allot_queue(dev, slots_req); 12270f0f8a8SRavi Kumar if (unlikely(cmd_q == NULL)) 12370f0f8a8SRavi Kumar return 0; 12472775857SAmaranath Somalapuram enq_cnt += process_ops_to_enqueue(qp, ops, cmd_q, cur_ops, 12572775857SAmaranath Somalapuram nb_ops, slots_req, b_idx); 12672775857SAmaranath Somalapuram i++; 12772775857SAmaranath Somalapuram } 12870f0f8a8SRavi Kumar 12970f0f8a8SRavi Kumar qp->qp_stats.enqueued_count += enq_cnt; 130ef4b04f8SRavi Kumar return enq_cnt; 131ef4b04f8SRavi Kumar } 132ef4b04f8SRavi Kumar 133ef4b04f8SRavi Kumar static uint16_t 13470f0f8a8SRavi Kumar ccp_pmd_dequeue_burst(void *queue_pair, struct rte_crypto_op **ops, 13570f0f8a8SRavi Kumar uint16_t nb_ops) 136ef4b04f8SRavi Kumar { 13770f0f8a8SRavi Kumar struct ccp_qp *qp = queue_pair; 13872775857SAmaranath Somalapuram uint16_t nb_dequeued = 0, i, total_nb_ops; 139ef4b04f8SRavi Kumar 14072775857SAmaranath Somalapuram nb_dequeued = process_ops_to_dequeue(qp, ops, nb_ops, &total_nb_ops); 14172775857SAmaranath Somalapuram 14272775857SAmaranath Somalapuram if (total_nb_ops) { 14372775857SAmaranath Somalapuram while (nb_dequeued != total_nb_ops) { 14472775857SAmaranath Somalapuram nb_dequeued = process_ops_to_dequeue(qp, 14572775857SAmaranath Somalapuram ops, nb_ops, &total_nb_ops); 14672775857SAmaranath Somalapuram } 14772775857SAmaranath Somalapuram } 14870f0f8a8SRavi Kumar 149ffdace42SRavi Kumar /* Free session if a session-less crypto op */ 150ffdace42SRavi Kumar for (i = 0; i < nb_dequeued; i++) 151ffdace42SRavi Kumar if (unlikely(ops[i]->sess_type == 152ffdace42SRavi Kumar RTE_CRYPTO_OP_SESSIONLESS)) { 153bdce2564SAkhil Goyal struct ccp_session *sess = 1542a440d6aSAkhil Goyal CRYPTODEV_GET_SYM_SESS_PRIV(ops[i]->sym->session); 155725d2a7fSFan Zhang 156bdce2564SAkhil Goyal memset(sess, 0, sizeof(*sess)); 157ffdace42SRavi Kumar rte_mempool_put(qp->sess_mp, 158ffdace42SRavi Kumar ops[i]->sym->session); 159ffdace42SRavi Kumar ops[i]->sym->session = NULL; 160ffdace42SRavi Kumar } 16170f0f8a8SRavi Kumar qp->qp_stats.dequeued_count += nb_dequeued; 16270f0f8a8SRavi Kumar 163ef4b04f8SRavi Kumar return nb_dequeued; 164ef4b04f8SRavi Kumar } 165ef4b04f8SRavi Kumar 166ef4b04f8SRavi Kumar /* 167ef4b04f8SRavi Kumar * The set of PCI devices this driver supports 168ef4b04f8SRavi Kumar */ 169ef4b04f8SRavi Kumar static struct rte_pci_id ccp_pci_id[] = { 170e849b88fSDavid Marchand { RTE_PCI_DEVICE(AMD_PCI_VENDOR_ID, AMD_PCI_CCP_5A), }, 171e849b88fSDavid Marchand { RTE_PCI_DEVICE(AMD_PCI_VENDOR_ID, AMD_PCI_CCP_5B), }, 172e849b88fSDavid Marchand { RTE_PCI_DEVICE(AMD_PCI_VENDOR_ID, AMD_PCI_CCP_RV), }, 173ef4b04f8SRavi Kumar {.device_id = 0}, 174ef4b04f8SRavi Kumar }; 175ef4b04f8SRavi Kumar 1760054d84fSRavi Kumar /** Remove ccp pmd */ 1770054d84fSRavi Kumar static int 178889317b7SAmaranath Somalapuram cryptodev_ccp_remove(struct rte_pci_device *pci_dev) 1790054d84fSRavi Kumar { 180889317b7SAmaranath Somalapuram char name[RTE_CRYPTODEV_NAME_MAX_LEN]; 181889317b7SAmaranath Somalapuram struct rte_cryptodev *dev; 182889317b7SAmaranath Somalapuram 183889317b7SAmaranath Somalapuram if (pci_dev == NULL) 184889317b7SAmaranath Somalapuram return -EINVAL; 185889317b7SAmaranath Somalapuram 186889317b7SAmaranath Somalapuram rte_pci_device_name(&pci_dev->addr, name, sizeof(name)); 187889317b7SAmaranath Somalapuram 188889317b7SAmaranath Somalapuram if (name[0] == '\0') 189889317b7SAmaranath Somalapuram return -EINVAL; 190889317b7SAmaranath Somalapuram 191889317b7SAmaranath Somalapuram dev = rte_cryptodev_pmd_get_named_dev(name); 192889317b7SAmaranath Somalapuram if (dev == NULL) 193889317b7SAmaranath Somalapuram return -ENODEV; 194ef4b04f8SRavi Kumar 195ef4b04f8SRavi Kumar ccp_pmd_init_done = 0; 196ef4b04f8SRavi Kumar 197a247fcd9SStephen Hemminger CCP_LOG_INFO("Closing ccp device %s on numa socket %u", name, rte_socket_id()); 198ef4b04f8SRavi Kumar 199889317b7SAmaranath Somalapuram return rte_cryptodev_pmd_destroy(dev); 2000054d84fSRavi Kumar } 2010054d84fSRavi Kumar 202ef4b04f8SRavi Kumar /** Create crypto device */ 203ef4b04f8SRavi Kumar static int 204ef4b04f8SRavi Kumar cryptodev_ccp_create(const char *name, 205889317b7SAmaranath Somalapuram struct rte_pci_device *pci_dev, 206889317b7SAmaranath Somalapuram struct ccp_pmd_init_params *init_params, 207889317b7SAmaranath Somalapuram struct rte_pci_driver *pci_drv) 208ef4b04f8SRavi Kumar { 209ef4b04f8SRavi Kumar struct rte_cryptodev *dev; 210ef4b04f8SRavi Kumar struct ccp_private *internals; 211ef4b04f8SRavi Kumar 212e0d88a39SRavi Kumar if (init_params->def_p.name[0] == '\0') 2136723c0fcSBruce Richardson strlcpy(init_params->def_p.name, name, 2146723c0fcSBruce Richardson sizeof(init_params->def_p.name)); 215ef4b04f8SRavi Kumar 216e0d88a39SRavi Kumar dev = rte_cryptodev_pmd_create(init_params->def_p.name, 217889317b7SAmaranath Somalapuram &pci_dev->device, 218e0d88a39SRavi Kumar &init_params->def_p); 219ef4b04f8SRavi Kumar if (dev == NULL) { 220ef4b04f8SRavi Kumar CCP_LOG_ERR("failed to create cryptodev vdev"); 221ef4b04f8SRavi Kumar goto init_error; 222ef4b04f8SRavi Kumar } 223ef4b04f8SRavi Kumar 224e849b88fSDavid Marchand if (ccp_probe_device(pci_dev) != 0) { 225ef4b04f8SRavi Kumar CCP_LOG_ERR("failed to detect CCP crypto device"); 226ef4b04f8SRavi Kumar goto init_error; 227ef4b04f8SRavi Kumar } 228e849b88fSDavid Marchand cryptodev_cnt++; 229ef4b04f8SRavi Kumar 230*f665790aSDavid Marchand CCP_LOG_DBG("CCP : Crypto device count = %d", cryptodev_cnt); 231889317b7SAmaranath Somalapuram dev->device = &pci_dev->device; 232889317b7SAmaranath Somalapuram dev->device->driver = &pci_drv->driver; 233ef4b04f8SRavi Kumar dev->driver_id = ccp_cryptodev_driver_id; 234ef4b04f8SRavi Kumar 235ef4b04f8SRavi Kumar /* register rx/tx burst functions for data path */ 236ef4b04f8SRavi Kumar dev->dev_ops = ccp_pmd_ops; 237ef4b04f8SRavi Kumar dev->enqueue_burst = ccp_pmd_enqueue_burst; 238ef4b04f8SRavi Kumar dev->dequeue_burst = ccp_pmd_dequeue_burst; 239ef4b04f8SRavi Kumar 240ef4b04f8SRavi Kumar dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO | 241ef4b04f8SRavi Kumar RTE_CRYPTODEV_FF_HW_ACCELERATED | 242b3aaf24dSPablo de Lara RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING | 243b3aaf24dSPablo de Lara RTE_CRYPTODEV_FF_SYM_SESSIONLESS; 244ef4b04f8SRavi Kumar 245ef4b04f8SRavi Kumar internals = dev->data->dev_private; 246ef4b04f8SRavi Kumar 247e0d88a39SRavi Kumar internals->max_nb_qpairs = init_params->def_p.max_nb_queue_pairs; 248e0d88a39SRavi Kumar internals->auth_opt = init_params->auth_opt; 249ef4b04f8SRavi Kumar internals->crypto_num_dev = cryptodev_cnt; 250ef4b04f8SRavi Kumar 251d54c72ecSAkhil Goyal rte_cryptodev_pmd_probing_finish(dev); 252d54c72ecSAkhil Goyal 253ef4b04f8SRavi Kumar return 0; 254ef4b04f8SRavi Kumar 255ef4b04f8SRavi Kumar init_error: 256ef4b04f8SRavi Kumar CCP_LOG_ERR("driver %s: %s() failed", 257e0d88a39SRavi Kumar init_params->def_p.name, __func__); 258889317b7SAmaranath Somalapuram cryptodev_ccp_remove(pci_dev); 259ef4b04f8SRavi Kumar 260ef4b04f8SRavi Kumar return -EFAULT; 261ef4b04f8SRavi Kumar } 262ef4b04f8SRavi Kumar 2630054d84fSRavi Kumar /** Probe ccp pmd */ 2640054d84fSRavi Kumar static int 265889317b7SAmaranath Somalapuram cryptodev_ccp_probe(struct rte_pci_driver *pci_drv __rte_unused, 266889317b7SAmaranath Somalapuram struct rte_pci_device *pci_dev) 2670054d84fSRavi Kumar { 268ef4b04f8SRavi Kumar int rc = 0; 269889317b7SAmaranath Somalapuram char name[RTE_CRYPTODEV_NAME_MAX_LEN]; 270e0d88a39SRavi Kumar struct ccp_pmd_init_params init_params = { 271e0d88a39SRavi Kumar .def_p = { 272ef4b04f8SRavi Kumar "", 273ef4b04f8SRavi Kumar sizeof(struct ccp_private), 274ef4b04f8SRavi Kumar rte_socket_id(), 275e1fc5b76SPablo de Lara CCP_PMD_MAX_QUEUE_PAIRS 276e0d88a39SRavi Kumar }, 277e0d88a39SRavi Kumar .auth_opt = CCP_PMD_AUTH_OPT_CCP, 278ef4b04f8SRavi Kumar }; 279ef4b04f8SRavi Kumar 280ef4b04f8SRavi Kumar if (ccp_pmd_init_done) { 281a247fcd9SStephen Hemminger CCP_LOG_INFO("CCP PMD already initialized"); 282ef4b04f8SRavi Kumar return -EFAULT; 283ef4b04f8SRavi Kumar } 284889317b7SAmaranath Somalapuram rte_pci_device_name(&pci_dev->addr, name, sizeof(name)); 285889317b7SAmaranath Somalapuram if (name[0] == '\0') 286ef4b04f8SRavi Kumar return -EINVAL; 287ef4b04f8SRavi Kumar 288e0d88a39SRavi Kumar init_params.def_p.max_nb_queue_pairs = CCP_PMD_MAX_QUEUE_PAIRS; 289ef4b04f8SRavi Kumar 290a247fcd9SStephen Hemminger CCP_LOG_INFO("Initialising %s on NUMA node %d", name, 291e0d88a39SRavi Kumar init_params.def_p.socket_id); 292a247fcd9SStephen Hemminger CCP_LOG_INFO("Max number of queue pairs = %d", 293e0d88a39SRavi Kumar init_params.def_p.max_nb_queue_pairs); 294a247fcd9SStephen Hemminger CCP_LOG_INFO("Authentication offload to %s", 295e0d88a39SRavi Kumar ((init_params.auth_opt == 0) ? "CCP" : "CPU")); 296ef4b04f8SRavi Kumar 297889317b7SAmaranath Somalapuram rte_pci_device_name(&pci_dev->addr, name, sizeof(name)); 298889317b7SAmaranath Somalapuram 299889317b7SAmaranath Somalapuram rc = cryptodev_ccp_create(name, pci_dev, &init_params, pci_drv); 300ef4b04f8SRavi Kumar if (rc) 301ef4b04f8SRavi Kumar return rc; 302ef4b04f8SRavi Kumar ccp_pmd_init_done = 1; 3030054d84fSRavi Kumar return 0; 3040054d84fSRavi Kumar } 3050054d84fSRavi Kumar 306889317b7SAmaranath Somalapuram static struct rte_pci_driver cryptodev_ccp_pmd_drv = { 307889317b7SAmaranath Somalapuram .id_table = ccp_pci_id, 308889317b7SAmaranath Somalapuram .drv_flags = RTE_PCI_DRV_NEED_MAPPING, 3090054d84fSRavi Kumar .probe = cryptodev_ccp_probe, 3100054d84fSRavi Kumar .remove = cryptodev_ccp_remove 3110054d84fSRavi Kumar }; 3120054d84fSRavi Kumar 3130054d84fSRavi Kumar static struct cryptodev_driver ccp_crypto_drv; 3140054d84fSRavi Kumar 315889317b7SAmaranath Somalapuram RTE_PMD_REGISTER_PCI(CRYPTODEV_NAME_CCP_PMD, cryptodev_ccp_pmd_drv); 316889317b7SAmaranath Somalapuram RTE_PMD_REGISTER_KMOD_DEP(CRYPTODEV_NAME_CCP_PMD, "* igb_uio | uio_pci_generic | vfio-pci"); 3170054d84fSRavi Kumar RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_CCP_PMD, 318e0d88a39SRavi Kumar "max_nb_queue_pairs=<int> " 319e0d88a39SRavi Kumar "socket_id=<int> " 320e0d88a39SRavi Kumar "ccp_auth_opt=<int>"); 3210054d84fSRavi Kumar RTE_PMD_REGISTER_CRYPTO_DRIVER(ccp_crypto_drv, cryptodev_ccp_pmd_drv.driver, 3220054d84fSRavi Kumar ccp_cryptodev_driver_id); 3230d526c7aSDavid Marchand RTE_LOG_REGISTER_DEFAULT(crypto_ccp_logtype, NOTICE); 324