| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/27 14:22 | flow | patch-triage |
1mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies the Marvell 88E6xxx Ethernet switch driver (drivers/net/dsa/mv88e6xxx) and adds a new DSA tag protocol in net/dsa/tag_dsa.c. The Marvell 88E6xxx driver is for physical hardware switches and is not emulated in standard QEMU/GCE environments. The new tag protocol in tag_dsa.c simply reuses existing transmit and receive functions (edsa_xmit, edsa_rcv) and contains no new executable logic. Therefore, the new code is unreachable and cannot be fuzzed in a virtualized environment.",
"WorthFuzzing": false
} |
| 1/1 | 2026/07/27 14:22 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 9ee73e46f41f2256563b7c4c03f1c3e1da10d95b\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Mon Jul 27 14:22:45 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/Documentation/devicetree/bindings/net/dsa/dsa-port.yaml b/Documentation/devicetree/bindings/net/dsa/dsa-port.yaml\nindex 4801204699534b..8d12c8f1bd51ec 100644\n--- a/Documentation/devicetree/bindings/net/dsa/dsa-port.yaml\n+++ b/Documentation/devicetree/bindings/net/dsa/dsa-port.yaml\n@@ -53,6 +53,7 @@ properties:\n enum:\n - dsa\n - edsa\n+ - edsa-ptp-reserved2-ts\n - ocelot\n - ocelot-8021q\n - rtl8_4\ndiff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c\nindex 80b877c74513d6..e92524beb40c46 100644\n--- a/drivers/net/dsa/mv88e6xxx/chip.c\n+++ b/drivers/net/dsa/mv88e6xxx/chip.c\n@@ -3271,7 +3271,8 @@ static int mv88e6xxx_setup_port_mode(struct mv88e6xxx_chip *chip, int port)\n \tif (chip-\u003etag_protocol == DSA_TAG_PROTO_DSA)\n \t\treturn mv88e6xxx_set_port_mode_dsa(chip, port);\n \n-\tif (chip-\u003etag_protocol == DSA_TAG_PROTO_EDSA)\n+\tif (chip-\u003etag_protocol == DSA_TAG_PROTO_EDSA ||\n+\t chip-\u003etag_protocol == DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS)\n \t\treturn mv88e6xxx_set_port_mode_edsa(chip, port);\n \n \treturn -EINVAL;\n@@ -6370,6 +6371,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {\n \t\t.edsa_support = MV88E6XXX_EDSA_SUPPORTED,\n \t\t.ptp_support = true,\n \t\t.ops = \u0026mv88e6341_ops,\n+\t\t.supports_ptp_embedded_ts = true,\n \t},\n \n \t[MV88E6350] = {\n@@ -6447,6 +6449,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {\n \t\t.edsa_support = MV88E6XXX_EDSA_SUPPORTED,\n \t\t.ptp_support = true,\n \t\t.ops = \u0026mv88e6352_ops,\n+\t\t.supports_ptp_embedded_ts = true,\n \t},\n \t[MV88E6361] = {\n \t\t.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6361,\n@@ -6635,6 +6638,7 @@ static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev)\n \tchip-\u003edev = dev;\n \n \tmutex_init(\u0026chip-\u003ereg_lock);\n+\tspin_lock_init(\u0026chip-\u003eptp_clock_lock);\n \tINIT_LIST_HEAD(\u0026chip-\u003emdios);\n \tidr_init(\u0026chip-\u003epolicies);\n \tINIT_LIST_HEAD(\u0026chip-\u003emsts);\n@@ -6658,9 +6662,17 @@ static int mv88e6xxx_change_tag_protocol(struct dsa_switch *ds,\n \tstruct mv88e6xxx_chip *chip = ds-\u003epriv;\n \tenum dsa_tag_protocol old_protocol;\n \tstruct dsa_port *cpu_dp;\n-\tint err;\n+\tint err = 0;\n \n+\t/* The embedded arrival-time-stamp protocol is an EDSA extension: EDSA\n+\t * is the modern tag format for these switches, so it is the one we\n+\t * extend; the legacy DSA tag is intentionally left un-extended.\n+\t */\n \tswitch (proto) {\n+\tcase DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS:\n+\t\tif (!chip-\u003einfo-\u003esupports_ptp_embedded_ts)\n+\t\t\treturn -EPROTONOSUPPORT;\n+\t\tfallthrough;\n \tcase DSA_TAG_PROTO_EDSA:\n \t\tswitch (chip-\u003einfo-\u003eedsa_support) {\n \t\tcase MV88E6XXX_EDSA_UNSUPPORTED:\n@@ -6689,7 +6701,12 @@ static int mv88e6xxx_change_tag_protocol(struct dsa_switch *ds,\n \t\t\tgoto unwind;\n \t\t}\n \t}\n+\n+\tif (chip-\u003einfo-\u003eptp_support)\n+\t\terr = mv88e6xxx_hwtstamp_setup_arr_ts(chip);\n \tmv88e6xxx_reg_unlock(chip);\n+\tif (err)\n+\t\tgoto unwind;\n \n \treturn 0;\n \n@@ -6699,6 +6716,15 @@ static int mv88e6xxx_change_tag_protocol(struct dsa_switch *ds,\n \tmv88e6xxx_reg_lock(chip);\n \tdsa_switch_for_each_cpu_port_continue_reverse(cpu_dp, ds)\n \t\tmv88e6xxx_setup_port_mode(chip, cpu_dp-\u003eindex);\n+\tif (chip-\u003einfo-\u003eptp_support) {\n+\t\t/* Nothing else can be done here, but leaving a port embedding\n+\t\t * time stamps the driver will not strip corrupts every PTP\n+\t\t * event frame it receives, so make the failure visible.\n+\t\t */\n+\t\tif (mv88e6xxx_hwtstamp_setup_arr_ts(chip))\n+\t\t\tdev_err(chip-\u003edev,\n+\t\t\t\t\"failed to restore arrival time stamp mode\\n\");\n+\t}\n \tmv88e6xxx_reg_unlock(chip);\n \n \treturn err;\ndiff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h\nindex e966e7c4cc5dea..c75a71464b20ab 100644\n--- a/drivers/net/dsa/mv88e6xxx/chip.h\n+++ b/drivers/net/dsa/mv88e6xxx/chip.h\n@@ -180,6 +180,13 @@ struct mv88e6xxx_info {\n \t * port 0, 1 means internal PHYs range starts at port 1, etc\n \t */\n \tunsigned int internal_phys_offset;\n+\n+\t/* The switch can embed the PTP arrival time stamp in the reserved2\n+\t * field of the PTP common header, which the edsa-ptp-reserved2-ts\n+\t * tag protocol selects. Otherwise arrival time stamps are only\n+\t * available from the switch registers.\n+\t */\n+\tbool supports_ptp_embedded_ts;\n };\n \n struct mv88e6xxx_atu_entry {\n@@ -419,9 +426,12 @@ struct mv88e6xxx_chip {\n \t/* GPIO resources */\n \tu8 gpio_data[2];\n \n-\t/* This cyclecounter abstracts the switch PTP time.\n-\t * reg_lock must be held for any operation that read()s.\n+\t/* This cyclecounter abstracts the switch PTP time. ptp_clock_lock\n+\t * protects tstamp_cc and tstamp_tc. tstamp_cycles caches the\n+\t * result most recently returned by mv88e6xxx_ptp_read_cycles().\n \t */\n+\tspinlock_t\t\tptp_clock_lock;\n+\tu64\t\t\ttstamp_cycles;\n \tstruct cyclecounter\ttstamp_cc;\n \tstruct timecounter\ttstamp_tc;\n \tstruct delayed_work\toverflow_work;\n@@ -815,6 +825,14 @@ static inline bool mv88e6xxx_has_lag(struct mv88e6xxx_chip *chip)\n \treturn !!chip-\u003einfo-\u003eglobal2_addr;\n }\n \n+/* Whether the active tagging protocol has the switch embed arrival time stamps\n+ * in the frame instead of leaving them in the PTP arrival registers.\n+ */\n+static inline bool mv88e6xxx_ptp_embedded_ts(struct mv88e6xxx_chip *chip)\n+{\n+\treturn chip-\u003etag_protocol == DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS;\n+}\n+\n static inline bool mv88e6xxx_has_tcam(struct mv88e6xxx_chip *chip)\n {\n \treturn !!chip-\u003einfo-\u003etcam_addr;\ndiff --git a/drivers/net/dsa/mv88e6xxx/hwtstamp.c b/drivers/net/dsa/mv88e6xxx/hwtstamp.c\nindex 6e6472a3b75ad7..74eaadeeeb7842 100644\n--- a/drivers/net/dsa/mv88e6xxx/hwtstamp.c\n+++ b/drivers/net/dsa/mv88e6xxx/hwtstamp.c\n@@ -15,6 +15,7 @@\n #include \"hwtstamp.h\"\n #include \"ptp.h\"\n #include \u003clinux/ptp_classify.h\u003e\n+#include \u003clinux/unaligned.h\u003e\n \n #define SKB_PTP_TYPE(__skb) (*(unsigned int *)((__skb)-\u003ecb))\n \n@@ -94,6 +95,7 @@ static int mv88e6xxx_set_hwtstamp_config(struct mv88e6xxx_chip *chip, int port,\n \tconst struct mv88e6xxx_ptp_ops *ptp_ops = chip-\u003einfo-\u003eops-\u003eptp_ops;\n \tstruct mv88e6xxx_port_hwtstamp *ps = \u0026chip-\u003eport_hwtstamp[port];\n \tbool tstamp_enable = false;\n+\tint err = 0;\n \n \t/* Prevent the TX/RX paths from trying to interact with the\n \t * timestamp hardware while we reconfigure it.\n@@ -147,20 +149,30 @@ static int mv88e6xxx_set_hwtstamp_config(struct mv88e6xxx_chip *chip, int port,\n \tif (tstamp_enable) {\n \t\tchip-\u003eenable_count += 1;\n \t\tif (chip-\u003eenable_count == 1 \u0026\u0026 ptp_ops-\u003eglobal_enable)\n-\t\t\tptp_ops-\u003eglobal_enable(chip);\n-\t\tif (ptp_ops-\u003eport_enable)\n-\t\t\tptp_ops-\u003eport_enable(chip, port);\n+\t\t\terr = ptp_ops-\u003eglobal_enable(chip);\n+\t\tif (!err \u0026\u0026 ptp_ops-\u003eport_enable)\n+\t\t\terr = ptp_ops-\u003eport_enable(chip, port);\n \t} else {\n \t\tif (ptp_ops-\u003eport_disable)\n-\t\t\tptp_ops-\u003eport_disable(chip, port);\n+\t\t\terr = ptp_ops-\u003eport_disable(chip, port);\n \t\tchip-\u003eenable_count -= 1;\n \t\tif (chip-\u003eenable_count == 0 \u0026\u0026 ptp_ops-\u003eglobal_disable)\n \t\t\tptp_ops-\u003eglobal_disable(chip);\n \t}\n \tmv88e6xxx_reg_unlock(chip);\n \n+\tif (err)\n+\t\treturn err;\n+\n \t/* Once hardware has been configured, enable timestamp checks\n \t * in the RX/TX paths.\n+\t *\n+\t * In embedded mode the switch starts overwriting the PTP header's\n+\t * reserved2 field as soon as CFG2 is armed above, which is before the\n+\t * RX path begins restoring it; on the way down the RX path stops\n+\t * restoring before the hardware stops embedding. An event frame\n+\t * received inside either window is delivered with the switch's\n+\t * arrival counter still in its header.\n \t */\n \tif (tstamp_enable)\n \t\tset_bit(MV88E6XXX_HWTSTAMP_ENABLED, \u0026ps-\u003estate);\n@@ -216,6 +228,10 @@ static struct ptp_header *mv88e6xxx_should_tstamp(struct mv88e6xxx_chip *chip,\n \tif (!chip-\u003einfo-\u003eptp_support)\n \t\treturn NULL;\n \n+\t/* Marvell switches do not support IEEE 1588-2002 (PTPv1). */\n+\tif ((type \u0026 PTP_CLASS_VMASK) != PTP_CLASS_V2)\n+\t\treturn NULL;\n+\n \thdr = ptp_parse_header(skb, type);\n \tif (!hdr)\n \t\treturn NULL;\n@@ -245,6 +261,52 @@ static int seq_match(struct sk_buff *skb, u16 ts_seqid)\n \treturn ts_seqid == ntohs(hdr-\u003esequence_id);\n }\n \n+/* Recover the arrival time the switch wrote over the reserved2 field of the PTP\n+ * common header, restoring the field afterwards.\n+ */\n+static bool parse_embedded_ts(struct sk_buff *skb, u64 *ns)\n+{\n+\tunsigned int off = MV88E6XXX_PTP_ARR_TS_OFFSET;\n+\tstruct ptp_header *hdr;\n+\n+\t*ns = 0;\n+\n+\tif (skb_linearize(skb))\n+\t\treturn false;\n+\n+\thdr = ptp_parse_header(skb, SKB_PTP_TYPE(skb));\n+\tif (!hdr)\n+\t\treturn false;\n+\n+\t*ns = get_unaligned_be32((u8 *)hdr + off);\n+\tmemset((u8 *)hdr + off, 0, 4);\n+\tskb_checksum_complete_unset(skb);\n+\n+\treturn true;\n+}\n+\n+/* Apply the arrival time the switch embedded in the frame. No register access\n+ * is needed, so this runs inline on the receive path rather than being handed\n+ * to the PTP worker. Returns false if the frame could not be restored.\n+ */\n+static bool mv88e6xxx_ptp_rx_timestamp(struct mv88e6xxx_chip *chip,\n+\t\t\t\t struct sk_buff *skb)\n+{\n+\tstruct skb_shared_hwtstamps *shwt;\n+\tu64 ns;\n+\n+\tif (!parse_embedded_ts(skb, \u0026ns))\n+\t\treturn false;\n+\n+\tns = mv88e6xxx_timecounter_cyc2time(chip, ns);\n+\n+\tshwt = skb_hwtstamps(skb);\n+\tmemset(shwt, 0, sizeof(*shwt));\n+\tshwt-\u003ehwtstamp = ns_to_ktime(ns);\n+\n+\treturn true;\n+}\n+\n static void mv88e6xxx_get_rxts(struct mv88e6xxx_chip *chip,\n \t\t\t struct mv88e6xxx_port_hwtstamp *ps,\n \t\t\t struct sk_buff *skb, u16 reg,\n@@ -289,9 +351,7 @@ static void mv88e6xxx_get_rxts(struct mv88e6xxx_chip *chip,\n \t\tif (mv88e6xxx_ts_valid(status) \u0026\u0026 seq_match(skb, seq_id)) {\n \t\t\tns = timehi \u003c\u003c 16 | timelo;\n \n-\t\t\tmv88e6xxx_reg_lock(chip);\n-\t\t\tns = timecounter_cyc2time(\u0026chip-\u003etstamp_tc, ns);\n-\t\t\tmv88e6xxx_reg_unlock(chip);\n+\t\t\tns = mv88e6xxx_timecounter_cyc2time(chip, ns);\n \t\t\tshwt = skb_hwtstamps(skb);\n \t\t\tmemset(shwt, 0, sizeof(*shwt));\n \t\t\tshwt-\u003ehwtstamp = ns_to_ktime(ns);\n@@ -308,7 +368,6 @@ static void mv88e6xxx_rxtstamp_work(struct mv88e6xxx_chip *chip,\n \tstruct sk_buff *skb;\n \n \tskb = skb_dequeue(\u0026ps-\u003erx_queue);\n-\n \tif (skb)\n \t\tmv88e6xxx_get_rxts(chip, ps, skb, ptp_ops-\u003earr0_sts_reg,\n \t\t\t\t \u0026ps-\u003erx_queue);\n@@ -319,9 +378,16 @@ static void mv88e6xxx_rxtstamp_work(struct mv88e6xxx_chip *chip,\n \t\t\t\t \u0026ps-\u003erx_queue2);\n }\n \n-static int is_pdelay_resp(const struct ptp_header *hdr)\n+static bool is_pdelay_msg(const struct ptp_header *hdr)\n {\n-\treturn (hdr-\u003etsmt \u0026 0xf) == 3;\n+\tswitch (ptp_get_msgtype(hdr, PTP_CLASS_V2)) {\n+\tcase PTP_MSGTYPE_PDELAY_REQ:\n+\t\tfallthrough;\n+\tcase PTP_MSGTYPE_PDELAY_RESP:\n+\t\treturn true;\n+\tdefault:\n+\t\treturn false;\n+\t}\n }\n \n bool mv88e6xxx_port_rxtstamp(struct dsa_switch *ds, int port,\n@@ -343,7 +409,22 @@ bool mv88e6xxx_port_rxtstamp(struct dsa_switch *ds, int port,\n \n \tSKB_PTP_TYPE(skb) = type;\n \n-\tif (is_pdelay_resp(hdr))\n+\t/* Embedded arrival times can be returned inline. The switch has\n+\t * overwritten the reserved2 field; if it cannot be restored the frame\n+\t * is no longer what the sender transmitted, so drop it rather than\n+\t * pass up a corrupted header that will fail the PTP-over-UDP checksum\n+\t * anyway.\n+\t */\n+\tif (mv88e6xxx_ptp_embedded_ts(chip)) {\n+\t\tif (!mv88e6xxx_ptp_rx_timestamp(chip, skb)) {\n+\t\t\tkfree_skb_reason(skb, SKB_DROP_REASON_NOMEM);\n+\t\t\treturn true;\n+\t\t}\n+\n+\t\treturn false;\n+\t}\n+\n+\tif (is_pdelay_msg(hdr))\n \t\tskb_queue_tail(\u0026ps-\u003erx_queue2, skb);\n \telse\n \t\tskb_queue_tail(\u0026ps-\u003erx_queue, skb);\n@@ -409,9 +490,7 @@ static int mv88e6xxx_txtstamp_work(struct mv88e6xxx_chip *chip,\n \n \tmemset(\u0026shhwtstamps, 0, sizeof(shhwtstamps));\n \ttime_raw = ((u32)departure_block[2] \u003c\u003c 16) | departure_block[1];\n-\tmv88e6xxx_reg_lock(chip);\n-\tns = timecounter_cyc2time(\u0026chip-\u003etstamp_tc, time_raw);\n-\tmv88e6xxx_reg_unlock(chip);\n+\tns = mv88e6xxx_timecounter_cyc2time(chip, time_raw);\n \tshhwtstamps.hwtstamp = ns_to_ktime(ns);\n \n \tdev_dbg(chip-\u003edev,\n@@ -454,7 +533,9 @@ long mv88e6xxx_hwtstamp_work(struct ptp_clock_info *ptp)\n \t\tif (test_bit(MV88E6XXX_HWTSTAMP_TX_IN_PROGRESS, \u0026ps-\u003estate))\n \t\t\trestart |= mv88e6xxx_txtstamp_work(chip, ps);\n \n-\t\tmv88e6xxx_rxtstamp_work(chip, ps);\n+\t\t/* Embedded arrival times are applied on the receive path. */\n+\t\tif (!mv88e6xxx_ptp_embedded_ts(chip))\n+\t\t\tmv88e6xxx_rxtstamp_work(chip, ps);\n \t}\n \n \treturn restart ? 1 : -1;\n@@ -523,14 +604,43 @@ int mv88e6165_global_enable(struct mv88e6xxx_chip *chip)\n \n int mv88e6352_hwtstamp_port_disable(struct mv88e6xxx_chip *chip, int port)\n {\n-\treturn mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,\n-\t\t\t\t\tMV88E6XXX_PORT_PTP_CFG0_DISABLE_PTP);\n+\tint err;\n+\n+\terr = mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,\n+\t\t\t\t MV88E6XXX_PORT_PTP_CFG0_DISABLE_PTP);\n+\tif (err)\n+\t\treturn err;\n+\n+\terr = mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG2, 0);\n+\tif (err)\n+\t\treturn err;\n+\n+\treturn 0;\n+}\n+\n+/* Return the CFG2 ArrTSMode field for the active arrival time-stamp mode. */\n+static u16 mv88e6xxx_arr_ts_cfg2(struct mv88e6xxx_chip *chip)\n+{\n+\treturn mv88e6xxx_ptp_embedded_ts(chip) ?\n+\t\tMV88E6XXX_PORT_PTP_CFG2_ARR_TS_RESERVED2 :\n+\t\tMV88E6XXX_PORT_PTP_CFG2_ARR_TS_DISABLED;\n }\n \n int mv88e6352_hwtstamp_port_enable(struct mv88e6xxx_chip *chip, int port)\n {\n-\treturn mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,\n-\t\t\t\t\tMV88E6XXX_PORT_PTP_CFG0_DISABLE_TSPEC_MATCH);\n+\tint err;\n+\n+\terr = mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG2,\n+\t\t\t\t mv88e6xxx_arr_ts_cfg2(chip));\n+\tif (err)\n+\t\treturn err;\n+\n+\terr = mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,\n+\t\t\t\t MV88E6XXX_PORT_PTP_CFG0_DISABLE_TSPEC_MATCH);\n+\tif (err)\n+\t\treturn err;\n+\n+\treturn 0;\n }\n \n static int mv88e6xxx_hwtstamp_port_setup(struct mv88e6xxx_chip *chip, int port)\n@@ -549,6 +659,72 @@ static int mv88e6xxx_hwtstamp_port_setup(struct mv88e6xxx_chip *chip, int port)\n \treturn 0;\n }\n \n+/* Program the hardware for the arrival time-stamp mode the active tagging\n+ * protocol selects. Called from setup and again whenever the protocol changes,\n+ * as that is what decides where arrival time stamps are delivered.\n+ *\n+ * Must be called with the register lock held.\n+ */\n+int mv88e6xxx_hwtstamp_setup_arr_ts(struct mv88e6xxx_chip *chip)\n+{\n+\tconst struct mv88e6xxx_ptp_ops *ptp_ops = chip-\u003einfo-\u003eops-\u003eptp_ops;\n+\tint err, ret = 0;\n+\tint i;\n+\n+\t/* In embedded mode the switch stamps every event message it forwards,\n+\t * peer delay included, so leave the arrival capture pointer alone\n+\t * rather than diverting peer delay messages to the ARRIVAL1 registers.\n+\t */\n+\terr = mv88e6xxx_ptp_write(chip, MV88E6XXX_PTP_TS_ARRIVAL_PTR,\n+\t\t\t\t mv88e6xxx_ptp_embedded_ts(chip) ? 0 :\n+\t\t\t\t MV88E6XXX_PTP_MSGTYPE_PDLAY_REQ |\n+\t\t\t\t MV88E6XXX_PTP_MSGTYPE_PDLAY_RES);\n+\tif (err)\n+\t\treturn err;\n+\n+\tif (!chip-\u003einfo-\u003esupports_ptp_embedded_ts)\n+\t\treturn 0;\n+\n+\tfor (i = 0; i \u003c mv88e6xxx_num_ports(chip); ++i) {\n+\t\tstruct mv88e6xxx_port_hwtstamp *ps = \u0026chip-\u003eport_hwtstamp[i];\n+\n+\t\t/* Anything already queued was queued under the previous mode\n+\t\t * and can no longer be matched with an arrival time.\n+\t\t */\n+\t\tskb_queue_purge(\u0026ps-\u003erx_queue);\n+\t\tskb_queue_purge(\u0026ps-\u003erx_queue2);\n+\n+\t\t/* The arrival registers keep capturing in embedded mode with\n+\t\t * nothing to drain them, so clear the status here or the\n+\t\t * register path resumes on a stale capture.\n+\t\t */\n+\t\terr = mv88e6xxx_port_ptp_write(chip, i, ptp_ops-\u003earr0_sts_reg, 0);\n+\t\tif (err \u0026\u0026 !ret)\n+\t\t\tret = err;\n+\n+\t\terr = mv88e6xxx_port_ptp_write(chip, i, ptp_ops-\u003earr1_sts_reg, 0);\n+\t\tif (err \u0026\u0026 !ret)\n+\t\t\tret = err;\n+\n+\t\t/* Ports that have not enabled time stamping pick the mode up in\n+\t\t * mv88e6352_hwtstamp_port_enable().\n+\t\t */\n+\t\tif (ps-\u003etstamp_config.rx_filter == HWTSTAMP_FILTER_NONE)\n+\t\t\tcontinue;\n+\n+\t\t/* Program every port even if one fails. A port left embedding\n+\t\t * time stamps that the driver no longer strips corrupts the\n+\t\t * PTP header of every event frame it receives.\n+\t\t */\n+\t\terr = mv88e6xxx_port_ptp_write(chip, i, MV88E6XXX_PORT_PTP_CFG2,\n+\t\t\t\t\t mv88e6xxx_arr_ts_cfg2(chip));\n+\t\tif (err \u0026\u0026 !ret)\n+\t\t\tret = err;\n+\t}\n+\n+\treturn ret;\n+}\n+\n int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip)\n {\n \tconst struct mv88e6xxx_ptp_ops *ptp_ops = chip-\u003einfo-\u003eops-\u003eptp_ops;\n@@ -584,9 +760,7 @@ int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip)\n \tif (err)\n \t\treturn err;\n \n-\t/* Use ARRIVAL1 for peer delay response messages. */\n-\terr = mv88e6xxx_ptp_write(chip, MV88E6XXX_PTP_TS_ARRIVAL_PTR,\n-\t\t\t\t MV88E6XXX_PTP_MSGTYPE_PDLAY_RES);\n+\terr = mv88e6xxx_hwtstamp_setup_arr_ts(chip);\n \tif (err)\n \t\treturn err;\n \ndiff --git a/drivers/net/dsa/mv88e6xxx/hwtstamp.h b/drivers/net/dsa/mv88e6xxx/hwtstamp.h\nindex c359821d5a6eaa..2fe7c7429bff1f 100644\n--- a/drivers/net/dsa/mv88e6xxx/hwtstamp.h\n+++ b/drivers/net/dsa/mv88e6xxx/hwtstamp.h\n@@ -13,6 +13,8 @@\n #ifndef _MV88E6XXX_HWTSTAMP_H\n #define _MV88E6XXX_HWTSTAMP_H\n \n+#include \u003clinux/ptp_classify.h\u003e\n+\n #include \"chip.h\"\n \n /* Global 6352 PTP registers */\n@@ -64,10 +66,21 @@\n \n /* Offset 0x02: PTP Configuration 2 */\n #define MV88E6XXX_PORT_PTP_CFG2\t\t\t\t0x02\n-#define MV88E6XXX_PORT_PTP_CFG2_EMBED_ARRIVAL\t\t0x1000\n #define MV88E6XXX_PORT_PTP_CFG2_DEP_IRQ_EN\t\t0x0002\n #define MV88E6XXX_PORT_PTP_CFG2_ARR_IRQ_EN\t\t0x0001\n \n+/* Arrival Time Stamp Mode (ArrTSMode), CFG2 bits [15:8]: configures how the\n+ * switch embeds the arrival time stamp (PTPArr0Time) into enabled PTP event\n+ * frames. A non-zero value is the byte offset, from the start of the PTP common\n+ * header, at which the switch overwrites four bytes in place; we always point\n+ * it at the header's reserved2 field so the frame length is left alone.\n+ */\n+#define MV88E6XXX_PTP_ARR_TS_OFFSET\t\t\t\\\n+\toffsetof(struct ptp_header, reserved2)\n+#define MV88E6XXX_PORT_PTP_CFG2_ARR_TS_DISABLED\t\t0x0000\n+#define MV88E6XXX_PORT_PTP_CFG2_ARR_TS_RESERVED2\t\\\n+\t(MV88E6XXX_PTP_ARR_TS_OFFSET \u003c\u003c 8)\n+\n /* Offset 0x03: PTP LED Configuration */\n #define MV88E6XXX_PORT_PTP_LED_CFG\t0x03\n \n@@ -126,6 +139,7 @@ int mv88e6xxx_get_ts_info(struct dsa_switch *ds, int port,\n \n long mv88e6xxx_hwtstamp_work(struct ptp_clock_info *ptp);\n int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip);\n+int mv88e6xxx_hwtstamp_setup_arr_ts(struct mv88e6xxx_chip *chip);\n void mv88e6xxx_hwtstamp_free(struct mv88e6xxx_chip *chip);\n int mv88e6352_hwtstamp_port_enable(struct mv88e6xxx_chip *chip, int port);\n int mv88e6352_hwtstamp_port_disable(struct mv88e6xxx_chip *chip, int port);\n@@ -172,6 +186,11 @@ static inline int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip)\n \treturn 0;\n }\n \n+static inline int mv88e6xxx_hwtstamp_setup_arr_ts(struct mv88e6xxx_chip *chip)\n+{\n+\treturn 0;\n+}\n+\n static inline void mv88e6xxx_hwtstamp_free(struct mv88e6xxx_chip *chip)\n {\n }\ndiff --git a/drivers/net/dsa/mv88e6xxx/ptp.c b/drivers/net/dsa/mv88e6xxx/ptp.c\nindex f7603573d3a984..2a7f97625e3756 100644\n--- a/drivers/net/dsa/mv88e6xxx/ptp.c\n+++ b/drivers/net/dsa/mv88e6xxx/ptp.c\n@@ -231,15 +231,37 @@ static void mv88e6352_tai_event_work(struct work_struct *ugly)\n \n \t/* We only have one timestamping channel. */\n \tev.index = 0;\n-\tmv88e6xxx_reg_lock(chip);\n-\tev.timestamp = timecounter_cyc2time(\u0026chip-\u003etstamp_tc, raw_ts);\n-\tmv88e6xxx_reg_unlock(chip);\n+\tev.timestamp = mv88e6xxx_timecounter_cyc2time(chip, raw_ts);\n \n \tptp_clock_event(chip-\u003eptp_clock, \u0026ev);\n out:\n \tschedule_delayed_work(\u0026chip-\u003etai_event_work, TAI_EVENT_WORK_INTERVAL);\n }\n \n+/* Refresh the cached counter value that the read() callback returns. The\n+ * read cannot acquire the register lock whilst holding ptp_clock_lock\n+ * because MDIO reads can sleep. The caller must hold reg_lock, which\n+ * serializes against the other timecounter writers.\n+ */\n+static void mv88e6xxx_ptp_read_cycles(struct mv88e6xxx_chip *chip)\n+{\n+\tconst struct mv88e6xxx_ptp_ops *ptp_ops = chip-\u003einfo-\u003eops-\u003eptp_ops;\n+\n+\tif (ptp_ops-\u003eclock_read)\n+\t\tchip-\u003etstamp_cycles = ptp_ops-\u003eclock_read(\u0026chip-\u003etstamp_cc);\n+}\n+\n+u64 mv88e6xxx_timecounter_cyc2time(struct mv88e6xxx_chip *chip, u64 cycles)\n+{\n+\tu64 ns;\n+\n+\tspin_lock_bh(\u0026chip-\u003eptp_clock_lock);\n+\tns = timecounter_cyc2time(\u0026chip-\u003etstamp_tc, cycles);\n+\tspin_unlock_bh(\u0026chip-\u003eptp_clock_lock);\n+\n+\treturn ns;\n+}\n+\n static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)\n {\n \tstruct mv88e6xxx_chip *chip = ptp_to_chip(ptp);\n@@ -258,9 +280,12 @@ static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)\n \tdiff = div_u64(adj, chip-\u003ecc_coeffs-\u003ecc_mult_dem);\n \n \tmv88e6xxx_reg_lock(chip);\n+\tmv88e6xxx_ptp_read_cycles(chip);\n \n+\tspin_lock_bh(\u0026chip-\u003eptp_clock_lock);\n \ttimecounter_read(\u0026chip-\u003etstamp_tc);\n \tchip-\u003etstamp_cc.mult = neg_adj ? mult - diff : mult + diff;\n+\tspin_unlock_bh(\u0026chip-\u003eptp_clock_lock);\n \n \tmv88e6xxx_reg_unlock(chip);\n \n@@ -271,8 +296,16 @@ static int mv88e6xxx_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)\n {\n \tstruct mv88e6xxx_chip *chip = ptp_to_chip(ptp);\n \n+\t/* No register access is needed here, but reg_lock still serialises\n+\t * this against the other timecounter writers, which drop it only\n+\t * after their hardware read has completed.\n+\t */\n \tmv88e6xxx_reg_lock(chip);\n+\n+\tspin_lock_bh(\u0026chip-\u003eptp_clock_lock);\n \ttimecounter_adjtime(\u0026chip-\u003etstamp_tc, delta);\n+\tspin_unlock_bh(\u0026chip-\u003eptp_clock_lock);\n+\n \tmv88e6xxx_reg_unlock(chip);\n \n \treturn 0;\n@@ -285,7 +318,12 @@ static int mv88e6xxx_ptp_gettime(struct ptp_clock_info *ptp,\n \tu64 ns;\n \n \tmv88e6xxx_reg_lock(chip);\n+\tmv88e6xxx_ptp_read_cycles(chip);\n+\n+\tspin_lock_bh(\u0026chip-\u003eptp_clock_lock);\n \tns = timecounter_read(\u0026chip-\u003etstamp_tc);\n+\tspin_unlock_bh(\u0026chip-\u003eptp_clock_lock);\n+\n \tmv88e6xxx_reg_unlock(chip);\n \n \t*ts = ns_to_timespec64(ns);\n@@ -302,7 +340,12 @@ static int mv88e6xxx_ptp_settime(struct ptp_clock_info *ptp,\n \tns = timespec64_to_ns(ts);\n \n \tmv88e6xxx_reg_lock(chip);\n+\tmv88e6xxx_ptp_read_cycles(chip);\n+\n+\tspin_lock_bh(\u0026chip-\u003eptp_clock_lock);\n \ttimecounter_init(\u0026chip-\u003etstamp_tc, \u0026chip-\u003etstamp_cc, ns);\n+\tspin_unlock_bh(\u0026chip-\u003eptp_clock_lock);\n+\n \tmv88e6xxx_reg_unlock(chip);\n \n \treturn 0;\n@@ -444,14 +487,12 @@ const struct mv88e6xxx_ptp_ops mv88e6390_ptp_ops = {\n \t\t(1 \u003c\u003c HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),\n };\n \n+/* Return the value most recently fetched by mv88e6xxx_ptp_read_cycles()\n+ * rather than reading the hardware over MDIO.\n+ */\n static u64 mv88e6xxx_ptp_clock_read(struct cyclecounter *cc)\n {\n-\tstruct mv88e6xxx_chip *chip = cc_to_chip(cc);\n-\n-\tif (chip-\u003einfo-\u003eops-\u003eptp_ops-\u003eclock_read)\n-\t\treturn chip-\u003einfo-\u003eops-\u003eptp_ops-\u003eclock_read(cc);\n-\n-\treturn 0;\n+\treturn cc_to_chip(cc)-\u003etstamp_cycles;\n }\n \n /* With a 250MHz input clock, the 32-bit timestamp counter overflows in ~17.2\n@@ -486,6 +527,12 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)\n \tchip-\u003etstamp_cc.mult\t= chip-\u003ecc_coeffs-\u003ecc_mult;\n \tchip-\u003etstamp_cc.shift\t= chip-\u003ecc_coeffs-\u003ecc_shift;\n \n+\t/* Prime the cycle counter cache for the timecounter_init() below.\n+\t * The caller holds reg_lock, and nothing can reach the PTP clock\n+\t * until ptp_clock_register() below, so no locking is needed here.\n+\t */\n+\tmv88e6xxx_ptp_read_cycles(chip);\n+\n \ttimecounter_init(\u0026chip-\u003etstamp_tc, \u0026chip-\u003etstamp_cc,\n \t\t\t ktime_to_ns(ktime_get_real()));\n \ndiff --git a/drivers/net/dsa/mv88e6xxx/ptp.h b/drivers/net/dsa/mv88e6xxx/ptp.h\nindex 95bdddb0bf39f8..44718e120de20c 100644\n--- a/drivers/net/dsa/mv88e6xxx/ptp.h\n+++ b/drivers/net/dsa/mv88e6xxx/ptp.h\n@@ -68,6 +68,7 @@\n \n int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip);\n void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip);\n+u64 mv88e6xxx_timecounter_cyc2time(struct mv88e6xxx_chip *chip, u64 cycles);\n \n #define ptp_to_chip(ptp) container_of(ptp, struct mv88e6xxx_chip,\t\\\n \t\t\t\t ptp_clock_info)\ndiff --git a/include/net/dsa.h b/include/net/dsa.h\nindex 8c16ef23cc102a..2dfcc549de2964 100644\n--- a/include/net/dsa.h\n+++ b/include/net/dsa.h\n@@ -59,6 +59,7 @@ struct tc_action;\n #define DSA_TAG_PROTO_MXL_GSW1XX_VALUE\t\t31\n #define DSA_TAG_PROTO_MXL862_VALUE\t\t32\n #define DSA_TAG_PROTO_NETC_VALUE\t\t33\n+#define DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS_VALUE\t34\n \n enum dsa_tag_protocol {\n \tDSA_TAG_PROTO_NONE\t\t= DSA_TAG_PROTO_NONE_VALUE,\n@@ -95,6 +96,7 @@ enum dsa_tag_protocol {\n \tDSA_TAG_PROTO_MXL_GSW1XX\t= DSA_TAG_PROTO_MXL_GSW1XX_VALUE,\n \tDSA_TAG_PROTO_MXL862\t\t= DSA_TAG_PROTO_MXL862_VALUE,\n \tDSA_TAG_PROTO_NETC\t\t= DSA_TAG_PROTO_NETC_VALUE,\n+\tDSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS = DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS_VALUE,\n };\n \n struct dsa_switch;\ndiff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c\nindex d5ffee35fbb53b..7490ecc04aa574 100644\n--- a/net/dsa/tag_dsa.c\n+++ b/net/dsa/tag_dsa.c\n@@ -402,6 +402,23 @@ static const struct dsa_device_ops edsa_netdev_ops = {\n \n DSA_TAG_DRIVER(edsa_netdev_ops);\n MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_EDSA, EDSA_NAME);\n+\n+#define EDSA_PTP_RESERVED2_TS_NAME\t\"edsa-ptp-reserved2-ts\"\n+\n+/* Same wire format as EDSA, except that the switch overwrites the reserved2\n+ * field of the PTP common header with the frame's arrival time stamp.\n+ */\n+static const struct dsa_device_ops edsa_ptp_reserved2_ts_netdev_ops = {\n+\t.name\t\t = EDSA_PTP_RESERVED2_TS_NAME,\n+\t.proto\t\t = DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS,\n+\t.xmit\t\t = edsa_xmit,\n+\t.rcv\t\t = edsa_rcv,\n+\t.needed_headroom = EDSA_HLEN,\n+};\n+\n+DSA_TAG_DRIVER(edsa_ptp_reserved2_ts_netdev_ops);\n+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS,\n+\t\t\t EDSA_PTP_RESERVED2_TS_NAME);\n #endif\t/* CONFIG_NET_DSA_TAG_EDSA */\n \n static struct dsa_tag_driver *dsa_tag_drivers[] = {\n@@ -410,6 +427,7 @@ static struct dsa_tag_driver *dsa_tag_drivers[] = {\n #endif\n #if IS_ENABLED(CONFIG_NET_DSA_TAG_EDSA)\n \t\u0026DSA_TAG_DRIVER_NAME(edsa_netdev_ops),\n+\t\u0026DSA_TAG_DRIVER_NAME(edsa_ptp_reserved2_ts_netdev_ops),\n #endif\n };\n \n"
} |
| 2/1 | 2026/07/27 14:22 | agent | patch-evaluator |
1mModel:best-expensive Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies the Marvell 88E6xxx Ethernet switch driver (drivers/net/dsa/mv88e6xxx) and adds a new DSA tag protocol in net/dsa/tag_dsa.c. The Marvell 88E6xxx driver is for physical hardware switches and is not emulated in standard QEMU/GCE environments. The new tag protocol in tag_dsa.c simply reuses existing transmit and receive functions (edsa_xmit, edsa_rcv) and contains no new executable logic. Therefore, the new code is unreachable and cannot be fuzzed in a virtualized environment.",
"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). - Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU. - Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove) that are executed only during PCI hot-unplug or sysfs driver unbind operations. If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. Prefer non-static, non-inlined API entrypoint functions over internal static helper functions (which are inlined by the compiler and do not have distinct symbol addresses). 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 9ee73e46f41f2256563b7c4c03f1c3e1da10d95b
Author: syz-cluster <triage@syzkaller.com>
Date: Mon Jul 27 14:22:45 2026 +0000
syz-cluster: applied patch under review
diff --git a/Documentation/devicetree/bindings/net/dsa/dsa-port.yaml b/Documentation/devicetree/bindings/net/dsa/dsa-port.yaml
index 4801204699534b..8d12c8f1bd51ec 100644
--- a/Documentation/devicetree/bindings/net/dsa/dsa-port.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/dsa-port.yaml
@@ -53,6 +53,7 @@ properties:
enum:
- dsa
- edsa
+ - edsa-ptp-reserved2-ts
- ocelot
- ocelot-8021q
- rtl8_4
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 80b877c74513d6..e92524beb40c46 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -3271,7 +3271,8 @@ static int mv88e6xxx_setup_port_mode(struct mv88e6xxx_chip *chip, int port)
if (chip->tag_protocol == DSA_TAG_PROTO_DSA)
return mv88e6xxx_set_port_mode_dsa(chip, port);
- if (chip->tag_protocol == DSA_TAG_PROTO_EDSA)
+ if (chip->tag_protocol == DSA_TAG_PROTO_EDSA ||
+ chip->tag_protocol == DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS)
return mv88e6xxx_set_port_mode_edsa(chip, port);
return -EINVAL;
@@ -6370,6 +6371,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.edsa_support = MV88E6XXX_EDSA_SUPPORTED,
.ptp_support = true,
.ops = &mv88e6341_ops,
+ .supports_ptp_embedded_ts = true,
},
[MV88E6350] = {
@@ -6447,6 +6449,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.edsa_support = MV88E6XXX_EDSA_SUPPORTED,
.ptp_support = true,
.ops = &mv88e6352_ops,
+ .supports_ptp_embedded_ts = true,
},
[MV88E6361] = {
.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6361,
@@ -6635,6 +6638,7 @@ static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev)
chip->dev = dev;
mutex_init(&chip->reg_lock);
+ spin_lock_init(&chip->ptp_clock_lock);
INIT_LIST_HEAD(&chip->mdios);
idr_init(&chip->policies);
INIT_LIST_HEAD(&chip->msts);
@@ -6658,9 +6662,17 @@ static int mv88e6xxx_change_tag_protocol(struct dsa_switch *ds,
struct mv88e6xxx_chip *chip = ds->priv;
enum dsa_tag_protocol old_protocol;
struct dsa_port *cpu_dp;
- int err;
+ int err = 0;
+ /* The embedded arrival-time-stamp protocol is an EDSA extension: EDSA
+ * is the modern tag format for these switches, so it is the one we
+ * extend; the legacy DSA tag is intentionally left un-extended.
+ */
switch (proto) {
+ case DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS:
+ if (!chip->info->supports_ptp_embedded_ts)
+ return -EPROTONOSUPPORT;
+ fallthrough;
case DSA_TAG_PROTO_EDSA:
switch (chip->info->edsa_support) {
case MV88E6XXX_EDSA_UNSUPPORTED:
@@ -6689,7 +6701,12 @@ static int mv88e6xxx_change_tag_protocol(struct dsa_switch *ds,
goto unwind;
}
}
+
+ if (chip->info->ptp_support)
+ err = mv88e6xxx_hwtstamp_setup_arr_ts(chip);
mv88e6xxx_reg_unlock(chip);
+ if (err)
+ goto unwind;
return 0;
@@ -6699,6 +6716,15 @@ static int mv88e6xxx_change_tag_protocol(struct dsa_switch *ds,
mv88e6xxx_reg_lock(chip);
dsa_switch_for_each_cpu_port_continue_reverse(cpu_dp, ds)
mv88e6xxx_setup_port_mode(chip, cpu_dp->index);
+ if (chip->info->ptp_support) {
+ /* Nothing else can be done here, but leaving a port embedding
+ * time stamps the driver will not strip corrupts every PTP
+ * event frame it receives, so make the failure visible.
+ */
+ if (mv88e6xxx_hwtstamp_setup_arr_ts(chip))
+ dev_err(chip->dev,
+ "failed to restore arrival time stamp mode\n");
+ }
mv88e6xxx_reg_unlock(chip);
return err;
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index e966e7c4cc5dea..c75a71464b20ab 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -180,6 +180,13 @@ struct mv88e6xxx_info {
* port 0, 1 means internal PHYs range starts at port 1, etc
*/
unsigned int internal_phys_offset;
+
+ /* The switch can embed the PTP arrival time stamp in the reserved2
+ * field of the PTP common header, which the edsa-ptp-reserved2-ts
+ * tag protocol selects. Otherwise arrival time stamps are only
+ * available from the switch registers.
+ */
+ bool supports_ptp_embedded_ts;
};
struct mv88e6xxx_atu_entry {
@@ -419,9 +426,12 @@ struct mv88e6xxx_chip {
/* GPIO resources */
u8 gpio_data[2];
- /* This cyclecounter abstracts the switch PTP time.
- * reg_lock must be held for any operation that read()s.
+ /* This cyclecounter abstracts the switch PTP time. ptp_clock_lock
+ * protects tstamp_cc and tstamp_tc. tstamp_cycles caches the
+ * result most recently returned by mv88e6xxx_ptp_read_cycles().
*/
+ spinlock_t ptp_clock_lock;
+ u64 tstamp_cycles;
struct cyclecounter tstamp_cc;
struct timecounter tstamp_tc;
struct delayed_work overflow_work;
@@ -815,6 +825,14 @@ static inline bool mv88e6xxx_has_lag(struct mv88e6xxx_chip *chip)
return !!chip->info->global2_addr;
}
+/* Whether the active tagging protocol has the switch embed arrival time stamps
+ * in the frame instead of leaving them in the PTP arrival registers.
+ */
+static inline bool mv88e6xxx_ptp_embedded_ts(struct mv88e6xxx_chip *chip)
+{
+ return chip->tag_protocol == DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS;
+}
+
static inline bool mv88e6xxx_has_tcam(struct mv88e6xxx_chip *chip)
{
return !!chip->info->tcam_addr;
diff --git a/drivers/net/dsa/mv88e6xxx/hwtstamp.c b/drivers/net/dsa/mv88e6xxx/hwtstamp.c
index 6e6472a3b75ad7..74eaadeeeb7842 100644
--- a/drivers/net/dsa/mv88e6xxx/hwtstamp.c
+++ b/drivers/net/dsa/mv88e6xxx/hwtstamp.c
@@ -15,6 +15,7 @@
#include "hwtstamp.h"
#include "ptp.h"
#include <linux/ptp_classify.h>
+#include <linux/unaligned.h>
#define SKB_PTP_TYPE(__skb) (*(unsigned int *)((__skb)->cb))
@@ -94,6 +95,7 @@ static int mv88e6xxx_set_hwtstamp_config(struct mv88e6xxx_chip *chip, int port,
const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
bool tstamp_enable = false;
+ int err = 0;
/* Prevent the TX/RX paths from trying to interact with the
* timestamp hardware while we reconfigure it.
@@ -147,20 +149,30 @@ static int mv88e6xxx_set_hwtstamp_config(struct mv88e6xxx_chip *chip, int port,
if (tstamp_enable) {
chip->enable_count += 1;
if (chip->enable_count == 1 && ptp_ops->global_enable)
- ptp_ops->global_enable(chip);
- if (ptp_ops->port_enable)
- ptp_ops->port_enable(chip, port);
+ err = ptp_ops->global_enable(chip);
+ if (!err && ptp_ops->port_enable)
+ err = ptp_ops->port_enable(chip, port);
} else {
if (ptp_ops->port_disable)
- ptp_ops->port_disable(chip, port);
+ err = ptp_ops->port_disable(chip, port);
chip->enable_count -= 1;
if (chip->enable_count == 0 && ptp_ops->global_disable)
ptp_ops->global_disable(chip);
}
mv88e6xxx_reg_unlock(chip);
+ if (err)
+ return err;
+
/* Once hardware has been configured, enable timestamp checks
* in the RX/TX paths.
+ *
+ * In embedded mode the switch starts overwriting the PTP header's
+ * reserved2 field as soon as CFG2 is armed above, which is before the
+ * RX path begins restoring it; on the way down the RX path stops
+ * restoring before the hardware stops embedding. An event frame
+ * received inside either window is delivered with the switch's
+ * arrival counter still in its header.
*/
if (tstamp_enable)
set_bit(MV88E6XXX_HWTSTAMP_ENABLED, &ps->state);
@@ -216,6 +228,10 @@ static struct ptp_header *mv88e6xxx_should_tstamp(struct mv88e6xxx_chip *chip,
if (!chip->info->ptp_support)
return NULL;
+ /* Marvell switches do not support IEEE 1588-2002 (PTPv1). */
+ if ((type & PTP_CLASS_VMASK) != PTP_CLASS_V2)
+ return NULL;
+
hdr = ptp_parse_header(skb, type);
if (!hdr)
return NULL;
@@ -245,6 +261,52 @@ static int seq_match(struct sk_buff *skb, u16 ts_seqid)
return ts_seqid == ntohs(hdr->sequence_id);
}
+/* Recover the arrival time the switch wrote over the reserved2 field of the PTP
+ * common header, restoring the field afterwards.
+ */
+static bool parse_embedded_ts(struct sk_buff *skb, u64 *ns)
+{
+ unsigned int off = MV88E6XXX_PTP_ARR_TS_OFFSET;
+ struct ptp_header *hdr;
+
+ *ns = 0;
+
+ if (skb_linearize(skb))
+ return false;
+
+ hdr = ptp_parse_header(skb, SKB_PTP_TYPE(skb));
+ if (!hdr)
+ return false;
+
+ *ns = get_unaligned_be32((u8 *)hdr + off);
+ memset((u8 *)hdr + off, 0, 4);
+ skb_checksum_complete_unset(skb);
+
+ return true;
+}
+
+/* Apply the arrival time the switch embedded in the frame. No register access
+ * is needed, so this runs inline on the receive path rather than being handed
+ * to the PTP worker. Returns false if the frame could not be restored.
+ */
+static bool mv88e6xxx_ptp_rx_timestamp(struct mv88e6xxx_chip *chip,
+ struct sk_buff *skb)
+{
+ struct skb_shared_hwtstamps *shwt;
+ u64 ns;
+
+ if (!parse_embedded_ts(skb, &ns))
+ return false;
+
+ ns = mv88e6xxx_timecounter_cyc2time(chip, ns);
+
+ shwt = skb_hwtstamps(skb);
+ memset(shwt, 0, sizeof(*shwt));
+ shwt->hwtstamp = ns_to_ktime(ns);
+
+ return true;
+}
+
static void mv88e6xxx_get_rxts(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_port_hwtstamp *ps,
struct sk_buff *skb, u16 reg,
@@ -289,9 +351,7 @@ static void mv88e6xxx_get_rxts(struct mv88e6xxx_chip *chip,
if (mv88e6xxx_ts_valid(status) && seq_match(skb, seq_id)) {
ns = timehi << 16 | timelo;
- mv88e6xxx_reg_lock(chip);
- ns = timecounter_cyc2time(&chip->tstamp_tc, ns);
- mv88e6xxx_reg_unlock(chip);
+ ns = mv88e6xxx_timecounter_cyc2time(chip, ns);
shwt = skb_hwtstamps(skb);
memset(shwt, 0, sizeof(*shwt));
shwt->hwtstamp = ns_to_ktime(ns);
@@ -308,7 +368,6 @@ static void mv88e6xxx_rxtstamp_work(struct mv88e6xxx_chip *chip,
struct sk_buff *skb;
skb = skb_dequeue(&ps->rx_queue);
-
if (skb)
mv88e6xxx_get_rxts(chip, ps, skb, ptp_ops->arr0_sts_reg,
&ps->rx_queue);
@@ -319,9 +378,16 @@ static void mv88e6xxx_rxtstamp_work(struct mv88e6xxx_chip *chip,
&ps->rx_queue2);
}
-static int is_pdelay_resp(const struct ptp_header *hdr)
+static bool is_pdelay_msg(const struct ptp_header *hdr)
{
- return (hdr->tsmt & 0xf) == 3;
+ switch (ptp_get_msgtype(hdr, PTP_CLASS_V2)) {
+ case PTP_MSGTYPE_PDELAY_REQ:
+ fallthrough;
+ case PTP_MSGTYPE_PDELAY_RESP:
+ return true;
+ default:
+ return false;
+ }
}
bool mv88e6xxx_port_rxtstamp(struct dsa_switch *ds, int port,
@@ -343,7 +409,22 @@ bool mv88e6xxx_port_rxtstamp(struct dsa_switch *ds, int port,
SKB_PTP_TYPE(skb) = type;
- if (is_pdelay_resp(hdr))
+ /* Embedded arrival times can be returned inline. The switch has
+ * overwritten the reserved2 field; if it cannot be restored the frame
+ * is no longer what the sender transmitted, so drop it rather than
+ * pass up a corrupted header that will fail the PTP-over-UDP checksum
+ * anyway.
+ */
+ if (mv88e6xxx_ptp_embedded_ts(chip)) {
+ if (!mv88e6xxx_ptp_rx_timestamp(chip, skb)) {
+ kfree_skb_reason(skb, SKB_DROP_REASON_NOMEM);
+ return true;
+ }
+
+ return false;
+ }
+
+ if (is_pdelay_msg(hdr))
skb_queue_tail(&ps->rx_queue2, skb);
else
skb_queue_tail(&ps->rx_queue, skb);
@@ -409,9 +490,7 @@ static int mv88e6xxx_txtstamp_work(struct mv88e6xxx_chip *chip,
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
time_raw = ((u32)departure_block[2] << 16) | departure_block[1];
- mv88e6xxx_reg_lock(chip);
- ns = timecounter_cyc2time(&chip->tstamp_tc, time_raw);
- mv88e6xxx_reg_unlock(chip);
+ ns = mv88e6xxx_timecounter_cyc2time(chip, time_raw);
shhwtstamps.hwtstamp = ns_to_ktime(ns);
dev_dbg(chip->dev,
@@ -454,7 +533,9 @@ long mv88e6xxx_hwtstamp_work(struct ptp_clock_info *ptp)
if (test_bit(MV88E6XXX_HWTSTAMP_TX_IN_PROGRESS, &ps->state))
restart |= mv88e6xxx_txtstamp_work(chip, ps);
- mv88e6xxx_rxtstamp_work(chip, ps);
+ /* Embedded arrival times are applied on the receive path. */
+ if (!mv88e6xxx_ptp_embedded_ts(chip))
+ mv88e6xxx_rxtstamp_work(chip, ps);
}
return restart ? 1 : -1;
@@ -523,14 +604,43 @@ int mv88e6165_global_enable(struct mv88e6xxx_chip *chip)
int mv88e6352_hwtstamp_port_disable(struct mv88e6xxx_chip *chip, int port)
{
- return mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,
- MV88E6XXX_PORT_PTP_CFG0_DISABLE_PTP);
+ int err;
+
+ err = mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,
+ MV88E6XXX_PORT_PTP_CFG0_DISABLE_PTP);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG2, 0);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+/* Return the CFG2 ArrTSMode field for the active arrival time-stamp mode. */
+static u16 mv88e6xxx_arr_ts_cfg2(struct mv88e6xxx_chip *chip)
+{
+ return mv88e6xxx_ptp_embedded_ts(chip) ?
+ MV88E6XXX_PORT_PTP_CFG2_ARR_TS_RESERVED2 :
+ MV88E6XXX_PORT_PTP_CFG2_ARR_TS_DISABLED;
}
int mv88e6352_hwtstamp_port_enable(struct mv88e6xxx_chip *chip, int port)
{
- return mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,
- MV88E6XXX_PORT_PTP_CFG0_DISABLE_TSPEC_MATCH);
+ int err;
+
+ err = mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG2,
+ mv88e6xxx_arr_ts_cfg2(chip));
+ if (err)
+ return err;
+
+ err = mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,
+ MV88E6XXX_PORT_PTP_CFG0_DISABLE_TSPEC_MATCH);
+ if (err)
+ return err;
+
+ return 0;
}
static int mv88e6xxx_hwtstamp_port_setup(struct mv88e6xxx_chip *chip, int port)
@@ -549,6 +659,72 @@ static int mv88e6xxx_hwtstamp_port_setup(struct mv88e6xxx_chip *chip, int port)
return 0;
}
+/* Program the hardware for the arrival time-stamp mode the active tagging
+ * protocol selects. Called from setup and again whenever the protocol changes,
+ * as that is what decides where arrival time stamps are delivered.
+ *
+ * Must be called with the register lock held.
+ */
+int mv88e6xxx_hwtstamp_setup_arr_ts(struct mv88e6xxx_chip *chip)
+{
+ const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
+ int err, ret = 0;
+ int i;
+
+ /* In embedded mode the switch stamps every event message it forwards,
+ * peer delay included, so leave the arrival capture pointer alone
+ * rather than diverting peer delay messages to the ARRIVAL1 registers.
+ */
+ err = mv88e6xxx_ptp_write(chip, MV88E6XXX_PTP_TS_ARRIVAL_PTR,
+ mv88e6xxx_ptp_embedded_ts(chip) ? 0 :
+ MV88E6XXX_PTP_MSGTYPE_PDLAY_REQ |
+ MV88E6XXX_PTP_MSGTYPE_PDLAY_RES);
+ if (err)
+ return err;
+
+ if (!chip->info->supports_ptp_embedded_ts)
+ return 0;
+
+ for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
+ struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[i];
+
+ /* Anything already queued was queued under the previous mode
+ * and can no longer be matched with an arrival time.
+ */
+ skb_queue_purge(&ps->rx_queue);
+ skb_queue_purge(&ps->rx_queue2);
+
+ /* The arrival registers keep capturing in embedded mode with
+ * nothing to drain them, so clear the status here or the
+ * register path resumes on a stale capture.
+ */
+ err = mv88e6xxx_port_ptp_write(chip, i, ptp_ops->arr0_sts_reg, 0);
+ if (err && !ret)
+ ret = err;
+
+ err = mv88e6xxx_port_ptp_write(chip, i, ptp_ops->arr1_sts_reg, 0);
+ if (err && !ret)
+ ret = err;
+
+ /* Ports that have not enabled time stamping pick the mode up in
+ * mv88e6352_hwtstamp_port_enable().
+ */
+ if (ps->tstamp_config.rx_filter == HWTSTAMP_FILTER_NONE)
+ continue;
+
+ /* Program every port even if one fails. A port left embedding
+ * time stamps that the driver no longer strips corrupts the
+ * PTP header of every event frame it receives.
+ */
+ err = mv88e6xxx_port_ptp_write(chip, i, MV88E6XXX_PORT_PTP_CFG2,
+ mv88e6xxx_arr_ts_cfg2(chip));
+ if (err && !ret)
+ ret = err;
+ }
+
+ return ret;
+}
+
int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip)
{
const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
@@ -584,9 +760,7 @@ int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip)
if (err)
return err;
- /* Use ARRIVAL1 for peer delay response messages. */
- err = mv88e6xxx_ptp_write(chip, MV88E6XXX_PTP_TS_ARRIVAL_PTR,
- MV88E6XXX_PTP_MSGTYPE_PDLAY_RES);
+ err = mv88e6xxx_hwtstamp_setup_arr_ts(chip);
if (err)
return err;
diff --git a/drivers/net/dsa/mv88e6xxx/hwtstamp.h b/drivers/net/dsa/mv88e6xxx/hwtstamp.h
index c359821d5a6eaa..2fe7c7429bff1f 100644
--- a/drivers/net/dsa/mv88e6xxx/hwtstamp.h
+++ b/drivers/net/dsa/mv88e6xxx/hwtstamp.h
@@ -13,6 +13,8 @@
#ifndef _MV88E6XXX_HWTSTAMP_H
#define _MV88E6XXX_HWTSTAMP_H
+#include <linux/ptp_classify.h>
+
#include "chip.h"
/* Global 6352 PTP registers */
@@ -64,10 +66,21 @@
/* Offset 0x02: PTP Configuration 2 */
#define MV88E6XXX_PORT_PTP_CFG2 0x02
-#define MV88E6XXX_PORT_PTP_CFG2_EMBED_ARRIVAL 0x1000
#define MV88E6XXX_PORT_PTP_CFG2_DEP_IRQ_EN 0x0002
#define MV88E6XXX_PORT_PTP_CFG2_ARR_IRQ_EN 0x0001
+/* Arrival Time Stamp Mode (ArrTSMode), CFG2 bits [15:8]: configures how the
+ * switch embeds the arrival time stamp (PTPArr0Time) into enabled PTP event
+ * frames. A non-zero value is the byte offset, from the start of the PTP common
+ * header, at which the switch overwrites four bytes in place; we always point
+ * it at the header's reserved2 field so the frame length is left alone.
+ */
+#define MV88E6XXX_PTP_ARR_TS_OFFSET \
+ offsetof(struct ptp_header, reserved2)
+#define MV88E6XXX_PORT_PTP_CFG2_ARR_TS_DISABLED 0x0000
+#define MV88E6XXX_PORT_PTP_CFG2_ARR_TS_RESERVED2 \
+ (MV88E6XXX_PTP_ARR_TS_OFFSET << 8)
+
/* Offset 0x03: PTP LED Configuration */
#define MV88E6XXX_PORT_PTP_LED_CFG 0x03
@@ -126,6 +139,7 @@ int mv88e6xxx_get_ts_info(struct dsa_switch *ds, int port,
long mv88e6xxx_hwtstamp_work(struct ptp_clock_info *ptp);
int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip);
+int mv88e6xxx_hwtstamp_setup_arr_ts(struct mv88e6xxx_chip *chip);
void mv88e6xxx_hwtstamp_free(struct mv88e6xxx_chip *chip);
int mv88e6352_hwtstamp_port_enable(struct mv88e6xxx_chip *chip, int port);
int mv88e6352_hwtstamp_port_disable(struct mv88e6xxx_chip *chip, int port);
@@ -172,6 +186,11 @@ static inline int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip)
return 0;
}
+static inline int mv88e6xxx_hwtstamp_setup_arr_ts(struct mv88e6xxx_chip *chip)
+{
+ return 0;
+}
+
static inline void mv88e6xxx_hwtstamp_free(struct mv88e6xxx_chip *chip)
{
}
diff --git a/drivers/net/dsa/mv88e6xxx/ptp.c b/drivers/net/dsa/mv88e6xxx/ptp.c
index f7603573d3a984..2a7f97625e3756 100644
--- a/drivers/net/dsa/mv88e6xxx/ptp.c
+++ b/drivers/net/dsa/mv88e6xxx/ptp.c
@@ -231,15 +231,37 @@ static void mv88e6352_tai_event_work(struct work_struct *ugly)
/* We only have one timestamping channel. */
ev.index = 0;
- mv88e6xxx_reg_lock(chip);
- ev.timestamp = timecounter_cyc2time(&chip->tstamp_tc, raw_ts);
- mv88e6xxx_reg_unlock(chip);
+ ev.timestamp = mv88e6xxx_timecounter_cyc2time(chip, raw_ts);
ptp_clock_event(chip->ptp_clock, &ev);
out:
schedule_delayed_work(&chip->tai_event_work, TAI_EVENT_WORK_INTERVAL);
}
+/* Refresh the cached counter value that the read() callback returns. The
+ * read cannot acquire the register lock whilst holding ptp_clock_lock
+ * because MDIO reads can sleep. The caller must hold reg_lock, which
+ * serializes against the other timecounter writers.
+ */
+static void mv88e6xxx_ptp_read_cycles(struct mv88e6xxx_chip *chip)
+{
+ const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
+
+ if (ptp_ops->clock_read)
+ chip->tstamp_cycles = ptp_ops->clock_read(&chip->tstamp_cc);
+}
+
+u64 mv88e6xxx_timecounter_cyc2time(struct mv88e6xxx_chip *chip, u64 cycles)
+{
+ u64 ns;
+
+ spin_lock_bh(&chip->ptp_clock_lock);
+ ns = timecounter_cyc2time(&chip->tstamp_tc, cycles);
+ spin_unlock_bh(&chip->ptp_clock_lock);
+
+ return ns;
+}
+
static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{
struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
@@ -258,9 +280,12 @@ static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
diff = div_u64(adj, chip->cc_coeffs->cc_mult_dem);
mv88e6xxx_reg_lock(chip);
+ mv88e6xxx_ptp_read_cycles(chip);
+ spin_lock_bh(&chip->ptp_clock_lock);
timecounter_read(&chip->tstamp_tc);
chip->tstamp_cc.mult = neg_adj ? mult - diff : mult + diff;
+ spin_unlock_bh(&chip->ptp_clock_lock);
mv88e6xxx_reg_unlock(chip);
@@ -271,8 +296,16 @@ static int mv88e6xxx_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
+ /* No register access is needed here, but reg_lock still serialises
+ * this against the other timecounter writers, which drop it only
+ * after their hardware read has completed.
+ */
mv88e6xxx_reg_lock(chip);
+
+ spin_lock_bh(&chip->ptp_clock_lock);
timecounter_adjtime(&chip->tstamp_tc, delta);
+ spin_unlock_bh(&chip->ptp_clock_lock);
+
mv88e6xxx_reg_unlock(chip);
return 0;
@@ -285,7 +318,12 @@ static int mv88e6xxx_ptp_gettime(struct ptp_clock_info *ptp,
u64 ns;
mv88e6xxx_reg_lock(chip);
+ mv88e6xxx_ptp_read_cycles(chip);
+
+ spin_lock_bh(&chip->ptp_clock_lock);
ns = timecounter_read(&chip->tstamp_tc);
+ spin_unlock_bh(&chip->ptp_clock_lock);
+
mv88e6xxx_reg_unlock(chip);
*ts = ns_to_timespec64(ns);
@@ -302,7 +340,12 @@ static int mv88e6xxx_ptp_settime(struct ptp_clock_info *ptp,
ns = timespec64_to_ns(ts);
mv88e6xxx_reg_lock(chip);
+ mv88e6xxx_ptp_read_cycles(chip);
+
+ spin_lock_bh(&chip->ptp_clock_lock);
timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc, ns);
+ spin_unlock_bh(&chip->ptp_clock_lock);
+
mv88e6xxx_reg_unlock(chip);
return 0;
@@ -444,14 +487,12 @@ const struct mv88e6xxx_ptp_ops mv88e6390_ptp_ops = {
(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
};
+/* Return the value most recently fetched by mv88e6xxx_ptp_read_cycles()
+ * rather than reading the hardware over MDIO.
+ */
static u64 mv88e6xxx_ptp_clock_read(struct cyclecounter *cc)
{
- struct mv88e6xxx_chip *chip = cc_to_chip(cc);
-
- if (chip->info->ops->ptp_ops->clock_read)
- return chip->info->ops->ptp_ops->clock_read(cc);
-
- return 0;
+ return cc_to_chip(cc)->tstamp_cycles;
}
/* With a 250MHz input clock, the 32-bit timestamp counter overflows in ~17.2
@@ -486,6 +527,12 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
chip->tstamp_cc.mult = chip->cc_coeffs->cc_mult;
chip->tstamp_cc.shift = chip->cc_coeffs->cc_shift;
+ /* Prime the cycle counter cache for the timecounter_init() below.
+ * The caller holds reg_lock, and nothing can reach the PTP clock
+ * until ptp_clock_register() below, so no locking is needed here.
+ */
+ mv88e6xxx_ptp_read_cycles(chip);
+
timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc,
ktime_to_ns(ktime_get_real()));
diff --git a/drivers/net/dsa/mv88e6xxx/ptp.h b/drivers/net/dsa/mv88e6xxx/ptp.h
index 95bdddb0bf39f8..44718e120de20c 100644
--- a/drivers/net/dsa/mv88e6xxx/ptp.h
+++ b/drivers/net/dsa/mv88e6xxx/ptp.h
@@ -68,6 +68,7 @@
int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip);
void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip);
+u64 mv88e6xxx_timecounter_cyc2time(struct mv88e6xxx_chip *chip, u64 cycles);
#define ptp_to_chip(ptp) container_of(ptp, struct mv88e6xxx_chip, \
ptp_clock_info)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 8c16ef23cc102a..2dfcc549de2964 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -59,6 +59,7 @@ struct tc_action;
#define DSA_TAG_PROTO_MXL_GSW1XX_VALUE 31
#define DSA_TAG_PROTO_MXL862_VALUE 32
#define DSA_TAG_PROTO_NETC_VALUE 33
+#define DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS_VALUE 34
enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
@@ -95,6 +96,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_MXL_GSW1XX = DSA_TAG_PROTO_MXL_GSW1XX_VALUE,
DSA_TAG_PROTO_MXL862 = DSA_TAG_PROTO_MXL862_VALUE,
DSA_TAG_PROTO_NETC = DSA_TAG_PROTO_NETC_VALUE,
+ DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS = DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS_VALUE,
};
struct dsa_switch;
diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c
index d5ffee35fbb53b..7490ecc04aa574 100644
--- a/net/dsa/tag_dsa.c
+++ b/net/dsa/tag_dsa.c
@@ -402,6 +402,23 @@ static const struct dsa_device_ops edsa_netdev_ops = {
DSA_TAG_DRIVER(edsa_netdev_ops);
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_EDSA, EDSA_NAME);
+
+#define EDSA_PTP_RESERVED2_TS_NAME "edsa-ptp-reserved2-ts"
+
+/* Same wire format as EDSA, except that the switch overwrites the reserved2
+ * field of the PTP common header with the frame's arrival time stamp.
+ */
+static const struct dsa_device_ops edsa_ptp_reserved2_ts_netdev_ops = {
+ .name = EDSA_PTP_RESERVED2_TS_NAME,
+ .proto = DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS,
+ .xmit = edsa_xmit,
+ .rcv = edsa_rcv,
+ .needed_headroom = EDSA_HLEN,
+};
+
+DSA_TAG_DRIVER(edsa_ptp_reserved2_ts_netdev_ops);
+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS,
+ EDSA_PTP_RESERVED2_TS_NAME);
#endif /* CONFIG_NET_DSA_TAG_EDSA */
static struct dsa_tag_driver *dsa_tag_drivers[] = {
@@ -410,6 +427,7 @@ static struct dsa_tag_driver *dsa_tag_drivers[] = {
#endif
#if IS_ENABLED(CONFIG_NET_DSA_TAG_EDSA)
&DSA_TAG_DRIVER_NAME(edsa_netdev_ops),
+ &DSA_TAG_DRIVER_NAME(edsa_ptp_reserved2_ts_netdev_ops),
#endif
};
|
| 3/2 | 2026/07/27 14:22 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13093 output: 33 thoughts: 214 Thoughts: **Assessing the Virtualization Impact of a New DSA Tag Protocol** Okay, so we've got a new patch introducing `edsa-ptp-reserved2-ts`, which is a DSA tag protocol. Looks like it's touching `drivers/net/dsa/mv88e6xxx/` and `net/dsa/tag_dsa.c`. Right, that means it's a driver for the Marvell 88E6xxx Ethernet switches. Interesting. It seems we are supporting PTP arrival timestamps in the `reserved2` field of the PTP common header. Functionally, this is a change to the network driver. Now, the critical question, as always: how isolated is this? Given that it's a DSA implementation, it inherently relies on a physical switch device. My main concern is whether this is going to be reproducible, and if this will cause issues down the line with the code. Can this be reached and tested within a virtualized environment? DSA, by its very nature, needs the switch. The question is: is `mv88e6xxx` emulated in QEMU? I doubt it. Let's do a quick search to see if any QEMU emulation exists for these specific Marvell 88E6xxx switches. Frankly, it's rare to find such detailed hardware emulation in QEMU, especially for something as specialized as an Ethernet switch. It tends to be abstracted at a higher layer. We're going to need to dig deeper. I'll search the kernel source itself for `mv88e6xxx` just to be certain. Is this driver purely a hardware driver? |
| 4/2 | 2026/07/27 14:22 | tool | grepper |
0mArgs:{
"Expression": "mv88e6xxx",
"PathPrefix": "drivers/net/dsa/"
}Results: {
"Output": "\nFull output is too long, showing 500 out of 10141 lines.\nUse more precise expression if possible.\n\ndrivers/net/dsa/Kconfig=73=source \"drivers/net/dsa/microchip/Kconfig\"\ndrivers/net/dsa/Kconfig-74-\ndrivers/net/dsa/Kconfig:75:source \"drivers/net/dsa/mv88e6xxx/Kconfig\"\ndrivers/net/dsa/Kconfig-76-\n--\ndrivers/net/dsa/Makefile=21=obj-y\t\t\t\t+= microchip/\ndrivers/net/dsa/Makefile:22:obj-y\t\t\t\t+= mv88e6xxx/\ndrivers/net/dsa/Makefile-23-obj-y\t\t\t\t+= mxl862xx/\n--\ndrivers/net/dsa/mv88e6060.h-5- *\ndrivers/net/dsa/mv88e6060.h:6: * Based on mv88e6xxx.h\ndrivers/net/dsa/mv88e6060.h-7- * Copyright (c) 2008 Marvell Semiconductor\n--\ndrivers/net/dsa/mv88e6xxx/Makefile-1-# SPDX-License-Identifier: GPL-2.0\ndrivers/net/dsa/mv88e6xxx/Makefile:2:obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o\ndrivers/net/dsa/mv88e6xxx/Makefile:3:mv88e6xxx-objs := chip.o\ndrivers/net/dsa/mv88e6xxx/Makefile:4:mv88e6xxx-objs += devlink.o\ndrivers/net/dsa/mv88e6xxx/Makefile:5:mv88e6xxx-objs += global1.o\ndrivers/net/dsa/mv88e6xxx/Makefile:6:mv88e6xxx-objs += global1_atu.o\ndrivers/net/dsa/mv88e6xxx/Makefile:7:mv88e6xxx-objs += global1_vtu.o\ndrivers/net/dsa/mv88e6xxx/Makefile:8:mv88e6xxx-objs += global2.o\ndrivers/net/dsa/mv88e6xxx/Makefile:9:mv88e6xxx-objs += global2_avb.o\ndrivers/net/dsa/mv88e6xxx/Makefile:10:mv88e6xxx-objs += global2_scratch.o\ndrivers/net/dsa/mv88e6xxx/Makefile:11:mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o\ndrivers/net/dsa/mv88e6xxx/Makefile:12:mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_LEDS) += leds.o\ndrivers/net/dsa/mv88e6xxx/Makefile:13:mv88e6xxx-objs += pcs-6185.o\ndrivers/net/dsa/mv88e6xxx/Makefile:14:mv88e6xxx-objs += pcs-6352.o\ndrivers/net/dsa/mv88e6xxx/Makefile:15:mv88e6xxx-objs += pcs-639x.o\ndrivers/net/dsa/mv88e6xxx/Makefile:16:mv88e6xxx-objs += phy.o\ndrivers/net/dsa/mv88e6xxx/Makefile:17:mv88e6xxx-objs += port.o\ndrivers/net/dsa/mv88e6xxx/Makefile:18:mv88e6xxx-objs += port_hidden.o\ndrivers/net/dsa/mv88e6xxx/Makefile:19:mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += ptp.o\ndrivers/net/dsa/mv88e6xxx/Makefile:20:mv88e6xxx-objs += serdes.o\ndrivers/net/dsa/mv88e6xxx/Makefile:21:mv88e6xxx-objs += smi.o\ndrivers/net/dsa/mv88e6xxx/Makefile:22:mv88e6xxx-objs += switchdev.o\ndrivers/net/dsa/mv88e6xxx/Makefile:23:mv88e6xxx-objs += trace.o\ndrivers/net/dsa/mv88e6xxx/Makefile:24:mv88e6xxx-objs += tcflower.o\ndrivers/net/dsa/mv88e6xxx/Makefile:25:mv88e6xxx-objs += tcam.o\ndrivers/net/dsa/mv88e6xxx/Makefile-26-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-14-#include \u003clinux/delay.h\u003e\ndrivers/net/dsa/mv88e6xxx/chip.c:15:#include \u003clinux/dsa/mv88e6xxx.h\u003e\ndrivers/net/dsa/mv88e6xxx/chip.c-16-#include \u003clinux/etherdevice.h\u003e\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-28-#include \u003clinux/of_mdio.h\u003e\ndrivers/net/dsa/mv88e6xxx/chip.c:29:#include \u003clinux/platform_data/mv88e6xxx.h\u003e\ndrivers/net/dsa/mv88e6xxx/chip.c-30-#include \u003clinux/property.h\u003e\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-48-\ndrivers/net/dsa/mv88e6xxx/chip.c:49:static void assert_reg_lock(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-50-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-56-\ndrivers/net/dsa/mv88e6xxx/chip.c:57:int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val)\ndrivers/net/dsa/mv88e6xxx/chip.c-58-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-62-\ndrivers/net/dsa/mv88e6xxx/chip.c:63:\terr = mv88e6xxx_smi_read(chip, addr, reg, val);\ndrivers/net/dsa/mv88e6xxx/chip.c-64-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-72-\ndrivers/net/dsa/mv88e6xxx/chip.c:73:int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val)\ndrivers/net/dsa/mv88e6xxx/chip.c-74-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-78-\ndrivers/net/dsa/mv88e6xxx/chip.c:79:\terr = mv88e6xxx_smi_write(chip, addr, reg, val);\ndrivers/net/dsa/mv88e6xxx/chip.c-80-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-88-\ndrivers/net/dsa/mv88e6xxx/chip.c:89:int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,\ndrivers/net/dsa/mv88e6xxx/chip.c-90-\t\t\tu16 mask, u16 val)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-101-\tfor (i = 0; time_before(jiffies, timeout) || (i \u003c 2); i++) {\ndrivers/net/dsa/mv88e6xxx/chip.c:102:\t\terr = mv88e6xxx_read(chip, addr, reg, \u0026data);\ndrivers/net/dsa/mv88e6xxx/chip.c-103-\t\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-114-\ndrivers/net/dsa/mv88e6xxx/chip.c:115:\terr = mv88e6xxx_read(chip, addr, reg, \u0026data);\ndrivers/net/dsa/mv88e6xxx/chip.c-116-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-125-\ndrivers/net/dsa/mv88e6xxx/chip.c:126:int mv88e6xxx_wait_bit(struct mv88e6xxx_chip *chip, int addr, int reg,\ndrivers/net/dsa/mv88e6xxx/chip.c-127-\t\t int bit, int val)\ndrivers/net/dsa/mv88e6xxx/chip.c-128-{\ndrivers/net/dsa/mv88e6xxx/chip.c:129:\treturn mv88e6xxx_wait_mask(chip, addr, reg, BIT(bit),\ndrivers/net/dsa/mv88e6xxx/chip.c-130-\t\t\t\t val ? BIT(bit) : 0x0000);\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-132-\ndrivers/net/dsa/mv88e6xxx/chip.c:133:struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-134-{\ndrivers/net/dsa/mv88e6xxx/chip.c:135:\tstruct mv88e6xxx_mdio_bus *mdio_bus;\ndrivers/net/dsa/mv88e6xxx/chip.c-136-\ndrivers/net/dsa/mv88e6xxx/chip.c-137-\tmdio_bus = list_first_entry_or_null(\u0026chip-\u003emdios,\ndrivers/net/dsa/mv88e6xxx/chip.c:138:\t\t\t\t\t struct mv88e6xxx_mdio_bus, list);\ndrivers/net/dsa/mv88e6xxx/chip.c-139-\tif (!mdio_bus)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-144-\ndrivers/net/dsa/mv88e6xxx/chip.c:145:static void mv88e6xxx_g1_irq_mask(struct irq_data *d)\ndrivers/net/dsa/mv88e6xxx/chip.c-146-{\ndrivers/net/dsa/mv88e6xxx/chip.c:147:\tstruct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);\ndrivers/net/dsa/mv88e6xxx/chip.c-148-\tunsigned int n = d-\u003ehwirq;\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-152-\ndrivers/net/dsa/mv88e6xxx/chip.c:153:static void mv88e6xxx_g1_irq_unmask(struct irq_data *d)\ndrivers/net/dsa/mv88e6xxx/chip.c-154-{\ndrivers/net/dsa/mv88e6xxx/chip.c:155:\tstruct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);\ndrivers/net/dsa/mv88e6xxx/chip.c-156-\tunsigned int n = d-\u003ehwirq;\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-160-\ndrivers/net/dsa/mv88e6xxx/chip.c:161:static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-162-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-169-\ndrivers/net/dsa/mv88e6xxx/chip.c:170:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c:171:\terr = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, \u0026reg);\ndrivers/net/dsa/mv88e6xxx/chip.c:172:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-173-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-186-\ndrivers/net/dsa/mv88e6xxx/chip.c:187:\t\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c:188:\t\terr = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, \u0026ctl1);\ndrivers/net/dsa/mv88e6xxx/chip.c-189-\t\tif (err)\ndrivers/net/dsa/mv88e6xxx/chip.c-190-\t\t\tgoto unlock;\ndrivers/net/dsa/mv88e6xxx/chip.c:191:\t\terr = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, \u0026reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-192-unlock:\ndrivers/net/dsa/mv88e6xxx/chip.c:193:\t\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-194-\t\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-202-\ndrivers/net/dsa/mv88e6xxx/chip.c:203:static irqreturn_t mv88e6xxx_g1_irq_thread_fn(int irq, void *dev_id)\ndrivers/net/dsa/mv88e6xxx/chip.c-204-{\ndrivers/net/dsa/mv88e6xxx/chip.c:205:\tstruct mv88e6xxx_chip *chip = dev_id;\ndrivers/net/dsa/mv88e6xxx/chip.c-206-\ndrivers/net/dsa/mv88e6xxx/chip.c:207:\treturn mv88e6xxx_g1_irq_thread_work(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-208-}\ndrivers/net/dsa/mv88e6xxx/chip.c-209-\ndrivers/net/dsa/mv88e6xxx/chip.c:210:static void mv88e6xxx_g1_irq_bus_lock(struct irq_data *d)\ndrivers/net/dsa/mv88e6xxx/chip.c-211-{\ndrivers/net/dsa/mv88e6xxx/chip.c:212:\tstruct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);\ndrivers/net/dsa/mv88e6xxx/chip.c-213-\ndrivers/net/dsa/mv88e6xxx/chip.c:214:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-215-}\ndrivers/net/dsa/mv88e6xxx/chip.c-216-\ndrivers/net/dsa/mv88e6xxx/chip.c:217:static void mv88e6xxx_g1_irq_bus_sync_unlock(struct irq_data *d)\ndrivers/net/dsa/mv88e6xxx/chip.c-218-{\ndrivers/net/dsa/mv88e6xxx/chip.c:219:\tstruct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);\ndrivers/net/dsa/mv88e6xxx/chip.c-220-\tu16 mask = GENMASK(chip-\u003eg1_irq.nirqs, 0);\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-223-\ndrivers/net/dsa/mv88e6xxx/chip.c:224:\terr = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, \u0026reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-225-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-230-\ndrivers/net/dsa/mv88e6xxx/chip.c:231:\terr = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-232-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-235-out:\ndrivers/net/dsa/mv88e6xxx/chip.c:236:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-237-}\ndrivers/net/dsa/mv88e6xxx/chip.c-238-\ndrivers/net/dsa/mv88e6xxx/chip.c:239:static const struct irq_chip mv88e6xxx_g1_irq_chip = {\ndrivers/net/dsa/mv88e6xxx/chip.c:240:\t.name\t\t\t= \"mv88e6xxx-g1\",\ndrivers/net/dsa/mv88e6xxx/chip.c:241:\t.irq_mask\t\t= mv88e6xxx_g1_irq_mask,\ndrivers/net/dsa/mv88e6xxx/chip.c:242:\t.irq_unmask\t\t= mv88e6xxx_g1_irq_unmask,\ndrivers/net/dsa/mv88e6xxx/chip.c:243:\t.irq_bus_lock\t\t= mv88e6xxx_g1_irq_bus_lock,\ndrivers/net/dsa/mv88e6xxx/chip.c:244:\t.irq_bus_sync_unlock\t= mv88e6xxx_g1_irq_bus_sync_unlock,\ndrivers/net/dsa/mv88e6xxx/chip.c-245-};\ndrivers/net/dsa/mv88e6xxx/chip.c-246-\ndrivers/net/dsa/mv88e6xxx/chip.c:247:static int mv88e6xxx_g1_irq_domain_map(struct irq_domain *d,\ndrivers/net/dsa/mv88e6xxx/chip.c-248-\t\t\t\t unsigned int irq,\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-250-{\ndrivers/net/dsa/mv88e6xxx/chip.c:251:\tstruct mv88e6xxx_chip *chip = d-\u003ehost_data;\ndrivers/net/dsa/mv88e6xxx/chip.c-252-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-259-\ndrivers/net/dsa/mv88e6xxx/chip.c:260:static const struct irq_domain_ops mv88e6xxx_g1_irq_domain_ops = {\ndrivers/net/dsa/mv88e6xxx/chip.c:261:\t.map\t= mv88e6xxx_g1_irq_domain_map,\ndrivers/net/dsa/mv88e6xxx/chip.c-262-\t.xlate\t= irq_domain_xlate_twocell,\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-265-/* To be called with reg_lock held */\ndrivers/net/dsa/mv88e6xxx/chip.c:266:static void mv88e6xxx_g1_irq_free_common(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-267-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-270-\ndrivers/net/dsa/mv88e6xxx/chip.c:271:\tmv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, \u0026mask);\ndrivers/net/dsa/mv88e6xxx/chip.c-272-\tmask \u0026= ~GENMASK(chip-\u003eg1_irq.nirqs, 0);\ndrivers/net/dsa/mv88e6xxx/chip.c:273:\tmv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);\ndrivers/net/dsa/mv88e6xxx/chip.c-274-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-282-\ndrivers/net/dsa/mv88e6xxx/chip.c:283:static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-284-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-290-\ndrivers/net/dsa/mv88e6xxx/chip.c:291:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c:292:\tmv88e6xxx_g1_irq_free_common(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c:293:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-294-}\ndrivers/net/dsa/mv88e6xxx/chip.c-295-\ndrivers/net/dsa/mv88e6xxx/chip.c:296:static int mv88e6xxx_g1_irq_setup_common(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-297-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-303-\t\tNULL, chip-\u003eg1_irq.nirqs, 0,\ndrivers/net/dsa/mv88e6xxx/chip.c:304:\t\t\u0026mv88e6xxx_g1_irq_domain_ops, chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-305-\tif (!chip-\u003eg1_irq.domain)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-310-\ndrivers/net/dsa/mv88e6xxx/chip.c:311:\tchip-\u003eg1_irq.chip = mv88e6xxx_g1_irq_chip;\ndrivers/net/dsa/mv88e6xxx/chip.c-312-\tchip-\u003eg1_irq.masked = ~0;\ndrivers/net/dsa/mv88e6xxx/chip.c-313-\ndrivers/net/dsa/mv88e6xxx/chip.c:314:\terr = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, \u0026mask);\ndrivers/net/dsa/mv88e6xxx/chip.c-315-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-319-\ndrivers/net/dsa/mv88e6xxx/chip.c:320:\terr = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);\ndrivers/net/dsa/mv88e6xxx/chip.c-321-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-324-\t/* Reading the interrupt status clears (most of) them */\ndrivers/net/dsa/mv88e6xxx/chip.c:325:\terr = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, \u0026reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-326-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-332-\tmask \u0026= ~GENMASK(chip-\u003eg1_irq.nirqs, 0);\ndrivers/net/dsa/mv88e6xxx/chip.c:333:\tmv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);\ndrivers/net/dsa/mv88e6xxx/chip.c-334-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-345-\ndrivers/net/dsa/mv88e6xxx/chip.c:346:static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-347-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-351-\ndrivers/net/dsa/mv88e6xxx/chip.c:352:\terr = mv88e6xxx_g1_irq_setup_common(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-353-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-362-\tsnprintf(chip-\u003eirq_name, sizeof(chip-\u003eirq_name),\ndrivers/net/dsa/mv88e6xxx/chip.c:363:\t\t \"mv88e6xxx-%s\", dev_name(chip-\u003edev));\ndrivers/net/dsa/mv88e6xxx/chip.c-364-\ndrivers/net/dsa/mv88e6xxx/chip.c:365:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-366-\terr = request_threaded_irq(chip-\u003eirq, NULL,\ndrivers/net/dsa/mv88e6xxx/chip.c:367:\t\t\t\t mv88e6xxx_g1_irq_thread_fn,\ndrivers/net/dsa/mv88e6xxx/chip.c-368-\t\t\t\t IRQF_ONESHOT | IRQF_SHARED,\ndrivers/net/dsa/mv88e6xxx/chip.c-369-\t\t\t\t chip-\u003eirq_name, chip);\ndrivers/net/dsa/mv88e6xxx/chip.c:370:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-371-\tif (err)\ndrivers/net/dsa/mv88e6xxx/chip.c:372:\t\tmv88e6xxx_g1_irq_free_common(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-373-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-376-\ndrivers/net/dsa/mv88e6xxx/chip.c:377:static void mv88e6xxx_irq_poll(struct kthread_work *work)\ndrivers/net/dsa/mv88e6xxx/chip.c-378-{\ndrivers/net/dsa/mv88e6xxx/chip.c:379:\tstruct mv88e6xxx_chip *chip = container_of(work,\ndrivers/net/dsa/mv88e6xxx/chip.c:380:\t\t\t\t\t\t struct mv88e6xxx_chip,\ndrivers/net/dsa/mv88e6xxx/chip.c-381-\t\t\t\t\t\t irq_poll_work.work);\ndrivers/net/dsa/mv88e6xxx/chip.c:382:\tmv88e6xxx_g1_irq_thread_work(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-383-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-387-\ndrivers/net/dsa/mv88e6xxx/chip.c:388:static int mv88e6xxx_irq_poll_setup(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-389-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-391-\ndrivers/net/dsa/mv88e6xxx/chip.c:392:\terr = mv88e6xxx_g1_irq_setup_common(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-393-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-396-\tkthread_init_delayed_work(\u0026chip-\u003eirq_poll_work,\ndrivers/net/dsa/mv88e6xxx/chip.c:397:\t\t\t\t mv88e6xxx_irq_poll);\ndrivers/net/dsa/mv88e6xxx/chip.c-398-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-408-\ndrivers/net/dsa/mv88e6xxx/chip.c:409:static void mv88e6xxx_irq_poll_free(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-410-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-413-\ndrivers/net/dsa/mv88e6xxx/chip.c:414:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c:415:\tmv88e6xxx_g1_irq_free_common(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c:416:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-417-}\ndrivers/net/dsa/mv88e6xxx/chip.c-418-\ndrivers/net/dsa/mv88e6xxx/chip.c:419:static int mv88e6xxx_port_config_interface(struct mv88e6xxx_chip *chip,\ndrivers/net/dsa/mv88e6xxx/chip.c-420-\t\t\t\t\t int port, phy_interface_t interface)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-440-\ndrivers/net/dsa/mv88e6xxx/chip.c:441:static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-442-\t\t\t\t int link, int speed, int duplex, int pause,\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-467-\ndrivers/net/dsa/mv88e6xxx/chip.c:468:\terr = mv88e6xxx_port_config_interface(chip, port, mode);\ndrivers/net/dsa/mv88e6xxx/chip.c-469-restore_link:\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-475-\ndrivers/net/dsa/mv88e6xxx/chip.c:476:static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port)\ndrivers/net/dsa/mv88e6xxx/chip.c-477-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-482-\ndrivers/net/dsa/mv88e6xxx/chip.c:483:static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port)\ndrivers/net/dsa/mv88e6xxx/chip.c-484-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-491-\tif (chip-\u003einfo-\u003efamily == MV88E6XXX_FAMILY_6250)\ndrivers/net/dsa/mv88e6xxx/chip.c:492:\t\treturn mv88e6xxx_phy_is_internal(chip, port);\ndrivers/net/dsa/mv88e6xxx/chip.c-493-\ndrivers/net/dsa/mv88e6xxx/chip.c:494:\terr = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, \u0026reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-495-\tif (err) {\n--\ndrivers/net/dsa/mv88e6xxx/chip.c=505=static const u8 mv88e6185_phy_interface_modes[] = {\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-514-\ndrivers/net/dsa/mv88e6xxx/chip.c:515:static void mv88e6095_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-516-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-521-\ndrivers/net/dsa/mv88e6xxx/chip.c:522:\tif (mv88e6xxx_phy_is_internal(chip, port)) {\ndrivers/net/dsa/mv88e6xxx/chip.c-523-\t\t__set_bit(PHY_INTERFACE_MODE_MII, config-\u003esupported_interfaces);\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-533-\ndrivers/net/dsa/mv88e6xxx/chip.c:534:static void mv88e6185_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-535-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-547-\ndrivers/net/dsa/mv88e6xxx/chip.c:548:static const u8 mv88e6xxx_phy_interface_modes[] = {\ndrivers/net/dsa/mv88e6xxx/chip.c-549-\t[MV88E6XXX_PORT_STS_CMODE_MII_PHY]\t= PHY_INTERFACE_MODE_REVMII,\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-562-\ndrivers/net/dsa/mv88e6xxx/chip.c:563:static void mv88e6xxx_translate_cmode(u8 cmode, unsigned long *supported)\ndrivers/net/dsa/mv88e6xxx/chip.c-564-{\ndrivers/net/dsa/mv88e6xxx/chip.c:565:\tif (cmode \u003c ARRAY_SIZE(mv88e6xxx_phy_interface_modes) \u0026\u0026\ndrivers/net/dsa/mv88e6xxx/chip.c:566:\t mv88e6xxx_phy_interface_modes[cmode])\ndrivers/net/dsa/mv88e6xxx/chip.c:567:\t\t__set_bit(mv88e6xxx_phy_interface_modes[cmode], supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-568-\telse if (cmode == MV88E6XXX_PORT_STS_CMODE_RGMII)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c=572=static void\ndrivers/net/dsa/mv88e6xxx/chip.c:573:mv88e6250_setup_supported_interfaces(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-574-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-579-\ndrivers/net/dsa/mv88e6xxx/chip.c:580:\terr = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, \u0026reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-581-\tif (err) {\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-621-\ndrivers/net/dsa/mv88e6xxx/chip.c:622:static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-623-\t\t\t\t struct phylink_config *config)\ndrivers/net/dsa/mv88e6xxx/chip.c-624-{\ndrivers/net/dsa/mv88e6xxx/chip.c:625:\tif (!mv88e6xxx_phy_is_internal(chip, port))\ndrivers/net/dsa/mv88e6xxx/chip.c-626-\t\tmv88e6250_setup_supported_interfaces(chip, port, config);\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-630-\ndrivers/net/dsa/mv88e6xxx/chip.c:631:static void mv88e6351_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-632-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-636-\t/* Translate the default cmode */\ndrivers/net/dsa/mv88e6xxx/chip.c:637:\tmv88e6xxx_translate_cmode(chip-\u003eports[port].cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-638-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-642-\ndrivers/net/dsa/mv88e6xxx/chip.c:643:static int mv88e63xx_get_port_serdes_cmode(struct mv88e6xxx_chip *chip, int port)\ndrivers/net/dsa/mv88e6xxx/chip.c-644-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-647-\ndrivers/net/dsa/mv88e6xxx/chip.c:648:\terr = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, \u0026reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-649-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-656-\tval = reg \u0026 ~MV88E6XXX_PORT_STS_PHY_DETECT;\ndrivers/net/dsa/mv88e6xxx/chip.c:657:\terr = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, val);\ndrivers/net/dsa/mv88e6xxx/chip.c-658-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-660-\ndrivers/net/dsa/mv88e6xxx/chip.c:661:\terr = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, \u0026val);\ndrivers/net/dsa/mv88e6xxx/chip.c-662-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-665-\t/* Restore PHY_DETECT value */\ndrivers/net/dsa/mv88e6xxx/chip.c:666:\terr = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-667-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-672-\ndrivers/net/dsa/mv88e6xxx/chip.c:673:static void mv88e6352_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-674-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-679-\t/* Translate the default cmode */\ndrivers/net/dsa/mv88e6xxx/chip.c:680:\tmv88e6xxx_translate_cmode(chip-\u003eports[port].cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-681-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-695-\t\telse\ndrivers/net/dsa/mv88e6xxx/chip.c:696:\t\t\tmv88e6xxx_translate_cmode(cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-697-\t}\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-699-\ndrivers/net/dsa/mv88e6xxx/chip.c:700:static void mv88e632x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-701-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-706-\t/* Translate the default cmode */\ndrivers/net/dsa/mv88e6xxx/chip.c:707:\tmv88e6xxx_translate_cmode(chip-\u003eports[port].cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-708-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-718-\t\telse\ndrivers/net/dsa/mv88e6xxx/chip.c:719:\t\t\tmv88e6xxx_translate_cmode(cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-720-\t}\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-722-\ndrivers/net/dsa/mv88e6xxx/chip.c:723:static void mv88e6341_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-724-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-728-\t/* Translate the default cmode */\ndrivers/net/dsa/mv88e6xxx/chip.c:729:\tmv88e6xxx_translate_cmode(chip-\u003eports[port].cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-730-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-744-\ndrivers/net/dsa/mv88e6xxx/chip.c:745:static void mv88e6390_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-746-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-750-\t/* Translate the default cmode */\ndrivers/net/dsa/mv88e6xxx/chip.c:751:\tmv88e6xxx_translate_cmode(chip-\u003eports[port].cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-752-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-766-\ndrivers/net/dsa/mv88e6xxx/chip.c:767:static void mv88e6390x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-768-\t\t\t\t\tstruct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-801-\ndrivers/net/dsa/mv88e6xxx/chip.c:802:static void mv88e6393x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-803-\t\t\t\t\tstruct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-810-\ndrivers/net/dsa/mv88e6xxx/chip.c:811:\tmv88e6xxx_translate_cmode(chip-\u003eports[port].cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-812-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-845-\ndrivers/net/dsa/mv88e6xxx/chip.c:846:static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-847-\t\t\t struct phylink_config *config)\ndrivers/net/dsa/mv88e6xxx/chip.c-848-{\ndrivers/net/dsa/mv88e6xxx/chip.c:849:\tstruct mv88e6xxx_chip *chip = ds-\u003epriv;\ndrivers/net/dsa/mv88e6xxx/chip.c-850-\ndrivers/net/dsa/mv88e6xxx/chip.c:851:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-852-\tchip-\u003einfo-\u003eops-\u003ephylink_get_caps(chip, port, config);\ndrivers/net/dsa/mv88e6xxx/chip.c:853:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-854-\ndrivers/net/dsa/mv88e6xxx/chip.c:855:\tif (mv88e6xxx_phy_is_internal(chip, port)) {\ndrivers/net/dsa/mv88e6xxx/chip.c-856-\t\t__set_bit(PHY_INTERFACE_MODE_INTERNAL,\n--\ndrivers/net/dsa/mv88e6xxx/chip.c=864=static struct phylink_pcs *\ndrivers/net/dsa/mv88e6xxx/chip.c:865:mv88e6xxx_mac_select_pcs(struct phylink_config *config,\ndrivers/net/dsa/mv88e6xxx/chip.c-866-\t\t\t phy_interface_t interface)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-868-\tstruct dsa_port *dp = dsa_phylink_to_port(config);\ndrivers/net/dsa/mv88e6xxx/chip.c:869:\tstruct mv88e6xxx_chip *chip = dp-\u003eds-\u003epriv;\ndrivers/net/dsa/mv88e6xxx/chip.c-870-\tstruct phylink_pcs *pcs = NULL;\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-878-\ndrivers/net/dsa/mv88e6xxx/chip.c:879:static int mv88e6xxx_mac_prepare(struct phylink_config *config,\ndrivers/net/dsa/mv88e6xxx/chip.c-880-\t\t\t\t unsigned int mode, phy_interface_t interface)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-882-\tstruct dsa_port *dp = dsa_phylink_to_port(config);\ndrivers/net/dsa/mv88e6xxx/chip.c:883:\tstruct mv88e6xxx_chip *chip = dp-\u003eds-\u003epriv;\ndrivers/net/dsa/mv88e6xxx/chip.c-884-\tint port = dp-\u003eindex;\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-893-\t chip-\u003einfo-\u003eops-\u003eport_set_link) {\ndrivers/net/dsa/mv88e6xxx/chip.c:894:\t\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-895-\t\terr = chip-\u003einfo-\u003eops-\u003eport_set_link(chip, port,\ndrivers/net/dsa/mv88e6xxx/chip.c-896-\t\t\t\t\t\t LINK_FORCED_DOWN);\ndrivers/net/dsa/mv88e6xxx/chip.c:897:\t\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-898-\t}\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-902-\ndrivers/net/dsa/mv88e6xxx/chip.c:903:static void mv88e6xxx_mac_config(struct phylink_config *config,\ndrivers/net/dsa/mv88e6xxx/chip.c-904-\t\t\t\t unsigned int mode,\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-907-\tstruct dsa_port *dp = dsa_phylink_to_port(config);\ndrivers/net/dsa/mv88e6xxx/chip.c:908:\tstruct mv88e6xxx_chip *chip = dp-\u003eds-\u003epriv;\ndrivers/net/dsa/mv88e6xxx/chip.c-909-\tint port = dp-\u003eindex;\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-911-\ndrivers/net/dsa/mv88e6xxx/chip.c:912:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-913-\ndrivers/net/dsa/mv88e6xxx/chip.c:914:\tif (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(chip, port)) {\ndrivers/net/dsa/mv88e6xxx/chip.c:915:\t\terr = mv88e6xxx_port_config_interface(chip, port,\ndrivers/net/dsa/mv88e6xxx/chip.c-916-\t\t\t\t\t\t state-\u003einterface);\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-921-err_unlock:\ndrivers/net/dsa/mv88e6xxx/chip.c:922:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-923-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-927-\ndrivers/net/dsa/mv88e6xxx/chip.c:928:static int mv88e6xxx_mac_finish(struct phylink_config *config,\ndrivers/net/dsa/mv88e6xxx/chip.c-929-\t\t\t\tunsigned int mode, phy_interface_t interface)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-931-\tstruct dsa_port *dp = dsa_phylink_to_port(config);\ndrivers/net/dsa/mv88e6xxx/chip.c:932:\tstruct mv88e6xxx_chip *chip = dp-\u003eds-\u003epriv;\ndrivers/net/dsa/mv88e6xxx/chip.c-933-\tint port = dp-\u003eindex;\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-941-\t */\ndrivers/net/dsa/mv88e6xxx/chip.c:942:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-943-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-946-\t chip-\u003eports[port].interface != interface) ||\ndrivers/net/dsa/mv88e6xxx/chip.c:947:\t (mode == MLO_AN_PHY \u0026\u0026 mv88e6xxx_port_ppu_updates(chip, port))))\ndrivers/net/dsa/mv88e6xxx/chip.c-948-\t\terr = chip-\u003einfo-\u003eops-\u003eport_set_link(chip, port, LINK_UNFORCED);\ndrivers/net/dsa/mv88e6xxx/chip.c-949-\ndrivers/net/dsa/mv88e6xxx/chip.c:950:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-951-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-956-\ndrivers/net/dsa/mv88e6xxx/chip.c:957:static void mv88e6xxx_mac_link_down(struct phylink_config *config,\n\n"
} |
| 5/2 | 2026/07/27 14:22 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 28184 output: 43 thoughts: 88 Thoughts: **Investigating Marvell 88E6xxx Switch Emulation** Okay, so I'm looking at a driver for Marvell 88E6xxx switches. My initial thought is, is there any QEMU emulation for this specific switch? I know QEMU's got a lot of capabilities, but these specialized networking components can be tricky. Unfortunately, a quick search reveals no standard QEMU emulation specifically for the Marvell 88E6xxx. Now I need to refine my search. Am I dealing with something that's strictly hardware-dependent, or is there any possibility of software emulation, even if it's not directly integrated with QEMU? Let's dig deeper. The logical next step is to explore the kernel source, specifically the `drivers/net/dsa/mv88e6xxx/Kconfig` file. That should give me a good understanding of the driver's dependencies and potential for a software-based representation, or whether it's tightly coupled to the hardware. |
| 6/2 | 2026/07/27 14:23 | tool | read-file |
0mArgs:{
"File": "drivers/net/dsa/mv88e6xxx/Kconfig",
"FirstLine": 1,
"LineCount": 100
}Results: {
"Contents": " 1:\t# SPDX-License-Identifier: GPL-2.0-only\n 2:\tconfig NET_DSA_MV88E6XXX\n 3:\t\ttristate \"Marvell 88E6xxx Ethernet switch fabric support\"\n 4:\t\tdepends on NET_DSA\n 5:\t\tselect IRQ_DOMAIN\n 6:\t\tselect NET_DSA_TAG_EDSA\n 7:\t\tselect NET_DSA_TAG_DSA\n 8:\t\thelp\n 9:\t\t This driver adds support for most of the Marvell 88E6xxx models of\n 10:\t\t Ethernet switch chips, except 88E6060.\n 11:\t\n 12:\tconfig NET_DSA_MV88E6XXX_PTP\n 13:\t\tbool \"PTP support for Marvell 88E6xxx\"\n 14:\t\tdefault n\n 15:\t\tdepends on (NET_DSA_MV88E6XXX = y \u0026\u0026 PTP_1588_CLOCK = y) || \\\n 16:\t\t (NET_DSA_MV88E6XXX = m \u0026\u0026 PTP_1588_CLOCK)\n 17:\t\thelp\n 18:\t\t Say Y to enable PTP hardware timestamping on Marvell 88E6xxx switch\n 19:\t\t chips that support it.\n 20:\t\n 21:\tconfig NET_DSA_MV88E6XXX_LEDS\n 22:\t\tbool \"LED support for Marvell 88E6xxx\"\n 23:\t\tdefault y\n 24:\t\tdepends on NET_DSA_MV88E6XXX\n 25:\t\tdepends on LEDS_CLASS=y || LEDS_CLASS=NET_DSA_MV88E6XXX\n 26:\t\tdepends on LEDS_TRIGGERS\n 27:\t\thelp\n 28:\t\t This enabled support for controlling the LEDs attached to the\n 29:\t\t Marvell 88E6xxx switch chips.\n"
} |
| 7/2 | 2026/07/27 14:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 29026 output: 46 thoughts: 297 Thoughts: **Analyzing the DSA Driver Interactions** Okay, so I'm looking at this code and it's definitely related to a driver for the Marvell 88E6xxx Ethernet switch chips. Right off the bat, I know that DSA, or Distributed Switch Architecture, depends on having a *real* physical switch chip connected via something like MDIO or SPI. This isn't something that's usually emulated in a standard QEMU or Google Compute Engine setup. My immediate question is, "Can this code *even* be reached in a virtualized environment?" If there's no QEMU emulation for the `mv88e6xxx` chip, the driver's probe function is going to fail – it won't find the hardware, and the device just won't register. So, before I dig too deep, I need to see if there's any clever mocking or emulation within the kernel itself, either for DSA in general or specifically for this driver. I'd expect DSA drivers to be designed for physical hardware, so this seems unlikely. Let's see… maybe `dsa_loop` or something similar? Ah, `dsa_loop.c` is indeed a mock DSA driver, but it doesn't utilize `mv88e6xxx` functionality, so it's a dead end for my purposes. Okay, so the core changes seem to be concentrated in `drivers/net/dsa/mv88e6xxx/` and `net/dsa/tag_dsa.c`. The key change in `tag_dsa.c` appears to be adding a new tag protocol: `edsa-ptp-reserved2-ts`. Now, the crucial question is: Can I somehow trigger the use of that `edsa-ptp-reserved2-ts` tag protocol *without* the `mv88e6xxx` driver being successfully loaded? I need to check that `net/dsa/tag_dsa.c` file more closely. |
| 8/2 | 2026/07/27 14:23 | tool | grepper |
0mArgs:{
"Expression": "edsa_ptp_reserved2_ts_netdev_ops",
"PathPrefix": "net/dsa/tag_dsa.c"
}Results: {
"Output": "net/dsa/tag_dsa.c=404=MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_EDSA, EDSA_NAME);\n--\nnet/dsa/tag_dsa.c-410- */\nnet/dsa/tag_dsa.c:411:static const struct dsa_device_ops edsa_ptp_reserved2_ts_netdev_ops = {\nnet/dsa/tag_dsa.c-412-\t.name\t\t = EDSA_PTP_RESERVED2_TS_NAME,\n--\nnet/dsa/tag_dsa.c-418-\nnet/dsa/tag_dsa.c:419:DSA_TAG_DRIVER(edsa_ptp_reserved2_ts_netdev_ops);\nnet/dsa/tag_dsa.c-420-MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS,\n--\nnet/dsa/tag_dsa.c=424=static struct dsa_tag_driver *dsa_tag_drivers[] = {\n--\nnet/dsa/tag_dsa.c-429-\t\u0026DSA_TAG_DRIVER_NAME(edsa_netdev_ops),\nnet/dsa/tag_dsa.c:430:\t\u0026DSA_TAG_DRIVER_NAME(edsa_ptp_reserved2_ts_netdev_ops),\nnet/dsa/tag_dsa.c-431-#endif\n"
} |
| 9/2 | 2026/07/27 14:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 30189 output: 38 thoughts: 57 Thoughts: Okay, here's my interpretation of those thoughts, tailored for an expert audience, as if they were my own: **Investigating Tag Driver Compatibility** Right, the tag driver is registered. The immediate question in my mind is, does this registration actually translate into usability downstream? Specifically, can this driver be leveraged by `dsa_loop` or any other emulated DSA driver I'm familiar with? I need to ascertain the extent of its accessibility within the software architecture. Let's cut straight to the chase and test a specific scenario. I want to determine if `dsa_loop` is capable of utilizing a specific tagging protocol identifier, let's go with `DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS`. This is likely where the rubber meets the road. This tag protocol is a good test case, I know its characteristics. If `dsa_loop` can't utilize this one, that is a good sign there are issues somewhere in the driver. A successful test here would give me confidence about the design's flexibility. Let's see how it goes. |
| 10/2 | 2026/07/27 14:23 | tool | grepper |
0mArgs:{
"Expression": "DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS",
"PathPrefix": ""
}Results: {
"Output": "drivers/net/dsa/mv88e6xxx/chip.c=3262=static int mv88e6xxx_setup_port_mode(struct mv88e6xxx_chip *chip, int port)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-3274-\tif (chip-\u003etag_protocol == DSA_TAG_PROTO_EDSA ||\ndrivers/net/dsa/mv88e6xxx/chip.c:3275:\t chip-\u003etag_protocol == DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS)\ndrivers/net/dsa/mv88e6xxx/chip.c-3276-\t\treturn mv88e6xxx_set_port_mode_edsa(chip, port);\n--\ndrivers/net/dsa/mv88e6xxx/chip.c=6659=static int mv88e6xxx_change_tag_protocol(struct dsa_switch *ds,\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-6671-\tswitch (proto) {\ndrivers/net/dsa/mv88e6xxx/chip.c:6672:\tcase DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS:\ndrivers/net/dsa/mv88e6xxx/chip.c-6673-\t\tif (!chip-\u003einfo-\u003esupports_ptp_embedded_ts)\n--\ndrivers/net/dsa/mv88e6xxx/chip.h=831=static inline bool mv88e6xxx_ptp_embedded_ts(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.h-832-{\ndrivers/net/dsa/mv88e6xxx/chip.h:833:\treturn chip-\u003etag_protocol == DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS;\ndrivers/net/dsa/mv88e6xxx/chip.h-834-}\n--\ninclude/net/dsa.h=26=struct tc_action;\n--\ninclude/net/dsa.h-61-#define DSA_TAG_PROTO_NETC_VALUE\t\t33\ninclude/net/dsa.h:62:#define DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS_VALUE\t34\ninclude/net/dsa.h-63-\ninclude/net/dsa.h=64=enum dsa_tag_protocol {\n--\ninclude/net/dsa.h-98-\tDSA_TAG_PROTO_NETC\t\t= DSA_TAG_PROTO_NETC_VALUE,\ninclude/net/dsa.h:99:\tDSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS = DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS_VALUE,\ninclude/net/dsa.h-100-};\n--\nnet/dsa/tag_dsa.c=411=static const struct dsa_device_ops edsa_ptp_reserved2_ts_netdev_ops = {\nnet/dsa/tag_dsa.c-412-\t.name\t\t = EDSA_PTP_RESERVED2_TS_NAME,\nnet/dsa/tag_dsa.c:413:\t.proto\t\t = DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS,\nnet/dsa/tag_dsa.c-414-\t.xmit\t\t = edsa_xmit,\n--\nnet/dsa/tag_dsa.c=419=DSA_TAG_DRIVER(edsa_ptp_reserved2_ts_netdev_ops);\nnet/dsa/tag_dsa.c:420:MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS,\nnet/dsa/tag_dsa.c-421-\t\t\t EDSA_PTP_RESERVED2_TS_NAME);\n"
} |
| 11/2 | 2026/07/27 14:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 31541 output: 38 thoughts: 105 Thoughts: **Investigating Tag Protocol Configuration for Emulated DSA Devices** Okay, so the tag protocol seems to be exclusively handled by the `mv88e6xxx` driver, which raises a question. Is there a way, via sysfs or netlink, to configure the tag protocol for emulated devices like `dsa_loop`, or perhaps other similar emulations? The DSA framework itself offers the ability to modify the tag protocol through the `dsa_switch_ops->change_tag_protocol` function, which is promising. However, if a device like `dsa_loop` *doesn't* implement this `change_tag_protocol` function, it'll simply stick with its default, initial protocol. Time to dig into `dsa_loop.c` and see what the implementation details look like, if any, there. Let's see if that hook is implemented and how it is behaving. |
| 12/2 | 2026/07/27 14:23 | tool | grepper |
0mError:no matches Args: {
"Expression": "change_tag_protocol",
"PathPrefix": "drivers/net/dsa/dsa_loop.c"
}Results: {
"error": "no matches"
} |
| 13/2 | 2026/07/27 14:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 31890 output: 38 thoughts: 15 Thoughts: Okay, let's see. My first thought is: **Decoding the `dsa_loop` Protocol**. Right, so I need to quickly determine the specific tagging protocol that `dsa_loop` employs. It's a fundamental step, really. I can't analyze or even understand its function properly without knowing what kind of tagging it's built upon. Is it a simple checksum, something more robust like a CRC, or perhaps something more advanced that incorporates error correction or cryptographic hashing? Gotta figure out the basics before diving any deeper. Let's get cracking. |
| 14/2 | 2026/07/27 14:23 | tool | grepper |
0mArgs:{
"Expression": "DSA_TAG_PROTO",
"PathPrefix": "drivers/net/dsa/dsa_loop.c"
}Results: {
"Output": "drivers/net/dsa/dsa_loop.c=125=static enum dsa_tag_protocol dsa_loop_get_protocol(struct dsa_switch *ds,\n--\ndrivers/net/dsa/dsa_loop.c-130-\ndrivers/net/dsa/dsa_loop.c:131:\treturn DSA_TAG_PROTO_NONE;\ndrivers/net/dsa/dsa_loop.c-132-}\n"
} |
| 15/2 | 2026/07/27 14:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 32188 output: 34 thoughts: 513 Thoughts: **Analyzing the DSA Code Path in a Virtualized Environment**
Okay, so `dsa_loop` uses `DSA_TAG_PROTO_NONE`, that much is clear. My immediate thought is, are there any *other* DSA drivers that might be emulated? Let's check. Ah, `drivers/net/dsa/mock.c`...no, nothing there.
Hmm, the real question is, how can we trigger `edsa_xmit` or `edsa_rcv` without relying on `mv88e6xxx`? Because, realistically, if someone configures a DSA tree through the device tree in a virtual environment, we're unlikely to have a working `mv88e6xxx` instance without a specialized I2C/MDIO mock.
Wait...Syzkaller. Syzkaller's got `syz_genetlink` and other pseudo-syscalls, but it doesn't *natively* emulate MDIO devices. It needs a specific driver for that, right? Unless...
Ah, yes, Syzkaller can inject packets. If we could create a device with `edsa_ptp_reserved2_ts_netdev_ops`, then we'd be using `edsa_xmit` and `edsa_rcv`. But hold on, those aren't *new* functions; they're reused from `edsa_netdev_ops`. So it looks like the relevant code snippet is:
```c
static const struct dsa_device_ops edsa_ptp_reserved2_ts_netdev_ops = {
.name = EDSA_PTP_RESERVED2_TS_NAME,
.proto = DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS,
.xmit = edsa_xmit,
.rcv = edsa_rcv,
.needed_headroom = EDSA_HLEN,
};
```
So the "new" thing in `net/dsa/tag_dsa.c` is just the *registration* of that struct. The meat of the functionality...it's really in `drivers/net/dsa/mv88e6xxx/`.
And that's the kicker. Since `mv88e6xxx` is a *hardware* driver for Marvell switches, and it's not emulated in QEMU (at least not by default), it's *unreachable* in a virtualized environment. So the code there is basically dead code in my specific use case. I should probably double-check if there's any way to instantiate `mv88e6xxx` via some kind of software mock, but my gut tells me it's purely hardware-based.
|
| 16/2 | 2026/07/27 14:23 | tool | grepper |
0mError:no matches Args: {
"Expression": "mv88e6xxx",
"PathPrefix": "tools/testing/selftests/"
}Results: {
"error": "no matches"
} |
| 17/2 | 2026/07/27 14:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 33359 output: 33 thoughts: 18 Thoughts: Okay, here's my attempt at summarizing those thoughts from a first-person, expert perspective, aiming for a fulsome rendering: **Kernel Testing of `mv88e6xxx` - A Deep Dive** Alright, I'm digging into this `mv88e6xxx` driver in the kernel again, and my first question *always* pops up: Are we truly exhausting *all* the testing possibilities? Sure, I'm familiar with the standard methods, the typical procedures, the basic checks that are almost certainly in place... but I can't help but wonder, is there another angle? Is there a subtle corner case, an obscure hardware interaction, some offbeat configuration scenario that we're somehow missing in our test suite? I'm thinking, beyond the obvious, what are the implicit assumptions we're making about the hardware's behavior or the surrounding system? Have we covered the edge conditions, the error paths, the less-traveled configurations? I want to make sure we're not just confirming what we already know works but proactively hunting down potential issues before they surface in the field. This is not about just running the tests. This is about making sure, from the ground up, we're building a rock-solid, reliable driver. Perhaps the documentation points to some obscure test paths. |
| 18/2 | 2026/07/27 14:23 | tool | grepper |
0mArgs:{
"Expression": "mv88e6xxx",
"PathPrefix": "drivers/net/dsa/"
}Results: {
"Output": "\nFull output is too long, showing 500 out of 10141 lines.\nUse more precise expression if possible.\n\ndrivers/net/dsa/Kconfig=73=source \"drivers/net/dsa/microchip/Kconfig\"\ndrivers/net/dsa/Kconfig-74-\ndrivers/net/dsa/Kconfig:75:source \"drivers/net/dsa/mv88e6xxx/Kconfig\"\ndrivers/net/dsa/Kconfig-76-\n--\ndrivers/net/dsa/Makefile=21=obj-y\t\t\t\t+= microchip/\ndrivers/net/dsa/Makefile:22:obj-y\t\t\t\t+= mv88e6xxx/\ndrivers/net/dsa/Makefile-23-obj-y\t\t\t\t+= mxl862xx/\n--\ndrivers/net/dsa/mv88e6060.h-5- *\ndrivers/net/dsa/mv88e6060.h:6: * Based on mv88e6xxx.h\ndrivers/net/dsa/mv88e6060.h-7- * Copyright (c) 2008 Marvell Semiconductor\n--\ndrivers/net/dsa/mv88e6xxx/Makefile-1-# SPDX-License-Identifier: GPL-2.0\ndrivers/net/dsa/mv88e6xxx/Makefile:2:obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o\ndrivers/net/dsa/mv88e6xxx/Makefile:3:mv88e6xxx-objs := chip.o\ndrivers/net/dsa/mv88e6xxx/Makefile:4:mv88e6xxx-objs += devlink.o\ndrivers/net/dsa/mv88e6xxx/Makefile:5:mv88e6xxx-objs += global1.o\ndrivers/net/dsa/mv88e6xxx/Makefile:6:mv88e6xxx-objs += global1_atu.o\ndrivers/net/dsa/mv88e6xxx/Makefile:7:mv88e6xxx-objs += global1_vtu.o\ndrivers/net/dsa/mv88e6xxx/Makefile:8:mv88e6xxx-objs += global2.o\ndrivers/net/dsa/mv88e6xxx/Makefile:9:mv88e6xxx-objs += global2_avb.o\ndrivers/net/dsa/mv88e6xxx/Makefile:10:mv88e6xxx-objs += global2_scratch.o\ndrivers/net/dsa/mv88e6xxx/Makefile:11:mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o\ndrivers/net/dsa/mv88e6xxx/Makefile:12:mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_LEDS) += leds.o\ndrivers/net/dsa/mv88e6xxx/Makefile:13:mv88e6xxx-objs += pcs-6185.o\ndrivers/net/dsa/mv88e6xxx/Makefile:14:mv88e6xxx-objs += pcs-6352.o\ndrivers/net/dsa/mv88e6xxx/Makefile:15:mv88e6xxx-objs += pcs-639x.o\ndrivers/net/dsa/mv88e6xxx/Makefile:16:mv88e6xxx-objs += phy.o\ndrivers/net/dsa/mv88e6xxx/Makefile:17:mv88e6xxx-objs += port.o\ndrivers/net/dsa/mv88e6xxx/Makefile:18:mv88e6xxx-objs += port_hidden.o\ndrivers/net/dsa/mv88e6xxx/Makefile:19:mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += ptp.o\ndrivers/net/dsa/mv88e6xxx/Makefile:20:mv88e6xxx-objs += serdes.o\ndrivers/net/dsa/mv88e6xxx/Makefile:21:mv88e6xxx-objs += smi.o\ndrivers/net/dsa/mv88e6xxx/Makefile:22:mv88e6xxx-objs += switchdev.o\ndrivers/net/dsa/mv88e6xxx/Makefile:23:mv88e6xxx-objs += trace.o\ndrivers/net/dsa/mv88e6xxx/Makefile:24:mv88e6xxx-objs += tcflower.o\ndrivers/net/dsa/mv88e6xxx/Makefile:25:mv88e6xxx-objs += tcam.o\ndrivers/net/dsa/mv88e6xxx/Makefile-26-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-14-#include \u003clinux/delay.h\u003e\ndrivers/net/dsa/mv88e6xxx/chip.c:15:#include \u003clinux/dsa/mv88e6xxx.h\u003e\ndrivers/net/dsa/mv88e6xxx/chip.c-16-#include \u003clinux/etherdevice.h\u003e\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-28-#include \u003clinux/of_mdio.h\u003e\ndrivers/net/dsa/mv88e6xxx/chip.c:29:#include \u003clinux/platform_data/mv88e6xxx.h\u003e\ndrivers/net/dsa/mv88e6xxx/chip.c-30-#include \u003clinux/property.h\u003e\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-48-\ndrivers/net/dsa/mv88e6xxx/chip.c:49:static void assert_reg_lock(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-50-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-56-\ndrivers/net/dsa/mv88e6xxx/chip.c:57:int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val)\ndrivers/net/dsa/mv88e6xxx/chip.c-58-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-62-\ndrivers/net/dsa/mv88e6xxx/chip.c:63:\terr = mv88e6xxx_smi_read(chip, addr, reg, val);\ndrivers/net/dsa/mv88e6xxx/chip.c-64-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-72-\ndrivers/net/dsa/mv88e6xxx/chip.c:73:int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val)\ndrivers/net/dsa/mv88e6xxx/chip.c-74-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-78-\ndrivers/net/dsa/mv88e6xxx/chip.c:79:\terr = mv88e6xxx_smi_write(chip, addr, reg, val);\ndrivers/net/dsa/mv88e6xxx/chip.c-80-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-88-\ndrivers/net/dsa/mv88e6xxx/chip.c:89:int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,\ndrivers/net/dsa/mv88e6xxx/chip.c-90-\t\t\tu16 mask, u16 val)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-101-\tfor (i = 0; time_before(jiffies, timeout) || (i \u003c 2); i++) {\ndrivers/net/dsa/mv88e6xxx/chip.c:102:\t\terr = mv88e6xxx_read(chip, addr, reg, \u0026data);\ndrivers/net/dsa/mv88e6xxx/chip.c-103-\t\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-114-\ndrivers/net/dsa/mv88e6xxx/chip.c:115:\terr = mv88e6xxx_read(chip, addr, reg, \u0026data);\ndrivers/net/dsa/mv88e6xxx/chip.c-116-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-125-\ndrivers/net/dsa/mv88e6xxx/chip.c:126:int mv88e6xxx_wait_bit(struct mv88e6xxx_chip *chip, int addr, int reg,\ndrivers/net/dsa/mv88e6xxx/chip.c-127-\t\t int bit, int val)\ndrivers/net/dsa/mv88e6xxx/chip.c-128-{\ndrivers/net/dsa/mv88e6xxx/chip.c:129:\treturn mv88e6xxx_wait_mask(chip, addr, reg, BIT(bit),\ndrivers/net/dsa/mv88e6xxx/chip.c-130-\t\t\t\t val ? BIT(bit) : 0x0000);\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-132-\ndrivers/net/dsa/mv88e6xxx/chip.c:133:struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-134-{\ndrivers/net/dsa/mv88e6xxx/chip.c:135:\tstruct mv88e6xxx_mdio_bus *mdio_bus;\ndrivers/net/dsa/mv88e6xxx/chip.c-136-\ndrivers/net/dsa/mv88e6xxx/chip.c-137-\tmdio_bus = list_first_entry_or_null(\u0026chip-\u003emdios,\ndrivers/net/dsa/mv88e6xxx/chip.c:138:\t\t\t\t\t struct mv88e6xxx_mdio_bus, list);\ndrivers/net/dsa/mv88e6xxx/chip.c-139-\tif (!mdio_bus)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-144-\ndrivers/net/dsa/mv88e6xxx/chip.c:145:static void mv88e6xxx_g1_irq_mask(struct irq_data *d)\ndrivers/net/dsa/mv88e6xxx/chip.c-146-{\ndrivers/net/dsa/mv88e6xxx/chip.c:147:\tstruct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);\ndrivers/net/dsa/mv88e6xxx/chip.c-148-\tunsigned int n = d-\u003ehwirq;\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-152-\ndrivers/net/dsa/mv88e6xxx/chip.c:153:static void mv88e6xxx_g1_irq_unmask(struct irq_data *d)\ndrivers/net/dsa/mv88e6xxx/chip.c-154-{\ndrivers/net/dsa/mv88e6xxx/chip.c:155:\tstruct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);\ndrivers/net/dsa/mv88e6xxx/chip.c-156-\tunsigned int n = d-\u003ehwirq;\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-160-\ndrivers/net/dsa/mv88e6xxx/chip.c:161:static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-162-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-169-\ndrivers/net/dsa/mv88e6xxx/chip.c:170:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c:171:\terr = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, \u0026reg);\ndrivers/net/dsa/mv88e6xxx/chip.c:172:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-173-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-186-\ndrivers/net/dsa/mv88e6xxx/chip.c:187:\t\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c:188:\t\terr = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, \u0026ctl1);\ndrivers/net/dsa/mv88e6xxx/chip.c-189-\t\tif (err)\ndrivers/net/dsa/mv88e6xxx/chip.c-190-\t\t\tgoto unlock;\ndrivers/net/dsa/mv88e6xxx/chip.c:191:\t\terr = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, \u0026reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-192-unlock:\ndrivers/net/dsa/mv88e6xxx/chip.c:193:\t\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-194-\t\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-202-\ndrivers/net/dsa/mv88e6xxx/chip.c:203:static irqreturn_t mv88e6xxx_g1_irq_thread_fn(int irq, void *dev_id)\ndrivers/net/dsa/mv88e6xxx/chip.c-204-{\ndrivers/net/dsa/mv88e6xxx/chip.c:205:\tstruct mv88e6xxx_chip *chip = dev_id;\ndrivers/net/dsa/mv88e6xxx/chip.c-206-\ndrivers/net/dsa/mv88e6xxx/chip.c:207:\treturn mv88e6xxx_g1_irq_thread_work(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-208-}\ndrivers/net/dsa/mv88e6xxx/chip.c-209-\ndrivers/net/dsa/mv88e6xxx/chip.c:210:static void mv88e6xxx_g1_irq_bus_lock(struct irq_data *d)\ndrivers/net/dsa/mv88e6xxx/chip.c-211-{\ndrivers/net/dsa/mv88e6xxx/chip.c:212:\tstruct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);\ndrivers/net/dsa/mv88e6xxx/chip.c-213-\ndrivers/net/dsa/mv88e6xxx/chip.c:214:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-215-}\ndrivers/net/dsa/mv88e6xxx/chip.c-216-\ndrivers/net/dsa/mv88e6xxx/chip.c:217:static void mv88e6xxx_g1_irq_bus_sync_unlock(struct irq_data *d)\ndrivers/net/dsa/mv88e6xxx/chip.c-218-{\ndrivers/net/dsa/mv88e6xxx/chip.c:219:\tstruct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);\ndrivers/net/dsa/mv88e6xxx/chip.c-220-\tu16 mask = GENMASK(chip-\u003eg1_irq.nirqs, 0);\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-223-\ndrivers/net/dsa/mv88e6xxx/chip.c:224:\terr = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, \u0026reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-225-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-230-\ndrivers/net/dsa/mv88e6xxx/chip.c:231:\terr = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-232-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-235-out:\ndrivers/net/dsa/mv88e6xxx/chip.c:236:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-237-}\ndrivers/net/dsa/mv88e6xxx/chip.c-238-\ndrivers/net/dsa/mv88e6xxx/chip.c:239:static const struct irq_chip mv88e6xxx_g1_irq_chip = {\ndrivers/net/dsa/mv88e6xxx/chip.c:240:\t.name\t\t\t= \"mv88e6xxx-g1\",\ndrivers/net/dsa/mv88e6xxx/chip.c:241:\t.irq_mask\t\t= mv88e6xxx_g1_irq_mask,\ndrivers/net/dsa/mv88e6xxx/chip.c:242:\t.irq_unmask\t\t= mv88e6xxx_g1_irq_unmask,\ndrivers/net/dsa/mv88e6xxx/chip.c:243:\t.irq_bus_lock\t\t= mv88e6xxx_g1_irq_bus_lock,\ndrivers/net/dsa/mv88e6xxx/chip.c:244:\t.irq_bus_sync_unlock\t= mv88e6xxx_g1_irq_bus_sync_unlock,\ndrivers/net/dsa/mv88e6xxx/chip.c-245-};\ndrivers/net/dsa/mv88e6xxx/chip.c-246-\ndrivers/net/dsa/mv88e6xxx/chip.c:247:static int mv88e6xxx_g1_irq_domain_map(struct irq_domain *d,\ndrivers/net/dsa/mv88e6xxx/chip.c-248-\t\t\t\t unsigned int irq,\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-250-{\ndrivers/net/dsa/mv88e6xxx/chip.c:251:\tstruct mv88e6xxx_chip *chip = d-\u003ehost_data;\ndrivers/net/dsa/mv88e6xxx/chip.c-252-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-259-\ndrivers/net/dsa/mv88e6xxx/chip.c:260:static const struct irq_domain_ops mv88e6xxx_g1_irq_domain_ops = {\ndrivers/net/dsa/mv88e6xxx/chip.c:261:\t.map\t= mv88e6xxx_g1_irq_domain_map,\ndrivers/net/dsa/mv88e6xxx/chip.c-262-\t.xlate\t= irq_domain_xlate_twocell,\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-265-/* To be called with reg_lock held */\ndrivers/net/dsa/mv88e6xxx/chip.c:266:static void mv88e6xxx_g1_irq_free_common(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-267-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-270-\ndrivers/net/dsa/mv88e6xxx/chip.c:271:\tmv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, \u0026mask);\ndrivers/net/dsa/mv88e6xxx/chip.c-272-\tmask \u0026= ~GENMASK(chip-\u003eg1_irq.nirqs, 0);\ndrivers/net/dsa/mv88e6xxx/chip.c:273:\tmv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);\ndrivers/net/dsa/mv88e6xxx/chip.c-274-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-282-\ndrivers/net/dsa/mv88e6xxx/chip.c:283:static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-284-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-290-\ndrivers/net/dsa/mv88e6xxx/chip.c:291:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c:292:\tmv88e6xxx_g1_irq_free_common(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c:293:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-294-}\ndrivers/net/dsa/mv88e6xxx/chip.c-295-\ndrivers/net/dsa/mv88e6xxx/chip.c:296:static int mv88e6xxx_g1_irq_setup_common(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-297-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-303-\t\tNULL, chip-\u003eg1_irq.nirqs, 0,\ndrivers/net/dsa/mv88e6xxx/chip.c:304:\t\t\u0026mv88e6xxx_g1_irq_domain_ops, chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-305-\tif (!chip-\u003eg1_irq.domain)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-310-\ndrivers/net/dsa/mv88e6xxx/chip.c:311:\tchip-\u003eg1_irq.chip = mv88e6xxx_g1_irq_chip;\ndrivers/net/dsa/mv88e6xxx/chip.c-312-\tchip-\u003eg1_irq.masked = ~0;\ndrivers/net/dsa/mv88e6xxx/chip.c-313-\ndrivers/net/dsa/mv88e6xxx/chip.c:314:\terr = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, \u0026mask);\ndrivers/net/dsa/mv88e6xxx/chip.c-315-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-319-\ndrivers/net/dsa/mv88e6xxx/chip.c:320:\terr = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);\ndrivers/net/dsa/mv88e6xxx/chip.c-321-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-324-\t/* Reading the interrupt status clears (most of) them */\ndrivers/net/dsa/mv88e6xxx/chip.c:325:\terr = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, \u0026reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-326-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-332-\tmask \u0026= ~GENMASK(chip-\u003eg1_irq.nirqs, 0);\ndrivers/net/dsa/mv88e6xxx/chip.c:333:\tmv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);\ndrivers/net/dsa/mv88e6xxx/chip.c-334-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-345-\ndrivers/net/dsa/mv88e6xxx/chip.c:346:static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-347-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-351-\ndrivers/net/dsa/mv88e6xxx/chip.c:352:\terr = mv88e6xxx_g1_irq_setup_common(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-353-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-362-\tsnprintf(chip-\u003eirq_name, sizeof(chip-\u003eirq_name),\ndrivers/net/dsa/mv88e6xxx/chip.c:363:\t\t \"mv88e6xxx-%s\", dev_name(chip-\u003edev));\ndrivers/net/dsa/mv88e6xxx/chip.c-364-\ndrivers/net/dsa/mv88e6xxx/chip.c:365:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-366-\terr = request_threaded_irq(chip-\u003eirq, NULL,\ndrivers/net/dsa/mv88e6xxx/chip.c:367:\t\t\t\t mv88e6xxx_g1_irq_thread_fn,\ndrivers/net/dsa/mv88e6xxx/chip.c-368-\t\t\t\t IRQF_ONESHOT | IRQF_SHARED,\ndrivers/net/dsa/mv88e6xxx/chip.c-369-\t\t\t\t chip-\u003eirq_name, chip);\ndrivers/net/dsa/mv88e6xxx/chip.c:370:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-371-\tif (err)\ndrivers/net/dsa/mv88e6xxx/chip.c:372:\t\tmv88e6xxx_g1_irq_free_common(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-373-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-376-\ndrivers/net/dsa/mv88e6xxx/chip.c:377:static void mv88e6xxx_irq_poll(struct kthread_work *work)\ndrivers/net/dsa/mv88e6xxx/chip.c-378-{\ndrivers/net/dsa/mv88e6xxx/chip.c:379:\tstruct mv88e6xxx_chip *chip = container_of(work,\ndrivers/net/dsa/mv88e6xxx/chip.c:380:\t\t\t\t\t\t struct mv88e6xxx_chip,\ndrivers/net/dsa/mv88e6xxx/chip.c-381-\t\t\t\t\t\t irq_poll_work.work);\ndrivers/net/dsa/mv88e6xxx/chip.c:382:\tmv88e6xxx_g1_irq_thread_work(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-383-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-387-\ndrivers/net/dsa/mv88e6xxx/chip.c:388:static int mv88e6xxx_irq_poll_setup(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-389-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-391-\ndrivers/net/dsa/mv88e6xxx/chip.c:392:\terr = mv88e6xxx_g1_irq_setup_common(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-393-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-396-\tkthread_init_delayed_work(\u0026chip-\u003eirq_poll_work,\ndrivers/net/dsa/mv88e6xxx/chip.c:397:\t\t\t\t mv88e6xxx_irq_poll);\ndrivers/net/dsa/mv88e6xxx/chip.c-398-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-408-\ndrivers/net/dsa/mv88e6xxx/chip.c:409:static void mv88e6xxx_irq_poll_free(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.c-410-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-413-\ndrivers/net/dsa/mv88e6xxx/chip.c:414:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c:415:\tmv88e6xxx_g1_irq_free_common(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c:416:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-417-}\ndrivers/net/dsa/mv88e6xxx/chip.c-418-\ndrivers/net/dsa/mv88e6xxx/chip.c:419:static int mv88e6xxx_port_config_interface(struct mv88e6xxx_chip *chip,\ndrivers/net/dsa/mv88e6xxx/chip.c-420-\t\t\t\t\t int port, phy_interface_t interface)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-440-\ndrivers/net/dsa/mv88e6xxx/chip.c:441:static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-442-\t\t\t\t int link, int speed, int duplex, int pause,\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-467-\ndrivers/net/dsa/mv88e6xxx/chip.c:468:\terr = mv88e6xxx_port_config_interface(chip, port, mode);\ndrivers/net/dsa/mv88e6xxx/chip.c-469-restore_link:\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-475-\ndrivers/net/dsa/mv88e6xxx/chip.c:476:static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port)\ndrivers/net/dsa/mv88e6xxx/chip.c-477-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-482-\ndrivers/net/dsa/mv88e6xxx/chip.c:483:static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port)\ndrivers/net/dsa/mv88e6xxx/chip.c-484-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-491-\tif (chip-\u003einfo-\u003efamily == MV88E6XXX_FAMILY_6250)\ndrivers/net/dsa/mv88e6xxx/chip.c:492:\t\treturn mv88e6xxx_phy_is_internal(chip, port);\ndrivers/net/dsa/mv88e6xxx/chip.c-493-\ndrivers/net/dsa/mv88e6xxx/chip.c:494:\terr = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, \u0026reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-495-\tif (err) {\n--\ndrivers/net/dsa/mv88e6xxx/chip.c=505=static const u8 mv88e6185_phy_interface_modes[] = {\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-514-\ndrivers/net/dsa/mv88e6xxx/chip.c:515:static void mv88e6095_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-516-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-521-\ndrivers/net/dsa/mv88e6xxx/chip.c:522:\tif (mv88e6xxx_phy_is_internal(chip, port)) {\ndrivers/net/dsa/mv88e6xxx/chip.c-523-\t\t__set_bit(PHY_INTERFACE_MODE_MII, config-\u003esupported_interfaces);\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-533-\ndrivers/net/dsa/mv88e6xxx/chip.c:534:static void mv88e6185_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-535-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-547-\ndrivers/net/dsa/mv88e6xxx/chip.c:548:static const u8 mv88e6xxx_phy_interface_modes[] = {\ndrivers/net/dsa/mv88e6xxx/chip.c-549-\t[MV88E6XXX_PORT_STS_CMODE_MII_PHY]\t= PHY_INTERFACE_MODE_REVMII,\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-562-\ndrivers/net/dsa/mv88e6xxx/chip.c:563:static void mv88e6xxx_translate_cmode(u8 cmode, unsigned long *supported)\ndrivers/net/dsa/mv88e6xxx/chip.c-564-{\ndrivers/net/dsa/mv88e6xxx/chip.c:565:\tif (cmode \u003c ARRAY_SIZE(mv88e6xxx_phy_interface_modes) \u0026\u0026\ndrivers/net/dsa/mv88e6xxx/chip.c:566:\t mv88e6xxx_phy_interface_modes[cmode])\ndrivers/net/dsa/mv88e6xxx/chip.c:567:\t\t__set_bit(mv88e6xxx_phy_interface_modes[cmode], supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-568-\telse if (cmode == MV88E6XXX_PORT_STS_CMODE_RGMII)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c=572=static void\ndrivers/net/dsa/mv88e6xxx/chip.c:573:mv88e6250_setup_supported_interfaces(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-574-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-579-\ndrivers/net/dsa/mv88e6xxx/chip.c:580:\terr = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, \u0026reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-581-\tif (err) {\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-621-\ndrivers/net/dsa/mv88e6xxx/chip.c:622:static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-623-\t\t\t\t struct phylink_config *config)\ndrivers/net/dsa/mv88e6xxx/chip.c-624-{\ndrivers/net/dsa/mv88e6xxx/chip.c:625:\tif (!mv88e6xxx_phy_is_internal(chip, port))\ndrivers/net/dsa/mv88e6xxx/chip.c-626-\t\tmv88e6250_setup_supported_interfaces(chip, port, config);\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-630-\ndrivers/net/dsa/mv88e6xxx/chip.c:631:static void mv88e6351_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-632-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-636-\t/* Translate the default cmode */\ndrivers/net/dsa/mv88e6xxx/chip.c:637:\tmv88e6xxx_translate_cmode(chip-\u003eports[port].cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-638-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-642-\ndrivers/net/dsa/mv88e6xxx/chip.c:643:static int mv88e63xx_get_port_serdes_cmode(struct mv88e6xxx_chip *chip, int port)\ndrivers/net/dsa/mv88e6xxx/chip.c-644-{\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-647-\ndrivers/net/dsa/mv88e6xxx/chip.c:648:\terr = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, \u0026reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-649-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-656-\tval = reg \u0026 ~MV88E6XXX_PORT_STS_PHY_DETECT;\ndrivers/net/dsa/mv88e6xxx/chip.c:657:\terr = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, val);\ndrivers/net/dsa/mv88e6xxx/chip.c-658-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-660-\ndrivers/net/dsa/mv88e6xxx/chip.c:661:\terr = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, \u0026val);\ndrivers/net/dsa/mv88e6xxx/chip.c-662-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-665-\t/* Restore PHY_DETECT value */\ndrivers/net/dsa/mv88e6xxx/chip.c:666:\terr = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, reg);\ndrivers/net/dsa/mv88e6xxx/chip.c-667-\tif (err)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-672-\ndrivers/net/dsa/mv88e6xxx/chip.c:673:static void mv88e6352_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-674-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-679-\t/* Translate the default cmode */\ndrivers/net/dsa/mv88e6xxx/chip.c:680:\tmv88e6xxx_translate_cmode(chip-\u003eports[port].cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-681-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-695-\t\telse\ndrivers/net/dsa/mv88e6xxx/chip.c:696:\t\t\tmv88e6xxx_translate_cmode(cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-697-\t}\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-699-\ndrivers/net/dsa/mv88e6xxx/chip.c:700:static void mv88e632x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-701-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-706-\t/* Translate the default cmode */\ndrivers/net/dsa/mv88e6xxx/chip.c:707:\tmv88e6xxx_translate_cmode(chip-\u003eports[port].cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-708-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-718-\t\telse\ndrivers/net/dsa/mv88e6xxx/chip.c:719:\t\t\tmv88e6xxx_translate_cmode(cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-720-\t}\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-722-\ndrivers/net/dsa/mv88e6xxx/chip.c:723:static void mv88e6341_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-724-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-728-\t/* Translate the default cmode */\ndrivers/net/dsa/mv88e6xxx/chip.c:729:\tmv88e6xxx_translate_cmode(chip-\u003eports[port].cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-730-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-744-\ndrivers/net/dsa/mv88e6xxx/chip.c:745:static void mv88e6390_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-746-\t\t\t\t struct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-750-\t/* Translate the default cmode */\ndrivers/net/dsa/mv88e6xxx/chip.c:751:\tmv88e6xxx_translate_cmode(chip-\u003eports[port].cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-752-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-766-\ndrivers/net/dsa/mv88e6xxx/chip.c:767:static void mv88e6390x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-768-\t\t\t\t\tstruct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-801-\ndrivers/net/dsa/mv88e6xxx/chip.c:802:static void mv88e6393x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-803-\t\t\t\t\tstruct phylink_config *config)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-810-\ndrivers/net/dsa/mv88e6xxx/chip.c:811:\tmv88e6xxx_translate_cmode(chip-\u003eports[port].cmode, supported);\ndrivers/net/dsa/mv88e6xxx/chip.c-812-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-845-\ndrivers/net/dsa/mv88e6xxx/chip.c:846:static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port,\ndrivers/net/dsa/mv88e6xxx/chip.c-847-\t\t\t struct phylink_config *config)\ndrivers/net/dsa/mv88e6xxx/chip.c-848-{\ndrivers/net/dsa/mv88e6xxx/chip.c:849:\tstruct mv88e6xxx_chip *chip = ds-\u003epriv;\ndrivers/net/dsa/mv88e6xxx/chip.c-850-\ndrivers/net/dsa/mv88e6xxx/chip.c:851:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-852-\tchip-\u003einfo-\u003eops-\u003ephylink_get_caps(chip, port, config);\ndrivers/net/dsa/mv88e6xxx/chip.c:853:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-854-\ndrivers/net/dsa/mv88e6xxx/chip.c:855:\tif (mv88e6xxx_phy_is_internal(chip, port)) {\ndrivers/net/dsa/mv88e6xxx/chip.c-856-\t\t__set_bit(PHY_INTERFACE_MODE_INTERNAL,\n--\ndrivers/net/dsa/mv88e6xxx/chip.c=864=static struct phylink_pcs *\ndrivers/net/dsa/mv88e6xxx/chip.c:865:mv88e6xxx_mac_select_pcs(struct phylink_config *config,\ndrivers/net/dsa/mv88e6xxx/chip.c-866-\t\t\t phy_interface_t interface)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-868-\tstruct dsa_port *dp = dsa_phylink_to_port(config);\ndrivers/net/dsa/mv88e6xxx/chip.c:869:\tstruct mv88e6xxx_chip *chip = dp-\u003eds-\u003epriv;\ndrivers/net/dsa/mv88e6xxx/chip.c-870-\tstruct phylink_pcs *pcs = NULL;\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-878-\ndrivers/net/dsa/mv88e6xxx/chip.c:879:static int mv88e6xxx_mac_prepare(struct phylink_config *config,\ndrivers/net/dsa/mv88e6xxx/chip.c-880-\t\t\t\t unsigned int mode, phy_interface_t interface)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-882-\tstruct dsa_port *dp = dsa_phylink_to_port(config);\ndrivers/net/dsa/mv88e6xxx/chip.c:883:\tstruct mv88e6xxx_chip *chip = dp-\u003eds-\u003epriv;\ndrivers/net/dsa/mv88e6xxx/chip.c-884-\tint port = dp-\u003eindex;\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-893-\t chip-\u003einfo-\u003eops-\u003eport_set_link) {\ndrivers/net/dsa/mv88e6xxx/chip.c:894:\t\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-895-\t\terr = chip-\u003einfo-\u003eops-\u003eport_set_link(chip, port,\ndrivers/net/dsa/mv88e6xxx/chip.c-896-\t\t\t\t\t\t LINK_FORCED_DOWN);\ndrivers/net/dsa/mv88e6xxx/chip.c:897:\t\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-898-\t}\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-902-\ndrivers/net/dsa/mv88e6xxx/chip.c:903:static void mv88e6xxx_mac_config(struct phylink_config *config,\ndrivers/net/dsa/mv88e6xxx/chip.c-904-\t\t\t\t unsigned int mode,\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-907-\tstruct dsa_port *dp = dsa_phylink_to_port(config);\ndrivers/net/dsa/mv88e6xxx/chip.c:908:\tstruct mv88e6xxx_chip *chip = dp-\u003eds-\u003epriv;\ndrivers/net/dsa/mv88e6xxx/chip.c-909-\tint port = dp-\u003eindex;\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-911-\ndrivers/net/dsa/mv88e6xxx/chip.c:912:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-913-\ndrivers/net/dsa/mv88e6xxx/chip.c:914:\tif (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(chip, port)) {\ndrivers/net/dsa/mv88e6xxx/chip.c:915:\t\terr = mv88e6xxx_port_config_interface(chip, port,\ndrivers/net/dsa/mv88e6xxx/chip.c-916-\t\t\t\t\t\t state-\u003einterface);\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-921-err_unlock:\ndrivers/net/dsa/mv88e6xxx/chip.c:922:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-923-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-927-\ndrivers/net/dsa/mv88e6xxx/chip.c:928:static int mv88e6xxx_mac_finish(struct phylink_config *config,\ndrivers/net/dsa/mv88e6xxx/chip.c-929-\t\t\t\tunsigned int mode, phy_interface_t interface)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-931-\tstruct dsa_port *dp = dsa_phylink_to_port(config);\ndrivers/net/dsa/mv88e6xxx/chip.c:932:\tstruct mv88e6xxx_chip *chip = dp-\u003eds-\u003epriv;\ndrivers/net/dsa/mv88e6xxx/chip.c-933-\tint port = dp-\u003eindex;\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-941-\t */\ndrivers/net/dsa/mv88e6xxx/chip.c:942:\tmv88e6xxx_reg_lock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-943-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-946-\t chip-\u003eports[port].interface != interface) ||\ndrivers/net/dsa/mv88e6xxx/chip.c:947:\t (mode == MLO_AN_PHY \u0026\u0026 mv88e6xxx_port_ppu_updates(chip, port))))\ndrivers/net/dsa/mv88e6xxx/chip.c-948-\t\terr = chip-\u003einfo-\u003eops-\u003eport_set_link(chip, port, LINK_UNFORCED);\ndrivers/net/dsa/mv88e6xxx/chip.c-949-\ndrivers/net/dsa/mv88e6xxx/chip.c:950:\tmv88e6xxx_reg_unlock(chip);\ndrivers/net/dsa/mv88e6xxx/chip.c-951-\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-956-\ndrivers/net/dsa/mv88e6xxx/chip.c:957:static void mv88e6xxx_mac_link_down(struct phylink_config *config,\n\n"
} |
| 19/2 | 2026/07/27 14:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 48171 output: 39 thoughts: 230 Thoughts: **Analyzing the Potential Impact of the New Tag Protocol** Okay, so this `mv88e6xxx` driver is strictly hardware-focused, no QEMU emulation there, which is what I suspected. The edits in `net/dsa/tag_dsa.c` are simply registering this new tag protocol; it's specific to the Marvell switch. My initial thought was: could a clever user craft a dummy netdev and point it to the new `edsa-ptp-reserved2-ts` tag? But then, I remembered that DSA tag protocols are fundamentally linked to DSA switches. Unless we're dealing with a DSA switch, this approach is dead in the water. If we don't have a DSA switch emulated, and the only one available (`dsa_loop`) leverages `DSA_TAG_PROTO_NONE`, this tag protocol is unreachable. Hmmm, could we manipulate `dsa_loop` and override its tag protocol? It's a long shot, but worth checking. I'll need to see if `dsa_loop` offers any mechanism to change its tag protocol dynamically. A quick search for `change_tag_protocol` within `dsa_loop.c` yielded nothing. I need to examine the `dsa_switch_ops` struct within `dsa_loop.c` next to be sure. |
| 20/2 | 2026/07/27 14:23 | tool | grepper |
0mArgs:{
"Expression": "dsa_switch_ops",
"PathPrefix": "drivers/net/dsa/dsa_loop.c"
}Results: {
"Output": "drivers/net/dsa/dsa_loop.c=326=static void dsa_loop_phylink_get_caps(struct dsa_switch *dsa, int port,\n--\ndrivers/net/dsa/dsa_loop.c-333-\ndrivers/net/dsa/dsa_loop.c:334:static const struct dsa_switch_ops dsa_loop_driver = {\ndrivers/net/dsa/dsa_loop.c-335-\t.get_tag_protocol\t= dsa_loop_get_protocol,\n"
} |
| 21/2 | 2026/07/27 14:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 48881 output: 41 thoughts: 15 Thoughts: Okay, let's dive into this. Here's my thought process on what I'm about to do: **Analyzing the `dsa_loop_driver` Implementation** Alright, I'm going to take a look at the `dsa_loop_driver` implementation. My initial goal is to understand precisely what this driver does. I need to figure out its role in the larger system. Is it handling data transfers, managing resources, or something else entirely? I'm going to be looking for key functions, data structures, and any specific algorithms it might be employing. Given my expertise, I'm probably going to be mentally mapping this to other similar drivers I've worked with in the past and looking for common patterns or any unusual aspects. I'll likely be assessing its performance characteristics in my head as well, as I go. |
| 22/2 | 2026/07/27 14:23 | tool | read-file |
0mArgs:{
"File": "drivers/net/dsa/dsa_loop.c",
"FirstLine": 334,
"LineCount": 20
}Results: {
"Contents": " 334:\tstatic const struct dsa_switch_ops dsa_loop_driver = {\n 335:\t\t.get_tag_protocol\t= dsa_loop_get_protocol,\n 336:\t\t.setup\t\t\t= dsa_loop_setup,\n 337:\t\t.teardown\t\t= dsa_loop_teardown,\n 338:\t\t.get_strings\t\t= dsa_loop_get_strings,\n 339:\t\t.get_ethtool_stats\t= dsa_loop_get_ethtool_stats,\n 340:\t\t.get_sset_count\t\t= dsa_loop_get_sset_count,\n 341:\t\t.get_ethtool_phy_stats\t= dsa_loop_get_ethtool_stats,\n 342:\t\t.phy_read\t\t= dsa_loop_phy_read,\n 343:\t\t.phy_write\t\t= dsa_loop_phy_write,\n 344:\t\t.port_bridge_join\t= dsa_loop_port_bridge_join,\n 345:\t\t.port_bridge_leave\t= dsa_loop_port_bridge_leave,\n 346:\t\t.port_stp_state_set\t= dsa_loop_port_stp_state_set,\n 347:\t\t.port_vlan_filtering\t= dsa_loop_port_vlan_filtering,\n 348:\t\t.port_vlan_add\t\t= dsa_loop_port_vlan_add,\n 349:\t\t.port_vlan_del\t\t= dsa_loop_port_vlan_del,\n 350:\t\t.port_change_mtu\t= dsa_loop_port_change_mtu,\n 351:\t\t.port_max_mtu\t\t= dsa_loop_port_max_mtu,\n 352:\t\t.phylink_get_caps\t= dsa_loop_phylink_get_caps,\n 353:\t};\n"
} |
| 23/2 | 2026/07/27 14:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 49628 output: 38 thoughts: 353 Thoughts: **Analyzing the Patch's Impact on Fuzzing** Okay, let's break this down. It looks like this patch doesn't implement `change_tag_protocol`, which means `dsa_loop` will default to `DSA_TAG_PROTO_NONE`. My first thought is: are there *any* other ways to test these DSA tag protocols? Syzkaller has the ability to inject packets into devices, so if a network device uses `edsa_ptp_reserved2_ts_netdev_ops`, then theoretically its `xmit` and `rcv` functions could be triggered. But hang on… `edsa_ptp_reserved2_ts_netdev_ops` relies on `edsa_xmit` and `edsa_rcv`, which are *already* being fuzzed through `edsa_netdev_ops`. So, what's *new* here? Looking at `tag_dsa.c`, it seems the only addition is the registration of a struct. The real logic is actually buried in `drivers/net/dsa/mv88e6xxx/`, which is a hardware driver. And that's the kicker. Since `mv88e6xxx` is a hardware driver, it's completely unreachable in a virtualized environment like QEMU or GCE. The new code in `tag_dsa.c` is just a struct definition and registration – it doesn't contain any new executable logic, it's just reusing `edsa_xmit` and `edsa_rcv`. This means this patch doesn't introduce any new reachable functional changes in a virtualized environment. So I should definitely return `WorthFuzzing=false`. Just to be absolutely sure, I'm going to double check if there's any other place where `DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS` is being used, just to be thorough. |
| 24/2 | 2026/07/27 14:23 | tool | grepper |
0mArgs:{
"Expression": "DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS",
"PathPrefix": ""
}Results: {
"Output": "drivers/net/dsa/mv88e6xxx/chip.c=3262=static int mv88e6xxx_setup_port_mode(struct mv88e6xxx_chip *chip, int port)\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-3274-\tif (chip-\u003etag_protocol == DSA_TAG_PROTO_EDSA ||\ndrivers/net/dsa/mv88e6xxx/chip.c:3275:\t chip-\u003etag_protocol == DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS)\ndrivers/net/dsa/mv88e6xxx/chip.c-3276-\t\treturn mv88e6xxx_set_port_mode_edsa(chip, port);\n--\ndrivers/net/dsa/mv88e6xxx/chip.c=6659=static int mv88e6xxx_change_tag_protocol(struct dsa_switch *ds,\n--\ndrivers/net/dsa/mv88e6xxx/chip.c-6671-\tswitch (proto) {\ndrivers/net/dsa/mv88e6xxx/chip.c:6672:\tcase DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS:\ndrivers/net/dsa/mv88e6xxx/chip.c-6673-\t\tif (!chip-\u003einfo-\u003esupports_ptp_embedded_ts)\n--\ndrivers/net/dsa/mv88e6xxx/chip.h=831=static inline bool mv88e6xxx_ptp_embedded_ts(struct mv88e6xxx_chip *chip)\ndrivers/net/dsa/mv88e6xxx/chip.h-832-{\ndrivers/net/dsa/mv88e6xxx/chip.h:833:\treturn chip-\u003etag_protocol == DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS;\ndrivers/net/dsa/mv88e6xxx/chip.h-834-}\n--\ninclude/net/dsa.h=26=struct tc_action;\n--\ninclude/net/dsa.h-61-#define DSA_TAG_PROTO_NETC_VALUE\t\t33\ninclude/net/dsa.h:62:#define DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS_VALUE\t34\ninclude/net/dsa.h-63-\ninclude/net/dsa.h=64=enum dsa_tag_protocol {\n--\ninclude/net/dsa.h-98-\tDSA_TAG_PROTO_NETC\t\t= DSA_TAG_PROTO_NETC_VALUE,\ninclude/net/dsa.h:99:\tDSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS = DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS_VALUE,\ninclude/net/dsa.h-100-};\n--\nnet/dsa/tag_dsa.c=411=static const struct dsa_device_ops edsa_ptp_reserved2_ts_netdev_ops = {\nnet/dsa/tag_dsa.c-412-\t.name\t\t = EDSA_PTP_RESERVED2_TS_NAME,\nnet/dsa/tag_dsa.c:413:\t.proto\t\t = DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS,\nnet/dsa/tag_dsa.c-414-\t.xmit\t\t = edsa_xmit,\n--\nnet/dsa/tag_dsa.c=419=DSA_TAG_DRIVER(edsa_ptp_reserved2_ts_netdev_ops);\nnet/dsa/tag_dsa.c:420:MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_EDSA_PTP_RESERVED2_TS,\nnet/dsa/tag_dsa.c-421-\t\t\t EDSA_PTP_RESERVED2_TS_NAME);\n"
} |
| 25/2 | 2026/07/27 14:24 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 51463 output: 169 thoughts: 65 Thoughts: **My Assessment of the Code Path** Alright, let's break this down. My analysis indicates the vulnerability *only* exists within the `mv88e6xxx` driver and its related `tag_dsa.c` file. The problem, as I see it, is that `mv88e6xxx` is a hardware driver. And, as a hardware driver, it is *not* emulated within QEMU. That means the specific code section in question is completely unreachable in a QEMU-based fuzzing environment. Given this fundamental limitation, attempting to fuzz this code is a waste of resources. Therefore, I will mark this code path as `WorthFuzzing=false` and clearly state this hardware dependency as the primary reason. |
| 26/2 | 2026/07/27 14:24 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch modifies the Marvell 88E6xxx Ethernet switch driver (drivers/net/dsa/mv88e6xxx) and adds a new DSA tag protocol in net/dsa/tag_dsa.c. The Marvell 88E6xxx driver is for physical hardware switches and is not emulated in standard QEMU/GCE environments. The new tag protocol in tag_dsa.c simply reuses existing transmit and receive functions (edsa_xmit, edsa_rcv) and contains no new executable logic. Therefore, the new code is unreachable and cannot be fuzzed in a virtualized environment.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies the Marvell 88E6xxx Ethernet switch driver (drivers/net/dsa/mv88e6xxx) and adds a new DSA tag protocol in net/dsa/tag_dsa.c. The Marvell 88E6xxx driver is for physical hardware switches and is not emulated in standard QEMU/GCE environments. The new tag protocol in tag_dsa.c simply reuses existing transmit and receive functions (edsa_xmit, edsa_rcv) and contains no new executable logic. Therefore, the new code is unreachable and cannot be fuzzed in a virtualized environment.",
"WorthFuzzing": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|