AI Trajectory


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

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch is a pure refactoring of the Microchip KSZ DSA driver. It moves chip-specific functions (like MTU configuration, TC setup, MIB stats reading, and drive strength parsing) from the common `ksz_common.c` file to their respective chip-specific files (`ksz8.c` and `ksz9477.c`). It also removes a no-op call to `ksz_parse_drive_strength` in `lan937x_main.c` which only printed warnings for unsupported properties. No new functional logic or reachable code paths are introduced.",
  "WorthFuzzing": false
}

1/1 2026/07/02 13:56 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit d6edbbd8fab9105b1aba0f6f9417f5479476a79f\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Thu Jul 2 13:56:25 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c\nindex 586916570a841b..c4c769028a20c9 100644\n--- a/drivers/net/dsa/microchip/ksz8.c\n+++ b/drivers/net/dsa/microchip/ksz8.c\n@@ -36,6 +36,52 @@\n #include \"ksz8_reg.h\"\n #include \"ksz8.h\"\n \n+/* ksz88x3_drive_strengths - Drive strength mapping for KSZ8863, KSZ8873, ..\n+ *\t\t\t     variants.\n+ * This values are documented in KSZ8873 and KSZ8863 datasheets.\n+ */\n+static const struct ksz_drive_strength ksz88x3_drive_strengths[] = {\n+\t{ 0,  8000 },\n+\t{ KSZ8873_DRIVE_STRENGTH_16MA, 16000 },\n+};\n+\n+struct ksz88xx_stats_raw {\n+\tu64 rx;\n+\tu64 rx_hi;\n+\tu64 rx_undersize;\n+\tu64 rx_fragments;\n+\tu64 rx_oversize;\n+\tu64 rx_jabbers;\n+\tu64 rx_symbol_err;\n+\tu64 rx_crc_err;\n+\tu64 rx_align_err;\n+\tu64 rx_mac_ctrl;\n+\tu64 rx_pause;\n+\tu64 rx_bcast;\n+\tu64 rx_mcast;\n+\tu64 rx_ucast;\n+\tu64 rx_64_or_less;\n+\tu64 rx_65_127;\n+\tu64 rx_128_255;\n+\tu64 rx_256_511;\n+\tu64 rx_512_1023;\n+\tu64 rx_1024_1522;\n+\tu64 tx;\n+\tu64 tx_hi;\n+\tu64 tx_late_col;\n+\tu64 tx_pause;\n+\tu64 tx_bcast;\n+\tu64 tx_mcast;\n+\tu64 tx_ucast;\n+\tu64 tx_deferred;\n+\tu64 tx_total_col;\n+\tu64 tx_exc_col;\n+\tu64 tx_single_col;\n+\tu64 tx_mult_col;\n+\tu64 rx_discards;\n+\tu64 tx_discards;\n+};\n+\n static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)\n {\n \tksz_rmw8(dev, addr, bits, set ? bits : 0);\n@@ -158,10 +204,17 @@ static int ksz8_reset_switch(struct ksz_device *dev)\n \treturn 0;\n }\n \n-static int ksz8863_change_mtu(struct ksz_device *dev, int frame_size)\n+static int ksz88xx_change_mtu(struct dsa_switch *ds, int port, int mtu)\n {\n+\tstruct ksz_device *dev = ds-\u003epriv;\n+\tint frame_size;\n \tu8 ctrl2 = 0;\n \n+\tif (!dsa_is_cpu_port(dev-\u003eds, port))\n+\t\treturn 0;\n+\n+\tframe_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;\n+\n \tif (frame_size \u003c= KSZ8_LEGAL_PACKET_SIZE)\n \t\tctrl2 |= KSZ8863_LEGAL_PACKET_ENABLE;\n \telse if (frame_size \u003e KSZ8863_NORMAL_PACKET_SIZE)\n@@ -171,11 +224,18 @@ static int ksz8863_change_mtu(struct ksz_device *dev, int frame_size)\n \t\t\tKSZ8863_HUGE_PACKET_ENABLE, ctrl2);\n }\n \n-static int ksz8795_change_mtu(struct ksz_device *dev, int frame_size)\n+static int ksz87xx_change_mtu(struct dsa_switch *ds, int port, int mtu)\n {\n+\tstruct ksz_device *dev = ds-\u003epriv;\n \tu8 ctrl1 = 0, ctrl2 = 0;\n+\tu16 frame_size;\n \tint ret;\n \n+\tif (!dsa_is_cpu_port(dev-\u003eds, port))\n+\t\treturn 0;\n+\n+\tframe_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;\n+\n \tif (frame_size \u003e KSZ8_LEGAL_PACKET_SIZE)\n \t\tctrl2 |= SW_LEGAL_PACKET_DISABLE;\n \tif (frame_size \u003e KSZ8863_NORMAL_PACKET_SIZE)\n@@ -188,29 +248,14 @@ static int ksz8795_change_mtu(struct ksz_device *dev, int frame_size)\n \treturn ksz_rmw8(dev, REG_SW_CTRL_2, SW_LEGAL_PACKET_DISABLE, ctrl2);\n }\n \n-static int ksz8_change_mtu(struct dsa_switch *ds, int port, int mtu)\n+static int ksz87xx_max_mtu(struct dsa_switch *ds, int port)\n {\n-\tstruct ksz_device *dev = ds-\u003epriv;\n-\tu16 frame_size;\n-\n-\tif (!dsa_is_cpu_port(dev-\u003eds, port))\n-\t\treturn 0;\n-\n-\tframe_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;\n-\n-\tswitch (dev-\u003echip_id) {\n-\tcase KSZ8795_CHIP_ID:\n-\tcase KSZ8794_CHIP_ID:\n-\tcase KSZ8765_CHIP_ID:\n-\t\treturn ksz8795_change_mtu(dev, frame_size);\n-\tcase KSZ8463_CHIP_ID:\n-\tcase KSZ88X3_CHIP_ID:\n-\tcase KSZ8864_CHIP_ID:\n-\tcase KSZ8895_CHIP_ID:\n-\t\treturn ksz8863_change_mtu(dev, frame_size);\n-\t}\n+\treturn KSZ8795_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;\n+}\n \n-\treturn -EOPNOTSUPP;\n+static int ksz88xx_max_mtu(struct dsa_switch *ds, int port)\n+{\n+\treturn KSZ8863_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;\n }\n \n static int ksz8_port_queue_split(struct ksz_device *dev, int port, int queues)\n@@ -1746,6 +1791,159 @@ static void ksz8_port_mirror_del(struct dsa_switch *ds, int port,\n \t\t\t     PORT_MIRROR_SNIFFER, false);\n }\n \n+static u8 ksz8463_tc_ctrl(int port, int queue)\n+{\n+\tu8 reg;\n+\n+\treg = 0xC8 + port * 4;\n+\treg += ((3 - queue) / 2) * 2;\n+\treg++;\n+\treg -= (queue \u0026 1);\n+\treturn reg;\n+}\n+\n+/**\n+ * ksz88x3_tc_ets_add - Configure ETS (Enhanced Transmission Selection)\n+ *                      for a port on KSZ88x3 switch\n+ * @dev: Pointer to the KSZ switch device structure\n+ * @port: Port number to configure\n+ * @p: Pointer to offload replace parameters describing ETS bands and mapping\n+ *\n+ * The KSZ88x3 supports two scheduling modes: Strict Priority and\n+ * Weighted Fair Queuing (WFQ). Both modes have fixed behavior:\n+ *   - No configurable queue-to-priority mapping\n+ *   - No weight adjustment in WFQ mode\n+ *\n+ * This function configures the switch to use strict priority mode by\n+ * clearing the WFQ enable bit for all queues associated with ETS bands.\n+ * If strict priority is not explicitly requested, the switch will default\n+ * to WFQ mode.\n+ *\n+ * Return: 0 on success, or a negative error code on failure\n+ */\n+static int ksz88x3_tc_ets_add(struct ksz_device *dev, int port,\n+\t\t\t      struct tc_ets_qopt_offload_replace_params *p)\n+{\n+\tint ret, band;\n+\n+\t/* Only strict priority mode is supported for now.\n+\t * WFQ is implicitly enabled when strict mode is disabled.\n+\t */\n+\tfor (band = 0; band \u003c p-\u003ebands; band++) {\n+\t\tint queue = ksz_ets_band_to_queue(p, band);\n+\t\tu8 reg;\n+\n+\t\t/* Calculate TXQ Split Control register address for this\n+\t\t * port/queue\n+\t\t */\n+\t\treg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);\n+\t\tif (ksz_is_ksz8463(dev))\n+\t\t\treg = ksz8463_tc_ctrl(port, queue);\n+\n+\t\t/* Clear WFQ enable bit to select strict priority scheduling */\n+\t\tret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE, 0);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ksz88x3_tc_ets_del - Reset ETS (Enhanced Transmission Selection) config\n+ *                      for a port on KSZ88x3 switch\n+ * @dev: Pointer to the KSZ switch device structure\n+ * @port: Port number to reset\n+ *\n+ * The KSZ88x3 supports only fixed scheduling modes: Strict Priority or\n+ * Weighted Fair Queuing (WFQ), with no reconfiguration of weights or\n+ * queue mapping. This function resets the port’s scheduling mode to\n+ * the default, which is WFQ, by enabling the WFQ bit for all queues.\n+ *\n+ * Return: 0 on success, or a negative error code on failure\n+ */\n+static int ksz88x3_tc_ets_del(struct ksz_device *dev, int port)\n+{\n+\tint ret, queue;\n+\n+\t/* Iterate over all transmit queues for this port */\n+\tfor (queue = 0; queue \u003c dev-\u003einfo-\u003enum_tx_queues; queue++) {\n+\t\tu8 reg;\n+\n+\t\t/* Calculate TXQ Split Control register address for this\n+\t\t * port/queue\n+\t\t */\n+\t\treg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);\n+\t\tif (ksz_is_ksz8463(dev))\n+\t\t\treg = ksz8463_tc_ctrl(port, queue);\n+\n+\t\t/* Set WFQ enable bit to revert back to default scheduling\n+\t\t * mode\n+\t\t */\n+\t\tret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE,\n+\t\t\t       KSZ8873_TXQ_WFQ_ENABLE);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int ksz8_tc_setup_qdisc_ets(struct dsa_switch *ds, int port,\n+\t\t\t\t   struct tc_ets_qopt_offload *qopt)\n+{\n+\tstruct ksz_device *dev = ds-\u003epriv;\n+\tint ret;\n+\n+\tif (!(ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)))\n+\t\treturn -EOPNOTSUPP;\n+\n+\tif (qopt-\u003eparent != TC_H_ROOT) {\n+\t\tdev_err(dev-\u003edev, \"Parent should be \\\"root\\\"\\n\");\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+\n+\tswitch (qopt-\u003ecommand) {\n+\tcase TC_ETS_REPLACE:\n+\t\tret = ksz_tc_ets_validate(dev, port, \u0026qopt-\u003ereplace_params);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\treturn ksz88x3_tc_ets_add(dev, port, \u0026qopt-\u003ereplace_params);\n+\tcase TC_ETS_DESTROY:\n+\t\treturn ksz88x3_tc_ets_del(dev, port);\n+\tcase TC_ETS_STATS:\n+\tcase TC_ETS_GRAFT:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+\n+\treturn -EOPNOTSUPP;\n+}\n+\n+static int ksz87xx_setup_tc(struct dsa_switch *ds, int port,\n+\t\t\t    enum tc_setup_type type, void *type_data)\n+{\n+\tswitch (type) {\n+\tcase TC_SETUP_QDISC_CBS:\n+\t\treturn ksz_setup_tc_cbs(ds, port, type_data);\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+}\n+\n+static int ksz8_setup_tc(struct dsa_switch *ds, int port,\n+\t\t\t enum tc_setup_type type, void *type_data)\n+{\n+\tswitch (type) {\n+\tcase TC_SETUP_QDISC_CBS:\n+\t\treturn ksz_setup_tc_cbs(ds, port, type_data);\n+\tcase TC_SETUP_QDISC_ETS:\n+\t\treturn ksz8_tc_setup_qdisc_ets(ds, port, type_data);\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+}\n+\n static void ksz8795_cpu_interface_select(struct ksz_device *dev, int port)\n {\n \tstruct ksz_port *p = \u0026dev-\u003eports[port];\n@@ -2053,6 +2251,171 @@ static int ksz8_enable_stp_addr(struct ksz_device *dev)\n \treturn ksz8_w_sta_mac_table(dev, 0, \u0026alu);\n }\n \n+static void ksz88xx_r_mib_stats64(struct ksz_device *dev, int port)\n+{\n+\tstruct ethtool_pause_stats *pstats;\n+\tstruct rtnl_link_stats64 *stats;\n+\tstruct ksz88xx_stats_raw *raw;\n+\tstruct ksz_port_mib *mib;\n+\n+\tmib = \u0026dev-\u003eports[port].mib;\n+\tstats = \u0026mib-\u003estats64;\n+\tpstats = \u0026mib-\u003epause_stats;\n+\traw = (struct ksz88xx_stats_raw *)mib-\u003ecounters;\n+\n+\tspin_lock(\u0026mib-\u003estats64_lock);\n+\n+\tstats-\u003erx_packets = raw-\u003erx_bcast + raw-\u003erx_mcast + raw-\u003erx_ucast +\n+\t\traw-\u003erx_pause;\n+\tstats-\u003etx_packets = raw-\u003etx_bcast + raw-\u003etx_mcast + raw-\u003etx_ucast +\n+\t\traw-\u003etx_pause;\n+\n+\t/* HW counters are counting bytes + FCS which is not acceptable\n+\t * for rtnl_link_stats64 interface\n+\t */\n+\tstats-\u003erx_bytes = raw-\u003erx + raw-\u003erx_hi - stats-\u003erx_packets * ETH_FCS_LEN;\n+\tstats-\u003etx_bytes = raw-\u003etx + raw-\u003etx_hi - stats-\u003etx_packets * ETH_FCS_LEN;\n+\n+\tstats-\u003erx_length_errors = raw-\u003erx_undersize + raw-\u003erx_fragments +\n+\t\traw-\u003erx_oversize;\n+\n+\tstats-\u003erx_crc_errors = raw-\u003erx_crc_err;\n+\tstats-\u003erx_frame_errors = raw-\u003erx_align_err;\n+\tstats-\u003erx_dropped = raw-\u003erx_discards;\n+\tstats-\u003erx_errors = stats-\u003erx_length_errors + stats-\u003erx_crc_errors +\n+\t\tstats-\u003erx_frame_errors  + stats-\u003erx_dropped;\n+\n+\tstats-\u003etx_window_errors = raw-\u003etx_late_col;\n+\tstats-\u003etx_fifo_errors = raw-\u003etx_discards;\n+\tstats-\u003etx_aborted_errors = raw-\u003etx_exc_col;\n+\tstats-\u003etx_errors = stats-\u003etx_window_errors + stats-\u003etx_fifo_errors +\n+\t\tstats-\u003etx_aborted_errors;\n+\n+\tstats-\u003emulticast = raw-\u003erx_mcast;\n+\tstats-\u003ecollisions = raw-\u003etx_total_col;\n+\n+\tpstats-\u003etx_pause_frames = raw-\u003etx_pause;\n+\tpstats-\u003erx_pause_frames = raw-\u003erx_pause;\n+\n+\tspin_unlock(\u0026mib-\u003estats64_lock);\n+}\n+\n+/**\n+ * ksz88x3_drive_strength_write() - Set the drive strength configuration for\n+ *\t\t\t\t    KSZ8863 compatible chip variants.\n+ * @dev:       ksz device\n+ * @props:     Array of drive strength properties to be set\n+ * @num_props: Number of properties in the array\n+ *\n+ * This function applies the specified drive strength settings to KSZ88X3 chip\n+ * variants (KSZ8873, KSZ8863).\n+ * It ensures the configurations align with what the chip variant supports and\n+ * warns or errors out on unsupported settings.\n+ *\n+ * Return: 0 on success, error code otherwise\n+ */\n+static int ksz88x3_drive_strength_write(struct ksz_device *dev,\n+\t\t\t\t\tstruct ksz_driver_strength_prop *props,\n+\t\t\t\t\tint num_props)\n+{\n+\tsize_t array_size = ARRAY_SIZE(ksz88x3_drive_strengths);\n+\tint microamp;\n+\tint i, ret;\n+\n+\tfor (i = 0; i \u003c num_props; i++) {\n+\t\tif (props[i].value == -1 || i == KSZ_DRIVER_STRENGTH_IO)\n+\t\t\tcontinue;\n+\n+\t\tdev_warn(dev-\u003edev, \"%s is not supported by this chip variant\\n\",\n+\t\t\t props[i].name);\n+\t}\n+\n+\tmicroamp = props[KSZ_DRIVER_STRENGTH_IO].value;\n+\tret = ksz_drive_strength_to_reg(ksz88x3_drive_strengths, array_size,\n+\t\t\t\t\tmicroamp);\n+\tif (ret \u003c 0) {\n+\t\tksz_drive_strength_error(dev, ksz88x3_drive_strengths,\n+\t\t\t\t\t array_size, microamp);\n+\t\treturn ret;\n+\t}\n+\n+\treturn ksz_rmw8(dev, KSZ8873_REG_GLOBAL_CTRL_12,\n+\t\t\tKSZ8873_DRIVE_STRENGTH_16MA, ret);\n+}\n+\n+/**\n+ * ksz8_parse_drive_strength() - Extract and apply drive strength configurations\n+ *\t\t\t\t from device tree properties.\n+ * @dev:\tksz device\n+ *\n+ * This function reads the specified drive strength properties from the\n+ * device tree, validates against the supported chip variants, and sets\n+ * them accordingly. An error should be critical here, as the drive strength\n+ * settings are crucial for EMI compliance.\n+ *\n+ * Return: 0 on success, error code otherwise\n+ */\n+static int ksz8_parse_drive_strength(struct ksz_device *dev)\n+{\n+\tstruct ksz_driver_strength_prop of_props[] = {\n+\t\t[KSZ_DRIVER_STRENGTH_HI] = {\n+\t\t\t.name = \"microchip,hi-drive-strength-microamp\",\n+\t\t\t.offset = SW_HI_SPEED_DRIVE_STRENGTH_S,\n+\t\t\t.value = -1,\n+\t\t},\n+\t\t[KSZ_DRIVER_STRENGTH_LO] = {\n+\t\t\t.name = \"microchip,lo-drive-strength-microamp\",\n+\t\t\t.offset = SW_LO_SPEED_DRIVE_STRENGTH_S,\n+\t\t\t.value = -1,\n+\t\t},\n+\t\t[KSZ_DRIVER_STRENGTH_IO] = {\n+\t\t\t.name = \"microchip,io-drive-strength-microamp\",\n+\t\t\t.offset = 0, /* don't care */\n+\t\t\t.value = -1,\n+\t\t},\n+\t};\n+\tstruct device_node *np = dev-\u003edev-\u003eof_node;\n+\tbool have_any_prop = false;\n+\tint i, ret;\n+\n+\tfor (i = 0; i \u003c ARRAY_SIZE(of_props); i++) {\n+\t\tret = of_property_read_u32(np, of_props[i].name,\n+\t\t\t\t\t   \u0026of_props[i].value);\n+\t\tif (ret \u0026\u0026 ret != -EINVAL)\n+\t\t\tdev_warn(dev-\u003edev, \"Failed to read %s\\n\",\n+\t\t\t\t of_props[i].name);\n+\t\tif (ret)\n+\t\t\tcontinue;\n+\n+\t\thave_any_prop = true;\n+\t}\n+\n+\tif (!have_any_prop)\n+\t\treturn 0;\n+\n+\tswitch (dev-\u003echip_id) {\n+\tcase KSZ88X3_CHIP_ID:\n+\t\treturn ksz88x3_drive_strength_write(dev, of_props,\n+\t\t\t\t\t\t    ARRAY_SIZE(of_props));\n+\tcase KSZ8795_CHIP_ID:\n+\tcase KSZ8794_CHIP_ID:\n+\tcase KSZ8765_CHIP_ID:\n+\t\treturn ksz_drive_strength_write(dev, of_props,\n+\t\t\t\t\t\tARRAY_SIZE(of_props));\n+\tdefault:\n+\t\t/* KSZ8864, KSZ8895 */\n+\t\tfor (i = 0; i \u003c ARRAY_SIZE(of_props); i++) {\n+\t\t\tif (of_props[i].value == -1)\n+\t\t\t\tcontinue;\n+\n+\t\t\tdev_warn(dev-\u003edev, \"%s is not supported by this chip variant\\n\",\n+\t\t\t\t of_props[i].name);\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n static int ksz8_setup(struct dsa_switch *ds)\n {\n \tstruct ksz_device *dev = ds-\u003epriv;\n@@ -2075,7 +2438,7 @@ static int ksz8_setup(struct dsa_switch *ds)\n \t\treturn ret;\n \t}\n \n-\tret = ksz_parse_drive_strength(dev);\n+\tret = ksz8_parse_drive_strength(dev);\n \tif (ret)\n \t\treturn ret;\n \n@@ -2551,8 +2914,8 @@ const struct dsa_switch_ops ksz8463_switch_ops = {\n \t.port_mirror_del\t= ksz8_port_mirror_del,\n \t.get_stats64\t\t= ksz_get_stats64,\n \t.get_pause_stats\t= ksz_get_pause_stats,\n-\t.port_change_mtu\t= ksz8_change_mtu,\n-\t.port_max_mtu\t\t= ksz_max_mtu,\n+\t.port_change_mtu\t= ksz88xx_change_mtu,\n+\t.port_max_mtu\t\t= ksz88xx_max_mtu,\n \t.suspend\t\t= ksz_suspend,\n \t.resume\t\t\t= ksz_resume,\n \t.get_ts_info\t\t= ksz_get_ts_info,\n@@ -2560,7 +2923,7 @@ const struct dsa_switch_ops ksz8463_switch_ops = {\n \t.port_hwtstamp_set\t= ksz_hwtstamp_set,\n \t.port_txtstamp\t\t= ksz_port_txtstamp,\n \t.port_rxtstamp\t\t= ksz_port_rxtstamp,\n-\t.port_setup_tc\t\t= ksz_setup_tc,\n+\t.port_setup_tc\t\t= ksz8_setup_tc,\n \t.port_get_default_prio\t= ksz_port_get_default_prio,\n \t.port_set_default_prio\t= ksz_port_set_default_prio,\n \t.port_get_dscp_prio\t= ksz_port_get_dscp_prio,\n@@ -2601,8 +2964,8 @@ const struct dsa_switch_ops ksz87xx_switch_ops = {\n \t.port_mirror_del\t= ksz8_port_mirror_del,\n \t.get_stats64\t\t= ksz_get_stats64,\n \t.get_pause_stats\t= ksz_get_pause_stats,\n-\t.port_change_mtu\t= ksz8_change_mtu,\n-\t.port_max_mtu\t\t= ksz_max_mtu,\n+\t.port_change_mtu\t= ksz87xx_change_mtu,\n+\t.port_max_mtu\t\t= ksz87xx_max_mtu,\n \t.suspend\t\t= ksz_suspend,\n \t.resume\t\t\t= ksz_resume,\n \t.get_ts_info\t\t= ksz_get_ts_info,\n@@ -2610,7 +2973,7 @@ const struct dsa_switch_ops ksz87xx_switch_ops = {\n \t.port_hwtstamp_set\t= ksz_hwtstamp_set,\n \t.port_txtstamp\t\t= ksz_port_txtstamp,\n \t.port_rxtstamp\t\t= ksz_port_rxtstamp,\n-\t.port_setup_tc\t\t= ksz_setup_tc,\n+\t.port_setup_tc\t\t= ksz87xx_setup_tc,\n \t.port_get_default_prio\t= ksz_port_get_default_prio,\n \t.port_set_default_prio\t= ksz_port_set_default_prio,\n \t.port_get_dscp_prio\t= ksz_port_get_dscp_prio,\n@@ -2652,8 +3015,8 @@ const struct dsa_switch_ops ksz88xx_switch_ops = {\n \t.port_mirror_del\t= ksz8_port_mirror_del,\n \t.get_stats64\t\t= ksz_get_stats64,\n \t.get_pause_stats\t= ksz_get_pause_stats,\n-\t.port_change_mtu\t= ksz8_change_mtu,\n-\t.port_max_mtu\t\t= ksz_max_mtu,\n+\t.port_change_mtu\t= ksz88xx_change_mtu,\n+\t.port_max_mtu\t\t= ksz88xx_max_mtu,\n \t.get_wol\t\t= ksz_get_wol,\n \t.set_wol\t\t= ksz_set_wol,\n \t.suspend\t\t= ksz_suspend,\n@@ -2663,7 +3026,7 @@ const struct dsa_switch_ops ksz88xx_switch_ops = {\n \t.port_hwtstamp_set\t= ksz_hwtstamp_set,\n \t.port_txtstamp\t\t= ksz_port_txtstamp,\n \t.port_rxtstamp\t\t= ksz_port_rxtstamp,\n-\t.port_setup_tc\t\t= ksz_setup_tc,\n+\t.port_setup_tc\t\t= ksz8_setup_tc,\n \t.port_get_default_prio\t= ksz_port_get_default_prio,\n \t.port_set_default_prio\t= ksz_port_set_default_prio,\n \t.port_get_dscp_prio\t= ksz_port_get_dscp_prio,\ndiff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c\nindex f3f0c98dfb5a7f..3ee995545c5795 100644\n--- a/drivers/net/dsa/microchip/ksz9477.c\n+++ b/drivers/net/dsa/microchip/ksz9477.c\n@@ -15,6 +15,7 @@\n #include \u003clinux/if_hsr.h\u003e\n #include \u003clinux/if_vlan.h\u003e\n #include \u003cnet/dsa.h\u003e\n+#include \u003cnet/ieee8021q.h\u003e\n #include \u003cnet/switchdev.h\u003e\n \n #include \"ksz9477_reg.h\"\n@@ -60,6 +61,11 @@ static int ksz9477_change_mtu(struct dsa_switch *ds, int port, int mtu)\n \t\t\t\t  REG_SW_MTU_MASK, frame_size);\n }\n \n+int ksz9477_max_mtu(struct dsa_switch *ds, int port)\n+{\n+\treturn KSZ9477_MAX_FRAME_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;\n+}\n+\n static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev)\n {\n \tunsigned int val;\n@@ -478,8 +484,8 @@ static int ksz9477_half_duplex_monitor(struct ksz_device *dev, int port,\n \treturn ret;\n }\n \n-int ksz9477_errata_monitor(struct ksz_device *dev, int port,\n-\t\t\t   u64 tx_late_col)\n+static int ksz9477_errata_monitor(struct ksz_device *dev, int port,\n+\t\t\t\t  u64 tx_late_col)\n {\n \tu8 status;\n \tint ret;\n@@ -497,6 +503,24 @@ int ksz9477_errata_monitor(struct ksz_device *dev, int port,\n \treturn ret;\n }\n \n+static void ksz9477_r_mib_stats64(struct ksz_device *dev, int port)\n+{\n+\tstruct ksz_stats_raw *raw;\n+\tstruct ksz_port_mib *mib;\n+\tint ret;\n+\n+\tksz_r_mib_stats64(dev, port);\n+\n+\tif (dev-\u003einfo-\u003ephy_errata_9477 \u0026\u0026 !ksz_is_sgmii_port(dev, port)) {\n+\t\tmib = \u0026dev-\u003eports[port].mib;\n+\t\traw = (struct ksz_stats_raw *)mib-\u003ecounters;\n+\n+\t\tret = ksz9477_errata_monitor(dev, port, raw-\u003etx_late_col);\n+\t\tif (ret)\n+\t\t\tdev_err(dev-\u003edev, \"Failed to monitor transmission halt\\n\");\n+\t}\n+};\n+\n void ksz9477_port_init_cnt(struct ksz_device *dev, int port)\n {\n \tstruct ksz_port_mib *mib = \u0026dev-\u003eports[port].mib;\n@@ -1176,6 +1200,58 @@ void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,\n \t\t\t     PORT_MIRROR_SNIFFER, false);\n }\n \n+static bool ksz9477_get_gbit(struct ksz_device *dev, int port)\n+{\n+\tconst u8 *bitval = dev-\u003einfo-\u003exmii_ctrl1;\n+\tconst u16 *regs = dev-\u003einfo-\u003eregs;\n+\tbool gbit = false;\n+\tu8 data8;\n+\tbool val;\n+\n+\tksz_pread8(dev, port, regs[P_XMII_CTRL_1], \u0026data8);\n+\n+\tval = FIELD_GET(P_GMII_1GBIT_M, data8);\n+\n+\tif (val == bitval[P_GMII_1GBIT])\n+\t\tgbit = true;\n+\n+\treturn gbit;\n+}\n+\n+static phy_interface_t ksz9477_get_xmii(struct ksz_device *dev, int port,\n+\t\t\t\t\tbool gbit)\n+{\n+\tconst u8 *bitval = dev-\u003einfo-\u003exmii_ctrl1;\n+\tconst u16 *regs = dev-\u003einfo-\u003eregs;\n+\tphy_interface_t interface;\n+\tu8 data8;\n+\tu8 val;\n+\n+\tksz_pread8(dev, port, regs[P_XMII_CTRL_1], \u0026data8);\n+\n+\tval = FIELD_GET(P_MII_SEL_M, data8);\n+\n+\tif (val == bitval[P_MII_SEL]) {\n+\t\tif (gbit)\n+\t\t\tinterface = PHY_INTERFACE_MODE_GMII;\n+\t\telse\n+\t\t\tinterface = PHY_INTERFACE_MODE_MII;\n+\t} else if (val == bitval[P_RMII_SEL]) {\n+\t\tinterface = PHY_INTERFACE_MODE_RMII;\n+\t} else {\n+\t\tinterface = PHY_INTERFACE_MODE_RGMII;\n+\t\tif (data8 \u0026 P_RGMII_ID_EG_ENABLE)\n+\t\t\tinterface = PHY_INTERFACE_MODE_RGMII_TXID;\n+\t\tif (data8 \u0026 P_RGMII_ID_IG_ENABLE) {\n+\t\t\tinterface = PHY_INTERFACE_MODE_RGMII_RXID;\n+\t\t\tif (data8 \u0026 P_RGMII_ID_EG_ENABLE)\n+\t\t\t\tinterface = PHY_INTERFACE_MODE_RGMII_ID;\n+\t\t}\n+\t}\n+\n+\treturn interface;\n+}\n+\n static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port)\n {\n \tphy_interface_t interface;\n@@ -1184,9 +1260,9 @@ static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port)\n \tif (dev-\u003einfo-\u003einternal_phy[port])\n \t\treturn PHY_INTERFACE_MODE_NA;\n \n-\tgbit = ksz_get_gbit(dev, port);\n+\tgbit = ksz9477_get_gbit(dev, port);\n \n-\tinterface = ksz_get_xmii(dev, port, gbit);\n+\tinterface = ksz9477_get_xmii(dev, port, gbit);\n \n \treturn interface;\n }\n@@ -1335,6 +1411,28 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)\n \tksz_pwrite8(dev, port, regs[REG_PORT_PME_CTRL], 0);\n }\n \n+int ksz9477_set_default_prio_queue_mapping(struct ksz_device *dev, int port)\n+{\n+\tu32 queue_map = 0;\n+\tint ipm;\n+\n+\tfor (ipm = 0; ipm \u003c dev-\u003einfo-\u003enum_ipms; ipm++) {\n+\t\tint queue;\n+\n+\t\t/* Traffic Type (TT) is corresponding to the Internal Priority\n+\t\t * Map (IPM) in the switch. Traffic Class (TC) is\n+\t\t * corresponding to the queue in the switch.\n+\t\t */\n+\t\tqueue = ieee8021q_tt_to_tc(ipm, dev-\u003einfo-\u003enum_tx_queues);\n+\t\tif (queue \u003c 0)\n+\t\t\treturn queue;\n+\n+\t\tqueue_map |= queue \u003c\u003c (ipm * KSZ9477_PORT_TC_MAP_S);\n+\t}\n+\n+\treturn ksz_pwrite32(dev, port, KSZ9477_PORT_MRI_TC_MAP__4, queue_map);\n+}\n+\n static int ksz9477_dsa_port_setup(struct dsa_switch *ds, int port)\n {\n \tstruct ksz_device *dev = ds-\u003epriv;\n@@ -1517,6 +1615,58 @@ int ksz9477_enable_stp_addr(struct ksz_device *dev)\n \treturn 0;\n }\n \n+/**\n+ * ksz9477_parse_drive_strength() - Extract and apply drive strength\n+ *\t\t\t\t    configurations from device tree properties.\n+ * @dev:\tksz device\n+ *\n+ * This function reads the specified drive strength properties from the\n+ * device tree, validates against the supported chip variants, and sets\n+ * them accordingly. An error should be critical here, as the drive strength\n+ * settings are crucial for EMI compliance.\n+ *\n+ * Return: 0 on success, error code otherwise\n+ */\n+static int ksz9477_parse_drive_strength(struct ksz_device *dev)\n+{\n+\tstruct ksz_driver_strength_prop of_props[] = {\n+\t\t[KSZ_DRIVER_STRENGTH_HI] = {\n+\t\t\t.name = \"microchip,hi-drive-strength-microamp\",\n+\t\t\t.offset = SW_HI_SPEED_DRIVE_STRENGTH_S,\n+\t\t\t.value = -1,\n+\t\t},\n+\t\t[KSZ_DRIVER_STRENGTH_LO] = {\n+\t\t\t.name = \"microchip,lo-drive-strength-microamp\",\n+\t\t\t.offset = SW_LO_SPEED_DRIVE_STRENGTH_S,\n+\t\t\t.value = -1,\n+\t\t},\n+\t\t[KSZ_DRIVER_STRENGTH_IO] = {\n+\t\t\t.name = \"microchip,io-drive-strength-microamp\",\n+\t\t\t.offset = 0, /* don't care */\n+\t\t\t.value = -1,\n+\t\t},\n+\t};\n+\tstruct device_node *np = dev-\u003edev-\u003eof_node;\n+\tbool have_any_prop = false;\n+\tint i, ret;\n+\n+\tfor (i = 0; i \u003c ARRAY_SIZE(of_props); i++) {\n+\t\tret = of_property_read_u32(np, of_props[i].name,\n+\t\t\t\t\t   \u0026of_props[i].value);\n+\t\tif (ret \u0026\u0026 ret != -EINVAL)\n+\t\t\tdev_warn(dev-\u003edev, \"Failed to read %s\\n\",\n+\t\t\t\t of_props[i].name);\n+\t\tif (ret)\n+\t\t\tcontinue;\n+\n+\t\thave_any_prop = true;\n+\t}\n+\n+\tif (!have_any_prop)\n+\t\treturn 0;\n+\n+\treturn ksz_drive_strength_write(dev, of_props, ARRAY_SIZE(of_props));\n+}\n static int ksz9477_setup(struct dsa_switch *ds)\n {\n \tstruct ksz_device *dev = ds-\u003epriv;\n@@ -1539,7 +1689,7 @@ static int ksz9477_setup(struct dsa_switch *ds)\n \t\treturn ret;\n \t}\n \n-\tret = ksz_parse_drive_strength(dev);\n+\tret = ksz9477_parse_drive_strength(dev);\n \tif (ret)\n \t\treturn ret;\n \n@@ -2052,7 +2202,7 @@ const struct ksz_dev_ops ksz9477_dev_ops = {\n \t.cfg_port_member = ksz9477_cfg_port_member,\n \t.r_mib_cnt = ksz9477_r_mib_cnt,\n \t.r_mib_pkt = ksz9477_r_mib_pkt,\n-\t.r_mib_stat64 = ksz_r_mib_stats64,\n+\t.r_mib_stat64 = ksz9477_r_mib_stats64,\n \t.freeze_mib = ksz9477_freeze_mib,\n \t.port_init_cnt = ksz9477_port_init_cnt,\n \t.pme_write8 = ksz_write8,\n@@ -2098,7 +2248,7 @@ const struct dsa_switch_ops ksz9477_switch_ops = {\n \t.get_stats64\t\t= ksz_get_stats64,\n \t.get_pause_stats\t= ksz_get_pause_stats,\n \t.port_change_mtu\t= ksz9477_change_mtu,\n-\t.port_max_mtu\t\t= ksz_max_mtu,\n+\t.port_max_mtu\t\t= ksz9477_max_mtu,\n \t.get_wol\t\t= ksz_get_wol,\n \t.set_wol\t\t= ksz_set_wol,\n \t.suspend\t\t= ksz_suspend,\ndiff --git a/drivers/net/dsa/microchip/ksz9477.h b/drivers/net/dsa/microchip/ksz9477.h\nindex 92a1d889224d3e..a84c000000e66e 100644\n--- a/drivers/net/dsa/microchip/ksz9477.h\n+++ b/drivers/net/dsa/microchip/ksz9477.h\n@@ -21,6 +21,7 @@ void ksz9477_freeze_mib(struct ksz_device *dev, int port, bool freeze);\n void ksz9477_port_init_cnt(struct ksz_device *dev, int port);\n int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port,\n \t\t\t\tbool flag, struct netlink_ext_ack *extack);\n+int ksz9477_max_mtu(struct dsa_switch *ds, int port);\n int ksz9477_port_vlan_add(struct dsa_switch *ds, int port,\n \t\t\t  const struct switchdev_obj_port_vlan *vlan,\n \t\t\t  struct netlink_ext_ack *extack);\n@@ -31,8 +32,6 @@ int ksz9477_port_mirror_add(struct dsa_switch *ds, int port,\n \t\t\t    bool ingress, struct netlink_ext_ack *extack);\n void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,\n \t\t\t     struct dsa_mall_mirror_tc_entry *mirror);\n-int ksz9477_errata_monitor(struct ksz_device *dev, int port,\n-\t\t\t   u64 tx_late_col);\n int ksz9477_fdb_dump(struct dsa_switch *ds, int port,\n \t\t     dsa_fdb_dump_cb_t *cb, void *data);\n int ksz9477_fdb_add(struct dsa_switch *ds, int port,\n@@ -45,6 +44,7 @@ int ksz9477_mdb_del(struct dsa_switch *ds, int port,\n \t\t    const struct switchdev_obj_port_mdb *mdb, struct dsa_db db);\n int ksz9477_enable_stp_addr(struct ksz_device *dev);\n void ksz9477_port_queue_split(struct ksz_device *dev, int port);\n+int ksz9477_set_default_prio_queue_mapping(struct ksz_device *dev, int port);\n \n int ksz9477_port_acl_init(struct ksz_device *dev, int port);\n void ksz9477_port_acl_free(struct ksz_device *dev, int port);\ndiff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c\nindex d1726778bb488e..67ab6ddb9e53f2 100644\n--- a/drivers/net/dsa/microchip/ksz_common.c\n+++ b/drivers/net/dsa/microchip/ksz_common.c\n@@ -37,82 +37,6 @@\n \n #define MIB_COUNTER_NUM 0x20\n \n-struct ksz_stats_raw {\n-\tu64 rx_hi;\n-\tu64 rx_undersize;\n-\tu64 rx_fragments;\n-\tu64 rx_oversize;\n-\tu64 rx_jabbers;\n-\tu64 rx_symbol_err;\n-\tu64 rx_crc_err;\n-\tu64 rx_align_err;\n-\tu64 rx_mac_ctrl;\n-\tu64 rx_pause;\n-\tu64 rx_bcast;\n-\tu64 rx_mcast;\n-\tu64 rx_ucast;\n-\tu64 rx_64_or_less;\n-\tu64 rx_65_127;\n-\tu64 rx_128_255;\n-\tu64 rx_256_511;\n-\tu64 rx_512_1023;\n-\tu64 rx_1024_1522;\n-\tu64 rx_1523_2000;\n-\tu64 rx_2001;\n-\tu64 tx_hi;\n-\tu64 tx_late_col;\n-\tu64 tx_pause;\n-\tu64 tx_bcast;\n-\tu64 tx_mcast;\n-\tu64 tx_ucast;\n-\tu64 tx_deferred;\n-\tu64 tx_total_col;\n-\tu64 tx_exc_col;\n-\tu64 tx_single_col;\n-\tu64 tx_mult_col;\n-\tu64 rx_total;\n-\tu64 tx_total;\n-\tu64 rx_discards;\n-\tu64 tx_discards;\n-};\n-\n-struct ksz88xx_stats_raw {\n-\tu64 rx;\n-\tu64 rx_hi;\n-\tu64 rx_undersize;\n-\tu64 rx_fragments;\n-\tu64 rx_oversize;\n-\tu64 rx_jabbers;\n-\tu64 rx_symbol_err;\n-\tu64 rx_crc_err;\n-\tu64 rx_align_err;\n-\tu64 rx_mac_ctrl;\n-\tu64 rx_pause;\n-\tu64 rx_bcast;\n-\tu64 rx_mcast;\n-\tu64 rx_ucast;\n-\tu64 rx_64_or_less;\n-\tu64 rx_65_127;\n-\tu64 rx_128_255;\n-\tu64 rx_256_511;\n-\tu64 rx_512_1023;\n-\tu64 rx_1024_1522;\n-\tu64 tx;\n-\tu64 tx_hi;\n-\tu64 tx_late_col;\n-\tu64 tx_pause;\n-\tu64 tx_bcast;\n-\tu64 tx_mcast;\n-\tu64 tx_ucast;\n-\tu64 tx_deferred;\n-\tu64 tx_total_col;\n-\tu64 tx_exc_col;\n-\tu64 tx_single_col;\n-\tu64 tx_mult_col;\n-\tu64 rx_discards;\n-\tu64 tx_discards;\n-};\n-\n static const struct ksz_mib_names ksz88xx_mib_names[] = {\n \t{ 0x00, \"rx\" },\n \t{ 0x01, \"rx_hi\" },\n@@ -189,28 +113,6 @@ static const struct ksz_mib_names ksz9477_mib_names[] = {\n \t{ 0x83, \"tx_discards\" },\n };\n \n-struct ksz_driver_strength_prop {\n-\tconst char *name;\n-\tint offset;\n-\tint value;\n-};\n-\n-enum ksz_driver_strength_type {\n-\tKSZ_DRIVER_STRENGTH_HI,\n-\tKSZ_DRIVER_STRENGTH_LO,\n-\tKSZ_DRIVER_STRENGTH_IO,\n-};\n-\n-/**\n- * struct ksz_drive_strength - drive strength mapping\n- * @reg_val:\tregister value\n- * @microamp:\tmicroamp value\n- */\n-struct ksz_drive_strength {\n-\tu32 reg_val;\n-\tu32 microamp;\n-};\n-\n /* ksz9477_drive_strengths - Drive strength mapping for KSZ9477 variants\n  *\n  * This values are not documented in KSZ9477 variants but confirmed by\n@@ -246,15 +148,6 @@ static const struct ksz_drive_strength ksz9477_drive_strengths[] = {\n \t{ SW_DRIVE_STRENGTH_28MA, 28000 },\n };\n \n-/* ksz88x3_drive_strengths - Drive strength mapping for KSZ8863, KSZ8873, ..\n- *\t\t\t     variants.\n- * This values are documented in KSZ8873 and KSZ8863 datasheets.\n- */\n-static const struct ksz_drive_strength ksz88x3_drive_strengths[] = {\n-\t{ 0,  8000 },\n-\t{ KSZ8873_DRIVE_STRENGTH_16MA, 16000 },\n-};\n-\n /**\n  * ksz_phylink_mac_disable_tx_lpi() - Callback to signal LPI support (Dummy)\n  * @config: phylink config structure\n@@ -2013,7 +1906,6 @@ void ksz_r_mib_stats64(struct ksz_device *dev, int port)\n \tstruct rtnl_link_stats64 *stats;\n \tstruct ksz_stats_raw *raw;\n \tstruct ksz_port_mib *mib;\n-\tint ret;\n \n \tmib = \u0026dev-\u003eports[port].mib;\n \tstats = \u0026mib-\u003estats64;\n@@ -2055,61 +1947,6 @@ void ksz_r_mib_stats64(struct ksz_device *dev, int port)\n \tpstats-\u003erx_pause_frames = raw-\u003erx_pause;\n \n \tspin_unlock(\u0026mib-\u003estats64_lock);\n-\n-\tif (dev-\u003einfo-\u003ephy_errata_9477 \u0026\u0026 !ksz_is_sgmii_port(dev, port)) {\n-\t\tret = ksz9477_errata_monitor(dev, port, raw-\u003etx_late_col);\n-\t\tif (ret)\n-\t\t\tdev_err(dev-\u003edev, \"Failed to monitor transmission halt\\n\");\n-\t}\n-}\n-\n-void ksz88xx_r_mib_stats64(struct ksz_device *dev, int port)\n-{\n-\tstruct ethtool_pause_stats *pstats;\n-\tstruct rtnl_link_stats64 *stats;\n-\tstruct ksz88xx_stats_raw *raw;\n-\tstruct ksz_port_mib *mib;\n-\n-\tmib = \u0026dev-\u003eports[port].mib;\n-\tstats = \u0026mib-\u003estats64;\n-\tpstats = \u0026mib-\u003epause_stats;\n-\traw = (struct ksz88xx_stats_raw *)mib-\u003ecounters;\n-\n-\tspin_lock(\u0026mib-\u003estats64_lock);\n-\n-\tstats-\u003erx_packets = raw-\u003erx_bcast + raw-\u003erx_mcast + raw-\u003erx_ucast +\n-\t\traw-\u003erx_pause;\n-\tstats-\u003etx_packets = raw-\u003etx_bcast + raw-\u003etx_mcast + raw-\u003etx_ucast +\n-\t\traw-\u003etx_pause;\n-\n-\t/* HW counters are counting bytes + FCS which is not acceptable\n-\t * for rtnl_link_stats64 interface\n-\t */\n-\tstats-\u003erx_bytes = raw-\u003erx + raw-\u003erx_hi - stats-\u003erx_packets * ETH_FCS_LEN;\n-\tstats-\u003etx_bytes = raw-\u003etx + raw-\u003etx_hi - stats-\u003etx_packets * ETH_FCS_LEN;\n-\n-\tstats-\u003erx_length_errors = raw-\u003erx_undersize + raw-\u003erx_fragments +\n-\t\traw-\u003erx_oversize;\n-\n-\tstats-\u003erx_crc_errors = raw-\u003erx_crc_err;\n-\tstats-\u003erx_frame_errors = raw-\u003erx_align_err;\n-\tstats-\u003erx_dropped = raw-\u003erx_discards;\n-\tstats-\u003erx_errors = stats-\u003erx_length_errors + stats-\u003erx_crc_errors +\n-\t\tstats-\u003erx_frame_errors  + stats-\u003erx_dropped;\n-\n-\tstats-\u003etx_window_errors = raw-\u003etx_late_col;\n-\tstats-\u003etx_fifo_errors = raw-\u003etx_discards;\n-\tstats-\u003etx_aborted_errors = raw-\u003etx_exc_col;\n-\tstats-\u003etx_errors = stats-\u003etx_window_errors + stats-\u003etx_fifo_errors +\n-\t\tstats-\u003etx_aborted_errors;\n-\n-\tstats-\u003emulticast = raw-\u003erx_mcast;\n-\tstats-\u003ecollisions = raw-\u003etx_total_col;\n-\n-\tpstats-\u003etx_pause_frames = raw-\u003etx_pause;\n-\tpstats-\u003erx_pause_frames = raw-\u003erx_pause;\n-\n-\tspin_unlock(\u0026mib-\u003estats64_lock);\n }\n \n void ksz_get_stats64(struct dsa_switch *ds, int port,\n@@ -2885,28 +2722,6 @@ void ksz_port_bridge_leave(struct dsa_switch *ds, int port,\n \t */\n }\n \n-int ksz9477_set_default_prio_queue_mapping(struct ksz_device *dev, int port)\n-{\n-\tu32 queue_map = 0;\n-\tint ipm;\n-\n-\tfor (ipm = 0; ipm \u003c dev-\u003einfo-\u003enum_ipms; ipm++) {\n-\t\tint queue;\n-\n-\t\t/* Traffic Type (TT) is corresponding to the Internal Priority\n-\t\t * Map (IPM) in the switch. Traffic Class (TC) is\n-\t\t * corresponding to the queue in the switch.\n-\t\t */\n-\t\tqueue = ieee8021q_tt_to_tc(ipm, dev-\u003einfo-\u003enum_tx_queues);\n-\t\tif (queue \u003c 0)\n-\t\t\treturn queue;\n-\n-\t\tqueue_map |= queue \u003c\u003c (ipm * KSZ9477_PORT_TC_MAP_S);\n-\t}\n-\n-\treturn ksz_pwrite32(dev, port, KSZ9477_PORT_MRI_TC_MAP__4, queue_map);\n-}\n-\n void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)\n {\n \tstruct ksz_device *dev = ds-\u003epriv;\n@@ -2984,40 +2799,6 @@ int ksz_port_bridge_flags(struct dsa_switch *ds, int port,\n \treturn 0;\n }\n \n-int ksz_max_mtu(struct dsa_switch *ds, int port)\n-{\n-\tstruct ksz_device *dev = ds-\u003epriv;\n-\n-\tswitch (dev-\u003echip_id) {\n-\tcase KSZ8795_CHIP_ID:\n-\tcase KSZ8794_CHIP_ID:\n-\tcase KSZ8765_CHIP_ID:\n-\t\treturn KSZ8795_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;\n-\tcase KSZ8463_CHIP_ID:\n-\tcase KSZ88X3_CHIP_ID:\n-\tcase KSZ8864_CHIP_ID:\n-\tcase KSZ8895_CHIP_ID:\n-\t\treturn KSZ8863_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;\n-\tcase KSZ8563_CHIP_ID:\n-\tcase KSZ8567_CHIP_ID:\n-\tcase KSZ9477_CHIP_ID:\n-\tcase KSZ9563_CHIP_ID:\n-\tcase KSZ9567_CHIP_ID:\n-\tcase KSZ9893_CHIP_ID:\n-\tcase KSZ9896_CHIP_ID:\n-\tcase KSZ9897_CHIP_ID:\n-\tcase LAN9370_CHIP_ID:\n-\tcase LAN9371_CHIP_ID:\n-\tcase LAN9372_CHIP_ID:\n-\tcase LAN9373_CHIP_ID:\n-\tcase LAN9374_CHIP_ID:\n-\tcase LAN9646_CHIP_ID:\n-\t\treturn KSZ9477_MAX_FRAME_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;\n-\t}\n-\n-\treturn -EOPNOTSUPP;\n-}\n-\n int ksz_set_mac_eee(struct dsa_switch *ds, int port,\n \t\t    struct ethtool_keee *e)\n {\n@@ -3086,39 +2867,6 @@ void ksz_set_xmii(struct ksz_device *dev, int port, phy_interface_t interface)\n \tksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8);\n }\n \n-phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit)\n-{\n-\tconst u8 *bitval = dev-\u003einfo-\u003exmii_ctrl1;\n-\tconst u16 *regs = dev-\u003einfo-\u003eregs;\n-\tphy_interface_t interface;\n-\tu8 data8;\n-\tu8 val;\n-\n-\tksz_pread8(dev, port, regs[P_XMII_CTRL_1], \u0026data8);\n-\n-\tval = FIELD_GET(P_MII_SEL_M, data8);\n-\n-\tif (val == bitval[P_MII_SEL]) {\n-\t\tif (gbit)\n-\t\t\tinterface = PHY_INTERFACE_MODE_GMII;\n-\t\telse\n-\t\t\tinterface = PHY_INTERFACE_MODE_MII;\n-\t} else if (val == bitval[P_RMII_SEL]) {\n-\t\tinterface = PHY_INTERFACE_MODE_RMII;\n-\t} else {\n-\t\tinterface = PHY_INTERFACE_MODE_RGMII;\n-\t\tif (data8 \u0026 P_RGMII_ID_EG_ENABLE)\n-\t\t\tinterface = PHY_INTERFACE_MODE_RGMII_TXID;\n-\t\tif (data8 \u0026 P_RGMII_ID_IG_ENABLE) {\n-\t\t\tinterface = PHY_INTERFACE_MODE_RGMII_RXID;\n-\t\t\tif (data8 \u0026 P_RGMII_ID_EG_ENABLE)\n-\t\t\t\tinterface = PHY_INTERFACE_MODE_RGMII_ID;\n-\t\t}\n-\t}\n-\n-\treturn interface;\n-}\n-\n bool ksz_phylink_need_config(struct phylink_config *config,\n \t\t\t     unsigned int mode)\n {\n@@ -3154,24 +2902,6 @@ void ksz_phylink_mac_config(struct phylink_config *config,\n \t\tksz_set_xmii(dev, port, state-\u003einterface);\n }\n \n-bool ksz_get_gbit(struct ksz_device *dev, int port)\n-{\n-\tconst u8 *bitval = dev-\u003einfo-\u003exmii_ctrl1;\n-\tconst u16 *regs = dev-\u003einfo-\u003eregs;\n-\tbool gbit = false;\n-\tu8 data8;\n-\tbool val;\n-\n-\tksz_pread8(dev, port, regs[P_XMII_CTRL_1], \u0026data8);\n-\n-\tval = FIELD_GET(P_GMII_1GBIT_M, data8);\n-\n-\tif (val == bitval[P_GMII_1GBIT])\n-\t\tgbit = true;\n-\n-\treturn gbit;\n-}\n-\n static int ksz_switch_detect(struct ksz_device *dev)\n {\n \tu8 id1, id2, id4;\n@@ -3314,8 +3044,8 @@ static int ksz_setup_tc_mode(struct ksz_device *dev, int port, u8 scheduler,\n \t\t\t   FIELD_PREP(MTI_SHAPING_M, shaper));\n }\n \n-static int ksz_setup_tc_cbs(struct dsa_switch *ds, int port,\n-\t\t\t    struct tc_cbs_qopt_offload *qopt)\n+int ksz_setup_tc_cbs(struct dsa_switch *ds, int port,\n+\t\t     struct tc_cbs_qopt_offload *qopt)\n {\n \tstruct ksz_device *dev = ds-\u003epriv;\n \tint ret;\n@@ -3380,8 +3110,8 @@ static int ksz_disable_egress_rate_limit(struct ksz_device *dev, int port)\n \treturn 0;\n }\n \n-static int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,\n-\t\t\t\t int band)\n+int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,\n+\t\t\t  int band)\n {\n \t/* Compared to queues, bands prioritize packets differently. In strict\n \t * priority mode, the lowest priority is assigned to Queue 0 while the\n@@ -3390,104 +3120,6 @@ static int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,\n \treturn p-\u003ebands - 1 - band;\n }\n \n-static u8 ksz8463_tc_ctrl(int port, int queue)\n-{\n-\tu8 reg;\n-\n-\treg = 0xC8 + port * 4;\n-\treg += ((3 - queue) / 2) * 2;\n-\treg++;\n-\treg -= (queue \u0026 1);\n-\treturn reg;\n-}\n-\n-/**\n- * ksz88x3_tc_ets_add - Configure ETS (Enhanced Transmission Selection)\n- *                      for a port on KSZ88x3 switch\n- * @dev: Pointer to the KSZ switch device structure\n- * @port: Port number to configure\n- * @p: Pointer to offload replace parameters describing ETS bands and mapping\n- *\n- * The KSZ88x3 supports two scheduling modes: Strict Priority and\n- * Weighted Fair Queuing (WFQ). Both modes have fixed behavior:\n- *   - No configurable queue-to-priority mapping\n- *   - No weight adjustment in WFQ mode\n- *\n- * This function configures the switch to use strict priority mode by\n- * clearing the WFQ enable bit for all queues associated with ETS bands.\n- * If strict priority is not explicitly requested, the switch will default\n- * to WFQ mode.\n- *\n- * Return: 0 on success, or a negative error code on failure\n- */\n-static int ksz88x3_tc_ets_add(struct ksz_device *dev, int port,\n-\t\t\t      struct tc_ets_qopt_offload_replace_params *p)\n-{\n-\tint ret, band;\n-\n-\t/* Only strict priority mode is supported for now.\n-\t * WFQ is implicitly enabled when strict mode is disabled.\n-\t */\n-\tfor (band = 0; band \u003c p-\u003ebands; band++) {\n-\t\tint queue = ksz_ets_band_to_queue(p, band);\n-\t\tu8 reg;\n-\n-\t\t/* Calculate TXQ Split Control register address for this\n-\t\t * port/queue\n-\t\t */\n-\t\treg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);\n-\t\tif (ksz_is_ksz8463(dev))\n-\t\t\treg = ksz8463_tc_ctrl(port, queue);\n-\n-\t\t/* Clear WFQ enable bit to select strict priority scheduling */\n-\t\tret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE, 0);\n-\t\tif (ret)\n-\t\t\treturn ret;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/**\n- * ksz88x3_tc_ets_del - Reset ETS (Enhanced Transmission Selection) config\n- *                      for a port on KSZ88x3 switch\n- * @dev: Pointer to the KSZ switch device structure\n- * @port: Port number to reset\n- *\n- * The KSZ88x3 supports only fixed scheduling modes: Strict Priority or\n- * Weighted Fair Queuing (WFQ), with no reconfiguration of weights or\n- * queue mapping. This function resets the port’s scheduling mode to\n- * the default, which is WFQ, by enabling the WFQ bit for all queues.\n- *\n- * Return: 0 on success, or a negative error code on failure\n- */\n-static int ksz88x3_tc_ets_del(struct ksz_device *dev, int port)\n-{\n-\tint ret, queue;\n-\n-\t/* Iterate over all transmit queues for this port */\n-\tfor (queue = 0; queue \u003c dev-\u003einfo-\u003enum_tx_queues; queue++) {\n-\t\tu8 reg;\n-\n-\t\t/* Calculate TXQ Split Control register address for this\n-\t\t * port/queue\n-\t\t */\n-\t\treg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);\n-\t\tif (ksz_is_ksz8463(dev))\n-\t\t\treg = ksz8463_tc_ctrl(port, queue);\n-\n-\t\t/* Set WFQ enable bit to revert back to default scheduling\n-\t\t * mode\n-\t\t */\n-\t\tret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE,\n-\t\t\t       KSZ8873_TXQ_WFQ_ENABLE);\n-\t\tif (ret)\n-\t\t\treturn ret;\n-\t}\n-\n-\treturn 0;\n-}\n-\n static int ksz_queue_set_strict(struct ksz_device *dev, int port, int queue)\n {\n \tint ret;\n@@ -3580,8 +3212,8 @@ static int ksz_tc_ets_del(struct ksz_device *dev, int port)\n \treturn ksz9477_set_default_prio_queue_mapping(dev, port);\n }\n \n-static int ksz_tc_ets_validate(struct ksz_device *dev, int port,\n-\t\t\t       struct tc_ets_qopt_offload_replace_params *p)\n+int ksz_tc_ets_validate(struct ksz_device *dev, int port,\n+\t\t\tstruct tc_ets_qopt_offload_replace_params *p)\n {\n \tint band;\n \n@@ -3622,9 +3254,6 @@ static int ksz_tc_setup_qdisc_ets(struct dsa_switch *ds, int port,\n \tstruct ksz_device *dev = ds-\u003epriv;\n \tint ret;\n \n-\tif (is_ksz8(dev) \u0026\u0026 !(ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)))\n-\t\treturn -EOPNOTSUPP;\n-\n \tif (qopt-\u003eparent != TC_H_ROOT) {\n \t\tdev_err(dev-\u003edev, \"Parent should be \\\"root\\\"\\n\");\n \t\treturn -EOPNOTSUPP;\n@@ -3636,16 +3265,9 @@ static int ksz_tc_setup_qdisc_ets(struct dsa_switch *ds, int port,\n \t\tif (ret)\n \t\t\treturn ret;\n \n-\t\tif (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev))\n-\t\t\treturn ksz88x3_tc_ets_add(dev, port,\n-\t\t\t\t\t\t  \u0026qopt-\u003ereplace_params);\n-\t\telse\n-\t\t\treturn ksz_tc_ets_add(dev, port, \u0026qopt-\u003ereplace_params);\n+\t\treturn ksz_tc_ets_add(dev, port, \u0026qopt-\u003ereplace_params);\n \tcase TC_ETS_DESTROY:\n-\t\tif (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev))\n-\t\t\treturn ksz88x3_tc_ets_del(dev, port);\n-\t\telse\n-\t\t\treturn ksz_tc_ets_del(dev, port);\n+\t\treturn ksz_tc_ets_del(dev, port);\n \tcase TC_ETS_STATS:\n \tcase TC_ETS_GRAFT:\n \t\treturn -EOPNOTSUPP;\n@@ -3704,6 +3326,34 @@ int ksz_handle_wake_reason(struct ksz_device *dev, int port)\n \t\t\t\tpme_status);\n }\n \n+/**\n+ * ksz_is_port_mac_global_usable - Check if the MAC address on a given port\n+ *                                 can be used as a global address.\n+ * @ds: Pointer to the DSA switch structure.\n+ * @port: The port number on which the MAC address is to be checked.\n+ *\n+ * This function examines the MAC address set on the specified port and\n+ * determines if it can be used as a global address for the switch.\n+ *\n+ * Return: true if the port's MAC address can be used as a global address, false\n+ * otherwise.\n+ */\n+static bool ksz_is_port_mac_global_usable(struct dsa_switch *ds, int port)\n+{\n+\tstruct net_device *user = dsa_to_port(ds, port)-\u003euser;\n+\tconst unsigned char *addr = user-\u003edev_addr;\n+\tstruct ksz_switch_macaddr *switch_macaddr;\n+\tstruct ksz_device *dev = ds-\u003epriv;\n+\n+\tASSERT_RTNL();\n+\n+\tswitch_macaddr = dev-\u003eswitch_macaddr;\n+\tif (switch_macaddr \u0026\u0026 !ether_addr_equal(switch_macaddr-\u003eaddr, addr))\n+\t\treturn false;\n+\n+\treturn true;\n+}\n+\n /**\n  * ksz_get_wol - Get Wake-on-LAN settings for a specified port.\n  * @ds: The dsa_switch structure.\n@@ -3897,34 +3547,6 @@ int ksz_port_set_mac_address(struct dsa_switch *ds, int port,\n \treturn 0;\n }\n \n-/**\n- * ksz_is_port_mac_global_usable - Check if the MAC address on a given port\n- *                                 can be used as a global address.\n- * @ds: Pointer to the DSA switch structure.\n- * @port: The port number on which the MAC address is to be checked.\n- *\n- * This function examines the MAC address set on the specified port and\n- * determines if it can be used as a global address for the switch.\n- *\n- * Return: true if the port's MAC address can be used as a global address, false\n- * otherwise.\n- */\n-bool ksz_is_port_mac_global_usable(struct dsa_switch *ds, int port)\n-{\n-\tstruct net_device *user = dsa_to_port(ds, port)-\u003euser;\n-\tconst unsigned char *addr = user-\u003edev_addr;\n-\tstruct ksz_switch_macaddr *switch_macaddr;\n-\tstruct ksz_device *dev = ds-\u003epriv;\n-\n-\tASSERT_RTNL();\n-\n-\tswitch_macaddr = dev-\u003eswitch_macaddr;\n-\tif (switch_macaddr \u0026\u0026 !ether_addr_equal(switch_macaddr-\u003eaddr, addr))\n-\t\treturn false;\n-\n-\treturn true;\n-}\n-\n /**\n  * ksz_switch_macaddr_get - Program the switch's MAC address register.\n  * @ds: DSA switch instance.\n@@ -4132,8 +3754,8 @@ static void ksz_parse_rgmii_delay(struct ksz_device *dev, int port_num,\n  * Returns: If found, the corresponding register value for that drive strength\n  * is returned. Otherwise, -EINVAL is returned indicating an invalid value.\n  */\n-static int ksz_drive_strength_to_reg(const struct ksz_drive_strength *array,\n-\t\t\t\t     size_t array_size, int microamp)\n+int ksz_drive_strength_to_reg(const struct ksz_drive_strength *array,\n+\t\t\t      size_t array_size, int microamp)\n {\n \tint i;\n \n@@ -4156,9 +3778,9 @@ static int ksz_drive_strength_to_reg(const struct ksz_drive_strength *array,\n  * is detected. It lists out all the supported drive strength values for\n  * reference in the error message.\n  */\n-static void ksz_drive_strength_error(struct ksz_device *dev,\n-\t\t\t\t     const struct ksz_drive_strength *array,\n-\t\t\t\t     size_t array_size, int microamp)\n+void ksz_drive_strength_error(struct ksz_device *dev,\n+\t\t\t      const struct ksz_drive_strength *array,\n+\t\t\t      size_t array_size, int microamp)\n {\n \tchar supported_values[100];\n \tsize_t remaining_size;\n@@ -4185,8 +3807,8 @@ static void ksz_drive_strength_error(struct ksz_device *dev,\n }\n \n /**\n- * ksz9477_drive_strength_write() - Set the drive strength for specific KSZ9477\n- *\t\t\t\t    chip variants.\n+ * ksz_drive_strength_write() - Set the drive strength for specific KSZ9477\n+ *\t\t\t\tand the KSZ87xx chip variants.\n  * @dev:       ksz device\n  * @props:     Array of drive strength properties to be applied\n  * @num_props: Number of properties in the array\n@@ -4197,9 +3819,9 @@ static void ksz_drive_strength_error(struct ksz_device *dev,\n  *\n  * Return: 0 on successful configuration, a negative error code on failure.\n  */\n-static int ksz9477_drive_strength_write(struct ksz_device *dev,\n-\t\t\t\t\tstruct ksz_driver_strength_prop *props,\n-\t\t\t\t\tint num_props)\n+int ksz_drive_strength_write(struct ksz_device *dev,\n+\t\t\t     struct ksz_driver_strength_prop *props,\n+\t\t\t     int num_props)\n {\n \tsize_t array_size = ARRAY_SIZE(ksz9477_drive_strengths);\n \tint i, ret, reg;\n@@ -4236,130 +3858,6 @@ static int ksz9477_drive_strength_write(struct ksz_device *dev,\n \treturn ksz_rmw8(dev, reg, mask, val);\n }\n \n-/**\n- * ksz88x3_drive_strength_write() - Set the drive strength configuration for\n- *\t\t\t\t    KSZ8863 compatible chip variants.\n- * @dev:       ksz device\n- * @props:     Array of drive strength properties to be set\n- * @num_props: Number of properties in the array\n- *\n- * This function applies the specified drive strength settings to KSZ88X3 chip\n- * variants (KSZ8873, KSZ8863).\n- * It ensures the configurations align with what the chip variant supports and\n- * warns or errors out on unsupported settings.\n- *\n- * Return: 0 on success, error code otherwise\n- */\n-static int ksz88x3_drive_strength_write(struct ksz_device *dev,\n-\t\t\t\t\tstruct ksz_driver_strength_prop *props,\n-\t\t\t\t\tint num_props)\n-{\n-\tsize_t array_size = ARRAY_SIZE(ksz88x3_drive_strengths);\n-\tint microamp;\n-\tint i, ret;\n-\n-\tfor (i = 0; i \u003c num_props; i++) {\n-\t\tif (props[i].value == -1 || i == KSZ_DRIVER_STRENGTH_IO)\n-\t\t\tcontinue;\n-\n-\t\tdev_warn(dev-\u003edev, \"%s is not supported by this chip variant\\n\",\n-\t\t\t props[i].name);\n-\t}\n-\n-\tmicroamp = props[KSZ_DRIVER_STRENGTH_IO].value;\n-\tret = ksz_drive_strength_to_reg(ksz88x3_drive_strengths, array_size,\n-\t\t\t\t\tmicroamp);\n-\tif (ret \u003c 0) {\n-\t\tksz_drive_strength_error(dev, ksz88x3_drive_strengths,\n-\t\t\t\t\t array_size, microamp);\n-\t\treturn ret;\n-\t}\n-\n-\treturn ksz_rmw8(dev, KSZ8873_REG_GLOBAL_CTRL_12,\n-\t\t\tKSZ8873_DRIVE_STRENGTH_16MA, ret);\n-}\n-\n-/**\n- * ksz_parse_drive_strength() - Extract and apply drive strength configurations\n- *\t\t\t\tfrom device tree properties.\n- * @dev:\tksz device\n- *\n- * This function reads the specified drive strength properties from the\n- * device tree, validates against the supported chip variants, and sets\n- * them accordingly. An error should be critical here, as the drive strength\n- * settings are crucial for EMI compliance.\n- *\n- * Return: 0 on success, error code otherwise\n- */\n-int ksz_parse_drive_strength(struct ksz_device *dev)\n-{\n-\tstruct ksz_driver_strength_prop of_props[] = {\n-\t\t[KSZ_DRIVER_STRENGTH_HI] = {\n-\t\t\t.name = \"microchip,hi-drive-strength-microamp\",\n-\t\t\t.offset = SW_HI_SPEED_DRIVE_STRENGTH_S,\n-\t\t\t.value = -1,\n-\t\t},\n-\t\t[KSZ_DRIVER_STRENGTH_LO] = {\n-\t\t\t.name = \"microchip,lo-drive-strength-microamp\",\n-\t\t\t.offset = SW_LO_SPEED_DRIVE_STRENGTH_S,\n-\t\t\t.value = -1,\n-\t\t},\n-\t\t[KSZ_DRIVER_STRENGTH_IO] = {\n-\t\t\t.name = \"microchip,io-drive-strength-microamp\",\n-\t\t\t.offset = 0, /* don't care */\n-\t\t\t.value = -1,\n-\t\t},\n-\t};\n-\tstruct device_node *np = dev-\u003edev-\u003eof_node;\n-\tbool have_any_prop = false;\n-\tint i, ret;\n-\n-\tfor (i = 0; i \u003c ARRAY_SIZE(of_props); i++) {\n-\t\tret = of_property_read_u32(np, of_props[i].name,\n-\t\t\t\t\t   \u0026of_props[i].value);\n-\t\tif (ret \u0026\u0026 ret != -EINVAL)\n-\t\t\tdev_warn(dev-\u003edev, \"Failed to read %s\\n\",\n-\t\t\t\t of_props[i].name);\n-\t\tif (ret)\n-\t\t\tcontinue;\n-\n-\t\thave_any_prop = true;\n-\t}\n-\n-\tif (!have_any_prop)\n-\t\treturn 0;\n-\n-\tswitch (dev-\u003echip_id) {\n-\tcase KSZ88X3_CHIP_ID:\n-\t\treturn ksz88x3_drive_strength_write(dev, of_props,\n-\t\t\t\t\t\t    ARRAY_SIZE(of_props));\n-\tcase KSZ8795_CHIP_ID:\n-\tcase KSZ8794_CHIP_ID:\n-\tcase KSZ8765_CHIP_ID:\n-\tcase KSZ8563_CHIP_ID:\n-\tcase KSZ8567_CHIP_ID:\n-\tcase KSZ9477_CHIP_ID:\n-\tcase KSZ9563_CHIP_ID:\n-\tcase KSZ9567_CHIP_ID:\n-\tcase KSZ9893_CHIP_ID:\n-\tcase KSZ9896_CHIP_ID:\n-\tcase KSZ9897_CHIP_ID:\n-\tcase LAN9646_CHIP_ID:\n-\t\treturn ksz9477_drive_strength_write(dev, of_props,\n-\t\t\t\t\t\t    ARRAY_SIZE(of_props));\n-\tdefault:\n-\t\tfor (i = 0; i \u003c ARRAY_SIZE(of_props); i++) {\n-\t\t\tif (of_props[i].value == -1)\n-\t\t\t\tcontinue;\n-\n-\t\t\tdev_warn(dev-\u003edev, \"%s is not supported by this chip variant\\n\",\n-\t\t\t\t of_props[i].name);\n-\t\t}\n-\t}\n-\n-\treturn 0;\n-}\n-\n static int ksz8463_configure_straps_spi(struct ksz_device *dev)\n {\n \tstruct pinctrl *pinctrl;\ndiff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h\nindex b4a5673ba365cb..acaf70e6f393c9 100644\n--- a/drivers/net/dsa/microchip/ksz_common.h\n+++ b/drivers/net/dsa/microchip/ksz_common.h\n@@ -14,6 +14,7 @@\n #include \u003clinux/phy.h\u003e\n #include \u003clinux/regmap.h\u003e\n #include \u003cnet/dsa.h\u003e\n+#include \u003cnet/pkt_cls.h\u003e\n #include \u003clinux/irq.h\u003e\n #include \u003clinux/platform_data/microchip-ksz.h\u003e\n \n@@ -40,6 +41,45 @@ struct vlan_table {\n \tu32 table[3];\n };\n \n+struct ksz_stats_raw {\n+\tu64 rx_hi;\n+\tu64 rx_undersize;\n+\tu64 rx_fragments;\n+\tu64 rx_oversize;\n+\tu64 rx_jabbers;\n+\tu64 rx_symbol_err;\n+\tu64 rx_crc_err;\n+\tu64 rx_align_err;\n+\tu64 rx_mac_ctrl;\n+\tu64 rx_pause;\n+\tu64 rx_bcast;\n+\tu64 rx_mcast;\n+\tu64 rx_ucast;\n+\tu64 rx_64_or_less;\n+\tu64 rx_65_127;\n+\tu64 rx_128_255;\n+\tu64 rx_256_511;\n+\tu64 rx_512_1023;\n+\tu64 rx_1024_1522;\n+\tu64 rx_1523_2000;\n+\tu64 rx_2001;\n+\tu64 tx_hi;\n+\tu64 tx_late_col;\n+\tu64 tx_pause;\n+\tu64 tx_bcast;\n+\tu64 tx_mcast;\n+\tu64 tx_ucast;\n+\tu64 tx_deferred;\n+\tu64 tx_total_col;\n+\tu64 tx_exc_col;\n+\tu64 tx_single_col;\n+\tu64 tx_mult_col;\n+\tu64 rx_total;\n+\tu64 tx_total;\n+\tu64 rx_discards;\n+\tu64 tx_discards;\n+};\n+\n struct ksz_port_mib {\n \tstruct mutex cnt_mutex;\t\t/* structure access */\n \tu8 cnt_ptr;\n@@ -393,12 +433,8 @@ int ksz_switch_resume(struct device *dev);\n void ksz_teardown(struct dsa_switch *ds);\n \n void ksz_init_mib_timer(struct ksz_device *dev);\n-bool ksz_is_port_mac_global_usable(struct dsa_switch *ds, int port);\n void ksz_r_mib_stats64(struct ksz_device *dev, int port);\n-void ksz88xx_r_mib_stats64(struct ksz_device *dev, int port);\n void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state);\n-bool ksz_get_gbit(struct ksz_device *dev, int port);\n-phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit);\n extern const struct ksz_chip_data ksz_switch_chips[];\n int ksz_switch_macaddr_get(struct dsa_switch *ds, int port,\n \t\t\t   struct netlink_ext_ack *extack);\n@@ -443,11 +479,15 @@ void ksz_phylink_mac_link_down(struct phylink_config *config,\n \t\t\t       unsigned int mode,\n \t\t\t       phy_interface_t interface);\n \n-int ksz_max_mtu(struct dsa_switch *ds, int port);\n-\n int ksz_set_mac_eee(struct dsa_switch *ds, int port,\n \t\t    struct ethtool_keee *e);\n \n+int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,\n+\t\t\t  int band);\n+int ksz_setup_tc_cbs(struct dsa_switch *ds, int port,\n+\t\t     struct tc_cbs_qopt_offload *qopt);\n+int ksz_tc_ets_validate(struct ksz_device *dev, int port,\n+\t\t\tstruct tc_ets_qopt_offload_replace_params *p);\n int ksz_setup_tc(struct dsa_switch *ds, int port,\n \t\t enum tc_setup_type type, void *type_data);\n \n@@ -471,8 +511,37 @@ int ksz_mdio_register(struct ksz_device *dev);\n int ksz_pirq_setup(struct ksz_device *dev, u8 p);\n int ksz_girq_setup(struct ksz_device *dev);\n void ksz_irq_free(struct ksz_irq *kirq);\n-int ksz_parse_drive_strength(struct ksz_device *dev);\n-int ksz9477_set_default_prio_queue_mapping(struct ksz_device *dev, int port);\n+\n+struct ksz_driver_strength_prop {\n+\tconst char *name;\n+\tint offset;\n+\tint value;\n+};\n+\n+enum ksz_driver_strength_type {\n+\tKSZ_DRIVER_STRENGTH_HI,\n+\tKSZ_DRIVER_STRENGTH_LO,\n+\tKSZ_DRIVER_STRENGTH_IO,\n+};\n+\n+/**\n+ * struct ksz_drive_strength - drive strength mapping\n+ * @reg_val:\tregister value\n+ * @microamp:\tmicroamp value\n+ */\n+struct ksz_drive_strength {\n+\tu32 reg_val;\n+\tu32 microamp;\n+};\n+\n+void ksz_drive_strength_error(struct ksz_device *dev,\n+\t\t\t      const struct ksz_drive_strength *array,\n+\t\t\t      size_t array_size, int microamp);\n+int ksz_drive_strength_to_reg(const struct ksz_drive_strength *array,\n+\t\t\t      size_t array_size, int microamp);\n+int ksz_drive_strength_write(struct ksz_device *dev,\n+\t\t\t     struct ksz_driver_strength_prop *props,\n+\t\t\t     int num_props);\n \n /* Common register access functions */\n static inline struct regmap *ksz_regmap_8(struct ksz_device *dev)\ndiff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c\nindex 8eb5337b0c102e..86ce3a86705f93 100644\n--- a/drivers/net/dsa/microchip/lan937x_main.c\n+++ b/drivers/net/dsa/microchip/lan937x_main.c\n@@ -787,10 +787,6 @@ static int lan937x_setup(struct dsa_switch *ds)\n \t\treturn ret;\n \t}\n \n-\tret = ksz_parse_drive_strength(dev);\n-\tif (ret)\n-\t\treturn ret;\n-\n \t/* set broadcast storm protection 10% rate */\n \tstorm_mask = BROADCAST_STORM_RATE;\n \tstorm_rate = (BROADCAST_STORM_VALUE * BROADCAST_STORM_PROT_RATE) / 100;\n@@ -983,7 +979,7 @@ const struct dsa_switch_ops lan937x_switch_ops = {\n \t.get_stats64\t\t= ksz_get_stats64,\n \t.get_pause_stats\t= ksz_get_pause_stats,\n \t.port_change_mtu\t= lan937x_change_mtu,\n-\t.port_max_mtu\t\t= ksz_max_mtu,\n+\t.port_max_mtu\t\t= ksz9477_max_mtu,\n \t.suspend\t\t= ksz_suspend,\n \t.resume\t\t\t= ksz_resume,\n \t.get_ts_info\t\t= ksz_get_ts_info,\n"
}

