AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/07/26 00:05 flow patch-triage
1m Args:
null

Results:
{
  "EnableConfigs": [
    "MOTORCOMM_PHY"
  ],
  "FocusSymbols": [
    "genphy_c45_template_testmode",
    "yt8824_aneg_done",
    "yt8824_config_aneg",
    "yt8824_config_init",
    "yt8824_config_intr",
    "yt8824_handle_interrupt",
    "yt8824_probe",
    "yt8824_read_page",
    "yt8824_read_status",
    "yt8824_resume",
    "yt8824_soft_reset",
    "yt8824_suspend",
    "yt8824_write_page"
  ],
  "Reasoning": "The patch adds support for the Motorcomm YT8824 Quad Ports 2.5Gbps Ethernet PHY. PHY drivers are accessible and fuzzable in virtualized environments (like QEMU) via emulated MDIO buses (e.g., through USB network adapters like smsc95xx that expose an MDIO bus). Syzkaller can emulate the USB device, respond to MDIO reads with the Motorcomm PHY ID (0x4f51e8b8), and trigger the instantiation and execution of this PHY driver.",
  "WorthFuzzing": true
}

1/1 2026/07/26 00:05 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 73220979cbb0a817f79ed04666a7be05179b9435\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Sun Jul 26 00:05:10 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c\nindex 5071605a1a117a..04c79d4b35c592 100644\n--- a/drivers/net/phy/motorcomm.c\n+++ b/drivers/net/phy/motorcomm.c\n@@ -1,23 +1,32 @@\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/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 PHY8824 top extend addr offset internal and external*/\n+#define INTERNAL_PHY8824_TOP_EXTEND_OFFSET    (5)\n+#define EXTERNAL_PHY8824_TOP_EXTEND_OFFSET    (4)\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@@ -29,6 +38,18 @@\n  *  ------------------------------------------------------------\n  */\n \n+/* YT8824 Register Overview\n+ *\tUTP Register space\t|\tFIBER Register space\n+ *  ------------------------------------------------------------\n+ * |\tUTP MII\t\t\t|\tFIBER MII\t        |\n+ * |\tUTP MMD\t\t\t|\t\t\t\t|\n+ * |\tUTP Extended\t\t|\tFIBER Extended\t\t|\n+ * |\tUTP Top Extended\t|\tFIBER 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@@ -375,6 +396,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_FIBER_SPACE\t\t\t(0x1)\n+#define YT8824_RSSR_UTP_SPACE\t\t\t(0x0)\n+#define YT8824_UTP_TEMPLATE_TEST_MODE1\t\t1\n+#define YT8824_UTP_TEMPLATE_TEST_NORMAL\t\t0\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@@ -393,6 +423,11 @@ struct yt8521_priv {\n \tu8 reg_page;\n };\n \n+struct yt8824_shared_priv {\n+\tunsigned int interface_mode;\n+\tunsigned int offset;\n+};\n+\n /**\n  * ytphy_read_ext() - read a PHY's extended register\n  * @phydev: a pointer to a \u0026struct phy_device\n@@ -431,6 +466,107 @@ 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: the value of regnum reg 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+ * ytphy_write_top_ext_with_lock() - write a PHY's top 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: the value of regnum reg or negative error code\n+ */\n+static int ytphy_write_top_ext_with_lock(struct phy_device *phydev, u16 regnum,\n+\t\t\t\t\t u16 val)\n+{\n+\tint ret;\n+\n+\tphy_lock_mdio_bus(phydev);\n+\tret = ytphy_write_top_ext(phydev, regnum, val);\n+\tphy_unlock_mdio_bus(phydev);\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * ytphy_read_top_ext_with_lock() - read a PHY's top 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_with_lock(struct phy_device *phydev, u16 regnum)\n+{\n+\tint ret;\n+\n+\tphy_lock_mdio_bus(phydev);\n+\tret = ytphy_read_top_ext(phydev, regnum);\n+\tphy_unlock_mdio_bus(phydev);\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * phy8824_page_write_lock() - write page for YT8824\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ * @page: reg page(YT8824_RSSR_FIBER_SPACE/YT8824_RSSR_UTP_SPACE).\n+ *\n+ * Returns: the value of regnum reg or negative error code\n+ */\n+static int phy8824_page_write_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\treturn ret;\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+\tphy_unlock_mdio_bus(phydev);\n+\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@@ -623,8 +759,1165 @@ static int ytphy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)\n \t\t\tgoto err_restore_page;\n \t}\n \n-err_restore_page:\n-\treturn phy_restore_page(phydev, old_page, ret);\n+err_restore_page:\n+\treturn phy_restore_page(phydev, old_page, ret);\n+}\n+\n+/**\n+ * yt8824_read_page() - read reg page\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: current reg space of yt8824 (YT8824_RSSR_FIBER_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: The reg page(YT8824_RSSR_FIBER_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+\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 = 0;\n+\n+\tret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn genphy_c45_template_testmode(phydev,\n+\t\t\t\t\t    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;\n+\tint ret = 0;\n+\n+\told_page = phy_select_page(phydev, YT8824_RSSR_FIBER_SPACE);\n+\tif (old_page \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = __phy_read(phydev, MII_BMCR);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\t/* isolation */\n+\tret |= BMCR_ISOLATE;\n+\tret = __phy_write(phydev, MII_BMCR, ret);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+err_restore_page:\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_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = phy_read(phydev, MII_BMCR);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret |= BMCR_RESET;\n+\tret = phy_write(phydev, MII_BMCR, ret);\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_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn genphy_c45_template_testmode(phydev,\n+\t\t\t\t\t    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+\tunsigned int retry = 12;\n+\tint old_page;\n+\tint ret = -1;\n+\n+\told_page = phy_select_page(phydev, YT8824_RSSR_FIBER_SPACE);\n+\tif (old_page \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = __phy_read(phydev, MII_BMCR);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\t/* disable isolation */\n+\tret \u0026= ~BIT(10);\n+\t/* soft reset */\n+\tret |= BMCR_RESET;\n+\tret = __phy_write(phydev, MII_BMCR, ret);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tdo {\n+\t\tmsleep(50);\n+\t\tret = __phy_read(phydev, MII_BMCR);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t} while ((ret \u0026 BMCR_RESET) \u0026\u0026 --retry);\n+\n+\tif (ret \u0026 BMCR_RESET)\n+\t\treturn -ETIMEDOUT;\n+\n+err_restore_page:\n+\treturn phy_restore_page(phydev, old_page, 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+\tint ret;\n+\n+\tif (phydev-\u003einterface == 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\treturn ret;\n+\t\tret = yt8824_utp_softreset_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\t/* normal mode */\n+\t\tret = yt8824_utp_normal_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\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\treturn ret;\n+\n+\t\t/* sds isolation */\n+\t\tret = yt8824_sds_isolate_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\t/* utp soft reset */\n+\t\tret = yt8824_utp_softreset_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\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\treturn ret;\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\treturn ret;\n+\t}\n+\treturn 0;\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 data = 0;\n+\tint ret = 0;\n+\n+\tret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* power down */\n+\tdata = phy_read(phydev, MII_BMCR);\n+\tif (data \u003c 0)\n+\t\treturn data;\n+\tdata |= BMCR_PDOWN;\n+\tret = phy_write(phydev, MII_BMCR, data);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\t/* pll calibration */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0001, 0x0003);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa20e, 0x0cba);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa20a, 0xc3f1);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa20c, 0x1620);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0x0a00);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0x0e00);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\t/* optimization utp */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0001, 0x0003);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\t/* enable nibble */\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa003, 0x0003);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\t/* idle err detect enable */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x03d0, 0x5210);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\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\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x037c, 0x6068);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0388, 0x00a0);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\t/* optimized fast retrain */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0359, 0x2140);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x000c, 0xc1a0);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\t/* 2.5G template tone */\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2fa, 0x0083);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x04e2, 0x0149);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\t/* optimized 2.5G template */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x047e, 0x3939);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x047f, 0x3939);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0480, 0x3939);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0481, 0x3939);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\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\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0340, 0x301d);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\t/* 100M template amplitude */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x046e, 0x4545);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x046f, 0x4545);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0470, 0x4545);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0471, 0x4545);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\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\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x071f, 0x0036);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\t/* 10M template amplitude */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x046b, 0x1818);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x046c, 0x1818);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\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\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0467, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0468, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0469, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\t/* optimize utp 1000M performance */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x034a, 0xff03);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x00f8, 0xb3ff);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0059, 0x4040);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x032c, 0x5094);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x032d, 0xd094);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x032e, 0x5308);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0322, 0x6440);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x04d3, 0x5220);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x04d2, 0x5220);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\t/* optimized EMC CS */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x00c8, 0xffff);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x00be, 0x6406);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x037a, 0x40ff);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\t/* optimized EMC RE */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0482, 0xffff);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d5, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d6, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d7, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d8, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa218, 0x006e);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xfff0);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xfff0);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xffff);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xffff);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\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+\tstruct yt8824_shared_priv *shared_priv;\n+\tint ret = 0, old_page;\n+\tu16 val_1, val_2, val_3, tmp;\n+\tu16 data = 0;\n+\tint port;\n+\n+\tshared_priv = phy_package_get_priv(phydev);\n+\tport = phydev-\u003emdio.addr - shared_priv-\u003eoffset;\n+\told_page = phy_select_page(phydev, YT8824_RSSR_FIBER_SPACE);\n+\tif (old_page \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* read efuse */\n+\tval_1 = ytphy_read_top_ext(phydev, 0xa13e);\n+\tif (val_1 \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tval_2 = ytphy_read_top_ext(phydev, 0xa13f);\n+\tif (val_2 \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tval_3 = ytphy_read_top_ext(phydev, 0xa140);\n+\tif (val_3 \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tif (port == 0) {\n+\t\t/* Serdes optimization */\n+\t\tret = ytphy_write_ext(phydev, 0x04be, 0x000d);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x049f, 0x7ded);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x04a9, 0x009f);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\t/* analog CDR */\n+\t\tret = ytphy_write_ext(phydev, 0x0406, 0x0800);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\t/* optimized VCO */\n+\t\tret = ytphy_write_ext(phydev, 0x0438, 0x9024);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x0439, 0x00c0);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\t/* optimized PLL lock */\n+\t\tret = ytphy_read_ext(phydev, 0x0429);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret \u0026= ~(BIT(13) | BIT(12));\n+\t\ttmp = (val_1 \u0026 (BIT(7) | BIT(6)) \u003e\u003e 6);\n+\t\tret |= (tmp \u003c\u003c 12);\n+\t\tret = ytphy_write_ext(phydev, 0x0429, ret);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_read_ext(phydev, 0x0441);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret \u0026= ~(BIT(1) | BIT(0));\n+\t\ttmp = (val_1 \u0026 (BIT(5) | BIT(4)) \u003e\u003e 4);\n+\t\tret |= tmp;\n+\t\tret = ytphy_write_ext(phydev, 0x0441, ret);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_read_ext(phydev, 0x042b);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret \u0026= ~(BIT(13) | BIT(12));\n+\t\ttmp = (val_3 \u0026 (BIT(1) | BIT(0)));\n+\t\tret |= (tmp \u003c\u003c 12);\n+\t\tret = ytphy_write_ext(phydev, 0x042b, ret);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x043a, 0x1006);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x042a, 0xf070);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\t/* cable length threshold */\n+\t\tret = ytphy_write_ext(phydev, 0x0491, 0x007f);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x0492, 0x7f7f);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\t/* Serdes training threshold */\n+\t\tret = ytphy_write_ext(phydev, 0x0454, 0x0f14);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x0497, 0x0a44);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\t/* digital eye diagram of SerDes */\n+\t\tret = ytphy_write_ext(phydev, 0x04cd, 0x0000);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\t/* Serdes LDO */\n+\t\tret = ytphy_read_ext(phydev, 0x04b5);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret \u0026= ~(BIT(6) | BIT(5) | BIT(4));\n+\t\ttmp = (val_2 \u0026 (BIT(4) | BIT(3) | BIT(2)) \u003e\u003e 2);\n+\t\tret |= (tmp \u003c\u003c 4);\n+\t\tret = ytphy_write_ext(phydev, 0x04b5, ret);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_read_ext(phydev, 0x04b4);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret \u0026= ~(BIT(10) | BIT(9) | BIT(8));\n+\t\ttmp = (val_2 \u0026 (BIT(7) | BIT(6) | BIT(5)) \u003e\u003e 5);\n+\t\tret |= (tmp \u003c\u003c 8);\n+\t\tret = ytphy_write_ext(phydev, 0x04b4, ret);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\t/* optimized Serdes RX */\n+\t\tret = ytphy_write_ext(phydev, 0x04af, 0x45e3);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x048a, 0x0fff);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x0408, 0x7c00);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x04d6, 0x007f);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x044f, 0xff08);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\t/* optimized Serdes TX */\n+\t\tret = ytphy_write_ext(phydev, 0x048e, 0x7d00);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x000d, 0x0606);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\t/* Serdes manual config */\n+\t\tret = ytphy_write_ext(phydev, 0x04b0, 0x0804);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x04b1, 0x7074);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x04af, 0x45e7);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\t/* restart calibration */\n+\t\tret = ytphy_write_ext(phydev, 0x0003, 0x5603);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x0492, 0x7fff);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x0492, 0x7f7f);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x2000, 0x0040);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\n+\t\tret = ytphy_write_ext(phydev, 0x2000, 0x0000);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err_restore_page;\n+\t}\n+\n+\t/* TX preamble padded to 8; RX IPG always \u003e 8 */\n+\tdata \u0026= ~YT8824_SDS_CFG_MIN_PRE_MASK;\n+\tdata |= YT8824_SDS_TX_PRE_PADDING;\n+\tdata |= YT8824_SDS_EN_FILL_PRE;\n+\tret = __phy_write(phydev, MII_RESV1, data);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tdata = __phy_read(phydev, MII_BMCR);\n+\tif (data \u003c 0)\n+\t\tgoto err_restore_page;\n+\tdata |= BMCR_RESET;\n+\tdata |= BMCR_ANENABLE;\n+\tret = __phy_write(phydev, MII_BMCR, data);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+err_restore_page:\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+\tstruct yt8824_shared_priv *shared_priv;\n+\tint port = 0;\n+\tint ret = 0;\n+\tu16 data;\n+\n+\tret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tshared_priv = phy_package_get_priv(phydev);\n+\tport = phydev-\u003emdio.addr - shared_priv-\u003eoffset;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x1, 0x3);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tdata = phy_read(phydev, MII_BMCR);\n+\tif (data \u003c 0)\n+\t\treturn ret;\n+\tdata |= BMCR_PDOWN;\n+\tret = phy_write(phydev, MII_BMCR, data);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tif (port == 0) {\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0xa20e, 0xcba);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0xa20a, 0xc3f1);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0xa20c, 0x1620);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0xa00);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0xe00);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0xa003, 0x3);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t}\n+\tret = ytphy_write_ext_with_lock(phydev, 0x3d0, 0x5210);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x372, 0x5038);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x37c, 0x6068);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x388, 0xa0);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x359, 0x2140);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_top_ext_with_lock(phydev, 0xa2fa, 0x83);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x4e2, 0x149);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* 2.5G tempate */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x47e, 0x3939);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x47f, 0x3939);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x480, 0x3939);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x481, 0x3939);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* 1000 cable length threshold */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x336, 0xab0a);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x340, 0x301d);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* 1000 performance */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x34a, 0xff03);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xf8, 0xb3ff);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x32c, 0x5094);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x32d, 0xd094);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x32e, 0x5308);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x322, 0x6440);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x4d3, 0x5220);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x4d2, 0x5220);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* 100 tempate */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x46e, 0x4545);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x46f, 0x4545);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x470, 0x4545);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x471, 0x4545);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* 100 cable length threshold */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x30b, 0xaa1d);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x71f, 0x36);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* 10 tempate */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x46b, 0x1818);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x46c, 0x1818);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* 10 tempate MAU*/\n+\tret = ytphy_write_ext_with_lock(phydev, 0x466, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x467, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x468, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x469, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* EMC CS */\n+\tret = ytphy_write_ext_with_lock(phydev, 0xc8, 0xfff);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xbe, 0x6406);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x37a, 0x40ff);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* EMC RE*/\n+\tret = ytphy_write_ext_with_lock(phydev, 0x482, 0xffff);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tif (port == 0) {\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0x482, 0xffff);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0xa2d5, 0x1f1f);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0xa2d6, 0x1f1f);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0xa2d7, 0x1f1f);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0xa2d8, 0x1f1f);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0xa218, 0x6e);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xfff0);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xfff0);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xffff);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xffff);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t}\n+\tret = ytphy_write_ext_with_lock(phydev, 0xc, 0x41a1);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = genphy_c45_template_testmode(phydev,\n+\t\t\t\t\t   YT8824_UTP_TEMPLATE_TEST_MODE1);\n+\tif (ret)\n+\t\treturn ret;\n+\tdata = phy_read(phydev, MII_BMCR);\n+\tif (data \u003c 0)\n+\t\treturn ret;\n+\tdata |= BMCR_RESET;\n+\tdata |= BMCR_ANENABLE;\n+\tret = phy_write(phydev, MII_BMCR, data);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = genphy_c45_template_testmode(phydev,\n+\t\t\t\t\t   YT8824_UTP_TEMPLATE_TEST_NORMAL);\n+\tif (ret)\n+\t\treturn ret;\n+\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+\tint ret;\n+\n+\tif (phydev-\u003einterface == PHY_INTERFACE_MODE_INTERNAL) {\n+\t\tret = yt8824_internal_config_init_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t} else {\n+\t\tret = yt8824_extern_config_utp_init_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tret = yt8824_extern_config_sds_init_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t}\n+\tret = yt8824_soft_reset(phydev);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tphydev_dbg(phydev, \"%s done, phy addr: %d\\n\",\n+\t\t   __func__, phydev-\u003emdio.addr);\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * yt8824_config_intr() - phy8824 interrupt configuration\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_config_intr(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *shared_priv;\n+\tint ret = 0;\n+\tint port;\n+\n+\tshared_priv = phy_package_get_priv(phydev);\n+\tif ((phydev-\u003emdio.addr - shared_priv-\u003eoffset) \u003c 2)\n+\t\tport = 0;\n+\telse\n+\t\tport = 2;\n+\tret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tif (phydev-\u003einterrupts == PHY_INTERRUPT_ENABLED) {\n+\t\t/* top ext reg 0xa000\n+\t\t * bit6 int_polarity 1'b0 low active, 1'b1 high active\n+\t\t */\n+\t\tret = ytphy_read_top_ext_with_lock(phydev,\n+\t\t\t\t\t\t   YT8521_REG_SPACE_SELECT_REG);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\tret = ytphy_write_top_ext_with_lock(phydev,\n+\t\t\t\t\t\t    YT8521_REG_SPACE_SELECT_REG,\n+\t\t\t\t\t\t    ret \u0026 (~BIT(6)));\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\t/* top ext reg 0xa019\n+\t\t * bit5 intr_phy_pulse_en 1'b0 level, 1'b1 pulse\n+\t\t */\n+\t\tret = ytphy_read_top_ext_with_lock(phydev, 0xa019);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\tret = ytphy_write_top_ext_with_lock(phydev, 0xa019,\n+\t\t\t\t\t\t    ret | BIT(5));\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\t/* top ext reg 0xa018 phy_pulse_lth bit14:8\n+\t\t * top ext reg 0xa019 timer_tick_sel bit8:7\n+\t\t * bit14:8 phy_pulse_lth bit8:7 timer_tick_sel   pulse width\n+\t\t * 0x007a\t\t0x0002\t\t10ms pulse width\n+\t\t * 0x0064\t\t0x0001\t\t1ms pulse width\n+\t\t * 0x004e\t\t0x0000\t\t100ms pulse width\n+\t\t * 0x0009\t\t0x0000\t\t10ms pulse width\n+\t\t */\n+\t\tret = ytphy_read_top_ext_with_lock(phydev, 0xa018);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\tret \u0026= ~0x7f00;\n+\t\tret |= (0x0009 \u003c\u003c 8);\n+\t\tret = ytphy_write_top_ext_with_lock(phydev, 0xa018, ret);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\tret = ytphy_read_top_ext_with_lock(phydev, 0xa019);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\tret \u0026= ~0x180;\n+\t\tret |= (0x0000 \u003c\u003c 7);\n+\t\tret = ytphy_write_top_ext_with_lock(phydev, 0xa019, ret);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\t/* top ext reg 0xa01c interrupt state(Read Clear)\n+\t\t * bit11 PHY3 1: phy3 link up/down occurs, 0: not occur\n+\t\t * bit10 PHY2 1: phy2 link up/down occurs, 0: not occur\n+\t\t * bit9  PHY1 1: phy1 link up/down occurs, 0: not occur\n+\t\t * bit8  PHY0 1: phy0 link up/down occurs, 0: not occur\n+\t\t *\n+\t\t * bit7  PHY3 1: phy3 link down occurs, 0: not occur\n+\t\t * bit6  PHY2 1: phy2 link down occurs, 0: not occur\n+\t\t * bit5  PHY1 1: phy1 link down occurs, 0: not occur\n+\t\t * bit4  PHY0 1: phy0 link down occurs, 0: not occur\n+\t\t *\n+\t\t * bit3  PHY3 1: phy3 link up occurs, 0: not occur\n+\t\t * bit2  PHY2 1: phy2 link up occurs, 0: not occur\n+\t\t * bit1  PHY1 1: phy1 link up occurs, 0: not occur\n+\t\t * bit0  PHY0 1: phy0 link up occurs, 0: not occur\n+\t\t */\n+\t\tret = ytphy_read_top_ext_with_lock(phydev, 0xa01c);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\t/* top ext reg 0xa01a\n+\t\t * bit5 intn_wol_mode 1'b1 enable intn_wol pin output\n+\t\t * bit4 intn_mode 1'b1 enable intn pin output\n+\t\t */\n+\t\tret = ytphy_read_top_ext_with_lock(phydev, 0xa01a);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\tret \u0026= ~BIT(5);\n+\t\tret |= BIT(4);\n+\t\tret = ytphy_write_top_ext_with_lock(phydev, 0xa01a, ret);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\t/* top ext reg 0xa01b interrupt mask\n+\t\t * bit11 1'b1 enable interrupt signal(link up/down) to intr pin\n+\t\t * bit7 1'b1 enable interrupt signal(link down) to intr pin\n+\t\t * bit3 1'b1 enable interrupt signal(link up) to intr pin\n+\t\t *\n+\t\t * bit10 1'b1 enable interrupt signal(link up/down) to intr pin\n+\t\t * bit6 1'b1 enable interrupt signal(link down) to intr pin\n+\t\t * bit2 1'b1 enable interrupt signal(link up) to intr pin\n+\t\t *\n+\t\t * bit9 1'b1 enable interrupt signal(link up/down) to intr pin\n+\t\t * bit5 1'b1 enable interrupt signal(link down) to intr pin\n+\t\t * bit1 1'b1 enable interrupt signal(link up) to intr pin\n+\t\t *\n+\t\t * bit8 1'b1 enable interrupt signal(link up/down) to intr pin\n+\t\t * bit4 1'b1 enable interrupt signal(link down) to intr pin\n+\t\t * bit0 1'b1 enable interrupt signal(link up) to intr pin\n+\t\t */\n+\t\tret = ytphy_read_top_ext_with_lock(phydev, 0xa01b);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\tret |= (BIT(port + 8) | BIT(port + 4) | BIT(port));\n+\t\tret = ytphy_write_top_ext_with_lock(phydev, 0xa01b, ret);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t}\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_handle_interrupt() - phy8824 interrupt handle\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static irqreturn_t yt8824_handle_interrupt(struct phy_device *phydev)\n+{\n+\tint ret = 0;\n+\n+\tret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\t/* top ext reg 0xa01c interrupt state(Read Clear)\n+\t * bit11 PHY3 interrupt 1: phy3 link up/down happened, 0: not happened\n+\t * bit10 PHY2 interrupt 1: phy2 link up/down happened, 0: not happened\n+\t * bit9  PHY1 interrupt 1: phy1 link up/down happened, 0: not happened\n+\t * bit8  PHY0 interrupt 1: phy0 link up/down happened, 0: not happened\n+\t * bit7  PHY3 link down 1: phy3 link down happened, 0: not happened\n+\t * bit6  PHY2 link down 1: phy2 link down happened, 0: not happened\n+\t * bit5  PHY1 link down 1: phy1 link down happened, 0: not happened\n+\t * bit4  PHY0 link down 1: phy0 link down happened, 0: not happened\n+\t * bit3  PHY3 link up 1: phy3 link up happened, 0: not happened\n+\t * bit2  PHY2 link up 1: phy2 link up happened, 0: not happened\n+\t * bit1  PHY1 link up 1: phy1 link up happened, 0: not happened\n+\t * bit0  PHY0 link up 1: phy0 link up happened, 0: not happened\n+\t */\n+\tret = ytphy_read_top_ext_with_lock(phydev, 0xa01c);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tphy_trigger_machine(phydev);\n+\tif (ret \u003e 0)\n+\t\treturn IRQ_HANDLED;\n+\telse\n+\t\treturn IRQ_NONE;\n }\n \n static int yt8531_set_wol(struct phy_device *phydev,\n@@ -3059,6 +4352,371 @@ static int yt8821_resume(struct phy_device *phydev)\n \treturn yt8821_modify_utp_fiber_bmcr(phydev, BMCR_PDOWN, 0);\n }\n \n+/**\n+ * yt8824_aneg_done()  - check negotiation state.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_aneg_done(struct phy_device *phydev)\n+{\n+\tint link = 0;\n+\tint ret = 0;\n+\n+\tret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tlink = !!(phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG) \u0026\n+\t\t\t     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+\n+\treturn link;\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+ * @status: The link status, include speed, duplex and link state.\n+ * @lpa: link partner advertising.\n+ *\n+ * Returns: 1 (utp link),0 (no link) or negative errno code\n+ */\n+static int yt8824_read_status_paged(struct phy_device *phydev,\n+\t\t\t\t    int *status, int *lpa)\n+{\n+\tint ret = 0;\n+\n+\tret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = phy_read(phydev, MII_LPA);\n+\t*lpa = ret;\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG);\n+\t*status = ret;\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = !!(*status \u0026 YTPHY_SSR_LINK);\n+\n+\treturn ret;\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+\tint link;\n+\tint lpa;\n+\tint val;\n+\n+\tphydev-\u003epause = 0;\n+\tphydev-\u003easym_pause = 0;\n+\tphydev-\u003elink = 0;\n+\tphydev-\u003espeed = SPEED_UNKNOWN;\n+\tphydev-\u003eduplex = DUPLEX_UNKNOWN;\n+\n+\tlink = yt8824_read_status_paged(phydev,\n+\t\t\t\t\t\u0026val, \u0026lpa);\n+\tif (link \u003c 0)\n+\t\treturn link;\n+\n+\tif (link) {\n+\t\tphydev-\u003elink = 1;\n+\t\tphydev-\u003epause = !!(lpa \u0026 BIT(10));\n+\t\tphydev-\u003easym_pause = !!(lpa \u0026 BIT(11));\n+\n+\t\t/* update speed \u0026 duplex */\n+\t\tyt8821_adjust_status(phydev, val);\n+\t} else {\n+\t\tphydev-\u003elink = 0;\n+\t\tphydev-\u003epause = 0;\n+\t\tphydev-\u003easym_pause = 0;\n+\t\tphydev-\u003espeed = SPEED_UNKNOWN;\n+\t\tphydev-\u003eduplex = DUPLEX_UNKNOWN;\n+\t}\n+\n+\treturn 0;\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_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = phy_read(phydev, MII_BMCR);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret \u0026= ~BMCR_PDOWN;\n+\tret \u0026= ~BMCR_ISOLATE;\n+\n+\treturn phy_write(phydev, MII_BMCR, ret);\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 = 0;\n+\n+\tret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = phy_read(phydev, MII_BMCR);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn phy_write(phydev, MII_BMCR, ret | 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+\tint ret;\n+\n+\tif (phydev-\u003einterface == 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\treturn ret;\n+\t\t/* utp power on */\n+\t\tret = yt8824_utp_power_on(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\t/* normal mode */\n+\t\tret = yt8824_utp_normal_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\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\treturn ret;\n+\n+\t\t/* sds isolation */\n+\t\tret = yt8824_sds_isolate_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\t/* utp power on */\n+\t\tret = yt8824_utp_power_on(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\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\treturn ret;\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\treturn ret;\n+\t}\n+\treturn 0;\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+\treturn yt8824_power_on(phydev);\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+\tint ret;\n+\n+\tif (phydev-\u003einterface == 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\treturn ret;\n+\t\t/* utp power down */\n+\t\tret = yt8824_utp_power_down(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\t/* normal mode */\n+\t\tret = yt8824_utp_normal_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\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\treturn ret;\n+\n+\t\t/* sds isolation */\n+\t\tret = yt8824_sds_isolate_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\t/* utp power down */\n+\t\tret = yt8824_utp_power_down(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\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\treturn ret;\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\treturn ret;\n+\t}\n+\treturn 0;\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+\treturn yt8824_power_down(phydev);\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+\tint phy_ctrl = 0;\n+\tint ret = 0;\n+\n+\tret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\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)\n+\t\treturn ret;\n+\n+\treturn genphy_config_aneg(phydev);\n+}\n+\n+/**\n+ * yt8824_phy_package_probe_once()  - init phy packet 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+\tpriv-\u003einterface_mode = PHY_INTERFACE_MODE_NA;\n+\tpriv-\u003eoffset = INTERNAL_PHY8824_TOP_EXTEND_OFFSET;\n+\tif (!of_property_read_string(np, \"motorcomm,interface-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\tpriv-\u003eoffset = EXTERNAL_PHY8824_TOP_EXTEND_OFFSET;\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\tpriv-\u003eoffset = INTERNAL_PHY8824_TOP_EXTEND_OFFSET;\n+\t\t} else {\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\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+\tstruct yt8521_priv *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+\tpriv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);\n+\tif (!priv)\n+\t\treturn -ENOMEM;\n+\n+\tphydev-\u003epriv = priv;\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@@ -3145,13 +4803,31 @@ 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= yt8821_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.config_intr            = yt8824_config_intr,\n+\t\t.handle_interrupt\t= yt8824_handle_interrupt,\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@@ -3161,6 +4837,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 1269517414288f..e77b503899ee0d 100644\n--- a/drivers/net/phy/phy-c45.c\n+++ b/drivers/net/phy/phy-c45.c\n@@ -1283,6 +1283,26 @@ 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 Test mode 1 to Test mode 7\n+ *\n+ * Description: Set template testmode include Test mode 1 to Test mode 7\n+ */\n+int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode)\n+{\n+\tint ctrl;\n+\n+\tctrl = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TEMPLATE);\n+\tif (ctrl \u003c 0)\n+\t\treturn ctrl;\n+\tctrl \u0026= ~(0x7 \u003c\u003c 13);\n+\tctrl |= test_mode \u003c\u003c 13;\n+\treturn phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TEMPLATE, 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 fc680901275b73..7c02cc6970ae11 100644\n--- a/include/linux/phy.h\n+++ b/include/linux/phy.h\n@@ -2330,6 +2330,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 b2541c948fc1eb..5ae91cdf024c8e 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_TEMPLATE 132\t/* Template 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"
}

