Skip to content

Commit 3640dbc

Browse files
ilanpeer2jmberg-intel
authored andcommitted
wifi: iwlwifi: Fix A-MSDU TSO preparation
The TSO preparation assumed that the skb head contained the headers while the rest of the data was in the fragments. Since this is not always true, e.g., it is possible that the data was linearised, modify the TSO preparation to start the data processing after the network headers. Fixes: 7f5e303 ("wifi: iwlwifi: map entire SKB when sending AMSDUs") Signed-off-by: Ilan Peer <[email protected]> Reviewed-by: Benjamin Berg <[email protected]> Signed-off-by: Miri Korenblit <[email protected]> Link: https://patch.msgid.link/20250209143303.75769a4769bf.Iaf79e8538093cdf8c446c292cc96164ad6498f61@changeid Signed-off-by: Johannes Berg <[email protected]>
1 parent 3b08e60 commit 3640dbc

File tree

3 files changed

+18
-12
lines changed

3 files changed

+18
-12
lines changed

drivers/net/wireless/intel/iwlwifi/pcie/internal.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
22
/*
3-
* Copyright (C) 2003-2015, 2018-2024 Intel Corporation
3+
* Copyright (C) 2003-2015, 2018-2025 Intel Corporation
44
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
55
* Copyright (C) 2016-2017 Intel Deutschland GmbH
66
*/
@@ -646,7 +646,8 @@ dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, unsigned int offset,
646646
unsigned int len);
647647
struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb,
648648
struct iwl_cmd_meta *cmd_meta,
649-
u8 **hdr, unsigned int hdr_room);
649+
u8 **hdr, unsigned int hdr_room,
650+
unsigned int offset);
650651

651652
void iwl_pcie_free_tso_pages(struct iwl_trans *trans, struct sk_buff *skb,
652653
struct iwl_cmd_meta *cmd_meta);

drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
22
/*
33
* Copyright (C) 2017 Intel Deutschland GmbH
4-
* Copyright (C) 2018-2020, 2023-2024 Intel Corporation
4+
* Copyright (C) 2018-2020, 2023-2025 Intel Corporation
55
*/
66
#include <net/tso.h>
77
#include <linux/tcp.h>
@@ -188,7 +188,8 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans,
188188
(3 + snap_ip_tcp_hdrlen + sizeof(struct ethhdr));
189189

190190
/* Our device supports 9 segments at most, it will fit in 1 page */
191-
sgt = iwl_pcie_prep_tso(trans, skb, out_meta, &start_hdr, hdr_room);
191+
sgt = iwl_pcie_prep_tso(trans, skb, out_meta, &start_hdr, hdr_room,
192+
snap_ip_tcp_hdrlen + hdr_len);
192193
if (!sgt)
193194
return -ENOMEM;
194195

drivers/net/wireless/intel/iwlwifi/pcie/tx.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
22
/*
3-
* Copyright (C) 2003-2014, 2018-2021, 2023-2024 Intel Corporation
3+
* Copyright (C) 2003-2014, 2018-2021, 2023-2025 Intel Corporation
44
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
55
* Copyright (C) 2016-2017 Intel Deutschland GmbH
66
*/
@@ -1855,6 +1855,7 @@ dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, unsigned int offset,
18551855
* @cmd_meta: command meta to store the scatter list information for unmapping
18561856
* @hdr: output argument for TSO headers
18571857
* @hdr_room: requested length for TSO headers
1858+
* @offset: offset into the data from which mapping should start
18581859
*
18591860
* Allocate space for a scatter gather list and TSO headers and map the SKB
18601861
* using the scatter gather list. The SKB is unmapped again when the page is
@@ -1864,30 +1865,32 @@ dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, unsigned int offset,
18641865
*/
18651866
struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb,
18661867
struct iwl_cmd_meta *cmd_meta,
1867-
u8 **hdr, unsigned int hdr_room)
1868+
u8 **hdr, unsigned int hdr_room,
1869+
unsigned int offset)
18681870
{
18691871
struct sg_table *sgt;
1872+
unsigned int n_segments;
18701873

18711874
if (WARN_ON_ONCE(skb_has_frag_list(skb)))
18721875
return NULL;
18731876

1877+
n_segments = DIV_ROUND_UP(skb->len - offset, skb_shinfo(skb)->gso_size);
18741878
*hdr = iwl_pcie_get_page_hdr(trans,
18751879
hdr_room + __alignof__(struct sg_table) +
18761880
sizeof(struct sg_table) +
1877-
(skb_shinfo(skb)->nr_frags + 1) *
1878-
sizeof(struct scatterlist),
1881+
n_segments * sizeof(struct scatterlist),
18791882
skb);
18801883
if (!*hdr)
18811884
return NULL;
18821885

18831886
sgt = (void *)PTR_ALIGN(*hdr + hdr_room, __alignof__(struct sg_table));
18841887
sgt->sgl = (void *)(sgt + 1);
18851888

1886-
sg_init_table(sgt->sgl, skb_shinfo(skb)->nr_frags + 1);
1889+
sg_init_table(sgt->sgl, n_segments);
18871890

18881891
/* Only map the data, not the header (it is copied to the TSO page) */
1889-
sgt->orig_nents = skb_to_sgvec(skb, sgt->sgl, skb_headlen(skb),
1890-
skb->data_len);
1892+
sgt->orig_nents = skb_to_sgvec(skb, sgt->sgl, offset,
1893+
skb->len - offset);
18911894
if (WARN_ON_ONCE(sgt->orig_nents <= 0))
18921895
return NULL;
18931896

@@ -1939,7 +1942,8 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
19391942
(3 + snap_ip_tcp_hdrlen + sizeof(struct ethhdr)) + iv_len;
19401943

19411944
/* Our device supports 9 segments at most, it will fit in 1 page */
1942-
sgt = iwl_pcie_prep_tso(trans, skb, out_meta, &start_hdr, hdr_room);
1945+
sgt = iwl_pcie_prep_tso(trans, skb, out_meta, &start_hdr, hdr_room,
1946+
snap_ip_tcp_hdrlen + hdr_len + iv_len);
19431947
if (!sgt)
19441948
return -ENOMEM;
19451949

0 commit comments

Comments
 (0)