AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/09/15 10:59 flow patch-triage
1m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "KMSANReasoning": "",
  "NeedsKMSAN": false,
  "Reasoning": "The patch series adds support for the Motorcomm YT8824 quad-port 2.5G Ethernet PHY in drivers/net/phy/motorcomm.c and adds an associated helper genphy_c45_template_testmode in drivers/net/phy/phy-c45.c. The modified code targets a specific physical Ethernet PHY transceiver that requires physical hardware and specific Device Tree description ('ethernet-phy-package'), which is not present or emulated in standard virtualized x86_64/QEMU fuzzing environments. The helper genphy_c45_template_testmode is solely called by the YT8824 driver, and probe immediately fails without the OF node. Therefore, the code is structurally unreachable.",
  "WorthFuzzing": false
}

1/1 2026/09/15 10:59 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit ae31ea1a6b52c868b9c7a749612861f0c172be9a\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Tue Sep 15 10:59:48 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/Documentation/devicetree/bindings/net/motorcomm,yt8824.yaml b/Documentation/devicetree/bindings/net/motorcomm,yt8824.yaml\nnew file mode 100644\nindex 0000000000000..93e9f765404a3\n--- /dev/null\n+++ b/Documentation/devicetree/bindings/net/motorcomm,yt8824.yaml\n@@ -0,0 +1,59 @@\n+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)\n+%YAML 1.2\n+---\n+$id: http://devicetree.org/schemas/net/motorcomm,yt8824.yaml#\n+$schema: http://devicetree.org/meta-schemas/core.yaml#\n+\n+title: MotorComm YT8824 Ethernet PHY\n+\n+maintainers:\n+  - Kyle Switch \u003ckyle.switch@motor-comm.com\u003e\n+\n+description:\n+  Motorcomm YT8824 Ethernet PHY is a PHY package of 4 PHYs.\n+\n+$ref: ethernet-phy-package.yaml#\n+\n+properties:\n+  compatible:\n+    enum:\n+      - motorcomm,yt8824-package\n+\n+required:\n+  - compatible\n+  - phy-mode\n+  - reg\n+\n+unevaluatedProperties: false\n+\n+examples:\n+  - |\n+    mdio {\n+        #address-cells = \u003c1\u003e;\n+        #size-cells = \u003c0\u003e;\n+\n+        ethernet-phy-package@0 {\n+            #address-cells = \u003c1\u003e;\n+            #size-cells = \u003c0\u003e;\n+            compatible = \"motorcomm,yt8824-package\";\n+            reg = \u003c9\u003e;\n+\n+            phy-mode = \"internal\";\n+\n+            ethernet-phy@4 {\n+                reg = \u003c4\u003e;\n+            };\n+\n+            ethernet-phy@5 {\n+                reg = \u003c5\u003e;\n+            };\n+\n+            ethernet-phy@6 {\n+                reg = \u003c6\u003e;\n+            };\n+\n+            ethernet-phy@7 {\n+                reg = \u003c7\u003e;\n+            };\n+        };\n+    };\ndiff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig\nindex d3835597e3795..996d75afed446 100644\n--- a/drivers/net/phy/Kconfig\n+++ b/drivers/net/phy/Kconfig\n@@ -361,9 +361,10 @@ config MICROSEMI_PHY\n \n config MOTORCOMM_PHY\n \ttristate \"Motorcomm PHYs\"\n+\tselect PHY_PACKAGE\n \thelp\n \t  Enables support for Motorcomm network PHYs.\n-\t  Currently supports YT85xx Gigabit Ethernet PHYs.\n+\t  Currently supports YT85xx Gigabit Ethernet PHYs and YT8824 4 * 2.5G PHY.\n \n config NATIONAL_PHY\n \ttristate \"National Semiconductor PHYs\"\ndiff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c\nindex 90a4f86f2758b..b60948c9ce884 100644\n--- a/drivers/net/phy/motorcomm.c\n+++ b/drivers/net/phy/motorcomm.c\n@@ -1,24 +1,31 @@\n // SPDX-License-Identifier: GPL-2.0+\n /*\n- * Motorcomm 8511/8521/8522/8531/8531S/8821 PHY driver.\n+ * Motorcomm 8511/8521/8522/8531/8531S/8821/8824 PHY driver.\n  *\n  * Author: Peter Geis \u003cpgwipeout@gmail.com\u003e\n  * Author: Frank \u003cFrank.Sae@motor-comm.com\u003e\n+ * Author: Kyle \u003ckyle.switch@motor-comm.com\u003e\n  */\n \n #include \u003clinux/clk.h\u003e\n #include \u003clinux/etherdevice.h\u003e\n #include \u003clinux/kernel.h\u003e\n+#include \u003clinux/mdio.h\u003e\n #include \u003clinux/module.h\u003e\n+#include \u003clinux/of.h\u003e\n+#include \u003clinux/of_net.h\u003e\n #include \u003clinux/phy.h\u003e\n #include \u003clinux/property.h\u003e\n \n+#include \"phylib.h\"\n+\n #define PHY_ID_YT8511\t\t0x0000010a\n #define PHY_ID_YT8521\t\t0x0000011a\n #define PHY_ID_YT8522\t\t0x4f51e928\n #define PHY_ID_YT8531\t\t0x4f51e91b\n #define PHY_ID_YT8531S\t\t0x4f51e91a\n #define PHY_ID_YT8821\t\t0x4f51ea19\n+#define PHY_ID_YT8824\t\t0x4f51e8b8\n /* YT8521/YT8531S/YT8821 Register Overview\n  *\tUTP Register space\t|\tFIBER Register space\n  *  ------------------------------------------------------------\n@@ -30,6 +37,18 @@\n  *  ------------------------------------------------------------\n  */\n \n+/* YT8824 Register Overview\n+ * UTP Register space | USXGMII Register space\n+ *  ------------------------------------------------------------\n+ * | UTP MII\t\t| USXGMII MII\t\t|\n+ * | UTP MMD\t\t|\t\t\t|\n+ * | UTP Extended\t| USXGMII Extended\t|\n+ * | UTP Top Extended\t| USXGMII Top Extended\t|\n+ *  ------------------------------------------------------------\n+ * |   Common Top Extended\t\t\t|\n+ *  ------------------------------------------------------------\n+ */\n+\n /* 0x10 ~ 0x15 , 0x1E and 0x1F are common MII registers of yt phy */\n \n /* Specific Function Control Register */\n@@ -381,6 +400,13 @@\n #define YT8821_CHIP_MODE_AUTO_BX2500_SGMII\t0\n #define YT8821_CHIP_MODE_FORCE_BX2500\t\t1\n \n+#define YT8824_RSSR_SPACE_MASK\t\t\tBIT(0)\n+#define YT8824_RSSR_USXGMII_SPACE\t\t(0x1)\n+#define YT8824_RSSR_UTP_SPACE\t\t\t(0x0)\n+#define YT8824_SDS_CFG_MIN_PRE_MASK\t\tGENMASK(3, 0)\n+#define YT8824_SDS_EN_FILL_PRE\t\t\tBIT(13)\n+#define YT8824_SDS_TX_PRE_PADDING\t\t(0x7)\n+\n struct yt8521_priv {\n \t/* combo_advertising is used for case of YT8521 in combo mode,\n \t * this means that yt8521 may work in utp or fiber mode which depends\n@@ -399,6 +425,12 @@ struct yt8521_priv {\n \tu8 reg_page;\n };\n \n+struct yt8824_shared_priv {\n+\tphy_interface_t interface_mode;\n+\t/* shared_lock used to UTPs operation isolation during swap reg space */\n+\tstruct mutex shared_lock;\n+};\n+\n /**\n  * ytphy_read_ext() - read a PHY's extended register\n  * @phydev: a pointer to a \u0026struct phy_device\n@@ -437,6 +469,70 @@ static int ytphy_read_ext_with_lock(struct phy_device *phydev, u16 regnum)\n \treturn ret;\n }\n \n+/**\n+ * ytphy_read_top_ext() - read a PHY's top extended register for YT8824\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ * @regnum: register number to read\n+ *\n+ * Returns: the value of regnum reg or negative error code\n+ */\n+static int ytphy_read_top_ext(struct phy_device *phydev, u16 regnum)\n+{\n+\tint ret;\n+\n+\tlockdep_assert_held(\u0026phydev-\u003emdio.bus-\u003emdio_lock);\n+\tret = __phy_package_write(phydev, 0, YTPHY_PAGE_SELECT, regnum);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn __phy_package_read(phydev, 0, YTPHY_PAGE_DATA);\n+}\n+\n+/**\n+ * ytphy_write_top_ext() - write a PHY's top extended register for YT8824\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ * @regnum: register number to write\n+ * @val: register val to write\n+ *\n+ * Returns: 0 or negative error code\n+ */\n+static int ytphy_write_top_ext(struct phy_device *phydev, u16 regnum,\n+\t\t\t       u16 val)\n+{\n+\tint ret;\n+\n+\tlockdep_assert_held(\u0026phydev-\u003emdio.bus-\u003emdio_lock);\n+\tret = __phy_package_write(phydev, 0, YTPHY_PAGE_SELECT, regnum);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn __phy_package_write(phydev, 0, YTPHY_PAGE_DATA, val);\n+}\n+\n+/**\n+ * phy8824_page_write_with_lock() - write page for YT8824\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ * @page: reg page(YT8824_RSSR_USXGMII_SPACE/YT8824_RSSR_UTP_SPACE).\n+ *\n+ * Returns: 0 or negative error code\n+ */\n+static int phy8824_page_write_with_lock(struct phy_device *phydev, int page)\n+{\n+\tint ret;\n+\n+\tphy_lock_mdio_bus(phydev);\n+\tret = ytphy_read_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG);\n+\tif (ret \u003c 0)\n+\t\tgoto err;\n+\tret \u0026= ~YT8824_RSSR_SPACE_MASK;\n+\tret |= (page \u0026 YT8824_RSSR_SPACE_MASK);\n+\tret = ytphy_write_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG, ret);\n+\n+err:\n+\tphy_unlock_mdio_bus(phydev);\n+\treturn ret;\n+}\n+\n /**\n  * ytphy_write_ext() - write a PHY's extended register\n  * @phydev: a pointer to a \u0026struct phy_device\n@@ -622,15 +718,1057 @@ static int ytphy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)\n \t\tmask = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL;\n \t\tret = ytphy_modify_ext(phydev, YTPHY_WOL_CONFIG_REG, mask, 0);\n \n-\t\t/* Disable WOL interrupt */\n-\t\tret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG,\n-\t\t\t\t   YTPHY_IER_WOL, 0);\n+\t\t/* Disable WOL interrupt */\n+\t\tret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG,\n+\t\t\t\t   YTPHY_IER_WOL, 0);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\t}\n+\n+err_restore_page:\n+\treturn phy_restore_page(phydev, old_page, ret);\n+}\n+\n+/**\n+ * yt8824_read_page() - read PHY8824 reg page\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: current reg space of yt8824 (YT8824_RSSR_USXGMII_SPACE/\n+ * YT8824_RSSR_UTP_SPACE) or negative errno code\n+ */\n+static int yt8824_read_page(struct phy_device *phydev)\n+{\n+\tint old_page;\n+\n+\told_page = ytphy_read_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG);\n+\tif (old_page \u003c 0)\n+\t\treturn old_page;\n+\n+\treturn old_page \u0026 YT8824_RSSR_SPACE_MASK;\n+};\n+\n+/**\n+ * yt8824_write_page() - write reg page\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ * @page: Reg page(YT8824_RSSR_USXGMII_SPACE/YT8824_RSSR_UTP_SPACE) to write.\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_write_page(struct phy_device *phydev, int page)\n+{\n+\tint old_page;\n+\tu16 data;\n+\n+\told_page = ytphy_read_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG);\n+\tif (old_page \u003c 0)\n+\t\treturn old_page;\n+\tdata = old_page \u0026 (~YT8824_RSSR_SPACE_MASK);\n+\tdata |= page;\n+\n+\treturn ytphy_write_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG, data);\n+};\n+\n+/**\n+ * yt8824_utp_invalid_test_mode_paged() - config YT8824 to invalid test mode.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_utp_invalid_test_mode_paged(struct phy_device *phydev)\n+{\n+\tint ret;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn genphy_c45_template_testmode\n+\t\t(phydev, MDIO_PMA_10GBT_TESTMODE_1);\n+}\n+\n+/**\n+ * yt8824_sds_isolate_paged() - enable YT8824 serdes isolate.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_sds_isolate_paged(struct phy_device *phydev)\n+{\n+\tint old_page = YT8824_RSSR_UTP_SPACE;\n+\tint ret = 0;\n+\n+\told_page = phy_select_page(phydev, YT8824_RSSR_USXGMII_SPACE);\n+\tif (old_page \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* enable sds isolate */\n+\tret = __phy_modify(phydev, MII_BMCR, BMCR_ISOLATE, BMCR_ISOLATE);\n+\n+err_restore_page:\n+\t/* restore page, release the lock */\n+\treturn phy_restore_page(phydev, old_page, ret);\n+}\n+\n+/**\n+ * yt8824_utp_softreset_paged() - config YT8824 UTP softreset.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_utp_softreset_paged(struct phy_device *phydev)\n+{\n+\tint ret = 0;\n+\tint val;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = phy_modify(phydev, MII_BMCR, BMCR_RESET, BMCR_RESET);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* wait until softreset done. */\n+\treturn phy_read_poll_timeout(phydev, MII_BMCR, val, !(val \u0026 BMCR_RESET),\n+\t\t\t\t     50000, 600000, true);\n+}\n+\n+/**\n+ * yt8824_utp_normal_test_mode_paged() - config YT8824 to normal test mode.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_utp_normal_test_mode_paged(struct phy_device *phydev)\n+{\n+\tint ret = 0;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn genphy_c45_template_testmode(phydev,\n+\t\t\t\t\t    MDIO_PMA_10GBT_TESTMODE_NORMAL);\n+}\n+\n+/**\n+ * yt8824_sds_isolate_and_softreset_paged() - disable YT8824 serdes isolate\n+ * and sds softreset.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_sds_isolate_and_softreset_paged(struct phy_device *phydev)\n+{\n+\tint old_page = YT8824_RSSR_UTP_SPACE;\n+\tint val = 0;\n+\tint ret = -1;\n+\n+\told_page = phy_select_page(phydev, YT8824_RSSR_USXGMII_SPACE);\n+\tif (old_page \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* sds softreset and disable isolate */\n+\tret = __phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ISOLATE,\n+\t\t\t   BMCR_RESET \u0026 ~BMCR_ISOLATE);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* poll while still holding the lock */\n+\tret = read_poll_timeout(__phy_read, val,\n+\t\t\t\t(val \u003c 0) || !(val \u0026 BMCR_RESET), 50000, 600000,\n+\t\t\t\ttrue, phydev, MII_BMCR);\n+\tif (val \u003c 0)\n+\t\tret = val;\n+\n+err_restore_page:\n+\t/* restore page, release the lock */\n+\treturn phy_restore_page(phydev, old_page, ret);\n+}\n+\n+/**\n+ * yt8824_restore_working_status() - called to do store working status\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ * @ret: operation's return code\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_restore_working_status(struct phy_device *phydev, int ret)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint r;\n+\n+\t/* configure normal test mode */\n+\tr = yt8824_utp_normal_test_mode_paged(phydev);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\tif (priv-\u003einterface_mode != PHY_INTERFACE_MODE_INTERNAL) {\n+\t\t/* sds soft reset and disable isolation */\n+\t\tr = yt8824_sds_isolate_and_softreset_paged(phydev);\n+\t\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\t\tret = r;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_soft_reset() - called to do PHY software reset\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_soft_reset(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tif (priv-\u003einterface_mode == PHY_INTERFACE_MODE_INTERNAL) {\n+\t\t/* invalid test mode */\n+\t\tret = yt8824_utp_invalid_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t\tret = yt8824_utp_softreset_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t\t/* normal mode */\n+\t\tret = yt8824_utp_normal_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t} else {\n+\t\t/* invalid test mode */\n+\t\tret = yt8824_utp_invalid_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* sds isolation */\n+\t\tret = yt8824_sds_isolate_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* utp soft reset */\n+\t\tret = yt8824_utp_softreset_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* normal mode */\n+\t\tret = yt8824_utp_normal_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* sds soft reset and disable isolation */\n+\t\tret = yt8824_sds_isolate_and_softreset_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t}\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\treturn ret;\n+retry:\n+\tret = yt8824_restore_working_status(phydev, ret);\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_extern_config_utp_init_paged() - config external phy8824 utp init\n+ * @phydev: target phy_device struct\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_extern_config_utp_init_paged(struct phy_device *phydev)\n+{\n+\tint ret = 0;\n+\tint val = 0;\n+\tint r;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* power down */\n+\tret = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* pll calibration */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0001, 0x0003);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa20e, 0x0cba);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa20a, 0xc3f1);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa20c, 0x1620);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0x0a00);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0x0e00);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimization utp */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0001, 0x0003);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* enable nibble */\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa003, 0x0003);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* idle err detect enable */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x03d0, 0x5210);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized 2.5G long cable performance */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0372, 0x5038);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x037c, 0x6068);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0388, 0x00a0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized fast retrain */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0359, 0x2140);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x000c, 0xc1a0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* 2.5G template tone */\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2fa, 0x0083);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x04e2, 0x0149);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized 2.5G template */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x047e, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x047f, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0480, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0481, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized 1000M cable length threshold */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0336, 0xab0a);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0340, 0x301d);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* 100M template amplitude */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x046e, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x046f, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0470, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0471, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized 100M cable length threshold */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x030b, 0xaa1d);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x071f, 0x0036);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* 10M template amplitude */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x046b, 0x1818);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x046c, 0x1818);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized 10M cable length threshold */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0466, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0467, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0468, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0469, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimize utp 1000M performance */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x034a, 0xff03);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x00f8, 0xb3ff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0059, 0x4040);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x032c, 0x5094);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x032d, 0xd094);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x032e, 0x5308);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0322, 0x6440);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x04d3, 0x5220);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x04d2, 0x5220);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized EMC CS */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x00c8, 0xffff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x00be, 0x6406);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x037a, 0x40ff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized EMC RE */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0482, 0xffff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d5, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d6, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d7, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d8, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa218, 0x006e);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xfff0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xfff0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xffff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xffff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = genphy_c45_template_testmode(phydev, MDIO_PMA_10GBT_TESTMODE_1);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_normal;\n+\t/* reset */\n+\tret = phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE,\n+\t\t\t BMCR_RESET | BMCR_ANENABLE);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_normal;\n+\tret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val \u0026 BMCR_RESET),\n+\t\t\t\t    50000, 600000, true);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_normal;\n+\n+\tret = genphy_c45_template_testmode(phydev,\n+\t\t\t\t\t   MDIO_PMA_10GBT_TESTMODE_NORMAL);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_normal;\n+\treturn 0;\n+\n+err_restore:\n+\tr = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\treturn ret;\n+\n+err_restore_normal:\n+\tr = genphy_c45_template_testmode(phydev,\n+\t\t\t\t\t MDIO_PMA_10GBT_TESTMODE_NORMAL);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\tr = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_extern_config_sds_init_paged() - config external phy8824 sds init\n+ * @phydev: target phy_device struct\n+ *\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_extern_config_sds_init_paged(struct phy_device *phydev)\n+{\n+\tint old_page = YT8824_RSSR_UTP_SPACE;\n+\tint val_1, val_2, val_3, tmp;\n+\tint ret = -1;\n+\tint val;\n+\n+\told_page = phy_select_page(phydev, YT8824_RSSR_USXGMII_SPACE);\n+\tif (old_page \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* read efuse */\n+\tret = ytphy_read_top_ext(phydev, 0xa13e);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\telse\n+\t\tval_1 = ret;\n+\n+\tret = ytphy_read_top_ext(phydev, 0xa13f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\telse\n+\t\tval_2 = ret;\n+\n+\tret = ytphy_read_top_ext(phydev, 0xa140);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\telse\n+\t\tval_3 = ret;\n+\n+\t/* Serdes optimization */\n+\tret = ytphy_write_ext(phydev, 0x04be, 0x000d);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x049f, 0x7ded);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x04a9, 0x009f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* analog CDR */\n+\tret = ytphy_write_ext(phydev, 0x0406, 0x0800);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* optimized VCO */\n+\tret = ytphy_write_ext(phydev, 0x0438, 0x9024);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x0439, 0x00c0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* optimized PLL lock */\n+\tret = ytphy_read_ext(phydev, 0x0429);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret \u0026= ~(BIT(13) | BIT(12));\n+\ttmp = (val_1 \u0026 (BIT(7) | BIT(6))) \u003e\u003e 6;\n+\tret |= (tmp \u003c\u003c 12);\n+\tret = ytphy_write_ext(phydev, 0x0429, ret);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_read_ext(phydev, 0x0441);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret \u0026= ~(BIT(1) | BIT(0));\n+\ttmp = (val_1 \u0026 (BIT(5) | BIT(4))) \u003e\u003e 4;\n+\tret |= tmp;\n+\tret = ytphy_write_ext(phydev, 0x0441, ret);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_read_ext(phydev, 0x042b);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret \u0026= ~(BIT(13) | BIT(12));\n+\ttmp = (val_3 \u0026 (BIT(1) | BIT(0)));\n+\tret |= (tmp \u003c\u003c 12);\n+\tret = ytphy_write_ext(phydev, 0x042b, ret);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x043a, 0x1006);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x042a, 0xf070);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* cable length threshold */\n+\tret = ytphy_write_ext(phydev, 0x0491, 0x007f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x0492, 0x7f7f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* Serdes training threshold */\n+\tret = ytphy_write_ext(phydev, 0x0454, 0x0f14);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x0497, 0x0a44);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* digital eye diagram of SerDes */\n+\tret = ytphy_write_ext(phydev, 0x04cd, 0x0000);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* Serdes LDO */\n+\tret = ytphy_read_ext(phydev, 0x04b5);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret \u0026= ~(BIT(6) | BIT(5) | BIT(4));\n+\ttmp = (val_2 \u0026 (BIT(4) | BIT(3) | BIT(2))) \u003e\u003e 2;\n+\tret |= (tmp \u003c\u003c 4);\n+\tret = ytphy_write_ext(phydev, 0x04b5, ret);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_read_ext(phydev, 0x04b4);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret \u0026= ~(BIT(10) | BIT(9) | BIT(8));\n+\ttmp = (val_2 \u0026 (BIT(7) | BIT(6) | BIT(5))) \u003e\u003e 5;\n+\tret |= (tmp \u003c\u003c 8);\n+\tret = ytphy_write_ext(phydev, 0x04b4, ret);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* optimized Serdes RX */\n+\tret = ytphy_write_ext(phydev, 0x04af, 0x45e3);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x048a, 0x0fff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x0408, 0x7c00);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x04d6, 0x007f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x044f, 0xff08);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* optimized Serdes TX */\n+\tret = ytphy_write_ext(phydev, 0x048e, 0x7d00);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x000d, 0x0606);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* Serdes manual config */\n+\tret = ytphy_write_ext(phydev, 0x04b0, 0x0804);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x04b1, 0x7074);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x04af, 0x45e7);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* restart calibration */\n+\tret = ytphy_write_ext(phydev, 0x0003, 0x5603);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x0492, 0x7fff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x0492, 0x7f7f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x2000, 0x0040);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x2000, 0x0000);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* TX preamble padded to 8; RX IPG always \u003e 8 */\n+\tret = __phy_read(phydev, MII_RESV1);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\tret \u0026= ~YT8824_SDS_CFG_MIN_PRE_MASK;\n+\tret |= YT8824_SDS_TX_PRE_PADDING;\n+\tret |= YT8824_SDS_EN_FILL_PRE;\n+\tret = __phy_write(phydev, MII_RESV1, ret);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\t/* reset serdes */\n+\tret = __phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE,\n+\t\t\t   BMCR_RESET | BMCR_ANENABLE);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\t/* poll while still holding the lock; __phy_read takes no lock */\n+\tret = read_poll_timeout(__phy_read, val,\n+\t\t\t\t(val \u003c 0) || !(val \u0026 BMCR_RESET), 50000, 600000,\n+\t\t\t\ttrue, phydev, MII_BMCR);\n+\tif (val \u003c 0)\n+\t\tret = val;\n+err_restore_page:\n+\t/* restore page, release the lock */\n+\treturn phy_restore_page(phydev, old_page, ret);\n+}\n+\n+/**\n+ * yt8824_internal_config_init_paged() - config internal phy8824 init\n+ * @phydev: target phy_device struct\n+ *\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_internal_config_init_paged(struct phy_device *phydev)\n+{\n+\tint ret = 0;\n+\tint val = 0;\n+\tint r = 0;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x1, 0x3);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* power down */\n+\tret = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa20e, 0xcba);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa20a, 0xc3f1);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa20c, 0x1620);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0xa00);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0xe00);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa003, 0x3);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x3d0, 0x5210);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x372, 0x5038);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x37c, 0x6068);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x388, 0xa0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x359, 0x2140);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2fa, 0x83);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x4e2, 0x149);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* 2.5G tempate */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x47e, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x47f, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x480, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x481, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* 1000 cable length threshold */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x336, 0xab0a);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x340, 0x301d);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* 1000 performance */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x34a, 0xff03);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xf8, 0xb3ff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x32c, 0x5094);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x32d, 0xd094);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x32e, 0x5308);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x322, 0x6440);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x4d3, 0x5220);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x4d2, 0x5220);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* 100 tempate */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x46e, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x46f, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x470, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x471, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* 100 cable length threshold */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x30b, 0xaa1d);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x71f, 0x36);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* 10 tempate */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x46b, 0x1818);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x46c, 0x1818);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* 10 tempate MAU*/\n+\tret = ytphy_write_ext_with_lock(phydev, 0x466, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x467, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x468, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x469, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* EMC CS, Inconsistent with external phy */\n+\tret = ytphy_write_ext_with_lock(phydev, 0xc8, 0xfff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xbe, 0x6406);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x37a, 0x40ff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* EMC RE*/\n+\tret = ytphy_write_ext_with_lock(phydev, 0x482, 0xffff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d5, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d6, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d7, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d8, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa218, 0x6e);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xfff0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xfff0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xffff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xffff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xc, 0x41a1);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = genphy_c45_template_testmode(phydev, MDIO_PMA_10GBT_TESTMODE_1);\n+\tif (ret)\n+\t\tgoto err_restore_normal;\n+\t/* reset */\n+\tret = phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE,\n+\t\t\t BMCR_RESET | BMCR_ANENABLE);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_normal;\n+\tret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val \u0026 BMCR_RESET),\n+\t\t\t\t    50000, 600000, true);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_normal;\n+\n+\tret = genphy_c45_template_testmode(phydev,\n+\t\t\t\t\t   MDIO_PMA_10GBT_TESTMODE_NORMAL);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_normal;\n+\n+\treturn 0;\n+\n+err_restore:\n+\tr = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\treturn ret;\n+\n+err_restore_normal:\n+\tr = genphy_c45_template_testmode(phydev,\n+\t\t\t\t\t MDIO_PMA_10GBT_TESTMODE_NORMAL);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\tr = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_config_init() - phy initializatioin\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_config_init(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tif (priv-\u003einterface_mode == PHY_INTERFACE_MODE_INTERNAL) {\n+\t\tret = yt8824_internal_config_init_paged(phydev);\n \t\tif (ret \u003c 0)\n-\t\t\tgoto err_restore_page;\n+\t\t\tgoto err;\n+\t} else {\n+\t\tret = yt8824_extern_config_sds_init_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err;\n+\t\tret = yt8824_extern_config_utp_init_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err;\n \t}\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\tret = yt8824_soft_reset(phydev);\n \n-err_restore_page:\n-\treturn phy_restore_page(phydev, old_page, ret);\n+\tphydev_dbg(phydev, \"%s done, phy addr: %d\\n\", __func__,\n+\t\t   phydev-\u003emdio.addr);\n+\treturn ret;\n+err:\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\treturn ret;\n }\n \n static int yt8531_set_wol(struct phy_device *phydev,\n@@ -3104,6 +4242,418 @@ static int yt8821_resume(struct phy_device *phydev)\n \treturn yt8821_modify_utp_fiber_bmcr(phydev, BMCR_PDOWN, 0);\n }\n \n+/**\n+ * yt8824_get_features - read mmd register to get 2.5G capability\n+ * @phydev: target phy_device struct\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_get_features(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\tgoto err;\n+\tret = yt8821_get_features(phydev);\n+\n+err:\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_aneg_done()  - check negotiation state.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: link status or negative errno code\n+ */\n+static int yt8824_aneg_done(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint link = 0;\n+\tint ret = 0;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\tgoto err;\n+\n+\tret = phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG);\n+\tif (ret \u003c 0)\n+\t\tgoto err;\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\tlink = !!(ret \u0026 YTPHY_SSR_LINK);\n+\n+\tphydev_dbg(phydev, \"%s, phy addr: %d, link_utp: %d\\n\", __func__,\n+\t\t   phydev-\u003emdio.addr, link);\n+\treturn link;\n+err:\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_read_status_paged() -  determines the speed and duplex of one page\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_read_status_paged(struct phy_device *phydev)\n+{\n+\tint link = 0;\n+\tint ret = 0;\n+\tint val = 0;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = genphy_read_status(phydev);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tif (phydev-\u003eautoneg_complete) {\n+\t\tret = genphy_c45_read_lpa(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t}\n+\n+\tret = phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tval = ret;\n+\n+\tlink = val \u0026 YTPHY_SSR_LINK;\n+\tif (link)\n+\t\tyt8821_adjust_status(phydev, val);\n+\n+\tif (link) {\n+\t\tif (phydev-\u003elink == 0)\n+\t\t\tphydev_dbg(phydev, \"%s, phy addr: %d, link up\\n\",\n+\t\t\t\t   __func__, phydev-\u003emdio.addr);\n+\t\tphydev-\u003elink = 1;\n+\t} else {\n+\t\tif (phydev-\u003elink == 1)\n+\t\t\tphydev_dbg(phydev, \"%s, phy addr: %d, link down\\n\",\n+\t\t\t\t   __func__, phydev-\u003emdio.addr);\n+\t\tphydev-\u003elink = 0;\n+\t}\n+\tphy_resolve_aneg_pause(phydev);\n+\treturn 0;\n+}\n+\n+/**\n+ * yt8824_read_status() -  determines the negotiated speed and duplex\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_read_status(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tret = yt8824_read_status_paged(phydev);\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_utp_power_on(): utp power on.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_utp_power_on(struct phy_device *phydev)\n+{\n+\tint ret = 0;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0x0);\n+}\n+\n+/**\n+ * yt8824_utp_power_down(): utp power down.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_utp_power_down(struct phy_device *phydev)\n+{\n+\tint ret;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn phy_modify(phydev, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN);\n+}\n+\n+/**\n+ * yt8824_power_on()  - set utp power on.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * NOTE: need WA like softreset\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_power_on(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\tint r;\n+\n+\tif (priv-\u003einterface_mode == PHY_INTERFACE_MODE_INTERNAL) {\n+\t\t/* invalid test mode */\n+\t\tret = yt8824_utp_invalid_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t\t/* utp power on */\n+\t\tret = yt8824_utp_power_on(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t\t/* normal mode */\n+\t\tret = yt8824_utp_normal_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t} else {\n+\t\t/* invalid test mode */\n+\t\tret = yt8824_utp_invalid_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* sds isolation */\n+\t\tret = yt8824_sds_isolate_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* utp power on */\n+\t\tret = yt8824_utp_power_on(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* normal mode */\n+\t\tret = yt8824_utp_normal_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* sds soft reset and disable isolation */\n+\t\tret = yt8824_sds_isolate_and_softreset_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t}\n+\treturn 0;\n+\n+retry:\n+\t/*\n+\t * If the PHY up operation succeeds but the subsequent operation\n+\t * fails, revert to the default state.\n+\t */\n+\tr = yt8824_utp_power_down(phydev);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\tret = yt8824_restore_working_status(phydev, ret);\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_resume() - resume the hardware\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_resume(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tret = yt8824_power_on(phydev);\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_power_down()  - set utp power down.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * NOTE: need WA like softreset\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_power_down(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\tint r;\n+\n+\tif (priv-\u003einterface_mode == PHY_INTERFACE_MODE_INTERNAL) {\n+\t\t/* invalid test mode */\n+\t\tret = yt8824_utp_invalid_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t\t/* utp power down */\n+\t\tret = yt8824_utp_power_down(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t\t/* normal mode */\n+\t\tret = yt8824_utp_normal_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t} else {\n+\t\t/* invalid test mode */\n+\t\tret = yt8824_utp_invalid_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* sds isolation */\n+\t\tret = yt8824_sds_isolate_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* utp power down */\n+\t\tret = yt8824_utp_power_down(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* normal mode */\n+\t\tret = yt8824_utp_normal_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* sds soft reset and disable isolation */\n+\t\tret = yt8824_sds_isolate_and_softreset_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t}\n+\treturn 0;\n+\n+retry:\n+\t/*\n+\t * If the PHY down operation succeeds but the subsequent operation\n+\t * fails, revert to the default state.\n+\t */\n+\tr = yt8824_utp_power_on(phydev);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\tret = yt8824_restore_working_status(phydev, ret);\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_suspend() - suspend the hardware\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_suspend(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tret = yt8824_power_down(phydev);\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_config_aneg() - config negotiation\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_config_aneg(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint phy_ctrl = 0;\n+\tint ret;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\tgoto err;\n+\n+\tif (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,\n+\t\t\t      phydev-\u003eadvertising))\n+\t\tphy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G;\n+\n+\tret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,\n+\t\t\t\t     MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl);\n+\tif (ret \u003c 0)\n+\t\tgoto err;\n+\n+\tret = __genphy_config_aneg(phydev, ret);\n+\n+err:\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_phy_package_probe_once()  - init phy package for phy8824.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_phy_package_probe_once(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tstruct device_node *np = phy_package_get_node(phydev);\n+\tint res;\n+\n+\tif (!priv || !np) {\n+\t\tphydev_err(phydev, \"%s: missing shared priv or DT node\\n\",\n+\t\t\t   __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\t/* Initialise shared lock for YT8824 */\n+\tmutex_init(\u0026priv-\u003eshared_lock);\n+\tres = of_get_phy_mode(np, \u0026priv-\u003einterface_mode);\n+\tif (res \u003c 0) {\n+\t\tphydev_warn(phydev, \"%s, phy-mode missing in DTS.\\n\", __func__);\n+\t\tpriv-\u003einterface_mode = PHY_INTERFACE_MODE_INTERNAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * yt8824_probe() - phy8824 probe.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_probe(struct phy_device *phydev)\n+{\n+\tstruct device *dev = \u0026phydev-\u003emdio.dev;\n+\tstruct yt8824_shared_priv *shared_priv;\n+\tint ret;\n+\n+\tret = devm_of_phy_package_join(dev, phydev, sizeof(*shared_priv));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (phy_package_probe_once(phydev)) {\n+\t\tret = yt8824_phy_package_probe_once(phydev);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n static struct phy_driver motorcomm_phy_drvs[] = {\n \t{\n \t\tPHY_ID_MATCH_EXACT(PHY_ID_YT8511),\n@@ -3190,13 +4740,29 @@ static struct phy_driver motorcomm_phy_drvs[] = {\n \t\t.suspend\t\t= yt8821_suspend,\n \t\t.resume\t\t\t= yt8821_resume,\n \t},\n+\t{\n+\t\tPHY_ID_MATCH_EXACT(PHY_ID_YT8824),\n+\t\t.name = \"YT8824 Quad Ports 2.5Gbps Ethernet\",\n+\t\t.get_features = yt8824_get_features,\n+\t\t.read_page = yt8824_read_page,\n+\t\t.write_page = yt8824_write_page,\n+\t\t.probe = yt8824_probe,\n+\t\t.config_aneg = yt8824_config_aneg,\n+\t\t.aneg_done = yt8824_aneg_done,\n+\t\t.config_init = yt8824_config_init,\n+\t\t.read_status = yt8824_read_status,\n+\t\t.soft_reset = yt8824_soft_reset,\n+\t\t.suspend = yt8824_suspend,\n+\t\t.resume = yt8824_resume,\n+\t},\n };\n \n module_phy_driver(motorcomm_phy_drvs);\n \n-MODULE_DESCRIPTION(\"Motorcomm 8511/8521/8531/8531S/8821 PHY driver\");\n+MODULE_DESCRIPTION(\"Motorcomm 8511/8521/8531/8531S/8821/8824 PHY driver\");\n MODULE_AUTHOR(\"Peter Geis\");\n MODULE_AUTHOR(\"Frank\");\n+MODULE_AUTHOR(\"Kyle\");\n MODULE_LICENSE(\"GPL\");\n \n static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = {\n@@ -3206,6 +4772,7 @@ static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = {\n \t{ PHY_ID_MATCH_EXACT(PHY_ID_YT8531) },\n \t{ PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) },\n \t{ PHY_ID_MATCH_EXACT(PHY_ID_YT8821) },\n+\t{ PHY_ID_MATCH_EXACT(PHY_ID_YT8824) },\n \t{ /* sentinel */ }\n };\n \ndiff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c\nindex 870920311f9a0..f8e03d3afa457 100644\n--- a/drivers/net/phy/phy-c45.c\n+++ b/drivers/net/phy/phy-c45.c\n@@ -1408,6 +1408,30 @@ int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable)\n }\n EXPORT_SYMBOL_GPL(genphy_c45_fast_retrain);\n \n+/**\n+ * genphy_c45_template_testmode - configure template testmode registers\n+ * @phydev: target phy_device struct\n+ * @test_mode: testmode includes Normal to Test mode 7\n+ *\n+ * Description: Set template testmode include Normal to Test mode 7\n+ *\n+ * Return: 0 on success, or a negative error code on failure (e.g. register\n+ * read/write error).\n+ */\n+int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode)\n+{\n+\tint ctrl;\n+\n+\tif (test_mode \u003c MDIO_PMA_10GBT_TESTMODE_NORMAL ||\n+\t    test_mode \u003e MDIO_PMA_10GBT_TESTMODE_7)\n+\t\treturn -EOPNOTSUPP;\n+\n+\tctrl = FIELD_PREP(MDIO_PMA_10GBT_TESTMODE_MASK, test_mode);\n+\treturn phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TESTMODE,\n+\t\t\t      MDIO_PMA_10GBT_TESTMODE_MASK, ctrl);\n+}\n+EXPORT_SYMBOL_GPL(genphy_c45_template_testmode);\n+\n /**\n  * genphy_c45_plca_get_cfg - get PLCA configuration from standard registers\n  * @phydev: target phy_device struct\ndiff --git a/include/linux/phy.h b/include/linux/phy.h\nindex 3d8afe6b7f1c5..fb827cc3c98f4 100644\n--- a/include/linux/phy.h\n+++ b/include/linux/phy.h\n@@ -2357,6 +2357,7 @@ int genphy_c45_loopback(struct phy_device *phydev, bool enable, int speed);\n int genphy_c45_pma_resume(struct phy_device *phydev);\n int genphy_c45_pma_suspend(struct phy_device *phydev);\n int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable);\n+int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode);\n int genphy_c45_plca_get_cfg(struct phy_device *phydev,\n \t\t\t    struct phy_plca_cfg *plca_cfg);\n int genphy_c45_plca_set_cfg(struct phy_device *phydev,\ndiff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h\nindex 06f4bc3c20c71..353ca13c64fca 100644\n--- a/include/uapi/linux/mdio.h\n+++ b/include/uapi/linux/mdio.h\n@@ -63,6 +63,7 @@\n /* Media-dependent registers. */\n #define MDIO_PMA_10GBT_SWAPPOL\t130\t/* 10GBASE-T pair swap \u0026 polarity */\n #define MDIO_PMA_10GBT_TXPWR\t131\t/* 10GBASE-T TX power control */\n+#define MDIO_PMA_10GBT_TESTMODE 132 /* Test mode control */\n #define MDIO_PMA_10GBT_SNR\t133\t/* 10GBASE-T SNR margin, lane A.\n \t\t\t\t\t * Lanes B-D are numbered 134-136. */\n #define MDIO_PMA_10GBR_FSRT_CSR\t147\t/* 10GBASE-R fast retrain status and control */\n@@ -320,6 +321,17 @@\n /* PMA 10GBASE-R Fast Retrain status and control register. */\n #define MDIO_PMA_10GBR_FSRT_ENABLE\t0x0001\t/* Fast retrain enable */\n \n+/* PMA 10GBASE-T Template Test Mode Register*/\n+#define MDIO_PMA_10GBT_TESTMODE_MASK GENMASK(15, 13) /* Template test mode */\n+#define MDIO_PMA_10GBT_TESTMODE_NORMAL 0x0 /* Template Normal */\n+#define MDIO_PMA_10GBT_TESTMODE_1 0x1 /* Template TestMode1 */\n+#define MDIO_PMA_10GBT_TESTMODE_2 0x2 /* Template TestMode2 */\n+#define MDIO_PMA_10GBT_TESTMODE_3 0x3 /* Template TestMode3 */\n+#define MDIO_PMA_10GBT_TESTMODE_4 0x4 /* Template TestMode4 */\n+#define MDIO_PMA_10GBT_TESTMODE_5 0x5 /* Template TestMode5 */\n+#define MDIO_PMA_10GBT_TESTMODE_6 0x6 /* Template TestMode6 */\n+#define MDIO_PMA_10GBT_TESTMODE_7 0x7 /* Template TestMode7 */\n+\n /* PCS 10GBASE-R/-T status register 1. */\n #define MDIO_PCS_10GBRT_STAT1_BLKLK\t0x0001\t/* Block lock attained */\n \n"
}

2/1 2026/09/15 10:59 agent patch-evaluator
1m Model:
core

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch series adds support for the Motorcomm YT8824 quad-port 2.5G Ethernet PHY in drivers/net/phy/motorcomm.c and adds an associated helper genphy_c45_template_testmode in drivers/net/phy/phy-c45.c. The modified code targets a specific physical Ethernet PHY transceiver that requires physical hardware and specific Device Tree description ('ethernet-phy-package'), which is not present or emulated in standard virtualized x86_64/QEMU fuzzing environments. The helper genphy_c45_template_testmode is solely called by the YT8824 driver, and probe immediately fails without the OF node. Therefore, the code is structurally unreachable.",
  "WorthFuzzing": false
}

Instruction:
You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.

================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.

- REACHABILITY IS THE PRIMARY GATE:
  Fuzzing can only discover bugs in code that can actually execute in standard virtualized
  environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
  If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
  regardless of whether it adds assertions or complex logic.

- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
  Patch authors routinely label changes as "cleanups", "refactorings", or state
  "No functional change intended". Do NOT take these claims at face value.
  Code refactorings that rearrange logic, introduce helper functions, or alter state management
  in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
  If reachable executable code is modified or refactored, it MUST be fuzzed.

- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
  When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
  BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
  Even if the author believes the invariant always holds, fuzzing is essential to verify whether
  an unusual sequence of operations can violate it.

