1*a0008a36SMengyuan Lou // SPDX-License-Identifier: GPL-2.0 2*a0008a36SMengyuan Lou /* Copyright (c) 2015 - 2025 Beijing WangXun Technology Co., Ltd. */ 3*a0008a36SMengyuan Lou 4*a0008a36SMengyuan Lou #include <linux/types.h> 5*a0008a36SMengyuan Lou #include <linux/module.h> 6*a0008a36SMengyuan Lou #include <linux/pci.h> 7*a0008a36SMengyuan Lou #include <linux/netdevice.h> 8*a0008a36SMengyuan Lou #include <linux/string.h> 9*a0008a36SMengyuan Lou #include <linux/etherdevice.h> 10*a0008a36SMengyuan Lou 11*a0008a36SMengyuan Lou #include "../libwx/wx_type.h" 12*a0008a36SMengyuan Lou #include "../libwx/wx_vf_common.h" 13*a0008a36SMengyuan Lou #include "ngbevf_type.h" 14*a0008a36SMengyuan Lou 15*a0008a36SMengyuan Lou /* ngbevf_pci_tbl - PCI Device ID Table 16*a0008a36SMengyuan Lou * 17*a0008a36SMengyuan Lou * Wildcard entries (PCI_ANY_ID) should come last 18*a0008a36SMengyuan Lou * Last entry must be all 0s 19*a0008a36SMengyuan Lou * 20*a0008a36SMengyuan Lou * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, 21*a0008a36SMengyuan Lou * Class, Class Mask, private data (not used) } 22*a0008a36SMengyuan Lou */ 23*a0008a36SMengyuan Lou static const struct pci_device_id ngbevf_pci_tbl[] = { 24*a0008a36SMengyuan Lou { PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860AL_W), 0}, 25*a0008a36SMengyuan Lou { PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860A2), 0}, 26*a0008a36SMengyuan Lou { PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860A2S), 0}, 27*a0008a36SMengyuan Lou { PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860A4), 0}, 28*a0008a36SMengyuan Lou { PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860A4S), 0}, 29*a0008a36SMengyuan Lou { PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860AL2), 0}, 30*a0008a36SMengyuan Lou { PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860AL2S), 0}, 31*a0008a36SMengyuan Lou { PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860AL4), 0}, 32*a0008a36SMengyuan Lou { PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860AL4S), 0}, 33*a0008a36SMengyuan Lou { PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860NCSI), 0}, 34*a0008a36SMengyuan Lou { PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860A1), 0}, 35*a0008a36SMengyuan Lou { PCI_VDEVICE(WANGXUN, NGBEVF_DEV_ID_EM_WX1860AL1), 0}, 36*a0008a36SMengyuan Lou /* required last entry */ 37*a0008a36SMengyuan Lou { .device = 0 } 38*a0008a36SMengyuan Lou }; 39*a0008a36SMengyuan Lou 40*a0008a36SMengyuan Lou /** 41*a0008a36SMengyuan Lou * ngbevf_probe - Device Initialization Routine 42*a0008a36SMengyuan Lou * @pdev: PCI device information struct 43*a0008a36SMengyuan Lou * @ent: entry in ngbevf_pci_tbl 44*a0008a36SMengyuan Lou * 45*a0008a36SMengyuan Lou * Return: return 0 on success, negative on failure 46*a0008a36SMengyuan Lou * 47*a0008a36SMengyuan Lou * ngbevf_probe initializes an adapter identified by a pci_dev structure. 48*a0008a36SMengyuan Lou * The OS initialization, configuring of the adapter private structure, 49*a0008a36SMengyuan Lou * and a hardware reset occur. 50*a0008a36SMengyuan Lou **/ 51*a0008a36SMengyuan Lou static int ngbevf_probe(struct pci_dev *pdev, 52*a0008a36SMengyuan Lou const struct pci_device_id __always_unused *ent) 53*a0008a36SMengyuan Lou { 54*a0008a36SMengyuan Lou struct net_device *netdev; 55*a0008a36SMengyuan Lou struct wx *wx = NULL; 56*a0008a36SMengyuan Lou int err; 57*a0008a36SMengyuan Lou 58*a0008a36SMengyuan Lou err = pci_enable_device_mem(pdev); 59*a0008a36SMengyuan Lou if (err) 60*a0008a36SMengyuan Lou return err; 61*a0008a36SMengyuan Lou 62*a0008a36SMengyuan Lou err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 63*a0008a36SMengyuan Lou if (err) { 64*a0008a36SMengyuan Lou dev_err(&pdev->dev, 65*a0008a36SMengyuan Lou "No usable DMA configuration, aborting\n"); 66*a0008a36SMengyuan Lou goto err_pci_disable_dev; 67*a0008a36SMengyuan Lou } 68*a0008a36SMengyuan Lou 69*a0008a36SMengyuan Lou err = pci_request_selected_regions(pdev, 70*a0008a36SMengyuan Lou pci_select_bars(pdev, IORESOURCE_MEM), 71*a0008a36SMengyuan Lou dev_driver_string(&pdev->dev)); 72*a0008a36SMengyuan Lou if (err) { 73*a0008a36SMengyuan Lou dev_err(&pdev->dev, 74*a0008a36SMengyuan Lou "pci_request_selected_regions failed 0x%x\n", err); 75*a0008a36SMengyuan Lou goto err_pci_disable_dev; 76*a0008a36SMengyuan Lou } 77*a0008a36SMengyuan Lou 78*a0008a36SMengyuan Lou pci_set_master(pdev); 79*a0008a36SMengyuan Lou 80*a0008a36SMengyuan Lou netdev = devm_alloc_etherdev_mqs(&pdev->dev, 81*a0008a36SMengyuan Lou sizeof(struct wx), 82*a0008a36SMengyuan Lou NGBEVF_MAX_TX_QUEUES, 83*a0008a36SMengyuan Lou NGBEVF_MAX_RX_QUEUES); 84*a0008a36SMengyuan Lou if (!netdev) { 85*a0008a36SMengyuan Lou err = -ENOMEM; 86*a0008a36SMengyuan Lou goto err_pci_release_regions; 87*a0008a36SMengyuan Lou } 88*a0008a36SMengyuan Lou 89*a0008a36SMengyuan Lou SET_NETDEV_DEV(netdev, &pdev->dev); 90*a0008a36SMengyuan Lou 91*a0008a36SMengyuan Lou wx = netdev_priv(netdev); 92*a0008a36SMengyuan Lou wx->netdev = netdev; 93*a0008a36SMengyuan Lou wx->pdev = pdev; 94*a0008a36SMengyuan Lou 95*a0008a36SMengyuan Lou wx->msg_enable = netif_msg_init(-1, NETIF_MSG_DRV | 96*a0008a36SMengyuan Lou NETIF_MSG_PROBE | NETIF_MSG_LINK); 97*a0008a36SMengyuan Lou wx->hw_addr = devm_ioremap(&pdev->dev, 98*a0008a36SMengyuan Lou pci_resource_start(pdev, 0), 99*a0008a36SMengyuan Lou pci_resource_len(pdev, 0)); 100*a0008a36SMengyuan Lou if (!wx->hw_addr) { 101*a0008a36SMengyuan Lou err = -EIO; 102*a0008a36SMengyuan Lou goto err_pci_release_regions; 103*a0008a36SMengyuan Lou } 104*a0008a36SMengyuan Lou 105*a0008a36SMengyuan Lou netdev->features |= NETIF_F_HIGHDMA; 106*a0008a36SMengyuan Lou pci_set_drvdata(pdev, wx); 107*a0008a36SMengyuan Lou 108*a0008a36SMengyuan Lou return 0; 109*a0008a36SMengyuan Lou 110*a0008a36SMengyuan Lou err_pci_release_regions: 111*a0008a36SMengyuan Lou pci_release_selected_regions(pdev, 112*a0008a36SMengyuan Lou pci_select_bars(pdev, IORESOURCE_MEM)); 113*a0008a36SMengyuan Lou err_pci_disable_dev: 114*a0008a36SMengyuan Lou pci_disable_device(pdev); 115*a0008a36SMengyuan Lou return err; 116*a0008a36SMengyuan Lou } 117*a0008a36SMengyuan Lou 118*a0008a36SMengyuan Lou /** 119*a0008a36SMengyuan Lou * ngbevf_remove - Device Removal Routine 120*a0008a36SMengyuan Lou * @pdev: PCI device information struct 121*a0008a36SMengyuan Lou * 122*a0008a36SMengyuan Lou * ngbevf_remove is called by the PCI subsystem to alert the driver 123*a0008a36SMengyuan Lou * that it should release a PCI device. The could be caused by a 124*a0008a36SMengyuan Lou * Hot-Plug event, or because the driver is going to be removed from 125*a0008a36SMengyuan Lou * memory. 126*a0008a36SMengyuan Lou **/ 127*a0008a36SMengyuan Lou static void ngbevf_remove(struct pci_dev *pdev) 128*a0008a36SMengyuan Lou { 129*a0008a36SMengyuan Lou wxvf_remove(pdev); 130*a0008a36SMengyuan Lou } 131*a0008a36SMengyuan Lou 132*a0008a36SMengyuan Lou static DEFINE_SIMPLE_DEV_PM_OPS(ngbevf_pm_ops, wxvf_suspend, wxvf_resume); 133*a0008a36SMengyuan Lou 134*a0008a36SMengyuan Lou static struct pci_driver ngbevf_driver = { 135*a0008a36SMengyuan Lou .name = KBUILD_MODNAME, 136*a0008a36SMengyuan Lou .id_table = ngbevf_pci_tbl, 137*a0008a36SMengyuan Lou .probe = ngbevf_probe, 138*a0008a36SMengyuan Lou .remove = ngbevf_remove, 139*a0008a36SMengyuan Lou .shutdown = wxvf_shutdown, 140*a0008a36SMengyuan Lou /* Power Management Hooks */ 141*a0008a36SMengyuan Lou .driver.pm = pm_sleep_ptr(&ngbevf_pm_ops) 142*a0008a36SMengyuan Lou }; 143*a0008a36SMengyuan Lou 144*a0008a36SMengyuan Lou module_pci_driver(ngbevf_driver); 145*a0008a36SMengyuan Lou 146*a0008a36SMengyuan Lou MODULE_DEVICE_TABLE(pci, ngbevf_pci_tbl); 147*a0008a36SMengyuan Lou MODULE_AUTHOR("Beijing WangXun Technology Co., Ltd, <software@trustnetic.com>"); 148*a0008a36SMengyuan Lou MODULE_DESCRIPTION("WangXun(R) Gigabit PCI Express Network Driver"); 149*a0008a36SMengyuan Lou MODULE_LICENSE("GPL"); 150