AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/09/12 07:53 flow patch-triage
0m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "KMSANReasoning": "",
  "NeedsKMSAN": false,
  "Reasoning": "The patch adds support for the Motorcomm YT8824 Ethernet PHY (a quad-port 2.5Gbps PHY) in drivers/net/phy/motorcomm.c, DT bindings, and a helper genphy_c45_template_testmode in phy-c45.c which is only invoked by the YT8824 driver. The code requires physical Motorcomm YT8824 PHY hardware (PHY ID 0x4f51e8b8) on an MDIO bus and requires Device Tree ethernet-phy-package configuration, which is not emulated or present in standard QEMU/amd64 virtual fuzzing environments. Consequently, all modified code is structurally unreachable.",
  "WorthFuzzing": false
}

1/1 2026/09/12 07:53 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 0d7e25abaff6527c44f6b696871d3a747ed9fd21\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Sat Sep 12 07:52:59 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 b4ef927fd4a67..1dd80e06e2370 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..7f949ab53b547 100644\n--- a/drivers/net/phy/motorcomm.c\n+++ b/drivers/net/phy/motorcomm.c\n@@ -1,24 +1,29 @@\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/module.h\u003e\n+#include \u003clinux/of.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 +35,18 @@\n  *  ------------------------------------------------------------\n  */\n \n+/* YT8824 Register Overview\n+ *\tUTP Register space\t|\tUSXGMII Register space\n+ *  ------------------------------------------------------------\n+ * |\tUTP MII\t\t\t|\tUSXGMII MII\t        |\n+ * |\tUTP MMD\t\t\t|\t\t\t\t|\n+ * |\tUTP Extended\t\t|\tUSXGMII Extended\t|\n+ * |\tUTP Top Extended\t|\tUSXGMII Top Extended\t|\n+ *  ------------------------------------------------------------\n+ * |\t\t\tCommon 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 +398,15 @@\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_UTP_TEMPLATE_TEST_MODE1\t\t0x1\n+#define YT8824_UTP_TEMPLATE_TEST_NORMAL\t\t0x0\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+\tunsigned int 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@@ -626,11 +722,1058 @@ static int ytphy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)\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\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, YT8824_UTP_TEMPLATE_TEST_MODE1);\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,\n+\t\t\t\t     !(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\n+\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_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, (val \u003c 0) ||\n+\t\t\t\t!(val \u0026 BMCR_RESET),\n+\t\t\t\t50000, 600000, true, 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\n+\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_MODE1);\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,\n+\t\t\t\t    !(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\n+\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_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 YT8824_UTP_TEMPLATE_TEST_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, (val \u003c 0) ||\n+\t\t\t\t!(val \u0026 BMCR_RESET),\n+\t\t\t\t50000, 600000, true, 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\n+\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_MODE1);\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,\n+\t\t\t\t    !(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\n+\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_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 YT8824_UTP_TEMPLATE_TEST_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;\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\",\n+\t\t   __func__, 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 +4247,429 @@ 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\",\n+\t\t   __func__, 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,\n+\t\t\t\t   \"%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,\n+\t\t\t\t   \"%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,\n+\t\t\t\t     MDIO_AN_10GBT_CTRL,\n+\t\t\t\t     MDIO_AN_10GBT_CTRL_ADV2_5G,\n+\t\t\t\t     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+\tconst char *interface_mode_name;\n+\n+\t/* Initialise shared lock for YT8824 */\n+\tmutex_init(\u0026priv-\u003eshared_lock);\n+\tpriv-\u003einterface_mode = PHY_INTERFACE_MODE_INTERNAL;\n+\tif (!of_property_read_string(np, \"phy-mode\",\n+\t\t\t\t     \u0026interface_mode_name)) {\n+\t\tif (!strcasecmp(interface_mode_name,\n+\t\t\t\tphy_modes(PHY_INTERFACE_MODE_USXGMII))) {\n+\t\t\tpriv-\u003einterface_mode = PHY_INTERFACE_MODE_USXGMII;\n+\t\t} else if (!strcasecmp\n+\t\t\t\t(interface_mode_name,\n+\t\t\t\t phy_modes(PHY_INTERFACE_MODE_INTERNAL))) {\n+\t\t\tpriv-\u003einterface_mode = PHY_INTERFACE_MODE_INTERNAL;\n+\t\t} else {\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t} else {\n+\t\tphydev_warn(phydev, \"%s, phy-mode missing in DTS.\\n\",\n+\t\t\t    __func__);\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 +4756,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\t\t\t= \"YT8824 Quad Ports 2.5Gbps Ethernet\",\n+\t\t.get_features\t\t= yt8824_get_features,\n+\t\t.read_page\t\t= yt8824_read_page,\n+\t\t.write_page\t\t= yt8824_write_page,\n+\t\t.probe\t\t        = yt8824_probe,\n+\t\t.config_aneg\t\t= yt8824_config_aneg,\n+\t\t.aneg_done\t\t= yt8824_aneg_done,\n+\t\t.config_init\t\t= yt8824_config_init,\n+\t\t.read_status\t\t= yt8824_read_status,\n+\t\t.soft_reset\t\t= yt8824_soft_reset,\n+\t\t.suspend\t\t= yt8824_suspend,\n+\t\t.resume\t\t\t= 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 +4788,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..528e3f4143110 100644\n--- a/drivers/net/phy/phy-c45.c\n+++ b/drivers/net/phy/phy-c45.c\n@@ -1408,6 +1408,61 @@ 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+ *\tread/write error).\n+ */\n+int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode)\n+{\n+\tint ctrl = 0;\n+\n+\tswitch (test_mode) {\n+\tcase 0:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_NORMAL;\n+\t\tbreak;\n+\n+\tcase 1:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_1;\n+\t\tbreak;\n+\n+\tcase 2:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_2;\n+\t\tbreak;\n+\n+\tcase 3:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_3;\n+\t\tbreak;\n+\n+\tcase 4:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_4;\n+\t\tbreak;\n+\n+\tcase 5:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_5;\n+\t\tbreak;\n+\n+\tcase 6:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_6;\n+\t\tbreak;\n+\n+\tcase 7:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_7;\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\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..8576a48877c6d 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\t/* 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 0xE000\t/* Template test mode */\n+#define MDIO_PMA_10GBT_TESTMODE_NORMAL 0x0000\t/* Template Normal */\n+#define MDIO_PMA_10GBT_TESTMODE_1 0x2000 /* Template TestMode1 */\n+#define MDIO_PMA_10GBT_TESTMODE_2 0x4000 /* Template TestMode2 */\n+#define MDIO_PMA_10GBT_TESTMODE_3 0x6000 /* Template TestMode3 */\n+#define MDIO_PMA_10GBT_TESTMODE_4 0x8000 /* Template TestMode4 */\n+#define MDIO_PMA_10GBT_TESTMODE_5 0xa000 /* Template TestMode5 */\n+#define MDIO_PMA_10GBT_TESTMODE_6 0xc000 /* Template TestMode6 */\n+#define MDIO_PMA_10GBT_TESTMODE_7 0xe000 /* 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/12 07:53 agent patch-evaluator
0m Model:
core

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch adds support for the Motorcomm YT8824 Ethernet PHY (a quad-port 2.5Gbps PHY) in drivers/net/phy/motorcomm.c, DT bindings, and a helper genphy_c45_template_testmode in phy-c45.c which is only invoked by the YT8824 driver. The code requires physical Motorcomm YT8824 PHY hardware (PHY ID 0x4f51e8b8) on an MDIO bus and requires Device Tree ethernet-phy-package configuration, which is not emulated or present in standard QEMU/amd64 virtual fuzzing environments. Consequently, all modified 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 0d7e25abaff6527c44f6b696871d3a747ed9fd21
Author: syz-cluster <triage@syzkaller.com>
Date:   Sat Sep 12 07:52:59 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 b4ef927fd4a67..1dd80e06e2370 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..7f949ab53b547 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -1,24 +1,29 @@
 // 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/module.h>
