A NAPI poll can retain a partially assembled frame across invocations. The stop path clears port->rx_skb without freeing the skb retained in napi->skb. If the interface is reopened, napi_get_frags() returns that stale skb. The next frame overwrites its fragment array from index zero while len and data_len still include the partial frame. This can lose page references belonging to the old fragments or pass an skb with inconsistent fragment accounting to GRO. If the interface is removed without reopening, NAPI teardown eventually frees the stale skb. Free a pending fragment skb after disabling NAPI and before clearing the saved RX state. Count the discarded frame as dropped under the RX statistics sequence counter. Use the irqsave update helpers because ndo_stop runs in preemptible process context while 32-bit statistics writers must not be preempted. The issue was found by inspecting the partial frame lifetime and statistics writer contexts. The series was tested on a D-Link DIR-685 with media playback and ksmbd transfers under ping load. Fixes: 06937db21ee3 ("net: ethernet: cortina: Make RX SKB per-port") Signed-off-by: Linus Walleij --- drivers/net/ethernet/cortina/gemini.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c index 7569c9935b85..be2b9702718f 100644 --- a/drivers/net/ethernet/cortina/gemini.c +++ b/drivers/net/ethernet/cortina/gemini.c @@ -2224,12 +2224,19 @@ static int gmac_open(struct net_device *netdev) static int gmac_stop(struct net_device *netdev) { struct gemini_ethernet_port *port = netdev_priv(netdev); + unsigned long flags; hrtimer_cancel(&port->rx_coalesce_timer); netif_tx_stop_all_queues(netdev); gmac_disable_tx_rx(netdev); gmac_stop_dma(port); napi_disable(&port->napi); + if (port->rx_skb) { + napi_free_frags(&port->napi); + flags = u64_stats_update_begin_irqsave(&port->rx_stats_syncp); + port->stats.rx_dropped++; + u64_stats_update_end_irqrestore(&port->rx_stats_syncp, flags); + } port->rx_skb = NULL; port->rx_frag_nr = 0; port->rx_dropping = false; -- 2.56.0