xref: /linux/drivers/net/ethernet/zte/dinghai/en_pf.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * ZTE DingHai Ethernet driver
4  * Copyright (c) 2022-2026, ZTE Corporation.
5  */
6 
7 #include <linux/module.h>
8 #include <linux/pci.h>
9 #include <net/devlink.h>
10 #include <linux/dma-mapping.h>
11 #include "en_pf.h"
12 #include "dh_queue.h"
13 
14 MODULE_AUTHOR("Junyang Han <han.junyang@zte.com.cn>");
15 MODULE_DESCRIPTION("ZTE DingHai series Ethernet driver");
16 MODULE_LICENSE("GPL");
17 
18 static const struct devlink_ops zxdh_pf_devlink_ops = {};
19 
20 static const struct pci_device_id zxdh_pf_pci_table[] = {
21 	{ PCI_DEVICE(ZXDH_PF_VENDOR_ID, ZXDH_PF_DEVICE_ID) },
22 	{ PCI_DEVICE(ZXDH_PF_VENDOR_ID, ZXDH_VF_DEVICE_ID) },
23 	{ }
24 };
25 
26 MODULE_DEVICE_TABLE(pci, zxdh_pf_pci_table);
27 
zxdh_core_alloc_priv(struct zxdh_core_dev * zxdh_dev,size_t size)28 void *zxdh_core_alloc_priv(struct zxdh_core_dev *zxdh_dev, size_t size)
29 {
30 	void *priv = kzalloc(size, GFP_KERNEL);
31 
32 	if (priv)
33 		zxdh_dev->priv = priv;
34 	return priv;
35 }
36 
zxdh_core_free_priv(struct zxdh_core_dev * zxdh_dev)37 void zxdh_core_free_priv(struct zxdh_core_dev *zxdh_dev)
38 {
39 	kfree(zxdh_dev->priv);
40 }
41 
zxdh_pf_pci_init(struct zxdh_core_dev * zxdh_dev)42 static int zxdh_pf_pci_init(struct zxdh_core_dev *zxdh_dev)
43 {
44 	struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
45 	int ret;
46 
47 	pci_set_drvdata(zxdh_dev->pdev, zxdh_dev);
48 
49 	ret = pci_enable_device(zxdh_dev->pdev);
50 	if (ret) {
51 		dev_err(zxdh_dev->device, "pci_enable_device failed: %d\n", ret);
52 		return ret;
53 	}
54 
55 	dma_set_mask_and_coherent(zxdh_dev->device, DMA_BIT_MASK(64));
56 
57 	ret = pci_request_selected_regions(zxdh_dev->pdev,
58 					   pci_select_bars(zxdh_dev->pdev, IORESOURCE_MEM),
59 					   "dh-pf");
60 	if (ret) {
61 		dev_err(zxdh_dev->device, "pci_request_selected_regions failed: %d\n", ret);
62 		goto err_pci;
63 	}
64 
65 	pci_set_master(zxdh_dev->pdev);
66 	ret = pci_save_state(zxdh_dev->pdev);
67 	if (ret) {
68 		dev_err(zxdh_dev->device, "pci_save_state failed: %d\n", ret);
69 		goto err_pci_save_state;
70 	}
71 
72 	if (!(pci_resource_flags(zxdh_dev->pdev, 0) & IORESOURCE_MEM)) {
73 		ret = -ENODEV;
74 		dev_err(zxdh_dev->device, "BAR 0 is not an MMIO resource\n");
75 		goto err_pci_save_state;
76 	}
77 
78 	pf_dev->pci_ioremap_addr[0] =
79 		ioremap(pci_resource_start(zxdh_dev->pdev, 0),
80 			pci_resource_len(zxdh_dev->pdev, 0));
81 	if (!pf_dev->pci_ioremap_addr[0]) {
82 		ret = -ENOMEM;
83 		dev_err(zxdh_dev->device, "dh pf pci ioremap failed\n");
84 		goto err_pci_save_state;
85 	}
86 
87 	return 0;
88 
89 err_pci_save_state:
90 	pci_release_selected_regions(zxdh_dev->pdev,
91 				     pci_select_bars(zxdh_dev->pdev, IORESOURCE_MEM));
92 err_pci:
93 	pci_disable_device(zxdh_dev->pdev);
94 	return ret;
95 }
96 
zxdh_pf_pci_close(struct zxdh_core_dev * zxdh_dev)97 void zxdh_pf_pci_close(struct zxdh_core_dev *zxdh_dev)
98 {
99 	struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
100 
101 	iounmap(pf_dev->pci_ioremap_addr[0]);
102 	pci_release_selected_regions(zxdh_dev->pdev,
103 				     pci_select_bars(zxdh_dev->pdev, IORESOURCE_MEM));
104 	pci_disable_device(zxdh_dev->pdev);
105 }
106 
zxdh_pf_pci_find_capability(struct pci_dev * pdev,u8 cfg_type,u32 ioresource_types,int * bars)107 int zxdh_pf_pci_find_capability(struct pci_dev *pdev, u8 cfg_type,
108 				u32 ioresource_types, int *bars)
109 {
110 	int pos;
111 	u8 type;
112 	u8 bar;
113 
114 	for (pos = pci_find_capability(pdev, PCI_CAP_ID_VNDR); pos > 0;
115 	     pos = pci_find_next_capability(pdev, pos, PCI_CAP_ID_VNDR)) {
116 		pci_read_config_byte(pdev,
117 				     pos + offsetof(struct zxdh_pf_pci_cap,
118 							cfg_type), &type);
119 		pci_read_config_byte(pdev,
120 				     pos + offsetof(struct zxdh_pf_pci_cap, bar), &bar);
121 
122 		/* ignore structures with reserved BAR values */
123 		if (bar > ZXDH_PF_MAX_BAR_VAL)
124 			continue;
125 
126 		if (type == cfg_type) {
127 			if (pci_resource_len(pdev, bar) &&
128 			    pci_resource_flags(pdev, bar) & ioresource_types) {
129 				*bars |= (1 << bar);
130 				return pos;
131 			}
132 		}
133 	}
134 
135 	return 0;
136 }
137 
zxdh_pf_map_capability(struct zxdh_core_dev * zxdh_dev,int off,size_t minlen,u32 align,u32 start,u32 size,size_t * len,resource_size_t * pa,u32 * bar_off)138 void __iomem *zxdh_pf_map_capability(struct zxdh_core_dev *zxdh_dev, int off,
139 				     size_t minlen, u32 align,
140 				     u32 start, u32 size,
141 				     size_t *len, resource_size_t *pa,
142 				     u32 *bar_off)
143 {
144 	struct pci_dev *pdev = zxdh_dev->pdev;
145 	void __iomem *p;
146 	u32 offset;
147 	u32 length;
148 	u8 bar;
149 
150 	pci_read_config_byte(pdev,
151 			     off + offsetof(struct zxdh_pf_pci_cap, bar), &bar);
152 
153 	if (bar > ZXDH_PF_MAX_BAR_VAL) {
154 		dev_err(zxdh_dev->device, "invalid bar %u\n", bar);
155 		return NULL;
156 	}
157 
158 	pci_read_config_dword(pdev,
159 			      off + offsetof(struct zxdh_pf_pci_cap,
160 						offset), &offset);
161 	pci_read_config_dword(pdev,
162 			      off + offsetof(struct zxdh_pf_pci_cap,
163 						length), &length);
164 
165 	if (bar_off)
166 		*bar_off = offset;
167 
168 	if (length <= start) {
169 		dev_err(zxdh_dev->device, "bad capability len %u (>%u expected)\n",
170 			length, start);
171 		return NULL;
172 	}
173 
174 	if (length - start < minlen) {
175 		dev_err(zxdh_dev->device, "bad capability len %u (>=%zu expected)\n",
176 			length, minlen);
177 		return NULL;
178 	}
179 
180 	length -= start;
181 	if (start + offset < offset) {
182 		dev_err(zxdh_dev->device, "map wrap-around %u+%u\n", start, offset);
183 		return NULL;
184 	}
185 
186 	offset += start;
187 	if (offset & (align - 1)) {
188 		dev_err(zxdh_dev->device, "offset %u not aligned to %u\n", offset, align);
189 		return NULL;
190 	}
191 
192 	if (length > size)
193 		length = size;
194 
195 	if (len)
196 		*len = length;
197 
198 	if (length + offset < offset ||
199 	    length + offset > pci_resource_len(pdev, bar)) {
200 		dev_err(zxdh_dev->device,
201 			"map %u@%u out of range on bar %u length %lu\n",
202 			length, offset, bar,
203 			(unsigned long)pci_resource_len(pdev, bar));
204 		return NULL;
205 	}
206 
207 	p = pci_iomap_range(pdev, bar, offset, length);
208 	if (!p) {
209 		dev_err(zxdh_dev->device, "unable to map custom queue %u@%u on bar %u\n",
210 			length, offset, bar);
211 	} else if (pa) {
212 		*pa = pci_resource_start(pdev, bar) + offset;
213 	}
214 
215 	return p;
216 }
217 
zxdh_pf_common_cfg_init(struct zxdh_core_dev * zxdh_dev)218 int zxdh_pf_common_cfg_init(struct zxdh_core_dev *zxdh_dev)
219 {
220 	struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
221 	struct pci_dev *pdev = zxdh_dev->pdev;
222 	int common;
223 
224 	/* check for a common config: if not, use legacy mode (bar 0). */
225 	common = zxdh_pf_pci_find_capability(pdev, ZXDH_PCI_CAP_COMMON_CFG,
226 					     IORESOURCE_MEM,
227 					     &pf_dev->modern_bars);
228 	if (!common) {
229 		dev_err(zxdh_dev->device,
230 			"missing capabilities, leaving for legacy driver\n");
231 		return -ENODEV;
232 	}
233 
234 	pf_dev->common = zxdh_pf_map_capability(zxdh_dev, common,
235 						sizeof(struct zxdh_pf_pci_common_cfg),
236 						ZXDH_PF_ALIGN4, 0,
237 						sizeof(struct zxdh_pf_pci_common_cfg),
238 						NULL, NULL, NULL);
239 	if (!pf_dev->common) {
240 		dev_err(zxdh_dev->device, "pf_dev->common is null\n");
241 		return -EINVAL;
242 	}
243 
244 	return 0;
245 }
246 
zxdh_pf_notify_cfg_init(struct zxdh_core_dev * zxdh_dev)247 int zxdh_pf_notify_cfg_init(struct zxdh_core_dev *zxdh_dev)
248 {
249 	struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
250 	struct pci_dev *pdev = zxdh_dev->pdev;
251 	u32 notify_length;
252 	u32 notify_offset;
253 	int notify;
254 
255 	/* If common is there, these should be too... */
256 	notify = zxdh_pf_pci_find_capability(pdev, ZXDH_PCI_CAP_NOTIFY_CFG,
257 					     IORESOURCE_MEM,
258 					     &pf_dev->modern_bars);
259 	if (!notify) {
260 		dev_err(zxdh_dev->device, "missing notify cfg capability\n");
261 		return -EINVAL;
262 	}
263 
264 	pci_read_config_dword(pdev,
265 			      notify + offsetof(struct zxdh_pf_pci_notify_cap,
266 				notify_off_multiplier),
267 		&pf_dev->notify_offset_multiplier);
268 	pci_read_config_dword(pdev,
269 			      notify + offsetof(struct zxdh_pf_pci_notify_cap,
270 				cap.length), &notify_length);
271 	pci_read_config_dword(pdev,
272 			      notify + offsetof(struct zxdh_pf_pci_notify_cap,
273 				cap.offset), &notify_offset);
274 
275 	/* We don't know how many VQs we'll map, ahead of the time.
276 	 * If notify length is small, map it all now. Otherwise,
277 	 * map each VQ individually later.
278 	 */
279 	if (notify_length <= PAGE_SIZE - (notify_offset % PAGE_SIZE)) {
280 		pf_dev->notify_base = zxdh_pf_map_capability(zxdh_dev, notify,
281 							     ZXDH_PF_MAP_MINLEN2,
282 							    ZXDH_PF_ALIGN2, 0,
283 							    notify_length,
284 							    &pf_dev->notify_len,
285 							    &pf_dev->notify_pa, NULL);
286 		if (!pf_dev->notify_base) {
287 			dev_err(zxdh_dev->device, "pf_dev->notify_base is null\n");
288 			return -EINVAL;
289 		}
290 	} else {
291 		pf_dev->notify_map_cap = notify;
292 	}
293 
294 	return 0;
295 }
296 
zxdh_pf_device_cfg_init(struct zxdh_core_dev * zxdh_dev)297 int zxdh_pf_device_cfg_init(struct zxdh_core_dev *zxdh_dev)
298 {
299 	struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
300 	struct pci_dev *pdev = zxdh_dev->pdev;
301 	int device;
302 
303 	/* Device capability is only mandatory for
304 	 * devices that have device-specific configuration.
305 	 */
306 	device = zxdh_pf_pci_find_capability(pdev, ZXDH_PCI_CAP_DEVICE_CFG,
307 					     IORESOURCE_MEM,
308 					     &pf_dev->modern_bars);
309 
310 	/* we don't know how much we should map,
311 	 * but PAGE_SIZE is more than enough for all existing devices.
312 	 */
313 	if (device) {
314 		pf_dev->device = zxdh_pf_map_capability(zxdh_dev, device, 0,
315 							ZXDH_PF_ALIGN4, 0, PAGE_SIZE,
316 						       &pf_dev->device_len, NULL,
317 						       &pf_dev->dev_cfg_bar_off);
318 		if (!pf_dev->device) {
319 			dev_err(zxdh_dev->device, "pf_dev->device is null\n");
320 			return -EINVAL;
321 		}
322 	}
323 	return 0;
324 }
325 
zxdh_pf_modern_cfg_uninit(struct zxdh_core_dev * zxdh_dev)326 void zxdh_pf_modern_cfg_uninit(struct zxdh_core_dev *zxdh_dev)
327 {
328 	struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
329 	struct pci_dev *pdev = zxdh_dev->pdev;
330 
331 	if (pf_dev->device)
332 		pci_iounmap(pdev, pf_dev->device);
333 	if (pf_dev->notify_base)
334 		pci_iounmap(pdev, pf_dev->notify_base);
335 	pci_iounmap(pdev, pf_dev->common);
336 }
337 
zxdh_pf_modern_cfg_init(struct zxdh_core_dev * zxdh_dev)338 int zxdh_pf_modern_cfg_init(struct zxdh_core_dev *zxdh_dev)
339 {
340 	struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
341 	struct pci_dev *pdev = zxdh_dev->pdev;
342 	int ret;
343 
344 	ret = zxdh_pf_common_cfg_init(zxdh_dev);
345 	if (ret) {
346 		dev_err(zxdh_dev->device, "zxdh_pf_common_cfg_init failed: %d\n", ret);
347 		return ret;
348 	}
349 
350 	ret = zxdh_pf_notify_cfg_init(zxdh_dev);
351 	if (ret) {
352 		dev_err(zxdh_dev->device, "zxdh_pf_notify_cfg_init failed: %d\n", ret);
353 		goto err_map_notify;
354 	}
355 
356 	ret = zxdh_pf_device_cfg_init(zxdh_dev);
357 	if (ret) {
358 		dev_err(zxdh_dev->device, "zxdh_pf_device_cfg_init failed: %d\n", ret);
359 		goto err_map_device;
360 	}
361 
362 	return 0;
363 
364 err_map_device:
365 	if (pf_dev->notify_base)
366 		pci_iounmap(pdev, pf_dev->notify_base);
367 err_map_notify:
368 	pci_iounmap(pdev, pf_dev->common);
369 	return ret;
370 }
371 
zxdh_pf_probe(struct pci_dev * pdev,const struct pci_device_id * id)372 static int zxdh_pf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
373 {
374 	struct zxdh_core_dev *zxdh_dev;
375 	struct zxdh_pf_dev *pf_dev;
376 	struct devlink *devlink;
377 	int ret;
378 
379 	devlink = devlink_alloc(&zxdh_pf_devlink_ops, sizeof(struct zxdh_core_dev),
380 				&pdev->dev);
381 	if (!devlink)
382 		return -ENOMEM;
383 
384 	zxdh_dev = devlink_priv(devlink);
385 	zxdh_dev->device = &pdev->dev;
386 	zxdh_dev->pdev = pdev;
387 	zxdh_dev->devlink = devlink;
388 
389 	pf_dev = zxdh_core_alloc_priv(zxdh_dev, sizeof(*pf_dev));
390 	if (!pf_dev) {
391 		dev_err(&pdev->dev, "zxdh_pf_dev alloc failed\n");
392 		ret = -ENOMEM;
393 		goto err_pf_dev;
394 	}
395 
396 	ret = zxdh_pf_pci_init(zxdh_dev);
397 	if (ret) {
398 		dev_err(&pdev->dev, "zxdh_pf_pci_init failed: %d\n", ret);
399 		goto err_pci_init;
400 	}
401 
402 	ret = zxdh_pf_modern_cfg_init(zxdh_dev);
403 	if (ret) {
404 		dev_err(&pdev->dev, "zxdh_pf_modern_cfg_init failed: %d\n", ret);
405 		goto err_cfg_init;
406 	}
407 
408 	devlink_register(devlink);
409 
410 	return 0;
411 
412 err_cfg_init:
413 	zxdh_pf_pci_close(zxdh_dev);
414 err_pci_init:
415 	zxdh_core_free_priv(zxdh_dev);
416 err_pf_dev:
417 	devlink_free(devlink);
418 	return ret;
419 }
420 
zxdh_pf_remove(struct pci_dev * pdev)421 static void zxdh_pf_remove(struct pci_dev *pdev)
422 {
423 	struct zxdh_core_dev *zxdh_dev = pci_get_drvdata(pdev);
424 	struct devlink *devlink = priv_to_devlink(zxdh_dev);
425 
426 	devlink_unregister(devlink);
427 	zxdh_pf_modern_cfg_uninit(zxdh_dev);
428 	zxdh_pf_pci_close(zxdh_dev);
429 	zxdh_core_free_priv(zxdh_dev);
430 	devlink_free(devlink);
431 	pci_set_drvdata(pdev, NULL);
432 }
433 
zxdh_pf_shutdown(struct pci_dev * pdev)434 static void zxdh_pf_shutdown(struct pci_dev *pdev)
435 {
436 	if (system_state == SYSTEM_POWER_OFF)
437 		pci_set_power_state(pdev, PCI_D3hot);
438 	pci_disable_device(pdev);
439 }
440 
441 static struct pci_driver zxdh_pf_driver = {
442 	.name = "dinghai10e",
443 	.id_table = zxdh_pf_pci_table,
444 	.probe = zxdh_pf_probe,
445 	.remove = zxdh_pf_remove,
446 	.shutdown = zxdh_pf_shutdown,
447 };
448 
449 module_pci_driver(zxdh_pf_driver);
450