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