[PATCH net-next v2 0/2] net: ethernet: cortina: Gemini Ethernet fixes, part 2

COLD22d

5 messages, 2 authors, 22d ago · open the first message on its own page

[PATCH net-next v2 0/2] net: ethernet: cortina: Gemini Ethernet fixes, part 2

From: Linus Walleij <linusw@kernel.org>
Date: 2026-09-14 21:26:55

Fix two RX-path issues: acknowledge FIFO overruns with the correct status
bit and bound descriptor processing when malformed chains lack EOF.

Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
Changes in v2:
- Resend as prerequisite patches didn't yet reach the merge base.
- Link to v1: https://patch.msgid.link/20260909-b4-gemini-ethernet-fixes-2-v1-0-5ea3aa393f41@kernel.org

---
Linus Walleij (2):
      net: ethernet: cortina: Ack RX overrun interrupt correctly
      net: ethernet: cortina: Bound RX descriptor processing

 drivers/net/ethernet/cortina/gemini.c | 34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)
---
base-commit: c20065162307a94f88124f2adb00777a475ab4d7
change-id: 20260908-b4-gemini-ethernet-fixes-2-d4c2ee15d11a

Best regards,
--  
Linus Walleij [off-list ref]

[PATCH net-next v2 1/2] net: ethernet: cortina: Ack RX overrun interrupt correctly

From: Linus Walleij <linusw@kernel.org>
Date: 2026-09-14 21:26:57

The RX overrun interrupt is reported in interrupt status register 4, but
gmac_irq() acknowledges it using the RX descriptor error bit from status
register 0. For GMAC0 this writes the GMAC1 overrun bit, while for GMAC1
the shift leaves no bit in the 32-bit register.

Acknowledge the same per-port RX overrun bit that was detected.

Fixes: 4d5ae32f5e1e ("net: ethernet: Add a driver for Gemini gigabit ethernet")
Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
 drivers/net/ethernet/cortina/gemini.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index f08de623e6f7..2dd2fa801829 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -1798,7 +1798,7 @@ static irqreturn_t gmac_irq(int irq, void *data)
 
 	if (val & (GMAC0_RX_OVERRUN_INT_BIT << (netdev->dev_id * 8))) {
 		spin_lock(&geth->irq_lock);
-		writel(GMAC0_RXDERR_INT_BIT << (netdev->dev_id * 8),
+		writel(GMAC0_RX_OVERRUN_INT_BIT << (netdev->dev_id * 8),
 		       geth->base + GLOBAL_INTERRUPT_STATUS_4_REG);
 		u64_stats_update_begin(&port->ir_stats_syncp);
 		++port->stats.rx_fifo_errors;
-- 
2.55.0

[PATCH net-next v2 2/2] net: ethernet: cortina: Bound RX descriptor processing

From: Linus Walleij <linusw@kernel.org>
Date: 2026-09-14 21:27:00

NAPI budgets received packets, so gmac_rx() only consumes budget when an
EOF descriptor completes a frame. A malformed descriptor stream without
EOF can consequently make one poll consume the entire snapshotted RX ring,
which may contain up to 32768 descriptors. The error paths can also flood
the kernel log while doing so.

Keep the packet budget EOF-based, but impose a separate descriptor limit
which allows MAX_SKB_FRAGS descriptors for every packet in the budget. If
the limit is reached with descriptors still pending, return the full NAPI
budget to retain ownership and continue in another poll. Ratelimit errors
reported from malformed descriptor paths.

Fixes: 4d5ae32f5e1e ("net: ethernet: Add a driver for Gemini gigabit ethernet")
Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
 drivers/net/ethernet/cortina/gemini.c | 32 +++++++++++++++++++++-----------
 1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index 2dd2fa801829..2fe7fd0202d2 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/net.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
@@ -736,7 +737,8 @@ gmac_get_queue_page(struct gemini_ethernet *geth,
 	mapping = addr & PAGE_MASK;
 
 	if (!geth->freeq_pages) {
-		dev_err(geth->dev, "try to get page with no page list\n");
+		dev_err_ratelimited(geth->dev,
+				    "try to get page with no page list\n");
 		return NULL;
 	}
 
@@ -1441,7 +1443,7 @@ static struct sk_buff *gmac_skb_if_good_frame(struct gemini_ethernet_port *port,
 }
 
 static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget,
-			    unsigned int *freeq_consumed)
+			    unsigned int *freeq_consumed, bool *reschedule)
 {
 	struct gemini_ethernet_port *port = netdev_priv(netdev);
 	unsigned short m = (1 << port->rxq_order) - 1;
@@ -1449,6 +1451,8 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget,
 	void __iomem *ptr_reg = port->rxq_rwptr;
 	unsigned int frag_nr = port->rx_frag_nr;
 	struct sk_buff *skb = port->rx_skb;
+	/* Bound malformed chains while allowing maximum fragments per frame. */
+	unsigned int desc_limit = budget * MAX_SKB_FRAGS;
 	unsigned int consumed = 0;
 	unsigned int frame_len, frag_len;
 	struct gmac_rxdesc *rx = NULL;
@@ -1475,7 +1479,7 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget,
 	r = rw.bits.rptr;
 	w = rw.bits.wptr;
 
-	while (budget && w != r) {
+	while (budget && consumed < desc_limit && w != r) {
 		page = NULL;
 		rx = port->rxq_ring + r;
 		word0 = rx->word0;
@@ -1502,15 +1506,18 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget,
 		}
 
 		if (!mapping) {
-			netdev_err(netdev,
-				   "rxq[%u]: HW BUG: zero DMA desc\n", r);
+			if (net_ratelimit())
+				netdev_err(netdev,
+					   "rxq[%u]: HW BUG: zero DMA desc\n",
+					   r);
 			goto err_drop;
 		}
 
 		/* Freeq pointers are one page off */
 		gpage = gmac_get_queue_page(geth, port, mapping + PAGE_SIZE);
 		if (!gpage) {
-			dev_err(geth->dev, "could not find mapping\n");
+			dev_err_ratelimited(geth->dev,
+					    "could not find mapping\n");
 			goto err_drop;
 		}
 		page = gpage->page;
@@ -1535,7 +1542,7 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget,
 		if (frag_nr == MAX_SKB_FRAGS)
 			goto err_drop;
 
-		if (frag_len == 0)
+		if (frag_len == 0 && net_ratelimit())
 			netdev_err(netdev, "Received fragment with len = 0\n");
 
 		skb_fill_page_desc(skb, frag_nr, page, page_offs, frag_len);
@@ -1579,6 +1586,7 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget,
 	port->rx_frag_nr = frag_nr;
 	port->rx_dropping = dropping;
 	*freeq_consumed = consumed;
+	*reschedule = budget && w != r;
 	writew(r, ptr_reg);
 	return received;
 }
@@ -1590,12 +1598,13 @@ static int gmac_napi_poll(struct napi_struct *napi, int budget)
 	unsigned int freeq_threshold;
 	unsigned int freeq_consumed;
 	unsigned int received;
+	bool reschedule;
 
 	freeq_threshold = 1 << (geth->freeq_order - 1);
 	u64_stats_update_begin(&port->rx_stats_syncp);
 
-	received = gmac_rx(napi->dev, budget, &freeq_consumed);
-	if (received < budget)
+	received = gmac_rx(napi->dev, budget, &freeq_consumed, &reschedule);
+	if (!reschedule && received < budget)
 		++port->rx_napi_exits;
 
 	u64_stats_update_end(&port->rx_stats_syncp);
@@ -1606,10 +1615,11 @@ static int gmac_napi_poll(struct napi_struct *napi, int budget)
 		geth_fill_freeq(geth, true);
 	}
 
-	if (received < budget && napi_complete_done(napi, received))
+	if (!reschedule && received < budget &&
+	    napi_complete_done(napi, received))
 		gmac_enable_rx_irq(napi->dev, 1);
 
-	return received;
+	return reschedule ? budget : received;
 }
 
 static void gmac_dump_dma_state(struct net_device *netdev)
