AI Trajectory


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

Results:
{
  "EnableConfigs": [
    "R8169"
  ],
  "FocusSymbols": [
    "phylink_set_mac_capabilities",
    "rtl_init_phylink",
    "rtl8169_pcs_config",
    "rtl8169_pcs_get_state",
    "rtl_mac_link_up",
    "rtl_mac_link_down",
    "rtl_mac_select_pcs",
    "rtl_mac_disable_tx_lpi",
    "rtl_mac_enable_tx_lpi",
    "rtl8169_change_mtu",
    "rtl_lowpower_hidden_functions",
    "r8127_sfp_init_1g",
    "r8127_sfp_init_10g",
    "rtl8169_ioctl"
  ],
  "Reasoning": "The patch migrates the Realtek r8169 Ethernet driver from phylib to phylink, introducing significant functional changes to the driver's initialization, link management, and MTU handling. It also adds a new phylink API `phylink_set_mac_capabilities` to dynamically update MAC capabilities. These are reachable control-path functions that should be fuzzed, especially via syz_pci and netlink/ioctl interfaces.",
  "WorthFuzzing": true
}

1/1 2026/07/07 16:34 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 1f78500456b8393ead6d6fbc15a49c3b5850a9f4\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Tue Jul 7 16:34:39 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/ethernet/realtek/Kconfig b/drivers/net/ethernet/realtek/Kconfig\nindex 9b0f4f9631dbaa..49ac72734225f7 100644\n--- a/drivers/net/ethernet/realtek/Kconfig\n+++ b/drivers/net/ethernet/realtek/Kconfig\n@@ -88,6 +88,7 @@ config R8169\n \tselect CRC32\n \tselect PHYLIB\n \tselect REALTEK_PHY\n+\tselect PHYLINK\n \thelp\n \t  Say Y here if you have a Realtek Ethernet adapter belonging to\n \t  the following families:\ndiff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c\nindex ec4fc21fa21fb0..12e073b9a61479 100644\n--- a/drivers/net/ethernet/realtek/r8169_main.c\n+++ b/drivers/net/ethernet/realtek/r8169_main.c\n@@ -26,12 +26,12 @@\n #include \u003clinux/dma-mapping.h\u003e\n #include \u003clinux/pm_runtime.h\u003e\n #include \u003clinux/bitfield.h\u003e\n+#include \u003clinux/phylink.h\u003e\n #include \u003clinux/prefetch.h\u003e\n #include \u003clinux/ipv6.h\u003e\n #include \u003clinux/unaligned.h\u003e\n #include \u003cnet/ip6_checksum.h\u003e\n #include \u003cnet/netdev_queues.h\u003e\n-#include \u003cnet/phy/realtek_phy.h\u003e\n \n #include \"r8169.h\"\n #include \"r8169_firmware.h\"\n@@ -96,6 +96,28 @@\n #define JUMBO_9K\t(9 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)\n #define JUMBO_16K\t(SZ_16K - VLAN_ETH_HLEN - ETH_FCS_LEN)\n \n+#define OCP_SDS_ADDR_REG\t\t0xEB10\n+#define OCP_SDS_CMD_REG\t\t\t0xEB0E\n+#define OCP_SDS_DATA_REG\t\t0xEB14\n+#define SDS_CMD_READ\t\t\t0x0001\n+#define RTL_SDS_C22_BASE\t\t0x40\n+#define RTL_SDS_C45_BASE\t\t0x0080\n+#define RTL_PKG_DETECT\t\t\t0xdc00\n+#define RTL_PKG_DETECT_MASK\t\t0x0078\n+#define RTL_PKG_DETECT_8116AF\t\t0x0030\n+#define RTL_INT_HW_ID\t\t\t0xd006\n+#define RTL_INT_HW_ID_MASK\t\t0x00ff\n+#define RTL_INT_HW_ID_8116AF\t\t0x0000\n+#define RTL8116AF_FUNC_PM_CSR\t\t0x80\n+#define RTL8116AF_FUNC_EXP_LNKCTL\t0x44\n+#define RTL_PM_D3HOT\t\t\tGENMASK(1, 0)\n+#define R8127_SDS_CMD\t\t\t0x2348\n+#define R8127_SDS_ADDR\t\t\t0x234a\n+#define R8127_SDS_DATA_IN\t\t0x234c\n+#define R8127_SDS_DATA_OUT\t\t0x234e\n+#define R8127_SDS_CMD_EXEC\t\tBIT(0)\n+#define R8127_SDS_CMD_WE\t\tBIT(1)\n+\n static const struct rtl_chip_info {\n \tu32 mask;\n \tu32 val;\n@@ -334,11 +356,13 @@ enum rtl_registers {\n \tALDPS_LTR\t= 0xe0a2,\n \tLTR_OBFF_LOCK\t= 0xe032,\n \tLTR_SNOOP\t= 0xe034,\n+\tSEND_LTR_MSG\t= 0xe038,\n \n #define ALDPS_LTR_EN\t\t\tBIT(0)\n #define LTR_OBFF_LOCK_EN\t\tBIT(0)\n #define LINK_SPEED_CHANGE_EN\t\tBIT(14)\n #define LTR_SNOOP_EN\t\t\tGENMASK(15, 14)\n+#define LTR_MSG_EN\t\t\tBIT(0)\n };\n \n enum rtl8168_8101_registers {\n@@ -728,6 +752,12 @@ enum rtl_dash_type {\n \tRTL_DASH_25_BP,\n };\n \n+enum rtl_sfp_mode {\n+\tRTL_SFP_NONE,\n+\tRTL_SFP_8168_AF,\n+\tRTL_SFP_8127_ATF,\n+};\n+\n struct rtl8169_private {\n \tvoid __iomem *mmio_addr;\t/* memory map physical address */\n \tstruct pci_dev *pci_dev;\n@@ -736,6 +766,7 @@ struct rtl8169_private {\n \tstruct napi_struct napi;\n \tenum mac_version mac_version;\n \tenum rtl_dash_type dash_type;\n+\tenum rtl_sfp_mode sfp_mode;\n \tu32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */\n \tu32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */\n \tu32 dirty_tx;\n@@ -750,6 +781,7 @@ struct rtl8169_private {\n \tu32 irq_mask;\n \tint irq;\n \tstruct clk *clk;\n+\tint speed;\n \n \tstruct {\n \t\tDECLARE_BITMAP(flags, RTL_FLAG_MAX);\n@@ -762,7 +794,6 @@ struct rtl8169_private {\n \tunsigned supports_gmii:1;\n \tunsigned aspm_manageable:1;\n \tunsigned dash_enabled:1;\n-\tbool sfp_mode:1;\n \tdma_addr_t counters_phys_addr;\n \tstruct rtl8169_counters *counters;\n \tstruct rtl8169_tc_offsets tc_offset;\n@@ -774,6 +805,11 @@ struct rtl8169_private {\n \tstruct r8169_led_classdev *leds;\n \n \tu32 ocp_base;\n+\tstruct phylink *phylink;\n+\tstruct phylink_config phylink_config;\n+\tstruct phylink_pcs pcs;\n+\tstruct ethtool_pauseparam saved_pause;\n+\tbool jumbo_pause_saved;\n };\n \n typedef void (*rtl_generic_fct)(struct rtl8169_private *tp);\n@@ -1128,10 +1164,6 @@ static int r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)\n \tif (rtl_ocp_reg_failure(reg))\n \t\treturn 0;\n \n-\t/* Return dummy MII_PHYSID2 in SFP mode to match SFP PHY driver */\n-\tif (tp-\u003esfp_mode \u0026\u0026 reg == (OCP_STD_PHY_BASE + 2 * MII_PHYSID2))\n-\t\treturn PHY_ID_RTL_DUMMY_SFP \u0026 0xffff;\n-\n \tRTL_W32(tp, GPHY_OCP, reg \u003c\u003c 15);\n \n \treturn rtl_loop_wait_high(tp, \u0026rtl_ocp_gphy_cond, 25, 10) ?\n@@ -1199,6 +1231,67 @@ static void r8127_sfp_sds_phy_reset(struct rtl8169_private *tp)\n \tusleep_range(10, 20);\n }\n \n+DECLARE_RTL_COND(r8127_sds_cmd_cond)\n+{\n+\treturn RTL_R16(tp, R8127_SDS_CMD) \u0026 R8127_SDS_CMD_EXEC;\n+}\n+\n+static u16 r8127_sds_read(struct rtl8169_private *tp, u16 index, u16 page, u16 reg)\n+{\n+\tu16 addr = (index \u003c\u003c 11) | (page \u003c\u003c 5) | reg;\n+\n+\tRTL_W16(tp, R8127_SDS_ADDR, addr);\n+\tRTL_W16(tp, R8127_SDS_CMD, R8127_SDS_CMD_EXEC);\n+\n+\tif (rtl_loop_wait_low(tp, \u0026r8127_sds_cmd_cond, 10, 100))\n+\t\treturn RTL_R16(tp, R8127_SDS_DATA_OUT);\n+\n+\treturn 0xffff;\n+}\n+\n+static void r8127_sds_write(struct rtl8169_private *tp, u16 index, u16 page,\n+\t\t\t    u16 reg, u16 val)\n+{\n+\tu16 addr = (index \u003c\u003c 11) | (page \u003c\u003c 5) | reg;\n+\n+\tRTL_W16(tp, R8127_SDS_DATA_IN, val);\n+\tRTL_W16(tp, R8127_SDS_ADDR, addr);\n+\tRTL_W16(tp, R8127_SDS_CMD, R8127_SDS_CMD_EXEC | R8127_SDS_CMD_WE);\n+\n+\trtl_loop_wait_low(tp, \u0026r8127_sds_cmd_cond, 10, 100);\n+}\n+\n+static void r8127_sds_modify(struct rtl8169_private *tp, u16 index, u16 page,\n+\t\t\t     u16 reg, u16 clearmask, u16 setmask)\n+{\n+\tu16 val = r8127_sds_read(tp, index, page, reg);\n+\n+\tval = (val \u0026 ~clearmask) | setmask;\n+\tr8127_sds_write(tp, index, page, reg, val);\n+}\n+\n+static void r8127_sfp_init_1g(struct rtl8169_private *tp)\n+{\n+\tint val;\n+\n+\tr8127_sfp_sds_phy_reset(tp);\n+\n+\tr8127_sds_modify(tp, 0, 1, 31, 0, BIT(3));\n+\tr8127_sds_modify(tp, 0, 2,  0, BIT(13) | BIT(12) | BIT(6), BIT(12) | BIT(6));\n+\tr8127_sds_modify(tp, 0, 0,  4, 0, BIT(2));\n+\n+\tRTL_W16(tp, 0x233a, 0x8004);\n+\tRTL_W16(tp, 0x233e, (RTL_R16(tp, 0x233e) \u0026 ~0x3003) | 0x0002);\n+\n+\tr8168_phy_ocp_write(tp, 0xc40a, 0x0000);\n+\tr8168_phy_ocp_write(tp, 0xc466, 0x0000);\n+\tr8168_phy_ocp_write(tp, 0xc808, 0x0000);\n+\tr8168_phy_ocp_write(tp, 0xc80a, 0x0000);\n+\n+\tval = r8168_phy_ocp_read(tp, 0xc804);\n+\tr8168_phy_ocp_write(tp, 0xc804, (val \u0026 ~0x000f) | 0x000c);\n+}\n+\n static void r8127_sfp_init_10g(struct rtl8169_private *tp)\n {\n \tint val;\n@@ -1217,12 +1310,6 @@ static void r8127_sfp_init_10g(struct rtl8169_private *tp)\n \tr8168_phy_ocp_write(tp, 0xc804, (val \u0026 ~0x000f) | 0x000c);\n }\n \n-static void rtl_sfp_init(struct rtl8169_private *tp)\n-{\n-\tif (tp-\u003emac_version == RTL_GIGA_MAC_VER_80)\n-\t\tr8127_sfp_init_10g(tp);\n-}\n-\n static void rtl_sfp_reset(struct rtl8169_private *tp)\n {\n \tif (tp-\u003emac_version == RTL_GIGA_MAC_VER_80)\n@@ -1283,6 +1370,15 @@ static void mac_mcu_write(struct rtl8169_private *tp, int reg, int value)\n \tr8168_mac_ocp_write(tp, tp-\u003eocp_base + reg, value);\n }\n \n+static bool rtl_is_8116af(struct rtl8169_private *tp)\n+{\n+\treturn tp-\u003emac_version == RTL_GIGA_MAC_VER_52 \u0026\u0026\n+\t\t(r8168_mac_ocp_read(tp, RTL_PKG_DETECT) \u0026 RTL_PKG_DETECT_MASK) ==\n+\t\tRTL_PKG_DETECT_8116AF \u0026\u0026\n+\t\t(r8168_mac_ocp_read(tp, RTL_INT_HW_ID) \u0026 RTL_INT_HW_ID_MASK) ==\n+\t\tRTL_INT_HW_ID_8116AF;\n+}\n+\n static int mac_mcu_read(struct rtl8169_private *tp, int reg)\n {\n \treturn r8168_mac_ocp_read(tp, tp-\u003eocp_base + reg);\n@@ -1578,6 +1674,20 @@ static bool rtl_dash_is_enabled(struct rtl8169_private *tp)\n \t}\n }\n \n+static enum rtl_sfp_mode rtl_get_sfp_mode(struct rtl8169_private *tp)\n+{\n+\tif (rtl_is_8125(tp)) {\n+\t\tu16 data = r8168_mac_ocp_read(tp, RTL_INT_HW_ID);\n+\n+\t\tif ((data \u0026 0xff) == 0x07)\n+\t\t\treturn RTL_SFP_8127_ATF;\n+\t} else if (rtl_is_8116af(tp)) {\n+\t\treturn RTL_SFP_8168_AF;\n+\t}\n+\n+\treturn RTL_SFP_NONE;\n+}\n+\n static enum rtl_dash_type rtl_get_dash_type(struct rtl8169_private *tp)\n {\n \tswitch (tp-\u003emac_version) {\n@@ -1673,16 +1783,14 @@ static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)\n \trtl_pci_commit(tp);\n }\n \n-static void rtl_link_chg_patch(struct rtl8169_private *tp)\n+static void rtl_link_chg_patch(struct rtl8169_private *tp, int speed)\n {\n-\tstruct phy_device *phydev = tp-\u003ephydev;\n-\n \tif (tp-\u003emac_version == RTL_GIGA_MAC_VER_34 ||\n \t    tp-\u003emac_version == RTL_GIGA_MAC_VER_38) {\n-\t\tif (phydev-\u003espeed == SPEED_1000) {\n+\t\tif (speed == SPEED_1000) {\n \t\t\trtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011);\n \t\t\trtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);\n-\t\t} else if (phydev-\u003espeed == SPEED_100) {\n+\t\t} else if (speed == SPEED_100) {\n \t\t\trtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f);\n \t\t\trtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);\n \t\t} else {\n@@ -1692,7 +1800,7 @@ static void rtl_link_chg_patch(struct rtl8169_private *tp)\n \t\trtl_reset_packet_filter(tp);\n \t} else if (tp-\u003emac_version == RTL_GIGA_MAC_VER_35 ||\n \t\t   tp-\u003emac_version == RTL_GIGA_MAC_VER_36) {\n-\t\tif (phydev-\u003espeed == SPEED_1000) {\n+\t\tif (speed == SPEED_1000) {\n \t\t\trtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011);\n \t\t\trtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);\n \t\t} else {\n@@ -1700,7 +1808,7 @@ static void rtl_link_chg_patch(struct rtl8169_private *tp)\n \t\t\trtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f);\n \t\t}\n \t} else if (tp-\u003emac_version == RTL_GIGA_MAC_VER_37) {\n-\t\tif (phydev-\u003espeed == SPEED_10) {\n+\t\tif (speed == SPEED_10) {\n \t\t\trtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02);\n \t\t\trtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060a);\n \t\t} else {\n@@ -2074,11 +2182,11 @@ rtl_coalesce_info(struct rtl8169_private *tp)\n \t\tci = rtl_coalesce_info_8168_8136;\n \n \t/* if speed is unknown assume highest one */\n-\tif (tp-\u003ephydev-\u003espeed == SPEED_UNKNOWN)\n+\tif (tp-\u003espeed == SPEED_UNKNOWN)\n \t\treturn ci;\n \n \tfor (; ci-\u003espeed; ci++) {\n-\t\tif (tp-\u003ephydev-\u003espeed == ci-\u003espeed)\n+\t\tif (tp-\u003espeed == ci-\u003espeed)\n \t\t\treturn ci;\n \t}\n \n@@ -2236,7 +2344,7 @@ static void rtl_set_eee_txidle_timer(struct rtl8169_private *tp)\n \n static unsigned int r8169_get_tx_lpi_timer_us(struct rtl8169_private *tp)\n {\n-\tunsigned int speed = tp-\u003ephydev-\u003espeed;\n+\tunsigned int speed = tp-\u003espeed;\n \tunsigned int timer = tp-\u003etx_lpi_timer;\n \n \tif (!timer || speed == SPEED_UNKNOWN)\n@@ -2254,7 +2362,7 @@ static int rtl8169_get_eee(struct net_device *dev, struct ethtool_keee *data)\n \tif (!rtl_supports_eee(tp))\n \t\treturn -EOPNOTSUPP;\n \n-\tret = phy_ethtool_get_eee(tp-\u003ephydev, data);\n+\tret = phylink_ethtool_get_eee(tp-\u003ephylink, data);\n \tif (ret)\n \t\treturn ret;\n \n@@ -2270,7 +2378,7 @@ static int rtl8169_set_eee(struct net_device *dev, struct ethtool_keee *data)\n \tif (!rtl_supports_eee(tp))\n \t\treturn -EOPNOTSUPP;\n \n-\treturn phy_ethtool_set_eee(tp-\u003ephydev, data);\n+\treturn phylink_ethtool_set_eee(tp-\u003ephylink, data);\n }\n \n static void rtl8169_get_ringparam(struct net_device *dev,\n@@ -2301,13 +2409,8 @@ static void rtl8169_get_pauseparam(struct net_device *dev,\n \t\t\t\t   struct ethtool_pauseparam *data)\n {\n \tstruct rtl8169_private *tp = netdev_priv(dev);\n-\tbool tx_pause, rx_pause;\n \n-\tphy_get_pause(tp-\u003ephydev, \u0026tx_pause, \u0026rx_pause);\n-\n-\tdata-\u003eautoneg = tp-\u003ephydev-\u003eautoneg;\n-\tdata-\u003etx_pause = tx_pause ? 1 : 0;\n-\tdata-\u003erx_pause = rx_pause ? 1 : 0;\n+\tphylink_ethtool_get_pauseparam(tp-\u003ephylink, data);\n }\n \n static int rtl8169_set_pauseparam(struct net_device *dev,\n@@ -2318,9 +2421,7 @@ static int rtl8169_set_pauseparam(struct net_device *dev,\n \tif (dev-\u003emtu \u003e ETH_DATA_LEN)\n \t\treturn -EOPNOTSUPP;\n \n-\tphy_set_asym_pause(tp-\u003ephydev, data-\u003erx_pause, data-\u003etx_pause);\n-\n-\treturn 0;\n+\treturn phylink_ethtool_set_pauseparam(tp-\u003ephylink, data);\n }\n \n static void rtl8169_get_eth_mac_stats(struct net_device *dev,\n@@ -2386,34 +2487,27 @@ static void rtl8169_get_eth_ctrl_stats(struct net_device *dev,\n \t\tle32_to_cpu(tp-\u003ecounters-\u003erx_unknown_opcode);\n }\n \n-static int rtl8169_set_link_ksettings(struct net_device *ndev,\n-\t\t\t\t      const struct ethtool_link_ksettings *cmd)\n+static int rtl8169_get_link_ksettings(struct net_device *ndev,\n+\t\t\t\t      struct ethtool_link_ksettings *cmd)\n {\n \tstruct rtl8169_private *tp = netdev_priv(ndev);\n-\tstruct phy_device *phydev = tp-\u003ephydev;\n-\tint duplex = cmd-\u003ebase.duplex;\n-\tint speed = cmd-\u003ebase.speed;\n-\n-\tif (!tp-\u003esfp_mode)\n-\t\treturn phy_ethtool_ksettings_set(phydev, cmd);\n-\n-\tif (cmd-\u003ebase.autoneg != AUTONEG_DISABLE)\n-\t\treturn -EINVAL;\n \n-\tif (!phy_check_valid(speed, duplex, phydev-\u003esupported))\n-\t\treturn -EINVAL;\n-\n-\tmutex_lock(\u0026phydev-\u003elock);\n+\treturn phylink_ethtool_ksettings_get(tp-\u003ephylink, cmd);\n+}\n \n-\tphydev-\u003eautoneg = AUTONEG_DISABLE;\n-\tphydev-\u003espeed = speed;\n-\tphydev-\u003eduplex = duplex;\n+static int rtl8169_set_link_ksettings(struct net_device *ndev,\n+\t\t\t\t      const struct ethtool_link_ksettings *cmd)\n+{\n+\tstruct rtl8169_private *tp = netdev_priv(ndev);\n \n-\trtl_sfp_init(tp);\n+\treturn phylink_ethtool_ksettings_set(tp-\u003ephylink, cmd);\n+}\n \n-\tmutex_unlock(\u0026phydev-\u003elock);\n+static int rtl8169_nway_reset(struct net_device *dev)\n+{\n+\tstruct rtl8169_private *tp = netdev_priv(dev);\n \n-\treturn 0;\n+\treturn phylink_ethtool_nway_reset(tp-\u003ephylink);\n }\n \n static const struct ethtool_ops rtl8169_ethtool_ops = {\n@@ -2431,10 +2525,10 @@ static const struct ethtool_ops rtl8169_ethtool_ops = {\n \t.get_sset_count\t\t= rtl8169_get_sset_count,\n \t.get_ethtool_stats\t= rtl8169_get_ethtool_stats,\n \t.get_ts_info\t\t= ethtool_op_get_ts_info,\n-\t.nway_reset\t\t= phy_ethtool_nway_reset,\n+\t.nway_reset\t\t= rtl8169_nway_reset,\n \t.get_eee\t\t= rtl8169_get_eee,\n \t.set_eee\t\t= rtl8169_set_eee,\n-\t.get_link_ksettings\t= phy_ethtool_get_link_ksettings,\n+\t.get_link_ksettings\t= rtl8169_get_link_ksettings,\n \t.set_link_ksettings\t= rtl8169_set_link_ksettings,\n \t.get_ringparam\t\t= rtl8169_get_ringparam,\n \t.get_pause_stats\t= rtl8169_get_pause_stats,\n@@ -2499,9 +2593,10 @@ void r8169_apply_firmware(struct rtl8169_private *tp)\n \t\ttp-\u003eocp_base = OCP_STD_PHY_BASE;\n \n \t\t/* PHY soft reset may still be in progress */\n-\t\tphy_read_poll_timeout(tp-\u003ephydev, MII_BMCR, val,\n-\t\t\t\t      !(val \u0026 BMCR_RESET),\n-\t\t\t\t      50000, 600000, true);\n+\t\tif (tp-\u003ephydev)\n+\t\t\tphy_read_poll_timeout(tp-\u003ephydev, MII_BMCR, val,\n+\t\t\t\t\t      !(val \u0026 BMCR_RESET),\n+\t\t\t\t\t      50000, 600000, true);\n \t}\n }\n \n@@ -2538,6 +2633,8 @@ static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)\n \n static void rtl8169_init_phy(struct rtl8169_private *tp)\n {\n+\tphy_init_hw(tp-\u003ephydev);\n+\tphy_resume(tp-\u003ephydev);\n \tr8169_hw_phy_config(tp, tp-\u003ephydev, tp-\u003emac_version);\n \n \tif (tp-\u003emac_version \u003c= RTL_GIGA_MAC_VER_06) {\n@@ -2552,9 +2649,6 @@ static void rtl8169_init_phy(struct rtl8169_private *tp)\n \t    tp-\u003epci_dev-\u003esubsystem_device == 0xe000)\n \t\tphy_write_paged(tp-\u003ephydev, 0x0001, 0x10, 0xf01b);\n \n-\tif (tp-\u003esfp_mode)\n-\t\trtl_sfp_init(tp);\n-\n \t/* We may have called phy_speed_down before */\n \tphy_speed_up(tp-\u003ephydev);\n \n@@ -2657,15 +2751,6 @@ static void rtl_jumbo_config(struct rtl8169_private *tp)\n \n \tif (pci_is_pcie(tp-\u003epci_dev) \u0026\u0026 tp-\u003esupports_gmii)\n \t\tpcie_set_readrq(tp-\u003epci_dev, readrq);\n-\n-\t/* Chip doesn't support pause in jumbo mode */\n-\tif (jumbo) {\n-\t\tlinkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT,\n-\t\t\t\t   tp-\u003ephydev-\u003eadvertising);\n-\t\tlinkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,\n-\t\t\t\t   tp-\u003ephydev-\u003eadvertising);\n-\t\tphy_start_aneg(tp-\u003ephydev);\n-\t}\n }\n \n DECLARE_RTL_COND(rtl_chipcmd_cond)\n@@ -2780,7 +2865,7 @@ static void rtl_prepare_power_down(struct rtl8169_private *tp)\n \t\trtl_ephy_write(tp, 0x19, 0xff64);\n \n \tif (device_may_wakeup(tp_to_dev(tp))) {\n-\t\tphy_speed_down(tp-\u003ephydev, false);\n+\t\tphylink_speed_down(tp-\u003ephylink, false);\n \t\trtl_wol_enable_rx(tp);\n \t}\n }\n@@ -2832,6 +2917,16 @@ static void rtl8169_set_magic_reg(struct rtl8169_private *tp)\n \tRTL_W32(tp, 0x7c, val);\n }\n \n+static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)\n+{\n+\tstruct rtl8169_private *tp = netdev_priv(dev);\n+\n+\tif (!netif_running(dev))\n+\t\treturn -ENODEV;\n+\n+\treturn phylink_mii_ioctl(tp-\u003ephylink, ifr, cmd);\n+}\n+\n static void rtl_set_rx_mode(struct net_device *dev)\n {\n \tu32 rx_mode = AcceptBroadcast | AcceptMyPhys | AcceptMulticast;\n@@ -3098,8 +3193,22 @@ static void rtl_enable_ltr(struct rtl8169_private *tp)\n \t\tr8168_mac_ocp_write(tp, 0xcdf2, 0x9003);\n \t\tr8168_mac_ocp_modify(tp, LTR_OBFF_LOCK, 0x0000, LINK_SPEED_CHANGE_EN);\n \t\tbreak;\n-\tcase RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:\n \tcase RTL_GIGA_MAC_VER_52:\n+\t\tr8168_mac_ocp_write(tp, 0xcdd0, 0x9003);\n+\t\tr8168_mac_ocp_modify(tp, LTR_SNOOP, 0x0000, LTR_SNOOP_EN);\n+\t\tr8168_mac_ocp_write(tp, 0xe02c, 0x1880);\n+\t\tr8168_mac_ocp_write(tp, 0xe02e, 0x4880);\n+\t\tr8168_mac_ocp_modify(tp, ALDPS_LTR, 0x0000, ALDPS_LTR_EN);\n+\t\tr8168_mac_ocp_write(tp, 0xcdd8, 0x9003);\n+\t\tr8168_mac_ocp_write(tp, 0xcdda, 0x9003);\n+\t\tr8168_mac_ocp_write(tp, 0xcddc, 0x9003);\n+\t\tr8168_mac_ocp_write(tp, 0xcdd2, 0x883c);\n+\t\tr8168_mac_ocp_write(tp, 0xcdd4, 0x8c12);\n+\t\tr8168_mac_ocp_write(tp, 0xcdd6, 0x9003);\n+\t\tr8168_mac_ocp_write(tp, 0xe0a6, 0x9003);\n+\t\tr8168_mac_ocp_write(tp, 0xe0a8, 0x9003);\n+\t\tbreak;\n+\tcase RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:\n \t\tr8168_mac_ocp_modify(tp, ALDPS_LTR, 0x0000, ALDPS_LTR_EN);\n \t\tRTL_W8(tp, COMBO_LTR_EXTEND, RTL_R8(tp, COMBO_LTR_EXTEND) | COMBO_LTR_EXTEND_EN);\n \t\tfallthrough;\n@@ -3119,6 +3228,7 @@ static void rtl_enable_ltr(struct rtl8169_private *tp)\n \t}\n \t/* chip can trigger LTR */\n \tr8168_mac_ocp_modify(tp, LTR_OBFF_LOCK, 0x0003, LTR_OBFF_LOCK_EN);\n+\tr8168_mac_ocp_modify(tp, SEND_LTR_MSG, 0x0000, LTR_MSG_EN);\n }\n \n static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)\n@@ -3152,6 +3262,7 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)\n \t\trtl_enable_ltr(tp);\n \t\tswitch (tp-\u003emac_version) {\n \t\tcase RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:\n+\t\tcase RTL_GIGA_MAC_VER_52:\n \t\tcase RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_LAST:\n \t\t\t/* reset ephy tx/rx disable timer */\n \t\t\tr8168_mac_ocp_modify(tp, 0xe094, 0xff00, 0);\n@@ -3164,6 +3275,7 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)\n \t} else {\n \t\tswitch (tp-\u003emac_version) {\n \t\tcase RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:\n+\t\tcase RTL_GIGA_MAC_VER_52:\n \t\tcase RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_LAST:\n \t\t\tr8168_mac_ocp_modify(tp, 0xe092, 0x00ff, 0);\n \t\t\tbreak;\n@@ -3657,6 +3769,35 @@ static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)\n \tr8168_mac_ocp_modify(tp, 0xe860, 0x0000, 0x0080);\n }\n \n+static void rtl_lowpower_hidden_functions(struct pci_dev *pdev)\n+{\n+\tunsigned int slot = PCI_SLOT(pdev-\u003edevfn);\n+\tstruct pci_bus *bus = pdev-\u003ebus;\n+\tunsigned int devfn;\n+\tint func;\n+\tint ret;\n+\tu32 val;\n+\n+\tfor (func = 2; func \u003c 8; func++) {\n+\t\tdevfn = PCI_DEVFN(slot, func);\n+\n+\t\tret = pci_bus_read_config_dword(bus, devfn, RTL8116AF_FUNC_PM_CSR, \u0026val);\n+\t\tif (!ret \u0026\u0026 !PCI_POSSIBLE_ERROR(val)) {\n+\t\t\tval \u0026= ~PCI_PM_CTRL_PME_STATUS;\n+\t\t\tval \u0026= ~(PCI_PM_CTRL_STATE_MASK | PCI_PM_CTRL_PME_ENABLE);\n+\t\t\tval |= (RTL_PM_D3HOT | PCI_PM_CTRL_PME_ENABLE);\n+\t\t\tpci_bus_write_config_dword(bus, devfn, RTL8116AF_FUNC_PM_CSR, val);\n+\t\t}\n+\n+\t\tret = pci_bus_read_config_dword(bus, devfn, RTL8116AF_FUNC_EXP_LNKCTL, \u0026val);\n+\t\tif (!ret \u0026\u0026 !PCI_POSSIBLE_ERROR(val)) {\n+\t\t\tval \u0026= ~((PCI_EXP_LNKSTA_LBMS | PCI_EXP_LNKSTA_LABS) \u003c\u003c 16);\n+\t\t\tval |= PCI_EXP_LNKCTL_ASPMC;\n+\t\t\tpci_bus_write_config_dword(bus, devfn, RTL8116AF_FUNC_EXP_LNKCTL, val);\n+\t\t}\n+\t}\n+}\n+\n static void rtl_hw_start_8117(struct rtl8169_private *tp)\n {\n \tstatic const struct ephy_info e_info_8117[] = {\n@@ -3693,12 +3834,14 @@ static void rtl_hw_start_8117(struct rtl8169_private *tp)\n \n \trtl_pcie_state_l2l3_disable(tp);\n \n-\trg_saw_cnt = phy_read_paged(tp-\u003ephydev, 0x0c42, 0x13) \u0026 0x3fff;\n-\tif (rg_saw_cnt \u003e 0) {\n-\t\tu16 sw_cnt_1ms_ini;\n+\tif (tp-\u003ephydev) {\n+\t\trg_saw_cnt = phy_read_paged(tp-\u003ephydev, 0x0c42, 0x13) \u0026 0x3fff;\n+\t\tif (rg_saw_cnt \u003e 0) {\n+\t\t\tu16 sw_cnt_1ms_ini;\n \n-\t\tsw_cnt_1ms_ini = (16000000 / rg_saw_cnt) \u0026 0x0fff;\n-\t\tr8168_mac_ocp_modify(tp, 0xd412, 0x0fff, sw_cnt_1ms_ini);\n+\t\t\tsw_cnt_1ms_ini = (16000000 / rg_saw_cnt) \u0026 0x0fff;\n+\t\t\tr8168_mac_ocp_modify(tp, 0xd412, 0x0fff, sw_cnt_1ms_ini);\n+\t\t}\n \t}\n \n \tr8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0000);\n@@ -3711,6 +3854,9 @@ static void rtl_hw_start_8117(struct rtl8169_private *tp)\n \tr8168_mac_ocp_write(tp, 0xc094, 0x0000);\n \tr8168_mac_ocp_write(tp, 0xc09e, 0x0000);\n \n+\tif (rtl_is_8116af(tp))\n+\t\trtl_lowpower_hidden_functions(tp-\u003epci_dev);\n+\n \t/* firmware is for MAC only */\n \tr8169_apply_firmware(tp);\n }\n@@ -4139,12 +4285,25 @@ static void rtl_hw_start(struct  rtl8169_private *tp)\n static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)\n {\n \tstruct rtl8169_private *tp = netdev_priv(dev);\n+\tbool jumbo_before = dev-\u003emtu \u003e ETH_DATA_LEN;\n+\tbool jumbo_after = new_mtu \u003e ETH_DATA_LEN;\n \n \tWRITE_ONCE(dev-\u003emtu, new_mtu);\n \tnetdev_update_features(dev);\n \trtl_jumbo_config(tp);\n \trtl_set_eee_txidle_timer(tp);\n \n+\tif (jumbo_before != jumbo_after) {\n+\t\tunsigned long caps = tp-\u003ephylink_config.mac_capabilities;\n+\n+\t\tif (jumbo_after)\n+\t\t\tcaps \u0026= ~(MAC_SYM_PAUSE | MAC_ASYM_PAUSE);\n+\t\telse\n+\t\t\tcaps |= (MAC_SYM_PAUSE | MAC_ASYM_PAUSE);\n+\n+\t\tphylink_set_mac_capabilities(tp-\u003ephylink, caps);\n+\t}\n+\n \treturn 0;\n }\n \n@@ -4869,8 +5028,13 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)\n \t\tgoto out;\n \t}\n \n-\tif (status \u0026 LinkChg)\n-\t\tphy_mac_interrupt(tp-\u003ephydev);\n+\tif (status \u0026 LinkChg) {\n+\t\tif (tp-\u003ephydev)\n+\t\t\tphy_mac_interrupt(tp-\u003ephydev);\n+\t\telse if (tp-\u003esfp_mode)\n+\t\t\tphylink_mac_change(tp-\u003ephylink,\n+\t\t\t\t\t   !!(RTL_R8(tp, PHYstatus) \u0026 LinkStatus));\n+\t}\n \n \trtl_irq_disable(tp);\n \tnapi_schedule(\u0026tp-\u003enapi);\n@@ -4930,9 +5094,6 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)\n \n static void rtl_enable_tx_lpi(struct rtl8169_private *tp, bool enable)\n {\n-\tif (!rtl_supports_eee(tp))\n-\t\treturn;\n-\n \tswitch (tp-\u003emac_version) {\n \tcase RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_52:\n \t\t/* Adjust EEE LED frequency */\n@@ -4963,40 +5124,15 @@ static void rtl_enable_tx_lpi(struct rtl8169_private *tp, bool enable)\n \t}\n }\n \n-static void r8169_phylink_handler(struct net_device *ndev)\n-{\n-\tstruct rtl8169_private *tp = netdev_priv(ndev);\n-\tstruct device *d = tp_to_dev(tp);\n-\n-\tif (netif_carrier_ok(ndev)) {\n-\t\trtl_link_chg_patch(tp);\n-\t\trtl_enable_tx_lpi(tp, tp-\u003ephydev-\u003eenable_tx_lpi);\n-\t\tpm_request_resume(d);\n-\t} else {\n-\t\tpm_runtime_idle(d);\n-\t}\n-\n-\tphy_print_status(tp-\u003ephydev);\n-}\n-\n static int r8169_phy_connect(struct rtl8169_private *tp)\n {\n-\tstruct phy_device *phydev = tp-\u003ephydev;\n-\tphy_interface_t phy_mode;\n \tint ret;\n \n-\tphy_mode = tp-\u003esupports_gmii ? PHY_INTERFACE_MODE_GMII :\n-\t\t   PHY_INTERFACE_MODE_MII;\n-\n-\tret = phy_connect_direct(tp-\u003edev, phydev, r8169_phylink_handler,\n-\t\t\t\t phy_mode);\n-\tif (ret)\n+\tret = phylink_connect_phy(tp-\u003ephylink, tp-\u003ephydev);\n+\tif (ret) {\n+\t\tnetdev_err(tp-\u003edev, \"failed to connect phy\\n\");\n \t\treturn ret;\n-\n-\tif (!tp-\u003esupports_gmii)\n-\t\tphy_set_max_speed(phydev, SPEED_100);\n-\n-\tphy_attached_info(phydev);\n+\t}\n \n \treturn 0;\n }\n@@ -5007,10 +5143,10 @@ static void rtl8169_down(struct rtl8169_private *tp)\n \t/* Clear all task flags */\n \tbitmap_zero(tp-\u003ewk.flags, RTL_FLAG_MAX);\n \n-\tphy_stop(tp-\u003ephydev);\n+\tphylink_stop(tp-\u003ephylink);\n \n \t/* Reset SerDes PHY to bring down fiber link */\n-\tif (tp-\u003esfp_mode)\n+\tif (tp-\u003esfp_mode == RTL_SFP_8127_ATF)\n \t\trtl_sfp_reset(tp);\n \n \trtl8169_update_counters(tp);\n@@ -5032,14 +5168,14 @@ static void rtl8169_up(struct rtl8169_private *tp)\n \t\trtl8168_driver_start(tp);\n \n \tpci_set_master(tp-\u003epci_dev);\n-\tphy_init_hw(tp-\u003ephydev);\n-\tphy_resume(tp-\u003ephydev);\n-\trtl8169_init_phy(tp);\n+\tif (tp-\u003ephydev)\n+\t\trtl8169_init_phy(tp);\n+\n \tnapi_enable(\u0026tp-\u003enapi);\n \tenable_work(\u0026tp-\u003ewk.work);\n \trtl_reset_work(tp);\n \n-\tphy_start(tp-\u003ephydev);\n+\tphylink_start(tp-\u003ephylink);\n }\n \n static int rtl8169_close(struct net_device *dev)\n@@ -5055,7 +5191,7 @@ static int rtl8169_close(struct net_device *dev)\n \n \tfree_irq(tp-\u003eirq, tp);\n \n-\tphy_disconnect(tp-\u003ephydev);\n+\tphylink_disconnect_phy(tp-\u003ephylink);\n \n \tdma_free_coherent(\u0026pdev-\u003edev, R8169_RX_RING_BYTES, tp-\u003eRxDescArray,\n \t\t\t  tp-\u003eRxPhyAddr);\n@@ -5112,9 +5248,11 @@ static int rtl_open(struct net_device *dev)\n \tif (retval \u003c 0)\n \t\tgoto err_release_fw_2;\n \n-\tretval = r8169_phy_connect(tp);\n-\tif (retval)\n-\t\tgoto err_free_irq;\n+\tif (tp-\u003ephydev) {\n+\t\tretval = r8169_phy_connect(tp);\n+\t\tif (retval)\n+\t\t\tgoto err_free_irq;\n+\t}\n \n \trtl8169_up(tp);\n \trtl8169_init_counter_offsets(tp);\n@@ -5190,8 +5328,11 @@ static int rtl8169_runtime_resume(struct device *dev)\n \trtl_rar_set(tp, tp-\u003edev-\u003edev_addr);\n \t__rtl8169_set_wol(tp, tp-\u003esaved_wolopts);\n \n-\tif (tp-\u003eTxDescArray)\n+\tif (tp-\u003eTxDescArray) {\n+\t\trtnl_lock();\n \t\trtl8169_up(tp);\n+\t\trtnl_unlock();\n+\t}\n \n \tnetif_device_attach(tp-\u003edev);\n \n@@ -5288,6 +5429,7 @@ static void rtl_remove_one(struct pci_dev *pdev)\n \t\tr8169_remove_leds(tp-\u003eleds);\n \n \tunregister_netdev(tp-\u003edev);\n+\tphylink_destroy(tp-\u003ephylink);\n \n \tif (tp-\u003edash_type != RTL_DASH_NONE)\n \t\trtl8168_driver_stop(tp);\n@@ -5310,7 +5452,7 @@ static const struct net_device_ops rtl_netdev_ops = {\n \t.ndo_fix_features\t= rtl8169_fix_features,\n \t.ndo_set_features\t= rtl8169_set_features,\n \t.ndo_set_mac_address\t= rtl_set_mac_address,\n-\t.ndo_eth_ioctl\t\t= phy_do_ioctl_running,\n+\t.ndo_eth_ioctl\t\t= rtl8169_ioctl,\n \t.ndo_set_rx_mode\t= rtl_set_rx_mode,\n #ifdef CONFIG_NET_POLL_CONTROLLER\n \t.ndo_poll_controller\t= rtl8169_netpoll,\n@@ -5474,16 +5616,6 @@ static int r8169_mdio_register(struct rtl8169_private *tp)\n \t\treturn -EUNATCH;\n \t}\n \n-\ttp-\u003ephydev-\u003emac_managed_pm = true;\n-\tif (rtl_supports_eee(tp))\n-\t\tphy_support_eee(tp-\u003ephydev);\n-\tphy_support_asym_pause(tp-\u003ephydev);\n-\n-\t/* mimic behavior of r8125/r8126 vendor drivers */\n-\tif (tp-\u003emac_version == RTL_GIGA_MAC_VER_61)\n-\t\tphy_disable_eee_mode(tp-\u003ephydev,\n-\t\t\t\t     ETHTOOL_LINK_MODE_2500baseT_Full_BIT);\n-\n \t/* PHY will be woken up in rtl_open() */\n \tphy_suspend(tp-\u003ephydev);\n \n@@ -5599,6 +5731,242 @@ static bool rtl_aspm_is_safe(struct rtl8169_private *tp)\n \treturn false;\n }\n \n+static void rtl_mac_link_down(struct phylink_config *config, unsigned int mode,\n+\t\t\t      phy_interface_t interface)\n+{\n+\tstruct rtl8169_private *tp = container_of(config, struct rtl8169_private, phylink_config);\n+\n+\ttp-\u003espeed = SPEED_UNKNOWN;\n+\tpm_runtime_idle(tp_to_dev(tp));\n+}\n+\n+static void rtl_mac_link_up(struct phylink_config *config, struct phy_device *phydev,\n+\t\t\t    unsigned int mode, phy_interface_t interface,\n+\t\t\t    int speed, int duplex, bool tx_pause, bool rx_pause)\n+{\n+\tstruct rtl8169_private *tp = container_of(config, struct rtl8169_private, phylink_config);\n+\tstruct device *d = tp_to_dev(tp);\n+\n+\ttp-\u003espeed = speed;\n+\trtl_link_chg_patch(tp, speed);\n+\n+\tpm_request_resume(d);\n+}\n+\n+static struct phylink_pcs *rtl_mac_select_pcs(struct phylink_config *config,\n+\t\t\t\t\t      phy_interface_t interface)\n+{\n+\tstruct rtl8169_private *tp = container_of(config, struct rtl8169_private, phylink_config);\n+\n+\tif (!tp-\u003epcs.ops)\n+\t\treturn NULL;\n+\n+\tif (interface == PHY_INTERFACE_MODE_1000BASEX ||\n+\t    interface == PHY_INTERFACE_MODE_10GBASER)\n+\t\treturn \u0026tp-\u003epcs;\n+\n+\treturn NULL;\n+}\n+\n+static void rtl_mac_config(struct phylink_config *config, unsigned int mode,\n+\t\t\t   const struct phylink_link_state *state)\n+{\n+}\n+\n+static u16 rtl8169_sds_read(struct rtl8169_private *tp, u16 sds_reg)\n+{\n+\tunsigned long flags;\n+\tu16 val = 0;\n+\n+\traw_spin_lock_irqsave(\u0026tp-\u003emac_ocp_lock, flags);\n+\t__r8168_mac_ocp_write(tp, OCP_SDS_ADDR_REG, sds_reg);\n+\t__r8168_mac_ocp_write(tp, OCP_SDS_CMD_REG, SDS_CMD_READ);\n+\tval = __r8168_mac_ocp_read(tp, OCP_SDS_DATA_REG);\n+\traw_spin_unlock_irqrestore(\u0026tp-\u003emac_ocp_lock, flags);\n+\n+\treturn val;\n+}\n+\n+static void rtl8169_pcs_get_state(struct phylink_pcs *pcs,\n+\t\t\t\t  unsigned int neg_mode,\n+\t\t\t\t  struct phylink_link_state *state)\n+{\n+\tstruct rtl8169_private *tp = container_of(pcs, struct rtl8169_private, pcs);\n+\n+\tif (tp-\u003esfp_mode == RTL_SFP_8127_ATF) {\n+\t\tu16 stat1;\n+\n+\t\tstat1 = rtl8169_sds_read(tp, RTL_SDS_C45_BASE + MDIO_STAT1);\n+\n+\t\tif (!(stat1 \u0026 MDIO_STAT1_LSTATUS))\n+\t\t\tstat1 = rtl8169_sds_read(tp, RTL_SDS_C45_BASE + MDIO_STAT1);\n+\n+\t\tstate-\u003elink = !!(stat1 \u0026 MDIO_STAT1_LSTATUS);\n+\t\tif (!state-\u003elink)\n+\t\t\treturn;\n+\n+\t\tstate-\u003eduplex = DUPLEX_FULL;\n+\t\tstate-\u003espeed = SPEED_10000;\n+\t} else {\n+\t\tu16 bmsr, lpa;\n+\n+\t\tbmsr = rtl8169_sds_read(tp, RTL_SDS_C22_BASE + MII_BMSR);\n+\t\tlpa = rtl8169_sds_read(tp, RTL_SDS_C22_BASE + MII_LPA);\n+\t\tphylink_mii_c22_pcs_decode_state(state, neg_mode, bmsr, lpa);\n+\t}\n+}\n+\n+static int rtl8169_pcs_config(struct phylink_pcs *pcs, unsigned int mode,\n+\t\t\t      phy_interface_t interface,\n+\t\t\t      const unsigned long *advertising,\n+\t\t\t      bool permit_pause_to_mac)\n+{\n+\tstruct rtl8169_private *tp = container_of(pcs, struct rtl8169_private, pcs);\n+\n+\tif (tp-\u003esfp_mode == RTL_SFP_8127_ATF) {\n+\t\tswitch (interface) {\n+\t\tcase PHY_INTERFACE_MODE_10GBASER:\n+\t\t\tr8127_sfp_init_10g(tp);\n+\t\t\tbreak;\n+\t\tcase PHY_INTERFACE_MODE_1000BASEX:\n+\t\t\tr8127_sfp_init_1g(tp);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tnetdev_err(tp-\u003edev, \"Unsupported SFP interface mode: %s\\n\",\n+\t\t\t\t   phy_modes(interface));\n+\t\t\treturn -EOPNOTSUPP;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int rtl8169_pcs_validate(struct phylink_pcs *pcs, unsigned long *supported,\n+\t\t\t\tconst struct phylink_link_state *state)\n+{\n+\treturn 0;\n+}\n+\n+static void rtl8169_pcs_an_restart(struct phylink_pcs *pcs)\n+{\n+}\n+\n+static void rtl_mac_disable_tx_lpi(struct phylink_config *config)\n+{\n+\tstruct rtl8169_private *tp = container_of(config, struct rtl8169_private, phylink_config);\n+\n+\trtl_enable_tx_lpi(tp, false);\n+}\n+\n+static int rtl_mac_enable_tx_lpi(struct phylink_config *config, u32 timer, bool tx_clk_stop)\n+{\n+\tstruct rtl8169_private *tp = container_of(config, struct rtl8169_private, phylink_config);\n+\n+\trtl_enable_tx_lpi(tp, true);\n+\n+\treturn 0;\n+}\n+\n+static const struct phylink_mac_ops rtl_phylink_mac_ops = {\n+\t.mac_select_pcs = rtl_mac_select_pcs,\n+\t.mac_config = rtl_mac_config,\n+\t.mac_link_down  = rtl_mac_link_down,\n+\t.mac_link_up    = rtl_mac_link_up,\n+\t.mac_disable_tx_lpi = rtl_mac_disable_tx_lpi,\n+\t.mac_enable_tx_lpi = rtl_mac_enable_tx_lpi,\n+};\n+\n+static unsigned long rtl8169_get_lpi_caps(struct rtl8169_private *tp)\n+{\n+\tunsigned long caps = 0;\n+\n+\tif (!rtl_supports_eee(tp) || tp-\u003esfp_mode == RTL_SFP_8127_ATF)\n+\t\treturn 0;\n+\n+\tcaps |= MAC_100FD | MAC_1000FD;\n+\n+\t/* mimic behavior of r8125/r8126 vendor drivers\n+\t * RTL_GIGA_MAC_VER_61 doesn't support 2.5G eee\n+\t */\n+\tif (tp-\u003emac_version \u003e= RTL_GIGA_MAC_VER_63)\n+\t\tcaps |= MAC_2500FD;\n+\tif (tp-\u003emac_version \u003e= RTL_GIGA_MAC_VER_70)\n+\t\tcaps |= MAC_5000FD;\n+\tif (tp-\u003emac_version == RTL_GIGA_MAC_VER_80)\n+\t\tcaps |= MAC_10000FD;\n+\n+\treturn caps;\n+}\n+\n+static const struct phylink_pcs_ops r8169_pcs_ops = {\n+\t.pcs_validate = rtl8169_pcs_validate,\n+\t.pcs_get_state = rtl8169_pcs_get_state,\n+\t.pcs_config = rtl8169_pcs_config,\n+\t.pcs_an_restart = rtl8169_pcs_an_restart,\n+};\n+\n+static int rtl_init_phylink(struct rtl8169_private *tp)\n+{\n+\tstruct phylink *pl;\n+\tphy_interface_t phy_mode;\n+\n+\ttp-\u003ephylink_config.dev = \u0026tp-\u003edev-\u003edev;\n+\ttp-\u003ephylink_config.type = PHYLINK_NETDEV;\n+\ttp-\u003ephylink_config.mac_managed_pm = true;\n+\ttp-\u003ephylink_config.lpi_capabilities = rtl8169_get_lpi_caps(tp);\n+\ttp-\u003ephylink_config.mac_capabilities |= MAC_ASYM_PAUSE | MAC_SYM_PAUSE;\n+\n+\tswitch (tp-\u003esfp_mode) {\n+\tcase RTL_SFP_8168_AF:\n+\t\ttp-\u003epcs.ops = \u0026r8169_pcs_ops;\n+\t\ttp-\u003ephylink_config.default_an_inband = true;\n+\t\tphy_mode = PHY_INTERFACE_MODE_1000BASEX;\n+\t\ttp-\u003ephylink_config.mac_capabilities |= MAC_1000FD;\n+\t\tbreak;\n+\tcase RTL_SFP_8127_ATF:\n+\t\ttp-\u003epcs.ops = \u0026r8169_pcs_ops;\n+\t\tphy_mode = PHY_INTERFACE_MODE_10GBASER;\n+\t\ttp-\u003ephylink_config.default_an_inband = true;\n+\t\ttp-\u003ephylink_config.mac_capabilities |= MAC_1000FD | MAC_10000FD;\n+\t\tbreak;\n+\tdefault:\n+\t\tphy_mode = PHY_INTERFACE_MODE_INTERNAL;\n+\t\ttp-\u003ephylink_config.mac_capabilities |= MAC_10 | MAC_100;\n+\n+\t\tif (tp-\u003emac_version == RTL_GIGA_MAC_VER_80)\n+\t\t\ttp-\u003ephylink_config.mac_capabilities |= MAC_1000FD | MAC_2500FD |\n+\t\t\t\t\t\t\t       MAC_5000FD | MAC_10000FD;\n+\t\telse if (tp-\u003emac_version == RTL_GIGA_MAC_VER_70)\n+\t\t\ttp-\u003ephylink_config.mac_capabilities |= MAC_1000FD |\n+\t\t\t\t\t\t\t       MAC_2500FD | MAC_5000FD;\n+\t\telse if (tp-\u003emac_version \u003e= RTL_GIGA_MAC_VER_61)\n+\t\t\ttp-\u003ephylink_config.mac_capabilities |= MAC_1000FD | MAC_2500FD;\n+\t\telse\n+\t\t\tif (tp-\u003esupports_gmii)\n+\t\t\t\ttp-\u003ephylink_config.mac_capabilities |= MAC_1000FD;\n+\n+\t\tif (tp-\u003emac_version \u003c RTL_GIGA_MAC_VER_61)\n+\t\t\tphy_mode = tp-\u003esupports_gmii ? PHY_INTERFACE_MODE_GMII :\n+\t\t\t\t   PHY_INTERFACE_MODE_MII;\n+\t\telse\n+\t\t\tphy_mode = PHY_INTERFACE_MODE_INTERNAL;\n+\t\tbreak;\n+\t}\n+\n+\t__set_bit(phy_mode, tp-\u003ephylink_config.supported_interfaces);\n+\tif (tp-\u003ephylink_config.lpi_capabilities)\n+\t\t__set_bit(phy_mode, tp-\u003ephylink_config.lpi_interfaces);\n+\n+\tpl = phylink_create(\u0026tp-\u003ephylink_config, tp_to_dev(tp)-\u003efwnode,\n+\t\t\t    phy_mode, \u0026rtl_phylink_mac_ops);\n+\tif (IS_ERR(pl))\n+\t\treturn PTR_ERR(pl);\n+\n+\ttp-\u003ephylink = pl;\n+\n+\treturn 0;\n+}\n+\n static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)\n {\n \tconst struct rtl_chip_info *chip;\n@@ -5667,6 +6035,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)\n \t\t\t\t     ext_xid_str, xid);\n \ttp-\u003emac_version = chip-\u003emac_version;\n \ttp-\u003efw_name = chip-\u003efw_name;\n+\ttp-\u003espeed = SPEED_UNKNOWN;\n \n \t/* Disable ASPM L1 as that cause random device stop working\n \t * problems as well as full system hangs for some PCIe devices users.\n@@ -5679,12 +6048,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)\n \t}\n \ttp-\u003easpm_manageable = !rc;\n \n-\tif (rtl_is_8125(tp)) {\n-\t\tu16 data = r8168_mac_ocp_read(tp, 0xd006);\n-\n-\t\tif ((data \u0026 0xff) == 0x07)\n-\t\t\ttp-\u003esfp_mode = true;\n-\t}\n+\ttp-\u003esfp_mode = rtl_get_sfp_mode(tp);\n \n \ttp-\u003edash_type = rtl_get_dash_type(tp);\n \ttp-\u003edash_enabled = rtl_dash_is_enabled(tp);\n@@ -5788,13 +6152,23 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)\n \n \tpci_set_drvdata(pdev, tp);\n \n-\trc = r8169_mdio_register(tp);\n+\trc = rtl_init_phylink(tp);\n \tif (rc)\n \t\treturn rc;\n \n+\tif (tp-\u003esfp_mode == RTL_SFP_NONE) {\n+\t\trc = r8169_mdio_register(tp);\n+\t\tif (rc) {\n+\t\t\tphylink_destroy(tp-\u003ephylink);\n+\t\t\treturn rc;\n+\t\t}\n+\t}\n+\n \trc = register_netdev(dev);\n-\tif (rc)\n+\tif (rc) {\n+\t\tphylink_destroy(tp-\u003ephylink);\n \t\treturn rc;\n+\t}\n \n \tif (IS_ENABLED(CONFIG_R8169_LEDS)) {\n \t\tif (rtl_is_8125(tp))\ndiff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c\nindex 59dfe35afa54fc..c450ee33b75cc1 100644\n--- a/drivers/net/phy/phylink.c\n+++ b/drivers/net/phy/phylink.c\n@@ -1828,6 +1828,72 @@ int phylink_set_fixed_link(struct phylink *pl,\n }\n EXPORT_SYMBOL_GPL(phylink_set_fixed_link);\n \n+/**\n+ * phylink_set_mac_capabilities() - Dynamically update MAC capabilities\n+ * @pl: a pointer to a \u0026struct phylink returned from phylink_create()\n+ * @mac_capabilities: the new MAC capabilities mask\n+ *\n+ * This function allows a MAC driver to dynamically change its capabilities,\n+ * such as losing/gaining Pause frame support based on MTU size.\n+ * It recalculates supported link modes and triggers renegotiation if needed.\n+ */\n+void phylink_set_mac_capabilities(struct phylink *pl, unsigned long mac_capabilities)\n+{\n+\tstruct phylink_link_state *config = \u0026pl-\u003elink_config;\n+\tunsigned long caps_added, caps_removed;\n+\n+\tASSERT_RTNL();\n+\n+\tcaps_added = mac_capabilities \u0026 ~pl-\u003econfig-\u003emac_capabilities;\n+\tcaps_removed = pl-\u003econfig-\u003emac_capabilities \u0026 ~mac_capabilities;\n+\n+\tif (!caps_added \u0026\u0026 !caps_removed)\n+\t\treturn;\n+\n+\tmutex_lock(\u0026pl-\u003estate_mutex);\n+\n+\tpl-\u003econfig-\u003emac_capabilities = mac_capabilities;\n+\n+\tif (caps_removed \u0026 MAC_SYM_PAUSE)\n+\t\tlinkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, pl-\u003esupported);\n+\tif (caps_removed \u0026 MAC_ASYM_PAUSE)\n+\t\tlinkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, pl-\u003esupported);\n+\n+\tlinkmode_and(config-\u003eadvertising, config-\u003eadvertising, pl-\u003esupported);\n+\n+\tif (caps_added \u0026 MAC_SYM_PAUSE) {\n+\t\tlinkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, pl-\u003esupported);\n+\t\tif (pl-\u003ephydev \u0026\u0026 !phylink_test(pl-\u003ephydev-\u003esupported, Pause))\n+\t\t\tlinkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, pl-\u003esupported);\n+\t}\n+\tif (caps_added \u0026 MAC_ASYM_PAUSE) {\n+\t\tlinkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, pl-\u003esupported);\n+\t\tif (pl-\u003ephydev \u0026\u0026 !phylink_test(pl-\u003ephydev-\u003esupported, Asym_Pause))\n+\t\t\tlinkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, pl-\u003esupported);\n+\t}\n+\n+\tlinkmode_and(config-\u003eadvertising, config-\u003eadvertising, pl-\u003esupported);\n+\n+\tif (config-\u003epause \u0026 MLO_PAUSE_AN) {\n+\t\tif (phylink_test(pl-\u003esupported, Pause))\n+\t\t\tlinkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, config-\u003eadvertising);\n+\n+\t\tif (phylink_test(pl-\u003esupported, Asym_Pause))\n+\t\t\tlinkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, config-\u003eadvertising);\n+\t}\n+\n+\tif (!pl-\u003ephydev)\n+\t\tphylink_change_inband_advert(pl);\n+\n+\tmutex_unlock(\u0026pl-\u003estate_mutex);\n+\n+\tif (pl-\u003ephydev) {\n+\t\tlinkmode_copy(pl-\u003ephydev-\u003eadvertising, config-\u003eadvertising);\n+\t\tphy_start_aneg(pl-\u003ephydev);\n+\t}\n+}\n+EXPORT_SYMBOL_GPL(phylink_set_mac_capabilities);\n+\n /**\n  * phylink_create() - create a phylink instance\n  * @config: a pointer to the target \u0026struct phylink_config\ndiff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c\nindex b65d0f5fa1a014..4721ba071cbbe4 100644\n--- a/drivers/net/phy/realtek/realtek_main.c\n+++ b/drivers/net/phy/realtek/realtek_main.c\n@@ -17,7 +17,6 @@\n #include \u003clinux/delay.h\u003e\n #include \u003clinux/clk.h\u003e\n #include \u003clinux/string_choices.h\u003e\n-#include \u003cnet/phy/realtek_phy.h\u003e\n \n #include \"../phylib.h\"\n #include \"realtek.h\"\n@@ -2646,45 +2645,6 @@ static irqreturn_t rtl8221b_handle_interrupt(struct phy_device *phydev)\n \treturn IRQ_HANDLED;\n }\n \n-static int rtlgen_sfp_get_features(struct phy_device *phydev)\n-{\n-\tlinkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,\n-\t\t\t phydev-\u003esupported);\n-\n-\t/* set default mode */\n-\tphydev-\u003espeed = SPEED_10000;\n-\tphydev-\u003eduplex = DUPLEX_FULL;\n-\n-\tphydev-\u003eport = PORT_FIBRE;\n-\n-\treturn 0;\n-}\n-\n-static int rtlgen_sfp_read_status(struct phy_device *phydev)\n-{\n-\tint val, err;\n-\n-\terr = genphy_update_link(phydev);\n-\tif (err)\n-\t\treturn err;\n-\n-\tif (!phydev-\u003elink)\n-\t\treturn 0;\n-\n-\tval = phy_read(phydev, RTL_PHYSR);\n-\tif (val \u003c 0)\n-\t\treturn val;\n-\n-\trtlgen_decode_physr(phydev, val);\n-\n-\treturn 0;\n-}\n-\n-static int rtlgen_sfp_config_aneg(struct phy_device *phydev)\n-{\n-\treturn 0;\n-}\n-\n static struct phy_driver realtek_drvs[] = {\n \t{\n \t\tPHY_ID_MATCH_EXACT(0x00008201),\n@@ -2934,20 +2894,6 @@ static struct phy_driver realtek_drvs[] = {\n \t\t.write_page\t= rtl821x_write_page,\n \t\t.read_mmd\t= rtl822x_read_mmd,\n \t\t.write_mmd\t= rtl822x_write_mmd,\n-\t}, {\n-\t\tPHY_ID_MATCH_EXACT(PHY_ID_RTL_DUMMY_SFP),\n-\t\t.name\t\t= \"Realtek SFP PHY Mode\",\n-\t\t.flags\t\t= PHY_IS_INTERNAL,\n-\t\t.probe\t\t= rtl822x_probe,\n-\t\t.get_features\t= rtlgen_sfp_get_features,\n-\t\t.config_aneg\t= rtlgen_sfp_config_aneg,\n-\t\t.read_status\t= rtlgen_sfp_read_status,\n-\t\t.suspend\t= genphy_suspend,\n-\t\t.resume\t\t= rtlgen_resume,\n-\t\t.read_page\t= rtl821x_read_page,\n-\t\t.write_page\t= rtl821x_write_page,\n-\t\t.read_mmd\t= rtl822x_read_mmd,\n-\t\t.write_mmd\t= rtl822x_write_mmd,\n \t}, {\n \t\tPHY_ID_MATCH_EXACT(0x001ccad0),\n \t\t.name\t\t= \"RTL8224 2.5Gbps PHY\",\ndiff --git a/include/linux/phylink.h b/include/linux/phylink.h\nindex 2bc0db3d52ac8d..56642ab961a753 100644\n--- a/include/linux/phylink.h\n+++ b/include/linux/phylink.h\n@@ -842,4 +842,6 @@ void phylink_replay_link_begin(struct phylink *pl);\n \n void phylink_replay_link_end(struct phylink *pl);\n \n+void phylink_set_mac_capabilities(struct phylink *pl, unsigned long mac_capabilities);\n+\n #endif\ndiff --git a/include/net/phy/realtek_phy.h b/include/net/phy/realtek_phy.h\ndeleted file mode 100644\nindex d683bc1b0659cd..00000000000000\n--- a/include/net/phy/realtek_phy.h\n+++ /dev/null\n@@ -1,7 +0,0 @@\n-/* SPDX-License-Identifier: GPL-2.0 */\n-#ifndef _REALTEK_PHY_H\n-#define _REALTEK_PHY_H\n-\n-#define\tPHY_ID_RTL_DUMMY_SFP\t0x001ccbff\n-\n-#endif /* _REALTEK_PHY_H */\n"
}

2/1 2026/07/07 16:34 agent patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
{
  "EnableConfigs": [
    "R8169"
  ],
  "FocusSymbols": [
    "phylink_set_mac_capabilities",
    "rtl_init_phylink",
    "rtl8169_pcs_config",
    "rtl8169_pcs_get_state",
    "rtl_mac_link_up",
    "rtl_mac_link_down",
    "rtl_mac_select_pcs",
    "rtl_mac_disable_tx_lpi",
    "rtl_mac_enable_tx_lpi",
    "rtl8169_change_mtu",
    "rtl_lowpower_hidden_functions",
    "r8127_sfp_init_1g",
    "r8127_sfp_init_10g",
    "rtl8169_ioctl"
  ],
  "Reasoning": "The patch migrates the Realtek r8169 Ethernet driver from phylib to phylink, introducing significant functional changes to the driver's initialization, link management, and MTU handling. It also adds a new phylink API `phylink_set_mac_capabilities` to dynamically update MAC capabilities. These are reachable control-path functions that should be fuzzed, especially via syz_pci and netlink/ioctl interfaces.",
  "WorthFuzzing": true
}

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

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

Return WorthFuzzing=false if the patch only contains:
- Modifications to Documentation/, Kconfig files, or code comments.
- Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints.
- Changes to numeric constants or macros that do not functionally alter execution flow.
- Code paths that are impossible to reach in virtualized environments like GCE or QEMU,
even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim).

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