2/1 2026/07/26 00:05 agent patch-evaluator
1m Model:
best-expensive

Args:
null

Results:
{
  "EnableConfigs": [
    "MOTORCOMM_PHY"
  ],
  "FocusSymbols": [
    "genphy_c45_template_testmode",
    "yt8824_aneg_done",
    "yt8824_config_aneg",
    "yt8824_config_init",
    "yt8824_config_intr",
    "yt8824_handle_interrupt",
    "yt8824_probe",
    "yt8824_read_page",
    "yt8824_read_status",
    "yt8824_resume",
    "yt8824_soft_reset",
    "yt8824_suspend",
    "yt8824_write_page"
  ],
  "Reasoning": "The patch adds support for the Motorcomm YT8824 Quad Ports 2.5Gbps Ethernet PHY. PHY drivers are accessible and fuzzable in virtualized environments (like QEMU) via emulated MDIO buses (e.g., through USB network adapters like smsc95xx that expose an MDIO bus). Syzkaller can emulate the USB device, respond to MDIO reads with the Motorcomm PHY ID (0x4f51e8b8), and trigger the instantiation and execution of this PHY driver.",
  "WorthFuzzing": true
}

Instruction:
You are an expert Linux kernel maintainer.
Your job is to review a provided patch series and determine
if it makes functional changes to the kernel that should be fuzzed.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively
use your code access tools to examine the actual source code and confirm any assumptions.

Return WorthFuzzing=false if the patch only contains:
- Modifications to Documentation/, Kconfig files, or code comments.
- Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints.
- Changes to numeric constants or macros that do not functionally alter execution flow.
- Code paths that are impossible to reach in virtualized environments like GCE or QEMU,
  even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim).
- Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed,
  ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU.
- Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove)
  that are executed only during PCI hot-unplug or sysfs driver unbind operations.

If it modifies reachable core kernel logic, drivers, or architectures, use your code search
tools to verify the code can be executed, then return WorthFuzzing=true.

When returning WorthFuzzing=true, you MUST ALSO:
1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols.
   Avoid listing generic hot-path functions to prevent skewed test distributions.
   Prefer non-static, non-inlined API entrypoint functions over internal static helper functions
   (which are inlined by the compiler and do not have distinct symbol addresses).
2. Identify any specific CONFIG_ options required to properly test this new/modified feature.
   Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions.
   Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs
   needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs
   output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
For your convenience, here is the diff of the changes:
commit 73220979cbb0a817f79ed04666a7be05179b9435
Author: syz-cluster <triage@syzkaller.com>
Date:   Sun Jul 26 00:05:10 2026 +0000

    syz-cluster: applied patch under review

diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
index 5071605a1a117a..04c79d4b35c592 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -1,23 +1,32 @@
 // 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/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 PHY8824 top extend addr offset internal and external*/
+#define INTERNAL_PHY8824_TOP_EXTEND_OFFSET    (5)
+#define EXTERNAL_PHY8824_TOP_EXTEND_OFFSET    (4)
+
 #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
  *  ------------------------------------------------------------
@@ -29,6 +38,18 @@
  *  ------------------------------------------------------------
  */
 
+/* YT8824 Register Overview
+ *	UTP Register space	|	FIBER Register space
+ *  ------------------------------------------------------------
+ * |	UTP MII			|	FIBER MII	        |
+ * |	UTP MMD			|				|
+ * |	UTP Extended		|	FIBER Extended		|
+ * |	UTP Top Extended	|	FIBER Top Extended	|
+ *  ------------------------------------------------------------
+ * |			Common Top Extended			|
+ *  ------------------------------------------------------------
+ */
+
 /* 0x10 ~ 0x15 , 0x1E and 0x1F are common MII registers of yt phy */
 
 /* Specific Function Control Register */
@@ -375,6 +396,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_FIBER_SPACE			(0x1)
+#define YT8824_RSSR_UTP_SPACE			(0x0)
+#define YT8824_UTP_TEMPLATE_TEST_MODE1		1
+#define YT8824_UTP_TEMPLATE_TEST_NORMAL		0
+#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
@@ -393,6 +423,11 @@ struct yt8521_priv {
 	u8 reg_page;
 };
 
