1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2018-2022 Advanced Micro Devices, Inc. 3 */ 4 5 #include <stdio.h> 6 #include <errno.h> 7 #include <string.h> 8 #include <stdint.h> 9 10 #include <rte_common.h> 11 #include <rte_interrupts.h> 12 #include <rte_log.h> 13 #include <rte_pci.h> 14 #include <bus_pci_driver.h> 15 #include <rte_eal.h> 16 #include <ethdev_pci.h> 17 #include <rte_dev.h> 18 #include <rte_kvargs.h> 19 20 #include "ionic.h" 21 #include "ionic_if.h" 22 #include "ionic_dev.h" 23 #include "ionic_ethdev.h" 24 #include "ionic_logs.h" 25 26 static const struct rte_pci_id pci_id_ionic_map[] = { 27 { RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_PF) }, 28 { RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_VF) }, 29 { RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_MGMT) }, 30 { .vendor_id = 0, /* sentinel */ }, 31 }; 32 33 static int 34 ionic_pci_setup(struct ionic_adapter *adapter) 35 { 36 struct ionic_dev_bar *bar = adapter->bars.bar; 37 unsigned int num_bars = adapter->bars.num_bars; 38 struct ionic_dev *idev = &adapter->idev; 39 struct rte_pci_device *bus_dev = adapter->bus_dev; 40 uint32_t sig; 41 uint8_t *bar0_base; 42 unsigned int i; 43 44 /* BAR0: dev_cmd and interrupts */ 45 if (num_bars < 1) { 46 IONIC_PRINT(ERR, "No bars found, aborting\n"); 47 return -EFAULT; 48 } 49 50 if (bar->len < IONIC_BAR0_SIZE) { 51 IONIC_PRINT(ERR, 52 "Resource bar size %lu too small, aborting\n", 53 bar->len); 54 return -EFAULT; 55 } 56 57 bar0_base = bar->vaddr; 58 idev->dev_info = (union ionic_dev_info_regs *) 59 &bar0_base[IONIC_BAR0_DEV_INFO_REGS_OFFSET]; 60 idev->dev_cmd = (union ionic_dev_cmd_regs *) 61 &bar0_base[IONIC_BAR0_DEV_CMD_REGS_OFFSET]; 62 idev->intr_status = (struct ionic_intr_status *) 63 &bar0_base[IONIC_BAR0_INTR_STATUS_OFFSET]; 64 idev->intr_ctrl = (struct ionic_intr *) 65 &bar0_base[IONIC_BAR0_INTR_CTRL_OFFSET]; 66 67 sig = ioread32(&idev->dev_info->signature); 68 if (sig != IONIC_DEV_INFO_SIGNATURE) { 69 IONIC_PRINT(ERR, "Incompatible firmware signature %#x", 70 sig); 71 return -EFAULT; 72 } 73 74 for (i = 0; i < IONIC_DEVINFO_FWVERS_BUFLEN; i++) 75 adapter->fw_version[i] = 76 ioread8(&idev->dev_info->fw_version[i]); 77 adapter->fw_version[IONIC_DEVINFO_FWVERS_BUFLEN - 1] = '\0'; 78 79 adapter->name = bus_dev->device.name; 80 81 IONIC_PRINT(DEBUG, "%s firmware version: %s", 82 adapter->name, adapter->fw_version); 83 84 /* BAR1: doorbells */ 85 bar++; 86 if (num_bars < IONIC_BARS_MIN) { 87 IONIC_PRINT(ERR, "Doorbell bar missing, aborting\n"); 88 return -EFAULT; 89 } 90 91 idev->db_pages = bar->vaddr; 92 93 return 0; 94 } 95 96 const char *ionic_pci_devargs_arr[] = { 97 PMD_IONIC_CMB_KVARG, 98 NULL, 99 }; 100 101 static int 102 ionic_pci_devarg_cmb(const char *key __rte_unused, const char *val, void *arg) 103 { 104 struct ionic_adapter *adapter = arg; 105 106 if (!strcmp(val, "1")) { 107 IONIC_PRINT(NOTICE, "%s enabled", PMD_IONIC_CMB_KVARG); 108 adapter->q_in_cmb = true; 109 } else if (!strcmp(val, "0")) { 110 IONIC_PRINT(DEBUG, "%s disabled (default)", 111 PMD_IONIC_CMB_KVARG); 112 } else { 113 IONIC_PRINT(ERR, "%s=%s invalid, use 1 or 0", 114 PMD_IONIC_CMB_KVARG, val); 115 return -ERANGE; 116 } 117 118 return 0; 119 } 120 121 static int 122 ionic_pci_devargs(struct ionic_adapter *adapter, struct rte_devargs *devargs) 123 { 124 struct rte_kvargs *kvlist; 125 int err = 0; 126 127 if (!devargs) 128 return 0; 129 130 kvlist = rte_kvargs_parse(devargs->args, ionic_pci_devargs_arr); 131 if (!kvlist) { 132 IONIC_PRINT(ERR, "Couldn't parse args '%s'", devargs->args); 133 return -EINVAL; 134 } 135 136 if (rte_kvargs_count(kvlist, PMD_IONIC_CMB_KVARG) == 1) { 137 err = rte_kvargs_process(kvlist, PMD_IONIC_CMB_KVARG, 138 ionic_pci_devarg_cmb, adapter); 139 if (err < 0) 140 goto free_kvlist; 141 } 142 143 free_kvlist: 144 rte_kvargs_free(kvlist); 145 return err; 146 } 147 148 static void 149 ionic_pci_copy_bus_info(struct ionic_adapter *adapter, 150 struct rte_eth_dev *eth_dev) 151 { 152 rte_eth_copy_pci_info(eth_dev, adapter->bus_dev); 153 } 154 155 static int 156 ionic_pci_configure_intr(struct ionic_adapter *adapter) 157 { 158 struct rte_pci_device *pci_dev = 159 (struct rte_pci_device *)(adapter->bus_dev); 160 struct rte_intr_handle *intr_handle = pci_dev->intr_handle; 161 int err; 162 163 IONIC_PRINT(ERR, "Configuring %u intrs", adapter->nintrs); 164 165 if (rte_intr_efd_enable(intr_handle, adapter->nintrs)) { 166 IONIC_PRINT(ERR, "Fail to create eventfd"); 167 return -1; 168 } 169 170 if (rte_intr_dp_is_en(intr_handle)) { 171 IONIC_PRINT(NOTICE, 172 "Packet I/O interrupt on datapath is enabled"); 173 if (rte_intr_vec_list_alloc(intr_handle, "intr_vec", 174 adapter->nintrs)) { 175 IONIC_PRINT(ERR, "Failed to allocate %u vectors", 176 adapter->nintrs); 177 return -ENOMEM; 178 } 179 } 180 181 err = rte_intr_callback_register(intr_handle, 182 ionic_dev_interrupt_handler, 183 adapter); 184 if (err) { 185 IONIC_PRINT(ERR, 186 "Failure registering interrupts handler (%d)", err); 187 return err; 188 } 189 190 /* enable intr mapping */ 191 err = rte_intr_enable(intr_handle); 192 if (err) { 193 IONIC_PRINT(ERR, "Failure enabling interrupts (%d)", err); 194 return err; 195 } 196 197 return 0; 198 } 199 200 static void 201 ionic_pci_unconfigure_intr(struct ionic_adapter *adapter) 202 { 203 struct rte_pci_device *pci_dev = 204 (struct rte_pci_device *)(adapter->bus_dev); 205 struct rte_intr_handle *intr_handle = pci_dev->intr_handle; 206 207 rte_intr_disable(intr_handle); 208 209 rte_intr_callback_unregister(intr_handle, 210 ionic_dev_interrupt_handler, 211 adapter); 212 } 213 214 static const struct ionic_dev_intf ionic_pci_intf = { 215 .setup = ionic_pci_setup, 216 .devargs = ionic_pci_devargs, 217 .copy_bus_info = ionic_pci_copy_bus_info, 218 .configure_intr = ionic_pci_configure_intr, 219 .unconfigure_intr = ionic_pci_unconfigure_intr, 220 }; 221 222 static int 223 eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 224 struct rte_pci_device *pci_dev) 225 { 226 struct rte_mem_resource *resource; 227 struct ionic_bars bars; 228 unsigned long i; 229 230 IONIC_PRINT(NOTICE, "Initializing device %s %s", 231 pci_dev->device.name, 232 rte_eal_process_type() == RTE_PROC_SECONDARY ? 233 "[SECONDARY]" : ""); 234 235 bars.num_bars = 0; 236 for (i = 0; i < PCI_MAX_RESOURCE && i < IONIC_BARS_MAX; i++) { 237 resource = &pci_dev->mem_resource[i]; 238 if (resource->phys_addr == 0 || resource->len == 0) 239 continue; 240 241 bars.bar[bars.num_bars].vaddr = resource->addr; 242 bars.bar[bars.num_bars].bus_addr = resource->phys_addr; 243 bars.bar[bars.num_bars].len = resource->len; 244 bars.num_bars++; 245 } 246 247 return eth_ionic_dev_probe((void *)pci_dev, 248 &pci_dev->device, 249 &bars, 250 &ionic_pci_intf, 251 pci_dev->id.device_id, 252 pci_dev->id.vendor_id); 253 } 254 255 static int 256 eth_ionic_pci_remove(struct rte_pci_device *pci_dev) 257 { 258 return eth_ionic_dev_remove(&pci_dev->device); 259 } 260 261 static struct rte_pci_driver rte_pci_ionic_pmd = { 262 .id_table = pci_id_ionic_map, 263 .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC | 264 RTE_PCI_DRV_WC_ACTIVATE, 265 .probe = eth_ionic_pci_probe, 266 .remove = eth_ionic_pci_remove, 267 }; 268 269 RTE_PMD_REGISTER_PCI(net_ionic_pci, rte_pci_ionic_pmd); 270 RTE_PMD_REGISTER_PCI_TABLE(net_ionic_pci, pci_id_ionic_map); 271 RTE_PMD_REGISTER_KMOD_DEP(net_ionic_pci, "* igb_uio | uio_pci_generic | vfio-pci"); 272 RTE_PMD_REGISTER_PARAM_STRING(net_ionic_pci, 273 PMD_IONIC_CMB_KVARG "=<0|1>" 274 ); 275