Re: [PATCH 6.13 088/207] wifi: iwlwifi: Fix A-MSDU TSO preparation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

if you pick this patch, then please also pick "wifi: iwlwifi: pcie: Fix
TSO preparation" which was submitted recently. Otherwise there is a
regression in the n_segments calculation that can lead to packet loss.


https://lore.kernel.org/linux-wireless/20250306122425.8c0e23a3d583.I3cb4d6768c9d28ce3da6cd0a6c65466176cfc1ee@changeid/

Benjamin

On Mon, 2025-03-10 at 18:04 +0100, Greg Kroah-Hartman wrote:
> 6.13-stable review patch.  If anyone has any objections, please let me know.
> 
> ------------------
> 
> From: Ilan Peer <ilan.peer@xxxxxxxxx>
> 
> [ Upstream commit 3640dbc1f75ce15d128ea4af44226960d894f3fd ]
> 
> 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: 7f5e3038f029 ("wifi: iwlwifi: map entire SKB when sending AMSDUs")
> Signed-off-by: Ilan Peer <ilan.peer@xxxxxxxxx>
> Reviewed-by: Benjamin Berg <benjamin.berg@xxxxxxxxx>
> Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@xxxxxxxxx>
> Link: https://patch.msgid.link/20250209143303.75769a4769bf.Iaf79e8538093cdf8c446c292cc96164ad6498f61@changeid
> Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx>
> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
> ---
>  .../wireless/intel/iwlwifi/pcie/internal.h    |  5 +++--
>  .../net/wireless/intel/iwlwifi/pcie/tx-gen2.c |  5 +++--
>  drivers/net/wireless/intel/iwlwifi/pcie/tx.c  | 20 +++++++++++--------
>  3 files changed, 18 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
> index 27a7e0b5b3d51..ebe9b25cc53a9 100644
> --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
> +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
> @@ -1,6 +1,6 @@
>  /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
>  /*
> - * Copyright (C) 2003-2015, 2018-2024 Intel Corporation
> + * Copyright (C) 2003-2015, 2018-2025 Intel Corporation
>   * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
>   * Copyright (C) 2016-2017 Intel Deutschland GmbH
>   */
> @@ -643,7 +643,8 @@ dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, unsigned int offset,
>  				    unsigned int len);
>  struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb,
>  				   struct iwl_cmd_meta *cmd_meta,
> -				   u8 **hdr, unsigned int hdr_room);
> +				   u8 **hdr, unsigned int hdr_room,
> +				   unsigned int offset);
>  
>  void iwl_pcie_free_tso_pages(struct iwl_trans *trans, struct sk_buff *skb,
>  			     struct iwl_cmd_meta *cmd_meta);
> diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
> index 7bb74a480d7f1..477a05cd1288b 100644
> --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
> +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
> @@ -1,7 +1,7 @@
>  // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
>  /*
>   * Copyright (C) 2017 Intel Deutschland GmbH
> - * Copyright (C) 2018-2020, 2023-2024 Intel Corporation
> + * Copyright (C) 2018-2020, 2023-2025 Intel Corporation
>   */
>  #include <net/tso.h>
>  #include <linux/tcp.h>
> @@ -188,7 +188,8 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans,
>  		(3 + snap_ip_tcp_hdrlen + sizeof(struct ethhdr));
>  
>  	/* Our device supports 9 segments at most, it will fit in 1 page */
> -	sgt = iwl_pcie_prep_tso(trans, skb, out_meta, &start_hdr, hdr_room);
> +	sgt = iwl_pcie_prep_tso(trans, skb, out_meta, &start_hdr, hdr_room,
> +				snap_ip_tcp_hdrlen + hdr_len);
>  	if (!sgt)
>  		return -ENOMEM;
>  
> diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
> index 1ef14340953c3..f46bdc0a5fec9 100644
> --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
> +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
> @@ -1,6 +1,6 @@
>  // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
>  /*
> - * Copyright (C) 2003-2014, 2018-2021, 2023-2024 Intel Corporation
> + * Copyright (C) 2003-2014, 2018-2021, 2023-2025 Intel Corporation
>   * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
>   * Copyright (C) 2016-2017 Intel Deutschland GmbH
>   */
> @@ -1853,6 +1853,7 @@ dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, unsigned int offset,
>   * @cmd_meta: command meta to store the scatter list information for unmapping
>   * @hdr: output argument for TSO headers
>   * @hdr_room: requested length for TSO headers
> + * @offset: offset into the data from which mapping should start
>   *
>   * Allocate space for a scatter gather list and TSO headers and map the SKB
>   * using the scatter gather list. The SKB is unmapped again when the page is
> @@ -1862,18 +1863,20 @@ dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, unsigned int offset,
>   */
>  struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb,
>  				   struct iwl_cmd_meta *cmd_meta,
> -				   u8 **hdr, unsigned int hdr_room)
> +				   u8 **hdr, unsigned int hdr_room,
> +				   unsigned int offset)
>  {
>  	struct sg_table *sgt;
> +	unsigned int n_segments;
>  
>  	if (WARN_ON_ONCE(skb_has_frag_list(skb)))
>  		return NULL;
>  
> +	n_segments = DIV_ROUND_UP(skb->len - offset, skb_shinfo(skb)->gso_size);
>  	*hdr = iwl_pcie_get_page_hdr(trans,
>  				     hdr_room + __alignof__(struct sg_table) +
>  				     sizeof(struct sg_table) +
> -				     (skb_shinfo(skb)->nr_frags + 1) *
> -				     sizeof(struct scatterlist),
> +				     n_segments * sizeof(struct scatterlist),
>  				     skb);
>  	if (!*hdr)
>  		return NULL;
> @@ -1881,11 +1884,11 @@ struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb,
>  	sgt = (void *)PTR_ALIGN(*hdr + hdr_room, __alignof__(struct sg_table));
>  	sgt->sgl = (void *)(sgt + 1);
>  
> -	sg_init_table(sgt->sgl, skb_shinfo(skb)->nr_frags + 1);
> +	sg_init_table(sgt->sgl, n_segments);
>  
>  	/* Only map the data, not the header (it is copied to the TSO page) */
> -	sgt->orig_nents = skb_to_sgvec(skb, sgt->sgl, skb_headlen(skb),
> -				       skb->data_len);
> +	sgt->orig_nents = skb_to_sgvec(skb, sgt->sgl, offset,
> +				       skb->len - offset);
>  	if (WARN_ON_ONCE(sgt->orig_nents <= 0))
>  		return NULL;
>  
> @@ -1937,7 +1940,8 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
>  		(3 + snap_ip_tcp_hdrlen + sizeof(struct ethhdr)) + iv_len;
>  
>  	/* Our device supports 9 segments at most, it will fit in 1 page */
> -	sgt = iwl_pcie_prep_tso(trans, skb, out_meta, &start_hdr, hdr_room);
> +	sgt = iwl_pcie_prep_tso(trans, skb, out_meta, &start_hdr, hdr_room,
> +				snap_ip_tcp_hdrlen + hdr_len + iv_len);
>  	if (!sgt)
>  		return -ENOMEM;
>  






[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux