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 
12 #include "aq_pci_func.h"
13 #include "aq_nic.h"
14 #include "aq_vec.h"
15 #include "aq_hw.h"
16 #include <linux/interrupt.h>
17 
18 struct aq_pci_func_s {
19 	struct pci_dev *pdev;
20 	struct aq_nic_s *port[AQ_CFG_PCI_FUNC_PORTS];
21 	void __iomem *mmio;
22 	void *aq_vec[AQ_CFG_PCI_FUNC_MSIX_IRQS];
23 	resource_size_t mmio_pa;
24 	unsigned int msix_entry_mask;
25 	unsigned int ports;
26 	bool is_pci_enabled;
27 	bool is_regions;
28 	bool is_pci_using_dac;
29 	struct aq_hw_caps_s aq_hw_caps;
30 };
31 
32 struct aq_pci_func_s *aq_pci_func_alloc(struct aq_hw_ops *aq_hw_ops,
33 					struct pci_dev *pdev,
34 					const struct net_device_ops *ndev_ops,
35 					const struct ethtool_ops *eth_ops)
36 {
37 	struct aq_pci_func_s *self = NULL;
38 	int err = 0;
39 	unsigned int port = 0U;
40 
41 	if (!aq_hw_ops) {
42 		err = -EFAULT;
43 		goto err_exit;
44 	}
45 	self = kzalloc(sizeof(*self), GFP_KERNEL);
46 	if (!self) {
47 		err = -ENOMEM;
48 		goto err_exit;
49 	}
50 
51 	pci_set_drvdata(pdev, self);
52 	self->pdev = pdev;
53 
54 	err = aq_hw_ops->get_hw_caps(NULL, &self->aq_hw_caps);
55 	if (err < 0)
56 		goto err_exit;
57 
58 	self->ports = self->aq_hw_caps.ports;
59 
60 	for (port = 0; port < self->ports; ++port) {
61 		struct aq_nic_s *aq_nic = aq_nic_alloc_cold(ndev_ops, eth_ops,
62 							    &pdev->dev, self,
63 							    port, aq_hw_ops);
64 
65 		if (!aq_nic) {
66 			err = -ENOMEM;
67 			goto err_exit;
68 		}
69 		self->port[port] = aq_nic;
70 	}
71 
72 err_exit:
73 	if (err < 0) {
74 		if (self)
75 			aq_pci_func_free(self);
76 		self = NULL;
77 	}
78 
79 	(void)err;
80 	return self;
81 }
82 
83 int aq_pci_func_init(struct aq_pci_func_s *self)
84 {
85 	int err = 0;
86 	unsigned int bar = 0U;
87 	unsigned int port = 0U;
88 
89 	err = pci_enable_device(self->pdev);
90 	if (err < 0)
91 		goto err_exit;
92 
93 	self->is_pci_enabled = true;
94 
95 	err = pci_set_dma_mask(self->pdev, DMA_BIT_MASK(64));
96 	if (!err) {
97 		err = pci_set_consistent_dma_mask(self->pdev, DMA_BIT_MASK(64));
98 		self->is_pci_using_dac = 1;
99 	}
100 	if (err) {
101 		err = pci_set_dma_mask(self->pdev, DMA_BIT_MASK(32));
102 		if (!err)
103 			err = pci_set_consistent_dma_mask(self->pdev,
104 							  DMA_BIT_MASK(32));
105 		self->is_pci_using_dac = 0;
106 	}
107 	if (err != 0) {
108 		err = -ENOSR;
109 		goto err_exit;
110 	}
111 
112 	err = pci_request_regions(self->pdev, AQ_CFG_DRV_NAME "_mmio");
113 	if (err < 0)
114 		goto err_exit;
115 
116 	self->is_regions = true;
117 
118 	pci_set_master(self->pdev);
119 
120 	for (bar = 0; bar < 4; ++bar) {
121 		if (IORESOURCE_MEM & pci_resource_flags(self->pdev, bar)) {
122 			resource_size_t reg_sz;
123 
124 			self->mmio_pa = pci_resource_start(self->pdev, bar);
125 			if (self->mmio_pa == 0U) {
126 				err = -EIO;
127 				goto err_exit;
128 			}
129 
130 			reg_sz = pci_resource_len(self->pdev, bar);
131 			if ((reg_sz <= 24 /*ATL_REGS_SIZE*/)) {
132 				err = -EIO;
133 				goto err_exit;
134 			}
135 
136 			self->mmio = ioremap_nocache(self->mmio_pa, reg_sz);
137 			if (!self->mmio) {
138 				err = -EIO;
139 				goto err_exit;
140 			}
141 			break;
142 		}
143 	}
144 
145 	/*enable interrupts */
146 #if !AQ_CFG_FORCE_LEGACY_INT
147 	err = pci_alloc_irq_vectors(self->pdev, self->aq_hw_caps.msix_irqs,
148 			      self->aq_hw_caps.msix_irqs, PCI_IRQ_MSIX);
149 
150 	if (err < 0) {
151 		err = pci_alloc_irq_vectors(self->pdev, 1, 1,
152 				PCI_IRQ_MSI | PCI_IRQ_LEGACY);
153 		if (err < 0)
154 			goto err_exit;
155 	}
156 #endif
157 
158 	/* net device init */
159 	for (port = 0; port < self->ports; ++port) {
160 		if (!self->port[port])
161 			continue;
162 
163 		err = aq_nic_cfg_start(self->port[port]);
164 		if (err < 0)
165 			goto err_exit;
166 
167 		err = aq_nic_ndev_init(self->port[port]);
168 		if (err < 0)
169 			goto err_exit;
170 
171 		err = aq_nic_ndev_register(self->port[port]);
172 		if (err < 0)
173 			goto err_exit;
174 	}
175 
176 err_exit:
177 	if (err < 0)
178 		aq_pci_func_deinit(self);
179 	return err;
180 }
181 
182 int aq_pci_func_alloc_irq(struct aq_pci_func_s *self, unsigned int i,
183 			  char *name, void *aq_vec, cpumask_t *affinity_mask)
184 {
185 	struct pci_dev *pdev = self->pdev;
186 	int err = 0;
187 
188 	if (pdev->msix_enabled || pdev->msi_enabled)
189 		err = request_irq(pci_irq_vector(pdev, i), aq_vec_isr, 0,
190 				  name, aq_vec);
191 	else
192 		err = request_irq(pci_irq_vector(pdev, i), aq_vec_isr_legacy,
193 				  IRQF_SHARED, name, aq_vec);
194 
195 	if (err >= 0) {
196 		self->msix_entry_mask |= (1 << i);
197 		self->aq_vec[i] = aq_vec;
198 
199 		if (pdev->msix_enabled)
200 			irq_set_affinity_hint(pci_irq_vector(pdev, i),
201 					      affinity_mask);
202 	}
203 
204 	return err;
205 }
206 
207 void aq_pci_func_free_irqs(struct aq_pci_func_s *self)
208 {
209 	struct pci_dev *pdev = self->pdev;
210 	unsigned int i = 0U;
211 
212 	for (i = 32U; i--;) {
213 		if (!((1U << i) & self->msix_entry_mask))
214 			continue;
215 
216 		if (pdev->msix_enabled)
217 			irq_set_affinity_hint(pci_irq_vector(pdev, i), NULL);
218 		free_irq(pci_irq_vector(pdev, i), self->aq_vec[i]);
219 		self->msix_entry_mask &= ~(1U << i);
220 	}
221 }
222 
223 void __iomem *aq_pci_func_get_mmio(struct aq_pci_func_s *self)
224 {
225 	return self->mmio;
226 }
227 
228 unsigned int aq_pci_func_get_irq_type(struct aq_pci_func_s *self)
229 {
230 	if (self->pdev->msix_enabled)
231 		return AQ_HW_IRQ_MSIX;
232 	if (self->pdev->msi_enabled)
233 		return AQ_HW_IRQ_MSIX;
234 	return AQ_HW_IRQ_LEGACY;
235 }
236 
237 void aq_pci_func_deinit(struct aq_pci_func_s *self)
238 {
239 	if (!self)
240 		goto err_exit;
241 
242 	aq_pci_func_free_irqs(self);
243 	pci_free_irq_vectors(self->pdev);
244 
245 	if (self->is_regions)
246 		pci_release_regions(self->pdev);
247 
248 	if (self->is_pci_enabled)
249 		pci_disable_device(self->pdev);
250 
251 err_exit:;
252 }
253 
254 void aq_pci_func_free(struct aq_pci_func_s *self)
255 {
256 	unsigned int port = 0U;
257 
258 	if (!self)
259 		goto err_exit;
260 
261 	for (port = 0; port < self->ports; ++port) {
262 		if (!self->port[port])
263 			continue;
264 
265 		aq_nic_ndev_free(self->port[port]);
266 	}
267 
268 	kfree(self);
269 
270 err_exit:;
271 }
272 
273 int aq_pci_func_change_pm_state(struct aq_pci_func_s *self,
274 				pm_message_t *pm_msg)
275 {
276 	int err = 0;
277 	unsigned int port = 0U;
278 
279 	if (!self) {
280 		err = -EFAULT;
281 		goto err_exit;
282 	}
283 	for (port = 0; port < self->ports; ++port) {
284 		if (!self->port[port])
285 			continue;
286 
287 		(void)aq_nic_change_pm_state(self->port[port], pm_msg);
288 	}
289 
290 err_exit:
291 	return err;
292 }
293