17c125393SAlfredo Cardigliano /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0) 27c125393SAlfredo Cardigliano * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. 37c125393SAlfredo Cardigliano */ 47c125393SAlfredo Cardigliano 55ef51809SAlfredo Cardigliano #include <rte_pci.h> 65ef51809SAlfredo Cardigliano #include <rte_bus_pci.h> 75ef51809SAlfredo Cardigliano #include <rte_ethdev.h> 85ef51809SAlfredo Cardigliano #include <rte_ethdev_driver.h> 95ef51809SAlfredo Cardigliano #include <rte_malloc.h> 10*669c8de6SAlfredo Cardigliano #include <rte_ethdev_pci.h> 115ef51809SAlfredo Cardigliano 127c125393SAlfredo Cardigliano #include "ionic_logs.h" 135ef51809SAlfredo Cardigliano #include "ionic.h" 145ef51809SAlfredo Cardigliano #include "ionic_dev.h" 155ef51809SAlfredo Cardigliano #include "ionic_mac_api.h" 16*669c8de6SAlfredo Cardigliano #include "ionic_lif.h" 17*669c8de6SAlfredo Cardigliano #include "ionic_ethdev.h" 18*669c8de6SAlfredo Cardigliano 19*669c8de6SAlfredo Cardigliano static int eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params); 20*669c8de6SAlfredo Cardigliano static int eth_ionic_dev_uninit(struct rte_eth_dev *eth_dev); 217c125393SAlfredo Cardigliano 227c125393SAlfredo Cardigliano int ionic_logtype; 237c125393SAlfredo Cardigliano 245ef51809SAlfredo Cardigliano static const struct rte_pci_id pci_id_ionic_map[] = { 255ef51809SAlfredo Cardigliano { RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_PF) }, 265ef51809SAlfredo Cardigliano { RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_VF) }, 275ef51809SAlfredo Cardigliano { RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_MGMT) }, 285ef51809SAlfredo Cardigliano { .vendor_id = 0, /* sentinel */ }, 295ef51809SAlfredo Cardigliano }; 305ef51809SAlfredo Cardigliano 31*669c8de6SAlfredo Cardigliano static const struct eth_dev_ops ionic_eth_dev_ops = { 32*669c8de6SAlfredo Cardigliano }; 33*669c8de6SAlfredo Cardigliano 34*669c8de6SAlfredo Cardigliano static int 35*669c8de6SAlfredo Cardigliano eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params) 36*669c8de6SAlfredo Cardigliano { 37*669c8de6SAlfredo Cardigliano struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 38*669c8de6SAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 39*669c8de6SAlfredo Cardigliano struct ionic_adapter *adapter = (struct ionic_adapter *)init_params; 40*669c8de6SAlfredo Cardigliano int err; 41*669c8de6SAlfredo Cardigliano 42*669c8de6SAlfredo Cardigliano IONIC_PRINT_CALL(); 43*669c8de6SAlfredo Cardigliano 44*669c8de6SAlfredo Cardigliano eth_dev->dev_ops = &ionic_eth_dev_ops; 45*669c8de6SAlfredo Cardigliano 46*669c8de6SAlfredo Cardigliano /* Multi-process not supported, primary does initialization anyway */ 47*669c8de6SAlfredo Cardigliano if (rte_eal_process_type() != RTE_PROC_PRIMARY) 48*669c8de6SAlfredo Cardigliano return 0; 49*669c8de6SAlfredo Cardigliano 50*669c8de6SAlfredo Cardigliano rte_eth_copy_pci_info(eth_dev, pci_dev); 51*669c8de6SAlfredo Cardigliano 52*669c8de6SAlfredo Cardigliano lif->index = adapter->nlifs; 53*669c8de6SAlfredo Cardigliano lif->eth_dev = eth_dev; 54*669c8de6SAlfredo Cardigliano lif->adapter = adapter; 55*669c8de6SAlfredo Cardigliano adapter->lifs[adapter->nlifs] = lif; 56*669c8de6SAlfredo Cardigliano 57*669c8de6SAlfredo Cardigliano err = ionic_lif_alloc(lif); 58*669c8de6SAlfredo Cardigliano if (err) { 59*669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate LIFs: %d, aborting", 60*669c8de6SAlfredo Cardigliano err); 61*669c8de6SAlfredo Cardigliano goto err; 62*669c8de6SAlfredo Cardigliano } 63*669c8de6SAlfredo Cardigliano 64*669c8de6SAlfredo Cardigliano err = ionic_lif_init(lif); 65*669c8de6SAlfredo Cardigliano if (err) { 66*669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot init LIFs: %d, aborting", err); 67*669c8de6SAlfredo Cardigliano goto err_free_lif; 68*669c8de6SAlfredo Cardigliano } 69*669c8de6SAlfredo Cardigliano 70*669c8de6SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Port %u initialized", eth_dev->data->port_id); 71*669c8de6SAlfredo Cardigliano 72*669c8de6SAlfredo Cardigliano return 0; 73*669c8de6SAlfredo Cardigliano 74*669c8de6SAlfredo Cardigliano err_free_lif: 75*669c8de6SAlfredo Cardigliano ionic_lif_free(lif); 76*669c8de6SAlfredo Cardigliano err: 77*669c8de6SAlfredo Cardigliano return err; 78*669c8de6SAlfredo Cardigliano } 79*669c8de6SAlfredo Cardigliano 80*669c8de6SAlfredo Cardigliano static int 81*669c8de6SAlfredo Cardigliano eth_ionic_dev_uninit(struct rte_eth_dev *eth_dev) 82*669c8de6SAlfredo Cardigliano { 83*669c8de6SAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 84*669c8de6SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 85*669c8de6SAlfredo Cardigliano 86*669c8de6SAlfredo Cardigliano IONIC_PRINT_CALL(); 87*669c8de6SAlfredo Cardigliano 88*669c8de6SAlfredo Cardigliano if (rte_eal_process_type() != RTE_PROC_PRIMARY) 89*669c8de6SAlfredo Cardigliano return 0; 90*669c8de6SAlfredo Cardigliano 91*669c8de6SAlfredo Cardigliano adapter->lifs[lif->index] = NULL; 92*669c8de6SAlfredo Cardigliano 93*669c8de6SAlfredo Cardigliano ionic_lif_deinit(lif); 94*669c8de6SAlfredo Cardigliano ionic_lif_free(lif); 95*669c8de6SAlfredo Cardigliano 96*669c8de6SAlfredo Cardigliano eth_dev->dev_ops = NULL; 97*669c8de6SAlfredo Cardigliano 98*669c8de6SAlfredo Cardigliano return 0; 99*669c8de6SAlfredo Cardigliano } 100*669c8de6SAlfredo Cardigliano 1015ef51809SAlfredo Cardigliano static int 1025ef51809SAlfredo Cardigliano eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 1035ef51809SAlfredo Cardigliano struct rte_pci_device *pci_dev) 1045ef51809SAlfredo Cardigliano { 105*669c8de6SAlfredo Cardigliano char name[RTE_ETH_NAME_MAX_LEN]; 1065ef51809SAlfredo Cardigliano struct rte_mem_resource *resource; 1075ef51809SAlfredo Cardigliano struct ionic_adapter *adapter; 1085ef51809SAlfredo Cardigliano struct ionic_hw *hw; 1095ef51809SAlfredo Cardigliano unsigned long i; 1105ef51809SAlfredo Cardigliano int err; 1115ef51809SAlfredo Cardigliano 1125ef51809SAlfredo Cardigliano /* Check structs (trigger error at compilation time) */ 1135ef51809SAlfredo Cardigliano ionic_struct_size_checks(); 1145ef51809SAlfredo Cardigliano 1155ef51809SAlfredo Cardigliano /* Multi-process not supported */ 1165ef51809SAlfredo Cardigliano if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 1175ef51809SAlfredo Cardigliano err = -EPERM; 1185ef51809SAlfredo Cardigliano goto err; 1195ef51809SAlfredo Cardigliano } 1205ef51809SAlfredo Cardigliano 1215ef51809SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Initializing device %s", 1225ef51809SAlfredo Cardigliano pci_dev->device.name); 1235ef51809SAlfredo Cardigliano 1245ef51809SAlfredo Cardigliano adapter = rte_zmalloc("ionic", sizeof(*adapter), 0); 1255ef51809SAlfredo Cardigliano if (!adapter) { 1265ef51809SAlfredo Cardigliano IONIC_PRINT(ERR, "OOM"); 1275ef51809SAlfredo Cardigliano err = -ENOMEM; 1285ef51809SAlfredo Cardigliano goto err; 1295ef51809SAlfredo Cardigliano } 1305ef51809SAlfredo Cardigliano 1315ef51809SAlfredo Cardigliano adapter->pci_dev = pci_dev; 1325ef51809SAlfredo Cardigliano hw = &adapter->hw; 1335ef51809SAlfredo Cardigliano 1345ef51809SAlfredo Cardigliano hw->device_id = pci_dev->id.device_id; 1355ef51809SAlfredo Cardigliano hw->vendor_id = pci_dev->id.vendor_id; 1365ef51809SAlfredo Cardigliano 1375ef51809SAlfredo Cardigliano err = ionic_init_mac(hw); 1385ef51809SAlfredo Cardigliano if (err != 0) { 1395ef51809SAlfredo Cardigliano IONIC_PRINT(ERR, "Mac init failed: %d", err); 1405ef51809SAlfredo Cardigliano err = -EIO; 1415ef51809SAlfredo Cardigliano goto err_free_adapter; 1425ef51809SAlfredo Cardigliano } 1435ef51809SAlfredo Cardigliano 1445ef51809SAlfredo Cardigliano adapter->is_mgmt_nic = (pci_dev->id.device_id == IONIC_DEV_ID_ETH_MGMT); 1455ef51809SAlfredo Cardigliano 1465ef51809SAlfredo Cardigliano adapter->num_bars = 0; 1475ef51809SAlfredo Cardigliano for (i = 0; i < PCI_MAX_RESOURCE && i < IONIC_BARS_MAX; i++) { 1485ef51809SAlfredo Cardigliano resource = &pci_dev->mem_resource[i]; 1495ef51809SAlfredo Cardigliano if (resource->phys_addr == 0 || resource->len == 0) 1505ef51809SAlfredo Cardigliano continue; 1515ef51809SAlfredo Cardigliano adapter->bars[adapter->num_bars].vaddr = resource->addr; 1525ef51809SAlfredo Cardigliano adapter->bars[adapter->num_bars].bus_addr = resource->phys_addr; 1535ef51809SAlfredo Cardigliano adapter->bars[adapter->num_bars].len = resource->len; 1545ef51809SAlfredo Cardigliano adapter->num_bars++; 1555ef51809SAlfredo Cardigliano } 1565ef51809SAlfredo Cardigliano 1575ef51809SAlfredo Cardigliano /* Discover ionic dev resources */ 1585ef51809SAlfredo Cardigliano 1595ef51809SAlfredo Cardigliano err = ionic_setup(adapter); 1605ef51809SAlfredo Cardigliano if (err) { 1615ef51809SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot setup device: %d, aborting", err); 1625ef51809SAlfredo Cardigliano goto err_free_adapter; 1635ef51809SAlfredo Cardigliano } 1645ef51809SAlfredo Cardigliano 1655ef51809SAlfredo Cardigliano err = ionic_identify(adapter); 1665ef51809SAlfredo Cardigliano if (err) { 1675ef51809SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot identify device: %d, aborting", 1685ef51809SAlfredo Cardigliano err); 1695ef51809SAlfredo Cardigliano goto err_free_adapter; 1705ef51809SAlfredo Cardigliano } 1715ef51809SAlfredo Cardigliano 1725ef51809SAlfredo Cardigliano err = ionic_init(adapter); 1735ef51809SAlfredo Cardigliano if (err) { 1745ef51809SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot init device: %d, aborting", err); 1755ef51809SAlfredo Cardigliano goto err_free_adapter; 1765ef51809SAlfredo Cardigliano } 1775ef51809SAlfredo Cardigliano 17823bf4ddbSAlfredo Cardigliano /* Configure the ports */ 17923bf4ddbSAlfredo Cardigliano err = ionic_port_identify(adapter); 18023bf4ddbSAlfredo Cardigliano if (err) { 18123bf4ddbSAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot identify port: %d, aborting", 18223bf4ddbSAlfredo Cardigliano err); 18323bf4ddbSAlfredo Cardigliano goto err_free_adapter; 18423bf4ddbSAlfredo Cardigliano } 18523bf4ddbSAlfredo Cardigliano 18623bf4ddbSAlfredo Cardigliano err = ionic_port_init(adapter); 18723bf4ddbSAlfredo Cardigliano if (err) { 18823bf4ddbSAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot init port: %d, aborting", err); 18923bf4ddbSAlfredo Cardigliano goto err_free_adapter; 19023bf4ddbSAlfredo Cardigliano } 19123bf4ddbSAlfredo Cardigliano 192*669c8de6SAlfredo Cardigliano /* Configure LIFs */ 193*669c8de6SAlfredo Cardigliano err = ionic_lif_identify(adapter); 194*669c8de6SAlfredo Cardigliano if (err) { 195*669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot identify lif: %d, aborting", err); 196*669c8de6SAlfredo Cardigliano goto err_free_adapter; 197*669c8de6SAlfredo Cardigliano } 198*669c8de6SAlfredo Cardigliano 199*669c8de6SAlfredo Cardigliano /* Allocate and init LIFs */ 200*669c8de6SAlfredo Cardigliano err = ionic_lifs_size(adapter); 201*669c8de6SAlfredo Cardigliano if (err) { 202*669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot size LIFs: %d, aborting", err); 203*669c8de6SAlfredo Cardigliano goto err_free_adapter; 204*669c8de6SAlfredo Cardigliano } 205*669c8de6SAlfredo Cardigliano 206*669c8de6SAlfredo Cardigliano adapter->nlifs = 0; 207*669c8de6SAlfredo Cardigliano for (i = 0; i < adapter->ident.dev.nlifs; i++) { 208*669c8de6SAlfredo Cardigliano snprintf(name, sizeof(name), "net_%s_lif_%lu", 209*669c8de6SAlfredo Cardigliano pci_dev->device.name, i); 210*669c8de6SAlfredo Cardigliano 211*669c8de6SAlfredo Cardigliano err = rte_eth_dev_create(&pci_dev->device, name, 212*669c8de6SAlfredo Cardigliano sizeof(struct ionic_lif), 213*669c8de6SAlfredo Cardigliano NULL, NULL, 214*669c8de6SAlfredo Cardigliano eth_ionic_dev_init, adapter); 215*669c8de6SAlfredo Cardigliano if (err) { 216*669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot create eth device for " 217*669c8de6SAlfredo Cardigliano "ionic lif %s", name); 218*669c8de6SAlfredo Cardigliano break; 219*669c8de6SAlfredo Cardigliano } 220*669c8de6SAlfredo Cardigliano 221*669c8de6SAlfredo Cardigliano adapter->nlifs++; 222*669c8de6SAlfredo Cardigliano } 223*669c8de6SAlfredo Cardigliano 2245ef51809SAlfredo Cardigliano return 0; 2255ef51809SAlfredo Cardigliano 2265ef51809SAlfredo Cardigliano err_free_adapter: 2275ef51809SAlfredo Cardigliano rte_free(adapter); 2285ef51809SAlfredo Cardigliano err: 2295ef51809SAlfredo Cardigliano return err; 2305ef51809SAlfredo Cardigliano } 2315ef51809SAlfredo Cardigliano 2325ef51809SAlfredo Cardigliano static int 2335ef51809SAlfredo Cardigliano eth_ionic_pci_remove(struct rte_pci_device *pci_dev __rte_unused) 2345ef51809SAlfredo Cardigliano { 235*669c8de6SAlfredo Cardigliano char name[RTE_ETH_NAME_MAX_LEN]; 236*669c8de6SAlfredo Cardigliano struct ionic_adapter *adapter = NULL; 237*669c8de6SAlfredo Cardigliano struct rte_eth_dev *eth_dev; 238*669c8de6SAlfredo Cardigliano struct ionic_lif *lif; 239*669c8de6SAlfredo Cardigliano uint32_t i; 240*669c8de6SAlfredo Cardigliano 241*669c8de6SAlfredo Cardigliano /* Adapter lookup is using (the first) eth_dev name */ 242*669c8de6SAlfredo Cardigliano snprintf(name, sizeof(name), "net_%s_lif_0", 243*669c8de6SAlfredo Cardigliano pci_dev->device.name); 244*669c8de6SAlfredo Cardigliano 245*669c8de6SAlfredo Cardigliano eth_dev = rte_eth_dev_allocated(name); 246*669c8de6SAlfredo Cardigliano if (eth_dev) { 247*669c8de6SAlfredo Cardigliano lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 248*669c8de6SAlfredo Cardigliano adapter = lif->adapter; 249*669c8de6SAlfredo Cardigliano } 250*669c8de6SAlfredo Cardigliano 251*669c8de6SAlfredo Cardigliano if (adapter) { 252*669c8de6SAlfredo Cardigliano for (i = 0; i < adapter->nlifs; i++) { 253*669c8de6SAlfredo Cardigliano lif = adapter->lifs[i]; 254*669c8de6SAlfredo Cardigliano rte_eth_dev_destroy(lif->eth_dev, eth_ionic_dev_uninit); 255*669c8de6SAlfredo Cardigliano } 256*669c8de6SAlfredo Cardigliano 257*669c8de6SAlfredo Cardigliano rte_free(adapter); 258*669c8de6SAlfredo Cardigliano } 259*669c8de6SAlfredo Cardigliano 2605ef51809SAlfredo Cardigliano return 0; 2615ef51809SAlfredo Cardigliano } 2625ef51809SAlfredo Cardigliano 2635ef51809SAlfredo Cardigliano static struct rte_pci_driver rte_ionic_pmd = { 2645ef51809SAlfredo Cardigliano .id_table = pci_id_ionic_map, 2655ef51809SAlfredo Cardigliano .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, 2665ef51809SAlfredo Cardigliano .probe = eth_ionic_pci_probe, 2675ef51809SAlfredo Cardigliano .remove = eth_ionic_pci_remove, 2685ef51809SAlfredo Cardigliano }; 2695ef51809SAlfredo Cardigliano 2705ef51809SAlfredo Cardigliano RTE_PMD_REGISTER_PCI(net_ionic, rte_ionic_pmd); 2715ef51809SAlfredo Cardigliano RTE_PMD_REGISTER_PCI_TABLE(net_ionic, pci_id_ionic_map); 2725ef51809SAlfredo Cardigliano RTE_PMD_REGISTER_KMOD_DEP(net_ionic, "* igb_uio | uio_pci_generic | vfio-pci"); 2735ef51809SAlfredo Cardigliano 2747c125393SAlfredo Cardigliano RTE_INIT(ionic_init_log) 2757c125393SAlfredo Cardigliano { 2767c125393SAlfredo Cardigliano ionic_logtype = rte_log_register("pmd.net.ionic"); 2777c125393SAlfredo Cardigliano if (ionic_logtype >= 0) 2787c125393SAlfredo Cardigliano rte_log_set_level(ionic_logtype, RTE_LOG_NOTICE); 2797c125393SAlfredo Cardigliano } 280