================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:

- Non-kernel and non-executable changes:
  * Modifications to Documentation/, comments, or spelling fixes.
  * User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
    that do not affect the compiled kernel image (vmlinux) or kernel modules.
  * Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
    that do not alter control flow or data structures.
  * Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
  * Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
    ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
  * Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
    physical PCI hot-unplug or manual sysfs driver unbinding.
  * Code paths exclusive to architectures other than the target architecture.

================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
  * Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
    BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
  * Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
  * Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
  * Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).

================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:

- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
  Do NOT list generic, ubiquitous functions called by almost every program in the corpus
  (including, but not limited to: general memory allocators and deallocators, page fault
  and trap handlers, or core synchronization primitives; this is not an exhaustive list).
  Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
  which severely dilutes fuzzing effort away from the actual changes.

- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
  List functions that specifically implement the logic being added or altered, or direct API entrypoints
  for the subsystem feature under review.

- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
  Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
  distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
  If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
  functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).

================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any '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:
Target architecture: amd64

For your convenience, here is the diff of the changes:
commit ae31ea1a6b52c868b9c7a749612861f0c172be9a
Author: syz-cluster <triage@syzkaller.com>
Date:   Tue Sep 15 10:59:48 2026 +0000

    syz-cluster: applied patch under review

diff --git a/Documentation/devicetree/bindings/net/motorcomm,yt8824.yaml b/Documentation/devicetree/bindings/net/motorcomm,yt8824.yaml
new file mode 100644
index 0000000000000..93e9f765404a3
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/motorcomm,yt8824.yaml
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/motorcomm,yt8824.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MotorComm YT8824 Ethernet PHY
+
+maintainers:
+  - Kyle Switch <kyle.switch@motor-comm.com>
+
+description:
+  Motorcomm YT8824 Ethernet PHY is a PHY package of 4 PHYs.
+
+$ref: ethernet-phy-package.yaml#
+
+properties:
+  compatible:
+    enum:
+      - motorcomm,yt8824-package
+
+required:
+  - compatible
+  - phy-mode
+  - reg
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    mdio {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        ethernet-phy-package@0 {
+            #address-cells = <1>;
+            #size-cells = <0>;
+            compatible = "motorcomm,yt8824-package";
+            reg = <9>;
+
+            phy-mode = "internal";
+
+            ethernet-phy@4 {
+                reg = <4>;
+            };
+
+            ethernet-phy@5 {
+                reg = <5>;
+            };
+
+            ethernet-phy@6 {
+                reg = <6>;
+            };
+
+            ethernet-phy@7 {
+                reg = <7>;
+            };
+        };
+    };
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index d3835597e3795..996d75afed446 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -361,9 +361,10 @@ config MICROSEMI_PHY
 
 config MOTORCOMM_PHY
 	tristate "Motorcomm PHYs"
+	select PHY_PACKAGE
 	help
 	  Enables support for Motorcomm network PHYs.
-	  Currently supports YT85xx Gigabit Ethernet PHYs.
+	  Currently supports YT85xx Gigabit Ethernet PHYs and YT8824 4 * 2.5G PHY.
 
 config NATIONAL_PHY
 	tristate "National Semiconductor PHYs"
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
index 90a4f86f2758b..b60948c9ce884 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -1,24 +1,31 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Motorcomm 8511/8521/8522/8531/8531S/8821 PHY driver.
+ * Motorcomm 8511/8521/8522/8531/8531S/8821/8824 PHY driver.
  *
  * Author: Peter Geis <pgwipeout@gmail.com>
  * Author: Frank <Frank.Sae@motor-comm.com>
+ * Author: Kyle <kyle.switch@motor-comm.com>
  */
 
 #include <linux/clk.h>
 #include <linux/etherdevice.h>
 #include <linux/kernel.h>
+#include <linux/mdio.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
 #include <linux/phy.h>
 #include <linux/property.h>
 
+#include "phylib.h"
+
 #define PHY_ID_YT8511		0x0000010a
 #define PHY_ID_YT8521		0x0000011a
 #define PHY_ID_YT8522		0x4f51e928
 #define PHY_ID_YT8531		0x4f51e91b
 #define PHY_ID_YT8531S		0x4f51e91a
 #define PHY_ID_YT8821		0x4f51ea19
+#define PHY_ID_YT8824		0x4f51e8b8
 /* YT8521/YT8531S/YT8821 Register Overview
  *	UTP Register space	|	FIBER Register space
  *  ------------------------------------------------------------
@@ -30,6 +37,18 @@
  *  ------------------------------------------------------------
  */
 
+/* YT8824 Register Overview
+ * UTP Register space | USXGMII Register space
+ *  ------------------------------------------------------------
+ * | UTP MII		| USXGMII MII		|
+ * | UTP MMD		|			|
+ * | UTP Extended	| USXGMII Extended	|
+ * | UTP Top Extended	| USXGMII Top Extended	|
+ *  ------------------------------------------------------------
+ * |   Common Top Extended			|
+ *  ------------------------------------------------------------
+ */
+
 /* 0x10 ~ 0x15 , 0x1E and 0x1F are common MII registers of yt phy */
 
 /* Specific Function Control Register */
@@ -381,6 +400,13 @@
 #define YT8821_CHIP_MODE_AUTO_BX2500_SGMII	0
 #define YT8821_CHIP_MODE_FORCE_BX2500		1
 
+#define YT8824_RSSR_SPACE_MASK			BIT(0)
+#define YT8824_RSSR_USXGMII_SPACE		(0x1)
+#define YT8824_RSSR_UTP_SPACE			(0x0)
+#define YT8824_SDS_CFG_MIN_PRE_MASK		GENMASK(3, 0)
+#define YT8824_SDS_EN_FILL_PRE			BIT(13)
+#define YT8824_SDS_TX_PRE_PADDING		(0x7)
+
 struct yt8521_priv {
 	/* combo_advertising is used for case of YT8521 in combo mode,
 	 * this means that yt8521 may work in utp or fiber mode which depends
@@ -399,6 +425,12 @@ struct yt8521_priv {
 	u8 reg_page;
 };
 
+struct yt8824_shared_priv {
+	phy_interface_t interface_mode;
+	/* shared_lock used to UTPs operation isolation during swap reg space */
+	struct mutex shared_lock;
+};
+
 /**
  * ytphy_read_ext() - read a PHY's extended register
  * @phydev: a pointer to a &struct phy_device
@@ -437,6 +469,70 @@ static int ytphy_read_ext_with_lock(struct phy_device *phydev, u16 regnum)
 	return ret;
 }
 
+/**
+ * ytphy_read_top_ext() - read a PHY's top extended register for YT8824
+ * @phydev: a pointer to a &struct phy_device
+ * @regnum: register number to read
+ *
+ * Returns: the value of regnum reg or negative error code
+ */
+static int ytphy_read_top_ext(struct phy_device *phydev, u16 regnum)
+{
+	int ret;
+
+	lockdep_assert_held(&phydev->mdio.bus->mdio_lock);
+	ret = __phy_package_write(phydev, 0, YTPHY_PAGE_SELECT, regnum);
+	if (ret < 0)
+		return ret;
+
+	return __phy_package_read(phydev, 0, YTPHY_PAGE_DATA);
+}
+
+/**
+ * ytphy_write_top_ext() - write a PHY's top extended register for YT8824
+ * @phydev: a pointer to a &struct phy_device
+ * @regnum: register number to write
+ * @val: register val to write
+ *
+ * Returns: 0 or negative error code
+ */
+static int ytphy_write_top_ext(struct phy_device *phydev, u16 regnum,
+			       u16 val)
+{
+	int ret;
+
+	lockdep_assert_held(&phydev->mdio.bus->mdio_lock);
+	ret = __phy_package_write(phydev, 0, YTPHY_PAGE_SELECT, regnum);
+	if (ret < 0)
+		return ret;
+
+	return __phy_package_write(phydev, 0, YTPHY_PAGE_DATA, val);
+}
+
+/**
+ * phy8824_page_write_with_lock() - write page for YT8824
+ * @phydev: a pointer to a &struct phy_device
+ * @page: reg page(YT8824_RSSR_USXGMII_SPACE/YT8824_RSSR_UTP_SPACE).
+ *
+ * Returns: 0 or negative error code
+ */
+static int phy8824_page_write_with_lock(struct phy_device *phydev, int page)
+{
+	int ret;
+
+	phy_lock_mdio_bus(phydev);
+	ret = ytphy_read_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG);
+	if (ret < 0)
+		goto err;
+	ret &= ~YT8824_RSSR_SPACE_MASK;
+	ret |= (page & YT8824_RSSR_SPACE_MASK);
+	ret = ytphy_write_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG, ret);
+
+err:
+	phy_unlock_mdio_bus(phydev);
+	return ret;
+}
+
 /**
  * ytphy_write_ext() - write a PHY's extended register
  * @phydev: a pointer to a &struct phy_device
@@ -622,15 +718,1057 @@ static int ytphy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
 		mask = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL;
 		ret = ytphy_modify_ext(phydev, YTPHY_WOL_CONFIG_REG, mask, 0);
 
-		/* Disable WOL interrupt */
-		ret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG,
-				   YTPHY_IER_WOL, 0);
+		/* Disable WOL interrupt */
+		ret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG,
+				   YTPHY_IER_WOL, 0);
+		if (ret < 0)
+			goto err_restore_page;
+	}
+
+err_restore_page:
+	return phy_restore_page(phydev, old_page, ret);
+}
+
+/**
+ * yt8824_read_page() - read PHY8824 reg page
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: current reg space of yt8824 (YT8824_RSSR_USXGMII_SPACE/
+ * YT8824_RSSR_UTP_SPACE) or negative errno code
+ */
+static int yt8824_read_page(struct phy_device *phydev)
+{
+	int old_page;
+
+	old_page = ytphy_read_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG);
+	if (old_page < 0)
+		return old_page;
+
+	return old_page & YT8824_RSSR_SPACE_MASK;
+};
+
+/**
+ * yt8824_write_page() - write reg page
+ * @phydev: a pointer to a &struct phy_device
+ * @page: Reg page(YT8824_RSSR_USXGMII_SPACE/YT8824_RSSR_UTP_SPACE) to write.
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_write_page(struct phy_device *phydev, int page)
+{
+	int old_page;
+	u16 data;
+
+	old_page = ytphy_read_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG);
+	if (old_page < 0)
+		return old_page;
+	data = old_page & (~YT8824_RSSR_SPACE_MASK);
+	data |= page;
+
+	return ytphy_write_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG, data);
+};
+
+/**
+ * yt8824_utp_invalid_test_mode_paged() - config YT8824 to invalid test mode.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_utp_invalid_test_mode_paged(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	return genphy_c45_template_testmode
+		(phydev, MDIO_PMA_10GBT_TESTMODE_1);
+}
+
+/**
+ * yt8824_sds_isolate_paged() - enable YT8824 serdes isolate.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_sds_isolate_paged(struct phy_device *phydev)
+{
+	int old_page = YT8824_RSSR_UTP_SPACE;
+	int ret = 0;
+
+	old_page = phy_select_page(phydev, YT8824_RSSR_USXGMII_SPACE);
+	if (old_page < 0)
+		goto err_restore_page;
+
+	/* enable sds isolate */
+	ret = __phy_modify(phydev, MII_BMCR, BMCR_ISOLATE, BMCR_ISOLATE);
+
+err_restore_page:
+	/* restore page, release the lock */
+	return phy_restore_page(phydev, old_page, ret);
+}
+
+/**
+ * yt8824_utp_softreset_paged() - config YT8824 UTP softreset.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_utp_softreset_paged(struct phy_device *phydev)
+{
+	int ret = 0;
+	int val;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+	ret = phy_modify(phydev, MII_BMCR, BMCR_RESET, BMCR_RESET);
+	if (ret < 0)
+		return ret;
+	/* wait until softreset done. */
+	return phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET),
+				     50000, 600000, true);
+}
+
+/**
+ * yt8824_utp_normal_test_mode_paged() - config YT8824 to normal test mode.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_utp_normal_test_mode_paged(struct phy_device *phydev)
+{
+	int ret = 0;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	return genphy_c45_template_testmode(phydev,
+					    MDIO_PMA_10GBT_TESTMODE_NORMAL);
+}
+
+/**
+ * yt8824_sds_isolate_and_softreset_paged() - disable YT8824 serdes isolate
+ * and sds softreset.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_sds_isolate_and_softreset_paged(struct phy_device *phydev)
+{
+	int old_page = YT8824_RSSR_UTP_SPACE;
+	int val = 0;
+	int ret = -1;
+
+	old_page = phy_select_page(phydev, YT8824_RSSR_USXGMII_SPACE);
+	if (old_page < 0)
+		goto err_restore_page;
+
+	/* sds softreset and disable isolate */
+	ret = __phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ISOLATE,
+			   BMCR_RESET & ~BMCR_ISOLATE);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* poll while still holding the lock */
+	ret = read_poll_timeout(__phy_read, val,
+				(val < 0) || !(val & BMCR_RESET), 50000, 600000,
+				true, phydev, MII_BMCR);
+	if (val < 0)
+		ret = val;
+
+err_restore_page:
+	/* restore page, release the lock */
+	return phy_restore_page(phydev, old_page, ret);
+}
+
+/**
+ * yt8824_restore_working_status() - called to do store working status
+ * @phydev: a pointer to a &struct phy_device
+ * @ret: operation's return code
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_restore_working_status(struct phy_device *phydev, int ret)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int r;
+
+	/* configure normal test mode */
+	r = yt8824_utp_normal_test_mode_paged(phydev);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	if (priv->interface_mode != PHY_INTERFACE_MODE_INTERNAL) {
+		/* sds soft reset and disable isolation */
+		r = yt8824_sds_isolate_and_softreset_paged(phydev);
+		if (ret >= 0 && r < 0)
+			ret = r;
+	}
+
+	return ret;
+}
+
+/**
+ * yt8824_soft_reset() - called to do PHY software reset
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_soft_reset(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+
+	mutex_lock(&priv->shared_lock);
+	if (priv->interface_mode == PHY_INTERFACE_MODE_INTERNAL) {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+		ret = yt8824_utp_softreset_paged(phydev);
+		if (ret < 0)
+			goto retry;
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+	} else {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* sds isolation */
+		ret = yt8824_sds_isolate_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* utp soft reset */
+		ret = yt8824_utp_softreset_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* sds soft reset and disable isolation */
+		ret = yt8824_sds_isolate_and_softreset_paged(phydev);
+		if (ret < 0)
+			goto retry;
+	}
+	mutex_unlock(&priv->shared_lock);
+	return ret;
+retry:
+	ret = yt8824_restore_working_status(phydev, ret);
+	mutex_unlock(&priv->shared_lock);
+
+	return ret;
+}
+
+/**
+ * yt8824_extern_config_utp_init_paged() - config external phy8824 utp init
+ * @phydev: target phy_device struct
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_extern_config_utp_init_paged(struct phy_device *phydev)
+{
+	int ret = 0;
+	int val = 0;
+	int r;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+	/* power down */
+	ret = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN);
+	if (ret < 0)
+		goto err_restore;
+
+	/* pll calibration */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0001, 0x0003);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa20e, 0x0cba);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa20a, 0xc3f1);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa20c, 0x1620);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0x0a00);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0x0e00);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimization utp */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0001, 0x0003);
+	if (ret < 0)
+		goto err_restore;
+
+	/* enable nibble */
+	ret = ytphy_write_ext_with_lock(phydev, 0xa003, 0x0003);
+	if (ret < 0)
+		goto err_restore;
+
+	/* idle err detect enable */
+	ret = ytphy_write_ext_with_lock(phydev, 0x03d0, 0x5210);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized 2.5G long cable performance */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0372, 0x5038);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x037c, 0x6068);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0388, 0x00a0);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized fast retrain */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0359, 0x2140);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x000c, 0xc1a0);
+	if (ret < 0)
+		goto err_restore;
+
+	/* 2.5G template tone */
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2fa, 0x0083);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x04e2, 0x0149);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized 2.5G template */
+	ret = ytphy_write_ext_with_lock(phydev, 0x047e, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x047f, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0480, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0481, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized 1000M cable length threshold */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0336, 0xab0a);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0340, 0x301d);
+	if (ret < 0)
+		goto err_restore;
+
+	/* 100M template amplitude */
+	ret = ytphy_write_ext_with_lock(phydev, 0x046e, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x046f, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0470, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0471, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized 100M cable length threshold */
+	ret = ytphy_write_ext_with_lock(phydev, 0x030b, 0xaa1d);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x071f, 0x0036);
+	if (ret < 0)
+		goto err_restore;
+
+	/* 10M template amplitude */
+	ret = ytphy_write_ext_with_lock(phydev, 0x046b, 0x1818);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x046c, 0x1818);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized 10M cable length threshold */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0466, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0467, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0468, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0469, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimize utp 1000M performance */
+	ret = ytphy_write_ext_with_lock(phydev, 0x034a, 0xff03);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x00f8, 0xb3ff);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0059, 0x4040);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x032c, 0x5094);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x032d, 0xd094);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x032e, 0x5308);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0322, 0x6440);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x04d3, 0x5220);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x04d2, 0x5220);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized EMC CS */
+	ret = ytphy_write_ext_with_lock(phydev, 0x00c8, 0xffff);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x00be, 0x6406);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x037a, 0x40ff);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized EMC RE */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0482, 0xffff);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d5, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d6, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d7, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d8, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa218, 0x006e);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xfff0);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xfff0);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xffff);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xffff);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = genphy_c45_template_testmode(phydev, MDIO_PMA_10GBT_TESTMODE_1);
+	if (ret < 0)
+		goto err_restore_normal;
+	/* reset */
+	ret = phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE,
+			 BMCR_RESET | BMCR_ANENABLE);
+	if (ret < 0)
+		goto err_restore_normal;
+	ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET),
+				    50000, 600000, true);
+	if (ret < 0)
+		goto err_restore_normal;
+
+	ret = genphy_c45_template_testmode(phydev,
+					   MDIO_PMA_10GBT_TESTMODE_NORMAL);
+	if (ret < 0)
+		goto err_restore_normal;
+	return 0;
+
+err_restore:
+	r = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	return ret;
+
+err_restore_normal:
+	r = genphy_c45_template_testmode(phydev,
+					 MDIO_PMA_10GBT_TESTMODE_NORMAL);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	r = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	return ret;
+}
+
+/**
+ * yt8824_extern_config_sds_init_paged() - config external phy8824 sds init
+ * @phydev: target phy_device struct
+ *
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_extern_config_sds_init_paged(struct phy_device *phydev)
+{
+	int old_page = YT8824_RSSR_UTP_SPACE;
+	int val_1, val_2, val_3, tmp;
+	int ret = -1;
+	int val;
+
+	old_page = phy_select_page(phydev, YT8824_RSSR_USXGMII_SPACE);
+	if (old_page < 0)
+		goto err_restore_page;
+
+	/* read efuse */
+	ret = ytphy_read_top_ext(phydev, 0xa13e);
+	if (ret < 0)
+		goto err_restore_page;
+	else
+		val_1 = ret;
+
+	ret = ytphy_read_top_ext(phydev, 0xa13f);
+	if (ret < 0)
+		goto err_restore_page;
+	else
+		val_2 = ret;
+
+	ret = ytphy_read_top_ext(phydev, 0xa140);
+	if (ret < 0)
+		goto err_restore_page;
+	else
+		val_3 = ret;
+
+	/* Serdes optimization */
+	ret = ytphy_write_ext(phydev, 0x04be, 0x000d);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x049f, 0x7ded);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x04a9, 0x009f);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* analog CDR */
+	ret = ytphy_write_ext(phydev, 0x0406, 0x0800);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* optimized VCO */
+	ret = ytphy_write_ext(phydev, 0x0438, 0x9024);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x0439, 0x00c0);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* optimized PLL lock */
+	ret = ytphy_read_ext(phydev, 0x0429);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret &= ~(BIT(13) | BIT(12));
+	tmp = (val_1 & (BIT(7) | BIT(6))) >> 6;
+	ret |= (tmp << 12);
+	ret = ytphy_write_ext(phydev, 0x0429, ret);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_read_ext(phydev, 0x0441);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret &= ~(BIT(1) | BIT(0));
+	tmp = (val_1 & (BIT(5) | BIT(4))) >> 4;
+	ret |= tmp;
+	ret = ytphy_write_ext(phydev, 0x0441, ret);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_read_ext(phydev, 0x042b);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret &= ~(BIT(13) | BIT(12));
+	tmp = (val_3 & (BIT(1) | BIT(0)));
+	ret |= (tmp << 12);
+	ret = ytphy_write_ext(phydev, 0x042b, ret);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x043a, 0x1006);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x042a, 0xf070);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* cable length threshold */
+	ret = ytphy_write_ext(phydev, 0x0491, 0x007f);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x0492, 0x7f7f);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* Serdes training threshold */
+	ret = ytphy_write_ext(phydev, 0x0454, 0x0f14);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x0497, 0x0a44);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* digital eye diagram of SerDes */
+	ret = ytphy_write_ext(phydev, 0x04cd, 0x0000);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* Serdes LDO */
+	ret = ytphy_read_ext(phydev, 0x04b5);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret &= ~(BIT(6) | BIT(5) | BIT(4));
+	tmp = (val_2 & (BIT(4) | BIT(3) | BIT(2))) >> 2;
+	ret |= (tmp << 4);
+	ret = ytphy_write_ext(phydev, 0x04b5, ret);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_read_ext(phydev, 0x04b4);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret &= ~(BIT(10) | BIT(9) | BIT(8));
+	tmp = (val_2 & (BIT(7) | BIT(6) | BIT(5))) >> 5;
+	ret |= (tmp << 8);
+	ret = ytphy_write_ext(phydev, 0x04b4, ret);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* optimized Serdes RX */
+	ret = ytphy_write_ext(phydev, 0x04af, 0x45e3);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x048a, 0x0fff);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x0408, 0x7c00);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x04d6, 0x007f);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x044f, 0xff08);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* optimized Serdes TX */
+	ret = ytphy_write_ext(phydev, 0x048e, 0x7d00);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x000d, 0x0606);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* Serdes manual config */
+	ret = ytphy_write_ext(phydev, 0x04b0, 0x0804);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x04b1, 0x7074);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x04af, 0x45e7);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* restart calibration */
+	ret = ytphy_write_ext(phydev, 0x0003, 0x5603);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x0492, 0x7fff);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x0492, 0x7f7f);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x2000, 0x0040);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x2000, 0x0000);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* TX preamble padded to 8; RX IPG always > 8 */
+	ret = __phy_read(phydev, MII_RESV1);
+	if (ret < 0)
+		goto err_restore_page;
+	ret &= ~YT8824_SDS_CFG_MIN_PRE_MASK;
+	ret |= YT8824_SDS_TX_PRE_PADDING;
+	ret |= YT8824_SDS_EN_FILL_PRE;
+	ret = __phy_write(phydev, MII_RESV1, ret);
+	if (ret < 0)
+		goto err_restore_page;
+	/* reset serdes */
+	ret = __phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE,
+			   BMCR_RESET | BMCR_ANENABLE);
+	if (ret < 0)
+		goto err_restore_page;
+	/* poll while still holding the lock; __phy_read takes no lock */
+	ret = read_poll_timeout(__phy_read, val,
+				(val < 0) || !(val & BMCR_RESET), 50000, 600000,
+				true, phydev, MII_BMCR);
+	if (val < 0)
+		ret = val;
+err_restore_page:
+	/* restore page, release the lock */
+	return phy_restore_page(phydev, old_page, ret);
+}
+
+/**
+ * yt8824_internal_config_init_paged() - config internal phy8824 init
+ * @phydev: target phy_device struct
+ *
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_internal_config_init_paged(struct phy_device *phydev)
+{
+	int ret = 0;
+	int val = 0;
+	int r = 0;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x1, 0x3);
+	if (ret < 0)
+		return ret;
+	/* power down */
+	ret = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa20e, 0xcba);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa20a, 0xc3f1);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa20c, 0x1620);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0xa00);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0xe00);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa003, 0x3);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x3d0, 0x5210);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x372, 0x5038);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x37c, 0x6068);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x388, 0xa0);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x359, 0x2140);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2fa, 0x83);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x4e2, 0x149);
+	if (ret < 0)
+		goto err_restore;
+	/* 2.5G tempate */
+	ret = ytphy_write_ext_with_lock(phydev, 0x47e, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x47f, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x480, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x481, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+	/* 1000 cable length threshold */
+	ret = ytphy_write_ext_with_lock(phydev, 0x336, 0xab0a);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x340, 0x301d);
+	if (ret < 0)
+		goto err_restore;
+	/* 1000 performance */
+	ret = ytphy_write_ext_with_lock(phydev, 0x34a, 0xff03);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xf8, 0xb3ff);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x32c, 0x5094);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x32d, 0xd094);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x32e, 0x5308);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x322, 0x6440);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x4d3, 0x5220);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x4d2, 0x5220);
+	if (ret < 0)
+		goto err_restore;
+	/* 100 tempate */
+	ret = ytphy_write_ext_with_lock(phydev, 0x46e, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x46f, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x470, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x471, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+	/* 100 cable length threshold */
+	ret = ytphy_write_ext_with_lock(phydev, 0x30b, 0xaa1d);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x71f, 0x36);
+	if (ret < 0)
+		goto err_restore;
+	/* 10 tempate */
+	ret = ytphy_write_ext_with_lock(phydev, 0x46b, 0x1818);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x46c, 0x1818);
+	if (ret < 0)
+		goto err_restore;
+	/* 10 tempate MAU*/
+	ret = ytphy_write_ext_with_lock(phydev, 0x466, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x467, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x468, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x469, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+	/* EMC CS, Inconsistent with external phy */
+	ret = ytphy_write_ext_with_lock(phydev, 0xc8, 0xfff);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xbe, 0x6406);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x37a, 0x40ff);
+	if (ret < 0)
+		goto err_restore;
+	/* EMC RE*/
+	ret = ytphy_write_ext_with_lock(phydev, 0x482, 0xffff);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d5, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d6, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d7, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d8, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa218, 0x6e);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xfff0);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xfff0);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xffff);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xffff);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xc, 0x41a1);
+	if (ret < 0)
+		goto err_restore;
+	ret = genphy_c45_template_testmode(phydev, MDIO_PMA_10GBT_TESTMODE_1);
+	if (ret)
+		goto err_restore_normal;
+	/* reset */
+	ret = phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE,
+			 BMCR_RESET | BMCR_ANENABLE);
+	if (ret < 0)
+		goto err_restore_normal;
+	ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET),
+				    50000, 600000, true);
+	if (ret < 0)
+		goto err_restore_normal;
+
+	ret = genphy_c45_template_testmode(phydev,
+					   MDIO_PMA_10GBT_TESTMODE_NORMAL);
+	if (ret < 0)
+		goto err_restore_normal;
+
+	return 0;
+
+err_restore:
+	r = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	return ret;
+
+err_restore_normal:
+	r = genphy_c45_template_testmode(phydev,
+					 MDIO_PMA_10GBT_TESTMODE_NORMAL);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	r = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	return ret;
+}
+
+/**
+ * yt8824_config_init() - phy initializatioin
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_config_init(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+
+	mutex_lock(&priv->shared_lock);
+	if (priv->interface_mode == PHY_INTERFACE_MODE_INTERNAL) {
+		ret = yt8824_internal_config_init_paged(phydev);
 		if (ret < 0)
-			goto err_restore_page;
+			goto err;
+	} else {
+		ret = yt8824_extern_config_sds_init_paged(phydev);
+		if (ret < 0)
+			goto err;
+		ret = yt8824_extern_config_utp_init_paged(phydev);
+		if (ret < 0)
+			goto err;
 	}
+	mutex_unlock(&priv->shared_lock);
+	ret = yt8824_soft_reset(phydev);
 
-err_restore_page:
-	return phy_restore_page(phydev, old_page, ret);
+	phydev_dbg(phydev, "%s done, phy addr: %d\n", __func__,
+		   phydev->mdio.addr);
+	return ret;
+err:
+	mutex_unlock(&priv->shared_lock);
+	return ret;
 }
 
 static int yt8531_set_wol(struct phy_device *phydev,
@@ -3104,6 +4242,418 @@ static int yt8821_resume(struct phy_device *phydev)
 	return yt8821_modify_utp_fiber_bmcr(phydev, BMCR_PDOWN, 0);
 }
 
+/**
+ * yt8824_get_features - read mmd register to get 2.5G capability
+ * @phydev: target phy_device struct
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_get_features(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+
+	mutex_lock(&priv->shared_lock);
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		goto err;
+	ret = yt8821_get_features(phydev);
+
+err:
+	mutex_unlock(&priv->shared_lock);
+	return ret;
+}
+
+/**
+ * yt8824_aneg_done()  - check negotiation state.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: link status or negative errno code
+ */
+static int yt8824_aneg_done(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int link = 0;
+	int ret = 0;
+
+	mutex_lock(&priv->shared_lock);
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		goto err;
+
+	ret = phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG);
+	if (ret < 0)
+		goto err;
+	mutex_unlock(&priv->shared_lock);
+	link = !!(ret & YTPHY_SSR_LINK);
+
+	phydev_dbg(phydev, "%s, phy addr: %d, link_utp: %d\n", __func__,
+		   phydev->mdio.addr, link);
+	return link;
+err:
+	mutex_unlock(&priv->shared_lock);
+	return ret;
+}
+
+/**
+ * yt8824_read_status_paged() -  determines the speed and duplex of one page
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_read_status_paged(struct phy_device *phydev)
+{
+	int link = 0;
+	int ret = 0;
+	int val = 0;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	ret = genphy_read_status(phydev);
+	if (ret < 0)
+		return ret;
+
+	if (phydev->autoneg_complete) {
+		ret = genphy_c45_read_lpa(phydev);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG);
+	if (ret < 0)
+		return ret;
+
+	val = ret;
+
+	link = val & YTPHY_SSR_LINK;
+	if (link)
+		yt8821_adjust_status(phydev, val);
+
+	if (link) {
+		if (phydev->link == 0)
+			phydev_dbg(phydev, "%s, phy addr: %d, link up\n",
+				   __func__, phydev->mdio.addr);
+		phydev->link = 1;
+	} else {
+		if (phydev->link == 1)
+			phydev_dbg(phydev, "%s, phy addr: %d, link down\n",
+				   __func__, phydev->mdio.addr);
+		phydev->link = 0;
+	}
+	phy_resolve_aneg_pause(phydev);
+	return 0;
+}
+
+/**
+ * yt8824_read_status() -  determines the negotiated speed and duplex
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_read_status(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+
+	mutex_lock(&priv->shared_lock);
+	ret = yt8824_read_status_paged(phydev);
+	mutex_unlock(&priv->shared_lock);
+
+	return ret;
+}
+
+/**
+ * yt8824_utp_power_on(): utp power on.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_utp_power_on(struct phy_device *phydev)
+{
+	int ret = 0;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0x0);
+}
+
+/**
+ * yt8824_utp_power_down(): utp power down.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_utp_power_down(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	return phy_modify(phydev, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN);
+}
+
+/**
+ * yt8824_power_on()  - set utp power on.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * NOTE: need WA like softreset
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_power_on(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+	int r;
+
+	if (priv->interface_mode == PHY_INTERFACE_MODE_INTERNAL) {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+		/* utp power on */
+		ret = yt8824_utp_power_on(phydev);
+		if (ret < 0)
+			goto retry;
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+	} else {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* sds isolation */
+		ret = yt8824_sds_isolate_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* utp power on */
+		ret = yt8824_utp_power_on(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* sds soft reset and disable isolation */
+		ret = yt8824_sds_isolate_and_softreset_paged(phydev);
+		if (ret < 0)
+			goto retry;
+	}
+	return 0;
+
+retry:
+	/*
+	 * If the PHY up operation succeeds but the subsequent operation
+	 * fails, revert to the default state.
+	 */
+	r = yt8824_utp_power_down(phydev);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	ret = yt8824_restore_working_status(phydev, ret);
+	return ret;
+}
+
+/**
+ * yt8824_resume() - resume the hardware
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_resume(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+
+	mutex_lock(&priv->shared_lock);
+	ret = yt8824_power_on(phydev);
+	mutex_unlock(&priv->shared_lock);
+
+	return ret;
+}
+
+/**
+ * yt8824_power_down()  - set utp power down.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * NOTE: need WA like softreset
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_power_down(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+	int r;
+
+	if (priv->interface_mode == PHY_INTERFACE_MODE_INTERNAL) {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+		/* utp power down */
+		ret = yt8824_utp_power_down(phydev);
+		if (ret < 0)
+			goto retry;
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+	} else {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* sds isolation */
+		ret = yt8824_sds_isolate_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* utp power down */
+		ret = yt8824_utp_power_down(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* sds soft reset and disable isolation */
+		ret = yt8824_sds_isolate_and_softreset_paged(phydev);
+		if (ret < 0)
+			goto retry;
+	}
+	return 0;
+
+retry:
+	/*
+	 * If the PHY down operation succeeds but the subsequent operation
+	 * fails, revert to the default state.
+	 */
+	r = yt8824_utp_power_on(phydev);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	ret = yt8824_restore_working_status(phydev, ret);
+	return ret;
+}
+
+/**
+ * yt8824_suspend() - suspend the hardware
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_suspend(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+
+	mutex_lock(&priv->shared_lock);
+	ret = yt8824_power_down(phydev);
+	mutex_unlock(&priv->shared_lock);
+
+	return ret;
+}
+
+/**
+ * yt8824_config_aneg() - config negotiation
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_config_aneg(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int phy_ctrl = 0;
+	int ret;
+
+	mutex_lock(&priv->shared_lock);
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		goto err;
+
+	if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
+			      phydev->advertising))
+		phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G;
+
+	ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
+				     MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl);
+	if (ret < 0)
+		goto err;
+
+	ret = __genphy_config_aneg(phydev, ret);
+
+err:
+	mutex_unlock(&priv->shared_lock);
+	return ret;
+}
+
+/**
+ * yt8824_phy_package_probe_once()  - init phy package for phy8824.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_phy_package_probe_once(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	struct device_node *np = phy_package_get_node(phydev);
+	int res;
+
+	if (!priv || !np) {
+		phydev_err(phydev, "%s: missing shared priv or DT node\n",
+			   __func__);
+		return -EINVAL;
+	}
+	/* Initialise shared lock for YT8824 */
+	mutex_init(&priv->shared_lock);
+	res = of_get_phy_mode(np, &priv->interface_mode);
+	if (res < 0) {
+		phydev_warn(phydev, "%s, phy-mode missing in DTS.\n", __func__);
+		priv->interface_mode = PHY_INTERFACE_MODE_INTERNAL;
+	}
+
+	return 0;
+}
+
+/**
+ * yt8824_probe() - phy8824 probe.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_probe(struct phy_device *phydev)
+{
+	struct device *dev = &phydev->mdio.dev;
+	struct yt8824_shared_priv *shared_priv;
+	int ret;
+
+	ret = devm_of_phy_package_join(dev, phydev, sizeof(*shared_priv));
+	if (ret)
+		return ret;
+
+	if (phy_package_probe_once(phydev)) {
+		ret = yt8824_phy_package_probe_once(phydev);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static struct phy_driver motorcomm_phy_drvs[] = {
 	{
 		PHY_ID_MATCH_EXACT(PHY_ID_YT8511),
@@ -3190,13 +4740,29 @@ static struct phy_driver motorcomm_phy_drvs[] = {
 		.suspend		= yt8821_suspend,
 		.resume			= yt8821_resume,
 	},
+	{
+		PHY_ID_MATCH_EXACT(PHY_ID_YT8824),
+		.name = "YT8824 Quad Ports 2.5Gbps Ethernet",
+		.get_features = yt8824_get_features,
+		.read_page = yt8824_read_page,
+		.write_page = yt8824_write_page,
+		.probe = yt8824_probe,
+		.config_aneg = yt8824_config_aneg,
+		.aneg_done = yt8824_aneg_done,
+		.config_init = yt8824_config_init,
+		.read_status = yt8824_read_status,
+		.soft_reset = yt8824_soft_reset,
+		.suspend = yt8824_suspend,
+		.resume = yt8824_resume,
+	},
 };
 
 module_phy_driver(motorcomm_phy_drvs);
 
-MODULE_DESCRIPTION("Motorcomm 8511/8521/8531/8531S/8821 PHY driver");
+MODULE_DESCRIPTION("Motorcomm 8511/8521/8531/8531S/8821/8824 PHY driver");
 MODULE_AUTHOR("Peter Geis");
 MODULE_AUTHOR("Frank");
+MODULE_AUTHOR("Kyle");
 MODULE_LICENSE("GPL");
 
 static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = {
@@ -3206,6 +4772,7 @@ static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = {
 	{ PHY_ID_MATCH_EXACT(PHY_ID_YT8531) },
 	{ PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) },
 	{ PHY_ID_MATCH_EXACT(PHY_ID_YT8821) },
+	{ PHY_ID_MATCH_EXACT(PHY_ID_YT8824) },
 	{ /* sentinel */ }
 };
 
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index 870920311f9a0..f8e03d3afa457 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -1408,6 +1408,30 @@ int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable)
 }
 EXPORT_SYMBOL_GPL(genphy_c45_fast_retrain);
 