+struct yt8824_shared_priv {
+	unsigned int interface_mode;
+	unsigned int offset;
+};
+
 /**
  * ytphy_read_ext() - read a PHY's extended register
  * @phydev: a pointer to a &struct phy_device
@@ -431,6 +466,107 @@ 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: the value of regnum reg 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);
+}
+
+/**
+ * ytphy_write_top_ext_with_lock() - write a PHY's top register for YT8824
+ * @phydev: a pointer to a &struct phy_device
+ * @regnum: register number to write
+ * @val: register val to write
+ *
+ * Returns: the value of regnum reg or negative error code
+ */
+static int ytphy_write_top_ext_with_lock(struct phy_device *phydev, u16 regnum,
+					 u16 val)
+{
+	int ret;
+
+	phy_lock_mdio_bus(phydev);
+	ret = ytphy_write_top_ext(phydev, regnum, val);
+	phy_unlock_mdio_bus(phydev);
+
+	return ret;
+}
+
+/**
+ * ytphy_read_top_ext_with_lock() - read a PHY's top 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_with_lock(struct phy_device *phydev, u16 regnum)
+{
+	int ret;
+
+	phy_lock_mdio_bus(phydev);
+	ret = ytphy_read_top_ext(phydev, regnum);
+	phy_unlock_mdio_bus(phydev);
+
+	return ret;
+}
+
+/**
+ * phy8824_page_write_lock() - write page for YT8824
+ * @phydev: a pointer to a &struct phy_device
+ * @page: reg page(YT8824_RSSR_FIBER_SPACE/YT8824_RSSR_UTP_SPACE).
+ *
+ * Returns: the value of regnum reg or negative error code
+ */
+static int phy8824_page_write_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)
+		return ret;
+	ret &= ~YT8824_RSSR_SPACE_MASK;
+	ret |= (page & YT8824_RSSR_SPACE_MASK);
+	ret = ytphy_write_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG, ret);
+	phy_unlock_mdio_bus(phydev);
+
+	return ret;
+}
+
 /**
  * ytphy_write_ext() - write a PHY's extended register
  * @phydev: a pointer to a &struct phy_device
@@ -623,8 +759,1165 @@ static int ytphy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
 			goto err_restore_page;
 	}
 
-err_restore_page:
-	return phy_restore_page(phydev, old_page, ret);
+err_restore_page:
+	return phy_restore_page(phydev, old_page, ret);
+}
+
+/**
+ * yt8824_read_page() - read reg page
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: current reg space of yt8824 (YT8824_RSSR_FIBER_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: The reg page(YT8824_RSSR_FIBER_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);
+	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 = 0;
+
+	ret = phy8824_page_write_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;
+	int ret = 0;
+
+	old_page = phy_select_page(phydev, YT8824_RSSR_FIBER_SPACE);
+	if (old_page < 0)
+		goto err_restore_page;
+
+	ret = __phy_read(phydev, MII_BMCR);
+	if (ret < 0)
+		goto err_restore_page;
+	/* isolation */
+	ret |= BMCR_ISOLATE;
+	ret = __phy_write(phydev, MII_BMCR, ret);
+	if (ret < 0)
+		goto err_restore_page;
+
+err_restore_page:
+	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_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+	ret = phy_read(phydev, MII_BMCR);
+	if (ret < 0)
+		return ret;
+	ret |= BMCR_RESET;
+	ret = phy_write(phydev, MII_BMCR, ret);
+	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_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)
+{
+	unsigned int retry = 12;
+	int old_page;
+	int ret = -1;
+
+	old_page = phy_select_page(phydev, YT8824_RSSR_FIBER_SPACE);
+	if (old_page < 0)
+		goto err_restore_page;
+
+	ret = __phy_read(phydev, MII_BMCR);
+	if (ret < 0)
+		return ret;
+
+	/* disable isolation */
+	ret &= ~BIT(10);
+	/* soft reset */
+	ret |= BMCR_RESET;
+	ret = __phy_write(phydev, MII_BMCR, ret);
+	if (ret < 0)
+		return ret;
+	do {
+		msleep(50);
+		ret = __phy_read(phydev, MII_BMCR);
+		if (ret < 0)
+			return ret;
+	} while ((ret & BMCR_RESET) && --retry);
+
+	if (ret & BMCR_RESET)
+		return -ETIMEDOUT;
+
+err_restore_page:
+	return phy_restore_page(phydev, old_page, 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)
+{
+	int ret;
+
+	if (phydev->interface == PHY_INTERFACE_MODE_INTERNAL) {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			return ret;
+		ret = yt8824_utp_softreset_paged(phydev);
+		if (ret < 0)
+			return ret;
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			return ret;
+	} else {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			return ret;
+
+		/* sds isolation */
+		ret = yt8824_sds_isolate_paged(phydev);
+		if (ret < 0)
+			return ret;
+
+		/* utp soft reset */
+		ret = yt8824_utp_softreset_paged(phydev);
+		if (ret < 0)
+			return ret;
+
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			return ret;
+
+		/* sds soft reset and disable isolation */
+		ret = yt8824_sds_isolate_and_softreset_paged(phydev);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+/**
+ * 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 data = 0;
+	int ret = 0;
+
+	ret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+	/* power down */
+	data = phy_read(phydev, MII_BMCR);
+	if (data < 0)
+		return data;
+	data |= BMCR_PDOWN;
+	ret = phy_write(phydev, MII_BMCR, data);
+	if (ret < 0)
+		return ret;
+
+	/* pll calibration */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0001, 0x0003);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa20e, 0x0cba);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa20a, 0xc3f1);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa20c, 0x1620);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0x0a00);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0x0e00);
+	if (ret < 0)
+		return ret;
+
+	/* optimization utp */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0001, 0x0003);
+	if (ret < 0)
+		return ret;
+
+	/* enable nibble */
+	ret = ytphy_write_ext_with_lock(phydev, 0xa003, 0x0003);
+	if (ret < 0)
+		return ret;
+
+	/* idle err detect enable */
+	ret = ytphy_write_ext_with_lock(phydev, 0x03d0, 0x5210);
+	if (ret < 0)
+		return ret;
+
+	/* optimized 2.5G long cable performance */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0372, 0x5038);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x037c, 0x6068);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0388, 0x00a0);
+	if (ret < 0)
+		return ret;
+
+	/* optimized fast retrain */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0359, 0x2140);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x000c, 0xc1a0);
+	if (ret < 0)
+		return ret;
+
+	/* 2.5G template tone */
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2fa, 0x0083);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x04e2, 0x0149);
+	if (ret < 0)
+		return ret;
+
+	/* optimized 2.5G template */
+	ret = ytphy_write_ext_with_lock(phydev, 0x047e, 0x3939);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x047f, 0x3939);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0480, 0x3939);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0481, 0x3939);
+	if (ret < 0)
+		return ret;
+
+	/* optimized 1000M cable length threshold */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0336, 0xab0a);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0340, 0x301d);
+	if (ret < 0)
+		return ret;
+
+	/* 100M template amplitude */
+	ret = ytphy_write_ext_with_lock(phydev, 0x046e, 0x4545);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x046f, 0x4545);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0470, 0x4545);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0471, 0x4545);
+	if (ret < 0)
+		return ret;
+
+	/* optimized 100M cable length threshold */
+	ret = ytphy_write_ext_with_lock(phydev, 0x030b, 0xaa1d);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x071f, 0x0036);
+	if (ret < 0)
+		return ret;
+
+	/* 10M template amplitude */
+	ret = ytphy_write_ext_with_lock(phydev, 0x046b, 0x1818);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x046c, 0x1818);
+	if (ret < 0)
+		return ret;
+
+	/* optimized 10M cable length threshold */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0466, 0x6c6c);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0467, 0x6c6c);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0468, 0x6c6c);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0469, 0x6c6c);
+	if (ret < 0)
+		return ret;
+
+	/* optimize utp 1000M performance */
+	ret = ytphy_write_ext_with_lock(phydev, 0x034a, 0xff03);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x00f8, 0xb3ff);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0059, 0x4040);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x032c, 0x5094);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x032d, 0xd094);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x032e, 0x5308);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0322, 0x6440);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x04d3, 0x5220);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x04d2, 0x5220);
+	if (ret < 0)
+		return ret;
+
+	/* optimized EMC CS */
+	ret = ytphy_write_ext_with_lock(phydev, 0x00c8, 0xffff);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x00be, 0x6406);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x037a, 0x40ff);
+	if (ret < 0)
+		return ret;
+
+	/* optimized EMC RE */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0482, 0xffff);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d5, 0x1f1f);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d6, 0x1f1f);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d7, 0x1f1f);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d8, 0x1f1f);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa218, 0x006e);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xfff0);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xfff0);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xffff);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xffff);
+	if (ret < 0)
+		return ret;
+
+	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)
+{
+	struct yt8824_shared_priv *shared_priv;
+	int ret = 0, old_page;
+	u16 val_1, val_2, val_3, tmp;
+	u16 data = 0;
+	int port;
+
+	shared_priv = phy_package_get_priv(phydev);
+	port = phydev->mdio.addr - shared_priv->offset;
+	old_page = phy_select_page(phydev, YT8824_RSSR_FIBER_SPACE);
+	if (old_page < 0)
+		goto err_restore_page;
+
+	/* read efuse */
+	val_1 = ytphy_read_top_ext(phydev, 0xa13e);
+	if (val_1 < 0)
+		goto err_restore_page;
+
+	val_2 = ytphy_read_top_ext(phydev, 0xa13f);
+	if (val_2 < 0)
+		goto err_restore_page;
+
+	val_3 = ytphy_read_top_ext(phydev, 0xa140);
+	if (val_3 < 0)
+		goto err_restore_page;
+
+	if (port == 0) {
+		/* 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 */
+	data &= ~YT8824_SDS_CFG_MIN_PRE_MASK;
+	data |= YT8824_SDS_TX_PRE_PADDING;
+	data |= YT8824_SDS_EN_FILL_PRE;
+	ret = __phy_write(phydev, MII_RESV1, data);
+	if (ret < 0)
+		goto err_restore_page;
+
+	data = __phy_read(phydev, MII_BMCR);
+	if (data < 0)
+		goto err_restore_page;
+	data |= BMCR_RESET;
+	data |= BMCR_ANENABLE;
+	ret = __phy_write(phydev, MII_BMCR, data);
+	if (ret < 0)
+		goto err_restore_page;
+
+err_restore_page:
+	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)
+{
+	struct yt8824_shared_priv *shared_priv;
+	int port = 0;
+	int ret = 0;
+	u16 data;
+
+	ret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	shared_priv = phy_package_get_priv(phydev);
+	port = phydev->mdio.addr - shared_priv->offset;
+	ret = ytphy_write_ext_with_lock(phydev, 0x1, 0x3);
+	if (ret < 0)
+		return ret;
+	data = phy_read(phydev, MII_BMCR);
+	if (data < 0)
+		return ret;
+	data |= BMCR_PDOWN;
+	ret = phy_write(phydev, MII_BMCR, data);
+	if (ret < 0)
+		return ret;
+	if (port == 0) {
+		ret = ytphy_write_ext_with_lock(phydev, 0xa20e, 0xcba);
+		if (ret < 0)
+			return ret;
+		ret = ytphy_write_ext_with_lock(phydev, 0xa20a, 0xc3f1);
+		if (ret < 0)
+			return ret;
+		ret = ytphy_write_ext_with_lock(phydev, 0xa20c, 0x1620);
+		if (ret < 0)
+			return ret;
+		ret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0xa00);
+		if (ret < 0)
+			return ret;
+		ret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0xe00);
+		if (ret < 0)
+			return ret;
+		ret = ytphy_write_ext_with_lock(phydev, 0xa003, 0x3);
+		if (ret < 0)
+			return ret;
+	}
+	ret = ytphy_write_ext_with_lock(phydev, 0x3d0, 0x5210);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x372, 0x5038);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x37c, 0x6068);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x388, 0xa0);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x359, 0x2140);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_top_ext_with_lock(phydev, 0xa2fa, 0x83);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x4e2, 0x149);
+	if (ret < 0)
+		return ret;
+	/* 2.5G tempate */
+	ret = ytphy_write_ext_with_lock(phydev, 0x47e, 0x3939);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x47f, 0x3939);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x480, 0x3939);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x481, 0x3939);
+	if (ret < 0)
+		return ret;
+	/* 1000 cable length threshold */
+	ret = ytphy_write_ext_with_lock(phydev, 0x336, 0xab0a);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x340, 0x301d);
+	if (ret < 0)
+		return ret;
+	/* 1000 performance */
+	ret = ytphy_write_ext_with_lock(phydev, 0x34a, 0xff03);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0xf8, 0xb3ff);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x32c, 0x5094);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x32d, 0xd094);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x32e, 0x5308);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x322, 0x6440);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x4d3, 0x5220);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x4d2, 0x5220);
+	if (ret < 0)
+		return ret;
+	/* 100 tempate */
+	ret = ytphy_write_ext_with_lock(phydev, 0x46e, 0x4545);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x46f, 0x4545);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x470, 0x4545);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x471, 0x4545);
+	if (ret < 0)
+		return ret;
+	/* 100 cable length threshold */
+	ret = ytphy_write_ext_with_lock(phydev, 0x30b, 0xaa1d);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x71f, 0x36);
+	if (ret < 0)
+		return ret;
+	/* 10 tempate */
+	ret = ytphy_write_ext_with_lock(phydev, 0x46b, 0x1818);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x46c, 0x1818);
+	if (ret < 0)
+		return ret;
+	/* 10 tempate MAU*/
+	ret = ytphy_write_ext_with_lock(phydev, 0x466, 0x6c6c);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x467, 0x6c6c);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x468, 0x6c6c);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x469, 0x6c6c);
+	if (ret < 0)
+		return ret;
+	/* EMC CS */
+	ret = ytphy_write_ext_with_lock(phydev, 0xc8, 0xfff);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0xbe, 0x6406);
+	if (ret < 0)
+		return ret;
+	ret = ytphy_write_ext_with_lock(phydev, 0x37a, 0x40ff);
+	if (ret < 0)
+		return ret;
+	/* EMC RE*/
+	ret = ytphy_write_ext_with_lock(phydev, 0x482, 0xffff);
+	if (ret < 0)
+		return ret;
+	if (port == 0) {
+		ret = ytphy_write_ext_with_lock(phydev, 0x482, 0xffff);
+		if (ret < 0)
+			return ret;
+		ret = ytphy_write_ext_with_lock(phydev, 0xa2d5, 0x1f1f);
+		if (ret < 0)
+			return ret;
+		ret = ytphy_write_ext_with_lock(phydev, 0xa2d6, 0x1f1f);
+		if (ret < 0)
+			return ret;
+		ret = ytphy_write_ext_with_lock(phydev, 0xa2d7, 0x1f1f);
+		if (ret < 0)
+			return ret;
+		ret = ytphy_write_ext_with_lock(phydev, 0xa2d8, 0x1f1f);
+		if (ret < 0)
+			return ret;
+		ret = ytphy_write_ext_with_lock(phydev, 0xa218, 0x6e);
+		if (ret < 0)
+			return ret;
+		ret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xfff0);
+		if (ret < 0)
+			return ret;
+		ret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xfff0);
+		if (ret < 0)
+			return ret;
+		ret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xffff);
+		if (ret < 0)
+			return ret;
+		ret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xffff);
+		if (ret < 0)
+			return ret;
+	}
+	ret = ytphy_write_ext_with_lock(phydev, 0xc, 0x41a1);
+	if (ret < 0)
+		return ret;
+	ret = genphy_c45_template_testmode(phydev,
+					   YT8824_UTP_TEMPLATE_TEST_MODE1);
+	if (ret)
+		return ret;
+	data = phy_read(phydev, MII_BMCR);
+	if (data < 0)
+		return ret;
+	data |= BMCR_RESET;
+	data |= BMCR_ANENABLE;
+	ret = phy_write(phydev, MII_BMCR, data);
+	if (ret < 0)
+		return ret;
+	ret = genphy_c45_template_testmode(phydev,
+					   YT8824_UTP_TEMPLATE_TEST_NORMAL);
+	if (ret)
+		return ret;
+
+	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)
+{
+	int ret;
+
+	if (phydev->interface == PHY_INTERFACE_MODE_INTERNAL) {
+		ret = yt8824_internal_config_init_paged(phydev);
+		if (ret < 0)
+			return ret;
+	} else {
+		ret = yt8824_extern_config_utp_init_paged(phydev);
+		if (ret < 0)
+			return ret;
+		ret = yt8824_extern_config_sds_init_paged(phydev);
+		if (ret < 0)
+			return ret;
+	}
+	ret = yt8824_soft_reset(phydev);
+	if (ret < 0)
+		return ret;
+
+	phydev_dbg(phydev, "%s done, phy addr: %d\n",
+		   __func__, phydev->mdio.addr);
+
+	return 0;
+}
+
+/**
+ * yt8824_config_intr() - phy8824 interrupt configuration
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_config_intr(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *shared_priv;
+	int ret = 0;
+	int port;
+
+	shared_priv = phy_package_get_priv(phydev);
+	if ((phydev->mdio.addr - shared_priv->offset) < 2)
+		port = 0;
+	else
+		port = 2;
+	ret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+		/* top ext reg 0xa000
+		 * bit6 int_polarity 1'b0 low active, 1'b1 high active
+		 */
+		ret = ytphy_read_top_ext_with_lock(phydev,
+						   YT8521_REG_SPACE_SELECT_REG);
+		if (ret < 0)
+			return ret;
+
+		ret = ytphy_write_top_ext_with_lock(phydev,
+						    YT8521_REG_SPACE_SELECT_REG,
+						    ret & (~BIT(6)));
+		if (ret < 0)
+			return ret;
+
+		/* top ext reg 0xa019
+		 * bit5 intr_phy_pulse_en 1'b0 level, 1'b1 pulse
+		 */
+		ret = ytphy_read_top_ext_with_lock(phydev, 0xa019);
+		if (ret < 0)
+			return ret;
+
+		ret = ytphy_write_top_ext_with_lock(phydev, 0xa019,
+						    ret | BIT(5));
+		if (ret < 0)
+			return ret;
+
+		/* top ext reg 0xa018 phy_pulse_lth bit14:8
+		 * top ext reg 0xa019 timer_tick_sel bit8:7
+		 * bit14:8 phy_pulse_lth bit8:7 timer_tick_sel   pulse width
+		 * 0x007a		0x0002		10ms pulse width
+		 * 0x0064		0x0001		1ms pulse width
+		 * 0x004e		0x0000		100ms pulse width
+		 * 0x0009		0x0000		10ms pulse width
+		 */
+		ret = ytphy_read_top_ext_with_lock(phydev, 0xa018);
+		if (ret < 0)
+			return ret;
+
+		ret &= ~0x7f00;
+		ret |= (0x0009 << 8);
+		ret = ytphy_write_top_ext_with_lock(phydev, 0xa018, ret);
+		if (ret < 0)
+			return ret;
+
+		ret = ytphy_read_top_ext_with_lock(phydev, 0xa019);
+		if (ret < 0)
+			return ret;
+
+		ret &= ~0x180;
+		ret |= (0x0000 << 7);
+		ret = ytphy_write_top_ext_with_lock(phydev, 0xa019, ret);
+		if (ret < 0)
+			return ret;
+
+		/* top ext reg 0xa01c interrupt state(Read Clear)
+		 * bit11 PHY3 1: phy3 link up/down occurs, 0: not occur
+		 * bit10 PHY2 1: phy2 link up/down occurs, 0: not occur
+		 * bit9  PHY1 1: phy1 link up/down occurs, 0: not occur
+		 * bit8  PHY0 1: phy0 link up/down occurs, 0: not occur
+		 *
+		 * bit7  PHY3 1: phy3 link down occurs, 0: not occur
+		 * bit6  PHY2 1: phy2 link down occurs, 0: not occur
+		 * bit5  PHY1 1: phy1 link down occurs, 0: not occur
+		 * bit4  PHY0 1: phy0 link down occurs, 0: not occur
+		 *
+		 * bit3  PHY3 1: phy3 link up occurs, 0: not occur
+		 * bit2  PHY2 1: phy2 link up occurs, 0: not occur
+		 * bit1  PHY1 1: phy1 link up occurs, 0: not occur
+		 * bit0  PHY0 1: phy0 link up occurs, 0: not occur
+		 */
+		ret = ytphy_read_top_ext_with_lock(phydev, 0xa01c);
+		if (ret < 0)
+			return ret;
+
+		/* top ext reg 0xa01a
+		 * bit5 intn_wol_mode 1'b1 enable intn_wol pin output
+		 * bit4 intn_mode 1'b1 enable intn pin output
+		 */
+		ret = ytphy_read_top_ext_with_lock(phydev, 0xa01a);
+		if (ret < 0)
+			return ret;
+
+		ret &= ~BIT(5);
+		ret |= BIT(4);
+		ret = ytphy_write_top_ext_with_lock(phydev, 0xa01a, ret);
+		if (ret < 0)
+			return ret;
+
+		/* top ext reg 0xa01b interrupt mask
+		 * bit11 1'b1 enable interrupt signal(link up/down) to intr pin
+		 * bit7 1'b1 enable interrupt signal(link down) to intr pin
+		 * bit3 1'b1 enable interrupt signal(link up) to intr pin
+		 *
+		 * bit10 1'b1 enable interrupt signal(link up/down) to intr pin
+		 * bit6 1'b1 enable interrupt signal(link down) to intr pin
+		 * bit2 1'b1 enable interrupt signal(link up) to intr pin
+		 *
+		 * bit9 1'b1 enable interrupt signal(link up/down) to intr pin
+		 * bit5 1'b1 enable interrupt signal(link down) to intr pin
+		 * bit1 1'b1 enable interrupt signal(link up) to intr pin
+		 *
+		 * bit8 1'b1 enable interrupt signal(link up/down) to intr pin
+		 * bit4 1'b1 enable interrupt signal(link down) to intr pin
+		 * bit0 1'b1 enable interrupt signal(link up) to intr pin
+		 */
+		ret = ytphy_read_top_ext_with_lock(phydev, 0xa01b);
+		if (ret < 0)
+			return ret;
+
+		ret |= (BIT(port + 8) | BIT(port + 4) | BIT(port));
+		ret = ytphy_write_top_ext_with_lock(phydev, 0xa01b, ret);
+		if (ret < 0)
+			return ret;
+	}
+	return ret;
+}
+
+/**
+ * yt8824_handle_interrupt() - phy8824 interrupt handle
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static irqreturn_t yt8824_handle_interrupt(struct phy_device *phydev)
+{
+	int ret = 0;
+
+	ret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	/* top ext reg 0xa01c interrupt state(Read Clear)
+	 * bit11 PHY3 interrupt 1: phy3 link up/down happened, 0: not happened
+	 * bit10 PHY2 interrupt 1: phy2 link up/down happened, 0: not happened
+	 * bit9  PHY1 interrupt 1: phy1 link up/down happened, 0: not happened
+	 * bit8  PHY0 interrupt 1: phy0 link up/down happened, 0: not happened
+	 * bit7  PHY3 link down 1: phy3 link down happened, 0: not happened
+	 * bit6  PHY2 link down 1: phy2 link down happened, 0: not happened
+	 * bit5  PHY1 link down 1: phy1 link down happened, 0: not happened
+	 * bit4  PHY0 link down 1: phy0 link down happened, 0: not happened
+	 * bit3  PHY3 link up 1: phy3 link up happened, 0: not happened
+	 * bit2  PHY2 link up 1: phy2 link up happened, 0: not happened
+	 * bit1  PHY1 link up 1: phy1 link up happened, 0: not happened
+	 * bit0  PHY0 link up 1: phy0 link up happened, 0: not happened
+	 */
+	ret = ytphy_read_top_ext_with_lock(phydev, 0xa01c);
+	if (ret < 0)
+		return ret;
+	phy_trigger_machine(phydev);
+	if (ret > 0)
+		return IRQ_HANDLED;
+	else
+		return IRQ_NONE;
 }
 
 static int yt8531_set_wol(struct phy_device *phydev,
@@ -3059,6 +4352,371 @@ static int yt8821_resume(struct phy_device *phydev)
 	return yt8821_modify_utp_fiber_bmcr(phydev, BMCR_PDOWN, 0);
 }
 
