]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
UBUNTU: Ubuntu-4.15.0-96.97
[mirror_ubuntu-bionic-kernel.git] / drivers / net / ethernet / aquantia / atlantic / aq_pci_func.c
CommitLineData
a4d36e20
DV
1/*
2 * aQuantia Corporation Network Driver
3 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 */
9
10/* File aq_pci_func.c: Definition of PCI functions. */
11
32b96adf
IR
12#include <linux/interrupt.h>
13#include <linux/module.h>
14
015e2f7c 15#include "aq_main.h"
a4d36e20
DV
16#include "aq_nic.h"
17#include "aq_vec.h"
18#include "aq_hw.h"
015e2f7c 19#include "aq_pci_func.h"
32b96adf
IR
20#include "hw_atl/hw_atl_a0.h"
21#include "hw_atl/hw_atl_b0.h"
a4d36e20 22
32b96adf 23static const struct pci_device_id aq_pci_tbl[] = {
c4d5815c
IR
24 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_0001), },
25 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D100), },
26 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D107), },
27 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D108), },
28 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D109), },
29
30 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC100), },
31 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC107), },
32 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC108), },
33 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC109), },
34 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC111), },
35 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC112), },
36
37 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC100S), },
38 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC107S), },
39 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC108S), },
40 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC109S), },
41 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC111S), },
42 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC112S), },
43
44 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC111E), },
45 { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC112E), },
46
32b96adf
IR
47 {}
48};
49
d67984d9
IR
50const struct aq_board_revision_s hw_atl_boards[] = {
51 { AQ_DEVICE_ID_0001, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc107, },
52 { AQ_DEVICE_ID_D100, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc100, },
53 { AQ_DEVICE_ID_D107, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc107, },
54 { AQ_DEVICE_ID_D108, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc108, },
55 { AQ_DEVICE_ID_D109, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc109, },
56
57 { AQ_DEVICE_ID_0001, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc107, },
58 { AQ_DEVICE_ID_D100, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc100, },
59 { AQ_DEVICE_ID_D107, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc107, },
60 { AQ_DEVICE_ID_D108, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc108, },
61 { AQ_DEVICE_ID_D109, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc109, },
62
63 { AQ_DEVICE_ID_AQC100, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107, },
64 { AQ_DEVICE_ID_AQC107, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107, },
65 { AQ_DEVICE_ID_AQC108, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc108, },
66 { AQ_DEVICE_ID_AQC109, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc109, },
67 { AQ_DEVICE_ID_AQC111, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc111, },
68 { AQ_DEVICE_ID_AQC112, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc112, },
69
70 { AQ_DEVICE_ID_AQC100S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc100s, },
71 { AQ_DEVICE_ID_AQC107S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107s, },
72 { AQ_DEVICE_ID_AQC108S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc108s, },
73 { AQ_DEVICE_ID_AQC109S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc109s, },
74 { AQ_DEVICE_ID_AQC111S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc111s, },
75 { AQ_DEVICE_ID_AQC112S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc112s, },
76
77 { AQ_DEVICE_ID_AQC111E, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc111e, },
78 { AQ_DEVICE_ID_AQC112E, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc112e, },
79};
80
32b96adf
IR
81MODULE_DEVICE_TABLE(pci, aq_pci_tbl);
82
d67984d9
IR
83static int aq_pci_probe_get_hw_by_id(struct pci_dev *pdev,
84 const struct aq_hw_ops **ops,
85 const struct aq_hw_caps_s **caps)
32b96adf 86{
d67984d9
IR
87 int i = 0;
88
89 if (pdev->vendor != PCI_VENDOR_ID_AQUANTIA)
90 return -EINVAL;
91
92 for (i = 0; i < ARRAY_SIZE(hw_atl_boards); i++) {
93 if (hw_atl_boards[i].devid == pdev->device &&
94 (hw_atl_boards[i].revision == AQ_HWREV_ANY ||
95 hw_atl_boards[i].revision == pdev->revision)) {
96 *ops = hw_atl_boards[i].ops;
97 *caps = hw_atl_boards[i].caps;
98 break;
99 }
100 }
32b96adf 101
d67984d9
IR
102 if (i == ARRAY_SIZE(hw_atl_boards))
103 return -EINVAL;
32b96adf 104
d67984d9 105 return 0;
32b96adf
IR
106}
107
015e2f7c 108int aq_pci_func_init(struct pci_dev *pdev)
a4d36e20
DV
109{
110 int err = 0;
a4d36e20 111
015e2f7c 112 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
a4d36e20 113 if (!err) {
015e2f7c
IR
114 err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
115
a4d36e20
DV
116 }
117 if (err) {
015e2f7c 118 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
a4d36e20 119 if (!err)
015e2f7c 120 err = pci_set_consistent_dma_mask(pdev,
a4d36e20 121 DMA_BIT_MASK(32));
a4d36e20
DV
122 }
123 if (err != 0) {
124 err = -ENOSR;
125 goto err_exit;
126 }
127
015e2f7c 128 err = pci_request_regions(pdev, AQ_CFG_DRV_NAME "_mmio");
a4d36e20
DV
129 if (err < 0)
130 goto err_exit;
131
015e2f7c 132 pci_set_master(pdev);
a4d36e20 133
015e2f7c 134 return 0;
a4d36e20
DV
135
136err_exit:
a4d36e20
DV
137 return err;
138}
139
015e2f7c 140int aq_pci_func_alloc_irq(struct aq_nic_s *self, unsigned int i,
a4d36e20
DV
141 char *name, void *aq_vec, cpumask_t *affinity_mask)
142{
36a4a50f 143 struct pci_dev *pdev = self->pdev;
a4d36e20
DV
144 int err = 0;
145
36a4a50f
CH
146 if (pdev->msix_enabled || pdev->msi_enabled)
147 err = request_irq(pci_irq_vector(pdev, i), aq_vec_isr, 0,
a4d36e20 148 name, aq_vec);
36a4a50f
CH
149 else
150 err = request_irq(pci_irq_vector(pdev, i), aq_vec_isr_legacy,
a4d36e20 151 IRQF_SHARED, name, aq_vec);
a4d36e20
DV
152
153 if (err >= 0) {
154 self->msix_entry_mask |= (1 << i);
155 self->aq_vec[i] = aq_vec;
156
36a4a50f
CH
157 if (pdev->msix_enabled)
158 irq_set_affinity_hint(pci_irq_vector(pdev, i),
a4d36e20
DV
159 affinity_mask);
160 }
a4d36e20
DV
161 return err;
162}
163
015e2f7c 164void aq_pci_func_free_irqs(struct aq_nic_s *self)
a4d36e20 165{
36a4a50f 166 struct pci_dev *pdev = self->pdev;
a4d36e20
DV
167 unsigned int i = 0U;
168
169 for (i = 32U; i--;) {
170 if (!((1U << i) & self->msix_entry_mask))
171 continue;
172
36a4a50f
CH
173 if (pdev->msix_enabled)
174 irq_set_affinity_hint(pci_irq_vector(pdev, i), NULL);
ecd05225 175 free_irq(pci_irq_vector(pdev, i), self->aq_vec[i]);
a4d36e20
DV
176 self->msix_entry_mask &= ~(1U << i);
177 }
178}
179
015e2f7c 180unsigned int aq_pci_func_get_irq_type(struct aq_nic_s *self)
a4d36e20 181{
36a4a50f
CH
182 if (self->pdev->msix_enabled)
183 return AQ_HW_IRQ_MSIX;
184 if (self->pdev->msi_enabled)
185 return AQ_HW_IRQ_MSIX;
186 return AQ_HW_IRQ_LEGACY;
a4d36e20
DV
187}
188
015e2f7c 189static void aq_pci_free_irq_vectors(struct aq_nic_s *self)
a4d36e20 190{
36a4a50f 191 pci_free_irq_vectors(self->pdev);
015e2f7c 192}
a4d36e20 193
015e2f7c
IR
194static int aq_pci_probe(struct pci_dev *pdev,
195 const struct pci_device_id *pci_id)
196{
197 struct aq_nic_s *self = NULL;
198 int err = 0;
199 struct net_device *ndev;
200 resource_size_t mmio_pa;
201 u32 bar;
202 u32 numvecs;
a4d36e20 203
015e2f7c
IR
204 err = pci_enable_device(pdev);
205 if (err)
206 return err;
a4d36e20 207
015e2f7c
IR
208 err = aq_pci_func_init(pdev);
209 if (err)
210 goto err_pci_func;
a4d36e20 211
015e2f7c
IR
212 ndev = aq_ndev_alloc();
213 if (!ndev)
214 goto err_ndev;
a4d36e20 215
015e2f7c
IR
216 self = netdev_priv(ndev);
217 self->pdev = pdev;
218 SET_NETDEV_DEV(ndev, &pdev->dev);
219 pci_set_drvdata(pdev, self);
a4d36e20 220
015e2f7c
IR
221 err = aq_pci_probe_get_hw_by_id(pdev, &self->aq_hw_ops,
222 &aq_nic_get_cfg(self)->aq_hw_caps);
223 if (err)
224 goto err_ioremap;
a4d36e20 225
015e2f7c
IR
226 self->aq_hw = kzalloc(sizeof(*self->aq_hw), GFP_KERNEL);
227 self->aq_hw->aq_nic_cfg = aq_nic_get_cfg(self);
a4d36e20 228
015e2f7c
IR
229 for (bar = 0; bar < 4; ++bar) {
230 if (IORESOURCE_MEM & pci_resource_flags(pdev, bar)) {
231 resource_size_t reg_sz;
6849540a 232
015e2f7c
IR
233 mmio_pa = pci_resource_start(pdev, bar);
234 if (mmio_pa == 0U) {
235 err = -EIO;
236 goto err_ioremap;
237 }
a4d36e20 238
015e2f7c
IR
239 reg_sz = pci_resource_len(pdev, bar);
240 if ((reg_sz <= 24 /*ATL_REGS_SIZE*/)) {
241 err = -EIO;
242 goto err_ioremap;
243 }
a4d36e20 244
015e2f7c
IR
245 self->aq_hw->mmio = ioremap_nocache(mmio_pa, reg_sz);
246 if (!self->aq_hw->mmio) {
247 err = -EIO;
248 goto err_ioremap;
249 }
250 break;
251 }
252 }
a4d36e20 253
015e2f7c
IR
254 if (bar == 4) {
255 err = -EIO;
256 goto err_ioremap;
a4d36e20 257 }
a4d36e20 258
015e2f7c
IR
259 numvecs = min((u8)AQ_CFG_VECS_DEF,
260 aq_nic_get_cfg(self)->aq_hw_caps->msix_irqs);
261 numvecs = min(numvecs, num_online_cpus());
262 /*enable interrupts */
263#if !AQ_CFG_FORCE_LEGACY_INT
264 err = pci_alloc_irq_vectors(self->pdev, numvecs, numvecs,
265 PCI_IRQ_MSIX);
266
267 if (err < 0) {
268 err = pci_alloc_irq_vectors(self->pdev, 1, 1,
269 PCI_IRQ_MSI | PCI_IRQ_LEGACY);
270 if (err < 0)
271 goto err_hwinit;
a4d36e20 272 }
015e2f7c 273#endif
a4d36e20 274
015e2f7c
IR
275 /* net device init */
276 aq_nic_cfg_start(self);
32b96adf 277
015e2f7c 278 aq_nic_ndev_init(self);
32b96adf 279
015e2f7c 280 err = aq_nic_ndev_register(self);
32b96adf 281 if (err < 0)
015e2f7c 282 goto err_register;
32b96adf 283
015e2f7c
IR
284 return 0;
285
286err_register:
287 aq_nic_free_vectors(self);
288 aq_pci_free_irq_vectors(self);
289err_hwinit:
290 iounmap(self->aq_hw->mmio);
291err_ioremap:
292 free_netdev(ndev);
293err_pci_func:
294 pci_release_regions(pdev);
295err_ndev:
296 pci_disable_device(pdev);
32b96adf
IR
297 return err;
298}
299
300static void aq_pci_remove(struct pci_dev *pdev)
301{
015e2f7c
IR
302 struct aq_nic_s *self = pci_get_drvdata(pdev);
303
304 if (self->ndev) {
305 if (self->ndev->reg_state == NETREG_REGISTERED)
306 unregister_netdev(self->ndev);
307 aq_nic_free_vectors(self);
308 aq_pci_free_irq_vectors(self);
309 iounmap(self->aq_hw->mmio);
310 kfree(self->aq_hw);
311 pci_release_regions(pdev);
312 free_netdev(self->ndev);
313 }
32b96adf 314
015e2f7c 315 pci_disable_device(pdev);
32b96adf
IR
316}
317
0540cadb
IR
318static void aq_pci_shutdown(struct pci_dev *pdev)
319{
320 struct aq_nic_s *self = pci_get_drvdata(pdev);
321
322 aq_nic_shutdown(self);
323
324 pci_disable_device(pdev);
325
326 if (system_state == SYSTEM_POWER_OFF) {
327 pci_wake_from_d3(pdev, false);
328 pci_set_power_state(pdev, PCI_D3hot);
329 }
330}
331
32b96adf
IR
332static int aq_pci_suspend(struct pci_dev *pdev, pm_message_t pm_msg)
333{
015e2f7c 334 struct aq_nic_s *self = pci_get_drvdata(pdev);
32b96adf 335
015e2f7c 336 return aq_nic_change_pm_state(self, &pm_msg);
32b96adf
IR
337}
338
339static int aq_pci_resume(struct pci_dev *pdev)
340{
015e2f7c 341 struct aq_nic_s *self = pci_get_drvdata(pdev);
32b96adf
IR
342 pm_message_t pm_msg = PMSG_RESTORE;
343
015e2f7c 344 return aq_nic_change_pm_state(self, &pm_msg);
32b96adf
IR
345}
346
347static struct pci_driver aq_pci_ops = {
348 .name = AQ_CFG_DRV_NAME,
349 .id_table = aq_pci_tbl,
350 .probe = aq_pci_probe,
351 .remove = aq_pci_remove,
352 .suspend = aq_pci_suspend,
353 .resume = aq_pci_resume,
0540cadb 354 .shutdown = aq_pci_shutdown,
32b96adf
IR
355};
356
357module_pci_driver(aq_pci_ops);