+/**
+ * genphy_c45_template_testmode - configure template testmode registers
+ * @phydev: target phy_device struct
+ * @test_mode: testmode includes Normal to Test mode 7
+ *
+ * Description: Set template testmode include Normal to Test mode 7
+ *
+ * Return: 0 on success, or a negative error code on failure (e.g. register
+ * read/write error).
+ */
+int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode)
+{
+	int ctrl;
+
+	if (test_mode < MDIO_PMA_10GBT_TESTMODE_NORMAL ||
+	    test_mode > MDIO_PMA_10GBT_TESTMODE_7)
+		return -EOPNOTSUPP;
+
+	ctrl = FIELD_PREP(MDIO_PMA_10GBT_TESTMODE_MASK, test_mode);
+	return phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TESTMODE,
+			      MDIO_PMA_10GBT_TESTMODE_MASK, ctrl);
+}
+EXPORT_SYMBOL_GPL(genphy_c45_template_testmode);
+
 /**
  * genphy_c45_plca_get_cfg - get PLCA configuration from standard registers
  * @phydev: target phy_device struct
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 3d8afe6b7f1c5..fb827cc3c98f4 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -2357,6 +2357,7 @@ int genphy_c45_loopback(struct phy_device *phydev, bool enable, int speed);
 int genphy_c45_pma_resume(struct phy_device *phydev);
 int genphy_c45_pma_suspend(struct phy_device *phydev);
 int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable);
+int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode);
 int genphy_c45_plca_get_cfg(struct phy_device *phydev,
 			    struct phy_plca_cfg *plca_cfg);
 int genphy_c45_plca_set_cfg(struct phy_device *phydev,
diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h
index 06f4bc3c20c71..353ca13c64fca 100644
--- a/include/uapi/linux/mdio.h
+++ b/include/uapi/linux/mdio.h
@@ -63,6 +63,7 @@
 /* Media-dependent registers. */
 #define MDIO_PMA_10GBT_SWAPPOL	130	/* 10GBASE-T pair swap & polarity */
 #define MDIO_PMA_10GBT_TXPWR	131	/* 10GBASE-T TX power control */
+#define MDIO_PMA_10GBT_TESTMODE 132 /* Test mode control */
 #define MDIO_PMA_10GBT_SNR	133	/* 10GBASE-T SNR margin, lane A.
 					 * Lanes B-D are numbered 134-136. */
 #define MDIO_PMA_10GBR_FSRT_CSR	147	/* 10GBASE-R fast retrain status and control */
@@ -320,6 +321,17 @@
 /* PMA 10GBASE-R Fast Retrain status and control register. */
 #define MDIO_PMA_10GBR_FSRT_ENABLE	0x0001	/* Fast retrain enable */
 
+/* PMA 10GBASE-T Template Test Mode Register*/
+#define MDIO_PMA_10GBT_TESTMODE_MASK GENMASK(15, 13) /* Template test mode */
+#define MDIO_PMA_10GBT_TESTMODE_NORMAL 0x0 /* Template Normal */
+#define MDIO_PMA_10GBT_TESTMODE_1 0x1 /* Template TestMode1 */
+#define MDIO_PMA_10GBT_TESTMODE_2 0x2 /* Template TestMode2 */
+#define MDIO_PMA_10GBT_TESTMODE_3 0x3 /* Template TestMode3 */
+#define MDIO_PMA_10GBT_TESTMODE_4 0x4 /* Template TestMode4 */
+#define MDIO_PMA_10GBT_TESTMODE_5 0x5 /* Template TestMode5 */
+#define MDIO_PMA_10GBT_TESTMODE_6 0x6 /* Template TestMode6 */
+#define MDIO_PMA_10GBT_TESTMODE_7 0x7 /* Template TestMode7 */
+
 /* PCS 10GBASE-R/-T status register 1. */
 #define MDIO_PCS_10GBRT_STAT1_BLKLK	0x0001	/* Block lock attained */
 

3/2 2026/09/15 10:59 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 25927
							output: 19
							thoughts: 951
						

Thoughts:
**Fuzzing Feasibility Analysis: Motorcomm YT8824 PHY Driver**

Alright, let's break down this patch and see if it's a good candidate for fuzzing. First, I need to understand what it *does*. It looks like we have:

1.  **Devicetree bindings:** A new binding definition for the `motorcomm,yt8824` device. Okay, standard stuff for device discovery.
2.  **Kconfig update:**  Enabling support for the YT8824 PHY within the `PHY_PACKAGE` framework. This suggests a modular design, which is good.
3.  **Core driver implementation:** The meat of the patch: a new `motorcomm.c` driver with a ton of new functions, including specific read/write operations (paged and unpaged), initialization, configuration, power management, auto-negotiation, and status read functions.  They seem quite low level. There's also a modification to `ytphy_set_wol` with a critical check added, which is good: ensures that a failure in the modification function correctly returns the error.
4.  **phy-c45.c update:** Addition of `genphy_c45_template_testmode`, which suggests some generic test mode functionality, potentially interesting for fault injection.
5.  **Header updates:** Function prototypes and macros added in `phy.h` and `mdio.h`. Standard stuff, necessary for the new driver.