When returning WorthFuzzing=true, you MUST ALSO:
1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols.
   Avoid listing generic hot-path functions to prevent skewed test distributions.
2. Identify any specific CONFIG_ options required to properly test this new/modified feature.
   Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions.
   Do not list too generic configs (we already have them enabled). Only list those that
   specifically cover the modified code. List them in the EnableConfigs output array,
   and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


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

Prompt:
For your convenience, here is the diff of the changes:
commit 1f78500456b8393ead6d6fbc15a49c3b5850a9f4
Author: syz-cluster <triage@syzkaller.com>
Date:   Tue Jul 7 16:34:39 2026 +0000

    syz-cluster: applied patch under review

diff --git a/drivers/net/ethernet/realtek/Kconfig b/drivers/net/ethernet/realtek/Kconfig
index 9b0f4f9631dbaa..49ac72734225f7 100644
--- a/drivers/net/ethernet/realtek/Kconfig
+++ b/drivers/net/ethernet/realtek/Kconfig
@@ -88,6 +88,7 @@ config R8169
 	select CRC32
 	select PHYLIB
 	select REALTEK_PHY
+	select PHYLINK
 	help
 	  Say Y here if you have a Realtek Ethernet adapter belonging to
 	  the following families:
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index ec4fc21fa21fb0..12e073b9a61479 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -26,12 +26,12 @@
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
 #include <linux/bitfield.h>
+#include <linux/phylink.h>
 #include <linux/prefetch.h>
 #include <linux/ipv6.h>
 #include <linux/unaligned.h>
 #include <net/ip6_checksum.h>
 #include <net/netdev_queues.h>
-#include <net/phy/realtek_phy.h>
 
 #include "r8169.h"
 #include "r8169_firmware.h"
@@ -96,6 +96,28 @@
 #define JUMBO_9K	(9 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
 #define JUMBO_16K	(SZ_16K - VLAN_ETH_HLEN - ETH_FCS_LEN)
 
+#define OCP_SDS_ADDR_REG		0xEB10
+#define OCP_SDS_CMD_REG			0xEB0E
+#define OCP_SDS_DATA_REG		0xEB14
+#define SDS_CMD_READ			0x0001
+#define RTL_SDS_C22_BASE		0x40
+#define RTL_SDS_C45_BASE		0x0080
+#define RTL_PKG_DETECT			0xdc00
+#define RTL_PKG_DETECT_MASK		0x0078
+#define RTL_PKG_DETECT_8116AF		0x0030
+#define RTL_INT_HW_ID			0xd006
+#define RTL_INT_HW_ID_MASK		0x00ff
+#define RTL_INT_HW_ID_8116AF		0x0000
+#define RTL8116AF_FUNC_PM_CSR		0x80
+#define RTL8116AF_FUNC_EXP_LNKCTL	0x44
+#define RTL_PM_D3HOT			GENMASK(1, 0)
+#define R8127_SDS_CMD			0x2348
+#define R8127_SDS_ADDR			0x234a
+#define R8127_SDS_DATA_IN		0x234c
+#define R8127_SDS_DATA_OUT		0x234e
+#define R8127_SDS_CMD_EXEC		BIT(0)
+#define R8127_SDS_CMD_WE		BIT(1)
+
 static const struct rtl_chip_info {
 	u32 mask;
 	u32 val;
@@ -334,11 +356,13 @@ enum rtl_registers {
 	ALDPS_LTR	= 0xe0a2,
 	LTR_OBFF_LOCK	= 0xe032,
 	LTR_SNOOP	= 0xe034,
+	SEND_LTR_MSG	= 0xe038,
 
 #define ALDPS_LTR_EN			BIT(0)
 #define LTR_OBFF_LOCK_EN		BIT(0)
 #define LINK_SPEED_CHANGE_EN		BIT(14)
 #define LTR_SNOOP_EN			GENMASK(15, 14)
+#define LTR_MSG_EN			BIT(0)
 };
 
 enum rtl8168_8101_registers {
@@ -728,6 +752,12 @@ enum rtl_dash_type {
 	RTL_DASH_25_BP,
 };
 
+enum rtl_sfp_mode {
+	RTL_SFP_NONE,
+	RTL_SFP_8168_AF,
+	RTL_SFP_8127_ATF,
+};
+
 struct rtl8169_private {
 	void __iomem *mmio_addr;	/* memory map physical address */
 	struct pci_dev *pci_dev;
@@ -736,6 +766,7 @@ struct rtl8169_private {
 	struct napi_struct napi;
 	enum mac_version mac_version;
 	enum rtl_dash_type dash_type;
+	enum rtl_sfp_mode sfp_mode;
 	u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
 	u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
 	u32 dirty_tx;
@@ -750,6 +781,7 @@ struct rtl8169_private {
 	u32 irq_mask;
 	int irq;
 	struct clk *clk;
+	int speed;
 
 	struct {
 		DECLARE_BITMAP(flags, RTL_FLAG_MAX);
@@ -762,7 +794,6 @@ struct rtl8169_private {
 	unsigned supports_gmii:1;
 	unsigned aspm_manageable:1;
 	unsigned dash_enabled:1;
-	bool sfp_mode:1;
 	dma_addr_t counters_phys_addr;
 	struct rtl8169_counters *counters;
 	struct rtl8169_tc_offsets tc_offset;
@@ -774,6 +805,11 @@ struct rtl8169_private {
 	struct r8169_led_classdev *leds;
 
 	u32 ocp_base;
+	struct phylink *phylink;
+	struct phylink_config phylink_config;
+	struct phylink_pcs pcs;
+	struct ethtool_pauseparam saved_pause;
+	bool jumbo_pause_saved;
 };
 
 typedef void (*rtl_generic_fct)(struct rtl8169_private *tp);
@@ -1128,10 +1164,6 @@ static int r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
 	if (rtl_ocp_reg_failure(reg))
 		return 0;
 
-	/* Return dummy MII_PHYSID2 in SFP mode to match SFP PHY driver */
-	if (tp->sfp_mode && reg == (OCP_STD_PHY_BASE + 2 * MII_PHYSID2))
-		return PHY_ID_RTL_DUMMY_SFP & 0xffff;
-
 	RTL_W32(tp, GPHY_OCP, reg << 15);
 
 	return rtl_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ?
@@ -1199,6 +1231,67 @@ static void r8127_sfp_sds_phy_reset(struct rtl8169_private *tp)
 	usleep_range(10, 20);
 }
 
+DECLARE_RTL_COND(r8127_sds_cmd_cond)
+{
+	return RTL_R16(tp, R8127_SDS_CMD) & R8127_SDS_CMD_EXEC;
+}
+
+static u16 r8127_sds_read(struct rtl8169_private *tp, u16 index, u16 page, u16 reg)
+{
+	u16 addr = (index << 11) | (page << 5) | reg;
+
+	RTL_W16(tp, R8127_SDS_ADDR, addr);
+	RTL_W16(tp, R8127_SDS_CMD, R8127_SDS_CMD_EXEC);
+
+	if (rtl_loop_wait_low(tp, &r8127_sds_cmd_cond, 10, 100))
+		return RTL_R16(tp, R8127_SDS_DATA_OUT);
+
+	return 0xffff;
+}
+
+static void r8127_sds_write(struct rtl8169_private *tp, u16 index, u16 page,
+			    u16 reg, u16 val)
+{
+	u16 addr = (index << 11) | (page << 5) | reg;
+
+	RTL_W16(tp, R8127_SDS_DATA_IN, val);
+	RTL_W16(tp, R8127_SDS_ADDR, addr);
+	RTL_W16(tp, R8127_SDS_CMD, R8127_SDS_CMD_EXEC | R8127_SDS_CMD_WE);
+
+	rtl_loop_wait_low(tp, &r8127_sds_cmd_cond, 10, 100);
+}
+
+static void r8127_sds_modify(struct rtl8169_private *tp, u16 index, u16 page,
+			     u16 reg, u16 clearmask, u16 setmask)
+{
+	u16 val = r8127_sds_read(tp, index, page, reg);
+
+	val = (val & ~clearmask) | setmask;
+	r8127_sds_write(tp, index, page, reg, val);
+}
+
+static void r8127_sfp_init_1g(struct rtl8169_private *tp)
+{
+	int val;
+
+	r8127_sfp_sds_phy_reset(tp);
+
+	r8127_sds_modify(tp, 0, 1, 31, 0, BIT(3));
+	r8127_sds_modify(tp, 0, 2,  0, BIT(13) | BIT(12) | BIT(6), BIT(12) | BIT(6));
+	r8127_sds_modify(tp, 0, 0,  4, 0, BIT(2));
+
+	RTL_W16(tp, 0x233a, 0x8004);
+	RTL_W16(tp, 0x233e, (RTL_R16(tp, 0x233e) & ~0x3003) | 0x0002);
+
+	r8168_phy_ocp_write(tp, 0xc40a, 0x0000);
+	r8168_phy_ocp_write(tp, 0xc466, 0x0000);
+	r8168_phy_ocp_write(tp, 0xc808, 0x0000);
+	r8168_phy_ocp_write(tp, 0xc80a, 0x0000);
+
+	val = r8168_phy_ocp_read(tp, 0xc804);
+	r8168_phy_ocp_write(tp, 0xc804, (val & ~0x000f) | 0x000c);
+}
+
 static void r8127_sfp_init_10g(struct rtl8169_private *tp)
 {
 	int val;
@@ -1217,12 +1310,6 @@ static void r8127_sfp_init_10g(struct rtl8169_private *tp)
 	r8168_phy_ocp_write(tp, 0xc804, (val & ~0x000f) | 0x000c);
 }
 
-static void rtl_sfp_init(struct rtl8169_private *tp)
-{
-	if (tp->mac_version == RTL_GIGA_MAC_VER_80)
-		r8127_sfp_init_10g(tp);
-}
-
 static void rtl_sfp_reset(struct rtl8169_private *tp)
 {
 	if (tp->mac_version == RTL_GIGA_MAC_VER_80)
@@ -1283,6 +1370,15 @@ static void mac_mcu_write(struct rtl8169_private *tp, int reg, int value)
 	r8168_mac_ocp_write(tp, tp->ocp_base + reg, value);
 }
 
+static bool rtl_is_8116af(struct rtl8169_private *tp)
+{
+	return tp->mac_version == RTL_GIGA_MAC_VER_52 &&
+		(r8168_mac_ocp_read(tp, RTL_PKG_DETECT) & RTL_PKG_DETECT_MASK) ==
+		RTL_PKG_DETECT_8116AF &&
+		(r8168_mac_ocp_read(tp, RTL_INT_HW_ID) & RTL_INT_HW_ID_MASK) ==
+		RTL_INT_HW_ID_8116AF;
+}
+
 static int mac_mcu_read(struct rtl8169_private *tp, int reg)
 {
 	return r8168_mac_ocp_read(tp, tp->ocp_base + reg);
@@ -1578,6 +1674,20 @@ static bool rtl_dash_is_enabled(struct rtl8169_private *tp)
 	}
 }
 
+static enum rtl_sfp_mode rtl_get_sfp_mode(struct rtl8169_private *tp)
+{
+	if (rtl_is_8125(tp)) {
+		u16 data = r8168_mac_ocp_read(tp, RTL_INT_HW_ID);
+
+		if ((data & 0xff) == 0x07)
+			return RTL_SFP_8127_ATF;
+	} else if (rtl_is_8116af(tp)) {
+		return RTL_SFP_8168_AF;
+	}
+
+	return RTL_SFP_NONE;
+}
+
 static enum rtl_dash_type rtl_get_dash_type(struct rtl8169_private *tp)
 {
 	switch (tp->mac_version) {
@@ -1673,16 +1783,14 @@ static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
 	rtl_pci_commit(tp);
 }
 
-static void rtl_link_chg_patch(struct rtl8169_private *tp)
+static void rtl_link_chg_patch(struct rtl8169_private *tp, int speed)
 {
-	struct phy_device *phydev = tp->phydev;
-
 	if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
 	    tp->mac_version == RTL_GIGA_MAC_VER_38) {
-		if (phydev->speed == SPEED_1000) {
+		if (speed == SPEED_1000) {
 			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011);
 			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);
-		} else if (phydev->speed == SPEED_100) {
+		} else if (speed == SPEED_100) {
 			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f);
 			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);
 		} else {
@@ -1692,7 +1800,7 @@ static void rtl_link_chg_patch(struct rtl8169_private *tp)
 		rtl_reset_packet_filter(tp);
 	} else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
 		   tp->mac_version == RTL_GIGA_MAC_VER_36) {
-		if (phydev->speed == SPEED_1000) {
+		if (speed == SPEED_1000) {
 			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011);
 			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);
 		} else {
@@ -1700,7 +1808,7 @@ static void rtl_link_chg_patch(struct rtl8169_private *tp)
 			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f);
 		}
 	} else if (tp->mac_version == RTL_GIGA_MAC_VER_37) {
-		if (phydev->speed == SPEED_10) {
+		if (speed == SPEED_10) {
 			rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02);
 			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060a);
 		} else {
@@ -2074,11 +2182,11 @@ rtl_coalesce_info(struct rtl8169_private *tp)
 		ci = rtl_coalesce_info_8168_8136;
 
 	/* if speed is unknown assume highest one */
-	if (tp->phydev->speed == SPEED_UNKNOWN)
+	if (tp->speed == SPEED_UNKNOWN)
 		return ci;
 
 	for (; ci->speed; ci++) {
-		if (tp->phydev->speed == ci->speed)
+		if (tp->speed == ci->speed)
 			return ci;
 	}
 
@@ -2236,7 +2344,7 @@ static void rtl_set_eee_txidle_timer(struct rtl8169_private *tp)
 
 static unsigned int r8169_get_tx_lpi_timer_us(struct rtl8169_private *tp)
 {
-	unsigned int speed = tp->phydev->speed;
+	unsigned int speed = tp->speed;
 	unsigned int timer = tp->tx_lpi_timer;
 
 	if (!timer || speed == SPEED_UNKNOWN)
@@ -2254,7 +2362,7 @@ static int rtl8169_get_eee(struct net_device *dev, struct ethtool_keee *data)
 	if (!rtl_supports_eee(tp))
 		return -EOPNOTSUPP;
 
-	ret = phy_ethtool_get_eee(tp->phydev, data);
+	ret = phylink_ethtool_get_eee(tp->phylink, data);
 	if (ret)
 		return ret;
 
@@ -2270,7 +2378,7 @@ static int rtl8169_set_eee(struct net_device *dev, struct ethtool_keee *data)
 	if (!rtl_supports_eee(tp))
 		return -EOPNOTSUPP;
 
-	return phy_ethtool_set_eee(tp->phydev, data);
+	return phylink_ethtool_set_eee(tp->phylink, data);
 }
 
 static void rtl8169_get_ringparam(struct net_device *dev,
@@ -2301,13 +2409,8 @@ static void rtl8169_get_pauseparam(struct net_device *dev,
 				   struct ethtool_pauseparam *data)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
-	bool tx_pause, rx_pause;
 
-	phy_get_pause(tp->phydev, &tx_pause, &rx_pause);
-
-	data->autoneg = tp->phydev->autoneg;
-	data->tx_pause = tx_pause ? 1 : 0;
-	data->rx_pause = rx_pause ? 1 : 0;
+	phylink_ethtool_get_pauseparam(tp->phylink, data);
 }
 
 static int rtl8169_set_pauseparam(struct net_device *dev,
@@ -2318,9 +2421,7 @@ static int rtl8169_set_pauseparam(struct net_device *dev,
 	if (dev->mtu > ETH_DATA_LEN)
 		return -EOPNOTSUPP;
 
-	phy_set_asym_pause(tp->phydev, data->rx_pause, data->tx_pause);
-
-	return 0;
+	return phylink_ethtool_set_pauseparam(tp->phylink, data);
 }
 
 static void rtl8169_get_eth_mac_stats(struct net_device *dev,
@@ -2386,34 +2487,27 @@ static void rtl8169_get_eth_ctrl_stats(struct net_device *dev,
 		le32_to_cpu(tp->counters->rx_unknown_opcode);
 }
 
-static int rtl8169_set_link_ksettings(struct net_device *ndev,
-				      const struct ethtool_link_ksettings *cmd)
+static int rtl8169_get_link_ksettings(struct net_device *ndev,
+				      struct ethtool_link_ksettings *cmd)
 {
 	struct rtl8169_private *tp = netdev_priv(ndev);
-	struct phy_device *phydev = tp->phydev;
-	int duplex = cmd->base.duplex;
-	int speed = cmd->base.speed;
-
-	if (!tp->sfp_mode)
-		return phy_ethtool_ksettings_set(phydev, cmd);
-
-	if (cmd->base.autoneg != AUTONEG_DISABLE)
-		return -EINVAL;
 
-	if (!phy_check_valid(speed, duplex, phydev->supported))
-		return -EINVAL;
-
-	mutex_lock(&phydev->lock);
+	return phylink_ethtool_ksettings_get(tp->phylink, cmd);
+}
 
-	phydev->autoneg = AUTONEG_DISABLE;
-	phydev->speed = speed;
-	phydev->duplex = duplex;
+static int rtl8169_set_link_ksettings(struct net_device *ndev,
+				      const struct ethtool_link_ksettings *cmd)
+{
+	struct rtl8169_private *tp = netdev_priv(ndev);
 
-	rtl_sfp_init(tp);
+	return phylink_ethtool_ksettings_set(tp->phylink, cmd);
+}
 
-	mutex_unlock(&phydev->lock);
+static int rtl8169_nway_reset(struct net_device *dev)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
 
-	return 0;
+	return phylink_ethtool_nway_reset(tp->phylink);
 }
 
 static const struct ethtool_ops rtl8169_ethtool_ops = {
@@ -2431,10 +2525,10 @@ static const struct ethtool_ops rtl8169_ethtool_ops = {
 	.get_sset_count		= rtl8169_get_sset_count,
 	.get_ethtool_stats	= rtl8169_get_ethtool_stats,
 	.get_ts_info		= ethtool_op_get_ts_info,
-	.nway_reset		= phy_ethtool_nway_reset,
+	.nway_reset		= rtl8169_nway_reset,
 	.get_eee		= rtl8169_get_eee,
 	.set_eee		= rtl8169_set_eee,
-	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
+	.get_link_ksettings	= rtl8169_get_link_ksettings,
 	.set_link_ksettings	= rtl8169_set_link_ksettings,
 	.get_ringparam		= rtl8169_get_ringparam,
 	.get_pause_stats	= rtl8169_get_pause_stats,
@@ -2499,9 +2593,10 @@ void r8169_apply_firmware(struct rtl8169_private *tp)
 		tp->ocp_base = OCP_STD_PHY_BASE;
 
 		/* PHY soft reset may still be in progress */
-		phy_read_poll_timeout(tp->phydev, MII_BMCR, val,
-				      !(val & BMCR_RESET),
-				      50000, 600000, true);
+		if (tp->phydev)
+			phy_read_poll_timeout(tp->phydev, MII_BMCR, val,
+					      !(val & BMCR_RESET),
+					      50000, 600000, true);
 	}
 }
 
@@ -2538,6 +2633,8 @@ static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
 
 static void rtl8169_init_phy(struct rtl8169_private *tp)
 {
+	phy_init_hw(tp->phydev);
+	phy_resume(tp->phydev);
 	r8169_hw_phy_config(tp, tp->phydev, tp->mac_version);
 
 	if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
@@ -2552,9 +2649,6 @@ static void rtl8169_init_phy(struct rtl8169_private *tp)
 	    tp->pci_dev->subsystem_device == 0xe000)
 		phy_write_paged(tp->phydev, 0x0001, 0x10, 0xf01b);
 
-	if (tp->sfp_mode)
-		rtl_sfp_init(tp);
-
 	/* We may have called phy_speed_down before */
 	phy_speed_up(tp->phydev);
 
@@ -2657,15 +2751,6 @@ static void rtl_jumbo_config(struct rtl8169_private *tp)
 
 	if (pci_is_pcie(tp->pci_dev) && tp->supports_gmii)
 		pcie_set_readrq(tp->pci_dev, readrq);
-
-	/* Chip doesn't support pause in jumbo mode */
-	if (jumbo) {
-		linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT,
-				   tp->phydev->advertising);
-		linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
-				   tp->phydev->advertising);
-		phy_start_aneg(tp->phydev);
-	}
 }
 
 DECLARE_RTL_COND(rtl_chipcmd_cond)
@@ -2780,7 +2865,7 @@ static void rtl_prepare_power_down(struct rtl8169_private *tp)
 		rtl_ephy_write(tp, 0x19, 0xff64);
 
 	if (device_may_wakeup(tp_to_dev(tp))) {
-		phy_speed_down(tp->phydev, false);
+		phylink_speed_down(tp->phylink, false);
 		rtl_wol_enable_rx(tp);
 	}
 }
@@ -2832,6 +2917,16 @@ static void rtl8169_set_magic_reg(struct rtl8169_private *tp)
 	RTL_W32(tp, 0x7c, val);
 }
 
+static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+
+	if (!netif_running(dev))
+		return -ENODEV;
+
+	return phylink_mii_ioctl(tp->phylink, ifr, cmd);
+}
+
 static void rtl_set_rx_mode(struct net_device *dev)
 {
 	u32 rx_mode = AcceptBroadcast | AcceptMyPhys | AcceptMulticast;
@@ -3098,8 +3193,22 @@ static void rtl_enable_ltr(struct rtl8169_private *tp)
 		r8168_mac_ocp_write(tp, 0xcdf2, 0x9003);
 		r8168_mac_ocp_modify(tp, LTR_OBFF_LOCK, 0x0000, LINK_SPEED_CHANGE_EN);
 		break;
-	case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
 	case RTL_GIGA_MAC_VER_52:
+		r8168_mac_ocp_write(tp, 0xcdd0, 0x9003);
+		r8168_mac_ocp_modify(tp, LTR_SNOOP, 0x0000, LTR_SNOOP_EN);
+		r8168_mac_ocp_write(tp, 0xe02c, 0x1880);
+		r8168_mac_ocp_write(tp, 0xe02e, 0x4880);
+		r8168_mac_ocp_modify(tp, ALDPS_LTR, 0x0000, ALDPS_LTR_EN);
+		r8168_mac_ocp_write(tp, 0xcdd8, 0x9003);
+		r8168_mac_ocp_write(tp, 0xcdda, 0x9003);
+		r8168_mac_ocp_write(tp, 0xcddc, 0x9003);
+		r8168_mac_ocp_write(tp, 0xcdd2, 0x883c);
+		r8168_mac_ocp_write(tp, 0xcdd4, 0x8c12);
+		r8168_mac_ocp_write(tp, 0xcdd6, 0x9003);
+		r8168_mac_ocp_write(tp, 0xe0a6, 0x9003);
+		r8168_mac_ocp_write(tp, 0xe0a8, 0x9003);
+		break;
+	case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
 		r8168_mac_ocp_modify(tp, ALDPS_LTR, 0x0000, ALDPS_LTR_EN);
 		RTL_W8(tp, COMBO_LTR_EXTEND, RTL_R8(tp, COMBO_LTR_EXTEND) | COMBO_LTR_EXTEND_EN);
 		fallthrough;
@@ -3119,6 +3228,7 @@ static void rtl_enable_ltr(struct rtl8169_private *tp)
 	}
 	/* chip can trigger LTR */
 	r8168_mac_ocp_modify(tp, LTR_OBFF_LOCK, 0x0003, LTR_OBFF_LOCK_EN);
+	r8168_mac_ocp_modify(tp, SEND_LTR_MSG, 0x0000, LTR_MSG_EN);
 }
 
 static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
@@ -3152,6 +3262,7 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
 		rtl_enable_ltr(tp);
 		switch (tp->mac_version) {
 		case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
+		case RTL_GIGA_MAC_VER_52:
 		case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_LAST:
 			/* reset ephy tx/rx disable timer */
 			r8168_mac_ocp_modify(tp, 0xe094, 0xff00, 0);
@@ -3164,6 +3275,7 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
 	} else {
 		switch (tp->mac_version) {
 		case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
+		case RTL_GIGA_MAC_VER_52:
 		case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_LAST:
 			r8168_mac_ocp_modify(tp, 0xe092, 0x00ff, 0);
 			break;
@@ -3657,6 +3769,35 @@ static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)
 	r8168_mac_ocp_modify(tp, 0xe860, 0x0000, 0x0080);
 }
 
+static void rtl_lowpower_hidden_functions(struct pci_dev *pdev)
+{
+	unsigned int slot = PCI_SLOT(pdev->devfn);
+	struct pci_bus *bus = pdev->bus;
+	unsigned int devfn;
+	int func;
+	int ret;
+	u32 val;
+
+	for (func = 2; func < 8; func++) {
+		devfn = PCI_DEVFN(slot, func);
+
+		ret = pci_bus_read_config_dword(bus, devfn, RTL8116AF_FUNC_PM_CSR, &val);
+		if (!ret && !PCI_POSSIBLE_ERROR(val)) {
+			val &= ~PCI_PM_CTRL_PME_STATUS;
+			val &= ~(PCI_PM_CTRL_STATE_MASK | PCI_PM_CTRL_PME_ENABLE);
+			val |= (RTL_PM_D3HOT | PCI_PM_CTRL_PME_ENABLE);
+			pci_bus_write_config_dword(bus, devfn, RTL8116AF_FUNC_PM_CSR, val);
+		}
+
+		ret = pci_bus_read_config_dword(bus, devfn, RTL8116AF_FUNC_EXP_LNKCTL, &val);
+		if (!ret && !PCI_POSSIBLE_ERROR(val)) {
+			val &= ~((PCI_EXP_LNKSTA_LBMS | PCI_EXP_LNKSTA_LABS) << 16);
+			val |= PCI_EXP_LNKCTL_ASPMC;
+			pci_bus_write_config_dword(bus, devfn, RTL8116AF_FUNC_EXP_LNKCTL, val);
+		}
+	}
+}
+
 static void rtl_hw_start_8117(struct rtl8169_private *tp)
 {
 	static const struct ephy_info e_info_8117[] = {
@@ -3693,12 +3834,14 @@ static void rtl_hw_start_8117(struct rtl8169_private *tp)
 
 	rtl_pcie_state_l2l3_disable(tp);
 
-	rg_saw_cnt = phy_read_paged(tp->phydev, 0x0c42, 0x13) & 0x3fff;
-	if (rg_saw_cnt > 0) {
-		u16 sw_cnt_1ms_ini;
+	if (tp->phydev) {
+		rg_saw_cnt = phy_read_paged(tp->phydev, 0x0c42, 0x13) & 0x3fff;
+		if (rg_saw_cnt > 0) {
+			u16 sw_cnt_1ms_ini;
 
-		sw_cnt_1ms_ini = (16000000 / rg_saw_cnt) & 0x0fff;
-		r8168_mac_ocp_modify(tp, 0xd412, 0x0fff, sw_cnt_1ms_ini);
+			sw_cnt_1ms_ini = (16000000 / rg_saw_cnt) & 0x0fff;
+			r8168_mac_ocp_modify(tp, 0xd412, 0x0fff, sw_cnt_1ms_ini);
+		}
 	}
 
 	r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0000);
@@ -3711,6 +3854,9 @@ static void rtl_hw_start_8117(struct rtl8169_private *tp)
 	r8168_mac_ocp_write(tp, 0xc094, 0x0000);
 	r8168_mac_ocp_write(tp, 0xc09e, 0x0000);
 
+	if (rtl_is_8116af(tp))
+		rtl_lowpower_hidden_functions(tp->pci_dev);
+
 	/* firmware is for MAC only */
 	r8169_apply_firmware(tp);
 }
@@ -4139,12 +4285,25 @@ static void rtl_hw_start(struct  rtl8169_private *tp)
 static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
+	bool jumbo_before = dev->mtu > ETH_DATA_LEN;
+	bool jumbo_after = new_mtu > ETH_DATA_LEN;
 
 	WRITE_ONCE(dev->mtu, new_mtu);
 	netdev_update_features(dev);
 	rtl_jumbo_config(tp);
 	rtl_set_eee_txidle_timer(tp);
 
+	if (jumbo_before != jumbo_after) {
+		unsigned long caps = tp->phylink_config.mac_capabilities;
+
+		if (jumbo_after)
+			caps &= ~(MAC_SYM_PAUSE | MAC_ASYM_PAUSE);
+		else
+			caps |= (MAC_SYM_PAUSE | MAC_ASYM_PAUSE);
+
+		phylink_set_mac_capabilities(tp->phylink, caps);
+	}
+
 	return 0;
 }
 
@@ -4869,8 +5028,13 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
 		goto out;
 	}
 
-	if (status & LinkChg)
-		phy_mac_interrupt(tp->phydev);
+	if (status & LinkChg) {
+		if (tp->phydev)
+			phy_mac_interrupt(tp->phydev);
+		else if (tp->sfp_mode)
+			phylink_mac_change(tp->phylink,
+					   !!(RTL_R8(tp, PHYstatus) & LinkStatus));
+	}
 
 	rtl_irq_disable(tp);
 	napi_schedule(&tp->napi);
@@ -4930,9 +5094,6 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
 
 static void rtl_enable_tx_lpi(struct rtl8169_private *tp, bool enable)
 {
-	if (!rtl_supports_eee(tp))
-		return;
-
 	switch (tp->mac_version) {
 	case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_52:
 		/* Adjust EEE LED frequency */
@@ -4963,40 +5124,15 @@ static void rtl_enable_tx_lpi(struct rtl8169_private *tp, bool enable)
 	}
 }
 
-static void r8169_phylink_handler(struct net_device *ndev)
-{
-	struct rtl8169_private *tp = netdev_priv(ndev);
-	struct device *d = tp_to_dev(tp);
-
-	if (netif_carrier_ok(ndev)) {
-		rtl_link_chg_patch(tp);
-		rtl_enable_tx_lpi(tp, tp->phydev->enable_tx_lpi);
-		pm_request_resume(d);
-	} else {
-		pm_runtime_idle(d);
-	}
-
-	phy_print_status(tp->phydev);
-}
-
 static int r8169_phy_connect(struct rtl8169_private *tp)
 {
-	struct phy_device *phydev = tp->phydev;
-	phy_interface_t phy_mode;
 	int ret;
 
-	phy_mode = tp->supports_gmii ? PHY_INTERFACE_MODE_GMII :
-		   PHY_INTERFACE_MODE_MII;
-
-	ret = phy_connect_direct(tp->dev, phydev, r8169_phylink_handler,
-				 phy_mode);
-	if (ret)
+	ret = phylink_connect_phy(tp->phylink, tp->phydev);
+	if (ret) {
+		netdev_err(tp->dev, "failed to connect phy\n");
 		return ret;
-
-	if (!tp->supports_gmii)
-		phy_set_max_speed(phydev, SPEED_100);
-
-	phy_attached_info(phydev);
+	}
 
 	return 0;
 }
@@ -5007,10 +5143,10 @@ static void rtl8169_down(struct rtl8169_private *tp)
 	/* Clear all task flags */
 	bitmap_zero(tp->wk.flags, RTL_FLAG_MAX);
 
-	phy_stop(tp->phydev);
+	phylink_stop(tp->phylink);
 
 	/* Reset SerDes PHY to bring down fiber link */
-	if (tp->sfp_mode)
+	if (tp->sfp_mode == RTL_SFP_8127_ATF)
 		rtl_sfp_reset(tp);
 
 	rtl8169_update_counters(tp);
@@ -5032,14 +5168,14 @@ static void rtl8169_up(struct rtl8169_private *tp)
 		rtl8168_driver_start(tp);
 
 	pci_set_master(tp->pci_dev);
-	phy_init_hw(tp->phydev);
-	phy_resume(tp->phydev);
-	rtl8169_init_phy(tp);
+	if (tp->phydev)
+		rtl8169_init_phy(tp);
+
 	napi_enable(&tp->napi);
 	enable_work(&tp->wk.work);
 	rtl_reset_work(tp);
 
-	phy_start(tp->phydev);
+	phylink_start(tp->phylink);
 }
 
 static int rtl8169_close(struct net_device *dev)
@@ -5055,7 +5191,7 @@ static int rtl8169_close(struct net_device *dev)
 
 	free_irq(tp->irq, tp);
 
-	phy_disconnect(tp->phydev);
+	phylink_disconnect_phy(tp->phylink);
 
 	dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
 			  tp->RxPhyAddr);
@@ -5112,9 +5248,11 @@ static int rtl_open(struct net_device *dev)
 	if (retval < 0)
 		goto err_release_fw_2;
 
-	retval = r8169_phy_connect(tp);
-	if (retval)
-		goto err_free_irq;
+	if (tp->phydev) {
+		retval = r8169_phy_connect(tp);
+		if (retval)
+			goto err_free_irq;
+	}
 
 	rtl8169_up(tp);
 	rtl8169_init_counter_offsets(tp);
@@ -5190,8 +5328,11 @@ static int rtl8169_runtime_resume(struct device *dev)
 	rtl_rar_set(tp, tp->dev->dev_addr);
 	__rtl8169_set_wol(tp, tp->saved_wolopts);
 
-	if (tp->TxDescArray)
+	if (tp->TxDescArray) {
+		rtnl_lock();
 		rtl8169_up(tp);
+		rtnl_unlock();
+	}
 
 	netif_device_attach(tp->dev);
 
@@ -5288,6 +5429,7 @@ static void rtl_remove_one(struct pci_dev *pdev)
 		r8169_remove_leds(tp->leds);
 
 	unregister_netdev(tp->dev);
+	phylink_destroy(tp->phylink);
 
 	if (tp->dash_type != RTL_DASH_NONE)
 		rtl8168_driver_stop(tp);
@@ -5310,7 +5452,7 @@ static const struct net_device_ops rtl_netdev_ops = {
 	.ndo_fix_features	= rtl8169_fix_features,
 	.ndo_set_features	= rtl8169_set_features,
 	.ndo_set_mac_address	= rtl_set_mac_address,
-	.ndo_eth_ioctl		= phy_do_ioctl_running,
+	.ndo_eth_ioctl		= rtl8169_ioctl,
 	.ndo_set_rx_mode	= rtl_set_rx_mode,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= rtl8169_netpoll,
@@ -5474,16 +5616,6 @@ static int r8169_mdio_register(struct rtl8169_private *tp)
 		return -EUNATCH;
 	}
 
-	tp->phydev->mac_managed_pm = true;
-	if (rtl_supports_eee(tp))
-		phy_support_eee(tp->phydev);
-	phy_support_asym_pause(tp->phydev);
-
-	/* mimic behavior of r8125/r8126 vendor drivers */
-	if (tp->mac_version == RTL_GIGA_MAC_VER_61)
-		phy_disable_eee_mode(tp->phydev,
-				     ETHTOOL_LINK_MODE_2500baseT_Full_BIT);
-
 	/* PHY will be woken up in rtl_open() */
 	phy_suspend(tp->phydev);
 
@@ -5599,6 +5731,242 @@ static bool rtl_aspm_is_safe(struct rtl8169_private *tp)
 	return false;
 }
 