2/1 2026/07/02 13:56 agent patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch is a pure refactoring of the Microchip KSZ DSA driver. It moves chip-specific functions (like MTU configuration, TC setup, MIB stats reading, and drive strength parsing) from the common `ksz_common.c` file to their respective chip-specific files (`ksz8.c` and `ksz9477.c`). It also removes a no-op call to `ksz_parse_drive_strength` in `lan937x_main.c` which only printed warnings for unsupported properties. No new functional logic or reachable code paths are introduced.",
  "WorthFuzzing": false
}

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 d6edbbd8fab9105b1aba0f6f9417f5479476a79f
Author: syz-cluster <triage@syzkaller.com>
Date:   Thu Jul 2 13:56:25 2026 +0000

    syz-cluster: applied patch under review

diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index 586916570a841b..c4c769028a20c9 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -36,6 +36,52 @@
 #include "ksz8_reg.h"
 #include "ksz8.h"
 
+/* ksz88x3_drive_strengths - Drive strength mapping for KSZ8863, KSZ8873, ..
+ *			     variants.
+ * This values are documented in KSZ8873 and KSZ8863 datasheets.
+ */
+static const struct ksz_drive_strength ksz88x3_drive_strengths[] = {
+	{ 0,  8000 },
+	{ KSZ8873_DRIVE_STRENGTH_16MA, 16000 },
+};
+
+struct ksz88xx_stats_raw {
+	u64 rx;
+	u64 rx_hi;
+	u64 rx_undersize;
+	u64 rx_fragments;
+	u64 rx_oversize;
+	u64 rx_jabbers;
+	u64 rx_symbol_err;
+	u64 rx_crc_err;
+	u64 rx_align_err;
+	u64 rx_mac_ctrl;
+	u64 rx_pause;
+	u64 rx_bcast;
+	u64 rx_mcast;
+	u64 rx_ucast;
+	u64 rx_64_or_less;
+	u64 rx_65_127;
+	u64 rx_128_255;
+	u64 rx_256_511;
+	u64 rx_512_1023;
+	u64 rx_1024_1522;
+	u64 tx;
+	u64 tx_hi;
+	u64 tx_late_col;
+	u64 tx_pause;
+	u64 tx_bcast;
+	u64 tx_mcast;
+	u64 tx_ucast;
+	u64 tx_deferred;
+	u64 tx_total_col;
+	u64 tx_exc_col;
+	u64 tx_single_col;
+	u64 tx_mult_col;
+	u64 rx_discards;
+	u64 tx_discards;
+};
+
 static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
 {
 	ksz_rmw8(dev, addr, bits, set ? bits : 0);
@@ -158,10 +204,17 @@ static int ksz8_reset_switch(struct ksz_device *dev)
 	return 0;
 }
 
