xref: /linux/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c (revision afeea2758b4f1210361ce2a91d8fa3e7df606ad2)
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