14610ac93SAndrew Boyer /* SPDX-License-Identifier: BSD-3-Clause 24610ac93SAndrew Boyer * Copyright 2021-2024 Advanced Micro Devices, Inc. 34610ac93SAndrew Boyer */ 44610ac93SAndrew Boyer 54610ac93SAndrew Boyer #include <inttypes.h> 64610ac93SAndrew Boyer 74610ac93SAndrew Boyer #include <rte_common.h> 84610ac93SAndrew Boyer #include <rte_malloc.h> 94610ac93SAndrew Boyer #include <rte_bitops.h> 104610ac93SAndrew Boyer 114610ac93SAndrew Boyer #include "ionic_crypto.h" 124610ac93SAndrew Boyer 13*a677112dSAndrew Boyer static const struct rte_memzone * 14*a677112dSAndrew Boyer iocpt_dma_zone_reserve(const char *type_name, uint16_t qid, size_t size, 15*a677112dSAndrew Boyer unsigned int align, int socket_id) 16*a677112dSAndrew Boyer { 17*a677112dSAndrew Boyer char zone_name[RTE_MEMZONE_NAMESIZE]; 18*a677112dSAndrew Boyer const struct rte_memzone *mz; 19*a677112dSAndrew Boyer int err; 20*a677112dSAndrew Boyer 21*a677112dSAndrew Boyer err = snprintf(zone_name, sizeof(zone_name), 22*a677112dSAndrew Boyer "iocpt_%s_%u", type_name, qid); 23*a677112dSAndrew Boyer if (err >= RTE_MEMZONE_NAMESIZE) { 24*a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Name %s too long", type_name); 25*a677112dSAndrew Boyer return NULL; 26*a677112dSAndrew Boyer } 27*a677112dSAndrew Boyer 28*a677112dSAndrew Boyer mz = rte_memzone_lookup(zone_name); 29*a677112dSAndrew Boyer if (mz != NULL) 30*a677112dSAndrew Boyer return mz; 31*a677112dSAndrew Boyer 32*a677112dSAndrew Boyer return rte_memzone_reserve_aligned(zone_name, size, socket_id, 33*a677112dSAndrew Boyer RTE_MEMZONE_IOVA_CONTIG, align); 34*a677112dSAndrew Boyer } 35*a677112dSAndrew Boyer 36*a677112dSAndrew Boyer static int 37*a677112dSAndrew Boyer iocpt_alloc_objs(struct iocpt_dev *dev) 38*a677112dSAndrew Boyer { 39*a677112dSAndrew Boyer int err; 40*a677112dSAndrew Boyer 41*a677112dSAndrew Boyer IOCPT_PRINT(DEBUG, "Crypto: %s", dev->name); 42*a677112dSAndrew Boyer 43*a677112dSAndrew Boyer dev->info_sz = RTE_ALIGN(sizeof(*dev->info), rte_mem_page_size()); 44*a677112dSAndrew Boyer dev->info_z = iocpt_dma_zone_reserve("info", 0, dev->info_sz, 45*a677112dSAndrew Boyer IONIC_ALIGN, dev->socket_id); 46*a677112dSAndrew Boyer if (dev->info_z == NULL) { 47*a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Cannot allocate dev info memory"); 48*a677112dSAndrew Boyer err = -ENOMEM; 49*a677112dSAndrew Boyer goto err_out; 50*a677112dSAndrew Boyer } 51*a677112dSAndrew Boyer 52*a677112dSAndrew Boyer dev->info = dev->info_z->addr; 53*a677112dSAndrew Boyer dev->info_pa = dev->info_z->iova; 54*a677112dSAndrew Boyer 55*a677112dSAndrew Boyer return 0; 56*a677112dSAndrew Boyer 57*a677112dSAndrew Boyer err_out: 58*a677112dSAndrew Boyer return err; 59*a677112dSAndrew Boyer } 60*a677112dSAndrew Boyer 614610ac93SAndrew Boyer static int 624610ac93SAndrew Boyer iocpt_init(struct iocpt_dev *dev) 634610ac93SAndrew Boyer { 64*a677112dSAndrew Boyer int err; 65*a677112dSAndrew Boyer 66*a677112dSAndrew Boyer /* Uses dev_cmds */ 67*a677112dSAndrew Boyer err = iocpt_dev_init(dev, dev->info_pa); 68*a677112dSAndrew Boyer if (err != 0) 69*a677112dSAndrew Boyer return err; 70*a677112dSAndrew Boyer 714610ac93SAndrew Boyer dev->state |= IOCPT_DEV_F_INITED; 724610ac93SAndrew Boyer 734610ac93SAndrew Boyer return 0; 744610ac93SAndrew Boyer } 754610ac93SAndrew Boyer 764610ac93SAndrew Boyer void 774610ac93SAndrew Boyer iocpt_configure(struct iocpt_dev *dev) 784610ac93SAndrew Boyer { 794610ac93SAndrew Boyer RTE_SET_USED(dev); 804610ac93SAndrew Boyer } 814610ac93SAndrew Boyer 824610ac93SAndrew Boyer void 834610ac93SAndrew Boyer iocpt_deinit(struct iocpt_dev *dev) 844610ac93SAndrew Boyer { 854610ac93SAndrew Boyer IOCPT_PRINT_CALL(); 864610ac93SAndrew Boyer 874610ac93SAndrew Boyer if (!(dev->state & IOCPT_DEV_F_INITED)) 884610ac93SAndrew Boyer return; 894610ac93SAndrew Boyer 904610ac93SAndrew Boyer dev->state &= ~IOCPT_DEV_F_INITED; 914610ac93SAndrew Boyer } 924610ac93SAndrew Boyer 93*a677112dSAndrew Boyer static void 94*a677112dSAndrew Boyer iocpt_free_objs(struct iocpt_dev *dev) 95*a677112dSAndrew Boyer { 96*a677112dSAndrew Boyer IOCPT_PRINT_CALL(); 97*a677112dSAndrew Boyer 98*a677112dSAndrew Boyer if (dev->info != NULL) { 99*a677112dSAndrew Boyer rte_memzone_free(dev->info_z); 100*a677112dSAndrew Boyer dev->info_z = NULL; 101*a677112dSAndrew Boyer dev->info = NULL; 102*a677112dSAndrew Boyer dev->info_pa = 0; 103*a677112dSAndrew Boyer } 104*a677112dSAndrew Boyer } 105*a677112dSAndrew Boyer 1064610ac93SAndrew Boyer static int 1074610ac93SAndrew Boyer iocpt_devargs(struct rte_devargs *devargs, struct iocpt_dev *dev) 1084610ac93SAndrew Boyer { 1094610ac93SAndrew Boyer RTE_SET_USED(devargs); 1104610ac93SAndrew Boyer RTE_SET_USED(dev); 1114610ac93SAndrew Boyer 1124610ac93SAndrew Boyer return 0; 1134610ac93SAndrew Boyer } 1144610ac93SAndrew Boyer 1154610ac93SAndrew Boyer int 1164610ac93SAndrew Boyer iocpt_probe(void *bus_dev, struct rte_device *rte_dev, 1174610ac93SAndrew Boyer struct iocpt_dev_bars *bars, const struct iocpt_dev_intf *intf, 1184610ac93SAndrew Boyer uint8_t driver_id, uint8_t socket_id) 1194610ac93SAndrew Boyer { 1204610ac93SAndrew Boyer struct rte_cryptodev_pmd_init_params init_params = { 1214610ac93SAndrew Boyer "iocpt", 1224610ac93SAndrew Boyer sizeof(struct iocpt_dev), 1234610ac93SAndrew Boyer socket_id, 1244610ac93SAndrew Boyer RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS 1254610ac93SAndrew Boyer }; 1264610ac93SAndrew Boyer struct rte_cryptodev *cdev; 1274610ac93SAndrew Boyer struct iocpt_dev *dev; 12825c896eaSAndrew Boyer uint32_t i, sig; 1294610ac93SAndrew Boyer int err; 1304610ac93SAndrew Boyer 13125c896eaSAndrew Boyer /* Check structs (trigger error at compilation time) */ 13225c896eaSAndrew Boyer iocpt_struct_size_checks(); 13325c896eaSAndrew Boyer 1344610ac93SAndrew Boyer if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 1354610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Multi-process not supported"); 1364610ac93SAndrew Boyer err = -EPERM; 1374610ac93SAndrew Boyer goto err; 1384610ac93SAndrew Boyer } 1394610ac93SAndrew Boyer 1404610ac93SAndrew Boyer cdev = rte_cryptodev_pmd_create(rte_dev->name, rte_dev, &init_params); 1414610ac93SAndrew Boyer if (cdev == NULL) { 1424610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Out of memory"); 1434610ac93SAndrew Boyer err = -ENOMEM; 1444610ac93SAndrew Boyer goto err; 1454610ac93SAndrew Boyer } 1464610ac93SAndrew Boyer 1474610ac93SAndrew Boyer dev = cdev->data->dev_private; 1484610ac93SAndrew Boyer dev->crypto_dev = cdev; 1494610ac93SAndrew Boyer dev->bus_dev = bus_dev; 1504610ac93SAndrew Boyer dev->intf = intf; 1514610ac93SAndrew Boyer dev->driver_id = driver_id; 1524610ac93SAndrew Boyer dev->socket_id = socket_id; 1534610ac93SAndrew Boyer 1544610ac93SAndrew Boyer for (i = 0; i < bars->num_bars; i++) { 1554610ac93SAndrew Boyer struct ionic_dev_bar *bar = &bars->bar[i]; 1564610ac93SAndrew Boyer 1574610ac93SAndrew Boyer IOCPT_PRINT(DEBUG, 1584610ac93SAndrew Boyer "bar[%u] = { .va = %p, .pa = %#jx, .len = %lu }", 1594610ac93SAndrew Boyer i, bar->vaddr, bar->bus_addr, bar->len); 1604610ac93SAndrew Boyer if (bar->vaddr == NULL) { 1614610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Null bar found, aborting"); 1624610ac93SAndrew Boyer err = -EFAULT; 1634610ac93SAndrew Boyer goto err_destroy_crypto_dev; 1644610ac93SAndrew Boyer } 1654610ac93SAndrew Boyer 1664610ac93SAndrew Boyer dev->bars.bar[i].vaddr = bar->vaddr; 1674610ac93SAndrew Boyer dev->bars.bar[i].bus_addr = bar->bus_addr; 1684610ac93SAndrew Boyer dev->bars.bar[i].len = bar->len; 1694610ac93SAndrew Boyer } 1704610ac93SAndrew Boyer dev->bars.num_bars = bars->num_bars; 1714610ac93SAndrew Boyer 1724610ac93SAndrew Boyer err = iocpt_devargs(rte_dev->devargs, dev); 1734610ac93SAndrew Boyer if (err != 0) { 1744610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Cannot parse device arguments"); 1754610ac93SAndrew Boyer goto err_destroy_crypto_dev; 1764610ac93SAndrew Boyer } 1774610ac93SAndrew Boyer 1784610ac93SAndrew Boyer err = iocpt_setup_bars(dev); 1794610ac93SAndrew Boyer if (err != 0) { 1804610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Cannot setup BARs: %d, aborting", err); 1814610ac93SAndrew Boyer goto err_destroy_crypto_dev; 1824610ac93SAndrew Boyer } 1834610ac93SAndrew Boyer 18425c896eaSAndrew Boyer sig = ioread32(&dev->dev_info->signature); 18525c896eaSAndrew Boyer if (sig != IOCPT_DEV_INFO_SIGNATURE) { 18625c896eaSAndrew Boyer IOCPT_PRINT(ERR, "Incompatible firmware signature %#x", sig); 18725c896eaSAndrew Boyer err = -EFAULT; 18825c896eaSAndrew Boyer goto err_destroy_crypto_dev; 18925c896eaSAndrew Boyer } 19025c896eaSAndrew Boyer 19125c896eaSAndrew Boyer for (i = 0; i < IOCPT_FWVERS_BUFLEN; i++) 19225c896eaSAndrew Boyer dev->fw_version[i] = ioread8(&dev->dev_info->fw_version[i]); 19325c896eaSAndrew Boyer dev->fw_version[IOCPT_FWVERS_BUFLEN - 1] = '\0'; 19425c896eaSAndrew Boyer IOCPT_PRINT(DEBUG, "%s firmware: %s", dev->name, dev->fw_version); 19525c896eaSAndrew Boyer 196*a677112dSAndrew Boyer err = iocpt_dev_identify(dev); 197*a677112dSAndrew Boyer if (err != 0) { 198*a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Cannot identify device: %d, aborting", 199*a677112dSAndrew Boyer err); 200*a677112dSAndrew Boyer goto err_destroy_crypto_dev; 201*a677112dSAndrew Boyer } 202*a677112dSAndrew Boyer 203*a677112dSAndrew Boyer err = iocpt_alloc_objs(dev); 204*a677112dSAndrew Boyer if (err != 0) { 205*a677112dSAndrew Boyer IOCPT_PRINT(ERR, "Cannot alloc device objects: %d", err); 206*a677112dSAndrew Boyer goto err_destroy_crypto_dev; 207*a677112dSAndrew Boyer } 208*a677112dSAndrew Boyer 2094610ac93SAndrew Boyer err = iocpt_init(dev); 2104610ac93SAndrew Boyer if (err != 0) { 2114610ac93SAndrew Boyer IOCPT_PRINT(ERR, "Cannot init device: %d, aborting", err); 212*a677112dSAndrew Boyer goto err_free_objs; 2134610ac93SAndrew Boyer } 2144610ac93SAndrew Boyer 2154610ac93SAndrew Boyer return 0; 2164610ac93SAndrew Boyer 217*a677112dSAndrew Boyer err_free_objs: 218*a677112dSAndrew Boyer iocpt_free_objs(dev); 2194610ac93SAndrew Boyer err_destroy_crypto_dev: 2204610ac93SAndrew Boyer rte_cryptodev_pmd_destroy(cdev); 2214610ac93SAndrew Boyer err: 2224610ac93SAndrew Boyer return err; 2234610ac93SAndrew Boyer } 2244610ac93SAndrew Boyer 2254610ac93SAndrew Boyer int 2264610ac93SAndrew Boyer iocpt_remove(struct rte_device *rte_dev) 2274610ac93SAndrew Boyer { 2284610ac93SAndrew Boyer struct rte_cryptodev *cdev; 2294610ac93SAndrew Boyer struct iocpt_dev *dev; 2304610ac93SAndrew Boyer 2314610ac93SAndrew Boyer cdev = rte_cryptodev_pmd_get_named_dev(rte_dev->name); 2324610ac93SAndrew Boyer if (cdev == NULL) { 2334610ac93SAndrew Boyer IOCPT_PRINT(DEBUG, "Cannot find device %s", rte_dev->name); 2344610ac93SAndrew Boyer return -ENODEV; 2354610ac93SAndrew Boyer } 2364610ac93SAndrew Boyer 2374610ac93SAndrew Boyer dev = cdev->data->dev_private; 2384610ac93SAndrew Boyer 2394610ac93SAndrew Boyer iocpt_deinit(dev); 2404610ac93SAndrew Boyer 241*a677112dSAndrew Boyer iocpt_dev_reset(dev); 242*a677112dSAndrew Boyer 243*a677112dSAndrew Boyer iocpt_free_objs(dev); 244*a677112dSAndrew Boyer 2454610ac93SAndrew Boyer rte_cryptodev_pmd_destroy(cdev); 2464610ac93SAndrew Boyer 2474610ac93SAndrew Boyer return 0; 2484610ac93SAndrew Boyer } 2494610ac93SAndrew Boyer 2504610ac93SAndrew Boyer RTE_LOG_REGISTER_DEFAULT(iocpt_logtype, NOTICE); 251