+#include <linux/of.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 +35,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 +398,15 @@
 #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_UTP_TEMPLATE_TEST_MODE1		0x1
+#define YT8824_UTP_TEMPLATE_TEST_NORMAL		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 {
+	unsigned int 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
@@ -626,11 +722,1058 @@ static int ytphy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
 		ret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG,
 				   YTPHY_IER_WOL, 0);
 		if (ret < 0)
-			goto err_restore_page;
+			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, YT8824_UTP_TEMPLATE_TEST_MODE1);
+}
+
+/**
+ * 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, YT8824_UTP_TEMPLATE_TEST_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, YT8824_UTP_TEMPLATE_TEST_MODE1);
+	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, YT8824_UTP_TEMPLATE_TEST_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,
+					 YT8824_UTP_TEMPLATE_TEST_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, YT8824_UTP_TEMPLATE_TEST_MODE1);
+	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, YT8824_UTP_TEMPLATE_TEST_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,
+					 YT8824_UTP_TEMPLATE_TEST_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;
+	} 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 +4247,429 @@ 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);
+	const char *interface_mode_name;
+
+	/* Initialise shared lock for YT8824 */
+	mutex_init(&priv->shared_lock);
+	priv->interface_mode = PHY_INTERFACE_MODE_INTERNAL;
+	if (!of_property_read_string(np, "phy-mode",
+				     &interface_mode_name)) {
+		if (!strcasecmp(interface_mode_name,
+				phy_modes(PHY_INTERFACE_MODE_USXGMII))) {
+			priv->interface_mode = PHY_INTERFACE_MODE_USXGMII;
+		} else if (!strcasecmp
+				(interface_mode_name,
+				 phy_modes(PHY_INTERFACE_MODE_INTERNAL))) {
+			priv->interface_mode = PHY_INTERFACE_MODE_INTERNAL;
+		} else {
+			return -EINVAL;
+		}
+	} else {
+		phydev_warn(phydev, "%s, phy-mode missing in DTS.\n",
+			    __func__);
+	}
+
+	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 +4756,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 +4788,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..528e3f4143110 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -1408,6 +1408,61 @@ 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 = 0;
+
+	switch (test_mode) {
+	case 0:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_NORMAL;
+		break;
+
+	case 1:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_1;
+		break;
+
+	case 2:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_2;
+		break;
+
+	case 3:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_3;
+		break;
+
+	case 4:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_4;
+		break;
+
+	case 5:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_5;
+		break;
+
+	case 6:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_6;
+		break;
+
+	case 7:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_7;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	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..8576a48877c6d 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 0xE000	/* Template test mode */
+#define MDIO_PMA_10GBT_TESTMODE_NORMAL 0x0000	/* Template Normal */
+#define MDIO_PMA_10GBT_TESTMODE_1 0x2000 /* Template TestMode1 */
+#define MDIO_PMA_10GBT_TESTMODE_2 0x4000 /* Template TestMode2 */
+#define MDIO_PMA_10GBT_TESTMODE_3 0x6000 /* Template TestMode3 */
+#define MDIO_PMA_10GBT_TESTMODE_4 0x8000 /* Template TestMode4 */
+#define MDIO_PMA_10GBT_TESTMODE_5 0xa000 /* Template TestMode5 */
+#define MDIO_PMA_10GBT_TESTMODE_6 0xc000 /* Template TestMode6 */
+#define MDIO_PMA_10GBT_TESTMODE_7 0xe000 /* Template TestMode7 */
+
 /* PCS 10GBASE-R/-T status register 1. */
 #define MDIO_PCS_10GBRT_STAT1_BLKLK	0x0001	/* Block lock attained */
 

3/2 2026/09/12 07:53 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 26207
							output: 26
							thoughts: 951
						

Thoughts:
**Analyzing the Motorcomm YT8824 PHY Patch for Syzkaller Fuzzing Potential**

Okay, let's break this down. My initial thought is to determine if this patch, which introduces support for the YT8824 PHY, is a good candidate for Syzkaller fuzzing. First, I need to understand the scope of the changes. I see:

1.  Documentation updates: That's usually not where the juicy bugs are, but always good to know.
2.  Kconfig changes: Adding `PHY_PACKAGE` selection, and description changes. Potentially relevant, but I need to understand the implications of `PHY_PACKAGE`.
3.  The core of the patch: The `motorcomm.c` driver has been extended with numerous functions specifically for the YT8824 PHY. This includes read/write functions for registers, configuration and initialization routines, and power management. This is where I'll focus most of my attention. The `phy-c45.c` and `phy.h` changes look related to a general test mode capability.
4.  MDIO definitions: New definitions in `mdio.h` for test mode settings. These are very interesting, as they define the communication protocol

Now comes the crucial part: reachability. Is this new PHY driver, and the functions it adds, accessible within a Syzkaller-fuzzable environment? Let's see...

I know `motorcomm.c` is an MDIO PHY driver. The key question is, can Syzkaller trigger code paths within MDIO PHY drivers? I need to figure out how these PHY drivers are probed and bound to the system. Are they solely tied to physical MDIO buses, or is there a way to instantiate MDIO/PHY devices virtually? Can I create an MDIO device in a way Syzkaller can interact with? This is the million-dollar question. If they are bound to a real MDIO, I would need a different environment.

I need to search within Syzkaller, and even within the kernel itself, for how MDIO devices are created or controlled. I'll search for things like "mdio", "phy\_driver", and see if there are any userspace interfaces that allow me to create an MDIO PHY. If I can instatiate one virtually, I am in luck. That would open the door to fuzzing the YT8824 and the other drivers.



4/2 2026/09/12 07:53 tool grepper
0m Args:
{
  "Expression": "mdio.*new_device|phy_device_create"
}

Results:
{
  "Output": "drivers/net/mdio/fwnode_mdio.c=117=int fwnode_mdiobus_register_phy(struct mii_bus *bus,\n--\ndrivers/net/mdio/fwnode_mdio.c-134-\telse\ndrivers/net/mdio/fwnode_mdio.c:135:\t\tphy = phy_device_create(bus, addr, phy_id, 0, NULL);\ndrivers/net/mdio/fwnode_mdio.c-136-\tif (IS_ERR(phy)) {\n--\ndrivers/net/phy/nxp-tja11xx.c=551=static void tja1102_p1_register(struct work_struct *work)\n--\ndrivers/net/phy/nxp-tja11xx.c-585-\t\t/* Real PHY ID of Port 1 is 0 */\ndrivers/net/phy/nxp-tja11xx.c:586:\t\tphy = phy_device_create(bus, addr, PHY_ID_TJA1102, false, NULL);\ndrivers/net/phy/nxp-tja11xx.c-587-\t\tif (IS_ERR(phy)) {\n--\ndrivers/net/phy/nxp-tja11xx.c-592-\ndrivers/net/phy/nxp-tja11xx.c:593:\t\t/* Overwrite parent device. phy_device_create() set parent to\ndrivers/net/phy/nxp-tja11xx.c-594-\t\t * the mii_bus-\u003edev, which is not correct in case.\n--\ndrivers/net/phy/phy_device.c=728=static int phy_request_driver_module(struct phy_device *dev, u32 phy_id)\n--\ndrivers/net/phy/phy_device.c-747-\ndrivers/net/phy/phy_device.c:748:struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,\ndrivers/net/phy/phy_device.c-749-\t\t\t\t     bool is_c45,\n--\ndrivers/net/phy/phy_device.c-839-}\ndrivers/net/phy/phy_device.c:840:EXPORT_SYMBOL(phy_device_create);\ndrivers/net/phy/phy_device.c-841-\n--\ndrivers/net/phy/phy_device.c=1071=struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)\n--\ndrivers/net/phy/phy_device.c-1096-\t\tif (!r)\ndrivers/net/phy/phy_device.c:1097:\t\t\treturn phy_device_create(bus, addr, phy_id,\ndrivers/net/phy/phy_device.c-1098-\t\t\t\t\t\t true, \u0026c45_ids);\n--\ndrivers/net/phy/phy_device.c-1100-\ndrivers/net/phy/phy_device.c:1101:\treturn phy_device_create(bus, addr, phy_id, is_c45, \u0026c45_ids);\ndrivers/net/phy/phy_device.c-1102-}\n--\ninclude/linux/phy.h=2167=int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum,\n--\ninclude/linux/phy.h-2169-\ninclude/linux/phy.h:2170:struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,\ninclude/linux/phy.h-2171-\t\t\t\t     bool is_c45,\n"
}

5/2 2026/09/12 07:53 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 28658
							output: 25
							thoughts: 130
						

Thoughts:
**My Investigation into PHY Device Probing**

Okay, hold on a second! I need to clarify something fundamental: How exactly do we probe these PHY devices? Let me trace the initialization sequence. I'm thinking, a PHY device is created, either through the Device Tree fwnode (which makes sense, preconfigured hardware) or during the MDIO bus registration using `mdiobus_register`. Right, and then the critical step is the PHY driver binding, this likely depends on what's read from the hardware itself, specifically the `phy_id` register, or also a Device Tree match, right? I need to check something related to this so I'll check `genphy_c45_template_testmode` in `drivers/net/phy/phy-c45.c` to remind myself about its structure. Okay, so I now understand this, where is `genphy_c45_template_testmode` actually *called*? Time for a quick `grep` to track down those usages. I can use this to understand the logic.



6/2 2026/09/12 07:53 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, YT8824_UTP_TEMPLATE_TEST_MODE1);\n--\ndrivers/net/phy/motorcomm.c=841=static int yt8824_utp_normal_test_mode_paged(struct phy_device *phydev)\n--\ndrivers/net/phy/motorcomm.c-848-\ndrivers/net/phy/motorcomm.c:849:\treturn genphy_c45_template_testmode\ndrivers/net/phy/motorcomm.c-850-\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_NORMAL);\n--\ndrivers/net/phy/motorcomm.c=979=static int yt8824_extern_config_utp_init_paged(struct phy_device *phydev)\n--\ndrivers/net/phy/motorcomm.c-1232-\ndrivers/net/phy/motorcomm.c:1233:\tret = genphy_c45_template_testmode\ndrivers/net/phy/motorcomm.c-1234-\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_MODE1);\n--\ndrivers/net/phy/motorcomm.c-1247-\ndrivers/net/phy/motorcomm.c:1248:\tret = genphy_c45_template_testmode\ndrivers/net/phy/motorcomm.c-1249-\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_NORMAL);\n--\ndrivers/net/phy/motorcomm.c-1260-err_restore_normal:\ndrivers/net/phy/motorcomm.c:1261:\tr = genphy_c45_template_testmode(phydev,\ndrivers/net/phy/motorcomm.c-1262-\t\t\t\t\t YT8824_UTP_TEMPLATE_TEST_NORMAL);\n--\ndrivers/net/phy/motorcomm.c=1520=static int yt8824_internal_config_init_paged(struct phy_device *phydev)\n--\ndrivers/net/phy/motorcomm.c-1704-\t\tgoto err_restore;\ndrivers/net/phy/motorcomm.c:1705:\tret = genphy_c45_template_testmode\ndrivers/net/phy/motorcomm.c-1706-\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_MODE1);\n--\ndrivers/net/phy/motorcomm.c-1719-\ndrivers/net/phy/motorcomm.c:1720:\tret = genphy_c45_template_testmode\ndrivers/net/phy/motorcomm.c-1721-\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_NORMAL);\n--\ndrivers/net/phy/motorcomm.c-1733-err_restore_normal:\ndrivers/net/phy/motorcomm.c:1734:\tr = genphy_c45_template_testmode(phydev,\ndrivers/net/phy/motorcomm.c-1735-\t\t\t\t\t YT8824_UTP_TEMPLATE_TEST_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-1463-}\ndrivers/net/phy/phy-c45.c:1464:EXPORT_SYMBOL_GPL(genphy_c45_template_testmode);\ndrivers/net/phy/phy-c45.c-1465-\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"
}

