| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/02 17:41 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch introduces a new vendor-specific PCIe Ethernet driver (ZTE DingHai). This driver requires physical PCIe hardware that is not emulated in standard QEMU, making it unreachable and untestable in virtualized fuzzing environments.",
"WorthFuzzing": false
} |
| 1/1 | 2026/08/02 17:41 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 59cc142747536d1fa2ac1c53fa4bc31445791eb2\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Sun Aug 2 17:41:31 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/MAINTAINERS b/MAINTAINERS\nindex 2fb1c75afd163..73692b09bf7ba 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -29440,6 +29440,12 @@ S:\tMaintained\n T:\tgit git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git\n F:\tsound/hda/codecs/senarytech.c\n \n+ZTE DINGHAI ETHERNET DRIVER\n+M:\tJunyang Han \u003chan.junyang@zte.com.cn\u003e\n+L:\tnetdev@vger.kernel.org\n+S:\tMaintained\n+F:\tdrivers/net/ethernet/zte/\n+\n THE REST\n M:\tLinus Torvalds \u003ctorvalds@linux-foundation.org\u003e\n L:\tlinux-kernel@vger.kernel.org\ndiff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig\nindex b8f70e2a1763a..c2b6996b0cfe1 100644\n--- a/drivers/net/ethernet/Kconfig\n+++ b/drivers/net/ethernet/Kconfig\n@@ -188,5 +188,6 @@ source \"drivers/net/ethernet/wangxun/Kconfig\"\n source \"drivers/net/ethernet/wiznet/Kconfig\"\n source \"drivers/net/ethernet/xilinx/Kconfig\"\n source \"drivers/net/ethernet/xircom/Kconfig\"\n+source \"drivers/net/ethernet/zte/Kconfig\"\n \n endif # ETHERNET\ndiff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile\nindex 57344fec6ce04..a34bcbd4df4e9 100644\n--- a/drivers/net/ethernet/Makefile\n+++ b/drivers/net/ethernet/Makefile\n@@ -104,3 +104,4 @@ obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/\n obj-$(CONFIG_NET_VENDOR_SYNOPSYS) += synopsys/\n obj-$(CONFIG_NET_VENDOR_PENSANDO) += pensando/\n obj-$(CONFIG_OA_TC6) += oa_tc6.o\n+obj-$(CONFIG_NET_VENDOR_ZTE) += zte/\ndiff --git a/drivers/net/ethernet/zte/Kconfig b/drivers/net/ethernet/zte/Kconfig\nnew file mode 100644\nindex 0000000000000..b95c2fc7db77a\n--- /dev/null\n+++ b/drivers/net/ethernet/zte/Kconfig\n@@ -0,0 +1,20 @@\n+# SPDX-License-Identifier: GPL-2.0-only\n+#\n+# ZTE driver configuration\n+#\n+\n+config NET_VENDOR_ZTE\n+ bool \"ZTE devices\"\n+ default y\n+ help\n+ If you have a network (Ethernet) card belonging to this class, say Y.\n+ Note that the answer to this question doesn't directly affect the\n+ kernel: saying N will just cause the configurator to skip all\n+ the questions about Zte cards. If you say Y, you will be asked\n+ for your specific card in the following questions.\n+\n+if NET_VENDOR_ZTE\n+\n+source \"drivers/net/ethernet/zte/dinghai/Kconfig\"\n+\n+endif # NET_VENDOR_ZTE\ndiff --git a/drivers/net/ethernet/zte/Makefile b/drivers/net/ethernet/zte/Makefile\nnew file mode 100644\nindex 0000000000000..cd9929b61559c\n--- /dev/null\n+++ b/drivers/net/ethernet/zte/Makefile\n@@ -0,0 +1,6 @@\n+# SPDX-License-Identifier: GPL-2.0-only\n+#\n+# Makefile for the ZTE device drivers\n+#\n+\n+obj-$(CONFIG_DINGHAI) += dinghai/\ndiff --git a/drivers/net/ethernet/zte/dinghai/Kconfig b/drivers/net/ethernet/zte/dinghai/Kconfig\nnew file mode 100644\nindex 0000000000000..121be3bf7707f\n--- /dev/null\n+++ b/drivers/net/ethernet/zte/dinghai/Kconfig\n@@ -0,0 +1,34 @@\n+# SPDX-License-Identifier: GPL-2.0-only\n+#\n+# ZTE DingHai Ethernet driver configuration\n+#\n+\n+config DINGHAI\n+ bool \"ZTE DingHai Ethernet driver\"\n+ depends on PCI\n+ select NET_DEVLINK\n+ help\n+ This driver supports ZTE DingHai Ethernet devices.\n+\n+ DingHai is a high-performance Ethernet controller that supports\n+ multiple features including hardware offloading, SR-IOV, and\n+ advanced virtualization capabilities.\n+\n+ If you say Y here, you can select specific driver variants below.\n+\n+ If unsure, say N.\n+\n+if DINGHAI\n+\n+config DINGHAI_PF\n+ tristate \"ZTE DingHai PF (Physical Function) driver\"\n+ help\n+ This driver supports ZTE DingHai PCI Express Ethernet\n+ adapters (PF).\n+\n+ To compile this driver as a module, choose M here. The module\n+ will be named dinghai10e.\n+\n+ If unsure, say N.\n+\n+endif # DINGHAI\ndiff --git a/drivers/net/ethernet/zte/dinghai/Makefile b/drivers/net/ethernet/zte/dinghai/Makefile\nnew file mode 100644\nindex 0000000000000..e2f4da33df593\n--- /dev/null\n+++ b/drivers/net/ethernet/zte/dinghai/Makefile\n@@ -0,0 +1,7 @@\n+# SPDX-License-Identifier: GPL-2.0-only\n+#\n+# Makefile for ZTE DingHai Ethernet driver\n+#\n+\n+obj-$(CONFIG_DINGHAI_PF) += dinghai10e.o\n+dinghai10e-y := en_pf.o\ndiff --git a/drivers/net/ethernet/zte/dinghai/dh_queue.h b/drivers/net/ethernet/zte/dinghai/dh_queue.h\nnew file mode 100644\nindex 0000000000000..5b63895c1ea1e\n--- /dev/null\n+++ b/drivers/net/ethernet/zte/dinghai/dh_queue.h\n@@ -0,0 +1,56 @@\n+/* SPDX-License-Identifier: GPL-2.0-only */\n+/*\n+ * ZTE DingHai Ethernet driver - PCI capability definitions\n+ * Copyright (c) 2022-2026, ZTE Corporation.\n+ */\n+\n+#ifndef __DH_QUEUE_H__\n+#define __DH_QUEUE_H__\n+\n+#include \u003clinux/types.h\u003e\n+\n+/* This is the PCI capability header: */\n+struct zxdh_pf_pci_cap {\n+\t__u8 cap_vndr;\t\t/* Generic PCI field: PCI_CAP_ID_VNDR */\n+\t__u8 cap_next;\t\t/* Generic PCI field: next ptr. */\n+\t__u8 cap_len;\t\t/* Generic PCI field: capability length */\n+\t__u8 cfg_type;\t\t/* Identifies the structure. */\n+\t__u8 bar;\t\t/* Where to find it. */\n+\t__u8 id;\t\t/* Multiple capabilities of the same type */\n+\t__u8 padding[2];\t\t/* Pad to full dword. */\n+\t__le32 offset;\t\t/* Offset within bar. */\n+\t__le32 length;\t\t/* Length of the structure, in bytes. */\n+};\n+\n+/* Fields in ZXDH_PF_PCI_CAP_COMMON_CFG: */\n+struct zxdh_pf_pci_common_cfg {\n+\t/* About the whole device. */\n+\t__le32 device_feature_select; /* read-write */\n+\t__le32 device_feature;\t/* read-only */\n+\t__le32 guest_feature_select; /* read-write */\n+\t__le32 guest_feature;\t\t/* read-write */\n+\t__le16 msix_config;\t\t/* read-write */\n+\t__le16 num_queues;\t\t/* read-only */\n+\t__u8 device_status;\t\t/* read-write */\n+\t__u8 config_generation;\t/* read-only */\n+\n+\t/* About a specific virtqueue. */\n+\t__le16 queue_select;\t\t/* read-write */\n+\t__le16 queue_size;\t\t/* read-write, power of 2. */\n+\t__le16 queue_msix_vector;\t/* read-write */\n+\t__le16 queue_enable;\t\t/* read-write */\n+\t__le16 queue_notify_off;\t/* read-only */\n+\t__le32 queue_desc_lo;\t\t/* read-write */\n+\t__le32 queue_desc_hi;\t\t/* read-write */\n+\t__le32 queue_avail_lo;\t\t/* read-write */\n+\t__le32 queue_avail_hi;\t\t/* read-write */\n+\t__le32 queue_used_lo;\t\t/* read-write */\n+\t__le32 queue_used_hi;\t\t/* read-write */\n+};\n+\n+struct zxdh_pf_pci_notify_cap {\n+\tstruct zxdh_pf_pci_cap cap;\n+\t__le32 notify_off_multiplier; /* Multiplier for queue_notify_off. */\n+};\n+\n+#endif /* __DH_QUEUE_H__ */\ndiff --git a/drivers/net/ethernet/zte/dinghai/en_pf.c b/drivers/net/ethernet/zte/dinghai/en_pf.c\nnew file mode 100644\nindex 0000000000000..86d4374088203\n--- /dev/null\n+++ b/drivers/net/ethernet/zte/dinghai/en_pf.c\n@@ -0,0 +1,449 @@\n+// SPDX-License-Identifier: GPL-2.0-only\n+/*\n+ * ZTE DingHai Ethernet driver\n+ * Copyright (c) 2022-2026, ZTE Corporation.\n+ */\n+\n+#include \u003clinux/module.h\u003e\n+#include \u003clinux/pci.h\u003e\n+#include \u003cnet/devlink.h\u003e\n+#include \u003clinux/dma-mapping.h\u003e\n+#include \"en_pf.h\"\n+#include \"dh_queue.h\"\n+\n+MODULE_AUTHOR(\"Junyang Han \u003chan.junyang@zte.com.cn\u003e\");\n+MODULE_DESCRIPTION(\"ZTE DingHai series Ethernet driver\");\n+MODULE_LICENSE(\"GPL\");\n+\n+static const struct devlink_ops zxdh_pf_devlink_ops = {};\n+\n+static const struct pci_device_id zxdh_pf_pci_table[] = {\n+\t{ PCI_DEVICE(ZXDH_PF_VENDOR_ID, ZXDH_PF_DEVICE_ID) },\n+\t{ PCI_DEVICE(ZXDH_PF_VENDOR_ID, ZXDH_VF_DEVICE_ID) },\n+\t{ }\n+};\n+\n+MODULE_DEVICE_TABLE(pci, zxdh_pf_pci_table);\n+\n+void *zxdh_core_alloc_priv(struct zxdh_core_dev *zxdh_dev, size_t size)\n+{\n+\tvoid *priv = kzalloc(size, GFP_KERNEL);\n+\n+\tif (priv)\n+\t\tzxdh_dev-\u003epriv = priv;\n+\treturn priv;\n+}\n+\n+void zxdh_core_free_priv(struct zxdh_core_dev *zxdh_dev)\n+{\n+\tkfree(zxdh_dev-\u003epriv);\n+}\n+\n+static int zxdh_pf_pci_init(struct zxdh_core_dev *zxdh_dev)\n+{\n+\tstruct zxdh_pf_dev *pf_dev = zxdh_dev-\u003epriv;\n+\tint ret;\n+\n+\tpci_set_drvdata(zxdh_dev-\u003epdev, zxdh_dev);\n+\n+\tret = pci_enable_device(zxdh_dev-\u003epdev);\n+\tif (ret) {\n+\t\tdev_err(zxdh_dev-\u003edevice, \"pci_enable_device failed: %d\\n\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\tdma_set_mask_and_coherent(zxdh_dev-\u003edevice, DMA_BIT_MASK(64));\n+\n+\tret = pci_request_selected_regions(zxdh_dev-\u003epdev,\n+\t\t\t\t\t pci_select_bars(zxdh_dev-\u003epdev, IORESOURCE_MEM),\n+\t\t\t\t\t \"dh-pf\");\n+\tif (ret) {\n+\t\tdev_err(zxdh_dev-\u003edevice, \"pci_request_selected_regions failed: %d\\n\", ret);\n+\t\tgoto err_pci;\n+\t}\n+\n+\tpci_set_master(zxdh_dev-\u003epdev);\n+\tret = pci_save_state(zxdh_dev-\u003epdev);\n+\tif (ret) {\n+\t\tdev_err(zxdh_dev-\u003edevice, \"pci_save_state failed: %d\\n\", ret);\n+\t\tgoto err_pci_save_state;\n+\t}\n+\n+\tif (!(pci_resource_flags(zxdh_dev-\u003epdev, 0) \u0026 IORESOURCE_MEM)) {\n+\t\tret = -ENODEV;\n+\t\tdev_err(zxdh_dev-\u003edevice, \"BAR 0 is not an MMIO resource\\n\");\n+\t\tgoto err_pci_save_state;\n+\t}\n+\n+\tpf_dev-\u003epci_ioremap_addr[0] =\n+\t\tioremap(pci_resource_start(zxdh_dev-\u003epdev, 0),\n+\t\t\tpci_resource_len(zxdh_dev-\u003epdev, 0));\n+\tif (!pf_dev-\u003epci_ioremap_addr[0]) {\n+\t\tret = -ENOMEM;\n+\t\tdev_err(zxdh_dev-\u003edevice, \"dh pf pci ioremap failed\\n\");\n+\t\tgoto err_pci_save_state;\n+\t}\n+\n+\treturn 0;\n+\n+err_pci_save_state:\n+\tpci_release_selected_regions(zxdh_dev-\u003epdev,\n+\t\t\t\t pci_select_bars(zxdh_dev-\u003epdev, IORESOURCE_MEM));\n+err_pci:\n+\tpci_disable_device(zxdh_dev-\u003epdev);\n+\treturn ret;\n+}\n+\n+void zxdh_pf_pci_close(struct zxdh_core_dev *zxdh_dev)\n+{\n+\tstruct zxdh_pf_dev *pf_dev = zxdh_dev-\u003epriv;\n+\n+\tiounmap(pf_dev-\u003epci_ioremap_addr[0]);\n+\tpci_release_selected_regions(zxdh_dev-\u003epdev,\n+\t\t\t\t pci_select_bars(zxdh_dev-\u003epdev, IORESOURCE_MEM));\n+\tpci_disable_device(zxdh_dev-\u003epdev);\n+}\n+\n+int zxdh_pf_pci_find_capability(struct pci_dev *pdev, u8 cfg_type,\n+\t\t\t\tu32 ioresource_types, int *bars)\n+{\n+\tint pos;\n+\tu8 type;\n+\tu8 bar;\n+\n+\tfor (pos = pci_find_capability(pdev, PCI_CAP_ID_VNDR); pos \u003e 0;\n+\t pos = pci_find_next_capability(pdev, pos, PCI_CAP_ID_VNDR)) {\n+\t\tpci_read_config_byte(pdev,\n+\t\t\t\t pos + offsetof(struct zxdh_pf_pci_cap,\n+\t\t\t\t\t\t\tcfg_type), \u0026type);\n+\t\tpci_read_config_byte(pdev,\n+\t\t\t\t pos + offsetof(struct zxdh_pf_pci_cap, bar), \u0026bar);\n+\n+\t\t/* ignore structures with reserved BAR values */\n+\t\tif (bar \u003e ZXDH_PF_MAX_BAR_VAL)\n+\t\t\tcontinue;\n+\n+\t\tif (type == cfg_type) {\n+\t\t\tif (pci_resource_len(pdev, bar) \u0026\u0026\n+\t\t\t pci_resource_flags(pdev, bar) \u0026 ioresource_types) {\n+\t\t\t\t*bars |= (1 \u003c\u003c bar);\n+\t\t\t\treturn pos;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void __iomem *zxdh_pf_map_capability(struct zxdh_core_dev *zxdh_dev, int off,\n+\t\t\t\t size_t minlen, u32 align,\n+\t\t\t\t u32 start, u32 size,\n+\t\t\t\t size_t *len, resource_size_t *pa,\n+\t\t\t\t u32 *bar_off)\n+{\n+\tstruct pci_dev *pdev = zxdh_dev-\u003epdev;\n+\tvoid __iomem *p;\n+\tu32 offset;\n+\tu32 length;\n+\tu8 bar;\n+\n+\tpci_read_config_byte(pdev,\n+\t\t\t off + offsetof(struct zxdh_pf_pci_cap, bar), \u0026bar);\n+\n+\tif (bar \u003e ZXDH_PF_MAX_BAR_VAL) {\n+\t\tdev_err(zxdh_dev-\u003edevice, \"invalid bar %u\\n\", bar);\n+\t\treturn NULL;\n+\t}\n+\n+\tpci_read_config_dword(pdev,\n+\t\t\t off + offsetof(struct zxdh_pf_pci_cap,\n+\t\t\t\t\t\toffset), \u0026offset);\n+\tpci_read_config_dword(pdev,\n+\t\t\t off + offsetof(struct zxdh_pf_pci_cap,\n+\t\t\t\t\t\tlength), \u0026length);\n+\n+\tif (bar_off)\n+\t\t*bar_off = offset;\n+\n+\tif (length \u003c= start) {\n+\t\tdev_err(zxdh_dev-\u003edevice, \"bad capability len %u (\u003e%u expected)\\n\",\n+\t\t\tlength, start);\n+\t\treturn NULL;\n+\t}\n+\n+\tif (length - start \u003c minlen) {\n+\t\tdev_err(zxdh_dev-\u003edevice, \"bad capability len %u (\u003e=%zu expected)\\n\",\n+\t\t\tlength, minlen);\n+\t\treturn NULL;\n+\t}\n+\n+\tlength -= start;\n+\tif (start + offset \u003c offset) {\n+\t\tdev_err(zxdh_dev-\u003edevice, \"map wrap-around %u+%u\\n\", start, offset);\n+\t\treturn NULL;\n+\t}\n+\n+\toffset += start;\n+\tif (offset \u0026 (align - 1)) {\n+\t\tdev_err(zxdh_dev-\u003edevice, \"offset %u not aligned to %u\\n\", offset, align);\n+\t\treturn NULL;\n+\t}\n+\n+\tif (length \u003e size)\n+\t\tlength = size;\n+\n+\tif (len)\n+\t\t*len = length;\n+\n+\tif (length + offset \u003c offset ||\n+\t length + offset \u003e pci_resource_len(pdev, bar)) {\n+\t\tdev_err(zxdh_dev-\u003edevice,\n+\t\t\t\"map %u@%u out of range on bar %u length %lu\\n\",\n+\t\t\tlength, offset, bar,\n+\t\t\t(unsigned long)pci_resource_len(pdev, bar));\n+\t\treturn NULL;\n+\t}\n+\n+\tp = pci_iomap_range(pdev, bar, offset, length);\n+\tif (!p) {\n+\t\tdev_err(zxdh_dev-\u003edevice, \"unable to map custom queue %u@%u on bar %u\\n\",\n+\t\t\tlength, offset, bar);\n+\t} else if (pa) {\n+\t\t*pa = pci_resource_start(pdev, bar) + offset;\n+\t}\n+\n+\treturn p;\n+}\n+\n+int zxdh_pf_common_cfg_init(struct zxdh_core_dev *zxdh_dev)\n+{\n+\tstruct zxdh_pf_dev *pf_dev = zxdh_dev-\u003epriv;\n+\tstruct pci_dev *pdev = zxdh_dev-\u003epdev;\n+\tint common;\n+\n+\t/* check for a common config: if not, use legacy mode (bar 0). */\n+\tcommon = zxdh_pf_pci_find_capability(pdev, ZXDH_PCI_CAP_COMMON_CFG,\n+\t\t\t\t\t IORESOURCE_MEM,\n+\t\t\t\t\t \u0026pf_dev-\u003emodern_bars);\n+\tif (!common) {\n+\t\tdev_err(zxdh_dev-\u003edevice,\n+\t\t\t\"missing capabilities, leaving for legacy driver\\n\");\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tpf_dev-\u003ecommon = zxdh_pf_map_capability(zxdh_dev, common,\n+\t\t\t\t\t\tsizeof(struct zxdh_pf_pci_common_cfg),\n+\t\t\t\t\t\tZXDH_PF_ALIGN4, 0,\n+\t\t\t\t\t\tsizeof(struct zxdh_pf_pci_common_cfg),\n+\t\t\t\t\t\tNULL, NULL, NULL);\n+\tif (!pf_dev-\u003ecommon) {\n+\t\tdev_err(zxdh_dev-\u003edevice, \"pf_dev-\u003ecommon is null\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int zxdh_pf_notify_cfg_init(struct zxdh_core_dev *zxdh_dev)\n+{\n+\tstruct zxdh_pf_dev *pf_dev = zxdh_dev-\u003epriv;\n+\tstruct pci_dev *pdev = zxdh_dev-\u003epdev;\n+\tu32 notify_length;\n+\tu32 notify_offset;\n+\tint notify;\n+\n+\t/* If common is there, these should be too... */\n+\tnotify = zxdh_pf_pci_find_capability(pdev, ZXDH_PCI_CAP_NOTIFY_CFG,\n+\t\t\t\t\t IORESOURCE_MEM,\n+\t\t\t\t\t \u0026pf_dev-\u003emodern_bars);\n+\tif (!notify) {\n+\t\tdev_err(zxdh_dev-\u003edevice, \"missing notify cfg capability\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tpci_read_config_dword(pdev,\n+\t\t\t notify + offsetof(struct zxdh_pf_pci_notify_cap,\n+\t\t\t\tnotify_off_multiplier),\n+\t\t\u0026pf_dev-\u003enotify_offset_multiplier);\n+\tpci_read_config_dword(pdev,\n+\t\t\t notify + offsetof(struct zxdh_pf_pci_notify_cap,\n+\t\t\t\tcap.length), \u0026notify_length);\n+\tpci_read_config_dword(pdev,\n+\t\t\t notify + offsetof(struct zxdh_pf_pci_notify_cap,\n+\t\t\t\tcap.offset), \u0026notify_offset);\n+\n+\t/* We don't know how many VQs we'll map, ahead of the time.\n+\t * If notify length is small, map it all now. Otherwise,\n+\t * map each VQ individually later.\n+\t */\n+\tif (notify_length \u003c= PAGE_SIZE - (notify_offset % PAGE_SIZE)) {\n+\t\tpf_dev-\u003enotify_base = zxdh_pf_map_capability(zxdh_dev, notify,\n+\t\t\t\t\t\t\t ZXDH_PF_MAP_MINLEN2,\n+\t\t\t\t\t\t\t ZXDH_PF_ALIGN2, 0,\n+\t\t\t\t\t\t\t notify_length,\n+\t\t\t\t\t\t\t \u0026pf_dev-\u003enotify_len,\n+\t\t\t\t\t\t\t \u0026pf_dev-\u003enotify_pa, NULL);\n+\t\tif (!pf_dev-\u003enotify_base) {\n+\t\t\tdev_err(zxdh_dev-\u003edevice, \"pf_dev-\u003enotify_base is null\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t} else {\n+\t\tpf_dev-\u003enotify_map_cap = notify;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int zxdh_pf_device_cfg_init(struct zxdh_core_dev *zxdh_dev)\n+{\n+\tstruct zxdh_pf_dev *pf_dev = zxdh_dev-\u003epriv;\n+\tstruct pci_dev *pdev = zxdh_dev-\u003epdev;\n+\tint device;\n+\n+\t/* Device capability is only mandatory for\n+\t * devices that have device-specific configuration.\n+\t */\n+\tdevice = zxdh_pf_pci_find_capability(pdev, ZXDH_PCI_CAP_DEVICE_CFG,\n+\t\t\t\t\t IORESOURCE_MEM,\n+\t\t\t\t\t \u0026pf_dev-\u003emodern_bars);\n+\n+\t/* we don't know how much we should map,\n+\t * but PAGE_SIZE is more than enough for all existing devices.\n+\t */\n+\tif (device) {\n+\t\tpf_dev-\u003edevice = zxdh_pf_map_capability(zxdh_dev, device, 0,\n+\t\t\t\t\t\t\tZXDH_PF_ALIGN4, 0, PAGE_SIZE,\n+\t\t\t\t\t\t \u0026pf_dev-\u003edevice_len, NULL,\n+\t\t\t\t\t\t \u0026pf_dev-\u003edev_cfg_bar_off);\n+\t\tif (!pf_dev-\u003edevice) {\n+\t\t\tdev_err(zxdh_dev-\u003edevice, \"pf_dev-\u003edevice is null\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+void zxdh_pf_modern_cfg_uninit(struct zxdh_core_dev *zxdh_dev)\n+{\n+\tstruct zxdh_pf_dev *pf_dev = zxdh_dev-\u003epriv;\n+\tstruct pci_dev *pdev = zxdh_dev-\u003epdev;\n+\n+\tif (pf_dev-\u003edevice)\n+\t\tpci_iounmap(pdev, pf_dev-\u003edevice);\n+\tif (pf_dev-\u003enotify_base)\n+\t\tpci_iounmap(pdev, pf_dev-\u003enotify_base);\n+\tpci_iounmap(pdev, pf_dev-\u003ecommon);\n+}\n+\n+int zxdh_pf_modern_cfg_init(struct zxdh_core_dev *zxdh_dev)\n+{\n+\tstruct zxdh_pf_dev *pf_dev = zxdh_dev-\u003epriv;\n+\tstruct pci_dev *pdev = zxdh_dev-\u003epdev;\n+\tint ret;\n+\n+\tret = zxdh_pf_common_cfg_init(zxdh_dev);\n+\tif (ret) {\n+\t\tdev_err(zxdh_dev-\u003edevice, \"zxdh_pf_common_cfg_init failed: %d\\n\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\tret = zxdh_pf_notify_cfg_init(zxdh_dev);\n+\tif (ret) {\n+\t\tdev_err(zxdh_dev-\u003edevice, \"zxdh_pf_notify_cfg_init failed: %d\\n\", ret);\n+\t\tgoto err_map_notify;\n+\t}\n+\n+\tret = zxdh_pf_device_cfg_init(zxdh_dev);\n+\tif (ret) {\n+\t\tdev_err(zxdh_dev-\u003edevice, \"zxdh_pf_device_cfg_init failed: %d\\n\", ret);\n+\t\tgoto err_map_device;\n+\t}\n+\n+\treturn 0;\n+\n+err_map_device:\n+\tif (pf_dev-\u003enotify_base)\n+\t\tpci_iounmap(pdev, pf_dev-\u003enotify_base);\n+err_map_notify:\n+\tpci_iounmap(pdev, pf_dev-\u003ecommon);\n+\treturn ret;\n+}\n+\n+static int zxdh_pf_probe(struct pci_dev *pdev, const struct pci_device_id *id)\n+{\n+\tstruct zxdh_core_dev *zxdh_dev;\n+\tstruct zxdh_pf_dev *pf_dev;\n+\tstruct devlink *devlink;\n+\tint ret;\n+\n+\tdevlink = devlink_alloc(\u0026zxdh_pf_devlink_ops, sizeof(struct zxdh_core_dev),\n+\t\t\t\t\u0026pdev-\u003edev);\n+\tif (!devlink)\n+\t\treturn -ENOMEM;\n+\n+\tzxdh_dev = devlink_priv(devlink);\n+\tzxdh_dev-\u003edevice = \u0026pdev-\u003edev;\n+\tzxdh_dev-\u003epdev = pdev;\n+\tzxdh_dev-\u003edevlink = devlink;\n+\n+\tpf_dev = zxdh_core_alloc_priv(zxdh_dev, sizeof(*pf_dev));\n+\tif (!pf_dev) {\n+\t\tdev_err(\u0026pdev-\u003edev, \"zxdh_pf_dev alloc failed\\n\");\n+\t\tret = -ENOMEM;\n+\t\tgoto err_pf_dev;\n+\t}\n+\n+\tret = zxdh_pf_pci_init(zxdh_dev);\n+\tif (ret) {\n+\t\tdev_err(\u0026pdev-\u003edev, \"zxdh_pf_pci_init failed: %d\\n\", ret);\n+\t\tgoto err_pci_init;\n+\t}\n+\n+\tret = zxdh_pf_modern_cfg_init(zxdh_dev);\n+\tif (ret) {\n+\t\tdev_err(\u0026pdev-\u003edev, \"zxdh_pf_modern_cfg_init failed: %d\\n\", ret);\n+\t\tgoto err_cfg_init;\n+\t}\n+\n+\tdevlink_register(devlink);\n+\n+\treturn 0;\n+\n+err_cfg_init:\n+\tzxdh_pf_pci_close(zxdh_dev);\n+err_pci_init:\n+\tzxdh_core_free_priv(zxdh_dev);\n+err_pf_dev:\n+\tdevlink_free(devlink);\n+\treturn ret;\n+}\n+\n+static void zxdh_pf_remove(struct pci_dev *pdev)\n+{\n+\tstruct zxdh_core_dev *zxdh_dev = pci_get_drvdata(pdev);\n+\tstruct devlink *devlink = priv_to_devlink(zxdh_dev);\n+\n+\tdevlink_unregister(devlink);\n+\tzxdh_pf_modern_cfg_uninit(zxdh_dev);\n+\tzxdh_pf_pci_close(zxdh_dev);\n+\tzxdh_core_free_priv(zxdh_dev);\n+\tdevlink_free(devlink);\n+\tpci_set_drvdata(pdev, NULL);\n+}\n+\n+static void zxdh_pf_shutdown(struct pci_dev *pdev)\n+{\n+\tif (system_state == SYSTEM_POWER_OFF)\n+\t\tpci_set_power_state(pdev, PCI_D3hot);\n+\tpci_disable_device(pdev);\n+}\n+\n+static struct pci_driver zxdh_pf_driver = {\n+\t.name = \"dinghai10e\",\n+\t.id_table = zxdh_pf_pci_table,\n+\t.probe = zxdh_pf_probe,\n+\t.remove = zxdh_pf_remove,\n+\t.shutdown = zxdh_pf_shutdown,\n+};\n+\n+module_pci_driver(zxdh_pf_driver);\ndiff --git a/drivers/net/ethernet/zte/dinghai/en_pf.h b/drivers/net/ethernet/zte/dinghai/en_pf.h\nnew file mode 100644\nindex 0000000000000..7373dee8d1a9f\n--- /dev/null\n+++ b/drivers/net/ethernet/zte/dinghai/en_pf.h\n@@ -0,0 +1,75 @@\n+/* SPDX-License-Identifier: GPL-2.0-only */\n+/*\n+ * ZTE DingHai Ethernet driver - PF header\n+ * Copyright (c) 2022-2026, ZTE Corporation.\n+ */\n+\n+#ifndef __ZXDH_EN_PF_H__\n+#define __ZXDH_EN_PF_H__\n+\n+#include \u003clinux/types.h\u003e\n+\n+#define ZXDH_PF_VENDOR_ID\t0x1cf2\n+#define ZXDH_PF_DEVICE_ID\t0x8040\n+#define ZXDH_VF_DEVICE_ID\t0x8041\n+\n+/* Common configuration */\n+#define ZXDH_PCI_CAP_COMMON_CFG\t1\n+/* Notifications */\n+#define ZXDH_PCI_CAP_NOTIFY_CFG\t2\n+/* ISR access */\n+#define ZXDH_PCI_CAP_ISR_CFG\t\t3\n+/* Device specific configuration */\n+#define ZXDH_PCI_CAP_DEVICE_CFG\t4\n+/* PCI configuration access */\n+#define ZXDH_PCI_CAP_PCI_CFG\t\t5\n+\n+#define ZXDH_PF_MAX_BAR_VAL\t\t0x5\n+#define ZXDH_PF_ALIGN4\t\t\t4\n+#define ZXDH_PF_ALIGN2\t\t\t2\n+#define ZXDH_PF_MAP_MINLEN2\t\t2\n+\n+struct zxdh_core_dev {\n+\tstruct device *device;\n+\tstruct pci_dev *pdev;\n+\tstruct devlink *devlink;\n+\tvoid *priv;\n+};\n+\n+struct zxdh_pf_dev {\n+\tstruct zxdh_pf_pci_common_cfg __iomem *common;\n+\t/* Device-specific data (non-legacy mode) */\n+\t/* Base of vq notifications (non-legacy mode). */\n+\tvoid __iomem *device;\n+\tvoid __iomem *notify_base;\n+\t/* Physical base of vq notifications */\n+\tresource_size_t notify_pa;\n+\t/* So we can sanity-check accesses. */\n+\tsize_t notify_len;\n+\tsize_t device_len;\n+\t/* Capability for when we need to map notifications per-vq. */\n+\ts32 notify_map_cap;\n+\tu32 notify_offset_multiplier;\n+\t/* Multiply queue_notify_off by this value. (non-legacy mode). */\n+\ts32 modern_bars;\n+\tvoid __iomem *pci_ioremap_addr[6];\n+\tu32 dev_cfg_bar_off;\n+};\n+\n+void *zxdh_core_alloc_priv(struct zxdh_core_dev *zxdh_dev, size_t size);\n+void zxdh_core_free_priv(struct zxdh_core_dev *zxdh_dev);\n+void zxdh_pf_pci_close(struct zxdh_core_dev *zxdh_dev);\n+int zxdh_pf_pci_find_capability(struct pci_dev *pdev, u8 cfg_type,\n+\t\t\t\tu32 ioresource_types, int *bars);\n+void __iomem *zxdh_pf_map_capability(struct zxdh_core_dev *zxdh_dev, int off,\n+\t\t\t\t size_t minlen, u32 align,\n+\t\t\t\t u32 start, u32 size,\n+\t\t\t\t size_t *len, resource_size_t *pa,\n+\t\t\t\t u32 *bar_off);\n+int zxdh_pf_common_cfg_init(struct zxdh_core_dev *zxdh_dev);\n+int zxdh_pf_notify_cfg_init(struct zxdh_core_dev *zxdh_dev);\n+int zxdh_pf_device_cfg_init(struct zxdh_core_dev *zxdh_dev);\n+void zxdh_pf_modern_cfg_uninit(struct zxdh_core_dev *zxdh_dev);\n+int zxdh_pf_modern_cfg_init(struct zxdh_core_dev *zxdh_dev);\n+\n+#endif /* __ZXDH_EN_PF_H__ */\n"
} |
| 2/1 | 2026/08/02 17:41 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch introduces a new vendor-specific PCIe Ethernet driver (ZTE DingHai). This driver requires physical PCIe hardware that is not emulated in standard QEMU, making it unreachable and untestable in virtualized fuzzing environments.",
"WorthFuzzing": false
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). - Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU. - Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove) that are executed only during PCI hot-unplug or sysfs driver unbind operations. If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. Prefer non-static, non-inlined API entrypoint functions over internal static helper functions (which are inlined by the compiler and do not have distinct symbol addresses). 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 59cc142747536d1fa2ac1c53fa4bc31445791eb2
Author: syz-cluster <triage@syzkaller.com>
Date: Sun Aug 2 17:41:31 2026 +0000
syz-cluster: applied patch under review
diff --git a/MAINTAINERS b/MAINTAINERS
index 2fb1c75afd163..73692b09bf7ba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -29440,6 +29440,12 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
F: sound/hda/codecs/senarytech.c
+ZTE DINGHAI ETHERNET DRIVER
+M: Junyang Han <han.junyang@zte.com.cn>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/ethernet/zte/
+
THE REST
M: Linus Torvalds <torvalds@linux-foundation.org>
L: linux-kernel@vger.kernel.org
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index b8f70e2a1763a..c2b6996b0cfe1 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -188,5 +188,6 @@ source "drivers/net/ethernet/wangxun/Kconfig"
source "drivers/net/ethernet/wiznet/Kconfig"
source "drivers/net/ethernet/xilinx/Kconfig"
source "drivers/net/ethernet/xircom/Kconfig"
+source "drivers/net/ethernet/zte/Kconfig"
endif # ETHERNET
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index 57344fec6ce04..a34bcbd4df4e9 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -104,3 +104,4 @@ obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/
obj-$(CONFIG_NET_VENDOR_SYNOPSYS) += synopsys/
obj-$(CONFIG_NET_VENDOR_PENSANDO) += pensando/
obj-$(CONFIG_OA_TC6) += oa_tc6.o
+obj-$(CONFIG_NET_VENDOR_ZTE) += zte/
diff --git a/drivers/net/ethernet/zte/Kconfig b/drivers/net/ethernet/zte/Kconfig
new file mode 100644
index 0000000000000..b95c2fc7db77a
--- /dev/null
+++ b/drivers/net/ethernet/zte/Kconfig
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# ZTE driver configuration
+#
+
+config NET_VENDOR_ZTE
+ bool "ZTE devices"
+ default y
+ help
+ If you have a network (Ethernet) card belonging to this class, say Y.
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Zte cards. If you say Y, you will be asked
+ for your specific card in the following questions.
+
+if NET_VENDOR_ZTE
+
+source "drivers/net/ethernet/zte/dinghai/Kconfig"
+
+endif # NET_VENDOR_ZTE
diff --git a/drivers/net/ethernet/zte/Makefile b/drivers/net/ethernet/zte/Makefile
new file mode 100644
index 0000000000000..cd9929b61559c
--- /dev/null
+++ b/drivers/net/ethernet/zte/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Makefile for the ZTE device drivers
+#
+
+obj-$(CONFIG_DINGHAI) += dinghai/
diff --git a/drivers/net/ethernet/zte/dinghai/Kconfig b/drivers/net/ethernet/zte/dinghai/Kconfig
new file mode 100644
index 0000000000000..121be3bf7707f
--- /dev/null
+++ b/drivers/net/ethernet/zte/dinghai/Kconfig
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# ZTE DingHai Ethernet driver configuration
+#
+
+config DINGHAI
+ bool "ZTE DingHai Ethernet driver"
+ depends on PCI
+ select NET_DEVLINK
+ help
+ This driver supports ZTE DingHai Ethernet devices.
+
+ DingHai is a high-performance Ethernet controller that supports
+ multiple features including hardware offloading, SR-IOV, and
+ advanced virtualization capabilities.
+
+ If you say Y here, you can select specific driver variants below.
+
+ If unsure, say N.
+
+if DINGHAI
+
+config DINGHAI_PF
+ tristate "ZTE DingHai PF (Physical Function) driver"
+ help
+ This driver supports ZTE DingHai PCI Express Ethernet
+ adapters (PF).
+
+ To compile this driver as a module, choose M here. The module
+ will be named dinghai10e.
+
+ If unsure, say N.
+
+endif # DINGHAI
diff --git a/drivers/net/ethernet/zte/dinghai/Makefile b/drivers/net/ethernet/zte/dinghai/Makefile
new file mode 100644
index 0000000000000..e2f4da33df593
--- /dev/null
+++ b/drivers/net/ethernet/zte/dinghai/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Makefile for ZTE DingHai Ethernet driver
+#
+
+obj-$(CONFIG_DINGHAI_PF) += dinghai10e.o
+dinghai10e-y := en_pf.o
diff --git a/drivers/net/ethernet/zte/dinghai/dh_queue.h b/drivers/net/ethernet/zte/dinghai/dh_queue.h
new file mode 100644
index 0000000000000..5b63895c1ea1e
--- /dev/null
+++ b/drivers/net/ethernet/zte/dinghai/dh_queue.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * ZTE DingHai Ethernet driver - PCI capability definitions
+ * Copyright (c) 2022-2026, ZTE Corporation.
+ */
+
+#ifndef __DH_QUEUE_H__
+#define __DH_QUEUE_H__
+
+#include <linux/types.h>
+
+/* This is the PCI capability header: */
+struct zxdh_pf_pci_cap {
+ __u8 cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */
+ __u8 cap_next; /* Generic PCI field: next ptr. */
+ __u8 cap_len; /* Generic PCI field: capability length */
+ __u8 cfg_type; /* Identifies the structure. */
+ __u8 bar; /* Where to find it. */
+ __u8 id; /* Multiple capabilities of the same type */
+ __u8 padding[2]; /* Pad to full dword. */
+ __le32 offset; /* Offset within bar. */
+ __le32 length; /* Length of the structure, in bytes. */
+};
+
+/* Fields in ZXDH_PF_PCI_CAP_COMMON_CFG: */
+struct zxdh_pf_pci_common_cfg {
+ /* About the whole device. */
+ __le32 device_feature_select; /* read-write */
+ __le32 device_feature; /* read-only */
+ __le32 guest_feature_select; /* read-write */
+ __le32 guest_feature; /* read-write */
+ __le16 msix_config; /* read-write */
+ __le16 num_queues; /* read-only */
+ __u8 device_status; /* read-write */
+ __u8 config_generation; /* read-only */
+
+ /* About a specific virtqueue. */
+ __le16 queue_select; /* read-write */
+ __le16 queue_size; /* read-write, power of 2. */
+ __le16 queue_msix_vector; /* read-write */
+ __le16 queue_enable; /* read-write */
+ __le16 queue_notify_off; /* read-only */
+ __le32 queue_desc_lo; /* read-write */
+ __le32 queue_desc_hi; /* read-write */
+ __le32 queue_avail_lo; /* read-write */
+ __le32 queue_avail_hi; /* read-write */
+ __le32 queue_used_lo; /* read-write */
+ __le32 queue_used_hi; /* read-write */
+};
+
+struct zxdh_pf_pci_notify_cap {
+ struct zxdh_pf_pci_cap cap;
+ __le32 notify_off_multiplier; /* Multiplier for queue_notify_off. */
+};
+
+#endif /* __DH_QUEUE_H__ */
diff --git a/drivers/net/ethernet/zte/dinghai/en_pf.c b/drivers/net/ethernet/zte/dinghai/en_pf.c
new file mode 100644
index 0000000000000..86d4374088203
--- /dev/null
+++ b/drivers/net/ethernet/zte/dinghai/en_pf.c
@@ -0,0 +1,449 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ZTE DingHai Ethernet driver
+ * Copyright (c) 2022-2026, ZTE Corporation.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <net/devlink.h>
+#include <linux/dma-mapping.h>
+#include "en_pf.h"
+#include "dh_queue.h"
+
+MODULE_AUTHOR("Junyang Han <han.junyang@zte.com.cn>");
+MODULE_DESCRIPTION("ZTE DingHai series Ethernet driver");
+MODULE_LICENSE("GPL");
+
+static const struct devlink_ops zxdh_pf_devlink_ops = {};
+
+static const struct pci_device_id zxdh_pf_pci_table[] = {
+ { PCI_DEVICE(ZXDH_PF_VENDOR_ID, ZXDH_PF_DEVICE_ID) },
+ { PCI_DEVICE(ZXDH_PF_VENDOR_ID, ZXDH_VF_DEVICE_ID) },
+ { }
+};
+
+MODULE_DEVICE_TABLE(pci, zxdh_pf_pci_table);
+
+void *zxdh_core_alloc_priv(struct zxdh_core_dev *zxdh_dev, size_t size)
+{
+ void *priv = kzalloc(size, GFP_KERNEL);
+
+ if (priv)
+ zxdh_dev->priv = priv;
+ return priv;
+}
+
+void zxdh_core_free_priv(struct zxdh_core_dev *zxdh_dev)
+{
+ kfree(zxdh_dev->priv);
+}
+
+static int zxdh_pf_pci_init(struct zxdh_core_dev *zxdh_dev)
+{
+ struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
+ int ret;
+
+ pci_set_drvdata(zxdh_dev->pdev, zxdh_dev);
+
+ ret = pci_enable_device(zxdh_dev->pdev);
+ if (ret) {
+ dev_err(zxdh_dev->device, "pci_enable_device failed: %d\n", ret);
+ return ret;
+ }
+
+ dma_set_mask_and_coherent(zxdh_dev->device, DMA_BIT_MASK(64));
+
+ ret = pci_request_selected_regions(zxdh_dev->pdev,
+ pci_select_bars(zxdh_dev->pdev, IORESOURCE_MEM),
+ "dh-pf");
+ if (ret) {
+ dev_err(zxdh_dev->device, "pci_request_selected_regions failed: %d\n", ret);
+ goto err_pci;
+ }
+
+ pci_set_master(zxdh_dev->pdev);
+ ret = pci_save_state(zxdh_dev->pdev);
+ if (ret) {
+ dev_err(zxdh_dev->device, "pci_save_state failed: %d\n", ret);
+ goto err_pci_save_state;
+ }
+
+ if (!(pci_resource_flags(zxdh_dev->pdev, 0) & IORESOURCE_MEM)) {
+ ret = -ENODEV;
+ dev_err(zxdh_dev->device, "BAR 0 is not an MMIO resource\n");
+ goto err_pci_save_state;
+ }
+
+ pf_dev->pci_ioremap_addr[0] =
+ ioremap(pci_resource_start(zxdh_dev->pdev, 0),
+ pci_resource_len(zxdh_dev->pdev, 0));
+ if (!pf_dev->pci_ioremap_addr[0]) {
+ ret = -ENOMEM;
+ dev_err(zxdh_dev->device, "dh pf pci ioremap failed\n");
+ goto err_pci_save_state;
+ }
+
+ return 0;
+
+err_pci_save_state:
+ pci_release_selected_regions(zxdh_dev->pdev,
+ pci_select_bars(zxdh_dev->pdev, IORESOURCE_MEM));
+err_pci:
+ pci_disable_device(zxdh_dev->pdev);
+ return ret;
+}
+
+void zxdh_pf_pci_close(struct zxdh_core_dev *zxdh_dev)
+{
+ struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
+
+ iounmap(pf_dev->pci_ioremap_addr[0]);
+ pci_release_selected_regions(zxdh_dev->pdev,
+ pci_select_bars(zxdh_dev->pdev, IORESOURCE_MEM));
+ pci_disable_device(zxdh_dev->pdev);
+}
+
+int zxdh_pf_pci_find_capability(struct pci_dev *pdev, u8 cfg_type,
+ u32 ioresource_types, int *bars)
+{
+ int pos;
+ u8 type;
+ u8 bar;
+
+ for (pos = pci_find_capability(pdev, PCI_CAP_ID_VNDR); pos > 0;
+ pos = pci_find_next_capability(pdev, pos, PCI_CAP_ID_VNDR)) {
+ pci_read_config_byte(pdev,
+ pos + offsetof(struct zxdh_pf_pci_cap,
+ cfg_type), &type);
+ pci_read_config_byte(pdev,
+ pos + offsetof(struct zxdh_pf_pci_cap, bar), &bar);
+
+ /* ignore structures with reserved BAR values */
+ if (bar > ZXDH_PF_MAX_BAR_VAL)
+ continue;
+
+ if (type == cfg_type) {
+ if (pci_resource_len(pdev, bar) &&
+ pci_resource_flags(pdev, bar) & ioresource_types) {
+ *bars |= (1 << bar);
+ return pos;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void __iomem *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)
+{
+ struct pci_dev *pdev = zxdh_dev->pdev;
+ void __iomem *p;
+ u32 offset;
+ u32 length;
+ u8 bar;
+
+ pci_read_config_byte(pdev,
+ off + offsetof(struct zxdh_pf_pci_cap, bar), &bar);
+
+ if (bar > ZXDH_PF_MAX_BAR_VAL) {
+ dev_err(zxdh_dev->device, "invalid bar %u\n", bar);
+ return NULL;
+ }
+
+ pci_read_config_dword(pdev,
+ off + offsetof(struct zxdh_pf_pci_cap,
+ offset), &offset);
+ pci_read_config_dword(pdev,
+ off + offsetof(struct zxdh_pf_pci_cap,
+ length), &length);
+
+ if (bar_off)
+ *bar_off = offset;
+
+ if (length <= start) {
+ dev_err(zxdh_dev->device, "bad capability len %u (>%u expected)\n",
+ length, start);
+ return NULL;
+ }
+
+ if (length - start < minlen) {
+ dev_err(zxdh_dev->device, "bad capability len %u (>=%zu expected)\n",
+ length, minlen);
+ return NULL;
+ }
+
+ length -= start;
+ if (start + offset < offset) {
+ dev_err(zxdh_dev->device, "map wrap-around %u+%u\n", start, offset);
+ return NULL;
+ }
+
+ offset += start;
+ if (offset & (align - 1)) {
+ dev_err(zxdh_dev->device, "offset %u not aligned to %u\n", offset, align);
+ return NULL;
+ }
+
+ if (length > size)
+ length = size;
+
+ if (len)
+ *len = length;
+
+ if (length + offset < offset ||
+ length + offset > pci_resource_len(pdev, bar)) {
+ dev_err(zxdh_dev->device,
+ "map %u@%u out of range on bar %u length %lu\n",
+ length, offset, bar,
+ (unsigned long)pci_resource_len(pdev, bar));
+ return NULL;
+ }
+
+ p = pci_iomap_range(pdev, bar, offset, length);
+ if (!p) {
+ dev_err(zxdh_dev->device, "unable to map custom queue %u@%u on bar %u\n",
+ length, offset, bar);
+ } else if (pa) {
+ *pa = pci_resource_start(pdev, bar) + offset;
+ }
+
+ return p;
+}
+
+int zxdh_pf_common_cfg_init(struct zxdh_core_dev *zxdh_dev)
+{
+ struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
+ struct pci_dev *pdev = zxdh_dev->pdev;
+ int common;
+
+ /* check for a common config: if not, use legacy mode (bar 0). */
+ common = zxdh_pf_pci_find_capability(pdev, ZXDH_PCI_CAP_COMMON_CFG,
+ IORESOURCE_MEM,
+ &pf_dev->modern_bars);
+ if (!common) {
+ dev_err(zxdh_dev->device,
+ "missing capabilities, leaving for legacy driver\n");
+ return -ENODEV;
+ }
+
+ pf_dev->common = zxdh_pf_map_capability(zxdh_dev, common,
+ sizeof(struct zxdh_pf_pci_common_cfg),
+ ZXDH_PF_ALIGN4, 0,
+ sizeof(struct zxdh_pf_pci_common_cfg),
+ NULL, NULL, NULL);
+ if (!pf_dev->common) {
+ dev_err(zxdh_dev->device, "pf_dev->common is null\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int zxdh_pf_notify_cfg_init(struct zxdh_core_dev *zxdh_dev)
+{
+ struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
+ struct pci_dev *pdev = zxdh_dev->pdev;
+ u32 notify_length;
+ u32 notify_offset;
+ int notify;
+
+ /* If common is there, these should be too... */
+ notify = zxdh_pf_pci_find_capability(pdev, ZXDH_PCI_CAP_NOTIFY_CFG,
+ IORESOURCE_MEM,
+ &pf_dev->modern_bars);
+ if (!notify) {
+ dev_err(zxdh_dev->device, "missing notify cfg capability\n");
+ return -EINVAL;
+ }
+
+ pci_read_config_dword(pdev,
+ notify + offsetof(struct zxdh_pf_pci_notify_cap,
+ notify_off_multiplier),
+ &pf_dev->notify_offset_multiplier);
+ pci_read_config_dword(pdev,
+ notify + offsetof(struct zxdh_pf_pci_notify_cap,
+ cap.length), ¬ify_length);
+ pci_read_config_dword(pdev,
+ notify + offsetof(struct zxdh_pf_pci_notify_cap,
+ cap.offset), ¬ify_offset);
+
+ /* We don't know how many VQs we'll map, ahead of the time.
+ * If notify length is small, map it all now. Otherwise,
+ * map each VQ individually later.
+ */
+ if (notify_length <= PAGE_SIZE - (notify_offset % PAGE_SIZE)) {
+ pf_dev->notify_base = zxdh_pf_map_capability(zxdh_dev, notify,
+ ZXDH_PF_MAP_MINLEN2,
+ ZXDH_PF_ALIGN2, 0,
+ notify_length,
+ &pf_dev->notify_len,
+ &pf_dev->notify_pa, NULL);
+ if (!pf_dev->notify_base) {
+ dev_err(zxdh_dev->device, "pf_dev->notify_base is null\n");
+ return -EINVAL;
+ }
+ } else {
+ pf_dev->notify_map_cap = notify;
+ }
+
+ return 0;
+}
+
+int zxdh_pf_device_cfg_init(struct zxdh_core_dev *zxdh_dev)
+{
+ struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
+ struct pci_dev *pdev = zxdh_dev->pdev;
+ int device;
+
+ /* Device capability is only mandatory for
+ * devices that have device-specific configuration.
+ */
+ device = zxdh_pf_pci_find_capability(pdev, ZXDH_PCI_CAP_DEVICE_CFG,
+ IORESOURCE_MEM,
+ &pf_dev->modern_bars);
+
+ /* we don't know how much we should map,
+ * but PAGE_SIZE is more than enough for all existing devices.
+ */
+ if (device) {
+ pf_dev->device = zxdh_pf_map_capability(zxdh_dev, device, 0,
+ ZXDH_PF_ALIGN4, 0, PAGE_SIZE,
+ &pf_dev->device_len, NULL,
+ &pf_dev->dev_cfg_bar_off);
+ if (!pf_dev->device) {
+ dev_err(zxdh_dev->device, "pf_dev->device is null\n");
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+void zxdh_pf_modern_cfg_uninit(struct zxdh_core_dev *zxdh_dev)
+{
+ struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
+ struct pci_dev *pdev = zxdh_dev->pdev;
+
+ if (pf_dev->device)
+ pci_iounmap(pdev, pf_dev->device);
+ if (pf_dev->notify_base)
+ pci_iounmap(pdev, pf_dev->notify_base);
+ pci_iounmap(pdev, pf_dev->common);
+}
+
+int zxdh_pf_modern_cfg_init(struct zxdh_core_dev *zxdh_dev)
+{
+ struct zxdh_pf_dev *pf_dev = zxdh_dev->priv;
+ struct pci_dev *pdev = zxdh_dev->pdev;
+ int ret;
+
+ ret = zxdh_pf_common_cfg_init(zxdh_dev);
+ if (ret) {
+ dev_err(zxdh_dev->device, "zxdh_pf_common_cfg_init failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = zxdh_pf_notify_cfg_init(zxdh_dev);
+ if (ret) {
+ dev_err(zxdh_dev->device, "zxdh_pf_notify_cfg_init failed: %d\n", ret);
+ goto err_map_notify;
+ }
+
+ ret = zxdh_pf_device_cfg_init(zxdh_dev);
+ if (ret) {
+ dev_err(zxdh_dev->device, "zxdh_pf_device_cfg_init failed: %d\n", ret);
+ goto err_map_device;
+ }
+
+ return 0;
+
+err_map_device:
+ if (pf_dev->notify_base)
+ pci_iounmap(pdev, pf_dev->notify_base);
+err_map_notify:
+ pci_iounmap(pdev, pf_dev->common);
+ return ret;
+}
+
+static int zxdh_pf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct zxdh_core_dev *zxdh_dev;
+ struct zxdh_pf_dev *pf_dev;
+ struct devlink *devlink;
+ int ret;
+
+ devlink = devlink_alloc(&zxdh_pf_devlink_ops, sizeof(struct zxdh_core_dev),
+ &pdev->dev);
+ if (!devlink)
+ return -ENOMEM;
+
+ zxdh_dev = devlink_priv(devlink);
+ zxdh_dev->device = &pdev->dev;
+ zxdh_dev->pdev = pdev;
+ zxdh_dev->devlink = devlink;
+
+ pf_dev = zxdh_core_alloc_priv(zxdh_dev, sizeof(*pf_dev));
+ if (!pf_dev) {
+ dev_err(&pdev->dev, "zxdh_pf_dev alloc failed\n");
+ ret = -ENOMEM;
+ goto err_pf_dev;
+ }
+
+ ret = zxdh_pf_pci_init(zxdh_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "zxdh_pf_pci_init failed: %d\n", ret);
+ goto err_pci_init;
+ }
+
+ ret = zxdh_pf_modern_cfg_init(zxdh_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "zxdh_pf_modern_cfg_init failed: %d\n", ret);
+ goto err_cfg_init;
+ }
+
+ devlink_register(devlink);
+
+ return 0;
+
+err_cfg_init:
+ zxdh_pf_pci_close(zxdh_dev);
+err_pci_init:
+ zxdh_core_free_priv(zxdh_dev);
+err_pf_dev:
+ devlink_free(devlink);
+ return ret;
+}
+
+static void zxdh_pf_remove(struct pci_dev *pdev)
+{
+ struct zxdh_core_dev *zxdh_dev = pci_get_drvdata(pdev);
+ struct devlink *devlink = priv_to_devlink(zxdh_dev);
+
+ devlink_unregister(devlink);
+ zxdh_pf_modern_cfg_uninit(zxdh_dev);
+ zxdh_pf_pci_close(zxdh_dev);
+ zxdh_core_free_priv(zxdh_dev);
+ devlink_free(devlink);
+ pci_set_drvdata(pdev, NULL);
+}
+
+static void zxdh_pf_shutdown(struct pci_dev *pdev)
+{
+ if (system_state == SYSTEM_POWER_OFF)
+ pci_set_power_state(pdev, PCI_D3hot);
+ pci_disable_device(pdev);
+}
+
+static struct pci_driver zxdh_pf_driver = {
+ .name = "dinghai10e",
+ .id_table = zxdh_pf_pci_table,
+ .probe = zxdh_pf_probe,
+ .remove = zxdh_pf_remove,
+ .shutdown = zxdh_pf_shutdown,
+};
+
+module_pci_driver(zxdh_pf_driver);
diff --git a/drivers/net/ethernet/zte/dinghai/en_pf.h b/drivers/net/ethernet/zte/dinghai/en_pf.h
new file mode 100644
index 0000000000000..7373dee8d1a9f
--- /dev/null
+++ b/drivers/net/ethernet/zte/dinghai/en_pf.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * ZTE DingHai Ethernet driver - PF header
+ * Copyright (c) 2022-2026, ZTE Corporation.
+ */
+
+#ifndef __ZXDH_EN_PF_H__
+#define __ZXDH_EN_PF_H__
+
+#include <linux/types.h>
+
+#define ZXDH_PF_VENDOR_ID 0x1cf2
+#define ZXDH_PF_DEVICE_ID 0x8040
+#define ZXDH_VF_DEVICE_ID 0x8041
+
+/* Common configuration */
+#define ZXDH_PCI_CAP_COMMON_CFG 1
+/* Notifications */
+#define ZXDH_PCI_CAP_NOTIFY_CFG 2
+/* ISR access */
+#define ZXDH_PCI_CAP_ISR_CFG 3
+/* Device specific configuration */
+#define ZXDH_PCI_CAP_DEVICE_CFG 4
+/* PCI configuration access */
+#define ZXDH_PCI_CAP_PCI_CFG 5
+
+#define ZXDH_PF_MAX_BAR_VAL 0x5
+#define ZXDH_PF_ALIGN4 4
+#define ZXDH_PF_ALIGN2 2
+#define ZXDH_PF_MAP_MINLEN2 2
+
+struct zxdh_core_dev {
+ struct device *device;
+ struct pci_dev *pdev;
+ struct devlink *devlink;
+ void *priv;
+};
+
+struct zxdh_pf_dev {
+ struct zxdh_pf_pci_common_cfg __iomem *common;
+ /* Device-specific data (non-legacy mode) */
+ /* Base of vq notifications (non-legacy mode). */
+ void __iomem *device;
+ void __iomem *notify_base;
+ /* Physical base of vq notifications */
+ resource_size_t notify_pa;
+ /* So we can sanity-check accesses. */
+ size_t notify_len;
+ size_t device_len;
+ /* Capability for when we need to map notifications per-vq. */
+ s32 notify_map_cap;
+ u32 notify_offset_multiplier;
+ /* Multiply queue_notify_off by this value. (non-legacy mode). */
+ s32 modern_bars;
+ void __iomem *pci_ioremap_addr[6];
+ u32 dev_cfg_bar_off;
+};
+
+void *zxdh_core_alloc_priv(struct zxdh_core_dev *zxdh_dev, size_t size);
+void zxdh_core_free_priv(struct zxdh_core_dev *zxdh_dev);
+void zxdh_pf_pci_close(struct zxdh_core_dev *zxdh_dev);
+int zxdh_pf_pci_find_capability(struct pci_dev *pdev, u8 cfg_type,
+ u32 ioresource_types, int *bars);
+void __iomem *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);
+int zxdh_pf_common_cfg_init(struct zxdh_core_dev *zxdh_dev);
+int zxdh_pf_notify_cfg_init(struct zxdh_core_dev *zxdh_dev);
+int zxdh_pf_device_cfg_init(struct zxdh_core_dev *zxdh_dev);
+void zxdh_pf_modern_cfg_uninit(struct zxdh_core_dev *zxdh_dev);
+int zxdh_pf_modern_cfg_init(struct zxdh_core_dev *zxdh_dev);
+
+#endif /* __ZXDH_EN_PF_H__ */
|
| 3/2 | 2026/08/02 17:41 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11049 output: 78 thoughts: 532 Thoughts: **WorthFuzzing Decision for the ZTE DingHai Ethernet Driver** Okay, let's break this down. We've got a new patch introducing a driver for ZTE DingHai Ethernet devices. It's sitting in `drivers/net/ethernet/zte/dinghai/` and is a PCI driver specifically, named `dinghai10e`. My initial scan shows the driver sets up some PCI capabilities, devlink and seems to be a basic PCI driver probe. No netdev registration at this point. Now, according to the directions, I need to check if this is worth fuzzing. The instructions tell me to flag it as `WorthFuzzing=false` if the patch *only* contains code in specific driver types. Specifically, it highlights "vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU". Aha! This is a ZTE DingHai Ethernet driver. It's a vendor-specific PCIe NIC driver. The question is, is this emulated in QEMU? I doubt it. There's no indication that this hardware is supported or emulated within the standard QEMU environment. The instructions are pretty explicit on this point. Let me confirm the driver's nature. Yes, it's a ZTE DingHai Ethernet driver. It's referencing `CONFIG_DINGHAI_PF` and uses `PCI_DEVICE` macro with vendor ID 0x1cf2 and device ID 0x8040. So we are talking about a vendor-specific PCI device, with a specific hardware configuration. This confirms the requirement for a physical PCIe card. It's not something I can just spin up in QEMU. Therefore, since this driver requires physical PCIe hardware not emulated, the `WorthFuzzing` should be false. This aligns perfectly with the instructions I received. I'm confident in saying that the current patch falls into the "vendor-specific PCIe" category as described. So, I'll go ahead and set `WorthFuzzing=false` and provide the reasoning that it is a vendor-specific PCIe driver for hardware not emulated in standard QEMU. |
| 4/2 | 2026/08/02 17:41 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch introduces a new vendor-specific PCIe Ethernet driver (ZTE DingHai). This driver requires physical PCIe hardware that is not emulated in standard QEMU, making it unreachable and untestable in virtualized fuzzing environments.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch introduces a new vendor-specific PCIe Ethernet driver (ZTE DingHai). This driver requires physical PCIe hardware that is not emulated in standard QEMU, making it unreachable and untestable in virtualized fuzzing environments.",
"WorthFuzzing": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|