Now, the crucial question: *reachability*. Can we actually *hit* this code in a fuzzing environment?  Specifically, the Motorcomm YT8824 is a PHY, a physical layer device. The description mentions the 8511/8521/8522/8531/8531S/8821/8824 PHY driver. This means it interacts with an Ethernet PHY on a MDIO bus or device tree.  The question is can we instantiate these? Can we emulate this in a virtual environment like Syzkaller or QEMU without needing actual hardware?

I need to dig deeper. How does the kernel probe for these PHY devices?  Are there virtual or mock MDIO bus implementations we could leverage? Can we create an MDIO bus or PHY device via netlink, a virtual bus, or even USB?  The key is to figure out if we can *mock* the existence of this hardware or, failing that, if Syzkaller offers any support for interacting with PHY or MDIO devices. I need to search the kernel source and Syzkaller documentation to determine that.



4/2 2026/09/15 11:00 tool grepper
0m Args:
{
  "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=2105=static int sfp_sm_probe_phy(struct sfp *sfp, int addr, bool is_c45)\n--\ndrivers/net/phy/sfp.c-2120-\ndrivers/net/phy/sfp.c:2121:\terr = phy_device_register(phy);\ndrivers/net/phy/sfp.c-2122-\tif (err) {\ndrivers/net/phy/sfp.c-2123-\t\tphy_device_free(phy);\ndrivers/net/phy/sfp.c:2124:\t\tdev_err(sfp-\u003edev, \"phy_device_register failed: %pe\\n\",\ndrivers/net/phy/sfp.c-2125-\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=2177=struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);\ninclude/linux/phy.h:2178:int phy_device_register(struct phy_device *phy);\ninclude/linux/phy.h-2179-void phy_device_free(struct phy_device *phydev);\n"
}

5/2 2026/09/15 11:00 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 30620
							output: 21
							thoughts: 182
						

Thoughts:
**My Line of Inquiry: PHY Driver Matching and Probing**

Okay, let's break this down. My goal is to understand how a PHY driver, specifically one designed for something like a Motorcomm YT8824, actually gets matched and probed in the kernel. I need to refresh my memory on the fundamental flow. Right, looking at `drivers/net/phy/phy_device.c`, the key functions are `phy_bus_match` and `phy_probe`. Now, for drivers like the `motorcomm_phy_drvs`, my understanding is that the matching process relies on identifying the PHY based on its `phy_id`. Specifically, it uses something like `PHY_ID_MATCH_EXACT(PHY_ID_YT8824)`. That's the driver's unique identifier.

But here's where I need to clarify things. Where exactly does this `phydev` structure originate from? I believe it's either through an MDIO bus scanning process, or potentially from a device tree registration. I need to confirm this.

Now, my real question is regarding the testing environment. Does QEMU, or even the dreaded syzkaller, provide a realistic scenario with an MDIO bus or, more specifically, an actual Motorcomm YT8824 PHY chip that I can interact with? It's a long shot, but maybe... Wait a minute... Could USB net or USB Ethernet adapters potentially expose or utilize MDIO buses? I need to investigate. It's a long shot, but I need to investigate any potential USB devices that might utilize phylib or an MDIO bus. I should look into those drivers.



6/2 2026/09/15 11:00 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "mdiobus_register.*usb"
}

Results:
{
  "error": "no matches"
}

7/2 2026/09/15 11:00 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 31188
							output: 32
							thoughts: 10
						

Thoughts:
Okay, here's my attempt at summarizing the thought process, as if I were a seasoned professional in the field, speaking directly to another expert:

**Investigating the USB Network Driver Landscape**

Alright, time to dig into the drivers/net/usb area. Specifically, I'm thinking about the network aspect that utilizes USB connections. My initial focus is to pinpoint any potential trouble spots or areas ripe for optimization within this specific part of the codebase. I need to get a high-level overview of the implementation, making sure it aligns with the expected behavior of network data exchange and data transfer. Any irregularities here? Compatibility issues? Let’s see what we can find. I want to check for efficient resource management, potential bottlenecks, or race conditions. Knowing the architecture of network data management inside a USB connection is my priority. Let's start the evaluation now.



8/2 2026/09/15 11:00 tool grepper
0m Args:
{
  "Expression": "phy_device|mdiobus",
  "PathPrefix": "drivers/net/usb"
}

Results:
{
  "Output": "drivers/net/usb/asix.h=178=struct asix_common_private {\n--\ndrivers/net/usb/asix.h-185-\tstruct mii_bus *mdio;\ndrivers/net/usb/asix.h:186:\tstruct phy_device *phydev;\ndrivers/net/usb/asix.h:187:\tstruct phy_device *phydev_int;\ndrivers/net/usb/asix.h-188-\tstruct phylink *phylink;\n--\ndrivers/net/usb/asix_devices.c=669=static int ax88772_init_mdio(struct usbnet *dev)\n--\ndrivers/net/usb/asix_devices.c-673-\ndrivers/net/usb/asix_devices.c:674:\tpriv-\u003emdio = mdiobus_alloc();\ndrivers/net/usb/asix_devices.c-675-\tif (!priv-\u003emdio)\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) {\ndrivers/net/usb/asix_devices.c-689-\t\tnetdev_err(dev-\u003enet, \"Could not register MDIO bus (err %d)\\n\", ret);\ndrivers/net/usb/asix_devices.c:690:\t\tmdiobus_free(priv-\u003emdio);\ndrivers/net/usb/asix_devices.c-691-\t\tpriv-\u003emdio = NULL;\n--\ndrivers/net/usb/asix_devices.c=697=static void ax88772_mdio_unregister(struct asix_common_private *priv)\ndrivers/net/usb/asix_devices.c-698-{\ndrivers/net/usb/asix_devices.c:699:\tmdiobus_unregister(priv-\u003emdio);\ndrivers/net/usb/asix_devices.c:700:\tmdiobus_free(priv-\u003emdio);\ndrivers/net/usb/asix_devices.c-701-}\n--\ndrivers/net/usb/asix_devices.c=703=static int ax88772_init_phy(struct usbnet *dev)\n--\ndrivers/net/usb/asix_devices.c-707-\ndrivers/net/usb/asix_devices.c:708:\tpriv-\u003ephydev = mdiobus_get_phy(priv-\u003emdio, priv-\u003ephy_addr);\ndrivers/net/usb/asix_devices.c-709-\tif (!priv-\u003ephydev) {\n--\ndrivers/net/usb/asix_devices.c-731-\t */\ndrivers/net/usb/asix_devices.c:732:\tpriv-\u003ephydev_int = mdiobus_get_phy(priv-\u003emdio, AX_EMBD_PHY_ADDR);\ndrivers/net/usb/asix_devices.c-733-\tif (!priv-\u003ephydev_int) {\n--\ndrivers/net/usb/asix_devices.c=762=static void ax88772_mac_link_up(struct phylink_config *config,\ndrivers/net/usb/asix_devices.c:763:\t\t\t       struct phy_device *phy,\ndrivers/net/usb/asix_devices.c-764-\t\t\t       unsigned int mode, phy_interface_t interface,\n--\ndrivers/net/usb/ax88172a.c=18=struct ax88172a_private {\ndrivers/net/usb/ax88172a.c-19-\tstruct mii_bus *mdio;\ndrivers/net/usb/ax88172a.c:20:\tstruct phy_device *phydev;\ndrivers/net/usb/ax88172a.c-21-\tchar phy_name[PHY_ID_SIZE];\n--\ndrivers/net/usb/ax88172a.c=29=static void ax88172a_adjust_link(struct net_device *netdev)\ndrivers/net/usb/ax88172a.c-30-{\ndrivers/net/usb/ax88172a.c:31:\tstruct phy_device *phydev = netdev-\u003ephydev;\ndrivers/net/usb/ax88172a.c-32-\tstruct usbnet *dev = netdev_priv(netdev);\n--\ndrivers/net/usb/ax88172a.c=61=static int ax88172a_init_mdio(struct usbnet *dev)\n--\ndrivers/net/usb/ax88172a.c-65-\ndrivers/net/usb/ax88172a.c:66:\tpriv-\u003emdio = mdiobus_alloc();\ndrivers/net/usb/ax88172a.c-67-\tif (!priv-\u003emdio) {\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/ax88172a.c-89-mfree:\ndrivers/net/usb/ax88172a.c:90:\tmdiobus_free(priv-\u003emdio);\ndrivers/net/usb/ax88172a.c-91-\treturn ret;\n--\ndrivers/net/usb/ax88172a.c=94=static void ax88172a_remove_mdio(struct usbnet *dev)\n--\ndrivers/net/usb/ax88172a.c-98-\tnetdev_info(dev-\u003enet, \"deregistering mdio bus %s\\n\", priv-\u003emdio-\u003eid);\ndrivers/net/usb/ax88172a.c:99:\tmdiobus_unregister(priv-\u003emdio);\ndrivers/net/usb/ax88172a.c:100:\tmdiobus_free(priv-\u003emdio);\ndrivers/net/usb/ax88172a.c-101-}\n--\ndrivers/net/usb/lan78xx.c=413=struct lan78xx_net {\n--\ndrivers/net/usb/lan78xx.c-441-\tstruct mutex\t\tdev_mutex; /* serialise open/stop wrt suspend/resume */\ndrivers/net/usb/lan78xx.c:442:\tstruct mutex\t\tmdiobus_mutex; /* for MDIO bus access */\ndrivers/net/usb/lan78xx.c-443-\tunsigned int\t\tpipe_in, pipe_out, pipe_intr;\n--\ndrivers/net/usb/lan78xx.c-458-\tu32\t\t\tchiprev;\ndrivers/net/usb/lan78xx.c:459:\tstruct mii_bus\t\t*mdiobus;\ndrivers/net/usb/lan78xx.c-460-\tphy_interface_t\t\tinterface;\n--\ndrivers/net/usb/lan78xx.c=946=static int lan78xx_flush_rx_fifo(struct lan78xx_net *dev)\n--\ndrivers/net/usb/lan78xx.c-950-\ndrivers/net/usb/lan78xx.c:951:/* Loop until the read is completed with timeout called with mdiobus_mutex held */\ndrivers/net/usb/lan78xx.c:952:static int lan78xx_mdiobus_wait_not_busy(struct lan78xx_net *dev)\ndrivers/net/usb/lan78xx.c-953-{\n--\ndrivers/net/usb/lan78xx.c=1582=static int lan78xx_mac_reset(struct lan78xx_net *dev)\n--\ndrivers/net/usb/lan78xx.c-1587-\ndrivers/net/usb/lan78xx.c:1588:\tmutex_lock(\u0026dev-\u003emdiobus_mutex);\ndrivers/net/usb/lan78xx.c-1589-\n--\ndrivers/net/usb/lan78xx.c-1593-\t */\ndrivers/net/usb/lan78xx.c:1594:\tret = lan78xx_mdiobus_wait_not_busy(dev);\ndrivers/net/usb/lan78xx.c-1595-\tif (ret \u003c 0)\n--\ndrivers/net/usb/lan78xx.c-1622-exit_unlock:\ndrivers/net/usb/lan78xx.c:1623:\tmutex_unlock(\u0026dev-\u003emdiobus_mutex);\ndrivers/net/usb/lan78xx.c-1624-\n--\ndrivers/net/usb/lan78xx.c=1944=static int lan78xx_init_mac_address(struct lan78xx_net *dev)\n--\ndrivers/net/usb/lan78xx.c-2011-/* MDIO read and write wrappers for phylib */\ndrivers/net/usb/lan78xx.c:2012:static int lan78xx_mdiobus_read(struct mii_bus *bus, int phy_id, int idx)\ndrivers/net/usb/lan78xx.c-2013-{\n--\ndrivers/net/usb/lan78xx.c-2021-\ndrivers/net/usb/lan78xx.c:2022:\tmutex_lock(\u0026dev-\u003emdiobus_mutex);\ndrivers/net/usb/lan78xx.c-2023-\ndrivers/net/usb/lan78xx.c-2024-\t/* confirm MII not busy */\ndrivers/net/usb/lan78xx.c:2025:\tret = lan78xx_mdiobus_wait_not_busy(dev);\ndrivers/net/usb/lan78xx.c-2026-\tif (ret \u003c 0)\n--\ndrivers/net/usb/lan78xx.c-2034-\ndrivers/net/usb/lan78xx.c:2035:\tret = lan78xx_mdiobus_wait_not_busy(dev);\ndrivers/net/usb/lan78xx.c-2036-\tif (ret \u003c 0)\n--\ndrivers/net/usb/lan78xx.c-2045-done:\ndrivers/net/usb/lan78xx.c:2046:\tmutex_unlock(\u0026dev-\u003emdiobus_mutex);\ndrivers/net/usb/lan78xx.c-2047-\tusb_autopm_put_interface(dev-\u003eintf);\n--\ndrivers/net/usb/lan78xx.c-2051-\ndrivers/net/usb/lan78xx.c:2052:static int lan78xx_mdiobus_write(struct mii_bus *bus, int phy_id, int idx,\ndrivers/net/usb/lan78xx.c-2053-\t\t\t\t u16 regval)\n--\ndrivers/net/usb/lan78xx.c-2062-\ndrivers/net/usb/lan78xx.c:2063:\tmutex_lock(\u0026dev-\u003emdiobus_mutex);\ndrivers/net/usb/lan78xx.c-2064-\ndrivers/net/usb/lan78xx.c-2065-\t/* confirm MII not busy */\ndrivers/net/usb/lan78xx.c:2066:\tret = lan78xx_mdiobus_wait_not_busy(dev);\ndrivers/net/usb/lan78xx.c-2067-\tif (ret \u003c 0)\n--\ndrivers/net/usb/lan78xx.c-2080-\ndrivers/net/usb/lan78xx.c:2081:\tret = lan78xx_mdiobus_wait_not_busy(dev);\ndrivers/net/usb/lan78xx.c-2082-\tif (ret \u003c 0)\n--\ndrivers/net/usb/lan78xx.c-2085-done:\ndrivers/net/usb/lan78xx.c:2086:\tmutex_unlock(\u0026dev-\u003emdiobus_mutex);\ndrivers/net/usb/lan78xx.c-2087-\tusb_autopm_put_interface(dev-\u003eintf);\n--\ndrivers/net/usb/lan78xx.c=2091=static int lan78xx_mdio_init(struct lan78xx_net *dev)\n--\ndrivers/net/usb/lan78xx.c-2095-\ndrivers/net/usb/lan78xx.c:2096:\tdev-\u003emdiobus = mdiobus_alloc();\ndrivers/net/usb/lan78xx.c:2097:\tif (!dev-\u003emdiobus) {\ndrivers/net/usb/lan78xx.c-2098-\t\tnetdev_err(dev-\u003enet, \"can't allocate MDIO bus\\n\");\n--\ndrivers/net/usb/lan78xx.c-2101-\ndrivers/net/usb/lan78xx.c:2102:\tdev-\u003emdiobus-\u003epriv = (void *)dev;\ndrivers/net/usb/lan78xx.c:2103:\tdev-\u003emdiobus-\u003eread = lan78xx_mdiobus_read;\ndrivers/net/usb/lan78xx.c:2104:\tdev-\u003emdiobus-\u003ewrite = lan78xx_mdiobus_write;\ndrivers/net/usb/lan78xx.c:2105:\tdev-\u003emdiobus-\u003ename = \"lan78xx-mdiobus\";\ndrivers/net/usb/lan78xx.c:2106:\tdev-\u003emdiobus-\u003eparent = \u0026dev-\u003eudev-\u003edev;\ndrivers/net/usb/lan78xx.c-2107-\ndrivers/net/usb/lan78xx.c:2108:\tsnprintf(dev-\u003emdiobus-\u003eid, MII_BUS_ID_SIZE, \"usb-%03d:%03d\",\ndrivers/net/usb/lan78xx.c-2109-\t\t dev-\u003eudev-\u003ebus-\u003ebusnum, dev-\u003eudev-\u003edevnum);\n--\ndrivers/net/usb/lan78xx.c-2114-\t\t/* set to internal PHY id */\ndrivers/net/usb/lan78xx.c:2115:\t\tdev-\u003emdiobus-\u003ephy_mask = ~(1 \u003c\u003c 1);\ndrivers/net/usb/lan78xx.c-2116-\t\tbreak;\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/lan78xx.c-2128-\ndrivers/net/usb/lan78xx.c:2129:\tnetdev_dbg(dev-\u003enet, \"registered mdiobus bus %s\\n\", dev-\u003emdiobus-\u003eid);\ndrivers/net/usb/lan78xx.c-2130-\treturn 0;\ndrivers/net/usb/lan78xx.c-2131-exit1:\ndrivers/net/usb/lan78xx.c:2132:\tmdiobus_free(dev-\u003emdiobus);\ndrivers/net/usb/lan78xx.c-2133-\treturn ret;\n--\ndrivers/net/usb/lan78xx.c=2136=static void lan78xx_remove_mdio(struct lan78xx_net *dev)\ndrivers/net/usb/lan78xx.c-2137-{\ndrivers/net/usb/lan78xx.c:2138:\tmdiobus_unregister(dev-\u003emdiobus);\ndrivers/net/usb/lan78xx.c:2139:\tmdiobus_free(dev-\u003emdiobus);\ndrivers/net/usb/lan78xx.c-2140-}\n--\ndrivers/net/usb/lan78xx.c=2477=static void lan78xx_mac_link_up(struct phylink_config *config,\ndrivers/net/usb/lan78xx.c:2478:\t\t\t\tstruct phy_device *phy,\ndrivers/net/usb/lan78xx.c-2479-\t\t\t\tunsigned int mode, phy_interface_t interface,\n--\ndrivers/net/usb/lan78xx.c=2626=static int lan78xx_set_fixed_link(struct lan78xx_net *dev)\n--\ndrivers/net/usb/lan78xx.c-2648- */\ndrivers/net/usb/lan78xx.c:2649:static struct phy_device *lan78xx_get_phy(struct lan78xx_net *dev)\ndrivers/net/usb/lan78xx.c-2650-{\ndrivers/net/usb/lan78xx.c:2651:\tstruct phy_device *phydev;\ndrivers/net/usb/lan78xx.c-2652-\ndrivers/net/usb/lan78xx.c-2653-\t/* Attempt to locate a PHY on the MDIO bus */\ndrivers/net/usb/lan78xx.c:2654:\tphydev = phy_find_first(dev-\u003emdiobus);\ndrivers/net/usb/lan78xx.c-2655-\n--\ndrivers/net/usb/lan78xx.c=2769=static int lan78xx_configure_leds_from_dt(struct lan78xx_net *dev,\ndrivers/net/usb/lan78xx.c:2770:\t\t\t\t\t  struct phy_device *phydev)\ndrivers/net/usb/lan78xx.c-2771-{\n--\ndrivers/net/usb/lan78xx.c=2858=static int lan78xx_phy_init(struct lan78xx_net *dev)\ndrivers/net/usb/lan78xx.c-2859-{\ndrivers/net/usb/lan78xx.c:2860:\tstruct phy_device *phydev;\ndrivers/net/usb/lan78xx.c-2861-\tint ret;\n--\ndrivers/net/usb/lan78xx.c-2904-\t\tnetdev_err(dev-\u003enet, \"can't attach PHY to %s, error %pe\\n\",\ndrivers/net/usb/lan78xx.c:2905:\t\t\t   dev-\u003emdiobus-\u003eid, ERR_PTR(ret));\ndrivers/net/usb/lan78xx.c-2906-\t\tgoto phylink_uninit;\n--\ndrivers/net/usb/lan78xx.c=4655=static int lan78xx_probe(struct usb_interface *intf,\n--\ndrivers/net/usb/lan78xx.c-4688-\tskb_queue_head_init(\u0026dev-\u003erxq_overflow);\ndrivers/net/usb/lan78xx.c:4689:\tmutex_init(\u0026dev-\u003emdiobus_mutex);\ndrivers/net/usb/lan78xx.c-4690-\tmutex_init(\u0026dev-\u003edev_mutex);\n--\ndrivers/net/usb/smsc95xx.c=60=struct smsc95xx_priv {\n--\ndrivers/net/usb/smsc95xx.c-74-\tstruct fwnode_handle *irqfwnode;\ndrivers/net/usb/smsc95xx.c:75:\tstruct mii_bus *mdiobus;\ndrivers/net/usb/smsc95xx.c:76:\tstruct phy_device *phydev;\ndrivers/net/usb/smsc95xx.c-77-\tstruct task_struct *pm_task;\n--\ndrivers/net/usb/smsc95xx.c=218=static void smsc95xx_mdio_write(struct usbnet *dev, int phy_id, int idx,\n--\ndrivers/net/usb/smsc95xx.c-259-\ndrivers/net/usb/smsc95xx.c:260:static int smsc95xx_mdiobus_reset(struct mii_bus *bus)\ndrivers/net/usb/smsc95xx.c-261-{\n--\ndrivers/net/usb/smsc95xx.c-296-\ndrivers/net/usb/smsc95xx.c:297:static int smsc95xx_mdiobus_read(struct mii_bus *bus, int phy_id, int idx)\ndrivers/net/usb/smsc95xx.c-298-{\n--\ndrivers/net/usb/smsc95xx.c-303-\ndrivers/net/usb/smsc95xx.c:304:static int smsc95xx_mdiobus_write(struct mii_bus *bus, int phy_id, int idx,\ndrivers/net/usb/smsc95xx.c-305-\t\t\t\t  u16 regval)\n--\ndrivers/net/usb/smsc95xx.c=798=static int smsc95xx_set_pauseparam(struct net_device *ndev,\n--\ndrivers/net/usb/smsc95xx.c-802-\tstruct smsc95xx_priv *pdata;\ndrivers/net/usb/smsc95xx.c:803:\tstruct phy_device *phydev;\ndrivers/net/usb/smsc95xx.c-804-\tstruct usbnet *dev;\n--\ndrivers/net/usb/smsc95xx.c=1147=static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)\n--\ndrivers/net/usb/smsc95xx.c-1217-\ndrivers/net/usb/smsc95xx.c:1218:\tpdata-\u003emdiobus = mdiobus_alloc();\ndrivers/net/usb/smsc95xx.c:1219:\tif (!pdata-\u003emdiobus) {\ndrivers/net/usb/smsc95xx.c-1220-\t\tret = -ENOMEM;\n--\ndrivers/net/usb/smsc95xx.c-1229-\tif (pdata-\u003eis_internal_phy)\ndrivers/net/usb/smsc95xx.c:1230:\t\tpdata-\u003emdiobus-\u003ephy_mask = ~(1u \u003c\u003c SMSC95XX_INTERNAL_PHY_ID);\ndrivers/net/usb/smsc95xx.c-1231-\ndrivers/net/usb/smsc95xx.c:1232:\tpdata-\u003emdiobus-\u003epriv = dev;\ndrivers/net/usb/smsc95xx.c:1233:\tpdata-\u003emdiobus-\u003eread = smsc95xx_mdiobus_read;\ndrivers/net/usb/smsc95xx.c:1234:\tpdata-\u003emdiobus-\u003ewrite = smsc95xx_mdiobus_write;\ndrivers/net/usb/smsc95xx.c:1235:\tpdata-\u003emdiobus-\u003ereset = smsc95xx_mdiobus_reset;\ndrivers/net/usb/smsc95xx.c:1236:\tpdata-\u003emdiobus-\u003ename = \"smsc95xx-mdiobus\";\ndrivers/net/usb/smsc95xx.c:1237:\tpdata-\u003emdiobus-\u003eparent = \u0026dev-\u003eudev-\u003edev;\ndrivers/net/usb/smsc95xx.c-1238-\ndrivers/net/usb/smsc95xx.c:1239:\tsnprintf(pdata-\u003emdiobus-\u003eid, ARRAY_SIZE(pdata-\u003emdiobus-\u003eid),\ndrivers/net/usb/smsc95xx.c-1240-\t\t \"usb-%03d:%03d\", dev-\u003eudev-\u003ebus-\u003ebusnum, dev-\u003eudev-\u003edevnum);\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--\ndrivers/net/usb/smsc95xx.c-1247-\ndrivers/net/usb/smsc95xx.c:1248:\tpdata-\u003ephydev = phy_find_first(pdata-\u003emdiobus);\ndrivers/net/usb/smsc95xx.c-1249-\tif (!pdata-\u003ephydev) {\n--\ndrivers/net/usb/smsc95xx.c-1288-\tif (ret) {\ndrivers/net/usb/smsc95xx.c:1289:\t\tnetdev_err(dev-\u003enet, \"can't attach PHY to %s\\n\", pdata-\u003emdiobus-\u003eid);\ndrivers/net/usb/smsc95xx.c-1290-\t\tgoto unregister_mdio;\n--\ndrivers/net/usb/smsc95xx.c-1297-unregister_mdio:\ndrivers/net/usb/smsc95xx.c:1298:\tmdiobus_unregister(pdata-\u003emdiobus);\ndrivers/net/usb/smsc95xx.c-1299-\ndrivers/net/usb/smsc95xx.c-1300-free_mdio:\ndrivers/net/usb/smsc95xx.c:1301:\tmdiobus_free(pdata-\u003emdiobus);\ndrivers/net/usb/smsc95xx.c-1302-\n--\ndrivers/net/usb/smsc95xx.c=1317=static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)\n--\ndrivers/net/usb/smsc95xx.c-1321-\tphy_disconnect(dev-\u003enet-\u003ephydev);\ndrivers/net/usb/smsc95xx.c:1322:\tmdiobus_unregister(pdata-\u003emdiobus);\ndrivers/net/usb/smsc95xx.c:1323:\tmdiobus_free(pdata-\u003emdiobus);\ndrivers/net/usb/smsc95xx.c-1324-\tirq_dispose_mapping(irq_find_mapping(pdata-\u003eirqdomain, PHY_HWIRQ));\n"
}

9/2 2026/09/15 11:00 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 38268
							output: 24
							thoughts: 415
						

Thoughts:
**My Line of Inquiry: USB Gadget Emulation and PHY Identification**

Okay, hold on a second! I need to re-evaluate something regarding USB gadget emulation. Specifically, I need to know if the `raw_gadget` driver can effectively emulate a USB-to-Ethernet adapter like an ASIX AX88172A, SMSC95xx, or even an ASIX-based device like the LAN78xx.

If so, I'm thinking about the implications. If I'm successfully emulating one of these via `raw_gadget` and using the `dummy_hcd`, what happens when the MDIO bus comes into play? Right, the device registers an MDIO bus with `mdiobus_register(priv->mdio)`.

I have to dive deeper into `mdiobus_register`, especially the `mdiobus_scan` function. As I recall, this is where the system tries to determine what's on the MDIO bus by reading `MII_PHYSID1` and `MII_PHYSID2` using the `bus->read()` function. This gets me thinking...

Now, here's where things get interesting. What if the emulated USB device *responds* with arbitrary values during the `mdiobus_scan`? Let's say, it returns a PHY ID, like the one for a YT8824, which is `PHY_ID_YT8824` (0x4f51e8b8). Is that possible? It should be!

Wait a minute, let me pull up the code for `yt8824_probe`!

```c
static int yt8824_probe(struct phy_device *phydev)
{
	struct device *dev = &phydev->mdio.dev;
	struct yt8824_shared_priv *shared_priv;
	int ret;

	ret = devm_of_phy_package_join(dev, phydev, sizeof(*shared_priv));
	if (ret)
		return ret;

	if (phy_package_probe_once(phydev)) {
		ret = yt8824_phy_package_probe_once(phydev);
		if (ret)
			return ret;
	}

	return 0;
}
```

Okay, the `yt8824_probe` function is particularly interesting. Specifically, that line `devm_of_phy_package_join(dev, phydev, sizeof(*shared_priv));`. This is crucial. I need to understand exactly what `devm_of_phy_package_join` is doing. This seems to be the key step in handling the PHY association. From here I need to look at what `devm_of_phy_package_join` does and how it handles the PHY ID, and then how that impacts the entire emulated device.



10/2 2026/09/15 11:00 tool grepper
0m Args:
{
  "Expression": "devm_of_phy_package_join"
}

Results:
{
  "Output": "drivers/net/phy/motorcomm.c=4638=static int yt8824_probe(struct phy_device *phydev)\n--\ndrivers/net/phy/motorcomm.c-4643-\ndrivers/net/phy/motorcomm.c:4644:\tret = devm_of_phy_package_join(dev, phydev, sizeof(*shared_priv));\ndrivers/net/phy/motorcomm.c-4645-\tif (ret)\n--\ndrivers/net/phy/phy_package.c=405=EXPORT_SYMBOL_GPL(devm_phy_package_join);\n--\ndrivers/net/phy/phy_package.c-407-/**\ndrivers/net/phy/phy_package.c:408: * devm_of_phy_package_join - resource managed of_phy_package_join()\ndrivers/net/phy/phy_package.c-409- * @dev: device that is registering this PHY package\n--\ndrivers/net/phy/phy_package.c-416- */\ndrivers/net/phy/phy_package.c:417:int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev,\ndrivers/net/phy/phy_package.c-418-\t\t\t     size_t priv_size)\n--\ndrivers/net/phy/phy_package.c-438-}\ndrivers/net/phy/phy_package.c:439:EXPORT_SYMBOL_GPL(devm_of_phy_package_join);\ndrivers/net/phy/phy_package.c-440-\n--\ndrivers/net/phy/phylib.h=32=int devm_phy_package_join(struct device *dev, struct phy_device *phydev,\ndrivers/net/phy/phylib.h-33-\t\t\t  int base_addr, size_t priv_size);\ndrivers/net/phy/phylib.h:34:int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev,\ndrivers/net/phy/phylib.h-35-\t\t\t     size_t priv_size);\n--\ndrivers/net/phy/qcom/qca807x.c=694=static int qca807x_probe(struct phy_device *phydev)\n--\ndrivers/net/phy/qcom/qca807x.c-701-\ndrivers/net/phy/qcom/qca807x.c:702:\tret = devm_of_phy_package_join(dev, phydev, sizeof(*shared_priv));\ndrivers/net/phy/qcom/qca807x.c-703-\tif (ret)\n--\ndrivers/net/phy/xpowers/acx00.c=195=static int acx00_ephy_init_package(struct phy_device *phydev,\n--\ndrivers/net/phy/xpowers/acx00.c-235-\ndrivers/net/phy/xpowers/acx00.c:236:\tret = devm_of_phy_package_join(dev, phydev, 0);\ndrivers/net/phy/xpowers/acx00.c-237-\tif (ret)\n"
}

11/2 2026/09/15 11:00 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 40173
							output: 39
							thoughts: 36
						

Thoughts:
Here's my summary, as if I were thinking these thoughts:

**Analyzing `devm_of_phy_package_join`**

Okay, time to dig into this. I'm going to grab that `devm_of_phy_package_join` function from `drivers/net/phy/phy_package.c` using the read-file command. This is probably a good starting point for understanding how the device-managed PHY package joining process works. I want to see how the driver handles associating PHYs with the relevant devices, especially in the context of device tree configurations. This function likely manages resource allocation and dependencies when PHY packages are integrated. Let's see what's in there.



12/2 2026/09/15 11:00 tool read-file
0m Args:
{
  "File": "drivers/net/phy/phy_package.c",
  "FirstLine": 405,
  "LineCount": 40
}

Results:
{
  "Contents": " 405:\tEXPORT_SYMBOL_GPL(devm_phy_package_join);\n 406:\t\n 407:\t/**\n 408:\t * devm_of_phy_package_join - resource managed of_phy_package_join()\n 409:\t * @dev: device that is registering this PHY package\n 410:\t * @phydev: target phy_device struct\n 411:\t * @priv_size: if non-zero allocate this amount of bytes for private data\n 412:\t *\n 413:\t * Managed of_phy_package_join(). Shared storage fetched by this function,\n 414:\t * phy_package_leave() is automatically called on driver detach. See\n 415:\t * of_phy_package_join() for more information.\n 416:\t */\n 417:\tint devm_of_phy_package_join(struct device *dev, struct phy_device *phydev,\n 418:\t\t\t\t     size_t priv_size)\n 419:\t{\n 420:\t\tstruct phy_device **ptr;\n 421:\t\tint ret;\n 422:\t\n 423:\t\tptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr),\n 424:\t\t\t\t   GFP_KERNEL);\n 425:\t\tif (!ptr)\n 426:\t\t\treturn -ENOMEM;\n 427:\t\n 428:\t\tret = of_phy_package_join(phydev, priv_size);\n 429:\t\n 430:\t\tif (!ret) {\n 431:\t\t\t*ptr = phydev;\n 432:\t\t\tdevres_add(dev, ptr);\n 433:\t\t} else {\n 434:\t\t\tdevres_free(ptr);\n 435:\t\t}\n 436:\t\n 437:\t\treturn ret;\n 438:\t}\n 439:\tEXPORT_SYMBOL_GPL(devm_of_phy_package_join);\n 440:\t\n 441:\tMODULE_DESCRIPTION(\"PHY package support\");\n 442:\tMODULE_LICENSE(\"GPL\");\n"
}

13/2 2026/09/15 11:00 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 40966
							output: 33
							thoughts: 16
						

Thoughts:
Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person:

**Analyzing the `of_phy_package_join` Function**

Alright, let's dive in. My immediate thought is, "Okay, `of_phy_package_join`, what's *that* about?" I need to understand its role in this system. I'm already anticipating that it probably relates to some fundamental aspect of the PHY layer, perhaps dealing with the aggregation, deaggregation, or coordination of physical layer data units. Given the name, "join" is a strong indicator that this will involve some form of assembly or combining of elements. Is it related to burst assembly, frame concatenation, perhaps some higher-level multiplexing scheme? The `of` prefix suggests it's a part of OpenFlow, so I should be looking at how this fits within the OpenFlow protocol's abstraction of the PHY layer. I need to quickly recall my understanding of the relevant OpenFlow specifications and how PHY interactions are typically handled in this environment. What are the dependencies? Where does this function get called? And, critically, what are the upstream and downstream data flows this function impacts? Right, I need to look into it to understand its behaviour!



