From: Paolo Abeni <pabeni@redhat.com>
To: Wang Jun <1742789905@qq.com>, kuba@kernel.org
Cc: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
simon.horman@corigine.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, gszhai@bjtu.edu.cn,
25125332@bjtu.edu.cn, 25125283@bjtu.edu.cn, 23120469@bjtu.edu.cn,
stable@vger.kernel.org
Subject: Re: [PATCH] net: ns83820: check DMA mapping errors in hard_start_xmit
Date: Tue, 31 Mar 2026 12:05:19 +0200 [thread overview]
Message-ID: <51dfd8ae-dc4e-4837-9b00-c596c457117e@redhat.com> (raw)
In-Reply-To: <tencent_5F1EACA5E1063E7E346A4138913F7486A009@qq.com>
On 3/27/26 2:16 AM, Wang Jun wrote:
> The ns83820 driver currently ignores the return values of dma_map_single()
> and skb_frag_dma_map() in the transmit path. If DMA mapping fails due to
> IOMMU exhaustion or SWIOTLB pressure, the driver may proceed with invalid
> DMA addresses, potentially causing hardware errors, data corruption, or
> system instability.
>
> Additionally, if mapping fails midway through processing fragmented
> packets,previously mapped DMA resources are not released, leading
> to DMA resource leaks.
>
> Fix this by:
> 1. Checking dma_mapping_error() after each DMA mapping call.
> 2. Implementing an error handling path to unmap successfully
> mapped buffers(both linear and fragments) using
> dma_unmap_single().
> 3. Freeing the skb using dev_kfree_skb_any() to safely handle
> both process and softirq contexts, as hard_start_xmit may be
> called with IRQs enabled.
> 4. Returning NETDEV_TX_OK to drop the packet gracefully and
> prevent TX queue stagnation.
>
> This ensures compliance with the DMA API guidelines and
> improves driver stability under memory pressure.
>
> Fixes: fd9e4d6fec15 ("natsemi: switch from 'pci_' to 'dma_' API")
The fix tag looks wrong, as the above just to mechanical substitution of
used APIs. The issue is pre-existent
> Cc: stable@vger.kernel.org
> Signed-off-by: Wang Jun <1742789905@qq.com>
> ---
> drivers/net/ethernet/natsemi/ns83820.c | 32 ++++++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
>
> diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
> index cdbf82affa7b..90465e4977c3 100644
> --- a/drivers/net/ethernet/natsemi/ns83820.c
> +++ b/drivers/net/ethernet/natsemi/ns83820.c
> @@ -1051,6 +1051,12 @@ static netdev_tx_t ns83820_hard_start_xmit(struct sk_buff *skb,
> int stopped = 0;
> int do_intr = 0;
> volatile __le32 *first_desc;
> + dma_addr_t frag_dma_addr[MAX_SKB_FRAGS];
> + unsigned int frag_dma_len[MAX_SKB_FRAGS];
> + int frag_mapped_count = 0;
> + dma_addr_t main_buf = 0;
> + unsigned int main_len = 0;
> + int i;
Please respect the reverse christmas tree order above.
> dprintk("ns83820_hard_start_xmit\n");
>
> @@ -1121,6 +1127,13 @@ static netdev_tx_t ns83820_hard_start_xmit(struct sk_buff *skb,
> buf = dma_map_single(&dev->pci_dev->dev, skb->data, len,
> DMA_TO_DEVICE);
>
> + if (dma_mapping_error(&dev->pci_dev->dev, buf)) {
> + dev_kfree_skb_any(skb);
> + return NETDEV_TX_OK;
> + }
> + main_buf = buf;
> + main_len = len;
> +
> first_desc = dev->tx_descs + (free_idx * DESC_SIZE);
>
> for (;;) {
> @@ -1144,6 +1157,15 @@ static netdev_tx_t ns83820_hard_start_xmit(struct sk_buff *skb,
>
> buf = skb_frag_dma_map(&dev->pci_dev->dev, frag, 0,
> skb_frag_size(frag), DMA_TO_DEVICE);
> + if (dma_mapping_error(&dev->pci_dev->dev, buf))
> + goto dma_map_error;
> +
> + if (frag_mapped_count < MAX_SKB_FRAGS) {
> + frag_dma_addr[frag_mapped_count] = buf;
> + frag_dma_len[frag_mapped_count] = skb_frag_size(frag);
> + frag_mapped_count++;
> + }
> +
> dprintk("frag: buf=%08Lx page=%08lx offset=%08lx\n",
> (long long)buf, (long) page_to_pfn(frag->page),
> frag->page_offset);
> @@ -1166,6 +1188,16 @@ static netdev_tx_t ns83820_hard_start_xmit(struct sk_buff *skb,
> if (stopped && (dev->tx_done_idx != tx_done_idx) && start_tx_okay(dev))
> netif_start_queue(ndev);
>
> + return NETDEV_TX_OK;
> +dma_map_error:
> + dma_unmap_single(&dev->pci_dev->dev, main_buf, main_len, DMA_TO_DEVICE);
> + for (i = 0; i < frag_mapped_count; i++) {
> + dma_unmap_single(&dev->pci_dev->dev, frag_dma_addr[i], frag_dma_len[i],
> + DMA_TO_DEVICE);
> + }
> +
> + dev_kfree_skb_any(skb);
AI review says:
If nr_free < MIN_TX_DESC_FREE earlier in the function, netif_stop_queue
is called and the stopped flag is set to 1. By returning NETDEV_TX_OK
directly from the error path, we skip the race check at the end of the
normal
flow:
if (stopped && (dev->tx_done_idx != tx_done_idx) && start_tx_okay(dev))
netif_start_queue(ndev);
If all pending packets completed concurrently right before the queue was
stopped, could this cause the TX queue to stall indefinitely until the
tx watchdog fires?
next prev parent reply other threads:[~2026-03-31 10:05 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-27 1:16 [PATCH] net: ns83820: check DMA mapping errors in hard_start_xmit Wang Jun
2026-03-31 10:05 ` Paolo Abeni [this message]
2026-03-31 11:14 ` Wang Jun
2026-03-31 12:09 ` Eric Dumazet
2026-03-31 12:21 ` [PATCH v2] net: ns83820: fix DMA mapping error handling in hard_start_xmit Wang Jun
2026-03-31 23:49 ` Joe Damato
2026-04-01 1:07 ` Jakub Kicinski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=51dfd8ae-dc4e-4837-9b00-c596c457117e@redhat.com \
--to=pabeni@redhat.com \
--cc=1742789905@qq.com \
--cc=23120469@bjtu.edu.cn \
--cc=25125283@bjtu.edu.cn \
--cc=25125332@bjtu.edu.cn \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=gszhai@bjtu.edu.cn \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=simon.horman@corigine.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox