2 * aQuantia Corporation Network Driver
3 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
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.
10 /* File aq_pci_func.c: Definition of PCI functions. */
12 #include "aq_pci_func.h"
16 #include <linux/interrupt.h>
18 struct aq_pci_func_s
{
20 struct aq_nic_s
*port
[AQ_CFG_PCI_FUNC_PORTS
];
22 void *aq_vec
[AQ_CFG_PCI_FUNC_MSIX_IRQS
];
23 resource_size_t mmio_pa
;
24 unsigned int msix_entry_mask
;
28 bool is_pci_using_dac
;
29 struct aq_hw_caps_s aq_hw_caps
;
32 struct aq_pci_func_s
*aq_pci_func_alloc(struct aq_hw_ops
*aq_hw_ops
,
34 const struct net_device_ops
*ndev_ops
,
35 const struct ethtool_ops
*eth_ops
)
37 struct aq_pci_func_s
*self
= NULL
;
39 unsigned int port
= 0U;
45 self
= kzalloc(sizeof(*self
), GFP_KERNEL
);
51 pci_set_drvdata(pdev
, self
);
54 err
= aq_hw_ops
->get_hw_caps(NULL
, &self
->aq_hw_caps
, pdev
->device
,
55 pdev
->subsystem_device
);
59 self
->ports
= self
->aq_hw_caps
.ports
;
61 for (port
= 0; port
< self
->ports
; ++port
) {
62 struct aq_nic_s
*aq_nic
= aq_nic_alloc_cold(ndev_ops
, eth_ops
,
70 self
->port
[port
] = aq_nic
;
76 aq_pci_func_free(self
);
84 int aq_pci_func_init(struct aq_pci_func_s
*self
)
87 unsigned int bar
= 0U;
88 unsigned int port
= 0U;
89 unsigned int numvecs
= 0U;
91 err
= pci_enable_device(self
->pdev
);
95 self
->is_pci_enabled
= true;
97 err
= pci_set_dma_mask(self
->pdev
, DMA_BIT_MASK(64));
99 err
= pci_set_consistent_dma_mask(self
->pdev
, DMA_BIT_MASK(64));
100 self
->is_pci_using_dac
= 1;
103 err
= pci_set_dma_mask(self
->pdev
, DMA_BIT_MASK(32));
105 err
= pci_set_consistent_dma_mask(self
->pdev
,
107 self
->is_pci_using_dac
= 0;
114 err
= pci_request_regions(self
->pdev
, AQ_CFG_DRV_NAME
"_mmio");
118 self
->is_regions
= true;
120 pci_set_master(self
->pdev
);
122 for (bar
= 0; bar
< 4; ++bar
) {
123 if (IORESOURCE_MEM
& pci_resource_flags(self
->pdev
, bar
)) {
124 resource_size_t reg_sz
;
126 self
->mmio_pa
= pci_resource_start(self
->pdev
, bar
);
127 if (self
->mmio_pa
== 0U) {
132 reg_sz
= pci_resource_len(self
->pdev
, bar
);
133 if ((reg_sz
<= 24 /*ATL_REGS_SIZE*/)) {
138 self
->mmio
= ioremap_nocache(self
->mmio_pa
, reg_sz
);
147 numvecs
= min((u8
)AQ_CFG_VECS_DEF
, self
->aq_hw_caps
.msix_irqs
);
148 numvecs
= min(numvecs
, num_online_cpus());
150 /* enable interrupts */
151 #if !AQ_CFG_FORCE_LEGACY_INT
152 err
= pci_alloc_irq_vectors(self
->pdev
, numvecs
, numvecs
, PCI_IRQ_MSIX
);
155 err
= pci_alloc_irq_vectors(self
->pdev
, 1, 1,
156 PCI_IRQ_MSI
| PCI_IRQ_LEGACY
);
160 #endif /* AQ_CFG_FORCE_LEGACY_INT */
162 /* net device init */
163 for (port
= 0; port
< self
->ports
; ++port
) {
164 if (!self
->port
[port
])
167 err
= aq_nic_cfg_start(self
->port
[port
]);
171 err
= aq_nic_ndev_init(self
->port
[port
]);
175 err
= aq_nic_ndev_register(self
->port
[port
]);
182 aq_pci_func_deinit(self
);
186 int aq_pci_func_alloc_irq(struct aq_pci_func_s
*self
, unsigned int i
,
187 char *name
, void *aq_vec
, cpumask_t
*affinity_mask
)
189 struct pci_dev
*pdev
= self
->pdev
;
192 if (pdev
->msix_enabled
|| pdev
->msi_enabled
)
193 err
= request_irq(pci_irq_vector(pdev
, i
), aq_vec_isr
, 0,
196 err
= request_irq(pci_irq_vector(pdev
, i
), aq_vec_isr_legacy
,
197 IRQF_SHARED
, name
, aq_vec
);
200 self
->msix_entry_mask
|= (1 << i
);
201 self
->aq_vec
[i
] = aq_vec
;
203 if (pdev
->msix_enabled
)
204 irq_set_affinity_hint(pci_irq_vector(pdev
, i
),
211 void aq_pci_func_free_irqs(struct aq_pci_func_s
*self
)
213 struct pci_dev
*pdev
= self
->pdev
;
216 for (i
= 32U; i
--;) {
217 if (!((1U << i
) & self
->msix_entry_mask
))
220 if (pdev
->msix_enabled
)
221 irq_set_affinity_hint(pci_irq_vector(pdev
, i
), NULL
);
222 free_irq(pci_irq_vector(pdev
, i
), self
->aq_vec
[i
]);
223 self
->msix_entry_mask
&= ~(1U << i
);
227 void __iomem
*aq_pci_func_get_mmio(struct aq_pci_func_s
*self
)
232 unsigned int aq_pci_func_get_irq_type(struct aq_pci_func_s
*self
)
234 if (self
->pdev
->msix_enabled
)
235 return AQ_HW_IRQ_MSIX
;
236 if (self
->pdev
->msi_enabled
)
237 return AQ_HW_IRQ_MSIX
;
238 return AQ_HW_IRQ_LEGACY
;
241 void aq_pci_func_deinit(struct aq_pci_func_s
*self
)
246 aq_pci_func_free_irqs(self
);
247 pci_free_irq_vectors(self
->pdev
);
249 if (self
->is_regions
)
250 pci_release_regions(self
->pdev
);
252 if (self
->is_pci_enabled
)
253 pci_disable_device(self
->pdev
);
258 void aq_pci_func_free(struct aq_pci_func_s
*self
)
260 unsigned int port
= 0U;
265 for (port
= 0; port
< self
->ports
; ++port
) {
266 if (!self
->port
[port
])
269 aq_nic_ndev_free(self
->port
[port
]);
280 int aq_pci_func_change_pm_state(struct aq_pci_func_s
*self
,
281 pm_message_t
*pm_msg
)
284 unsigned int port
= 0U;
290 for (port
= 0; port
< self
->ports
; ++port
) {
291 if (!self
->port
[port
])
294 (void)aq_nic_change_pm_state(self
->port
[port
], pm_msg
);