| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/13 17:22 | flow | patch-triage |
1mArgs:null Results: {
"EnableConfigs": [
"DAP8211R_PHY"
],
"FocusSymbols": [
"dap8211r_probe",
"dap8211r_config_init",
"pkg_gen_write",
"info_show",
"pkg_gen_show"
],
"Reasoning": "The patch introduces a new Ethernet PHY driver for DAPU Telecom DAP8211R(I). The driver can be probed in a virtualized environment by emulating a USB Ethernet device that registers an MDIO bus and responds to MDIO reads with the DAP8211R PHY ID. Once probed, the driver's `config_init` and debugfs operations (`info_show`, `pkg_gen_show`, `pkg_gen_write`) can be exercised by userspace.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/13 17:22 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 3346f71500b6a7bb1b05a83b822819f14966dad1\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Mon Jul 13 17:22:46 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/Documentation/devicetree/bindings/net/dapu,dap8211r.yaml b/Documentation/devicetree/bindings/net/dapu,dap8211r.yaml\nnew file mode 100644\nindex 00000000000000..208a82f779d61e\n--- /dev/null\n+++ b/Documentation/devicetree/bindings/net/dapu,dap8211r.yaml\n@@ -0,0 +1,78 @@\n+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)\n+%YAML 1.2\n+---\n+$id: http://devicetree.org/schemas/net/dapu,dap8211r.yaml#\n+$schema: http://devicetree.org/meta-schemas/core.yaml#\n+\n+title: DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY\n+\n+maintainers:\n+ - Artem Shimko \u003ca.shimko.dev@gmail.com\u003e\n+\n+description: |\n+ The DAP8211R(I) is a Gigabit Ethernet PHY with RGMII interface,\n+ supporting IEEE 802.3az Energy Efficient Ethernet, IEEE 1588 SyncE,\n+ and an internal packet generator for diagnostics.\n+\n+ Specifications:\n+ - 10BASE-Te, 100BASE-TX, 1000BASE-T\n+ - RGMII with configurable TX/RX clock delays (150 ps steps, 0-2250 ps)\n+ - IEEE 802.3az-2010 Energy Efficient Ethernet\n+ - IEEE 1588 SyncE support\n+ - Internal packet generator and checker for link diagnostics\n+\n+allOf:\n+ - $ref: ethernet-phy.yaml#\n+\n+properties:\n+ compatible:\n+ const: ethernet-phy-id0008.011b\n+\n+ reg:\n+ maxItems: 1\n+\n+ rx-internal-delay-ps:\n+ description:\n+ RGMII RX clock delay in picoseconds. The PHY supports 150 ps steps\n+ from 0 to 2250 ps. If not specified, defaults to 1950 ps. If the\n+ requested value does not exactly match a supported step, the driver\n+ selects the nearest supported value and issues a warning.\n+ enum: [0, 150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500,\n+ 1650, 1800, 1950, 2100, 2250]\n+ default: 1950\n+\n+ tx-internal-delay-ps:\n+ description:\n+ RGMII TX clock delay in picoseconds. The PHY supports 150 ps steps\n+ from 0 to 2250 ps. If not specified, defaults to 1950 ps. If the\n+ requested value does not exactly match a supported step, the driver\n+ selects the nearest supported value and issues a warning.\n+ enum: [0, 150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500,\n+ 1650, 1800, 1950, 2100, 2250]\n+ default: 1950\n+\n+ tx-inverted-clk:\n+ $ref: /schemas/types.yaml#/definitions/flag\n+ description:\n+ If present, the RGMII TX clock to the MAC is inverted (180 degree\n+ phase shift relative to the data lines). This is a vendor-specific\n+ extension for boards where PCB trace length or MAC requirements\n+ necessitate clock inversion. Only use this property after hardware\n+ signal integrity validation.\n+\n+unevaluatedProperties: false\n+\n+examples:\n+ - |\n+ mdio {\n+ #address-cells = \u003c1\u003e;\n+ #size-cells = \u003c0\u003e;\n+\n+ ethernet-phy@1 {\n+ compatible = \"ethernet-phy-ieee802.3-c22\";\n+ reg = \u003c1\u003e;\n+ rx-internal-delay-ps = \u003c1050\u003e;\n+ tx-internal-delay-ps = \u003c1150\u003e;\n+ tx-inverted-clk;\n+ };\n+ };\n\\ No newline at end of file\ndiff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig\nindex 099f25dceabbc7..4576f707ac9445 100644\n--- a/drivers/net/phy/Kconfig\n+++ b/drivers/net/phy/Kconfig\n@@ -237,6 +237,16 @@ config DAVICOM_PHY\n \thelp\n \t Currently supports dm9161e and dm9131\n \n+config DAP8211R_PHY\n+\ttristate \"DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY\"\n+\tdepends on OF\n+\thelp\n+\t Support for the DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY.\n+\t This PHY is designed for enterprise and industrial networking\n+\t applications, supporting 10/100/1000 Mbps operation.\n+\t RGMII with: configurable TX/RX clock delays, optional flag to enable\n+\t 180-degree TX clock phase shift and internal packet generator.\n+\n config ICPLUS_PHY\n \ttristate \"ICPlus PHYs\"\n \thelp\ndiff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile\nindex de660ae949453d..ad35733eb4bb61 100644\n--- a/drivers/net/phy/Makefile\n+++ b/drivers/net/phy/Makefile\n@@ -53,6 +53,7 @@ obj-$(CONFIG_BROADCOM_PHY)\t+= broadcom.o\n obj-$(CONFIG_CICADA_PHY)\t+= cicada.o\n obj-$(CONFIG_CORTINA_PHY)\t+= cortina.o\n obj-$(CONFIG_DAVICOM_PHY)\t+= davicom.o\n+obj-$(CONFIG_DAP8211R_PHY)\t+= dap8211r.o\n obj-$(CONFIG_DP83640_PHY)\t+= dp83640.o\n obj-$(CONFIG_DP83822_PHY)\t+= dp83822.o\n obj-$(CONFIG_DP83848_PHY)\t+= dp83848.o\ndiff --git a/drivers/net/phy/dap8211r.c b/drivers/net/phy/dap8211r.c\nnew file mode 100644\nindex 00000000000000..bd695bc4953a2b\n--- /dev/null\n+++ b/drivers/net/phy/dap8211r.c\n@@ -0,0 +1,544 @@\n+// SPDX-License-Identifier: GPL\n+/*\n+ * Driver for the DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY.\n+ *\n+ * Specifications:\n+ * - IEEE 802.3 10BASE-Te, 100BASE-TX, 1000BASE-T\n+ * - IEEE 802.3az-2010 Energy Efficient Ethernet\n+ * - IEEE 1588 SyncE support\n+ * - RGMII\n+ * - Package Generator for diagnostics\n+ *\n+ * Author: Artem Shimko \u003ca.shimko.dev@gmail.com\u003e\n+ */\n+\n+#include \u003clinux/bitfield.h\u003e\n+#include \u003clinux/debugfs.h\u003e\n+#include \u003clinux/ethtool.h\u003e\n+#include \u003clinux/kernel.h\u003e\n+#include \u003clinux/mii.h\u003e\n+#include \u003clinux/module.h\u003e\n+#include \u003clinux/netdevice.h\u003e\n+#include \u003clinux/of.h\u003e\n+#include \u003clinux/phy.h\u003e\n+\n+#define DAP8211R_PHY_ID\t\t\t0x0008011B\n+#define DAP8211R_PHY_ID_MASK\t\t0xFFFFFFFF\n+\n+#define DAP8211R_EXT_ADD\t\t0x1E\n+#define DAP8211R_EXT_DATA\t\t0x1F\n+\n+#define DAP8211R_PKGC5\t\t\t0xA0\n+#define DAP8211R_PKG_PL_MASK\t\tGENMASK(1, 0)\n+#define DAP8211R_PKG_PL_5AA5\t\tBIT(1)\n+#define DAP8211R_PKG_COR_CRC\t\tBIT(2)\n+#define DAP8211R_PKG_GEN_EN\t\tBIT(12)\n+#define DAP8211R_PKG_GEN_MODE\t\tBIT(13)\n+#define DAP8211R_PKG_GATE_EN\t\tBIT(14)\n+#define DAP8211R_PKG_CHK_EN\t\tBIT(15)\n+#define DAP8211R_PKG_GEN_MASK\t\tGENMASK(15, 12)\n+\n+#define DAP8211R_PHY_CON\t\t0xA001\n+#define DAP8211R_PHY_LDO_EN\t\tBIT(6)\n+#define DAP8211R_PHY_RX_DLY\t\tBIT(8)\n+#define DAP8211R_PHY_GATE_RX_CLK\tBIT(9)\n+#define DAP8211R_PHY_SW_RST\t\tBIT(15)\n+\n+#define DAP8211R_RGMII_CON\t\t0xA003\n+#define DAP8211R_RGMII_TX_DEL_MASK\tGENMASK(3, 0)\n+#define DAP8211R_RGMII_RX_DEL_MASK\tGENMASK(13, 10)\n+#define DAP8211R_RGMII_CLK_INVERT\tBIT(14)\n+\n+/* Default RGMII delay (1.95ns == 13 * 150)ps) */\n+#define DAP8211R_DEFAULT_DELAY_PS\t1950\n+\n+struct dap8211r_delay_config {\n+\tu32 ps;\n+\tu8 sel;\n+};\n+\n+static const struct dap8211r_delay_config delay_config[] = {\n+\t{ 0, 0},\n+\t{ 150, 1},\n+\t{ 300, 2},\n+\t{ 450, 3},\n+\t{ 600, 4},\n+\t{ 750, 5},\n+\t{ 900, 6},\n+\t{1050, 7},\n+\t{1200, 8},\n+\t{1350, 9},\n+\t{1500, 10},\n+\t{1650, 11},\n+\t{1800, 12},\n+\t{1950, 13},\n+\t{2100, 14},\n+\t{2250, 15},\n+};\n+\n+#define DAP8211R_DELAY_COUNT\tARRAY_SIZE(delay_config)\n+\n+struct dap8211r_priv {\n+\tstruct device *dev;\n+#if IS_ENABLED(CONFIG_DEBUG_FS)\n+\tstruct dentry *root_dir;\n+\tbool crc_cor;\n+\tbool loopback;\n+#endif\n+};\n+\n+/**\n+ * dap8211r_delay_ps_to_sel() - Convert picoseconds to register value\n+ * @ps: Delay in picoseconds (0-2250)\n+ *\n+ * Converts a delay value in picoseconds to the corresponding register value\n+ * for RGMII delay configuration. The PHY supports 150ps steps from 0 to 2250ps.\n+ *\n+ * Return: Register value (0-15)\n+ */\n+static u16 dap8211r_delay_ps_to_sel(struct phy_device *phydev, u32 ps)\n+{\n+\tint i, best_idx = 0;\n+\tu32 best_diff = UINT_MAX, diff = 0;\n+\n+\tif (!ps)\n+\t\treturn 0;\n+\n+\tfor (i = 0; i \u003c DAP8211R_DELAY_COUNT; i++) {\n+\t\tdiff = abs(ps - delay_config[i].ps);\n+\n+\t\tif (diff \u003c best_diff) {\n+\t\t\tbest_diff = diff;\n+\t\t\tbest_idx = i;\n+\t\t}\n+\n+\t\tif (!diff)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (best_diff)\n+\t\tphydev_warn(phydev, \"Delay %u ps not found, using closest %u ps\\n\", ps,\n+\t\t\t delay_config[best_idx].ps);\n+\n+\tphydev_dbg(phydev, \"Delay ps idx: %u\\n\", delay_config[best_idx].sel);\n+\n+\treturn delay_config[best_idx].sel;\n+}\n+\n+/**\n+ * dap8211r_read_ext() - Read extended register\n+ * @phydev: PHY device structure\n+ * @reg: Extended register address\n+ *\n+ * Reads a PHY extended register using the indirect access method.\n+ * The caller must hold the MDIO bus lock.\n+ *\n+ * Return: Register value on success, or negative error code\n+ */\n+static int dap8211r_read_ext(struct phy_device *phydev, u16 reg)\n+{\n+\tint ret;\n+\n+\tphy_lock_mdio_bus(phydev);\n+\tret = __phy_write(phydev, DAP8211R_EXT_ADD, reg);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n+\n+\tret = __phy_read(phydev, DAP8211R_EXT_DATA);\n+out:\n+\tphy_unlock_mdio_bus(phydev);\n+\treturn ret;\n+}\n+\n+/**\n+ * dap8211r_modify_ext() - Modify extended register bits\n+ * @phydev: PHY device structure\n+ * @reg: Extended register address\n+ * @mask: Bit mask of bits to clear\n+ * @set: Bit mask of bits to set\n+ *\n+ * Modifies a PHY extended register using the indirect access method.\n+ * New value = (old value \u0026 ~mask) | set.\n+ * The caller must hold the MDIO bus lock.\n+ *\n+ * Return: 0 on success, or negative error code\n+ */\n+static int dap8211r_modify_ext(struct phy_device *phydev, u16 reg, u16 mask, u16 set)\n+{\n+\tint ret;\n+\n+\tphy_lock_mdio_bus(phydev);\n+\tret = __phy_write(phydev, DAP8211R_EXT_ADD, reg);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n+\n+\tret = __phy_modify(phydev, DAP8211R_EXT_DATA, mask, set);\n+out:\n+\tphy_unlock_mdio_bus(phydev);\n+\treturn ret;\n+}\n+\n+/**\n+ * dap8211r_get_rgmii_delay() - Get RGMII delay from device tree\n+ * @phydev: PHY device structure\n+ * @prop_name: Device tree property name\n+ *\n+ * Reads the RGMII delay from the device tree. If the property is not\n+ * specified, the default delay (1950ps) is used.\n+ *\n+ * Return: Register value (0-15) or default if property not found\n+ */\n+static u32 dap8211r_get_rgmii_delay(struct phy_device *phydev, const char *prop_name)\n+{\n+\tstruct device_node *np = phydev-\u003emdio.dev.of_node;\n+\tint ret;\n+\tu32 ps = 0;\n+\n+\tret = of_property_read_u32(np, prop_name, \u0026ps);\n+\tif (ret) {\n+\t\tphydev_dbg(phydev, \"Using default delay (%ups)\\n\", DAP8211R_DEFAULT_DELAY_PS);\n+\t\tps = DAP8211R_DEFAULT_DELAY_PS;\n+\t}\n+\n+\treturn dap8211r_delay_ps_to_sel(phydev, ps);\n+}\n+\n+/**\n+ * dap8211r_config_init() - Initialize PHY\n+ * @phydev: PHY device structure\n+ *\n+ * Configures the PHY during initialization:\n+ * - RGMII delays based on interface mode\n+ * - TX clock invertion\n+ * - Software reset to apply settings\n+ *\n+ * Return: 0 on success, or negative error code\n+ */\n+static int dap8211r_config_init(struct phy_device *phydev)\n+{\n+\tstruct device_node *phydev_node = phydev-\u003emdio.dev.of_node;\n+\tu16 mask = 0, set = 0;\n+\tint ret;\n+\n+\tswitch (phydev-\u003einterface) {\n+\tcase PHY_INTERFACE_MODE_RGMII:\n+\t\tbreak;\n+\tcase PHY_INTERFACE_MODE_RGMII_RXID:\n+\t\tset = FIELD_PREP(DAP8211R_RGMII_RX_DEL_MASK,\n+\t\t\t\t dap8211r_get_rgmii_delay(phydev, \"rx-internal-delay-ps\"));\n+\t\tmask = DAP8211R_RGMII_RX_DEL_MASK;\n+\t\tbreak;\n+\tcase PHY_INTERFACE_MODE_RGMII_ID:\n+\t\tset = FIELD_PREP(DAP8211R_RGMII_RX_DEL_MASK,\n+\t\t\t\t dap8211r_get_rgmii_delay(phydev, \"rx-internal-delay-ps\"));\n+\t\tmask = DAP8211R_RGMII_RX_DEL_MASK;\n+\t\tfallthrough;\n+\tcase PHY_INTERFACE_MODE_RGMII_TXID:\n+\t\tset |= FIELD_PREP(DAP8211R_RGMII_TX_DEL_MASK,\n+\t\t\t\t dap8211r_get_rgmii_delay(phydev, \"tx-internal-delay-ps\"));\n+\t\tmask |= DAP8211R_RGMII_TX_DEL_MASK;\n+\t\tbreak;\n+\tdefault:\n+\t\tphydev_err(phydev, \"Unsupported interface: %d\\n\",\n+\t\t\t phydev-\u003einterface);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (of_property_read_bool(phydev_node, \"tx-use-inverted-clk\"))\n+\t\tset |= DAP8211R_RGMII_CLK_INVERT;\n+\n+\tmask |= DAP8211R_RGMII_CLK_INVERT;\n+\n+\tret = dap8211r_modify_ext(phydev, DAP8211R_PHY_CON, DAP8211R_PHY_SW_RST, 0);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Wait for reset self-clear */\n+\tfsleep(200);\n+\n+\tret = dap8211r_modify_ext(phydev, DAP8211R_RGMII_CON, mask, set);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tphydev_dbg(phydev, \"RGMII configured: interface=%d, mask=0x%04x, set=0x%04x\\n\",\n+\t\t phydev-\u003einterface, mask, set);\n+\n+\treturn 0;\n+}\n+\n+#if IS_ENABLED(CONFIG_DEBUG_FS)\n+\n+/**\n+ * info_show() - Show PHY status information\n+ * @sf: Sequence file structure\n+ * @data: Private data (struct dap8211r_priv *)\n+ *\n+ * Displays PHY configuration and status registers for debugging.\n+ *\n+ * Return: 0 on success, or negative error code\n+ */\n+static int info_show(struct seq_file *sf, void *data)\n+{\n+\tstruct dap8211r_priv *priv = sf-\u003eprivate;\n+\tstruct phy_device *phydev = to_phy_device(priv-\u003edev);\n+\tint val;\n+\n+\tval = dap8211r_read_ext(phydev, DAP8211R_PHY_CON);\n+\tif (val \u003c 0)\n+\t\treturn val;\n+\n+\tseq_printf(sf, \"PHY_CON: 0x%04x\\n\", val);\n+\tseq_printf(sf, \" LDO enabled: %s\\n\", FIELD_GET(DAP8211R_PHY_LDO_EN, val) ?\n+\t\t \"yes\" : \"no\");\n+\tseq_printf(sf, \" RX dly en: %s\\n\", FIELD_GET(DAP8211R_PHY_RX_DLY, val) ?\n+\t\t \"yes\" : \"no\");\n+\tseq_printf(sf, \" RX ckl gating: %s\\n\", FIELD_GET(DAP8211R_PHY_GATE_RX_CLK, val) ?\n+\t\t \"yes\" : \"no\");\n+\n+\tval = dap8211r_read_ext(phydev, DAP8211R_RGMII_CON);\n+\tif (val \u003c 0)\n+\t\treturn val;\n+\n+\tseq_printf(sf, \"RGMII_CON: 0x%04x\\n\", val);\n+\tseq_printf(sf, \" TX delay idx: %lx\\n\", FIELD_GET(DAP8211R_RGMII_TX_DEL_MASK, val));\n+\tseq_printf(sf, \" RX delay idx: %lx\\n\", FIELD_GET(DAP8211R_RGMII_RX_DEL_MASK, val));\n+\tseq_printf(sf, \" CLK invert: %s\\n\", FIELD_GET(DAP8211R_RGMII_CLK_INVERT, val) ?\n+\t\t \"yes\" : \"no\");\n+\n+\tval = phy_read(phydev, MII_BMSR);\n+\tif (val \u003c 0)\n+\t\treturn val;\n+\n+\tseq_printf(sf, \"BMSR: 0x%04x\\n\", val);\n+\tseq_printf(sf, \" Link: %s\\n\", FIELD_GET(BMSR_LSTATUS, val) ?\n+\t\t \"up\" : \"down\");\n+\tseq_printf(sf, \" AN complete: %s\\n\", FIELD_GET(BMSR_ANEGCOMPLETE, val) ?\n+\t\t \"yes\" : \"no\");\n+\n+\tval = dap8211r_read_ext(phydev, DAP8211R_PKGC5);\n+\tif (val \u003c 0)\n+\t\treturn val;\n+\n+\tif (FIELD_GET(DAP8211R_PKG_GEN_EN, val) \u0026\u0026\n+\t FIELD_GET(DAP8211R_PKG_CHK_EN, val))\n+\t\tseq_puts(sf, \"WARNING: Package Generating enabled\\n\");\n+\n+\treturn 0;\n+}\n+DEFINE_SHOW_ATTRIBUTE(info);\n+\n+/**\n+ * pkg_gen_show() - Show packet generator status\n+ * @sf: Sequence file structure\n+ * @data: Private data (struct dap8211r_priv *)\n+ *\n+ * Displays the current status of the internal packet generator,\n+ * including CRC corruption and loopback settings.\n+ *\n+ * Return: 0 on success, or negative error code\n+ */\n+static int pkg_gen_show(struct seq_file *sf, void *data)\n+{\n+\tstruct dap8211r_priv *priv = sf-\u003eprivate;\n+\tstruct phy_device *phydev = to_phy_device(priv-\u003edev);\n+\tint val;\n+\n+\tval = dap8211r_read_ext(phydev, DAP8211R_PKGC5);\n+\tif (val \u003c 0)\n+\t\treturn val;\n+\n+\tseq_puts(sf, \"Package Generating: \");\n+\tif (FIELD_GET(DAP8211R_PKG_GEN_EN, val) \u0026\u0026\n+\t FIELD_GET(DAP8211R_PKG_CHK_EN, val))\n+\t\tseq_puts(sf, \"enabled\\n\");\n+\telse\n+\t\tseq_puts(sf, \"disabled\\n\");\n+\n+\tseq_printf(sf, \"CRC corruption en: %s\\n\", FIELD_GET(DAP8211R_PKG_COR_CRC, val) ?\n+\t\t \"enabled\" : \"disabled\");\n+\n+\tval = phy_read(phydev, MII_BMCR);\n+\tif (val \u003c 0)\n+\t\treturn val;\n+\n+\tseq_printf(sf, \"Loopback en: %s\\n\", FIELD_GET(BMCR_LOOPBACK, val) ?\n+\t\t \"enabled\" : \"disabled\");\n+\treturn 0;\n+}\n+\n+/**\n+ * pkg_gen_write() - Enable/disable packet generator\n+ * @file: File structure\n+ * @user_buf: User space buffer\n+ * @count: Buffer size\n+ * @ppos: File position\n+ *\n+ * Enables or disables the internal packet generator.\n+ * Also controls loopback and CRC corruption via debugfs flags.\n+ *\n+ * NOTE: We intentionally do not use genphy_loopback() here.\n+ * genphy_loopback() does a full BMCR overwrite (mask = ~0) and\n+ * waits up to 500 ms for link in loopback mode. This is too\n+ * heavy for a diagnostic packet generator:\n+ *\n+ * - It destroys all other BMCR state (speed, duplex, AN config).\n+ * - The 500 ms link poll is unnecessary: we already have a link\n+ * or are deliberately setting up a test condition.\n+ * - We want to minimize changes to BMCR during debugging.\n+ *\n+ * Return: Number of bytes written on success, or negative error code\n+ */\n+static ssize_t pkg_gen_write(struct file *file,\n+\t\t\t const char __user *user_buf,\n+\t\t\t size_t count, loff_t *ppos)\n+{\n+\tstruct seq_file *sf = file-\u003eprivate_data;\n+\tstruct dap8211r_priv *priv = sf-\u003eprivate;\n+\tstruct phy_device *phydev = to_phy_device(priv-\u003edev);\n+\tbool en;\n+\tu16 mask, set, set_bmcr;\n+\tint ret;\n+\n+\tret = kstrtobool_from_user(user_buf, count, \u0026en);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (en) {\n+\t\tset = DAP8211R_PKG_GEN_EN | DAP8211R_PKG_CHK_EN | DAP8211R_PKG_PL_5AA5;\n+\n+\t\tif (priv-\u003ecrc_cor)\n+\t\t\tset |= DAP8211R_PKG_COR_CRC;\n+\n+\t\tif (priv-\u003eloopback)\n+\t\t\tset_bmcr = BMCR_LOOPBACK;\n+\t\telse\n+\t\t\tset_bmcr = BMCR_ANENABLE;\n+\t} else {\n+\t\tset = DAP8211R_PKG_GEN_MODE | DAP8211R_PKG_GATE_EN;\n+\t\tset_bmcr = BMCR_ANENABLE;\n+\t}\n+\n+\tret = phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK | BMCR_ANENABLE, set_bmcr);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tmask = DAP8211R_PKG_GEN_MASK | DAP8211R_PKG_PL_MASK | DAP8211R_PKG_COR_CRC;\n+\tret = dap8211r_modify_ext(phydev, DAP8211R_PKGC5, mask, set);\n+\tif (ret \u003c 0) {\n+\t\tphy_modify(phydev, MII_BMCR, BMCR_LOOPBACK, 0);\n+\t\treturn ret;\n+\t}\n+\n+\treturn count;\n+}\n+DEFINE_SHOW_STORE_ATTRIBUTE(pkg_gen);\n+\n+/**\n+ * dap8211r_debug_init() - Initialize debugfs entries\n+ * @priv: Private driver data\n+ *\n+ * Creates debugfs directory and files for PHY debugging.\n+ * - info: PHY status information\n+ * - pkg_gen: Enable/disable generator (1/0)\n+ * - pkg_gen_crc_cor: Enable CRC corruption (Y/N)\n+ * - pkg_gen_loopback: Enable loopback (Y/N)\n+ *\n+ * Debugfs is only available when CONFIG_DEBUG_FS is enabled.\n+ */\n+static void dap8211r_debug_init(struct dap8211r_priv *priv)\n+{\n+\tpriv-\u003eroot_dir = debugfs_create_dir(dev_name(priv-\u003edev), NULL);\n+\tif (IS_ERR(priv-\u003eroot_dir))\n+\t\treturn;\n+\n+\tdebugfs_create_file(\"info\", 0444, priv-\u003eroot_dir, priv,\n+\t\t\t \u0026info_fops);\n+\tdebugfs_create_file(\"pkg_gen\", 0644, priv-\u003eroot_dir, priv,\n+\t\t\t \u0026pkg_gen_fops);\n+\tdebugfs_create_bool(\"pkg_gen_crc_cor\", 0644, priv-\u003eroot_dir,\n+\t\t\t \u0026priv-\u003ecrc_cor);\n+\tdebugfs_create_bool(\"pkg_gen_loopback\", 0644, priv-\u003eroot_dir,\n+\t\t\t \u0026priv-\u003eloopback);\n+}\n+\n+/**\n+ * dap8211r_debug_remove() - Remove debugfs entries\n+ * @priv: Private driver data\n+ *\n+ * Recursively removes all debugfs files and directories created\n+ * by dap8211r_debug_init().\n+ */\n+static void dap8211r_debug_remove(struct dap8211r_priv *priv)\n+{\n+\tdebugfs_remove_recursive(priv-\u003eroot_dir);\n+}\n+\n+#else /* !CONFIG_DEBUG_FS */\n+static void dap8211r_debug_init(struct dap8211r_priv *priv) {}\n+static void dap8211r_debug_remove(struct dap8211r_priv *priv) {}\n+#endif /* CONFIG_DEBUG_FS */\n+\n+/**\n+ * dap8211r_probe() - PHY probe callback\n+ * @phydev: PHY device structure\n+ *\n+ * Called when the PHY is discovered. Allocates and initializes\n+ * private driver data and debugfs entries.\n+ *\n+ * Return: 0 on success, or negative error code\n+ */\n+static int dap8211r_probe(struct phy_device *phydev)\n+{\n+\tstruct device *dev = \u0026phydev-\u003emdio.dev;\n+\tstruct dap8211r_priv *priv;\n+\n+\tpriv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);\n+\tif (!priv)\n+\t\treturn -ENOMEM;\n+\n+\tpriv-\u003edev = dev;\n+\tphydev-\u003epriv = priv;\n+\n+\tdap8211r_debug_init(priv);\n+\tphydev_dbg(phydev, \"DAP8211R PHY probed\\n\");\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * dap8211r_remove() - PHY remove callback\n+ * @phydev: PHY device structure\n+ *\n+ * Called when the PHY is removed. Cleans up private driver data\n+ * and debugfs entries.\n+ */\n+static void dap8211r_remove(struct phy_device *phydev)\n+{\n+\tdap8211r_debug_remove(phydev-\u003epriv);\n+}\n+\n+static struct phy_driver dap8211r_driver[] = {\n+\t{\n+\t\tPHY_ID_MATCH_EXACT(DAP8211R_PHY_ID),\n+\t\t.name\t\t= \"DAP8211R Gigabit Ethernet\",\n+\t\t.probe = dap8211r_probe,\n+\t\t.remove\t\t= dap8211r_remove,\n+\t\t.config_init\t= dap8211r_config_init,\n+\t\t.read_status\t= genphy_read_status,\n+\t\t.set_loopback\t= genphy_loopback,\n+\t\t.config_aneg\t= genphy_config_aneg,\n+\t\t.suspend\t= genphy_suspend,\n+\t\t.resume\t\t= genphy_resume,\n+\t},\n+};\n+module_phy_driver(dap8211r_driver);\n+\n+MODULE_DESCRIPTION(\"DAP8211R Gigabit Ethernet PHY driver\");\n+MODULE_AUTHOR(\"Artem Shimko \u003ca.shimko.dev@gmail.com\u003e\");\n+MODULE_LICENSE(\"GPL\");\n+\n+static const struct mdio_device_id __maybe_unused dap8211r_tb[] = {\n+\t{ DAP8211R_PHY_ID, DAP8211R_PHY_ID_MASK },\n+\t{ /* sentinel */ }\n+};\n+MODULE_DEVICE_TABLE(mdio, dap8211r_tb);\n"
} |
| 2/1 | 2026/07/13 17:22 | agent | patch-evaluator |
1mModel:gemini-3.1-pro-preview Args: null Results: {
"EnableConfigs": [
"DAP8211R_PHY"
],
"FocusSymbols": [
"dap8211r_probe",
"dap8211r_config_init",
"pkg_gen_write",
"info_show",
"pkg_gen_show"
],
"Reasoning": "The patch introduces a new Ethernet PHY driver for DAPU Telecom DAP8211R(I). The driver can be probed in a virtualized environment by emulating a USB Ethernet device that registers an MDIO bus and responds to MDIO reads with the DAP8211R PHY ID. Once probed, the driver's `config_init` and debugfs operations (`info_show`, `pkg_gen_show`, `pkg_gen_write`) can be exercised by userspace.",
"WorthFuzzing": true
}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). 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. 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. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. 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 3346f71500b6a7bb1b05a83b822819f14966dad1
Author: syz-cluster <triage@syzkaller.com>
Date: Mon Jul 13 17:22:46 2026 +0000
syz-cluster: applied patch under review
diff --git a/Documentation/devicetree/bindings/net/dapu,dap8211r.yaml b/Documentation/devicetree/bindings/net/dapu,dap8211r.yaml
new file mode 100644
index 00000000000000..208a82f779d61e
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dapu,dap8211r.yaml
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/dapu,dap8211r.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY
+
+maintainers:
+ - Artem Shimko <a.shimko.dev@gmail.com>
+
+description: |
+ The DAP8211R(I) is a Gigabit Ethernet PHY with RGMII interface,
+ supporting IEEE 802.3az Energy Efficient Ethernet, IEEE 1588 SyncE,
+ and an internal packet generator for diagnostics.
+
+ Specifications:
+ - 10BASE-Te, 100BASE-TX, 1000BASE-T
+ - RGMII with configurable TX/RX clock delays (150 ps steps, 0-2250 ps)
+ - IEEE 802.3az-2010 Energy Efficient Ethernet
+ - IEEE 1588 SyncE support
+ - Internal packet generator and checker for link diagnostics
+
+allOf:
+ - $ref: ethernet-phy.yaml#
+
+properties:
+ compatible:
+ const: ethernet-phy-id0008.011b
+
+ reg:
+ maxItems: 1
+
+ rx-internal-delay-ps:
+ description:
+ RGMII RX clock delay in picoseconds. The PHY supports 150 ps steps
+ from 0 to 2250 ps. If not specified, defaults to 1950 ps. If the
+ requested value does not exactly match a supported step, the driver
+ selects the nearest supported value and issues a warning.
+ enum: [0, 150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500,
+ 1650, 1800, 1950, 2100, 2250]
+ default: 1950
+
+ tx-internal-delay-ps:
+ description:
+ RGMII TX clock delay in picoseconds. The PHY supports 150 ps steps
+ from 0 to 2250 ps. If not specified, defaults to 1950 ps. If the
+ requested value does not exactly match a supported step, the driver
+ selects the nearest supported value and issues a warning.
+ enum: [0, 150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500,
+ 1650, 1800, 1950, 2100, 2250]
+ default: 1950
+
+ tx-inverted-clk:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ If present, the RGMII TX clock to the MAC is inverted (180 degree
+ phase shift relative to the data lines). This is a vendor-specific
+ extension for boards where PCB trace length or MAC requirements
+ necessitate clock inversion. Only use this property after hardware
+ signal integrity validation.
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ rx-internal-delay-ps = <1050>;
+ tx-internal-delay-ps = <1150>;
+ tx-inverted-clk;
+ };
+ };
\ No newline at end of file
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 099f25dceabbc7..4576f707ac9445 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -237,6 +237,16 @@ config DAVICOM_PHY
help
Currently supports dm9161e and dm9131
+config DAP8211R_PHY
+ tristate "DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY"
+ depends on OF
+ help
+ Support for the DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY.
+ This PHY is designed for enterprise and industrial networking
+ applications, supporting 10/100/1000 Mbps operation.
+ RGMII with: configurable TX/RX clock delays, optional flag to enable
+ 180-degree TX clock phase shift and internal packet generator.
+
config ICPLUS_PHY
tristate "ICPlus PHYs"
help
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index de660ae949453d..ad35733eb4bb61 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
obj-$(CONFIG_CICADA_PHY) += cicada.o
obj-$(CONFIG_CORTINA_PHY) += cortina.o
obj-$(CONFIG_DAVICOM_PHY) += davicom.o
+obj-$(CONFIG_DAP8211R_PHY) += dap8211r.o
obj-$(CONFIG_DP83640_PHY) += dp83640.o
obj-$(CONFIG_DP83822_PHY) += dp83822.o
obj-$(CONFIG_DP83848_PHY) += dp83848.o
diff --git a/drivers/net/phy/dap8211r.c b/drivers/net/phy/dap8211r.c
new file mode 100644
index 00000000000000..bd695bc4953a2b
--- /dev/null
+++ b/drivers/net/phy/dap8211r.c
@@ -0,0 +1,544 @@
+// SPDX-License-Identifier: GPL
+/*
+ * Driver for the DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY.
+ *
+ * Specifications:
+ * - IEEE 802.3 10BASE-Te, 100BASE-TX, 1000BASE-T
+ * - IEEE 802.3az-2010 Energy Efficient Ethernet
+ * - IEEE 1588 SyncE support
+ * - RGMII
+ * - Package Generator for diagnostics
+ *
+ * Author: Artem Shimko <a.shimko.dev@gmail.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/debugfs.h>
+#include <linux/ethtool.h>
+#include <linux/kernel.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/phy.h>
+
+#define DAP8211R_PHY_ID 0x0008011B
+#define DAP8211R_PHY_ID_MASK 0xFFFFFFFF
+
+#define DAP8211R_EXT_ADD 0x1E
+#define DAP8211R_EXT_DATA 0x1F
+
+#define DAP8211R_PKGC5 0xA0
+#define DAP8211R_PKG_PL_MASK GENMASK(1, 0)
+#define DAP8211R_PKG_PL_5AA5 BIT(1)
+#define DAP8211R_PKG_COR_CRC BIT(2)
+#define DAP8211R_PKG_GEN_EN BIT(12)
+#define DAP8211R_PKG_GEN_MODE BIT(13)
+#define DAP8211R_PKG_GATE_EN BIT(14)
+#define DAP8211R_PKG_CHK_EN BIT(15)
+#define DAP8211R_PKG_GEN_MASK GENMASK(15, 12)
+
+#define DAP8211R_PHY_CON 0xA001
+#define DAP8211R_PHY_LDO_EN BIT(6)
+#define DAP8211R_PHY_RX_DLY BIT(8)
+#define DAP8211R_PHY_GATE_RX_CLK BIT(9)
+#define DAP8211R_PHY_SW_RST BIT(15)
+
+#define DAP8211R_RGMII_CON 0xA003
+#define DAP8211R_RGMII_TX_DEL_MASK GENMASK(3, 0)
+#define DAP8211R_RGMII_RX_DEL_MASK GENMASK(13, 10)
+#define DAP8211R_RGMII_CLK_INVERT BIT(14)
+
+/* Default RGMII delay (1.95ns == 13 * 150)ps) */
+#define DAP8211R_DEFAULT_DELAY_PS 1950
+
+struct dap8211r_delay_config {
+ u32 ps;
+ u8 sel;
+};
+
+static const struct dap8211r_delay_config delay_config[] = {
+ { 0, 0},
+ { 150, 1},
+ { 300, 2},
+ { 450, 3},
+ { 600, 4},
+ { 750, 5},
+ { 900, 6},
+ {1050, 7},
+ {1200, 8},
+ {1350, 9},
+ {1500, 10},
+ {1650, 11},
+ {1800, 12},
+ {1950, 13},
+ {2100, 14},
+ {2250, 15},
+};
+
+#define DAP8211R_DELAY_COUNT ARRAY_SIZE(delay_config)
+
+struct dap8211r_priv {
+ struct device *dev;
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+ struct dentry *root_dir;
+ bool crc_cor;
+ bool loopback;
+#endif
+};
+
+/**
+ * dap8211r_delay_ps_to_sel() - Convert picoseconds to register value
+ * @ps: Delay in picoseconds (0-2250)
+ *
+ * Converts a delay value in picoseconds to the corresponding register value
+ * for RGMII delay configuration. The PHY supports 150ps steps from 0 to 2250ps.
+ *
+ * Return: Register value (0-15)
+ */
+static u16 dap8211r_delay_ps_to_sel(struct phy_device *phydev, u32 ps)
+{
+ int i, best_idx = 0;
+ u32 best_diff = UINT_MAX, diff = 0;
+
+ if (!ps)
+ return 0;
+
+ for (i = 0; i < DAP8211R_DELAY_COUNT; i++) {
+ diff = abs(ps - delay_config[i].ps);
+
+ if (diff < best_diff) {
+ best_diff = diff;
+ best_idx = i;
+ }
+
+ if (!diff)
+ break;
+ }
+
+ if (best_diff)
+ phydev_warn(phydev, "Delay %u ps not found, using closest %u ps\n", ps,
+ delay_config[best_idx].ps);
+
+ phydev_dbg(phydev, "Delay ps idx: %u\n", delay_config[best_idx].sel);
+
+ return delay_config[best_idx].sel;
+}
+
+/**
+ * dap8211r_read_ext() - Read extended register
+ * @phydev: PHY device structure
+ * @reg: Extended register address
+ *
+ * Reads a PHY extended register using the indirect access method.
+ * The caller must hold the MDIO bus lock.
+ *
+ * Return: Register value on success, or negative error code
+ */
+static int dap8211r_read_ext(struct phy_device *phydev, u16 reg)
+{
+ int ret;
+
+ phy_lock_mdio_bus(phydev);
+ ret = __phy_write(phydev, DAP8211R_EXT_ADD, reg);
+ if (ret < 0)
+ goto out;
+
+ ret = __phy_read(phydev, DAP8211R_EXT_DATA);
+out:
+ phy_unlock_mdio_bus(phydev);
+ return ret;
+}
+
+/**
+ * dap8211r_modify_ext() - Modify extended register bits
+ * @phydev: PHY device structure
+ * @reg: Extended register address
+ * @mask: Bit mask of bits to clear
+ * @set: Bit mask of bits to set
+ *
+ * Modifies a PHY extended register using the indirect access method.
+ * New value = (old value & ~mask) | set.
+ * The caller must hold the MDIO bus lock.
+ *
+ * Return: 0 on success, or negative error code
+ */
+static int dap8211r_modify_ext(struct phy_device *phydev, u16 reg, u16 mask, u16 set)
+{
+ int ret;
+
+ phy_lock_mdio_bus(phydev);
+ ret = __phy_write(phydev, DAP8211R_EXT_ADD, reg);
+ if (ret < 0)
+ goto out;
+
+ ret = __phy_modify(phydev, DAP8211R_EXT_DATA, mask, set);
+out:
+ phy_unlock_mdio_bus(phydev);
+ return ret;
+}
+
+/**
+ * dap8211r_get_rgmii_delay() - Get RGMII delay from device tree
+ * @phydev: PHY device structure
+ * @prop_name: Device tree property name
+ *
+ * Reads the RGMII delay from the device tree. If the property is not
+ * specified, the default delay (1950ps) is used.
+ *
+ * Return: Register value (0-15) or default if property not found
+ */
+static u32 dap8211r_get_rgmii_delay(struct phy_device *phydev, const char *prop_name)
+{
+ struct device_node *np = phydev->mdio.dev.of_node;
+ int ret;
+ u32 ps = 0;
+
+ ret = of_property_read_u32(np, prop_name, &ps);
+ if (ret) {
+ phydev_dbg(phydev, "Using default delay (%ups)\n", DAP8211R_DEFAULT_DELAY_PS);
+ ps = DAP8211R_DEFAULT_DELAY_PS;
+ }
+
+ return dap8211r_delay_ps_to_sel(phydev, ps);
+}
+
+/**
+ * dap8211r_config_init() - Initialize PHY
+ * @phydev: PHY device structure
+ *
+ * Configures the PHY during initialization:
+ * - RGMII delays based on interface mode
+ * - TX clock invertion
+ * - Software reset to apply settings
+ *
+ * Return: 0 on success, or negative error code
+ */
+static int dap8211r_config_init(struct phy_device *phydev)
+{
+ struct device_node *phydev_node = phydev->mdio.dev.of_node;
+ u16 mask = 0, set = 0;
+ int ret;
+
+ switch (phydev->interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ break;
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ set = FIELD_PREP(DAP8211R_RGMII_RX_DEL_MASK,
+ dap8211r_get_rgmii_delay(phydev, "rx-internal-delay-ps"));
+ mask = DAP8211R_RGMII_RX_DEL_MASK;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ set = FIELD_PREP(DAP8211R_RGMII_RX_DEL_MASK,
+ dap8211r_get_rgmii_delay(phydev, "rx-internal-delay-ps"));
+ mask = DAP8211R_RGMII_RX_DEL_MASK;
+ fallthrough;
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ set |= FIELD_PREP(DAP8211R_RGMII_TX_DEL_MASK,
+ dap8211r_get_rgmii_delay(phydev, "tx-internal-delay-ps"));
+ mask |= DAP8211R_RGMII_TX_DEL_MASK;
+ break;
+ default:
+ phydev_err(phydev, "Unsupported interface: %d\n",
+ phydev->interface);
+ return -EINVAL;
+ }
+
+ if (of_property_read_bool(phydev_node, "tx-use-inverted-clk"))
+ set |= DAP8211R_RGMII_CLK_INVERT;
+
+ mask |= DAP8211R_RGMII_CLK_INVERT;
+
+ ret = dap8211r_modify_ext(phydev, DAP8211R_PHY_CON, DAP8211R_PHY_SW_RST, 0);
+ if (ret)
+ return ret;
+
+ /* Wait for reset self-clear */
+ fsleep(200);
+
+ ret = dap8211r_modify_ext(phydev, DAP8211R_RGMII_CON, mask, set);
+ if (ret)
+ return ret;
+
+ phydev_dbg(phydev, "RGMII configured: interface=%d, mask=0x%04x, set=0x%04x\n",
+ phydev->interface, mask, set);
+
+ return 0;
+}
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+
+/**
+ * info_show() - Show PHY status information
+ * @sf: Sequence file structure
+ * @data: Private data (struct dap8211r_priv *)
+ *
+ * Displays PHY configuration and status registers for debugging.
+ *
+ * Return: 0 on success, or negative error code
+ */
+static int info_show(struct seq_file *sf, void *data)
+{
+ struct dap8211r_priv *priv = sf->private;
+ struct phy_device *phydev = to_phy_device(priv->dev);
+ int val;
+
+ val = dap8211r_read_ext(phydev, DAP8211R_PHY_CON);
+ if (val < 0)
+ return val;
+
+ seq_printf(sf, "PHY_CON: 0x%04x\n", val);
+ seq_printf(sf, " LDO enabled: %s\n", FIELD_GET(DAP8211R_PHY_LDO_EN, val) ?
+ "yes" : "no");
+ seq_printf(sf, " RX dly en: %s\n", FIELD_GET(DAP8211R_PHY_RX_DLY, val) ?
+ "yes" : "no");
+ seq_printf(sf, " RX ckl gating: %s\n", FIELD_GET(DAP8211R_PHY_GATE_RX_CLK, val) ?
+ "yes" : "no");
+
+ val = dap8211r_read_ext(phydev, DAP8211R_RGMII_CON);
+ if (val < 0)
+ return val;
+
+ seq_printf(sf, "RGMII_CON: 0x%04x\n", val);
+ seq_printf(sf, " TX delay idx: %lx\n", FIELD_GET(DAP8211R_RGMII_TX_DEL_MASK, val));
+ seq_printf(sf, " RX delay idx: %lx\n", FIELD_GET(DAP8211R_RGMII_RX_DEL_MASK, val));
+ seq_printf(sf, " CLK invert: %s\n", FIELD_GET(DAP8211R_RGMII_CLK_INVERT, val) ?
+ "yes" : "no");
+
+ val = phy_read(phydev, MII_BMSR);
+ if (val < 0)
+ return val;
+
+ seq_printf(sf, "BMSR: 0x%04x\n", val);
+ seq_printf(sf, " Link: %s\n", FIELD_GET(BMSR_LSTATUS, val) ?
+ "up" : "down");
+ seq_printf(sf, " AN complete: %s\n", FIELD_GET(BMSR_ANEGCOMPLETE, val) ?
+ "yes" : "no");
+
+ val = dap8211r_read_ext(phydev, DAP8211R_PKGC5);
+ if (val < 0)
+ return val;
+
+ if (FIELD_GET(DAP8211R_PKG_GEN_EN, val) &&
+ FIELD_GET(DAP8211R_PKG_CHK_EN, val))
+ seq_puts(sf, "WARNING: Package Generating enabled\n");
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(info);
+
+/**
+ * pkg_gen_show() - Show packet generator status
+ * @sf: Sequence file structure
+ * @data: Private data (struct dap8211r_priv *)
+ *
+ * Displays the current status of the internal packet generator,
+ * including CRC corruption and loopback settings.
+ *
+ * Return: 0 on success, or negative error code
+ */
+static int pkg_gen_show(struct seq_file *sf, void *data)
+{
+ struct dap8211r_priv *priv = sf->private;
+ struct phy_device *phydev = to_phy_device(priv->dev);
+ int val;
+
+ val = dap8211r_read_ext(phydev, DAP8211R_PKGC5);
+ if (val < 0)
+ return val;
+
+ seq_puts(sf, "Package Generating: ");
+ if (FIELD_GET(DAP8211R_PKG_GEN_EN, val) &&
+ FIELD_GET(DAP8211R_PKG_CHK_EN, val))
+ seq_puts(sf, "enabled\n");
+ else
+ seq_puts(sf, "disabled\n");
+
+ seq_printf(sf, "CRC corruption en: %s\n", FIELD_GET(DAP8211R_PKG_COR_CRC, val) ?
+ "enabled" : "disabled");
+
+ val = phy_read(phydev, MII_BMCR);
+ if (val < 0)
+ return val;
+
+ seq_printf(sf, "Loopback en: %s\n", FIELD_GET(BMCR_LOOPBACK, val) ?
+ "enabled" : "disabled");
+ return 0;
+}
+
+/**
+ * pkg_gen_write() - Enable/disable packet generator
+ * @file: File structure
+ * @user_buf: User space buffer
+ * @count: Buffer size
+ * @ppos: File position
+ *
+ * Enables or disables the internal packet generator.
+ * Also controls loopback and CRC corruption via debugfs flags.
+ *
+ * NOTE: We intentionally do not use genphy_loopback() here.
+ * genphy_loopback() does a full BMCR overwrite (mask = ~0) and
+ * waits up to 500 ms for link in loopback mode. This is too
+ * heavy for a diagnostic packet generator:
+ *
+ * - It destroys all other BMCR state (speed, duplex, AN config).
+ * - The 500 ms link poll is unnecessary: we already have a link
+ * or are deliberately setting up a test condition.
+ * - We want to minimize changes to BMCR during debugging.
+ *
+ * Return: Number of bytes written on success, or negative error code
+ */
+static ssize_t pkg_gen_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct seq_file *sf = file->private_data;
+ struct dap8211r_priv *priv = sf->private;
+ struct phy_device *phydev = to_phy_device(priv->dev);
+ bool en;
+ u16 mask, set, set_bmcr;
+ int ret;
+
+ ret = kstrtobool_from_user(user_buf, count, &en);
+ if (ret)
+ return ret;
+
+ if (en) {
+ set = DAP8211R_PKG_GEN_EN | DAP8211R_PKG_CHK_EN | DAP8211R_PKG_PL_5AA5;
+
+ if (priv->crc_cor)
+ set |= DAP8211R_PKG_COR_CRC;
+
+ if (priv->loopback)
+ set_bmcr = BMCR_LOOPBACK;
+ else
+ set_bmcr = BMCR_ANENABLE;
+ } else {
+ set = DAP8211R_PKG_GEN_MODE | DAP8211R_PKG_GATE_EN;
+ set_bmcr = BMCR_ANENABLE;
+ }
+
+ ret = phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK | BMCR_ANENABLE, set_bmcr);
+ if (ret < 0)
+ return ret;
+
+ mask = DAP8211R_PKG_GEN_MASK | DAP8211R_PKG_PL_MASK | DAP8211R_PKG_COR_CRC;
+ ret = dap8211r_modify_ext(phydev, DAP8211R_PKGC5, mask, set);
+ if (ret < 0) {
+ phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK, 0);
+ return ret;
+ }
+
+ return count;
+}
+DEFINE_SHOW_STORE_ATTRIBUTE(pkg_gen);
+
+/**
+ * dap8211r_debug_init() - Initialize debugfs entries
+ * @priv: Private driver data
+ *
+ * Creates debugfs directory and files for PHY debugging.
+ * - info: PHY status information
+ * - pkg_gen: Enable/disable generator (1/0)
+ * - pkg_gen_crc_cor: Enable CRC corruption (Y/N)
+ * - pkg_gen_loopback: Enable loopback (Y/N)
+ *
+ * Debugfs is only available when CONFIG_DEBUG_FS is enabled.
+ */
+static void dap8211r_debug_init(struct dap8211r_priv *priv)
+{
+ priv->root_dir = debugfs_create_dir(dev_name(priv->dev), NULL);
+ if (IS_ERR(priv->root_dir))
+ return;
+
+ debugfs_create_file("info", 0444, priv->root_dir, priv,
+ &info_fops);
+ debugfs_create_file("pkg_gen", 0644, priv->root_dir, priv,
+ &pkg_gen_fops);
+ debugfs_create_bool("pkg_gen_crc_cor", 0644, priv->root_dir,
+ &priv->crc_cor);
+ debugfs_create_bool("pkg_gen_loopback", 0644, priv->root_dir,
+ &priv->loopback);
+}
+
+/**
+ * dap8211r_debug_remove() - Remove debugfs entries
+ * @priv: Private driver data
+ *
+ * Recursively removes all debugfs files and directories created
+ * by dap8211r_debug_init().
+ */
+static void dap8211r_debug_remove(struct dap8211r_priv *priv)
+{
+ debugfs_remove_recursive(priv->root_dir);
+}
+
+#else /* !CONFIG_DEBUG_FS */
+static void dap8211r_debug_init(struct dap8211r_priv *priv) {}
+static void dap8211r_debug_remove(struct dap8211r_priv *priv) {}
+#endif /* CONFIG_DEBUG_FS */
+
+/**
+ * dap8211r_probe() - PHY probe callback
+ * @phydev: PHY device structure
+ *
+ * Called when the PHY is discovered. Allocates and initializes
+ * private driver data and debugfs entries.
+ *
+ * Return: 0 on success, or negative error code
+ */
+static int dap8211r_probe(struct phy_device *phydev)
+{
+ struct device *dev = &phydev->mdio.dev;
+ struct dap8211r_priv *priv;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+ phydev->priv = priv;
+
+ dap8211r_debug_init(priv);
+ phydev_dbg(phydev, "DAP8211R PHY probed\n");
+
+ return 0;
+}
+
+/**
+ * dap8211r_remove() - PHY remove callback
+ * @phydev: PHY device structure
+ *
+ * Called when the PHY is removed. Cleans up private driver data
+ * and debugfs entries.
+ */
+static void dap8211r_remove(struct phy_device *phydev)
+{
+ dap8211r_debug_remove(phydev->priv);
+}
+
+static struct phy_driver dap8211r_driver[] = {
+ {
+ PHY_ID_MATCH_EXACT(DAP8211R_PHY_ID),
+ .name = "DAP8211R Gigabit Ethernet",
+ .probe = dap8211r_probe,
+ .remove = dap8211r_remove,
+ .config_init = dap8211r_config_init,
+ .read_status = genphy_read_status,
+ .set_loopback = genphy_loopback,
+ .config_aneg = genphy_config_aneg,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ },
+};
+module_phy_driver(dap8211r_driver);
+
+MODULE_DESCRIPTION("DAP8211R Gigabit Ethernet PHY driver");
+MODULE_AUTHOR("Artem Shimko <a.shimko.dev@gmail.com>");
+MODULE_LICENSE("GPL");
+
+static const struct mdio_device_id __maybe_unused dap8211r_tb[] = {
+ { DAP8211R_PHY_ID, DAP8211R_PHY_ID_MASK },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(mdio, dap8211r_tb);
|
| 3/2 | 2026/07/13 17:22 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10134 output: 23 thoughts: 511 Thoughts: **Thoughts on Probing the New DAP8211R PHY Driver in a Fuzzing Context** Okay, so we've got a new PHY driver, `dap8211r.c`, for the DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY. It looks straightforward, implements the standard probe, remove, and configuration functions, and even adds debugfs entries if `CONFIG_DEBUG_FS` is enabled. My immediate thought is, can this be reached, and more importantly, can we reach this driver in a fuzzing environment like syzkaller? PHY drivers are typically probed either when a network device registers a PHY, or through an MDIO bus scan. In syzkaller, we could potentially inject MDIO devices directly, or maybe even use a dummy network device that registers a PHY. I know syzkaller has some network fuzzing capabilities already, like `syz_genetlink_get_family`, but to specifically target this PHY, we'd probably be looking at `ioctl(SIOCSMIIREG)` calls, or perhaps interacting through netlink, assuming a suitable netlink interface is available. Or, the most direct approach might be to probe it via the MDIO bus if we have a mock MDIO bus. Now, syzkaller has proven itself capable with `vkms` for DRM and `mac80211_hwsim` for wifi, so does it have a way to probe arbitrary PHY drivers? Can we create a virtual MDIO bus? Or, would using Distributed Switch Architecture (`dsa`) be a path toward probing this driver? We should be able to fuzz the `mdio` bus. The crucial question is, how do we *trigger* `dap8211r_probe`? My first instinct is to check if the MDIO bus exposes a way to create devices from userspace, or to see if any existing PHY fuzzers can be repurposed. I'll need to dig into the kernel source, search for `mdio` and `phy` to identify any relevant instantiation mechanisms. Thinking about it, syzkaller *can* load modules. If there's a device tree overlay, or something similar, it *might* probe it automatically. However, syzkaller doesn't usually handle DT overlays unless specifically configured for it, so that’s probably not the standard path. I see now that `drivers/net/phy/mdio_bus.c` seems to be relevant. Hold on, syzkaller can use `ioctl(SIOCSMIIREG)` to interact with PHYs, but that assumes the PHY device already *exists*. So that gets us back to: can we create this PHY device dynamically? I need to find a way to verify that `dap8211r_probe` can be reached. This is the crucial point for a successful fuzzing campaign. |
| 4/2 | 2026/07/13 17:22 | tool | grepper |
0mArgs:{
"Expression": "dap8211r_probe"
}Results: {
"Output": "drivers/net/phy/dap8211r.c=478=static void dap8211r_debug_remove(struct dap8211r_priv *priv) {}\n--\ndrivers/net/phy/dap8211r.c-481-/**\ndrivers/net/phy/dap8211r.c:482: * dap8211r_probe() - PHY probe callback\ndrivers/net/phy/dap8211r.c-483- * @phydev: PHY device structure\n--\ndrivers/net/phy/dap8211r.c-489- */\ndrivers/net/phy/dap8211r.c:490:static int dap8211r_probe(struct phy_device *phydev)\ndrivers/net/phy/dap8211r.c-491-{\n--\ndrivers/net/phy/dap8211r.c=520=static struct phy_driver dap8211r_driver[] = {\n--\ndrivers/net/phy/dap8211r.c-523-\t\t.name\t\t= \"DAP8211R Gigabit Ethernet\",\ndrivers/net/phy/dap8211r.c:524:\t\t.probe = dap8211r_probe,\ndrivers/net/phy/dap8211r.c-525-\t\t.remove\t\t= dap8211r_remove,\n"
} |
| 5/2 | 2026/07/13 17:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11658 output: 18 thoughts: 130 Thoughts: **Probing PHY Drivers with Syzkaller** Okay, so I'm wondering if syzkaller can actually get at those PHY drivers. It seems like the usual ways a PHY driver is loaded – either through an MDIO bus scan and matching ID, or by a Device Tree node specifying the PHY – probably won't work in a QEMU-like virtualized environment. Unless there's an emulated MDIO bus with that *exact* ID, or some clever software registration method, the probe function is just not going to get called, right? Hmm, let's see... are there any options like `dsa_loop`, `fixed-phy`, or that `mdio-mock` thing? Maybe there's some kind of mock MDIO bus implementation I can leverage. I should probably dig into the code and see if there's a good way to simulate the hardware interaction needed to get these drivers to load. Let me look for a mock MDIO bus or something similar to see what's available. |
| 6/2 | 2026/07/13 17:23 | tool | grepper |
0mError:no matches Args: {
"Expression": "mdio.*mock"
}Results: {
"error": "no matches"
} |
| 7/2 | 2026/07/13 17:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12034 output: 19 thoughts: 18 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience, presented in the first person: **Investigating Userspace PHY Device Registration** Alright, let's dive into this. My initial thought is to probe whether it's actually possible to register a PHY device directly from userspace. I'm thinking about the implications here. Traditionally, PHY device management has been firmly rooted in the kernel, primarily due to the need for direct hardware access, interrupt handling, and managing the low-level communication protocols (MDIO, etc.). However, with the evolution of drivers and potential for more abstracted hardware interfaces, I'm curious if there's been any advancement in allowing userspace applications to participate in the PHY device lifecycle. Maybe via a well-defined API that provides safe and controlled access to the necessary kernel functionality. I'm wondering if there's a mechanism, perhaps through a character device, netlink socket, or even a newer, more sophisticated interface like UIO or VFIO, that would facilitate this. My immediate concern is security and resource management; how would we ensure that a userspace application doesn't inadvertently interfere with other network interfaces or introduce vulnerabilities? I'll need to explore the kernel source code, specifically looking at the relevant subsystem drivers, and see if there are any hints or existing mechanisms that could be extended or adapted for this purpose. I'm also interested in how this might interact with existing networking stack configurations, like bonding or bridging. |
| 8/2 | 2026/07/13 17:23 | tool | grepper |
0mArgs:{
"Expression": "phy_device_register"
}Results: {
"Output": "drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c=931=static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata)\n--\ndrivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c-975-\ndrivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c:976:\tret = phy_device_register(phydev);\ndrivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c-977-\tif (ret) {\ndrivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c:978:\t\tnetdev_err(pdata-\u003enetdev, \"phy_device_register failed\\n\");\ndrivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c-979-\t\tphy_device_free(phydev);\n--\ndrivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c=716=hns_mac_register_phydev(struct mii_bus *mdio, struct hns_mac_cb *mac_cb,\n--\ndrivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c-744-\t */\ndrivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c:745:\trc = phy_device_register(phy);\ndrivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c-746-\tif (rc) {\n--\ndrivers/net/ethernet/socionext/netsec.c=1929=static int netsec_register_mdio(struct netsec_priv *priv, u32 phy_addr)\n--\ndrivers/net/ethernet/socionext/netsec.c-1983-\ndrivers/net/ethernet/socionext/netsec.c:1984:\t\tret = phy_device_register(priv-\u003ephydev);\ndrivers/net/ethernet/socionext/netsec.c-1985-\t\tif (ret) {\n--\ndrivers/net/ethernet/socionext/netsec.c-1988-\t\t\tdev_err(priv-\u003edev,\ndrivers/net/ethernet/socionext/netsec.c:1989:\t\t\t\t\"phy_device_register err(%d)\\n\", ret);\ndrivers/net/ethernet/socionext/netsec.c-1990-\t\t}\n--\ndrivers/net/mdio/fwnode_mdio.c=42=fwnode_find_mii_timestamper(struct fwnode_handle *fwnode)\n--\ndrivers/net/mdio/fwnode_mdio.c-69-\ndrivers/net/mdio/fwnode_mdio.c:70:int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,\ndrivers/net/mdio/fwnode_mdio.c-71-\t\t\t\t struct phy_device *phy,\n--\ndrivers/net/mdio/fwnode_mdio.c-103-\t */\ndrivers/net/mdio/fwnode_mdio.c:104:\trc = phy_device_register(phy);\ndrivers/net/mdio/fwnode_mdio.c-105-\tif (rc) {\n--\ndrivers/net/mdio/fwnode_mdio.c-114-}\ndrivers/net/mdio/fwnode_mdio.c:115:EXPORT_SYMBOL(fwnode_mdiobus_phy_device_register);\ndrivers/net/mdio/fwnode_mdio.c-116-\ndrivers/net/mdio/fwnode_mdio.c=117=int fwnode_mdiobus_register_phy(struct mii_bus *bus,\n--\ndrivers/net/mdio/fwnode_mdio.c-149-\t\t/* All data is now stored in the phy struct, so register it */\ndrivers/net/mdio/fwnode_mdio.c:150:\t\trc = phy_device_register(phy);\ndrivers/net/mdio/fwnode_mdio.c-151-\t\tif (rc) {\n--\ndrivers/net/mdio/fwnode_mdio.c-156-\t} else if (is_of_node(child)) {\ndrivers/net/mdio/fwnode_mdio.c:157:\t\trc = fwnode_mdiobus_phy_device_register(bus, phy, child, addr);\ndrivers/net/mdio/fwnode_mdio.c-158-\t\tif (rc)\n--\ndrivers/net/mdio/mdio-xgene.c=263=struct phy_device *xgene_enet_phy_register(struct mii_bus *bus, int phy_addr)\n--\ndrivers/net/mdio/mdio-xgene.c-270-\ndrivers/net/mdio/mdio-xgene.c:271:\tif (phy_device_register(phy_dev))\ndrivers/net/mdio/mdio-xgene.c-272-\t\tphy_device_free(phy_dev);\n--\ndrivers/net/mdio/of_mdio.c=32=static int of_get_phy_id(struct device_node *device, u32 *phy_id)\n--\ndrivers/net/mdio/of_mdio.c-36-\ndrivers/net/mdio/of_mdio.c:37:int of_mdiobus_phy_device_register(struct mii_bus *mdio, struct phy_device *phy,\ndrivers/net/mdio/of_mdio.c-38-\t\t\t\t struct device_node *child, u32 addr)\ndrivers/net/mdio/of_mdio.c-39-{\ndrivers/net/mdio/of_mdio.c:40:\treturn fwnode_mdiobus_phy_device_register(mdio, phy,\ndrivers/net/mdio/of_mdio.c-41-\t\t\t\t\t\t of_fwnode_handle(child),\n--\ndrivers/net/mdio/of_mdio.c-43-}\ndrivers/net/mdio/of_mdio.c:44:EXPORT_SYMBOL(of_mdiobus_phy_device_register);\ndrivers/net/mdio/of_mdio.c-45-\n--\ndrivers/net/phy/fixed_phy.c=131=struct phy_device *fixed_phy_register(const struct fixed_phy_status *status,\n--\ndrivers/net/phy/fixed_phy.c-162-\ndrivers/net/phy/fixed_phy.c:163:\tret = phy_device_register(phy);\ndrivers/net/phy/fixed_phy.c-164-\tif (ret) {\n--\ndrivers/net/phy/mdio_bus_provider.c=408=static struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr, bool c45)\n--\ndrivers/net/phy/mdio_bus_provider.c-437-\ndrivers/net/phy/mdio_bus_provider.c:438:\terr = phy_device_register(phydev);\ndrivers/net/phy/mdio_bus_provider.c-439-\tif (err) {\n--\ndrivers/net/phy/nxp-tja11xx.c=551=static void tja1102_p1_register(struct work_struct *work)\n--\ndrivers/net/phy/nxp-tja11xx.c-597-\ndrivers/net/phy/nxp-tja11xx.c:598:\t\tret = of_mdiobus_phy_device_register(bus, phy, child, addr);\ndrivers/net/phy/nxp-tja11xx.c-599-\t\tif (ret) {\n--\ndrivers/net/phy/phy_device.c=1103=EXPORT_SYMBOL(get_phy_device);\n--\ndrivers/net/phy/phy_device.c-1105-/**\ndrivers/net/phy/phy_device.c:1106: * phy_device_register - Register the phy device on the MDIO bus\ndrivers/net/phy/phy_device.c-1107- * @phydev: phy_device structure to be added to the MDIO bus\ndrivers/net/phy/phy_device.c-1108- */\ndrivers/net/phy/phy_device.c:1109:int phy_device_register(struct phy_device *phydev)\ndrivers/net/phy/phy_device.c-1110-{\n--\ndrivers/net/phy/phy_device.c-1141-}\ndrivers/net/phy/phy_device.c:1142:EXPORT_SYMBOL(phy_device_register);\ndrivers/net/phy/phy_device.c-1143-\n--\ndrivers/net/phy/phy_device.c-1148- * This doesn't free the phy_device itself, it merely reverses the effects\ndrivers/net/phy/phy_device.c:1149: * of phy_device_register(). Use phy_device_free() to free the device\ndrivers/net/phy/phy_device.c-1150- * after calling this function.\n--\ndrivers/net/phy/sfp.c=2070=static int sfp_sm_probe_phy(struct sfp *sfp, int addr, bool is_c45)\n--\ndrivers/net/phy/sfp.c-2085-\ndrivers/net/phy/sfp.c:2086:\terr = phy_device_register(phy);\ndrivers/net/phy/sfp.c-2087-\tif (err) {\ndrivers/net/phy/sfp.c-2088-\t\tphy_device_free(phy);\ndrivers/net/phy/sfp.c:2089:\t\tdev_err(sfp-\u003edev, \"phy_device_register failed: %pe\\n\",\ndrivers/net/phy/sfp.c-2090-\t\t\tERR_PTR(err));\n--\ninclude/linux/fwnode_mdio.h-11-#if IS_ENABLED(CONFIG_FWNODE_MDIO)\ninclude/linux/fwnode_mdio.h:12:int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,\ninclude/linux/fwnode_mdio.h-13-\t\t\t\t struct phy_device *phy,\n--\ninclude/linux/fwnode_mdio.h=16=int fwnode_mdiobus_register_phy(struct mii_bus *bus,\n--\ninclude/linux/fwnode_mdio.h-19-#else /* CONFIG_FWNODE_MDIO */\ninclude/linux/fwnode_mdio.h:20:int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,\ninclude/linux/fwnode_mdio.h-21-\t\t\t\t struct phy_device *phy,\n--\ninclude/linux/of_mdio.h=49=bool of_phy_is_fixed_link(struct device_node *np);\ninclude/linux/of_mdio.h:50:int of_mdiobus_phy_device_register(struct mii_bus *mdio, struct phy_device *phy,\ninclude/linux/of_mdio.h-51-\t\t\t\t struct device_node *child, u32 addr);\n--\ninclude/linux/of_mdio.h=140=static inline bool of_phy_is_fixed_link(struct device_node *np)\n--\ninclude/linux/of_mdio.h-144-\ninclude/linux/of_mdio.h:145:static inline int of_mdiobus_phy_device_register(struct mii_bus *mdio,\ninclude/linux/of_mdio.h-146-\t\t\t\t\t struct phy_device *phy,\n--\ninclude/linux/phy.h=2159=struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);\ninclude/linux/phy.h:2160:int phy_device_register(struct phy_device *phy);\ninclude/linux/phy.h-2161-void phy_device_free(struct phy_device *phydev);\n"
} |
| 9/2 | 2026/07/13 17:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 15534 output: 19 thoughts: 331 Thoughts: **MDIO Bus Investigation for syzkaller** Okay, so I'm thinking about how we can potentially leverage syzkaller to reach the MDIO bus. I know syzkaller can use `ioctl(SIOCSMIIREG)` to write to it, which is intriguing. The catch, of course, is that there needs to *be* an MDIO bus present. Does syzkaller already have a way to establish one? Hmm, it does have `syz_genetlink_get_family` and `syz_init_net_socket`. And, hey, there's some evidence of `mdio` bus fuzzing in the codebase, but nothing explicit. Alright, what about creating a scenario where one gets created? I know `dap8211r_probe` gets called during a PHY device registration. Now the question is, can we *force* a PHY device registration from userspace? Nope, `phy_device_register` isn't exposed. Okay, back to the drawing board. Is there a virtual network device that *might* register a PHY? Thinking about `macb`, `xgbe`, `hns`, `netsec`, and `fixed_phy`. But, wait, `fixed_phy` definitely can't be registered from userspace. Then what about DSA? I recall that DSA can be configured via netlink or sysfs, but upon further reflection, it is configured via device tree. Okay, let's step back, syzkaller has `syz_usb_connect`. Could a USB network adapter get us there? Are there any USB Ethernet adapters that use MDIO and can probe arbitrary PHYs? Yes! It appears that drivers like `drivers/net/usb/lan78xx.c`, `smsc95xx.c`, `asix`, or `cdc_ether` could be potential candidates. Let's dig deeper and see if any of these USB network drivers register and scan an MDIO bus. This feels like the most promising angle at the moment. |
| 10/2 | 2026/07/13 17:23 | tool | grepper |
0mArgs:{
"Expression": "mdiobus_register"
}Results: {
"Output": "\nFull output is too long, showing 500 out of 1127 lines.\nUse more precise expression if possible.\n\nDocumentation/driver-api/driver-model/devres.rst=348=MDIO\n--\nDocumentation/driver-api/driver-model/devres.rst-350- devm_mdiobus_alloc_size()\nDocumentation/driver-api/driver-model/devres.rst:351: devm_mdiobus_register()\nDocumentation/driver-api/driver-model/devres.rst:352: devm_of_mdiobus_register()\nDocumentation/driver-api/driver-model/devres.rst-353-\n--\nDocumentation/firmware-guide/acpi/dsd/motorcomm-yt8xxx-phy.rst=12=device (the same objects that are registered via\nDocumentation/firmware-guide/acpi/dsd/motorcomm-yt8xxx-phy.rst:13:``fwnode_mdiobus_register_phy()``). MAC-side connection properties such as\nDocumentation/firmware-guide/acpi/dsd/motorcomm-yt8xxx-phy.rst-14-``phy-handle`` and ``phy-mode`` are documented in [acpi-mdio-phy]_.\n--\nDocumentation/firmware-guide/acpi/dsd/phy.rst=7=The PHYs on an MDIO bus [phy] are probed and registered using\nDocumentation/firmware-guide/acpi/dsd/phy.rst:8:fwnode_mdiobus_register_phy().\nDocumentation/firmware-guide/acpi/dsd/phy.rst-9-\n--\nDocumentation/networking/phy.rst=40=registered as a distinct device.\n--\nDocumentation/networking/phy.rst-56- driver needs, setup the mii_bus structure, and register with the PAL using\nDocumentation/networking/phy.rst:57: mdiobus_register. Similarly, there's a remove function to undo all of\nDocumentation/networking/phy.rst-58- that (use mdiobus_unregister).\n--\narch/powerpc/platforms/82xx/ep8248e.c=109=static int ep8248e_mdio_probe(struct platform_device *ofdev)\n--\narch/powerpc/platforms/82xx/ep8248e.c-132-\narch/powerpc/platforms/82xx/ep8248e.c:133:\tret = of_mdiobus_register(bus, ofdev-\u003edev.of_node);\narch/powerpc/platforms/82xx/ep8248e.c-134-\tif (ret)\n--\narch/powerpc/platforms/pasemi/gpio_mdio.c=207=static int gpio_mdio_probe(struct platform_device *ofdev)\n--\narch/powerpc/platforms/pasemi/gpio_mdio.c-243-\narch/powerpc/platforms/pasemi/gpio_mdio.c:244:\terr = of_mdiobus_register(new_bus, np);\narch/powerpc/platforms/pasemi/gpio_mdio.c-245-\n--\ndrivers/net/dsa/bcm_sf2.c=607=static int bcm_sf2_mdio_register(struct dsa_switch *ds)\n--\ndrivers/net/dsa/bcm_sf2.c-683-\ndrivers/net/dsa/bcm_sf2.c:684:\terr = mdiobus_register(priv-\u003euser_mii_bus);\ndrivers/net/dsa/bcm_sf2.c-685-\tif (err)\n--\ndrivers/net/dsa/lantiq/lantiq_gswip_common.c=187=static int gswip_mdio(struct gswip_priv *priv)\n--\ndrivers/net/dsa/lantiq/lantiq_gswip_common.c-213-\ndrivers/net/dsa/lantiq/lantiq_gswip_common.c:214:\terr = devm_of_mdiobus_register(dev, bus, mdio_np);\ndrivers/net/dsa/lantiq/lantiq_gswip_common.c-215-\n--\ndrivers/net/dsa/microchip/ksz9477.c=321=static int ksz9477_pcs_create(struct ksz_device *dev)\n--\ndrivers/net/dsa/microchip/ksz9477.c-341-\ndrivers/net/dsa/microchip/ksz9477.c:342:\tret = devm_mdiobus_register(dev-\u003edev, bus);\ndrivers/net/dsa/microchip/ksz9477.c-343-\tif (ret)\n--\ndrivers/net/dsa/microchip/ksz_common.c=2321=int ksz_mdio_register(struct ksz_device *dev)\n--\ndrivers/net/dsa/microchip/ksz_common.c-2392-\ndrivers/net/dsa/microchip/ksz_common.c:2393:\tret = devm_of_mdiobus_register(ds-\u003edev, bus, mdio_np);\ndrivers/net/dsa/microchip/ksz_common.c-2394-\tif (ret) {\n--\ndrivers/net/dsa/microchip/lan937x_main.c=685=static int lan937x_mdio_register(struct ksz_device *dev)\n--\ndrivers/net/dsa/microchip/lan937x_main.c-755-\ndrivers/net/dsa/microchip/lan937x_main.c:756:\tret = devm_of_mdiobus_register(ds-\u003edev, bus, mdio_np);\ndrivers/net/dsa/microchip/lan937x_main.c-757-\tif (ret)\n--\ndrivers/net/dsa/mt7530.c=2371=mt7530_setup_mdio(struct mt7530_priv *priv)\n--\ndrivers/net/dsa/mt7530.c-2406-\ndrivers/net/dsa/mt7530.c:2407:\tret = devm_of_mdiobus_register(dev, bus, mnp);\ndrivers/net/dsa/mt7530.c-2408-\tif (ret) {\n--\ndrivers/net/dsa/mv88e6xxx/chip.c=3834=static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-3887-\ndrivers/net/dsa/mv88e6xxx/chip.c:3888:\terr = of_mdiobus_register(bus, np);\ndrivers/net/dsa/mv88e6xxx/chip.c-3889-\tif (err) {\n--\ndrivers/net/dsa/mxl862xx/mxl862xx.c=267=static int mxl862xx_setup_mdio(struct dsa_switch *ds)\n--\ndrivers/net/dsa/mxl862xx/mxl862xx.c-292-\ndrivers/net/dsa/mxl862xx/mxl862xx.c:293:\tret = devm_of_mdiobus_register(dev, bus, mdio_np);\ndrivers/net/dsa/mxl862xx/mxl862xx.c-294-\tof_node_put(mdio_np);\n--\ndrivers/net/dsa/netc/netc_main.c=149=static int netc_port_create_emdio_bus(struct netc_port *np,\n--\ndrivers/net/dsa/netc/netc_main.c-179-\ndrivers/net/dsa/netc/netc_main.c:180:\terr = devm_of_mdiobus_register(dev, bus, node);\ndrivers/net/dsa/netc/netc_main.c-181-\tif (err)\n--\ndrivers/net/dsa/ocelot/felix_vsc9959.c=957=static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)\n--\ndrivers/net/dsa/ocelot/felix_vsc9959.c-1013-\t/* Needed in order to initialize the bus mutex lock */\ndrivers/net/dsa/ocelot/felix_vsc9959.c:1014:\trc = mdiobus_register(bus);\ndrivers/net/dsa/ocelot/felix_vsc9959.c-1015-\tif (rc \u003c 0) {\n--\ndrivers/net/dsa/ocelot/seville_vsc9953.c=878=static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)\n--\ndrivers/net/dsa/ocelot/seville_vsc9953.c-903-\t/* Needed in order to initialize the bus mutex lock */\ndrivers/net/dsa/ocelot/seville_vsc9953.c:904:\trc = devm_of_mdiobus_register(dev, bus, NULL);\ndrivers/net/dsa/ocelot/seville_vsc9953.c-905-\tif (rc \u003c 0) {\n--\ndrivers/net/dsa/qca/ar9331.c=357=static int ar9331_sw_mbus_init(struct ar9331_sw_priv *priv)\n--\ndrivers/net/dsa/qca/ar9331.c-381-\ndrivers/net/dsa/qca/ar9331.c:382:\tret = devm_of_mdiobus_register(dev, mbus, mnp);\ndrivers/net/dsa/qca/ar9331.c-383-\tof_node_put(mnp);\n--\ndrivers/net/dsa/qca/qca8k-8xxx.c=947=qca8k_mdio_register(struct qca8k_priv *priv)\n--\ndrivers/net/dsa/qca/qca8k-8xxx.c-986-\ndrivers/net/dsa/qca/qca8k-8xxx.c:987:\tret = devm_of_mdiobus_register(dev, bus, mdio);\ndrivers/net/dsa/qca/qca8k-8xxx.c-988-\n--\ndrivers/net/dsa/realtek/rtl83xx.c=74=int rtl83xx_setup_user_mdio(struct dsa_switch *ds)\n--\ndrivers/net/dsa/realtek/rtl83xx.c-99-\ndrivers/net/dsa/realtek/rtl83xx.c:100:\tret = devm_of_mdiobus_register(priv-\u003edev, bus, mdio_np);\ndrivers/net/dsa/realtek/rtl83xx.c-101-\tif (ret) {\n--\ndrivers/net/dsa/rzn1_a5psw.c=1117=static int a5psw_probe_mdio(struct a5psw *a5psw, struct device_node *node)\n--\ndrivers/net/dsa/rzn1_a5psw.c-1143-\ndrivers/net/dsa/rzn1_a5psw.c:1144:\treturn devm_of_mdiobus_register(dev, bus, node);\ndrivers/net/dsa/rzn1_a5psw.c-1145-}\n--\ndrivers/net/dsa/sja1105/sja1105.h=307=void sja1105_frame_memory_partitioning(struct sja1105_private *priv);\n--\ndrivers/net/dsa/sja1105/sja1105.h-309-/* From sja1105_mdio.c */\ndrivers/net/dsa/sja1105/sja1105.h:310:int sja1105_mdiobus_register(struct dsa_switch *ds);\ndrivers/net/dsa/sja1105/sja1105.h-311-void sja1105_mdiobus_unregister(struct dsa_switch *ds);\n--\ndrivers/net/dsa/sja1105/sja1105_main.c=3026=static int sja1105_setup(struct dsa_switch *ds)\n--\ndrivers/net/dsa/sja1105/sja1105_main.c-3067-\ndrivers/net/dsa/sja1105/sja1105_main.c:3068:\trc = sja1105_mdiobus_register(ds);\ndrivers/net/dsa/sja1105/sja1105_main.c-3069-\tif (rc \u003c 0) {\n--\ndrivers/net/dsa/sja1105/sja1105_mdio.c=258=static int sja1105_mdiobus_base_tx_register(struct sja1105_private *priv,\n--\ndrivers/net/dsa/sja1105/sja1105_mdio.c-287-\ndrivers/net/dsa/sja1105/sja1105_mdio.c:288:\trc = of_mdiobus_register(bus, np);\ndrivers/net/dsa/sja1105/sja1105_mdio.c-289-\tif (rc) {\n--\ndrivers/net/dsa/sja1105/sja1105_mdio.c=312=static int sja1105_mdiobus_base_t1_register(struct sja1105_private *priv,\n--\ndrivers/net/dsa/sja1105/sja1105_mdio.c-343-\ndrivers/net/dsa/sja1105/sja1105_mdio.c:344:\trc = of_mdiobus_register(bus, np);\ndrivers/net/dsa/sja1105/sja1105_mdio.c-345-\tif (rc) {\n--\ndrivers/net/dsa/sja1105/sja1105_mdio.c=368=static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)\n--\ndrivers/net/dsa/sja1105/sja1105_mdio.c-395-\ndrivers/net/dsa/sja1105/sja1105_mdio.c:396:\trc = mdiobus_register(bus);\ndrivers/net/dsa/sja1105/sja1105_mdio.c-397-\tif (rc) {\n--\ndrivers/net/dsa/sja1105/sja1105_mdio.c=439=static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv)\n--\ndrivers/net/dsa/sja1105/sja1105_mdio.c-458-\ndrivers/net/dsa/sja1105/sja1105_mdio.c:459:int sja1105_mdiobus_register(struct dsa_switch *ds)\ndrivers/net/dsa/sja1105/sja1105_mdio.c-460-{\n--\ndrivers/net/dsa/yt921x.c=595=yt921x_mbus_int_init(struct yt921x_priv *priv, struct device_node *mnp)\n--\ndrivers/net/dsa/yt921x.c-612-\ndrivers/net/dsa/yt921x.c:613:\tres = devm_of_mdiobus_register(dev, mbus, mnp);\ndrivers/net/dsa/yt921x.c-614-\tif (res)\n--\ndrivers/net/dsa/yt921x.c=726=yt921x_mbus_ext_init(struct yt921x_priv *priv, struct device_node *mnp)\n--\ndrivers/net/dsa/yt921x.c-743-\ndrivers/net/dsa/yt921x.c:744:\tres = devm_of_mdiobus_register(dev, mbus, mnp);\ndrivers/net/dsa/yt921x.c-745-\tif (res)\n--\ndrivers/net/ethernet/8390/ax88796.c=459=static int ax_mii_init(struct net_device *dev)\n--\ndrivers/net/ethernet/8390/ax88796.c-478-\ndrivers/net/ethernet/8390/ax88796.c:479:\terr = mdiobus_register(ax-\u003emii_bus);\ndrivers/net/ethernet/8390/ax88796.c-480-\tif (err)\n--\ndrivers/net/ethernet/actions/owl-emac.c=1321=static int owl_emac_mdio_init(struct net_device *netdev)\n--\ndrivers/net/ethernet/actions/owl-emac.c-1345-\ndrivers/net/ethernet/actions/owl-emac.c:1346:\tret = devm_of_mdiobus_register(dev, priv-\u003emii, mdio_node);\ndrivers/net/ethernet/actions/owl-emac.c-1347-\n--\ndrivers/net/ethernet/adi/adin1110.c=509=static int adin1110_register_mdiobus(struct adin1110_priv *priv,\n--\ndrivers/net/ethernet/adi/adin1110.c-529-\ndrivers/net/ethernet/adi/adin1110.c:530:\tret = devm_mdiobus_register(dev, mii_bus);\ndrivers/net/ethernet/adi/adin1110.c-531-\tif (ret)\n--\ndrivers/net/ethernet/aeroflex/greth.c=1290=static int greth_mdio_init(struct greth_private *greth)\n--\ndrivers/net/ethernet/aeroflex/greth.c-1306-\ndrivers/net/ethernet/aeroflex/greth.c:1307:\tret = mdiobus_register(greth-\u003emdio);\ndrivers/net/ethernet/aeroflex/greth.c-1308-\tif (ret) {\n--\ndrivers/net/ethernet/agere/et131x.c=3931=static int et131x_pci_setup(struct pci_dev *pdev,\n--\ndrivers/net/ethernet/agere/et131x.c-4026-\ndrivers/net/ethernet/agere/et131x.c:4027:\trc = mdiobus_register(adapter-\u003emii_bus);\ndrivers/net/ethernet/agere/et131x.c-4028-\tif (rc \u003c 0) {\n--\ndrivers/net/ethernet/altera/altera_tse_main.c=121=static int altera_tse_mdio_create(struct net_device *dev, unsigned int id)\n--\ndrivers/net/ethernet/altera/altera_tse_main.c-157-\ndrivers/net/ethernet/altera/altera_tse_main.c:158:\tret = of_mdiobus_register(mdio, mdio_node);\ndrivers/net/ethernet/altera/altera_tse_main.c-159-\tif (ret != 0) {\n--\ndrivers/net/ethernet/amd/au1000_eth.c=1061=static int au1000_probe(struct platform_device *pdev)\n--\ndrivers/net/ethernet/amd/au1000_eth.c-1221-\ndrivers/net/ethernet/amd/au1000_eth.c:1222:\terr = mdiobus_register(aup-\u003emii_bus);\ndrivers/net/ethernet/amd/au1000_eth.c-1223-\tif (err) {\n--\ndrivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c=3428=static int xgbe_phy_init(struct xgbe_prv_data *pdata)\n--\ndrivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c-3717-\tsnprintf(mii-\u003eid, sizeof(mii-\u003eid), \"%s\", dev_name(pdata-\u003edev));\ndrivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c:3718:\tret = mdiobus_register(mii);\ndrivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c-3719-\tif (ret) {\ndrivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c:3720:\t\tdev_err(pdata-\u003edev, \"mdiobus_register failed\\n\");\ndrivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c-3721-\t\treturn ret;\n--\ndrivers/net/ethernet/apm/xgene-v2/mdio.c=98=int xge_mdio_config(struct net_device *ndev)\n--\ndrivers/net/ethernet/apm/xgene-v2/mdio.c-118-\tmdio_bus-\u003ephy_mask = 0x1;\ndrivers/net/ethernet/apm/xgene-v2/mdio.c:119:\tret = mdiobus_register(mdio_bus);\ndrivers/net/ethernet/apm/xgene-v2/mdio.c-120-\tif (ret)\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c=837=int xgene_enet_phy_connect(struct net_device *ndev)\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-887-\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c:888:static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata,\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-889-\t\t\t\t struct mii_bus *mdio)\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-912-\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c:913:\t\tret = of_mdiobus_register(mdio, mdio_np);\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-914-\t\tof_node_put(mdio_np);\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-921-\t/* Register the MDIO bus */\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c:922:\tret = mdiobus_register(mdio);\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-923-\tif (ret)\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c=939=int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-957-\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c:958:\tret = xgene_mdiobus_register(pdata, mdio_bus);\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-959-\tif (ret) {\n--\ndrivers/net/ethernet/arc/emac_mdio.c=131=int arc_mdio_probe(struct arc_emac_priv *priv)\n--\ndrivers/net/ethernet/arc/emac_mdio.c-172-\ndrivers/net/ethernet/arc/emac_mdio.c:173:\terror = of_mdiobus_register(bus, mdio_node);\ndrivers/net/ethernet/arc/emac_mdio.c-174-\tof_node_put(mdio_node);\n--\ndrivers/net/ethernet/asix/ax88796c_main.c=966=static int ax88796c_probe(struct spi_device *spi)\n--\ndrivers/net/ethernet/asix/ax88796c_main.c-1010-\ndrivers/net/ethernet/asix/ax88796c_main.c:1011:\tret = devm_mdiobus_register(\u0026spi-\u003edev, ax_local-\u003emdiobus);\ndrivers/net/ethernet/asix/ax88796c_main.c-1012-\tif (ret \u003c 0) {\n--\ndrivers/net/ethernet/atheros/ag71xx.c=687=static int ag71xx_mdio_probe(struct ag71xx *ag)\n--\ndrivers/net/ethernet/atheros/ag71xx.c-727-\tmnp = of_get_child_by_name(np, \"mdio\");\ndrivers/net/ethernet/atheros/ag71xx.c:728:\terr = devm_of_mdiobus_register(dev, mii_bus, mnp);\ndrivers/net/ethernet/atheros/ag71xx.c-729-\tof_node_put(mnp);\n--\ndrivers/net/ethernet/broadcom/b44.c=2234=static int b44_register_phy_one(struct b44 *bp)\n--\ndrivers/net/ethernet/broadcom/b44.c-2259-\ndrivers/net/ethernet/broadcom/b44.c:2260:\terr = mdiobus_register(mii_bus);\ndrivers/net/ethernet/broadcom/b44.c-2261-\tif (err) {\n--\ndrivers/net/ethernet/broadcom/bcm63xx_enet.c=1713=static int bcm_enet_probe(struct platform_device *pdev)\n--\ndrivers/net/ethernet/broadcom/bcm63xx_enet.c-1829-\ndrivers/net/ethernet/broadcom/bcm63xx_enet.c:1830:\t\tret = mdiobus_register(bus);\ndrivers/net/ethernet/broadcom/bcm63xx_enet.c-1831-\t\tif (ret) {\n--\ndrivers/net/ethernet/broadcom/bgmac-bcma-mdio.c=211=struct mii_bus *bcma_mdio_mii_register(struct bgmac *bgmac)\n--\ndrivers/net/ethernet/broadcom/bgmac-bcma-mdio.c-235-\ndrivers/net/ethernet/broadcom/bgmac-bcma-mdio.c:236:\terr = of_mdiobus_register(mii_bus, np);\ndrivers/net/ethernet/broadcom/bgmac-bcma-mdio.c-237-\tof_node_put(np);\n--\ndrivers/net/ethernet/broadcom/genet/bcmmii.c=193=int bcmgenet_mii_config(struct net_device *dev, bool init)\n--\ndrivers/net/ethernet/broadcom/genet/bcmmii.c-233-\t\tphy_name = \"external RvMII\";\ndrivers/net/ethernet/broadcom/genet/bcmmii.c:234:\t\t/* of_mdiobus_register took care of reading the 'max-speed'\ndrivers/net/ethernet/broadcom/genet/bcmmii.c-235-\t\t * PHY property for us, effectively limiting the PHY supported\n--\ndrivers/net/ethernet/broadcom/sb1250-mac.c=2157=static int sbmac_init(struct platform_device *pldev, long long base)\n--\ndrivers/net/ethernet/broadcom/sb1250-mac.c-2227-\t */\ndrivers/net/ethernet/broadcom/sb1250-mac.c:2228:\terr = mdiobus_register(sc-\u003emii_bus);\ndrivers/net/ethernet/broadcom/sb1250-mac.c-2229-\tif (err) {\n--\ndrivers/net/ethernet/broadcom/tg3.c=1505=static int tg3_mdio_init(struct tg3 *tp)\n--\ndrivers/net/ethernet/broadcom/tg3.c-1557-\ndrivers/net/ethernet/broadcom/tg3.c:1558:\ti = mdiobus_register(tp-\u003emdio_bus);\ndrivers/net/ethernet/broadcom/tg3.c-1559-\tif (i) {\n--\ndrivers/net/ethernet/cadence/macb_main.c=1023=static int macb_mii_probe(struct net_device *dev)\n--\ndrivers/net/ethernet/cadence/macb_main.c-1096-\ndrivers/net/ethernet/cadence/macb_main.c:1097:static int macb_mdiobus_register(struct macb *bp, struct device_node *mdio_np)\ndrivers/net/ethernet/cadence/macb_main.c-1098-{\n--\ndrivers/net/ethernet/cadence/macb_main.c-1104-\tif (mdio_np)\ndrivers/net/ethernet/cadence/macb_main.c:1105:\t\treturn of_mdiobus_register(bp-\u003emii_bus, mdio_np);\ndrivers/net/ethernet/cadence/macb_main.c-1106-\n--\ndrivers/net/ethernet/cadence/macb_main.c-1118-\ndrivers/net/ethernet/cadence/macb_main.c:1119:\t\t\treturn of_mdiobus_register(bp-\u003emii_bus, np);\ndrivers/net/ethernet/cadence/macb_main.c-1120-\t\t}\ndrivers/net/ethernet/cadence/macb_main.c-1121-\ndrivers/net/ethernet/cadence/macb_main.c:1122:\treturn mdiobus_register(bp-\u003emii_bus);\ndrivers/net/ethernet/cadence/macb_main.c-1123-}\n--\ndrivers/net/ethernet/cadence/macb_main.c=1125=static int macb_mii_init(struct macb *bp)\n--\ndrivers/net/ethernet/cadence/macb_main.c-1158-\ndrivers/net/ethernet/cadence/macb_main.c:1159:\terr = macb_mdiobus_register(bp, mdio_np);\ndrivers/net/ethernet/cadence/macb_main.c-1160-\tif (err)\n--\ndrivers/net/ethernet/davicom/dm9051.c=1107=static int dm9051_mdio_register(struct board_info *db)\n--\ndrivers/net/ethernet/davicom/dm9051.c-1124-\ndrivers/net/ethernet/davicom/dm9051.c:1125:\tret = devm_mdiobus_register(\u0026spi-\u003edev, db-\u003emdiobus);\ndrivers/net/ethernet/davicom/dm9051.c-1126-\tif (ret)\n--\ndrivers/net/ethernet/engleder/tsnep_main.c=2423=static int tsnep_mdio_init(struct tsnep_adapter *adapter)\n--\ndrivers/net/ethernet/engleder/tsnep_main.c-2454-\ndrivers/net/ethernet/engleder/tsnep_main.c:2455:\tretval = of_mdiobus_register(adapter-\u003emdiobus, np);\ndrivers/net/ethernet/engleder/tsnep_main.c-2456-\n--\ndrivers/net/ethernet/ethoc.c=1024=static int ethoc_probe(struct platform_device *pdev)\n--\ndrivers/net/ethernet/ethoc.c-1207-\ndrivers/net/ethernet/ethoc.c:1208:\tret = mdiobus_register(priv-\u003emdio);\ndrivers/net/ethernet/ethoc.c-1209-\tif (ret) {\n--\ndrivers/net/ethernet/faraday/ftgmac100.c=1734=static int ftgmac100_setup_mdio(struct net_device *netdev)\n--\ndrivers/net/ethernet/faraday/ftgmac100.c-1769-\ndrivers/net/ethernet/faraday/ftgmac100.c:1770:\terr = devm_of_mdiobus_register(priv-\u003edev, priv-\u003emii_bus, mdio_np);\ndrivers/net/ethernet/faraday/ftgmac100.c-1771-\tof_node_put(mdio_np);\n--\ndrivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c=36=static int enetc_pci_mdio_probe(struct pci_dev *pdev,\n--\ndrivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c-90-\ndrivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c:91:\terr = of_mdiobus_register(bus, dev-\u003eof_node);\ndrivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c-92-\tif (err)\n--\ndrivers/net/ethernet/freescale/enetc/enetc_pf_common.c=160=static int enetc_mdio_probe(struct enetc_pf *pf, struct device_node *np)\n--\ndrivers/net/ethernet/freescale/enetc/enetc_pf_common.c-186-\ndrivers/net/ethernet/freescale/enetc/enetc_pf_common.c:187:\terr = of_mdiobus_register(bus, np);\ndrivers/net/ethernet/freescale/enetc/enetc_pf_common.c-188-\tif (err)\n--\ndrivers/net/ethernet/freescale/enetc/enetc_pf_common.c=202=static int enetc_imdio_create(struct enetc_pf *pf)\n--\ndrivers/net/ethernet/freescale/enetc/enetc_pf_common.c-236-\ndrivers/net/ethernet/freescale/enetc/enetc_pf_common.c:237:\terr = mdiobus_register(bus);\ndrivers/net/ethernet/freescale/enetc/enetc_pf_common.c-238-\tif (err) {\n--\ndrivers/net/ethernet/freescale/fec_main.c=3042=static int fec_enet_mii_init(struct platform_device *pdev)\n--\ndrivers/net/ethernet/freescale/fec_main.c-3160-\ndrivers/net/ethernet/freescale/fec_main.c:3161:\terr = of_mdiobus_register(fep-\u003emii_bus, node);\ndrivers/net/ethernet/freescale/fec_main.c-3162-\tif (err)\n--\ndrivers/net/ethernet/freescale/fec_mpc52xx_phy.c=65=static int mpc52xx_fec_mdio_probe(struct platform_device *of)\n--\ndrivers/net/ethernet/freescale/fec_mpc52xx_phy.c-105-\ndrivers/net/ethernet/freescale/fec_mpc52xx_phy.c:106:\terr = of_mdiobus_register(bus, np);\ndrivers/net/ethernet/freescale/fec_mpc52xx_phy.c-107-\tif (err)\n--\ndrivers/net/ethernet/freescale/fs_enet/mii-bitbang.c=149=static int fs_enet_mdio_probe(struct platform_device *ofdev)\n--\ndrivers/net/ethernet/freescale/fs_enet/mii-bitbang.c-175-\ndrivers/net/ethernet/freescale/fs_enet/mii-bitbang.c:176:\tret = of_mdiobus_register(new_bus, ofdev-\u003edev.of_node);\ndrivers/net/ethernet/freescale/fs_enet/mii-bitbang.c-177-\tif (ret)\n--\ndrivers/net/ethernet/freescale/fs_enet/mii-fec.c=97=static int fs_enet_mdio_probe(struct platform_device *ofdev)\n--\ndrivers/net/ethernet/freescale/fs_enet/mii-fec.c-166-\ndrivers/net/ethernet/freescale/fs_enet/mii-fec.c:167:\tret = of_mdiobus_register(new_bus, ofdev-\u003edev.of_node);\ndrivers/net/ethernet/freescale/fs_enet/mii-fec.c-168-\tif (ret)\n--\ndrivers/net/ethernet/freescale/fsl_pq_mdio.c=409=static int fsl_pq_mdio_probe(struct platform_device *pdev)\n--\ndrivers/net/ethernet/freescale/fsl_pq_mdio.c-493-\ndrivers/net/ethernet/freescale/fsl_pq_mdio.c:494:\terr = of_mdiobus_register(new_bus, np);\ndrivers/net/ethernet/freescale/fsl_pq_mdio.c-495-\tif (err) {\n--\ndrivers/net/ethernet/freescale/xgmac_mdio.c=371=static int xgmac_mdio_probe(struct platform_device *pdev)\n--\ndrivers/net/ethernet/freescale/xgmac_mdio.c-426-\tif (is_of_node(fwnode))\ndrivers/net/ethernet/freescale/xgmac_mdio.c:427:\t\tret = of_mdiobus_register(bus, to_of_node(fwnode));\ndrivers/net/ethernet/freescale/xgmac_mdio.c-428-\telse if (is_acpi_node(fwnode))\ndrivers/net/ethernet/freescale/xgmac_mdio.c:429:\t\tret = acpi_mdiobus_register(bus, fwnode);\ndrivers/net/ethernet/freescale/xgmac_mdio.c-430-\telse\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c=266=int hbg_mdio_init(struct hbg_priv *priv)\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-291-\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:292:\tret = devm_mdiobus_register(dev, mdio_bus);\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-293-\tif (ret)\n--\ndrivers/net/ethernet/hisilicon/hix5hd2_gmac.c=1094=static int hix5hd2_dev_probe(struct platform_device *pdev)\n--\ndrivers/net/ethernet/hisilicon/hix5hd2_gmac.c-1185-\ndrivers/net/ethernet/hisilicon/hix5hd2_gmac.c:1186:\tret = of_mdiobus_register(bus, node);\ndrivers/net/ethernet/hisilicon/hix5hd2_gmac.c-1187-\tif (ret)\n--\ndrivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c=123=int hclge_mac_mdio_config(struct hclge_dev *hdev)\n--\ndrivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c-154-\tmdio_bus-\u003ephy_mask = ~(1U \u003c\u003c mac-\u003ephy_addr);\ndrivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c:155:\tret = mdiobus_register(mdio_bus);\ndrivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c-156-\tif (ret) {\n--\ndrivers/net/ethernet/hisilicon/hns_mdio.c=495=static int hns_mdio_probe(struct platform_device *pdev)\n--\ndrivers/net/ethernet/hisilicon/hns_mdio.c-583-\ndrivers/net/ethernet/hisilicon/hns_mdio.c:584:\t\tret = of_mdiobus_register(new_bus, pdev-\u003edev.of_node);\ndrivers/net/ethernet/hisilicon/hns_mdio.c-585-\t} else if (is_acpi_node(pdev-\u003edev.fwnode)) {\n--\ndrivers/net/ethernet/hisilicon/hns_mdio.c-592-\t\t/* Register the MDIO bus */\ndrivers/net/ethernet/hisilicon/hns_mdio.c:593:\t\tret = mdiobus_register(new_bus);\ndrivers/net/ethernet/hisilicon/hns_mdio.c-594-\t} else {\n--\ndrivers/net/ethernet/ibm/emac/core.c=2560=static int emac_dt_mdio_probe(struct emac_instance *dev)\n--\ndrivers/net/ethernet/ibm/emac/core.c-2584-\tsnprintf(bus-\u003eid, MII_BUS_ID_SIZE, \"%s\", dev-\u003eofdev-\u003ename);\ndrivers/net/ethernet/ibm/emac/core.c:2585:\tres = devm_of_mdiobus_register(\u0026dev-\u003eofdev-\u003edev, bus, mii_np);\ndrivers/net/ethernet/ibm/emac/core.c-2586-\tif (res) {\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_phy.c=1026=int ixgbe_mii_bus_init(struct ixgbe_hw *hw)\n--\ndrivers/net/ethernet/intel/ixgbe/ixgbe_phy.c-1088-\tadapter-\u003emii_bus = bus;\ndrivers/net/ethernet/intel/ixgbe/ixgbe_phy.c:1089:\treturn mdiobus_register(bus);\ndrivers/net/ethernet/intel/ixgbe/ixgbe_phy.c-1090-}\n--\ndrivers/net/ethernet/lantiq_etop.c=385=ltq_etop_mdio_init(struct net_device *dev)\n--\ndrivers/net/ethernet/lantiq_etop.c-402-\t\t priv-\u003epdev-\u003ename, priv-\u003epdev-\u003eid);\ndrivers/net/ethernet/lantiq_etop.c:403:\tif (mdiobus_register(priv-\u003emii_bus)) {\ndrivers/net/ethernet/lantiq_etop.c-404-\t\terr = -ENXIO;\n--\ndrivers/net/ethernet/marvell/mvmdio.c=283=static int orion_mdio_probe(struct platform_device *pdev)\n--\ndrivers/net/ethernet/marvell/mvmdio.c-381-\t/* For the platforms not supporting DT/ACPI fall-back\ndrivers/net/ethernet/marvell/mvmdio.c:382:\t * to mdiobus_register via of_mdiobus_register.\ndrivers/net/ethernet/marvell/mvmdio.c-383-\t */\ndrivers/net/ethernet/marvell/mvmdio.c-384-\tif (is_acpi_node(pdev-\u003edev.fwnode))\ndrivers/net/ethernet/marvell/mvmdio.c:385:\t\tret = acpi_mdiobus_register(bus, pdev-\u003edev.fwnode);\ndrivers/net/ethernet/marvell/mvmdio.c-386-\telse\ndrivers/net/ethernet/marvell/mvmdio.c:387:\t\tret = of_mdiobus_register(bus, pdev-\u003edev.of_node);\ndrivers/net/ethernet/marvell/mvmdio.c-388-\tif (ret \u003c 0) {\n--\ndrivers/net/ethernet/marvell/pxa168_eth.c=1387=static int pxa168_eth_probe(struct platform_device *pdev)\n--\ndrivers/net/ethernet/marvell/pxa168_eth.c-1504-\tpep-\u003esmi_bus-\u003ephy_mask = 0xffffffff;\ndrivers/net/ethernet/marvell/pxa168_eth.c:1505:\terr = mdiobus_register(pep-\u003esmi_bus);\ndrivers/net/ethernet/marvell/pxa168_eth.c-1506-\tif (err)\n--\ndrivers/net/ethernet/mediatek/mtk_eth_soc.c=998=static int mtk_mdio_init(struct mtk_eth *eth)\n--\ndrivers/net/ethernet/mediatek/mtk_eth_soc.c-1037-\tdev_dbg(eth-\u003edev, \"MDC is running on %d Hz\\n\", MDC_MAX_FREQ / eth-\u003emdc_divider);\ndrivers/net/ethernet/mediatek/mtk_eth_soc.c:1038:\tret = of_mdiobus_register(eth-\u003emii_bus, mii_np);\ndrivers/net/ethernet/mediatek/mtk_eth_soc.c-1039-\n--\ndrivers/net/ethernet/mediatek/mtk_star_emac.c=1422=static int mtk_star_mdio_init(struct net_device *ndev)\n--\ndrivers/net/ethernet/mediatek/mtk_star_emac.c-1447-\ndrivers/net/ethernet/mediatek/mtk_star_emac.c:1448:\tret = devm_of_mdiobus_register(dev, priv-\u003emii, mdio_node);\ndrivers/net/ethernet/mediatek/mtk_star_emac.c-1449-\n--\ndrivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c=287=int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv)\n--\ndrivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c-332-\ndrivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c:333:\tret = mdiobus_register(priv-\u003emdiobus);\ndrivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c-334-\tif (ret)\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_mdio.c=253=int fbnic_mdiobus_create(struct fbnic_dev *fbd)\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_mdio.c-272-\ndrivers/net/ethernet/meta/fbnic/fbnic_mdio.c:273:\terr = devm_mdiobus_register(fbd-\u003edev, bus);\ndrivers/net/ethernet/meta/fbnic/fbnic_mdio.c-274-\tif (err) {\n--\ndrivers/net/ethernet/micrel/ks8851_common.c=1036=static int ks8851_register_mdiobus(struct ks8851_net *ks, struct device *dev)\n--\ndrivers/net/ethernet/micrel/ks8851_common.c-1052-\ndrivers/net/ethernet/micrel/ks8851_common.c:1053:\tret = mdiobus_register(mii_bus);\ndrivers/net/ethernet/micrel/ks8851_common.c-1054-\tif (ret)\ndrivers/net/ethernet/micrel/ks8851_common.c:1055:\t\tgoto err_mdiobus_register;\ndrivers/net/ethernet/micrel/ks8851_common.c-1056-\n--\ndrivers/net/ethernet/micrel/ks8851_common.c-1060-\n\n"
} |
| 11/2 | 2026/07/13 17:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 29244 output: 31 thoughts: 86 Thoughts: **Examining the MDIO Bus Driver Landscape** Okay, let's see... I'm looking at a few MDIO bus-related functions – `fbnic_mdiobus_create`, `mlxbf_gige_mdio_probe`, `mtk_star_mdio_init`, and so on. My initial thought is: can we build an MDIO bus driver from user space? This is a question I often consider when reviewing driver architectures for flexibility and potential offloading. The direction I'm taking is guided by the desire to identify a driver to look into to satisfy that concern. I recall seeing `drivers/net/usb/lan78xx.c` utilize `mdiobus_register`, which implies it is a bus itself, and not a device. Based on what I've seen, it's possible that this is the best place to start my investigation. Let's delve into `lan78xx.c` and see what insights it can offer. |
| 12/2 | 2026/07/13 17:23 | tool | grepper |
0mArgs:{
"Expression": "mdiobus_register",
"PathPrefix": "drivers/net/usb/"
}Results: {
"Output": "drivers/net/usb/asix_devices.c=669=static int ax88772_init_mdio(struct usbnet *dev)\n--\ndrivers/net/usb/asix_devices.c-686-\ndrivers/net/usb/asix_devices.c:687:\tret = mdiobus_register(priv-\u003emdio);\ndrivers/net/usb/asix_devices.c-688-\tif (ret) {\n--\ndrivers/net/usb/ax88172a.c=61=static int ax88172a_init_mdio(struct usbnet *dev)\n--\ndrivers/net/usb/ax88172a.c-79-\ndrivers/net/usb/ax88172a.c:80:\tret = mdiobus_register(priv-\u003emdio);\ndrivers/net/usb/ax88172a.c-81-\tif (ret) {\n--\ndrivers/net/usb/lan78xx.c=2091=static int lan78xx_mdio_init(struct lan78xx_net *dev)\n--\ndrivers/net/usb/lan78xx.c-2121-\tnode = of_get_child_by_name(dev-\u003eudev-\u003edev.of_node, \"mdio\");\ndrivers/net/usb/lan78xx.c:2122:\tret = of_mdiobus_register(dev-\u003emdiobus, node);\ndrivers/net/usb/lan78xx.c-2123-\tof_node_put(node);\n--\ndrivers/net/usb/smsc95xx.c=1147=static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)\n--\ndrivers/net/usb/smsc95xx.c-1241-\ndrivers/net/usb/smsc95xx.c:1242:\tret = mdiobus_register(pdata-\u003emdiobus);\ndrivers/net/usb/smsc95xx.c-1243-\tif (ret) {\n"
} |
| 13/2 | 2026/07/13 17:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 30110 output: 48 thoughts: 678 Thoughts: **Reaching `dap8211r_probe` Through USB Fuzzing: A Strategy** Okay, so I've been digging into this and it looks like `smsc95xx`, `lan78xx`, `ax88172a`, and `asix_devices` all register an MDIO bus. That's key. When they do, `mdiobus_register` scans it. Now, if we can emulate a USB device, and `syzkaller` *can* do that via `syz_usb_connect`, we can feed it arbitrary responses to MDIO reads. Here's the trick: If the USB device responds to an MDIO read on address X with the PHY ID of DAP8211R (that's `0x0008011B`), `mdiobus_scan` will pick it up, allocate a `phy_device`, and register it. Then, the driver core will match that PHY ID and probe the `dap8211r_driver`. Therefore, `dap8211r_probe` is definitely reachable in a virtualized environment via USB fuzzing! Wait, though, we need to make sure that `DAP8211R_PHY` is actually enabled in the kernel config. Ah, the patch *adds* `config DAP8211R_PHY`. That's it! We need to enable it, so, `EnableConfigs: ["DAP8211R_PHY"]`. Got it. Now, let's look at the driver code and see what functions we should focus on. From a quick glance, we have `dap8211r_probe`, `dap8211r_remove`, `dap8211r_config_init`, `info_show`, `pkg_gen_show`, and `pkg_gen_write`. Wait, those `info_show`, `pkg_gen_show`, `pkg_gen_write` functions are debugfs operations. Are those reachable by `syzkaller`? Yes, they are. `syzkaller` can open and read/write debugfs files if it knows the paths. The paths would be something like `/sys/kernel/debug/<dev_name>/info` or `/sys/kernel/debug/pkg_gen`. The `dev_name` will be the name of the PHY device, like `mdio-bus:01`. That's great, `syzkaller` *can* fuzz debugfs! Let's dive deeper into `dap8211r_config_init`. It reads properties from the device tree: `rx-internal-delay-ps`, `tx-internal-delay-ps`, and `tx-use-inverted-clk`. Here's the catch: since we're instantiating this via USB MDIO scan, there's no device tree node for the PHY – unless we use DT overlays, which `syzkaller` doesn't typically touch. If there's no DT node, `phydev->mdio.dev.of_node` will be NULL. Thus, `of_property_read_u32` will return an error, and it will just use the default delay `DAP8211R_DEFAULT_DELAY_PS`. The same applies for `of_property_read_bool`, which returns false. This means `dap8211r_config_init` will still execute and configure the PHY, but with default values. Now let's see what we can do with `pkg_gen_write`... |
| 14/2 | 2026/07/13 17:23 | tool | read-file |
0mError:argument "FirstLine" has wrong type: got string, want int Args: {
"File": "drivers/net/phy/dap8211r.c",
"FirstLine": "330",
"LineCount": "100"
}Results: {
"error": "argument \"FirstLine\" has wrong type: got string, want int"
} |
| 15/2 | 2026/07/13 17:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 31652 output: 44 thoughts: 12 Thoughts: Here's your summary: **The Debugging Dance: A Moment of Clarity** Okay, so I was looking at that error message again, and it finally clicked. Of course! I'm such a fool sometimes. I was so focused on the logic of the algorithm that I completely missed the type mismatch. I passed a string, a perfectly valid string at that, as the input for `FirstLine`. But it expects an integer, obviously. The code's going to choke if I try to feed it the wrong data type. This is basic, almost embarrassing. But I'm glad I caught it early. Now to fix that and move on. |
| 16/2 | 2026/07/13 17:23 | tool | read-file |
0mArgs:{
"File": "drivers/net/phy/dap8211r.c",
"FirstLine": 330,
"LineCount": 100
}Results: {
"Contents": " 330:\t/**\n 331:\t * pkg_gen_show() - Show packet generator status\n 332:\t * @sf: Sequence file structure\n 333:\t * @data: Private data (struct dap8211r_priv *)\n 334:\t *\n 335:\t * Displays the current status of the internal packet generator,\n 336:\t * including CRC corruption and loopback settings.\n 337:\t *\n 338:\t * Return: 0 on success, or negative error code\n 339:\t */\n 340:\tstatic int pkg_gen_show(struct seq_file *sf, void *data)\n 341:\t{\n 342:\t\tstruct dap8211r_priv *priv = sf-\u003eprivate;\n 343:\t\tstruct phy_device *phydev = to_phy_device(priv-\u003edev);\n 344:\t\tint val;\n 345:\t\n 346:\t\tval = dap8211r_read_ext(phydev, DAP8211R_PKGC5);\n 347:\t\tif (val \u003c 0)\n 348:\t\t\treturn val;\n 349:\t\n 350:\t\tseq_puts(sf, \"Package Generating: \");\n 351:\t\tif (FIELD_GET(DAP8211R_PKG_GEN_EN, val) \u0026\u0026\n 352:\t\t FIELD_GET(DAP8211R_PKG_CHK_EN, val))\n 353:\t\t\tseq_puts(sf, \"enabled\\n\");\n 354:\t\telse\n 355:\t\t\tseq_puts(sf, \"disabled\\n\");\n 356:\t\n 357:\t\tseq_printf(sf, \"CRC corruption en: %s\\n\", FIELD_GET(DAP8211R_PKG_COR_CRC, val) ?\n 358:\t\t\t \"enabled\" : \"disabled\");\n 359:\t\n 360:\t\tval = phy_read(phydev, MII_BMCR);\n 361:\t\tif (val \u003c 0)\n 362:\t\t\treturn val;\n 363:\t\n 364:\t\tseq_printf(sf, \"Loopback en: %s\\n\", FIELD_GET(BMCR_LOOPBACK, val) ?\n 365:\t\t\t \"enabled\" : \"disabled\");\n 366:\t\treturn 0;\n 367:\t}\n 368:\t\n 369:\t/**\n 370:\t * pkg_gen_write() - Enable/disable packet generator\n 371:\t * @file: File structure\n 372:\t * @user_buf: User space buffer\n 373:\t * @count: Buffer size\n 374:\t * @ppos: File position\n 375:\t *\n 376:\t * Enables or disables the internal packet generator.\n 377:\t * Also controls loopback and CRC corruption via debugfs flags.\n 378:\t *\n 379:\t * NOTE: We intentionally do not use genphy_loopback() here.\n 380:\t * genphy_loopback() does a full BMCR overwrite (mask = ~0) and\n 381:\t * waits up to 500 ms for link in loopback mode. This is too\n 382:\t * heavy for a diagnostic packet generator:\n 383:\t *\n 384:\t * - It destroys all other BMCR state (speed, duplex, AN config).\n 385:\t * - The 500 ms link poll is unnecessary: we already have a link\n 386:\t * or are deliberately setting up a test condition.\n 387:\t * - We want to minimize changes to BMCR during debugging.\n 388:\t *\n 389:\t * Return: Number of bytes written on success, or negative error code\n 390:\t */\n 391:\tstatic ssize_t pkg_gen_write(struct file *file,\n 392:\t\t\t\t const char __user *user_buf,\n 393:\t\t\t\t size_t count, loff_t *ppos)\n 394:\t{\n 395:\t\tstruct seq_file *sf = file-\u003eprivate_data;\n 396:\t\tstruct dap8211r_priv *priv = sf-\u003eprivate;\n 397:\t\tstruct phy_device *phydev = to_phy_device(priv-\u003edev);\n 398:\t\tbool en;\n 399:\t\tu16 mask, set, set_bmcr;\n 400:\t\tint ret;\n 401:\t\n 402:\t\tret = kstrtobool_from_user(user_buf, count, \u0026en);\n 403:\t\tif (ret)\n 404:\t\t\treturn ret;\n 405:\t\n 406:\t\tif (en) {\n 407:\t\t\tset = DAP8211R_PKG_GEN_EN | DAP8211R_PKG_CHK_EN | DAP8211R_PKG_PL_5AA5;\n 408:\t\n 409:\t\t\tif (priv-\u003ecrc_cor)\n 410:\t\t\t\tset |= DAP8211R_PKG_COR_CRC;\n 411:\t\n 412:\t\t\tif (priv-\u003eloopback)\n 413:\t\t\t\tset_bmcr = BMCR_LOOPBACK;\n 414:\t\t\telse\n 415:\t\t\t\tset_bmcr = BMCR_ANENABLE;\n 416:\t\t} else {\n 417:\t\t\tset = DAP8211R_PKG_GEN_MODE | DAP8211R_PKG_GATE_EN;\n 418:\t\t\tset_bmcr = BMCR_ANENABLE;\n 419:\t\t}\n 420:\t\n 421:\t\tret = phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK | BMCR_ANENABLE, set_bmcr);\n 422:\t\tif (ret \u003c 0)\n 423:\t\t\treturn ret;\n 424:\t\n 425:\t\tmask = DAP8211R_PKG_GEN_MASK | DAP8211R_PKG_PL_MASK | DAP8211R_PKG_COR_CRC;\n 426:\t\tret = dap8211r_modify_ext(phydev, DAP8211R_PKGC5, mask, set);\n 427:\t\tif (ret \u003c 0) {\n 428:\t\t\tphy_modify(phydev, MII_BMCR, BMCR_LOOPBACK, 0);\n 429:\t\t\treturn ret;\n"
} |
| 17/2 | 2026/07/13 17:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 33542 output: 45 thoughts: 1006 Thoughts: **Analyzing the DAP8211R PHY Driver for Fuzzing** Okay, let's break this down systematically. My goal is to identify the key entry points for fuzzing the DAP8211R PHY driver, keeping in mind the context of using syzkaller. First, I see the driver exposes a few `debugfs` files: `info` (read-only), `pkg_gen` (read-write), and a couple of bools: `pkg_gen_crc_cor`, `pkg_gen_loopback`. These are directly accessible by syzkaller which is very convenient. Now, the interesting thing is figuring out how the core PHY initialization happens. The critical function is `dap8211r_config_init`. It's called by `phy_init_hw`, which in turn is called by `phy_attach_direct`. `phy_attach_direct` is triggered when a network device attaches to the PHY. If I can get a USB ethernet device to emulate a PHY connection, I can trigger `dap8211r_config_init`. That seems like a straightforward path, so it's definately on the list. Along with the initialization, the `pkg_gen_write` and `info_show` functions are reachable via `debugfs`. I've also scanned through the code for helper functions, there's `dap8211r_read_ext`, `dap8211r_modify_ext`, `dap8211r_delay_ps_to_sel`, and `dap8211r_get_rgmii_delay`. While interesting, they aren't the primary targets. So, the focus points are: * `dap8211r_config_init` * `pkg_gen_write` * `info_show` * `pkg_gen_show` `info_show` and `pkg_gen_show` appear to be simple register reads and prints. Not super complex, but part of the driver's operation. `pkg_gen_write` is definitely more interesting, it's modifying PHY registers. Then there is `dap8211r_config_init`, the PHY configuration function. Let's check the configuration requirements. `CONFIG_DAP8211R_PHY` is the primary one, of course. Wait, `CONFIG_DEBUG_FS` is needed for the debugfs files. Thankfully syzkaller has `CONFIG_DEBUG_FS` enabled, so that's taken care of. A double check of the Kconfig reveals a dependency on `OF` (Open Firmware, aka Device Tree). That's a key point. Does this mean it's strictly a Device Tree-based probe? No, but the code does use `of_property_read_u32` and `of_property_read_bool`, which have stubs when OF isn't enabled. Since it depends on OF, they will be built only if OF is enabled. I know syzkaller tests on various architectures, including x86\_64 and arm64, and often `CONFIG_OF` is enabled (especially on arm64 and sometimes on x86\_64 for testing). What about the Device Tree dependency in more detail? Since the PHY is probed via USB MDIO scan, there won't be an `of_node` attached to `phydev->mdio.dev`. In this situation, the `of_property_read_u32` functions will return `-EINVAL` and the driver will use default values. This is fine; it's just a different codepath. Any other configurations? No `CONFIG_NETWORK_PHY_TIMESTAMPING` or `CONFIG_MACSEC`. Time to review the focus points again, taking into account how the driver is actually used: * `dap8211r_config_init` (PHY initialization). * `pkg_gen_write` (debugfs access for register writes). * `dap8211r_probe` (device probe). I'll include those. |
| 18/2 | 2026/07/13 17:24 | tool | grepper |
0mArgs:{
"Expression": "^static.* dap8211r_",
"PathPrefix": "drivers/net/phy/dap8211r.c"
}Results: {
"Output": "drivers/net/phy/dap8211r.c=55=struct dap8211r_delay_config {\n--\ndrivers/net/phy/dap8211r.c-59-\ndrivers/net/phy/dap8211r.c:60:static const struct dap8211r_delay_config delay_config[] = {\ndrivers/net/phy/dap8211r.c-61-\t{ 0, 0},\n--\ndrivers/net/phy/dap8211r.c=81=struct dap8211r_priv {\n--\ndrivers/net/phy/dap8211r.c-98- */\ndrivers/net/phy/dap8211r.c:99:static u16 dap8211r_delay_ps_to_sel(struct phy_device *phydev, u32 ps)\ndrivers/net/phy/dap8211r.c-100-{\n--\ndrivers/net/phy/dap8211r.c-137- */\ndrivers/net/phy/dap8211r.c:138:static int dap8211r_read_ext(struct phy_device *phydev, u16 reg)\ndrivers/net/phy/dap8211r.c-139-{\n--\ndrivers/net/phy/dap8211r.c-165- */\ndrivers/net/phy/dap8211r.c:166:static int dap8211r_modify_ext(struct phy_device *phydev, u16 reg, u16 mask, u16 set)\ndrivers/net/phy/dap8211r.c-167-{\n--\ndrivers/net/phy/dap8211r.c-190- */\ndrivers/net/phy/dap8211r.c:191:static u32 dap8211r_get_rgmii_delay(struct phy_device *phydev, const char *prop_name)\ndrivers/net/phy/dap8211r.c-192-{\n--\ndrivers/net/phy/dap8211r.c-216- */\ndrivers/net/phy/dap8211r.c:217:static int dap8211r_config_init(struct phy_device *phydev)\ndrivers/net/phy/dap8211r.c-218-{\n--\ndrivers/net/phy/dap8211r.c=434=DEFINE_SHOW_STORE_ATTRIBUTE(pkg_gen);\n--\ndrivers/net/phy/dap8211r.c-447- */\ndrivers/net/phy/dap8211r.c:448:static void dap8211r_debug_init(struct dap8211r_priv *priv)\ndrivers/net/phy/dap8211r.c-449-{\n--\ndrivers/net/phy/dap8211r.c-470- */\ndrivers/net/phy/dap8211r.c:471:static void dap8211r_debug_remove(struct dap8211r_priv *priv)\ndrivers/net/phy/dap8211r.c-472-{\n--\ndrivers/net/phy/dap8211r.c-476-#else /* !CONFIG_DEBUG_FS */\ndrivers/net/phy/dap8211r.c:477:static void dap8211r_debug_init(struct dap8211r_priv *priv) {}\ndrivers/net/phy/dap8211r.c:478:static void dap8211r_debug_remove(struct dap8211r_priv *priv) {}\ndrivers/net/phy/dap8211r.c-479-#endif /* CONFIG_DEBUG_FS */\n--\ndrivers/net/phy/dap8211r.c-489- */\ndrivers/net/phy/dap8211r.c:490:static int dap8211r_probe(struct phy_device *phydev)\ndrivers/net/phy/dap8211r.c-491-{\n--\ndrivers/net/phy/dap8211r.c-514- */\ndrivers/net/phy/dap8211r.c:515:static void dap8211r_remove(struct phy_device *phydev)\ndrivers/net/phy/dap8211r.c-516-{\n--\ndrivers/net/phy/dap8211r.c-519-\ndrivers/net/phy/dap8211r.c:520:static struct phy_driver dap8211r_driver[] = {\ndrivers/net/phy/dap8211r.c-521-\t{\n--\ndrivers/net/phy/dap8211r.c=538=MODULE_LICENSE(\"GPL\");\ndrivers/net/phy/dap8211r.c-539-\ndrivers/net/phy/dap8211r.c:540:static const struct mdio_device_id __maybe_unused dap8211r_tb[] = {\ndrivers/net/phy/dap8211r.c-541-\t{ DAP8211R_PHY_ID, DAP8211R_PHY_ID_MASK },\n"
} |
| 19/2 | 2026/07/13 17:24 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 36912 output: 192 thoughts: 508 Thoughts: **Fuzzing Strategy for the DAP8211R PHY Driver** Okay, let's break this down. I've got a new Ethernet PHY driver, the DAP8211R(I), and I need to figure out the best fuzzing approach. Looking at the functions, I'm thinking I'll focus on `dap8211r_config_init`, `pkg_gen_write`, `dap8211r_probe`, `info_show`, and `pkg_gen_show`. These seem like the key entry points and debug interfaces. Now, I see that `DAP8211R_PHY` is a tristate config, so that's a go for `EnableConfigs`. This is an important piece of the puzzle. The bigger question is, *should* I fuzz this? Absolutely. This is a new PHY driver, and the fact that it can be reached through USB MDIO scanning and via debugfs makes it a prime target. The driver has `config_init` to set up the driver and it implements debugfs operations, all of which represent potential attack surfaces. So, let's summarize the logic behind the fuzzing approach: The patch introduces a new Ethernet PHY driver for the DAPU Telecom DAP8211R(I). It can be probed in a virtualized environment by emulating a USB Ethernet device. Once probed, the driver's initialization and debugfs operations are ready to be used. This makes for a perfect target for fuzzing. My primary focus will be on these symbols: `dap8211r_probe`, `dap8211r_config_init`, `pkg_gen_write`, `info_show`, and `pkg_gen_show`. The `DAP8211R_PHY` configuration is necessary to get this going. Alright, I'm confident in my plan. Time to use the `set-results` tool and get this process started. |
| 20/2 | 2026/07/13 17:24 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"DAP8211R_PHY"
],
"FocusSymbols": [
"dap8211r_probe",
"dap8211r_config_init",
"pkg_gen_write",
"info_show",
"pkg_gen_show"
],
"Reasoning": "The patch introduces a new Ethernet PHY driver for DAPU Telecom DAP8211R(I). The driver can be probed in a virtualized environment by emulating a USB Ethernet device that registers an MDIO bus and responds to MDIO reads with the DAP8211R PHY ID. Once probed, the driver's `config_init` and debugfs operations (`info_show`, `pkg_gen_show`, `pkg_gen_write`) can be exercised by userspace.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"DAP8211R_PHY"
],
"FocusSymbols": [
"dap8211r_probe",
"dap8211r_config_init",
"pkg_gen_write",
"info_show",
"pkg_gen_show"
],
"Reasoning": "The patch introduces a new Ethernet PHY driver for DAPU Telecom DAP8211R(I). The driver can be probed in a virtualized environment by emulating a USB Ethernet device that registers an MDIO bus and responds to MDIO reads with the DAP8211R PHY ID. Once probed, the driver's `config_init` and debugfs operations (`info_show`, `pkg_gen_show`, `pkg_gen_write`) can be exercised by userspace.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|