7/2 2026/09/12 07:53 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 30360
							output: 28
							thoughts: 440
						

Thoughts:
**My Fuzzing Roadblock**

Okay, so `genphy_c45_template_testmode` only gets called within `drivers/net/phy/motorcomm.c`. That's the starting point. My goal: can I even *reach* or instantiate a Motorcomm PHY, specifically the YT8824, during my amd64 QEMU syzkaller fuzzing runs? Let's check the guidelines.

Right, the negative criteria... I remember, "Structurally unreachable hardware." Specifically, "Vendor-specific PCIe switches, SmartNICs, or GPU drivers... requiring physical ASIC/PCIe cards not emulated in standard QEMU."

Hang on... Is an Ethernet PHY driver *structurally* unreachable? The YT8824 is a discrete Ethernet PHY chip – a physical chip. It's a "Quad Ports 2.5Gbps Ethernet PHY." It connects over MDIO to a MAC or SoC and is identified via devicetree bindings like `motorcomm,yt8824-package` or the MDIO PHY ID 0x4f51e8b8.

Okay, does *standard* QEMU, the one syzkaller uses, emulate this? Nope. QEMU emulates virtual network interfaces like e1000, virtio-net, rtl8139, and so on. None of those have a Motorcomm PHY chip. It doesn't look like they have the option to add any.