14/2 2026/09/15 11:01 tool grepper
0m Args:
{
  "Expression": "int of_phy_package_join",
  "PathPrefix": "drivers/net/phy"
}

Results:
{
  "Output": "drivers/net/phy/phy_package.c=276=EXPORT_SYMBOL_GPL(phy_package_join);\n--\ndrivers/net/phy/phy_package.c-297- */\ndrivers/net/phy/phy_package.c:298:int of_phy_package_join(struct phy_device *phydev, size_t priv_size)\ndrivers/net/phy/phy_package.c-299-{\n--\ndrivers/net/phy/phylib.h=29=int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size);\ndrivers/net/phy/phylib.h:30:int of_phy_package_join(struct phy_device *phydev, size_t priv_size);\ndrivers/net/phy/phylib.h-31-void phy_package_leave(struct phy_device *phydev);\n"
}

15/2 2026/09/15 11:01 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 41513
							output: 39
							thoughts: 33
						

Thoughts:
Here's my summary, as though I'm thinking through this process:

**Diving into the PHY Package Join Function**

Okay, let's get down to brass tacks. I'm going to pull up `drivers/net/phy/phy_package.c` and zero in on that `of_phy_package_join` function around line 298. I need to understand exactly how the system is handling the integration of these PHY packages, particularly with the device tree integration. I'm expecting this function to be the core of bringing these PHYs into the system after they've been described by the device tree. I'm looking for the registration, binding, or initialization logic. This likely handles the interplay between the PHY driver itself and the device tree information. I'm curious if it's responsible for resource allocation, IRQ setup, or probing the PHY's capabilities based on what's declared in the device tree node. Time to dig in and see exactly how it works.



16/2 2026/09/15 11:01 tool read-file
0m Args:
{
  "File": "drivers/net/phy/phy_package.c",
  "FirstLine": 295,
  "LineCount": 40
}

Results:
{
  "Contents": " 295:\t * node is not detected or is not valid or doesn't match the expected node\n 296:\t * name for PHY package.\n 297:\t */\n 298:\tint of_phy_package_join(struct phy_device *phydev, size_t priv_size)\n 299:\t{\n 300:\t\tstruct device_node *node = phydev-\u003emdio.dev.of_node;\n 301:\t\tstruct device_node *package_node;\n 302:\t\tu32 base_addr;\n 303:\t\tint ret;\n 304:\t\n 305:\t\tif (!node)\n 306:\t\t\treturn -EINVAL;\n 307:\t\n 308:\t\tpackage_node = of_get_parent(node);\n 309:\t\tif (!package_node)\n 310:\t\t\treturn -EINVAL;\n 311:\t\n 312:\t\tif (!of_node_name_eq(package_node, \"ethernet-phy-package\")) {\n 313:\t\t\tret = -EINVAL;\n 314:\t\t\tgoto exit;\n 315:\t\t}\n 316:\t\n 317:\t\tif (of_property_read_u32(package_node, \"reg\", \u0026base_addr)) {\n 318:\t\t\tret = -EINVAL;\n 319:\t\t\tgoto exit;\n 320:\t\t}\n 321:\t\n 322:\t\tret = phy_package_join(phydev, base_addr, priv_size);\n 323:\t\tif (ret)\n 324:\t\t\tgoto exit;\n 325:\t\n 326:\t\tphydev-\u003eshared-\u003enp = package_node;\n 327:\t\n 328:\t\treturn 0;\n 329:\texit:\n 330:\t\tof_node_put(package_node);\n 331:\t\treturn ret;\n 332:\t}\n 333:\tEXPORT_SYMBOL_GPL(of_phy_package_join);\n 334:\t\n"
}

17/2 2026/09/15 11:01 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 42350
							output: 27
							thoughts: 494
						

Thoughts:
**Analyzing the `of_phy_package_join` Function and Its Implications**

Okay, let's break this down. I'm looking at this `of_phy_package_join` function, specifically how it's used with `yt8824`. The code first grabs the device node from `phydev->mdio.dev.of_node`. If this is NULL, which I'm assuming is the typical scenario without DeviceTree (like on x86/amd64 systems when using MDIO scanning in environments like QEMU or USB), it immediately returns `-EINVAL`.

And then look at `yt8824_probe`:  If `devm_of_phy_package_join` returns `-EINVAL`, the `yt8824_probe` function *immediately* returns. So, basically, if the device node lookup fails, the driver initialization just bails out. This means none of the `yt8824_*` functions will ever get called!

Now, the question becomes: is DeviceTree even *available* on x86_64, especially within something like syzkaller?  My understanding is that on amd64, ACPI is the standard and OpenFirmware/DeviceTree (`CONFIG_OF`) is typically disabled or absent, especially those `ethernet-phy-package` nodes. I'm reasonably sure syzkaller runs a standard amd64 kernel in QEMU *without* DT.

Just to be sure, let's double-check the configuration (`CONFIG_OF`) on x86/amd64... need to verify that this is indeed disabled.



18/2 2026/09/15 11:01 tool grepper
0m Args:
{
  "Expression": "config OF\\b",
  "PathPrefix": "drivers/of"
}

Results:
{
  "Output": "drivers/of/Kconfig=8=config BUILTIN_DTB_ALL\n--\ndrivers/of/Kconfig-10-\ndrivers/of/Kconfig:11:menuconfig OF\ndrivers/of/Kconfig-12-\tbool \"Device Tree and Open Firmware support\"\n"
}

19/2 2026/09/15 11:01 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 43302
							output: 25
							thoughts: 152
						

Thoughts:
Here's my thought process, summarized as you requested:

**Delving into the Motorcomm YT8824**

Okay, hold on a second! Before I go any further, I need to confirm something *really* fundamental: is the Motorcomm YT8824 actually a physical hardware Ethernet PHY? The patch documentation *should* clarify this. Ah, here we go! Yes, the patch explicitly states: "Motorcomm YT8824 Ethernet PHY is a PHY package of 4 PHYs." Excellent. And it continues, "Enables support for Motorcomm network PHYs. Currently supports YT85xx Gigabit Ethernet PHYs and YT8824 4 * 2.5G PHY." That's good confirmation.

Now, a new detail surfaces in the code which I need to get my head around. What about this `genphy_c45_template_testmode` thing that was added in `drivers/net/phy/phy-c45.c`? Where exactly is that function called from within the kernel's Ethernet PHY driver structure? Time to use my favorite tool: grepper! I'll get to the bottom of this.



20/2 2026/09/15 11:01 tool grepper
0m Args:
{
  "Expression": "genphy_c45_template_testmode"
}

Results:
{
  "Output": "drivers/net/phy/motorcomm.c=777=static int yt8824_utp_invalid_test_mode_paged(struct phy_device *phydev)\n--\ndrivers/net/phy/motorcomm.c-784-\ndrivers/net/phy/motorcomm.c:785:\treturn genphy_c45_template_testmode\ndrivers/net/phy/motorcomm.c-786-\t\t(phydev, MDIO_PMA_10GBT_TESTMODE_1);\n--\ndrivers/net/phy/motorcomm.c=840=static int yt8824_utp_normal_test_mode_paged(struct phy_device *phydev)\n--\ndrivers/net/phy/motorcomm.c-847-\ndrivers/net/phy/motorcomm.c:848:\treturn genphy_c45_template_testmode(phydev,\ndrivers/net/phy/motorcomm.c-849-\t\t\t\t\t    MDIO_PMA_10GBT_TESTMODE_NORMAL);\n--\ndrivers/net/phy/motorcomm.c=978=static int yt8824_extern_config_utp_init_paged(struct phy_device *phydev)\n--\ndrivers/net/phy/motorcomm.c-1231-\ndrivers/net/phy/motorcomm.c:1232:\tret = genphy_c45_template_testmode(phydev, MDIO_PMA_10GBT_TESTMODE_1);\ndrivers/net/phy/motorcomm.c-1233-\tif (ret \u003c 0)\n--\ndrivers/net/phy/motorcomm.c-1244-\ndrivers/net/phy/motorcomm.c:1245:\tret = genphy_c45_template_testmode(phydev,\ndrivers/net/phy/motorcomm.c-1246-\t\t\t\t\t   MDIO_PMA_10GBT_TESTMODE_NORMAL);\n--\ndrivers/net/phy/motorcomm.c-1257-err_restore_normal:\ndrivers/net/phy/motorcomm.c:1258:\tr = genphy_c45_template_testmode(phydev,\ndrivers/net/phy/motorcomm.c-1259-\t\t\t\t\t MDIO_PMA_10GBT_TESTMODE_NORMAL);\n--\ndrivers/net/phy/motorcomm.c=1517=static int yt8824_internal_config_init_paged(struct phy_device *phydev)\n--\ndrivers/net/phy/motorcomm.c-1701-\t\tgoto err_restore;\ndrivers/net/phy/motorcomm.c:1702:\tret = genphy_c45_template_testmode(phydev, MDIO_PMA_10GBT_TESTMODE_1);\ndrivers/net/phy/motorcomm.c-1703-\tif (ret)\n--\ndrivers/net/phy/motorcomm.c-1714-\ndrivers/net/phy/motorcomm.c:1715:\tret = genphy_c45_template_testmode(phydev,\ndrivers/net/phy/motorcomm.c-1716-\t\t\t\t\t   MDIO_PMA_10GBT_TESTMODE_NORMAL);\n--\ndrivers/net/phy/motorcomm.c-1728-err_restore_normal:\ndrivers/net/phy/motorcomm.c:1729:\tr = genphy_c45_template_testmode(phydev,\ndrivers/net/phy/motorcomm.c-1730-\t\t\t\t\t MDIO_PMA_10GBT_TESTMODE_NORMAL);\n--\ndrivers/net/phy/phy-c45.c=1409=EXPORT_SYMBOL_GPL(genphy_c45_fast_retrain);\n--\ndrivers/net/phy/phy-c45.c-1411-/**\ndrivers/net/phy/phy-c45.c:1412: * genphy_c45_template_testmode - configure template testmode registers\ndrivers/net/phy/phy-c45.c-1413- * @phydev: target phy_device struct\n--\ndrivers/net/phy/phy-c45.c-1420- */\ndrivers/net/phy/phy-c45.c:1421:int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode)\ndrivers/net/phy/phy-c45.c-1422-{\n--\ndrivers/net/phy/phy-c45.c-1432-}\ndrivers/net/phy/phy-c45.c:1433:EXPORT_SYMBOL_GPL(genphy_c45_template_testmode);\ndrivers/net/phy/phy-c45.c-1434-\n--\ninclude/linux/phy.h=2359=int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable);\ninclude/linux/phy.h:2360:int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode);\ninclude/linux/phy.h-2361-int genphy_c45_plca_get_cfg(struct phy_device *phydev,\n"
}

21/2 2026/09/15 11:01 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 45061
							output: 38
							thoughts: 448
						

Thoughts:
**Analyzing the `motorcomm.c` Changes**

Okay, so `genphy_c45_template_testmode` is *only* called by the yt8824 functions in `motorcomm.c`. That's good to know. But, I need to understand what's going on with `ytphy_set_wol` also in `motorcomm.c`. Let's jump into lines 622-632 of `motorcomm.c` to refresh my memory on the function's structure. Ah, and what was that patch's impact on `ytphy_set_wol`? Time to pull up the `git diff` for that function in `drivers/net/phy/motorcomm.c`.

Hmm, this looks interesting. It seems like the patch simply added the line `if (ret < 0) goto err_restore_page;` right after disabling the WOL interrupt. This looks like a standard error handling procedure. Let's make sure, however, and review the code before and after the change in `ytphy_set_wol`.



22/2 2026/09/15 11:01 tool read-file
0m Args:
{
  "File": "drivers/net/phy/motorcomm.c",
  "FirstLine": 700,
  "LineCount": 40
}

Results:
{
  "Contents": " 700:\t\t\tval = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL;\n 701:\t\t\tval |= YTPHY_WCR_TYPE_PULSE | YTPHY_WCR_PULSE_WIDTH_672MS;\n 702:\t\t\tret = ytphy_modify_ext(phydev, YTPHY_WOL_CONFIG_REG, mask, val);\n 703:\t\t\tif (ret \u003c 0)\n 704:\t\t\t\tgoto err_restore_page;\n 705:\t\n 706:\t\t\t/* Enable WOL interrupt */\n 707:\t\t\tret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, 0,\n 708:\t\t\t\t\t   YTPHY_IER_WOL);\n 709:\t\t\tif (ret \u003c 0)\n 710:\t\t\t\tgoto err_restore_page;\n 711:\t\n 712:\t\t} else {\n 713:\t\t\told_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE);\n 714:\t\t\tif (old_page \u003c 0)\n 715:\t\t\t\tgoto err_restore_page;\n 716:\t\n 717:\t\t\t/* Disable WOL feature */\n 718:\t\t\tmask = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL;\n 719:\t\t\tret = ytphy_modify_ext(phydev, YTPHY_WOL_CONFIG_REG, mask, 0);\n 720:\t\n 721:\t\t\t/* Disable WOL interrupt */\n 722:\t\t\tret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG,\n 723:\t\t\t\t\t   YTPHY_IER_WOL, 0);\n 724:\t\t\tif (ret \u003c 0)\n 725:\t\t\t\tgoto err_restore_page;\n 726:\t\t}\n 727:\t\n 728:\terr_restore_page:\n 729:\t\treturn phy_restore_page(phydev, old_page, ret);\n 730:\t}\n 731:\t\n 732:\t/**\n 733:\t * yt8824_read_page() - read PHY8824 reg page\n 734:\t * @phydev: a pointer to a \u0026struct phy_device\n 735:\t *\n 736:\t * Returns: current reg space of yt8824 (YT8824_RSSR_USXGMII_SPACE/\n 737:\t * YT8824_RSSR_UTP_SPACE) or negative errno code\n 738:\t */\n 739:\tstatic int yt8824_read_page(struct phy_device *phydev)\n"
}

23/2 2026/09/15 11:01 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 46511
							output: 191
							thoughts: 2116
						

Thoughts:
**Analysis of Patch Reachability in a Fuzzing Context**

Alright, let's break this down. My initial thought was about the pointless addition in `ytphy_set_wol`. Essentially, it added a check that was already implicitly there, a classic no-op. But the core question is whether the changes within `drivers/net/phy/motorcomm.c` are accessible via fuzzing.

My primary concern, which I need to resolve, is whether it is "Structurally unreachable hardware." I'm very familiar with the fuzzing environment, so let's use that knowledge here: Specifically, whether the Motorcomm YT8824 PHY driver *requires* physical hardware that isn't emulated by the standard QEMU setup I'm testing with.

I know that PHY drivers, by definition, manage external Ethernet transceiver chips. The YT8824 is such a chip from a real semiconductor company. My experience tells me that QEMU on x86/amd64 emulates Intel (e1000/e1000e), Virtio, and Realtek hardware, but none of these use PHYs that are managed by the kernel's phylib. Therefore, no physical MDIO bus (used to communicate with PHYs) is emulated, making this an immediate red flag.

The critical piece here is the use of Device Tree (DT). The `yt8824_probe` function *explicitly* uses `devm_of_phy_package_join` and expects an "ethernet-phy-package" node in the DT. Without DT, or a specific DT binding for a motorcomm YT8824, the probe fails immediately. Even if a mock MDIO bus were somehow triggered, the driver would fail as the OF node is expected to be present, and it is not in the context of amd64 + standard QEMU.

Furthermore, `genphy_c45_template_testmode` within this driver appears to be *exclusively* called by this driver; no other kernel code calls it. Meaning that, this patch is only relevant to physical Motorcomm hardware with specific Device Tree configurations.

The changes in `ytphy_set_wol` are ultimately inconsequential; this driver is unreachable anyway. I grepped the codebase and confirmed that `genphy_c45_template_testmode` isn't called anywhere else.

Hence, I conclude the changes are structurally unreachable within a standard QEMU fuzzing context.
Thus, **WorthFuzzing = false.**



24/2 2026/09/15 11:01 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch series adds support for the Motorcomm YT8824 quad-port 2.5G Ethernet PHY in drivers/net/phy/motorcomm.c and adds an associated helper genphy_c45_template_testmode in drivers/net/phy/phy-c45.c. The modified code targets a specific physical Ethernet PHY transceiver that requires physical hardware and specific Device Tree description ('ethernet-phy-package'), which is not present or emulated in standard virtualized x86_64/QEMU fuzzing environments. The helper genphy_c45_template_testmode is solely called by the YT8824 driver, and probe immediately fails without the OF node. Therefore, the code is structurally unreachable.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch series adds support for the Motorcomm YT8824 quad-port 2.5G Ethernet PHY in drivers/net/phy/motorcomm.c and adds an associated helper genphy_c45_template_testmode in drivers/net/phy/phy-c45.c. The modified code targets a specific physical Ethernet PHY transceiver that requires physical hardware and specific Device Tree description ('ethernet-phy-package'), which is not present or emulated in standard virtualized x86_64/QEMU fuzzing environments. The helper genphy_c45_template_testmode is solely called by the YT8824 driver, and probe immediately fails without the OF node. Therefore, the code is structurally unreachable.",
  "WorthFuzzing": false
}

25/1 2026/09/15 11:01 action If
0m Args:
{
  "WorthFuzzing": false
}

Results:
null

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)