+/**
+ * yt8824_aneg_done()  - check negotiation state.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_aneg_done(struct phy_device *phydev)
+{
+	int link = 0;
+	int ret = 0;
+
+	ret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	link = !!(phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG) &
+			     YTPHY_SSR_LINK);
+
+	phydev_dbg(phydev, "%s, phy addr: %d, link_utp: %d\n",
+		   __func__, phydev->mdio.addr, link);
+
+	return link;
+}
+
+/**
+ * yt8824_read_status_paged() -  determines the speed and duplex of one page
+ * @phydev: a pointer to a &struct phy_device
+ * @status: The link status, include speed, duplex and link state.
+ * @lpa: link partner advertising.
+ *
+ * Returns: 1 (utp link),0 (no link) or negative errno code
+ */
+static int yt8824_read_status_paged(struct phy_device *phydev,
+				    int *status, int *lpa)
+{
+	int ret = 0;
+
+	ret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	ret = phy_read(phydev, MII_LPA);
+	*lpa = ret;
+	if (ret < 0)
+		return ret;
+
+	ret = phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG);
+	*status = ret;
+	if (ret < 0)
+		return ret;
+
+	ret = !!(*status & YTPHY_SSR_LINK);
+
+	return ret;
+}
+
+/**
+ * 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)
+{
+	int link;
+	int lpa;
+	int val;
+
+	phydev->pause = 0;
+	phydev->asym_pause = 0;
+	phydev->link = 0;
+	phydev->speed = SPEED_UNKNOWN;
+	phydev->duplex = DUPLEX_UNKNOWN;
+
+	link = yt8824_read_status_paged(phydev,
+					&val, &lpa);
+	if (link < 0)
+		return link;
+
+	if (link) {
+		phydev->link = 1;
+		phydev->pause = !!(lpa & BIT(10));
+		phydev->asym_pause = !!(lpa & BIT(11));
+
+		/* update speed & duplex */
+		yt8821_adjust_status(phydev, val);
+	} else {
+		phydev->link = 0;
+		phydev->pause = 0;
+		phydev->asym_pause = 0;
+		phydev->speed = SPEED_UNKNOWN;
+		phydev->duplex = DUPLEX_UNKNOWN;
+	}
+
+	return 0;
+}
+
+/**
+ * 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_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	ret = phy_read(phydev, MII_BMCR);
+	if (ret < 0)
+		return ret;
+
+	ret &= ~BMCR_PDOWN;
+	ret &= ~BMCR_ISOLATE;
+
+	return phy_write(phydev, MII_BMCR, ret);
+}
+
+/**
+ * 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 = 0;
+
+	ret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	ret = phy_read(phydev, MII_BMCR);
+	if (ret < 0)
+		return ret;
+
+	return phy_write(phydev, MII_BMCR, ret | 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)
+{
+	int ret;
+
+	if (phydev->interface == PHY_INTERFACE_MODE_INTERNAL) {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			return ret;
+		/* utp power on */
+		ret = yt8824_utp_power_on(phydev);
+		if (ret < 0)
+			return ret;
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			return ret;
+	} else {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			return ret;
+
+		/* sds isolation */
+		ret = yt8824_sds_isolate_paged(phydev);
+		if (ret < 0)
+			return ret;
+
+		/* utp power on */
+		ret = yt8824_utp_power_on(phydev);
+		if (ret < 0)
+			return ret;
+
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			return ret;
+
+		/* sds soft reset and disable isolation */
+		ret = yt8824_sds_isolate_and_softreset_paged(phydev);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+/**
+ * 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)
+{
+	return yt8824_power_on(phydev);
+}
+
+/**
+ * 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)
+{
+	int ret;
+
+	if (phydev->interface == PHY_INTERFACE_MODE_INTERNAL) {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			return ret;
+		/* utp power down */
+		ret = yt8824_utp_power_down(phydev);
+		if (ret < 0)
+			return ret;
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			return ret;
+	} else {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			return ret;
+
+		/* sds isolation */
+		ret = yt8824_sds_isolate_paged(phydev);
+		if (ret < 0)
+			return ret;
+
+		/* utp power down */
+		ret = yt8824_utp_power_down(phydev);
+		if (ret < 0)
+			return ret;
+
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			return ret;
+
+		/* sds soft reset and disable isolation */
+		ret = yt8824_sds_isolate_and_softreset_paged(phydev);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+/**
+ * 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)
+{
+	return yt8824_power_down(phydev);
+}
+
+/**
+ * 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)
+{
+	int phy_ctrl = 0;
+	int ret = 0;
+
+	ret = phy8824_page_write_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	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)
+		return ret;
+
+	return genphy_config_aneg(phydev);
+}
+
+/**
+ * yt8824_phy_package_probe_once()  - init phy packet 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;
+
+	priv->interface_mode = PHY_INTERFACE_MODE_NA;
+	priv->offset = INTERNAL_PHY8824_TOP_EXTEND_OFFSET;
+	if (!of_property_read_string(np, "motorcomm,interface-mode",
+				     &interface_mode_name)) {
+		if (!strcasecmp(interface_mode_name,
+				phy_modes(PHY_INTERFACE_MODE_USXGMII))) {
+			priv->interface_mode = PHY_INTERFACE_MODE_USXGMII;
+			priv->offset = EXTERNAL_PHY8824_TOP_EXTEND_OFFSET;
+		} else if (!strcasecmp
+				(interface_mode_name,
+				 phy_modes(PHY_INTERFACE_MODE_INTERNAL))) {
+			priv->interface_mode = PHY_INTERFACE_MODE_INTERNAL;
+			priv->offset = INTERNAL_PHY8824_TOP_EXTEND_OFFSET;
+		} else {
+			return -EINVAL;
+		}
+	}
+	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;
+	struct yt8521_priv *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;
+	}
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	phydev->priv = priv;
+
+	return 0;
+}
+
 static struct phy_driver motorcomm_phy_drvs[] = {
 	{
 		PHY_ID_MATCH_EXACT(PHY_ID_YT8511),
@@ -3145,13 +4803,31 @@ 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		= yt8821_get_features,
+		.read_page		= yt8824_read_page,
+		.write_page		= yt8824_write_page,
+		.config_intr            = yt8824_config_intr,
+		.handle_interrupt	= yt8824_handle_interrupt,
+		.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[] = {
@@ -3161,6 +4837,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 1269517414288f..e77b503899ee0d 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -1283,6 +1283,26 @@ 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 Test mode 1 to Test mode 7
+ *
+ * Description: Set template testmode include Test mode 1 to Test mode 7
+ */
+int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode)
+{
+	int ctrl;
+
+	ctrl = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TEMPLATE);
+	if (ctrl < 0)
+		return ctrl;
+	ctrl &= ~(0x7 << 13);
+	ctrl |= test_mode << 13;
+	return phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TEMPLATE, 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 fc680901275b73..7c02cc6970ae11 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -2330,6 +2330,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 b2541c948fc1eb..5ae91cdf024c8e 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_TEMPLATE 132	/* Template 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 */

3/2 2026/07/26 00:05 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 24911
							output: 18
							thoughts: 254
						

Thoughts:
**Fuzzing the Motorcomm YT8824 PHY Driver**

Okay, so we've got a patch here that adds support for the Motorcomm YT8824, a quad-port 2.5Gbps Ethernet PHY driver. It's touching `drivers/net/phy/motorcomm.c`, `drivers/net/phy/phy-c45.c`, `include/linux/phy.h`, and `include/uapi/linux/mdio.h`. My immediate thought is, "Can we fuzz this thing?"

Being a PHY driver, it's pretty likely we can get to it through an MDIO bus. Those are usually accessible via emulation or through virtual network interfaces. Thinking QEMU, `macb`, `stmmac`... we should be able to create a dummy MDIO bus, too. Now, the real question is, does syzkaller play nice with PHY drivers? Can we even get it to target this code?

Wait, wasn't there some limited support for MDIO/PHY fuzzing in syzkaller? I seem to remember network device ioctls like `SIOCGMIIREG` and `SIOCSMIIREG` being able to reach PHY drivers if a virtual device has a PHY attached. And what about netlink interfaces? They should be able to configure PHYs as well.

Alright, before I dive too deep, let's make sure the `MOTORCOMM_PHY` option is even enabled or can be enabled. I'll search the Kconfig files. This will tell me if we even have a chance of fuzzing this thing.



4/2 2026/07/26 00:05 tool grepper
0m Args:
{
  "Expression": "MOTORCOMM_PHY"
}

Results:
{
  "Output": "arch/loongarch/configs/loongson32_defconfig=626=CONFIG_TXGBE=y\n--\narch/loongarch/configs/loongson32_defconfig-628-# CONFIG_NET_VENDOR_XILINX is not set\narch/loongarch/configs/loongson32_defconfig:629:CONFIG_MOTORCOMM_PHY=y\narch/loongarch/configs/loongson32_defconfig-630-CONFIG_PPP=m\n--\narch/loongarch/configs/loongson64_defconfig=642=CONFIG_TXGBE=y\n--\narch/loongarch/configs/loongson64_defconfig-644-# CONFIG_NET_VENDOR_XILINX is not set\narch/loongarch/configs/loongson64_defconfig:645:CONFIG_MOTORCOMM_PHY=y\narch/loongarch/configs/loongson64_defconfig-646-CONFIG_PPP=m\n--\narch/riscv/configs/defconfig=144=CONFIG_MICROSEMI_PHY=y\narch/riscv/configs/defconfig:145:CONFIG_MOTORCOMM_PHY=y\narch/riscv/configs/defconfig-146-CONFIG_INPUT_MOUSEDEV=y\n--\ndrivers/net/ethernet/hisilicon/Kconfig=147=config HIBMCGE\n--\ndrivers/net/ethernet/hisilicon/Kconfig-151-\tselect FIXED_PHY\ndrivers/net/ethernet/hisilicon/Kconfig:152:\tselect MOTORCOMM_PHY\ndrivers/net/ethernet/hisilicon/Kconfig-153-\tselect REALTEK_PHY\n--\ndrivers/net/ethernet/stmicro/stmmac/Kconfig=398=config DWMAC_MOTORCOMM\n--\ndrivers/net/ethernet/stmicro/stmmac/Kconfig-400-\tdepends on PCI\ndrivers/net/ethernet/stmicro/stmmac/Kconfig:401:\tselect MOTORCOMM_PHY\ndrivers/net/ethernet/stmicro/stmmac/Kconfig-402-\tselect STMMAC_LIBPCI\n--\ndrivers/net/phy/Kconfig=338=config MICROSEMI_PHY\n--\ndrivers/net/phy/Kconfig-346-\ndrivers/net/phy/Kconfig:347:config MOTORCOMM_PHY\ndrivers/net/phy/Kconfig-348-\ttristate \"Motorcomm PHYs\"\n--\ndrivers/net/phy/Makefile=82=obj-$(CONFIG_MICROSEMI_PHY)\t+= mscc/\ndrivers/net/phy/Makefile:83:obj-$(CONFIG_MOTORCOMM_PHY)\t+= motorcomm.o\ndrivers/net/phy/Makefile-84-obj-$(CONFIG_NATIONAL_PHY)\t+= national.o\n"
}

5/2 2026/07/26 00:05 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 26245
							output: 19
							thoughts: 1339
						

Thoughts:
**Fuzzing the YT8824 PHY Driver: A Deep Dive**

Okay, so I'm looking at this `CONFIG_MOTORCOMM_PHY` option.  First, the question is always: can I actually reach this thing in QEMU? Yes, PHY drivers are reachable; the key is either registering an MDIO device and binding to it, or using virtual network drivers that instantiate PHYs directly. Syzkaller gives me options like `syz_genetlink_get_family` and other interactions with PHYs, as well as the classic `ioctl(SIOCSMIIREG)` on a netdev that has a PHY.

Now, a crucial question: does Syzkaller actually *effectively* fuzz these PHY drivers?  I'm thinking, yeah, through MDIO ioctls or even netlink. Good.  Time to get specific. I need to list the functions that were added or modified in the patch:

*   `yt8824_read_page`
*   `yt8824_write_page`
*   `yt8824_config_intr`
*   `yt8824_handle_interrupt`
*   `yt8824_probe`
*   `yt8824_config_aneg`
*   `yt8824_aneg_done`
*   `yt8824_config_init`
*   `yt8824_read_status`
*   `yt8824_soft_reset`
*   `yt8824_suspend`
*   `yt8824_resume`

Alright, let's nail down the API entry points.  I can find them in the `struct phy_driver` callbacks.  That's where the rubber meets the road.  Here's the relevant `struct`:

```c
	{
		PHY_ID_MATCH_EXACT(PHY_ID_YT8824),
		.name			= "YT8824 Quad Ports 2.5Gbps Ethernet",
		.get_features		= yt8821_get_features,
		.read_page		= yt8824_read_page,
		.write_page		= yt8824_write_page,
		.config_intr            = yt8824_config_intr,
		.handle_interrupt	= yt8824_handle_interrupt,
		.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,
	},
```

So, the key functions that will be the focus of my fuzzing are:

*   `yt8824_read_page`
*   `yt8824_write_page`
*   `yt8824_config_intr`
*   `yt8824_handle_interrupt`
*   `yt8824_probe`
*   `yt8824_config_aneg`
*   `yt8824_aneg_done`
*   `yt8824_config_init`
*   `yt8824_read_status`
*   `yt8824_soft_reset`
*   `yt8824_suspend`
*   `yt8824_resume`

Next, I need to check if `yt8824_probe` and others are static. Yup, they all are. Now, while static, as function pointers in the `struct phy_driver`, they are very unlikely to be inlined and therefore very much fuzzeable!

And now: is `genphy_c45_template_testmode` exported? Yes! `EXPORT_SYMBOL_GPL(genphy_c45_template_testmode);`.

Back to the configs. Is `CONFIG_MOTORCOMM_PHY` sufficient? Yes, it seems to be. And of course I need `CONFIG_PHYLIB` which is a core config.

Important


6/2 2026/07/26 00:05 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "mdio-mockup"
}

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

7/2 2026/07/26 00:05 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 28642
							output: 17
							thoughts: 39
						

Thoughts:
Okay, let's see. My initial instinct is to look at the mockup MDIO driver first, see if there's anything useful there for testing. Nope, nothing immediately jumps out from the `drivers/net/phy/mdio-mockup.c` file that seems relevant. Alright, maybe a more standard fixed PHY driver could offer some clues. I'll switch gears and examine `drivers/net/phy/fixed_phy.c` next. Hopefully, something will reveal itself there.



8/2 2026/07/26 00:05 tool grepper
0m Args:
{
  "Expression": "fixed_phy"
}

