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), ¬ify_length);
271 pci_read_config_dword(pdev,
272 notify + offsetof(struct zxdh_pf_pci_notify_cap,
273 cap.offset), ¬ify_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