1
1
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2
2
/*
3
- * Copyright (C) 2003-2014, 2018-2021, 2023-2024 Intel Corporation
3
+ * Copyright (C) 2003-2014, 2018-2021, 2023-2025 Intel Corporation
4
4
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
5
5
* Copyright (C) 2016-2017 Intel Deutschland GmbH
6
6
*/
@@ -1855,6 +1855,7 @@ dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, unsigned int offset,
1855
1855
* @cmd_meta: command meta to store the scatter list information for unmapping
1856
1856
* @hdr: output argument for TSO headers
1857
1857
* @hdr_room: requested length for TSO headers
1858
+ * @offset: offset into the data from which mapping should start
1858
1859
*
1859
1860
* Allocate space for a scatter gather list and TSO headers and map the SKB
1860
1861
* 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,
1864
1865
*/
1865
1866
struct sg_table * iwl_pcie_prep_tso (struct iwl_trans * trans , struct sk_buff * skb ,
1866
1867
struct iwl_cmd_meta * cmd_meta ,
1867
- u8 * * hdr , unsigned int hdr_room )
1868
+ u8 * * hdr , unsigned int hdr_room ,
1869
+ unsigned int offset )
1868
1870
{
1869
1871
struct sg_table * sgt ;
1872
+ unsigned int n_segments ;
1870
1873
1871
1874
if (WARN_ON_ONCE (skb_has_frag_list (skb )))
1872
1875
return NULL ;
1873
1876
1877
+ n_segments = DIV_ROUND_UP (skb -> len - offset , skb_shinfo (skb )-> gso_size );
1874
1878
* hdr = iwl_pcie_get_page_hdr (trans ,
1875
1879
hdr_room + __alignof__(struct sg_table ) +
1876
1880
sizeof (struct sg_table ) +
1877
- (skb_shinfo (skb )-> nr_frags + 1 ) *
1878
- sizeof (struct scatterlist ),
1881
+ n_segments * sizeof (struct scatterlist ),
1879
1882
skb );
1880
1883
if (!* hdr )
1881
1884
return NULL ;
1882
1885
1883
1886
sgt = (void * )PTR_ALIGN (* hdr + hdr_room , __alignof__(struct sg_table ));
1884
1887
sgt -> sgl = (void * )(sgt + 1 );
1885
1888
1886
- sg_init_table (sgt -> sgl , skb_shinfo ( skb ) -> nr_frags + 1 );
1889
+ sg_init_table (sgt -> sgl , n_segments );
1887
1890
1888
1891
/* 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 );
1891
1894
if (WARN_ON_ONCE (sgt -> orig_nents <= 0 ))
1892
1895
return NULL ;
1893
1896
@@ -1939,7 +1942,8 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
1939
1942
(3 + snap_ip_tcp_hdrlen + sizeof (struct ethhdr )) + iv_len ;
1940
1943
1941
1944
/* 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 );
1943
1947
if (!sgt )
1944
1948
return - ENOMEM ;
1945
1949
0 commit comments