AI Trajectory


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

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch modifies a driver for physical hardware (MaxLinear MxL862xx switch) which is an MDIO device. There is no software emulator for this hardware in virtualized environments like QEMU or GCE, making the code unreachable during fuzzing.",
  "WorthFuzzing": false
}

1/1 2026/07/14 04:57 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit ba2f02d5c337d08c36f1b72383d98da50811284e\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Tue Jul 14 04:57:19 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/dsa/mxl862xx/Makefile b/drivers/net/dsa/mxl862xx/Makefile\nindex a7be0e6669dfa5..bccac0d0f703f6 100644\n--- a/drivers/net/dsa/mxl862xx/Makefile\n+++ b/drivers/net/dsa/mxl862xx/Makefile\n@@ -1,3 +1,3 @@\n # SPDX-License-Identifier: GPL-2.0\n obj-$(CONFIG_NET_DSA_MXL862) += mxl862xx_dsa.o\n-mxl862xx_dsa-y := mxl862xx.o mxl862xx-host.o mxl862xx-phylink.o\n+mxl862xx_dsa-y := mxl862xx.o mxl862xx-host.o mxl862xx-phylink.o mxl862xx-fw.o\ndiff --git a/drivers/net/dsa/mxl862xx/mxl862xx-cmd.h b/drivers/net/dsa/mxl862xx/mxl862xx-cmd.h\nindex c87a955c13c48e..e2aa2934e9e162 100644\n--- a/drivers/net/dsa/mxl862xx/mxl862xx-cmd.h\n+++ b/drivers/net/dsa/mxl862xx/mxl862xx-cmd.h\n@@ -70,6 +70,7 @@\n #define INT_GPHY_READ\t\t\t(GPY_GPY2XX_MAGIC + 0x1)\n #define INT_GPHY_WRITE\t\t\t(GPY_GPY2XX_MAGIC + 0x2)\n \n+#define SYS_MISC_FW_UPDATE\t\t(SYS_MISC_MAGIC + 0x1)\n #define SYS_MISC_FW_VERSION\t\t(SYS_MISC_MAGIC + 0x2)\n \n #define MXL862XX_XPCS_PCS_CONFIG\t(MXL862XX_XPCS_MAGIC + 0x1)\ndiff --git a/drivers/net/dsa/mxl862xx/mxl862xx-fw.c b/drivers/net/dsa/mxl862xx/mxl862xx-fw.c\nnew file mode 100644\nindex 00000000000000..88d53bea336fd5\n--- /dev/null\n+++ b/drivers/net/dsa/mxl862xx/mxl862xx-fw.c\n@@ -0,0 +1,439 @@\n+// SPDX-License-Identifier: GPL-2.0-or-later\n+/*\n+ * Firmware flash and devlink support for MaxLinear MxL862xx\n+ *\n+ * Copyright (C) 2025 Daniel Golle \u003cdaniel@makrotopia.org\u003e\n+ */\n+\n+#include \u003clinux/crc32.h\u003e\n+#include \u003clinux/delay.h\u003e\n+#include \u003clinux/device.h\u003e\n+#include \u003clinux/module.h\u003e\n+#include \u003clinux/netdevice.h\u003e\n+#include \u003clinux/of.h\u003e\n+#include \u003clinux/rtnetlink.h\u003e\n+#include \u003cnet/dsa.h\u003e\n+\n+#include \"mxl862xx.h\"\n+#include \"mxl862xx-api.h\"\n+#include \"mxl862xx-cmd.h\"\n+#include \"mxl862xx-fw.h\"\n+#include \"mxl862xx-host.h\"\n+\n+/* SB PDI registers (clause-22 SMDIO address space) */\n+#define MXL862XX_SB_PDI_CTRL\t\t0xe100\n+#define MXL862XX_SB_PDI_ADDR\t\t0xe101\n+#define MXL862XX_SB_PDI_DATA\t\t0xe102\n+#define MXL862XX_SB_PDI_STAT\t\t0xe103\n+\n+/* SB PDI CTRL modes */\n+#define MXL862XX_SB_PDI_CTRL_RST\t0x00\n+#define MXL862XX_SB_PDI_CTRL_WR\t0x02\n+\n+/* SB PDI handshake magic */\n+#define MXL862XX_SB_PDI_READY\t\t0xc55c\n+#define MXL862XX_SB_PDI_START\t\t0xf48f\n+#define MXL862XX_SB_PDI_END\t\t0x3cc3\n+\n+/* Firmware transfer geometry */\n+#define MXL862XX_FW_HDR_SIZE\t\t20\n+#define MXL862XX_FW_BANK_HALF\t\t16384\t/* words per half-bank */\n+#define MXL862XX_FW_BANK_SLICE\t\t32760\t/* words per full slice */\n+#define MXL862XX_FW_SB1_ADDR\t\t0x7800\t/* SB1 word address */\n+\n+/* Timeouts (generous upper bounds) */\n+#define MXL862XX_FW_READY_TIMEOUT_MS\t30000\n+#define MXL862XX_FW_ACK_TIMEOUT_MS\t5000\n+#define MXL862XX_FW_ERASE_TIMEOUT_MS\t300000\n+#define MXL862XX_FW_WRITE_TIMEOUT_MS\t120000\n+#define MXL862XX_FW_REBOOT_DELAY_MS\t5000\n+\n+static void mxl862xx_sb_pdi_reset(struct mxl862xx_priv *priv)\n+{\n+\tmxl862xx_smdio_write(priv, MXL862XX_SB_PDI_CTRL,\n+\t\t\t     MXL862XX_SB_PDI_CTRL_RST);\n+\tmxl862xx_smdio_write(priv, MXL862XX_SB_PDI_ADDR,\n+\t\t\t     MXL862XX_SB_PDI_CTRL_RST);\n+\tmxl862xx_smdio_write(priv, MXL862XX_SB_PDI_DATA,\n+\t\t\t     MXL862XX_SB_PDI_CTRL_RST);\n+}\n+\n+static int mxl862xx_sb_pdi_poll_stat(struct mxl862xx_priv *priv, u16 expected,\n+\t\t\t\t     unsigned long timeout_ms)\n+{\n+\tunsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);\n+\tint ret;\n+\n+\tdo {\n+\t\tret = mxl862xx_smdio_read(priv, MXL862XX_SB_PDI_STAT);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t\tif ((u16)ret == expected)\n+\t\t\treturn 0;\n+\t\tusleep_range(10000, 11000);\n+\t} while (time_before(jiffies, timeout));\n+\n+\treturn -ETIMEDOUT;\n+}\n+\n+static int mxl862xx_sb_pdi_flush_slice(struct mxl862xx_priv *priv,\n+\t\t\t\t       u32 data_written)\n+{\n+\tmxl862xx_sb_pdi_reset(priv);\n+\tmxl862xx_smdio_write(priv, MXL862XX_SB_PDI_STAT, data_written);\n+\n+\treturn mxl862xx_sb_pdi_poll_stat(priv, 0,\n+\t\t\t\t\t MXL862XX_FW_WRITE_TIMEOUT_MS);\n+}\n+\n+static void mxl862xx_flash_notify(struct devlink *dl, const char *status,\n+\t\t\t\t  u32 done, u32 total)\n+{\n+\tdevlink_flash_update_status_notify(dl, status, NULL, done, total);\n+}\n+\n+/**\n+ * mxl862xx_rescue_mode_detect - check whether the switch sits in MCUboot\n+ * @priv: driver private data\n+ *\n+ * MCUboot signals readiness for a firmware download with the SB PDI\n+ * ready magic; only the clause-22 SMDIO interface works in this state.\n+ *\n+ * Return: true if MCUboot is waiting for a firmware download.\n+ */\n+bool mxl862xx_rescue_mode_detect(struct mxl862xx_priv *priv)\n+{\n+\tint ret;\n+\n+\tret = mxl862xx_smdio_read(priv, MXL862XX_SB_PDI_STAT);\n+\n+\treturn ret == MXL862XX_SB_PDI_READY;\n+}\n+\n+/* device_reprobe() -\u003e remove() frees priv while the work runs, so\n+ * the work struct cannot live in mxl862xx_priv.\n+ */\n+struct mxl862xx_reprobe {\n+\tstruct device *dev;\n+\tstruct delayed_work dwork;\n+};\n+\n+static void mxl862xx_reprobe_work_fn(struct work_struct *work)\n+{\n+\tstruct mxl862xx_reprobe *reprobe =\n+\t\tcontainer_of(work, struct mxl862xx_reprobe, dwork.work);\n+\n+\tif (device_reprobe(reprobe-\u003edev))\n+\t\tdev_err(reprobe-\u003edev, \"reprobe failed\\n\");\n+\tput_device(reprobe-\u003edev);\n+\tkfree(reprobe);\n+\tmodule_put(THIS_MODULE);\n+}\n+\n+/* MCUboot firmware image header */\n+struct mxl862xx_fw_hdr {\n+\t__le32 image_type;\n+\t__le32 image_size_1;\n+\t__le32 image_checksum_1;\n+\t__le32 image_size_2;\n+\t__le32 image_checksum_2;\n+} __packed;\n+\n+static int mxl862xx_flash_firmware(struct mxl862xx_priv *priv,\n+\t\t\t\t   const struct firmware *fw,\n+\t\t\t\t   struct devlink *dl)\n+{\n+\tconst struct mxl862xx_fw_hdr *hdr;\n+\tu32 word_idx = 0, data_written = 0, idx = 0;\n+\tunsigned long next_notify = 0;\n+\tconst u8 *payload;\n+\tu32 payload_size;\n+\tu16 word, fdata;\n+\tint ret, i;\n+\tu32 crc;\n+\n+\tif (fw-\u003esize \u003c MXL862XX_FW_HDR_SIZE)\n+\t\treturn -EINVAL;\n+\n+\thdr = (const struct mxl862xx_fw_hdr *)fw-\u003edata;\n+\tpayload = fw-\u003edata + MXL862XX_FW_HDR_SIZE;\n+\tpayload_size = le32_to_cpu(hdr-\u003eimage_size_1) +\n+\t\t       le32_to_cpu(hdr-\u003eimage_size_2);\n+\n+\tif (payload_size \u003e fw-\u003esize - MXL862XX_FW_HDR_SIZE) {\n+\t\tdev_err(\u0026priv-\u003emdiodev-\u003edev,\n+\t\t\t\"flash: firmware file too small for declared size\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (le32_to_cpu(hdr-\u003eimage_size_1)) {\n+\t\tcrc = ~crc32_le(~0U, payload,\n+\t\t\t\tle32_to_cpu(hdr-\u003eimage_size_1));\n+\t\tif (crc != le32_to_cpu(hdr-\u003eimage_checksum_1)) {\n+\t\t\tdev_err(\u0026priv-\u003emdiodev-\u003edev,\n+\t\t\t\t\"flash: image 1 CRC mismatch (got %08x, expected %08x)\\n\",\n+\t\t\t\tcrc, le32_to_cpu(hdr-\u003eimage_checksum_1));\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\tif (le32_to_cpu(hdr-\u003eimage_size_2)) {\n+\t\tcrc = ~crc32_le(~0U,\n+\t\t\t\tpayload + le32_to_cpu(hdr-\u003eimage_size_1),\n+\t\t\t\tle32_to_cpu(hdr-\u003eimage_size_2));\n+\t\tif (crc != le32_to_cpu(hdr-\u003eimage_checksum_2)) {\n+\t\t\tdev_err(\u0026priv-\u003emdiodev-\u003edev,\n+\t\t\t\t\"flash: image 2 CRC mismatch (got %08x, expected %08x)\\n\",\n+\t\t\t\tcrc, le32_to_cpu(hdr-\u003eimage_checksum_2));\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\t/* Step 1: reboot the firmware into MCUboot rescue mode */\n+\tif (!priv-\u003erescue_mode) {\n+\t\tret = mxl862xx_api_wrap(priv, SYS_MISC_FW_UPDATE, NULL, 0,\n+\t\t\t\t\tfalse, false);\n+\t\tif (ret) {\n+\t\t\tdev_err(\u0026priv-\u003emdiodev-\u003edev,\n+\t\t\t\t\"flash: FW_UPDATE command failed: %pe\\n\",\n+\t\t\t\tERR_PTR(ret));\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\t/* Failures from here on must go through end_magic so MCUboot\n+\t * reboots instead of waiting forever.\n+\t */\n+\n+\t/* Step 2: wait for bootloader ready */\n+\tmxl862xx_flash_notify(dl, \"Waiting for bootloader\", 0, 0);\n+\tmxl862xx_sb_pdi_reset(priv);\n+\tret = mxl862xx_sb_pdi_poll_stat(priv, MXL862XX_SB_PDI_READY,\n+\t\t\t\t\tMXL862XX_FW_READY_TIMEOUT_MS);\n+\tif (ret) {\n+\t\tdev_err(\u0026priv-\u003emdiodev-\u003edev,\n+\t\t\t\"flash: bootloader not ready: %pe\\n\", ERR_PTR(ret));\n+\t\tgoto end_magic;\n+\t}\n+\n+\t/* Step 3: start handshake */\n+\tmxl862xx_smdio_write(priv, MXL862XX_SB_PDI_STAT,\n+\t\t\t     MXL862XX_SB_PDI_START);\n+\tret = mxl862xx_sb_pdi_poll_stat(priv, MXL862XX_SB_PDI_START + 1,\n+\t\t\t\t\tMXL862XX_FW_ACK_TIMEOUT_MS);\n+\tif (ret) {\n+\t\tdev_err(\u0026priv-\u003emdiodev-\u003edev,\n+\t\t\t\"flash: start handshake failed: %pe\\n\", ERR_PTR(ret));\n+\t\tgoto end_magic;\n+\t}\n+\n+\t/* Step 4: transfer image header */\n+\tmxl862xx_flash_notify(dl, \"Erasing flash\", 0, 0);\n+\tmxl862xx_smdio_write(priv, MXL862XX_SB_PDI_CTRL,\n+\t\t\t     MXL862XX_SB_PDI_CTRL_WR);\n+\tfor (i = 0; i \u003c MXL862XX_FW_HDR_SIZE / 2; i++) {\n+\t\tword = fw-\u003edata[i * 2] |\n+\t\t       ((u16)fw-\u003edata[i * 2 + 1] \u003c\u003c 8);\n+\t\tmxl862xx_smdio_write(priv, MXL862XX_SB_PDI_DATA, word);\n+\t}\n+\tmxl862xx_sb_pdi_reset(priv);\n+\n+\t/* the byte count in STAT triggers the erase */\n+\tmxl862xx_smdio_write(priv, MXL862XX_SB_PDI_STAT,\n+\t\t\t     MXL862XX_FW_HDR_SIZE);\n+\n+\t/* ACK is byte count + 1 */\n+\tret = mxl862xx_sb_pdi_poll_stat(priv, MXL862XX_FW_HDR_SIZE + 1,\n+\t\t\t\t\tMXL862XX_FW_ACK_TIMEOUT_MS);\n+\tif (ret) {\n+\t\tdev_err(\u0026priv-\u003emdiodev-\u003edev,\n+\t\t\t\"flash: header ACK failed: %pe\\n\", ERR_PTR(ret));\n+\t\tgoto end_magic;\n+\t}\n+\n+\t/* Step 5: wait for erase to complete */\n+\tret = mxl862xx_sb_pdi_poll_stat(priv, 0,\n+\t\t\t\t\tMXL862XX_FW_ERASE_TIMEOUT_MS);\n+\tif (ret) {\n+\t\tdev_err(\u0026priv-\u003emdiodev-\u003edev,\n+\t\t\t\"flash: erase timeout: %pe\\n\", ERR_PTR(ret));\n+\t\tgoto end_magic;\n+\t}\n+\n+\t/* Step 6: transfer payload */\n+\tmxl862xx_smdio_write(priv, MXL862XX_SB_PDI_CTRL,\n+\t\t\t     MXL862XX_SB_PDI_CTRL_WR);\n+\n+\twhile (idx \u003c payload_size) {\n+\t\tif (idx + 1 \u003c payload_size) {\n+\t\t\tfdata = payload[idx] |\n+\t\t\t\t((u16)payload[idx + 1] \u003c\u003c 8);\n+\t\t\tidx += 2;\n+\t\t\tdata_written += 2;\n+\t\t} else {\n+\t\t\tfdata = payload[idx];\n+\t\t\tidx++;\n+\t\t\tdata_written++;\n+\t\t}\n+\n+\t\tmxl862xx_smdio_write(priv, MXL862XX_SB_PDI_DATA, fdata);\n+\t\tword_idx++;\n+\n+\t\tif (idx \u003e= payload_size) {\n+\t\t\tret = mxl862xx_sb_pdi_flush_slice(priv, data_written);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\t/* Half-bank boundary: switch to SB1 address */\n+\t\tif (word_idx == MXL862XX_FW_BANK_HALF) {\n+\t\t\tmxl862xx_smdio_write(priv, MXL862XX_SB_PDI_CTRL,\n+\t\t\t\t\t     MXL862XX_SB_PDI_CTRL_RST);\n+\t\t\tmxl862xx_smdio_write(priv, MXL862XX_SB_PDI_ADDR,\n+\t\t\t\t\t     MXL862XX_FW_SB1_ADDR);\n+\t\t\tmxl862xx_smdio_write(priv, MXL862XX_SB_PDI_CTRL,\n+\t\t\t\t\t     MXL862XX_SB_PDI_CTRL_WR);\n+\t\t} else if (word_idx \u003e= MXL862XX_FW_BANK_SLICE) {\n+\t\t\tret = mxl862xx_sb_pdi_flush_slice(priv, data_written);\n+\t\t\tif (ret) {\n+\t\t\t\tdev_err(\u0026priv-\u003emdiodev-\u003edev,\n+\t\t\t\t\t\"flash: write timeout at %u/%u: %pe\\n\",\n+\t\t\t\t\tidx, payload_size, ERR_PTR(ret));\n+\t\t\t\tgoto end_magic;\n+\t\t\t}\n+\t\t\tword_idx = 0;\n+\t\t\tdata_written = 0;\n+\t\t\tmxl862xx_smdio_write(priv, MXL862XX_SB_PDI_CTRL,\n+\t\t\t\t\t     MXL862XX_SB_PDI_CTRL_WR);\n+\n+\t\t\tif (time_after(jiffies, next_notify)) {\n+\t\t\t\tmxl862xx_flash_notify(dl, \"Flashing\", idx,\n+\t\t\t\t\t\t      payload_size);\n+\t\t\t\tnext_notify = jiffies + msecs_to_jiffies(500);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tif (ret) {\n+\t\tdev_err(\u0026priv-\u003emdiodev-\u003edev,\n+\t\t\t\"flash: final write timeout: %pe\\n\", ERR_PTR(ret));\n+\t\tgoto end_magic;\n+\t}\n+\n+\tmxl862xx_flash_notify(dl, \"Flashing\", payload_size, payload_size);\n+\n+end_magic:\n+\t/* reboot MCUboot even after a failed transfer */\n+\tmxl862xx_smdio_write(priv, MXL862XX_SB_PDI_STAT,\n+\t\t\t     MXL862XX_SB_PDI_END);\n+\tmsleep(MXL862XX_FW_REBOOT_DELAY_MS);\n+\n+\treturn ret;\n+}\n+\n+int mxl862xx_devlink_info_get(struct dsa_switch *ds,\n+\t\t\t      struct devlink_info_req *req,\n+\t\t\t      struct netlink_ext_ack *extack)\n+{\n+\tstruct mxl862xx_priv *priv = ds-\u003epriv;\n+\tconst char *compatible;\n+\tchar ver_str[32];\n+\tint ret;\n+\n+\tif (!of_property_read_string_index(ds-\u003edev-\u003eof_node, \"compatible\", 0,\n+\t\t\t\t\t   \u0026compatible)) {\n+\t\tret = devlink_info_version_fixed_put(req,\n+\t\t\t\t\t\t     DEVLINK_INFO_VERSION_GENERIC_ASIC_ID,\n+\t\t\t\t\t\t     compatible);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\tif (priv-\u003erescue_mode)\n+\t\treturn devlink_info_version_running_put(req, \"fw\",\n+\t\t\t\t\t\t\t\"mcuboot-rescue\");\n+\n+\tsnprintf(ver_str, sizeof(ver_str), \"%u.%u.%u\",\n+\t\t priv-\u003efw_version.major, priv-\u003efw_version.minor,\n+\t\t priv-\u003efw_version.revision);\n+\n+\treturn devlink_info_version_running_put(req, \"fw\", ver_str);\n+}\n+\n+int mxl862xx_devlink_flash_update(struct dsa_switch *ds,\n+\t\t\t\t  struct devlink_flash_update_params *params,\n+\t\t\t\t  struct netlink_ext_ack *extack)\n+{\n+\tstruct mxl862xx_priv *priv = ds-\u003epriv;\n+\tstruct mxl862xx_sys_fw_image_version ver = {};\n+\tstruct mxl862xx_reprobe *reprobe;\n+\tstruct dsa_port *dp;\n+\tint ret, i;\n+\n+\tif (params-\u003ecomponent) {\n+\t\tNL_SET_ERR_MSG_MOD(extack, \"component is not supported\");\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+\n+\tif (priv-\u003erescue_mode)\n+\t\tdev_info(ds-\u003edev,\n+\t\t\t \"flash: recovering switch from MCUboot rescue mode\\n\");\n+\telse\n+\t\tdev_info(ds-\u003edev, \"flash: running firmware %u.%u.%u\\n\",\n+\t\t\t priv-\u003efw_version.major, priv-\u003efw_version.minor,\n+\t\t\t priv-\u003efw_version.revision);\n+\n+\t/* Close ports while the firmware is still alive so the DSA\n+\t * core's MDB/FDB tracking is drained, and detach user ports\n+\t * so userspace cannot reopen them during the flash. The\n+\t * conduit belongs to the MAC driver and is only closed.\n+\t */\n+\trtnl_lock();\n+\tdsa_switch_for_each_user_port(dp, ds) {\n+\t\tif (dp-\u003euser) {\n+\t\t\tdev_close(dp-\u003euser);\n+\t\t\tnetif_device_detach(dp-\u003euser);\n+\t\t}\n+\t}\n+\tdsa_switch_for_each_cpu_port(dp, ds)\n+\t\tdev_close(dp-\u003econduit);\n+\trtnl_unlock();\n+\n+\tpriv-\u003eblock_host = true;\n+\n+\tcancel_delayed_work_sync(\u0026priv-\u003estats_work);\n+\tfor (i = 0; i \u003c ds-\u003enum_ports; i++)\n+\t\tcancel_work_sync(\u0026priv-\u003eports[i].host_flood_work);\n+\n+\tret = mxl862xx_flash_firmware(priv, params-\u003efw, ds-\u003edevlink);\n+\tif (ret)\n+\t\tNL_SET_ERR_MSG_MOD(extack, \"firmware transfer failed\");\n+\n+\tif (!ret) {\n+\t\t/* lift the block to query the new firmware version */\n+\t\tpriv-\u003eblock_host = false;\n+\t\tpriv-\u003erescue_mode = false;\n+\t\tmemset(\u0026ver, 0, sizeof(ver));\n+\t\tif (!MXL862XX_API_READ_QUIET(priv, SYS_MISC_FW_VERSION, ver) \u0026\u0026\n+\t\t    ver.iv_major)\n+\t\t\tdev_info(ds-\u003edev, \"flash: new firmware %u.%u.%u\\n\",\n+\t\t\t\t ver.iv_major, ver.iv_minor,\n+\t\t\t\t le16_to_cpu(ver.iv_revision));\n+\t}\n+\n+\tpriv-\u003eskip_teardown = true;\n+\n+\treprobe = kzalloc_obj(*reprobe);\n+\tif (!reprobe)\n+\t\treturn ret;\n+\n+\tif (!try_module_get(THIS_MODULE)) {\n+\t\tkfree(reprobe);\n+\t\treturn ret;\n+\t}\n+\n+\treprobe-\u003edev = get_device(ds-\u003edev);\n+\tINIT_DELAYED_WORK(\u0026reprobe-\u003edwork, mxl862xx_reprobe_work_fn);\n+\tschedule_delayed_work(\u0026reprobe-\u003edwork, msecs_to_jiffies(500));\n+\n+\treturn ret;\n+}\ndiff --git a/drivers/net/dsa/mxl862xx/mxl862xx-fw.h b/drivers/net/dsa/mxl862xx/mxl862xx-fw.h\nnew file mode 100644\nindex 00000000000000..57c2000cfee519\n--- /dev/null\n+++ b/drivers/net/dsa/mxl862xx/mxl862xx-fw.h\n@@ -0,0 +1,18 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+\n+#ifndef __MXL862XX_FW_H\n+#define __MXL862XX_FW_H\n+\n+#include \u003cnet/dsa.h\u003e\n+\n+struct mxl862xx_priv;\n+\n+bool mxl862xx_rescue_mode_detect(struct mxl862xx_priv *priv);\n+int mxl862xx_devlink_info_get(struct dsa_switch *ds,\n+\t\t\t      struct devlink_info_req *req,\n+\t\t\t      struct netlink_ext_ack *extack);\n+int mxl862xx_devlink_flash_update(struct dsa_switch *ds,\n+\t\t\t\t  struct devlink_flash_update_params *params,\n+\t\t\t\t  struct netlink_ext_ack *extack);\n+\n+#endif /* __MXL862XX_FW_H */\ndiff --git a/drivers/net/dsa/mxl862xx/mxl862xx-host.c b/drivers/net/dsa/mxl862xx/mxl862xx-host.c\nindex 4acd216f7cc009..d6c0cdfa0e6892 100644\n--- a/drivers/net/dsa/mxl862xx/mxl862xx-host.c\n+++ b/drivers/net/dsa/mxl862xx/mxl862xx-host.c\n@@ -15,6 +15,7 @@\n #include \u003clinux/unaligned.h\u003e\n #include \u003cnet/dsa.h\u003e\n #include \"mxl862xx.h\"\n+#include \"mxl862xx-cmd.h\"\n #include \"mxl862xx-host.h\"\n \n #define CTRL_BUSY_MASK\t\t\tBIT(15)\n@@ -336,6 +337,15 @@ int mxl862xx_api_wrap(struct mxl862xx_priv *priv, u16 cmd, void *_data,\n \tint ret, cmd_ret;\n \tu16 max, crc, i;\n \n+\tif (priv-\u003eskip_teardown)\n+\t\treturn 0;\n+\n+\tif (priv-\u003erescue_mode)\n+\t\treturn -ENODEV;\n+\n+\tif (priv-\u003eblock_host \u0026\u0026 cmd != SYS_MISC_FW_UPDATE)\n+\t\treturn -EBUSY;\n+\n \tdev_dbg(\u0026priv-\u003emdiodev-\u003edev, \"CMD %04x DATA %*ph\\n\", cmd, size, data);\n \n \tmutex_lock_nested(\u0026priv-\u003emdiodev-\u003ebus-\u003emdio_lock, MDIO_MUTEX_NESTED);\n@@ -495,6 +505,41 @@ int mxl862xx_reset(struct mxl862xx_priv *priv)\n \treturn ret;\n }\n \n+#define MXL862XX_SMDIO_ADDR_REG\t\t0x1f\n+#define MXL862XX_SMDIO_PAGE_MASK\t0xfff0\n+#define MXL862XX_SMDIO_OFF_MASK\t\t0x000f\n+\n+int mxl862xx_smdio_read(struct mxl862xx_priv *priv, u32 addr)\n+{\n+\tstruct mii_bus *bus = priv-\u003emdiodev-\u003ebus;\n+\tint phy = priv-\u003emdiodev-\u003eaddr;\n+\tint ret;\n+\n+\tmutex_lock(\u0026bus-\u003emdio_lock);\n+\tret = __mdiobus_write(bus, phy, MXL862XX_SMDIO_ADDR_REG,\n+\t\t\t      addr \u0026 MXL862XX_SMDIO_PAGE_MASK);\n+\tif (ret \u003e= 0)\n+\t\tret = __mdiobus_read(bus, phy, addr \u0026 MXL862XX_SMDIO_OFF_MASK);\n+\tmutex_unlock(\u0026bus-\u003emdio_lock);\n+\treturn ret;\n+}\n+\n+int mxl862xx_smdio_write(struct mxl862xx_priv *priv, u32 addr, u16 val)\n+{\n+\tstruct mii_bus *bus = priv-\u003emdiodev-\u003ebus;\n+\tint phy = priv-\u003emdiodev-\u003eaddr;\n+\tint ret;\n+\n+\tmutex_lock(\u0026bus-\u003emdio_lock);\n+\tret = __mdiobus_write(bus, phy, MXL862XX_SMDIO_ADDR_REG,\n+\t\t\t      addr \u0026 MXL862XX_SMDIO_PAGE_MASK);\n+\tif (ret \u003e= 0)\n+\t\tret = __mdiobus_write(bus, phy, addr \u0026 MXL862XX_SMDIO_OFF_MASK,\n+\t\t\t\t      val);\n+\tmutex_unlock(\u0026bus-\u003emdio_lock);\n+\treturn ret;\n+}\n+\n void mxl862xx_host_init(struct mxl862xx_priv *priv)\n {\n \tINIT_WORK(\u0026priv-\u003ecrc_err_work, mxl862xx_crc_err_work_fn);\ndiff --git a/drivers/net/dsa/mxl862xx/mxl862xx-host.h b/drivers/net/dsa/mxl862xx/mxl862xx-host.h\nindex 66d6ae198aff45..4e054c6e4c0e40 100644\n--- a/drivers/net/dsa/mxl862xx/mxl862xx-host.h\n+++ b/drivers/net/dsa/mxl862xx/mxl862xx-host.h\n@@ -18,5 +18,7 @@ int mxl862xx_api_wrap(struct mxl862xx_priv *priv, u16 cmd, void *data, u16 size,\n \tmxl862xx_api_wrap(dev, cmd, \u0026(data), sizeof((data)), true, true)\n \n int mxl862xx_reset(struct mxl862xx_priv *priv);\n+int mxl862xx_smdio_read(struct mxl862xx_priv *priv, u32 addr);\n+int mxl862xx_smdio_write(struct mxl862xx_priv *priv, u32 addr, u16 val);\n \n #endif /* __MXL862XX_HOST_H */\ndiff --git a/drivers/net/dsa/mxl862xx/mxl862xx-phylink.c b/drivers/net/dsa/mxl862xx/mxl862xx-phylink.c\nindex b689652aa9b920..a5b6940b552e9e 100644\n--- a/drivers/net/dsa/mxl862xx/mxl862xx-phylink.c\n+++ b/drivers/net/dsa/mxl862xx/mxl862xx-phylink.c\n@@ -406,6 +406,8 @@ mxl862xx_phylink_mac_select_pcs(struct phylink_config *config,\n \n \tswitch (port) {\n \tcase 9 ... 16:\n+\t\tif (priv-\u003erescue_mode)\n+\t\t\treturn NULL;\n \t\tif (!MXL862XX_FW_VER_MIN(priv, 1, 0, 84)) {\n \t\t\tdev_warn_once(dp-\u003eds-\u003edev,\n \t\t\t\t      \"SerDes PCS unsupported on old firmware.\\n\");\ndiff --git a/drivers/net/dsa/mxl862xx/mxl862xx.c b/drivers/net/dsa/mxl862xx/mxl862xx.c\nindex 45d237b3a40f10..b7385cfa547458 100644\n--- a/drivers/net/dsa/mxl862xx/mxl862xx.c\n+++ b/drivers/net/dsa/mxl862xx/mxl862xx.c\n@@ -21,6 +21,7 @@\n #include \"mxl862xx.h\"\n #include \"mxl862xx-api.h\"\n #include \"mxl862xx-cmd.h\"\n+#include \"mxl862xx-fw.h\"\n #include \"mxl862xx-host.h\"\n #include \"mxl862xx-phylink.h\"\n \n@@ -628,9 +629,22 @@ static int mxl862xx_setup(struct dsa_switch *ds)\n \tif (ret)\n \t\treturn ret;\n \n-\tret = mxl862xx_wait_ready(ds);\n-\tif (ret)\n-\t\treturn ret;\n+\tpriv-\u003erescue_mode = mxl862xx_rescue_mode_detect(priv);\n+\tif (!priv-\u003erescue_mode) {\n+\t\tret = mxl862xx_wait_ready(ds);\n+\t\tif (ret) {\n+\t\t\t/* the reset may only now have triggered rescue mode */\n+\t\t\tpriv-\u003erescue_mode = mxl862xx_rescue_mode_detect(priv);\n+\t\t\tif (!priv-\u003erescue_mode)\n+\t\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\tif (priv-\u003erescue_mode) {\n+\t\tdev_warn(ds-\u003edev,\n+\t\t\t \"switch stuck in MCUboot rescue mode, use devlink to flash new firmware\\n\");\n+\t\treturn 0;\n+\t}\n \n \tmutex_init(\u0026priv-\u003eserdes_lock);\n \tfor (i = 0; i \u003c ARRAY_SIZE(priv-\u003eserdes_ports); i++)\n@@ -715,11 +729,21 @@ static int mxl862xx_port_state(struct dsa_switch *ds, int port, bool enable)\n static int mxl862xx_port_enable(struct dsa_switch *ds, int port,\n \t\t\t\tstruct phy_device *phydev)\n {\n+\tstruct mxl862xx_priv *priv = ds-\u003epriv;\n+\n+\tif (priv-\u003erescue_mode)\n+\t\treturn 0;\n+\n \treturn mxl862xx_port_state(ds, port, true);\n }\n \n static void mxl862xx_port_disable(struct dsa_switch *ds, int port)\n {\n+\tstruct mxl862xx_priv *priv = ds-\u003epriv;\n+\n+\tif (priv-\u003erescue_mode)\n+\t\treturn;\n+\n \tif (mxl862xx_port_state(ds, port, false))\n \t\tdev_err(ds-\u003edev, \"failed to disable port %d\\n\", port);\n }\n@@ -1337,6 +1361,12 @@ static int mxl862xx_port_setup(struct dsa_switch *ds, int port)\n \tbool is_cpu_port = dsa_port_is_cpu(dp);\n \tint ret;\n \n+\t/* DSA reinits failed user ports as unused; shared ports must\n+\t * succeed for the tree to register.\n+\t */\n+\tif (priv-\u003erescue_mode)\n+\t\treturn dsa_port_is_user(dp) ? -ENODEV : 0;\n+\n \tret = mxl862xx_port_state(ds, port, false);\n \tif (ret)\n \t\treturn ret;\n@@ -1628,6 +1658,9 @@ static void mxl862xx_port_stp_state_set(struct dsa_switch *ds, int port,\n \tstruct mxl862xx_priv *priv = ds-\u003epriv;\n \tint ret;\n \n+\tif (priv-\u003erescue_mode)\n+\t\treturn;\n+\n \tswitch (state) {\n \tcase BR_STATE_DISABLED:\n \t\tparam.port_state = cpu_to_le32(MXL862XX_STP_PORT_STATE_DISABLE);\n@@ -2086,6 +2119,8 @@ static const struct dsa_switch_ops mxl862xx_switch_ops = {\n \t.get_pause_stats = mxl862xx_get_pause_stats,\n \t.get_rmon_stats = mxl862xx_get_rmon_stats,\n \t.get_stats64 = mxl862xx_get_stats64,\n+\t.devlink_info_get = mxl862xx_devlink_info_get,\n+\t.devlink_flash_update = mxl862xx_devlink_flash_update,\n };\n \n static int mxl862xx_probe(struct mdio_device *mdiodev)\ndiff --git a/drivers/net/dsa/mxl862xx/mxl862xx.h b/drivers/net/dsa/mxl862xx/mxl862xx.h\nindex 432a5f3f2e08e6..5d21296561e3aa 100644\n--- a/drivers/net/dsa/mxl862xx/mxl862xx.h\n+++ b/drivers/net/dsa/mxl862xx/mxl862xx.h\n@@ -319,6 +319,12 @@ struct mxl862xx_fw_version {\n  * @evlan_ingress_size: per-port ingress Extended VLAN block size\n  * @evlan_egress_size:  per-port egress Extended VLAN block size\n  * @vf_block_size:      per-port VLAN Filter block size\n+ * @block_host:         reject firmware API commands (except FW_UPDATE)\n+ *                      during a firmware flash\n+ * @skip_teardown:      discard firmware API commands during the teardown\n+ *                      triggered by the post-flash reprobe\n+ * @rescue_mode:        switch is stuck in MCUboot; firmware API commands\n+ *                      fail fast, only clause-22 SMDIO works\n  * @stats_work:         periodic work item that polls RMON hardware counters\n  *                      and accumulates them into 64-bit per-port stats\n  */\n@@ -337,6 +343,9 @@ struct mxl862xx_priv {\n \tu16 evlan_ingress_size;\n \tu16 evlan_egress_size;\n \tu16 vf_block_size;\n+\tbool block_host;\n+\tbool skip_teardown;\n+\tbool rescue_mode;\n \tstruct delayed_work stats_work;\n };\n \ndiff --git a/include/net/dsa.h b/include/net/dsa.h\nindex 8c16ef23cc102a..c9e19348de6193 100644\n--- a/include/net/dsa.h\n+++ b/include/net/dsa.h\n@@ -1170,6 +1170,9 @@ struct dsa_switch_ops {\n \tint\t(*devlink_info_get)(struct dsa_switch *ds,\n \t\t\t\t    struct devlink_info_req *req,\n \t\t\t\t    struct netlink_ext_ack *extack);\n+\tint\t(*devlink_flash_update)(struct dsa_switch *ds,\n+\t\t\t\t\tstruct devlink_flash_update_params *params,\n+\t\t\t\t\tstruct netlink_ext_ack *extack);\n \tint\t(*devlink_sb_pool_get)(struct dsa_switch *ds,\n \t\t\t\t       unsigned int sb_index, u16 pool_index,\n \t\t\t\t       struct devlink_sb_pool_info *pool_info);\ndiff --git a/net/dsa/devlink.c b/net/dsa/devlink.c\nindex ed342f345692bb..25311a87cbc56d 100644\n--- a/net/dsa/devlink.c\n+++ b/net/dsa/devlink.c\n@@ -20,6 +20,18 @@ static int dsa_devlink_info_get(struct devlink *dl,\n \treturn -EOPNOTSUPP;\n }\n \n+static int dsa_devlink_flash_update(struct devlink *dl,\n+\t\t\t\t    struct devlink_flash_update_params *params,\n+\t\t\t\t    struct netlink_ext_ack *extack)\n+{\n+\tstruct dsa_switch *ds = dsa_devlink_to_ds(dl);\n+\n+\tif (!ds-\u003eops-\u003edevlink_flash_update)\n+\t\treturn -EOPNOTSUPP;\n+\n+\treturn ds-\u003eops-\u003edevlink_flash_update(ds, params, extack);\n+}\n+\n static int dsa_devlink_sb_pool_get(struct devlink *dl,\n \t\t\t\t   unsigned int sb_index, u16 pool_index,\n \t\t\t\t   struct devlink_sb_pool_info *pool_info)\n@@ -169,6 +181,7 @@ dsa_devlink_sb_occ_tc_port_bind_get(struct devlink_port *dlp,\n \n static const struct devlink_ops dsa_devlink_ops = {\n \t.info_get\t\t\t= dsa_devlink_info_get,\n+\t.flash_update\t\t\t= dsa_devlink_flash_update,\n \t.sb_pool_get\t\t\t= dsa_devlink_sb_pool_get,\n \t.sb_pool_set\t\t\t= dsa_devlink_sb_pool_set,\n \t.sb_port_pool_get\t\t= dsa_devlink_sb_port_pool_get,\n"
}

2/1 2026/07/14 04:57 agent patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch modifies a driver for physical hardware (MaxLinear MxL862xx switch) which is an MDIO device. There is no software emulator for this hardware in virtualized environments like QEMU or GCE, making the code unreachable during fuzzing.",
  "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 ba2f02d5c337d08c36f1b72383d98da50811284e
Author: syz-cluster <triage@syzkaller.com>
Date:   Tue Jul 14 04:57:19 2026 +0000

    syz-cluster: applied patch under review

diff --git a/drivers/net/dsa/mxl862xx/Makefile b/drivers/net/dsa/mxl862xx/Makefile
index a7be0e6669dfa5..bccac0d0f703f6 100644
--- a/drivers/net/dsa/mxl862xx/Makefile
+++ b/drivers/net/dsa/mxl862xx/Makefile
@@ -1,3 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_NET_DSA_MXL862) += mxl862xx_dsa.o
-mxl862xx_dsa-y := mxl862xx.o mxl862xx-host.o mxl862xx-phylink.o
+mxl862xx_dsa-y := mxl862xx.o mxl862xx-host.o mxl862xx-phylink.o mxl862xx-fw.o
diff --git a/drivers/net/dsa/mxl862xx/mxl862xx-cmd.h b/drivers/net/dsa/mxl862xx/mxl862xx-cmd.h
index c87a955c13c48e..e2aa2934e9e162 100644
--- a/drivers/net/dsa/mxl862xx/mxl862xx-cmd.h
+++ b/drivers/net/dsa/mxl862xx/mxl862xx-cmd.h
@@ -70,6 +70,7 @@
 #define INT_GPHY_READ			(GPY_GPY2XX_MAGIC + 0x1)
 #define INT_GPHY_WRITE			(GPY_GPY2XX_MAGIC + 0x2)
 
+#define SYS_MISC_FW_UPDATE		(SYS_MISC_MAGIC + 0x1)
 #define SYS_MISC_FW_VERSION		(SYS_MISC_MAGIC + 0x2)
 
 #define MXL862XX_XPCS_PCS_CONFIG	(MXL862XX_XPCS_MAGIC + 0x1)
diff --git a/drivers/net/dsa/mxl862xx/mxl862xx-fw.c b/drivers/net/dsa/mxl862xx/mxl862xx-fw.c
new file mode 100644
index 00000000000000..88d53bea336fd5
--- /dev/null
+++ b/drivers/net/dsa/mxl862xx/mxl862xx-fw.c
@@ -0,0 +1,439 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Firmware flash and devlink support for MaxLinear MxL862xx
+ *
+ * Copyright (C) 2025 Daniel Golle <daniel@makrotopia.org>
+ */
+
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/rtnetlink.h>
+#include <net/dsa.h>
+
+#include "mxl862xx.h"
+#include "mxl862xx-api.h"
+#include "mxl862xx-cmd.h"
+#include "mxl862xx-fw.h"
+#include "mxl862xx-host.h"
+
+/* SB PDI registers (clause-22 SMDIO address space) */
+#define MXL862XX_SB_PDI_CTRL		0xe100
+#define MXL862XX_SB_PDI_ADDR		0xe101
+#define MXL862XX_SB_PDI_DATA		0xe102
+#define MXL862XX_SB_PDI_STAT		0xe103
+
+/* SB PDI CTRL modes */
+#define MXL862XX_SB_PDI_CTRL_RST	0x00
+#define MXL862XX_SB_PDI_CTRL_WR	0x02
+
+/* SB PDI handshake magic */
+#define MXL862XX_SB_PDI_READY		0xc55c
+#define MXL862XX_SB_PDI_START		0xf48f
+#define MXL862XX_SB_PDI_END		0x3cc3
+
+/* Firmware transfer geometry */
+#define MXL862XX_FW_HDR_SIZE		20
+#define MXL862XX_FW_BANK_HALF		16384	/* words per half-bank */
+#define MXL862XX_FW_BANK_SLICE		32760	/* words per full slice */
+#define MXL862XX_FW_SB1_ADDR		0x7800	/* SB1 word address */
+
+/* Timeouts (generous upper bounds) */
+#define MXL862XX_FW_READY_TIMEOUT_MS	30000
+#define MXL862XX_FW_ACK_TIMEOUT_MS	5000
+#define MXL862XX_FW_ERASE_TIMEOUT_MS	300000
+#define MXL862XX_FW_WRITE_TIMEOUT_MS	120000
+#define MXL862XX_FW_REBOOT_DELAY_MS	5000
+
+static void mxl862xx_sb_pdi_reset(struct mxl862xx_priv *priv)
+{
+	mxl862xx_smdio_write(priv, MXL862XX_SB_PDI_CTRL,
+			     MXL862XX_SB_PDI_CTRL_RST);
+	mxl862xx_smdio_write(priv, MXL862XX_SB_PDI_ADDR,
+			     MXL862XX_SB_PDI_CTRL_RST);
+	mxl862xx_smdio_write(priv, MXL862XX_SB_PDI_DATA,
+			     MXL862XX_SB_PDI_CTRL_RST);
+}
+
+static int mxl862xx_sb_pdi_poll_stat(struct mxl862xx_priv *priv, u16 expected,
+				     unsigned long timeout_ms)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
+	int ret;
+
+	do {
+		ret = mxl862xx_smdio_read(priv, MXL862XX_SB_PDI_STAT);
+		if (ret < 0)
+			return ret;
+		if ((u16)ret == expected)
+			return 0;
+		usleep_range(10000, 11000);
+	} while (time_before(jiffies, timeout));
+
+	return -ETIMEDOUT;
+}
+
+static int mxl862xx_sb_pdi_flush_slice(struct mxl862xx_priv *priv,
+				       u32 data_written)
+{
+	mxl862xx_sb_pdi_reset(priv);
+	mxl862xx_smdio_write(priv, MXL862XX_SB_PDI_STAT, data_written);
+
+	return mxl862xx_sb_pdi_poll_stat(priv, 0,
+					 MXL862XX_FW_WRITE_TIMEOUT_MS);
+}
+
+static void mxl862xx_flash_notify(struct devlink *dl, const char *status,
+				  u32 done, u32 total)
+{
+	devlink_flash_update_status_notify(dl, status, NULL, done, total);
+}
+
+/**
+ * mxl862xx_rescue_mode_detect - check whether the switch sits in MCUboot
+ * @priv: driver private data
+ *
+ * MCUboot signals readiness for a firmware download with the SB PDI
+ * ready magic; only the clause-22 SMDIO interface works in this state.
+ *
+ * Return: true if MCUboot is waiting for a firmware download.
+ */
+bool mxl862xx_rescue_mode_detect(struct mxl862xx_priv *priv)
+{
+	int ret;
+
+	ret = mxl862xx_smdio_read(priv, MXL862XX_SB_PDI_STAT);
+
+	return ret == MXL862XX_SB_PDI_READY;
+}
+
+/* device_reprobe() -> remove() frees priv while the work runs, so
+ * the work struct cannot live in mxl862xx_priv.
+ */
+struct mxl862xx_reprobe {
+	struct device *dev;
+	struct delayed_work dwork;
+};
+
+static void mxl862xx_reprobe_work_fn(struct work_struct *work)
+{
+	struct mxl862xx_reprobe *reprobe =
+		container_of(work, struct mxl862xx_reprobe, dwork.work);
+
+	if (device_reprobe(reprobe->dev))
+		dev_err(reprobe->dev, "reprobe failed\n");
+	put_device(reprobe->dev);
+	kfree(reprobe);
+	module_put(THIS_MODULE);
+}
+
+/* MCUboot firmware image header */
+struct mxl862xx_fw_hdr {
+	__le32 image_type;
+	__le32 image_size_1;
+	__le32 image_checksum_1;
+	__le32 image_size_2;
+	__le32 image_checksum_2;
+} __packed;
+
+static int mxl862xx_flash_firmware(struct mxl862xx_priv *priv,
+				   const struct firmware *fw,
+				   struct devlink *dl)
+{
+	const struct mxl862xx_fw_hdr *hdr;
+	u32 word_idx = 0, data_written = 0, idx = 0;
+	unsigned long next_notify = 0;
+	const u8 *payload;
+	u32 payload_size;
+	u16 word, fdata;
+	int ret, i;
+	u32 crc;
+
+	if (fw->size < MXL862XX_FW_HDR_SIZE)
+		return -EINVAL;
+
+	hdr = (const struct mxl862xx_fw_hdr *)fw->data;
+	payload = fw->data + MXL862XX_FW_HDR_SIZE;
+	payload_size = le32_to_cpu(hdr->image_size_1) +
+		       le32_to_cpu(hdr->image_size_2);
+
+	if (payload_size > fw->size - MXL862XX_FW_HDR_SIZE) {
+		dev_err(&priv->mdiodev->dev,
+			"flash: firmware file too small for declared size\n");
+		return -EINVAL;
+	}
+
+	if (le32_to_cpu(hdr->image_size_1)) {
+		crc = ~crc32_le(~0U, payload,
+				le32_to_cpu(hdr->image_size_1));
+		if (crc != le32_to_cpu(hdr->image_checksum_1)) {
+			dev_err(&priv->mdiodev->dev,
+				"flash: image 1 CRC mismatch (got %08x, expected %08x)\n",
+				crc, le32_to_cpu(hdr->image_checksum_1));
+			return -EINVAL;
+		}
+	}
+
+	if (le32_to_cpu(hdr->image_size_2)) {
+		crc = ~crc32_le(~0U,
+				payload + le32_to_cpu(hdr->image_size_1),
+				le32_to_cpu(hdr->image_size_2));
+		if (crc != le32_to_cpu(hdr->image_checksum_2)) {
+			dev_err(&priv->mdiodev->dev,
+				"flash: image 2 CRC mismatch (got %08x, expected %08x)\n",
+				crc, le32_to_cpu(hdr->image_checksum_2));
+			return -EINVAL;
+		}
+	}
+
+	/* Step 1: reboot the firmware into MCUboot rescue mode */
+	if (!priv->rescue_mode) {
+		ret = mxl862xx_api_wrap(priv, SYS_MISC_FW_UPDATE, NULL, 0,
+					false, false);
+		if (ret) {
+			dev_err(&priv->mdiodev->dev,
+				"flash: FW_UPDATE command failed: %pe\n",
+				ERR_PTR(ret));
+			return ret;
+		}
+	}
+
+	/* Failures from here on must go through end_magic so MCUboot
+	 * reboots instead of waiting forever.
+	 */
+
+	/* Step 2: wait for bootloader ready */
+	mxl862xx_flash_notify(dl, "Waiting for bootloader", 0, 0);
+	mxl862xx_sb_pdi_reset(priv);
+	ret = mxl862xx_sb_pdi_poll_stat(priv, MXL862XX_SB_PDI_READY,
+					MXL862XX_FW_READY_TIMEOUT_MS);
+	if (ret) {
+		dev_err(&priv->mdiodev->dev,
+			"flash: bootloader not ready: %pe\n", ERR_PTR(ret));
+		goto end_magic;
+	}
+
+	/* Step 3: start handshake */
+	mxl862xx_smdio_write(priv, MXL862XX_SB_PDI_STAT,
+			     MXL862XX_SB_PDI_START);
+	ret = mxl862xx_sb_pdi_poll_stat(priv, MXL862XX_SB_PDI_START + 1,
+					MXL862XX_FW_ACK_TIMEOUT_MS);
+	if (ret) {
+		dev_err(&priv->mdiodev->dev,
+			"flash: start handshake failed: %pe\n", ERR_PTR(ret));
+		goto end_magic;
+	}
+
+	/* Step 4: transfer image header */
+	mxl862xx_flash_notify(dl, "Erasing flash", 0, 0);
+	mxl862xx_smdio_write(priv, MXL862XX_SB_PDI_CTRL,
+			     MXL862XX_SB_PDI_CTRL_WR);
+	for (i = 0; i < MXL862XX_FW_HDR_SIZE / 2; i++) {
+		word = fw->data[i * 2] |
+		       ((u16)fw->data[i * 2 + 1] << 8);
+		mxl862xx_smdio_write(priv, MXL862XX_SB_PDI_DATA, word);
+	}
+	mxl862xx_sb_pdi_reset(priv);
+
+	/* the byte count in STAT triggers the erase */
+	mxl862xx_smdio_write(priv, MXL862XX_SB_PDI_STAT,
+			     MXL862XX_FW_HDR_SIZE);
+
+	/* ACK is byte count + 1 */
+	ret = mxl862xx_sb_pdi_poll_stat(priv, MXL862XX_FW_HDR_SIZE + 1,
+					MXL862XX_FW_ACK_TIMEOUT_MS);
+	if (ret) {
+		dev_err(&priv->mdiodev->dev,
+			"flash: header ACK failed: %pe\n", ERR_PTR(ret));
+		goto end_magic;
+	}
+
+	/* Step 5: wait for erase to complete */
+	ret = mxl862xx_sb_pdi_poll_stat(priv, 0,
+					MXL862XX_FW_ERASE_TIMEOUT_MS);
+	if (ret) {
+		dev_err(&priv->mdiodev->dev,
+			"flash: erase timeout: %pe\n", ERR_PTR(ret));
+		goto end_magic;
+	}
+
+	/* Step 6: transfer payload */
+	mxl862xx_smdio_write(priv, MXL862XX_SB_PDI_CTRL,
+			     MXL862XX_SB_PDI_CTRL_WR);
+
+	while (idx < payload_size) {
+		if (idx + 1 < payload_size) {
+			fdata = payload[idx] |
+				((u16)payload[idx + 1] << 8);
+			idx += 2;
+			data_written += 2;
+		} else {
+			fdata = payload[idx];
+			idx++;
+			data_written++;
+		}
+
+		mxl862xx_smdio_write(priv, MXL862XX_SB_PDI_DATA, fdata);
+		word_idx++;
+
+		if (idx >= payload_size) {
+			ret = mxl862xx_sb_pdi_flush_slice(priv, data_written);
+			break;
+		}
+
+		/* Half-bank boundary: switch to SB1 address */
+		if (word_idx == MXL862XX_FW_BANK_HALF) {
+			mxl862xx_smdio_write(priv, MXL862XX_SB_PDI_CTRL,
+					     MXL862XX_SB_PDI_CTRL_RST);
+			mxl862xx_smdio_write(priv, MXL862XX_SB_PDI_ADDR,
+					     MXL862XX_FW_SB1_ADDR);
+			mxl862xx_smdio_write(priv, MXL862XX_SB_PDI_CTRL,
+					     MXL862XX_SB_PDI_CTRL_WR);
+		} else if (word_idx >= MXL862XX_FW_BANK_SLICE) {
+			ret = mxl862xx_sb_pdi_flush_slice(priv, data_written);
+			if (ret) {
+				dev_err(&priv->mdiodev->dev,
+					"flash: write timeout at %u/%u: %pe\n",
+					idx, payload_size, ERR_PTR(ret));
+				goto end_magic;
+			}
+			word_idx = 0;
+			data_written = 0;
+			mxl862xx_smdio_write(priv, MXL862XX_SB_PDI_CTRL,
+					     MXL862XX_SB_PDI_CTRL_WR);
+
+			if (time_after(jiffies, next_notify)) {
+				mxl862xx_flash_notify(dl, "Flashing", idx,
+						      payload_size);
+				next_notify = jiffies + msecs_to_jiffies(500);
+			}
+		}
+	}
+
+	if (ret) {
+		dev_err(&priv->mdiodev->dev,
+			"flash: final write timeout: %pe\n", ERR_PTR(ret));
+		goto end_magic;
+	}
+
+	mxl862xx_flash_notify(dl, "Flashing", payload_size, payload_size);
+
+end_magic:
+	/* reboot MCUboot even after a failed transfer */
+	mxl862xx_smdio_write(priv, MXL862XX_SB_PDI_STAT,
+			     MXL862XX_SB_PDI_END);
+	msleep(MXL862XX_FW_REBOOT_DELAY_MS);
+
+	return ret;
+}
+
+int mxl862xx_devlink_info_get(struct dsa_switch *ds,
+			      struct devlink_info_req *req,
+			      struct netlink_ext_ack *extack)
+{
+	struct mxl862xx_priv *priv = ds->priv;
+	const char *compatible;
+	char ver_str[32];
+	int ret;
+
+	if (!of_property_read_string_index(ds->dev->of_node, "compatible", 0,
+					   &compatible)) {
+		ret = devlink_info_version_fixed_put(req,
+						     DEVLINK_INFO_VERSION_GENERIC_ASIC_ID,
+						     compatible);
+		if (ret)
+			return ret;
+	}
+
+	if (priv->rescue_mode)
+		return devlink_info_version_running_put(req, "fw",
+							"mcuboot-rescue");
+
+	snprintf(ver_str, sizeof(ver_str), "%u.%u.%u",
+		 priv->fw_version.major, priv->fw_version.minor,
+		 priv->fw_version.revision);
+
+	return devlink_info_version_running_put(req, "fw", ver_str);
+}
+
+int mxl862xx_devlink_flash_update(struct dsa_switch *ds,
+				  struct devlink_flash_update_params *params,
+				  struct netlink_ext_ack *extack)
+{
+	struct mxl862xx_priv *priv = ds->priv;
+	struct mxl862xx_sys_fw_image_version ver = {};
+	struct mxl862xx_reprobe *reprobe;
+	struct dsa_port *dp;
+	int ret, i;
+
+	if (params->component) {
+		NL_SET_ERR_MSG_MOD(extack, "component is not supported");
+		return -EOPNOTSUPP;
+	}
+
+	if (priv->rescue_mode)
+		dev_info(ds->dev,
+			 "flash: recovering switch from MCUboot rescue mode\n");
+	else
+		dev_info(ds->dev, "flash: running firmware %u.%u.%u\n",
+			 priv->fw_version.major, priv->fw_version.minor,
+			 priv->fw_version.revision);
+
+	/* Close ports while the firmware is still alive so the DSA
+	 * core's MDB/FDB tracking is drained, and detach user ports
+	 * so userspace cannot reopen them during the flash. The
+	 * conduit belongs to the MAC driver and is only closed.
+	 */
+	rtnl_lock();
+	dsa_switch_for_each_user_port(dp, ds) {
+		if (dp->user) {
+			dev_close(dp->user);
+			netif_device_detach(dp->user);
+		}
+	}
+	dsa_switch_for_each_cpu_port(dp, ds)
+		dev_close(dp->conduit);
+	rtnl_unlock();
+
+	priv->block_host = true;
+
+	cancel_delayed_work_sync(&priv->stats_work);
+	for (i = 0; i < ds->num_ports; i++)
+		cancel_work_sync(&priv->ports[i].host_flood_work);
+
+	ret = mxl862xx_flash_firmware(priv, params->fw, ds->devlink);
+	if (ret)
+		NL_SET_ERR_MSG_MOD(extack, "firmware transfer failed");
+
+	if (!ret) {
+		/* lift the block to query the new firmware version */
+		priv->block_host = false;
+		priv->rescue_mode = false;
+		memset(&ver, 0, sizeof(ver));
+		if (!MXL862XX_API_READ_QUIET(priv, SYS_MISC_FW_VERSION, ver) &&
+		    ver.iv_major)
+			dev_info(ds->dev, "flash: new firmware %u.%u.%u\n",
+				 ver.iv_major, ver.iv_minor,
+				 le16_to_cpu(ver.iv_revision));
+	}
+
+	priv->skip_teardown = true;
+
+	reprobe = kzalloc_obj(*reprobe);
+	if (!reprobe)
+		return ret;
+
+	if (!try_module_get(THIS_MODULE)) {
+		kfree(reprobe);
+		return ret;
+	}
+
+	reprobe->dev = get_device(ds->dev);
+	INIT_DELAYED_WORK(&reprobe->dwork, mxl862xx_reprobe_work_fn);
+	schedule_delayed_work(&reprobe->dwork, msecs_to_jiffies(500));
+
+	return ret;
+}
diff --git a/drivers/net/dsa/mxl862xx/mxl862xx-fw.h b/drivers/net/dsa/mxl862xx/mxl862xx-fw.h
new file mode 100644
index 00000000000000..57c2000cfee519
--- /dev/null
+++ b/drivers/net/dsa/mxl862xx/mxl862xx-fw.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __MXL862XX_FW_H
+#define __MXL862XX_FW_H
+
+#include <net/dsa.h>
+
+struct mxl862xx_priv;
+
+bool mxl862xx_rescue_mode_detect(struct mxl862xx_priv *priv);
+int mxl862xx_devlink_info_get(struct dsa_switch *ds,
+			      struct devlink_info_req *req,
+			      struct netlink_ext_ack *extack);
+int mxl862xx_devlink_flash_update(struct dsa_switch *ds,
+				  struct devlink_flash_update_params *params,
+				  struct netlink_ext_ack *extack);
+
+#endif /* __MXL862XX_FW_H */
diff --git a/drivers/net/dsa/mxl862xx/mxl862xx-host.c b/drivers/net/dsa/mxl862xx/mxl862xx-host.c
index 4acd216f7cc009..d6c0cdfa0e6892 100644
--- a/drivers/net/dsa/mxl862xx/mxl862xx-host.c
+++ b/drivers/net/dsa/mxl862xx/mxl862xx-host.c
@@ -15,6 +15,7 @@
 #include <linux/unaligned.h>
 #include <net/dsa.h>
 #include "mxl862xx.h"
