From: Sasha Levin Date: Sat, 12 Jul 2025 14:54:13 +0000 (-0400) Subject: Fixes for 5.10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Fmaster;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.10 Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/ethernet-atl1-add-missing-dma-mapping-error-checks-a.patch b/queue-5.10/ethernet-atl1-add-missing-dma-mapping-error-checks-a.patch new file mode 100644 index 0000000000..2e1ce91b68 --- /dev/null +++ b/queue-5.10/ethernet-atl1-add-missing-dma-mapping-error-checks-a.patch @@ -0,0 +1,212 @@ +From 55fcc420956bf7b60afcfb84d51709cc8fc6bbd3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Jun 2025 16:16:24 +0200 +Subject: ethernet: atl1: Add missing DMA mapping error checks and count errors + +From: Thomas Fourier + +[ Upstream commit d72411d20905180cdc452c553be17481b24463d2 ] + +The `dma_map_XXX()` functions can fail and must be checked using +`dma_mapping_error()`. This patch adds proper error handling for all +DMA mapping calls. + +In `atl1_alloc_rx_buffers()`, if DMA mapping fails, the buffer is +deallocated and marked accordingly. + +In `atl1_tx_map()`, previously mapped buffers are unmapped and the +packet is dropped on failure. + +If `atl1_xmit_frame()` drops the packet, increment the tx_error counter. + +Fixes: f3cc28c79760 ("Add Attansic L1 ethernet driver.") +Signed-off-by: Thomas Fourier +Link: https://patch.msgid.link/20250625141629.114984-2-fourier.thomas@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/atheros/atlx/atl1.c | 78 +++++++++++++++++------- + 1 file changed, 56 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c +index eaf96d002fa50..2e950313f427a 100644 +--- a/drivers/net/ethernet/atheros/atlx/atl1.c ++++ b/drivers/net/ethernet/atheros/atlx/atl1.c +@@ -1861,14 +1861,21 @@ static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter) + break; + } + +- buffer_info->alloced = 1; +- buffer_info->skb = skb; +- buffer_info->length = (u16) adapter->rx_buffer_len; + page = virt_to_page(skb->data); + offset = offset_in_page(skb->data); + 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)) { ++ kfree_skb(skb); ++ adapter->soft_stats.rx_dropped++; ++ break; ++ } ++ ++ buffer_info->alloced = 1; ++ buffer_info->skb = skb; ++ buffer_info->length = (u16)adapter->rx_buffer_len; ++ + 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; +@@ -2180,8 +2187,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 bool 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; +@@ -2191,6 +2198,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; +@@ -2198,6 +2206,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 */ +@@ -2213,6 +2222,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; +@@ -2239,6 +2250,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; + } +@@ -2251,6 +2265,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; + } +@@ -2274,6 +2290,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; +@@ -2282,6 +2301,22 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, + + /* last tpd's buffer-info */ + buffer_info->skb = skb; ++ ++ return true; ++ ++ 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 false; + } + + static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count, +@@ -2352,10 +2387,8 @@ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb, + + len = skb_headlen(skb); + +- if (unlikely(skb->len <= 0)) { +- dev_kfree_skb_any(skb); +- return NETDEV_TX_OK; +- } ++ if (unlikely(skb->len <= 0)) ++ goto drop_packet; + + nr_frags = skb_shinfo(skb)->nr_frags; + for (f = 0; f < nr_frags; f++) { +@@ -2369,10 +2402,8 @@ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb, + if (skb->protocol == htons(ETH_P_IP)) { + proto_hdr_len = (skb_transport_offset(skb) + + tcp_hdrlen(skb)); +- if (unlikely(proto_hdr_len > len)) { +- dev_kfree_skb_any(skb); +- return NETDEV_TX_OK; +- } ++ if (unlikely(proto_hdr_len > len)) ++ goto drop_packet; + /* need additional TPD ? */ + if (proto_hdr_len != len) + count += (len - proto_hdr_len + +@@ -2404,23 +2435,26 @@ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb, + } + + tso = atl1_tso(adapter, skb, ptpd); +- if (tso < 0) { +- dev_kfree_skb_any(skb); +- return NETDEV_TX_OK; +- } ++ if (tso < 0) ++ goto drop_packet; + + if (!tso) { + ret_val = atl1_tx_csum(adapter, skb, ptpd); +- if (ret_val < 0) { +- dev_kfree_skb_any(skb); +- return NETDEV_TX_OK; +- } ++ if (ret_val < 0) ++ goto drop_packet; + } + +- atl1_tx_map(adapter, skb, ptpd); ++ if (!atl1_tx_map(adapter, skb, ptpd)) ++ goto drop_packet; ++ + atl1_tx_queue(adapter, count, ptpd); + atl1_update_mailbox(adapter); + return NETDEV_TX_OK; ++ ++drop_packet: ++ adapter->soft_stats.tx_errors++; ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; + } + + static int atl1_rings_clean(struct napi_struct *napi, int budget) +-- +2.39.5 + diff --git a/queue-5.10/series b/queue-5.10/series index 5c18796773..a87c8b5d05 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -184,3 +184,4 @@ pinctrl-qcom-msm-mark-certain-pins-as-invalid-for-interrupts.patch drm-sched-increment-job-count-before-swapping-tail-spsc-queue.patch usb-gadget-u_serial-fix-race-condition-in-tty-wakeup.patch revert-acpi-battery-negate-current-when-discharging.patch +ethernet-atl1-add-missing-dma-mapping-error-checks-a.patch