-- 
2.55.0

Re: [PATCH net-next v2 0/2] net: ethernet: cortina: Gemini Ethernet fixes, part 2

From: patchwork-bot+netdevbpf@kernel.org
Date: 2026-09-17 00:51:10

Hello:

This series was applied to netdev/net.git (main)
by Jakub Kicinski [off-list ref]:

On Mon, 14 Sep 2026 23:26:40 +0200 you wrote:
Fix two RX-path issues: acknowledge FIFO overruns with the correct status
bit and bound descriptor processing when malformed chains lack EOF.

Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
Changes in v2:
- Resend as prerequisite patches didn't yet reach the merge base.
- Link to v1: https://patch.msgid.link/20260909-b4-gemini-ethernet-fixes-2-v1-0-5ea3aa393f41@kernel.org

[...]
Here is the summary with links:
  - [net-next,v2,1/2] net: ethernet: cortina: Ack RX overrun interrupt correctly
    https://git.kernel.org/netdev/net/c/1dd85662fee6
  - [net-next,v2,2/2] net: ethernet: cortina: Bound RX descriptor processing
    (no matching commit)

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html

Re: [PATCH net-next v2 0/2] net: ethernet: cortina: Gemini Ethernet fixes, part 2

From: patchwork-bot+netdevbpf@kernel.org
Date: 2026-09-17 00:51:14

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski [off-list ref]:

On Mon, 14 Sep 2026 23:26:40 +0200 you wrote:
Fix two RX-path issues: acknowledge FIFO overruns with the correct status
bit and bound descriptor processing when malformed chains lack EOF.

Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
Changes in v2:
- Resend as prerequisite patches didn't yet reach the merge base.
- Link to v1: https://patch.msgid.link/20260909-b4-gemini-ethernet-fixes-2-v1-0-5ea3aa393f41@kernel.org

[...]
Here is the summary with links:
  - [net-next,v2,1/2] net: ethernet: cortina: Ack RX overrun interrupt correctly
    (no matching commit)
  - [net-next,v2,2/2] net: ethernet: cortina: Bound RX descriptor processing
    https://git.kernel.org/netdev/net-next/c/c5faf1d4df8f

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help