Results:
{
  "Output": "drivers/net/dsa/dsa_loop.c=438=static void dsa_loop_phydevs_unregister(void)\n--\ndrivers/net/dsa/dsa_loop.c-441-\t\tif (!IS_ERR(phydevs[i]))\ndrivers/net/dsa/dsa_loop.c:442:\t\t\tfixed_phy_unregister(phydevs[i]);\ndrivers/net/dsa/dsa_loop.c-443-\t}\n--\ndrivers/net/dsa/dsa_loop.c=482=static int __init dsa_loop_init(void)\n--\ndrivers/net/dsa/dsa_loop.c-491-\tfor (i = 0; i \u003c NUM_FIXED_PHYS; i++)\ndrivers/net/dsa/dsa_loop.c:492:\t\tphydevs[i] = fixed_phy_register_100fd();\ndrivers/net/dsa/dsa_loop.c-493-\n--\ndrivers/net/ethernet/broadcom/b44.c=2234=static int b44_register_phy_one(struct b44 *bp)\n--\ndrivers/net/ethernet/broadcom/b44.c-2272-\ndrivers/net/ethernet/broadcom/b44.c:2273:\t\tphydev = fixed_phy_register_100fd();\ndrivers/net/ethernet/broadcom/b44.c-2274-\t\tif (!IS_ERR(phydev))\n--\ndrivers/net/ethernet/broadcom/b44.c=2313=static void b44_unregister_phy_one(struct b44 *bp)\n--\ndrivers/net/ethernet/broadcom/b44.c-2322-\tif (phy_is_pseudo_fixed_link(phydev))\ndrivers/net/ethernet/broadcom/b44.c:2323:\t\tfixed_phy_unregister(phydev);\ndrivers/net/ethernet/broadcom/b44.c-2324-\tmdiobus_unregister(mii_bus);\n--\ndrivers/net/ethernet/broadcom/bgmac.c=1439=int bgmac_phy_connect_direct(struct bgmac *bgmac)\ndrivers/net/ethernet/broadcom/bgmac.c-1440-{\ndrivers/net/ethernet/broadcom/bgmac.c:1441:\tstruct fixed_phy_status fphy_status = {\ndrivers/net/ethernet/broadcom/bgmac.c-1442-\t\t.link = 1,\n--\ndrivers/net/ethernet/broadcom/bgmac.c-1448-\ndrivers/net/ethernet/broadcom/bgmac.c:1449:\tphy_dev = fixed_phy_register(\u0026fphy_status, NULL);\ndrivers/net/ethernet/broadcom/bgmac.c-1450-\tif (IS_ERR(phy_dev)) {\n--\ndrivers/net/ethernet/broadcom/genet/bcmmii.c=97=void bcmgenet_mii_setup(struct net_device *dev)\n--\ndrivers/net/ethernet/broadcom/genet/bcmmii.c-116-\ndrivers/net/ethernet/broadcom/genet/bcmmii.c:117:static int bcmgenet_fixed_phy_link_update(struct net_device *dev,\ndrivers/net/ethernet/broadcom/genet/bcmmii.c:118:\t\t\t\t\t  struct fixed_phy_status *status)\ndrivers/net/ethernet/broadcom/genet/bcmmii.c-119-{\n--\ndrivers/net/ethernet/broadcom/genet/bcmmii.c=186=static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)\n--\ndrivers/net/ethernet/broadcom/genet/bcmmii.c-188-\tif (bcmgenet_has_moca_link_det(priv))\ndrivers/net/ethernet/broadcom/genet/bcmmii.c:189:\t\tfixed_phy_set_link_update(priv-\u003edev-\u003ephydev,\ndrivers/net/ethernet/broadcom/genet/bcmmii.c:190:\t\t\t\t\t  bcmgenet_fixed_phy_link_update);\ndrivers/net/ethernet/broadcom/genet/bcmmii.c-191-}\n--\ndrivers/net/ethernet/faraday/ftgmac100.c=43=struct ftgmac100_match_data {\n--\ndrivers/net/ethernet/faraday/ftgmac100.c-66-/* For NC-SI to register a fixed-link phy device */\ndrivers/net/ethernet/faraday/ftgmac100.c:67:static struct fixed_phy_status ncsi_phy_status = {\ndrivers/net/ethernet/faraday/ftgmac100.c-68-\t.link = 1,\n--\ndrivers/net/ethernet/faraday/ftgmac100.c=1780=static void ftgmac100_phy_disconnect(struct net_device *netdev)\n--\ndrivers/net/ethernet/faraday/ftgmac100.c-1792-\tif (priv-\u003euse_ncsi)\ndrivers/net/ethernet/faraday/ftgmac100.c:1793:\t\tfixed_phy_unregister(phydev);\ndrivers/net/ethernet/faraday/ftgmac100.c-1794-}\n--\ndrivers/net/ethernet/faraday/ftgmac100.c=1848=static int ftgmac100_probe_ncsi(struct net_device *netdev,\n--\ndrivers/net/ethernet/faraday/ftgmac100.c-1866-\ndrivers/net/ethernet/faraday/ftgmac100.c:1867:\tphydev = fixed_phy_register(\u0026ncsi_phy_status, np);\ndrivers/net/ethernet/faraday/ftgmac100.c-1868-\tif (IS_ERR(phydev)) {\n--\ndrivers/net/ethernet/faraday/ftgmac100.c-1881-err_register_phy:\ndrivers/net/ethernet/faraday/ftgmac100.c:1882:\tfixed_phy_unregister(phydev);\ndrivers/net/ethernet/faraday/ftgmac100.c-1883-err_register_ndev:\n--\ndrivers/net/ethernet/freescale/fec_main.c=2981=static int fec_enet_mii_probe(struct net_device *ndev)\n--\ndrivers/net/ethernet/freescale/fec_main.c-3002-\t\t\tnetdev_info(ndev, \"no PHY, assuming direct connection to switch\\n\");\ndrivers/net/ethernet/freescale/fec_main.c:3003:\t\t\tphy_dev = fixed_phy_register_100fd();\ndrivers/net/ethernet/freescale/fec_main.c-3004-\t\t\tif (IS_ERR(phy_dev)) {\n--\ndrivers/net/ethernet/freescale/fec_main.c-3013-\t\t\tif (phy_is_pseudo_fixed_link(phy_dev))\ndrivers/net/ethernet/freescale/fec_main.c:3014:\t\t\t\tfixed_phy_unregister(phy_dev);\ndrivers/net/ethernet/freescale/fec_main.c-3015-\t\t\tnetdev_err(ndev, \"could not attach to PHY\\n\");\n--\ndrivers/net/ethernet/freescale/fec_main.c=4228=fec_enet_close(struct net_device *ndev)\n--\ndrivers/net/ethernet/freescale/fec_main.c-4243-\tif (!fep-\u003ephy_node \u0026\u0026 phy_is_pseudo_fixed_link(phy_dev))\ndrivers/net/ethernet/freescale/fec_main.c:4244:\t\tfixed_phy_unregister(phy_dev);\ndrivers/net/ethernet/freescale/fec_main.c-4245-\n--\ndrivers/net/ethernet/freescale/gianfar.c=3138=static const struct net_device_ops gfar_netdev_ops = {\n--\ndrivers/net/ethernet/freescale/gianfar.c-3147-\t.ndo_get_stats64 = gfar_get_stats64,\ndrivers/net/ethernet/freescale/gianfar.c:3148:\t.ndo_change_carrier = fixed_phy_change_carrier,\ndrivers/net/ethernet/freescale/gianfar.c-3149-\t.ndo_set_mac_address = gfar_set_mac_addr,\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c=228=void hbg_phy_stop(struct hbg_priv *priv)\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-232-\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:233:static void hbg_fixed_phy_uninit(void *data)\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-234-{\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:235:\tfixed_phy_unregister((struct phy_device *)data);\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-236-}\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-237-\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:238:static int hbg_fixed_phy_init(struct hbg_priv *priv)\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-239-{\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:240:\tstruct fixed_phy_status hbg_fixed_phy_status = {\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-241-\t\t.link = 1,\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-250-\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:251:\tphydev = fixed_phy_register(\u0026hbg_fixed_phy_status, NULL);\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-252-\tif (IS_ERR(phydev)) {\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-257-\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:258:\tret = devm_add_action_or_reset(dev, hbg_fixed_phy_uninit, phydev);\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-259-\tif (ret)\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c=266=int hbg_mdio_init(struct hbg_priv *priv)\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-275-\tif (mac-\u003ephy_addr == HBG_NO_PHY)\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:276:\t\treturn hbg_fixed_phy_init(priv);\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-277-\n--\ndrivers/net/mdio/of_mdio.c=412=int of_phy_register_fixed_link(struct device_node *np)\ndrivers/net/mdio/of_mdio.c-413-{\ndrivers/net/mdio/of_mdio.c:414:\tstruct fixed_phy_status status = {};\ndrivers/net/mdio/of_mdio.c-415-\tstruct device_node *fixed_link_node;\n--\ndrivers/net/mdio/of_mdio.c-459-register_phy:\ndrivers/net/mdio/of_mdio.c:460:\treturn PTR_ERR_OR_ZERO(fixed_phy_register(\u0026status, np));\ndrivers/net/mdio/of_mdio.c-461-}\n--\ndrivers/net/mdio/of_mdio.c=464=void of_phy_deregister_fixed_link(struct device_node *np)\n--\ndrivers/net/mdio/of_mdio.c-471-\ndrivers/net/mdio/of_mdio.c:472:\tfixed_phy_unregister(phydev);\ndrivers/net/mdio/of_mdio.c-473-\n--\ndrivers/net/phy/Makefile=63=obj-$(CONFIG_DP83TG720_PHY)\t+= dp83tg720.o\ndrivers/net/phy/Makefile:64:obj-$(CONFIG_FIXED_PHY)\t\t+= fixed_phy.o\ndrivers/net/phy/Makefile-65-obj-$(CONFIG_ICPLUS_PHY)\t+= icplus.o\n--\ndrivers/net/phy/fixed_phy.c-27-\ndrivers/net/phy/fixed_phy.c:28:struct fixed_phy {\ndrivers/net/phy/fixed_phy.c-29-\tstruct phy_device *phydev;\ndrivers/net/phy/fixed_phy.c:30:\tstruct fixed_phy_status status;\ndrivers/net/phy/fixed_phy.c:31:\tint (*link_update)(struct net_device *, struct fixed_phy_status *);\ndrivers/net/phy/fixed_phy.c-32-};\ndrivers/net/phy/fixed_phy.c-33-\ndrivers/net/phy/fixed_phy.c:34:static DECLARE_BITMAP(fixed_phy_ids, NUM_FP);\ndrivers/net/phy/fixed_phy.c:35:static struct fixed_phy fmb_fixed_phys[NUM_FP];\ndrivers/net/phy/fixed_phy.c-36-static struct mii_bus *fmb_mii_bus;\ndrivers/net/phy/fixed_phy.c-37-\ndrivers/net/phy/fixed_phy.c:38:static struct fixed_phy *fixed_phy_find(int addr)\ndrivers/net/phy/fixed_phy.c-39-{\ndrivers/net/phy/fixed_phy.c:40:\treturn test_bit(addr, fixed_phy_ids) ? fmb_fixed_phys + addr : NULL;\ndrivers/net/phy/fixed_phy.c-41-}\ndrivers/net/phy/fixed_phy.c-42-\ndrivers/net/phy/fixed_phy.c:43:int fixed_phy_change_carrier(struct net_device *dev, bool new_carrier)\ndrivers/net/phy/fixed_phy.c-44-{\ndrivers/net/phy/fixed_phy.c-45-\tstruct phy_device *phydev = dev-\u003ephydev;\ndrivers/net/phy/fixed_phy.c:46:\tstruct fixed_phy *fp;\ndrivers/net/phy/fixed_phy.c-47-\n--\ndrivers/net/phy/fixed_phy.c-50-\ndrivers/net/phy/fixed_phy.c:51:\tfp = fixed_phy_find(phydev-\u003emdio.addr);\ndrivers/net/phy/fixed_phy.c-52-\tif (!fp)\n--\ndrivers/net/phy/fixed_phy.c-58-}\ndrivers/net/phy/fixed_phy.c:59:EXPORT_SYMBOL_GPL(fixed_phy_change_carrier);\ndrivers/net/phy/fixed_phy.c-60-\ndrivers/net/phy/fixed_phy.c=61=static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num)\ndrivers/net/phy/fixed_phy.c-62-{\ndrivers/net/phy/fixed_phy.c:63:\tstruct fixed_phy *fp;\ndrivers/net/phy/fixed_phy.c-64-\ndrivers/net/phy/fixed_phy.c:65:\tfp = fixed_phy_find(phy_addr);\ndrivers/net/phy/fixed_phy.c-66-\tif (!fp)\n--\ndrivers/net/phy/fixed_phy.c=75=static int fixed_mdio_write(struct mii_bus *bus, int phy_addr, int reg_num,\n--\ndrivers/net/phy/fixed_phy.c-85- */\ndrivers/net/phy/fixed_phy.c:86:int fixed_phy_set_link_update(struct phy_device *phydev,\ndrivers/net/phy/fixed_phy.c-87-\t\t\t      int (*link_update)(struct net_device *,\ndrivers/net/phy/fixed_phy.c:88:\t\t\t\t\t\t struct fixed_phy_status *))\ndrivers/net/phy/fixed_phy.c-89-{\ndrivers/net/phy/fixed_phy.c:90:\tstruct fixed_phy *fp;\ndrivers/net/phy/fixed_phy.c-91-\n--\ndrivers/net/phy/fixed_phy.c-94-\ndrivers/net/phy/fixed_phy.c:95:\tfp = fixed_phy_find(phydev-\u003emdio.addr);\ndrivers/net/phy/fixed_phy.c-96-\tif (!fp)\n--\ndrivers/net/phy/fixed_phy.c-103-}\ndrivers/net/phy/fixed_phy.c:104:EXPORT_SYMBOL_GPL(fixed_phy_set_link_update);\ndrivers/net/phy/fixed_phy.c-105-\ndrivers/net/phy/fixed_phy.c:106:static void fixed_phy_del(int phy_addr)\ndrivers/net/phy/fixed_phy.c-107-{\ndrivers/net/phy/fixed_phy.c:108:\tstruct fixed_phy *fp;\ndrivers/net/phy/fixed_phy.c-109-\ndrivers/net/phy/fixed_phy.c:110:\tfp = fixed_phy_find(phy_addr);\ndrivers/net/phy/fixed_phy.c-111-\tif (!fp)\n--\ndrivers/net/phy/fixed_phy.c-114-\tmemset(fp, 0, sizeof(*fp));\ndrivers/net/phy/fixed_phy.c:115:\tclear_bit(phy_addr, fixed_phy_ids);\ndrivers/net/phy/fixed_phy.c-116-}\ndrivers/net/phy/fixed_phy.c-117-\ndrivers/net/phy/fixed_phy.c:118:static int fixed_phy_get_free_addr(void)\ndrivers/net/phy/fixed_phy.c-119-{\n--\ndrivers/net/phy/fixed_phy.c-122-\tdo {\ndrivers/net/phy/fixed_phy.c:123:\t\taddr = find_first_zero_bit(fixed_phy_ids, NUM_FP);\ndrivers/net/phy/fixed_phy.c-124-\t\tif (addr == NUM_FP)\ndrivers/net/phy/fixed_phy.c-125-\t\t\treturn -ENOSPC;\ndrivers/net/phy/fixed_phy.c:126:\t} while (test_and_set_bit(addr, fixed_phy_ids));\ndrivers/net/phy/fixed_phy.c-127-\n--\ndrivers/net/phy/fixed_phy.c-130-\ndrivers/net/phy/fixed_phy.c:131:struct phy_device *fixed_phy_register(const struct fixed_phy_status *status,\ndrivers/net/phy/fixed_phy.c-132-\t\t\t\t      struct device_node *np)\n--\ndrivers/net/phy/fixed_phy.c-145-\t/* Get the next available PHY address, up to NUM_FP */\ndrivers/net/phy/fixed_phy.c:146:\tphy_addr = fixed_phy_get_free_addr();\ndrivers/net/phy/fixed_phy.c-147-\tif (phy_addr \u003c 0)\n--\ndrivers/net/phy/fixed_phy.c-149-\ndrivers/net/phy/fixed_phy.c:150:\tfmb_fixed_phys[phy_addr].status = *status;\ndrivers/net/phy/fixed_phy.c:151:\tfmb_fixed_phys[phy_addr].status.link = true;\ndrivers/net/phy/fixed_phy.c-152-\n--\ndrivers/net/phy/fixed_phy.c-154-\tif (IS_ERR(phy)) {\ndrivers/net/phy/fixed_phy.c:155:\t\tfixed_phy_del(phy_addr);\ndrivers/net/phy/fixed_phy.c-156-\t\treturn ERR_PTR(-EINVAL);\n--\ndrivers/net/phy/fixed_phy.c-166-\t\tof_node_put(np);\ndrivers/net/phy/fixed_phy.c:167:\t\tfixed_phy_del(phy_addr);\ndrivers/net/phy/fixed_phy.c-168-\t\treturn ERR_PTR(ret);\n--\ndrivers/net/phy/fixed_phy.c-172-}\ndrivers/net/phy/fixed_phy.c:173:EXPORT_SYMBOL_GPL(fixed_phy_register);\ndrivers/net/phy/fixed_phy.c-174-\ndrivers/net/phy/fixed_phy.c:175:struct phy_device *fixed_phy_register_100fd(void)\ndrivers/net/phy/fixed_phy.c-176-{\ndrivers/net/phy/fixed_phy.c:177:\tstatic const struct fixed_phy_status status = {\ndrivers/net/phy/fixed_phy.c-178-\t\t.speed\t= SPEED_100,\n--\ndrivers/net/phy/fixed_phy.c-181-\ndrivers/net/phy/fixed_phy.c:182:\treturn fixed_phy_register(\u0026status, NULL);\ndrivers/net/phy/fixed_phy.c-183-}\ndrivers/net/phy/fixed_phy.c:184:EXPORT_SYMBOL_GPL(fixed_phy_register_100fd);\ndrivers/net/phy/fixed_phy.c-185-\ndrivers/net/phy/fixed_phy.c:186:void fixed_phy_unregister(struct phy_device *phy)\ndrivers/net/phy/fixed_phy.c-187-{\n--\ndrivers/net/phy/fixed_phy.c-189-\tof_node_put(phy-\u003emdio.dev.of_node);\ndrivers/net/phy/fixed_phy.c:190:\tfixed_phy_del(phy-\u003emdio.addr);\ndrivers/net/phy/fixed_phy.c-191-\tphy_device_free(phy);\ndrivers/net/phy/fixed_phy.c-192-}\ndrivers/net/phy/fixed_phy.c:193:EXPORT_SYMBOL_GPL(fixed_phy_unregister);\ndrivers/net/phy/fixed_phy.c-194-\n--\ndrivers/net/phy/phylink.c=3361=static int phylink_mii_emul_read(unsigned int reg,\n--\ndrivers/net/phy/phylink.c-3363-{\ndrivers/net/phy/phylink.c:3364:\tstruct fixed_phy_status fs;\ndrivers/net/phy/phylink.c-3365-\tunsigned long *lpa = state-\u003elp_advertising;\n--\ndrivers/net/phy/swphy.c-4- *\ndrivers/net/phy/swphy.c:5: * Code taken from fixed_phy.c by Russell King.\ndrivers/net/phy/swphy.c-6- *\n--\ndrivers/net/phy/swphy.c=71=static int swphy_decode_speed(int speed)\n--\ndrivers/net/phy/swphy.c-92- */\ndrivers/net/phy/swphy.c:93:int swphy_validate_state(const struct fixed_phy_status *state)\ndrivers/net/phy/swphy.c-94-{\n--\ndrivers/net/phy/swphy.c=106=EXPORT_SYMBOL_GPL(swphy_validate_state);\n--\ndrivers/net/phy/swphy.c-114- */\ndrivers/net/phy/swphy.c:115:int swphy_read_reg(int reg, const struct fixed_phy_status *state)\ndrivers/net/phy/swphy.c-116-{\n--\ndrivers/net/phy/swphy.h-4-\ndrivers/net/phy/swphy.h:5:struct fixed_phy_status;\ndrivers/net/phy/swphy.h-6-\ndrivers/net/phy/swphy.h:7:int swphy_validate_state(const struct fixed_phy_status *state);\ndrivers/net/phy/swphy.h:8:int swphy_read_reg(int reg, const struct fixed_phy_status *state);\ndrivers/net/phy/swphy.h-9-\n--\ninclude/linux/phy_fixed.h-6-\ninclude/linux/phy_fixed.h:7:struct fixed_phy_status {\ninclude/linux/phy_fixed.h-8-\tint speed;\n--\ninclude/linux/phy_fixed.h=16=struct net_device;\n--\ninclude/linux/phy_fixed.h-18-#if IS_ENABLED(CONFIG_FIXED_PHY)\ninclude/linux/phy_fixed.h:19:extern int fixed_phy_change_carrier(struct net_device *dev, bool new_carrier);\ninclude/linux/phy_fixed.h:20:struct phy_device *fixed_phy_register(const struct fixed_phy_status *status,\ninclude/linux/phy_fixed.h-21-\t\t\t\t      struct device_node *np);\ninclude/linux/phy_fixed.h:22:struct phy_device *fixed_phy_register_100fd(void);\ninclude/linux/phy_fixed.h-23-\ninclude/linux/phy_fixed.h:24:extern void fixed_phy_unregister(struct phy_device *phydev);\ninclude/linux/phy_fixed.h:25:extern int fixed_phy_set_link_update(struct phy_device *phydev,\ninclude/linux/phy_fixed.h-26-\t\t\tint (*link_update)(struct net_device *,\ninclude/linux/phy_fixed.h:27:\t\t\t\t\t   struct fixed_phy_status *));\ninclude/linux/phy_fixed.h-28-#else\ninclude/linux/phy_fixed.h=29=static inline struct phy_device *\ninclude/linux/phy_fixed.h:30:fixed_phy_register(const struct fixed_phy_status *status,\ninclude/linux/phy_fixed.h-31-\t\t   struct device_node *np)\n--\ninclude/linux/phy_fixed.h-35-\ninclude/linux/phy_fixed.h:36:static inline struct phy_device *fixed_phy_register_100fd(void)\ninclude/linux/phy_fixed.h-37-{\n--\ninclude/linux/phy_fixed.h-40-\ninclude/linux/phy_fixed.h:41:static inline void fixed_phy_unregister(struct phy_device *phydev)\ninclude/linux/phy_fixed.h-42-{\n"
}

9/2 2026/07/26 00:05 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 35894
							output: 17
							thoughts: 491
						

Thoughts:
**My Current Strategy for Emulating PHYs with Syzkaller**

Okay, so I need to figure out how to interact with PHYs (Physical Layer Transceivers) using syzkaller. The initial idea of `fixed_phy` is a dead end – it's for fixed link setups, not a general-purpose PHY emulation.

Then I started considering other syscalls available in syzkaller. I see `syz_genetlink_get_family`, `syz_genetlink_get_family_id`, `syz_genetlink_get_family_id_by_name`, `syz_init_net_socket` and `ioctl(SIOCSMIIREG)`. I wondered if I could somehow instantiate an MDIO bus and then attach a PHY to it directly. Sadly, I can't find anything related to creating MDIO buses.

I looked for existing examples, but `mdio-mockup` didn't show up in a search. However, there's `mdio-bcm-unimac`, which is a platform device. Also, even though syzkaller can trigger PHY code via `tun` or `veth`, neither of those options has a PHY attached. What about `macb`, `e1000`, or `virtio_net`?

But wait, `syz_genetlink_get_family` might be the key! It gives me access to the `ethtool` netlink interface, which *can* interact with PHYs. But I still need to figure out how a PHY device gets created in the first place.

I wondered if compiling the kernel with `CONFIG_MOTORCOMM_PHY=y` would automatically instantiate some virtual device using it, but I realize that's not how it works. PHY devices are usually created by MDIO bus drivers when they probe the bus and find a PHY ID that matches a specific driver. That led me back to the idea of creating an MDIO bus.

I looked for the ability to add platform devices, thinking that could be the basis to create an MDIO bus. However, there isn't a generic function like `syz_platform_device_add`.

Then, a lightbulb! I realized syzkaller has `syz_usb_connect` and `syz_usb_disconnect` for USB devices, and some USB network adapters *do* have MDIO buses and PHYs. Devices like `smsc95xx`, `asix`, and `r8152` come to mind. I need to investigate if they use the generic PHY framework, and that may be the key to triggering PHY code via syzkaller. I should check if `smsc95xx` uses `phylib`.



10/2 2026/07/26 00:05 tool grepper
0m Args:
{
  "Expression": "phy_connect"
}

Results:
{
  "Output": "\nFull output is too long, showing 500 out of 1176 lines.\nUse more precise expression if possible.\n\nDocumentation/networking/device_drivers/ethernet/freescale/dpaa2/mac-phy-support.rst=80=will do the following:\n--\nDocumentation/networking/device_drivers/ethernet/freescale/dpaa2/mac-phy-support.rst-83- - will create a PHYLINK instance associated with the received net_device\nDocumentation/networking/device_drivers/ethernet/freescale/dpaa2/mac-phy-support.rst:84: - connect to the PHY using phylink_of_phy_connect()\nDocumentation/networking/device_drivers/ethernet/freescale/dpaa2/mac-phy-support.rst-85-\n--\nDocumentation/networking/dsa/dsa.rst=453=logic basically looks like this:\n--\nDocumentation/networking/dsa/dsa.rst-456-  \"phy-handle\" property, if found, this PHY device is created and registered\nDocumentation/networking/dsa/dsa.rst:457:  using ``of_phy_connect()``\nDocumentation/networking/dsa/dsa.rst-458-\n--\nDocumentation/networking/dsa/dsa.rst=511=DSA features a standardized binding which is documented in\nDocumentation/networking/dsa/dsa.rst-512-``Documentation/devicetree/bindings/net/dsa/dsa.yaml``. PHY/MDIO library helper\nDocumentation/networking/dsa/dsa.rst:513:functions such as ``of_get_phy_mode()``, ``of_phy_connect()`` are also used to query\nDocumentation/networking/dsa/dsa.rst-514-per-port PHY specific details: interface connection, MDIO bus location, etc.\n--\nDocumentation/networking/phy.rst=185=Now, to connect, just call this function::\nDocumentation/networking/phy.rst-186-\nDocumentation/networking/phy.rst:187:\tphydev = phy_connect(dev, phy_name, \u0026adjust_link, interface);\nDocumentation/networking/phy.rst-188-\nDocumentation/networking/phy.rst-189-*phydev* is a pointer to the phy_device structure which represents the PHY.\nDocumentation/networking/phy.rst:190:If phy_connect is successful, it will return the pointer.  dev, here, is the\nDocumentation/networking/phy.rst-191-pointer to your net_device.  Once done, this function will have started the\n--\nDocumentation/networking/phy.rst=197=PHY-specific flags should be set in phydev-\u003edev_flags prior to the call\nDocumentation/networking/phy.rst:198:to phy_connect() such that the underlying PHY driver can check for flags\nDocumentation/networking/phy.rst-199-and perform specific operations based on them.\n--\nDocumentation/networking/phy.rst=229=PHY interface modes\n--\nDocumentation/networking/phy.rst-231-\nDocumentation/networking/phy.rst:232:The PHY interface mode supplied in the phy_connect() family of functions\nDocumentation/networking/phy.rst-233-defines the initial operating mode of the PHY interface.  This is not\n--\nDocumentation/networking/phy.rst=352=the SUPPORTED_Pause and SUPPORTED_AsymPause bits accordingly. This can be done\nDocumentation/networking/phy.rst:353:either before or after phy_connect() and/or as a result of implementing the\nDocumentation/networking/phy.rst-354-ethtool::set_pauseparam feature.\n--\nDocumentation/networking/sfp-phylink.rst=74=this documentation.\n--\nDocumentation/networking/sfp-phylink.rst-158-\nDocumentation/networking/sfp-phylink.rst:159:\tphy_dev = of_phy_connect(dev, node, link_func, flags, phy_interface);\nDocumentation/networking/sfp-phylink.rst-160-\n--\nDocumentation/networking/sfp-phylink.rst-162-\nDocumentation/networking/sfp-phylink.rst:163:\terr = phylink_of_phy_connect(priv-\u003ephylink, node, flags);\nDocumentation/networking/sfp-phylink.rst-164-\n--\nDocumentation/networking/sfp-phylink.rst-174-\nDocumentation/networking/sfp-phylink.rst:175:   of_phy_connect() was also passed a function pointer for link updates.\nDocumentation/networking/sfp-phylink.rst-176-   This function is replaced by a different form of MAC updates\n--\nDocumentation/networking/sfp-phylink.rst-192-   these functions. The old link update function for\nDocumentation/networking/sfp-phylink.rst:193:   :c:func:`of_phy_connect` becomes three methods: :c:func:`mac_link_up`,\nDocumentation/networking/sfp-phylink.rst-194-   :c:func:`mac_link_down`, and :c:func:`mac_config`. If step 1 was\n--\ndrivers/gpu/drm/i915/display/intel_tc.c=652=static bool tc_phy_verify_legacy_or_dp_alt_mode(struct intel_tc_port *tc,\n--\ndrivers/gpu/drm/i915/display/intel_tc.c-687-\ndrivers/gpu/drm/i915/display/intel_tc.c:688:static bool icl_tc_phy_connect(struct intel_tc_port *tc,\ndrivers/gpu/drm/i915/display/intel_tc.c-689-\t\t\t       int required_lanes)\n--\ndrivers/gpu/drm/i915/display/intel_tc.c=749=static const struct intel_tc_phy_ops icl_tc_phy_ops = {\n--\ndrivers/gpu/drm/i915/display/intel_tc.c-754-\t.get_hw_state = icl_tc_phy_get_hw_state,\ndrivers/gpu/drm/i915/display/intel_tc.c:755:\t.connect = icl_tc_phy_connect,\ndrivers/gpu/drm/i915/display/intel_tc.c-756-\t.disconnect = icl_tc_phy_disconnect,\n--\ndrivers/gpu/drm/i915/display/intel_tc.c=783=static const struct intel_tc_phy_ops tgl_tc_phy_ops = {\n--\ndrivers/gpu/drm/i915/display/intel_tc.c-788-\t.get_hw_state = icl_tc_phy_get_hw_state,\ndrivers/gpu/drm/i915/display/intel_tc.c:789:\t.connect = icl_tc_phy_connect,\ndrivers/gpu/drm/i915/display/intel_tc.c-790-\t.disconnect = icl_tc_phy_disconnect,\n--\ndrivers/gpu/drm/i915/display/intel_tc.c=889=static void adlp_tc_phy_get_hw_state(struct intel_tc_port *tc)\n--\ndrivers/gpu/drm/i915/display/intel_tc.c-907-\ndrivers/gpu/drm/i915/display/intel_tc.c:908:static bool adlp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)\ndrivers/gpu/drm/i915/display/intel_tc.c-909-{\n--\ndrivers/gpu/drm/i915/display/intel_tc.c=990=static const struct intel_tc_phy_ops adlp_tc_phy_ops = {\n--\ndrivers/gpu/drm/i915/display/intel_tc.c-995-\t.get_hw_state = adlp_tc_phy_get_hw_state,\ndrivers/gpu/drm/i915/display/intel_tc.c:996:\t.connect = adlp_tc_phy_connect,\ndrivers/gpu/drm/i915/display/intel_tc.c-997-\t.disconnect = adlp_tc_phy_disconnect,\n--\ndrivers/gpu/drm/i915/display/intel_tc.c=1168=static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)\n--\ndrivers/gpu/drm/i915/display/intel_tc.c-1195-\ndrivers/gpu/drm/i915/display/intel_tc.c:1196:static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)\ndrivers/gpu/drm/i915/display/intel_tc.c-1197-{\n--\ndrivers/gpu/drm/i915/display/intel_tc.c=1244=static const struct intel_tc_phy_ops xelpdp_tc_phy_ops = {\n--\ndrivers/gpu/drm/i915/display/intel_tc.c-1249-\t.get_hw_state = xelpdp_tc_phy_get_hw_state,\ndrivers/gpu/drm/i915/display/intel_tc.c:1250:\t.connect = xelpdp_tc_phy_connect,\ndrivers/gpu/drm/i915/display/intel_tc.c-1251-\t.disconnect = xelpdp_tc_phy_disconnect,\n--\ndrivers/gpu/drm/i915/display/intel_tc.c=1467=tc_phy_get_target_mode(struct intel_tc_port *tc)\n--\ndrivers/gpu/drm/i915/display/intel_tc.c-1473-\ndrivers/gpu/drm/i915/display/intel_tc.c:1474:static void tc_phy_connect(struct intel_tc_port *tc, int required_lanes)\ndrivers/gpu/drm/i915/display/intel_tc.c-1475-{\n--\ndrivers/gpu/drm/i915/display/intel_tc.c=1508=static void intel_tc_port_reset_mode(struct intel_tc_port *tc,\n--\ndrivers/gpu/drm/i915/display/intel_tc.c-1526-\tif (!force_disconnect)\ndrivers/gpu/drm/i915/display/intel_tc.c:1527:\t\ttc_phy_connect(tc, required_lanes);\ndrivers/gpu/drm/i915/display/intel_tc.c-1528-\n--\ndrivers/gpu/drm/i915/display/intel_tc.c=1699=void intel_tc_info(struct drm_printer *p,  struct intel_digital_port *dig_port)\n--\ndrivers/gpu/drm/i915/display/intel_tc.c-1714- * not be available/usable by the graphics driver: see the comment on\ndrivers/gpu/drm/i915/display/intel_tc.c:1715: * icl_tc_phy_connect(). So in our driver instead of adding the additional\ndrivers/gpu/drm/i915/display/intel_tc.c-1716- * concept of \"usable\" and make everything check for \"connected and usable\" we\n--\ndrivers/net/dsa/bcm_sf2.c=607=static int bcm_sf2_mdio_register(struct dsa_switch *ds)\n--\ndrivers/net/dsa/bcm_sf2.c-656-\ndrivers/net/dsa/bcm_sf2.c:657:\t/* We need to make sure that of_phy_connect() will not work by\ndrivers/net/dsa/bcm_sf2.c-658-\t * removing the 'phandle' and 'linux,phandle' properties and\n--\ndrivers/net/dsa/netc/netc_main.c=968=static bool netc_port_is_emdio_consumer(struct device_node *node)\n--\ndrivers/net/dsa/netc/netc_main.c-984-\ndrivers/net/dsa/netc/netc_main.c:985:/* Currently, phylink_of_phy_connect() is called by dsa_user_create(),\ndrivers/net/dsa/netc/netc_main.c-986- * so if the switch uses the external MDIO controller (like the EMDIO\ndrivers/net/dsa/netc/netc_main.c-987- * function) to manage the external PHYs. The MDIO bus may not be\ndrivers/net/dsa/netc/netc_main.c:988: * created when phylink_of_phy_connect() is called, so it will return\ndrivers/net/dsa/netc/netc_main.c-989- * an error and cause the switch driver to fail to probe.\ndrivers/net/dsa/netc/netc_main.c:990: * This workaround can be removed when DSA phylink_of_phy_connect()\ndrivers/net/dsa/netc/netc_main.c-991- * calls are moved from probe() to ndo_open().\n--\ndrivers/net/ethernet/8390/ax88796.c=364=static int ax_mii_probe(struct net_device *dev)\n--\ndrivers/net/ethernet/8390/ax88796.c-376-\ndrivers/net/ethernet/8390/ax88796.c:377:\tret = phy_connect_direct(dev, phy_dev, ax_handle_link_change,\ndrivers/net/ethernet/8390/ax88796.c-378-\t\t\t\t PHY_INTERFACE_MODE_MII);\n--\ndrivers/net/ethernet/adi/adin1110.c=1569=static int adin1110_probe_netdevs(struct adin1110_priv *priv)\n--\ndrivers/net/ethernet/adi/adin1110.c-1612-\ndrivers/net/ethernet/adi/adin1110.c:1613:\t\tport_priv-\u003ephydev = phy_connect(netdev,\ndrivers/net/ethernet/adi/adin1110.c-1614-\t\t\t\t\t\tphydev_name(port_priv-\u003ephydev),\n--\ndrivers/net/ethernet/aeroflex/greth.c=1253=static int greth_mdio_probe(struct net_device *dev)\n--\ndrivers/net/ethernet/aeroflex/greth.c-1267-\ndrivers/net/ethernet/aeroflex/greth.c:1268:\tret = phy_connect_direct(dev, phy, \u0026greth_link_change,\ndrivers/net/ethernet/aeroflex/greth.c-1269-\t\t\t\t greth-\u003egbit_mac ? PHY_INTERFACE_MODE_GMII : PHY_INTERFACE_MODE_MII);\n--\ndrivers/net/ethernet/agere/et131x.c=3273=static int et131x_mii_probe(struct net_device *netdev)\n--\ndrivers/net/ethernet/agere/et131x.c-3283-\ndrivers/net/ethernet/agere/et131x.c:3284:\tphydev = phy_connect(netdev, phydev_name(phydev),\ndrivers/net/ethernet/agere/et131x.c-3285-\t\t\t     \u0026et131x_adjust_link, PHY_INTERFACE_MODE_MII);\n--\ndrivers/net/ethernet/allwinner/sun4i-emac.c=167=static int emac_mdio_probe(struct net_device *dev)\n--\ndrivers/net/ethernet/allwinner/sun4i-emac.c-174-\t/* attach the mac to the phy */\ndrivers/net/ethernet/allwinner/sun4i-emac.c:175:\tphydev = of_phy_connect(db-\u003endev, db-\u003ephy_node,\ndrivers/net/ethernet/allwinner/sun4i-emac.c-176-\t\t\t\t\u0026emac_handle_link_change, 0,\n--\ndrivers/net/ethernet/altera/altera_tse_main.c=876=static int tse_open(struct net_device *dev)\n--\ndrivers/net/ethernet/altera/altera_tse_main.c-951-\ndrivers/net/ethernet/altera/altera_tse_main.c:952:\tret = phylink_of_phy_connect(priv-\u003ephylink, priv-\u003edevice-\u003eof_node, 0);\ndrivers/net/ethernet/altera/altera_tse_main.c-953-\tif (ret) {\n--\ndrivers/net/ethernet/amd/au1000_eth.c=472=static int au1000_mii_probe(struct net_device *dev)\n--\ndrivers/net/ethernet/amd/au1000_eth.c-538-\ndrivers/net/ethernet/amd/au1000_eth.c:539:\tphydev = phy_connect(dev, phydev_name(phydev),\ndrivers/net/ethernet/amd/au1000_eth.c-540-\t\t\t     \u0026au1000_adjust_link, PHY_INTERFACE_MODE_MII);\n--\ndrivers/net/ethernet/apm/xgene-v2/mdio.c=98=int xge_mdio_config(struct net_device *ndev)\n--\ndrivers/net/ethernet/apm/xgene-v2/mdio.c-128-\t}\ndrivers/net/ethernet/apm/xgene-v2/mdio.c:129:\tphydev = phy_connect(ndev, phydev_name(phydev),\ndrivers/net/ethernet/apm/xgene-v2/mdio.c-130-\t\t\t     \u0026xge_adjust_link,\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c=819=static struct acpi_device *acpi_phy_find_device(struct device *dev)\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-836-\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c:837:int xgene_enet_phy_connect(struct net_device *ndev)\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-838-{\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-847-\t\t\tnp = of_parse_phandle(dev-\u003eof_node, \"phy-handle\", i);\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c:848:\t\t\tphy_dev = of_phy_connect(ndev, np,\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-849-\t\t\t\t\t\t \u0026xgene_enet_adjust_link,\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-868-\t\tif (!phy_dev ||\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c:869:\t\t    phy_connect_direct(ndev, phy_dev, \u0026xgene_enet_adjust_link,\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-870-\t\t\t\t       pdata-\u003ephy_mode)) {\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c=939=int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-965-\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c:966:\tret = xgene_enet_phy_connect(ndev);\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.c-967-\tif (ret)\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.h=426=bool xgene_ring_mgr_init(struct xgene_enet_pdata *p);\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.h:427:int xgene_enet_phy_connect(struct net_device *ndev);\ndrivers/net/ethernet/apm/xgene/xgene_enet_hw.h-428-void xgene_enet_phy_disconnect(struct xgene_enet_pdata *pdata);\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_main.c=1651=static void xgene_enet_check_phy_handle(struct xgene_enet_pdata *pdata)\n--\ndrivers/net/ethernet/apm/xgene/xgene_enet_main.c-1660-\ndrivers/net/ethernet/apm/xgene/xgene_enet_main.c:1661:\tret = xgene_enet_phy_connect(pdata-\u003endev);\ndrivers/net/ethernet/apm/xgene/xgene_enet_main.c-1662-\tif (!ret)\n--\ndrivers/net/ethernet/arc/emac_main.c=858=int arc_emac_probe(struct net_device *ndev, int interface)\n--\ndrivers/net/ethernet/arc/emac_main.c-988-\ndrivers/net/ethernet/arc/emac_main.c:989:\tphydev = of_phy_connect(ndev, phy_node, arc_emac_adjust_link, 0,\ndrivers/net/ethernet/arc/emac_main.c-990-\t\t\t\tinterface);\ndrivers/net/ethernet/arc/emac_main.c-991-\tif (!phydev) {\ndrivers/net/ethernet/arc/emac_main.c:992:\t\tdev_err(dev, \"of_phy_connect() failed\\n\");\ndrivers/net/ethernet/arc/emac_main.c-993-\t\terr = -ENODEV;\n--\ndrivers/net/ethernet/asix/ax88796c_main.c=966=static int ax88796c_probe(struct spi_device *spi)\n--\ndrivers/net/ethernet/asix/ax88796c_main.c-1076-\t\t ax_local-\u003emdiobus-\u003eid, AX88796C_PHY_ID);\ndrivers/net/ethernet/asix/ax88796c_main.c:1077:\tax_local-\u003ephydev = phy_connect(ax_local-\u003endev, phy_id,\ndrivers/net/ethernet/asix/ax88796c_main.c-1078-\t\t\t\t       ax88796c_handle_link_change,\n--\ndrivers/net/ethernet/atheros/ag71xx.c=1404=static int ag71xx_open(struct net_device *ndev)\n--\ndrivers/net/ethernet/atheros/ag71xx.c-1409-\ndrivers/net/ethernet/atheros/ag71xx.c:1410:\tret = phylink_of_phy_connect(ag-\u003ephylink, ag-\u003epdev-\u003edev.of_node, 0);\ndrivers/net/ethernet/atheros/ag71xx.c-1411-\tif (ret) {\ndrivers/net/ethernet/atheros/ag71xx.c:1412:\t\tnetif_err(ag, link, ndev, \"phylink_of_phy_connect filed with err: %i\\n\",\ndrivers/net/ethernet/atheros/ag71xx.c-1413-\t\t\t  ret);\n--\ndrivers/net/ethernet/broadcom/asp2/bcmasp_intf.c=1074=static int bcmasp_phy_attach(struct bcmasp_intf *intf)\n--\ndrivers/net/ethernet/broadcom/asp2/bcmasp_intf.c-1082-\tphy_iface = bcmasp_phy_iface_for_connect(intf-\u003ephy_interface);\ndrivers/net/ethernet/broadcom/asp2/bcmasp_intf.c:1083:\tphydev = of_phy_connect(intf-\u003endev, intf-\u003ephy_dn,\ndrivers/net/ethernet/broadcom/asp2/bcmasp_intf.c-1084-\t\t\t\tbcmasp_adj_link, phy_flags,\n--\ndrivers/net/ethernet/broadcom/b44.c=2234=static int b44_register_phy_one(struct b44 *bp)\n--\ndrivers/net/ethernet/broadcom/b44.c-2280-\telse\ndrivers/net/ethernet/broadcom/b44.c:2281:\t\terr = phy_connect_direct(bp-\u003edev, phydev, \u0026b44_adjust_link,\ndrivers/net/ethernet/broadcom/b44.c-2282-\t\t\t\t\t PHY_INTERFACE_MODE_MII);\n--\ndrivers/net/ethernet/broadcom/bcm63xx_enet.c=890=static int bcm_enet_open(struct net_device *dev)\n--\ndrivers/net/ethernet/broadcom/bcm63xx_enet.c-909-\ndrivers/net/ethernet/broadcom/bcm63xx_enet.c:910:\t\tphydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link,\ndrivers/net/ethernet/broadcom/bcm63xx_enet.c-911-\t\t\t\t     PHY_INTERFACE_MODE_MII);\n--\ndrivers/net/ethernet/broadcom/bcmsysport.c=1928=static int bcm_sysport_open(struct net_device *dev)\n--\ndrivers/net/ethernet/broadcom/bcmsysport.c-1966-\ndrivers/net/ethernet/broadcom/bcmsysport.c:1967:\tphydev = of_phy_connect(dev, priv-\u003ephy_dn, bcm_sysport_adj_link,\ndrivers/net/ethernet/broadcom/bcmsysport.c-1968-\t\t\t\t0, priv-\u003ephy_interface);\n--\ndrivers/net/ethernet/broadcom/bgmac-bcma.c=79=static void bcma_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset, u32 mask,\n--\ndrivers/net/ethernet/broadcom/bgmac-bcma.c-84-\ndrivers/net/ethernet/broadcom/bgmac-bcma.c:85:static int bcma_phy_connect(struct bgmac *bgmac)\ndrivers/net/ethernet/broadcom/bgmac-bcma.c-86-{\n--\ndrivers/net/ethernet/broadcom/bgmac-bcma.c-99-\t\t\t bgmac-\u003ephyaddr);\ndrivers/net/ethernet/broadcom/bgmac-bcma.c:100:\t\tphy_dev = phy_connect(bgmac-\u003enet_dev, bus_id, bgmac_adjust_link,\ndrivers/net/ethernet/broadcom/bgmac-bcma.c-101-\t\t\t\t      PHY_INTERFACE_MODE_MII);\n--\ndrivers/net/ethernet/broadcom/bgmac-bcma.c-110-\t/* Assume a fixed link to the switch port */\ndrivers/net/ethernet/broadcom/bgmac-bcma.c:111:\treturn bgmac_phy_connect_direct(bgmac);\ndrivers/net/ethernet/broadcom/bgmac-bcma.c-112-}\n--\ndrivers/net/ethernet/broadcom/bgmac-bcma.c=124=static int bgmac_probe(struct bcma_device *core)\n--\ndrivers/net/ethernet/broadcom/bgmac-bcma.c-311-\tbgmac-\u003ecmn_maskset32 = bcma_bgmac_cmn_maskset32;\ndrivers/net/ethernet/broadcom/bgmac-bcma.c:312:\tbgmac-\u003ephy_connect = bcma_phy_connect;\ndrivers/net/ethernet/broadcom/bgmac-bcma.c-313-\n--\ndrivers/net/ethernet/broadcom/bgmac-platform.c=118=static void bgmac_nicpm_speed_set(struct net_device *net_dev)\n--\ndrivers/net/ethernet/broadcom/bgmac-platform.c-150-\ndrivers/net/ethernet/broadcom/bgmac-platform.c:151:static int platform_phy_connect(struct bgmac *bgmac)\ndrivers/net/ethernet/broadcom/bgmac-platform.c-152-{\n--\ndrivers/net/ethernet/broadcom/bgmac-platform.c=171=static int bgmac_probe(struct platform_device *pdev)\n--\ndrivers/net/ethernet/broadcom/bgmac-platform.c-242-\t\tof_node_put(phy_node);\ndrivers/net/ethernet/broadcom/bgmac-platform.c:243:\t\tbgmac-\u003ephy_connect = platform_phy_connect;\ndrivers/net/ethernet/broadcom/bgmac-platform.c-244-\t} else {\ndrivers/net/ethernet/broadcom/bgmac-platform.c:245:\t\tbgmac-\u003ephy_connect = bgmac_phy_connect_direct;\ndrivers/net/ethernet/broadcom/bgmac-platform.c-246-\t\tbgmac-\u003efeature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;\n--\ndrivers/net/ethernet/broadcom/bgmac.c=1437=EXPORT_SYMBOL_GPL(bgmac_adjust_link);\ndrivers/net/ethernet/broadcom/bgmac.c-1438-\ndrivers/net/ethernet/broadcom/bgmac.c:1439:int bgmac_phy_connect_direct(struct bgmac *bgmac)\ndrivers/net/ethernet/broadcom/bgmac.c-1440-{\n--\ndrivers/net/ethernet/broadcom/bgmac.c-1454-\ndrivers/net/ethernet/broadcom/bgmac.c:1455:\terr = phy_connect_direct(bgmac-\u003enet_dev, phy_dev, bgmac_adjust_link,\ndrivers/net/ethernet/broadcom/bgmac.c-1456-\t\t\t\t PHY_INTERFACE_MODE_MII);\n--\ndrivers/net/ethernet/broadcom/bgmac.c-1463-}\ndrivers/net/ethernet/broadcom/bgmac.c:1464:EXPORT_SYMBOL_GPL(bgmac_phy_connect_direct);\ndrivers/net/ethernet/broadcom/bgmac.c-1465-\n--\ndrivers/net/ethernet/broadcom/bgmac.c=1487=int bgmac_enet_probe(struct bgmac *bgmac)\n--\ndrivers/net/ethernet/broadcom/bgmac.c-1532-\ndrivers/net/ethernet/broadcom/bgmac.c:1533:\terr = bgmac_phy_connect(bgmac);\ndrivers/net/ethernet/broadcom/bgmac.c-1534-\tif (err) {\n--\ndrivers/net/ethernet/broadcom/bgmac.h=439=struct bgmac {\n--\ndrivers/net/ethernet/broadcom/bgmac.h-495-\t\t\t      u32 set);\ndrivers/net/ethernet/broadcom/bgmac.h:496:\tint (*phy_connect)(struct bgmac *bgmac);\ndrivers/net/ethernet/broadcom/bgmac.h-497-};\n--\ndrivers/net/ethernet/broadcom/bgmac.h=502=void bgmac_adjust_link(struct net_device *net_dev);\ndrivers/net/ethernet/broadcom/bgmac.h:503:int bgmac_phy_connect_direct(struct bgmac *bgmac);\ndrivers/net/ethernet/broadcom/bgmac.h-504-int bgmac_enet_suspend(struct bgmac *bgmac);\n--\ndrivers/net/ethernet/broadcom/bgmac.h=583=static inline void bgmac_umac_maskset(struct bgmac *bgmac, u16 offset, u32 mask, u32 set)\n--\ndrivers/net/ethernet/broadcom/bgmac.h-587-\ndrivers/net/ethernet/broadcom/bgmac.h:588:static inline int bgmac_phy_connect(struct bgmac *bgmac)\ndrivers/net/ethernet/broadcom/bgmac.h-589-{\ndrivers/net/ethernet/broadcom/bgmac.h:590:\treturn bgmac-\u003ephy_connect(bgmac);\ndrivers/net/ethernet/broadcom/bgmac.h-591-}\n--\ndrivers/net/ethernet/broadcom/genet/bcmmii.c=301=int bcmgenet_mii_probe(struct net_device *dev)\n--\ndrivers/net/ethernet/broadcom/genet/bcmmii.c-350-\tif (dn) {\ndrivers/net/ethernet/broadcom/genet/bcmmii.c:351:\t\tphydev = of_phy_connect(dev, priv-\u003ephy_dn, bcmgenet_mii_setup,\ndrivers/net/ethernet/broadcom/genet/bcmmii.c-352-\t\t\t\t\tphy_flags, phy_iface);\n--\ndrivers/net/ethernet/broadcom/genet/bcmmii.c-380-\ndrivers/net/ethernet/broadcom/genet/bcmmii.c:381:\t\tret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup,\ndrivers/net/ethernet/broadcom/genet/bcmmii.c-382-\t\t\t\t\t phy_iface);\n--\ndrivers/net/ethernet/broadcom/sb1250-mac.c=2324=static int sbmac_mii_probe(struct net_device *dev)\n--\ndrivers/net/ethernet/broadcom/sb1250-mac.c-2334-\ndrivers/net/ethernet/broadcom/sb1250-mac.c:2335:\tphy_dev = phy_connect(dev, dev_name(\u0026phy_dev-\u003emdio.dev),\ndrivers/net/ethernet/broadcom/sb1250-mac.c-2336-\t\t\t      \u0026sbmac_mii_poll, PHY_INTERFACE_MODE_GMII);\n--\ndrivers/net/ethernet/broadcom/tg3.c=2084=static int tg3_phy_init(struct tg3 *tp)\n--\ndrivers/net/ethernet/broadcom/tg3.c-2096-\t/* Attach the MAC to the PHY. */\ndrivers/net/ethernet/broadcom/tg3.c:2097:\tphydev = phy_connect(tp-\u003edev, phydev_name(phydev),\ndrivers/net/ethernet/broadcom/tg3.c-2098-\t\t\t     tg3_adjust_link, phydev-\u003einterface);\n--\ndrivers/net/ethernet/cadence/macb_main.c=982=static int macb_phylink_connect(struct macb *bp)\n--\ndrivers/net/ethernet/cadence/macb_main.c-989-\tif (dn)\ndrivers/net/ethernet/cadence/macb_main.c:990:\t\tret = phylink_of_phy_connect(bp-\u003ephylink, dn, 0);\ndrivers/net/ethernet/cadence/macb_main.c-991-\n--\ndrivers/net/ethernet/cavium/octeon/octeon_mgmt.c=945=static int octeon_mgmt_init_phy(struct net_device *netdev)\n--\ndrivers/net/ethernet/cavium/octeon/octeon_mgmt.c-955-\ndrivers/net/ethernet/cavium/octeon/octeon_mgmt.c:956:\tphydev = of_phy_connect(netdev, p-\u003ephy_np,\ndrivers/net/ethernet/cavium/octeon/octeon_mgmt.c-957-\t\t\t\tocteon_mgmt_adjust_link, 0,\n--\ndrivers/net/ethernet/cavium/thunder/thunder_bgx.c=1055=static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)\n--\ndrivers/net/ethernet/cavium/thunder/thunder_bgx.c-1119-\ndrivers/net/ethernet/cavium/thunder/thunder_bgx.c:1120:\t\tif (phy_connect_direct(lmac-\u003enetdev, lmac-\u003ephydev,\ndrivers/net/ethernet/cavium/thunder/thunder_bgx.c-1121-\t\t\t\t       bgx_lmac_handler,\n--\ndrivers/net/ethernet/davicom/dm9051.c=1132=static void dm9051_handle_link_change(struct net_device *ndev)\n--\ndrivers/net/ethernet/davicom/dm9051.c-1151- */\ndrivers/net/ethernet/davicom/dm9051.c:1152:static int dm9051_phy_connect(struct board_info *db)\ndrivers/net/ethernet/davicom/dm9051.c-1153-{\n--\ndrivers/net/ethernet/davicom/dm9051.c-1158-\ndrivers/net/ethernet/davicom/dm9051.c:1159:\tdb-\u003ephydev = phy_connect(db-\u003endev, phy_id, dm9051_handle_link_change,\ndrivers/net/ethernet/davicom/dm9051.c-1160-\t\t\t\t PHY_INTERFACE_MODE_MII);\n--\ndrivers/net/ethernet/davicom/dm9051.c=1164=static int dm9051_probe(struct spi_device *spi)\n--\ndrivers/net/ethernet/davicom/dm9051.c-1208-\ndrivers/net/ethernet/davicom/dm9051.c:1209:\tret = dm9051_phy_connect(db);\ndrivers/net/ethernet/davicom/dm9051.c-1210-\tif (ret)\n--\ndrivers/net/ethernet/engleder/tsnep_main.c=241=static int tsnep_phy_open(struct tsnep_adapter *adapter)\n--\ndrivers/net/ethernet/engleder/tsnep_main.c-246-\ndrivers/net/ethernet/engleder/tsnep_main.c:247:\tretval = phy_connect_direct(adapter-\u003enetdev, adapter-\u003ephydev,\ndrivers/net/ethernet/engleder/tsnep_main.c-248-\t\t\t\t    tsnep_phy_link_status_change,\n--\ndrivers/net/ethernet/ethoc.c=699=static int ethoc_mdio_probe(struct net_device *dev)\n--\ndrivers/net/ethernet/ethoc.c-715-\ndrivers/net/ethernet/ethoc.c:716:\terr = phy_connect_direct(dev, phy, ethoc_mdio_poll,\ndrivers/net/ethernet/ethoc.c-717-\t\t\t\t PHY_INTERFACE_MODE_GMII);\n--\ndrivers/net/ethernet/faraday/ftgmac100.c=1497=static int ftgmac100_mii_probe(struct net_device *netdev)\n--\ndrivers/net/ethernet/faraday/ftgmac100.c-1541-\ndrivers/net/ethernet/faraday/ftgmac100.c:1542:\tphydev = phy_connect(netdev, phydev_name(phydev),\ndrivers/net/ethernet/faraday/ftgmac100.c-1543-\t\t\t     \u0026ftgmac100_adjust_link, phy_intf);\n--\ndrivers/net/ethernet/faraday/ftgmac100.c=1848=static int ftgmac100_probe_ncsi(struct net_device *netdev,\n--\ndrivers/net/ethernet/faraday/ftgmac100.c-1872-\t}\ndrivers/net/ethernet/faraday/ftgmac100.c:1873:\terr = phy_connect_direct(netdev, phydev, ftgmac100_adjust_link,\ndrivers/net/ethernet/faraday/ftgmac100.c-1874-\t\t\t\t PHY_INTERFACE_MODE_RMII);\n--\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c=2941=static int dpaa_open(struct net_device *net_dev)\n--\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c-2950-\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c:2951:\terr = phylink_of_phy_connect(mac_dev-\u003ephylink,\ndrivers/net/ethernet/freescale/dpaa/dpaa_eth.c-2952-\t\t\t\t     mac_dev-\u003edev-\u003eof_node, 0);\n--\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c=560=int dpaa2_mac_connect(struct dpaa2_mac *mac)\n--\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c-634-\trtnl_lock();\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c:635:\terr = phylink_fwnode_phy_connect(mac-\u003ephylink, dpmac_node, 0);\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c-636-\trtnl_unlock();\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c-637-\tif (err) {\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c:638:\t\tnetdev_err(net_dev, \"phylink_fwnode_phy_connect() = %d\\n\", err);\ndrivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c-639-\t\tgoto err_phylink_destroy;\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c=2899=static int enetc_phylink_connect(struct net_device *ndev)\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c-2910-\ndrivers/net/ethernet/freescale/enetc/enetc.c:2911:\terr = phylink_of_phy_connect(priv-\u003ephylink, priv-\u003edev-\u003eof_node, 0);\ndrivers/net/ethernet/freescale/enetc/enetc.c-2912-\tif (err) {\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c=2974=int enetc_open(struct net_device *ndev)\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c-2992-\tif (err)\ndrivers/net/ethernet/freescale/enetc/enetc.c:2993:\t\tgoto err_phy_connect;\ndrivers/net/ethernet/freescale/enetc/enetc.c-2994-\n--\ndrivers/net/ethernet/freescale/enetc/enetc.c-3019-\t\tphylink_disconnect_phy(priv-\u003ephylink);\ndrivers/net/ethernet/freescale/enetc/enetc.c:3020:err_phy_connect:\ndrivers/net/ethernet/freescale/enetc/enetc.c-3021-\tenetc_free_irqs(priv);\n--\ndrivers/net/ethernet/freescale/fec_main.c=2981=static int fec_enet_mii_probe(struct net_device *ndev)\n--\ndrivers/net/ethernet/freescale/fec_main.c-2987-\tif (fep-\u003ephy_node) {\ndrivers/net/ethernet/freescale/fec_main.c:2988:\t\tphy_dev = of_phy_connect(ndev, fep-\u003ephy_node,\ndrivers/net/ethernet/freescale/fec_main.c-2989-\t\t\t\t\t \u0026fec_enet_adjust_link, 0,\n--\ndrivers/net/ethernet/freescale/fec_main.c-3009-\ndrivers/net/ethernet/freescale/fec_main.c:3010:\t\tret = phy_connect_direct(ndev, phy_dev, \u0026fec_enet_adjust_link,\ndrivers/net/ethernet/freescale/fec_main.c-3011-\t\t\t\t\t fep-\u003ephy_interface);\n--\ndrivers/net/ethernet/freescale/fec_mpc52xx.c=216=static int mpc52xx_fec_open(struct net_device *dev)\n--\ndrivers/net/ethernet/freescale/fec_mpc52xx.c-222-\tif (priv-\u003ephy_node) {\ndrivers/net/ethernet/freescale/fec_mpc52xx.c:223:\t\tphydev = of_phy_connect(priv-\u003endev, priv-\u003ephy_node,\ndrivers/net/ethernet/freescale/fec_mpc52xx.c-224-\t\t\t\t\tmpc52xx_fec_adjust_link, 0, 0);\ndrivers/net/ethernet/freescale/fec_mpc52xx.c-225-\t\tif (!phydev) {\ndrivers/net/ethernet/freescale/fec_mpc52xx.c:226:\t\t\tdev_err(\u0026dev-\u003edev, \"of_phy_connect failed\\n\");\ndrivers/net/ethernet/freescale/fec_mpc52xx.c-227-\t\t\treturn -ENODEV;\n--\ndrivers/net/ethernet/freescale/fs_enet/fs_enet-main.c=656=static int fs_enet_open(struct net_device *dev)\n--\ndrivers/net/ethernet/freescale/fs_enet/fs_enet-main.c-677-\ndrivers/net/ethernet/freescale/fs_enet/fs_enet-main.c:678:\terr = phylink_of_phy_connect(fep-\u003ephylink, fep-\u003edev-\u003eof_node, 0);\ndrivers/net/ethernet/freescale/fs_enet/fs_enet-main.c-679-\tif (err) {\n--\ndrivers/net/ethernet/freescale/gianfar.c=1640=static int init_phy(struct net_device *dev)\n--\ndrivers/net/ethernet/freescale/gianfar.c-1650-\ndrivers/net/ethernet/freescale/gianfar.c:1651:\tphydev = of_phy_connect(dev, priv-\u003ephy_node, \u0026adjust_link, 0,\ndrivers/net/ethernet/freescale/gianfar.c-1652-\t\t\t\tinterface);\n--\ndrivers/net/ethernet/freescale/ucc_geth.c=3167=static int ucc_geth_open(struct net_device *dev)\n--\ndrivers/net/ethernet/freescale/ucc_geth.c-3180-\ndrivers/net/ethernet/freescale/ucc_geth.c:3181:\terr = phylink_of_phy_connect(ugeth-\u003ephylink, ugeth-\u003edev-\u003eof_node, 0);\ndrivers/net/ethernet/freescale/ucc_geth.c-3182-\tif (err) {\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c=196=static void hbg_phy_disconnect(void *data)\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-200-\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:201:static int hbg_phy_connect(struct hbg_priv *priv)\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-202-{\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-206-\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:207:\tret = phy_connect_direct(priv-\u003enetdev, phydev, hbg_phy_adjust_link,\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-208-\t\t\t\t PHY_INTERFACE_MODE_SGMII);\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c=238=static int hbg_fixed_phy_init(struct hbg_priv *priv)\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-262-\tpriv-\u003emac.phydev = phydev;\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:263:\treturn hbg_phy_connect(priv);\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-264-}\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c=266=int hbg_mdio_init(struct hbg_priv *priv)\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-302-\thbg_mdio_init_hw(priv);\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:303:\treturn hbg_phy_connect(priv);\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-304-}\n--\n\n"
}

11/2 2026/07/26 00:05 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 49908
							output: 18
							thoughts: 897
						

Thoughts:
**My Current Analysis of the Motorcomm PHY Driver Vulnerability Potential**

Okay, so I'm thinking about the `motorcomm` PHY driver and how to potentially fuzz it using syzkaller. The driver, as I understand it, relies on `phy_connect`, but is used by virtual/emulated devices, and QEMU might play a role here. My immediate thought is about `macb` which is emulated in QEMU. Let's dig deeper: Does `macb` use `phylink_of_phy_connect` or just `phy_connect`? Ah, it uses `macb_phylink_connect` which then calls `phylink_of_phy_connect`.

Now, the crucial question: can syzkaller trigger `macb` within QEMU? Yes, syzkaller does run on QEMU, but it typically focuses on `e1000` or `virtio-net`. I need to find a way to reach the `motorcomm` PHY driver.

If `CONFIG_MOTORCOMM_PHY` is enabled, and syzkaller can somehow inject a device tree overlay or use `ioctl(SIOCSMIIREG)` on a dummy netdev, then it *could* reach the driver. Actually, syzkaller has `syz_genetlink_get_family`, etc., so there might be a route there. I know syzkaller can use `ioctl(SIOCSMIIREG)` to interact with PHY registers directly. The key is how to get the PHY driver bound to a PHY device.

How does that device actually get created in the first place? If `CONFIG_MOTORCOMM_PHY=y`, and there's an MDIO bus, the MDIO bus scans for PHYs. The `motorcomm` driver will bind if it sees `PHY_ID_YT8824` (0x4f51e8b8).

