1df69ba43SShannon Nelson // SPDX-License-Identifier: GPL-2.0 2df69ba43SShannon Nelson /* Copyright(c) 2017 - 2019 Pensando Systems, Inc */ 3df69ba43SShannon Nelson 4df69ba43SShannon Nelson #include <linux/module.h> 5df69ba43SShannon Nelson #include <linux/netdevice.h> 6df69ba43SShannon Nelson #include <linux/etherdevice.h> 7df69ba43SShannon Nelson #include <linux/pci.h> 8df69ba43SShannon Nelson 9df69ba43SShannon Nelson #include "ionic.h" 10df69ba43SShannon Nelson #include "ionic_bus.h" 11fbfb8031SShannon Nelson #include "ionic_debugfs.h" 12df69ba43SShannon Nelson 13df69ba43SShannon Nelson /* Supported devices */ 14df69ba43SShannon Nelson static const struct pci_device_id ionic_id_table[] = { 15df69ba43SShannon Nelson { PCI_VDEVICE(PENSANDO, PCI_DEVICE_ID_PENSANDO_IONIC_ETH_PF) }, 16df69ba43SShannon Nelson { PCI_VDEVICE(PENSANDO, PCI_DEVICE_ID_PENSANDO_IONIC_ETH_VF) }, 17df69ba43SShannon Nelson { 0, } /* end of table */ 18df69ba43SShannon Nelson }; 19df69ba43SShannon Nelson MODULE_DEVICE_TABLE(pci, ionic_id_table); 20df69ba43SShannon Nelson 21fbfb8031SShannon Nelson const char *ionic_bus_info(struct ionic *ionic) 22fbfb8031SShannon Nelson { 23fbfb8031SShannon Nelson return pci_name(ionic->pdev); 24fbfb8031SShannon Nelson } 25fbfb8031SShannon Nelson 26fbfb8031SShannon Nelson static int ionic_map_bars(struct ionic *ionic) 27fbfb8031SShannon Nelson { 28fbfb8031SShannon Nelson struct pci_dev *pdev = ionic->pdev; 29fbfb8031SShannon Nelson struct device *dev = ionic->dev; 30fbfb8031SShannon Nelson struct ionic_dev_bar *bars; 31fbfb8031SShannon Nelson unsigned int i, j; 32fbfb8031SShannon Nelson 33fbfb8031SShannon Nelson bars = ionic->bars; 34fbfb8031SShannon Nelson ionic->num_bars = 0; 35fbfb8031SShannon Nelson 36fbfb8031SShannon Nelson for (i = 0, j = 0; i < IONIC_BARS_MAX; i++) { 37fbfb8031SShannon Nelson if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM)) 38fbfb8031SShannon Nelson continue; 39fbfb8031SShannon Nelson bars[j].len = pci_resource_len(pdev, i); 40fbfb8031SShannon Nelson 41fbfb8031SShannon Nelson /* only map the whole bar 0 */ 42fbfb8031SShannon Nelson if (j > 0) { 43fbfb8031SShannon Nelson bars[j].vaddr = NULL; 44fbfb8031SShannon Nelson } else { 45fbfb8031SShannon Nelson bars[j].vaddr = pci_iomap(pdev, i, bars[j].len); 46fbfb8031SShannon Nelson if (!bars[j].vaddr) { 47fbfb8031SShannon Nelson dev_err(dev, 48fbfb8031SShannon Nelson "Cannot memory-map BAR %d, aborting\n", 49fbfb8031SShannon Nelson i); 50fbfb8031SShannon Nelson return -ENODEV; 51fbfb8031SShannon Nelson } 52fbfb8031SShannon Nelson } 53fbfb8031SShannon Nelson 54fbfb8031SShannon Nelson bars[j].bus_addr = pci_resource_start(pdev, i); 55fbfb8031SShannon Nelson bars[j].res_index = i; 56fbfb8031SShannon Nelson ionic->num_bars++; 57fbfb8031SShannon Nelson j++; 58fbfb8031SShannon Nelson } 59fbfb8031SShannon Nelson 60fbfb8031SShannon Nelson return 0; 61fbfb8031SShannon Nelson } 62fbfb8031SShannon Nelson 63fbfb8031SShannon Nelson static void ionic_unmap_bars(struct ionic *ionic) 64fbfb8031SShannon Nelson { 65fbfb8031SShannon Nelson struct ionic_dev_bar *bars = ionic->bars; 66fbfb8031SShannon Nelson unsigned int i; 67fbfb8031SShannon Nelson 68fbfb8031SShannon Nelson for (i = 0; i < IONIC_BARS_MAX; i++) { 69fbfb8031SShannon Nelson if (bars[i].vaddr) { 70fbfb8031SShannon Nelson iounmap(bars[i].vaddr); 71fbfb8031SShannon Nelson bars[i].bus_addr = 0; 72fbfb8031SShannon Nelson bars[i].vaddr = NULL; 73fbfb8031SShannon Nelson bars[i].len = 0; 74fbfb8031SShannon Nelson } 75fbfb8031SShannon Nelson } 76fbfb8031SShannon Nelson } 77fbfb8031SShannon Nelson 78df69ba43SShannon Nelson static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 79df69ba43SShannon Nelson { 80df69ba43SShannon Nelson struct device *dev = &pdev->dev; 81df69ba43SShannon Nelson struct ionic *ionic; 82fbfb8031SShannon Nelson int err; 83df69ba43SShannon Nelson 84df69ba43SShannon Nelson ionic = ionic_devlink_alloc(dev); 85df69ba43SShannon Nelson if (!ionic) 86df69ba43SShannon Nelson return -ENOMEM; 87df69ba43SShannon Nelson 88df69ba43SShannon Nelson ionic->pdev = pdev; 89df69ba43SShannon Nelson ionic->dev = dev; 90df69ba43SShannon Nelson pci_set_drvdata(pdev, ionic); 91fbfb8031SShannon Nelson mutex_init(&ionic->dev_cmd_lock); 92fbfb8031SShannon Nelson 93fbfb8031SShannon Nelson /* Query system for DMA addressing limitation for the device. */ 94fbfb8031SShannon Nelson err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(IONIC_ADDR_LEN)); 95fbfb8031SShannon Nelson if (err) { 96fbfb8031SShannon Nelson dev_err(dev, "Unable to obtain 64-bit DMA for consistent allocations, aborting. err=%d\n", 97fbfb8031SShannon Nelson err); 98fbfb8031SShannon Nelson goto err_out_clear_drvdata; 99fbfb8031SShannon Nelson } 100fbfb8031SShannon Nelson 101fbfb8031SShannon Nelson ionic_debugfs_add_dev(ionic); 102fbfb8031SShannon Nelson 103fbfb8031SShannon Nelson /* Setup PCI device */ 104fbfb8031SShannon Nelson err = pci_enable_device_mem(pdev); 105fbfb8031SShannon Nelson if (err) { 106fbfb8031SShannon Nelson dev_err(dev, "Cannot enable PCI device: %d, aborting\n", err); 107fbfb8031SShannon Nelson goto err_out_debugfs_del_dev; 108fbfb8031SShannon Nelson } 109fbfb8031SShannon Nelson 110fbfb8031SShannon Nelson err = pci_request_regions(pdev, IONIC_DRV_NAME); 111fbfb8031SShannon Nelson if (err) { 112fbfb8031SShannon Nelson dev_err(dev, "Cannot request PCI regions: %d, aborting\n", err); 113fbfb8031SShannon Nelson goto err_out_pci_disable_device; 114fbfb8031SShannon Nelson } 115fbfb8031SShannon Nelson 116fbfb8031SShannon Nelson pci_set_master(pdev); 117fbfb8031SShannon Nelson 118fbfb8031SShannon Nelson err = ionic_map_bars(ionic); 119fbfb8031SShannon Nelson if (err) 120fbfb8031SShannon Nelson goto err_out_pci_clear_master; 121fbfb8031SShannon Nelson 122fbfb8031SShannon Nelson /* Configure the device */ 123fbfb8031SShannon Nelson err = ionic_setup(ionic); 124fbfb8031SShannon Nelson if (err) { 125fbfb8031SShannon Nelson dev_err(dev, "Cannot setup device: %d, aborting\n", err); 126fbfb8031SShannon Nelson goto err_out_unmap_bars; 127fbfb8031SShannon Nelson } 128fbfb8031SShannon Nelson 129fbfb8031SShannon Nelson err = ionic_identify(ionic); 130fbfb8031SShannon Nelson if (err) { 131fbfb8031SShannon Nelson dev_err(dev, "Cannot identify device: %d, aborting\n", err); 132fbfb8031SShannon Nelson goto err_out_teardown; 133fbfb8031SShannon Nelson } 134fbfb8031SShannon Nelson 135fbfb8031SShannon Nelson err = ionic_init(ionic); 136fbfb8031SShannon Nelson if (err) { 137fbfb8031SShannon Nelson dev_err(dev, "Cannot init device: %d, aborting\n", err); 138fbfb8031SShannon Nelson goto err_out_teardown; 139fbfb8031SShannon Nelson } 140fbfb8031SShannon Nelson 14104436595SShannon Nelson /* Configure the ports */ 14204436595SShannon Nelson err = ionic_port_identify(ionic); 14304436595SShannon Nelson if (err) { 14404436595SShannon Nelson dev_err(dev, "Cannot identify port: %d, aborting\n", err); 14504436595SShannon Nelson goto err_out_reset; 14604436595SShannon Nelson } 14704436595SShannon Nelson 14804436595SShannon Nelson err = ionic_port_init(ionic); 14904436595SShannon Nelson if (err) { 15004436595SShannon Nelson dev_err(dev, "Cannot init port: %d, aborting\n", err); 15104436595SShannon Nelson goto err_out_reset; 15204436595SShannon Nelson } 15304436595SShannon Nelson 154fbfb8031SShannon Nelson err = ionic_devlink_register(ionic); 155fbfb8031SShannon Nelson if (err) 156fbfb8031SShannon Nelson dev_err(dev, "Cannot register devlink: %d\n", err); 157df69ba43SShannon Nelson 158df69ba43SShannon Nelson return 0; 159fbfb8031SShannon Nelson 16004436595SShannon Nelson err_out_reset: 16104436595SShannon Nelson ionic_reset(ionic); 162fbfb8031SShannon Nelson err_out_teardown: 163fbfb8031SShannon Nelson ionic_dev_teardown(ionic); 164fbfb8031SShannon Nelson err_out_unmap_bars: 165fbfb8031SShannon Nelson ionic_unmap_bars(ionic); 166fbfb8031SShannon Nelson pci_release_regions(pdev); 167fbfb8031SShannon Nelson err_out_pci_clear_master: 168fbfb8031SShannon Nelson pci_clear_master(pdev); 169fbfb8031SShannon Nelson err_out_pci_disable_device: 170fbfb8031SShannon Nelson pci_disable_device(pdev); 171fbfb8031SShannon Nelson err_out_debugfs_del_dev: 172fbfb8031SShannon Nelson ionic_debugfs_del_dev(ionic); 173fbfb8031SShannon Nelson err_out_clear_drvdata: 174fbfb8031SShannon Nelson mutex_destroy(&ionic->dev_cmd_lock); 175fbfb8031SShannon Nelson ionic_devlink_free(ionic); 176fbfb8031SShannon Nelson 177fbfb8031SShannon Nelson return err; 178df69ba43SShannon Nelson } 179df69ba43SShannon Nelson 180df69ba43SShannon Nelson static void ionic_remove(struct pci_dev *pdev) 181df69ba43SShannon Nelson { 182df69ba43SShannon Nelson struct ionic *ionic = pci_get_drvdata(pdev); 183df69ba43SShannon Nelson 184fbfb8031SShannon Nelson if (!ionic) 185fbfb8031SShannon Nelson return; 186fbfb8031SShannon Nelson 187fbfb8031SShannon Nelson ionic_devlink_unregister(ionic); 18804436595SShannon Nelson ionic_port_reset(ionic); 189fbfb8031SShannon Nelson ionic_reset(ionic); 190fbfb8031SShannon Nelson ionic_dev_teardown(ionic); 191fbfb8031SShannon Nelson ionic_unmap_bars(ionic); 192fbfb8031SShannon Nelson pci_release_regions(pdev); 193fbfb8031SShannon Nelson pci_clear_master(pdev); 194fbfb8031SShannon Nelson pci_disable_device(pdev); 195fbfb8031SShannon Nelson ionic_debugfs_del_dev(ionic); 196fbfb8031SShannon Nelson mutex_destroy(&ionic->dev_cmd_lock); 197df69ba43SShannon Nelson ionic_devlink_free(ionic); 198df69ba43SShannon Nelson } 199df69ba43SShannon Nelson 200df69ba43SShannon Nelson static struct pci_driver ionic_driver = { 201df69ba43SShannon Nelson .name = IONIC_DRV_NAME, 202df69ba43SShannon Nelson .id_table = ionic_id_table, 203df69ba43SShannon Nelson .probe = ionic_probe, 204df69ba43SShannon Nelson .remove = ionic_remove, 205df69ba43SShannon Nelson }; 206df69ba43SShannon Nelson 207df69ba43SShannon Nelson int ionic_bus_register_driver(void) 208df69ba43SShannon Nelson { 209df69ba43SShannon Nelson return pci_register_driver(&ionic_driver); 210df69ba43SShannon Nelson } 211df69ba43SShannon Nelson 212df69ba43SShannon Nelson void ionic_bus_unregister_driver(void) 213df69ba43SShannon Nelson { 214df69ba43SShannon Nelson pci_unregister_driver(&ionic_driver); 215df69ba43SShannon Nelson } 216