+static void rtl_mac_link_down(struct phylink_config *config, unsigned int mode,
+			      phy_interface_t interface)
+{
+	struct rtl8169_private *tp = container_of(config, struct rtl8169_private, phylink_config);
+
+	tp->speed = SPEED_UNKNOWN;
+	pm_runtime_idle(tp_to_dev(tp));
+}
+
+static void rtl_mac_link_up(struct phylink_config *config, struct phy_device *phydev,
+			    unsigned int mode, phy_interface_t interface,
+			    int speed, int duplex, bool tx_pause, bool rx_pause)
+{
+	struct rtl8169_private *tp = container_of(config, struct rtl8169_private, phylink_config);
+	struct device *d = tp_to_dev(tp);
+
+	tp->speed = speed;
+	rtl_link_chg_patch(tp, speed);
+
+	pm_request_resume(d);
+}
+
+static struct phylink_pcs *rtl_mac_select_pcs(struct phylink_config *config,
+					      phy_interface_t interface)
+{
+	struct rtl8169_private *tp = container_of(config, struct rtl8169_private, phylink_config);
+
+	if (!tp->pcs.ops)
+		return NULL;
+
+	if (interface == PHY_INTERFACE_MODE_1000BASEX ||
+	    interface == PHY_INTERFACE_MODE_10GBASER)
+		return &tp->pcs;
+
+	return NULL;
+}
+
+static void rtl_mac_config(struct phylink_config *config, unsigned int mode,
+			   const struct phylink_link_state *state)
+{
+}
+
+static u16 rtl8169_sds_read(struct rtl8169_private *tp, u16 sds_reg)
+{
+	unsigned long flags;
+	u16 val = 0;
+
+	raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
+	__r8168_mac_ocp_write(tp, OCP_SDS_ADDR_REG, sds_reg);
+	__r8168_mac_ocp_write(tp, OCP_SDS_CMD_REG, SDS_CMD_READ);
+	val = __r8168_mac_ocp_read(tp, OCP_SDS_DATA_REG);
+	raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
+
+	return val;
+}
+
+static void rtl8169_pcs_get_state(struct phylink_pcs *pcs,
+				  unsigned int neg_mode,
+				  struct phylink_link_state *state)
+{
+	struct rtl8169_private *tp = container_of(pcs, struct rtl8169_private, pcs);
+
+	if (tp->sfp_mode == RTL_SFP_8127_ATF) {
+		u16 stat1;
+
+		stat1 = rtl8169_sds_read(tp, RTL_SDS_C45_BASE + MDIO_STAT1);
+
+		if (!(stat1 & MDIO_STAT1_LSTATUS))
+			stat1 = rtl8169_sds_read(tp, RTL_SDS_C45_BASE + MDIO_STAT1);
+
+		state->link = !!(stat1 & MDIO_STAT1_LSTATUS);
+		if (!state->link)
+			return;
+
+		state->duplex = DUPLEX_FULL;
+		state->speed = SPEED_10000;
+	} else {
+		u16 bmsr, lpa;
+
+		bmsr = rtl8169_sds_read(tp, RTL_SDS_C22_BASE + MII_BMSR);
+		lpa = rtl8169_sds_read(tp, RTL_SDS_C22_BASE + MII_LPA);
+		phylink_mii_c22_pcs_decode_state(state, neg_mode, bmsr, lpa);
+	}
+}
+
+static int rtl8169_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+			      phy_interface_t interface,
+			      const unsigned long *advertising,
+			      bool permit_pause_to_mac)
+{
+	struct rtl8169_private *tp = container_of(pcs, struct rtl8169_private, pcs);
+
+	if (tp->sfp_mode == RTL_SFP_8127_ATF) {
+		switch (interface) {
+		case PHY_INTERFACE_MODE_10GBASER:
+			r8127_sfp_init_10g(tp);
+			break;
+		case PHY_INTERFACE_MODE_1000BASEX:
+			r8127_sfp_init_1g(tp);
+			break;
+		default:
+			netdev_err(tp->dev, "Unsupported SFP interface mode: %s\n",
+				   phy_modes(interface));
+			return -EOPNOTSUPP;
+		}
+	}
+
+	return 0;
+}
+
+static int rtl8169_pcs_validate(struct phylink_pcs *pcs, unsigned long *supported,
+				const struct phylink_link_state *state)
+{
+	return 0;
+}
+
+static void rtl8169_pcs_an_restart(struct phylink_pcs *pcs)
+{
+}
+
+static void rtl_mac_disable_tx_lpi(struct phylink_config *config)
+{
+	struct rtl8169_private *tp = container_of(config, struct rtl8169_private, phylink_config);
+
+	rtl_enable_tx_lpi(tp, false);
+}
+
+static int rtl_mac_enable_tx_lpi(struct phylink_config *config, u32 timer, bool tx_clk_stop)
+{
+	struct rtl8169_private *tp = container_of(config, struct rtl8169_private, phylink_config);
+
+	rtl_enable_tx_lpi(tp, true);
+
+	return 0;
+}
+
+static const struct phylink_mac_ops rtl_phylink_mac_ops = {
+	.mac_select_pcs = rtl_mac_select_pcs,
+	.mac_config = rtl_mac_config,
+	.mac_link_down  = rtl_mac_link_down,
+	.mac_link_up    = rtl_mac_link_up,
+	.mac_disable_tx_lpi = rtl_mac_disable_tx_lpi,
+	.mac_enable_tx_lpi = rtl_mac_enable_tx_lpi,
+};
+
+static unsigned long rtl8169_get_lpi_caps(struct rtl8169_private *tp)
+{
+	unsigned long caps = 0;
+
+	if (!rtl_supports_eee(tp) || tp->sfp_mode == RTL_SFP_8127_ATF)
+		return 0;
+
+	caps |= MAC_100FD | MAC_1000FD;
+
+	/* mimic behavior of r8125/r8126 vendor drivers
+	 * RTL_GIGA_MAC_VER_61 doesn't support 2.5G eee
+	 */
+	if (tp->mac_version >= RTL_GIGA_MAC_VER_63)
+		caps |= MAC_2500FD;
+	if (tp->mac_version >= RTL_GIGA_MAC_VER_70)
+		caps |= MAC_5000FD;
+	if (tp->mac_version == RTL_GIGA_MAC_VER_80)
+		caps |= MAC_10000FD;
+
+	return caps;
+}
+
+static const struct phylink_pcs_ops r8169_pcs_ops = {
+	.pcs_validate = rtl8169_pcs_validate,
+	.pcs_get_state = rtl8169_pcs_get_state,
+	.pcs_config = rtl8169_pcs_config,
+	.pcs_an_restart = rtl8169_pcs_an_restart,
+};
+
+static int rtl_init_phylink(struct rtl8169_private *tp)
+{
+	struct phylink *pl;
+	phy_interface_t phy_mode;
+
+	tp->phylink_config.dev = &tp->dev->dev;
+	tp->phylink_config.type = PHYLINK_NETDEV;
+	tp->phylink_config.mac_managed_pm = true;
+	tp->phylink_config.lpi_capabilities = rtl8169_get_lpi_caps(tp);
+	tp->phylink_config.mac_capabilities |= MAC_ASYM_PAUSE | MAC_SYM_PAUSE;
+
+	switch (tp->sfp_mode) {
+	case RTL_SFP_8168_AF:
+		tp->pcs.ops = &r8169_pcs_ops;
+		tp->phylink_config.default_an_inband = true;
+		phy_mode = PHY_INTERFACE_MODE_1000BASEX;
+		tp->phylink_config.mac_capabilities |= MAC_1000FD;
+		break;
+	case RTL_SFP_8127_ATF:
+		tp->pcs.ops = &r8169_pcs_ops;
+		phy_mode = PHY_INTERFACE_MODE_10GBASER;
+		tp->phylink_config.default_an_inband = true;
+		tp->phylink_config.mac_capabilities |= MAC_1000FD | MAC_10000FD;
+		break;
+	default:
+		phy_mode = PHY_INTERFACE_MODE_INTERNAL;
+		tp->phylink_config.mac_capabilities |= MAC_10 | MAC_100;
+
+		if (tp->mac_version == RTL_GIGA_MAC_VER_80)
+			tp->phylink_config.mac_capabilities |= MAC_1000FD | MAC_2500FD |
+							       MAC_5000FD | MAC_10000FD;
+		else if (tp->mac_version == RTL_GIGA_MAC_VER_70)
+			tp->phylink_config.mac_capabilities |= MAC_1000FD |
+							       MAC_2500FD | MAC_5000FD;
+		else if (tp->mac_version >= RTL_GIGA_MAC_VER_61)
+			tp->phylink_config.mac_capabilities |= MAC_1000FD | MAC_2500FD;
+		else
+			if (tp->supports_gmii)
+				tp->phylink_config.mac_capabilities |= MAC_1000FD;
+
+		if (tp->mac_version < RTL_GIGA_MAC_VER_61)
+			phy_mode = tp->supports_gmii ? PHY_INTERFACE_MODE_GMII :
+				   PHY_INTERFACE_MODE_MII;
+		else
+			phy_mode = PHY_INTERFACE_MODE_INTERNAL;
+		break;
+	}
+
+	__set_bit(phy_mode, tp->phylink_config.supported_interfaces);
+	if (tp->phylink_config.lpi_capabilities)
+		__set_bit(phy_mode, tp->phylink_config.lpi_interfaces);
+
+	pl = phylink_create(&tp->phylink_config, tp_to_dev(tp)->fwnode,
+			    phy_mode, &rtl_phylink_mac_ops);
+	if (IS_ERR(pl))
+		return PTR_ERR(pl);
+
+	tp->phylink = pl;
+
+	return 0;
+}
+
 static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	const struct rtl_chip_info *chip;
@@ -5667,6 +6035,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 				     ext_xid_str, xid);
 	tp->mac_version = chip->mac_version;
 	tp->fw_name = chip->fw_name;
