| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/10/12 09:08 | flow | patch-triage |
1mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"KMSANReasoning": "",
"NeedsKMSAN": false,
"Reasoning": "The patch modifies the Broadcom GENET Ethernet driver (drivers/net/ethernet/broadcom/genet/), which is a platform driver for built-in Ethernet MACs on Broadcom SoCs (such as BCM7xxx and BCM2711). This requires specific physical SoC hardware that is not present or emulated in standard virtualized environments (QEMU/GCE) on the target architecture (amd64). Thus, the modified code is structurally unreachable.",
"WorthFuzzing": false
} |
| 1/1 | 2026/10/12 09:08 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit b3a7994340884adb45fea44664e9afaa661d4312\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Mon Oct 12 09:08:09 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c\nindex 4c9db2f9fc25f..6455519e81beb 100644\n--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c\n+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c\n@@ -48,17 +48,44 @@\n #define GENET_Q0_TX_BD_CNT\t\\\n \t(TOTAL_DESC - priv-\u003ehw_params-\u003etx_queues * priv-\u003ehw_params-\u003etx_bds_per_q)\n \n-#define RX_BUF_LENGTH\t\t2048\n #define SKB_ALIGNMENT\t\t32\n \n+/* RBUF and TBUF hand a frame to the DMA once the threshold is reached. Both\n+ * registers are 8 bit in units of 16 bytes and want a multiple of the 256\n+ * byte burst size, so 0xf0 is the largest usable value.\n+ */\n+#define ENET_THLD_UNIT\t\t16\n+#define ENET_THLD_BURST\t\t256\n+#define ENET_THLD_DEFAULT\t0x80\n+#define ENET_THLD_MAX\t\t0xf0\n+\n+/* A frame ending just past the transmit threshold stops the transmitter once\n+ * a shorter frame follows, so pad frames that land there this far past it.\n+ */\n+#define ENET_TX_SAFE_MARGIN\t64\n+\n /* Page pool RX buffer layout:\n * RSB(64) + pad(2) | frame data | skb_shared_info\n- * The HW writes the 64B RSB + 2B alignment padding before the frame.\n+ * The HW writes the 64B RSB before every descriptor of a frame. Only the\n+ * first one also gets the 2B alignment padding.\n */\n-#define GENET_RSB_PAD\t\t(sizeof(struct status_64) + 2)\n+#define GENET_RBUF_ALIGN\t2\n+#define GENET_RSB_PAD\t\t(sizeof(struct status_64) + GENET_RBUF_ALIGN)\n \n-/* RX buffer plus the skb_shared_info napi_build_skb() places behind it */\n-#define GENET_RX_BUF_SIZE\tSKB_HEAD_ALIGN(RX_BUF_LENGTH)\n+/* A descriptor never spans more than one page, which also holds\n+ * skb_shared_info behind the frame, so on 4K pages the page bounds the\n+ * threshold before the register does. Larger pages fit several descriptors.\n+ */\n+#define ENET_SHINFO_LEN\t\tSKB_DATA_ALIGN(sizeof(struct skb_shared_info))\n+#define ENET_THLD_PAGE_LEN\tround_down(PAGE_SIZE - ENET_SHINFO_LEN - \\\n+\t\t\t\t\t sizeof(struct status_64), \\\n+\t\t\t\t\t ENET_THLD_BURST)\n+#define ENET_THLD_MAX_LEN\tmin_t(unsigned int, \\\n+\t\t\t\t ENET_THLD_MAX * ENET_THLD_UNIT, \\\n+\t\t\t\t ENET_THLD_PAGE_LEN)\n+\n+/* UMAC_MAX_FRAME_LEN is 14 bits wide and counts the FCS */\n+#define ENET_MAX_JUMBO_MTU\t(GENMASK(13, 0) - ENET_FRAME_OVERHEAD)\n \n /* Tx/Rx DMA register offset, skip 256 descriptors */\n #define WORDS_PER_BD(p)\t\t(p-\u003ehw_params-\u003ewords_per_bd)\n@@ -2119,6 +2146,15 @@ static void bcmgenet_hide_tsb(struct sk_buff *skb)\n \t__skb_pull(skb, sizeof(struct status_64));\n }\n \n+static void bcmgenet_tx_kick(struct bcmgenet_priv *priv,\n+\t\t\t struct bcmgenet_tx_ring *ring,\n+\t\t\t struct netdev_queue *txq)\n+{\n+\tif (!netdev_xmit_more() || netif_xmit_stopped(txq))\n+\t\tbcmgenet_tdma_ring_writel(priv, ring-\u003eindex,\n+\t\t\t\t\t ring-\u003eprod_index, TDMA_PROD_INDEX);\n+}\n+\n static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)\n {\n \tstruct bcmgenet_priv *priv = netdev_priv(dev);\n@@ -2148,6 +2184,42 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)\n \t\tgoto out;\n \t}\n \n+\t/* Both paths below write to the frame, which ether_setup() lets the\n+\t * stack share. Match their conditions so nothing else is copied.\n+\t */\n+\tif (unlikely(skb-\u003elen \u003e priv-\u003etx_thld_len \u0026\u0026\n+\t\t (skb-\u003eip_summed == CHECKSUM_PARTIAL ||\n+\t\t skb-\u003elen \u003c priv-\u003etx_thld_len + ENET_TX_SAFE_MARGIN))) {\n+\t\tskb = skb_share_check(skb, GFP_ATOMIC);\n+\t\tif (!skb) {\n+\t\t\tBCMGENET_STATS64_INC((\u0026ring-\u003estats64), dropped);\n+\t\t\tgoto drop;\n+\t\t}\n+\t}\n+\n+\t/* The MAC holds a frame to insert its checksum, but only as much as\n+\t * its FIFO takes. Longer frames are dropped silently.\n+\t */\n+\tif (unlikely(skb-\u003elen \u003e priv-\u003etx_thld_len) \u0026\u0026\n+\t skb-\u003eip_summed == CHECKSUM_PARTIAL) {\n+\t\tif (skb_checksum_help(skb)) {\n+\t\t\tBCMGENET_STATS64_INC((\u0026ring-\u003estats64), dropped);\n+\t\t\tdev_kfree_skb_any(skb);\n+\t\t\tgoto drop;\n+\t\t}\n+\t}\n+\n+\t/* Keep the frame out of the window just past the threshold */\n+\tif (unlikely(skb-\u003elen \u003e priv-\u003etx_thld_len \u0026\u0026\n+\t\t skb-\u003elen \u003c priv-\u003etx_thld_len + ENET_TX_SAFE_MARGIN)) {\n+\t\tif (skb_put_padto(skb, priv-\u003etx_thld_len + ENET_TX_SAFE_MARGIN)) {\n+\t\t\tBCMGENET_STATS64_INC((\u0026ring-\u003estats64), dropped);\n+\t\t\tgoto drop;\n+\t\t}\n+\t}\n+\n+\tnr_frags = skb_shinfo(skb)-\u003enr_frags;\n+\n \t/* Retain how many bytes will be sent on the wire, without TSB inserted\n \t * by transmit checksum offload\n \t */\n@@ -2155,10 +2227,8 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)\n \n \t/* add the Transmit Status Block */\n \tskb = bcmgenet_add_tsb(dev, skb, ring);\n-\tif (!skb) {\n-\t\tret = NETDEV_TX_OK;\n-\t\tgoto out;\n-\t}\n+\tif (!skb)\n+\t\tgoto drop;\n \n \tfor (i = 0; i \u003c= nr_frags; i++) {\n \t\ttx_cb_ptr = bcmgenet_get_txcb(priv, ring);\n@@ -2183,7 +2253,6 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)\n \t\tif (ret) {\n \t\t\tpriv-\u003emib.tx_dma_failed++;\n \t\t\tnetif_err(priv, tx_err, dev, \"Tx DMA map failed\\n\");\n-\t\t\tret = NETDEV_TX_OK;\n \t\t\tgoto out_unmap_frags;\n \t\t}\n \t\tdma_unmap_addr_set(tx_cb_ptr, dma_addr, mapping);\n@@ -2225,10 +2294,7 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)\n \tif (ring-\u003efree_bds \u003c= (MAX_SKB_FRAGS + 1))\n \t\tnetif_tx_stop_queue(txq);\n \n-\tif (!netdev_xmit_more() || netif_xmit_stopped(txq))\n-\t\t/* Packets are ready, update producer index */\n-\t\tbcmgenet_tdma_ring_writel(priv, ring-\u003eindex,\n-\t\t\t\t\t ring-\u003eprod_index, TDMA_PROD_INDEX);\n+\tbcmgenet_tx_kick(priv, ring, txq);\n out:\n \tspin_unlock(\u0026ring-\u003elock);\n \n@@ -2245,6 +2311,10 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)\n \t}\n \n \tdev_kfree_skb(skb);\n+drop:\n+\t/* The dropped frame may have been the last one of the batch */\n+\tbcmgenet_tx_kick(priv, ring, txq);\n+\tret = NETDEV_TX_OK;\n \tgoto out;\n }\n \n@@ -2252,7 +2322,7 @@ static int bcmgenet_rx_refill(struct bcmgenet_rx_ring *ring,\n \t\t\t struct enet_cb *cb)\n {\n \tstruct bcmgenet_priv *priv = ring-\u003epriv;\n-\tunsigned int size = GENET_RX_BUF_SIZE;\n+\tunsigned int size = SKB_HEAD_ALIGN(priv-\u003erx_buf_len);\n \tunsigned int offset;\n \tdma_addr_t mapping;\n \tstruct page *page;\n@@ -2267,7 +2337,7 @@ static int bcmgenet_rx_refill(struct bcmgenet_rx_ring *ring,\n \n \t/* page_pool handles DMA mapping via PP_FLAG_DMA_MAP */\n \tmapping = page_pool_get_dma_addr(page) + offset;\n-\tdma_sync_single_for_device(\u0026priv-\u003epdev-\u003edev, mapping, RX_BUF_LENGTH,\n+\tdma_sync_single_for_device(\u0026priv-\u003epdev-\u003edev, mapping, priv-\u003erx_buf_len,\n \t\t\t\t DMA_FROM_DEVICE);\n \n \tcb-\u003erx_page = page;\n@@ -2278,6 +2348,54 @@ static int bcmgenet_rx_refill(struct bcmgenet_rx_ring *ring,\n \treturn 0;\n }\n \n+/* Drop the frame being collected. Its remaining descriptors carry no SOP,\n+ * so they are dropped quietly until the next one does.\n+ */\n+static void bcmgenet_discard_frags(struct bcmgenet_rx_ring *ring)\n+{\n+\tring-\u003efrag_drop = true;\n+\n+\tif (!ring-\u003efrag_head)\n+\t\treturn;\n+\n+\tdev_kfree_skb_any(ring-\u003efrag_head);\n+\tring-\u003efrag_head = NULL;\n+}\n+\n+/* A frame longer than the threshold arrives in several descriptors, each with\n+ * its own status block. Only the first one carries a header, so hand the page\n+ * of every later one to the frame already being collected. Returns the frame\n+ * once EOP is in, NULL while more descriptors are expected or once the frame\n+ * had to be dropped.\n+ */\n+static struct sk_buff *bcmgenet_add_frag(struct bcmgenet_rx_ring *ring,\n+\t\t\t\t\t struct page *page,\n+\t\t\t\t\t unsigned int offset,\n+\t\t\t\t\t unsigned int size,\n+\t\t\t\t\t unsigned int dma_flag,\n+\t\t\t\t\t unsigned int len)\n+{\n+\tstruct sk_buff *head = ring-\u003efrag_head;\n+\n+\tif (unlikely(skb_shinfo(head)-\u003enr_frags \u003e= MAX_SKB_FRAGS)) {\n+\t\tBCMGENET_STATS64_INC((\u0026ring-\u003estats64), fragmented_errors);\n+\t\tbcmgenet_discard_frags(ring);\n+\t\tpage_pool_put_full_page(ring-\u003epage_pool, page, true);\n+\t\treturn NULL;\n+\t}\n+\n+\tskb_add_rx_frag(head, skb_shinfo(head)-\u003enr_frags, page,\n+\t\t\toffset + sizeof(struct status_64),\n+\t\t\tlen - sizeof(struct status_64), size);\n+\n+\tif (!(dma_flag \u0026 DMA_EOP))\n+\t\treturn NULL;\n+\n+\tring-\u003efrag_head = NULL;\n+\n+\treturn head;\n+}\n+\n /* bcmgenet_desc_rx - descriptor based rx process.\n * this could be called from bottom half, or from NAPI polling method.\n */\n@@ -2295,6 +2413,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,\n \tunsigned int rxpktprocessed = 0, rxpkttoprocess;\n \tunsigned int bytes_processed = 0;\n \tunsigned int p_index, mask;\n+\tunsigned int rxframes = 0;\n \tunsigned int discards;\n \n \t/* Clear status before servicing to reduce spurious interrupts */\n@@ -2329,6 +2448,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,\n \t\tunsigned int rx_offset, rx_size;\n \t\tstruct status_64 *status;\n \t\tstruct page *rx_page;\n+\t\tunsigned int min_len;\n \t\tvoid *hard_start;\n \t\t__be16 rx_csum;\n \n@@ -2341,14 +2461,15 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,\n \n \t\tif (bcmgenet_rx_refill(ring, cb)) {\n \t\t\tBCMGENET_STATS64_INC(stats, dropped);\n+\t\t\tbcmgenet_discard_frags(ring);\n \t\t\tgoto next;\n \t\t}\n \n \t\t/* Sync the full buffer; the HW may have written anywhere\n-\t\t * up to RX_BUF_LENGTH.\n+\t\t * up to priv-\u003erx_buf_len.\n \t\t */\n \t\tpage_pool_dma_sync_for_cpu(ring-\u003epage_pool, rx_page, rx_offset,\n-\t\t\t\t\t RX_BUF_LENGTH);\n+\t\t\t\t\t priv-\u003erx_buf_len);\n \n \t\thard_start = page_address(rx_page) + rx_offset;\n \t\tstatus = (struct status_64 *)hard_start;\n@@ -2365,20 +2486,42 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,\n \t\t\t __func__, p_index, ring-\u003ec_index,\n \t\t\t ring-\u003eread_ptr, dma_length_status);\n \n+\t\t/* Only the first descriptor carries the alignment pad. A head\n+\t\t * with more to come must hold the Ethernet header, and a\n+\t\t * continuation must hold payload.\n+\t\t */\n+\t\tif (dma_flag \u0026 DMA_SOP) {\n+\t\t\tmin_len = GENET_RSB_PAD;\n+\t\t\tif (!(dma_flag \u0026 DMA_EOP))\n+\t\t\t\tmin_len += ETH_HLEN;\n+\t\t} else {\n+\t\t\tmin_len = sizeof(struct status_64) + 1;\n+\t\t}\n+\n \t\t/* Reject lengths that would underflow the SKB build path. */\n-\t\tif (unlikely(len \u003e RX_BUF_LENGTH || len \u003c GENET_RSB_PAD)) {\n+\t\tif (unlikely(len \u003e priv-\u003erx_buf_len || len \u003c min_len)) {\n \t\t\tnetif_err(priv, rx_status, dev,\n \t\t\t\t \"invalid packet length %d\\n\", len);\n \t\t\tBCMGENET_STATS64_INC(stats, length_errors);\n+\t\t\tbcmgenet_discard_frags(ring);\n \t\t\tpage_pool_put_full_page(ring-\u003epage_pool, rx_page,\n \t\t\t\t\t\ttrue);\n \t\t\tgoto next;\n \t\t}\n \n-\t\tif (unlikely(!(dma_flag \u0026 DMA_EOP) || !(dma_flag \u0026 DMA_SOP))) {\n-\t\t\tnetif_err(priv, rx_status, dev,\n-\t\t\t\t \"dropping fragmented packet!\\n\");\n-\t\t\tBCMGENET_STATS64_INC(stats, fragmented_errors);\n+\t\t/* A new SOP resynchronizes after an incomplete frame */\n+\t\tif (dma_flag \u0026 DMA_SOP) {\n+\t\t\tif (ring-\u003efrag_head) {\n+\t\t\t\tBCMGENET_STATS64_INC(stats, fragmented_errors);\n+\t\t\t\tbcmgenet_discard_frags(ring);\n+\t\t\t}\n+\t\t\tring-\u003efrag_drop = false;\n+\t\t} else if (unlikely(!ring-\u003efrag_head)) {\n+\t\t\t/* Rest of a dropped frame, or no SOP seen yet */\n+\t\t\tif (!ring-\u003efrag_drop) {\n+\t\t\t\tBCMGENET_STATS64_INC(stats, fragmented_errors);\n+\t\t\t\tring-\u003efrag_drop = true;\n+\t\t\t}\n \t\t\tpage_pool_put_full_page(ring-\u003epage_pool, rx_page,\n \t\t\t\t\t\ttrue);\n \t\t\tgoto next;\n@@ -2408,17 +2551,27 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,\n \t\t\t\t\t\tDMA_RX_RXER)) == DMA_RX_RXER)\n \t\t\t\tu64_stats_inc(\u0026stats-\u003eerrors);\n \t\t\tu64_stats_update_end(\u0026stats-\u003esyncp);\n+\t\t\tbcmgenet_discard_frags(ring);\n \t\t\tpage_pool_put_full_page(ring-\u003epage_pool, rx_page,\n \t\t\t\t\t\ttrue);\n \t\t\tgoto next;\n \t\t} /* error packet */\n \n+\t\tif (!(dma_flag \u0026 DMA_SOP)) {\n+\t\t\tskb = bcmgenet_add_frag(ring, rx_page, rx_offset,\n+\t\t\t\t\t\trx_size, dma_flag, len);\n+\t\t\tif (!skb)\n+\t\t\t\tgoto next;\n+\t\t\tgoto deliver;\n+\t\t}\n+\n \t\t/* Build SKB from the page - data starts at hard_start,\n \t\t * frame begins after RSB(64) + pad(2) = 66 bytes.\n \t\t */\n \t\tskb = napi_build_skb(hard_start, rx_size);\n \t\tif (unlikely(!skb)) {\n \t\t\tBCMGENET_STATS64_INC(stats, dropped);\n+\t\t\tbcmgenet_discard_frags(ring);\n \t\t\tpage_pool_put_full_page(ring-\u003epage_pool, rx_page,\n \t\t\t\t\t\ttrue);\n \t\t\tgoto next;\n@@ -2430,17 +2583,26 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,\n \t\tskb_reserve(skb, GENET_RSB_PAD);\n \t\t__skb_put(skb, len - GENET_RSB_PAD);\n \n-\t\tif (priv-\u003ecrc_fwd_en) {\n-\t\t\tskb_trim(skb, skb-\u003elen - ETH_FCS_LEN);\n+\t\tif (unlikely(!(dma_flag \u0026 DMA_EOP))) {\n+\t\t\tring-\u003efrag_head = skb;\n+\t\t\tgoto next;\n+\t\t}\n+\n+deliver:\n+\t\t/* The FCS trim may release the page with the last status block */\n+\t\trx_csum = (__force __be16)(status-\u003erx_csum \u0026 0xffff);\n+\n+\t\tif (priv-\u003ecrc_fwd_en \u0026\u0026\n+\t\t unlikely(pskb_trim(skb, skb-\u003elen - ETH_FCS_LEN))) {\n+\t\t\tBCMGENET_STATS64_INC(stats, dropped);\n+\t\t\tdev_kfree_skb_any(skb);\n+\t\t\tgoto next;\n \t\t}\n \n \t\t/* Set up checksum offload */\n-\t\tif (dev-\u003efeatures \u0026 NETIF_F_RXCSUM) {\n-\t\t\trx_csum = (__force __be16)(status-\u003erx_csum \u0026 0xffff);\n-\t\t\tif (rx_csum) {\n-\t\t\t\tskb-\u003ecsum = (__force __wsum)ntohs(rx_csum);\n-\t\t\t\tskb-\u003eip_summed = CHECKSUM_COMPLETE;\n-\t\t\t}\n+\t\tif ((dev-\u003efeatures \u0026 NETIF_F_RXCSUM) \u0026\u0026 rx_csum) {\n+\t\t\tskb-\u003ecsum = (__force __wsum)ntohs(rx_csum);\n+\t\t\tskb-\u003eip_summed = CHECKSUM_COMPLETE;\n \t\t}\n \n \t\tlen = skb-\u003elen;\n@@ -2448,6 +2610,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,\n \n \t\t/*Finish setting up the received SKB and send it to the kernel*/\n \t\tskb-\u003eprotocol = eth_type_trans(skb, priv-\u003edev);\n+\t\trxframes++;\n \n \t\tu64_stats_update_begin(\u0026stats-\u003esyncp);\n \t\tu64_stats_inc(\u0026stats-\u003epackets);\n@@ -2474,7 +2637,8 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,\n \t}\n \n \tring-\u003edim.bytes = bytes_processed;\n-\tring-\u003edim.packets = rxpktprocessed;\n+\t/* A long frame spans several descriptors but is one packet */\n+\tring-\u003edim.packets = rxframes;\n \n \treturn rxpktprocessed;\n }\n@@ -2548,6 +2712,8 @@ static void bcmgenet_free_rx_buffers(struct bcmgenet_priv *priv)\n \t\t\tcb = ring-\u003ecbs + i;\n \t\t\tbcmgenet_free_rx_cb(cb, ring-\u003epage_pool);\n \t\t}\n+\t\t/* a partial frame still holds pages of this pool */\n+\t\tbcmgenet_discard_frags(ring);\n \t}\n }\n \n@@ -2617,6 +2783,67 @@ static void bcmgenet_link_intr_enable(struct bcmgenet_priv *priv)\n \tbcmgenet_intrl2_0_writel(priv, int0_enable, INTRL2_CPU_MASK_CLEAR);\n }\n \n+/* Receive threshold in register units. Covers the alignment bytes and the\n+ * frame up to the register maximum, but not the status block, which the\n+ * hardware adds on top. A longer frame arrives in several descriptors.\n+ */\n+static unsigned int bcmgenet_pkt_rdy_thld(unsigned int mtu)\n+{\n+\tunsigned int len = GENET_RBUF_ALIGN + mtu + ETH_HLEN + VLAN_HLEN;\n+\n+\tlen = round_up(len, ENET_THLD_BURST) / ENET_THLD_UNIT;\n+\n+\t/* Keep the reset default for the common MTUs */\n+\treturn clamp_t(unsigned int, len, ENET_THLD_DEFAULT,\n+\t\t ENET_THLD_MAX_LEN / ENET_THLD_UNIT);\n+}\n+\n+/* Transmit threshold in register units. Frames landing in the window just\n+ * past it are padded clear of it, so pick a threshold that leaves room for\n+ * that padding inside the frame the MTU allows. Size the window against the\n+ * longest frame the MAC has to accept, since the tag count is not bounded.\n+ */\n+static unsigned int bcmgenet_tx_pkt_rdy_thld(unsigned int mtu)\n+{\n+\tunsigned int thld = ENET_THLD_MAX;\n+\n+\t/* Keep the reset value while the MTU has no use for more */\n+\tif (mtu \u003c= ETH_DATA_LEN)\n+\t\treturn ENET_THLD_DEFAULT;\n+\n+\twhile (thld \u003e ENET_THLD_DEFAULT \u0026\u0026\n+\t ENET_MAX_FRAME_LEN(mtu) - ETH_FCS_LEN \u003e thld * ENET_THLD_UNIT \u0026\u0026\n+\t thld * ENET_THLD_UNIT + ENET_TX_SAFE_MARGIN \u003e mtu + ETH_HLEN)\n+\t\tthld -= ENET_THLD_BURST / ENET_THLD_UNIT;\n+\n+\treturn thld;\n+}\n+\n+/* A buffer has to hold everything the threshold lets the hardware deliver */\n+static unsigned int bcmgenet_rx_buf_len(unsigned int mtu)\n+{\n+\treturn sizeof(struct status_64) +\n+\t bcmgenet_pkt_rdy_thld(mtu) * ENET_THLD_UNIT;\n+}\n+\n+/* Program the MTU dependent registers. Call with the MAC disabled. */\n+static void bcmgenet_set_mtu_regs(struct bcmgenet_priv *priv, unsigned int mtu)\n+{\n+\tu32 tx_thld = bcmgenet_tx_pkt_rdy_thld(mtu);\n+\tu32 thld = bcmgenet_pkt_rdy_thld(mtu);\n+\n+\tpriv-\u003etx_thld_len = tx_thld * ENET_THLD_UNIT;\n+\tbcmgenet_umac_writel(priv, ENET_MAC_FRAME_LEN(mtu), UMAC_MAX_FRAME_LEN);\n+\n+\t/* GENET v1 maps other registers at these offsets */\n+\tif (GENET_IS_V1(priv))\n+\t\treturn;\n+\n+\tbcmgenet_rbuf_writel(priv, thld, RBUF_PKT_RDY_THLD);\n+\tbcmgenet_writel(tx_thld, priv-\u003ebase + priv-\u003ehw_params-\u003etbuf_offset +\n+\t\t\tTBUF_PKT_RDY_THLD);\n+}\n+\n static void init_umac(struct bcmgenet_priv *priv)\n {\n \tstruct device *kdev = \u0026priv-\u003epdev-\u003edev;\n@@ -2633,7 +2860,7 @@ static void init_umac(struct bcmgenet_priv *priv)\n \t\t\t UMAC_MIB_CTRL);\n \tbcmgenet_umac_writel(priv, 0, UMAC_MIB_CTRL);\n \n-\tbcmgenet_umac_writel(priv, ENET_MAX_MTU_SIZE, UMAC_MAX_FRAME_LEN);\n+\tbcmgenet_set_mtu_regs(priv, priv-\u003edev-\u003emtu);\n \n \t/* init tx registers, enable TSB */\n \treg = bcmgenet_tbuf_ctrl_get(priv);\n@@ -2739,7 +2966,7 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,\n \n \t/* Set flow period for ring != 0 */\n \tif (index)\n-\t\tflow_period_val = ENET_MAX_MTU_SIZE \u003c\u003c 16;\n+\t\tflow_period_val = ENET_MAC_FRAME_LEN(priv-\u003edev-\u003emtu) \u003c\u003c 16;\n \n \tbcmgenet_tdma_ring_writel(priv, index, 0, TDMA_PROD_INDEX);\n \tbcmgenet_tdma_ring_writel(priv, index, 0, TDMA_CONS_INDEX);\n@@ -2749,7 +2976,7 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,\n \t\t\t\t TDMA_FLOW_PERIOD);\n \tbcmgenet_tdma_ring_writel(priv, index,\n \t\t\t\t ((size \u003c\u003c DMA_RING_SIZE_SHIFT) |\n-\t\t\t\t RX_BUF_LENGTH), DMA_RING_BUF_SIZE);\n+\t\t\t\t priv-\u003erx_buf_len), DMA_RING_BUF_SIZE);\n \n \t/* Set start and end address, read and write pointers */\n \tbcmgenet_tdma_ring_writel(priv, index, start_ptr * words_per_bd,\n@@ -2768,8 +2995,9 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,\n static int bcmgenet_rx_ring_create_pool(struct bcmgenet_priv *priv,\n \t\t\t\t\tstruct bcmgenet_rx_ring *ring)\n {\n-\t/* Buffers share a page. bcmgenet_rx_refill() syncs each one for the\n-\t * device, PP_FLAG_DMA_SYNC_DEV would sync the whole page.\n+\t/* Buffers may share a page, depending on PAGE_SIZE and the MTU.\n+\t * bcmgenet_rx_refill() syncs each one for the device,\n+\t * PP_FLAG_DMA_SYNC_DEV would sync the whole page.\n \t */\n \tstruct page_pool_params pp_params = {\n \t\t.order = 0,\n@@ -2832,7 +3060,7 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,\n \tbcmgenet_rdma_ring_writel(priv, index, 0, RDMA_CONS_INDEX);\n \tbcmgenet_rdma_ring_writel(priv, index,\n \t\t\t\t ((size \u003c\u003c DMA_RING_SIZE_SHIFT) |\n-\t\t\t\t RX_BUF_LENGTH), DMA_RING_BUF_SIZE);\n+\t\t\t\t priv-\u003erx_buf_len), DMA_RING_BUF_SIZE);\n \tbcmgenet_rdma_ring_writel(priv, index,\n \t\t\t\t (DMA_FC_THRESH_LO \u003c\u003c\n \t\t\t\t DMA_XOFF_THRESHOLD_SHIFT) |\n@@ -3046,8 +3274,12 @@ static int bcmgenet_init_rx_queues(struct net_device *dev)\n \t/* Initialize Rx priority queues */\n \tfor (i = 0; i \u003c= priv-\u003ehw_params-\u003erx_queues; i++) {\n \t\tret = bcmgenet_init_rx_ring(priv, i, end - start, start, end);\n-\t\tif (ret)\n+\t\tif (ret) {\n+\t\t\t/* Only the rings before this one hold a NAPI */\n+\t\t\twhile (i--)\n+\t\t\t\tnetif_napi_del(\u0026priv-\u003erx_rings[i].napi);\n \t\t\treturn ret;\n+\t\t}\n \n \t\tstart = end;\n \t\tend += priv-\u003ehw_params-\u003erx_bds_per_q;\n@@ -3348,7 +3580,7 @@ static void bcmgenet_get_hw_addr(struct bcmgenet_priv *priv,\n \tput_unaligned_be16(addr_tmp, \u0026addr[4]);\n }\n \n-static void bcmgenet_netif_start(struct net_device *dev)\n+static void bcmgenet_netif_start(struct net_device *dev, bool start_phy)\n {\n \tstruct bcmgenet_priv *priv = netdev_priv(dev);\n \n@@ -3365,7 +3597,8 @@ static void bcmgenet_netif_start(struct net_device *dev)\n \t/* Monitor link interrupts now */\n \tbcmgenet_link_intr_enable(priv);\n \n-\tphy_start(dev-\u003ephydev);\n+\tif (start_phy)\n+\t\tphy_start(dev-\u003ephydev);\n }\n \n static int bcmgenet_open(struct net_device *dev)\n@@ -3428,8 +3661,9 @@ static int bcmgenet_open(struct net_device *dev)\n \n \tbcmgenet_phy_pause_set(dev, priv-\u003erx_pause, priv-\u003etx_pause);\n \n-\tbcmgenet_netif_start(dev);\n+\tbcmgenet_netif_start(dev, true);\n \n+\tpriv-\u003edatapath_up = true;\n \tnetif_tx_start_all_queues(dev);\n \n \treturn 0;\n@@ -3488,7 +3722,11 @@ static int bcmgenet_close(struct net_device *dev)\n \n \tnetif_dbg(priv, ifdown, dev, \"bcmgenet_close\\n\");\n \n-\tbcmgenet_netif_stop(dev, false);\n+\t/* A failed MTU change can have torn the datapath down already */\n+\tif (priv-\u003edatapath_up) {\n+\t\tbcmgenet_netif_stop(dev, false);\n+\t\tpriv-\u003edatapath_up = false;\n+\t}\n \n \t/* Really kill the PHY state machine and disconnect from it */\n \tphy_disconnect(dev-\u003ephydev);\n@@ -3736,6 +3974,76 @@ static int bcmgenet_change_carrier(struct net_device *dev, bool new_carrier)\n \treturn 0;\n }\n \n+static int bcmgenet_change_mtu(struct net_device *dev, int new_mtu)\n+{\n+\tstruct bcmgenet_priv *priv = netdev_priv(dev);\n+\tunsigned int old_mtu = dev-\u003emtu;\n+\tint ret;\n+\n+\t/* Every MTU dependent value is floored at ETH_DATA_LEN, so a change\n+\t * below it reprograms nothing and must not cost queued frames.\n+\t */\n+\tif (!netif_running(dev) ||\n+\t max_t(unsigned int, old_mtu, ETH_DATA_LEN) ==\n+\t max_t(unsigned int, new_mtu, ETH_DATA_LEN)) {\n+\t\tWRITE_ONCE(dev-\u003emtu, new_mtu);\n+\t\tpriv-\u003erx_buf_len = bcmgenet_rx_buf_len(new_mtu);\n+\t\treturn 0;\n+\t}\n+\n+\t/* The watchdog trips on an idle queue once the rings are gone */\n+\tnetif_device_detach(dev);\n+\n+\t/* Only the buffers and the MTU registers change, leave the PHY up */\n+\tbcmgenet_netif_stop(dev, false);\n+\tpriv-\u003edatapath_up = false;\n+\n+\tWRITE_ONCE(dev-\u003emtu, new_mtu);\n+\tpriv-\u003erx_buf_len = bcmgenet_rx_buf_len(new_mtu);\n+\tbcmgenet_set_mtu_regs(priv, new_mtu);\n+\n+\tret = bcmgenet_init_dma(priv, true);\n+\tif (ret) {\n+\t\t/* Retry the size that was allocated a moment ago */\n+\t\tWRITE_ONCE(dev-\u003emtu, old_mtu);\n+\t\tpriv-\u003erx_buf_len = bcmgenet_rx_buf_len(old_mtu);\n+\t\tbcmgenet_set_mtu_regs(priv, old_mtu);\n+\t\tif (bcmgenet_init_dma(priv, true)) {\n+\t\t\t/* Nothing left to run on. Take the interface down so\n+\t\t\t * that close and suspend do not tear it down twice.\n+\t\t\t */\n+\t\t\tnetdev_err(dev, \"failed to restore MTU %u, closing\\n\",\n+\t\t\t\t old_mtu);\n+\t\t\tnetif_close(dev);\n+\n+\t\t\t/* Mark the device present again, __dev_open()\n+\t\t\t * refuses a detached one. The queues stay stopped\n+\t\t\t * because the interface is down by now.\n+\t\t\t */\n+\t\t\tnetif_device_attach(dev);\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\tbcmgenet_hfb_restore(priv);\n+\tbcmgenet_netif_start(dev, false);\n+\n+\t/* bcmgenet_netif_start() only restores the link interrupt */\n+\tif (bcmgenet_has_mdio_intr(priv))\n+\t\tbcmgenet_intrl2_0_writel(priv, UMAC_IRQ_MDIO_EVENT,\n+\t\t\t\t\t INTRL2_CPU_MASK_CLEAR);\n+\n+\t/* A link event latched while the interrupts were off is gone. Internal\n+\t * PHYs on GENET v1-v4 are not polled, so resync the state machine.\n+\t */\n+\tphy_mac_interrupt(dev-\u003ephydev);\n+\n+\tpriv-\u003edatapath_up = true;\n+\tnetif_device_attach(dev);\n+\n+\treturn ret;\n+}\n+\n static const struct net_device_ops bcmgenet_netdev_ops = {\n \t.ndo_open\t\t= bcmgenet_open,\n \t.ndo_stop\t\t= bcmgenet_close,\n@@ -3747,6 +4055,7 @@ static const struct net_device_ops bcmgenet_netdev_ops = {\n \t.ndo_set_features\t= bcmgenet_set_features,\n \t.ndo_get_stats64\t= bcmgenet_get_stats64,\n \t.ndo_change_carrier\t= bcmgenet_change_carrier,\n+\t.ndo_change_mtu\t\t= bcmgenet_change_mtu,\n };\n \n /* GENET hardware parameters/characteristics */\n@@ -4100,6 +4409,11 @@ static int bcmgenet_probe(struct platform_device *pdev)\n \t/* Mii wait queue */\n \tinit_waitqueue_head(\u0026priv-\u003ewq);\n \tbcmgenet_hfb_init(priv);\n+\n+\t/* v1 cannot program the thresholds, so it stays at the default MTU */\n+\tpriv-\u003erx_buf_len = bcmgenet_rx_buf_len(dev-\u003emtu);\n+\tif (!GENET_IS_V1(priv))\n+\t\tdev-\u003emax_mtu = ENET_MAX_JUMBO_MTU;\n \tINIT_WORK(\u0026priv-\u003ebcmgenet_irq_work, bcmgenet_irq_task);\n \n \tpriv-\u003eclk_wol = devm_clk_get_optional(\u0026priv-\u003epdev-\u003edev, \"enet-wol\");\n@@ -4283,6 +4597,7 @@ static int bcmgenet_resume(struct device *d)\n \t\tbcmgenet_rdma_disable(priv);\n \t\tbcmgenet_intr_disable(priv);\n \t\tbcmgenet_fini_dma(priv);\n+\t\tpriv-\u003edatapath_up = false;\n \t\tenable_irq(priv-\u003eirq1);\n \t}\n \n@@ -4312,8 +4627,9 @@ static int bcmgenet_resume(struct device *d)\n \tif (!device_may_wakeup(d))\n \t\tphy_resume(dev-\u003ephydev);\n \n-\tbcmgenet_netif_start(dev);\n+\tbcmgenet_netif_start(dev, true);\n \n+\tpriv-\u003edatapath_up = true;\n \tnetif_device_attach(dev);\n \n \treturn 0;\n@@ -4375,6 +4691,7 @@ static int bcmgenet_suspend(struct device *d)\n \t} else {\n \t\t/* Teardown the interface */\n \t\tbcmgenet_netif_stop(dev, true);\n+\t\tpriv-\u003edatapath_up = false;\n \t}\n \n \treturn 0;\ndiff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h\nindex 86f2aed20dbe8..9c2c21081736a 100644\n--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h\n+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h\n@@ -28,13 +28,20 @@\n /* which ring is descriptor based */\n #define DESC_INDEX\t\t\t\t16\n \n-/* Body(1500) + EH_SIZE(14) + VLANTAG(4) + BRCMTAG(6) + FCS(4) = 1528.\n- * 1536 is multiple of 256 bytes\n- */\n #define ENET_BRCM_TAG_LEN\t6\n #define ENET_PAD\t\t8\n-#define ENET_MAX_MTU_SIZE\t(ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + \\\n-\t\t\t\t ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD)\n+\n+/* Longest frame the MAC must accept for a given MTU. ENET_PAD is slack the\n+ * driver has always carried, it rounded the default up to 1536 from 1528.\n+ */\n+#define ENET_FRAME_OVERHEAD\t(ETH_HLEN + VLAN_HLEN + ENET_BRCM_TAG_LEN + \\\n+\t\t\t\t ETH_FCS_LEN + ENET_PAD)\n+#define ENET_MAX_FRAME_LEN(mtu)\t((mtu) + ENET_FRAME_OVERHEAD)\n+\n+/* The MAC keeps accepting a standard frame below the default MTU */\n+#define ENET_MAC_FRAME_LEN(mtu)\tENET_MAX_FRAME_LEN(max_t(unsigned int, (mtu), \\\n+\t\t\t\t\t\t\tETH_DATA_LEN))\n+\n #define DMA_MAX_BURST_LENGTH 0x10\n \n /* misc. configuration */\n@@ -219,6 +226,8 @@ struct bcmgenet_rx_stats64 {\n #define RBUF_ALIGN_2B\t\t\t(1 \u003c\u003c 1)\n #define RBUF_BAD_DIS\t\t\t(1 \u003c\u003c 2)\n \n+#define RBUF_PKT_RDY_THLD\t\t0x08\n+\n #define RBUF_STATUS\t\t\t0x0C\n #define RBUF_STATUS_WOL\t\t(1 \u003c\u003c 0)\n #define RBUF_STATUS_MPD_INTR_ACTIVE\t(1 \u003c\u003c 1)\n@@ -249,6 +258,7 @@ struct bcmgenet_rx_stats64 {\n #define TBUF_CTRL\t\t\t0x00\n #define TBUF_64B_EN\t\t\t(1 \u003c\u003c 0)\n #define TBUF_BP_MC\t\t\t0x0C\n+#define TBUF_PKT_RDY_THLD\t\t0x10\n #define TBUF_ENERGY_CTRL\t\t0x14\n #define TBUF_EEE_EN\t\t\t(1 \u003c\u003c 0)\n #define TBUF_PM_EN\t\t\t(1 \u003c\u003c 1)\n@@ -575,6 +585,8 @@ struct bcmgenet_rx_ring {\n \tunsigned int\tcb_ptr;\t\t/* Rx ring initial CB ptr */\n \tunsigned int\tend_ptr;\t/* Rx ring end CB ptr */\n \tunsigned int\told_discards;\n+\tstruct sk_buff\t*frag_head;\t/* frame being reassembled */\n+\tbool\t\tfrag_drop;\t/* discarding until the next SOP */\n \tstruct bcmgenet_net_dim dim;\n \tu32\t\trx_max_coalesced_frames;\n \tu32\t\trx_coalesce_usecs;\n@@ -613,6 +625,8 @@ struct bcmgenet_priv {\n \tvoid __iomem *rx_bds;\n \tstruct enet_cb *rx_cbs;\n \tunsigned int num_rx_bds;\n+\tunsigned int rx_buf_len;\n+\tunsigned int tx_thld_len;\n \tstruct bcmgenet_rxnfc_rule rxnfc_rules[MAX_NUM_OF_FS_RULES];\n \tstruct list_head rxnfc_list;\n \n@@ -624,6 +638,7 @@ struct bcmgenet_priv {\n \tunsigned autoneg_pause:1;\n \tunsigned tx_pause:1;\n \tunsigned rx_pause:1;\n+\tunsigned datapath_up:1;\n \n \t/* MDIO bus variables */\n \twait_queue_head_t wq;\n"
} |
| 2/1 | 2026/10/12 09:08 | agent | patch-evaluator |
1mModel:core Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies the Broadcom GENET Ethernet driver (drivers/net/ethernet/broadcom/genet/), which is a platform driver for built-in Ethernet MACs on Broadcom SoCs (such as BCM7xxx and BCM2711). This requires specific physical SoC hardware that is not present or emulated in standard virtualized environments (QEMU/GCE) on the target architecture (amd64). Thus, the modified code is structurally unreachable.",
"WorthFuzzing": false
}Instruction: You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.
IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.
================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.
- REACHABILITY IS THE PRIMARY GATE:
Fuzzing can only discover bugs in code that can actually execute in standard virtualized
environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
regardless of whether it adds assertions or complex logic.
- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
Patch authors routinely label changes as "cleanups", "refactorings", or state
"No functional change intended". Do NOT take these claims at face value.
Code refactorings that rearrange logic, introduce helper functions, or alter state management
in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
If reachable executable code is modified or refactored, it MUST be fuzzed.
- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
Even if the author believes the invariant always holds, fuzzing is essential to verify whether
an unusual sequence of operations can violate it.
================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:
- Non-kernel and non-executable changes:
* Modifications to Documentation/, comments, or spelling fixes.
* User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
that do not affect the compiled kernel image (vmlinux) or kernel modules.
* Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
that do not alter control flow or data structures.
* Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
* Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
* Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
physical PCI hot-unplug or manual sysfs driver unbinding.
* Code paths exclusive to architectures other than the target architecture.
================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
* Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
* Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
* Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
* Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).
================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:
- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
Do NOT list generic, ubiquitous functions called by almost every program in the corpus
(including, but not limited to: general memory allocators and deallocators, page fault
and trap handlers, or core synchronization primitives; this is not an exhaustive list).
Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
which severely dilutes fuzzing effort away from the actual changes.
- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
List functions that specifically implement the logic being added or altered, or direct API entrypoints
for the subsystem feature under review.
- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).
================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any '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: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit b3a7994340884adb45fea44664e9afaa661d4312
Author: syz-cluster <triage@syzkaller.com>
Date: Mon Oct 12 09:08:09 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 4c9db2f9fc25f..6455519e81beb 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -48,17 +48,44 @@
#define GENET_Q0_TX_BD_CNT \
(TOTAL_DESC - priv->hw_params->tx_queues * priv->hw_params->tx_bds_per_q)
-#define RX_BUF_LENGTH 2048
#define SKB_ALIGNMENT 32
+/* RBUF and TBUF hand a frame to the DMA once the threshold is reached. Both
+ * registers are 8 bit in units of 16 bytes and want a multiple of the 256
+ * byte burst size, so 0xf0 is the largest usable value.
+ */
+#define ENET_THLD_UNIT 16
+#define ENET_THLD_BURST 256
+#define ENET_THLD_DEFAULT 0x80
+#define ENET_THLD_MAX 0xf0
+
+/* A frame ending just past the transmit threshold stops the transmitter once
+ * a shorter frame follows, so pad frames that land there this far past it.
+ */
+#define ENET_TX_SAFE_MARGIN 64
+
/* Page pool RX buffer layout:
* RSB(64) + pad(2) | frame data | skb_shared_info
- * The HW writes the 64B RSB + 2B alignment padding before the frame.
+ * The HW writes the 64B RSB before every descriptor of a frame. Only the
+ * first one also gets the 2B alignment padding.
*/
-#define GENET_RSB_PAD (sizeof(struct status_64) + 2)
+#define GENET_RBUF_ALIGN 2
+#define GENET_RSB_PAD (sizeof(struct status_64) + GENET_RBUF_ALIGN)
-/* RX buffer plus the skb_shared_info napi_build_skb() places behind it */
-#define GENET_RX_BUF_SIZE SKB_HEAD_ALIGN(RX_BUF_LENGTH)
+/* A descriptor never spans more than one page, which also holds
+ * skb_shared_info behind the frame, so on 4K pages the page bounds the
+ * threshold before the register does. Larger pages fit several descriptors.
+ */
+#define ENET_SHINFO_LEN SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
+#define ENET_THLD_PAGE_LEN round_down(PAGE_SIZE - ENET_SHINFO_LEN - \
+ sizeof(struct status_64), \
+ ENET_THLD_BURST)
+#define ENET_THLD_MAX_LEN min_t(unsigned int, \
+ ENET_THLD_MAX * ENET_THLD_UNIT, \
+ ENET_THLD_PAGE_LEN)
+
+/* UMAC_MAX_FRAME_LEN is 14 bits wide and counts the FCS */
+#define ENET_MAX_JUMBO_MTU (GENMASK(13, 0) - ENET_FRAME_OVERHEAD)
/* Tx/Rx DMA register offset, skip 256 descriptors */
#define WORDS_PER_BD(p) (p->hw_params->words_per_bd)
@@ -2119,6 +2146,15 @@ static void bcmgenet_hide_tsb(struct sk_buff *skb)
__skb_pull(skb, sizeof(struct status_64));
}
+static void bcmgenet_tx_kick(struct bcmgenet_priv *priv,
+ struct bcmgenet_tx_ring *ring,
+ struct netdev_queue *txq)
+{
+ if (!netdev_xmit_more() || netif_xmit_stopped(txq))
+ bcmgenet_tdma_ring_writel(priv, ring->index,
+ ring->prod_index, TDMA_PROD_INDEX);
+}
+
static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
@@ -2148,6 +2184,42 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
goto out;
}
+ /* Both paths below write to the frame, which ether_setup() lets the
+ * stack share. Match their conditions so nothing else is copied.
+ */
+ if (unlikely(skb->len > priv->tx_thld_len &&
+ (skb->ip_summed == CHECKSUM_PARTIAL ||
+ skb->len < priv->tx_thld_len + ENET_TX_SAFE_MARGIN))) {
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (!skb) {
+ BCMGENET_STATS64_INC((&ring->stats64), dropped);
+ goto drop;
+ }
+ }
+
+ /* The MAC holds a frame to insert its checksum, but only as much as
+ * its FIFO takes. Longer frames are dropped silently.
+ */
+ if (unlikely(skb->len > priv->tx_thld_len) &&
+ skb->ip_summed == CHECKSUM_PARTIAL) {
+ if (skb_checksum_help(skb)) {
+ BCMGENET_STATS64_INC((&ring->stats64), dropped);
+ dev_kfree_skb_any(skb);
+ goto drop;
+ }
+ }
+
+ /* Keep the frame out of the window just past the threshold */
+ if (unlikely(skb->len > priv->tx_thld_len &&
+ skb->len < priv->tx_thld_len + ENET_TX_SAFE_MARGIN)) {
+ if (skb_put_padto(skb, priv->tx_thld_len + ENET_TX_SAFE_MARGIN)) {
+ BCMGENET_STATS64_INC((&ring->stats64), dropped);
+ goto drop;
+ }
+ }
+
+ nr_frags = skb_shinfo(skb)->nr_frags;
+
/* Retain how many bytes will be sent on the wire, without TSB inserted
* by transmit checksum offload
*/
@@ -2155,10 +2227,8 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
/* add the Transmit Status Block */
skb = bcmgenet_add_tsb(dev, skb, ring);
- if (!skb) {
- ret = NETDEV_TX_OK;
- goto out;
- }
+ if (!skb)
+ goto drop;
for (i = 0; i <= nr_frags; i++) {
tx_cb_ptr = bcmgenet_get_txcb(priv, ring);
@@ -2183,7 +2253,6 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
if (ret) {
priv->mib.tx_dma_failed++;
netif_err(priv, tx_err, dev, "Tx DMA map failed\n");
- ret = NETDEV_TX_OK;
goto out_unmap_frags;
}
dma_unmap_addr_set(tx_cb_ptr, dma_addr, mapping);
@@ -2225,10 +2294,7 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
if (ring->free_bds <= (MAX_SKB_FRAGS + 1))
netif_tx_stop_queue(txq);
- if (!netdev_xmit_more() || netif_xmit_stopped(txq))
- /* Packets are ready, update producer index */
- bcmgenet_tdma_ring_writel(priv, ring->index,
- ring->prod_index, TDMA_PROD_INDEX);
+ bcmgenet_tx_kick(priv, ring, txq);
out:
spin_unlock(&ring->lock);
@@ -2245,6 +2311,10 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
}
dev_kfree_skb(skb);
+drop:
+ /* The dropped frame may have been the last one of the batch */
+ bcmgenet_tx_kick(priv, ring, txq);
+ ret = NETDEV_TX_OK;
goto out;
}
@@ -2252,7 +2322,7 @@ static int bcmgenet_rx_refill(struct bcmgenet_rx_ring *ring,
struct enet_cb *cb)
{
struct bcmgenet_priv *priv = ring->priv;
- unsigned int size = GENET_RX_BUF_SIZE;
+ unsigned int size = SKB_HEAD_ALIGN(priv->rx_buf_len);
unsigned int offset;
dma_addr_t mapping;
struct page *page;
@@ -2267,7 +2337,7 @@ static int bcmgenet_rx_refill(struct bcmgenet_rx_ring *ring,
/* page_pool handles DMA mapping via PP_FLAG_DMA_MAP */
mapping = page_pool_get_dma_addr(page) + offset;
- dma_sync_single_for_device(&priv->pdev->dev, mapping, RX_BUF_LENGTH,
+ dma_sync_single_for_device(&priv->pdev->dev, mapping, priv->rx_buf_len,
DMA_FROM_DEVICE);
cb->rx_page = page;
@@ -2278,6 +2348,54 @@ static int bcmgenet_rx_refill(struct bcmgenet_rx_ring *ring,
return 0;
}
+/* Drop the frame being collected. Its remaining descriptors carry no SOP,
+ * so they are dropped quietly until the next one does.
+ */
+static void bcmgenet_discard_frags(struct bcmgenet_rx_ring *ring)
+{
+ ring->frag_drop = true;
+
+ if (!ring->frag_head)
+ return;
+
+ dev_kfree_skb_any(ring->frag_head);
+ ring->frag_head = NULL;
+}
+
+/* A frame longer than the threshold arrives in several descriptors, each with
+ * its own status block. Only the first one carries a header, so hand the page
+ * of every later one to the frame already being collected. Returns the frame
+ * once EOP is in, NULL while more descriptors are expected or once the frame
+ * had to be dropped.
+ */
+static struct sk_buff *bcmgenet_add_frag(struct bcmgenet_rx_ring *ring,
+ struct page *page,
+ unsigned int offset,
+ unsigned int size,
+ unsigned int dma_flag,
+ unsigned int len)
+{
+ struct sk_buff *head = ring->frag_head;
+
+ if (unlikely(skb_shinfo(head)->nr_frags >= MAX_SKB_FRAGS)) {
+ BCMGENET_STATS64_INC((&ring->stats64), fragmented_errors);
+ bcmgenet_discard_frags(ring);
+ page_pool_put_full_page(ring->page_pool, page, true);
+ return NULL;
+ }
+
+ skb_add_rx_frag(head, skb_shinfo(head)->nr_frags, page,
+ offset + sizeof(struct status_64),
+ len - sizeof(struct status_64), size);
+
+ if (!(dma_flag & DMA_EOP))
+ return NULL;
+
+ ring->frag_head = NULL;
+
+ return head;
+}
+
/* bcmgenet_desc_rx - descriptor based rx process.
* this could be called from bottom half, or from NAPI polling method.
*/
@@ -2295,6 +2413,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
unsigned int rxpktprocessed = 0, rxpkttoprocess;
unsigned int bytes_processed = 0;
unsigned int p_index, mask;
+ unsigned int rxframes = 0;
unsigned int discards;
/* Clear status before servicing to reduce spurious interrupts */
@@ -2329,6 +2448,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
unsigned int rx_offset, rx_size;
struct status_64 *status;
struct page *rx_page;
+ unsigned int min_len;
void *hard_start;
__be16 rx_csum;
@@ -2341,14 +2461,15 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
if (bcmgenet_rx_refill(ring, cb)) {
BCMGENET_STATS64_INC(stats, dropped);
+ bcmgenet_discard_frags(ring);
goto next;
}
/* Sync the full buffer; the HW may have written anywhere
- * up to RX_BUF_LENGTH.
+ * up to priv->rx_buf_len.
*/
page_pool_dma_sync_for_cpu(ring->page_pool, rx_page, rx_offset,
- RX_BUF_LENGTH);
+ priv->rx_buf_len);
hard_start = page_address(rx_page) + rx_offset;
status = (struct status_64 *)hard_start;
@@ -2365,20 +2486,42 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
__func__, p_index, ring->c_index,
ring->read_ptr, dma_length_status);
+ /* Only the first descriptor carries the alignment pad. A head
+ * with more to come must hold the Ethernet header, and a
+ * continuation must hold payload.
+ */
+ if (dma_flag & DMA_SOP) {
+ min_len = GENET_RSB_PAD;
+ if (!(dma_flag & DMA_EOP))
+ min_len += ETH_HLEN;
+ } else {
+ min_len = sizeof(struct status_64) + 1;
+ }
+
/* Reject lengths that would underflow the SKB build path. */
- if (unlikely(len > RX_BUF_LENGTH || len < GENET_RSB_PAD)) {
+ if (unlikely(len > priv->rx_buf_len || len < min_len)) {
netif_err(priv, rx_status, dev,
"invalid packet length %d\n", len);
BCMGENET_STATS64_INC(stats, length_errors);
+ bcmgenet_discard_frags(ring);
page_pool_put_full_page(ring->page_pool, rx_page,
true);
goto next;
}
- if (unlikely(!(dma_flag & DMA_EOP) || !(dma_flag & DMA_SOP))) {
- netif_err(priv, rx_status, dev,
- "dropping fragmented packet!\n");
- BCMGENET_STATS64_INC(stats, fragmented_errors);
+ /* A new SOP resynchronizes after an incomplete frame */
+ if (dma_flag & DMA_SOP) {
+ if (ring->frag_head) {
+ BCMGENET_STATS64_INC(stats, fragmented_errors);
+ bcmgenet_discard_frags(ring);
+ }
+ ring->frag_drop = false;
+ } else if (unlikely(!ring->frag_head)) {
+ /* Rest of a dropped frame, or no SOP seen yet */
+ if (!ring->frag_drop) {
+ BCMGENET_STATS64_INC(stats, fragmented_errors);
+ ring->frag_drop = true;
+ }
page_pool_put_full_page(ring->page_pool, rx_page,
true);
goto next;
@@ -2408,17 +2551,27 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
DMA_RX_RXER)) == DMA_RX_RXER)
u64_stats_inc(&stats->errors);
u64_stats_update_end(&stats->syncp);
+ bcmgenet_discard_frags(ring);
page_pool_put_full_page(ring->page_pool, rx_page,
true);
goto next;
} /* error packet */
+ if (!(dma_flag & DMA_SOP)) {
+ skb = bcmgenet_add_frag(ring, rx_page, rx_offset,
+ rx_size, dma_flag, len);
+ if (!skb)
+ goto next;
+ goto deliver;
+ }
+
/* Build SKB from the page - data starts at hard_start,
* frame begins after RSB(64) + pad(2) = 66 bytes.
*/
skb = napi_build_skb(hard_start, rx_size);
if (unlikely(!skb)) {
BCMGENET_STATS64_INC(stats, dropped);
+ bcmgenet_discard_frags(ring);
page_pool_put_full_page(ring->page_pool, rx_page,
true);
goto next;
@@ -2430,17 +2583,26 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
skb_reserve(skb, GENET_RSB_PAD);
__skb_put(skb, len - GENET_RSB_PAD);
- if (priv->crc_fwd_en) {
- skb_trim(skb, skb->len - ETH_FCS_LEN);
+ if (unlikely(!(dma_flag & DMA_EOP))) {
+ ring->frag_head = skb;
+ goto next;
+ }
+
+deliver:
+ /* The FCS trim may release the page with the last status block */
+ rx_csum = (__force __be16)(status->rx_csum & 0xffff);
+
+ if (priv->crc_fwd_en &&
+ unlikely(pskb_trim(skb, skb->len - ETH_FCS_LEN))) {
+ BCMGENET_STATS64_INC(stats, dropped);
+ dev_kfree_skb_any(skb);
+ goto next;
}
/* Set up checksum offload */
- if (dev->features & NETIF_F_RXCSUM) {
- rx_csum = (__force __be16)(status->rx_csum & 0xffff);
- if (rx_csum) {
- skb->csum = (__force __wsum)ntohs(rx_csum);
- skb->ip_summed = CHECKSUM_COMPLETE;
- }
+ if ((dev->features & NETIF_F_RXCSUM) && rx_csum) {
+ skb->csum = (__force __wsum)ntohs(rx_csum);
+ skb->ip_summed = CHECKSUM_COMPLETE;
}
len = skb->len;
@@ -2448,6 +2610,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
/*Finish setting up the received SKB and send it to the kernel*/
skb->protocol = eth_type_trans(skb, priv->dev);
+ rxframes++;
u64_stats_update_begin(&stats->syncp);
u64_stats_inc(&stats->packets);
@@ -2474,7 +2637,8 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
}
ring->dim.bytes = bytes_processed;
- ring->dim.packets = rxpktprocessed;
+ /* A long frame spans several descriptors but is one packet */
+ ring->dim.packets = rxframes;
return rxpktprocessed;
}
@@ -2548,6 +2712,8 @@ static void bcmgenet_free_rx_buffers(struct bcmgenet_priv *priv)
cb = ring->cbs + i;
bcmgenet_free_rx_cb(cb, ring->page_pool);
}
+ /* a partial frame still holds pages of this pool */
+ bcmgenet_discard_frags(ring);
}
}
@@ -2617,6 +2783,67 @@ static void bcmgenet_link_intr_enable(struct bcmgenet_priv *priv)
bcmgenet_intrl2_0_writel(priv, int0_enable, INTRL2_CPU_MASK_CLEAR);
}
+/* Receive threshold in register units. Covers the alignment bytes and the
+ * frame up to the register maximum, but not the status block, which the
+ * hardware adds on top. A longer frame arrives in several descriptors.
+ */
+static unsigned int bcmgenet_pkt_rdy_thld(unsigned int mtu)
+{
+ unsigned int len = GENET_RBUF_ALIGN + mtu + ETH_HLEN + VLAN_HLEN;
+
+ len = round_up(len, ENET_THLD_BURST) / ENET_THLD_UNIT;
+
+ /* Keep the reset default for the common MTUs */
+ return clamp_t(unsigned int, len, ENET_THLD_DEFAULT,
+ ENET_THLD_MAX_LEN / ENET_THLD_UNIT);
+}
+
+/* Transmit threshold in register units. Frames landing in the window just
+ * past it are padded clear of it, so pick a threshold that leaves room for
+ * that padding inside the frame the MTU allows. Size the window against the
+ * longest frame the MAC has to accept, since the tag count is not bounded.
+ */
+static unsigned int bcmgenet_tx_pkt_rdy_thld(unsigned int mtu)
+{
+ unsigned int thld = ENET_THLD_MAX;
+
+ /* Keep the reset value while the MTU has no use for more */
+ if (mtu <= ETH_DATA_LEN)
+ return ENET_THLD_DEFAULT;
+
+ while (thld > ENET_THLD_DEFAULT &&
+ ENET_MAX_FRAME_LEN(mtu) - ETH_FCS_LEN > thld * ENET_THLD_UNIT &&
+ thld * ENET_THLD_UNIT + ENET_TX_SAFE_MARGIN > mtu + ETH_HLEN)
+ thld -= ENET_THLD_BURST / ENET_THLD_UNIT;
+
+ return thld;
+}
+
+/* A buffer has to hold everything the threshold lets the hardware deliver */
+static unsigned int bcmgenet_rx_buf_len(unsigned int mtu)
+{
+ return sizeof(struct status_64) +
+ bcmgenet_pkt_rdy_thld(mtu) * ENET_THLD_UNIT;
+}
+
+/* Program the MTU dependent registers. Call with the MAC disabled. */
+static void bcmgenet_set_mtu_regs(struct bcmgenet_priv *priv, unsigned int mtu)
+{
+ u32 tx_thld = bcmgenet_tx_pkt_rdy_thld(mtu);
+ u32 thld = bcmgenet_pkt_rdy_thld(mtu);
+
+ priv->tx_thld_len = tx_thld * ENET_THLD_UNIT;
+ bcmgenet_umac_writel(priv, ENET_MAC_FRAME_LEN(mtu), UMAC_MAX_FRAME_LEN);
+
+ /* GENET v1 maps other registers at these offsets */
+ if (GENET_IS_V1(priv))
+ return;
+
+ bcmgenet_rbuf_writel(priv, thld, RBUF_PKT_RDY_THLD);
+ bcmgenet_writel(tx_thld, priv->base + priv->hw_params->tbuf_offset +
+ TBUF_PKT_RDY_THLD);
+}
+
static void init_umac(struct bcmgenet_priv *priv)
{
struct device *kdev = &priv->pdev->dev;
@@ -2633,7 +2860,7 @@ static void init_umac(struct bcmgenet_priv *priv)
UMAC_MIB_CTRL);
bcmgenet_umac_writel(priv, 0, UMAC_MIB_CTRL);
- bcmgenet_umac_writel(priv, ENET_MAX_MTU_SIZE, UMAC_MAX_FRAME_LEN);
+ bcmgenet_set_mtu_regs(priv, priv->dev->mtu);
/* init tx registers, enable TSB */
reg = bcmgenet_tbuf_ctrl_get(priv);
@@ -2739,7 +2966,7 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
/* Set flow period for ring != 0 */
if (index)
- flow_period_val = ENET_MAX_MTU_SIZE << 16;
+ flow_period_val = ENET_MAC_FRAME_LEN(priv->dev->mtu) << 16;
bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_PROD_INDEX);
bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_CONS_INDEX);
@@ -2749,7 +2976,7 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
TDMA_FLOW_PERIOD);
bcmgenet_tdma_ring_writel(priv, index,
((size << DMA_RING_SIZE_SHIFT) |
- RX_BUF_LENGTH), DMA_RING_BUF_SIZE);
+ priv->rx_buf_len), DMA_RING_BUF_SIZE);
/* Set start and end address, read and write pointers */
bcmgenet_tdma_ring_writel(priv, index, start_ptr * words_per_bd,
@@ -2768,8 +2995,9 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
static int bcmgenet_rx_ring_create_pool(struct bcmgenet_priv *priv,
struct bcmgenet_rx_ring *ring)
{
- /* Buffers share a page. bcmgenet_rx_refill() syncs each one for the
- * device, PP_FLAG_DMA_SYNC_DEV would sync the whole page.
+ /* Buffers may share a page, depending on PAGE_SIZE and the MTU.
+ * bcmgenet_rx_refill() syncs each one for the device,
+ * PP_FLAG_DMA_SYNC_DEV would sync the whole page.
*/
struct page_pool_params pp_params = {
.order = 0,
@@ -2832,7 +3060,7 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_CONS_INDEX);
bcmgenet_rdma_ring_writel(priv, index,
((size << DMA_RING_SIZE_SHIFT) |
- RX_BUF_LENGTH), DMA_RING_BUF_SIZE);
+ priv->rx_buf_len), DMA_RING_BUF_SIZE);
bcmgenet_rdma_ring_writel(priv, index,
(DMA_FC_THRESH_LO <<
DMA_XOFF_THRESHOLD_SHIFT) |
@@ -3046,8 +3274,12 @@ static int bcmgenet_init_rx_queues(struct net_device *dev)
/* Initialize Rx priority queues */
for (i = 0; i <= priv->hw_params->rx_queues; i++) {
ret = bcmgenet_init_rx_ring(priv, i, end - start, start, end);
- if (ret)
+ if (ret) {
+ /* Only the rings before this one hold a NAPI */
+ while (i--)
+ netif_napi_del(&priv->rx_rings[i].napi);
return ret;
+ }
start = end;
end += priv->hw_params->rx_bds_per_q;
@@ -3348,7 +3580,7 @@ static void bcmgenet_get_hw_addr(struct bcmgenet_priv *priv,
put_unaligned_be16(addr_tmp, &addr[4]);
}
-static void bcmgenet_netif_start(struct net_device *dev)
+static void bcmgenet_netif_start(struct net_device *dev, bool start_phy)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
@@ -3365,7 +3597,8 @@ static void bcmgenet_netif_start(struct net_device *dev)
/* Monitor link interrupts now */
bcmgenet_link_intr_enable(priv);
- phy_start(dev->phydev);
+ if (start_phy)
+ phy_start(dev->phydev);
}
static int bcmgenet_open(struct net_device *dev)
@@ -3428,8 +3661,9 @@ static int bcmgenet_open(struct net_device *dev)
bcmgenet_phy_pause_set(dev, priv->rx_pause, priv->tx_pause);
- bcmgenet_netif_start(dev);
+ bcmgenet_netif_start(dev, true);
+ priv->datapath_up = true;
netif_tx_start_all_queues(dev);
return 0;
@@ -3488,7 +3722,11 @@ static int bcmgenet_close(struct net_device *dev)
netif_dbg(priv, ifdown, dev, "bcmgenet_close\n");
- bcmgenet_netif_stop(dev, false);
+ /* A failed MTU change can have torn the datapath down already */
+ if (priv->datapath_up) {
+ bcmgenet_netif_stop(dev, false);
+ priv->datapath_up = false;
+ }
/* Really kill the PHY state machine and disconnect from it */
phy_disconnect(dev->phydev);
@@ -3736,6 +3974,76 @@ static int bcmgenet_change_carrier(struct net_device *dev, bool new_carrier)
return 0;
}
+static int bcmgenet_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct bcmgenet_priv *priv = netdev_priv(dev);
+ unsigned int old_mtu = dev->mtu;
+ int ret;
+
+ /* Every MTU dependent value is floored at ETH_DATA_LEN, so a change
+ * below it reprograms nothing and must not cost queued frames.
+ */
+ if (!netif_running(dev) ||
+ max_t(unsigned int, old_mtu, ETH_DATA_LEN) ==
+ max_t(unsigned int, new_mtu, ETH_DATA_LEN)) {
+ WRITE_ONCE(dev->mtu, new_mtu);
+ priv->rx_buf_len = bcmgenet_rx_buf_len(new_mtu);
+ return 0;
+ }
+
+ /* The watchdog trips on an idle queue once the rings are gone */
+ netif_device_detach(dev);
+
+ /* Only the buffers and the MTU registers change, leave the PHY up */
+ bcmgenet_netif_stop(dev, false);
+ priv->datapath_up = false;
+
+ WRITE_ONCE(dev->mtu, new_mtu);
+ priv->rx_buf_len = bcmgenet_rx_buf_len(new_mtu);
+ bcmgenet_set_mtu_regs(priv, new_mtu);
+
+ ret = bcmgenet_init_dma(priv, true);
+ if (ret) {
+ /* Retry the size that was allocated a moment ago */
+ WRITE_ONCE(dev->mtu, old_mtu);
+ priv->rx_buf_len = bcmgenet_rx_buf_len(old_mtu);
+ bcmgenet_set_mtu_regs(priv, old_mtu);
+ if (bcmgenet_init_dma(priv, true)) {
+ /* Nothing left to run on. Take the interface down so
+ * that close and suspend do not tear it down twice.
+ */
+ netdev_err(dev, "failed to restore MTU %u, closing\n",
+ old_mtu);
+ netif_close(dev);
+
+ /* Mark the device present again, __dev_open()
+ * refuses a detached one. The queues stay stopped
+ * because the interface is down by now.
+ */
+ netif_device_attach(dev);
+ return ret;
+ }
+ }
+
+ bcmgenet_hfb_restore(priv);
+ bcmgenet_netif_start(dev, false);
+
+ /* bcmgenet_netif_start() only restores the link interrupt */
+ if (bcmgenet_has_mdio_intr(priv))
+ bcmgenet_intrl2_0_writel(priv, UMAC_IRQ_MDIO_EVENT,
+ INTRL2_CPU_MASK_CLEAR);
+
+ /* A link event latched while the interrupts were off is gone. Internal
+ * PHYs on GENET v1-v4 are not polled, so resync the state machine.
+ */
+ phy_mac_interrupt(dev->phydev);
+
+ priv->datapath_up = true;
+ netif_device_attach(dev);
+
+ return ret;
+}
+
static const struct net_device_ops bcmgenet_netdev_ops = {
.ndo_open = bcmgenet_open,
.ndo_stop = bcmgenet_close,
@@ -3747,6 +4055,7 @@ static const struct net_device_ops bcmgenet_netdev_ops = {
.ndo_set_features = bcmgenet_set_features,
.ndo_get_stats64 = bcmgenet_get_stats64,
.ndo_change_carrier = bcmgenet_change_carrier,
+ .ndo_change_mtu = bcmgenet_change_mtu,
};
/* GENET hardware parameters/characteristics */
@@ -4100,6 +4409,11 @@ static int bcmgenet_probe(struct platform_device *pdev)
/* Mii wait queue */
init_waitqueue_head(&priv->wq);
bcmgenet_hfb_init(priv);
+
+ /* v1 cannot program the thresholds, so it stays at the default MTU */
+ priv->rx_buf_len = bcmgenet_rx_buf_len(dev->mtu);
+ if (!GENET_IS_V1(priv))
+ dev->max_mtu = ENET_MAX_JUMBO_MTU;
INIT_WORK(&priv->bcmgenet_irq_work, bcmgenet_irq_task);
priv->clk_wol = devm_clk_get_optional(&priv->pdev->dev, "enet-wol");
@@ -4283,6 +4597,7 @@ static int bcmgenet_resume(struct device *d)
bcmgenet_rdma_disable(priv);
bcmgenet_intr_disable(priv);
bcmgenet_fini_dma(priv);
+ priv->datapath_up = false;
enable_irq(priv->irq1);
}
@@ -4312,8 +4627,9 @@ static int bcmgenet_resume(struct device *d)
if (!device_may_wakeup(d))
phy_resume(dev->phydev);
- bcmgenet_netif_start(dev);
+ bcmgenet_netif_start(dev, true);
+ priv->datapath_up = true;
netif_device_attach(dev);
return 0;
@@ -4375,6 +4691,7 @@ static int bcmgenet_suspend(struct device *d)
} else {
/* Teardown the interface */
bcmgenet_netif_stop(dev, true);
+ priv->datapath_up = false;
}
return 0;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
index 86f2aed20dbe8..9c2c21081736a 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -28,13 +28,20 @@
/* which ring is descriptor based */
#define DESC_INDEX 16
-/* Body(1500) + EH_SIZE(14) + VLANTAG(4) + BRCMTAG(6) + FCS(4) = 1528.
- * 1536 is multiple of 256 bytes
- */
#define ENET_BRCM_TAG_LEN 6
#define ENET_PAD 8
-#define ENET_MAX_MTU_SIZE (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + \
- ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD)
+
+/* Longest frame the MAC must accept for a given MTU. ENET_PAD is slack the
+ * driver has always carried, it rounded the default up to 1536 from 1528.
+ */
+#define ENET_FRAME_OVERHEAD (ETH_HLEN + VLAN_HLEN + ENET_BRCM_TAG_LEN + \
+ ETH_FCS_LEN + ENET_PAD)
+#define ENET_MAX_FRAME_LEN(mtu) ((mtu) + ENET_FRAME_OVERHEAD)
+
+/* The MAC keeps accepting a standard frame below the default MTU */
+#define ENET_MAC_FRAME_LEN(mtu) ENET_MAX_FRAME_LEN(max_t(unsigned int, (mtu), \
+ ETH_DATA_LEN))
+
#define DMA_MAX_BURST_LENGTH 0x10
/* misc. configuration */
@@ -219,6 +226,8 @@ struct bcmgenet_rx_stats64 {
#define RBUF_ALIGN_2B (1 << 1)
#define RBUF_BAD_DIS (1 << 2)
+#define RBUF_PKT_RDY_THLD 0x08
+
#define RBUF_STATUS 0x0C
#define RBUF_STATUS_WOL (1 << 0)
#define RBUF_STATUS_MPD_INTR_ACTIVE (1 << 1)
@@ -249,6 +258,7 @@ struct bcmgenet_rx_stats64 {
#define TBUF_CTRL 0x00
#define TBUF_64B_EN (1 << 0)
#define TBUF_BP_MC 0x0C
+#define TBUF_PKT_RDY_THLD 0x10
#define TBUF_ENERGY_CTRL 0x14
#define TBUF_EEE_EN (1 << 0)
#define TBUF_PM_EN (1 << 1)
@@ -575,6 +585,8 @@ struct bcmgenet_rx_ring {
unsigned int cb_ptr; /* Rx ring initial CB ptr */
unsigned int end_ptr; /* Rx ring end CB ptr */
unsigned int old_discards;
+ struct sk_buff *frag_head; /* frame being reassembled */
+ bool frag_drop; /* discarding until the next SOP */
struct bcmgenet_net_dim dim;
u32 rx_max_coalesced_frames;
u32 rx_coalesce_usecs;
@@ -613,6 +625,8 @@ struct bcmgenet_priv {
void __iomem *rx_bds;
struct enet_cb *rx_cbs;
unsigned int num_rx_bds;
+ unsigned int rx_buf_len;
+ unsigned int tx_thld_len;
struct bcmgenet_rxnfc_rule rxnfc_rules[MAX_NUM_OF_FS_RULES];
struct list_head rxnfc_list;
@@ -624,6 +638,7 @@ struct bcmgenet_priv {
unsigned autoneg_pause:1;
unsigned tx_pause:1;
unsigned rx_pause:1;
+ unsigned datapath_up:1;
/* MDIO bus variables */
wait_queue_head_t wq;
|
| 3/2 | 2026/10/12 09:08 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 13938 output: 39 thoughts: 325 Thoughts: **Analyzing the Broadcom GENET Patch** Okay, let's break this down. First, I need to understand exactly what this patch is doing. From the initial scan, it looks like it's focused on adding jumbo frame support and MTU changes to the Broadcom GENET Ethernet driver, specifically within `bcmgenet.c` and `bcmgenet.h`. That's a reasonable enhancement, and I see it's quite involved. The changes include adding a `.ndo_change_mtu` function, which is critical for actually allowing MTU configuration at runtime. It's also adding scatter-gather Rx reassembly which is good - efficient fragment handling is vital for jumbo frames. In the Tx path, it seems like they are handling padding and software checksums for frames exceeding a certain threshold, which makes sense. I see they are making the expected register configurations for MTU, DMA buffer lengths, and thresholds. Now, the crucial question: can I even *test* this effectively? The target architecture is amd64, which is good. That's what I'm working with. But, is `bcmgenet` available to test in a reasonable setting? The patch says it's for the Broadcom GENET Ethernet controller, like the ones used in the Raspberry Pi 4 (BCM2711) and set-top boxes (STBs / BCM7xxx). That's not a common development platform for me! I need to know if this is something I can actually probe in QEMU or GCE on amd64, a virtualized environment. Time to check the `Kconfig` file and the driver probe mechanisms. If I can't easily emulate the environment, validating this patch is going to be difficult. |
| 4/2 | 2026/10/12 09:08 | tool | grepper |
0mError:no matches Args: {
"Expression": "config BCMGENET",
"PathPrefixes": [
"drivers/net/ethernet/broadcom/genet/"
]
}Results: {
"error": "no matches"
} |
| 5/2 | 2026/10/12 09:08 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 14688 output: 35 thoughts: 12 Thoughts: Okay, here's my attempt at summarizing that thought process, tailored for an expert audience: **Hunting Down the BCMGENET Kconfig** Alright, time to get this show on the road. The immediate need here is to locate the Kconfig file for the bcmgenet driver. This isn't usually a wild goose chase, but it sets the stage for everything else I need to do. I need that configuration fragment so I can understand the available options, dependencies, and ultimately, how this driver is controlled within the broader kernel build system. The specifics will vary depending on the kernel version and the exact structure of the Broadcom tree, but the fundamental strategy remains the same: I need that Kconfig file. Let's see if it's in the obvious places, or if I need to dig deeper into the build system and device tree definitions. The path to it should be pretty straightforward. |
| 6/2 | 2026/10/12 09:08 | tool | grepper |
0mArgs:{
"Expression": "BCMGENET",
"PathPrefixes": [
"drivers/net/ethernet/broadcom/"
]
}Results: {
"Output": "\nFull output is too long, showing 200 out of 261 lines.\nUse more precise expression or PathPrefixes if possible.\n\nNumber of matching lines per file (5 files in total):\ndrivers/net/ethernet/broadcom/Kconfig:1\ndrivers/net/ethernet/broadcom/Makefile:1\ndrivers/net/ethernet/broadcom/genet/Makefile:1\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:60\ndrivers/net/ethernet/broadcom/genet/bcmgenet.h:7\n\ndrivers/net/ethernet/broadcom/Kconfig=63=config BCM63XX_ENET\n--\ndrivers/net/ethernet/broadcom/Kconfig-71-\ndrivers/net/ethernet/broadcom/Kconfig:72:config BCMGENET\ndrivers/net/ethernet/broadcom/Kconfig-73-\ttristate \"Broadcom GENET internal MAC support\"\n--\ndrivers/net/ethernet/broadcom/Makefile=8=obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o\ndrivers/net/ethernet/broadcom/Makefile:9:obj-$(CONFIG_BCMGENET) += genet/\ndrivers/net/ethernet/broadcom/Makefile-10-obj-$(CONFIG_BNX2) += bnx2.o\n--\ndrivers/net/ethernet/broadcom/genet/Makefile-1-# SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/ethernet/broadcom/genet/Makefile:2:obj-$(CONFIG_BCMGENET) += genet.o\ndrivers/net/ethernet/broadcom/genet/Makefile-3-genet-objs := bcmgenet.o bcmmii.o bcmgenet_wol.o\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=632=static void bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-732-\tbcmgenet_hfb_enable_filter(priv, f);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:733:\trule-\u003estate = BCMGENET_RXNFC_STATE_ENABLED;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-734-}\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=773=static void bcmgenet_hfb_init(struct bcmgenet_priv *priv)\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-779-\t\tINIT_LIST_HEAD(\u0026priv-\u003erxnfc_rules[i].list);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:780:\t\tpriv-\u003erxnfc_rules[i].state = BCMGENET_RXNFC_STATE_UNUSED;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-781-\t}\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=784=static void bcmgenet_hfb_restore(struct bcmgenet_priv *priv)\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-790-\tlist_for_each_entry(rule, \u0026priv-\u003erxnfc_list, list)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:791:\t\tif (rule-\u003estate != BCMGENET_RXNFC_STATE_UNUSED)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-792-\t\t\tbcmgenet_hfb_create_rxnfc_filter(priv, rule);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1015=enum bcmgenet_stat_type {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1016:\tBCMGENET_STAT_RTNL = -1,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1017:\tBCMGENET_STAT_MIB_RX,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1018:\tBCMGENET_STAT_MIB_TX,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1019:\tBCMGENET_STAT_RUNT,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1020:\tBCMGENET_STAT_MISC,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1021:\tBCMGENET_STAT_SOFT,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1022:\tBCMGENET_STAT_SOFT64,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1023-};\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1025=struct bcmgenet_stats {\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1039-\t.stat_offset = offsetof(struct rtnl_link_stats64, m), \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1040:\t.type = BCMGENET_STAT_RTNL, \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1041-}\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1053-\t.stat_offset = offsetof(struct bcmgenet_priv, s.m), \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1054:\t.type = BCMGENET_STAT_SOFT64, \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1055-\t.syncp_offset = offsetof(struct bcmgenet_priv, s.syncp), \\\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1057-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1058:#define STAT_GENET_MIB_RX(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_MIB_RX)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1059:#define STAT_GENET_MIB_TX(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_MIB_TX)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1060:#define STAT_GENET_RUNT(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_RUNT)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1061:#define STAT_GENET_SOFT_MIB(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_SOFT)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1062-\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1066-\t.stat_offset = offsetof(struct bcmgenet_priv, m), \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1067:\t.type = BCMGENET_STAT_MISC, \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1068-\t.reg_offset = offset, \\\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1107- */\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1108:#define BCMGENET_STAT_OFFSET\t0xc\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1109-\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1113=static const struct bcmgenet_stats bcmgenet_gstrings_stats[] = {\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1212-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1213:#define BCMGENET_STATS_LEN\tARRAY_SIZE(bcmgenet_gstrings_stats)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1214-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1215:#define BCMGENET_STATS64_ADD(stats, m, v) \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1216-\tdo { \\\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1221-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1222:#define BCMGENET_STATS64_INC(stats, m) \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1223-\tdo { \\\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1235=static int bcmgenet_get_sset_count(struct net_device *dev, int string_set)\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1238-\tcase ETH_SS_STATS:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1239:\t\treturn BCMGENET_STATS_LEN;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1240-\tdefault:\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1245=static void bcmgenet_get_strings(struct net_device *dev, u32 stringset,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1252-\tcase ETH_SS_STATS:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1253:\t\tfor (i = 0; i \u003c BCMGENET_STATS_LEN; i++) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1254-\t\t\tstr = bcmgenet_gstrings_stats[i].stat_string;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1300=static void bcmgenet_update_mib_counters(struct bcmgenet_priv *priv)\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1303-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1304:\tfor (i = 0; i \u003c BCMGENET_STATS_LEN; i++) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1305-\t\tconst struct bcmgenet_stats *s;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1311-\t\tswitch (s-\u003etype) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1312:\t\tcase BCMGENET_STAT_RTNL:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1313:\t\tcase BCMGENET_STAT_SOFT:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1314:\t\tcase BCMGENET_STAT_SOFT64:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1315-\t\t\tcontinue;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1316:\t\tcase BCMGENET_STAT_RUNT:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1317:\t\t\toffset += BCMGENET_STAT_OFFSET;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1318-\t\t\tfallthrough;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1319:\t\tcase BCMGENET_STAT_MIB_TX:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1320:\t\t\toffset += BCMGENET_STAT_OFFSET;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1321-\t\t\tfallthrough;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1322:\t\tcase BCMGENET_STAT_MIB_RX:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1323-\t\t\tval = bcmgenet_umac_readl(priv,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1326-\t\t\tbreak;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1327:\t\tcase BCMGENET_STAT_MISC:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1328-\t\t\tif (GENET_IS_V1(priv)) {\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1347=static void bcmgenet_get_ethtool_stats(struct net_device *dev,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1361-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1362:\tfor (i = 0; i \u003c BCMGENET_STATS_LEN; i++) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1363-\t\tconst struct bcmgenet_stats *s;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1368-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1369:\t\tif (s-\u003etype == BCMGENET_STAT_SOFT64) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1370-\t\t\tsyncp = (struct u64_stats_sync *)(p + s-\u003esyncp_offset);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1375-\t\t} else {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1376:\t\t\tif (s-\u003etype == BCMGENET_STAT_RTNL)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1377-\t\t\t\tp = (char *)\u0026stats64;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1533=static int bcmgenet_insert_flow(struct net_device *dev,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1567-\t\t\tloc_rule = \u0026priv-\u003erxnfc_rules[i];\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1568:\t\t\tif (loc_rule-\u003estate == BCMGENET_RXNFC_STATE_UNUSED) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1569-\t\t\t\tcmd-\u003efs.location = i;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1579-\t}\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1580:\tif (loc_rule-\u003estate == BCMGENET_RXNFC_STATE_ENABLED)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1581-\t\tbcmgenet_hfb_disable_filter(priv, cmd-\u003efs.location + 1);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1582:\tif (loc_rule-\u003estate != BCMGENET_RXNFC_STATE_UNUSED) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1583-\t\tlist_del(\u0026loc_rule-\u003elist);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1585-\t}\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1586:\tloc_rule-\u003estate = BCMGENET_RXNFC_STATE_UNUSED;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1587-\tmemcpy(\u0026loc_rule-\u003efs, \u0026cmd-\u003efs,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1597=static int bcmgenet_delete_flow(struct net_device *dev,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1607-\trule = \u0026priv-\u003erxnfc_rules[cmd-\u003efs.location];\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1608:\tif (rule-\u003estate == BCMGENET_RXNFC_STATE_UNUSED) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1609-\t\terr = -ENOENT;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1612-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1613:\tif (rule-\u003estate == BCMGENET_RXNFC_STATE_ENABLED)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1614-\t\tbcmgenet_hfb_disable_filter(priv, cmd-\u003efs.location + 1);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1615:\tif (rule-\u003estate != BCMGENET_RXNFC_STATE_UNUSED) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1616-\t\tlist_del(\u0026rule-\u003elist);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1618-\t}\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1619:\trule-\u003estate = BCMGENET_RXNFC_STATE_UNUSED;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1620-\tmemset(\u0026rule-\u003efs, 0, sizeof(struct ethtool_rx_flow_spec));\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1647=static int bcmgenet_get_flow(struct net_device *dev, struct ethtool_rxnfc *cmd,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1657-\trule = \u0026priv-\u003erxnfc_rules[loc];\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1658:\tif (rule-\u003estate == BCMGENET_RXNFC_STATE_UNUSED)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1659-\t\terr = -ENOENT;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=2082=static struct sk_buff *bcmgenet_add_tsb(struct net_device *dev,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2102-\t\t\tpriv-\u003emib.tx_realloc_tsb_failed++;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:2103:\t\t\tBCMGENET_STATS64_INC(stats, dropped);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2104-\t\t\treturn NULL;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=2158=static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2194-\t\tif (!skb) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:2195:\t\t\tBCMGENET_STATS64_INC((\u0026ring-\u003estats64), dropped);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2196-\t\t\tgoto drop;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2205-\t\tif (skb_checksum_help(skb)) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:2206:\t\t\tBCMGENET_STATS64_INC((\u0026ring-\u003estats64), dropped);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2207-\t\t\tdev_kfree_skb_any(skb);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2215-\t\tif (skb_put_padto(skb, priv-\u003etx_thld_len + ENET_TX_SAFE_MARGIN)) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:2216:\t\t\tBCMGENET_STATS64_INC((\u0026ring-\u003estats64), dropped);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2217-\t\t\tgoto drop;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=2371=static struct sk_buff *bcmgenet_add_frag(struct bcmgenet_rx_ring *ring,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2380-\tif (unlikely(skb_shinfo(head)-\u003enr_frags \u003e= MAX_SKB_FRAGS)) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:2381:\t\tBCMGENET_STATS64_INC((\u0026ring-\u003estats64), fragmented_errors);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2382-\t\tbcmgenet_discard_frags(ring);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=2402=static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2428-\t\tdiscards = discards - ring-\u003eold_discards;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:2429:\t\tBCMGENET_STATS64_ADD(stats, missed, discards);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2430-\t\tring-\u003eold_discards += discards;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2462-\t\tif (bcmgenet_rx_refill(ring, cb)) {\n\n"
} |
| 7/2 | 2026/10/12 09:08 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 21061 output: 39 thoughts: 24 Thoughts: Here's my thought process, as if I were considering that Kconfig file: **Investigating a Broadcom Ethernet Driver Configuration** Okay, let's dive in. I need to get a better handle on how this Broadcom Ethernet driver is configured. I immediately want to zero in on the `drivers/net/ethernet/broadcom/Kconfig` file. I'm assuming that's where the core configuration options are defined. My gut tells me that around line 72, there may be some crucial aspects I'm interested in; perhaps a specific feature, a hardware variant, or a dependency that I'm trying to trace. I'll need to open that file and start dissecting the options defined around that line to see if I can get the information I need. |
| 8/2 | 2026/10/12 09:08 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/Kconfig",
"FirstLine": 70,
"LineCount": 30
}Results: {
"Contents": " 70:\t\t MIPS chipset family (BCM63XX).\n 71:\t\n 72:\tconfig BCMGENET\n 73:\t\ttristate \"Broadcom GENET internal MAC support\"\n 74:\t\tdepends on HAS_IOMEM\n 75:\t\tdepends on PTP_1588_CLOCK_OPTIONAL || !ARCH_BCM2835\n 76:\t\tselect PHYLIB\n 77:\t\tselect FIXED_PHY\n 78:\t\tselect BCM7XXX_PHY\n 79:\t\tselect MDIO_BCM_UNIMAC\n 80:\t\tselect DIMLIB\n 81:\t\tselect PAGE_POOL\n 82:\t\tselect BROADCOM_PHY if ARCH_BCM2835\n 83:\t\thelp\n 84:\t\t This driver supports the built-in Ethernet MACs found in the\n 85:\t\t Broadcom BCM7xxx Set Top Box family chipset.\n 86:\t\n 87:\tconfig BNX2\n 88:\t\ttristate \"QLogic bnx2 support\"\n 89:\t\tdepends on PCI\n 90:\t\tselect CRC32\n 91:\t\tselect FW_LOADER\n 92:\t\thelp\n 93:\t\t This driver supports QLogic bnx2 gigabit Ethernet cards.\n 94:\t\n 95:\t\t To compile this driver as a module, choose M here: the module\n 96:\t\t will be called bnx2. This is recommended.\n 97:\t\n 98:\tconfig CNIC\n 99:\t\ttristate \"QLogic CNIC support\"\n"
} |
| 9/2 | 2026/10/12 09:08 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 21699 output: 48 thoughts: 72 Thoughts: Here's my analysis of what I'm thinking, rendered in the first person, as requested: **Navigating the BCMGENET Driver Registration** Okay, so I need to understand how the `bcmgenet` driver is initialized and registered. My immediate focus is on `drivers/net/ethernet/broadcom/genet/bcmgenet.c`. I need to figure out the exact registration mechanism, which dictates how the kernel knows to use this driver. Is it a standard platform driver using a resource list? Perhaps it's ACPI-based, pulling information from the Advanced Configuration and Power Interface tables? Or maybe it's using Device Tree (DT) or Open Firmware (OF) to describe the hardware. Could it be a PCI device, requiring PCI configuration and probing? The conventional method would be to jump to the `module_init` portion. To get a quick overview, I will now check the bottom of `bcmgenet.c` for clues. This is usually where the driver registration happens. |
| 10/2 | 2026/10/12 09:08 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/genet/bcmgenet.c",
"FirstLine": 4440,
"LineCount": 80
}Results: {
"Contents": "4440:\t\t\tif (has_acpi_companion(\u0026pdev-\u003edev)) {\n4441:\t\t\t\tu8 addr[ETH_ALEN];\n4442:\t\n4443:\t\t\t\tbcmgenet_get_hw_addr(priv, addr);\n4444:\t\t\t\teth_hw_addr_set(dev, addr);\n4445:\t\t\t}\n4446:\t\n4447:\t\tif (!is_valid_ether_addr(dev-\u003edev_addr)) {\n4448:\t\t\tdev_warn(\u0026pdev-\u003edev, \"using random Ethernet MAC\\n\");\n4449:\t\t\teth_hw_addr_random(dev);\n4450:\t\t}\n4451:\t\n4452:\t\treset_umac(priv);\n4453:\t\n4454:\t\terr = bcmgenet_mii_init(dev);\n4455:\t\tif (err)\n4456:\t\t\tgoto err_clk_disable;\n4457:\t\n4458:\t\t/* setup number of real queues + 1 */\n4459:\t\tnetif_set_real_num_tx_queues(priv-\u003edev, priv-\u003ehw_params-\u003etx_queues + 1);\n4460:\t\tnetif_set_real_num_rx_queues(priv-\u003edev, priv-\u003ehw_params-\u003erx_queues + 1);\n4461:\t\n4462:\t\t/* Set default coalescing parameters */\n4463:\t\tfor (i = 0; i \u003c= priv-\u003ehw_params-\u003erx_queues; i++) {\n4464:\t\t\tpriv-\u003erx_rings[i].priv = priv;\n4465:\t\t\tpriv-\u003erx_rings[i].index = i;\n4466:\t\t\tpriv-\u003erx_rings[i].rx_max_coalesced_frames = 1;\n4467:\t\t}\n4468:\t\n4469:\t\t/* Initialize u64 stats seq counter for 32bit machines */\n4470:\t\tfor (i = 0; i \u003c= GENET_MAX_MQ_CNT; i++) {\n4471:\t\t\tu64_stats_init(\u0026priv-\u003erx_rings[i].stats64.syncp);\n4472:\t\t\tu64_stats_init(\u0026priv-\u003etx_rings[i].stats64.syncp);\n4473:\t\t}\n4474:\t\n4475:\t\t/* libphy will determine the link state */\n4476:\t\tnetif_carrier_off(dev);\n4477:\t\n4478:\t\t/* Turn off the main clock, WOL clock is handled separately */\n4479:\t\tclk_disable_unprepare(priv-\u003eclk);\n4480:\t\n4481:\t\terr = register_netdev(dev);\n4482:\t\tif (err) {\n4483:\t\t\tbcmgenet_mii_exit(dev);\n4484:\t\t\tgoto err;\n4485:\t\t}\n4486:\t\n4487:\t\treturn err;\n4488:\t\n4489:\terr_clk_disable:\n4490:\t\tclk_disable_unprepare(priv-\u003eclk);\n4491:\terr:\n4492:\t\tfree_netdev(dev);\n4493:\t\treturn err;\n4494:\t}\n4495:\t\n4496:\tstatic void bcmgenet_remove(struct platform_device *pdev)\n4497:\t{\n4498:\t\tstruct bcmgenet_priv *priv = dev_to_priv(\u0026pdev-\u003edev);\n4499:\t\n4500:\t\tdev_set_drvdata(\u0026pdev-\u003edev, NULL);\n4501:\t\tunregister_netdev(priv-\u003edev);\n4502:\t\tbcmgenet_mii_exit(priv-\u003edev);\n4503:\t\tfree_netdev(priv-\u003edev);\n4504:\t}\n4505:\t\n4506:\tstatic void bcmgenet_shutdown(struct platform_device *pdev)\n4507:\t{\n4508:\t\tbcmgenet_remove(pdev);\n4509:\t}\n4510:\t\n4511:\t#ifdef CONFIG_PM_SLEEP\n4512:\tstatic int bcmgenet_resume_noirq(struct device *d)\n4513:\t{\n4514:\t\tstruct net_device *dev = dev_get_drvdata(d);\n4515:\t\tstruct bcmgenet_priv *priv = netdev_priv(dev);\n4516:\t\tint ret;\n4517:\t\tu32 reg;\n4518:\t\n4519:\t\tif (!netif_running(dev))\n"
} |
| 11/2 | 2026/10/12 09:08 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 23265 output: 48 thoughts: 20 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Analyzing the Tail End** Okay, so I need to zero in on what's happening from line 4519 onwards in this file. The assumption is that this region contains something of significant interest – potentially a crucial segment, a log of recent activity, the final results, or perhaps even an anomaly. Given the file size (which is implied, even if not explicitly stated), simply scanning from the beginning is inefficient; my primary focus now must be this specific chunk. I'm operating under the hypothesis that the critical information I seek resides in that section. Time is valuable, and focusing on the relevant section will be more time-efficient than a brute-force approach. I'm ready to parse the information and analyze the results. |
| 12/2 | 2026/10/12 09:08 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/genet/bcmgenet.c",
"FirstLine": 4700,
"LineCount": 80
}Results: {
"Contents": "4700:\tstatic int bcmgenet_suspend_noirq(struct device *d)\n4701:\t{\n4702:\t\tstruct net_device *dev = dev_get_drvdata(d);\n4703:\t\tstruct bcmgenet_priv *priv = netdev_priv(dev);\n4704:\t\tint ret = 0;\n4705:\t\n4706:\t\tif (!netif_running(dev))\n4707:\t\t\treturn 0;\n4708:\t\n4709:\t\t/* Prepare the device for Wake-on-LAN and switch to the slow clock */\n4710:\t\tif (device_may_wakeup(d) \u0026\u0026 priv-\u003ewolopts)\n4711:\t\t\tret = bcmgenet_power_down(priv, GENET_POWER_WOL_MAGIC);\n4712:\t\telse if (priv-\u003einternal_phy)\n4713:\t\t\tret = bcmgenet_power_down(priv, GENET_POWER_PASSIVE);\n4714:\t\n4715:\t\t/* Let the framework handle resumption and leave the clocks on */\n4716:\t\tif (ret)\n4717:\t\t\treturn ret;\n4718:\t\n4719:\t\t/* Turn off the clocks */\n4720:\t\tclk_disable_unprepare(priv-\u003eclk);\n4721:\t\n4722:\t\treturn 0;\n4723:\t}\n4724:\t#else\n4725:\t#define bcmgenet_suspend\tNULL\n4726:\t#define bcmgenet_suspend_noirq\tNULL\n4727:\t#define bcmgenet_resume\t\tNULL\n4728:\t#define bcmgenet_resume_noirq\tNULL\n4729:\t#endif /* CONFIG_PM_SLEEP */\n4730:\t\n4731:\tstatic const struct dev_pm_ops bcmgenet_pm_ops = {\n4732:\t\t.suspend\t= bcmgenet_suspend,\n4733:\t\t.suspend_noirq\t= bcmgenet_suspend_noirq,\n4734:\t\t.resume\t\t= bcmgenet_resume,\n4735:\t\t.resume_noirq\t= bcmgenet_resume_noirq,\n4736:\t};\n4737:\t\n4738:\tstatic const struct acpi_device_id genet_acpi_match[] = {\n4739:\t\t{ \"BCM6E4E\", (kernel_ulong_t)\u0026bcm2711_plat_data },\n4740:\t\t{ },\n4741:\t};\n4742:\tMODULE_DEVICE_TABLE(acpi, genet_acpi_match);\n4743:\t\n4744:\tstatic struct platform_driver bcmgenet_driver = {\n4745:\t\t.probe\t= bcmgenet_probe,\n4746:\t\t.remove = bcmgenet_remove,\n4747:\t\t.shutdown = bcmgenet_shutdown,\n4748:\t\t.driver\t= {\n4749:\t\t\t.name\t= \"bcmgenet\",\n4750:\t\t\t.of_match_table = bcmgenet_match,\n4751:\t\t\t.pm\t= \u0026bcmgenet_pm_ops,\n4752:\t\t\t.acpi_match_table = genet_acpi_match,\n4753:\t\t},\n4754:\t};\n4755:\tmodule_platform_driver(bcmgenet_driver);\n4756:\t\n4757:\tMODULE_AUTHOR(\"Broadcom Corporation\");\n4758:\tMODULE_DESCRIPTION(\"Broadcom GENET Ethernet controller driver\");\n4759:\tMODULE_ALIAS(\"platform:bcmgenet\");\n4760:\tMODULE_LICENSE(\"GPL\");\n4761:\tMODULE_SOFTDEP(\"pre: mdio-bcm-unimac\");\n"
} |
| 13/2 | 2026/10/12 09:08 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 24524 output: 48 thoughts: 387 Thoughts: **My Analysis of the `bcmgenet` Driver and Fuzzing Feasibility** Okay, so I'm looking at this `bcmgenet` code, and it's a `platform_driver`, which is standard. But wait, I need to consider whether it's even *reachable* in a standard fuzzing environment, specifically QEMU or GCE. That's the primary gating factor here. I have to make sure this code *can* execute in a virtualized setting. The prompt's Section 1 and Section 2 are clear: if it's structurally unreachable, it's a no-go for fuzzing, no matter what else it's doing. The prompt emphasizes that vendor-specific hardware that isn't emulated in QEMU is structurally unreachable. So, I need to figure out what kind of hardware this `bcmgenet` driver actually interfaces with. Is it something that's only found on a specific physical ASIC or PCIe card? If so, I'm wasting my time, at least for this stage of analysis. My next step has to be diving into `bcmgenet_match` and `bcmgenet_probe`. `bcmgenet_match` should give me some clue about the device IDs or board IDs it recognizes (and therefore, the specific hardware it's designed to support). Then, `bcmgenet_probe` will clarify how it initializes the hardware. Does the initialization rely on hardware registers that aren't emulated? Are there any obvious dependencies on non-standard hardware capabilities? From those functions, I'll be able to tell if it's reachable or not. |
| 14/2 | 2026/10/12 09:08 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/genet/bcmgenet.c",
"FirstLine": 4000,
"LineCount": 50
}Results: {
"Contents": "4000:\t\n4001:\t\tWRITE_ONCE(dev-\u003emtu, new_mtu);\n4002:\t\tpriv-\u003erx_buf_len = bcmgenet_rx_buf_len(new_mtu);\n4003:\t\tbcmgenet_set_mtu_regs(priv, new_mtu);\n4004:\t\n4005:\t\tret = bcmgenet_init_dma(priv, true);\n4006:\t\tif (ret) {\n4007:\t\t\t/* Retry the size that was allocated a moment ago */\n4008:\t\t\tWRITE_ONCE(dev-\u003emtu, old_mtu);\n4009:\t\t\tpriv-\u003erx_buf_len = bcmgenet_rx_buf_len(old_mtu);\n4010:\t\t\tbcmgenet_set_mtu_regs(priv, old_mtu);\n4011:\t\t\tif (bcmgenet_init_dma(priv, true)) {\n4012:\t\t\t\t/* Nothing left to run on. Take the interface down so\n4013:\t\t\t\t * that close and suspend do not tear it down twice.\n4014:\t\t\t\t */\n4015:\t\t\t\tnetdev_err(dev, \"failed to restore MTU %u, closing\\n\",\n4016:\t\t\t\t\t old_mtu);\n4017:\t\t\t\tnetif_close(dev);\n4018:\t\n4019:\t\t\t\t/* Mark the device present again, __dev_open()\n4020:\t\t\t\t * refuses a detached one. The queues stay stopped\n4021:\t\t\t\t * because the interface is down by now.\n4022:\t\t\t\t */\n4023:\t\t\t\tnetif_device_attach(dev);\n4024:\t\t\t\treturn ret;\n4025:\t\t\t}\n4026:\t\t}\n4027:\t\n4028:\t\tbcmgenet_hfb_restore(priv);\n4029:\t\tbcmgenet_netif_start(dev, false);\n4030:\t\n4031:\t\t/* bcmgenet_netif_start() only restores the link interrupt */\n4032:\t\tif (bcmgenet_has_mdio_intr(priv))\n4033:\t\t\tbcmgenet_intrl2_0_writel(priv, UMAC_IRQ_MDIO_EVENT,\n4034:\t\t\t\t\t\t INTRL2_CPU_MASK_CLEAR);\n4035:\t\n4036:\t\t/* A link event latched while the interrupts were off is gone. Internal\n4037:\t\t * PHYs on GENET v1-v4 are not polled, so resync the state machine.\n4038:\t\t */\n4039:\t\tphy_mac_interrupt(dev-\u003ephydev);\n4040:\t\n4041:\t\tpriv-\u003edatapath_up = true;\n4042:\t\tnetif_device_attach(dev);\n4043:\t\n4044:\t\treturn ret;\n4045:\t}\n4046:\t\n4047:\tstatic const struct net_device_ops bcmgenet_netdev_ops = {\n4048:\t\t.ndo_open\t\t= bcmgenet_open,\n4049:\t\t.ndo_stop\t\t= bcmgenet_close,\n"
} |
| 15/2 | 2026/10/12 09:08 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 26158 output: 48 thoughts: 34 Thoughts: Okay, let's dive into this. Here's how I'd approach that snippet, considering my expertise: **Checking Specific Code Sections** Alright, the task is clear. I need to zero in on lines 4050-4150. My first instinct, given what I'm looking at, is to examine the functions `bcmgenet_match` and `bcmgenet_probe`. These function names are strong indicators. "bcmgenet" clearly points to Broadcom's Gigabit Ethernet driver. The inclusion of `match` and `probe` suggests this area is responsible for device detection and initialization within the driver. I expect `bcmgenet_match` to be the probe table's function that checks if a device is supported. And I anticipate `bcmgenet_probe` will actually initialize and register the device if a match is found. I need to understand how the hardware is being identified and managed during the driver's loading. I'll need to pay close attention to the data structures these functions interact with, as those are the keys to how the driver functions. Let's see what these snippets have in store. |
| 16/2 | 2026/10/12 09:08 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/genet/bcmgenet.c",
"FirstLine": 4050,
"LineCount": 80
}Results: {
"Contents": "4050:\t\t.ndo_start_xmit\t\t= bcmgenet_xmit,\n4051:\t\t.ndo_tx_timeout\t\t= bcmgenet_timeout,\n4052:\t\t.ndo_set_rx_mode\t= bcmgenet_set_rx_mode,\n4053:\t\t.ndo_set_mac_address\t= bcmgenet_set_mac_addr,\n4054:\t\t.ndo_eth_ioctl\t\t= phy_do_ioctl_running,\n4055:\t\t.ndo_set_features\t= bcmgenet_set_features,\n4056:\t\t.ndo_get_stats64\t= bcmgenet_get_stats64,\n4057:\t\t.ndo_change_carrier\t= bcmgenet_change_carrier,\n4058:\t\t.ndo_change_mtu\t\t= bcmgenet_change_mtu,\n4059:\t};\n4060:\t\n4061:\t/* GENET hardware parameters/characteristics */\n4062:\tstatic const struct bcmgenet_hw_params bcmgenet_hw_params_v1 = {\n4063:\t\t.tx_queues = 0,\n4064:\t\t.tx_bds_per_q = 0,\n4065:\t\t.rx_queues = 0,\n4066:\t\t.rx_bds_per_q = 0,\n4067:\t\t.bp_in_en_shift = 16,\n4068:\t\t.bp_in_mask = 0xffff,\n4069:\t\t.hfb_filter_cnt = 16,\n4070:\t\t.hfb_filter_size = 64,\n4071:\t\t.qtag_mask = 0x1F,\n4072:\t\t.hfb_offset = 0x1000,\n4073:\t\t.hfb_reg_offset = GENET_RBUF_OFF + RBUF_HFB_CTRL_V1,\n4074:\t\t.rdma_offset = 0x2000,\n4075:\t\t.tdma_offset = 0x3000,\n4076:\t\t.words_per_bd = 2,\n4077:\t};\n4078:\t\n4079:\tstatic const struct bcmgenet_hw_params bcmgenet_hw_params_v2 = {\n4080:\t\t.tx_queues = 4,\n4081:\t\t.tx_bds_per_q = 32,\n4082:\t\t.rx_queues = 0,\n4083:\t\t.rx_bds_per_q = 0,\n4084:\t\t.bp_in_en_shift = 16,\n4085:\t\t.bp_in_mask = 0xffff,\n4086:\t\t.hfb_filter_cnt = 16,\n4087:\t\t.hfb_filter_size = 64,\n4088:\t\t.qtag_mask = 0x1F,\n4089:\t\t.tbuf_offset = 0x0600,\n4090:\t\t.hfb_offset = 0x1000,\n4091:\t\t.hfb_reg_offset = 0x2000,\n4092:\t\t.rdma_offset = 0x3000,\n4093:\t\t.tdma_offset = 0x4000,\n4094:\t\t.words_per_bd = 2,\n4095:\t};\n4096:\t\n4097:\tstatic const struct bcmgenet_hw_params bcmgenet_hw_params_v3 = {\n4098:\t\t.tx_queues = 4,\n4099:\t\t.tx_bds_per_q = 32,\n4100:\t\t.rx_queues = 0,\n4101:\t\t.rx_bds_per_q = 0,\n4102:\t\t.bp_in_en_shift = 17,\n4103:\t\t.bp_in_mask = 0x1ffff,\n4104:\t\t.hfb_filter_cnt = 48,\n4105:\t\t.hfb_filter_size = 128,\n4106:\t\t.qtag_mask = 0x3F,\n4107:\t\t.tbuf_offset = 0x0600,\n4108:\t\t.hfb_offset = 0x8000,\n4109:\t\t.hfb_reg_offset = 0xfc00,\n4110:\t\t.rdma_offset = 0x10000,\n4111:\t\t.tdma_offset = 0x11000,\n4112:\t\t.words_per_bd = 2,\n4113:\t};\n4114:\t\n4115:\tstatic const struct bcmgenet_hw_params bcmgenet_hw_params_v4 = {\n4116:\t\t.tx_queues = 4,\n4117:\t\t.tx_bds_per_q = 32,\n4118:\t\t.rx_queues = 0,\n4119:\t\t.rx_bds_per_q = 0,\n4120:\t\t.bp_in_en_shift = 17,\n4121:\t\t.bp_in_mask = 0x1ffff,\n4122:\t\t.hfb_filter_cnt = 48,\n4123:\t\t.hfb_filter_size = 128,\n4124:\t\t.qtag_mask = 0x3F,\n4125:\t\t.tbuf_offset = 0x0600,\n4126:\t\t.hfb_offset = 0x8000,\n4127:\t\t.hfb_reg_offset = 0xfc00,\n4128:\t\t.rdma_offset = 0x2000,\n4129:\t\t.tdma_offset = 0x4000,\n"
} |
| 17/2 | 2026/10/12 09:08 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 28073 output: 48 thoughts: 19 Thoughts: Okay, I'm ready to dive into that text and synthesize those thoughts. Here's my take, assuming I'm an expert in this field, and speaking in the first person: **Analyzing the Specified Section** Alright, so the directive is to zero in on lines 4130 through 4250. My immediate thought is, "Okay, that's a specific chunk. What's the context, and what's the broader argument or dataset these lines are situated within?" I'm mentally filing away the potential for this to be a crucial turning point, a detailed illustration, or a tangent depending on the prior and subsequent lines. I'll need to remember to maintain my analytical framework. I'm expecting to either find something quite specific or maybe a longer piece of writing. The precise location is suggestive of a detailed illustration or a longer piece of writing. I'll need to keep a keen eye out. |
| 18/2 | 2026/10/12 09:08 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/genet/bcmgenet.c",
"FirstLine": 4130,
"LineCount": 80
}Results: {
"Contents": "4130:\t\t.words_per_bd = 3,\n4131:\t};\n4132:\t\n4133:\t/* Infer hardware parameters from the detected GENET version */\n4134:\tstatic void bcmgenet_set_hw_params(struct bcmgenet_priv *priv)\n4135:\t{\n4136:\t\tconst struct bcmgenet_hw_params *params;\n4137:\t\tu32 reg;\n4138:\t\tu8 major;\n4139:\t\tu16 gphy_rev;\n4140:\t\n4141:\t\t/* default to latest values */\n4142:\t\tparams = \u0026bcmgenet_hw_params_v4;\n4143:\t\tbcmgenet_dma_regs = bcmgenet_dma_regs_v3plus;\n4144:\t\tgenet_dma_ring_regs = genet_dma_ring_regs_v4;\n4145:\t\tif (GENET_IS_V3(priv)) {\n4146:\t\t\tparams = \u0026bcmgenet_hw_params_v3;\n4147:\t\t\tbcmgenet_dma_regs = bcmgenet_dma_regs_v3plus;\n4148:\t\t\tgenet_dma_ring_regs = genet_dma_ring_regs_v123;\n4149:\t\t} else if (GENET_IS_V2(priv)) {\n4150:\t\t\tparams = \u0026bcmgenet_hw_params_v2;\n4151:\t\t\tbcmgenet_dma_regs = bcmgenet_dma_regs_v2;\n4152:\t\t\tgenet_dma_ring_regs = genet_dma_ring_regs_v123;\n4153:\t\t} else if (GENET_IS_V1(priv)) {\n4154:\t\t\tparams = \u0026bcmgenet_hw_params_v1;\n4155:\t\t\tbcmgenet_dma_regs = bcmgenet_dma_regs_v1;\n4156:\t\t\tgenet_dma_ring_regs = genet_dma_ring_regs_v123;\n4157:\t\t}\n4158:\t\tpriv-\u003ehw_params = params;\n4159:\t\n4160:\t\t/* Read GENET HW version */\n4161:\t\treg = bcmgenet_sys_readl(priv, SYS_REV_CTRL);\n4162:\t\tmajor = (reg \u003e\u003e 24 \u0026 0x0f);\n4163:\t\tif (major == 6 || major == 7)\n4164:\t\t\tmajor = 5;\n4165:\t\telse if (major == 5)\n4166:\t\t\tmajor = 4;\n4167:\t\telse if (major == 0)\n4168:\t\t\tmajor = 1;\n4169:\t\tif (major != priv-\u003eversion) {\n4170:\t\t\tdev_err(\u0026priv-\u003epdev-\u003edev,\n4171:\t\t\t\t\"GENET version mismatch, got: %d, configured for: %d\\n\",\n4172:\t\t\t\tmajor, priv-\u003eversion);\n4173:\t\t}\n4174:\t\n4175:\t\t/* Print the GENET core version */\n4176:\t\tdev_info(\u0026priv-\u003epdev-\u003edev, \"GENET \" GENET_VER_FMT,\n4177:\t\t\t major, (reg \u003e\u003e 16) \u0026 0x0f, reg \u0026 0xffff);\n4178:\t\n4179:\t\t/* Store the integrated PHY revision for the MDIO probing function\n4180:\t\t * to pass this information to the PHY driver. The PHY driver expects\n4181:\t\t * to find the PHY major revision in bits 15:8 while the GENET register\n4182:\t\t * stores that information in bits 7:0, account for that.\n4183:\t\t *\n4184:\t\t * On newer chips, starting with PHY revision G0, a new scheme is\n4185:\t\t * deployed similar to the Starfighter 2 switch with GPHY major\n4186:\t\t * revision in bits 15:8 and patch level in bits 7:0. Major revision 0\n4187:\t\t * is reserved as well as special value 0x01ff, we have a small\n4188:\t\t * heuristic to check for the new GPHY revision and re-arrange things\n4189:\t\t * so the GPHY driver is happy.\n4190:\t\t */\n4191:\t\tgphy_rev = reg \u0026 0xffff;\n4192:\t\n4193:\t\tif (GENET_IS_V5(priv)) {\n4194:\t\t\t/* The EPHY revision should come from the MDIO registers of\n4195:\t\t\t * the PHY not from GENET.\n4196:\t\t\t */\n4197:\t\t\tif (gphy_rev != 0) {\n4198:\t\t\t\tpr_warn(\"GENET is reporting EPHY revision: 0x%04x\\n\",\n4199:\t\t\t\t\tgphy_rev);\n4200:\t\t\t}\n4201:\t\t/* This is reserved so should require special treatment */\n4202:\t\t} else if (gphy_rev == 0 || gphy_rev == 0x01ff) {\n4203:\t\t\tpr_warn(\"Invalid GPHY revision detected: 0x%04x\\n\", gphy_rev);\n4204:\t\t\treturn;\n4205:\t\t/* This is the good old scheme, just GPHY major, no minor nor patch */\n4206:\t\t} else if ((gphy_rev \u0026 0xf0) != 0) {\n4207:\t\t\tpriv-\u003egphy_rev = gphy_rev \u003c\u003c 8;\n4208:\t\t/* This is the new scheme, GPHY major rolls over with 0x10 = rev G0 */\n4209:\t\t} else if ((gphy_rev \u0026 0xff00) != 0) {\n"
} |
| 19/2 | 2026/10/12 09:08 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 29875 output: 48 thoughts: 25 Thoughts: Here's my analysis of the provided text, rendered in the first person, assuming I'm an expert in the field: **Digging into bcmgenet_probe** Alright, let's zero in on lines 4370 through 4440. My immediate thought is, this is where the `bcmgenet_probe` function is defined. I need to understand the initial probing process for this specific Broadcom Gigabit Ethernet driver. I'm looking for the essential steps it takes during device detection and initialization. This segment likely details the critical initial setup – resource allocation, possibly register access to configure the hardware, and definitely the driver's interaction with the underlying bus subsystem. I'm expecting to see calls to common kernel functions for memory mapping, interrupt registration, and perhaps some initial PHY configuration. The details here are crucial for understanding the driver's overall behavior and where potential issues might arise during device enumeration. I'm especially interested in any platform-specific quirks or workarounds in this section. My aim is to grasp the core mechanics of how this Ethernet adapter gets off the ground and integrates with the system. |
| 20/2 | 2026/10/12 09:08 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/genet/bcmgenet.c",
"FirstLine": 4370,
"LineCount": 75
}Results: {
"Contents": "4370:\t\t\t\tdevice_set_wakeup_capable(\u0026pdev-\u003edev, 1);\n4371:\t\t}\n4372:\t\n4373:\t\t/* Set the needed headroom to account for any possible\n4374:\t\t * features enabling/disabling at runtime\n4375:\t\t */\n4376:\t\tdev-\u003eneeded_headroom += 64;\n4377:\t\n4378:\t\tpriv-\u003edev = dev;\n4379:\t\tpriv-\u003epdev = pdev;\n4380:\t\n4381:\t\tpdata = device_get_match_data(\u0026pdev-\u003edev);\n4382:\t\tif (pdata) {\n4383:\t\t\tpriv-\u003eversion = pdata-\u003eversion;\n4384:\t\t\tpriv-\u003edma_max_burst_length = pdata-\u003edma_max_burst_length;\n4385:\t\t\tpriv-\u003eflags = pdata-\u003eflags;\n4386:\t\t}\n4387:\t\n4388:\t\tpriv-\u003eclk = devm_clk_get_optional(\u0026priv-\u003epdev-\u003edev, \"enet\");\n4389:\t\tif (IS_ERR(priv-\u003eclk)) {\n4390:\t\t\tdev_dbg(\u0026priv-\u003epdev-\u003edev, \"failed to get enet clock\\n\");\n4391:\t\t\terr = PTR_ERR(priv-\u003eclk);\n4392:\t\t\tgoto err;\n4393:\t\t}\n4394:\t\n4395:\t\terr = clk_prepare_enable(priv-\u003eclk);\n4396:\t\tif (err)\n4397:\t\t\tgoto err;\n4398:\t\n4399:\t\tbcmgenet_set_hw_params(priv);\n4400:\t\n4401:\t\terr = -EIO;\n4402:\t\tif (bcmgenet_has_40bits(priv))\n4403:\t\t\terr = dma_set_mask_and_coherent(\u0026pdev-\u003edev, DMA_BIT_MASK(40));\n4404:\t\tif (err)\n4405:\t\t\terr = dma_set_mask_and_coherent(\u0026pdev-\u003edev, DMA_BIT_MASK(32));\n4406:\t\tif (err)\n4407:\t\t\tgoto err_clk_disable;\n4408:\t\n4409:\t\t/* Mii wait queue */\n4410:\t\tinit_waitqueue_head(\u0026priv-\u003ewq);\n4411:\t\tbcmgenet_hfb_init(priv);\n4412:\t\n4413:\t\t/* v1 cannot program the thresholds, so it stays at the default MTU */\n4414:\t\tpriv-\u003erx_buf_len = bcmgenet_rx_buf_len(dev-\u003emtu);\n4415:\t\tif (!GENET_IS_V1(priv))\n4416:\t\t\tdev-\u003emax_mtu = ENET_MAX_JUMBO_MTU;\n4417:\t\tINIT_WORK(\u0026priv-\u003ebcmgenet_irq_work, bcmgenet_irq_task);\n4418:\t\n4419:\t\tpriv-\u003eclk_wol = devm_clk_get_optional(\u0026priv-\u003epdev-\u003edev, \"enet-wol\");\n4420:\t\tif (IS_ERR(priv-\u003eclk_wol)) {\n4421:\t\t\tdev_dbg(\u0026priv-\u003epdev-\u003edev, \"failed to get enet-wol clock\\n\");\n4422:\t\t\terr = PTR_ERR(priv-\u003eclk_wol);\n4423:\t\t\tgoto err_clk_disable;\n4424:\t\t}\n4425:\t\n4426:\t\tpriv-\u003eclk_eee = devm_clk_get_optional(\u0026priv-\u003epdev-\u003edev, \"enet-eee\");\n4427:\t\tif (IS_ERR(priv-\u003eclk_eee)) {\n4428:\t\t\tdev_dbg(\u0026priv-\u003epdev-\u003edev, \"failed to get enet-eee clock\\n\");\n4429:\t\t\terr = PTR_ERR(priv-\u003eclk_eee);\n4430:\t\t\tgoto err_clk_disable;\n4431:\t\t}\n4432:\t\n4433:\t\t/* If this is an internal GPHY, power it on now, before UniMAC is\n4434:\t\t * brought out of reset as absolutely no UniMAC activity is allowed\n4435:\t\t */\n4436:\t\tif (device_get_phy_mode(\u0026pdev-\u003edev) == PHY_INTERFACE_MODE_INTERNAL)\n4437:\t\t\tbcmgenet_power_up(priv, GENET_POWER_PASSIVE);\n4438:\t\n4439:\t\tif (device_get_ethdev_address(\u0026pdev-\u003edev, dev))\n4440:\t\t\tif (has_acpi_companion(\u0026pdev-\u003edev)) {\n4441:\t\t\t\tu8 addr[ETH_ALEN];\n4442:\t\n4443:\t\t\t\tbcmgenet_get_hw_addr(priv, addr);\n4444:\t\t\t\teth_hw_addr_set(dev, addr);\n"
} |
| 21/2 | 2026/10/12 09:08 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 31477 output: 48 thoughts: 22 Thoughts: Okay, let's dive into this code. **Diving Deep into `bcmgenet_probe` Before Line 4370** Alright, I need to understand what's happening within `bcmgenet_probe` before it reaches line 4370. This function is the crucial entry point for initializing the Broadcom Gigabit Ethernet driver, so a good understanding of its early actions is key. I'll need to trace the execution flow and identify the key operations it performs before that specific line. My guess is it's likely involved with resource allocation, device identification, and possibly basic hardware setup at this point. I'll start by checking the function's arguments to know what I'm looking at. Let's see... looking at the code I want to quickly identify the key variables that are going to get initialized before we get to 4370. |
| 22/2 | 2026/10/12 09:08 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/genet/bcmgenet.c",
"FirstLine": 4320,
"LineCount": 55
}Results: {
"Contents": "4320:\t\t\terr = priv-\u003eirq0;\n4321:\t\t\tgoto err;\n4322:\t\t}\n4323:\t\tpriv-\u003eirq1 = platform_get_irq(pdev, 1);\n4324:\t\tif (priv-\u003eirq1 \u003c 0) {\n4325:\t\t\terr = priv-\u003eirq1;\n4326:\t\t\tgoto err;\n4327:\t\t}\n4328:\t\tpriv-\u003ewol_irq = platform_get_irq_optional(pdev, 2);\n4329:\t\tif (priv-\u003ewol_irq == -EPROBE_DEFER) {\n4330:\t\t\terr = priv-\u003ewol_irq;\n4331:\t\t\tgoto err;\n4332:\t\t}\n4333:\t\n4334:\t\tpriv-\u003ebase = devm_platform_ioremap_resource(pdev, 0);\n4335:\t\tif (IS_ERR(priv-\u003ebase)) {\n4336:\t\t\terr = PTR_ERR(priv-\u003ebase);\n4337:\t\t\tgoto err;\n4338:\t\t}\n4339:\t\n4340:\t\tspin_lock_init(\u0026priv-\u003ereg_lock);\n4341:\t\tspin_lock_init(\u0026priv-\u003elock);\n4342:\t\n4343:\t\t/* Set default pause parameters */\n4344:\t\tpriv-\u003eautoneg_pause = 1;\n4345:\t\tpriv-\u003etx_pause = 1;\n4346:\t\tpriv-\u003erx_pause = 1;\n4347:\t\n4348:\t\tSET_NETDEV_DEV(dev, \u0026pdev-\u003edev);\n4349:\t\tdev_set_drvdata(\u0026pdev-\u003edev, dev);\n4350:\t\tdev-\u003ewatchdog_timeo = 2 * HZ;\n4351:\t\tdev-\u003eethtool_ops = \u0026bcmgenet_ethtool_ops;\n4352:\t\tdev-\u003enetdev_ops = \u0026bcmgenet_netdev_ops;\n4353:\t\n4354:\t\tpriv-\u003emsg_enable = netif_msg_init(-1, GENET_MSG_DEFAULT);\n4355:\t\n4356:\t\t/* Set default features */\n4357:\t\tdev-\u003efeatures |= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM |\n4358:\t\t\t\t NETIF_F_RXCSUM;\n4359:\t\tdev-\u003ehw_features |= dev-\u003efeatures;\n4360:\t\tdev-\u003evlan_features |= dev-\u003efeatures;\n4361:\t\n4362:\t\tnetdev_sw_irq_coalesce_default_on(dev);\n4363:\t\n4364:\t\t/* Request the WOL interrupt and advertise suspend if available */\n4365:\t\tpriv-\u003ewol_irq_disabled = true;\n4366:\t\tif (priv-\u003ewol_irq \u003e 0) {\n4367:\t\t\terr = devm_request_irq(\u0026pdev-\u003edev, priv-\u003ewol_irq,\n4368:\t\t\t\t\t bcmgenet_wol_isr, 0, dev-\u003ename, priv);\n4369:\t\t\tif (!err)\n4370:\t\t\t\tdevice_set_wakeup_capable(\u0026pdev-\u003edev, 1);\n4371:\t\t}\n4372:\t\n4373:\t\t/* Set the needed headroom to account for any possible\n4374:\t\t * features enabling/disabling at runtime\n"
} |
| 23/2 | 2026/10/12 09:08 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 32643 output: 48 thoughts: 14 Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person: **Analyzing the Pre-4320 Stage** Alright, I'm thinking, "Let's zero in on what's going down *before* line 4320." That line number feels significant, almost certainly marking some critical juncture in the code or data. I’m not just going to read blindly; I need to understand the *lead-up*. My mind is automatically running through possible scenarios. Is 4320 a function call, a data load, a conditional jump, or a major computation? Is there a loop involved? Understanding the execution path and data dependencies leading *to* that line is paramount. I'm mentally parsing the code, remembering relevant variable scopes, anticipating any potential edge cases or threading issues. I'm already formulating hypotheses about the state of things at that specific point. I need that context to effectively troubleshoot, optimize, or understand the system’s behavior. I am, in essence, trying to build a complete mental model of the system’s condition prior to hitting that milestone. |
| 24/2 | 2026/10/12 09:08 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/genet/bcmgenet.c",
"FirstLine": 4280,
"LineCount": 45
}Results: {
"Contents": "4280:\t\n4281:\tstatic const struct bcmgenet_plat_data bcm7712_plat_data = {\n4282:\t\t.version = GENET_V5,\n4283:\t\t.dma_max_burst_length = DMA_MAX_BURST_LENGTH,\n4284:\t\t.flags = GENET_HAS_40BITS | GENET_HAS_EXT |\n4285:\t\t\t GENET_HAS_MDIO_INTR | GENET_HAS_MOCA_LINK_DET |\n4286:\t\t\t GENET_HAS_EPHY_16NM,\n4287:\t};\n4288:\t\n4289:\tstatic const struct of_device_id bcmgenet_match[] = {\n4290:\t\t{ .compatible = \"brcm,genet-v1\", .data = \u0026v1_plat_data },\n4291:\t\t{ .compatible = \"brcm,genet-v2\", .data = \u0026v2_plat_data },\n4292:\t\t{ .compatible = \"brcm,genet-v3\", .data = \u0026v3_plat_data },\n4293:\t\t{ .compatible = \"brcm,genet-v4\", .data = \u0026v4_plat_data },\n4294:\t\t{ .compatible = \"brcm,genet-v5\", .data = \u0026v5_plat_data },\n4295:\t\t{ .compatible = \"brcm,bcm2711-genet-v5\", .data = \u0026bcm2711_plat_data },\n4296:\t\t{ .compatible = \"brcm,bcm7712-genet-v5\", .data = \u0026bcm7712_plat_data },\n4297:\t\t{ },\n4298:\t};\n4299:\tMODULE_DEVICE_TABLE(of, bcmgenet_match);\n4300:\t\n4301:\tstatic int bcmgenet_probe(struct platform_device *pdev)\n4302:\t{\n4303:\t\tconst struct bcmgenet_plat_data *pdata;\n4304:\t\tstruct bcmgenet_priv *priv;\n4305:\t\tstruct net_device *dev;\n4306:\t\tunsigned int i;\n4307:\t\tint err = -EIO;\n4308:\t\n4309:\t\t/* Up to GENET_MAX_MQ_CNT + 1 TX queues and RX queues */\n4310:\t\tdev = alloc_etherdev_mqs(sizeof(*priv), GENET_MAX_MQ_CNT + 1,\n4311:\t\t\t\t\t GENET_MAX_MQ_CNT + 1);\n4312:\t\tif (!dev) {\n4313:\t\t\tdev_err(\u0026pdev-\u003edev, \"can't allocate net device\\n\");\n4314:\t\t\treturn -ENOMEM;\n4315:\t\t}\n4316:\t\n4317:\t\tpriv = netdev_priv(dev);\n4318:\t\tpriv-\u003eirq0 = platform_get_irq(pdev, 0);\n4319:\t\tif (priv-\u003eirq0 \u003c 0) {\n4320:\t\t\terr = priv-\u003eirq0;\n4321:\t\t\tgoto err;\n4322:\t\t}\n4323:\t\tpriv-\u003eirq1 = platform_get_irq(pdev, 1);\n4324:\t\tif (priv-\u003eirq1 \u003c 0) {\n"
} |
| 25/2 | 2026/10/12 09:08 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 33844 output: 20 thoughts: 501 Thoughts: **Analyzing the Broadcom GENET Driver on x86_64**
Okay, so I'm looking at this `bcmgenet` driver, and it's pretty clear what it's expecting: hardware. It's matching Open Firmware ("brcm,genet-v1", etc.) and ACPI ("BCM6E4E") device IDs. The driver is pulling in interrupt resources (`irq0`, `irq1`) and, crucially, a memory-mapped base address (`priv->base`) using `devm_platform_ioremap_resource`. It's reading hardware registers directly with `bcmgenet_sys_readl`. All the breadcrumbs point to physical hardware interaction, nothing abstract, nothing virtual!
Now, the obvious questions come to mind: Can this be triggered in a standard emulated environment? My initial thought is QEMU, or even Google Compute Engine. Then it hits me... wait a second, isn't the Raspberry Pi 4 BCM2711? And what about QEMU supporting that architecture? Yes, QEMU does have `raspi4b` (aarch64), but it's emulating an ARM architecture, not x86_64. Crucially, I'm running QEMU on `amd64`. So the million dollar question: Does QEMU, on x86_64, actually emulate Broadcom GENET? The answer quickly presents itself: No! There's no Broadcom GENET device model for x86_64 in QEMU. This is a dead end.
Next thought process: Can userspace somehow force the instantiation of a platform device? Can `syzkaller` or root-level access create one? But hold on, the Linux kernel doesn't work that way. Platform devices are *only* created through device tree, ACPI, or explicit kernel platform device registration. Maybe some debugfs/configfs interface, but that's a long shot, and in any case, it's typically for "dummy" platform devices (like virtio-mmio) *if* the driver exposes it, and even then, there has to be some configuration. Even if someone were to somehow force `bcmgenet_probe` to run, without that valid MMIO mapping (`priv->base`), `bcmgenet_sys_readl` would be reading garbage or cause an immediate crash. So, the likelihood of a platform device being successfully created for `bcmgenet` on `amd64` seems vanishingly small!
Time to verify: let's do a quick search within the kernel source tree itself, focusing on `arch/x86` and other relevant directories. I'll search for "bcmgenet" and "BCM6E4E" and see if there are any indications that this driver is actually ever instantiated or used in any x86_64 configuration. If the code is never active, I can start looking for a different avenue.
|
| 26/2 | 2026/10/12 09:09 | tool | grepper |
0mArgs:{
"Expression": "BCM6E4E"
}Results: {
"Output": "drivers/net/ethernet/broadcom/genet/bcmgenet.c=4738=static const struct acpi_device_id genet_acpi_match[] = {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:4739:\t{ \"BCM6E4E\", (kernel_ulong_t)\u0026bcm2711_plat_data },\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-4740-\t{ },\n"
} |
| 27/2 | 2026/10/12 09:09 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 35147 output: 27 thoughts: 36 Thoughts: Okay, here's my interpretation of those thoughts, tailored for an expert audience, presented in the first person: **Investigating the BCM6E4E Identifier** Alright, so "BCM6E4E" is isolated to `bcmgenet.c` – that's the starting point. This suggests it's likely a hardware or driver-specific identifier, and the `bcmgenet` part seems pretty self-explanatory. Now, to get a better handle on its context and usage within the broader kernel architecture, I need to see *where* this `bcmgenet` string is actually referenced. A full kernel tree search is the next logical step; I'll need to use my preferred tools to get a full view of where that string is used to fully understand its context and meaning. This is just the first step in reverse engineering this portion of the code. |
| 28/2 | 2026/10/12 09:09 | tool | grepper |
0mError:no matches Args: {
"Expression": "bcmgenet",
"PathPrefixes": [
"arch/"
]
}Results: {
"error": "no matches"
} |
| 29/2 | 2026/10/12 09:09 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 35412 output: 27 thoughts: 32 Thoughts: Here's my thought process, as if I were analyzing this code: **Finding the BCMGENET References** Okay, so I've quickly scanned the `arch/` directory, and it's immediately clear there's no code related to "bcmgenet" in there. That's not entirely surprising, but it means I need to broaden my search. It could be in a driver directory, a platform-specific section, or even a more generic networking area. My next move is obvious: I need to perform a full-tree search for the string "bcmgenet". This is the most efficient way to get a comprehensive understanding of where this module is being used, where it's being configured, and where its functions might be defined. It'll give me a list of all files that mention the keyword. From there, I can analyze the context surrounding each mention and determine its role within the project. This is a critical first step. I need this overview. |
| 30/2 | 2026/10/12 09:09 | tool | grepper |
0mArgs:{
"Expression": "bcmgenet",
"PathPrefixes": [
"drivers/"
]
}Results: {
"Output": "\nFull output is too long, showing 200 out of 2765 lines.\nUse more precise expression or PathPrefixes if possible.\n\nNumber of matching lines per file (5 files in total):\ndrivers/net/ethernet/broadcom/genet/Makefile:1\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:755\ndrivers/net/ethernet/broadcom/genet/bcmgenet.h:56\ndrivers/net/ethernet/broadcom/genet/bcmgenet_wol.c:38\ndrivers/net/ethernet/broadcom/genet/bcmmii.c:64\n\ndrivers/net/ethernet/broadcom/genet/Makefile=2=obj-$(CONFIG_BCMGENET) += genet.o\ndrivers/net/ethernet/broadcom/genet/Makefile:3:genet-objs := bcmgenet.o bcmmii.o bcmgenet_wol.o\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-7-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:8:#define pr_fmt(fmt)\t\t\t\t\"bcmgenet: \" fmt\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-9-\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-40-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:41:#include \"bcmgenet.h\"\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-42-\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-100-/* Forward declarations */\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:101:static void bcmgenet_set_rx_mode(struct net_device *dev);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-102-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:103:static inline void bcmgenet_writel(u32 value, void __iomem *offset)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-104-{\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-113-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:114:static inline u32 bcmgenet_readl(void __iomem *offset)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-115-{\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-121-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:122:static inline void dmadesc_set_length_status(struct bcmgenet_priv *priv,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-123-\t\t\t\t\t void __iomem *d, u32 value)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-124-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:125:\tbcmgenet_writel(value, d + DMA_DESC_LENGTH_STATUS);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-126-}\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-127-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:128:static inline void dmadesc_set_addr(struct bcmgenet_priv *priv,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-129-\t\t\t\t void __iomem *d,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-131-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:132:\tbcmgenet_writel(lower_32_bits(addr), d + DMA_DESC_ADDRESS_LO);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-133-\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-138-#ifdef CONFIG_PHYS_ADDR_T_64BIT\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:139:\tif (bcmgenet_has_40bits(priv))\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:140:\t\tbcmgenet_writel(upper_32_bits(addr), d + DMA_DESC_ADDRESS_HI);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-141-#endif\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-144-/* Combined address + length/status setter */\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:145:static inline void dmadesc_set(struct bcmgenet_priv *priv,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-146-\t\t\t void __iomem *d, dma_addr_t addr, u32 val)\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-156-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:157:static inline u32 bcmgenet_rbuf_ctrl_get(struct bcmgenet_priv *priv)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-158-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-159-\tif (GENET_IS_V1(priv))\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:160:\t\treturn bcmgenet_rbuf_readl(priv, RBUF_FLUSH_CTRL_V1);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-161-\telse\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:162:\t\treturn bcmgenet_sys_readl(priv, SYS_RBUF_FLUSH_CTRL);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-163-}\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-164-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:165:static inline void bcmgenet_rbuf_ctrl_set(struct bcmgenet_priv *priv, u32 val)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-166-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-167-\tif (GENET_IS_V1(priv))\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:168:\t\tbcmgenet_rbuf_writel(priv, val, RBUF_FLUSH_CTRL_V1);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-169-\telse\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:170:\t\tbcmgenet_sys_writel(priv, val, SYS_RBUF_FLUSH_CTRL);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-171-}\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-176- */\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:177:static inline u32 bcmgenet_tbuf_ctrl_get(struct bcmgenet_priv *priv)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-178-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-179-\tif (GENET_IS_V1(priv))\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:180:\t\treturn bcmgenet_rbuf_readl(priv, TBUF_CTRL_V1);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-181-\telse\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:182:\t\treturn bcmgenet_readl(priv-\u003ebase +\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-183-\t\t\t\t priv-\u003ehw_params-\u003etbuf_offset + TBUF_CTRL);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-185-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:186:static inline void bcmgenet_tbuf_ctrl_set(struct bcmgenet_priv *priv, u32 val)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-187-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-188-\tif (GENET_IS_V1(priv))\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:189:\t\tbcmgenet_rbuf_writel(priv, val, TBUF_CTRL_V1);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-190-\telse\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:191:\t\tbcmgenet_writel(val, priv-\u003ebase +\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-192-\t\t\t\tpriv-\u003ehw_params-\u003etbuf_offset + TBUF_CTRL);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-194-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:195:static inline u32 bcmgenet_bp_mc_get(struct bcmgenet_priv *priv)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-196-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-197-\tif (GENET_IS_V1(priv))\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:198:\t\treturn bcmgenet_rbuf_readl(priv, TBUF_BP_MC_V1);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-199-\telse\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:200:\t\treturn bcmgenet_readl(priv-\u003ebase +\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-201-\t\t\t\t priv-\u003ehw_params-\u003etbuf_offset + TBUF_BP_MC);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-203-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:204:static inline void bcmgenet_bp_mc_set(struct bcmgenet_priv *priv, u32 val)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-205-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-206-\tif (GENET_IS_V1(priv))\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:207:\t\tbcmgenet_rbuf_writel(priv, val, TBUF_BP_MC_V1);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-208-\telse\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:209:\t\tbcmgenet_writel(val, priv-\u003ebase +\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-210-\t\t\t\tpriv-\u003ehw_params-\u003etbuf_offset + TBUF_BP_MC);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=214=enum dma_reg {\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-249-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:250:static const u8 bcmgenet_dma_regs_v3plus[] = {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-251-\t[DMA_RING_CFG]\t\t= 0x00,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-285-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:286:static const u8 bcmgenet_dma_regs_v2[] = {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-287-\t[DMA_RING_CFG]\t\t= 0x00,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-313-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:314:static const u8 bcmgenet_dma_regs_v1[] = {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-315-\t[DMA_CTRL]\t\t= 0x00,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-340-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:341:/* Set at runtime once bcmgenet version is known */\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:342:static const u8 *bcmgenet_dma_regs;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-343-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:344:static inline struct bcmgenet_priv *dev_to_priv(struct device *dev)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-345-{\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-348-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:349:static inline u32 bcmgenet_tdma_readl(struct bcmgenet_priv *priv,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-350-\t\t\t\t enum dma_reg r)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-351-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:352:\treturn bcmgenet_readl(priv-\u003ebase + GENET_TDMA_REG_OFF +\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:353:\t\t\t DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-354-}\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-355-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:356:static inline void bcmgenet_tdma_writel(struct bcmgenet_priv *priv,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-357-\t\t\t\t\tu32 val, enum dma_reg r)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-358-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:359:\tbcmgenet_writel(val, priv-\u003ebase + GENET_TDMA_REG_OFF +\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:360:\t\t\tDMA_RINGS_SIZE + bcmgenet_dma_regs[r]);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-361-}\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-362-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:363:static inline u32 bcmgenet_rdma_readl(struct bcmgenet_priv *priv,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-364-\t\t\t\t enum dma_reg r)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-365-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:366:\treturn bcmgenet_readl(priv-\u003ebase + GENET_RDMA_REG_OFF +\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:367:\t\t\t DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-368-}\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-369-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:370:static inline void bcmgenet_rdma_writel(struct bcmgenet_priv *priv,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-371-\t\t\t\t\tu32 val, enum dma_reg r)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-372-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:373:\tbcmgenet_writel(val, priv-\u003ebase + GENET_RDMA_REG_OFF +\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:374:\t\t\tDMA_RINGS_SIZE + bcmgenet_dma_regs[r]);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-375-}\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=438=static const u8 *genet_dma_ring_regs;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-439-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:440:static inline u32 bcmgenet_tdma_ring_readl(struct bcmgenet_priv *priv,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-441-\t\t\t\t\t unsigned int ring,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-443-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:444:\treturn bcmgenet_readl(priv-\u003ebase + GENET_TDMA_REG_OFF +\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-445-\t\t\t (DMA_RING_SIZE * ring) +\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-448-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:449:static inline void bcmgenet_tdma_ring_writel(struct bcmgenet_priv *priv,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-450-\t\t\t\t\t unsigned int ring, u32 val,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-452-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:453:\tbcmgenet_writel(val, priv-\u003ebase + GENET_TDMA_REG_OFF +\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-454-\t\t\t(DMA_RING_SIZE * ring) +\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-457-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:458:static inline u32 bcmgenet_rdma_ring_readl(struct bcmgenet_priv *priv,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-459-\t\t\t\t\t unsigned int ring,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-461-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:462:\treturn bcmgenet_readl(priv-\u003ebase + GENET_RDMA_REG_OFF +\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-463-\t\t\t (DMA_RING_SIZE * ring) +\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-466-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:467:static inline void bcmgenet_rdma_ring_writel(struct bcmgenet_priv *priv,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-468-\t\t\t\t\t unsigned int ring, u32 val,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-470-{\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:471:\tbcmgenet_writel(val, priv-\u003ebase + GENET_RDMA_REG_OFF +\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-472-\t\t\t(DMA_RING_SIZE * ring) +\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-475-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:476:static void bcmgenet_hfb_enable_filter(struct bcmgenet_priv *priv, u32 f_index)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-477-{\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-481-\tif (GENET_IS_V1(priv) || GENET_IS_V2(priv)) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:482:\t\treg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-483-\t\treg |= (1 \u003c\u003c ((f_index % 32) + RBUF_HFB_FILTER_EN_SHIFT)) |\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-484-\t\t\tRBUF_HFB_EN;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:485:\t\tbcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-486-\t} else {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-487-\t\toffset = HFB_FLT_ENABLE_V3PLUS + (f_index \u003c 32) * sizeof(u32);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:488:\t\treg = bcmgenet_hfb_reg_readl(priv, offset);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-489-\t\treg |= (1 \u003c\u003c (f_index % 32));\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:490:\t\tbcmgenet_hfb_reg_writel(priv, reg, offset);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:491:\t\treg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-492-\t\treg |= RBUF_HFB_EN;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:493:\t\tbcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-494-\t}\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-496-\n\n"
} |
| 31/2 | 2026/10/12 09:09 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 42153 output: 131 thoughts: 1241 Thoughts: **Analysis of bcmgenet for Fuzzing Suitability** Okay, let's break this down. `bcmgenet` is a device driver. Specifically, it's for Broadcom's GENET internal MAC, the kind you find built into their BCM7xxx set-top box chips and the BCM2711 on the Raspberry Pi 4. This is a SoC/platform device, not PCI, USB, or anything virtual. The question is, can I even *run* this on an amd64 setup, like in QEMU or Google Compute Engine? No. Absolutely not. QEMU, on x86_64 or amd64, doesn't emulate any of the Broadcom GENET hardware. Not as a platform device, not even an ACPI entry like the BCM6E4E. Can ACPI or anything probe it in the standard QEMU / GCE environment? Nope. QEMU's ACPI tables only instantiate standard PC devices, or virtio devices. Never anything Broadcom specific. Furthermore, `bcmgenet` relies heavily on memory-mapped I/O registers at specific SoC physical addresses. It grabs these using `devm_platform_ioremap_resource` and needs interrupts configured with `platform_get_irq`. Then, it's talking directly to the hardware via reads to registers like `bcmgenet_sys_readl`. Even if, by some miracle, I could mock up a platform device via sysfs (which syzkaller *doesn't* do, and requires root access), it would immediately fail during probe. It would either error out with `-EINVAL`/`-ENXIO` on the `platform_get_irq` or `devm_platform_ioremap_resource` calls and that's it, probe failed! The modified code bits are all internal driver functions: `bcmgenet_xmit`, `bcmgenet_desc_rx`, `bcmgenet_add_frag`, and others. They're all driver callbacks. These functions *require* the device to be probed, the netdev registered, and up and running. Alright, let's go back and carefully analyze the Reachability instructions. The core triage philosophy is Reachability as the primary gate. If the code can't execute in standard virtualized environments, it shouldn't be fuzzed. The key negative criteria says: "Structurally unreachable hardware". This *perfectly* describes this situation. Broadcom GENET requires a Broadcom SoC. QEMU and GCE *don't* emulate that. They're not going to. The target architecture is amd64. `bcmgenet` is a platform driver for Broadcom SoC Ethernet MACs. It's structurally unreachable hardware on amd64 in QEMU because it relies on Broadcom SoC hardware/ASIC not emulated in standard QEMU or GCE. Could I somehow reach it via a virtual interface? No, it's a physical Ethernet NIC. Could I reach it on amd64? No. Even on ARM/MIPS, standard QEMU fuzzing VMs don't emulate GENET (and the target architecture is amd64). The code is *structurally* unreachable. So, the schema for `set-results`: * `WorthFuzzing`: false * `Reasoning`: Broadcom GENET is a platform driver for Broadcom SoC Ethernet MACs (e.g. BCM7xxx STB and BCM2711), requiring specific physical SoC hardware that is not emulated in standard QEMU or GCE virtualized environments on amd64. * `FocusSymbols`: \[ ] * `EnableConfigs`: \[ ] That seems right. Empty lists for `FocusSymbols` and `EnableConfigs` since `WorthFuzzing` is `false`. Ready to call `set-results`. |
| 32/2 | 2026/10/12 09:09 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch modifies the Broadcom GENET Ethernet driver (drivers/net/ethernet/broadcom/genet/), which is a platform driver for built-in Ethernet MACs on Broadcom SoCs (such as BCM7xxx and BCM2711). This requires specific physical SoC hardware that is not present or emulated in standard virtualized environments (QEMU/GCE) on the target architecture (amd64). Thus, the modified code is structurally unreachable.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies the Broadcom GENET Ethernet driver (drivers/net/ethernet/broadcom/genet/), which is a platform driver for built-in Ethernet MACs on Broadcom SoCs (such as BCM7xxx and BCM2711). This requires specific physical SoC hardware that is not present or emulated in standard virtualized environments (QEMU/GCE) on the target architecture (amd64). Thus, the modified code is structurally unreachable.",
"WorthFuzzing": false
} |
| 33/1 | 2026/10/12 09:09 | action | If |
0mArgs:{
"WorthFuzzing": false
}Results: null |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|