But, a virtual MDIO bus? Or maybe some kind of USB-to-MDIO adapter or similar thing could be used in syzkaller to reach this? Let me quickly scan the kernel and syzkaller source for any evidence of virtual MDIO buses or USB-MDIO adapters. That's the next avenue to check... otherwise, this driver is going to be a dead end for fuzzing.



8/2 2026/09/12 07:53 tool grepper
0m Args:
{
  "Expression": "mdio.*usb",
  "PathPrefix": "drivers/net/"
}

Results:
{
  "Output": "drivers/net/mdio/Makefile=20=obj-$(CONFIG_MDIO_MSCC_MIIM)\t\t+= mdio-mscc-miim.o\ndrivers/net/mdio/Makefile:21:obj-$(CONFIG_MDIO_MVUSB)\t\t+= mdio-mvusb.o\ndrivers/net/mdio/Makefile-22-obj-$(CONFIG_MDIO_OCTEON)\t\t+= mdio-octeon.o\n--\ndrivers/net/mdio/mdio-mvusb.c=32=static int mvusb_mdio_read(struct mii_bus *mdio, int dev, int reg)\ndrivers/net/mdio/mdio-mvusb.c-33-{\ndrivers/net/mdio/mdio-mvusb.c:34:\tstruct mvusb_mdio *mvusb = mdio-\u003epriv;\ndrivers/net/mdio/mdio-mvusb.c-35-\tint err, alen;\n--\ndrivers/net/mdio/mdio-mvusb.c=52=static int mvusb_mdio_write(struct mii_bus *mdio, int dev, int reg, u16 val)\ndrivers/net/mdio/mdio-mvusb.c-53-{\ndrivers/net/mdio/mdio-mvusb.c:54:\tstruct mvusb_mdio *mvusb = mdio-\u003epriv;\ndrivers/net/mdio/mdio-mvusb.c-55-\tint alen;\n--\ndrivers/net/mdio/mdio-mvusb.c-63-\ndrivers/net/mdio/mdio-mvusb.c:64:static int mvusb_mdio_probe(struct usb_interface *interface,\ndrivers/net/mdio/mdio-mvusb.c-65-\t\t\t    const struct usb_device_id *id)\n--\ndrivers/net/mdio/mdio-mvusb.c-67-\tstruct device *dev = \u0026interface-\u003edev;\ndrivers/net/mdio/mdio-mvusb.c:68:\tstruct mvusb_mdio *mvusb;\ndrivers/net/mdio/mdio-mvusb.c-69-\tstruct mii_bus *mdio;\ndrivers/net/mdio/mdio-mvusb.c-70-\ndrivers/net/mdio/mdio-mvusb.c:71:\tmdio = devm_mdiobus_alloc_size(dev, sizeof(*mvusb));\ndrivers/net/mdio/mdio-mvusb.c-72-\tif (!mdio)\n--\ndrivers/net/mdio/mdio-mvusb.c-82-\ndrivers/net/mdio/mdio-mvusb.c:83:\tsnprintf(mdio-\u003eid, MII_BUS_ID_SIZE, \"mvusb-%s\", dev_name(dev));\ndrivers/net/mdio/mdio-mvusb.c-84-\tmdio-\u003ename = mdio-\u003eid;\ndrivers/net/mdio/mdio-mvusb.c-85-\tmdio-\u003eparent = dev;\ndrivers/net/mdio/mdio-mvusb.c:86:\tmdio-\u003eread = mvusb_mdio_read;\ndrivers/net/mdio/mdio-mvusb.c:87:\tmdio-\u003ewrite = mvusb_mdio_write;\ndrivers/net/mdio/mdio-mvusb.c-88-\n--\ndrivers/net/mdio/mdio-mvusb.c-93-\ndrivers/net/mdio/mdio-mvusb.c:94:static void mvusb_mdio_disconnect(struct usb_interface *interface)\ndrivers/net/mdio/mdio-mvusb.c-95-{\ndrivers/net/mdio/mdio-mvusb.c:96:\tstruct mvusb_mdio *mvusb = usb_get_intfdata(interface);\ndrivers/net/mdio/mdio-mvusb.c-97-\ndrivers/net/mdio/mdio-mvusb.c:98:\tmdiobus_unregister(mvusb-\u003emdio);\ndrivers/net/mdio/mdio-mvusb.c-99-\tusb_set_intfdata(interface, NULL);\n--\ndrivers/net/usb/asix_devices.c=658=static int asix_resume(struct usb_interface *intf)\n--\ndrivers/net/usb/asix_devices.c-668-\ndrivers/net/usb/asix_devices.c:669:static int ax88772_init_mdio(struct usbnet *dev)\ndrivers/net/usb/asix_devices.c-670-{\n--\ndrivers/net/usb/asix_devices.c-683-\t/* mii bus name is usb-\u003cusb bus number\u003e-\u003cusb device number\u003e */\ndrivers/net/usb/asix_devices.c:684:\tsnprintf(priv-\u003emdio-\u003eid, MII_BUS_ID_SIZE, \"usb-%03d:%03d\",\ndrivers/net/usb/asix_devices.c-685-\t\t dev-\u003eudev-\u003ebus-\u003ebusnum, dev-\u003eudev-\u003edevnum);\n--\ndrivers/net/usb/ax88172a.c=55=static void ax88172a_status(struct usbnet *dev, struct urb *urb)\n--\ndrivers/net/usb/ax88172a.c-60-/* use phylib infrastructure */\ndrivers/net/usb/ax88172a.c:61:static int ax88172a_init_mdio(struct usbnet *dev)\ndrivers/net/usb/ax88172a.c-62-{\n--\ndrivers/net/usb/ax88172a.c-76-\t/* mii bus name is usb-\u003cusb bus number\u003e-\u003cusb device number\u003e */\ndrivers/net/usb/ax88172a.c:77:\tsnprintf(priv-\u003emdio-\u003eid, MII_BUS_ID_SIZE, \"usb-%03d:%03d\",\ndrivers/net/usb/ax88172a.c-78-\t\t dev-\u003eudev-\u003ebus-\u003ebusnum, dev-\u003eudev-\u003edevnum);\n--\ndrivers/net/usb/ax88172a.c-93-\ndrivers/net/usb/ax88172a.c:94:static void ax88172a_remove_mdio(struct usbnet *dev)\ndrivers/net/usb/ax88172a.c-95-{\n--\ndrivers/net/usb/lan78xx.c=2091=static int lan78xx_mdio_init(struct lan78xx_net *dev)\n--\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/smsc95xx.c=166=static u32 mii_address_cmd(int phy_id, int idx, u16 op)\n--\ndrivers/net/usb/smsc95xx.c-170-\ndrivers/net/usb/smsc95xx.c:171:static int smsc95xx_mdio_read(struct usbnet *dev, int phy_id, int idx)\ndrivers/net/usb/smsc95xx.c-172-{\n--\ndrivers/net/usb/smsc95xx.c-217-\ndrivers/net/usb/smsc95xx.c:218:static void smsc95xx_mdio_write(struct usbnet *dev, int phy_id, int idx,\ndrivers/net/usb/smsc95xx.c-219-\t\t\t\tint regval)\n"
}

9/2 2026/09/12 07:53 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 33230
							output: 24
							thoughts: 223
						

Thoughts:
**Diving into the Motorcomm PHY Driver**

Okay, hold on a second! I need to take a closer look at the `drivers/net/phy/motorcomm.c` file, specifically the `yt8824_probe` function. I have a hunch about what's going on, and this could be key. Let's examine this snippet:

```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;
}
```

Right, so we're joining a package using `devm_of_phy_package_join`, and potentially probing it. What's crucial here is that `devm_of_phy_package_join` likely manages resource allocation and association with the device tree. It seems to be setting up shared private data within the `yt8824_shared_priv` struct. The fact that `phy_package_probe_once` is called conditionally based on the return value of `devm_of_phy_package_join` is intriguing. Now, I need to understand this `devm_of_phy_package_join` function more precisely, and understand its implementation. It could be the linchpin in how the Motorcomm PHY is initialized and managed, especially concerning resource management and the device tree interaction.



10/2 2026/09/12 07:53 tool grepper
0m Args:
{
  "Expression": "devm_of_phy_package_join"
}

Results:
{
  "Output": "drivers/net/phy/motorcomm.c=4654=static int yt8824_probe(struct phy_device *phydev)\n--\ndrivers/net/phy/motorcomm.c-4659-\ndrivers/net/phy/motorcomm.c:4660:\tret = devm_of_phy_package_join(dev, phydev, sizeof(*shared_priv));\ndrivers/net/phy/motorcomm.c-4661-\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"
}

