175a6faf6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2ab3518acSMark Starovoytov /* Atlantic Network Driver 3ab3518acSMark Starovoytov * 4ab3518acSMark Starovoytov * Copyright (C) 2014-2019 aQuantia Corporation 5ab3518acSMark Starovoytov * Copyright (C) 2019-2020 Marvell International Ltd. 6a4d36e20SDavid VomLehn */ 7a4d36e20SDavid VomLehn 8a4d36e20SDavid VomLehn /* File aq_pci_func.c: Definition of PCI functions. */ 9a4d36e20SDavid VomLehn 105b97b0d1SIgor Russkikh #include <linux/interrupt.h> 115b97b0d1SIgor Russkikh #include <linux/module.h> 125b97b0d1SIgor Russkikh 1323ee07adSIgor Russkikh #include "aq_main.h" 14a4d36e20SDavid VomLehn #include "aq_nic.h" 15a4d36e20SDavid VomLehn #include "aq_vec.h" 16a4d36e20SDavid VomLehn #include "aq_hw.h" 1723ee07adSIgor Russkikh #include "aq_pci_func.h" 185b97b0d1SIgor Russkikh #include "hw_atl/hw_atl_a0.h" 195b97b0d1SIgor Russkikh #include "hw_atl/hw_atl_b0.h" 20b3f0c79cSIgor Russkikh #include "hw_atl2/hw_atl2.h" 218d0bcb01SDmitry Bogdanov #include "aq_filters.h" 224c013153SYana Esina #include "aq_drvinfo.h" 2362c1c2e6SDmitry Bogdanov #include "aq_macsec.h" 24a4d36e20SDavid VomLehn 255b97b0d1SIgor Russkikh static const struct pci_device_id aq_pci_tbl[] = { 26efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_0001), }, 27efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D100), }, 28efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D107), }, 29efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D108), }, 30efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D109), }, 31efe779b7SIgor Russkikh 32efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC100), }, 33efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC107), }, 34efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC108), }, 35efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC109), }, 36efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC111), }, 37efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC112), }, 38efe779b7SIgor Russkikh 39efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC100S), }, 40efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC107S), }, 41efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC108S), }, 42efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC109S), }, 43efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC111S), }, 44efe779b7SIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC112S), }, 45efe779b7SIgor Russkikh 46b3f0c79cSIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113DEV), }, 47b3f0c79cSIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113CS), }, 48b3f0c79cSIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC114CS), }, 49b3f0c79cSIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113), }, 50b3f0c79cSIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113C), }, 51b3f0c79cSIgor Russkikh { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC115C), }, 52413d5e09SNikita Danilov { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113CA), }, 53413d5e09SNikita Danilov { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC116C), }, 54b3f0c79cSIgor Russkikh 555b97b0d1SIgor Russkikh {} 565b97b0d1SIgor Russkikh }; 575b97b0d1SIgor Russkikh 58e8a22b5fSWei Yongjun static const struct aq_board_revision_s hw_atl_boards[] = { 594948293fSIgor Russkikh { AQ_DEVICE_ID_0001, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc107, }, 604948293fSIgor Russkikh { AQ_DEVICE_ID_D100, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc100, }, 614948293fSIgor Russkikh { AQ_DEVICE_ID_D107, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc107, }, 624948293fSIgor Russkikh { AQ_DEVICE_ID_D108, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc108, }, 634948293fSIgor Russkikh { AQ_DEVICE_ID_D109, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc109, }, 644948293fSIgor Russkikh 654948293fSIgor Russkikh { AQ_DEVICE_ID_0001, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc107, }, 664948293fSIgor Russkikh { AQ_DEVICE_ID_D100, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc100, }, 674948293fSIgor Russkikh { AQ_DEVICE_ID_D107, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc107, }, 684948293fSIgor Russkikh { AQ_DEVICE_ID_D108, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc108, }, 694948293fSIgor Russkikh { AQ_DEVICE_ID_D109, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc109, }, 704948293fSIgor Russkikh 716de556c3SRichard Clark { AQ_DEVICE_ID_AQC100, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc100, }, 724948293fSIgor Russkikh { AQ_DEVICE_ID_AQC107, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107, }, 734948293fSIgor Russkikh { AQ_DEVICE_ID_AQC108, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc108, }, 744948293fSIgor Russkikh { AQ_DEVICE_ID_AQC109, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc109, }, 754948293fSIgor Russkikh { AQ_DEVICE_ID_AQC111, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc111, }, 764948293fSIgor Russkikh { AQ_DEVICE_ID_AQC112, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc112, }, 774948293fSIgor Russkikh 784948293fSIgor Russkikh { AQ_DEVICE_ID_AQC100S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc100s, }, 794948293fSIgor Russkikh { AQ_DEVICE_ID_AQC107S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107s, }, 804948293fSIgor Russkikh { AQ_DEVICE_ID_AQC108S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc108s, }, 814948293fSIgor Russkikh { AQ_DEVICE_ID_AQC109S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc109s, }, 824948293fSIgor Russkikh { AQ_DEVICE_ID_AQC111S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc111s, }, 834948293fSIgor Russkikh { AQ_DEVICE_ID_AQC112S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc112s, }, 84b3f0c79cSIgor Russkikh 85b3f0c79cSIgor Russkikh { AQ_DEVICE_ID_AQC113DEV, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, 86b3f0c79cSIgor Russkikh { AQ_DEVICE_ID_AQC113, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, 87b3f0c79cSIgor Russkikh { AQ_DEVICE_ID_AQC113CS, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, 88b3f0c79cSIgor Russkikh { AQ_DEVICE_ID_AQC114CS, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, 89b3f0c79cSIgor Russkikh { AQ_DEVICE_ID_AQC113C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, 90413d5e09SNikita Danilov { AQ_DEVICE_ID_AQC115C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc115c, }, 91413d5e09SNikita Danilov { AQ_DEVICE_ID_AQC113CA, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, 92413d5e09SNikita Danilov { AQ_DEVICE_ID_AQC116C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc116c, }, 93413d5e09SNikita Danilov 944948293fSIgor Russkikh }; 954948293fSIgor Russkikh 965b97b0d1SIgor Russkikh MODULE_DEVICE_TABLE(pci, aq_pci_tbl); 975b97b0d1SIgor Russkikh 984948293fSIgor Russkikh static int aq_pci_probe_get_hw_by_id(struct pci_dev *pdev, 994948293fSIgor Russkikh const struct aq_hw_ops **ops, 1004948293fSIgor Russkikh const struct aq_hw_caps_s **caps) 1015b97b0d1SIgor Russkikh { 102a26b0b53SColin Ian King int i; 1035b97b0d1SIgor Russkikh 1044948293fSIgor Russkikh if (pdev->vendor != PCI_VENDOR_ID_AQUANTIA) 1054948293fSIgor Russkikh return -EINVAL; 1065b97b0d1SIgor Russkikh 1074948293fSIgor Russkikh for (i = 0; i < ARRAY_SIZE(hw_atl_boards); i++) { 1084948293fSIgor Russkikh if (hw_atl_boards[i].devid == pdev->device && 1094948293fSIgor Russkikh (hw_atl_boards[i].revision == AQ_HWREV_ANY || 1104948293fSIgor Russkikh hw_atl_boards[i].revision == pdev->revision)) { 1114948293fSIgor Russkikh *ops = hw_atl_boards[i].ops; 1124948293fSIgor Russkikh *caps = hw_atl_boards[i].caps; 1134948293fSIgor Russkikh break; 1144948293fSIgor Russkikh } 1154948293fSIgor Russkikh } 1164948293fSIgor Russkikh 1174948293fSIgor Russkikh if (i == ARRAY_SIZE(hw_atl_boards)) 1184948293fSIgor Russkikh return -EINVAL; 1194948293fSIgor Russkikh 1204948293fSIgor Russkikh return 0; 1215b97b0d1SIgor Russkikh } 1225b97b0d1SIgor Russkikh 123ab3518acSMark Starovoytov static int aq_pci_func_init(struct pci_dev *pdev) 124a4d36e20SDavid VomLehn { 125a26b0b53SColin Ian King int err; 126a4d36e20SDavid VomLehn 1273852e54eSChristophe JAILLET err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 1283852e54eSChristophe JAILLET if (err) 1293852e54eSChristophe JAILLET err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 130a4d36e20SDavid VomLehn if (err) { 131a4d36e20SDavid VomLehn err = -ENOSR; 132a4d36e20SDavid VomLehn goto err_exit; 133a4d36e20SDavid VomLehn } 134a4d36e20SDavid VomLehn 13523ee07adSIgor Russkikh err = pci_request_regions(pdev, AQ_CFG_DRV_NAME "_mmio"); 136a4d36e20SDavid VomLehn if (err < 0) 137a4d36e20SDavid VomLehn goto err_exit; 138a4d36e20SDavid VomLehn 13923ee07adSIgor Russkikh pci_set_master(pdev); 140a4d36e20SDavid VomLehn 14123ee07adSIgor Russkikh return 0; 142a4d36e20SDavid VomLehn 143a4d36e20SDavid VomLehn err_exit: 144a4d36e20SDavid VomLehn return err; 145a4d36e20SDavid VomLehn } 146a4d36e20SDavid VomLehn 14723ee07adSIgor Russkikh int aq_pci_func_alloc_irq(struct aq_nic_s *self, unsigned int i, 1484c83f170SIgor Russkikh char *name, irq_handler_t irq_handler, 1494c83f170SIgor Russkikh void *irq_arg, cpumask_t *affinity_mask) 150a4d36e20SDavid VomLehn { 15136a4a50fSChristoph Hellwig struct pci_dev *pdev = self->pdev; 152a26b0b53SColin Ian King int err; 153a4d36e20SDavid VomLehn 15436a4a50fSChristoph Hellwig if (pdev->msix_enabled || pdev->msi_enabled) 1554c83f170SIgor Russkikh err = request_irq(pci_irq_vector(pdev, i), irq_handler, 0, 1564c83f170SIgor Russkikh name, irq_arg); 15736a4a50fSChristoph Hellwig else 15836a4a50fSChristoph Hellwig err = request_irq(pci_irq_vector(pdev, i), aq_vec_isr_legacy, 1594c83f170SIgor Russkikh IRQF_SHARED, name, irq_arg); 160a4d36e20SDavid VomLehn 161a4d36e20SDavid VomLehn if (err >= 0) { 162a4d36e20SDavid VomLehn self->msix_entry_mask |= (1 << i); 163a4d36e20SDavid VomLehn 1644c83f170SIgor Russkikh if (pdev->msix_enabled && affinity_mask) 16536a4a50fSChristoph Hellwig irq_set_affinity_hint(pci_irq_vector(pdev, i), 166a4d36e20SDavid VomLehn affinity_mask); 167a4d36e20SDavid VomLehn } 1684c83f170SIgor Russkikh 169a4d36e20SDavid VomLehn return err; 170a4d36e20SDavid VomLehn } 171a4d36e20SDavid VomLehn 17223ee07adSIgor Russkikh void aq_pci_func_free_irqs(struct aq_nic_s *self) 173a4d36e20SDavid VomLehn { 17436a4a50fSChristoph Hellwig struct pci_dev *pdev = self->pdev; 175a26b0b53SColin Ian King unsigned int i; 1764c83f170SIgor Russkikh void *irq_data; 177a4d36e20SDavid VomLehn 178a4d36e20SDavid VomLehn for (i = 32U; i--;) { 179a4d36e20SDavid VomLehn if (!((1U << i) & self->msix_entry_mask)) 180a4d36e20SDavid VomLehn continue; 1814c83f170SIgor Russkikh if (self->aq_nic_cfg.link_irq_vec && 1824c83f170SIgor Russkikh i == self->aq_nic_cfg.link_irq_vec) 1834c83f170SIgor Russkikh irq_data = self; 1844c83f170SIgor Russkikh else if (i < AQ_CFG_VECS_MAX) 1854c83f170SIgor Russkikh irq_data = self->aq_vec[i]; 1864c83f170SIgor Russkikh else 18713b7997aSNikita Danilov continue; 188a4d36e20SDavid VomLehn 18936a4a50fSChristoph Hellwig if (pdev->msix_enabled) 19036a4a50fSChristoph Hellwig irq_set_affinity_hint(pci_irq_vector(pdev, i), NULL); 1914c83f170SIgor Russkikh free_irq(pci_irq_vector(pdev, i), irq_data); 192a4d36e20SDavid VomLehn self->msix_entry_mask &= ~(1U << i); 193a4d36e20SDavid VomLehn } 194a4d36e20SDavid VomLehn } 195a4d36e20SDavid VomLehn 19623ee07adSIgor Russkikh unsigned int aq_pci_func_get_irq_type(struct aq_nic_s *self) 197a4d36e20SDavid VomLehn { 19836a4a50fSChristoph Hellwig if (self->pdev->msix_enabled) 19936a4a50fSChristoph Hellwig return AQ_HW_IRQ_MSIX; 20036a4a50fSChristoph Hellwig if (self->pdev->msi_enabled) 20118eac376SIgor Russkikh return AQ_HW_IRQ_MSI; 2027b0c342fSNikita Danilov 203*ff9b5e14SDamien Le Moal return AQ_HW_IRQ_INTX; 204a4d36e20SDavid VomLehn } 205a4d36e20SDavid VomLehn 20623ee07adSIgor Russkikh static void aq_pci_free_irq_vectors(struct aq_nic_s *self) 207a4d36e20SDavid VomLehn { 20836a4a50fSChristoph Hellwig pci_free_irq_vectors(self->pdev); 209a4d36e20SDavid VomLehn } 2105b97b0d1SIgor Russkikh 2115b97b0d1SIgor Russkikh static int aq_pci_probe(struct pci_dev *pdev, 2125b97b0d1SIgor Russkikh const struct pci_device_id *pci_id) 2135b97b0d1SIgor Russkikh { 21423ee07adSIgor Russkikh struct net_device *ndev; 21523ee07adSIgor Russkikh resource_size_t mmio_pa; 2167b0c342fSNikita Danilov struct aq_nic_s *self; 21723ee07adSIgor Russkikh u32 numvecs; 2187b0c342fSNikita Danilov u32 bar; 2197b0c342fSNikita Danilov int err; 2205b97b0d1SIgor Russkikh 2215b97b0d1SIgor Russkikh err = pci_enable_device(pdev); 22223ee07adSIgor Russkikh if (err) 22323ee07adSIgor Russkikh return err; 2245b97b0d1SIgor Russkikh 22523ee07adSIgor Russkikh err = aq_pci_func_init(pdev); 22623ee07adSIgor Russkikh if (err) 22723ee07adSIgor Russkikh goto err_pci_func; 22823ee07adSIgor Russkikh 22923ee07adSIgor Russkikh ndev = aq_ndev_alloc(); 230f03e4f8aSWei Yongjun if (!ndev) { 231f03e4f8aSWei Yongjun err = -ENOMEM; 23223ee07adSIgor Russkikh goto err_ndev; 233f03e4f8aSWei Yongjun } 23423ee07adSIgor Russkikh 23523ee07adSIgor Russkikh self = netdev_priv(ndev); 23623ee07adSIgor Russkikh self->pdev = pdev; 23723ee07adSIgor Russkikh SET_NETDEV_DEV(ndev, &pdev->dev); 23823ee07adSIgor Russkikh pci_set_drvdata(pdev, self); 23923ee07adSIgor Russkikh 240f5dce08aSNikita Danilov mutex_init(&self->fwreq_mutex); 241f5dce08aSNikita Danilov 24223ee07adSIgor Russkikh err = aq_pci_probe_get_hw_by_id(pdev, &self->aq_hw_ops, 24323ee07adSIgor Russkikh &aq_nic_get_cfg(self)->aq_hw_caps); 24423ee07adSIgor Russkikh if (err) 24523ee07adSIgor Russkikh goto err_ioremap; 24623ee07adSIgor Russkikh 24723ee07adSIgor Russkikh self->aq_hw = kzalloc(sizeof(*self->aq_hw), GFP_KERNEL); 248370c1052SDan Carpenter if (!self->aq_hw) { 249370c1052SDan Carpenter err = -ENOMEM; 250370c1052SDan Carpenter goto err_ioremap; 251370c1052SDan Carpenter } 25223ee07adSIgor Russkikh self->aq_hw->aq_nic_cfg = aq_nic_get_cfg(self); 253b3f0c79cSIgor Russkikh if (self->aq_hw->aq_nic_cfg->aq_hw_caps->priv_data_len) { 254b3f0c79cSIgor Russkikh int len = self->aq_hw->aq_nic_cfg->aq_hw_caps->priv_data_len; 255b3f0c79cSIgor Russkikh 256b3f0c79cSIgor Russkikh self->aq_hw->priv = kzalloc(len, GFP_KERNEL); 257b3f0c79cSIgor Russkikh if (!self->aq_hw->priv) { 258b3f0c79cSIgor Russkikh err = -ENOMEM; 259b3f0c79cSIgor Russkikh goto err_free_aq_hw; 260b3f0c79cSIgor Russkikh } 261b3f0c79cSIgor Russkikh } 26223ee07adSIgor Russkikh 26323ee07adSIgor Russkikh for (bar = 0; bar < 4; ++bar) { 26423ee07adSIgor Russkikh if (IORESOURCE_MEM & pci_resource_flags(pdev, bar)) { 26523ee07adSIgor Russkikh resource_size_t reg_sz; 26623ee07adSIgor Russkikh 26723ee07adSIgor Russkikh mmio_pa = pci_resource_start(pdev, bar); 26823ee07adSIgor Russkikh if (mmio_pa == 0U) { 26923ee07adSIgor Russkikh err = -EIO; 270b3f0c79cSIgor Russkikh goto err_free_aq_hw_priv; 2715b97b0d1SIgor Russkikh } 27223ee07adSIgor Russkikh 27323ee07adSIgor Russkikh reg_sz = pci_resource_len(pdev, bar); 27423ee07adSIgor Russkikh if ((reg_sz <= 24 /*ATL_REGS_SIZE*/)) { 27523ee07adSIgor Russkikh err = -EIO; 276b3f0c79cSIgor Russkikh goto err_free_aq_hw_priv; 27723ee07adSIgor Russkikh } 27823ee07adSIgor Russkikh 2794bdc0d67SChristoph Hellwig self->aq_hw->mmio = ioremap(mmio_pa, reg_sz); 28023ee07adSIgor Russkikh if (!self->aq_hw->mmio) { 28123ee07adSIgor Russkikh err = -EIO; 282b3f0c79cSIgor Russkikh goto err_free_aq_hw_priv; 28323ee07adSIgor Russkikh } 28423ee07adSIgor Russkikh break; 28523ee07adSIgor Russkikh } 28623ee07adSIgor Russkikh } 28723ee07adSIgor Russkikh 28823ee07adSIgor Russkikh if (bar == 4) { 28923ee07adSIgor Russkikh err = -EIO; 290b3f0c79cSIgor Russkikh goto err_free_aq_hw_priv; 29123ee07adSIgor Russkikh } 29223ee07adSIgor Russkikh 29323ee07adSIgor Russkikh numvecs = min((u8)AQ_CFG_VECS_DEF, 29423ee07adSIgor Russkikh aq_nic_get_cfg(self)->aq_hw_caps->msix_irqs); 29523ee07adSIgor Russkikh numvecs = min(numvecs, num_online_cpus()); 29604a18399SEgor Pomozov /* Request IRQ vector for PTP */ 29704a18399SEgor Pomozov numvecs += 1; 29804a18399SEgor Pomozov 2994c83f170SIgor Russkikh numvecs += AQ_HW_SERVICE_IRQS; 30023ee07adSIgor Russkikh /*enable interrupts */ 301*ff9b5e14SDamien Le Moal #if !AQ_CFG_FORCE_INTX 302*ff9b5e14SDamien Le Moal err = pci_alloc_irq_vectors(self->pdev, 1, numvecs, PCI_IRQ_ALL_TYPES); 30358d813afSColin Ian King if (err < 0) 30423ee07adSIgor Russkikh goto err_hwinit; 30558d813afSColin Ian King numvecs = err; 30623ee07adSIgor Russkikh #endif 307a09bd81bSIgor Russkikh self->irqvecs = numvecs; 30823ee07adSIgor Russkikh 30923ee07adSIgor Russkikh /* net device init */ 31023ee07adSIgor Russkikh aq_nic_cfg_start(self); 31123ee07adSIgor Russkikh 31223ee07adSIgor Russkikh aq_nic_ndev_init(self); 31323ee07adSIgor Russkikh 31423ee07adSIgor Russkikh err = aq_nic_ndev_register(self); 31523ee07adSIgor Russkikh if (err < 0) 31623ee07adSIgor Russkikh goto err_register; 31723ee07adSIgor Russkikh 3184c013153SYana Esina aq_drvinfo_init(ndev); 3194c013153SYana Esina 32023ee07adSIgor Russkikh return 0; 32123ee07adSIgor Russkikh 32223ee07adSIgor Russkikh err_register: 32323ee07adSIgor Russkikh aq_nic_free_vectors(self); 32423ee07adSIgor Russkikh aq_pci_free_irq_vectors(self); 32523ee07adSIgor Russkikh err_hwinit: 32623ee07adSIgor Russkikh iounmap(self->aq_hw->mmio); 327b3f0c79cSIgor Russkikh err_free_aq_hw_priv: 328b3f0c79cSIgor Russkikh kfree(self->aq_hw->priv); 329370c1052SDan Carpenter err_free_aq_hw: 330370c1052SDan Carpenter kfree(self->aq_hw); 33123ee07adSIgor Russkikh err_ioremap: 33223ee07adSIgor Russkikh free_netdev(ndev); 33323ee07adSIgor Russkikh err_ndev: 334a09bd81bSIgor Russkikh pci_release_regions(pdev); 335a09bd81bSIgor Russkikh err_pci_func: 33623ee07adSIgor Russkikh pci_disable_device(pdev); 3377b0c342fSNikita Danilov 3385b97b0d1SIgor Russkikh return err; 3395b97b0d1SIgor Russkikh } 3405b97b0d1SIgor Russkikh 3415b97b0d1SIgor Russkikh static void aq_pci_remove(struct pci_dev *pdev) 3425b97b0d1SIgor Russkikh { 34323ee07adSIgor Russkikh struct aq_nic_s *self = pci_get_drvdata(pdev); 3445b97b0d1SIgor Russkikh 34523ee07adSIgor Russkikh if (self->ndev) { 3468d0bcb01SDmitry Bogdanov aq_clear_rxnfc_all_rules(self); 34723ee07adSIgor Russkikh if (self->ndev->reg_state == NETREG_REGISTERED) 34823ee07adSIgor Russkikh unregister_netdev(self->ndev); 34962c1c2e6SDmitry Bogdanov 35062c1c2e6SDmitry Bogdanov #if IS_ENABLED(CONFIG_MACSEC) 35162c1c2e6SDmitry Bogdanov aq_macsec_free(self); 35262c1c2e6SDmitry Bogdanov #endif 35323ee07adSIgor Russkikh aq_nic_free_vectors(self); 35423ee07adSIgor Russkikh aq_pci_free_irq_vectors(self); 35523ee07adSIgor Russkikh iounmap(self->aq_hw->mmio); 356b3f0c79cSIgor Russkikh kfree(self->aq_hw->priv); 35723ee07adSIgor Russkikh kfree(self->aq_hw); 35823ee07adSIgor Russkikh pci_release_regions(pdev); 35923ee07adSIgor Russkikh free_netdev(self->ndev); 36023ee07adSIgor Russkikh } 36123ee07adSIgor Russkikh 36223ee07adSIgor Russkikh pci_disable_device(pdev); 3635b97b0d1SIgor Russkikh } 3645b97b0d1SIgor Russkikh 36590869ddfSIgor Russkikh static void aq_pci_shutdown(struct pci_dev *pdev) 36690869ddfSIgor Russkikh { 36790869ddfSIgor Russkikh struct aq_nic_s *self = pci_get_drvdata(pdev); 36890869ddfSIgor Russkikh 36990869ddfSIgor Russkikh aq_nic_shutdown(self); 37090869ddfSIgor Russkikh 37190869ddfSIgor Russkikh pci_disable_device(pdev); 37290869ddfSIgor Russkikh 37390869ddfSIgor Russkikh if (system_state == SYSTEM_POWER_OFF) { 37490869ddfSIgor Russkikh pci_wake_from_d3(pdev, false); 37590869ddfSIgor Russkikh pci_set_power_state(pdev, PCI_D3hot); 37690869ddfSIgor Russkikh } 37790869ddfSIgor Russkikh } 37890869ddfSIgor Russkikh 3794f163bf8STom Rix #ifdef CONFIG_PM 3800f332507SChia-Lin Kao (AceLan) static int aq_suspend_common(struct device *dev) 3815b97b0d1SIgor Russkikh { 3828aaa112aSNikita Danilov struct aq_nic_s *nic = pci_get_drvdata(to_pci_dev(dev)); 3835b97b0d1SIgor Russkikh 3848aaa112aSNikita Danilov rtnl_lock(); 3858aaa112aSNikita Danilov 3868aaa112aSNikita Danilov nic->power_state = AQ_HW_POWER_STATE_D3; 3878aaa112aSNikita Danilov netif_device_detach(nic->ndev); 3888aaa112aSNikita Danilov netif_tx_stop_all_queues(nic->ndev); 3898aaa112aSNikita Danilov 39052a22f4dSPavel Belous if (netif_running(nic->ndev)) 3918aaa112aSNikita Danilov aq_nic_stop(nic); 3928aaa112aSNikita Danilov 3938aaa112aSNikita Danilov aq_nic_deinit(nic, !nic->aq_hw->aq_nic_cfg->wol); 3948aaa112aSNikita Danilov aq_nic_set_power(nic); 3955b97b0d1SIgor Russkikh 3968aaa112aSNikita Danilov rtnl_unlock(); 3975b97b0d1SIgor Russkikh 3988aaa112aSNikita Danilov return 0; 3995b97b0d1SIgor Russkikh } 4005b97b0d1SIgor Russkikh 4010f332507SChia-Lin Kao (AceLan) static int atl_resume_common(struct device *dev) 4028aaa112aSNikita Danilov { 4038aaa112aSNikita Danilov struct pci_dev *pdev = to_pci_dev(dev); 4048aaa112aSNikita Danilov struct aq_nic_s *nic; 40552a22f4dSPavel Belous int ret = 0; 4068aaa112aSNikita Danilov 4078aaa112aSNikita Danilov nic = pci_get_drvdata(pdev); 4088aaa112aSNikita Danilov 4098aaa112aSNikita Danilov rtnl_lock(); 4108aaa112aSNikita Danilov 4118aaa112aSNikita Danilov pci_set_power_state(pdev, PCI_D0); 4128aaa112aSNikita Danilov pci_restore_state(pdev); 4138aaa112aSNikita Danilov 41452a22f4dSPavel Belous if (netif_running(nic->ndev)) { 4154d88c339SSudarsana Reddy Kalluru ret = aq_nic_init(nic); 4164d88c339SSudarsana Reddy Kalluru if (ret) 4174d88c339SSudarsana Reddy Kalluru goto err_exit; 4184d88c339SSudarsana Reddy Kalluru 4198aaa112aSNikita Danilov ret = aq_nic_start(nic); 4208aaa112aSNikita Danilov if (ret) 4218aaa112aSNikita Danilov goto err_exit; 42252a22f4dSPavel Belous } 4238aaa112aSNikita Danilov 4248aaa112aSNikita Danilov netif_device_attach(nic->ndev); 4258aaa112aSNikita Danilov netif_tx_start_all_queues(nic->ndev); 4268aaa112aSNikita Danilov 4278aaa112aSNikita Danilov err_exit: 4288ce84271SDmitry Bezrukov if (ret < 0) 4298ce84271SDmitry Bezrukov aq_nic_deinit(nic, true); 4308ce84271SDmitry Bezrukov 4318aaa112aSNikita Danilov rtnl_unlock(); 4328aaa112aSNikita Danilov 4338aaa112aSNikita Danilov return ret; 4348aaa112aSNikita Danilov } 4358aaa112aSNikita Danilov 4368aaa112aSNikita Danilov static int aq_pm_freeze(struct device *dev) 4378aaa112aSNikita Danilov { 4380f332507SChia-Lin Kao (AceLan) return aq_suspend_common(dev); 4398aaa112aSNikita Danilov } 4408aaa112aSNikita Danilov 4418aaa112aSNikita Danilov static int aq_pm_suspend_poweroff(struct device *dev) 4428aaa112aSNikita Danilov { 4430f332507SChia-Lin Kao (AceLan) return aq_suspend_common(dev); 4448aaa112aSNikita Danilov } 4458aaa112aSNikita Danilov 4468aaa112aSNikita Danilov static int aq_pm_thaw(struct device *dev) 4478aaa112aSNikita Danilov { 4480f332507SChia-Lin Kao (AceLan) return atl_resume_common(dev); 4498aaa112aSNikita Danilov } 4508aaa112aSNikita Danilov 4518aaa112aSNikita Danilov static int aq_pm_resume_restore(struct device *dev) 4528aaa112aSNikita Danilov { 4530f332507SChia-Lin Kao (AceLan) return atl_resume_common(dev); 4548aaa112aSNikita Danilov } 4558aaa112aSNikita Danilov 4560ee0bbb0Szhengbin static const struct dev_pm_ops aq_pm_ops = { 4578aaa112aSNikita Danilov .suspend = aq_pm_suspend_poweroff, 4588aaa112aSNikita Danilov .poweroff = aq_pm_suspend_poweroff, 4598aaa112aSNikita Danilov .freeze = aq_pm_freeze, 4608aaa112aSNikita Danilov .resume = aq_pm_resume_restore, 4618aaa112aSNikita Danilov .restore = aq_pm_resume_restore, 4628aaa112aSNikita Danilov .thaw = aq_pm_thaw, 4638aaa112aSNikita Danilov }; 4644f163bf8STom Rix #endif 4658aaa112aSNikita Danilov 4665b97b0d1SIgor Russkikh static struct pci_driver aq_pci_ops = { 4675b97b0d1SIgor Russkikh .name = AQ_CFG_DRV_NAME, 4685b97b0d1SIgor Russkikh .id_table = aq_pci_tbl, 4695b97b0d1SIgor Russkikh .probe = aq_pci_probe, 4705b97b0d1SIgor Russkikh .remove = aq_pci_remove, 47190869ddfSIgor Russkikh .shutdown = aq_pci_shutdown, 4728aaa112aSNikita Danilov #ifdef CONFIG_PM 4738aaa112aSNikita Danilov .driver.pm = &aq_pm_ops, 4748aaa112aSNikita Danilov #endif 4755b97b0d1SIgor Russkikh }; 4765b97b0d1SIgor Russkikh 47758608082SNikita Danilov int aq_pci_func_register_driver(void) 47858608082SNikita Danilov { 47958608082SNikita Danilov return pci_register_driver(&aq_pci_ops); 48058608082SNikita Danilov } 48158608082SNikita Danilov 48258608082SNikita Danilov void aq_pci_func_unregister_driver(void) 48358608082SNikita Danilov { 48458608082SNikita Danilov pci_unregister_driver(&aq_pci_ops); 48558608082SNikita Danilov } 48658608082SNikita Danilov 487