-static int ksz8863_change_mtu(struct ksz_device *dev, int frame_size)
+static int ksz88xx_change_mtu(struct dsa_switch *ds, int port, int mtu)
 {
+	struct ksz_device *dev = ds->priv;
+	int frame_size;
 	u8 ctrl2 = 0;
 
+	if (!dsa_is_cpu_port(dev->ds, port))
+		return 0;
+
+	frame_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
+
 	if (frame_size <= KSZ8_LEGAL_PACKET_SIZE)
 		ctrl2 |= KSZ8863_LEGAL_PACKET_ENABLE;
 	else if (frame_size > KSZ8863_NORMAL_PACKET_SIZE)
@@ -171,11 +224,18 @@ static int ksz8863_change_mtu(struct ksz_device *dev, int frame_size)
 			KSZ8863_HUGE_PACKET_ENABLE, ctrl2);
 }
 
-static int ksz8795_change_mtu(struct ksz_device *dev, int frame_size)
+static int ksz87xx_change_mtu(struct dsa_switch *ds, int port, int mtu)
 {
+	struct ksz_device *dev = ds->priv;
 	u8 ctrl1 = 0, ctrl2 = 0;
+	u16 frame_size;
 	int ret;
 
+	if (!dsa_is_cpu_port(dev->ds, port))
+		return 0;
+
+	frame_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
+
 	if (frame_size > KSZ8_LEGAL_PACKET_SIZE)
 		ctrl2 |= SW_LEGAL_PACKET_DISABLE;
 	if (frame_size > KSZ8863_NORMAL_PACKET_SIZE)
@@ -188,29 +248,14 @@ static int ksz8795_change_mtu(struct ksz_device *dev, int frame_size)
 	return ksz_rmw8(dev, REG_SW_CTRL_2, SW_LEGAL_PACKET_DISABLE, ctrl2);
 }
 
-static int ksz8_change_mtu(struct dsa_switch *ds, int port, int mtu)
+static int ksz87xx_max_mtu(struct dsa_switch *ds, int port)
 {
-	struct ksz_device *dev = ds->priv;
-	u16 frame_size;
-
-	if (!dsa_is_cpu_port(dev->ds, port))
-		return 0;
-
-	frame_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
-
-	switch (dev->chip_id) {
-	case KSZ8795_CHIP_ID:
-	case KSZ8794_CHIP_ID:
-	case KSZ8765_CHIP_ID:
-		return ksz8795_change_mtu(dev, frame_size);
-	case KSZ8463_CHIP_ID:
-	case KSZ88X3_CHIP_ID:
-	case KSZ8864_CHIP_ID:
-	case KSZ8895_CHIP_ID:
-		return ksz8863_change_mtu(dev, frame_size);
-	}
+	return KSZ8795_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;
+}
 
-	return -EOPNOTSUPP;
+static int ksz88xx_max_mtu(struct dsa_switch *ds, int port)
+{
+	return KSZ8863_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;
 }
 
 static int ksz8_port_queue_split(struct ksz_device *dev, int port, int queues)
@@ -1746,6 +1791,159 @@ static void ksz8_port_mirror_del(struct dsa_switch *ds, int port,
 			     PORT_MIRROR_SNIFFER, false);
 }
 
