| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/10/03 04:21 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"KMSANReasoning": "",
"NeedsKMSAN": false,
"Reasoning": "The patch modifies the Broadcom GENET Ethernet MAC driver (drivers/net/ethernet/broadcom/genet/bcmgenet.c and bcmgenet.h). BCMGENET is a platform driver designed for integrated MACs found on Broadcom SoCs (such as BCM7xxx and BCM2711). It requires physical hardware/MMIO resources that are not present or emulated in standard virtualized environments (QEMU or GCE on amd64). Consequently, the modified code is structurally unreachable for syzkaller fuzzing on the target architecture.",
"WorthFuzzing": false
} |
| 1/1 | 2026/10/03 04:21 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 90a8bf8806629a40793a967db564a956b7d27ef3\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Sat Oct 3 04:21:44 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..62edbe51fe076 100644\n--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c\n+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c\n@@ -48,17 +48,42 @@\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 */\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+/* A descriptor is one page, which also holds skb_shared_info behind the frame,\n+ * so on 4K pages the page bounds the threshold before the register does.\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-/* 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+/* 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@@ -2148,6 +2173,31 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)\n \t\tgoto out;\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\tret = NETDEV_TX_OK;\n+\t\t\tgoto out;\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\tret = NETDEV_TX_OK;\n+\t\t\tgoto out;\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@@ -2252,7 +2302,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 +2317,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 +2328,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@@ -2329,6 +2427,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 +2440,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 +2465,32 @@ 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 */\n+\t\tmin_len = dma_flag \u0026 DMA_SOP ? GENET_RSB_PAD\n+\t\t\t\t\t : sizeof(struct status_64);\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\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 +2520,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,6 +2552,13 @@ 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 (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+\n \t\tif (priv-\u003ecrc_fwd_en) {\n \t\t\tskb_trim(skb, skb-\u003elen - ETH_FCS_LEN);\n \t\t}\n@@ -2548,6 +2677,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 +2748,62 @@ 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, but not the status block, which the hardware adds on top.\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+\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_MAX_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 +2820,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 +2926,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_MAX_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 +2936,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@@ -2832,7 +3019,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@@ -3348,7 +3535,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 +3552,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 +3616,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 +3677,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 +3929,66 @@ 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+\tif (!netif_running(dev)) {\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+\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 +4000,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 +4354,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@@ -4312,7 +4571,7 @@ 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 \tnetif_device_attach(dev);\n \ndiff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h\nindex 86f2aed20dbe8..0f31ad2f280d1 100644\n--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h\n+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h\n@@ -28,13 +28,14 @@\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 */\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 #define DMA_MAX_BURST_LENGTH 0x10\n \n /* misc. configuration */\n@@ -219,6 +220,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 +252,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 +579,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 +619,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 +632,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/03 04:21 | agent | patch-evaluator |
0mModel:core Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies the Broadcom GENET Ethernet MAC driver (drivers/net/ethernet/broadcom/genet/bcmgenet.c and bcmgenet.h). BCMGENET is a platform driver designed for integrated MACs found on Broadcom SoCs (such as BCM7xxx and BCM2711). It requires physical hardware/MMIO resources that are not present or emulated in standard virtualized environments (QEMU or GCE on amd64). Consequently, the modified code is structurally unreachable for syzkaller fuzzing on the target architecture.",
"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 90a8bf8806629a40793a967db564a956b7d27ef3
Author: syz-cluster <triage@syzkaller.com>
Date: Sat Oct 3 04:21:44 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..62edbe51fe076 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -48,17 +48,42 @@
#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.
*/
-#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)
+
+/* A descriptor is one page, which also holds skb_shared_info behind the frame,
+ * so on 4K pages the page bounds the threshold before the register does.
+ */
+#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)
-/* RX buffer plus the skb_shared_info napi_build_skb() places behind it */
-#define GENET_RX_BUF_SIZE SKB_HEAD_ALIGN(RX_BUF_LENGTH)
+/* 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)
@@ -2148,6 +2173,31 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
goto out;
}
+ /* 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);
+ ret = NETDEV_TX_OK;
+ goto out;
+ }
+ }
+
+ /* 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);
+ ret = NETDEV_TX_OK;
+ goto out;
+ }
+ }
+
+ nr_frags = skb_shinfo(skb)->nr_frags;
+
/* Retain how many bytes will be sent on the wire, without TSB inserted
* by transmit checksum offload
*/
@@ -2252,7 +2302,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 +2317,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 +2328,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.
*/
@@ -2329,6 +2427,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 +2440,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 +2465,32 @@ 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 */
+ min_len = dma_flag & DMA_SOP ? GENET_RSB_PAD
+ : sizeof(struct status_64);
+
/* 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);
page_pool_put_full_page(ring->page_pool, rx_page,
true);
goto next;
@@ -2408,17 +2520,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,6 +2552,13 @@ 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 (unlikely(!(dma_flag & DMA_EOP))) {
+ ring->frag_head = skb;
+ goto next;
+ }
+
+deliver:
+
if (priv->crc_fwd_en) {
skb_trim(skb, skb->len - ETH_FCS_LEN);
}
@@ -2548,6 +2677,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 +2748,62 @@ 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, but not the status block, which the hardware adds on top.
+ */
+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;
+
+ 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_MAX_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 +2820,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 +2926,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_MAX_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 +2936,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,
@@ -2832,7 +3019,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) |
@@ -3348,7 +3535,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 +3552,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 +3616,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 +3677,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 +3929,66 @@ 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;
+
+ if (!netif_running(dev)) {
+ 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);
+
+ 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 +4000,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 +4354,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");
@@ -4312,7 +4571,7 @@ 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);
netif_device_attach(dev);
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
index 86f2aed20dbe8..0f31ad2f280d1 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -28,13 +28,14 @@
/* 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 */
+#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)
+
#define DMA_MAX_BURST_LENGTH 0x10
/* misc. configuration */
@@ -219,6 +220,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 +252,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 +579,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 +619,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 +632,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/03 04:21 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 10983 output: 38 thoughts: 149 Thoughts: **Analyzing a Syzkaller Patch for Broadcom GENET Fuzzing on amd64** Okay, so I need to evaluate a patch for syzkaller, specifically targeting fuzzing improvements. The architecture is amd64, so that's the starting point. My initial thought is to zero in on the modified driver, which is `drivers/net/ethernet/broadcom/genet/bcmgenet.c` and `bcmgenet.h`. Right, Broadcom GENET - that's a Gigabit Ethernet controller driver. First, let's verify if this is even a viable target in the common virtualized environments like GCE or QEMU on amd64. I need to understand if this hardware is accessible or emulated sufficiently. I'll need to check the Kconfig entry for `BCMGENET` – look at its bus types, any architecture dependencies, and any hints about virtualizability. Time to either jump into some quick greps or delve into the Kconfig details. Let's see what the configuration reveals. |
| 4/2 | 2026/10/03 04:22 | tool | grepper |
0mError:no matches Args: {
"Expression": "config BCMGENET",
"PathPrefix": "drivers/net/ethernet/broadcom/genet/"
}Results: {
"error": "no matches"
} |
| 5/2 | 2026/10/03 04:22 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 11409 output: 34 thoughts: 24 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Hunting for the Kconfig File** Okay, so I need to configure something related to a Broadcom Ethernet driver. The most logical place to start is the `Kconfig` file, naturally. Let me consider where that's likely to reside. Given the typical kernel directory structure, it's most likely under `drivers/net/ethernet/broadcom/` or perhaps in `broadcom/genet/` if it's a more specific or generic Broadcom Ethernet driver. I’ll start by checking those two directories. The module configuration usually defines the Kconfig. I want to make sure I find the proper source. |
| 6/2 | 2026/10/03 04:22 | tool | grepper |
0mArgs:{
"Expression": "BCMGENET",
"PathPrefix": "drivers/net/ethernet/broadcom/"
}Results: {
"Output": "\nFull output is too long, showing 200 out of 253 lines.\nUse more precise expression if possible.\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=630=static void bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-730-\tbcmgenet_hfb_enable_filter(priv, f);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:731:\trule-\u003estate = BCMGENET_RXNFC_STATE_ENABLED;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-732-}\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=771=static void bcmgenet_hfb_init(struct bcmgenet_priv *priv)\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-777-\t\tINIT_LIST_HEAD(\u0026priv-\u003erxnfc_rules[i].list);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:778:\t\tpriv-\u003erxnfc_rules[i].state = BCMGENET_RXNFC_STATE_UNUSED;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-779-\t}\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=782=static void bcmgenet_hfb_restore(struct bcmgenet_priv *priv)\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-788-\tlist_for_each_entry(rule, \u0026priv-\u003erxnfc_list, list)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:789:\t\tif (rule-\u003estate != BCMGENET_RXNFC_STATE_UNUSED)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-790-\t\t\tbcmgenet_hfb_create_rxnfc_filter(priv, rule);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1013=enum bcmgenet_stat_type {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1014:\tBCMGENET_STAT_RTNL = -1,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1015:\tBCMGENET_STAT_MIB_RX,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1016:\tBCMGENET_STAT_MIB_TX,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1017:\tBCMGENET_STAT_RUNT,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1018:\tBCMGENET_STAT_MISC,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1019:\tBCMGENET_STAT_SOFT,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1020:\tBCMGENET_STAT_SOFT64,\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1021-};\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1023=struct bcmgenet_stats {\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1037-\t.stat_offset = offsetof(struct rtnl_link_stats64, m), \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1038:\t.type = BCMGENET_STAT_RTNL, \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1039-}\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1051-\t.stat_offset = offsetof(struct bcmgenet_priv, s.m), \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1052:\t.type = BCMGENET_STAT_SOFT64, \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1053-\t.syncp_offset = offsetof(struct bcmgenet_priv, s.syncp), \\\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1055-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1056:#define STAT_GENET_MIB_RX(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_MIB_RX)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1057:#define STAT_GENET_MIB_TX(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_MIB_TX)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1058:#define STAT_GENET_RUNT(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_RUNT)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1059:#define STAT_GENET_SOFT_MIB(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_SOFT)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1060-\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1064-\t.stat_offset = offsetof(struct bcmgenet_priv, m), \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1065:\t.type = BCMGENET_STAT_MISC, \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1066-\t.reg_offset = offset, \\\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1105- */\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1106:#define BCMGENET_STAT_OFFSET\t0xc\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1107-\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1111=static const struct bcmgenet_stats bcmgenet_gstrings_stats[] = {\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1210-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1211:#define BCMGENET_STATS_LEN\tARRAY_SIZE(bcmgenet_gstrings_stats)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1212-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1213:#define BCMGENET_STATS64_ADD(stats, m, v) \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1214-\tdo { \\\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1219-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1220:#define BCMGENET_STATS64_INC(stats, m) \\\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1221-\tdo { \\\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1233=static int bcmgenet_get_sset_count(struct net_device *dev, int string_set)\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1236-\tcase ETH_SS_STATS:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1237:\t\treturn BCMGENET_STATS_LEN;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1238-\tdefault:\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1243=static void bcmgenet_get_strings(struct net_device *dev, u32 stringset,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1250-\tcase ETH_SS_STATS:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1251:\t\tfor (i = 0; i \u003c BCMGENET_STATS_LEN; i++) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1252-\t\t\tstr = bcmgenet_gstrings_stats[i].stat_string;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1298=static void bcmgenet_update_mib_counters(struct bcmgenet_priv *priv)\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1301-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1302:\tfor (i = 0; i \u003c BCMGENET_STATS_LEN; i++) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1303-\t\tconst struct bcmgenet_stats *s;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1309-\t\tswitch (s-\u003etype) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1310:\t\tcase BCMGENET_STAT_RTNL:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1311:\t\tcase BCMGENET_STAT_SOFT:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1312:\t\tcase BCMGENET_STAT_SOFT64:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1313-\t\t\tcontinue;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1314:\t\tcase BCMGENET_STAT_RUNT:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1315:\t\t\toffset += BCMGENET_STAT_OFFSET;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1316-\t\t\tfallthrough;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1317:\t\tcase BCMGENET_STAT_MIB_TX:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1318:\t\t\toffset += BCMGENET_STAT_OFFSET;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1319-\t\t\tfallthrough;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1320:\t\tcase BCMGENET_STAT_MIB_RX:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1321-\t\t\tval = bcmgenet_umac_readl(priv,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1324-\t\t\tbreak;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1325:\t\tcase BCMGENET_STAT_MISC:\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1326-\t\t\tif (GENET_IS_V1(priv)) {\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1345=static void bcmgenet_get_ethtool_stats(struct net_device *dev,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1359-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1360:\tfor (i = 0; i \u003c BCMGENET_STATS_LEN; i++) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1361-\t\tconst struct bcmgenet_stats *s;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1366-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1367:\t\tif (s-\u003etype == BCMGENET_STAT_SOFT64) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1368-\t\t\tsyncp = (struct u64_stats_sync *)(p + s-\u003esyncp_offset);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1373-\t\t} else {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1374:\t\t\tif (s-\u003etype == BCMGENET_STAT_RTNL)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1375-\t\t\t\tp = (char *)\u0026stats64;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1531=static int bcmgenet_insert_flow(struct net_device *dev,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1565-\t\t\tloc_rule = \u0026priv-\u003erxnfc_rules[i];\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1566:\t\t\tif (loc_rule-\u003estate == BCMGENET_RXNFC_STATE_UNUSED) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1567-\t\t\t\tcmd-\u003efs.location = i;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1577-\t}\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1578:\tif (loc_rule-\u003estate == BCMGENET_RXNFC_STATE_ENABLED)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1579-\t\tbcmgenet_hfb_disable_filter(priv, cmd-\u003efs.location + 1);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1580:\tif (loc_rule-\u003estate != BCMGENET_RXNFC_STATE_UNUSED) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1581-\t\tlist_del(\u0026loc_rule-\u003elist);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1583-\t}\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1584:\tloc_rule-\u003estate = BCMGENET_RXNFC_STATE_UNUSED;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1585-\tmemcpy(\u0026loc_rule-\u003efs, \u0026cmd-\u003efs,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1595=static int bcmgenet_delete_flow(struct net_device *dev,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1605-\trule = \u0026priv-\u003erxnfc_rules[cmd-\u003efs.location];\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1606:\tif (rule-\u003estate == BCMGENET_RXNFC_STATE_UNUSED) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1607-\t\terr = -ENOENT;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1610-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1611:\tif (rule-\u003estate == BCMGENET_RXNFC_STATE_ENABLED)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1612-\t\tbcmgenet_hfb_disable_filter(priv, cmd-\u003efs.location + 1);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1613:\tif (rule-\u003estate != BCMGENET_RXNFC_STATE_UNUSED) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1614-\t\tlist_del(\u0026rule-\u003elist);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1616-\t}\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1617:\trule-\u003estate = BCMGENET_RXNFC_STATE_UNUSED;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1618-\tmemset(\u0026rule-\u003efs, 0, sizeof(struct ethtool_rx_flow_spec));\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=1645=static int bcmgenet_get_flow(struct net_device *dev, struct ethtool_rxnfc *cmd,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1655-\trule = \u0026priv-\u003erxnfc_rules[loc];\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:1656:\tif (rule-\u003estate == BCMGENET_RXNFC_STATE_UNUSED)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-1657-\t\terr = -ENOENT;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=2080=static struct sk_buff *bcmgenet_add_tsb(struct net_device *dev,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2100-\t\t\tpriv-\u003emib.tx_realloc_tsb_failed++;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:2101:\t\t\tBCMGENET_STATS64_INC(stats, dropped);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2102-\t\t\treturn NULL;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=2147=static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2181-\t\tif (skb_checksum_help(skb)) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:2182:\t\t\tBCMGENET_STATS64_INC((\u0026ring-\u003estats64), dropped);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2183-\t\t\tdev_kfree_skb_any(skb);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2192-\t\tif (skb_put_padto(skb, priv-\u003etx_thld_len + ENET_TX_SAFE_MARGIN)) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:2193:\t\t\tBCMGENET_STATS64_INC((\u0026ring-\u003estats64), dropped);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2194-\t\t\tret = NETDEV_TX_OK;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=2351=static struct sk_buff *bcmgenet_add_frag(struct bcmgenet_rx_ring *ring,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2360-\tif (unlikely(skb_shinfo(head)-\u003enr_frags \u003e= MAX_SKB_FRAGS)) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:2361:\t\tBCMGENET_STATS64_INC((\u0026ring-\u003estats64), fragmented_errors);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2362-\t\tbcmgenet_discard_frags(ring);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c=2382=static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2407-\t\tdiscards = discards - ring-\u003eold_discards;\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:2408:\t\tBCMGENET_STATS64_ADD(stats, missed, discards);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2409-\t\tring-\u003eold_discards += discards;\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2441-\t\tif (bcmgenet_rx_refill(ring, cb)) {\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:2442:\t\t\tBCMGENET_STATS64_INC(stats, dropped);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2443-\t\t\tbcmgenet_discard_frags(ring);\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-2475-\t\t\t\t \"invalid packet length %d\\n\", len);\n\n"
} |
| 7/2 | 2026/10/03 04:22 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 17664 output: 39 thoughts: 24 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Investigating Broadcom Ethernet Driver Configuration** Okay, I need to pinpoint something related to the Broadcom Ethernet driver configuration. My initial thought is to navigate to the `drivers/net/ethernet/broadcom/Kconfig` file. I'm specifically targeting around line 72, as that's often where the core driver options or perhaps relevant feature flags are defined. This file is the key to understanding how the Broadcom Ethernet driver is compiled and configured. Let me quickly examine it to see what I can find at that location. |
| 8/2 | 2026/10/03 04:22 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/Kconfig",
"FirstLine": 60,
"LineCount": 40
}Results: {
"Contents": " 60:\t\t This driver supports Ethernet controller integrated into Broadcom\n 61:\t\t BCM4908 family SoCs.\n 62:\t\n 63:\tconfig BCM63XX_ENET\n 64:\t\ttristate \"Broadcom 63xx internal mac support\"\n 65:\t\tdepends on BCM63XX\n 66:\t\tselect MII\n 67:\t\tselect PHYLIB\n 68:\t\thelp\n 69:\t\t This driver supports the ethernet MACs in the Broadcom 63xx\n 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/03 04:22 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 18401 output: 38 thoughts: 114 Thoughts: Okay, let me break this down. **Investigating the Broadcom GENET Driver** Alright, I need to understand how the `BCMGENET` driver works. First, I see this `tristate "Broadcom GENET internal MAC support"` option – sounds like it handles the Ethernet MACs within Broadcom's BCM7xxx set-top box chips, but also the BCM2835 and Raspberry Pi 4. Interesting. Now, the core question is *how* is this driver actually brought to life within the system? Is it registered as a `platform_driver`, through ACPI, or perhaps as a PCI device? I need to figure out the instantiation method to really understand it. The best path to understanding is to dig into `bcmgenet.c` – I'll search around for the `platform_driver` structure or the `probe` function, that should illuminate the instantiation path. That's where the magic happens, right? Let's get to it. |
| 10/2 | 2026/10/03 04:22 | tool | grepper |
0mArgs:{
"Expression": "module_platform_driver",
"PathPrefix": "drivers/net/ethernet/broadcom/genet/"
}Results: {
"Output": "drivers/net/ethernet/broadcom/genet/bcmgenet.c=4686=static struct platform_driver bcmgenet_driver = {\n--\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-4696-};\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:4697:module_platform_driver(bcmgenet_driver);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-4698-\n"
} |
| 11/2 | 2026/10/03 04:22 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 18912 output: 48 thoughts: 22 Thoughts: Here's a summary of my thought process, as requested: **Diving into the bcmgenet Driver** Okay, so I need to understand how this `bcmgenet_driver` is defined. My first step is to locate it. I'll head straight into `bcmgenet.c` and dig around for that definition. I'm assuming it's probably a static structure, or perhaps a function pointer array, but I need to see the actual implementation. I want to look at its members, any associated initialization code, and understand how it interacts with the broader framework. Let's see what secrets it's hiding! |
| 12/2 | 2026/10/03 04:22 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/genet/bcmgenet.c",
"FirstLine": 4670,
"LineCount": 35
}Results: {
"Contents": "4670:\t#define bcmgenet_resume_noirq\tNULL\n4671:\t#endif /* CONFIG_PM_SLEEP */\n4672:\t\n4673:\tstatic const struct dev_pm_ops bcmgenet_pm_ops = {\n4674:\t\t.suspend\t= bcmgenet_suspend,\n4675:\t\t.suspend_noirq\t= bcmgenet_suspend_noirq,\n4676:\t\t.resume\t\t= bcmgenet_resume,\n4677:\t\t.resume_noirq\t= bcmgenet_resume_noirq,\n4678:\t};\n4679:\t\n4680:\tstatic const struct acpi_device_id genet_acpi_match[] = {\n4681:\t\t{ \"BCM6E4E\", (kernel_ulong_t)\u0026bcm2711_plat_data },\n4682:\t\t{ },\n4683:\t};\n4684:\tMODULE_DEVICE_TABLE(acpi, genet_acpi_match);\n4685:\t\n4686:\tstatic struct platform_driver bcmgenet_driver = {\n4687:\t\t.probe\t= bcmgenet_probe,\n4688:\t\t.remove = bcmgenet_remove,\n4689:\t\t.shutdown = bcmgenet_shutdown,\n4690:\t\t.driver\t= {\n4691:\t\t\t.name\t= \"bcmgenet\",\n4692:\t\t\t.of_match_table = bcmgenet_match,\n4693:\t\t\t.pm\t= \u0026bcmgenet_pm_ops,\n4694:\t\t\t.acpi_match_table = genet_acpi_match,\n4695:\t\t},\n4696:\t};\n4697:\tmodule_platform_driver(bcmgenet_driver);\n4698:\t\n4699:\tMODULE_AUTHOR(\"Broadcom Corporation\");\n4700:\tMODULE_DESCRIPTION(\"Broadcom GENET Ethernet controller driver\");\n4701:\tMODULE_ALIAS(\"platform:bcmgenet\");\n4702:\tMODULE_LICENSE(\"GPL\");\n4703:\tMODULE_SOFTDEP(\"pre: mdio-bcm-unimac\");\n"
} |
| 13/2 | 2026/10/03 04:22 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 19709 output: 48 thoughts: 317 Thoughts: **My Assessment of `bcmgenet_probe`'s Fuzzing Feasibility** Okay, let's break this down. First, the core question: can I effectively fuzz `bcmgenet_probe` without real hardware? This is crucial; fuzzing is a waste of time if the target code is unreachable in a standard virtualized setup. The main thing I need to figure out is if it's possible to execute the code without having physical hardware available. Wait, the preamble highlights a crucial point – reachability is the *key*. Fuzzing is only useful if the code *can* actually be exercised in the standard environments I'm using (QEMU, GCE). I need to make sure `bcmgenet_probe` isn't one of those structurally unreachable cases. The text is making it clear that if the code is unreachable, forget about fuzzing it, regardless of any internal logic. Right, so the examples of unreachable code are useful. Things that depend on very specific hardware, like vendor-specific PCIe switches, or drivers tied to physical ASIC/PCIe cards that aren't emulated in QEMU (e.g., mlxsw, amdgpu). Also code paths that rely on PCI hot-unplug, or other specific physical interactions, or code paths exclusive to different architectures than what I'm targeting are dead ends. Now I need to focus on `bcmgenet_probe` itself. I'll need to go through the code of `bcmgenet_probe`. Let's analyze `bcmgenet_probe` to identify exactly what resources it requires to bind, if it requires physical Broadcom hardware, a device tree, or ACPI to initialize. That's the critical information here. Only then can I determine if I'm even in the game. |
| 14/2 | 2026/10/03 04:22 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/genet/bcmgenet.c",
"FirstLine": 4080,
"LineCount": 80
}Results: {
"Contents": "4080:\t{\n4081:\t\tconst struct bcmgenet_hw_params *params;\n4082:\t\tu32 reg;\n4083:\t\tu8 major;\n4084:\t\tu16 gphy_rev;\n4085:\t\n4086:\t\t/* default to latest values */\n4087:\t\tparams = \u0026bcmgenet_hw_params_v4;\n4088:\t\tbcmgenet_dma_regs = bcmgenet_dma_regs_v3plus;\n4089:\t\tgenet_dma_ring_regs = genet_dma_ring_regs_v4;\n4090:\t\tif (GENET_IS_V3(priv)) {\n4091:\t\t\tparams = \u0026bcmgenet_hw_params_v3;\n4092:\t\t\tbcmgenet_dma_regs = bcmgenet_dma_regs_v3plus;\n4093:\t\t\tgenet_dma_ring_regs = genet_dma_ring_regs_v123;\n4094:\t\t} else if (GENET_IS_V2(priv)) {\n4095:\t\t\tparams = \u0026bcmgenet_hw_params_v2;\n4096:\t\t\tbcmgenet_dma_regs = bcmgenet_dma_regs_v2;\n4097:\t\t\tgenet_dma_ring_regs = genet_dma_ring_regs_v123;\n4098:\t\t} else if (GENET_IS_V1(priv)) {\n4099:\t\t\tparams = \u0026bcmgenet_hw_params_v1;\n4100:\t\t\tbcmgenet_dma_regs = bcmgenet_dma_regs_v1;\n4101:\t\t\tgenet_dma_ring_regs = genet_dma_ring_regs_v123;\n4102:\t\t}\n4103:\t\tpriv-\u003ehw_params = params;\n4104:\t\n4105:\t\t/* Read GENET HW version */\n4106:\t\treg = bcmgenet_sys_readl(priv, SYS_REV_CTRL);\n4107:\t\tmajor = (reg \u003e\u003e 24 \u0026 0x0f);\n4108:\t\tif (major == 6 || major == 7)\n4109:\t\t\tmajor = 5;\n4110:\t\telse if (major == 5)\n4111:\t\t\tmajor = 4;\n4112:\t\telse if (major == 0)\n4113:\t\t\tmajor = 1;\n4114:\t\tif (major != priv-\u003eversion) {\n4115:\t\t\tdev_err(\u0026priv-\u003epdev-\u003edev,\n4116:\t\t\t\t\"GENET version mismatch, got: %d, configured for: %d\\n\",\n4117:\t\t\t\tmajor, priv-\u003eversion);\n4118:\t\t}\n4119:\t\n4120:\t\t/* Print the GENET core version */\n4121:\t\tdev_info(\u0026priv-\u003epdev-\u003edev, \"GENET \" GENET_VER_FMT,\n4122:\t\t\t major, (reg \u003e\u003e 16) \u0026 0x0f, reg \u0026 0xffff);\n4123:\t\n4124:\t\t/* Store the integrated PHY revision for the MDIO probing function\n4125:\t\t * to pass this information to the PHY driver. The PHY driver expects\n4126:\t\t * to find the PHY major revision in bits 15:8 while the GENET register\n4127:\t\t * stores that information in bits 7:0, account for that.\n4128:\t\t *\n4129:\t\t * On newer chips, starting with PHY revision G0, a new scheme is\n4130:\t\t * deployed similar to the Starfighter 2 switch with GPHY major\n4131:\t\t * revision in bits 15:8 and patch level in bits 7:0. Major revision 0\n4132:\t\t * is reserved as well as special value 0x01ff, we have a small\n4133:\t\t * heuristic to check for the new GPHY revision and re-arrange things\n4134:\t\t * so the GPHY driver is happy.\n4135:\t\t */\n4136:\t\tgphy_rev = reg \u0026 0xffff;\n4137:\t\n4138:\t\tif (GENET_IS_V5(priv)) {\n4139:\t\t\t/* The EPHY revision should come from the MDIO registers of\n4140:\t\t\t * the PHY not from GENET.\n4141:\t\t\t */\n4142:\t\t\tif (gphy_rev != 0) {\n4143:\t\t\t\tpr_warn(\"GENET is reporting EPHY revision: 0x%04x\\n\",\n4144:\t\t\t\t\tgphy_rev);\n4145:\t\t\t}\n4146:\t\t/* This is reserved so should require special treatment */\n4147:\t\t} else if (gphy_rev == 0 || gphy_rev == 0x01ff) {\n4148:\t\t\tpr_warn(\"Invalid GPHY revision detected: 0x%04x\\n\", gphy_rev);\n4149:\t\t\treturn;\n4150:\t\t/* This is the good old scheme, just GPHY major, no minor nor patch */\n4151:\t\t} else if ((gphy_rev \u0026 0xf0) != 0) {\n4152:\t\t\tpriv-\u003egphy_rev = gphy_rev \u003c\u003c 8;\n4153:\t\t/* This is the new scheme, GPHY major rolls over with 0x10 = rev G0 */\n4154:\t\t} else if ((gphy_rev \u0026 0xff00) != 0) {\n4155:\t\t\tpriv-\u003egphy_rev = gphy_rev;\n4156:\t\t}\n4157:\t\n4158:\t#ifdef CONFIG_PHYS_ADDR_T_64BIT\n4159:\t\tif (!bcmgenet_has_40bits(priv))\n"
} |
| 15/2 | 2026/10/03 04:22 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 21997 output: 48 thoughts: 15 Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person: **Initial Assessment of the Probe Function** Alright, let's dive into the `bcmgenet_probe` function. My initial thought process immediately focuses on this: I need to understand what this function is *supposed* to be doing. I'm assuming, given the naming, that this is the driver's probe function for a Broadcom Gigabit Ethernet (bcmgenet) controller. My brain's already prepped to look for the key elements: resource allocation, device identification, interrupt registration, and ultimately, driver initialization. I'll be expecting checks for hardware existence, potential conflicts, and the crucial steps for bringing the network interface online. The very nature of a "probe" function suggests that it will perform a detailed exploration of the hardware device and try to establish a preliminary driver binding. Let's see what's what. |
| 16/2 | 2026/10/03 04:22 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/genet/bcmgenet.c",
"FirstLine": 4010,
"LineCount": 70
}Results: {
"Contents": "4010:\t\t.rx_queues = 0,\n4011:\t\t.rx_bds_per_q = 0,\n4012:\t\t.bp_in_en_shift = 16,\n4013:\t\t.bp_in_mask = 0xffff,\n4014:\t\t.hfb_filter_cnt = 16,\n4015:\t\t.hfb_filter_size = 64,\n4016:\t\t.qtag_mask = 0x1F,\n4017:\t\t.hfb_offset = 0x1000,\n4018:\t\t.hfb_reg_offset = GENET_RBUF_OFF + RBUF_HFB_CTRL_V1,\n4019:\t\t.rdma_offset = 0x2000,\n4020:\t\t.tdma_offset = 0x3000,\n4021:\t\t.words_per_bd = 2,\n4022:\t};\n4023:\t\n4024:\tstatic const struct bcmgenet_hw_params bcmgenet_hw_params_v2 = {\n4025:\t\t.tx_queues = 4,\n4026:\t\t.tx_bds_per_q = 32,\n4027:\t\t.rx_queues = 0,\n4028:\t\t.rx_bds_per_q = 0,\n4029:\t\t.bp_in_en_shift = 16,\n4030:\t\t.bp_in_mask = 0xffff,\n4031:\t\t.hfb_filter_cnt = 16,\n4032:\t\t.hfb_filter_size = 64,\n4033:\t\t.qtag_mask = 0x1F,\n4034:\t\t.tbuf_offset = 0x0600,\n4035:\t\t.hfb_offset = 0x1000,\n4036:\t\t.hfb_reg_offset = 0x2000,\n4037:\t\t.rdma_offset = 0x3000,\n4038:\t\t.tdma_offset = 0x4000,\n4039:\t\t.words_per_bd = 2,\n4040:\t};\n4041:\t\n4042:\tstatic const struct bcmgenet_hw_params bcmgenet_hw_params_v3 = {\n4043:\t\t.tx_queues = 4,\n4044:\t\t.tx_bds_per_q = 32,\n4045:\t\t.rx_queues = 0,\n4046:\t\t.rx_bds_per_q = 0,\n4047:\t\t.bp_in_en_shift = 17,\n4048:\t\t.bp_in_mask = 0x1ffff,\n4049:\t\t.hfb_filter_cnt = 48,\n4050:\t\t.hfb_filter_size = 128,\n4051:\t\t.qtag_mask = 0x3F,\n4052:\t\t.tbuf_offset = 0x0600,\n4053:\t\t.hfb_offset = 0x8000,\n4054:\t\t.hfb_reg_offset = 0xfc00,\n4055:\t\t.rdma_offset = 0x10000,\n4056:\t\t.tdma_offset = 0x11000,\n4057:\t\t.words_per_bd = 2,\n4058:\t};\n4059:\t\n4060:\tstatic const struct bcmgenet_hw_params bcmgenet_hw_params_v4 = {\n4061:\t\t.tx_queues = 4,\n4062:\t\t.tx_bds_per_q = 32,\n4063:\t\t.rx_queues = 0,\n4064:\t\t.rx_bds_per_q = 0,\n4065:\t\t.bp_in_en_shift = 17,\n4066:\t\t.bp_in_mask = 0x1ffff,\n4067:\t\t.hfb_filter_cnt = 48,\n4068:\t\t.hfb_filter_size = 128,\n4069:\t\t.qtag_mask = 0x3F,\n4070:\t\t.tbuf_offset = 0x0600,\n4071:\t\t.hfb_offset = 0x8000,\n4072:\t\t.hfb_reg_offset = 0xfc00,\n4073:\t\t.rdma_offset = 0x2000,\n4074:\t\t.tdma_offset = 0x4000,\n4075:\t\t.words_per_bd = 3,\n4076:\t};\n4077:\t\n4078:\t/* Infer hardware parameters from the detected GENET version */\n4079:\tstatic void bcmgenet_set_hw_params(struct bcmgenet_priv *priv)\n"
} |
| 17/2 | 2026/10/03 04:22 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 23604 output: 48 thoughts: 16 Thoughts: Okay, let's dive into this. Here's my understanding, presented as a personal thought process, given my expertise: **Diving into the `bcmgenet_probe` Function** Alright, time to get my hands dirty. I need to understand this `bcmgenet_probe` function better. Where does this whole thing even *begin*? I need to trace its origins, understand its entry point. This probe routine is fundamental to the driver's operation, so knowing its exact starting point is crucial for grasping the overall system. Time to go hunting for the call site. |
| 18/2 | 2026/10/03 04:22 | tool | grepper |
0mArgs:{
"Expression": "^static int bcmgenet_probe",
"PathPrefix": "drivers/net/ethernet/broadcom/genet/bcmgenet.c"
}Results: {
"Output": "drivers/net/ethernet/broadcom/genet/bcmgenet.c=4244=MODULE_DEVICE_TABLE(of, bcmgenet_match);\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-4245-\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c:4246:static int bcmgenet_probe(struct platform_device *pdev)\ndrivers/net/ethernet/broadcom/genet/bcmgenet.c-4247-{\n"
} |
| 19/2 | 2026/10/03 04:22 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 23942 output: 48 thoughts: 20 Thoughts: Okay, let's dive into this. Here's my take on those thoughts, as if they're my own: **Analyzing the `bcmgenet_probe` Function** Alright, time to get to the core of this. Let's start by zeroing in on `bcmgenet_probe`, specifically around line 4246. I need to understand how this probe function behaves, particularly in the context of [my field of expertise, e.g., NIC driver initialization, hardware discovery, or network interface bring-up]. I'm expecting this is where the hardware interaction begins, or at the very least, where the device's capabilities are identified and initial setup is initiated. I'm going to pay close attention to the register access, resource allocation, and any potential interrupt handling that's happening here. The goal is to fully grasp the initialization sequence and identify any potential bottlenecks or areas for optimization based on my understanding of [relevant hardware details]. Let's see what we've got. |
| 20/2 | 2026/10/03 04:22 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/genet/bcmgenet.c",
"FirstLine": 4246,
"LineCount": 80
}Results: {
"Contents": "4246:\tstatic int bcmgenet_probe(struct platform_device *pdev)\n4247:\t{\n4248:\t\tconst struct bcmgenet_plat_data *pdata;\n4249:\t\tstruct bcmgenet_priv *priv;\n4250:\t\tstruct net_device *dev;\n4251:\t\tunsigned int i;\n4252:\t\tint err = -EIO;\n4253:\t\n4254:\t\t/* Up to GENET_MAX_MQ_CNT + 1 TX queues and RX queues */\n4255:\t\tdev = alloc_etherdev_mqs(sizeof(*priv), GENET_MAX_MQ_CNT + 1,\n4256:\t\t\t\t\t GENET_MAX_MQ_CNT + 1);\n4257:\t\tif (!dev) {\n4258:\t\t\tdev_err(\u0026pdev-\u003edev, \"can't allocate net device\\n\");\n4259:\t\t\treturn -ENOMEM;\n4260:\t\t}\n4261:\t\n4262:\t\tpriv = netdev_priv(dev);\n4263:\t\tpriv-\u003eirq0 = platform_get_irq(pdev, 0);\n4264:\t\tif (priv-\u003eirq0 \u003c 0) {\n4265:\t\t\terr = priv-\u003eirq0;\n4266:\t\t\tgoto err;\n4267:\t\t}\n4268:\t\tpriv-\u003eirq1 = platform_get_irq(pdev, 1);\n4269:\t\tif (priv-\u003eirq1 \u003c 0) {\n4270:\t\t\terr = priv-\u003eirq1;\n4271:\t\t\tgoto err;\n4272:\t\t}\n4273:\t\tpriv-\u003ewol_irq = platform_get_irq_optional(pdev, 2);\n4274:\t\tif (priv-\u003ewol_irq == -EPROBE_DEFER) {\n4275:\t\t\terr = priv-\u003ewol_irq;\n4276:\t\t\tgoto err;\n4277:\t\t}\n4278:\t\n4279:\t\tpriv-\u003ebase = devm_platform_ioremap_resource(pdev, 0);\n4280:\t\tif (IS_ERR(priv-\u003ebase)) {\n4281:\t\t\terr = PTR_ERR(priv-\u003ebase);\n4282:\t\t\tgoto err;\n4283:\t\t}\n4284:\t\n4285:\t\tspin_lock_init(\u0026priv-\u003ereg_lock);\n4286:\t\tspin_lock_init(\u0026priv-\u003elock);\n4287:\t\n4288:\t\t/* Set default pause parameters */\n4289:\t\tpriv-\u003eautoneg_pause = 1;\n4290:\t\tpriv-\u003etx_pause = 1;\n4291:\t\tpriv-\u003erx_pause = 1;\n4292:\t\n4293:\t\tSET_NETDEV_DEV(dev, \u0026pdev-\u003edev);\n4294:\t\tdev_set_drvdata(\u0026pdev-\u003edev, dev);\n4295:\t\tdev-\u003ewatchdog_timeo = 2 * HZ;\n4296:\t\tdev-\u003eethtool_ops = \u0026bcmgenet_ethtool_ops;\n4297:\t\tdev-\u003enetdev_ops = \u0026bcmgenet_netdev_ops;\n4298:\t\n4299:\t\tpriv-\u003emsg_enable = netif_msg_init(-1, GENET_MSG_DEFAULT);\n4300:\t\n4301:\t\t/* Set default features */\n4302:\t\tdev-\u003efeatures |= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM |\n4303:\t\t\t\t NETIF_F_RXCSUM;\n4304:\t\tdev-\u003ehw_features |= dev-\u003efeatures;\n4305:\t\tdev-\u003evlan_features |= dev-\u003efeatures;\n4306:\t\n4307:\t\tnetdev_sw_irq_coalesce_default_on(dev);\n4308:\t\n4309:\t\t/* Request the WOL interrupt and advertise suspend if available */\n4310:\t\tpriv-\u003ewol_irq_disabled = true;\n4311:\t\tif (priv-\u003ewol_irq \u003e 0) {\n4312:\t\t\terr = devm_request_irq(\u0026pdev-\u003edev, priv-\u003ewol_irq,\n4313:\t\t\t\t\t bcmgenet_wol_isr, 0, dev-\u003ename, priv);\n4314:\t\t\tif (!err)\n4315:\t\t\t\tdevice_set_wakeup_capable(\u0026pdev-\u003edev, 1);\n4316:\t\t}\n4317:\t\n4318:\t\t/* Set the needed headroom to account for any possible\n4319:\t\t * features enabling/disabling at runtime\n4320:\t\t */\n4321:\t\tdev-\u003eneeded_headroom += 64;\n4322:\t\n4323:\t\tpriv-\u003edev = dev;\n4324:\t\tpriv-\u003epdev = pdev;\n4325:\t\n"
} |
| 21/2 | 2026/10/03 04:22 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 25523 output: 48 thoughts: 309 Thoughts: **Analyzing the `bcmgenet` Driver's Potential in Virtualized Environments** Okay, let's break this down. First, it's a platform driver, `bcmgenet`. That means it's relying on `platform_get_irq()` calls, specifically for IRQ 0 and IRQ 1, and `devm_platform_ioremap_resource()` to handle memory-mapped I/O. So, it's expecting a platform device. The code shows matching against both an OF match table, `bcmgenet_match`, which indicates Device Tree usage, and an ACPI match table, specifically looking for "BCM6E4E". The question that pops into my head, and it's a critical one, is whether this driver is even *reachable* in a standard virtualized environment like QEMU on x86-64, or something like Google Compute Engine. Can I even *create* a `bcmgenet` platform device in a QEMU x86-64 context? Nope, not directly. QEMU, in its standard PC or Q35 configurations, relies on PCI/PCIe buses, and ACPI for the standard PC devices. It *doesn't* offer direct support for BCM6E4E ACPI or Broadcom GENET device tree nodes out of the box. Now, could I possibly inject an ACPI table, or maybe create a platform device somehow through sysfs? Maybe... but wait. Sysfs doesn't give you free rein to create arbitrary platform devices with IRQs and MMIO resources from userspace, unless there's a *specific* mechanism provided by the driver. And even if there were, I see that `SYS_REV_CTRL` is being read from `priv->base`. That's memory-mapped registers. No, not gonna happen. I need to dig into the driver's probe function at lines 4340 and beyond to confirm what I suspected. |
| 22/2 | 2026/10/03 04:22 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/genet/bcmgenet.c",
"FirstLine": 4325,
"LineCount": 50
}Results: {
"Contents": "4325:\t\n4326:\t\tpdata = device_get_match_data(\u0026pdev-\u003edev);\n4327:\t\tif (pdata) {\n4328:\t\t\tpriv-\u003eversion = pdata-\u003eversion;\n4329:\t\t\tpriv-\u003edma_max_burst_length = pdata-\u003edma_max_burst_length;\n4330:\t\t\tpriv-\u003eflags = pdata-\u003eflags;\n4331:\t\t}\n4332:\t\n4333:\t\tpriv-\u003eclk = devm_clk_get_optional(\u0026priv-\u003epdev-\u003edev, \"enet\");\n4334:\t\tif (IS_ERR(priv-\u003eclk)) {\n4335:\t\t\tdev_dbg(\u0026priv-\u003epdev-\u003edev, \"failed to get enet clock\\n\");\n4336:\t\t\terr = PTR_ERR(priv-\u003eclk);\n4337:\t\t\tgoto err;\n4338:\t\t}\n4339:\t\n4340:\t\terr = clk_prepare_enable(priv-\u003eclk);\n4341:\t\tif (err)\n4342:\t\t\tgoto err;\n4343:\t\n4344:\t\tbcmgenet_set_hw_params(priv);\n4345:\t\n4346:\t\terr = -EIO;\n4347:\t\tif (bcmgenet_has_40bits(priv))\n4348:\t\t\terr = dma_set_mask_and_coherent(\u0026pdev-\u003edev, DMA_BIT_MASK(40));\n4349:\t\tif (err)\n4350:\t\t\terr = dma_set_mask_and_coherent(\u0026pdev-\u003edev, DMA_BIT_MASK(32));\n4351:\t\tif (err)\n4352:\t\t\tgoto err_clk_disable;\n4353:\t\n4354:\t\t/* Mii wait queue */\n4355:\t\tinit_waitqueue_head(\u0026priv-\u003ewq);\n4356:\t\tbcmgenet_hfb_init(priv);\n4357:\t\n4358:\t\t/* v1 cannot program the thresholds, so it stays at the default MTU */\n4359:\t\tpriv-\u003erx_buf_len = bcmgenet_rx_buf_len(dev-\u003emtu);\n4360:\t\tif (!GENET_IS_V1(priv))\n4361:\t\t\tdev-\u003emax_mtu = ENET_MAX_JUMBO_MTU;\n4362:\t\tINIT_WORK(\u0026priv-\u003ebcmgenet_irq_work, bcmgenet_irq_task);\n4363:\t\n4364:\t\tpriv-\u003eclk_wol = devm_clk_get_optional(\u0026priv-\u003epdev-\u003edev, \"enet-wol\");\n4365:\t\tif (IS_ERR(priv-\u003eclk_wol)) {\n4366:\t\t\tdev_dbg(\u0026priv-\u003epdev-\u003edev, \"failed to get enet-wol clock\\n\");\n4367:\t\t\terr = PTR_ERR(priv-\u003eclk_wol);\n4368:\t\t\tgoto err_clk_disable;\n4369:\t\t}\n4370:\t\n4371:\t\tpriv-\u003eclk_eee = devm_clk_get_optional(\u0026priv-\u003epdev-\u003edev, \"enet-eee\");\n4372:\t\tif (IS_ERR(priv-\u003eclk_eee)) {\n4373:\t\t\tdev_dbg(\u0026priv-\u003epdev-\u003edev, \"failed to get enet-eee clock\\n\");\n4374:\t\t\terr = PTR_ERR(priv-\u003eclk_eee);\n"
} |
| 23/2 | 2026/10/03 04:22 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 27209 output: 48 thoughts: 152 Thoughts: **Analyzing the Initialization Sequence** Okay, let's break this down. I'm focusing on how the Broadcom Gigabit Ethernet (bcmgenet) driver initializes, specifically starting with the `bcmgenet_probe` function. It seems to call `bcmgenet_set_hw_params(priv)` first, which is likely where the hardware-specific parameters are configured. I see it reads from a register, `SYS_REV_CTRL`, using `bcmgenet_sys_readl`. It isolates the GPHY revision from the register's contents, storing the lower 16 bits in `gphy_rev`. A quick sanity check follows: If `gphy_rev` is either zero or `0x01ff`, the code flags an "Invalid GPHY revision," and bails out. Makes sense – those values probably represent some kind of error state, or perhaps an uninitialized state. Then, crucially, it calls `bcmgenet_mii_init(dev)`. That's the important bit – the Media Independent Interface (MII) initialization is how the driver actually *talks* to the PHY over the MDIO bus. Time to look into *that* function, `bcmgenet_mii_init`. That's where the real magic happens. |
| 24/2 | 2026/10/03 04:22 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/broadcom/genet/bcmgenet.c",
"FirstLine": 4385,
"LineCount": 40
}Results: {
"Contents": "4385:\t\t\tif (has_acpi_companion(\u0026pdev-\u003edev)) {\n4386:\t\t\t\tu8 addr[ETH_ALEN];\n4387:\t\n4388:\t\t\t\tbcmgenet_get_hw_addr(priv, addr);\n4389:\t\t\t\teth_hw_addr_set(dev, addr);\n4390:\t\t\t}\n4391:\t\n4392:\t\tif (!is_valid_ether_addr(dev-\u003edev_addr)) {\n4393:\t\t\tdev_warn(\u0026pdev-\u003edev, \"using random Ethernet MAC\\n\");\n4394:\t\t\teth_hw_addr_random(dev);\n4395:\t\t}\n4396:\t\n4397:\t\treset_umac(priv);\n4398:\t\n4399:\t\terr = bcmgenet_mii_init(dev);\n4400:\t\tif (err)\n4401:\t\t\tgoto err_clk_disable;\n4402:\t\n4403:\t\t/* setup number of real queues + 1 */\n4404:\t\tnetif_set_real_num_tx_queues(priv-\u003edev, priv-\u003ehw_params-\u003etx_queues + 1);\n4405:\t\tnetif_set_real_num_rx_queues(priv-\u003edev, priv-\u003ehw_params-\u003erx_queues + 1);\n4406:\t\n4407:\t\t/* Set default coalescing parameters */\n4408:\t\tfor (i = 0; i \u003c= priv-\u003ehw_params-\u003erx_queues; i++) {\n4409:\t\t\tpriv-\u003erx_rings[i].priv = priv;\n4410:\t\t\tpriv-\u003erx_rings[i].index = i;\n4411:\t\t\tpriv-\u003erx_rings[i].rx_max_coalesced_frames = 1;\n4412:\t\t}\n4413:\t\n4414:\t\t/* Initialize u64 stats seq counter for 32bit machines */\n4415:\t\tfor (i = 0; i \u003c= GENET_MAX_MQ_CNT; i++) {\n4416:\t\t\tu64_stats_init(\u0026priv-\u003erx_rings[i].stats64.syncp);\n4417:\t\t\tu64_stats_init(\u0026priv-\u003etx_rings[i].stats64.syncp);\n4418:\t\t}\n4419:\t\n4420:\t\t/* libphy will determine the link state */\n4421:\t\tnetif_carrier_off(dev);\n4422:\t\n4423:\t\t/* Turn off the main clock, WOL clock is handled separately */\n4424:\t\tclk_disable_unprepare(priv-\u003eclk);\n"
} |
| 25/2 | 2026/10/03 04:22 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 28381 output: 155 thoughts: 2173 Thoughts: **BCMGENET Unreachability Analysis and Verdict** Okay, let's break this down systematically. The instructions are clear: if the modified code is *structurally unreachable*, we don't fuzz. First, let's confirm the target architecture: amd64. Now, the driver in question is `bcmgenet`, which I know is Broadcom's GENET (Gigabit Ethernet controller) – typically found on their SoCs, like the BCM7xxx family and the BCM2711 used in Raspberry Pi 4. The latter is important because those are ARM/MIPS/ARM64 architectures. Can `bcmgenet` even compile for amd64? The Kconfig entry shows it *can* via `HAS_IOMEM`, which is true for amd64, but that's not the crucial factor. The key question: Is it *structurally unreachable hardware* on amd64 in a standard QEMU environment? Let's look at the hardware. BCMGENET is a Broadcom integrated MAC. QEMU's standard x86_64 setup emulates a host of other Ethernet controllers, but not this one. It's not a PCI device, and, importantly, it's a platform driver. Platform drivers require specific hardware resources (MMIO registers, IRQs) that are *not* emulated by standard QEMU on x86_64, or even *any* QEMU configuration I'm aware of. The driver probes rely on device tree or ACPI matches, and even if an ACPI device with HID "BCM6E4E" existed, it requires physical MMIO registers. Without emulation, the probe will fail. The driver initialization goes through several checks that will invariably fail because the hardware is not present. The net_device is never registered. Now, let's analyze the patch. It modifies a whole suite of `bcmgenet` internal functions. All these functions, while critical to the driver, are completely dependent on the underlying hardware being present. None of it is core subsystem code or generic networking functionality. Re-reading the fuzzing guidelines, especially Section 1 and 2, confirms this. Reachability is the primary gate. If the code is *structurally unreachable*, we don't fuzz. Section 2 explicitly lists "vendor-specific... requiring physical... cards not emulated in standard QEMU". This is exactly the situation we have. And BCMGENET is *not* accessible via a virtual bus (virtio, etc.). It's a platform driver dependent on physical Broadcom SoC hardware, specifically the integrated Ethernet MAC. Let's do a final check to confirm that we haven't missed any other modified files. Nope. Just the `.c` and `.h` for `bcmgenet`. Therefore, `WorthFuzzing` must be false. So, let's prepare the arguments for `set-results`: `WorthFuzzing` is `false`, `FocusSymbols` is an empty array, `EnableConfigs` is an empty array. The `Reasoning` should be crystal clear: BCMGENET is a driver for Broadcom SoC Ethernet controllers (BCM7xxx, BCM2711). It's a platform driver reliant on physical Broadcom hardware and MMIO resources. It's not emulated in standard QEMU or GCE on amd64. Therefore, the modified code is structurally unreachable for fuzzing. |
| 26/2 | 2026/10/03 04:22 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch modifies the Broadcom GENET Ethernet MAC driver (drivers/net/ethernet/broadcom/genet/bcmgenet.c and bcmgenet.h). BCMGENET is a platform driver designed for integrated MACs found on Broadcom SoCs (such as BCM7xxx and BCM2711). It requires physical hardware/MMIO resources that are not present or emulated in standard virtualized environments (QEMU or GCE on amd64). Consequently, the modified code is structurally unreachable for syzkaller fuzzing on the target architecture.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies the Broadcom GENET Ethernet MAC driver (drivers/net/ethernet/broadcom/genet/bcmgenet.c and bcmgenet.h). BCMGENET is a platform driver designed for integrated MACs found on Broadcom SoCs (such as BCM7xxx and BCM2711). It requires physical hardware/MMIO resources that are not present or emulated in standard virtualized environments (QEMU or GCE on amd64). Consequently, the modified code is structurally unreachable for syzkaller fuzzing on the target architecture.",
"WorthFuzzing": false
} |
| 27/1 | 2026/10/03 04:22 | 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) |
|---|