1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2021-2024 Advanced Micro Devices, Inc. 3 */ 4 5 #include <stdint.h> 6 #include <errno.h> 7 8 #include <rte_errno.h> 9 #include <rte_common.h> 10 #include <rte_log.h> 11 #include <rte_eal.h> 12 #include <bus_vdev_driver.h> 13 #include <rte_dev.h> 14 #include <rte_string_fns.h> 15 16 #include "ionic_crypto.h" 17 18 #define IOCPT_VDEV_DEV_BAR 0 19 #define IOCPT_VDEV_INTR_CTL_BAR 1 20 #define IOCPT_VDEV_INTR_CFG_BAR 2 21 #define IOCPT_VDEV_DB_BAR 3 22 #define IOCPT_VDEV_BARS_MAX 4 23 24 #define IOCPT_VDEV_DEV_INFO_REGS_OFFSET 0x0000 25 #define IOCPT_VDEV_DEV_CMD_REGS_OFFSET 0x0800 26 27 #define IOCPT_VDEV_FW_WAIT_US 1000 /* 1ms */ 28 #define IOCPT_VDEV_FW_WAIT_MAX 5000 /* 5s */ 29 30 static int 31 iocpt_vdev_setup_bars(struct iocpt_dev *dev) 32 { 33 struct iocpt_dev_bars *bars = &dev->bars; 34 uint8_t *bar0_base; 35 uint32_t fw_waits = 0; 36 uint8_t fw; 37 38 IOCPT_PRINT_CALL(); 39 40 /* BAR0: dev_cmd */ 41 bar0_base = bars->bar[IOCPT_VDEV_DEV_BAR].vaddr; 42 dev->dev_info = (union iocpt_dev_info_regs *) 43 &bar0_base[IOCPT_VDEV_DEV_INFO_REGS_OFFSET]; 44 dev->dev_cmd = (union iocpt_dev_cmd_regs *) 45 &bar0_base[IOCPT_VDEV_DEV_CMD_REGS_OFFSET]; 46 47 /* BAR1: interrupts */ 48 dev->intr_ctrl = (void *)bars->bar[IOCPT_VDEV_INTR_CTL_BAR].vaddr; 49 50 /* BAR3: doorbells */ 51 dev->db_pages = (void *)bars->bar[IOCPT_VDEV_DB_BAR].vaddr; 52 53 /* Wait for the FW to indicate readiness */ 54 while (1) { 55 fw = ioread8(&dev->dev_info->fw_status); 56 if ((fw & IOCPT_FW_STS_F_RUNNING) != 0) 57 break; 58 59 if (fw_waits > IOCPT_VDEV_FW_WAIT_MAX) { 60 IOCPT_PRINT(ERR, "Firmware readiness bit not set"); 61 return -ETIMEDOUT; 62 } 63 64 fw_waits++; 65 rte_delay_us_block(IOCPT_VDEV_FW_WAIT_US); 66 } 67 IOCPT_PRINT(DEBUG, "Firmware ready (%u waits)", fw_waits); 68 69 dev->name = rte_vdev_device_name(dev->bus_dev); 70 71 return 0; 72 } 73 74 static void 75 iocpt_vdev_unmap_bars(struct iocpt_dev *dev) 76 { 77 struct iocpt_dev_bars *bars = &dev->bars; 78 uint32_t i; 79 80 for (i = 0; i < IOCPT_VDEV_BARS_MAX; i++) 81 ionic_uio_rel_rsrc(dev->name, i, &bars->bar[i]); 82 } 83 84 static uint8_t iocpt_vdev_driver_id; 85 static const struct iocpt_dev_intf iocpt_vdev_intf = { 86 .setup_bars = iocpt_vdev_setup_bars, 87 .unmap_bars = iocpt_vdev_unmap_bars, 88 }; 89 90 static int 91 iocpt_vdev_probe(struct rte_vdev_device *vdev) 92 { 93 struct iocpt_dev_bars bars = {}; 94 const char *name = rte_vdev_device_name(vdev); 95 unsigned int i; 96 97 IOCPT_PRINT(NOTICE, "Initializing device %s%s", name, 98 rte_eal_process_type() == RTE_PROC_SECONDARY ? 99 " [SECONDARY]" : ""); 100 101 ionic_uio_scan_mcrypt_devices(); 102 103 for (i = 0; i < IOCPT_VDEV_BARS_MAX; i++) 104 ionic_uio_get_rsrc(name, i, &bars.bar[i]); 105 106 bars.num_bars = IOCPT_VDEV_BARS_MAX; 107 108 return iocpt_probe((void *)vdev, &vdev->device, 109 &bars, &iocpt_vdev_intf, 110 iocpt_vdev_driver_id, rte_socket_id()); 111 } 112 113 static int 114 iocpt_vdev_remove(struct rte_vdev_device *vdev) 115 { 116 return iocpt_remove(&vdev->device); 117 } 118 119 static struct rte_vdev_driver rte_vdev_iocpt_pmd = { 120 .probe = iocpt_vdev_probe, 121 .remove = iocpt_vdev_remove, 122 }; 123 124 static struct cryptodev_driver rte_vdev_iocpt_drv; 125 126 RTE_PMD_REGISTER_VDEV(crypto_ionic, rte_vdev_iocpt_pmd); 127 RTE_PMD_REGISTER_CRYPTO_DRIVER(rte_vdev_iocpt_drv, rte_vdev_iocpt_pmd.driver, 128 iocpt_vdev_driver_id); 129