+#include "mxl862xx-cmd.h"
 #include "mxl862xx-host.h"
 
 #define CTRL_BUSY_MASK			BIT(15)
@@ -336,6 +337,15 @@ int mxl862xx_api_wrap(struct mxl862xx_priv *priv, u16 cmd, void *_data,
 	int ret, cmd_ret;
 	u16 max, crc, i;
 
+	if (priv->skip_teardown)
+		return 0;
+
+	if (priv->rescue_mode)
+		return -ENODEV;
+
+	if (priv->block_host && cmd != SYS_MISC_FW_UPDATE)
+		return -EBUSY;
+
 	dev_dbg(&priv->mdiodev->dev, "CMD %04x DATA %*ph\n", cmd, size, data);
 
 	mutex_lock_nested(&priv->mdiodev->bus->mdio_lock, MDIO_MUTEX_NESTED);
@@ -495,6 +505,41 @@ int mxl862xx_reset(struct mxl862xx_priv *priv)
 	return ret;
 }
 
+#define MXL862XX_SMDIO_ADDR_REG		0x1f
+#define MXL862XX_SMDIO_PAGE_MASK	0xfff0
+#define MXL862XX_SMDIO_OFF_MASK		0x000f
+
+int mxl862xx_smdio_read(struct mxl862xx_priv *priv, u32 addr)
+{
+	struct mii_bus *bus = priv->mdiodev->bus;
+	int phy = priv->mdiodev->addr;
+	int ret;
+
+	mutex_lock(&bus->mdio_lock);
+	ret = __mdiobus_write(bus, phy, MXL862XX_SMDIO_ADDR_REG,
+			      addr & MXL862XX_SMDIO_PAGE_MASK);
+	if (ret >= 0)
+		ret = __mdiobus_read(bus, phy, addr & MXL862XX_SMDIO_OFF_MASK);
+	mutex_unlock(&bus->mdio_lock);
+	return ret;
+}
+
+int mxl862xx_smdio_write(struct mxl862xx_priv *priv, u32 addr, u16 val)
+{
+	struct mii_bus *bus = priv->mdiodev->bus;
+	int phy = priv->mdiodev->addr;
+	int ret;
+
+	mutex_lock(&bus->mdio_lock);
+	ret = __mdiobus_write(bus, phy, MXL862XX_SMDIO_ADDR_REG,
+			      addr & MXL862XX_SMDIO_PAGE_MASK);
+	if (ret >= 0)
+		ret = __mdiobus_write(bus, phy, addr & MXL862XX_SMDIO_OFF_MASK,
+				      val);
+	mutex_unlock(&bus->mdio_lock);
+	return ret;
+}
+
 void mxl862xx_host_init(struct mxl862xx_priv *priv)
 {
 	INIT_WORK(&priv->crc_err_work, mxl862xx_crc_err_work_fn);
diff --git a/drivers/net/dsa/mxl862xx/mxl862xx-host.h b/drivers/net/dsa/mxl862xx/mxl862xx-host.h
index 66d6ae198aff45..4e054c6e4c0e40 100644
--- a/drivers/net/dsa/mxl862xx/mxl862xx-host.h
+++ b/drivers/net/dsa/mxl862xx/mxl862xx-host.h
@@ -18,5 +18,7 @@ int mxl862xx_api_wrap(struct mxl862xx_priv *priv, u16 cmd, void *data, u16 size,
 	mxl862xx_api_wrap(dev, cmd, &(data), sizeof((data)), true, true)
 
 int mxl862xx_reset(struct mxl862xx_priv *priv);
+int mxl862xx_smdio_read(struct mxl862xx_priv *priv, u32 addr);
+int mxl862xx_smdio_write(struct mxl862xx_priv *priv, u32 addr, u16 val);
 
 #endif /* __MXL862XX_HOST_H */
diff --git a/drivers/net/dsa/mxl862xx/mxl862xx-phylink.c b/drivers/net/dsa/mxl862xx/mxl862xx-phylink.c
index b689652aa9b920..a5b6940b552e9e 100644
--- a/drivers/net/dsa/mxl862xx/mxl862xx-phylink.c
+++ b/drivers/net/dsa/mxl862xx/mxl862xx-phylink.c
@@ -406,6 +406,8 @@ mxl862xx_phylink_mac_select_pcs(struct phylink_config *config,
 
 	switch (port) {
 	case 9 ... 16:
+		if (priv->rescue_mode)
+			return NULL;
 		if (!MXL862XX_FW_VER_MIN(priv, 1, 0, 84)) {
 			dev_warn_once(dp->ds->dev,
 				      "SerDes PCS unsupported on old firmware.\n");
diff --git a/drivers/net/dsa/mxl862xx/mxl862xx.c b/drivers/net/dsa/mxl862xx/mxl862xx.c
index 45d237b3a40f10..b7385cfa547458 100644
--- a/drivers/net/dsa/mxl862xx/mxl862xx.c
+++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
@@ -21,6 +21,7 @@
 #include "mxl862xx.h"
 #include "mxl862xx-api.h"
 #include "mxl862xx-cmd.h"
+#include "mxl862xx-fw.h"
 #include "mxl862xx-host.h"
 #include "mxl862xx-phylink.h"
 
@@ -628,9 +629,22 @@ static int mxl862xx_setup(struct dsa_switch *ds)
 	if (ret)
 		return ret;
 
-	ret = mxl862xx_wait_ready(ds);
-	if (ret)
-		return ret;
+	priv->rescue_mode = mxl862xx_rescue_mode_detect(priv);
+	if (!priv->rescue_mode) {
+		ret = mxl862xx_wait_ready(ds);
+		if (ret) {
+			/* the reset may only now have triggered rescue mode */
+			priv->rescue_mode = mxl862xx_rescue_mode_detect(priv);
+			if (!priv->rescue_mode)
+				return ret;
+		}
+	}
+
+	if (priv->rescue_mode) {
+		dev_warn(ds->dev,
+			 "switch stuck in MCUboot rescue mode, use devlink to flash new firmware\n");
+		return 0;
+	}
 
 	mutex_init(&priv->serdes_lock);
 	for (i = 0; i < ARRAY_SIZE(priv->serdes_ports); i++)
@@ -715,11 +729,21 @@ static int mxl862xx_port_state(struct dsa_switch *ds, int port, bool enable)
 static int mxl862xx_port_enable(struct dsa_switch *ds, int port,
 				struct phy_device *phydev)
 {
+	struct mxl862xx_priv *priv = ds->priv;
+
+	if (priv->rescue_mode)
+		return 0;
+
 	return mxl862xx_port_state(ds, port, true);
 }
 
 static void mxl862xx_port_disable(struct dsa_switch *ds, int port)
 {
+	struct mxl862xx_priv *priv = ds->priv;
+
+	if (priv->rescue_mode)
+		return;
+
 	if (mxl862xx_port_state(ds, port, false))
 		dev_err(ds->dev, "failed to disable port %d\n", port);
 }
@@ -1337,6 +1361,12 @@ static int mxl862xx_port_setup(struct dsa_switch *ds, int port)
 	bool is_cpu_port = dsa_port_is_cpu(dp);
 	int ret;
 
+	/* DSA reinits failed user ports as unused; shared ports must
+	 * succeed for the tree to register.
+	 */
+	if (priv->rescue_mode)
+		return dsa_port_is_user(dp) ? -ENODEV : 0;
+
 	ret = mxl862xx_port_state(ds, port, false);
 	if (ret)
 		return ret;
@@ -1628,6 +1658,9 @@ static void mxl862xx_port_stp_state_set(struct dsa_switch *ds, int port,
 	struct mxl862xx_priv *priv = ds->priv;
 	int ret;
 
+	if (priv->rescue_mode)
+		return;
+
 	switch (state) {
 	case BR_STATE_DISABLED:
 		param.port_state = cpu_to_le32(MXL862XX_STP_PORT_STATE_DISABLE);
@@ -2086,6 +2119,8 @@ static const struct dsa_switch_ops mxl862xx_switch_ops = {
 	.get_pause_stats = mxl862xx_get_pause_stats,
 	.get_rmon_stats = mxl862xx_get_rmon_stats,
 	.get_stats64 = mxl862xx_get_stats64,
+	.devlink_info_get = mxl862xx_devlink_info_get,
+	.devlink_flash_update = mxl862xx_devlink_flash_update,
 };
 
 static int mxl862xx_probe(struct mdio_device *mdiodev)
diff --git a/drivers/net/dsa/mxl862xx/mxl862xx.h b/drivers/net/dsa/mxl862xx/mxl862xx.h
index 432a5f3f2e08e6..5d21296561e3aa 100644
--- a/drivers/net/dsa/mxl862xx/mxl862xx.h
+++ b/drivers/net/dsa/mxl862xx/mxl862xx.h
@@ -319,6 +319,12 @@ struct mxl862xx_fw_version {
  * @evlan_ingress_size: per-port ingress Extended VLAN block size
  * @evlan_egress_size:  per-port egress Extended VLAN block size
  * @vf_block_size:      per-port VLAN Filter block size
+ * @block_host:         reject firmware API commands (except FW_UPDATE)
+ *                      during a firmware flash
+ * @skip_teardown:      discard firmware API commands during the teardown
+ *                      triggered by the post-flash reprobe
+ * @rescue_mode:        switch is stuck in MCUboot; firmware API commands
+ *                      fail fast, only clause-22 SMDIO works
  * @stats_work:         periodic work item that polls RMON hardware counters
  *                      and accumulates them into 64-bit per-port stats
  */
@@ -337,6 +343,9 @@ struct mxl862xx_priv {
 	u16 evlan_ingress_size;
 	u16 evlan_egress_size;
 	u16 vf_block_size;
+	bool block_host;
+	bool skip_teardown;
+	bool rescue_mode;
 	struct delayed_work stats_work;
 };
 
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 8c16ef23cc102a..c9e19348de6193 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -1170,6 +1170,9 @@ struct dsa_switch_ops {
 	int	(*devlink_info_get)(struct dsa_switch *ds,
 				    struct devlink_info_req *req,
 				    struct netlink_ext_ack *extack);
+	int	(*devlink_flash_update)(struct dsa_switch *ds,
+					struct devlink_flash_update_params *params,
+					struct netlink_ext_ack *extack);
 	int	(*devlink_sb_pool_get)(struct dsa_switch *ds,
 				       unsigned int sb_index, u16 pool_index,
 				       struct devlink_sb_pool_info *pool_info);
diff --git a/net/dsa/devlink.c b/net/dsa/devlink.c
index ed342f345692bb..25311a87cbc56d 100644
--- a/net/dsa/devlink.c
+++ b/net/dsa/devlink.c
@@ -20,6 +20,18 @@ static int dsa_devlink_info_get(struct devlink *dl,
 	return -EOPNOTSUPP;
 }
 
+static int dsa_devlink_flash_update(struct devlink *dl,
+				    struct devlink_flash_update_params *params,
+				    struct netlink_ext_ack *extack)
+{
+	struct dsa_switch *ds = dsa_devlink_to_ds(dl);
+
+	if (!ds->ops->devlink_flash_update)
+		return -EOPNOTSUPP;
+
+	return ds->ops->devlink_flash_update(ds, params, extack);
+}
+
 static int dsa_devlink_sb_pool_get(struct devlink *dl,
 				   unsigned int sb_index, u16 pool_index,
 				   struct devlink_sb_pool_info *pool_info)
@@ -169,6 +181,7 @@ dsa_devlink_sb_occ_tc_port_bind_get(struct devlink_port *dlp,
 
 static const struct devlink_ops dsa_devlink_ops = {
 	.info_get			= dsa_devlink_info_get,
+	.flash_update			= dsa_devlink_flash_update,
 	.sb_pool_get			= dsa_devlink_sb_pool_get,
 	.sb_pool_set			= dsa_devlink_sb_pool_set,
 	.sb_port_pool_get		= dsa_devlink_sb_port_pool_get,

3/2 2026/07/14 04:57 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 12700
							output: 40
							thoughts: 185
						

Thoughts:
**Analyzing the MxL862xx Patch for Virtualization**

Okay, so we've got a new patch incorporating firmware flashing and devlink support for the MaxLinear MxL862xx switch. The changes are focused in `drivers/net/dsa/mxl862xx/` and `net/dsa/devlink.c`. This is intriguing because it enables firmware flashing through devlink – a pretty significant improvement.

My primary concern, as always, is how this interacts with virtualized environments. The driver in question is `drivers/net/dsa/mxl862xx/`, which immediately suggests we're dealing with a physical hardware driver. Specifically, it's a DSA switch driver for the MxL862xx. The very nature of DSA switches makes emulation highly improbable. They're typically deeply tied to the hardware.

Therefore, the question becomes: how can we test this in a virtual setting? We'll need to double-check if there's any mention of software emulation anywhere, though I highly doubt it. DSA switches are almost always a purely hardware concern. To be certain, I'll run a kernel search for `mxl862xx` to confirm and expand our knowledge.



4/2 2026/07/14 04:57 tool grepper
0m Args:
{
  "Expression": "mxl862xx",
  "PathPrefix": "drivers/net/dsa/mxl862xx/"
}

Results:
{
  "Output": "\nFull output is too long, showing 500 out of 2324 lines.\nUse more precise expression if possible.\n\ndrivers/net/dsa/mxl862xx/Makefile-1-# SPDX-License-Identifier: GPL-2.0\ndrivers/net/dsa/mxl862xx/Makefile:2:obj-$(CONFIG_NET_DSA_MXL862) += mxl862xx_dsa.o\ndrivers/net/dsa/mxl862xx/Makefile:3:mxl862xx_dsa-y := mxl862xx.o mxl862xx-host.o mxl862xx-phylink.o mxl862xx-fw.o\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h=16=struct mdio_relay_data {\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-23-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:24: * struct mxl862xx_register_mod - Register access parameter to directly\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-25- *                                modify internal registers\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-31- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:32:struct mxl862xx_register_mod {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-33-\t__le16 addr;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-38-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:39: * enum mxl862xx_mac_table_filter - Source/Destination MAC address filtering\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-40- *\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-45- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:46:enum mxl862xx_mac_table_filter {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-47-\tMXL862XX_MAC_FILTER_NONE = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-64-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:65: * struct mxl862xx_mac_table_add - MAC Table Entry to be added\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-66- * @fid: Filtering Identifier (FID) (not supported by all switches)\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-74- * @mac: MAC Address to add to the table\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:75: * @filter_flag: See \u0026enum mxl862xx_mac_table_filter\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-76- * @igmp_controlled: Packet is marked as IGMP controlled if destination MAC\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-83- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:84:struct mxl862xx_mac_table_add {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-85-\t__le16 fid;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-100-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:101: * struct mxl862xx_mac_table_remove - MAC Table Entry to be removed\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-102- * @fid: Filtering Identifier (FID)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-103- * @mac: MAC Address to be removed from the table.\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:104: * @filter_flag: See \u0026enum mxl862xx_mac_table_filter\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-105- * @tci: TCI for B-Step\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-109- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:110:struct mxl862xx_mac_table_remove {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-111-\t__le16 fid;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-117-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:118: * struct mxl862xx_mac_table_read - MAC Table Entry to be read\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-119- * @initial: Restart the get operation from the beginning of the table\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-128- * @mac: MAC Address. Filled out by the switch API implementation.\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:129: * @filter_flag: See \u0026enum mxl862xx_mac_table_filter\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-130- * @igmp_controlled: Packet is marked as IGMP controlled if destination MAC\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-141- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:142:struct mxl862xx_mac_table_read {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-143-\tu8 initial;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-162-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:163: * struct mxl862xx_mac_table_query - MAC Table Entry key-based lookup\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-164- * @mac: MAC Address to search for (input)\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-172- * @static_entry: Indicates if this is a Static Entry\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:173: * @filter_flag: See \u0026enum mxl862xx_mac_table_filter (input+output)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-174- * @igmp_controlled: IGMP controlled flag\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-180- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:181:struct mxl862xx_mac_table_query {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-182-\tu8 mac[ETH_ALEN];\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-200-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:201: * enum mxl862xx_mac_clear_type - MAC table clear type\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-202- * @MXL862XX_MAC_CLEAR_PHY_PORT: clear dynamic entries based on port_id\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-204- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:205:enum mxl862xx_mac_clear_type {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-206-\tMXL862XX_MAC_CLEAR_PHY_PORT = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-210-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:211: * struct mxl862xx_mac_table_clear - MAC table clear\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:212: * @type: see \u0026enum mxl862xx_mac_clear_type\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-213- * @port_id: physical port id\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-214- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:215:struct mxl862xx_mac_table_clear {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-216-\tu8 type;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-220-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:221: * enum mxl862xx_age_timer - Aging Timer Value.\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-222- * @MXL862XX_AGETIMER_1_SEC: 1 second aging time\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-228- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:229:enum mxl862xx_age_timer {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-230-\tMXL862XX_AGETIMER_1_SEC = 1,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-238-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:239: * struct mxl862xx_bridge_alloc - Bridge Allocation\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-240- * @bridge_id: If the bridge allocation is successful, a valid ID will be\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-247- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:248:struct mxl862xx_bridge_alloc {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-249-\t__le16 bridge_id;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-252-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:253: * enum mxl862xx_bridge_config_mask - Bridge configuration mask\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-254- * @MXL862XX_BRIDGE_CONFIG_MASK_MAC_LEARNING_LIMIT:\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-267- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:268:enum mxl862xx_bridge_config_mask {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-269-\tMXL862XX_BRIDGE_CONFIG_MASK_MAC_LEARNING_LIMIT = BIT(0),\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-278-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:279: * enum mxl862xx_bridge_port_egress_meter - Meters for egress traffic type\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-280- * @MXL862XX_BRIDGE_PORT_EGRESS_METER_BROADCAST:\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-293- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:294:enum mxl862xx_bridge_port_egress_meter {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-295-\tMXL862XX_BRIDGE_PORT_EGRESS_METER_BROADCAST = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-304-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:305: * struct mxl862xx_qos_meter_cfg - Rate meter configuration\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-306- * @enable: Enable/disable meter\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-320- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:321:struct mxl862xx_qos_meter_cfg {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-322-\tu8 enable;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-338-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:339: * enum mxl862xx_bridge_forward_mode - Bridge forwarding type of packet\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-340- * @MXL862XX_BRIDGE_FORWARD_FLOOD: Packet is flooded to port members of\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-343- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:344:enum mxl862xx_bridge_forward_mode {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-345-\tMXL862XX_BRIDGE_FORWARD_FLOOD = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-349-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:350: * struct mxl862xx_bridge_config - Bridge Configuration\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-351- * @bridge_id: Bridge ID (FID)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:352: * @mask: See \u0026enum mxl862xx_bridge_config_mask\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-353- * @mac_learning_limit_enable: Enable MAC learning limitation\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-363- * @forward_broadcast: Forwarding mode of broadcast traffic. See\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:364: *                     \u0026enum mxl862xx_bridge_forward_mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-365- * @forward_unknown_multicast_ip: Forwarding mode of unknown multicast IP\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-366- *                                traffic.\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:367: *                                See \u0026enum mxl862xx_bridge_forward_mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-368- * @forward_unknown_multicast_non_ip: Forwarding mode of unknown multicast\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-369- *                                    non-IP traffic.\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:370: *                                    See \u0026enum mxl862xx_bridge_forward_mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-371- * @forward_unknown_unicast: Forwarding mode of unknown unicast traffic. See\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:372: *                           \u0026enum mxl862xx_bridge_forward_mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-373- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:374:struct mxl862xx_bridge_config {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-375-\t__le16 bridge_id;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:376:\t__le32 mask; /* enum mxl862xx_bridge_config_mask */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-377-\tu8 mac_learning_limit_enable;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-382-\t__le16 traffic_sub_meter_id[MXL862XX_BRIDGE_PORT_EGRESS_METER_MAX];\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:383:\t__le32 forward_broadcast; /* enum mxl862xx_bridge_forward_mode */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:384:\t__le32 forward_unknown_multicast_ip; /* enum mxl862xx_bridge_forward_mode */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:385:\t__le32 forward_unknown_multicast_non_ip; /* enum mxl862xx_bridge_forward_mode */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:386:\t__le32 forward_unknown_unicast; /* enum mxl862xx_bridge_forward_mode */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-387-} __packed;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-389-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:390: * struct mxl862xx_bridge_port_alloc - Bridge Port Allocation\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-391- * @bridge_port_id: If the bridge port allocation is successful, a valid ID\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-397- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:398:struct mxl862xx_bridge_port_alloc {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-399-\t__le16 bridge_port_id;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-402-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:403: * enum mxl862xx_bridge_port_config_mask - Bridge Port configuration mask\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-404- * @MXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_ID:\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-462- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:463:enum mxl862xx_bridge_port_config_mask {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-464-\tMXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_ID = BIT(0),\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-491-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:492: * enum mxl862xx_color_marking_mode - Color Marking Mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-493- * @MXL862XX_MARKING_ALL_GREEN: mark packets (except critical) to green\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-501- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:502:enum mxl862xx_color_marking_mode {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-503-\tMXL862XX_MARKING_ALL_GREEN = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-513-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:514: * enum mxl862xx_color_remarking_mode - Color Remarking Mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-515- * @MXL862XX_REMARKING_NONE: values from last process stage\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-522- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:523:enum mxl862xx_color_remarking_mode {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-524-\tMXL862XX_REMARKING_NONE = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-533-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:534: * enum mxl862xx_pmapper_mapping_mode - P-mapper Mapping Mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-535- * @MXL862XX_PMAPPER_MAPPING_PCP: Use PCP for VLAN tagged packets to derive\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-541- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:542:enum mxl862xx_pmapper_mapping_mode {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-543-\tMXL862XX_PMAPPER_MAPPING_PCP = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-548-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:549: * struct mxl862xx_pmapper - P-mapper Configuration\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-550- * @pmapper_id: Index of P-mapper (0-31)\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-560- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:561:struct mxl862xx_pmapper {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-562-\t__le16 pmapper_id;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-566-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:567: * struct mxl862xx_bridge_port_config - Bridge Port Configuration\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-568- * @bridge_port_id: Bridge Port ID allocated by bridge port allocation\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:569: * @mask: See \u0026enum mxl862xx_bridge_port_config_mask\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-570- * @bridge_id: Bridge ID (FID) to which this bridge port is associated\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-583- * @ingress_marking_mode: Ingress color marking mode. See\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:584: *                        \u0026enum mxl862xx_color_marking_mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-585- * @egress_remarking_mode: Color remarking for egress traffic. See\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:586: *                         \u0026enum mxl862xx_color_remarking_mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-587- * @ingress_metering_enable: Traffic metering on ingress traffic applies\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-597- * @pmapper_mapping_mode: P-mapper mapping mode. See\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:598: *                        \u0026enum mxl862xx_pmapper_mapping_mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-599- * @pmapper_id_valid: When true, P-mapper is re-used; when false,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-653- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:654:struct mxl862xx_bridge_port_config {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-655-\t__le16 bridge_port_id;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:656:\t__le32 mask; /* enum mxl862xx_bridge_port_config_mask */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-657-\t__le16 bridge_id;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-663-\t__le16 egress_extended_vlan_block_size;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:664:\t__le32 ingress_marking_mode; /* enum mxl862xx_color_marking_mode */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:665:\t__le32 egress_remarking_mode; /* enum mxl862xx_color_remarking_mode */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-666-\tu8 ingress_metering_enable;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-672-\t__le16 dest_sub_if_id_group;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:673:\t__le32 pmapper_mapping_mode; /* enum mxl862xx_pmapper_mapping_mode */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-674-\tu8 pmapper_id_valid;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:675:\tstruct mxl862xx_pmapper pmapper;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-676-\t__le16 bridge_port_map[8];\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-709-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:710: * struct mxl862xx_cfg -  Global Switch configuration Attributes\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:711: * @mac_table_age_timer: See \u0026enum mxl862xx_age_timer\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-712- * @age_timer: Custom MAC table aging timer in seconds\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-722- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:723:struct mxl862xx_cfg {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:724:\t__le32 mac_table_age_timer; /* enum mxl862xx_age_timer */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-725-\t__le32 age_timer;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-734-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:735: * enum mxl862xx_extended_vlan_filter_type - Extended VLAN filter tag type\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-736- * @MXL862XX_EXTENDEDVLAN_FILTER_TYPE_NORMAL: Normal tagged\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-740- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:741:enum mxl862xx_extended_vlan_filter_type {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-742-\tMXL862XX_EXTENDEDVLAN_FILTER_TYPE_NORMAL = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-748-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:749: * enum mxl862xx_extended_vlan_filter_tpid - Extended VLAN filter TPID\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-750- * @MXL862XX_EXTENDEDVLAN_FILTER_TPID_NO_FILTER: No TPID filter\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-753- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:754:enum mxl862xx_extended_vlan_filter_tpid {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-755-\tMXL862XX_EXTENDEDVLAN_FILTER_TPID_NO_FILTER = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-760-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:761: * enum mxl862xx_extended_vlan_filter_dei - Extended VLAN filter DEI\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-762- * @MXL862XX_EXTENDEDVLAN_FILTER_DEI_NO_FILTER: No DEI filter\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-765- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:766:enum mxl862xx_extended_vlan_filter_dei {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-767-\tMXL862XX_EXTENDEDVLAN_FILTER_DEI_NO_FILTER = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-772-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:773: * enum mxl862xx_extended_vlan_treatment_remove_tag - Tag removal action\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-774- * @MXL862XX_EXTENDEDVLAN_TREATMENT_NOT_REMOVE_TAG: Do not remove tag\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-778- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:779:enum mxl862xx_extended_vlan_treatment_remove_tag {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-780-\tMXL862XX_EXTENDEDVLAN_TREATMENT_NOT_REMOVE_TAG = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-786-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:787: * enum mxl862xx_extended_vlan_treatment_priority - Treatment priority mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-788- * @MXL862XX_EXTENDEDVLAN_TREATMENT_PRIORITY_VAL: Use explicit value\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-792- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:793:enum mxl862xx_extended_vlan_treatment_priority {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-794-\tMXL862XX_EXTENDEDVLAN_TREATMENT_PRIORITY_VAL = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-800-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:801: * enum mxl862xx_extended_vlan_treatment_vid - Treatment VID mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-802- * @MXL862XX_EXTENDEDVLAN_TREATMENT_VID_VAL: Use explicit VID value\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-805- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:806:enum mxl862xx_extended_vlan_treatment_vid {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-807-\tMXL862XX_EXTENDEDVLAN_TREATMENT_VID_VAL = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-812-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:813: * enum mxl862xx_extended_vlan_treatment_tpid - Treatment TPID mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-814- * @MXL862XX_EXTENDEDVLAN_TREATMENT_INNER_TPID: Copy from inner tag\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-818- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:819:enum mxl862xx_extended_vlan_treatment_tpid {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-820-\tMXL862XX_EXTENDEDVLAN_TREATMENT_INNER_TPID = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-826-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:827: * enum mxl862xx_extended_vlan_treatment_dei - Treatment DEI mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-828- * @MXL862XX_EXTENDEDVLAN_TREATMENT_INNER_DEI: Copy from inner tag\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-832- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:833:enum mxl862xx_extended_vlan_treatment_dei {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-834-\tMXL862XX_EXTENDEDVLAN_TREATMENT_INNER_DEI = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-840-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:841: * enum mxl862xx_extended_vlan_4_tpid_mode - 4-TPID mode selector\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-842- * @MXL862XX_EXTENDEDVLAN_TPID_VTETYPE_1: VLAN TPID type 1\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-846- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:847:enum mxl862xx_extended_vlan_4_tpid_mode {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-848-\tMXL862XX_EXTENDEDVLAN_TPID_VTETYPE_1 = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-854-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:855: * enum mxl862xx_extended_vlan_filter_ethertype - Filter EtherType match\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-856- * @MXL862XX_EXTENDEDVLAN_FILTER_ETHERTYPE_NO_FILTER: No filter\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-864- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:865:enum mxl862xx_extended_vlan_filter_ethertype {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-866-\tMXL862XX_EXTENDEDVLAN_FILTER_ETHERTYPE_NO_FILTER = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-876-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:877: * struct mxl862xx_extendedvlan_filter_vlan - Per-tag filter in Extended VLAN\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:878: * @type: Tag presence/type match (see \u0026enum mxl862xx_extended_vlan_filter_type)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-879- * @priority_enable: Enable PCP value matching\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-882- * @vid_val: VID value to match\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:883: * @tpid: TPID match mode (see \u0026enum mxl862xx_extended_vlan_filter_tpid)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:884: * @dei: DEI match mode (see \u0026enum mxl862xx_extended_vlan_filter_dei)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-885- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:886:struct mxl862xx_extendedvlan_filter_vlan {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-887-\t__le32 type;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-896-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:897: * struct mxl862xx_extendedvlan_filter - Extended VLAN filter configuration\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-898- * @original_packet_filter_mode: If true, filter on original (pre-treatment)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-899- *                               packet\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:900: * @filter_4_tpid_mode: 4-TPID mode (see \u0026enum mxl862xx_extended_vlan_4_tpid_mode)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-901- * @outer_vlan: Outer VLAN tag filter\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-903- * @ether_type: EtherType filter (see\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:904: *              \u0026enum mxl862xx_extended_vlan_filter_ethertype)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-905- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:906:struct mxl862xx_extendedvlan_filter {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-907-\tu8 original_packet_filter_mode;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-908-\t__le32 filter_4_tpid_mode;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:909:\tstruct mxl862xx_extendedvlan_filter_vlan outer_vlan;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:910:\tstruct mxl862xx_extendedvlan_filter_vlan inner_vlan;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-911-\t__le32 ether_type;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-914-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:915: * struct mxl862xx_extendedvlan_treatment_vlan - Per-tag treatment in\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-916- *                                               Extended VLAN\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-917- * @priority_mode: Priority assignment mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:918: *                 (see \u0026enum mxl862xx_extended_vlan_treatment_priority)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-919- * @priority_val: Priority value (when mode is VAL)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-920- * @vid_mode: VID assignment mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:921: *            (see \u0026enum mxl862xx_extended_vlan_treatment_vid)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-922- * @vid_val: VID value (when mode is VAL)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-923- * @tpid: TPID assignment mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:924: *        (see \u0026enum mxl862xx_extended_vlan_treatment_tpid)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-925- * @dei: DEI assignment mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:926: *       (see \u0026enum mxl862xx_extended_vlan_treatment_dei)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-927- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:928:struct mxl862xx_extendedvlan_treatment_vlan {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-929-\t__le32 priority_mode;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-937-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:938: * struct mxl862xx_extendedvlan_treatment - Extended VLAN treatment\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-939- * @remove_tag: Tag removal action\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:940: *              (see \u0026enum mxl862xx_extended_vlan_treatment_remove_tag)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-941- * @treatment_4_tpid_mode: 4-TPID treatment mode\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-958- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:959:struct mxl862xx_extendedvlan_treatment {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-960-\t__le32 remove_tag;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-962-\tu8 add_outer_vlan;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:963:\tstruct mxl862xx_extendedvlan_treatment_vlan outer_vlan;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-964-\tu8 add_inner_vlan;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:965:\tstruct mxl862xx_extendedvlan_treatment_vlan inner_vlan;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-966-\tu8 reassign_bridge_port;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-980-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:981: * struct mxl862xx_extendedvlan_alloc - Extended VLAN block allocation\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-982- * @number_of_entries: Number of entries to allocate (input) / allocated\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-988- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:989:struct mxl862xx_extendedvlan_alloc {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-990-\t__le16 number_of_entries;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-994-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:995: * struct mxl862xx_extendedvlan_config - Extended VLAN entry configuration\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-996- * @extended_vlan_block_id: Block ID from allocation\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1002- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1003:struct mxl862xx_extendedvlan_config {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1004-\t__le16 extended_vlan_block_id;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1005-\t__le16 entry_index;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1006:\tstruct mxl862xx_extendedvlan_filter filter;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1007:\tstruct mxl862xx_extendedvlan_treatment treatment;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1008-} __packed;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1010-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1011: * enum mxl862xx_vlan_filter_tci_mask - VLAN Filter TCI mask\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1012- * @MXL862XX_VLAN_FILTER_TCI_MASK_VID: TCI mask for VLAN ID\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1015- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1016:enum mxl862xx_vlan_filter_tci_mask {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1017-\tMXL862XX_VLAN_FILTER_TCI_MASK_VID = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1022-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1023: * struct mxl862xx_vlanfilter_alloc - VLAN Filter block allocation\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1024- * @number_of_entries: Number of entries to allocate (input) / allocated\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1034- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1035:struct mxl862xx_vlanfilter_alloc {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1036-\t__le16 number_of_entries;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1043-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1044: * struct mxl862xx_vlanfilter_config - VLAN Filter entry configuration\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1045- * @vlan_filter_block_id: Block ID from allocation\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1047- * @vlan_filter_mask: TCI field(s) to match (see\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1048: *                    \u0026enum mxl862xx_vlan_filter_tci_mask)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1049- * @val: TCI value(s) to match (VID, PCP, or full TCI depending on mask)\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1054- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1055:struct mxl862xx_vlanfilter_config {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1056-\t__le16 vlan_filter_block_id;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1057-\t__le16 entry_index;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1058:\t__le32 vlan_filter_mask; /* enum mxl862xx_vlan_filter_tci_mask */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1059-\t__le32 val;\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1063-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1064: * enum mxl862xx_ss_sp_tag_mask - Special tag valid field indicator bits\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1065- * @MXL862XX_SS_SP_TAG_MASK_RX: valid RX special tag mode\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1069- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1070:enum mxl862xx_ss_sp_tag_mask {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1071-\tMXL862XX_SS_SP_TAG_MASK_RX = BIT(0),\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1077-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1078: * enum mxl862xx_ss_sp_tag_rx - RX special tag mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1079- * @MXL862XX_SS_SP_TAG_RX_NO_TAG_NO_INSERT: packet does NOT have special\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1085- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1086:enum mxl862xx_ss_sp_tag_rx {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1087-\tMXL862XX_SS_SP_TAG_RX_NO_TAG_NO_INSERT = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1092-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1093: * enum mxl862xx_ss_sp_tag_tx - TX special tag mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1094- * @MXL862XX_SS_SP_TAG_TX_NO_TAG_NO_REMOVE: packet does NOT have special\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1102- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1103:enum mxl862xx_ss_sp_tag_tx {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1104-\tMXL862XX_SS_SP_TAG_TX_NO_TAG_NO_REMOVE = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1110-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1111: * enum mxl862xx_ss_sp_tag_rx_pen - RX special tag info over preamble\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1112- * @MXL862XX_SS_SP_TAG_RX_PEN_ALL_0: special tag info inserted from byte 2\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1122- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1123:enum mxl862xx_ss_sp_tag_rx_pen {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1124-\tMXL862XX_SS_SP_TAG_RX_PEN_ALL_0 = 0,\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1130-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1131: * struct mxl862xx_ss_sp_tag - Special tag port settings\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1132- * @pid: port ID (1~16)\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1133: * @mask: See \u0026enum mxl862xx_ss_sp_tag_mask\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1134: * @rx: See \u0026enum mxl862xx_ss_sp_tag_rx\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1135: * @tx: See \u0026enum mxl862xx_ss_sp_tag_tx\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1136: * @rx_pen: See \u0026enum mxl862xx_ss_sp_tag_rx_pen\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1137- * @tx_pen: TX special tag info over preamble\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1140- */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1141:struct mxl862xx_ss_sp_tag {\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1142-\tu8 pid;\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1143:\tu8 mask; /* enum mxl862xx_ss_sp_tag_mask */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1144:\tu8 rx; /* enum mxl862xx_ss_sp_tag_rx */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1145:\tu8 tx; /* enum mxl862xx_ss_sp_tag_tx */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1146:\tu8 rx_pen; /* enum mxl862xx_ss_sp_tag_rx_pen */\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1147-\tu8 tx_pen; /* boolean */\n--\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1150-/**\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h:1151: * enum mxl862xx_logical_port_mode - Logical port mode\ndrivers/net/dsa/mxl862xx/mxl862xx-api.h-1152- * @MXL862XX_LOGICAL_PORT_8BIT_WLAN: WLAN with 8-bit station ID\n--\n\n"
}

5/2 2026/07/14 04:57 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 30767
							output: 37
							thoughts: 106
						

Thoughts:
**Analyzing the MXL862XX Switch Driver**

Okay, so I'm looking at `drivers/net/dsa/mxl862xx/mxl862xx.c`. Right off the bat, I need to figure out if this is a physical hardware driver, which it almost certainly is. The name `mxl862xx` strongly suggests it's a MaxLinear switch of some sort. The real question is whether there is any possibility, even a slim one, of emulating this driver for testing or development purposes?

To answer that I'll quickly check the Kconfig files. Either `drivers/net/dsa/mxl862xx/Kconfig` directly or the broader `drivers/net/dsa/Kconfig` to see if there are any hints about dependencies or configuration options that might give me some clues. This will give me a better understanding of how the driver is intended to be used and if there's any flexibility in how it's built or configured.



6/2 2026/07/14 04:57 tool grepper
0m Args:
{
  "Expression": "config NET_DSA_MXL862",
  "PathPrefix": "drivers/net/dsa/"
}

Results:
{
  "Output": "drivers/net/dsa/mxl862xx/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/dsa/mxl862xx/Kconfig:2:config NET_DSA_MXL862\ndrivers/net/dsa/mxl862xx/Kconfig-3-\ttristate \"MaxLinear MxL862xx\"\n"
}

7/2 2026/07/14 04:57 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 31237
							output: 43
							thoughts: 22
						

Thoughts:
Here's my take on the `drivers/net/dsa/mxl862xx/Kconfig` file, thinking like a seasoned embedded systems developer:

**Delving into the MXL862XX Kconfig**

Alright, let's dissect this Kconfig file for the Marvell MXL862XX DSA driver. Immediately, I'm looking for the core options and dependencies. My initial thoughts are geared toward understanding what features are configurable and how they tie into the broader kernel configuration. I need to get a grip on the conditional compilation, which is key.

I see the `config MXL862XX` option – that's the primary switch, I assume. I need to check its dependencies. Likely, this will depend on some base networking or DSA (Distributed Switch Architecture) configuration options. Let me quickly scan for those... Ah, `NET_DSA` seems like the obvious starting point. Good, that makes sense. I would expect some dependencies on MDIO as well. And probably some ARM-specific things since this is an embedded solution.

The `tristate` nature of it is standard. The user will be able to either build it into the kernel, as a module, or not include it at all, based on their setup.

Then, I'll analyze the individual sub-options within `MXL862XX`. I'm guessing there will be toggles for different PHY modes, management interfaces (MDIO?), and perhaps hardware features specific to different MXL862XX revisions, or even features like VLAN support. I need to determine if there are any default values for the most common use cases, especially if they are sensible defaults that a user will not need to change.

The presence of `help` text is crucial. That's where I will find the real meat of the configuration, the explanation of each option, what it does, and any potential side effects. I need to be sure that the descriptions are clear and accurate. Is there any cross-referencing to the device documentation or datasheets? That would be a huge plus.

I am also keeping an eye out for any potential conflicts. Does one option exclude another? Or are there interactions I need to be aware of? I need to analyze how this Kconfig file integrates with other configurations in the `drivers/net/dsa` subtree and possibly even the broader networking stack. I need to ensure it's clean and doesn't introduce any surprises.



8/2 2026/07/14 04:57 tool read-file
0m Args:
{
  "File": "drivers/net/dsa/mxl862xx/Kconfig",
  "FirstLine": 1,
  "LineCount": 100
}

Results:
{
  "Contents": "   1:\t# SPDX-License-Identifier: GPL-2.0-only\n   2:\tconfig NET_DSA_MXL862\n   3:\t\ttristate \"MaxLinear MxL862xx\"\n   4:\t\tdepends on NET_DSA\n   5:\t\tselect CRC16\n   6:\t\tselect NET_DSA_TAG_MXL_862XX\n   7:\t\thelp\n   8:\t\t  This enables support for the MaxLinear MxL862xx switch family.\n   9:\t\t  These switches have two 10GE SerDes interfaces, one typically\n  10:\t\t  used as CPU port.\n  11:\t\t   - MxL86282 has eight 2.5 Gigabit PHYs\n  12:\t\t   - MxL86252 has five 2.5 Gigabit PHYs\n"
}

9/2 2026/07/14 04:57 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 32031
							output: 42
							thoughts: 141
						

Thoughts:
**Analyzing the Hardware Switch Driver**

Okay, so I'm looking at this driver. It's a hardware switch driver, specifically for the MaxLinear MxL862xx. The first question that pops into my head is, can I even get at this thing in a virtualized environment? Likely not, since it's a *physical* hardware driver. Unless there's some kind of emulator for the MxL862xx, and that's pretty improbable.

Then I remember something important: syzbot, the automated kernel fuzzer I'm using, *doesn't* have that specific hardware. This driver is off the table for syzkaller.

Hmm, but is there *any* way to emulate it? Perhaps there's a workaround. Since it's an MDIO device, I think there may be an option, but the device needs to register with MDIO. Now, the next step is to examine `drivers/net/dsa/mxl862xx/mxl862xx.c` to see how it performs its probe, and see if there are any hooks I can use.



10/2 2026/07/14 04:57 tool grepper
0m Args:
{
  "Expression": "mxl862xx_probe",
  "PathPrefix": "drivers/net/dsa/mxl862xx/"
}

Results:
{
  "Output": "drivers/net/dsa/mxl862xx/mxl862xx.c=2090=static const struct dsa_switch_ops mxl862xx_switch_ops = {\n--\ndrivers/net/dsa/mxl862xx/mxl862xx.c-2125-\ndrivers/net/dsa/mxl862xx/mxl862xx.c:2126:static int mxl862xx_probe(struct mdio_device *mdiodev)\ndrivers/net/dsa/mxl862xx/mxl862xx.c-2127-{\n--\ndrivers/net/dsa/mxl862xx/mxl862xx.c=2235=static struct mdio_driver mxl862xx_driver = {\ndrivers/net/dsa/mxl862xx/mxl862xx.c:2236:\t.probe  = mxl862xx_probe,\ndrivers/net/dsa/mxl862xx/mxl862xx.c-2237-\t.remove = mxl862xx_remove,\n"
}

11/2 2026/07/14 04:57 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 32761
							output: 85
							thoughts: 404
						

Thoughts:
**MDIO Driver Fuzzing Feasibility Assessment**

Okay, so I'm looking at this patch for an MDIO driver. My initial thought is, can syzkaller even touch MDIO devices? Typically, they're probed through device tree or ACPI, not something syzkaller is readily set up to handle, unless there's a specific pseudo-device or a syzkaller-controlled virtual bus. I *don't* think syzkaller can directly inject MDIO devices, and even if it could, we'd be talking about needing the *specific* hardware or a detailed software emulator. And since this is a *physical* hardware driver, it's a non-starter in virtualized environments like GCE or QEMU. My gut says, "WorthFuzzing=false".

Let me double check... are there any Netlink interfaces that might provide a backdoor? Alright, the patch adds `mxl862xx_devlink_info_get` and `mxl862xx_devlink_flash_update`, which are devlink operations. Those are registered when the DSA switch is registered, and the DSA switch itself is registered in `mxl862xx_probe`. So if the device doesn't probe, these devlink ops *won't* be registered, and that code is unreachable.

Okay, is there *any* other conceivable path to reach this code? Nope, it's a pure hardware driver.

Wait... let me re-read the prompt. It says to return `WorthFuzzing=false` if the code path is unreachable in virtualized environments. And this is a hardware driver for a specific switch (MaxLinear MxL862xx) and there's no software emulator for it. This *definitely* falls under that category.

Alright, I'm confident. I will return `WorthFuzzing=false`.



12/2 2026/07/14 04:57 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch modifies a driver for physical hardware (MaxLinear MxL862xx switch) which is an MDIO device. There is no software emulator for this hardware in virtualized environments like QEMU or GCE, making the code unreachable during fuzzing.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch modifies a driver for physical hardware (MaxLinear MxL862xx switch) which is an MDIO device. There is no software emulator for this hardware in virtualized environments like QEMU or GCE, making the code unreachable during fuzzing.",
  "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)