+static u8 ksz8463_tc_ctrl(int port, int queue)
+{
+	u8 reg;
+
+	reg = 0xC8 + port * 4;
+	reg += ((3 - queue) / 2) * 2;
+	reg++;
+	reg -= (queue & 1);
+	return reg;
+}
+
+/**
+ * ksz88x3_tc_ets_add - Configure ETS (Enhanced Transmission Selection)
+ *                      for a port on KSZ88x3 switch
+ * @dev: Pointer to the KSZ switch device structure
+ * @port: Port number to configure
+ * @p: Pointer to offload replace parameters describing ETS bands and mapping
+ *
+ * The KSZ88x3 supports two scheduling modes: Strict Priority and
+ * Weighted Fair Queuing (WFQ). Both modes have fixed behavior:
+ *   - No configurable queue-to-priority mapping
+ *   - No weight adjustment in WFQ mode
+ *
+ * This function configures the switch to use strict priority mode by
+ * clearing the WFQ enable bit for all queues associated with ETS bands.
+ * If strict priority is not explicitly requested, the switch will default
+ * to WFQ mode.
+ *
+ * Return: 0 on success, or a negative error code on failure
+ */
+static int ksz88x3_tc_ets_add(struct ksz_device *dev, int port,
+			      struct tc_ets_qopt_offload_replace_params *p)
+{
+	int ret, band;
+
+	/* Only strict priority mode is supported for now.
+	 * WFQ is implicitly enabled when strict mode is disabled.
+	 */
+	for (band = 0; band < p->bands; band++) {
+		int queue = ksz_ets_band_to_queue(p, band);
+		u8 reg;
+
+		/* Calculate TXQ Split Control register address for this
+		 * port/queue
+		 */
+		reg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);
+		if (ksz_is_ksz8463(dev))
+			reg = ksz8463_tc_ctrl(port, queue);
+
+		/* Clear WFQ enable bit to select strict priority scheduling */
+		ret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE, 0);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ksz88x3_tc_ets_del - Reset ETS (Enhanced Transmission Selection) config
+ *                      for a port on KSZ88x3 switch
+ * @dev: Pointer to the KSZ switch device structure
+ * @port: Port number to reset
+ *
+ * The KSZ88x3 supports only fixed scheduling modes: Strict Priority or
+ * Weighted Fair Queuing (WFQ), with no reconfiguration of weights or
+ * queue mapping. This function resets the port’s scheduling mode to
+ * the default, which is WFQ, by enabling the WFQ bit for all queues.
+ *
+ * Return: 0 on success, or a negative error code on failure
+ */
+static int ksz88x3_tc_ets_del(struct ksz_device *dev, int port)
+{
+	int ret, queue;
+
+	/* Iterate over all transmit queues for this port */
+	for (queue = 0; queue < dev->info->num_tx_queues; queue++) {
+		u8 reg;
+
+		/* Calculate TXQ Split Control register address for this
+		 * port/queue
+		 */
+		reg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);
+		if (ksz_is_ksz8463(dev))
+			reg = ksz8463_tc_ctrl(port, queue);
+
+		/* Set WFQ enable bit to revert back to default scheduling
+		 * mode
+		 */
+		ret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE,
+			       KSZ8873_TXQ_WFQ_ENABLE);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int ksz8_tc_setup_qdisc_ets(struct dsa_switch *ds, int port,
+				   struct tc_ets_qopt_offload *qopt)
+{
+	struct ksz_device *dev = ds->priv;
+	int ret;
+
+	if (!(ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)))
+		return -EOPNOTSUPP;
+
+	if (qopt->parent != TC_H_ROOT) {
+		dev_err(dev->dev, "Parent should be \"root\"\n");
+		return -EOPNOTSUPP;
+	}
+
+	switch (qopt->command) {
+	case TC_ETS_REPLACE:
+		ret = ksz_tc_ets_validate(dev, port, &qopt->replace_params);
+		if (ret)
+			return ret;
+
+		return ksz88x3_tc_ets_add(dev, port, &qopt->replace_params);
+	case TC_ETS_DESTROY:
+		return ksz88x3_tc_ets_del(dev, port);
+	case TC_ETS_STATS:
+	case TC_ETS_GRAFT:
+		return -EOPNOTSUPP;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static int ksz87xx_setup_tc(struct dsa_switch *ds, int port,
+			    enum tc_setup_type type, void *type_data)
+{
+	switch (type) {
+	case TC_SETUP_QDISC_CBS:
+		return ksz_setup_tc_cbs(ds, port, type_data);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int ksz8_setup_tc(struct dsa_switch *ds, int port,
+			 enum tc_setup_type type, void *type_data)
+{
+	switch (type) {
+	case TC_SETUP_QDISC_CBS:
+		return ksz_setup_tc_cbs(ds, port, type_data);
+	case TC_SETUP_QDISC_ETS:
+		return ksz8_tc_setup_qdisc_ets(ds, port, type_data);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static void ksz8795_cpu_interface_select(struct ksz_device *dev, int port)
 {
 	struct ksz_port *p = &dev->ports[port];
@@ -2053,6 +2251,171 @@ static int ksz8_enable_stp_addr(struct ksz_device *dev)
 	return ksz8_w_sta_mac_table(dev, 0, &alu);
 }
 
+static void ksz88xx_r_mib_stats64(struct ksz_device *dev, int port)
+{
+	struct ethtool_pause_stats *pstats;
+	struct rtnl_link_stats64 *stats;
+	struct ksz88xx_stats_raw *raw;
+	struct ksz_port_mib *mib;
+
+	mib = &dev->ports[port].mib;
+	stats = &mib->stats64;
+	pstats = &mib->pause_stats;
+	raw = (struct ksz88xx_stats_raw *)mib->counters;
+
+	spin_lock(&mib->stats64_lock);
+
+	stats->rx_packets = raw->rx_bcast + raw->rx_mcast + raw->rx_ucast +
+		raw->rx_pause;
+	stats->tx_packets = raw->tx_bcast + raw->tx_mcast + raw->tx_ucast +
+		raw->tx_pause;
+
+	/* HW counters are counting bytes + FCS which is not acceptable
+	 * for rtnl_link_stats64 interface
+	 */
+	stats->rx_bytes = raw->rx + raw->rx_hi - stats->rx_packets * ETH_FCS_LEN;
+	stats->tx_bytes = raw->tx + raw->tx_hi - stats->tx_packets * ETH_FCS_LEN;
+
+	stats->rx_length_errors = raw->rx_undersize + raw->rx_fragments +
+		raw->rx_oversize;
+
+	stats->rx_crc_errors = raw->rx_crc_err;
+	stats->rx_frame_errors = raw->rx_align_err;
+	stats->rx_dropped = raw->rx_discards;
+	stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors +
+		stats->rx_frame_errors  + stats->rx_dropped;
+
+	stats->tx_window_errors = raw->tx_late_col;
+	stats->tx_fifo_errors = raw->tx_discards;
+	stats->tx_aborted_errors = raw->tx_exc_col;
+	stats->tx_errors = stats->tx_window_errors + stats->tx_fifo_errors +
+		stats->tx_aborted_errors;
+
+	stats->multicast = raw->rx_mcast;
+	stats->collisions = raw->tx_total_col;
+
+	pstats->tx_pause_frames = raw->tx_pause;
+	pstats->rx_pause_frames = raw->rx_pause;
+
+	spin_unlock(&mib->stats64_lock);
+}
+
+/**
+ * ksz88x3_drive_strength_write() - Set the drive strength configuration for
+ *				    KSZ8863 compatible chip variants.
+ * @dev:       ksz device
+ * @props:     Array of drive strength properties to be set
+ * @num_props: Number of properties in the array
+ *
+ * This function applies the specified drive strength settings to KSZ88X3 chip
+ * variants (KSZ8873, KSZ8863).
+ * It ensures the configurations align with what the chip variant supports and
+ * warns or errors out on unsupported settings.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int ksz88x3_drive_strength_write(struct ksz_device *dev,
+					struct ksz_driver_strength_prop *props,
+					int num_props)
+{
+	size_t array_size = ARRAY_SIZE(ksz88x3_drive_strengths);
+	int microamp;
+	int i, ret;
+
+	for (i = 0; i < num_props; i++) {
+		if (props[i].value == -1 || i == KSZ_DRIVER_STRENGTH_IO)
+			continue;
+
+		dev_warn(dev->dev, "%s is not supported by this chip variant\n",
+			 props[i].name);
+	}
+
+	microamp = props[KSZ_DRIVER_STRENGTH_IO].value;
+	ret = ksz_drive_strength_to_reg(ksz88x3_drive_strengths, array_size,
+					microamp);
+	if (ret < 0) {
+		ksz_drive_strength_error(dev, ksz88x3_drive_strengths,
+					 array_size, microamp);
+		return ret;
+	}
+
+	return ksz_rmw8(dev, KSZ8873_REG_GLOBAL_CTRL_12,
+			KSZ8873_DRIVE_STRENGTH_16MA, ret);
+}
+
+/**
+ * ksz8_parse_drive_strength() - Extract and apply drive strength configurations
+ *				 from device tree properties.
+ * @dev:	ksz device
+ *
+ * This function reads the specified drive strength properties from the
+ * device tree, validates against the supported chip variants, and sets
+ * them accordingly. An error should be critical here, as the drive strength
+ * settings are crucial for EMI compliance.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int ksz8_parse_drive_strength(struct ksz_device *dev)
+{
+	struct ksz_driver_strength_prop of_props[] = {
+		[KSZ_DRIVER_STRENGTH_HI] = {
+			.name = "microchip,hi-drive-strength-microamp",
+			.offset = SW_HI_SPEED_DRIVE_STRENGTH_S,
+			.value = -1,
+		},
+		[KSZ_DRIVER_STRENGTH_LO] = {
+			.name = "microchip,lo-drive-strength-microamp",
+			.offset = SW_LO_SPEED_DRIVE_STRENGTH_S,
+			.value = -1,
+		},
+		[KSZ_DRIVER_STRENGTH_IO] = {
+			.name = "microchip,io-drive-strength-microamp",
+			.offset = 0, /* don't care */
+			.value = -1,
+		},
+	};
+	struct device_node *np = dev->dev->of_node;
+	bool have_any_prop = false;
+	int i, ret;
+
+	for (i = 0; i < ARRAY_SIZE(of_props); i++) {
+		ret = of_property_read_u32(np, of_props[i].name,
+					   &of_props[i].value);
+		if (ret && ret != -EINVAL)
+			dev_warn(dev->dev, "Failed to read %s\n",
+				 of_props[i].name);
+		if (ret)
+			continue;
+
+		have_any_prop = true;
+	}
+
+	if (!have_any_prop)
+		return 0;
+
+	switch (dev->chip_id) {
+	case KSZ88X3_CHIP_ID:
+		return ksz88x3_drive_strength_write(dev, of_props,
+						    ARRAY_SIZE(of_props));
+	case KSZ8795_CHIP_ID:
+	case KSZ8794_CHIP_ID:
+	case KSZ8765_CHIP_ID:
+		return ksz_drive_strength_write(dev, of_props,
+						ARRAY_SIZE(of_props));
+	default:
+		/* KSZ8864, KSZ8895 */
+		for (i = 0; i < ARRAY_SIZE(of_props); i++) {
+			if (of_props[i].value == -1)
+				continue;
+
+			dev_warn(dev->dev, "%s is not supported by this chip variant\n",
+				 of_props[i].name);
+		}
+	}
+
+	return 0;
+}
+
 static int ksz8_setup(struct dsa_switch *ds)
 {
 	struct ksz_device *dev = ds->priv;
@@ -2075,7 +2438,7 @@ static int ksz8_setup(struct dsa_switch *ds)
 		return ret;
 	}
 
-	ret = ksz_parse_drive_strength(dev);
+	ret = ksz8_parse_drive_strength(dev);
 	if (ret)
 		return ret;
 
@@ -2551,8 +2914,8 @@ const struct dsa_switch_ops ksz8463_switch_ops = {
 	.port_mirror_del	= ksz8_port_mirror_del,
 	.get_stats64		= ksz_get_stats64,
 	.get_pause_stats	= ksz_get_pause_stats,
-	.port_change_mtu	= ksz8_change_mtu,
-	.port_max_mtu		= ksz_max_mtu,
+	.port_change_mtu	= ksz88xx_change_mtu,
+	.port_max_mtu		= ksz88xx_max_mtu,
 	.suspend		= ksz_suspend,
 	.resume			= ksz_resume,
 	.get_ts_info		= ksz_get_ts_info,
@@ -2560,7 +2923,7 @@ const struct dsa_switch_ops ksz8463_switch_ops = {
 	.port_hwtstamp_set	= ksz_hwtstamp_set,
 	.port_txtstamp		= ksz_port_txtstamp,
 	.port_rxtstamp		= ksz_port_rxtstamp,
-	.port_setup_tc		= ksz_setup_tc,
+	.port_setup_tc		= ksz8_setup_tc,
 	.port_get_default_prio	= ksz_port_get_default_prio,
 	.port_set_default_prio	= ksz_port_set_default_prio,
 	.port_get_dscp_prio	= ksz_port_get_dscp_prio,
@@ -2601,8 +2964,8 @@ const struct dsa_switch_ops ksz87xx_switch_ops = {
 	.port_mirror_del	= ksz8_port_mirror_del,
 	.get_stats64		= ksz_get_stats64,
 	.get_pause_stats	= ksz_get_pause_stats,
-	.port_change_mtu	= ksz8_change_mtu,
-	.port_max_mtu		= ksz_max_mtu,
+	.port_change_mtu	= ksz87xx_change_mtu,
+	.port_max_mtu		= ksz87xx_max_mtu,
 	.suspend		= ksz_suspend,
 	.resume			= ksz_resume,
 	.get_ts_info		= ksz_get_ts_info,
@@ -2610,7 +2973,7 @@ const struct dsa_switch_ops ksz87xx_switch_ops = {
 	.port_hwtstamp_set	= ksz_hwtstamp_set,
 	.port_txtstamp		= ksz_port_txtstamp,
 	.port_rxtstamp		= ksz_port_rxtstamp,
-	.port_setup_tc		= ksz_setup_tc,
+	.port_setup_tc		= ksz87xx_setup_tc,
 	.port_get_default_prio	= ksz_port_get_default_prio,
 	.port_set_default_prio	= ksz_port_set_default_prio,
 	.port_get_dscp_prio	= ksz_port_get_dscp_prio,
@@ -2652,8 +3015,8 @@ const struct dsa_switch_ops ksz88xx_switch_ops = {
 	.port_mirror_del	= ksz8_port_mirror_del,
 	.get_stats64		= ksz_get_stats64,
 	.get_pause_stats	= ksz_get_pause_stats,
-	.port_change_mtu	= ksz8_change_mtu,
-	.port_max_mtu		= ksz_max_mtu,
+	.port_change_mtu	= ksz88xx_change_mtu,
+	.port_max_mtu		= ksz88xx_max_mtu,
 	.get_wol		= ksz_get_wol,
 	.set_wol		= ksz_set_wol,
 	.suspend		= ksz_suspend,
@@ -2663,7 +3026,7 @@ const struct dsa_switch_ops ksz88xx_switch_ops = {
 	.port_hwtstamp_set	= ksz_hwtstamp_set,
 	.port_txtstamp		= ksz_port_txtstamp,
 	.port_rxtstamp		= ksz_port_rxtstamp,
-	.port_setup_tc		= ksz_setup_tc,
+	.port_setup_tc		= ksz8_setup_tc,
 	.port_get_default_prio	= ksz_port_get_default_prio,
 	.port_set_default_prio	= ksz_port_set_default_prio,
 	.port_get_dscp_prio	= ksz_port_get_dscp_prio,
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index f3f0c98dfb5a7f..3ee995545c5795 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -15,6 +15,7 @@
 #include <linux/if_hsr.h>
 #include <linux/if_vlan.h>
 #include <net/dsa.h>
+#include <net/ieee8021q.h>
 #include <net/switchdev.h>
 
 #include "ksz9477_reg.h"
@@ -60,6 +61,11 @@ static int ksz9477_change_mtu(struct dsa_switch *ds, int port, int mtu)
 				  REG_SW_MTU_MASK, frame_size);
 }
 
+int ksz9477_max_mtu(struct dsa_switch *ds, int port)
+{
+	return KSZ9477_MAX_FRAME_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;
+}
+
 static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev)
 {
 	unsigned int val;
@@ -478,8 +484,8 @@ static int ksz9477_half_duplex_monitor(struct ksz_device *dev, int port,
 	return ret;
 }
 
-int ksz9477_errata_monitor(struct ksz_device *dev, int port,
-			   u64 tx_late_col)
+static int ksz9477_errata_monitor(struct ksz_device *dev, int port,
+				  u64 tx_late_col)
 {
 	u8 status;
 	int ret;
@@ -497,6 +503,24 @@ int ksz9477_errata_monitor(struct ksz_device *dev, int port,
 	return ret;
 }
 
+static void ksz9477_r_mib_stats64(struct ksz_device *dev, int port)
+{
+	struct ksz_stats_raw *raw;
+	struct ksz_port_mib *mib;
+	int ret;
+
+	ksz_r_mib_stats64(dev, port);
+
+	if (dev->info->phy_errata_9477 && !ksz_is_sgmii_port(dev, port)) {
+		mib = &dev->ports[port].mib;
+		raw = (struct ksz_stats_raw *)mib->counters;
+
+		ret = ksz9477_errata_monitor(dev, port, raw->tx_late_col);
+		if (ret)
+			dev_err(dev->dev, "Failed to monitor transmission halt\n");
+	}
+};
+
 void ksz9477_port_init_cnt(struct ksz_device *dev, int port)
 {
 	struct ksz_port_mib *mib = &dev->ports[port].mib;
@@ -1176,6 +1200,58 @@ void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,
 			     PORT_MIRROR_SNIFFER, false);
 }
 
+static bool ksz9477_get_gbit(struct ksz_device *dev, int port)
+{
+	const u8 *bitval = dev->info->xmii_ctrl1;
+	const u16 *regs = dev->info->regs;
+	bool gbit = false;
+	u8 data8;
+	bool val;
+
+	ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8);
+
+	val = FIELD_GET(P_GMII_1GBIT_M, data8);
+
+	if (val == bitval[P_GMII_1GBIT])
+		gbit = true;
+
+	return gbit;
+}
+
+static phy_interface_t ksz9477_get_xmii(struct ksz_device *dev, int port,
+					bool gbit)
+{
+	const u8 *bitval = dev->info->xmii_ctrl1;
+	const u16 *regs = dev->info->regs;
+	phy_interface_t interface;
+	u8 data8;
+	u8 val;
+
+	ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8);
+
+	val = FIELD_GET(P_MII_SEL_M, data8);
+
+	if (val == bitval[P_MII_SEL]) {
+		if (gbit)
+			interface = PHY_INTERFACE_MODE_GMII;
+		else
+			interface = PHY_INTERFACE_MODE_MII;
+	} else if (val == bitval[P_RMII_SEL]) {
+		interface = PHY_INTERFACE_MODE_RMII;
+	} else {
+		interface = PHY_INTERFACE_MODE_RGMII;
+		if (data8 & P_RGMII_ID_EG_ENABLE)
+			interface = PHY_INTERFACE_MODE_RGMII_TXID;
+		if (data8 & P_RGMII_ID_IG_ENABLE) {
+			interface = PHY_INTERFACE_MODE_RGMII_RXID;
+			if (data8 & P_RGMII_ID_EG_ENABLE)
+				interface = PHY_INTERFACE_MODE_RGMII_ID;
+		}
+	}
+
+	return interface;
+}
+
 static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port)
 {
 	phy_interface_t interface;
@@ -1184,9 +1260,9 @@ static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port)
 	if (dev->info->internal_phy[port])
 		return PHY_INTERFACE_MODE_NA;
 
-	gbit = ksz_get_gbit(dev, port);
+	gbit = ksz9477_get_gbit(dev, port);
 
-	interface = ksz_get_xmii(dev, port, gbit);
+	interface = ksz9477_get_xmii(dev, port, gbit);
 
 	return interface;
 }
@@ -1335,6 +1411,28 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
 	ksz_pwrite8(dev, port, regs[REG_PORT_PME_CTRL], 0);
 }
 
+int ksz9477_set_default_prio_queue_mapping(struct ksz_device *dev, int port)
+{
+	u32 queue_map = 0;
+	int ipm;
+
+	for (ipm = 0; ipm < dev->info->num_ipms; ipm++) {
+		int queue;
+
+		/* Traffic Type (TT) is corresponding to the Internal Priority
+		 * Map (IPM) in the switch. Traffic Class (TC) is
+		 * corresponding to the queue in the switch.
+		 */
+		queue = ieee8021q_tt_to_tc(ipm, dev->info->num_tx_queues);
+		if (queue < 0)
+			return queue;
+
+		queue_map |= queue << (ipm * KSZ9477_PORT_TC_MAP_S);
+	}
+
+	return ksz_pwrite32(dev, port, KSZ9477_PORT_MRI_TC_MAP__4, queue_map);
+}
+
 static int ksz9477_dsa_port_setup(struct dsa_switch *ds, int port)
 {
 	struct ksz_device *dev = ds->priv;
@@ -1517,6 +1615,58 @@ int ksz9477_enable_stp_addr(struct ksz_device *dev)
 	return 0;
 }
 
+/**
+ * ksz9477_parse_drive_strength() - Extract and apply drive strength
+ *				    configurations from device tree properties.
+ * @dev:	ksz device
+ *
+ * This function reads the specified drive strength properties from the
+ * device tree, validates against the supported chip variants, and sets
+ * them accordingly. An error should be critical here, as the drive strength
+ * settings are crucial for EMI compliance.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int ksz9477_parse_drive_strength(struct ksz_device *dev)
+{
+	struct ksz_driver_strength_prop of_props[] = {
+		[KSZ_DRIVER_STRENGTH_HI] = {
+			.name = "microchip,hi-drive-strength-microamp",
+			.offset = SW_HI_SPEED_DRIVE_STRENGTH_S,
+			.value = -1,
+		},
+		[KSZ_DRIVER_STRENGTH_LO] = {
+			.name = "microchip,lo-drive-strength-microamp",
+			.offset = SW_LO_SPEED_DRIVE_STRENGTH_S,
+			.value = -1,
+		},
+		[KSZ_DRIVER_STRENGTH_IO] = {
+			.name = "microchip,io-drive-strength-microamp",
+			.offset = 0, /* don't care */
+			.value = -1,
+		},
+	};
+	struct device_node *np = dev->dev->of_node;
+	bool have_any_prop = false;
+	int i, ret;
+
+	for (i = 0; i < ARRAY_SIZE(of_props); i++) {
+		ret = of_property_read_u32(np, of_props[i].name,
+					   &of_props[i].value);
+		if (ret && ret != -EINVAL)
+			dev_warn(dev->dev, "Failed to read %s\n",
+				 of_props[i].name);
+		if (ret)
+			continue;
+
+		have_any_prop = true;
+	}
+
+	if (!have_any_prop)
+		return 0;
+
+	return ksz_drive_strength_write(dev, of_props, ARRAY_SIZE(of_props));
+}
 static int ksz9477_setup(struct dsa_switch *ds)
 {
 	struct ksz_device *dev = ds->priv;
@@ -1539,7 +1689,7 @@ static int ksz9477_setup(struct dsa_switch *ds)
 		return ret;
 	}
 