11/2 2026/09/12 07:53 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 34579
							output: 39
							thoughts: 36
						

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

**Diving into `phy_package.c`**

Alright, time to get into it. I need to take a look at the `devm_of_phy_package_join` function. I remember seeing that one in `drivers/net/phy/phy_package.c`. I'll use `read-file` to get the source code. Let's see what's going on in there and refresh my memory on the device tree and PHY package handling. I'm especially interested in how it's integrated with the device management library given the `devm_` prefix.



12/2 2026/09/12 07:53 tool read-file
0m Args:
{
  "File": "drivers/net/phy/phy_package.c",
  "FirstLine": 408,
  "LineCount": 40
}

Results:
{
  "Contents": " 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/12 07:53 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 35325
							output: 39
							thoughts: 13
						

Thoughts:
Okay, here's my interpretation of what's going on, summarized from the provided text, as if it's my own thought process, and assuming I'm an expert in the field:

**Analyzing `of_phy_package_join`**

Alright, let's dive into this `of_phy_package_join` function or concept. Immediately, I'm thinking about its implications within the larger PHY (Physical Layer) context. The name itself suggests a function related to joining or assembling something at the physical level. My mind's jumping through potential scenarios: Is this about packet aggregation, perhaps? Or is it more fundamental, dealing with the alignment and synchronization of incoming data streams at the very lowest level of the protocol stack?

Given my experience, I'm guessing this function likely sits between the raw signal processing and the more structured MAC (Medium Access Control) layer. It probably handles the nitty-gritty details of bit-level manipulation – maybe framing, error correction at the physical level, or even pre-processing for equalization. I need to understand its inputs and outputs to be sure, but I'm picturing it handling things like inter-symbol interference, channel impairments, and any pre-coding schemes in use.

Now, if it deals with joining, could it be part of a MIMO (Multiple-Input Multiple-Output) or beamforming scheme? That's a strong possibility. In this case, it might handle the combination of data streams from multiple antennas. Or, it might be about aggregating multiple smaller data units into larger physical-layer packets for efficient transmission over the air. I'll need to explore its architecture deeper to confirm. Regardless, it's clearly a crucial component, and I need to understand its precise role in the data flow to truly grasp its significance.



14/2 2026/09/12 07:53 tool read-file
0m Args:
{
  "File": "drivers/net/phy/phy_package.c",
  "FirstLine": 360,
  "LineCount": 45
}

Results:
{
  "Contents": " 360:\t\t}\n 361:\t\n 362:\t\tphydev-\u003eshared = NULL;\n 363:\t}\n 364:\tEXPORT_SYMBOL_GPL(phy_package_leave);\n 365:\t\n 366:\tstatic void devm_phy_package_leave(struct device *dev, void *res)\n 367:\t{\n 368:\t\tphy_package_leave(*(struct phy_device **)res);\n 369:\t}\n 370:\t\n 371:\t/**\n 372:\t * devm_phy_package_join - resource managed phy_package_join()\n 373:\t * @dev: device that is registering this PHY package\n 374:\t * @phydev: target phy_device struct\n 375:\t * @base_addr: cookie and base PHY address of PHY package for offset\n 376:\t *   calculation of global register access\n 377:\t * @priv_size: if non-zero allocate this amount of bytes for private data\n 378:\t *\n 379:\t * Managed phy_package_join(). Shared storage fetched by this function,\n 380:\t * phy_package_leave() is automatically called on driver detach. See\n 381:\t * phy_package_join() for more information.\n 382:\t */\n 383:\tint devm_phy_package_join(struct device *dev, struct phy_device *phydev,\n 384:\t\t\t\t  int base_addr, size_t priv_size)\n 385:\t{\n 386:\t\tstruct phy_device **ptr;\n 387:\t\tint ret;\n 388:\t\n 389:\t\tptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr),\n 390:\t\t\t\t   GFP_KERNEL);\n 391:\t\tif (!ptr)\n 392:\t\t\treturn -ENOMEM;\n 393:\t\n 394:\t\tret = phy_package_join(phydev, base_addr, priv_size);\n 395:\t\n 396:\t\tif (!ret) {\n 397:\t\t\t*ptr = phydev;\n 398:\t\t\tdevres_add(dev, ptr);\n 399:\t\t} else {\n 400:\t\t\tdevres_free(ptr);\n 401:\t\t}\n 402:\t\n 403:\t\treturn ret;\n 404:\t}\n"
}

15/2 2026/09/12 07:53 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 36397
							output: 22
							thoughts: 13
						

Thoughts:
Okay, here's my interpretation of what's going on, framed as a first-person expert summary, ready for a fellow expert.

**Analyzing `of_phy_package_join`**

Alright, let's dive into this `of_phy_package_join` function. My initial thought is to immediately consider the data structures and the overall system context it's operating within.  What kind of physical layer package are we dealing with? Is this related to Ethernet, a custom protocol, or something else entirely? I need to understand the underlying frame format.

My mind immediately starts forming a checklist:

*   **Data Structures:** What are the input package formats? Is it a structure, a class, or raw bytes? Are there any associated metadata? I need to verify how these data structures are defined and how `of_phy_package_join` references them. Any potential bitfields, alignment issues, or endianness considerations?
*   **Purpose:** What's the *goal* of this function? Is it combining multiple physical layer packets into a larger unit, perhaps a logical frame? Is it meant to add headers, trailers, or padding? Is it related to packet reassembly, encapsulation, or segmentation? I need to understand how this function fits into the overall data flow.
*   **Error Handling:** What happens if there's an issue with the input data, like an incomplete package or corrupted data? I need to ascertain how this function deals with error conditions. Does it return an error code, throw an exception, or log something? What is the expected behavior when things go wrong? Is error checking thorough?
*   **Performance:** Given the likely data volumes, I need to evaluate the performance impact of this function. Any potential bottlenecks? Are there loops, memory allocations, or copying operations that could slow things down? Is this function optimized for speed or simplicity?
*   **Security:** This is more of a secondary consideration. Is this function designed with any security aspects in mind? Is there any potential for buffer overflows or other vulnerabilities related to data manipulation?
*   **Side Effects:** What is being altered? Is there a state change? Any other functions reliant on this one?

Essentially, I need to understand the function's input, its output, its internal logic, the error handling, and its place in the grand scheme of things. By quickly walking through these items, I'll identify any areas that could be improved, optimized, or that may have unexpected consequences.



16/2 2026/09/12 07:53 tool grepper
0m Args:
{
  "Expression": "int of_phy_package_join"
}

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"
}

