From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9F09E3D5C07; Mon, 17 Aug 2026 15:27:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786980465; cv=none; b=bcQ5x9z2qhSCKkQOp5mTC4dWfQxCdcd5a5euiMIt0LBa1+TMDZr6So4S3wbOtc8CW2ZGf6w9V8+CKOLl1XQI15FSAVGDGRnTB0P3o67+Df5tYyZ1o+NXl7EN60O2WvFbQB3hz6K5NczoVIF+I6SGzR767XG99DMgaU1AaqiPWTg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786980465; c=relaxed/simple; bh=rAVui6J9Xlgk1gPH3eiMCGnUwPXIUK5zvDle3jHMS2g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ofOhmeliOx6gdGsOA6ik7OYLTumhhI5zsmIRChvIppGRdgVThEog3OKhBKsPhqtAHS+ej0fbPxYsKq02qrqFpS5PPwo+pwrmuCWjQvVthq5UH4WApKxdXya7ClL79Au6shQnYqvOyX7Z+YKPWCjDS2ih6FCu9HrlLbFnvGZnNEE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=eYB7iHiD; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="eYB7iHiD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 04BB21F000E9; Mon, 17 Aug 2026 15:27:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1786980464; bh=Z0rCtXZmFC8WiVpuHaewJ7J30E8LNRqdvtK9bLqsmrw=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=eYB7iHiDDmgCA0qNkZ2s4ii4cUYYpF9DQALt2k0lf1MHH576w15Chq+iKINlP1wAD Kj4dw7gicRb4elkv/kPsy7uSRMhPrKLcy8LDi/C9vaKb+Cvkl/x4id7KEjPO0koOMQ GDmDnxX8SvYg4ZcrxhbMKtzJxGmgAD9eVNPLZ2Rc= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Sukhdeep Singh , Yangyu Chen , Mina Almasry , Jakub Kicinski Subject: [PATCH 6.1 583/609] net: atlantic: free stranded TX buffers on ring deinit Date: Mon, 17 Aug 2026 15:34:39 +0200 Message-ID: <20260817132603.192477951@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260817132543.039278408@linuxfoundation.org> References: <20260817132543.039278408@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.1-stable review patch. If anyone has any objections, please let me know. ------------------ From: Yangyu Chen commit 452636ea5410a96e02ebaaf80b21e3620b98e0dd upstream. aq_vec_deinit() drains the TX rings with a single aq_ring_tx_clean() call, which frees at most AQ_CFG_TX_CLEAN_BUDGET (256) descriptors and stops at hw_head, which no longer moves once aq_vec_stop() has stopped the hardware and NAPI. Completed descriptors beyond the budget and everything still posted in [hw_head, sw_tail) keep their skb or xdp_frame when the interface goes down: aq_vec_ring_free() then frees the buffer ring and the references are lost for good. Today this is a silent memory leak on every interface down under TX/XDP_TX load. With the conversion of the RX path to page_pool posted for net-next it becomes much more visible: XDP_TX frames carry fragment references on the RX ring's page_pool, so a single stranded frame keeps the pool's inflight count above zero forever. page_pool_destroy() then never completes, the pool is leaked together with its pages, and "page_pool_release_retry() stalled pool shutdown" is warned every 60 seconds from that point on, on every ifdown, XDP detach or ring resize under XDP_TX load. Bring back aq_ring_tx_deinit() as it was before the removal and use it for teardown again, with one extension: TX rings can hold xdp_frames nowadays, so release those too. They are returned with xdp_return_frame() since this runs in process context. Fixes: eb36bedf28be ("net: aquantia: remove function aq_ring_tx_deinit") Cc: stable@vger.kernel.org # v4.11+ Reviewed-by: Sukhdeep Singh Signed-off-by: Yangyu Chen Acked-by: Mina Almasry Link: https://patch.msgid.link/tencent_EEDC35FAF2750A3A6A0B39BAE0E2C484860A@qq.com Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 29 +++++++++++++++++++++++ drivers/net/ethernet/aquantia/atlantic/aq_ring.h | 1 drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 2 - 3 files changed, 31 insertions(+), 1 deletion(-) --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c @@ -336,6 +336,35 @@ out: return !!budget; } +void aq_ring_tx_deinit(struct aq_ring_s *self) +{ + if (!self) + return; + + for (; self->sw_head != self->sw_tail; + self->sw_head = aq_ring_next_dx(self, self->sw_head)) { + struct aq_ring_buff_s *buff = &self->buff_ring[self->sw_head]; + struct device *ndev = aq_nic_get_dev(self->aq_nic); + + if (buff->is_mapped) { + if (buff->is_sop) { + dma_unmap_single(ndev, buff->pa, buff->len, + DMA_TO_DEVICE); + } else { + dma_unmap_page(ndev, buff->pa, buff->len, + DMA_TO_DEVICE); + } + } + + if (buff->is_eop) { + if (buff->skb) + dev_kfree_skb_any(buff->skb); + else if (buff->xdpf) + xdp_return_frame(buff->xdpf); + } + } +} + static void aq_rx_checksum(struct aq_ring_s *self, struct aq_ring_buff_s *buff, struct sk_buff *skb) --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h @@ -199,6 +199,7 @@ void aq_ring_update_queue_state(struct a void aq_ring_queue_wake(struct aq_ring_s *ring); void aq_ring_queue_stop(struct aq_ring_s *ring); bool aq_ring_tx_clean(struct aq_ring_s *self); +void aq_ring_tx_deinit(struct aq_ring_s *self); int aq_xdp_xmit(struct net_device *dev, int num_frames, struct xdp_frame **frames, u32 flags); int aq_ring_rx_clean(struct aq_ring_s *self, --- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c @@ -275,7 +275,7 @@ void aq_vec_deinit(struct aq_vec_s *self for (i = 0U; self->tx_rings > i; ++i) { ring = self->ring[i]; - aq_ring_tx_clean(&ring[AQ_VEC_TX_ID]); + aq_ring_tx_deinit(&ring[AQ_VEC_TX_ID]); aq_ring_rx_deinit(&ring[AQ_VEC_RX_ID]); }