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
);
58 self
->ports
= self
->aq_hw_caps
.ports
;
60 for (port
= 0; port
< self
->ports
; ++port
) {
61 struct aq_nic_s
*aq_nic
= aq_nic_alloc_cold(ndev_ops
, eth_ops
,
69 self
->port
[port
] = aq_nic
;
75 aq_pci_func_free(self
);
83 int aq_pci_func_init(struct aq_pci_func_s
*self
)
86 unsigned int bar
= 0U;
87 unsigned int port
= 0U;
88 unsigned int numvecs
= 0U;
90 err
= pci_enable_device(self
->pdev
);
94 self
->is_pci_enabled
= true;
96 err
= pci_set_dma_mask(self
->pdev
, DMA_BIT_MASK(64));
98 err
= pci_set_consistent_dma_mask(self
->pdev
, DMA_BIT_MASK(64));
99 self
->is_pci_using_dac
= 1;
102 err
= pci_set_dma_mask(self
->pdev
, DMA_BIT_MASK(32));
104 err
= pci_set_consistent_dma_mask(self
->pdev
,
106 self
->is_pci_using_dac
= 0;
113 err
= pci_request_regions(self
->pdev
, AQ_CFG_DRV_NAME
"_mmio");
117 self
->is_regions
= true;
119 pci_set_master(self
->pdev
);
121 for (bar
= 0; bar
< 4; ++bar
) {
122 if (IORESOURCE_MEM
& pci_resource_flags(self
->pdev
, bar
)) {
123 resource_size_t reg_sz
;
125 self
->mmio_pa
= pci_resource_start(self
->pdev
, bar
);
126 if (self
->mmio_pa
== 0U) {
131 reg_sz
= pci_resource_len(self
->pdev
, bar
);
132 if ((reg_sz
<= 24 /*ATL_REGS_SIZE*/)) {
137 self
->mmio
= ioremap_nocache(self
->mmio_pa
, reg_sz
);
146 numvecs
= min((u8
)AQ_CFG_VECS_DEF
, self
->aq_hw_caps
.msix_irqs
);
147 numvecs
= min(numvecs
, num_online_cpus());
149 /* enable interrupts */
150 #if !AQ_CFG_FORCE_LEGACY_INT
151 err
= pci_alloc_irq_vectors(self
->pdev
, numvecs
, numvecs
, PCI_IRQ_MSIX
);
154 err
= pci_alloc_irq_vectors(self
->pdev
, 1, 1,
155 PCI_IRQ_MSI
| PCI_IRQ_LEGACY
);
159 #endif /* AQ_CFG_FORCE_LEGACY_INT */
161 /* net device init */
162 for (port
= 0; port
< self
->ports
; ++port
) {
163 if (!self
->port
[port
])
166 err
= aq_nic_cfg_start(self
->port
[port
]);
170 err
= aq_nic_ndev_init(self
->port
[port
]);
174 err
= aq_nic_ndev_register(self
->port
[port
]);
181 aq_pci_func_deinit(self
);
185 int aq_pci_func_alloc_irq(struct aq_pci_func_s
*self
, unsigned int i
,
186 char *name
, void *aq_vec
, cpumask_t
*affinity_mask
)
188 struct pci_dev
*pdev
= self
->pdev
;
191 if (pdev
->msix_enabled
|| pdev
->msi_enabled
)
192 err
= request_irq(pci_irq_vector(pdev
, i
), aq_vec_isr
, 0,
195 err
= request_irq(pci_irq_vector(pdev
, i
), aq_vec_isr_legacy
,
196 IRQF_SHARED
, name
, aq_vec
);
199 self
->msix_entry_mask
|= (1 << i
);
200 self
->aq_vec
[i
] = aq_vec
;
202 if (pdev
->msix_enabled
)
203 irq_set_affinity_hint(pci_irq_vector(pdev
, i
),
210 void aq_pci_func_free_irqs(struct aq_pci_func_s
*self
)
212 struct pci_dev
*pdev
= self
->pdev
;
215 for (i
= 32U; i
--;) {
216 if (!((1U << i
) & self
->msix_entry_mask
))
219 if (pdev
->msix_enabled
)
220 irq_set_affinity_hint(pci_irq_vector(pdev
, i
), NULL
);
221 free_irq(pci_irq_vector(pdev
, i
), self
->aq_vec
[i
]);
222 self
->msix_entry_mask
&= ~(1U << i
);
226 void __iomem
*aq_pci_func_get_mmio(struct aq_pci_func_s
*self
)
231 unsigned int aq_pci_func_get_irq_type(struct aq_pci_func_s
*self
)
233 if (self
->pdev
->msix_enabled
)
234 return AQ_HW_IRQ_MSIX
;
235 if (self
->pdev
->msi_enabled
)
236 return AQ_HW_IRQ_MSIX
;
237 return AQ_HW_IRQ_LEGACY
;
240 void aq_pci_func_deinit(struct aq_pci_func_s
*self
)
245 aq_pci_func_free_irqs(self
);
246 pci_free_irq_vectors(self
->pdev
);
248 if (self
->is_regions
)
249 pci_release_regions(self
->pdev
);
251 if (self
->is_pci_enabled
)
252 pci_disable_device(self
->pdev
);
257 void aq_pci_func_free(struct aq_pci_func_s
*self
)
259 unsigned int port
= 0U;
264 for (port
= 0; port
< self
->ports
; ++port
) {
265 if (!self
->port
[port
])
268 aq_nic_ndev_free(self
->port
[port
]);
276 int aq_pci_func_change_pm_state(struct aq_pci_func_s
*self
,
277 pm_message_t
*pm_msg
)
280 unsigned int port
= 0U;
286 for (port
= 0; port
< self
->ports
; ++port
) {
287 if (!self
->port
[port
])
290 (void)aq_nic_change_pm_state(self
->port
[port
], pm_msg
);