+	tp->speed = SPEED_UNKNOWN;
 
 	/* Disable ASPM L1 as that cause random device stop working
 	 * problems as well as full system hangs for some PCIe devices users.
@@ -5679,12 +6048,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	}
 	tp->aspm_manageable = !rc;
 
-	if (rtl_is_8125(tp)) {
-		u16 data = r8168_mac_ocp_read(tp, 0xd006);
-
-		if ((data & 0xff) == 0x07)
-			tp->sfp_mode = true;
-	}
+	tp->sfp_mode = rtl_get_sfp_mode(tp);
 
 	tp->dash_type = rtl_get_dash_type(tp);
 	tp->dash_enabled = rtl_dash_is_enabled(tp);
@@ -5788,13 +6152,23 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	pci_set_drvdata(pdev, tp);
 
-	rc = r8169_mdio_register(tp);
+	rc = rtl_init_phylink(tp);
 	if (rc)
 		return rc;
 
+	if (tp->sfp_mode == RTL_SFP_NONE) {
+		rc = r8169_mdio_register(tp);
+		if (rc) {
+			phylink_destroy(tp->phylink);
+			return rc;
+		}
+	}
+
 	rc = register_netdev(dev);
-	if (rc)
+	if (rc) {
+		phylink_destroy(tp->phylink);
 		return rc;
+	}
 
 	if (IS_ENABLED(CONFIG_R8169_LEDS)) {
 		if (rtl_is_8125(tp))
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 59dfe35afa54fc..c450ee33b75cc1 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1828,6 +1828,72 @@ int phylink_set_fixed_link(struct phylink *pl,
 }
 EXPORT_SYMBOL_GPL(phylink_set_fixed_link);
 
+/**
+ * phylink_set_mac_capabilities() - Dynamically update MAC capabilities
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ * @mac_capabilities: the new MAC capabilities mask
+ *
+ * This function allows a MAC driver to dynamically change its capabilities,
+ * such as losing/gaining Pause frame support based on MTU size.
+ * It recalculates supported link modes and triggers renegotiation if needed.
+ */
+void phylink_set_mac_capabilities(struct phylink *pl, unsigned long mac_capabilities)
+{
+	struct phylink_link_state *config = &pl->link_config;
+	unsigned long caps_added, caps_removed;
+
+	ASSERT_RTNL();
+
+	caps_added = mac_capabilities & ~pl->config->mac_capabilities;
+	caps_removed = pl->config->mac_capabilities & ~mac_capabilities;
+
+	if (!caps_added && !caps_removed)
+		return;
+
+	mutex_lock(&pl->state_mutex);
+
+	pl->config->mac_capabilities = mac_capabilities;
+
+	if (caps_removed & MAC_SYM_PAUSE)
+		linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, pl->supported);
+	if (caps_removed & MAC_ASYM_PAUSE)
+		linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, pl->supported);
+
+	linkmode_and(config->advertising, config->advertising, pl->supported);
+
+	if (caps_added & MAC_SYM_PAUSE) {
+		linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, pl->supported);
+		if (pl->phydev && !phylink_test(pl->phydev->supported, Pause))
+			linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, pl->supported);
+	}
+	if (caps_added & MAC_ASYM_PAUSE) {
+		linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, pl->supported);
+		if (pl->phydev && !phylink_test(pl->phydev->supported, Asym_Pause))
+			linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, pl->supported);
+	}
+
+	linkmode_and(config->advertising, config->advertising, pl->supported);
+
+	if (config->pause & MLO_PAUSE_AN) {
+		if (phylink_test(pl->supported, Pause))
+			linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, config->advertising);
+
+		if (phylink_test(pl->supported, Asym_Pause))
+			linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, config->advertising);
+	}
+
+	if (!pl->phydev)
+		phylink_change_inband_advert(pl);
+
+	mutex_unlock(&pl->state_mutex);
+
+	if (pl->phydev) {
+		linkmode_copy(pl->phydev->advertising, config->advertising);
+		phy_start_aneg(pl->phydev);
+	}
+}
+EXPORT_SYMBOL_GPL(phylink_set_mac_capabilities);
+
 /**
  * phylink_create() - create a phylink instance
  * @config: a pointer to the target &struct phylink_config
diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c
index b65d0f5fa1a014..4721ba071cbbe4 100644
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/string_choices.h>
-#include <net/phy/realtek_phy.h>
 
 #include "../phylib.h"
 #include "realtek.h"
@@ -2646,45 +2645,6 @@ static irqreturn_t rtl8221b_handle_interrupt(struct phy_device *phydev)
 	return IRQ_HANDLED;
 }
 
-static int rtlgen_sfp_get_features(struct phy_device *phydev)
-{
-	linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
-			 phydev->supported);
-
-	/* set default mode */
-	phydev->speed = SPEED_10000;
-	phydev->duplex = DUPLEX_FULL;
-
-	phydev->port = PORT_FIBRE;
-
-	return 0;
-}
-
-static int rtlgen_sfp_read_status(struct phy_device *phydev)
-{
-	int val, err;
-
-	err = genphy_update_link(phydev);
-	if (err)
-		return err;
-
-	if (!phydev->link)
-		return 0;
-
-	val = phy_read(phydev, RTL_PHYSR);
-	if (val < 0)
-		return val;
-
-	rtlgen_decode_physr(phydev, val);
-
-	return 0;
-}
-
-static int rtlgen_sfp_config_aneg(struct phy_device *phydev)
-{
-	return 0;
-}
-
 static struct phy_driver realtek_drvs[] = {
 	{
 		PHY_ID_MATCH_EXACT(0x00008201),
@@ -2934,20 +2894,6 @@ static struct phy_driver realtek_drvs[] = {
 		.write_page	= rtl821x_write_page,
 		.read_mmd	= rtl822x_read_mmd,
 		.write_mmd	= rtl822x_write_mmd,
-	}, {
-		PHY_ID_MATCH_EXACT(PHY_ID_RTL_DUMMY_SFP),
-		.name		= "Realtek SFP PHY Mode",
-		.flags		= PHY_IS_INTERNAL,
-		.probe		= rtl822x_probe,
-		.get_features	= rtlgen_sfp_get_features,
-		.config_aneg	= rtlgen_sfp_config_aneg,
-		.read_status	= rtlgen_sfp_read_status,
-		.suspend	= genphy_suspend,
-		.resume		= rtlgen_resume,
-		.read_page	= rtl821x_read_page,
-		.write_page	= rtl821x_write_page,
-		.read_mmd	= rtl822x_read_mmd,
-		.write_mmd	= rtl822x_write_mmd,
 	}, {
 		PHY_ID_MATCH_EXACT(0x001ccad0),
 		.name		= "RTL8224 2.5Gbps PHY",
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 2bc0db3d52ac8d..56642ab961a753 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -842,4 +842,6 @@ void phylink_replay_link_begin(struct phylink *pl);
 
 void phylink_replay_link_end(struct phylink *pl);
 
+void phylink_set_mac_capabilities(struct phylink *pl, unsigned long mac_capabilities);
+
 #endif
diff --git a/include/net/phy/realtek_phy.h b/include/net/phy/realtek_phy.h
deleted file mode 100644
index d683bc1b0659cd..00000000000000
--- a/include/net/phy/realtek_phy.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _REALTEK_PHY_H
-#define _REALTEK_PHY_H
-
-#define	PHY_ID_RTL_DUMMY_SFP	0x001ccbff
-
-#endif /* _REALTEK_PHY_H */

3/2 2026/07/07 16:34 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 20458
							output: 37
							thoughts: 368
						

Thoughts:
**Analyzing the Reachability of a Network Driver Patch**

Okay, so I'm looking at this patch. It's a pretty substantial change, rewriting how the Realtek r8169 driver interacts with the phylink framework. Specifically, it's switching from directly using `phylib` to `phylink`, and there's a new function added to `phylink.c` called `phylink_set_mac_capabilities`. This is a significant functional shift within a core network driver and its associated framework. My immediate concern, as always, is how I can test this effectively, especially in a controlled environment.

The r8169 driver targets Realtek PCI Express Gigabit Ethernet controllers. My thought is can I use a virtualized environment for this. Can I use QEMU? I know QEMU *does* support the older `rtl8139` 10/100 Ethernet adapter, but not the r8169 out of the box. So, the question is how can I test this in a virtual environment? It's a PCI device, so QEMU would have to emulate the r8169 hardware. I need to make sure I don't confuse rtl8139 with the target. If the driver relies on a PCI bus, then the driver's `probe` function won't even be called unless QEMU properly emulates the device. Let me double check if QEMU provides that emulation specifically.



4/2 2026/07/07 16:34 tool grepper
0m Args:
{
  "Expression": "r8169",
  "PathPrefix": "drivers/net/ethernet/realtek/Kconfig"
}

Results:
{
  "Output": "drivers/net/ethernet/realtek/Kconfig=84=config R8169\n--\ndrivers/net/ethernet/realtek/Kconfig-100-\t  To compile this driver as a module, choose M here: the module\ndrivers/net/ethernet/realtek/Kconfig:101:\t  will be called r8169.  This is recommended.\ndrivers/net/ethernet/realtek/Kconfig-102-\n"
}

5/2 2026/07/07 16:34 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 21299
							output: 25
							thoughts: 258
						

Thoughts:
**My Syzkaller PCI Fuzzing Assessment**

Okay, so the first thing I'm thinking is, can Syzkaller hit this? My immediate reflex is to check for `syz_pci_device_add` or similar if it's a PCI driver, which usually means it needs an emulated PCI device or `vhci` or `pci` fuzzing support. But wait, I remember Syzkaller *does* have a dedicated PCI fuzzer that can inject PCI devices, which is great.

Right, `r8169` is indeed a PCI driver. That means Syzkaller *should* be able to tackle this using the `syz_pci` pseudo-device or by injecting PCI config space – classic PCI fuzzing approaches.

Actually, it hits me that Syzkaller's PCI fuzzer is designed to fuzz *any* PCI driver by effectively simulating the PCI device itself. This is really promising.

Now, I'm brought up short by the prompt mentioning code paths that are impossible in virtualized environments like GCE or QEMU, even with emulated hardware like USB or MAC80211. Okay, does Syzkaller's emulation actually cover that aspect?

Yes, wait, it clicks. Syzkaller's got `syz_pci`, which *absolutely* can emulate PCI devices. That's precisely what I need.

Alright, final step: let's verify if `r8169` is *currently* being fuzzed by Syzkaller.



6/2 2026/07/07 16:34 tool grepper
0m Args:
{
  "Expression": "r8169",
  "PathPrefix": ""
}

Results:
{
  "Output": "\nFull output is too long, showing 500 out of 536 lines.\nUse more precise expression if possible.\n\nDocumentation/core-api/dma-api.rst=741=example warning message may look like this::\n--\nDocumentation/core-api/dma-api.rst-748-\tsingle] [unmapped as page]\nDocumentation/core-api/dma-api.rst:749:\tModules linked in: nfsd exportfs bridge stp llc r8169\nDocumentation/core-api/dma-api.rst-750-\tPid: 0, comm: swapper Tainted: G        W  2.6.28-dmatest-09289-g8bb99c0 #1\n--\nDocumentation/leds/well-known-leds.txt=107=Good: !mdio-mux!mdio@2!switch@0!mdio:01:green:right\nDocumentation/leds/well-known-leds.txt:108:Good: r8169-0-200:00:yellow:bottom\nDocumentation/leds/well-known-leds.txt-109-\n--\nMAINTAINERS=136=S:\tMaintained\nMAINTAINERS:137:F:\tdrivers/net/ethernet/realtek/r8169*\nMAINTAINERS-138-\n--\ndrivers/net/ethernet/realtek/Kconfig=84=config R8169\n--\ndrivers/net/ethernet/realtek/Kconfig-100-\t  To compile this driver as a module, choose M here: the module\ndrivers/net/ethernet/realtek/Kconfig:101:\t  will be called r8169.  This is recommended.\ndrivers/net/ethernet/realtek/Kconfig-102-\n--\ndrivers/net/ethernet/realtek/Makefile=7=obj-$(CONFIG_8139TOO) += 8139too.o\ndrivers/net/ethernet/realtek/Makefile:8:r8169-y += r8169_main.o r8169_firmware.o r8169_phy_config.o\ndrivers/net/ethernet/realtek/Makefile:9:r8169-$(CONFIG_R8169_LEDS) += r8169_leds.o\ndrivers/net/ethernet/realtek/Makefile:10:obj-$(CONFIG_R8169) += r8169.o\ndrivers/net/ethernet/realtek/Makefile-11-obj-$(CONFIG_RTASE) += rtase/\n--\ndrivers/net/ethernet/realtek/r8169.h-1-/* SPDX-License-Identifier: GPL-2.0-only */\ndrivers/net/ethernet/realtek/r8169.h:2:/* r8169.h: RealTek 8169/8168/8101 ethernet driver.\ndrivers/net/ethernet/realtek/r8169.h-3- *\n--\ndrivers/net/ethernet/realtek/r8169.h=80=struct rtl8169_private;\ndrivers/net/ethernet/realtek/r8169.h:81:struct r8169_led_classdev;\ndrivers/net/ethernet/realtek/r8169.h-82-\ndrivers/net/ethernet/realtek/r8169.h:83:void r8169_apply_firmware(struct rtl8169_private *tp);\ndrivers/net/ethernet/realtek/r8169.h-84-u16 rtl8168h_2_get_adc_bias_ioffset(struct rtl8169_private *tp);\ndrivers/net/ethernet/realtek/r8169.h=85=u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr);\ndrivers/net/ethernet/realtek/r8169.h:86:void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev,\ndrivers/net/ethernet/realtek/r8169.h-87-\t\t\t enum mac_version ver);\ndrivers/net/ethernet/realtek/r8169.h-88-\ndrivers/net/ethernet/realtek/r8169.h:89:void r8169_get_led_name(struct rtl8169_private *tp, int idx,\ndrivers/net/ethernet/realtek/r8169.h-90-\t\t\tchar *buf, int buf_len);\n--\ndrivers/net/ethernet/realtek/r8169.h=92=int rtl8168_led_mod_ctrl(struct rtl8169_private *tp, u16 mask, u16 val);\ndrivers/net/ethernet/realtek/r8169.h:93:struct r8169_led_classdev *rtl8168_init_leds(struct net_device *ndev);\ndrivers/net/ethernet/realtek/r8169.h-94-int rtl8125_get_led_mode(struct rtl8169_private *tp, int index);\ndrivers/net/ethernet/realtek/r8169.h=95=int rtl8125_set_led_mode(struct rtl8169_private *tp, int index, u16 mode);\ndrivers/net/ethernet/realtek/r8169.h:96:struct r8169_led_classdev *rtl8125_init_leds(struct net_device *ndev);\ndrivers/net/ethernet/realtek/r8169.h:97:void r8169_remove_leds(struct r8169_led_classdev *leds);\n--\ndrivers/net/ethernet/realtek/r8169_firmware.c-1-// SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/ethernet/realtek/r8169_firmware.c:2:/* r8169_firmware.c: RealTek 8169/8168/8101 ethernet driver.\ndrivers/net/ethernet/realtek/r8169_firmware.c-3- *\n--\ndrivers/net/ethernet/realtek/r8169_firmware.c-13-\ndrivers/net/ethernet/realtek/r8169_firmware.c:14:#include \"r8169_firmware.h\"\ndrivers/net/ethernet/realtek/r8169_firmware.c-15-\n--\ndrivers/net/ethernet/realtek/r8169_firmware.h-1-/* SPDX-License-Identifier: GPL-2.0-only */\ndrivers/net/ethernet/realtek/r8169_firmware.h:2:/* r8169_firmware.h: RealTek 8169/8168/8101 ethernet driver.\ndrivers/net/ethernet/realtek/r8169_firmware.h-3- *\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-1-// SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/ethernet/realtek/r8169_leds.c:2:/* r8169_leds.c: Realtek 8169/8168/8101/8125 ethernet driver.\ndrivers/net/ethernet/realtek/r8169_leds.c-3- *\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-12-\ndrivers/net/ethernet/realtek/r8169_leds.c:13:#include \"r8169.h\"\ndrivers/net/ethernet/realtek/r8169_leds.c-14-\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-29-\ndrivers/net/ethernet/realtek/r8169_leds.c:30:struct r8169_led_classdev {\ndrivers/net/ethernet/realtek/r8169_leds.c-31-\tstruct led_classdev led;\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-35-\ndrivers/net/ethernet/realtek/r8169_leds.c:36:#define lcdev_to_r8169_ldev(lcdev) container_of(lcdev, struct r8169_led_classdev, led)\ndrivers/net/ethernet/realtek/r8169_leds.c-37-\ndrivers/net/ethernet/realtek/r8169_leds.c:38:static bool r8169_trigger_mode_is_valid(unsigned long flags)\ndrivers/net/ethernet/realtek/r8169_leds.c-39-{\n--\ndrivers/net/ethernet/realtek/r8169_leds.c=53=static int rtl8168_led_hw_control_is_supported(struct led_classdev *led_cdev,\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-55-{\ndrivers/net/ethernet/realtek/r8169_leds.c:56:\tstruct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);\ndrivers/net/ethernet/realtek/r8169_leds.c-57-\tstruct rtl8169_private *tp = netdev_priv(ldev-\u003endev);\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-59-\ndrivers/net/ethernet/realtek/r8169_leds.c:60:\tif (!r8169_trigger_mode_is_valid(flags)) {\ndrivers/net/ethernet/realtek/r8169_leds.c-61-\t\t/* Switch LED off to indicate that mode isn't supported */\n--\ndrivers/net/ethernet/realtek/r8169_leds.c=69=static int rtl8168_led_hw_control_set(struct led_classdev *led_cdev,\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-71-{\ndrivers/net/ethernet/realtek/r8169_leds.c:72:\tstruct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);\ndrivers/net/ethernet/realtek/r8169_leds.c-73-\tstruct rtl8169_private *tp = netdev_priv(ldev-\u003endev);\n--\ndrivers/net/ethernet/realtek/r8169_leds.c=89=static int rtl8168_led_hw_control_get(struct led_classdev *led_cdev,\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-91-{\ndrivers/net/ethernet/realtek/r8169_leds.c:92:\tstruct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);\ndrivers/net/ethernet/realtek/r8169_leds.c-93-\tstruct rtl8169_private *tp = netdev_priv(ldev-\u003endev);\n--\ndrivers/net/ethernet/realtek/r8169_leds.c=121=static struct device *\ndrivers/net/ethernet/realtek/r8169_leds.c:122:\tr8169_led_hw_control_get_device(struct led_classdev *led_cdev)\ndrivers/net/ethernet/realtek/r8169_leds.c-123-{\ndrivers/net/ethernet/realtek/r8169_leds.c:124:\tstruct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);\ndrivers/net/ethernet/realtek/r8169_leds.c-125-\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-128-\ndrivers/net/ethernet/realtek/r8169_leds.c:129:static void rtl8168_setup_ldev(struct r8169_led_classdev *ldev,\ndrivers/net/ethernet/realtek/r8169_leds.c-130-\t\t\t       struct net_device *ndev, int index)\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-138-\ndrivers/net/ethernet/realtek/r8169_leds.c:139:\tr8169_get_led_name(tp, index, led_name, LED_MAX_NAME_SIZE);\ndrivers/net/ethernet/realtek/r8169_leds.c-140-\tled_cdev-\u003ename = led_name;\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-145-\tled_cdev-\u003ehw_control_get = rtl8168_led_hw_control_get;\ndrivers/net/ethernet/realtek/r8169_leds.c:146:\tled_cdev-\u003ehw_control_get_device = r8169_led_hw_control_get_device;\ndrivers/net/ethernet/realtek/r8169_leds.c-147-\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-151-\ndrivers/net/ethernet/realtek/r8169_leds.c:152:struct r8169_led_classdev *rtl8168_init_leds(struct net_device *ndev)\ndrivers/net/ethernet/realtek/r8169_leds.c-153-{\ndrivers/net/ethernet/realtek/r8169_leds.c:154:\tstruct r8169_led_classdev *leds;\ndrivers/net/ethernet/realtek/r8169_leds.c-155-\tint i;\n--\ndrivers/net/ethernet/realtek/r8169_leds.c=167=static int rtl8125_led_hw_control_is_supported(struct led_classdev *led_cdev,\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-169-{\ndrivers/net/ethernet/realtek/r8169_leds.c:170:\tstruct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);\ndrivers/net/ethernet/realtek/r8169_leds.c-171-\tstruct rtl8169_private *tp = netdev_priv(ldev-\u003endev);\ndrivers/net/ethernet/realtek/r8169_leds.c-172-\ndrivers/net/ethernet/realtek/r8169_leds.c:173:\tif (!r8169_trigger_mode_is_valid(flags)) {\ndrivers/net/ethernet/realtek/r8169_leds.c-174-\t\t/* Switch LED off to indicate that mode isn't supported */\n--\ndrivers/net/ethernet/realtek/r8169_leds.c=182=static int rtl8125_led_hw_control_set(struct led_classdev *led_cdev,\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-184-{\ndrivers/net/ethernet/realtek/r8169_leds.c:185:\tstruct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);\ndrivers/net/ethernet/realtek/r8169_leds.c-186-\tstruct rtl8169_private *tp = netdev_priv(ldev-\u003endev);\n--\ndrivers/net/ethernet/realtek/r8169_leds.c=203=static int rtl8125_led_hw_control_get(struct led_classdev *led_cdev,\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-205-{\ndrivers/net/ethernet/realtek/r8169_leds.c:206:\tstruct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);\ndrivers/net/ethernet/realtek/r8169_leds.c-207-\tstruct rtl8169_private *tp = netdev_priv(ldev-\u003endev);\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-227-\ndrivers/net/ethernet/realtek/r8169_leds.c:228:static void rtl8125_setup_led_ldev(struct r8169_led_classdev *ldev,\ndrivers/net/ethernet/realtek/r8169_leds.c-229-\t\t\t\t   struct net_device *ndev, int index)\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-237-\ndrivers/net/ethernet/realtek/r8169_leds.c:238:\tr8169_get_led_name(tp, index, led_name, LED_MAX_NAME_SIZE);\ndrivers/net/ethernet/realtek/r8169_leds.c-239-\tled_cdev-\u003ename = led_name;\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-244-\tled_cdev-\u003ehw_control_get = rtl8125_led_hw_control_get;\ndrivers/net/ethernet/realtek/r8169_leds.c:245:\tled_cdev-\u003ehw_control_get_device = r8169_led_hw_control_get_device;\ndrivers/net/ethernet/realtek/r8169_leds.c-246-\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-250-\ndrivers/net/ethernet/realtek/r8169_leds.c:251:struct r8169_led_classdev *rtl8125_init_leds(struct net_device *ndev)\ndrivers/net/ethernet/realtek/r8169_leds.c-252-{\ndrivers/net/ethernet/realtek/r8169_leds.c:253:\tstruct r8169_led_classdev *leds;\ndrivers/net/ethernet/realtek/r8169_leds.c-254-\tint i;\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-265-\ndrivers/net/ethernet/realtek/r8169_leds.c:266:void r8169_remove_leds(struct r8169_led_classdev *leds)\ndrivers/net/ethernet/realtek/r8169_leds.c-267-{\n--\ndrivers/net/ethernet/realtek/r8169_leds.c-270-\ndrivers/net/ethernet/realtek/r8169_leds.c:271:\tfor (struct r8169_led_classdev *l = leds; l-\u003endev; l++)\ndrivers/net/ethernet/realtek/r8169_leds.c-272-\t\tled_classdev_unregister(\u0026l-\u003eled);\n--\ndrivers/net/ethernet/realtek/r8169_main.c-2-/*\ndrivers/net/ethernet/realtek/r8169_main.c:3: * r8169.c: RealTek 8169/8168/8101 ethernet driver.\ndrivers/net/ethernet/realtek/r8169_main.c-4- *\n--\ndrivers/net/ethernet/realtek/r8169_main.c-35-\ndrivers/net/ethernet/realtek/r8169_main.c:36:#include \"r8169.h\"\ndrivers/net/ethernet/realtek/r8169_main.c:37:#include \"r8169_firmware.h\"\ndrivers/net/ethernet/realtek/r8169_main.c-38-\n--\ndrivers/net/ethernet/realtek/r8169_main.c=761=struct rtl8169_private {\n--\ndrivers/net/ethernet/realtek/r8169_main.c-804-\ndrivers/net/ethernet/realtek/r8169_main.c:805:\tstruct r8169_led_classdev *leds;\ndrivers/net/ethernet/realtek/r8169_main.c-806-\n--\ndrivers/net/ethernet/realtek/r8169_main.c=815=typedef void (*rtl_generic_fct)(struct rtl8169_private *tp);\ndrivers/net/ethernet/realtek/r8169_main.c-816-\ndrivers/net/ethernet/realtek/r8169_main.c:817:MODULE_AUTHOR(\"Realtek and the Linux r8169 crew \u003cnetdev@vger.kernel.org\u003e\");\ndrivers/net/ethernet/realtek/r8169_main.c-818-MODULE_DESCRIPTION(\"RealTek RTL-8169 Gigabit Ethernet driver\");\n--\ndrivers/net/ethernet/realtek/r8169_main.c=880=static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-887-\ndrivers/net/ethernet/realtek/r8169_main.c:888:static void r8169_mod_reg8_cond(struct rtl8169_private *tp, int reg,\ndrivers/net/ethernet/realtek/r8169_main.c-889-\t\t\t\tu8 bits, bool cond)\n--\ndrivers/net/ethernet/realtek/r8169_main.c=1037=int rtl8125_get_led_mode(struct rtl8169_private *tp, int index)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-1053-\ndrivers/net/ethernet/realtek/r8169_main.c:1054:void r8169_get_led_name(struct rtl8169_private *tp, int idx,\ndrivers/net/ethernet/realtek/r8169_main.c-1055-\t\t\tchar *buf, int buf_len)\n--\ndrivers/net/ethernet/realtek/r8169_main.c=1387=DECLARE_RTL_COND(rtl_phyar_cond)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-1391-\ndrivers/net/ethernet/realtek/r8169_main.c:1392:static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value)\ndrivers/net/ethernet/realtek/r8169_main.c-1393-{\n--\ndrivers/net/ethernet/realtek/r8169_main.c-1403-\ndrivers/net/ethernet/realtek/r8169_main.c:1404:static int r8169_mdio_read(struct rtl8169_private *tp, int reg)\ndrivers/net/ethernet/realtek/r8169_main.c-1405-{\n--\ndrivers/net/ethernet/realtek/r8169_main.c=1439=static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-1442-\ndrivers/net/ethernet/realtek/r8169_main.c:1443:\tr8169_mdio_write(tp, reg, value);\ndrivers/net/ethernet/realtek/r8169_main.c-1444-\n--\ndrivers/net/ethernet/realtek/r8169_main.c=1448=static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-1457-\ndrivers/net/ethernet/realtek/r8169_main.c:1458:\tvalue = r8169_mdio_read(tp, reg);\ndrivers/net/ethernet/realtek/r8169_main.c-1459-\n--\ndrivers/net/ethernet/realtek/r8169_main.c=1465=static void rtl_writephy(struct rtl8169_private *tp, int location, int val)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-1475-\tdefault:\ndrivers/net/ethernet/realtek/r8169_main.c:1476:\t\tr8169_mdio_write(tp, location, val);\ndrivers/net/ethernet/realtek/r8169_main.c-1477-\t\tbreak;\n--\ndrivers/net/ethernet/realtek/r8169_main.c=1481=static int rtl_readphy(struct rtl8169_private *tp, int location)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-1489-\tdefault:\ndrivers/net/ethernet/realtek/r8169_main.c:1490:\t\treturn r8169_mdio_read(tp, location);\ndrivers/net/ethernet/realtek/r8169_main.c-1491-\t}\n--\ndrivers/net/ethernet/realtek/r8169_main.c=1710=static void rtl_set_d3_pll_down(struct rtl8169_private *tp, bool enable)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-1718-\tcase RTL_GIGA_MAC_VER_80:\ndrivers/net/ethernet/realtek/r8169_main.c:1719:\t\tr8169_mod_reg8_cond(tp, PMCH, D3_NO_PLL_DOWN, true);\ndrivers/net/ethernet/realtek/r8169_main.c-1720-\t\tbreak;\ndrivers/net/ethernet/realtek/r8169_main.c-1721-\tdefault:\ndrivers/net/ethernet/realtek/r8169_main.c:1722:\t\tr8169_mod_reg8_cond(tp, PMCH, D3HOT_NO_PLL_DOWN, true);\ndrivers/net/ethernet/realtek/r8169_main.c:1723:\t\tr8169_mod_reg8_cond(tp, PMCH, D3COLD_NO_PLL_DOWN, !enable);\ndrivers/net/ethernet/realtek/r8169_main.c-1724-\t\tbreak;\n--\ndrivers/net/ethernet/realtek/r8169_main.c=1830=static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-1844-\t} else {\ndrivers/net/ethernet/realtek/r8169_main.c:1845:\t\tr8169_mod_reg8_cond(tp, Config3, MagicPacket,\ndrivers/net/ethernet/realtek/r8169_main.c-1846-\t\t\t\t    wolopts \u0026 WAKE_MAGIC);\n--\ndrivers/net/ethernet/realtek/r8169_main.c-1848-\ndrivers/net/ethernet/realtek/r8169_main.c:1849:\tr8169_mod_reg8_cond(tp, Config3, LinkUp, wolopts \u0026 WAKE_PHY);\ndrivers/net/ethernet/realtek/r8169_main.c-1850-\tif (rtl_is_8125(tp))\n--\ndrivers/net/ethernet/realtek/r8169_main.c-1852-\t\t\t\t     wolopts \u0026 WAKE_PHY ? 0x13 : 0);\ndrivers/net/ethernet/realtek/r8169_main.c:1853:\tr8169_mod_reg8_cond(tp, Config5, UWF, wolopts \u0026 WAKE_UCAST);\ndrivers/net/ethernet/realtek/r8169_main.c:1854:\tr8169_mod_reg8_cond(tp, Config5, BWF, wolopts \u0026 WAKE_BCAST);\ndrivers/net/ethernet/realtek/r8169_main.c:1855:\tr8169_mod_reg8_cond(tp, Config5, MWF, wolopts \u0026 WAKE_MCAST);\ndrivers/net/ethernet/realtek/r8169_main.c:1856:\tr8169_mod_reg8_cond(tp, Config5, LanWake, wolopts);\ndrivers/net/ethernet/realtek/r8169_main.c-1857-\n--\ndrivers/net/ethernet/realtek/r8169_main.c-1859-\tcase RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:\ndrivers/net/ethernet/realtek/r8169_main.c:1860:\t\tr8169_mod_reg8_cond(tp, Config1, PMEnable, wolopts);\ndrivers/net/ethernet/realtek/r8169_main.c-1861-\t\tbreak;\n--\ndrivers/net/ethernet/realtek/r8169_main.c-1864-\tcase RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_LAST:\ndrivers/net/ethernet/realtek/r8169_main.c:1865:\t\tr8169_mod_reg8_cond(tp, Config2, PME_SIGNAL, wolopts);\ndrivers/net/ethernet/realtek/r8169_main.c-1866-\t\tbreak;\n--\ndrivers/net/ethernet/realtek/r8169_main.c=2326=static void rtl_set_eee_txidle_timer(struct rtl8169_private *tp)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-2344-\ndrivers/net/ethernet/realtek/r8169_main.c:2345:static unsigned int r8169_get_tx_lpi_timer_us(struct rtl8169_private *tp)\ndrivers/net/ethernet/realtek/r8169_main.c-2346-{\n--\ndrivers/net/ethernet/realtek/r8169_main.c=2357=static int rtl8169_get_eee(struct net_device *dev, struct ethtool_keee *data)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-2368-\ndrivers/net/ethernet/realtek/r8169_main.c:2369:\tdata-\u003etx_lpi_timer = r8169_get_tx_lpi_timer_us(tp);\ndrivers/net/ethernet/realtek/r8169_main.c-2370-\n--\ndrivers/net/ethernet/realtek/r8169_main.c=2576=static void rtl_release_firmware(struct rtl8169_private *tp)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-2584-\ndrivers/net/ethernet/realtek/r8169_main.c:2585:void r8169_apply_firmware(struct rtl8169_private *tp)\ndrivers/net/ethernet/realtek/r8169_main.c-2586-{\n--\ndrivers/net/ethernet/realtek/r8169_main.c=2634=static void rtl8169_init_phy(struct rtl8169_private *tp)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-2637-\tphy_resume(tp-\u003ephydev);\ndrivers/net/ethernet/realtek/r8169_main.c:2638:\tr8169_hw_phy_config(tp, tp-\u003ephydev, tp-\u003emac_version);\ndrivers/net/ethernet/realtek/r8169_main.c-2639-\n--\ndrivers/net/ethernet/realtek/r8169_main.c=2721=static void rtl_jumbo_config(struct rtl8169_private *tp)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-2732-\tcase RTL_GIGA_MAC_VER_17:\ndrivers/net/ethernet/realtek/r8169_main.c:2733:\t\tr8169_mod_reg8_cond(tp, Config4, BIT(0), jumbo);\ndrivers/net/ethernet/realtek/r8169_main.c-2734-\t\tbreak;\ndrivers/net/ethernet/realtek/r8169_main.c-2735-\tcase RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_26:\ndrivers/net/ethernet/realtek/r8169_main.c:2736:\t\tr8169_mod_reg8_cond(tp, Config3, Jumbo_En0, jumbo);\ndrivers/net/ethernet/realtek/r8169_main.c:2737:\t\tr8169_mod_reg8_cond(tp, Config4, Jumbo_En1, jumbo);\ndrivers/net/ethernet/realtek/r8169_main.c-2738-\t\tbreak;\ndrivers/net/ethernet/realtek/r8169_main.c-2739-\tcase RTL_GIGA_MAC_VER_28:\ndrivers/net/ethernet/realtek/r8169_main.c:2740:\t\tr8169_mod_reg8_cond(tp, Config3, Jumbo_En0, jumbo);\ndrivers/net/ethernet/realtek/r8169_main.c-2741-\t\tbreak;\n--\ndrivers/net/ethernet/realtek/r8169_main.c-2743-\t\tRTL_W8(tp, MaxTxPacketSize, jumbo ? 0x24 : 0x3f);\ndrivers/net/ethernet/realtek/r8169_main.c:2744:\t\tr8169_mod_reg8_cond(tp, Config3, Jumbo_En0, jumbo);\ndrivers/net/ethernet/realtek/r8169_main.c:2745:\t\tr8169_mod_reg8_cond(tp, Config4, BIT(0), jumbo);\ndrivers/net/ethernet/realtek/r8169_main.c-2746-\t\tbreak;\n--\ndrivers/net/ethernet/realtek/r8169_main.c=3801=static void rtl_hw_start_8117(struct rtl8169_private *tp)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-3860-\t/* firmware is for MAC only */\ndrivers/net/ethernet/realtek/r8169_main.c:3861:\tr8169_apply_firmware(tp);\ndrivers/net/ethernet/realtek/r8169_main.c-3862-}\n--\ndrivers/net/ethernet/realtek/r8169_main.c=5095=static void rtl_enable_tx_lpi(struct rtl8169_private *tp, bool enable)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-5126-\ndrivers/net/ethernet/realtek/r8169_main.c:5127:static int r8169_phy_connect(struct rtl8169_private *tp)\ndrivers/net/ethernet/realtek/r8169_main.c-5128-{\n--\ndrivers/net/ethernet/realtek/r8169_main.c=5217=static int rtl_open(struct net_device *dev)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-5251-\tif (tp-\u003ephydev) {\ndrivers/net/ethernet/realtek/r8169_main.c:5252:\t\tretval = r8169_phy_connect(tp);\ndrivers/net/ethernet/realtek/r8169_main.c-5253-\t\tif (retval)\n--\ndrivers/net/ethernet/realtek/r8169_main.c=5419=static void rtl_remove_one(struct pci_dev *pdev)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-5428-\tif (IS_ENABLED(CONFIG_R8169_LEDS))\ndrivers/net/ethernet/realtek/r8169_main.c:5429:\t\tr8169_remove_leds(tp-\u003eleds);\ndrivers/net/ethernet/realtek/r8169_main.c-5430-\n--\ndrivers/net/ethernet/realtek/r8169_main.c=5513=static void r8168g_wait_ll_share_fifo_ready(struct rtl8169_private *tp)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-5517-\ndrivers/net/ethernet/realtek/r8169_main.c:5518:static int r8169_mdio_read_reg(struct mii_bus *mii_bus, int phyaddr, int phyreg)\ndrivers/net/ethernet/realtek/r8169_main.c-5519-{\n--\ndrivers/net/ethernet/realtek/r8169_main.c-5527-\ndrivers/net/ethernet/realtek/r8169_main.c:5528:static int r8169_mdio_write_reg(struct mii_bus *mii_bus, int phyaddr,\ndrivers/net/ethernet/realtek/r8169_main.c-5529-\t\t\t\tint phyreg, u16 val)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-5540-\ndrivers/net/ethernet/realtek/r8169_main.c:5541:static int r8169_mdio_read_reg_c45(struct mii_bus *mii_bus, int addr,\ndrivers/net/ethernet/realtek/r8169_main.c-5542-\t\t\t\t   int devnum, int regnum)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-5554-\ndrivers/net/ethernet/realtek/r8169_main.c:5555:static int r8169_mdio_write_reg_c45(struct mii_bus *mii_bus, int addr,\ndrivers/net/ethernet/realtek/r8169_main.c-5556-\t\t\t\t    int devnum, int regnum, u16 val)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-5567-\ndrivers/net/ethernet/realtek/r8169_main.c:5568:static int r8169_mdio_register(struct rtl8169_private *tp)\ndrivers/net/ethernet/realtek/r8169_main.c-5569-{\n--\ndrivers/net/ethernet/realtek/r8169_main.c-5580-\t    tp-\u003emac_version == RTL_GIGA_MAC_VER_26)\ndrivers/net/ethernet/realtek/r8169_main.c:5581:\t\tr8169_mdio_write(tp, 0x1f, 0);\ndrivers/net/ethernet/realtek/r8169_main.c-5582-\n--\ndrivers/net/ethernet/realtek/r8169_main.c-5586-\ndrivers/net/ethernet/realtek/r8169_main.c:5587:\tnew_bus-\u003ename = \"r8169\";\ndrivers/net/ethernet/realtek/r8169_main.c-5588-\tnew_bus-\u003epriv = tp;\n--\ndrivers/net/ethernet/realtek/r8169_main.c-5591-\tnew_bus-\u003ephy_mask = GENMASK(31, 1);\ndrivers/net/ethernet/realtek/r8169_main.c:5592:\tsnprintf(new_bus-\u003eid, MII_BUS_ID_SIZE, \"r8169-%x-%x\",\ndrivers/net/ethernet/realtek/r8169_main.c-5593-\t\t pci_domain_nr(pdev-\u003ebus), pci_dev_id(pdev));\ndrivers/net/ethernet/realtek/r8169_main.c-5594-\ndrivers/net/ethernet/realtek/r8169_main.c:5595:\tnew_bus-\u003eread = r8169_mdio_read_reg;\ndrivers/net/ethernet/realtek/r8169_main.c:5596:\tnew_bus-\u003ewrite = r8169_mdio_write_reg;\ndrivers/net/ethernet/realtek/r8169_main.c-5597-\ndrivers/net/ethernet/realtek/r8169_main.c-5598-\tif (tp-\u003emac_version \u003e= RTL_GIGA_MAC_VER_40) {\ndrivers/net/ethernet/realtek/r8169_main.c:5599:\t\tnew_bus-\u003eread_c45 = r8169_mdio_read_reg_c45;\ndrivers/net/ethernet/realtek/r8169_main.c:5600:\t\tnew_bus-\u003ewrite_c45 = r8169_mdio_write_reg_c45;\ndrivers/net/ethernet/realtek/r8169_main.c-5601-\t}\n--\ndrivers/net/ethernet/realtek/r8169_main.c=5879=static unsigned long rtl8169_get_lpi_caps(struct rtl8169_private *tp)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-5900-\ndrivers/net/ethernet/realtek/r8169_main.c:5901:static const struct phylink_pcs_ops r8169_pcs_ops = {\ndrivers/net/ethernet/realtek/r8169_main.c-5902-\t.pcs_validate = rtl8169_pcs_validate,\n--\ndrivers/net/ethernet/realtek/r8169_main.c=5908=static int rtl_init_phylink(struct rtl8169_private *tp)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-5920-\tcase RTL_SFP_8168_AF:\ndrivers/net/ethernet/realtek/r8169_main.c:5921:\t\ttp-\u003epcs.ops = \u0026r8169_pcs_ops;\ndrivers/net/ethernet/realtek/r8169_main.c-5922-\t\ttp-\u003ephylink_config.default_an_inband = true;\n--\ndrivers/net/ethernet/realtek/r8169_main.c-5926-\tcase RTL_SFP_8127_ATF:\ndrivers/net/ethernet/realtek/r8169_main.c:5927:\t\ttp-\u003epcs.ops = \u0026r8169_pcs_ops;\ndrivers/net/ethernet/realtek/r8169_main.c-5928-\t\tphy_mode = PHY_INTERFACE_MODE_10GBASER;\n--\ndrivers/net/ethernet/realtek/r8169_main.c=5970=static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-6033-\t\treturn dev_err_probe(\u0026pdev-\u003edev, -ENODEV,\ndrivers/net/ethernet/realtek/r8169_main.c:6034:\t\t\t\t     \"unknown chip %sXID %x, contact r8169 maintainers (see MAINTAINERS file)\\n\",\ndrivers/net/ethernet/realtek/r8169_main.c-6035-\t\t\t\t     ext_xid_str, xid);\n--\ndrivers/net/ethernet/realtek/r8169_main.c-6159-\tif (tp-\u003esfp_mode == RTL_SFP_NONE) {\ndrivers/net/ethernet/realtek/r8169_main.c:6160:\t\trc = r8169_mdio_register(tp);\ndrivers/net/ethernet/realtek/r8169_main.c-6161-\t\tif (rc) {\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-2-/*\ndrivers/net/ethernet/realtek/r8169_phy_config.c:3: * r8169_phy_config.c: RealTek 8169/8168/8101 ethernet driver.\ndrivers/net/ethernet/realtek/r8169_phy_config.c-4- *\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-14-\ndrivers/net/ethernet/realtek/r8169_phy_config.c:15:#include \"r8169.h\"\ndrivers/net/ethernet/realtek/r8169_phy_config.c-16-\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c=432=static void rtl8168d_apply_firmware_cond(struct rtl8169_private *tp,\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-445-\telse\ndrivers/net/ethernet/realtek/r8169_phy_config.c:446:\t\tr8169_apply_firmware(tp);\ndrivers/net/ethernet/realtek/r8169_phy_config.c-447-}\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c=538=static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp,\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-551-\ndrivers/net/ethernet/realtek/r8169_phy_config.c:552:\tr8169_apply_firmware(tp);\ndrivers/net/ethernet/realtek/r8169_phy_config.c-553-\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c=583=static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp,\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-585-{\ndrivers/net/ethernet/realtek/r8169_phy_config.c:586:\tr8169_apply_firmware(tp);\ndrivers/net/ethernet/realtek/r8169_phy_config.c-587-\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c=641=static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp,\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-643-{\ndrivers/net/ethernet/realtek/r8169_phy_config.c:644:\tr8169_apply_firmware(tp);\ndrivers/net/ethernet/realtek/r8169_phy_config.c-645-\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c=669=static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp,\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-671-{\ndrivers/net/ethernet/realtek/r8169_phy_config.c:672:\tr8169_apply_firmware(tp);\ndrivers/net/ethernet/realtek/r8169_phy_config.c-673-\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c=677=static void rtl8411_hw_phy_config(struct rtl8169_private *tp,\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-679-{\ndrivers/net/ethernet/realtek/r8169_phy_config.c:680:\tr8169_apply_firmware(tp);\ndrivers/net/ethernet/realtek/r8169_phy_config.c-681-\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c=741=static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp,\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-745-\ndrivers/net/ethernet/realtek/r8169_phy_config.c:746:\tr8169_apply_firmware(tp);\ndrivers/net/ethernet/realtek/r8169_phy_config.c-747-\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c=789=static void rtl8168g_2_hw_phy_config(struct rtl8169_private *tp,\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-791-{\ndrivers/net/ethernet/realtek/r8169_phy_config.c:792:\tr8169_apply_firmware(tp);\ndrivers/net/ethernet/realtek/r8169_phy_config.c-793-\trtl8168g_config_eee_phy(phydev);\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c=796=static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp,\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-801-\ndrivers/net/ethernet/realtek/r8169_phy_config.c:802:\tr8169_apply_firmware(tp);\ndrivers/net/ethernet/realtek/r8169_phy_config.c-803-\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c=947=static void rtl8105e_hw_phy_config(struct rtl8169_private *tp,\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-953-\ndrivers/net/ethernet/realtek/r8169_phy_config.c:954:\tr8169_apply_firmware(tp);\ndrivers/net/ethernet/realtek/r8169_phy_config.c-955-\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c=961=static void rtl8402_hw_phy_config(struct rtl8169_private *tp,\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-967-\ndrivers/net/ethernet/realtek/r8169_phy_config.c:968:\tr8169_apply_firmware(tp);\ndrivers/net/ethernet/realtek/r8169_phy_config.c-969-\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c=977=static void rtl8106e_hw_phy_config(struct rtl8169_private *tp,\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-990-\ndrivers/net/ethernet/realtek/r8169_phy_config.c:991:\tr8169_apply_firmware(tp);\ndrivers/net/ethernet/realtek/r8169_phy_config.c-992-\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c=1001=static void rtl8125a_2_hw_phy_config(struct rtl8169_private *tp,\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-1045-\ndrivers/net/ethernet/realtek/r8169_phy_config.c:1046:\tr8169_apply_firmware(tp);\ndrivers/net/ethernet/realtek/r8169_phy_config.c-1047-\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c=1063=static void rtl8125b_hw_phy_config(struct rtl8169_private *tp,\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c-1065-{\ndrivers/net/ethernet/realtek/r8169_phy_config.c:1066:\tr8169_apply_firmware(tp);\ndrivers/net/ethernet/realtek/r8169_phy_config.c-1067-\trtl8168g_enable_gphy_10m(phydev);\n--\ndrivers/net/ethernet/realtek/r8169_phy_config.c=1098=static void rtl8125d_hw_phy_config(struct rtl8169_private *tp,\n\n"
}

7/2 2026/07/07 16:34 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 36659
							output: 38
							thoughts: 984
						

Thoughts:
**Fuzzing the r8169 Driver with syz_pci**

Okay, so we're looking at fuzzing the `r8169` driver, which is a PCI driver, using `syz_pci`.  Syzkaller's `syz_pci` pseudo-device is the key here. The question is, is this patch fuzz-worthy?  Yes, it seems to be! This patch involves significant changes, specifically the adoption of `phylink` by the `r8169` driver and the addition of `phylink_set_mac_capabilities` to `phylink.c`.

Right, let's dive into the details. I need to identify which functions are being modified or added. Let's see... in `drivers/net/ethernet/realtek/r8169_main.c` there's quite a list: `r8127_sds_read`, `r8127_sds_write`, `r8127_sds_modify`, `r8127_sfp_init_1g`, `r8127_sfp_init_10g`, `rtl_is_8116af`, `rtl_get_sfp_mode`, `rtl_link_chg_patch`, `rtl8169_get_link_ksettings`, `rtl8169_set_link_ksettings`, `rtl8169_nway_reset`, `rtl8169_ioctl`, `rtl_lowpower_hidden_functions`, `rtl8169_change_mtu`, `rtl_mac_link_down`, `rtl_mac_link_up`, `rtl_mac_select_pcs`, `rtl_mac_config`, `rtl8169_sds_read`, `rtl8169_pcs_get_state`, `rtl8169_pcs_config`, `rtl8169_pcs_validate`, `rtl8169_pcs_an_restart`, `rtl_mac_disable_tx_lpi`, `rtl_mac_enable_tx_lpi`, `rtl8169_get_lpi_caps`, and `rtl_init_phylink`. And in `drivers/net/phy/phylink.c`, we have `phylink_set_mac_capabilities`.

Next, I need to check if `CONFIG_R8169` is enabled by default.  It's probably enabled, being a common network driver, but let's be thorough and list it anyway. Wait, scratch that. The instructions are to list only specific configs that cover the modified code, and *not* include the "CONFIG_" prefix. Got it. So, `R8169` goes into `EnableConfigs` and `PHYLINK` as well, because `R8169` now selects it.

Okay, let's figure out what symbols to focus on for fuzzing. We want the new or significantly modified functions.  Alright, let's see...  We should focus on: `phylink_set_mac_capabilities`, `rtl_init_phylink`, `rtl8169_pcs_config`, `rtl8169_pcs_get_state`, `rtl_mac_link_up`, `rtl_mac_link_down`, `rtl_mac_select_pcs`, `rtl_mac_disable_tx_lpi`, `rtl_mac_enable_tx_lpi`, `rtl8169_change_mtu`, `rtl_lowpower_hidden_functions`, `r8127_sfp_init_1g`, `r8127_sfp_init_10g`, and `rtl8169_ioctl`.

Now, is `phylink_set_mac_capabilities` exported? Yes, it is!  `EXPORT_SYMBOL_GPL(phylink_set_mac_capabilities);` confirms it. And, let's check `rtl8169_change_mtu` - yep, it's been modified to call `phylink_set_mac_capabilities`.

Finally, a quick code search to verify everything. Makes sense!



8/2 2026/07/07 16:35 tool grepper
0m Args:
{
  "Expression": "phylink_set_mac_capabilities",
  "PathPrefix": "drivers/net/phy/phylink.c"
}

Results:
{
  "Output": "drivers/net/phy/phylink.c=1829=EXPORT_SYMBOL_GPL(phylink_set_fixed_link);\n--\ndrivers/net/phy/phylink.c-1831-/**\ndrivers/net/phy/phylink.c:1832: * phylink_set_mac_capabilities() - Dynamically update MAC capabilities\ndrivers/net/phy/phylink.c-1833- * @pl: a pointer to a \u0026struct phylink returned from phylink_create()\n--\ndrivers/net/phy/phylink.c-1839- */\ndrivers/net/phy/phylink.c:1840:void phylink_set_mac_capabilities(struct phylink *pl, unsigned long mac_capabilities)\ndrivers/net/phy/phylink.c-1841-{\n--\ndrivers/net/phy/phylink.c-1894-}\ndrivers/net/phy/phylink.c:1895:EXPORT_SYMBOL_GPL(phylink_set_mac_capabilities);\ndrivers/net/phy/phylink.c-1896-\n"
}

9/2 2026/07/07 16:35 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 38898
							output: 45
							thoughts: 34
						

Thoughts:
Here's my attempt at summarizing the thought process, tailored for an expert audience:

**Diving into the Realtek PHY Initialization**

Okay, time to get to the heart of this Realtek issue. I need to get a handle on how this PHY is initialized, so I'm heading straight for `rtl_init_phylink`. I'm going to navigate to `drivers/net/ethernet/realtek/r8169_main.c`. That's where I expect to find the low-level PHY interaction logic. Specifically, `rtl_init_phylink` likely handles the PHY's initial setup and configuration, including potentially autonegotiation and link speed/duplex setting. I'm hoping I can glean information from there that helps me get to the bottom of the problem. Time to see what's going on under the hood.



10/2 2026/07/07 16:35 tool grepper
0m Args:
{
  "Expression": "rtl_init_phylink",
  "PathPrefix": "drivers/net/ethernet/realtek/r8169_main.c"
}

Results:
{
  "Output": "drivers/net/ethernet/realtek/r8169_main.c=5901=static const struct phylink_pcs_ops r8169_pcs_ops = {\n--\ndrivers/net/ethernet/realtek/r8169_main.c-5907-\ndrivers/net/ethernet/realtek/r8169_main.c:5908:static int rtl_init_phylink(struct rtl8169_private *tp)\ndrivers/net/ethernet/realtek/r8169_main.c-5909-{\n--\ndrivers/net/ethernet/realtek/r8169_main.c=5970=static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)\n--\ndrivers/net/ethernet/realtek/r8169_main.c-6154-\ndrivers/net/ethernet/realtek/r8169_main.c:6155:\trc = rtl_init_phylink(tp);\ndrivers/net/ethernet/realtek/r8169_main.c-6156-\tif (rc)\n"
}

11/2 2026/07/07 16:35 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 39473
							output: 298
							thoughts: 514
						

Thoughts:
**Fuzzing Target Identification: r8169 Driver and phylink Framework**

Alright, let's break this down. This patch is definitely significant; it's got some real functional changes happening in the `r8169` driver and the `phylink` framework. Specifically, this move from `phylib` to `phylink`, alongside the addition of dynamic MAC capabilities updates within `phylink`, shouts "fuzz me!"

I've scoped out the key functions to target. Here's what I'm thinking:

*   `phylink_set_mac_capabilities` - this is going to be interesting, especially with dynamic updates.
*   `rtl_init_phylink`
*   `rtl8169_pcs_config`
*   `rtl8169_pcs_get_state` - Might be worth hitting with a state-aware fuzzer, since it's likely called periodically.
*   `rtl_mac_link_up`
*   `rtl_mac_link_down`
*   `rtl_mac_select_pcs`
*   `rtl_mac_disable_tx_lpi`
*   `rtl_mac_enable_tx_lpi`
*   `rtl8169_change_mtu` - Let's see if we can trigger some interesting edge cases through MTU manipulation.
*   `rtl_lowpower_hidden_functions` - Worth digging into the logic in these low-power functions.
*   `r8127_sfp_init_1g` - I'm interested in how this deals with 1G.
*   `r8127_sfp_init_10g` - Similarly, worth checking the 10G implementation.
*   `rtl8169_ioctl` - This will likely be fruitful!

Config-wise, `R8169` is our primary focus since it selects `PHYLINK`. Enabling `R8169` should get us everything we need. No need to explicitly list `PHYLINK`.

I just took a quick look at `rtl8169_change_mtu` and a few others. It confirms these functions are control path operations. Functions like `rtl8169_pcs_get_state` might be interesting for state-aware fuzzers. They aren't hot-path, but they are still valuable targets.
With this, I think we have a strong starting point. Now, let's get that fuzzing campaign rolling!



12/2 2026/07/07 16:35 tool set-results
0m Args:
{
  "EnableConfigs": [
    "R8169"
  ],
  "FocusSymbols": [
    "phylink_set_mac_capabilities",
    "rtl_init_phylink",
    "rtl8169_pcs_config",
    "rtl8169_pcs_get_state",
    "rtl_mac_link_up",
    "rtl_mac_link_down",
    "rtl_mac_select_pcs",
    "rtl_mac_disable_tx_lpi",
    "rtl_mac_enable_tx_lpi",
    "rtl8169_change_mtu",
    "rtl_lowpower_hidden_functions",
    "r8127_sfp_init_1g",
    "r8127_sfp_init_10g",
    "rtl8169_ioctl"
  ],
  "Reasoning": "The patch migrates the Realtek r8169 Ethernet driver from phylib to phylink, introducing significant functional changes to the driver's initialization, link management, and MTU handling. It also adds a new phylink API `phylink_set_mac_capabilities` to dynamically update MAC capabilities. These are reachable control-path functions that should be fuzzed, especially via syz_pci and netlink/ioctl interfaces.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "R8169"
  ],
  "FocusSymbols": [
    "phylink_set_mac_capabilities",
    "rtl_init_phylink",
    "rtl8169_pcs_config",
    "rtl8169_pcs_get_state",
    "rtl_mac_link_up",
    "rtl_mac_link_down",
    "rtl_mac_select_pcs",
    "rtl_mac_disable_tx_lpi",
    "rtl_mac_enable_tx_lpi",
    "rtl8169_change_mtu",
    "rtl_lowpower_hidden_functions",
    "r8127_sfp_init_1g",
    "r8127_sfp_init_10g",
    "rtl8169_ioctl"
  ],
  "Reasoning": "The patch migrates the Realtek r8169 Ethernet driver from phylib to phylink, introducing significant functional changes to the driver's initialization, link management, and MTU handling. It also adds a new phylink API `phylink_set_mac_capabilities` to dynamically update MAC capabilities. These are reachable control-path functions that should be fuzzed, especially via syz_pci and netlink/ioctl interfaces.",
  "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)