Can syzkaller emulate that PHY on an MDIO bus? I don't think so, not easily, unless there's a specific driver to fake the hardware (like a hypothetical `mdio-mockup`, but it doesn't exist) or by using an emulated device like `macb` (QEMU emulates other specific PHYs). Crucially, QEMU's `macb` *doesn't* emulate a Motorcomm PHY. It usually emulates National Semiconductor or Broadcom ones.

So, if QEMU *doesn't* emulate the Motorcomm PHY, the MDIO bus scan won't find `PHY_ID_YT8824`. The `motorcomm` driver will *never* bind. If the driver never binds, its probe, config, read and everything else are never executed.

Is there any way to force this binding? I remember seeing something about sysfs: I can echo the right `phy_id` to `/sys/bus/mdio_bus/drivers/motorcomm/bind`. But the device has to be *there* on the MDIO bus in the first place!

Can I create a dummy PHY device for syzkaller to use? There's `fixed-phy`, but it makes a PHY with a hardcoded ID (or a generated one), and binds to the `fixed-phy` driver, not the `motorcomm` one. Can I change the fixed PHY ID? No, looking at `fixed_phy_register`, it takes a `struct fixed_phy_status`, but not the ID.

Is there any other method to create a PHY device? Device Tree overlays! Syzkaller *could* inject those if `CONFIG_OF_OVERLAY` is enabled. But syzkaller *doesn't* do this with standard upstream Linux fuzzing (it *does* in some Android kernels).

What about that `mdio-mockup` I thought I'd seen? I searched and didn't find anything. Wait, does that mean I didn't search properly, or maybe I should check the kernel source more carefully? Let me search for `mdio` and `mockup` or `dummy` and see what turns up.



12/2 2026/07/26 00:06 tool grepper
0m Args:
{
  "Expression": "dummy.*mdio"
}

Results:
{
  "Output": "drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c=381=int stmmac_mdio_reset(struct mii_bus *bus)\n--\ndrivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c-416-\t * It doesn't complete its reset until at least one clock cycle\ndrivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c:417:\t * on MDC, so perform a dummy mdio read. To be updated for GMAC4\ndrivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c-418-\t * if needed.\n"
}

13/2 2026/07/26 00:06 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 51891
							output: 18
							thoughts: 11
						

Thoughts:
Okay, here's my interpretation of that thought process, tailored for an expert audience:

**MDIO & the Dummy – A Quick Scour**

Alright, so the initial thought process is pretty straightforward. I'm essentially starting a targeted search. My mental model kicks in immediately, and I'm homing in on anything related to "mdio" – presumably the Media Independent Interface, a standard I'm intimately familiar with – and something with the wildcard `.*` followed by "dummy." This wildcard suggests I'm after a broad match, possibly looking for configurations, registers, or code snippets involving a "dummy" or placeholder within the MDIO framework. This "dummy" could represent a variety of things: a testing setup, a stub for a non-existent PHY, a placeholder value, or even a specific debug tool's designation. The precise meaning hinges entirely on context. My expectation is to quickly identify relevant files or definitions to understand how the "dummy" concept is integrated with or impacts MDIO operations. This could be related to driver development, hardware bring-up, or even troubleshooting MDIO bus communication.



14/2 2026/07/26 00:06 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "mdio.*dummy"
}

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

15/2 2026/07/26 00:06 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 52166
							output: 24
							thoughts: 22
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**MDIO Software Interface Investigation**

Alright, I'm trying to recall – is there a *software* MDIO bus implementation I'm forgetting about? My mind keeps drifting towards potential areas where I've seen MDIO handling. If so, where is it generally going to be? 

I know the kernel's got robust MDIO driver support, so I'm thinking I should start digging through the driver space. Specifically, `drivers/net/mdio/` is the most logical starting point. That directory is where the core MDIO driver framework and associated PHY drivers typically reside. Let's see if there's any evidence of a software-based abstraction or interface within there. Hopefully the breadcrumbs are in place.



16/2 2026/07/26 00:06 tool codesearch-dir-index
0m Args:
{
  "Dir": "drivers/net/mdio"
}

Results:
{
  "Files": [
    "acpi_mdio.c",
    "fwnode_mdio.c",
    "mdio-airoha.c",
    "mdio-aspeed.c",
    "mdio-bcm-iproc.c",
    "mdio-bcm-unimac.c",
    "mdio-bitbang.c",
    "mdio-cavium.c",
    "mdio-cavium.h",
    "mdio-gpio.c",
    "mdio-hisi-femac.c",
    "mdio-i2c.c",
    "mdio-ipq4019.c",
    "mdio-ipq8064.c",
    "mdio-moxart.c",
    "mdio-mscc-miim.c",
    "mdio-mux-bcm-iproc.c",
    "mdio-mux-bcm6368.c",
    "mdio-mux-gpio.c",
    "mdio-mux-meson-g12a.c",
    "mdio-mux-meson-gxl.c",
    "mdio-mux-mmioreg.c",
    "mdio-mux-multiplexer.c",
    "mdio-mux.c",
    "mdio-mvusb.c",
    "mdio-octeon.c",
    "mdio-pic64hpsc.c",
    "mdio-realtek-rtl9300.c",
    "mdio-regmap.c",
    "mdio-sun4i.c",
    "mdio-thunder.c",
    "mdio-xgene.c",
    "of_mdio.c"
  ],
  "Subdirs": null
}

17/2 2026/07/26 00:06 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 52785
							output: 24
							thoughts: 343
						

Thoughts:
**My Syzkaller-Driven MDIO Epiphany**

Okay, so I'm thinking about how to get Syzkaller to interact with a PHY device specifically. I've got the MDIO driver files in mind: `mdio-bitbang.c`, `mdio-gpio.c`, `mdio-i2c.c`, `mdio-regmap.c`, and `mdio-mvusb.c`. The question is, can Syzkaller force the instantiation of a PHY with a certain ID?

I know Syzkaller *could* potentially use `ioctl(SIOCSMIIREG)` to write directly to a PHY's registers, but only if the PHY device already exists in the first place, which is the catch.

Wait a minute, if Syzkaller creates a virtual network device like `veth` or `tun`, it doesn’t have an MDIO bus, does it? Nope. And what about `mac80211_hwsim`? Nah. The `vkms` driver? Not there either. Ah, and what about `vhci` for USB? That's the key.

If I can get Syzkaller to emulate a USB device that *has* an MDIO bus, say `smsc95xx`, then that's the angle! If Syzkaller can emulate `smsc95xx` over USB, the `smsc95xx` driver will instantiate an MDIO bus. Then that MDIO bus will scan for PHYs by reading registers 2 and 3 – those crucial PHY ID registers.

Since Syzkaller completely controls the USB responses, I can make it return *any* value I want for those registers! I can give it the Motorcomm PHY ID, `0x4f51` and `0xe8b8`! If Syzkaller returns that ID, the MDIO bus will generate a PHY device with that ID, and the `motorcomm` driver will bind to it! Brilliant!

Now, let me just verify that the `smsc95xx` driver really does read the PHY ID from the device. That's the next step.



18/2 2026/07/26 00:06 tool grepper
0m Args:
{
  "Expression": "smsc95xx_mdio_read"
}

Results:
{
  "Output": "drivers/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=297=static int smsc95xx_mdiobus_read(struct mii_bus *bus, int phy_id, int idx)\n--\ndrivers/net/usb/smsc95xx.c-300-\ndrivers/net/usb/smsc95xx.c:301:\treturn smsc95xx_mdio_read(dev, phy_id, idx);\ndrivers/net/usb/smsc95xx.c-302-}\n--\ndrivers/net/usb/smsc95xx.c=1351=static int smsc95xx_link_ok(struct usbnet *dev)\n--\ndrivers/net/usb/smsc95xx.c-1356-\t/* first, a dummy read, needed to latch some MII phys */\ndrivers/net/usb/smsc95xx.c:1357:\tret = smsc95xx_mdio_read(dev, pdata-\u003ephydev-\u003emdio.addr, MII_BMSR);\ndrivers/net/usb/smsc95xx.c-1358-\tif (ret \u003c 0)\n--\ndrivers/net/usb/smsc95xx.c-1360-\ndrivers/net/usb/smsc95xx.c:1361:\tret = smsc95xx_mdio_read(dev, pdata-\u003ephydev-\u003emdio.addr, MII_BMSR);\ndrivers/net/usb/smsc95xx.c-1362-\tif (ret \u003c 0)\n--\ndrivers/net/usb/smsc95xx.c=1407=static int smsc95xx_enter_suspend1(struct usbnet *dev)\n--\ndrivers/net/usb/smsc95xx.c-1420-\t/* enable energy detect power-down mode */\ndrivers/net/usb/smsc95xx.c:1421:\tret = smsc95xx_mdio_read(dev, phy_id, PHY_MODE_CTRL_STS);\ndrivers/net/usb/smsc95xx.c-1422-\tif (ret \u003c 0)\n"
}

19/2 2026/07/26 00:06 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 54298
							output: 25
							thoughts: 150
						

Thoughts:
**Analyzing the USB-to-Ethernet Driver's PHY Detection**

Okay, so the `smsc95xx_mdio_read` function, right, that's what's hitting the USB bus to read the MDIO register. Makes sense. And if syzkaller is hooking into this using `dummy_hcd` for USB fuzzing, it can grab the reads for those MII_PHYSID1 and MII_PHYSID2 registers – registers 2 and 3 – and feed back a Motorcomm PHY ID. Bingo! The kernel will load the Motorcomm PHY driver. That's a solid pathway.

Now, a quick sanity check: does `smsc95xx` even *use* the generic PHY framework? I should check the `smsc95xx_mdiobus_read` function. That's the likely spot. Where is it being called? Probably in `smsc95xx_mdiobus_alloc` or something similar, setting up the MDIO bus. Right. Gotta confirm that the abstraction is in place. Need to look more deeply at the overall PHY instantiation.



20/2 2026/07/26 00:06 tool grepper
0m Args:
{
  "Expression": "smsc95xx_mdiobus_read"
}

Results:
{
  "Output": "drivers/net/usb/smsc95xx.c=260=static int smsc95xx_mdiobus_reset(struct mii_bus *bus)\n--\ndrivers/net/usb/smsc95xx.c-296-\ndrivers/net/usb/smsc95xx.c:297:static int smsc95xx_mdiobus_read(struct mii_bus *bus, int phy_id, int idx)\ndrivers/net/usb/smsc95xx.c-298-{\n--\ndrivers/net/usb/smsc95xx.c=1147=static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)\n--\ndrivers/net/usb/smsc95xx.c-1232-\tpdata-\u003emdiobus-\u003epriv = dev;\ndrivers/net/usb/smsc95xx.c:1233:\tpdata-\u003emdiobus-\u003eread = smsc95xx_mdiobus_read;\ndrivers/net/usb/smsc95xx.c-1234-\tpdata-\u003emdiobus-\u003ewrite = smsc95xx_mdiobus_write;\n"
}

21/2 2026/07/26 00:06 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 55019
							output: 19
							thoughts: 1385
						

Thoughts:
**Fuzzing Potential: YT8824 PHY Driver**

Okay, so I've got this `smsc95xx` driver, and it registers an `mdiobus`. When that happens, the bus is scanned, reading `MII_PHYSID1` and `MII_PHYSID2`. If syzkaller feeds it `0x4f51` and `0xe8b8`, the system will create a PHY device identified as `PHY_ID_YT8824`. Then `phy_device_register` gets called. The driver core will try to bind a driver and it will match `motorcomm_phy_drvs` to that `PHY_ID_YT8824`. Ultimately, `yt8824_probe` will be executed! After the network interface comes up, `phy_connect` (or something similar) will kick off, which, in turn, calls `yt8824_config_init`, `yt8824_config_aneg`, and so on. Also, syzkaller can trigger `yt8824_read_status` periodically (via the phylib state machine) or through ethtool. So, this PHY driver is absolutely within reach and definitely fuzzable using syzkaller via USB fuzzing.

Let's quickly confirm that the PHY ID for YT8824 is indeed as I thought: It's `0x4f51e8b8`. Therefore `MII_PHYSID1` will be `0x4f51` and `MII_PHYSID2` will be `0xe8b8`, which syzkaller's USB fuzzer should easily be able to provide.

So, this looks like a definite "WorthFuzzing=true" situation.

Now, what are the key symbols, the functions we need to focus on? I need to get the list of the interesting functions:
```c
yt8824_read_page
yt8824_write_page
yt8824_config_intr
yt8824_handle_interrupt
yt8824_probe
yt8824_config_aneg
yt8824_aneg_done
yt8824_config_init
yt8824_read_status
yt8824_soft_reset
yt8824_suspend
yt8824_resume
```
Are there any other functions? I need to make sure I don't miss anything. These are all internal static helpers, it's better to list the API entry points to avoid compiler inlining issues.

Okay, let's list the API entry points from `struct phy_driver` are:
`yt8824_read_page`
`yt8824_write_page`
`yt8824_config_intr`
`yt8824_handle_interrupt`
`yt8824_probe`
`yt8824_config_aneg`
`yt8824_aneg_done`
`yt8824_config_init`
`yt8824_read_status`
`yt8824_soft_reset`
`yt8824_suspend`
`yt8824_resume`

Ah, wait. There's also `genphy_c45_template_testmode`, which is added in `drivers/net/phy/phy-c45.c`. It's exported, so it's not static. I should definitely include that.
```c
int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode)
```

Now, let's confirm if `CONFIG_MOTORCOMM_PHY` is the only config that is required.
Yes, `MOTORCOMM_PHY` is the config for this driver.
Is there any other config?
The patch modifies `drivers/net/phy/phy-c45.c`, which is compiled if `CONFIG_PHYLIB` is enabled. `MOTORCOMM_PHY` depends on `PHYLIB`.
So `MOTORCOMM_PHY` is sufficient.

So, let's review the final list:
`yt8824_read_page`
`yt8824_write_page`
`yt8824_config_intr`
`yt8824_handle_interrupt`
`yt8824_probe`
`yt8824_config_aneg`
`yt882


22/2 2026/07/26 00:06 tool grepper
0m Args:
{
  "Expression": "config MOTORCOMM_PHY"
}

Results:
{
  "Output": "drivers/net/phy/Kconfig=338=config MICROSEMI_PHY\n--\ndrivers/net/phy/Kconfig-346-\ndrivers/net/phy/Kconfig:347:config MOTORCOMM_PHY\ndrivers/net/phy/Kconfig-348-\ttristate \"Motorcomm PHYs\"\n"
}

23/2 2026/07/26 00:06 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 57539
							output: 36
							thoughts: 21
						

Thoughts:
Here's my analysis of the `drivers/net/phy/Kconfig` file, specifically around the `MOTORCOMM_PHY` section:

**Diving into the MOTORCOMM_PHY Configuration**

Okay, let's get down to brass tacks. I need to understand how the MOTORCOMM PHY driver is configured within the broader networking infrastructure. I'll zero in on the relevant Kconfig file, expecting to find the standard configuration mechanisms – things like `bool`, `tristate`, `depends on`, and `select` directives. I'm looking for a clear description of the build options, any dependencies on other kernel features or hardware, and how the driver's inclusion is managed within the overall network PHY framework. I'll want to see how it's integrated, any special considerations for this specific PHY, and how it interacts with the broader networking subsystems. It's crucial to grasp how it fits into the build process and what conditions trigger its inclusion. The presence of any symbol definitions or defaults would also be highly interesting, as that will provide additional insight on how things are initialized, configured and handled. Understanding these details will allow me to ensure it's built, configured, and working as expected within the target environment.



24/2 2026/07/26 00:06 tool read-file
0m Args:
{
  "File": "drivers/net/phy/Kconfig",
  "FirstLine": 340,
  "LineCount": 20
}

Results:
{
  "Contents": " 340:\t\tdepends on MACSEC || MACSEC=n\n 341:\t\tdepends on PTP_1588_CLOCK_OPTIONAL || !NETWORK_PHY_TIMESTAMPING\n 342:\t\tselect CRYPTO_LIB_AES if MACSEC\n 343:\t\tselect PHY_PACKAGE\n 344:\t\thelp\n 345:\t\t  Currently supports VSC8514, VSC8530, VSC8531, VSC8540 and VSC8541 PHYs\n 346:\t\n 347:\tconfig MOTORCOMM_PHY\n 348:\t\ttristate \"Motorcomm PHYs\"\n 349:\t\thelp\n 350:\t\t  Enables support for Motorcomm network PHYs.\n 351:\t\t  Currently supports YT85xx Gigabit Ethernet PHYs.\n 352:\t\n 353:\tconfig NATIONAL_PHY\n 354:\t\ttristate \"National Semiconductor PHYs\"\n 355:\t\thelp\n 356:\t\t  Currently supports the DP83865 PHY.\n 357:\t\n 358:\tconfig NXP_CBTX_PHY\n 359:\t\ttristate \"NXP 100BASE-TX PHYs\"\n"
}

25/2 2026/07/26 00:06 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 58179
							output: 303
							thoughts: 336
						

Thoughts:
**My Assessment of the YT8824 PHY Driver Patch**

Okay, let's break this down. From what I see, this new driver for the Motorcomm YT8824 Quad Ports 2.5Gbps Ethernet PHY is pretty straightforward in terms of dependencies. It only needs `MOTORCOMM_PHY` to be specified, which, if I understand correctly, implies that it inherits the dependencies of the broader `menuconfig PHYLIB` or similar, which simplifies things. No custom stuff, which is always good.

Now, let's get into the specifics for fuzzing. It's flagged as `WorthFuzzing: true`, which is encouraging, and the patch has provided a useful list of `FocusSymbols`. These are the key functions we'll want to target with fuzzing: `yt8824_read_page`, `yt8824_write_page`, the interrupt configuration and handling functions, the probe function, the autonegotiation routines, initialization, status reading, reset, suspend/resume, and even `genphy_c45_template_testmode` – smart, covering all bases.

The `EnableConfigs` simply lists `MOTORCOMM_PHY` confirming the earlier dependency discussion.

The reasoning provided makes complete sense. We have a solid avenue for fuzzing this driver. The use of emulated MDIO buses in virtualized environments like QEMU opens up this driver to be fuzzed through tools like Syzkaller. Syzkaller can present itself as a USB device, simulate the MDIO reads, trigger the PHY instantiation when it sends the right PHY ID (0x4f51e8b8), and then the driver can be fuzzed. That's a classic setup for this kind of work. We should be able to get a lot out of this!



26/2 2026/07/26 00:07 tool set-results
0m Args:
{
  "EnableConfigs": [
    "MOTORCOMM_PHY"
  ],
  "FocusSymbols": [
    "genphy_c45_template_testmode",
    "yt8824_aneg_done",
    "yt8824_config_aneg",
    "yt8824_config_init",
    "yt8824_config_intr",
    "yt8824_handle_interrupt",
    "yt8824_probe",
    "yt8824_read_page",
    "yt8824_read_status",
    "yt8824_resume",
    "yt8824_soft_reset",
    "yt8824_suspend",
    "yt8824_write_page"
  ],
  "Reasoning": "The patch adds support for the Motorcomm YT8824 Quad Ports 2.5Gbps Ethernet PHY. PHY drivers are accessible and fuzzable in virtualized environments (like QEMU) via emulated MDIO buses (e.g., through USB network adapters like smsc95xx that expose an MDIO bus). Syzkaller can emulate the USB device, respond to MDIO reads with the Motorcomm PHY ID (0x4f51e8b8), and trigger the instantiation and execution of this PHY driver.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "MOTORCOMM_PHY"
  ],
  "FocusSymbols": [
    "genphy_c45_template_testmode",
    "yt8824_aneg_done",
    "yt8824_config_aneg",
    "yt8824_config_init",
    "yt8824_config_intr",
    "yt8824_handle_interrupt",
    "yt8824_probe",
    "yt8824_read_page",
    "yt8824_read_status",
    "yt8824_resume",
    "yt8824_soft_reset",
    "yt8824_suspend",
    "yt8824_write_page"
  ],
  "Reasoning": "The patch adds support for the Motorcomm YT8824 Quad Ports 2.5Gbps Ethernet PHY. PHY drivers are accessible and fuzzable in virtualized environments (like QEMU) via emulated MDIO buses (e.g., through USB network adapters like smsc95xx that expose an MDIO bus). Syzkaller can emulate the USB device, respond to MDIO reads with the Motorcomm PHY ID (0x4f51e8b8), and trigger the instantiation and execution of this PHY driver.",
  "WorthFuzzing": true
}

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)