| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/23 22:38 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies the Airoha SoC Gigabit Ethernet driver (drivers/net/ethernet/airoha/). This is a hardware-specific platform driver that requires specific Airoha SoC hardware (MMIO registers, IRQs) to probe successfully. It cannot be reached or tested in standard virtualized environments like QEMU or GCE.",
"WorthFuzzing": false
} |
| 1/1 | 2026/07/23 22:38 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 5211720442ad6b87c667e691b15677060d7601f0\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Thu Jul 23 22:38:50 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c\nindex 59001fd4b6f740..06f866d7137ee2 100644\n--- a/drivers/net/ethernet/airoha/airoha_eth.c\n+++ b/drivers/net/ethernet/airoha/airoha_eth.c\n@@ -934,7 +934,7 @@ static void airoha_qdma_wake_netdev_txqs(struct airoha_queue *q)\n \t\t\tif (!dev)\n \t\t\t\tcontinue;\n \n-\t\t\tif (dev-\u003eqdma != qdma)\n+\t\t\tif (rcu_access_pointer(dev-\u003eqdma) != qdma)\n \t\t\t\tcontinue;\n \n \t\t\tnetdev = netdev_from_priv(dev);\n@@ -1866,8 +1866,8 @@ static int airoha_dev_open(struct net_device *netdev)\n {\n \tstruct airoha_gdm_dev *dev = netdev_priv(netdev);\n \tstruct airoha_gdm_port *port = dev-\u003eport;\n-\tstruct airoha_qdma *qdma = dev-\u003eqdma;\n \tu32 pse_port = FE_PSE_PORT_PPE1;\n+\tstruct airoha_qdma *qdma;\n \tint err;\n \n \tnetif_tx_start_all_queues(netdev);\n@@ -1875,6 +1875,7 @@ static int airoha_dev_open(struct net_device *netdev)\n \tif (err)\n \t\treturn err;\n \n+\tqdma = airoha_qdma_deref(dev);\n \tif (netdev_uses_dsa(netdev))\n \t\tairoha_fe_set(qdma-\u003eeth, REG_GDM_INGRESS_CFG(port-\u003eid),\n \t\t\t GDM_STAG_EN_MASK);\n@@ -1898,7 +1899,6 @@ static int airoha_dev_stop(struct net_device *netdev)\n {\n \tstruct airoha_gdm_dev *dev = netdev_priv(netdev);\n \tstruct airoha_gdm_port *port = dev-\u003eport;\n-\tstruct airoha_qdma *qdma = dev-\u003eqdma;\n \n \tnetif_tx_disable(netdev);\n \tairoha_set_vip_for_gdm_port(dev, false);\n@@ -1906,7 +1906,7 @@ static int airoha_dev_stop(struct net_device *netdev)\n \tif (--port-\u003eusers)\n \t\tairoha_ppe_set_xmit_frame_size(dev);\n \telse\n-\t\tairoha_set_gdm_port_fwd_cfg(qdma-\u003eeth,\n+\t\tairoha_set_gdm_port_fwd_cfg(dev-\u003eeth,\n \t\t\t\t\t REG_GDM_FWD_CFG(port-\u003eid),\n \t\t\t\t\t FE_PSE_PORT_DROP);\n \treturn 0;\n@@ -1989,6 +1989,53 @@ static int airoha_enable_gdm2_loopback(struct airoha_gdm_dev *dev)\n \treturn 0;\n }\n \n+static int airoha_disable_gdm2_loopback(struct airoha_gdm_dev *dev)\n+{\n+\tstruct airoha_gdm_port *port = dev-\u003eport;\n+\tstruct airoha_eth *eth = dev-\u003eeth;\n+\tint i, src_port;\n+\tu32 pse_port;\n+\n+\tsrc_port = eth-\u003esoc-\u003eops.get_sport(dev-\u003eport, dev-\u003enbq);\n+\tif (src_port \u003c 0)\n+\t\treturn src_port;\n+\n+\tairoha_fe_clear(eth,\n+\t\t\tREG_SP_DFT_CPORT(src_port \u003e\u003e fls(SP_CPORT_DFT_MASK)),\n+\t\t\tSP_CPORT_MASK(src_port \u0026 SP_CPORT_DFT_MASK));\n+\n+\tairoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX),\n+\t\t GDM_STRIP_CRC_MASK);\n+\tairoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX),\n+\t\t\t\t FE_PSE_PORT_DROP);\n+\tairoha_fe_clear(eth, REG_GDM_LPBK_CFG(AIROHA_GDM2_IDX),\n+\t\t\tLPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK);\n+\tpse_port = airoha_ppe_is_enabled(eth, 1) ? FE_PSE_PORT_PPE2\n+\t\t\t\t\t\t : FE_PSE_PORT_PPE1;\n+\tairoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX),\n+\t\t\t\t pse_port);\n+\n+\tairoha_fe_rmw(eth, REG_FE_WAN_PORT, WAN0_MASK,\n+\t\t FIELD_PREP(WAN0_MASK, AIROHA_GDM2_IDX));\n+\n+\tfor (i = 0; i \u003c eth-\u003esoc-\u003enum_ppe; i++)\n+\t\tairoha_fe_clear(eth, REG_PPE_DFT_CPORT(i, AIROHA_GDM2_IDX),\n+\t\t\t\tDFT_CPORT_MASK(AIROHA_GDM2_IDX));\n+\n+\t/* Enable VIP and IFC for GDM2 */\n+\tairoha_fe_set(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX));\n+\tairoha_fe_set(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX));\n+\n+\tif (port-\u003eid == AIROHA_GDM4_IDX \u0026\u0026 airoha_is_7581(eth)) {\n+\t\tu32 mask = FC_ID_OF_SRC_PORT_MASK(dev-\u003enbq);\n+\n+\t\tairoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, mask,\n+\t\t\t FC_MAP6_DEF_VALUE \u0026 mask);\n+\t}\n+\n+\treturn 0;\n+}\n+\n static struct airoha_gdm_dev *\n airoha_get_wan_gdm_dev(struct airoha_eth *eth)\n {\n@@ -2015,15 +2062,50 @@ airoha_get_wan_gdm_dev(struct airoha_eth *eth)\n static void airoha_dev_set_qdma(struct airoha_gdm_dev *dev)\n {\n \tstruct net_device *netdev = netdev_from_priv(dev);\n+\tstruct airoha_qdma *cur_qdma, *qdma;\n \tstruct airoha_eth *eth = dev-\u003eeth;\n-\tint ppe_id;\n+\tint i, ppe_id;\n \n \t/* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */\n-\tdev-\u003eqdma = \u0026eth-\u003eqdma[!airoha_is_lan_gdm_dev(dev)];\n-\tnetdev-\u003eirq = dev-\u003eqdma-\u003eirq_banks[0].irq;\n+\tqdma = \u0026eth-\u003eqdma[!airoha_is_lan_gdm_dev(dev)];\n+\tcur_qdma = airoha_qdma_deref(dev);\n+\n+\tif (cur_qdma) {\n+\t\t/* Ensure any in-flight packets for the old QDMA in the TX path\n+\t\t * has completed before swapping the QDMA pointer.\n+\t\t */\n+\t\tnetif_tx_stop_all_queues(netdev);\n+\t\tsynchronize_rcu();\n+\t}\n+\n+\trcu_assign_pointer(dev-\u003eqdma, qdma);\n+\tnetdev-\u003eirq = qdma-\u003eirq_banks[0].irq;\n \n \tppe_id = !airoha_is_lan_gdm_dev(dev) \u0026\u0026 airoha_ppe_is_enabled(eth, 1);\n \tairoha_ppe_set_cpu_port(dev, ppe_id, airoha_get_fe_port(dev));\n+\n+\t/* Seed qos_stats baselines with the new QDMA block's current\n+\t * counter values to avoid a spurious spike on the first stats\n+\t * query after init or migration.\n+\t */\n+\tfor (i = 0; i \u003c ARRAY_SIZE(dev-\u003eqos_stats); i++) {\n+\t\tdev-\u003eqos_stats[i].cpu_tx_packets =\n+\t\t\tairoha_qdma_rr(qdma, REG_CNTR_VAL(i \u003c\u003c 1));\n+\t\tdev-\u003eqos_stats[i].fwd_tx_packets =\n+\t\t\tairoha_qdma_rr(qdma, REG_CNTR_VAL((i \u003c\u003c 1) + 1));\n+\t}\n+\n+\tif (cur_qdma) {\n+\t\t/* Wait for the pending TX completion on the old QDMA */\n+\t\tairoha_qdma_irq_disable(\u0026cur_qdma-\u003eirq_banks[0],\n+\t\t\t\t\tQDMA_INT_REG_IDX0, INT_TX_MASK);\n+\t\tfor (i = 0; i \u003c ARRAY_SIZE(cur_qdma-\u003eq_tx_irq); i++)\n+\t\t\tnapi_synchronize(\u0026cur_qdma-\u003eq_tx_irq[i].napi);\n+\n+\t\tairoha_qdma_irq_enable(\u0026cur_qdma-\u003eirq_banks[0],\n+\t\t\t\t QDMA_INT_REG_IDX0, INT_TX_MASK);\n+\t\tnetif_tx_wake_all_queues(netdev);\n+\t}\n }\n \n static int airoha_dev_init(struct net_device *netdev)\n@@ -2039,7 +2121,7 @@ static int airoha_dev_init(struct net_device *netdev)\n \t\tfallthrough;\n \tcase AIROHA_GDM2_IDX:\n \t\t/* GDM2 is always used as wan */\n-\t\tdev-\u003eflags |= AIROHA_PRIV_F_WAN;\n+\t\tdev-\u003eflags |= AIROHA_DEV_F_WAN;\n \t\tbreak;\n \tdefault:\n \t\tbreak;\n@@ -2178,9 +2260,9 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,\n \t\t\t\t struct net_device *netdev)\n {\n \tstruct airoha_gdm_dev *dev = netdev_priv(netdev);\n-\tstruct airoha_qdma *qdma = dev-\u003eqdma;\n \tu32 nr_frags, tag, msg0, msg1, len;\n \tstruct airoha_queue_entry *e;\n+\tstruct airoha_qdma *qdma;\n \tstruct netdev_queue *txq;\n \tstruct airoha_queue *q;\n \tLIST_HEAD(tx_list);\n@@ -2189,6 +2271,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,\n \tu16 index;\n \tu8 fport;\n \n+\trcu_read_lock();\n+\tqdma = rcu_dereference(dev-\u003eqdma);\n \tqid = airoha_qdma_get_txq(qdma, skb_get_queue_mapping(skb));\n \ttag = airoha_get_dsa_tag(skb, netdev);\n \n@@ -2238,6 +2322,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,\n \t\tnetif_tx_stop_queue(txq);\n \t\tq-\u003etxq_stopped = true;\n \t\tspin_unlock_bh(\u0026q-\u003elock);\n+\t\trcu_read_unlock();\n+\n \t\treturn NETDEV_TX_BUSY;\n \t}\n \n@@ -2303,6 +2389,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,\n \t\t\t\tFIELD_PREP(TX_RING_CPU_IDX_MASK, index));\n \n \tspin_unlock_bh(\u0026q-\u003elock);\n+\trcu_read_unlock();\n \n \treturn NETDEV_TX_OK;\n \n@@ -2315,6 +2402,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,\n error:\n \tdev_kfree_skb_any(skb);\n \tnetdev-\u003estats.tx_dropped++;\n+\trcu_read_unlock();\n \n \treturn NETDEV_TX_OK;\n }\n@@ -2394,17 +2482,19 @@ static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,\n \t\t\t\t\t const u16 *weights, u8 n_weights)\n {\n \tstruct airoha_gdm_dev *dev = netdev_priv(netdev);\n+\tstruct airoha_qdma *qdma;\n \tint i;\n \n+\tqdma = airoha_qdma_deref(dev);\n \tfor (i = 0; i \u003c AIROHA_NUM_QOS_QUEUES; i++)\n-\t\tairoha_qdma_clear(dev-\u003eqdma, REG_QUEUE_CLOSE_CFG(channel),\n+\t\tairoha_qdma_clear(qdma, REG_QUEUE_CLOSE_CFG(channel),\n \t\t\t\t TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i));\n \n \tfor (i = 0; i \u003c n_weights; i++) {\n \t\tu32 status;\n \t\tint err;\n \n-\t\tairoha_qdma_wr(dev-\u003eqdma, REG_TXWRR_WEIGHT_CFG,\n+\t\tairoha_qdma_wr(qdma, REG_TXWRR_WEIGHT_CFG,\n \t\t\t TWRR_RW_CMD_MASK |\n \t\t\t FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) |\n \t\t\t FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) |\n@@ -2412,12 +2502,12 @@ static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,\n \t\terr = read_poll_timeout(airoha_qdma_rr, status,\n \t\t\t\t\tstatus \u0026 TWRR_RW_CMD_DONE,\n \t\t\t\t\tUSEC_PER_MSEC, 10 * USEC_PER_MSEC,\n-\t\t\t\t\ttrue, dev-\u003eqdma, REG_TXWRR_WEIGHT_CFG);\n+\t\t\t\t\ttrue, qdma, REG_TXWRR_WEIGHT_CFG);\n \t\tif (err)\n \t\t\treturn err;\n \t}\n \n-\tairoha_qdma_rmw(dev-\u003eqdma, REG_CHAN_QOS_MODE(channel \u003e\u003e 3),\n+\tairoha_qdma_rmw(qdma, REG_CHAN_QOS_MODE(channel \u003e\u003e 3),\n \t\t\tCHAN_QOS_MODE_MASK(channel),\n \t\t\t__field_prep(CHAN_QOS_MODE_MASK(channel), mode));\n \n@@ -2481,17 +2571,22 @@ static int airoha_qdma_get_tx_ets_stats(struct net_device *netdev, int channel,\n \t\t\t\t\tstruct tc_ets_qopt_offload *opt)\n {\n \tstruct airoha_gdm_dev *dev = netdev_priv(netdev);\n-\tstruct airoha_qdma *qdma = dev-\u003eqdma;\n+\tu32 cpu_tx_packets, fwd_tx_packets;\n+\tstruct airoha_qdma *qdma;\n+\tu64 tx_packets;\n \n-\tu64 cpu_tx_packets = airoha_qdma_rr(qdma, REG_CNTR_VAL(channel \u003c\u003c 1));\n-\tu64 fwd_tx_packets = airoha_qdma_rr(qdma,\n-\t\t\t\t\t REG_CNTR_VAL((channel \u003c\u003c 1) + 1));\n-\tu64 tx_packets = (cpu_tx_packets - dev-\u003ecpu_tx_packets) +\n-\t\t\t (fwd_tx_packets - dev-\u003efwd_tx_packets);\n+\tqdma = airoha_qdma_deref(dev);\n+\tcpu_tx_packets = airoha_qdma_rr(qdma, REG_CNTR_VAL(channel \u003c\u003c 1));\n+\tfwd_tx_packets = airoha_qdma_rr(qdma,\n+\t\t\t\t\tREG_CNTR_VAL((channel \u003c\u003c 1) + 1));\n+\ttx_packets = (u32)(cpu_tx_packets -\n+\t\t\t dev-\u003eqos_stats[channel].cpu_tx_packets);\n+\ttx_packets += (u32)(fwd_tx_packets -\n+\t\t\t dev-\u003eqos_stats[channel].fwd_tx_packets);\n \n \t_bstats_update(opt-\u003estats.bstats, 0, tx_packets);\n-\tdev-\u003ecpu_tx_packets = cpu_tx_packets;\n-\tdev-\u003efwd_tx_packets = fwd_tx_packets;\n+\tdev-\u003eqos_stats[channel].cpu_tx_packets = cpu_tx_packets;\n+\tdev-\u003eqos_stats[channel].fwd_tx_packets = fwd_tx_packets;\n \n \treturn 0;\n }\n@@ -2747,16 +2842,18 @@ static int airoha_qdma_set_tx_rate_limit(struct net_device *netdev,\n \t\t\t\t\t u32 bucket_size)\n {\n \tstruct airoha_gdm_dev *dev = netdev_priv(netdev);\n+\tstruct airoha_qdma *qdma;\n \tint i, err;\n \n+\tqdma = airoha_qdma_deref(dev);\n \tfor (i = 0; i \u003c= TRTCM_PEAK_MODE; i++) {\n-\t\terr = airoha_qdma_set_trtcm_config(dev-\u003eqdma, channel,\n+\t\terr = airoha_qdma_set_trtcm_config(qdma, channel,\n \t\t\t\t\t\t REG_EGRESS_TRTCM_CFG, i,\n \t\t\t\t\t\t !!rate, TRTCM_METER_MODE);\n \t\tif (err)\n \t\t\treturn err;\n \n-\t\terr = airoha_qdma_set_trtcm_token_bucket(dev-\u003eqdma, channel,\n+\t\terr = airoha_qdma_set_trtcm_token_bucket(qdma, channel,\n \t\t\t\t\t\t\t REG_EGRESS_TRTCM_CFG,\n \t\t\t\t\t\t\t i, rate, bucket_size);\n \t\tif (err)\n@@ -2792,11 +2889,12 @@ static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev,\n \tu32 channel = TC_H_MIN(opt-\u003eclassid) % AIROHA_NUM_QOS_CHANNELS;\n \tint err, num_tx_queues = AIROHA_NUM_TX_RING + channel + 1;\n \tstruct airoha_gdm_dev *dev = netdev_priv(netdev);\n-\tstruct airoha_qdma *qdma = dev-\u003eqdma;\n+\tstruct airoha_qdma *qdma;\n \n \t/* Here we need to check the requested QDMA channel is not already\n \t * in use by another net_device running on the same QDMA block.\n \t */\n+\tqdma = airoha_qdma_deref(dev);\n \tif (test_and_set_bit(channel, qdma-\u003eqos_channel_map)) {\n \t\tNL_SET_ERR_MSG_MOD(opt-\u003eextack,\n \t\t\t\t \"qdma qos channel already in use\");\n@@ -2832,7 +2930,7 @@ static int airoha_qdma_set_rx_meter(struct airoha_gdm_dev *dev,\n \t\t\t\t u32 rate, u32 bucket_size,\n \t\t\t\t enum trtcm_unit_type unit_type)\n {\n-\tstruct airoha_qdma *qdma = dev-\u003eqdma;\n+\tstruct airoha_qdma *qdma = airoha_qdma_deref(dev);\n \tint i;\n \n \tfor (i = 0; i \u003c ARRAY_SIZE(qdma-\u003eq_rx); i++) {\n@@ -3007,10 +3105,11 @@ static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue)\n {\n \tstruct airoha_gdm_dev *dev = netdev_priv(netdev);\n \tint num_tx_queues = AIROHA_NUM_TX_RING;\n-\tstruct airoha_qdma *qdma = dev-\u003eqdma;\n+\tstruct airoha_qdma *qdma;\n \n \tairoha_qdma_set_tx_rate_limit(netdev, queue, 0, 0);\n \n+\tqdma = airoha_qdma_deref(dev);\n \tclear_bit(queue, qdma-\u003eqos_channel_map);\n \tclear_bit(queue, dev-\u003eqos_sq_bmap);\n \n@@ -3036,6 +3135,98 @@ static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev,\n \treturn 0;\n }\n \n+static void airoha_disable_qos_for_gdm34(struct net_device *netdev)\n+{\n+\tstruct airoha_gdm_dev *dev = netdev_priv(netdev);\n+\tstruct airoha_gdm_port *port = dev-\u003eport;\n+\tint err;\n+\n+\tif (port-\u003eid != AIROHA_GDM3_IDX \u0026\u0026\n+\t port-\u003eid != AIROHA_GDM4_IDX)\n+\t\treturn;\n+\n+\terr = airoha_disable_gdm2_loopback(dev);\n+\tif (err)\n+\t\tnetdev_warn(netdev,\n+\t\t\t \"failed disabling GDM2 loopback: %d\\n\", err);\n+\n+\tdev-\u003eflags \u0026= ~AIROHA_DEV_F_WAN;\n+\tairoha_dev_set_qdma(dev);\n+\n+\tairoha_set_macaddr(dev, netdev-\u003edev_addr);\n+\tairoha_ppe_set_xmit_frame_size(dev);\n+\n+\tif (netif_running(netdev))\n+\t\tairoha_set_gdm_port_fwd_cfg(dev-\u003eeth,\n+\t\t\t\t\t REG_GDM_FWD_CFG(port-\u003eid),\n+\t\t\t\t\t FE_PSE_PORT_PPE1);\n+}\n+\n+static int airoha_enable_qos_for_gdm34(struct net_device *netdev,\n+\t\t\t\t struct netlink_ext_ack *extack)\n+{\n+\tstruct airoha_gdm_dev *wan_dev, *dev = netdev_priv(netdev);\n+\tstruct airoha_gdm_port *port = dev-\u003eport;\n+\tstruct airoha_eth *eth = dev-\u003eeth;\n+\tint err = -EBUSY;\n+\n+\tif (port-\u003eid != AIROHA_GDM3_IDX \u0026\u0026\n+\t port-\u003eid != AIROHA_GDM4_IDX) {\n+\t\t/* HW QoS is always supported by GDM1 and GDM2 */\n+\t\treturn 0;\n+\t}\n+\n+\tif (!airoha_is_lan_gdm_dev(dev)) /* Already enabled */\n+\t\treturn 0;\n+\n+\tmutex_lock(\u0026flow_offload_mutex);\n+\n+\twan_dev = airoha_get_wan_gdm_dev(eth);\n+\tif (wan_dev) {\n+\t\tif ((wan_dev-\u003eflags \u0026 AIROHA_DEV_F_TX_QOS) ||\n+\t\t wan_dev-\u003eport-\u003eid == AIROHA_GDM2_IDX) {\n+\t\t\tNL_SET_ERR_MSG_MOD(extack,\n+\t\t\t\t\t \"QoS configured for WAN device\");\n+\t\t\tgoto error_unlock;\n+\t\t}\n+\t\tairoha_disable_qos_for_gdm34(netdev_from_priv(wan_dev));\n+\t}\n+\n+\tdev-\u003eflags |= AIROHA_DEV_F_WAN;\n+\tairoha_dev_set_qdma(dev);\n+\terr = airoha_enable_gdm2_loopback(dev);\n+\tif (err)\n+\t\tgoto error_disable_wan;\n+\n+\terr = airoha_set_macaddr(dev, netdev-\u003edev_addr);\n+\tif (err)\n+\t\tgoto error_disable_loopback;\n+\n+\tairoha_dev_set_xmit_frame_size(netdev);\n+\tif (netif_running(netdev)) {\n+\t\tu32 pse_port;\n+\n+\t\tpse_port = airoha_ppe_is_enabled(eth, 1) ? FE_PSE_PORT_PPE2\n+\t\t\t\t\t\t\t : FE_PSE_PORT_PPE1;\n+\t\tairoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port-\u003eid),\n+\t\t\t\t\t pse_port);\n+\t}\n+\n+\tmutex_unlock(\u0026flow_offload_mutex);\n+\n+\treturn 0;\n+\n+error_disable_loopback:\n+\tairoha_disable_gdm2_loopback(dev);\n+error_disable_wan:\n+\tdev-\u003eflags \u0026= ~AIROHA_DEV_F_WAN;\n+\tairoha_dev_set_qdma(dev);\n+error_unlock:\n+\tmutex_unlock(\u0026flow_offload_mutex);\n+\n+\treturn err;\n+}\n+\n static int airoha_tc_htb_destroy(struct net_device *netdev)\n {\n \tstruct airoha_gdm_dev *dev = netdev_priv(netdev);\n@@ -3044,6 +3235,8 @@ static int airoha_tc_htb_destroy(struct net_device *netdev)\n \tfor_each_set_bit(q, dev-\u003eqos_sq_bmap, AIROHA_NUM_QOS_CHANNELS)\n \t\tairoha_tc_remove_htb_queue(netdev, q);\n \n+\tdev-\u003eflags \u0026= ~AIROHA_DEV_F_TX_QOS;\n+\n \treturn 0;\n }\n \n@@ -3063,24 +3256,33 @@ static int airoha_tc_get_htb_get_leaf_queue(struct net_device *netdev,\n \treturn 0;\n }\n \n-static int airoha_tc_setup_qdisc_htb(struct net_device *dev,\n+static int airoha_tc_setup_qdisc_htb(struct net_device *netdev,\n \t\t\t\t struct tc_htb_qopt_offload *opt)\n {\n \tswitch (opt-\u003ecommand) {\n-\tcase TC_HTB_CREATE:\n+\tcase TC_HTB_CREATE: {\n+\t\tstruct airoha_gdm_dev *dev = netdev_priv(netdev);\n+\t\tint err;\n+\n+\t\terr = airoha_enable_qos_for_gdm34(netdev, opt-\u003eextack);\n+\t\tif (err)\n+\t\t\treturn err;\n+\n+\t\tdev-\u003eflags |= AIROHA_DEV_F_TX_QOS;\n \t\tbreak;\n+\t}\n \tcase TC_HTB_DESTROY:\n-\t\treturn airoha_tc_htb_destroy(dev);\n+\t\treturn airoha_tc_htb_destroy(netdev);\n \tcase TC_HTB_NODE_MODIFY:\n-\t\treturn airoha_tc_htb_modify_queue(dev, opt);\n+\t\treturn airoha_tc_htb_modify_queue(netdev, opt);\n \tcase TC_HTB_LEAF_ALLOC_QUEUE:\n-\t\treturn airoha_tc_htb_alloc_leaf_queue(dev, opt);\n+\t\treturn airoha_tc_htb_alloc_leaf_queue(netdev, opt);\n \tcase TC_HTB_LEAF_DEL:\n \tcase TC_HTB_LEAF_DEL_LAST:\n \tcase TC_HTB_LEAF_DEL_LAST_FORCE:\n-\t\treturn airoha_tc_htb_delete_leaf_queue(dev, opt);\n+\t\treturn airoha_tc_htb_delete_leaf_queue(netdev, opt);\n \tcase TC_HTB_LEAF_QUERY_QUEUE:\n-\t\treturn airoha_tc_get_htb_get_leaf_queue(dev, opt);\n+\t\treturn airoha_tc_get_htb_get_leaf_queue(netdev, opt);\n \tdefault:\n \t\treturn -EOPNOTSUPP;\n \t}\ndiff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h\nindex f6d01a8e8da139..b43a08e937959d 100644\n--- a/drivers/net/ethernet/airoha/airoha_eth.h\n+++ b/drivers/net/ethernet/airoha/airoha_eth.h\n@@ -543,19 +543,21 @@ struct airoha_qdma {\n \tDECLARE_BITMAP(qos_channel_map, AIROHA_NUM_QOS_CHANNELS);\n };\n \n-enum airoha_priv_flags {\n-\tAIROHA_PRIV_F_WAN = BIT(0),\n+enum airoha_dev_flags {\n+\tAIROHA_DEV_F_WAN\t= BIT(0),\n+\tAIROHA_DEV_F_TX_QOS\t= BIT(1),\n };\n \n struct airoha_gdm_dev {\n+\tstruct airoha_qdma __rcu *qdma;\n \tstruct airoha_gdm_port *port;\n-\tstruct airoha_qdma *qdma;\n \tstruct airoha_eth *eth;\n \n \tDECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS);\n-\t/* qos stats counters */\n-\tu64 cpu_tx_packets;\n-\tu64 fwd_tx_packets;\n+\tstruct {\n+\t\tu32 cpu_tx_packets;\n+\t\tu32 fwd_tx_packets;\n+\t} qos_stats[AIROHA_NUM_QOS_CHANNELS];\n \n \tu32 flags;\n \tint nbq;\n@@ -667,7 +669,7 @@ static inline u16 airoha_qdma_get_txq(struct airoha_qdma *qdma, u16 qid)\n \n static inline bool airoha_is_lan_gdm_dev(struct airoha_gdm_dev *dev)\n {\n-\treturn !(dev-\u003eflags \u0026 AIROHA_PRIV_F_WAN);\n+\treturn !(dev-\u003eflags \u0026 AIROHA_DEV_F_WAN);\n }\n \n static inline bool airoha_is_7581(struct airoha_eth *eth)\n@@ -684,6 +686,16 @@ int airoha_get_fe_port(struct airoha_gdm_dev *dev);\n bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,\n \t\t\t struct airoha_gdm_dev *dev);\n \n+extern struct mutex flow_offload_mutex;\n+\n+static inline struct airoha_qdma *\n+airoha_qdma_deref(struct airoha_gdm_dev *dev)\n+{\n+\treturn rcu_dereference_protected(dev-\u003eqdma,\n+\t\t\t\t\t lockdep_rtnl_is_held() ||\n+\t\t\t\t\t lockdep_is_held(\u0026flow_offload_mutex));\n+}\n+\n void airoha_ppe_set_xmit_frame_size(struct airoha_gdm_dev *dev);\n void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport);\n bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index);\ndiff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c\nindex fdb973fc779c83..3ccdf9fccb4a12 100644\n--- a/drivers/net/ethernet/airoha/airoha_ppe.c\n+++ b/drivers/net/ethernet/airoha/airoha_ppe.c\n@@ -15,7 +15,10 @@\n #include \"airoha_regs.h\"\n #include \"airoha_eth.h\"\n \n-static DEFINE_MUTEX(flow_offload_mutex);\n+/* Serialize airoha_gdm_dev flags, QDMA pointer and PPE CPU port\n+ * configuration.\n+ */\n+DEFINE_MUTEX(flow_offload_mutex);\n static DEFINE_SPINLOCK(ppe_lock);\n \n static const struct rhashtable_params airoha_flow_table_params = {\n@@ -86,8 +89,8 @@ static u32 airoha_ppe_get_timestamp(struct airoha_ppe *ppe)\n \n void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport)\n {\n-\tstruct airoha_qdma *qdma = dev-\u003eqdma;\n-\tstruct airoha_eth *eth = qdma-\u003eeth;\n+\tstruct airoha_qdma *qdma = airoha_qdma_deref(dev);\n+\tstruct airoha_eth *eth = dev-\u003eeth;\n \tu8 qdma_id = qdma - \u0026eth-\u003eqdma[0];\n \tu32 fe_cpu_port;\n \ndiff --git a/drivers/net/ethernet/airoha/airoha_regs.h b/drivers/net/ethernet/airoha/airoha_regs.h\nindex 6fed63d013b412..442b48c9b991ef 100644\n--- a/drivers/net/ethernet/airoha/airoha_regs.h\n+++ b/drivers/net/ethernet/airoha/airoha_regs.h\n@@ -375,6 +375,7 @@\n \n #define REG_SRC_PORT_FC_MAP6\t\t0x2298\n #define FC_ID_OF_SRC_PORT_MASK(_n)\tGENMASK(4 + ((_n) \u003c\u003c 3), ((_n) \u003c\u003c 3))\n+#define FC_MAP6_DEF_VALUE\t\t0x1b1a1918\n \n #define REG_WAN_MTU0\t\t\t0x2300\n #define WAN_MTU1_MASK\t\t\tGENMASK(29, 16)\n"
} |
| 2/1 | 2026/07/23 22:38 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies the Airoha SoC Gigabit Ethernet driver (drivers/net/ethernet/airoha/). This is a hardware-specific platform driver that requires specific Airoha SoC hardware (MMIO registers, IRQs) to probe successfully. It cannot be reached or tested in standard virtualized environments like QEMU or GCE.",
"WorthFuzzing": false
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 5211720442ad6b87c667e691b15677060d7601f0
Author: syz-cluster <triage@syzkaller.com>
Date: Thu Jul 23 22:38:50 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 59001fd4b6f740..06f866d7137ee2 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -934,7 +934,7 @@ static void airoha_qdma_wake_netdev_txqs(struct airoha_queue *q)
if (!dev)
continue;
- if (dev->qdma != qdma)
+ if (rcu_access_pointer(dev->qdma) != qdma)
continue;
netdev = netdev_from_priv(dev);
@@ -1866,8 +1866,8 @@ static int airoha_dev_open(struct net_device *netdev)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
struct airoha_gdm_port *port = dev->port;
- struct airoha_qdma *qdma = dev->qdma;
u32 pse_port = FE_PSE_PORT_PPE1;
+ struct airoha_qdma *qdma;
int err;
netif_tx_start_all_queues(netdev);
@@ -1875,6 +1875,7 @@ static int airoha_dev_open(struct net_device *netdev)
if (err)
return err;
+ qdma = airoha_qdma_deref(dev);
if (netdev_uses_dsa(netdev))
airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id),
GDM_STAG_EN_MASK);
@@ -1898,7 +1899,6 @@ static int airoha_dev_stop(struct net_device *netdev)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
struct airoha_gdm_port *port = dev->port;
- struct airoha_qdma *qdma = dev->qdma;
netif_tx_disable(netdev);
airoha_set_vip_for_gdm_port(dev, false);
@@ -1906,7 +1906,7 @@ static int airoha_dev_stop(struct net_device *netdev)
if (--port->users)
airoha_ppe_set_xmit_frame_size(dev);
else
- airoha_set_gdm_port_fwd_cfg(qdma->eth,
+ airoha_set_gdm_port_fwd_cfg(dev->eth,
REG_GDM_FWD_CFG(port->id),
FE_PSE_PORT_DROP);
return 0;
@@ -1989,6 +1989,53 @@ static int airoha_enable_gdm2_loopback(struct airoha_gdm_dev *dev)
return 0;
}
+static int airoha_disable_gdm2_loopback(struct airoha_gdm_dev *dev)
+{
+ struct airoha_gdm_port *port = dev->port;
+ struct airoha_eth *eth = dev->eth;
+ int i, src_port;
+ u32 pse_port;
+
+ src_port = eth->soc->ops.get_sport(dev->port, dev->nbq);
+ if (src_port < 0)
+ return src_port;
+
+ airoha_fe_clear(eth,
+ REG_SP_DFT_CPORT(src_port >> fls(SP_CPORT_DFT_MASK)),
+ SP_CPORT_MASK(src_port & SP_CPORT_DFT_MASK));
+
+ airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX),
+ GDM_STRIP_CRC_MASK);
+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX),
+ FE_PSE_PORT_DROP);
+ airoha_fe_clear(eth, REG_GDM_LPBK_CFG(AIROHA_GDM2_IDX),
+ LPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK);
+ pse_port = airoha_ppe_is_enabled(eth, 1) ? FE_PSE_PORT_PPE2
+ : FE_PSE_PORT_PPE1;
+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX),
+ pse_port);
+
+ airoha_fe_rmw(eth, REG_FE_WAN_PORT, WAN0_MASK,
+ FIELD_PREP(WAN0_MASK, AIROHA_GDM2_IDX));
+
+ for (i = 0; i < eth->soc->num_ppe; i++)
+ airoha_fe_clear(eth, REG_PPE_DFT_CPORT(i, AIROHA_GDM2_IDX),
+ DFT_CPORT_MASK(AIROHA_GDM2_IDX));
+
+ /* Enable VIP and IFC for GDM2 */
+ airoha_fe_set(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX));
+ airoha_fe_set(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX));
+
+ if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) {
+ u32 mask = FC_ID_OF_SRC_PORT_MASK(dev->nbq);
+
+ airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, mask,
+ FC_MAP6_DEF_VALUE & mask);
+ }
+
+ return 0;
+}
+
static struct airoha_gdm_dev *
airoha_get_wan_gdm_dev(struct airoha_eth *eth)
{
@@ -2015,15 +2062,50 @@ airoha_get_wan_gdm_dev(struct airoha_eth *eth)
static void airoha_dev_set_qdma(struct airoha_gdm_dev *dev)
{
struct net_device *netdev = netdev_from_priv(dev);
+ struct airoha_qdma *cur_qdma, *qdma;
struct airoha_eth *eth = dev->eth;
- int ppe_id;
+ int i, ppe_id;
/* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */
- dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)];
- netdev->irq = dev->qdma->irq_banks[0].irq;
+ qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)];
+ cur_qdma = airoha_qdma_deref(dev);
+
+ if (cur_qdma) {
+ /* Ensure any in-flight packets for the old QDMA in the TX path
+ * has completed before swapping the QDMA pointer.
+ */
+ netif_tx_stop_all_queues(netdev);
+ synchronize_rcu();
+ }
+
+ rcu_assign_pointer(dev->qdma, qdma);
+ netdev->irq = qdma->irq_banks[0].irq;
ppe_id = !airoha_is_lan_gdm_dev(dev) && airoha_ppe_is_enabled(eth, 1);
airoha_ppe_set_cpu_port(dev, ppe_id, airoha_get_fe_port(dev));
+
+ /* Seed qos_stats baselines with the new QDMA block's current
+ * counter values to avoid a spurious spike on the first stats
+ * query after init or migration.
+ */
+ for (i = 0; i < ARRAY_SIZE(dev->qos_stats); i++) {
+ dev->qos_stats[i].cpu_tx_packets =
+ airoha_qdma_rr(qdma, REG_CNTR_VAL(i << 1));
+ dev->qos_stats[i].fwd_tx_packets =
+ airoha_qdma_rr(qdma, REG_CNTR_VAL((i << 1) + 1));
+ }
+
+ if (cur_qdma) {
+ /* Wait for the pending TX completion on the old QDMA */
+ airoha_qdma_irq_disable(&cur_qdma->irq_banks[0],
+ QDMA_INT_REG_IDX0, INT_TX_MASK);
+ for (i = 0; i < ARRAY_SIZE(cur_qdma->q_tx_irq); i++)
+ napi_synchronize(&cur_qdma->q_tx_irq[i].napi);
+
+ airoha_qdma_irq_enable(&cur_qdma->irq_banks[0],
+ QDMA_INT_REG_IDX0, INT_TX_MASK);
+ netif_tx_wake_all_queues(netdev);
+ }
}
static int airoha_dev_init(struct net_device *netdev)
@@ -2039,7 +2121,7 @@ static int airoha_dev_init(struct net_device *netdev)
fallthrough;
case AIROHA_GDM2_IDX:
/* GDM2 is always used as wan */
- dev->flags |= AIROHA_PRIV_F_WAN;
+ dev->flags |= AIROHA_DEV_F_WAN;
break;
default:
break;
@@ -2178,9 +2260,9 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
struct net_device *netdev)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
- struct airoha_qdma *qdma = dev->qdma;
u32 nr_frags, tag, msg0, msg1, len;
struct airoha_queue_entry *e;
+ struct airoha_qdma *qdma;
struct netdev_queue *txq;
struct airoha_queue *q;
LIST_HEAD(tx_list);
@@ -2189,6 +2271,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
u16 index;
u8 fport;
+ rcu_read_lock();
+ qdma = rcu_dereference(dev->qdma);
qid = airoha_qdma_get_txq(qdma, skb_get_queue_mapping(skb));
tag = airoha_get_dsa_tag(skb, netdev);
@@ -2238,6 +2322,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
netif_tx_stop_queue(txq);
q->txq_stopped = true;
spin_unlock_bh(&q->lock);
+ rcu_read_unlock();
+
return NETDEV_TX_BUSY;
}
@@ -2303,6 +2389,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
FIELD_PREP(TX_RING_CPU_IDX_MASK, index));
spin_unlock_bh(&q->lock);
+ rcu_read_unlock();
return NETDEV_TX_OK;
@@ -2315,6 +2402,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
error:
dev_kfree_skb_any(skb);
netdev->stats.tx_dropped++;
+ rcu_read_unlock();
return NETDEV_TX_OK;
}
@@ -2394,17 +2482,19 @@ static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,
const u16 *weights, u8 n_weights)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_qdma *qdma;
int i;
+ qdma = airoha_qdma_deref(dev);
for (i = 0; i < AIROHA_NUM_QOS_QUEUES; i++)
- airoha_qdma_clear(dev->qdma, REG_QUEUE_CLOSE_CFG(channel),
+ airoha_qdma_clear(qdma, REG_QUEUE_CLOSE_CFG(channel),
TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i));
for (i = 0; i < n_weights; i++) {
u32 status;
int err;
- airoha_qdma_wr(dev->qdma, REG_TXWRR_WEIGHT_CFG,
+ airoha_qdma_wr(qdma, REG_TXWRR_WEIGHT_CFG,
TWRR_RW_CMD_MASK |
FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) |
FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) |
@@ -2412,12 +2502,12 @@ static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,
err = read_poll_timeout(airoha_qdma_rr, status,
status & TWRR_RW_CMD_DONE,
USEC_PER_MSEC, 10 * USEC_PER_MSEC,
- true, dev->qdma, REG_TXWRR_WEIGHT_CFG);
+ true, qdma, REG_TXWRR_WEIGHT_CFG);
if (err)
return err;
}
- airoha_qdma_rmw(dev->qdma, REG_CHAN_QOS_MODE(channel >> 3),
+ airoha_qdma_rmw(qdma, REG_CHAN_QOS_MODE(channel >> 3),
CHAN_QOS_MODE_MASK(channel),
__field_prep(CHAN_QOS_MODE_MASK(channel), mode));
@@ -2481,17 +2571,22 @@ static int airoha_qdma_get_tx_ets_stats(struct net_device *netdev, int channel,
struct tc_ets_qopt_offload *opt)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
- struct airoha_qdma *qdma = dev->qdma;
+ u32 cpu_tx_packets, fwd_tx_packets;
+ struct airoha_qdma *qdma;
+ u64 tx_packets;
- u64 cpu_tx_packets = airoha_qdma_rr(qdma, REG_CNTR_VAL(channel << 1));
- u64 fwd_tx_packets = airoha_qdma_rr(qdma,
- REG_CNTR_VAL((channel << 1) + 1));
- u64 tx_packets = (cpu_tx_packets - dev->cpu_tx_packets) +
- (fwd_tx_packets - dev->fwd_tx_packets);
+ qdma = airoha_qdma_deref(dev);
+ cpu_tx_packets = airoha_qdma_rr(qdma, REG_CNTR_VAL(channel << 1));
+ fwd_tx_packets = airoha_qdma_rr(qdma,
+ REG_CNTR_VAL((channel << 1) + 1));
+ tx_packets = (u32)(cpu_tx_packets -
+ dev->qos_stats[channel].cpu_tx_packets);
+ tx_packets += (u32)(fwd_tx_packets -
+ dev->qos_stats[channel].fwd_tx_packets);
_bstats_update(opt->stats.bstats, 0, tx_packets);
- dev->cpu_tx_packets = cpu_tx_packets;
- dev->fwd_tx_packets = fwd_tx_packets;
+ dev->qos_stats[channel].cpu_tx_packets = cpu_tx_packets;
+ dev->qos_stats[channel].fwd_tx_packets = fwd_tx_packets;
return 0;
}
@@ -2747,16 +2842,18 @@ static int airoha_qdma_set_tx_rate_limit(struct net_device *netdev,
u32 bucket_size)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_qdma *qdma;
int i, err;
+ qdma = airoha_qdma_deref(dev);
for (i = 0; i <= TRTCM_PEAK_MODE; i++) {
- err = airoha_qdma_set_trtcm_config(dev->qdma, channel,
+ err = airoha_qdma_set_trtcm_config(qdma, channel,
REG_EGRESS_TRTCM_CFG, i,
!!rate, TRTCM_METER_MODE);
if (err)
return err;
- err = airoha_qdma_set_trtcm_token_bucket(dev->qdma, channel,
+ err = airoha_qdma_set_trtcm_token_bucket(qdma, channel,
REG_EGRESS_TRTCM_CFG,
i, rate, bucket_size);
if (err)
@@ -2792,11 +2889,12 @@ static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev,
u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
int err, num_tx_queues = AIROHA_NUM_TX_RING + channel + 1;
struct airoha_gdm_dev *dev = netdev_priv(netdev);
- struct airoha_qdma *qdma = dev->qdma;
+ struct airoha_qdma *qdma;
/* Here we need to check the requested QDMA channel is not already
* in use by another net_device running on the same QDMA block.
*/
+ qdma = airoha_qdma_deref(dev);
if (test_and_set_bit(channel, qdma->qos_channel_map)) {
NL_SET_ERR_MSG_MOD(opt->extack,
"qdma qos channel already in use");
@@ -2832,7 +2930,7 @@ static int airoha_qdma_set_rx_meter(struct airoha_gdm_dev *dev,
u32 rate, u32 bucket_size,
enum trtcm_unit_type unit_type)
{
- struct airoha_qdma *qdma = dev->qdma;
+ struct airoha_qdma *qdma = airoha_qdma_deref(dev);
int i;
for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
@@ -3007,10 +3105,11 @@ static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
int num_tx_queues = AIROHA_NUM_TX_RING;
- struct airoha_qdma *qdma = dev->qdma;
+ struct airoha_qdma *qdma;
airoha_qdma_set_tx_rate_limit(netdev, queue, 0, 0);
+ qdma = airoha_qdma_deref(dev);
clear_bit(queue, qdma->qos_channel_map);
clear_bit(queue, dev->qos_sq_bmap);
@@ -3036,6 +3135,98 @@ static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev,
return 0;
}
+static void airoha_disable_qos_for_gdm34(struct net_device *netdev)
+{
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
+ int err;
+
+ if (port->id != AIROHA_GDM3_IDX &&
+ port->id != AIROHA_GDM4_IDX)
+ return;
+
+ err = airoha_disable_gdm2_loopback(dev);
+ if (err)
+ netdev_warn(netdev,
+ "failed disabling GDM2 loopback: %d\n", err);
+
+ dev->flags &= ~AIROHA_DEV_F_WAN;
+ airoha_dev_set_qdma(dev);
+
+ airoha_set_macaddr(dev, netdev->dev_addr);
+ airoha_ppe_set_xmit_frame_size(dev);
+
+ if (netif_running(netdev))
+ airoha_set_gdm_port_fwd_cfg(dev->eth,
+ REG_GDM_FWD_CFG(port->id),
+ FE_PSE_PORT_PPE1);
+}
+
+static int airoha_enable_qos_for_gdm34(struct net_device *netdev,
+ struct netlink_ext_ack *extack)
+{
+ struct airoha_gdm_dev *wan_dev, *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
+ struct airoha_eth *eth = dev->eth;
+ int err = -EBUSY;
+
+ if (port->id != AIROHA_GDM3_IDX &&
+ port->id != AIROHA_GDM4_IDX) {
+ /* HW QoS is always supported by GDM1 and GDM2 */
+ return 0;
+ }
+
+ if (!airoha_is_lan_gdm_dev(dev)) /* Already enabled */
+ return 0;
+
+ mutex_lock(&flow_offload_mutex);
+
+ wan_dev = airoha_get_wan_gdm_dev(eth);
+ if (wan_dev) {
+ if ((wan_dev->flags & AIROHA_DEV_F_TX_QOS) ||
+ wan_dev->port->id == AIROHA_GDM2_IDX) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "QoS configured for WAN device");
+ goto error_unlock;
+ }
+ airoha_disable_qos_for_gdm34(netdev_from_priv(wan_dev));
+ }
+
+ dev->flags |= AIROHA_DEV_F_WAN;
+ airoha_dev_set_qdma(dev);
+ err = airoha_enable_gdm2_loopback(dev);
+ if (err)
+ goto error_disable_wan;
+
+ err = airoha_set_macaddr(dev, netdev->dev_addr);
+ if (err)
+ goto error_disable_loopback;
+
+ airoha_dev_set_xmit_frame_size(netdev);
+ if (netif_running(netdev)) {
+ u32 pse_port;
+
+ pse_port = airoha_ppe_is_enabled(eth, 1) ? FE_PSE_PORT_PPE2
+ : FE_PSE_PORT_PPE1;
+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id),
+ pse_port);
+ }
+
+ mutex_unlock(&flow_offload_mutex);
+
+ return 0;
+
+error_disable_loopback:
+ airoha_disable_gdm2_loopback(dev);
+error_disable_wan:
+ dev->flags &= ~AIROHA_DEV_F_WAN;
+ airoha_dev_set_qdma(dev);
+error_unlock:
+ mutex_unlock(&flow_offload_mutex);
+
+ return err;
+}
+
static int airoha_tc_htb_destroy(struct net_device *netdev)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
@@ -3044,6 +3235,8 @@ static int airoha_tc_htb_destroy(struct net_device *netdev)
for_each_set_bit(q, dev->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS)
airoha_tc_remove_htb_queue(netdev, q);
+ dev->flags &= ~AIROHA_DEV_F_TX_QOS;
+
return 0;
}
@@ -3063,24 +3256,33 @@ static int airoha_tc_get_htb_get_leaf_queue(struct net_device *netdev,
return 0;
}
-static int airoha_tc_setup_qdisc_htb(struct net_device *dev,
+static int airoha_tc_setup_qdisc_htb(struct net_device *netdev,
struct tc_htb_qopt_offload *opt)
{
switch (opt->command) {
- case TC_HTB_CREATE:
+ case TC_HTB_CREATE: {
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ int err;
+
+ err = airoha_enable_qos_for_gdm34(netdev, opt->extack);
+ if (err)
+ return err;
+
+ dev->flags |= AIROHA_DEV_F_TX_QOS;
break;
+ }
case TC_HTB_DESTROY:
- return airoha_tc_htb_destroy(dev);
+ return airoha_tc_htb_destroy(netdev);
case TC_HTB_NODE_MODIFY:
- return airoha_tc_htb_modify_queue(dev, opt);
+ return airoha_tc_htb_modify_queue(netdev, opt);
case TC_HTB_LEAF_ALLOC_QUEUE:
- return airoha_tc_htb_alloc_leaf_queue(dev, opt);
+ return airoha_tc_htb_alloc_leaf_queue(netdev, opt);
case TC_HTB_LEAF_DEL:
case TC_HTB_LEAF_DEL_LAST:
case TC_HTB_LEAF_DEL_LAST_FORCE:
- return airoha_tc_htb_delete_leaf_queue(dev, opt);
+ return airoha_tc_htb_delete_leaf_queue(netdev, opt);
case TC_HTB_LEAF_QUERY_QUEUE:
- return airoha_tc_get_htb_get_leaf_queue(dev, opt);
+ return airoha_tc_get_htb_get_leaf_queue(netdev, opt);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index f6d01a8e8da139..b43a08e937959d 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -543,19 +543,21 @@ struct airoha_qdma {
DECLARE_BITMAP(qos_channel_map, AIROHA_NUM_QOS_CHANNELS);
};
-enum airoha_priv_flags {
- AIROHA_PRIV_F_WAN = BIT(0),
+enum airoha_dev_flags {
+ AIROHA_DEV_F_WAN = BIT(0),
+ AIROHA_DEV_F_TX_QOS = BIT(1),
};
struct airoha_gdm_dev {
+ struct airoha_qdma __rcu *qdma;
struct airoha_gdm_port *port;
- struct airoha_qdma *qdma;
struct airoha_eth *eth;
DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS);
- /* qos stats counters */
- u64 cpu_tx_packets;
- u64 fwd_tx_packets;
+ struct {
+ u32 cpu_tx_packets;
+ u32 fwd_tx_packets;
+ } qos_stats[AIROHA_NUM_QOS_CHANNELS];
u32 flags;
int nbq;
@@ -667,7 +669,7 @@ static inline u16 airoha_qdma_get_txq(struct airoha_qdma *qdma, u16 qid)
static inline bool airoha_is_lan_gdm_dev(struct airoha_gdm_dev *dev)
{
- return !(dev->flags & AIROHA_PRIV_F_WAN);
+ return !(dev->flags & AIROHA_DEV_F_WAN);
}
static inline bool airoha_is_7581(struct airoha_eth *eth)
@@ -684,6 +686,16 @@ int airoha_get_fe_port(struct airoha_gdm_dev *dev);
bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
struct airoha_gdm_dev *dev);
+extern struct mutex flow_offload_mutex;
+
+static inline struct airoha_qdma *
+airoha_qdma_deref(struct airoha_gdm_dev *dev)
+{
+ return rcu_dereference_protected(dev->qdma,
+ lockdep_rtnl_is_held() ||
+ lockdep_is_held(&flow_offload_mutex));
+}
+
void airoha_ppe_set_xmit_frame_size(struct airoha_gdm_dev *dev);
void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport);
bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index);
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
index fdb973fc779c83..3ccdf9fccb4a12 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -15,7 +15,10 @@
#include "airoha_regs.h"
#include "airoha_eth.h"
-static DEFINE_MUTEX(flow_offload_mutex);
+/* Serialize airoha_gdm_dev flags, QDMA pointer and PPE CPU port
+ * configuration.
+ */
+DEFINE_MUTEX(flow_offload_mutex);
static DEFINE_SPINLOCK(ppe_lock);
static const struct rhashtable_params airoha_flow_table_params = {
@@ -86,8 +89,8 @@ static u32 airoha_ppe_get_timestamp(struct airoha_ppe *ppe)
void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport)
{
- struct airoha_qdma *qdma = dev->qdma;
- struct airoha_eth *eth = qdma->eth;
+ struct airoha_qdma *qdma = airoha_qdma_deref(dev);
+ struct airoha_eth *eth = dev->eth;
u8 qdma_id = qdma - ð->qdma[0];
u32 fe_cpu_port;
diff --git a/drivers/net/ethernet/airoha/airoha_regs.h b/drivers/net/ethernet/airoha/airoha_regs.h
index 6fed63d013b412..442b48c9b991ef 100644
--- a/drivers/net/ethernet/airoha/airoha_regs.h
+++ b/drivers/net/ethernet/airoha/airoha_regs.h
@@ -375,6 +375,7 @@
#define REG_SRC_PORT_FC_MAP6 0x2298
#define FC_ID_OF_SRC_PORT_MASK(_n) GENMASK(4 + ((_n) << 3), ((_n) << 3))
+#define FC_MAP6_DEF_VALUE 0x1b1a1918
#define REG_WAN_MTU0 0x2300
#define WAN_MTU1_MASK GENMASK(29, 16)
|
| 3/2 | 2026/07/23 22:38 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10637 output: 40 thoughts: 217 Thoughts: **Analyzing the Airoha Ethernet Driver Patch** Okay, so I've got a patch here that's touching the Airoha ethernet driver. Specifically, it's modifying `airoha_eth.c`, `airoha_eth.h`, `airoha_ppe.c`, and `airoha_regs.h`. My initial thought is to figure out what this code is actually *doing*. Looks like the changes involve RCU protection for the `dev->qdma` pointer, and the introduction of `airoha_enable_qos_for_gdm34` and `airoha_disable_qos_for_gdm34` functions. There's also some work being done on QoS stats, making them per-channel now, and some flag modifications. First, let's establish if it's functional code. Yes, it's clearly modifying the airoha ethernet driver. Great, we know what it does at a top level. Next, I need to know if this code is actually *reachable*. Is this a driver that's going to be probed, or is it specific to particular hardware? Since it's located in `drivers/net/ethernet/airoha/airoha_eth.c`, I'll need to check the `Kconfig` for the driver. This will help determine if it's tied to a specific architecture or if I can test it in a VM. That will give a clear picture of how practical it is. |
| 4/2 | 2026/07/23 22:38 | tool | grepper |
0mArgs:{
"Expression": "config NET_VENDOR_AIROHA",
"PathPrefix": "drivers/net/ethernet/airoha/Kconfig"
}Results: {
"Output": "drivers/net/ethernet/airoha/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/ethernet/airoha/Kconfig:2:config NET_VENDOR_AIROHA\ndrivers/net/ethernet/airoha/Kconfig-3-\tbool \"Airoha devices\"\n"
} |
| 5/2 | 2026/07/23 22:38 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11298 output: 37 thoughts: 11 Thoughts: Okay, let's dive into this. Here's how I'd approach this task, as if these were my internal thoughts: **Analyzing Driver Configuration** Alright, before making any assumptions or jumping to conclusions, I need to get my hands dirty. I'm going to *actually* examine the driver's configuration. I need to see the raw data, the exact parameters, the way it's been set up. No guesswork here – the config file holds the truth. This is the bedrock; this is where the *real* answers lie. Let's see what we are dealing with. Let's make sure our assumptions are correct. |
| 6/2 | 2026/07/23 22:39 | tool | grepper |
0mError:no matches Args: {
"Expression": "config NET_VENDOR_AIROHA",
"PathPrefix": "drivers/net/ethernet/Kconfig"
}Results: {
"error": "no matches"
} |
| 7/2 | 2026/07/23 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11497 output: 39 thoughts: 24 Thoughts: Here's my thought process, summarized as you requested: **Investigating Airoha Ethernet Driver Configuration** Okay, so I need to find the configuration options related to the Airoha Ethernet driver. My first instinct is to check the `Kconfig` file within the driver's directory. Based on my experience, I'd expect the driver's source code to reside under the `drivers/net/ethernet` path, and considering the keyword, `airoha`, it is likely in an `airoha` subdirectory. So, I'll start by searching for `airoha` within the `drivers/net/ethernet/airoha/Kconfig` file. This is where I would expect to find the relevant configuration options and dependencies. This search is the starting point for understanding how the Airoha Ethernet driver is configured in this project. |
| 8/2 | 2026/07/23 22:39 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/airoha/Kconfig",
"FirstLine": 1,
"LineCount": 100
}Results: {
"Contents": " 1:\t# SPDX-License-Identifier: GPL-2.0-only\n 2:\tconfig NET_VENDOR_AIROHA\n 3:\t\tbool \"Airoha devices\"\n 4:\t\tdepends on ARCH_AIROHA || COMPILE_TEST\n 5:\t\thelp\n 6:\t\t If you have a Airoha SoC with ethernet, say Y.\n 7:\t\n 8:\tif NET_VENDOR_AIROHA\n 9:\t\n 10:\tconfig NET_AIROHA_NPU\n 11:\t\ttristate \"Airoha NPU support\"\n 12:\t\tselect WANT_DEV_COREDUMP\n 13:\t\tselect REGMAP_MMIO\n 14:\t\thelp\n 15:\t\t This driver supports Airoha Network Processor (NPU) available\n 16:\t\t on the Airoha Soc family.\n 17:\t\n 18:\tconfig NET_AIROHA\n 19:\t\ttristate \"Airoha SoC Gigabit Ethernet support\"\n 20:\t\tdepends on NET_DSA || !NET_DSA\n 21:\t\tselect NET_AIROHA_NPU\n 22:\t\tselect PAGE_POOL\n 23:\t\thelp\n 24:\t\t This driver supports the gigabit ethernet MACs in the\n 25:\t\t Airoha SoC family.\n 26:\t\n 27:\tconfig NET_AIROHA_FLOW_STATS\n 28:\t\tdefault y\n 29:\t\tbool \"Airoha flow stats\"\n 30:\t\tdepends on NET_AIROHA \u0026\u0026 NET_AIROHA_NPU\n 31:\t\thelp\n 32:\t\t Enable Airoha flowtable statistic counters.\n 33:\t\n 34:\tendif #NET_VENDOR_AIROHA\n"
} |
| 9/2 | 2026/07/23 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12188 output: 41 thoughts: 81 Thoughts: **Analyzing the Airoha Driver Dependency** Okay, so I'm looking at this driver, `NET_AIROHA`. The configuration suggests it relies on either `ARCH_AIROHA` or `COMPILE_TEST`. Hmm, a quick re-read… hang on, the more general `NET_VENDOR_AIROHA` seems to depend on the same conditional, `ARCH_AIROHA || COMPILE_TEST`. That's a little less specific, but potentially important. Now, I need to figure out if this is a platform driver. That's usually the giveaway for Airoha-specific hardware interactions. I'll need to check the source file, which I'm assuming is `airoha_eth.c`. My instinct is to look for something like `module_platform_driver` or something similarly named. I need to see how it's interfacing with the hardware directly. Time to dive into the code. |
| 10/2 | 2026/07/23 22:39 | tool | grepper |
0mArgs:{
"Expression": "module_platform_driver",
"PathPrefix": "drivers/net/ethernet/airoha/airoha_eth.c"
}Results: {
"Output": "drivers/net/ethernet/airoha/airoha_eth.c=3921=static struct platform_driver airoha_driver = {\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-3928-};\ndrivers/net/ethernet/airoha/airoha_eth.c:3929:module_platform_driver(airoha_driver);\ndrivers/net/ethernet/airoha/airoha_eth.c-3930-\n"
} |
| 11/2 | 2026/07/23 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12639 output: 24 thoughts: 177 Thoughts: **Analyzing the Reachability of This Platform Driver** Okay, so I'm looking at this driver and it's flagged as a platform driver. My immediate thought is, can I even get this thing to probe within a virtual machine environment? Platform drivers for very specific System-on-Chips, like this one, often require a Device Tree node or some kind of virtual device instantiation to even become active. Wait a second, though…syzkaller *can* sometimes instantiate platform devices. I recall seeing functions like `syz_deviced_add` (or something similar). But that typically becomes complicated unless there's a predefined pseudo-device setup, or if we're dealing with something standardized like PCI or USB. I do remember syzkaller having the capability to fuzz platform devices. It can inject Device Tree nodes or use `platform_device_register`. But, and this is the crux, if this driver is purely hardware-dependent for this specific SoC – `ARCH_AIROHA` – then it's *highly* unlikely to be reachable in the standard x86 VM environments I usually work in, unless someone's explicitly mocked it. So, the next logical step is to quickly check if syzkaller has a pre-existing description or test case targeting this `airoha` architecture or anything related to it. That's the key to figuring out if I can get at this thing without serious mocking. |
| 12/2 | 2026/07/23 22:39 | tool | grepper |
0mError:no matches Args: {
"Expression": "airoha",
"PathPrefix": "sys/"
}Results: {
"error": "no matches"
} |
| 13/2 | 2026/07/23 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13152 output: 34 thoughts: 203 Thoughts: **Analyzing the Prompt's Constraints** Okay, so the prompt is laying down some pretty specific ground rules. It's telling me, explicitly, that I *can't* use this tool to go digging through syzkaller syzlang descriptions. It makes sense; those are pseudo-syscalls, not something directly reflected in the kernel itself. And it seems like I'm supposed to use a different tool to read the descriptions, but there's no mention of that tool in my list. Now, the prompt shifts gears and mentions unreachable code paths in virtualized environments. It's pointing out that even with software-emulated hardware, certain drivers are essentially impossible to hit. Thinking about this, a platform driver for `ARCH_AIROHA` immediately sets off alarm bells. Unless there's some incredibly niche software emulation for this specific SoC's ethernet, it's highly improbable to trigger that code in any standard virtualization setup, like GCE or QEMU. That is, unless it's a PCI device or something else that can be made to run in virtualized hardware. Let's make sure it's not before making any assumptions. |
| 14/2 | 2026/07/23 22:39 | tool | grepper |
0mError:no matches Args: {
"Expression": "pci_driver",
"PathPrefix": "drivers/net/ethernet/airoha/"
}Results: {
"error": "no matches"
} |
| 15/2 | 2026/07/23 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13647 output: 35 thoughts: 20 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience: **Analyzing the System Architecture** Alright, so we're looking at something that seems to be a platform driver. That's a good starting point. My initial thought process is always to confirm the underlying structure and ensure I'm getting the right context. Given that it appears to be a platform driver, I need to know the specific device this driver's designed to manage. Therefore, the logical first step is to quickly examine the `of_match_table`. That table holds the keys to understanding how this driver identifies and binds to the target hardware based on the device tree bindings. I'm going to quickly look there and verify that the bindings are as expected, and that the device IDs match the actual hardware. I'll focus on how it matches the compatible strings or any other identifying data in the DT node. |
| 16/2 | 2026/07/23 22:39 | tool | grepper |
0mArgs:{
"Expression": "of_match_table",
"PathPrefix": "drivers/net/ethernet/airoha/"
}Results: {
"Output": "drivers/net/ethernet/airoha/airoha_eth.c=3921=static struct platform_driver airoha_driver = {\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-3925-\t\t.name = KBUILD_MODNAME,\ndrivers/net/ethernet/airoha/airoha_eth.c:3926:\t\t.of_match_table = of_airoha_match,\ndrivers/net/ethernet/airoha/airoha_eth.c-3927-\t},\n--\ndrivers/net/ethernet/airoha/airoha_npu.c=813=static struct platform_driver airoha_npu_driver = {\n--\ndrivers/net/ethernet/airoha/airoha_npu.c-817-\t\t.name = \"airoha-npu\",\ndrivers/net/ethernet/airoha/airoha_npu.c:818:\t\t.of_match_table = of_airoha_npu_match,\ndrivers/net/ethernet/airoha/airoha_npu.c-819-\t},\n"
} |
| 17/2 | 2026/07/23 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 14177 output: 100 thoughts: 469 Thoughts: **WorthFuzzing Assessment: Airoha SoC Ethernet Driver** Okay, let's break this down. First, it's an Airoha SoC Gigabit Ethernet driver – that means it's inherently tied to specific hardware. It directly interacts with Memory-Mapped I/O (MMIO) registers, which are unique to that Airoha SoC. Without the exact hardware, or a precise emulation, the driver's `probe` function is going to fail hard when it tries to access those registers or request interrupts. Even if we somehow manage to get the platform device instantiated, it's a dead end. I know syzkaller has some tricks with faking device tree nodes and `ioremap` to fuzz platform drivers, but this is a *very* specific SoC driver. I don't see it being supported out of the box. Frankly, we don't usually bother fuzzing SoC-specific ethernet drivers unless there's a good reason, or we're on the *actual* hardware. Ah, right, the prompt. It explicitly says to return `WorthFuzzing=false` if the code paths are unreachable in virtualized environments like QEMU or GCE, even with software emulation. This is a clear case. It's a platform driver for Airoha SoCs. It's not reachable in a standard QEMU or GCE environment without bespoke hardware emulation, which I highly doubt exists. Time to double-check, but I'm not optimistic. Okay, just to be sure, let's eliminate the possibility of some generic netlink interface or something similar that could be accessed *before* the device is probed. Looking at the code modifications: `airoha_dev_open`, `airoha_dev_stop`, `airoha_dev_xmit`, `airoha_tc_setup_qdisc_htb`. These are all `net_device_ops` or `tc` offload callbacks, right? They all need a `net_device` to be registered. And where's the `net_device` registered? In the `probe` function of the platform driver. So, no successful probe, no `net_device`, no reachable functions. It's all tightly coupled to that hardware-specific `probe` path. Therefore, this patch is a definite `WorthFuzzing=false`. It's simply not reachable in a typical virtualized environment. |
| 18/2 | 2026/07/23 22:39 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch modifies the Airoha SoC Gigabit Ethernet driver (drivers/net/ethernet/airoha/). This is a hardware-specific platform driver that requires specific Airoha SoC hardware (MMIO registers, IRQs) to probe successfully. It cannot be reached or tested in standard virtualized environments like QEMU or GCE.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies the Airoha SoC Gigabit Ethernet driver (drivers/net/ethernet/airoha/). This is a hardware-specific platform driver that requires specific Airoha SoC hardware (MMIO registers, IRQs) to probe successfully. It cannot be reached or tested in standard virtualized environments like QEMU or GCE.",
"WorthFuzzing": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|