-	ret = ksz_parse_drive_strength(dev);
+	ret = ksz9477_parse_drive_strength(dev);
 	if (ret)
 		return ret;
 
@@ -2052,7 +2202,7 @@ const struct ksz_dev_ops ksz9477_dev_ops = {
 	.cfg_port_member = ksz9477_cfg_port_member,
 	.r_mib_cnt = ksz9477_r_mib_cnt,
 	.r_mib_pkt = ksz9477_r_mib_pkt,
-	.r_mib_stat64 = ksz_r_mib_stats64,
+	.r_mib_stat64 = ksz9477_r_mib_stats64,
 	.freeze_mib = ksz9477_freeze_mib,
 	.port_init_cnt = ksz9477_port_init_cnt,
 	.pme_write8 = ksz_write8,
@@ -2098,7 +2248,7 @@ const struct dsa_switch_ops ksz9477_switch_ops = {
 	.get_stats64		= ksz_get_stats64,
 	.get_pause_stats	= ksz_get_pause_stats,
 	.port_change_mtu	= ksz9477_change_mtu,
-	.port_max_mtu		= ksz_max_mtu,
+	.port_max_mtu		= ksz9477_max_mtu,
 	.get_wol		= ksz_get_wol,
 	.set_wol		= ksz_set_wol,
 	.suspend		= ksz_suspend,
diff --git a/drivers/net/dsa/microchip/ksz9477.h b/drivers/net/dsa/microchip/ksz9477.h
index 92a1d889224d3e..a84c000000e66e 100644
--- a/drivers/net/dsa/microchip/ksz9477.h
+++ b/drivers/net/dsa/microchip/ksz9477.h
@@ -21,6 +21,7 @@ void ksz9477_freeze_mib(struct ksz_device *dev, int port, bool freeze);
 void ksz9477_port_init_cnt(struct ksz_device *dev, int port);
 int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port,
 				bool flag, struct netlink_ext_ack *extack);
+int ksz9477_max_mtu(struct dsa_switch *ds, int port);
 int ksz9477_port_vlan_add(struct dsa_switch *ds, int port,
 			  const struct switchdev_obj_port_vlan *vlan,
 			  struct netlink_ext_ack *extack);
@@ -31,8 +32,6 @@ int ksz9477_port_mirror_add(struct dsa_switch *ds, int port,
 			    bool ingress, struct netlink_ext_ack *extack);
 void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,
 			     struct dsa_mall_mirror_tc_entry *mirror);
-int ksz9477_errata_monitor(struct ksz_device *dev, int port,
-			   u64 tx_late_col);
 int ksz9477_fdb_dump(struct dsa_switch *ds, int port,
 		     dsa_fdb_dump_cb_t *cb, void *data);
 int ksz9477_fdb_add(struct dsa_switch *ds, int port,
@@ -45,6 +44,7 @@ int ksz9477_mdb_del(struct dsa_switch *ds, int port,
 		    const struct switchdev_obj_port_mdb *mdb, struct dsa_db db);
 int ksz9477_enable_stp_addr(struct ksz_device *dev);
 void ksz9477_port_queue_split(struct ksz_device *dev, int port);
+int ksz9477_set_default_prio_queue_mapping(struct ksz_device *dev, int port);
 
 int ksz9477_port_acl_init(struct ksz_device *dev, int port);
 void ksz9477_port_acl_free(struct ksz_device *dev, int port);
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index d1726778bb488e..67ab6ddb9e53f2 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -37,82 +37,6 @@
 
 #define MIB_COUNTER_NUM 0x20
 
-struct ksz_stats_raw {
-	u64 rx_hi;
-	u64 rx_undersize;
-	u64 rx_fragments;
-	u64 rx_oversize;
-	u64 rx_jabbers;
-	u64 rx_symbol_err;
-	u64 rx_crc_err;
-	u64 rx_align_err;
-	u64 rx_mac_ctrl;
-	u64 rx_pause;
-	u64 rx_bcast;
-	u64 rx_mcast;
-	u64 rx_ucast;
-	u64 rx_64_or_less;
-	u64 rx_65_127;
-	u64 rx_128_255;
-	u64 rx_256_511;
-	u64 rx_512_1023;
-	u64 rx_1024_1522;
-	u64 rx_1523_2000;
-	u64 rx_2001;
-	u64 tx_hi;
-	u64 tx_late_col;
-	u64 tx_pause;
-	u64 tx_bcast;
-	u64 tx_mcast;
-	u64 tx_ucast;
-	u64 tx_deferred;
-	u64 tx_total_col;
-	u64 tx_exc_col;
-	u64 tx_single_col;
-	u64 tx_mult_col;
-	u64 rx_total;
-	u64 tx_total;
-	u64 rx_discards;
-	u64 tx_discards;
-};
-
-struct ksz88xx_stats_raw {
-	u64 rx;
-	u64 rx_hi;
-	u64 rx_undersize;
-	u64 rx_fragments;
-	u64 rx_oversize;
-	u64 rx_jabbers;
-	u64 rx_symbol_err;
-	u64 rx_crc_err;
-	u64 rx_align_err;
-	u64 rx_mac_ctrl;
-	u64 rx_pause;
-	u64 rx_bcast;
-	u64 rx_mcast;
-	u64 rx_ucast;
-	u64 rx_64_or_less;
-	u64 rx_65_127;
-	u64 rx_128_255;
-	u64 rx_256_511;
-	u64 rx_512_1023;
-	u64 rx_1024_1522;
-	u64 tx;
-	u64 tx_hi;
-	u64 tx_late_col;
-	u64 tx_pause;
-	u64 tx_bcast;
-	u64 tx_mcast;
-	u64 tx_ucast;
-	u64 tx_deferred;
-	u64 tx_total_col;
-	u64 tx_exc_col;
-	u64 tx_single_col;
-	u64 tx_mult_col;
-	u64 rx_discards;
-	u64 tx_discards;
-};
-
 static const struct ksz_mib_names ksz88xx_mib_names[] = {
 	{ 0x00, "rx" },
 	{ 0x01, "rx_hi" },
@@ -189,28 +113,6 @@ static const struct ksz_mib_names ksz9477_mib_names[] = {
 	{ 0x83, "tx_discards" },
 };
 
-struct ksz_driver_strength_prop {
-	const char *name;
-	int offset;
-	int value;
-};
-
-enum ksz_driver_strength_type {
-	KSZ_DRIVER_STRENGTH_HI,
-	KSZ_DRIVER_STRENGTH_LO,
-	KSZ_DRIVER_STRENGTH_IO,
-};
-
-/**
- * struct ksz_drive_strength - drive strength mapping
- * @reg_val:	register value
- * @microamp:	microamp value
- */
-struct ksz_drive_strength {
-	u32 reg_val;
-	u32 microamp;
-};
-
 /* ksz9477_drive_strengths - Drive strength mapping for KSZ9477 variants
  *
  * This values are not documented in KSZ9477 variants but confirmed by
@@ -246,15 +148,6 @@ static const struct ksz_drive_strength ksz9477_drive_strengths[] = {
 	{ SW_DRIVE_STRENGTH_28MA, 28000 },
 };
 
-/* ksz88x3_drive_strengths - Drive strength mapping for KSZ8863, KSZ8873, ..
- *			     variants.
- * This values are documented in KSZ8873 and KSZ8863 datasheets.
- */
-static const struct ksz_drive_strength ksz88x3_drive_strengths[] = {
-	{ 0,  8000 },
-	{ KSZ8873_DRIVE_STRENGTH_16MA, 16000 },
-};
-
 /**
  * ksz_phylink_mac_disable_tx_lpi() - Callback to signal LPI support (Dummy)
  * @config: phylink config structure
@@ -2013,7 +1906,6 @@ void ksz_r_mib_stats64(struct ksz_device *dev, int port)
 	struct rtnl_link_stats64 *stats;
 	struct ksz_stats_raw *raw;
 	struct ksz_port_mib *mib;
-	int ret;
 
 	mib = &dev->ports[port].mib;
 	stats = &mib->stats64;
@@ -2055,61 +1947,6 @@ void ksz_r_mib_stats64(struct ksz_device *dev, int port)
 	pstats->rx_pause_frames = raw->rx_pause;
 
 	spin_unlock(&mib->stats64_lock);
-
-	if (dev->info->phy_errata_9477 && !ksz_is_sgmii_port(dev, port)) {
-		ret = ksz9477_errata_monitor(dev, port, raw->tx_late_col);
-		if (ret)
-			dev_err(dev->dev, "Failed to monitor transmission halt\n");
-	}
-}
-
-void ksz88xx_r_mib_stats64(struct ksz_device *dev, int port)
-{
-	struct ethtool_pause_stats *pstats;
-	struct rtnl_link_stats64 *stats;
-	struct ksz88xx_stats_raw *raw;
-	struct ksz_port_mib *mib;
-
-	mib = &dev->ports[port].mib;
-	stats = &mib->stats64;
-	pstats = &mib->pause_stats;
-	raw = (struct ksz88xx_stats_raw *)mib->counters;
-
-	spin_lock(&mib->stats64_lock);
-
-	stats->rx_packets = raw->rx_bcast + raw->rx_mcast + raw->rx_ucast +
-		raw->rx_pause;
-	stats->tx_packets = raw->tx_bcast + raw->tx_mcast + raw->tx_ucast +
-		raw->tx_pause;
-
-	/* HW counters are counting bytes + FCS which is not acceptable
-	 * for rtnl_link_stats64 interface
-	 */
-	stats->rx_bytes = raw->rx + raw->rx_hi - stats->rx_packets * ETH_FCS_LEN;
-	stats->tx_bytes = raw->tx + raw->tx_hi - stats->tx_packets * ETH_FCS_LEN;
-
-	stats->rx_length_errors = raw->rx_undersize + raw->rx_fragments +
-		raw->rx_oversize;
-
-	stats->rx_crc_errors = raw->rx_crc_err;
-	stats->rx_frame_errors = raw->rx_align_err;
-	stats->rx_dropped = raw->rx_discards;
-	stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors +
-		stats->rx_frame_errors  + stats->rx_dropped;
-
-	stats->tx_window_errors = raw->tx_late_col;
-	stats->tx_fifo_errors = raw->tx_discards;
-	stats->tx_aborted_errors = raw->tx_exc_col;
-	stats->tx_errors = stats->tx_window_errors + stats->tx_fifo_errors +
-		stats->tx_aborted_errors;
-
-	stats->multicast = raw->rx_mcast;
-	stats->collisions = raw->tx_total_col;
-
-	pstats->tx_pause_frames = raw->tx_pause;
-	pstats->rx_pause_frames = raw->rx_pause;
-
-	spin_unlock(&mib->stats64_lock);
 }
 
 void ksz_get_stats64(struct dsa_switch *ds, int port,
@@ -2885,28 +2722,6 @@ void ksz_port_bridge_leave(struct dsa_switch *ds, int port,
 	 */
 }
 
-int ksz9477_set_default_prio_queue_mapping(struct ksz_device *dev, int port)
-{
-	u32 queue_map = 0;
-	int ipm;
-
-	for (ipm = 0; ipm < dev->info->num_ipms; ipm++) {
-		int queue;
-
-		/* Traffic Type (TT) is corresponding to the Internal Priority
-		 * Map (IPM) in the switch. Traffic Class (TC) is
-		 * corresponding to the queue in the switch.
-		 */
-		queue = ieee8021q_tt_to_tc(ipm, dev->info->num_tx_queues);
-		if (queue < 0)
-			return queue;
-
-		queue_map |= queue << (ipm * KSZ9477_PORT_TC_MAP_S);
-	}
-
-	return ksz_pwrite32(dev, port, KSZ9477_PORT_MRI_TC_MAP__4, queue_map);
-}
-
 void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
 {
 	struct ksz_device *dev = ds->priv;
@@ -2984,40 +2799,6 @@ int ksz_port_bridge_flags(struct dsa_switch *ds, int port,
 	return 0;
 }
 
-int ksz_max_mtu(struct dsa_switch *ds, int port)
-{
-	struct ksz_device *dev = ds->priv;
-
-	switch (dev->chip_id) {
-	case KSZ8795_CHIP_ID:
-	case KSZ8794_CHIP_ID:
-	case KSZ8765_CHIP_ID:
-		return KSZ8795_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;
-	case KSZ8463_CHIP_ID:
-	case KSZ88X3_CHIP_ID:
-	case KSZ8864_CHIP_ID:
-	case KSZ8895_CHIP_ID:
-		return KSZ8863_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;
-	case KSZ8563_CHIP_ID:
-	case KSZ8567_CHIP_ID:
-	case KSZ9477_CHIP_ID:
-	case KSZ9563_CHIP_ID:
-	case KSZ9567_CHIP_ID:
-	case KSZ9893_CHIP_ID:
-	case KSZ9896_CHIP_ID:
-	case KSZ9897_CHIP_ID:
-	case LAN9370_CHIP_ID:
-	case LAN9371_CHIP_ID:
-	case LAN9372_CHIP_ID:
-	case LAN9373_CHIP_ID:
-	case LAN9374_CHIP_ID:
-	case LAN9646_CHIP_ID:
-		return KSZ9477_MAX_FRAME_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;
-	}
-
-	return -EOPNOTSUPP;
-}
-
 int ksz_set_mac_eee(struct dsa_switch *ds, int port,
 		    struct ethtool_keee *e)
 {
@@ -3086,39 +2867,6 @@ void ksz_set_xmii(struct ksz_device *dev, int port, phy_interface_t interface)
 	ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8);
 }
 
-phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit)
-{
-	const u8 *bitval = dev->info->xmii_ctrl1;
-	const u16 *regs = dev->info->regs;
-	phy_interface_t interface;
-	u8 data8;
-	u8 val;
-
-	ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8);
-
-	val = FIELD_GET(P_MII_SEL_M, data8);
-
-	if (val == bitval[P_MII_SEL]) {
-		if (gbit)
-			interface = PHY_INTERFACE_MODE_GMII;
-		else
-			interface = PHY_INTERFACE_MODE_MII;
-	} else if (val == bitval[P_RMII_SEL]) {
-		interface = PHY_INTERFACE_MODE_RMII;
-	} else {
-		interface = PHY_INTERFACE_MODE_RGMII;
-		if (data8 & P_RGMII_ID_EG_ENABLE)
-			interface = PHY_INTERFACE_MODE_RGMII_TXID;
-		if (data8 & P_RGMII_ID_IG_ENABLE) {
-			interface = PHY_INTERFACE_MODE_RGMII_RXID;
-			if (data8 & P_RGMII_ID_EG_ENABLE)
-				interface = PHY_INTERFACE_MODE_RGMII_ID;
-		}
-	}
-
-	return interface;
-}
-
 bool ksz_phylink_need_config(struct phylink_config *config,
 			     unsigned int mode)
 {
@@ -3154,24 +2902,6 @@ void ksz_phylink_mac_config(struct phylink_config *config,
 		ksz_set_xmii(dev, port, state->interface);
 }
 
-bool ksz_get_gbit(struct ksz_device *dev, int port)
-{
-	const u8 *bitval = dev->info->xmii_ctrl1;
-	const u16 *regs = dev->info->regs;
-	bool gbit = false;
-	u8 data8;
-	bool val;
-
-	ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8);
-
-	val = FIELD_GET(P_GMII_1GBIT_M, data8);
-
-	if (val == bitval[P_GMII_1GBIT])
-		gbit = true;
-
-	return gbit;
-}
-
 static int ksz_switch_detect(struct ksz_device *dev)
 {
 	u8 id1, id2, id4;
@@ -3314,8 +3044,8 @@ static int ksz_setup_tc_mode(struct ksz_device *dev, int port, u8 scheduler,
 			   FIELD_PREP(MTI_SHAPING_M, shaper));
 }
 
-static int ksz_setup_tc_cbs(struct dsa_switch *ds, int port,
-			    struct tc_cbs_qopt_offload *qopt)
+int ksz_setup_tc_cbs(struct dsa_switch *ds, int port,
+		     struct tc_cbs_qopt_offload *qopt)
 {
 	struct ksz_device *dev = ds->priv;
 	int ret;
@@ -3380,8 +3110,8 @@ static int ksz_disable_egress_rate_limit(struct ksz_device *dev, int port)
 	return 0;
 }
 
-static int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,
-				 int band)
+int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,
+			  int band)
 {
 	/* Compared to queues, bands prioritize packets differently. In strict
 	 * priority mode, the lowest priority is assigned to Queue 0 while the
@@ -3390,104 +3120,6 @@ static int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,
 	return p->bands - 1 - band;
 }
 
-static u8 ksz8463_tc_ctrl(int port, int queue)
-{
-	u8 reg;
-
-	reg = 0xC8 + port * 4;
-	reg += ((3 - queue) / 2) * 2;
-	reg++;
-	reg -= (queue & 1);
-	return reg;
-}
-
-/**
- * ksz88x3_tc_ets_add - Configure ETS (Enhanced Transmission Selection)
- *                      for a port on KSZ88x3 switch
- * @dev: Pointer to the KSZ switch device structure
- * @port: Port number to configure
- * @p: Pointer to offload replace parameters describing ETS bands and mapping
- *
- * The KSZ88x3 supports two scheduling modes: Strict Priority and
- * Weighted Fair Queuing (WFQ). Both modes have fixed behavior:
- *   - No configurable queue-to-priority mapping
- *   - No weight adjustment in WFQ mode
- *
- * This function configures the switch to use strict priority mode by
- * clearing the WFQ enable bit for all queues associated with ETS bands.
- * If strict priority is not explicitly requested, the switch will default
- * to WFQ mode.
- *
- * Return: 0 on success, or a negative error code on failure
- */
-static int ksz88x3_tc_ets_add(struct ksz_device *dev, int port,
-			      struct tc_ets_qopt_offload_replace_params *p)
-{
-	int ret, band;
-
-	/* Only strict priority mode is supported for now.
-	 * WFQ is implicitly enabled when strict mode is disabled.
-	 */
-	for (band = 0; band < p->bands; band++) {
-		int queue = ksz_ets_band_to_queue(p, band);
-		u8 reg;
-
-		/* Calculate TXQ Split Control register address for this
-		 * port/queue
-		 */
-		reg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);
-		if (ksz_is_ksz8463(dev))
-			reg = ksz8463_tc_ctrl(port, queue);
-
-		/* Clear WFQ enable bit to select strict priority scheduling */
-		ret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE, 0);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-/**
- * ksz88x3_tc_ets_del - Reset ETS (Enhanced Transmission Selection) config
- *                      for a port on KSZ88x3 switch
- * @dev: Pointer to the KSZ switch device structure
- * @port: Port number to reset
- *
- * The KSZ88x3 supports only fixed scheduling modes: Strict Priority or
- * Weighted Fair Queuing (WFQ), with no reconfiguration of weights or
- * queue mapping. This function resets the port’s scheduling mode to
- * the default, which is WFQ, by enabling the WFQ bit for all queues.
- *
- * Return: 0 on success, or a negative error code on failure
- */
-static int ksz88x3_tc_ets_del(struct ksz_device *dev, int port)
-{
-	int ret, queue;
-
-	/* Iterate over all transmit queues for this port */
-	for (queue = 0; queue < dev->info->num_tx_queues; queue++) {
-		u8 reg;
-
-		/* Calculate TXQ Split Control register address for this
-		 * port/queue
-		 */
-		reg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);
-		if (ksz_is_ksz8463(dev))
-			reg = ksz8463_tc_ctrl(port, queue);
-
-		/* Set WFQ enable bit to revert back to default scheduling
-		 * mode
-		 */
-		ret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE,
-			       KSZ8873_TXQ_WFQ_ENABLE);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
 static int ksz_queue_set_strict(struct ksz_device *dev, int port, int queue)
 {
 	int ret;
@@ -3580,8 +3212,8 @@ static int ksz_tc_ets_del(struct ksz_device *dev, int port)
 	return ksz9477_set_default_prio_queue_mapping(dev, port);
 }
 
-static int ksz_tc_ets_validate(struct ksz_device *dev, int port,
-			       struct tc_ets_qopt_offload_replace_params *p)
+int ksz_tc_ets_validate(struct ksz_device *dev, int port,
+			struct tc_ets_qopt_offload_replace_params *p)
 {
 	int band;
 
@@ -3622,9 +3254,6 @@ static int ksz_tc_setup_qdisc_ets(struct dsa_switch *ds, int port,
 	struct ksz_device *dev = ds->priv;
 	int ret;
 
-	if (is_ksz8(dev) && !(ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)))
-		return -EOPNOTSUPP;
-
 	if (qopt->parent != TC_H_ROOT) {
 		dev_err(dev->dev, "Parent should be \"root\"\n");
 		return -EOPNOTSUPP;
@@ -3636,16 +3265,9 @@ static int ksz_tc_setup_qdisc_ets(struct dsa_switch *ds, int port,
 		if (ret)
 			return ret;
 
-		if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev))
-			return ksz88x3_tc_ets_add(dev, port,
-						  &qopt->replace_params);
-		else
-			return ksz_tc_ets_add(dev, port, &qopt->replace_params);
+		return ksz_tc_ets_add(dev, port, &qopt->replace_params);
 	case TC_ETS_DESTROY:
-		if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev))
-			return ksz88x3_tc_ets_del(dev, port);
-		else
-			return ksz_tc_ets_del(dev, port);
+		return ksz_tc_ets_del(dev, port);
 	case TC_ETS_STATS:
 	case TC_ETS_GRAFT:
 		return -EOPNOTSUPP;
@@ -3704,6 +3326,34 @@ int ksz_handle_wake_reason(struct ksz_device *dev, int port)
 				pme_status);
 }
 
+/**
+ * ksz_is_port_mac_global_usable - Check if the MAC address on a given port
+ *                                 can be used as a global address.
+ * @ds: Pointer to the DSA switch structure.
+ * @port: The port number on which the MAC address is to be checked.
+ *
+ * This function examines the MAC address set on the specified port and
+ * determines if it can be used as a global address for the switch.
+ *
+ * Return: true if the port's MAC address can be used as a global address, false
+ * otherwise.
+ */
+static bool ksz_is_port_mac_global_usable(struct dsa_switch *ds, int port)
+{
+	struct net_device *user = dsa_to_port(ds, port)->user;
+	const unsigned char *addr = user->dev_addr;
+	struct ksz_switch_macaddr *switch_macaddr;
+	struct ksz_device *dev = ds->priv;
+
+	ASSERT_RTNL();
+
+	switch_macaddr = dev->switch_macaddr;
+	if (switch_macaddr && !ether_addr_equal(switch_macaddr->addr, addr))
+		return false;
+
+	return true;
+}
+
 /**
  * ksz_get_wol - Get Wake-on-LAN settings for a specified port.
  * @ds: The dsa_switch structure.
@@ -3897,34 +3547,6 @@ int ksz_port_set_mac_address(struct dsa_switch *ds, int port,
 	return 0;
 }
 
-/**
- * ksz_is_port_mac_global_usable - Check if the MAC address on a given port
- *                                 can be used as a global address.
- * @ds: Pointer to the DSA switch structure.
- * @port: The port number on which the MAC address is to be checked.
- *
- * This function examines the MAC address set on the specified port and
- * determines if it can be used as a global address for the switch.
- *
- * Return: true if the port's MAC address can be used as a global address, false
- * otherwise.
- */
-bool ksz_is_port_mac_global_usable(struct dsa_switch *ds, int port)
-{
-	struct net_device *user = dsa_to_port(ds, port)->user;
-	const unsigned char *addr = user->dev_addr;
-	struct ksz_switch_macaddr *switch_macaddr;
-	struct ksz_device *dev = ds->priv;
-
-	ASSERT_RTNL();
-
-	switch_macaddr = dev->switch_macaddr;
-	if (switch_macaddr && !ether_addr_equal(switch_macaddr->addr, addr))
-		return false;
-
-	return true;
-}
-
 /**
  * ksz_switch_macaddr_get - Program the switch's MAC address register.
  * @ds: DSA switch instance.
@@ -4132,8 +3754,8 @@ static void ksz_parse_rgmii_delay(struct ksz_device *dev, int port_num,
  * Returns: If found, the corresponding register value for that drive strength
  * is returned. Otherwise, -EINVAL is returned indicating an invalid value.
  */
-static int ksz_drive_strength_to_reg(const struct ksz_drive_strength *array,
-				     size_t array_size, int microamp)
+int ksz_drive_strength_to_reg(const struct ksz_drive_strength *array,
+			      size_t array_size, int microamp)
 {
 	int i;
 
@@ -4156,9 +3778,9 @@ static int ksz_drive_strength_to_reg(const struct ksz_drive_strength *array,
  * is detected. It lists out all the supported drive strength values for
  * reference in the error message.
  */
-static void ksz_drive_strength_error(struct ksz_device *dev,
-				     const struct ksz_drive_strength *array,
-				     size_t array_size, int microamp)
+void ksz_drive_strength_error(struct ksz_device *dev,
+			      const struct ksz_drive_strength *array,
+			      size_t array_size, int microamp)
 {
 	char supported_values[100];
 	size_t remaining_size;
@@ -4185,8 +3807,8 @@ static void ksz_drive_strength_error(struct ksz_device *dev,
 }
 
 /**
- * ksz9477_drive_strength_write() - Set the drive strength for specific KSZ9477
- *				    chip variants.
+ * ksz_drive_strength_write() - Set the drive strength for specific KSZ9477
+ *				and the KSZ87xx chip variants.
  * @dev:       ksz device
  * @props:     Array of drive strength properties to be applied
  * @num_props: Number of properties in the array
@@ -4197,9 +3819,9 @@ static void ksz_drive_strength_error(struct ksz_device *dev,
  *
  * Return: 0 on successful configuration, a negative error code on failure.
  */
-static int ksz9477_drive_strength_write(struct ksz_device *dev,
-					struct ksz_driver_strength_prop *props,
-					int num_props)
+int ksz_drive_strength_write(struct ksz_device *dev,
+			     struct ksz_driver_strength_prop *props,
+			     int num_props)
 {
 	size_t array_size = ARRAY_SIZE(ksz9477_drive_strengths);
 	int i, ret, reg;
@@ -4236,130 +3858,6 @@ static int ksz9477_drive_strength_write(struct ksz_device *dev,
 	return ksz_rmw8(dev, reg, mask, val);
 }
 
-/**
- * ksz88x3_drive_strength_write() - Set the drive strength configuration for
- *				    KSZ8863 compatible chip variants.
- * @dev:       ksz device
- * @props:     Array of drive strength properties to be set
- * @num_props: Number of properties in the array
- *
- * This function applies the specified drive strength settings to KSZ88X3 chip
- * variants (KSZ8873, KSZ8863).
- * It ensures the configurations align with what the chip variant supports and
- * warns or errors out on unsupported settings.
- *
- * Return: 0 on success, error code otherwise
- */
-static int ksz88x3_drive_strength_write(struct ksz_device *dev,
-					struct ksz_driver_strength_prop *props,
-					int num_props)
-{
-	size_t array_size = ARRAY_SIZE(ksz88x3_drive_strengths);
-	int microamp;
-	int i, ret;
-
-	for (i = 0; i < num_props; i++) {
-		if (props[i].value == -1 || i == KSZ_DRIVER_STRENGTH_IO)
-			continue;
-
-		dev_warn(dev->dev, "%s is not supported by this chip variant\n",
-			 props[i].name);
-	}
-
-	microamp = props[KSZ_DRIVER_STRENGTH_IO].value;
-	ret = ksz_drive_strength_to_reg(ksz88x3_drive_strengths, array_size,
-					microamp);
-	if (ret < 0) {
-		ksz_drive_strength_error(dev, ksz88x3_drive_strengths,
-					 array_size, microamp);
-		return ret;
-	}
-
-	return ksz_rmw8(dev, KSZ8873_REG_GLOBAL_CTRL_12,
-			KSZ8873_DRIVE_STRENGTH_16MA, ret);
-}
-
-/**
- * ksz_parse_drive_strength() - Extract and apply drive strength configurations
- *				from device tree properties.
- * @dev:	ksz device
- *
- * This function reads the specified drive strength properties from the
- * device tree, validates against the supported chip variants, and sets
- * them accordingly. An error should be critical here, as the drive strength
- * settings are crucial for EMI compliance.
- *
- * Return: 0 on success, error code otherwise
- */
-int ksz_parse_drive_strength(struct ksz_device *dev)
-{
-	struct ksz_driver_strength_prop of_props[] = {
-		[KSZ_DRIVER_STRENGTH_HI] = {
-			.name = "microchip,hi-drive-strength-microamp",
-			.offset = SW_HI_SPEED_DRIVE_STRENGTH_S,
-			.value = -1,
-		},
-		[KSZ_DRIVER_STRENGTH_LO] = {
-			.name = "microchip,lo-drive-strength-microamp",
-			.offset = SW_LO_SPEED_DRIVE_STRENGTH_S,
-			.value = -1,
-		},
-		[KSZ_DRIVER_STRENGTH_IO] = {
-			.name = "microchip,io-drive-strength-microamp",
-			.offset = 0, /* don't care */
-			.value = -1,
-		},
-	};
-	struct device_node *np = dev->dev->of_node;
-	bool have_any_prop = false;
-	int i, ret;
-
-	for (i = 0; i < ARRAY_SIZE(of_props); i++) {
-		ret = of_property_read_u32(np, of_props[i].name,
-					   &of_props[i].value);
-		if (ret && ret != -EINVAL)
-			dev_warn(dev->dev, "Failed to read %s\n",
-				 of_props[i].name);
-		if (ret)
-			continue;
-
-		have_any_prop = true;
-	}
-
-	if (!have_any_prop)
-		return 0;
-
-	switch (dev->chip_id) {
-	case KSZ88X3_CHIP_ID:
-		return ksz88x3_drive_strength_write(dev, of_props,
-						    ARRAY_SIZE(of_props));
-	case KSZ8795_CHIP_ID:
-	case KSZ8794_CHIP_ID:
-	case KSZ8765_CHIP_ID:
-	case KSZ8563_CHIP_ID:
-	case KSZ8567_CHIP_ID:
-	case KSZ9477_CHIP_ID:
-	case KSZ9563_CHIP_ID:
-	case KSZ9567_CHIP_ID:
-	case KSZ9893_CHIP_ID:
-	case KSZ9896_CHIP_ID:
-	case KSZ9897_CHIP_ID:
-	case LAN9646_CHIP_ID:
-		return ksz9477_drive_strength_write(dev, of_props,
-						    ARRAY_SIZE(of_props));
-	default:
-		for (i = 0; i < ARRAY_SIZE(of_props); i++) {
-			if (of_props[i].value == -1)
-				continue;
-
-			dev_warn(dev->dev, "%s is not supported by this chip variant\n",
-				 of_props[i].name);
-		}
-	}
-
-	return 0;
-}
-
 static int ksz8463_configure_straps_spi(struct ksz_device *dev)
 {
 	struct pinctrl *pinctrl;
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index b4a5673ba365cb..acaf70e6f393c9 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -14,6 +14,7 @@
 #include <linux/phy.h>
 #include <linux/regmap.h>
 #include <net/dsa.h>
+#include <net/pkt_cls.h>
 #include <linux/irq.h>
 #include <linux/platform_data/microchip-ksz.h>
 
@@ -40,6 +41,45 @@ struct vlan_table {
 	u32 table[3];
 };
 
+struct ksz_stats_raw {
+	u64 rx_hi;
+	u64 rx_undersize;
+	u64 rx_fragments;
+	u64 rx_oversize;
+	u64 rx_jabbers;
+	u64 rx_symbol_err;
+	u64 rx_crc_err;
+	u64 rx_align_err;
+	u64 rx_mac_ctrl;
+	u64 rx_pause;
+	u64 rx_bcast;
+	u64 rx_mcast;
+	u64 rx_ucast;
+	u64 rx_64_or_less;
+	u64 rx_65_127;
+	u64 rx_128_255;
+	u64 rx_256_511;
+	u64 rx_512_1023;
+	u64 rx_1024_1522;
+	u64 rx_1523_2000;
+	u64 rx_2001;
+	u64 tx_hi;
+	u64 tx_late_col;
+	u64 tx_pause;
+	u64 tx_bcast;
+	u64 tx_mcast;
+	u64 tx_ucast;
+	u64 tx_deferred;
+	u64 tx_total_col;
+	u64 tx_exc_col;
+	u64 tx_single_col;
+	u64 tx_mult_col;
+	u64 rx_total;
+	u64 tx_total;
+	u64 rx_discards;
+	u64 tx_discards;
+};
+
 struct ksz_port_mib {
 	struct mutex cnt_mutex;		/* structure access */
 	u8 cnt_ptr;
@@ -393,12 +433,8 @@ int ksz_switch_resume(struct device *dev);
 void ksz_teardown(struct dsa_switch *ds);
 
 void ksz_init_mib_timer(struct ksz_device *dev);
-bool ksz_is_port_mac_global_usable(struct dsa_switch *ds, int port);
 void ksz_r_mib_stats64(struct ksz_device *dev, int port);
-void ksz88xx_r_mib_stats64(struct ksz_device *dev, int port);
 void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state);
-bool ksz_get_gbit(struct ksz_device *dev, int port);
-phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit);
 extern const struct ksz_chip_data ksz_switch_chips[];
 int ksz_switch_macaddr_get(struct dsa_switch *ds, int port,
 			   struct netlink_ext_ack *extack);
@@ -443,11 +479,15 @@ void ksz_phylink_mac_link_down(struct phylink_config *config,
 			       unsigned int mode,
 			       phy_interface_t interface);
 
-int ksz_max_mtu(struct dsa_switch *ds, int port);
-
 int ksz_set_mac_eee(struct dsa_switch *ds, int port,
 		    struct ethtool_keee *e);
 
+int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,
+			  int band);
+int ksz_setup_tc_cbs(struct dsa_switch *ds, int port,
+		     struct tc_cbs_qopt_offload *qopt);
+int ksz_tc_ets_validate(struct ksz_device *dev, int port,
+			struct tc_ets_qopt_offload_replace_params *p);
 int ksz_setup_tc(struct dsa_switch *ds, int port,
 		 enum tc_setup_type type, void *type_data);
 
@@ -471,8 +511,37 @@ int ksz_mdio_register(struct ksz_device *dev);
 int ksz_pirq_setup(struct ksz_device *dev, u8 p);
 int ksz_girq_setup(struct ksz_device *dev);
 void ksz_irq_free(struct ksz_irq *kirq);
-int ksz_parse_drive_strength(struct ksz_device *dev);
-int ksz9477_set_default_prio_queue_mapping(struct ksz_device *dev, int port);
+
+struct ksz_driver_strength_prop {
+	const char *name;
+	int offset;
+	int value;
+};
+
+enum ksz_driver_strength_type {
+	KSZ_DRIVER_STRENGTH_HI,
+	KSZ_DRIVER_STRENGTH_LO,
+	KSZ_DRIVER_STRENGTH_IO,
+};
+
+/**
+ * struct ksz_drive_strength - drive strength mapping
+ * @reg_val:	register value
+ * @microamp:	microamp value
+ */
+struct ksz_drive_strength {
+	u32 reg_val;
+	u32 microamp;
+};
+
+void ksz_drive_strength_error(struct ksz_device *dev,
+			      const struct ksz_drive_strength *array,
+			      size_t array_size, int microamp);
+int ksz_drive_strength_to_reg(const struct ksz_drive_strength *array,
+			      size_t array_size, int microamp);
+int ksz_drive_strength_write(struct ksz_device *dev,
+			     struct ksz_driver_strength_prop *props,
+			     int num_props);
 
 /* Common register access functions */
 static inline struct regmap *ksz_regmap_8(struct ksz_device *dev)
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index 8eb5337b0c102e..86ce3a86705f93 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -787,10 +787,6 @@ static int lan937x_setup(struct dsa_switch *ds)
 		return ret;
 	}
 
-	ret = ksz_parse_drive_strength(dev);
-	if (ret)
-		return ret;
-
 	/* set broadcast storm protection 10% rate */
 	storm_mask = BROADCAST_STORM_RATE;
 	storm_rate = (BROADCAST_STORM_VALUE * BROADCAST_STORM_PROT_RATE) / 100;
@@ -983,7 +979,7 @@ const struct dsa_switch_ops lan937x_switch_ops = {
 	.get_stats64		= ksz_get_stats64,
 	.get_pause_stats	= ksz_get_pause_stats,
 	.port_change_mtu	= lan937x_change_mtu,
-	.port_max_mtu		= ksz_max_mtu,
+	.port_max_mtu		= ksz9477_max_mtu,
 	.suspend		= ksz_suspend,
 	.resume			= ksz_resume,
 	.get_ts_info		= ksz_get_ts_info,

3/2 2026/07/02 13:56 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 24533
							output: 155
							thoughts: 3215
						

Thoughts:
**Refactoring the Microchip DSA Driver**

Okay, here's the deal. I'm looking at a patch series that's clearly focused on refactoring the `ksz` DSA driver for Microchip switches. My initial impression is that this is purely about tidying things up, making the code more organized and easier to maintain. We're talking about moving functions from `ksz_common.c` to more specific files like `ksz8.c` and `ksz9477.c`, based on the chip families they're intended for. The function names have been updated to reflect this specificity, with the old `ksz_` prefix being replaced with chip-specific prefixes, like `ksz87xx_`, `ksz88xx_`, and `ksz9477_`.

I've carefully compared the original implementations with their refactored counterparts. The core logic of the functions like `ksz_change_mtu`, `ksz_max_mtu`, and `ksz_setup_tc` (and their chip-specific variations) seems identical. No new functionality has been introduced in the driver, it looks like, just a reorganization of existing code. I've also checked `ksz_parse_drive_strength` which has been refactored in `lan937x_setup` and noticed that the change doesn't introduce any functional changes. It has been confirmed the removal just gets rid of warnings and doesn't affect operation.

The functions like `ksz88xx_r_mib_stats64`, the `ksz_parse_drive_strength` calls, and the `ksz9477_*` functions were also moved to be more chip-specific.

So, after a thorough review, it's pretty clear that this patch is a pure refactoring exercise. It's about improved code structure, not adding new features or fixing bugs. Therefore, there's no reason to flag this as "WorthFuzzing". It doesn't introduce any new attack surfaces or complex logic that would be exposed to fuzzing.



4/2 2026/07/02 13:57 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch is a pure refactoring of the Microchip KSZ DSA driver. It moves chip-specific functions (like MTU configuration, TC setup, MIB stats reading, and drive strength parsing) from the common `ksz_common.c` file to their respective chip-specific files (`ksz8.c` and `ksz9477.c`). It also removes a no-op call to `ksz_parse_drive_strength` in `lan937x_main.c` which only printed warnings for unsupported properties. No new functional logic or reachable code paths are introduced.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch is a pure refactoring of the Microchip KSZ DSA driver. It moves chip-specific functions (like MTU configuration, TC setup, MIB stats reading, and drive strength parsing) from the common `ksz_common.c` file to their respective chip-specific files (`ksz8.c` and `ksz9477.c`). It also removes a no-op call to `ksz_parse_drive_strength` in `lan937x_main.c` which only printed warnings for unsupported properties. No new functional logic or reachable code paths are introduced.",
  "WorthFuzzing": false
}

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)