Skip to content

Commit b2ca166

Browse files
committed
Merge tag 'wireless-2024-08-14' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless
Kalle Valo says: ==================== wireless fixes for v6.11 We have few fixes to drivers. The most important here is a fix for iwlwifi which caused major slowdowns for several users. * tag 'wireless-2024-08-14' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless: wifi: iwlwifi: correctly lookup DMA address in SG table wifi: mt76: mt7921: fix NULL pointer access in mt7921_ipv6_addr_change wifi: brcmfmac: cfg80211: Handle SSID based pmksa deletion wifi: rtlwifi: rtl8192du: Initialise value32 in _rtl92du_init_queue_reserved_page wifi: ath12k: use 128 bytes aligned iova in transmit path for WCN7850 ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 6c569b7 + e37a918 commit b2ca166

File tree

10 files changed

+123
-17
lines changed

10 files changed

+123
-17
lines changed

drivers/net/wireless/ath/ath12k/dp_tx.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,60 @@ static int ath12k_dp_prepare_htt_metadata(struct sk_buff *skb)
162162
return 0;
163163
}
164164

165+
static void ath12k_dp_tx_move_payload(struct sk_buff *skb,
166+
unsigned long delta,
167+
bool head)
168+
{
169+
unsigned long len = skb->len;
170+
171+
if (head) {
172+
skb_push(skb, delta);
173+
memmove(skb->data, skb->data + delta, len);
174+
skb_trim(skb, len);
175+
} else {
176+
skb_put(skb, delta);
177+
memmove(skb->data + delta, skb->data, len);
178+
skb_pull(skb, delta);
179+
}
180+
}
181+
182+
static int ath12k_dp_tx_align_payload(struct ath12k_base *ab,
183+
struct sk_buff **pskb)
184+
{
185+
u32 iova_mask = ab->hw_params->iova_mask;
186+
unsigned long offset, delta1, delta2;
187+
struct sk_buff *skb2, *skb = *pskb;
188+
unsigned int headroom = skb_headroom(skb);
189+
int tailroom = skb_tailroom(skb);
190+
int ret = 0;
191+
192+
offset = (unsigned long)skb->data & iova_mask;
193+
delta1 = offset;
194+
delta2 = iova_mask - offset + 1;
195+
196+
if (headroom >= delta1) {
197+
ath12k_dp_tx_move_payload(skb, delta1, true);
198+
} else if (tailroom >= delta2) {
199+
ath12k_dp_tx_move_payload(skb, delta2, false);
200+
} else {
201+
skb2 = skb_realloc_headroom(skb, iova_mask);
202+
if (!skb2) {
203+
ret = -ENOMEM;
204+
goto out;
205+
}
206+
207+
dev_kfree_skb_any(skb);
208+
209+
offset = (unsigned long)skb2->data & iova_mask;
210+
if (offset)
211+
ath12k_dp_tx_move_payload(skb2, offset, true);
212+
*pskb = skb2;
213+
}
214+
215+
out:
216+
return ret;
217+
}
218+
165219
int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
166220
struct sk_buff *skb)
167221
{
@@ -184,6 +238,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
184238
bool tcl_ring_retry;
185239
bool msdu_ext_desc = false;
186240
bool add_htt_metadata = false;
241+
u32 iova_mask = ab->hw_params->iova_mask;
187242

188243
if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
189244
return -ESHUTDOWN;
@@ -279,6 +334,23 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
279334
goto fail_remove_tx_buf;
280335
}
281336

337+
if (iova_mask &&
338+
(unsigned long)skb->data & iova_mask) {
339+
ret = ath12k_dp_tx_align_payload(ab, &skb);
340+
if (ret) {
341+
ath12k_warn(ab, "failed to align TX buffer %d\n", ret);
342+
/* don't bail out, give original buffer
343+
* a chance even unaligned.
344+
*/
345+
goto map;
346+
}
347+
348+
/* hdr is pointing to a wrong place after alignment,
349+
* so refresh it for later use.
350+
*/
351+
hdr = (void *)skb->data;
352+
}
353+
map:
282354
ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
283355
if (dma_mapping_error(ab->dev, ti.paddr)) {
284356
atomic_inc(&ab->soc_stats.tx_err.misc_fail);

drivers/net/wireless/ath/ath12k/hw.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
924924

925925
.acpi_guid = NULL,
926926
.supports_dynamic_smps_6ghz = true,
927+
928+
.iova_mask = 0,
927929
},
928930
{
929931
.name = "wcn7850 hw2.0",
@@ -1000,6 +1002,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
10001002

10011003
.acpi_guid = &wcn7850_uuid,
10021004
.supports_dynamic_smps_6ghz = false,
1005+
1006+
.iova_mask = ATH12K_PCIE_MAX_PAYLOAD_SIZE - 1,
10031007
},
10041008
{
10051009
.name = "qcn9274 hw2.0",
@@ -1072,6 +1076,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
10721076

10731077
.acpi_guid = NULL,
10741078
.supports_dynamic_smps_6ghz = true,
1079+
1080+
.iova_mask = 0,
10751081
},
10761082
};
10771083

drivers/net/wireless/ath/ath12k/hw.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@
9696
#define ATH12K_M3_FILE "m3.bin"
9797
#define ATH12K_REGDB_FILE_NAME "regdb.bin"
9898

99+
#define ATH12K_PCIE_MAX_PAYLOAD_SIZE 128
100+
99101
enum ath12k_hw_rate_cck {
100102
ATH12K_HW_RATE_CCK_LP_11M = 0,
101103
ATH12K_HW_RATE_CCK_LP_5_5M,
@@ -215,6 +217,8 @@ struct ath12k_hw_params {
215217

216218
const guid_t *acpi_guid;
217219
bool supports_dynamic_smps_6ghz;
220+
221+
u32 iova_mask;
218222
};
219223

220224
struct ath12k_hw_ops {

drivers/net/wireless/ath/ath12k/mac.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9193,6 +9193,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
91939193

91949194
hw->vif_data_size = sizeof(struct ath12k_vif);
91959195
hw->sta_data_size = sizeof(struct ath12k_sta);
9196+
hw->extra_tx_headroom = ab->hw_params->iova_mask;
91969197

91979198
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
91989199
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);

drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4320,9 +4320,16 @@ brcmf_pmksa_v3_op(struct brcmf_if *ifp, struct cfg80211_pmksa *pmksa,
43204320
/* Single PMK operation */
43214321
pmk_op->count = cpu_to_le16(1);
43224322
length += sizeof(struct brcmf_pmksa_v3);
4323-
memcpy(pmk_op->pmk[0].bssid, pmksa->bssid, ETH_ALEN);
4324-
memcpy(pmk_op->pmk[0].pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
4325-
pmk_op->pmk[0].pmkid_len = WLAN_PMKID_LEN;
4323+
if (pmksa->bssid)
4324+
memcpy(pmk_op->pmk[0].bssid, pmksa->bssid, ETH_ALEN);
4325+
if (pmksa->pmkid) {
4326+
memcpy(pmk_op->pmk[0].pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
4327+
pmk_op->pmk[0].pmkid_len = WLAN_PMKID_LEN;
4328+
}
4329+
if (pmksa->ssid && pmksa->ssid_len) {
4330+
memcpy(pmk_op->pmk[0].ssid.SSID, pmksa->ssid, pmksa->ssid_len);
4331+
pmk_op->pmk[0].ssid.SSID_len = pmksa->ssid_len;
4332+
}
43264333
pmk_op->pmk[0].time_left = cpu_to_le32(alive ? BRCMF_PMKSA_NO_EXPIRY : 0);
43274334
}
43284335

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,8 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans);
639639
int iwl_pcie_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq,
640640
int slots_num, bool cmd_queue);
641641

642-
dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, void *addr);
642+
dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, unsigned int offset,
643+
unsigned int len);
643644
struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb,
644645
struct iwl_cmd_meta *cmd_meta,
645646
u8 **hdr, unsigned int hdr_room);

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans,
168168
struct ieee80211_hdr *hdr = (void *)skb->data;
169169
unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room;
170170
unsigned int mss = skb_shinfo(skb)->gso_size;
171+
unsigned int data_offset = 0;
171172
dma_addr_t start_hdr_phys;
172173
u16 length, amsdu_pad;
173174
u8 *start_hdr;
@@ -260,7 +261,8 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans,
260261
int ret;
261262

262263
tb_len = min_t(unsigned int, tso.size, data_left);
263-
tb_phys = iwl_pcie_get_sgt_tb_phys(sgt, tso.data);
264+
tb_phys = iwl_pcie_get_sgt_tb_phys(sgt, data_offset,
265+
tb_len);
264266
/* Not a real mapping error, use direct comparison */
265267
if (unlikely(tb_phys == DMA_MAPPING_ERROR))
266268
goto out_err;
@@ -272,6 +274,7 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans,
272274
goto out_err;
273275

274276
data_left -= tb_len;
277+
data_offset += tb_len;
275278
tso_build_data(skb, &tso, tb_len);
276279
}
277280
}

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

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1814,23 +1814,31 @@ static void *iwl_pcie_get_page_hdr(struct iwl_trans *trans,
18141814
/**
18151815
* iwl_pcie_get_sgt_tb_phys - Find TB address in mapped SG list
18161816
* @sgt: scatter gather table
1817-
* @addr: Virtual address
1817+
* @offset: Offset into the mapped memory (i.e. SKB payload data)
1818+
* @len: Length of the area
18181819
*
1819-
* Find the entry that includes the address for the given address and return
1820-
* correct physical address for the TB entry.
1820+
* Find the DMA address that corresponds to the SKB payload data at the
1821+
* position given by @offset.
18211822
*
18221823
* Returns: Address for TB entry
18231824
*/
1824-
dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, void *addr)
1825+
dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, unsigned int offset,
1826+
unsigned int len)
18251827
{
18261828
struct scatterlist *sg;
1829+
unsigned int sg_offset = 0;
18271830
int i;
18281831

1832+
/*
1833+
* Search the mapped DMA areas in the SG for the area that contains the
1834+
* data at offset with the given length.
1835+
*/
18291836
for_each_sgtable_dma_sg(sgt, sg, i) {
1830-
if (addr >= sg_virt(sg) &&
1831-
(u8 *)addr < (u8 *)sg_virt(sg) + sg_dma_len(sg))
1832-
return sg_dma_address(sg) +
1833-
((unsigned long)addr - (unsigned long)sg_virt(sg));
1837+
if (offset >= sg_offset &&
1838+
offset + len <= sg_offset + sg_dma_len(sg))
1839+
return sg_dma_address(sg) + offset - sg_offset;
1840+
1841+
sg_offset += sg_dma_len(sg);
18341842
}
18351843

18361844
WARN_ON_ONCE(1);
@@ -1875,7 +1883,9 @@ struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb,
18751883

18761884
sg_init_table(sgt->sgl, skb_shinfo(skb)->nr_frags + 1);
18771885

1878-
sgt->orig_nents = skb_to_sgvec(skb, sgt->sgl, 0, skb->len);
1886+
/* Only map the data, not the header (it is copied to the TSO page) */
1887+
sgt->orig_nents = skb_to_sgvec(skb, sgt->sgl, skb_headlen(skb),
1888+
skb->data_len);
18791889
if (WARN_ON_ONCE(sgt->orig_nents <= 0))
18801890
return NULL;
18811891

@@ -1900,6 +1910,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
19001910
struct ieee80211_hdr *hdr = (void *)skb->data;
19011911
unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room;
19021912
unsigned int mss = skb_shinfo(skb)->gso_size;
1913+
unsigned int data_offset = 0;
19031914
u16 length, iv_len, amsdu_pad;
19041915
dma_addr_t start_hdr_phys;
19051916
u8 *start_hdr, *pos_hdr;
@@ -2000,7 +2011,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
20002011
data_left);
20012012
dma_addr_t tb_phys;
20022013

2003-
tb_phys = iwl_pcie_get_sgt_tb_phys(sgt, tso.data);
2014+
tb_phys = iwl_pcie_get_sgt_tb_phys(sgt, data_offset, size);
20042015
/* Not a real mapping error, use direct comparison */
20052016
if (unlikely(tb_phys == DMA_MAPPING_ERROR))
20062017
return -EINVAL;
@@ -2011,6 +2022,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
20112022
tb_phys, size);
20122023

20132024
data_left -= size;
2025+
data_offset += size;
20142026
tso_build_data(skb, &tso, size);
20152027
}
20162028
}

drivers/net/wireless/mediatek/mt76/mt7921/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1183,7 +1183,7 @@ static void mt7921_ipv6_addr_change(struct ieee80211_hw *hw,
11831183
struct inet6_dev *idev)
11841184
{
11851185
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
1186-
struct mt792x_dev *dev = mvif->phy->dev;
1186+
struct mt792x_dev *dev = mt792x_hw_dev(hw);
11871187
struct inet6_ifaddr *ifa;
11881188
struct in6_addr ns_addrs[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
11891189
struct sk_buff *skb;

drivers/net/wireless/realtek/rtlwifi/rtl8192du/hw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,11 @@ static void _rtl92du_init_queue_reserved_page(struct ieee80211_hw *hw,
181181
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
182182
u32 txqpagenum, txqpageunit;
183183
u32 txqremainingpage;
184+
u32 value32 = 0;
184185
u32 numhq = 0;
185186
u32 numlq = 0;
186187
u32 numnq = 0;
187188
u32 numpubq;
188-
u32 value32;
189189

190190
if (rtlhal->macphymode != SINGLEMAC_SINGLEPHY) {
191191
numpubq = NORMAL_PAGE_NUM_PUBQ_92D_DUAL_MAC;

0 commit comments

Comments
 (0)