17/2 2026/09/12 07:53 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 37185
							output: 39
							thoughts: 13
						

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

**Analyzing the Function 'of\_phy\_package\_join'**

Alright, let's dive into this `of_phy_package_join` function. Just the name alone suggests it's involved in some sort of joining operation, likely within the context of a PHY package. Given my experience, I'm immediately thinking about the potential complexities. Is this a simple concatenation, or are there more sophisticated merging rules at play? Are we talking about combining data structures, perhaps packet headers, payload information, or control fields? The "PHY" prefix is a significant clue; it signals this is probably low-level, close to the physical layer. I need to consider factors such as framing, synchronization, error handling at this stage, and the implications for throughput or latency. What's the target system's architecture? Is this a hardware-accelerated process, or running entirely in software? The data type of the input, and output, is key. Let me see where this function fits into the bigger picture of the data stream processing pipeline.



18/2 2026/09/12 07:53 tool read-file
0m Args:
{
  "File": "drivers/net/phy/phy_package.c",
  "FirstLine": 298,
  "LineCount": 40
}

Results:
{
  "Contents": " 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 335:\t/**\n 336:\t * phy_package_leave - leave a common PHY group\n 337:\t * @phydev: target phy_device struct\n"
}

19/2 2026/09/12 07:53 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 38029
							output: 183
							thoughts: 1353
						

Thoughts:
**Unreachable Code Path Analysis: YT8824 PHY Driver**

Okay, let's break this down. My analysis indicates that the code added for the Motorcomm YT8824 Ethernet PHY is, for all intents and purposes, *unreachable* in a standard fuzzing setup targeting amd64 with QEMU.  Here's the reasoning:

First, `of_phy_package_join` is a hard dependency. It mandates the existence of an `ethernet-phy-package` DeviceTree node. The YT8824 probe function, `yt8824_probe`, calls `devm_of_phy_package_join`, and *cannot* even initialize without that node. On amd64, we're not dealing with DeviceTree by default, so we're immediately blocked.  The target is amd64.  Boom, no DT, no probe.

Second, the YT8824 is *physical* hardware. It's a discrete PHY chip, a quad 2.5G package. It requires an MDIO bus and a specific PHY ID (0x4f51e8b8). Standard QEMU, on amd64, doesn't emulate that kind of hardware. Even if we had *some* MDIO bus, there's no way the YT8824 PHY is going to be present or visible.

Third, let's solidify the point about `genphy_c45_template_testmode`, which the patch also modifies.  A quick code search shows that *only* the YT8824 driver calls that function.  It's entirely within the Motorcomm PHY driver context. No other network subsystem code, no other drivers, nothing.  It's effectively a private helper function.

Therefore, the modified code is firmly and definitively caught in the "Structurally unreachable hardware" category defined in the negative criteria, and it requires both hardware presence and specific DeviceTree configuration.  It's a clear case of returning `WorthFuzzing=false`. The fuzzing system is set up to target amd64 with standard QEMU environment, and we do not have hardware or device tree information.
The relevant `Reasoning` for the results would be: "The patch adds support for the Motorcomm YT8824 Ethernet PHY (a quad-port 2.5Gbps PHY package) in `drivers/net/phy/motorcomm.c`, devicetree bindings, and a generic helper `genphy_c45_template_testmode()` in `drivers/net/phy/phy-c45.c` which is solely called by the YT8824 driver. The driver requires physical Motorcomm YT8824 PHY hardware on an MDIO bus with matching PHY ID (0x4f51e8b8), as well as Open Firmware (Device Tree) bindings (`ethernet-phy-package`), none of which exist or are emulated in standard virtualized fuzzing environments (QEMU/GCE on amd64). As such, the modified code is structurally unreachable."



20/2 2026/09/12 07:53 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch adds support for the Motorcomm YT8824 Ethernet PHY (a quad-port 2.5Gbps PHY) in drivers/net/phy/motorcomm.c, DT bindings, and a helper genphy_c45_template_testmode in phy-c45.c which is only invoked by the YT8824 driver. The code requires physical Motorcomm YT8824 PHY hardware (PHY ID 0x4f51e8b8) on an MDIO bus and requires Device Tree ethernet-phy-package configuration, which is not emulated or present in standard QEMU/amd64 virtual fuzzing environments. Consequently, all modified code is structurally unreachable.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch adds support for the Motorcomm YT8824 Ethernet PHY (a quad-port 2.5Gbps PHY) in drivers/net/phy/motorcomm.c, DT bindings, and a helper genphy_c45_template_testmode in phy-c45.c which is only invoked by the YT8824 driver. The code requires physical Motorcomm YT8824 PHY hardware (PHY ID 0x4f51e8b8) on an MDIO bus and requires Device Tree ethernet-phy-package configuration, which is not emulated or present in standard QEMU/amd64 virtual fuzzing environments. Consequently, all modified code is structurally unreachable.",
  "WorthFuzzing": false
}

21/1 2026/09/12 07:53 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)