* [PATCH] (drivers/ethernet/atheros/atl1) test DMA mapping for error code
@ 2025-06-12 15:05 Thomas Fourier
2025-06-12 17:24 ` Charalampos Mitrodimas
2025-06-13 7:04 ` [PATCH] (drivers/ethernet/atheros/atl1) test DMA mapping for error code kernel test robot
0 siblings, 2 replies; 11+ messages in thread
From: Thomas Fourier @ 2025-06-12 15:05 UTC (permalink / raw)
Cc: Thomas Fourier, Chris Snook, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Ingo Molnar,
Thomas Gleixner, netdev, linux-kernel
According to Shuah Khan[1], all `dma_map()` functions should be tested
before using the pointer. This patch checks for errors in `dma_map()`
calls and in case of failure, unmaps the previously dma_mapped regions
and returns an error.
[1] https://events.static.linuxfound.org/sites/events/files/slides/Shuah_Khan_dma_map_error.pdf
Signed-off-by: Thomas Fourier <fourier.thomas@gmail.com>
---
drivers/net/ethernet/atheros/atlx/atl1.c | 38 ++++++++++++++++++++++--
1 file changed, 36 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index cfdb546a09e7..99d7a37b4ddf 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -1869,6 +1869,13 @@ static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
buffer_info->dma = dma_map_page(&pdev->dev, page, offset,
adapter->rx_buffer_len,
DMA_FROM_DEVICE);
+ if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
+ buffer_info->alloced = 0;
+ buffer_info->skb = NULL;
+ kfree_skb(skb);
+ adapter->soft_stats.rx_dropped++;
+ break;
+ }
rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
rfd_desc->coalese = 0;
@@ -2183,7 +2190,7 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
return 0;
}
-static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
+static int atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
struct tx_packet_desc *ptpd)
{
struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
@@ -2195,12 +2202,14 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
unsigned int f;
int retval;
u16 next_to_use;
+ u16 first_mapped;
u16 data_len;
u8 hdr_len;
buf_len -= skb->data_len;
nr_frags = skb_shinfo(skb)->nr_frags;
next_to_use = atomic_read(&tpd_ring->next_to_use);
+ first_mapped = next_to_use;
buffer_info = &tpd_ring->buffer_info[next_to_use];
BUG_ON(buffer_info->skb);
/* put skb in last TPD */
@@ -2216,6 +2225,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
buffer_info->dma = dma_map_page(&adapter->pdev->dev, page,
offset, hdr_len,
DMA_TO_DEVICE);
+ if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
+ goto dma_err;
if (++next_to_use == tpd_ring->count)
next_to_use = 0;
@@ -2242,6 +2253,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
page, offset,
buffer_info->length,
DMA_TO_DEVICE);
+ if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
+ goto dma_err;
if (++next_to_use == tpd_ring->count)
next_to_use = 0;
}
@@ -2254,6 +2267,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
buffer_info->dma = dma_map_page(&adapter->pdev->dev, page,
offset, buf_len,
DMA_TO_DEVICE);
+ if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
+ goto dma_err;
if (++next_to_use == tpd_ring->count)
next_to_use = 0;
}
@@ -2277,6 +2292,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev,
frag, i * ATL1_MAX_TX_BUF_LEN,
buffer_info->length, DMA_TO_DEVICE);
+ if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
+ goto dma_err;
if (++next_to_use == tpd_ring->count)
next_to_use = 0;
@@ -2285,6 +2302,22 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
/* last tpd's buffer-info */
buffer_info->skb = skb;
+
+ return 0;
+
+ dma_err:
+ while (first_mapped != next_to_use) {
+ buffer_info = &tpd_ring->buffer_info[first_mapped];
+ dma_unmap_page(&adapter->pdev->dev,
+ buffer_info->dma,
+ buffer_info->length,
+ DMA_TO_DEVICE);
+ buffer_info->dma = NULL;
+
+ if (++first_mapped == tdp_ring->count)
+ first_mapped = 0;
+ }
+ return -ENOMEM;
}
static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count,
@@ -2419,7 +2452,8 @@ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb,
}
}
- atl1_tx_map(adapter, skb, ptpd);
+ if (atl1_tx_map(adapter, skb, ptpd))
+ return NETDEV_TX_BUSY;
atl1_tx_queue(adapter, count, ptpd);
atl1_update_mailbox(adapter);
return NETDEV_TX_OK;
--
2.43.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH] (drivers/ethernet/atheros/atl1) test DMA mapping for error code
2025-06-12 15:05 [PATCH] (drivers/ethernet/atheros/atl1) test DMA mapping for error code Thomas Fourier
@ 2025-06-12 17:24 ` Charalampos Mitrodimas
2025-06-13 1:32 ` Jakub Kicinski
2025-06-13 7:04 ` [PATCH] (drivers/ethernet/atheros/atl1) test DMA mapping for error code kernel test robot
1 sibling, 1 reply; 11+ messages in thread
From: Charalampos Mitrodimas @ 2025-06-12 17:24 UTC (permalink / raw)
To: Thomas Fourier
Cc: Chris Snook, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Ingo Molnar, Thomas Gleixner, netdev,
linux-kernel
Thomas Fourier <fourier.thomas@gmail.com> writes:
> According to Shuah Khan[1], all `dma_map()` functions should be tested
> before using the pointer. This patch checks for errors in `dma_map()`
> calls and in case of failure, unmaps the previously dma_mapped regions
> and returns an error.
>
> [1] https://events.static.linuxfound.org/sites/events/files/slides/Shuah_Khan_dma_map_error.pdf
>
> Signed-off-by: Thomas Fourier <fourier.thomas@gmail.com>
> ---
> drivers/net/ethernet/atheros/atlx/atl1.c | 38 ++++++++++++++++++++++--
> 1 file changed, 36 insertions(+), 2 deletions(-)
> [...]
Hi Thomas,
This doesn't seem to build. You can also see it here[1].
[1]: https://patchwork.kernel.org/project/netdevbpf/patch/20250612150542.85239-2-fourier.thomas@gmail.com/
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] (drivers/ethernet/atheros/atl1) test DMA mapping for error code
2025-06-12 17:24 ` Charalampos Mitrodimas
@ 2025-06-13 1:32 ` Jakub Kicinski
2025-06-13 9:54 ` [PATCH v2] " Thomas Fourier
0 siblings, 1 reply; 11+ messages in thread
From: Jakub Kicinski @ 2025-06-13 1:32 UTC (permalink / raw)
To: Charalampos Mitrodimas
Cc: Thomas Fourier, Chris Snook, Andrew Lunn, David S. Miller,
Eric Dumazet, Paolo Abeni, Ingo Molnar, Thomas Gleixner, netdev,
linux-kernel
On Thu, 12 Jun 2025 17:24:02 +0000 Charalampos Mitrodimas wrote:
> This doesn't seem to build. You can also see it here[1].
>
> [1]: https://patchwork.kernel.org/project/netdevbpf/patch/20250612150542.85239-2-fourier.thomas@gmail.com/
Please don't share links to the patchwork checks.
Confirm its not a false positive and copy the output into the email.
Patchwork checks are *not* a public CI for people to yolo their
untested code into. Sharing links may give such impression.
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2] (drivers/ethernet/atheros/atl1) test DMA mapping for error code
2025-06-13 1:32 ` Jakub Kicinski
@ 2025-06-13 9:54 ` Thomas Fourier
2025-06-13 14:43 ` Jakub Kicinski
0 siblings, 1 reply; 11+ messages in thread
From: Thomas Fourier @ 2025-06-13 9:54 UTC (permalink / raw)
Cc: Thomas Fourier, Chris Snook, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Gleixner,
Ingo Molnar, netdev, linux-kernel
According to Shuah Khan[1], all `dma_map()` functions should be tested
before using the pointer. This patch checks for errors after all `dma_map()`
calls.
In `atl1_alloc_rx_buffers()`, the buffer is deallocated ans marked as such.
In `atl1_tx_map()`, the arleady dma_mapped buffers are de-mapped and an error
is returned.
[1] https://events.static.linuxfound.org/sites/events/files/slides/Shuah_Khan_dma_map_error.pdf
Signed-off-by: Thomas Fourier <fourier.thomas@gmail.com>
---
drivers/net/ethernet/atheros/atlx/atl1.c | 39 ++++++++++++++++++++++--
1 file changed, 37 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index cfdb546a09e7..d3cd51ccf621 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -1869,6 +1869,14 @@ static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
buffer_info->dma = dma_map_page(&pdev->dev, page, offset,
adapter->rx_buffer_len,
DMA_FROM_DEVICE);
+ if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
+ buffer_info->alloced = 0;
+ buffer_info->skb = NULL;
+ buffer_info->dma = 0;
+ kfree_skb(skb);
+ adapter->soft_stats.rx_dropped++;
+ break;
+ }
rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
rfd_desc->coalese = 0;
@@ -2183,7 +2191,7 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
return 0;
}
-static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
+static int atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
struct tx_packet_desc *ptpd)
{
struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
@@ -2195,12 +2203,14 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
unsigned int f;
int retval;
u16 next_to_use;
+ u16 first_mapped;
u16 data_len;
u8 hdr_len;
buf_len -= skb->data_len;
nr_frags = skb_shinfo(skb)->nr_frags;
next_to_use = atomic_read(&tpd_ring->next_to_use);
+ first_mapped = next_to_use;
buffer_info = &tpd_ring->buffer_info[next_to_use];
BUG_ON(buffer_info->skb);
/* put skb in last TPD */
@@ -2216,6 +2226,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
buffer_info->dma = dma_map_page(&adapter->pdev->dev, page,
offset, hdr_len,
DMA_TO_DEVICE);
+ if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
+ goto dma_err;
if (++next_to_use == tpd_ring->count)
next_to_use = 0;
@@ -2242,6 +2254,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
page, offset,
buffer_info->length,
DMA_TO_DEVICE);
+ if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
+ goto dma_err;
if (++next_to_use == tpd_ring->count)
next_to_use = 0;
}
@@ -2254,6 +2268,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
buffer_info->dma = dma_map_page(&adapter->pdev->dev, page,
offset, buf_len,
DMA_TO_DEVICE);
+ if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
+ goto dma_err;
if (++next_to_use == tpd_ring->count)
next_to_use = 0;
}
@@ -2277,6 +2293,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev,
frag, i * ATL1_MAX_TX_BUF_LEN,
buffer_info->length, DMA_TO_DEVICE);
+ if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
+ goto dma_err;
if (++next_to_use == tpd_ring->count)
next_to_use = 0;
@@ -2285,6 +2303,22 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
/* last tpd's buffer-info */
buffer_info->skb = skb;
+
+ return 0;
+
+ dma_err:
+ while (first_mapped != next_to_use) {
+ buffer_info = &tpd_ring->buffer_info[first_mapped];
+ dma_unmap_page(&adapter->pdev->dev,
+ buffer_info->dma,
+ buffer_info->length,
+ DMA_TO_DEVICE);
+ buffer_info->dma = 0;
+
+ if (++first_mapped == tpd_ring->count)
+ first_mapped = 0;
+ }
+ return -ENOMEM;
}
static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count,
@@ -2419,7 +2453,8 @@ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb,
}
}
- atl1_tx_map(adapter, skb, ptpd);
+ if (atl1_tx_map(adapter, skb, ptpd))
+ return NETDEV_TX_BUSY;
atl1_tx_queue(adapter, count, ptpd);
atl1_update_mailbox(adapter);
return NETDEV_TX_OK;
--
2.43.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH v2] (drivers/ethernet/atheros/atl1) test DMA mapping for error code
2025-06-13 9:54 ` [PATCH v2] " Thomas Fourier
@ 2025-06-13 14:43 ` Jakub Kicinski
2025-06-16 13:59 ` [PATCH net] ethernet: alt1: Fix missing DMA mapping tests Thomas Fourier
0 siblings, 1 reply; 11+ messages in thread
From: Jakub Kicinski @ 2025-06-13 14:43 UTC (permalink / raw)
To: Thomas Fourier
Cc: Chris Snook, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Thomas Gleixner, Ingo Molnar, netdev, linux-kernel
On Fri, 13 Jun 2025 11:54:08 +0200 Thomas Fourier wrote:
> According to Shuah Khan[1], all `dma_map()` functions should be tested
> before using the pointer. This patch checks for errors after all `dma_map()`
> calls.
Please read:
https://www.kernel.org/doc/html/next/process/maintainer-netdev.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH net] ethernet: alt1: Fix missing DMA mapping tests
2025-06-13 14:43 ` Jakub Kicinski
@ 2025-06-16 13:59 ` Thomas Fourier
2025-06-16 17:46 ` Jakub Kicinski
2025-06-17 21:59 ` Jakub Kicinski
0 siblings, 2 replies; 11+ messages in thread
From: Thomas Fourier @ 2025-06-16 13:59 UTC (permalink / raw)
Cc: Thomas Fourier, Chris Snook, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Ingo Molnar,
Thomas Gleixner, Jeff Garzik, netdev, linux-kernel
According to Shuah Khan[1], all `dma_map()` functions should be tested
before using the pointer. This patch checks for errors after all
`dma_map()` calls.
In `atl1_alloc_rx_buffers()`, when the dma mapping fails,
the buffer is deallocated ans marked as such.
In `atl1_tx_map()`, the previously dma_mapped buffers are de-mapped and an
error is returned.
[1] https://events.static.linuxfound.org/sites/events/files/slides/Shuah_Khan_dma_map_error.pdf
Fixes: f3cc28c79760 ("Add Attansic L1 ethernet driver.")
Signed-off-by: Thomas Fourier <fourier.thomas@gmail.com>
---
drivers/net/ethernet/atheros/atlx/atl1.c | 43 ++++++++++++++++++++++--
1 file changed, 40 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index cfdb546a09e7..dd0e01d3a023 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -1869,6 +1869,14 @@ static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
buffer_info->dma = dma_map_page(&pdev->dev, page, offset,
adapter->rx_buffer_len,
DMA_FROM_DEVICE);
+ if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
+ buffer_info->alloced = 0;
+ buffer_info->skb = NULL;
+ buffer_info->dma = 0;
+ kfree_skb(skb);
+ adapter->soft_stats.rx_dropped++;
+ break;
+ }
rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
rfd_desc->coalese = 0;
@@ -2183,8 +2191,8 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
return 0;
}
-static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
- struct tx_packet_desc *ptpd)
+static int atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
+ struct tx_packet_desc *ptpd)
{
struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
struct atl1_buffer *buffer_info;
@@ -2194,6 +2202,7 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
unsigned int nr_frags;
unsigned int f;
int retval;
+ u16 first_mapped;
u16 next_to_use;
u16 data_len;
u8 hdr_len;
@@ -2201,6 +2210,7 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
buf_len -= skb->data_len;
nr_frags = skb_shinfo(skb)->nr_frags;
next_to_use = atomic_read(&tpd_ring->next_to_use);
+ first_mapped = next_to_use;
buffer_info = &tpd_ring->buffer_info[next_to_use];
BUG_ON(buffer_info->skb);
/* put skb in last TPD */
@@ -2216,6 +2226,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
buffer_info->dma = dma_map_page(&adapter->pdev->dev, page,
offset, hdr_len,
DMA_TO_DEVICE);
+ if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
+ goto dma_err;
if (++next_to_use == tpd_ring->count)
next_to_use = 0;
@@ -2242,6 +2254,9 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
page, offset,
buffer_info->length,
DMA_TO_DEVICE);
+ if (dma_mapping_error(&adapter->pdev->dev,
+ buffer_info->dma))
+ goto dma_err;
if (++next_to_use == tpd_ring->count)
next_to_use = 0;
}
@@ -2254,6 +2269,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
buffer_info->dma = dma_map_page(&adapter->pdev->dev, page,
offset, buf_len,
DMA_TO_DEVICE);
+ if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
+ goto dma_err;
if (++next_to_use == tpd_ring->count)
next_to_use = 0;
}
@@ -2277,6 +2294,9 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev,
frag, i * ATL1_MAX_TX_BUF_LEN,
buffer_info->length, DMA_TO_DEVICE);
+ if (dma_mapping_error(&adapter->pdev->dev,
+ buffer_info->dma))
+ goto dma_err;
if (++next_to_use == tpd_ring->count)
next_to_use = 0;
@@ -2285,6 +2305,22 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
/* last tpd's buffer-info */
buffer_info->skb = skb;
+
+ return 0;
+
+ dma_err:
+ while (first_mapped != next_to_use) {
+ buffer_info = &tpd_ring->buffer_info[first_mapped];
+ dma_unmap_page(&adapter->pdev->dev,
+ buffer_info->dma,
+ buffer_info->length,
+ DMA_TO_DEVICE);
+ buffer_info->dma = 0;
+
+ if (++first_mapped == tpd_ring->count)
+ first_mapped = 0;
+ }
+ return -ENOMEM;
}
static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count,
@@ -2419,7 +2455,8 @@ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb,
}
}
- atl1_tx_map(adapter, skb, ptpd);
+ if (atl1_tx_map(adapter, skb, ptpd))
+ return NETDEV_TX_BUSY;
atl1_tx_queue(adapter, count, ptpd);
atl1_update_mailbox(adapter);
return NETDEV_TX_OK;
--
2.43.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH net] ethernet: alt1: Fix missing DMA mapping tests
2025-06-16 13:59 ` [PATCH net] ethernet: alt1: Fix missing DMA mapping tests Thomas Fourier
@ 2025-06-16 17:46 ` Jakub Kicinski
2025-06-17 15:47 ` Thomas Fourier
2025-06-17 21:59 ` Jakub Kicinski
1 sibling, 1 reply; 11+ messages in thread
From: Jakub Kicinski @ 2025-06-16 17:46 UTC (permalink / raw)
To: Thomas Fourier
Cc: Chris Snook, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Ingo Molnar, Thomas Gleixner, Jeff Garzik, netdev,
linux-kernel
On Mon, 16 Jun 2025 15:59:55 +0200 Thomas Fourier wrote:
> According to Shuah Khan[1]
Sorry for a non-technical question -- are you part of some outreach /
training program? The presentation you linked is from 2013, I wonder
what made you pick up this particular task.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH net] ethernet: alt1: Fix missing DMA mapping tests
2025-06-16 17:46 ` Jakub Kicinski
@ 2025-06-17 15:47 ` Thomas Fourier
2025-06-17 21:54 ` Jakub Kicinski
0 siblings, 1 reply; 11+ messages in thread
From: Thomas Fourier @ 2025-06-17 15:47 UTC (permalink / raw)
Cc: netdev, linux-kernel
On 16/06/2025 19:46, Jakub Kicinski wrote:
> On Mon, 16 Jun 2025 15:59:55 +0200 Thomas Fourier wrote:
>> According to Shuah Khan[1]
> Sorry for a non-technical question -- are you part of some outreach /
> training program? The presentation you linked is from 2013, I wonder
> what made you pick up this particular task.
I am doing a master thesis on static analysis and I am writing a checker
with
Smatch to test if error codes are well-checked. My supervisor suggested
that
I look at DMA mapping errors checks to see if people were interested in such
patches and because they are quite easy to statically assert.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH net] ethernet: alt1: Fix missing DMA mapping tests
2025-06-17 15:47 ` Thomas Fourier
@ 2025-06-17 21:54 ` Jakub Kicinski
0 siblings, 0 replies; 11+ messages in thread
From: Jakub Kicinski @ 2025-06-17 21:54 UTC (permalink / raw)
To: Thomas Fourier; +Cc: netdev, linux-kernel
On Tue, 17 Jun 2025 17:47:50 +0200 Thomas Fourier wrote:
> On 16/06/2025 19:46, Jakub Kicinski wrote:
> > On Mon, 16 Jun 2025 15:59:55 +0200 Thomas Fourier wrote:
> >> According to Shuah Khan[1]
> > Sorry for a non-technical question -- are you part of some outreach /
> > training program? The presentation you linked is from 2013, I wonder
> > what made you pick up this particular task.
>
> I am doing a master thesis on static analysis and I am writing a checker
> with
I see.
> Smatch to test if error codes are well-checked. My supervisor suggested
> that
>
> I look at DMA mapping errors checks to see if people were interested in such
>
> patches and because they are quite easy to statically assert.
Given the community's mixed experience with researches, would you
be willing to share the name of the institution ?
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH net] ethernet: alt1: Fix missing DMA mapping tests
2025-06-16 13:59 ` [PATCH net] ethernet: alt1: Fix missing DMA mapping tests Thomas Fourier
2025-06-16 17:46 ` Jakub Kicinski
@ 2025-06-17 21:59 ` Jakub Kicinski
1 sibling, 0 replies; 11+ messages in thread
From: Jakub Kicinski @ 2025-06-17 21:59 UTC (permalink / raw)
To: Thomas Fourier
Cc: Chris Snook, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Ingo Molnar, Thomas Gleixner, Jeff Garzik, netdev,
linux-kernel
On Mon, 16 Jun 2025 15:59:55 +0200 Thomas Fourier wrote:
> According to Shuah Khan[1], all `dma_map()` functions should be tested
> before using the pointer. This patch checks for errors after all
> `dma_map()` calls.
The link and reference to Shuah's presentation is not necessary.
Just say that the DMA functions can fail so we need the error check.
> In `atl1_alloc_rx_buffers()`, when the dma mapping fails,
> the buffer is deallocated ans marked as such.
>
> In `atl1_tx_map()`, the previously dma_mapped buffers are de-mapped and an
> error is returned.
>
> [1] https://events.static.linuxfound.org/sites/events/files/slides/Shuah_Khan_dma_map_error.pdf
>
> Fixes: f3cc28c79760 ("Add Attansic L1 ethernet driver.")
> Signed-off-by: Thomas Fourier <fourier.thomas@gmail.com>
Please don't send the new versions in reply to old ones.
For those of us who use their inbox as a FIFO of pending submissions
it messes up ordering.
> diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
> index cfdb546a09e7..dd0e01d3a023 100644
> --- a/drivers/net/ethernet/atheros/atlx/atl1.c
> +++ b/drivers/net/ethernet/atheros/atlx/atl1.c
> @@ -1869,6 +1869,14 @@ static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
> buffer_info->dma = dma_map_page(&pdev->dev, page, offset,
> adapter->rx_buffer_len,
> DMA_FROM_DEVICE);
> + if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
> + buffer_info->alloced = 0;
> + buffer_info->skb = NULL;
> + buffer_info->dma = 0;
maybe you could move the map call a little further up, before all the
buffer_info fields are populated? So we dont have to clean them up?
> + kfree_skb(skb);
> + adapter->soft_stats.rx_dropped++;
> + break;
> + }
> rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
> rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
> rfd_desc->coalese = 0;
> @@ -2183,8 +2191,8 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
> return 0;
> }
>
> -static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
> - struct tx_packet_desc *ptpd)
> +static int atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
> + struct tx_packet_desc *ptpd)
> {
> struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
> struct atl1_buffer *buffer_info;
> @@ -2194,6 +2202,7 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
> unsigned int nr_frags;
> unsigned int f;
> int retval;
> + u16 first_mapped;
> u16 next_to_use;
> u16 data_len;
> u8 hdr_len;
> @@ -2201,6 +2210,7 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
> buf_len -= skb->data_len;
> nr_frags = skb_shinfo(skb)->nr_frags;
> next_to_use = atomic_read(&tpd_ring->next_to_use);
> + first_mapped = next_to_use;
> buffer_info = &tpd_ring->buffer_info[next_to_use];
> BUG_ON(buffer_info->skb);
> /* put skb in last TPD */
> @@ -2216,6 +2226,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
> buffer_info->dma = dma_map_page(&adapter->pdev->dev, page,
> offset, hdr_len,
> DMA_TO_DEVICE);
> + if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
> + goto dma_err;
>
> if (++next_to_use == tpd_ring->count)
> next_to_use = 0;
> @@ -2242,6 +2254,9 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
> page, offset,
> buffer_info->length,
> DMA_TO_DEVICE);
> + if (dma_mapping_error(&adapter->pdev->dev,
> + buffer_info->dma))
> + goto dma_err;
> if (++next_to_use == tpd_ring->count)
> next_to_use = 0;
> }
> @@ -2254,6 +2269,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
> buffer_info->dma = dma_map_page(&adapter->pdev->dev, page,
> offset, buf_len,
> DMA_TO_DEVICE);
> + if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
> + goto dma_err;
> if (++next_to_use == tpd_ring->count)
> next_to_use = 0;
> }
> @@ -2277,6 +2294,9 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
> buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev,
> frag, i * ATL1_MAX_TX_BUF_LEN,
> buffer_info->length, DMA_TO_DEVICE);
> + if (dma_mapping_error(&adapter->pdev->dev,
> + buffer_info->dma))
> + goto dma_err;
>
> if (++next_to_use == tpd_ring->count)
> next_to_use = 0;
> @@ -2285,6 +2305,22 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
>
> /* last tpd's buffer-info */
> buffer_info->skb = skb;
> +
> + return 0;
> +
> + dma_err:
> + while (first_mapped != next_to_use) {
> + buffer_info = &tpd_ring->buffer_info[first_mapped];
> + dma_unmap_page(&adapter->pdev->dev,
> + buffer_info->dma,
> + buffer_info->length,
> + DMA_TO_DEVICE);
> + buffer_info->dma = 0;
> +
> + if (++first_mapped == tpd_ring->count)
> + first_mapped = 0;
> + }
> + return -ENOMEM;
> }
>
> static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count,
> @@ -2419,7 +2455,8 @@ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb,
> }
> }
>
> - atl1_tx_map(adapter, skb, ptpd);
> + if (atl1_tx_map(adapter, skb, ptpd))
> + return NETDEV_TX_BUSY;
You should drop the packet. Occasional packet loss is better than
having a packet that we can't map for some platform reasons blocking
the queue
> atl1_tx_queue(adapter, count, ptpd);
> atl1_update_mailbox(adapter);
> return NETDEV_TX_OK;
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] (drivers/ethernet/atheros/atl1) test DMA mapping for error code
2025-06-12 15:05 [PATCH] (drivers/ethernet/atheros/atl1) test DMA mapping for error code Thomas Fourier
2025-06-12 17:24 ` Charalampos Mitrodimas
@ 2025-06-13 7:04 ` kernel test robot
1 sibling, 0 replies; 11+ messages in thread
From: kernel test robot @ 2025-06-13 7:04 UTC (permalink / raw)
To: Thomas Fourier
Cc: oe-kbuild-all, Thomas Fourier, Chris Snook, Andrew Lunn,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Ingo Molnar,
Thomas Gleixner, netdev, linux-kernel
Hi Thomas,
kernel test robot noticed the following build errors:
[auto build test ERROR on linus/master]
[also build test ERROR on v6.16-rc1 next-20250612]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Thomas-Fourier/drivers-ethernet-atheros-atl1-test-DMA-mapping-for-error-code/20250612-231733
base: linus/master
patch link: https://lore.kernel.org/r/20250612150542.85239-2-fourier.thomas%40gmail.com
patch subject: [PATCH] (drivers/ethernet/atheros/atl1) test DMA mapping for error code
config: x86_64-rhel-9.4 (https://download.01.org/0day-ci/archive/20250613/202506131458.MnU50xNO-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250613/202506131458.MnU50xNO-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506131458.MnU50xNO-lkp@intel.com/
All error/warnings (new ones prefixed by >>):
drivers/net/ethernet/atheros/atlx/atl1.c: In function 'atl1_tx_map':
>> drivers/net/ethernet/atheros/atlx/atl1.c:2315:34: warning: assignment to 'dma_addr_t' {aka 'long long unsigned int'} from 'void *' makes integer from pointer without a cast [-Wint-conversion]
2315 | buffer_info->dma = NULL;
| ^
>> drivers/net/ethernet/atheros/atlx/atl1.c:2317:39: error: 'tdp_ring' undeclared (first use in this function); did you mean 'tpd_ring'?
2317 | if (++first_mapped == tdp_ring->count)
| ^~~~~~~~
| tpd_ring
drivers/net/ethernet/atheros/atlx/atl1.c:2317:39: note: each undeclared identifier is reported only once for each function it appears in
vim +2317 drivers/net/ethernet/atheros/atlx/atl1.c
2192
2193 static int atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
2194 struct tx_packet_desc *ptpd)
2195 {
2196 struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
2197 struct atl1_buffer *buffer_info;
2198 u16 buf_len = skb->len;
2199 struct page *page;
2200 unsigned long offset;
2201 unsigned int nr_frags;
2202 unsigned int f;
2203 int retval;
2204 u16 next_to_use;
2205 u16 first_mapped;
2206 u16 data_len;
2207 u8 hdr_len;
2208
2209 buf_len -= skb->data_len;
2210 nr_frags = skb_shinfo(skb)->nr_frags;
2211 next_to_use = atomic_read(&tpd_ring->next_to_use);
2212 first_mapped = next_to_use;
2213 buffer_info = &tpd_ring->buffer_info[next_to_use];
2214 BUG_ON(buffer_info->skb);
2215 /* put skb in last TPD */
2216 buffer_info->skb = NULL;
2217
2218 retval = (ptpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
2219 if (retval) {
2220 /* TSO */
2221 hdr_len = skb_tcp_all_headers(skb);
2222 buffer_info->length = hdr_len;
2223 page = virt_to_page(skb->data);
2224 offset = offset_in_page(skb->data);
2225 buffer_info->dma = dma_map_page(&adapter->pdev->dev, page,
2226 offset, hdr_len,
2227 DMA_TO_DEVICE);
2228 if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
2229 goto dma_err;
2230
2231 if (++next_to_use == tpd_ring->count)
2232 next_to_use = 0;
2233
2234 if (buf_len > hdr_len) {
2235 int i, nseg;
2236
2237 data_len = buf_len - hdr_len;
2238 nseg = (data_len + ATL1_MAX_TX_BUF_LEN - 1) /
2239 ATL1_MAX_TX_BUF_LEN;
2240 for (i = 0; i < nseg; i++) {
2241 buffer_info =
2242 &tpd_ring->buffer_info[next_to_use];
2243 buffer_info->skb = NULL;
2244 buffer_info->length =
2245 (ATL1_MAX_TX_BUF_LEN >=
2246 data_len) ? ATL1_MAX_TX_BUF_LEN : data_len;
2247 data_len -= buffer_info->length;
2248 page = virt_to_page(skb->data +
2249 (hdr_len + i * ATL1_MAX_TX_BUF_LEN));
2250 offset = offset_in_page(skb->data +
2251 (hdr_len + i * ATL1_MAX_TX_BUF_LEN));
2252 buffer_info->dma = dma_map_page(&adapter->pdev->dev,
2253 page, offset,
2254 buffer_info->length,
2255 DMA_TO_DEVICE);
2256 if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
2257 goto dma_err;
2258 if (++next_to_use == tpd_ring->count)
2259 next_to_use = 0;
2260 }
2261 }
2262 } else {
2263 /* not TSO */
2264 buffer_info->length = buf_len;
2265 page = virt_to_page(skb->data);
2266 offset = offset_in_page(skb->data);
2267 buffer_info->dma = dma_map_page(&adapter->pdev->dev, page,
2268 offset, buf_len,
2269 DMA_TO_DEVICE);
2270 if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
2271 goto dma_err;
2272 if (++next_to_use == tpd_ring->count)
2273 next_to_use = 0;
2274 }
2275
2276 for (f = 0; f < nr_frags; f++) {
2277 const skb_frag_t *frag = &skb_shinfo(skb)->frags[f];
2278 u16 i, nseg;
2279
2280 buf_len = skb_frag_size(frag);
2281
2282 nseg = (buf_len + ATL1_MAX_TX_BUF_LEN - 1) /
2283 ATL1_MAX_TX_BUF_LEN;
2284 for (i = 0; i < nseg; i++) {
2285 buffer_info = &tpd_ring->buffer_info[next_to_use];
2286 BUG_ON(buffer_info->skb);
2287
2288 buffer_info->skb = NULL;
2289 buffer_info->length = (buf_len > ATL1_MAX_TX_BUF_LEN) ?
2290 ATL1_MAX_TX_BUF_LEN : buf_len;
2291 buf_len -= buffer_info->length;
2292 buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev,
2293 frag, i * ATL1_MAX_TX_BUF_LEN,
2294 buffer_info->length, DMA_TO_DEVICE);
2295 if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
2296 goto dma_err;
2297
2298 if (++next_to_use == tpd_ring->count)
2299 next_to_use = 0;
2300 }
2301 }
2302
2303 /* last tpd's buffer-info */
2304 buffer_info->skb = skb;
2305
2306 return 0;
2307
2308 dma_err:
2309 while (first_mapped != next_to_use) {
2310 buffer_info = &tpd_ring->buffer_info[first_mapped];
2311 dma_unmap_page(&adapter->pdev->dev,
2312 buffer_info->dma,
2313 buffer_info->length,
2314 DMA_TO_DEVICE);
> 2315 buffer_info->dma = NULL;
2316
> 2317 if (++first_mapped == tdp_ring->count)
2318 first_mapped = 0;
2319 }
2320 return -ENOMEM;
2321 }
2322
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-06-17 21:59 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-12 15:05 [PATCH] (drivers/ethernet/atheros/atl1) test DMA mapping for error code Thomas Fourier
2025-06-12 17:24 ` Charalampos Mitrodimas
2025-06-13 1:32 ` Jakub Kicinski
2025-06-13 9:54 ` [PATCH v2] " Thomas Fourier
2025-06-13 14:43 ` Jakub Kicinski
2025-06-16 13:59 ` [PATCH net] ethernet: alt1: Fix missing DMA mapping tests Thomas Fourier
2025-06-16 17:46 ` Jakub Kicinski
2025-06-17 15:47 ` Thomas Fourier
2025-06-17 21:54 ` Jakub Kicinski
2025-06-17 21:59 ` Jakub Kicinski
2025-06-13 7:04 ` [PATCH] (drivers/ethernet/atheros/atl1) test DMA mapping for error code kernel test robot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.