Skip to content

Commit f818260

Browse files
Tamizh Chelvam Rajajeff-t-johnson
authored andcommitted
wifi: ath12k: Add support for 4-address frame notification
mac80211 currently relies on receiving 4-address frames from connected stations to trigger AP_VLAN interface creation. However, when ethernet encapsulation offload is enabled, mac80211 only receives 802.3 frames and cannot differentiate between 3-address and 4-address formats, preventing AP_VLAN creation. Enable mac80211 to detect 4-address traffic by converting 802.3 frames back into 802.11 frames in the driver and setting the FROM_DS and TO_DS bits using the RX_MSDU_END_INFO5_FROM_DS and RX_MSDU_END_INFO5_TO_DS fields. This restores 4-address frame visibility to mac80211 and allows it to trigger AP_VLAN interface creation. Skip this frame conversion once the AP_VLAN interface is created and the station is attached to it. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1 Signed-off-by: Tamizh Chelvam Raja <tamizh.raja@oss.qualcomm.com> Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com> Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com> Link: https://patch.msgid.link/20260525110942.2890212-6-tamizh.raja@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
1 parent 6d0572f commit f818260

10 files changed

Lines changed: 97 additions & 12 deletions

File tree

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ struct ath12k_dp_peer {
143143
struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS];
144144
struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1];
145145
struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1];
146+
147+
bool use_4addr;
146148
};
147149

148150
struct ath12k_dp_link_peer *

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,8 @@ static void ath12k_dp_rx_h_undecap_eth(struct ath12k_pdev_dp *dp_pdev,
11421142
void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
11431143
enum hal_encrypt_type enctype,
11441144
bool decrypted,
1145-
struct hal_rx_desc_data *rx_info)
1145+
struct hal_rx_desc_data *rx_info,
1146+
struct ath12k_dp_peer *peer)
11461147
{
11471148
enum ath12k_dp_rx_decap_type decap_type = rx_info->decap_type;
11481149
struct ethhdr *ehdr;
@@ -1166,6 +1167,13 @@ void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu
11661167
break;
11671168
}
11681169

1170+
if (peer && !peer->use_4addr &&
1171+
rx_info->is_from_ds && rx_info->is_to_ds) {
1172+
ath12k_dp_rx_h_undecap_eth(dp_pdev, msdu, enctype, rx_info,
1173+
decap_type);
1174+
break;
1175+
}
1176+
11691177
/* PN for mcast packets will be validated in mac80211;
11701178
* remove eth header and add 802.11 header.
11711179
*/

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ void ath12k_dp_extract_rx_desc_data(struct ath12k_hal *hal,
190190
void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
191191
enum hal_encrypt_type enctype,
192192
bool decrypted,
193-
struct hal_rx_desc_data *rx_info);
193+
struct hal_rx_desc_data *rx_info,
194+
struct ath12k_dp_peer *peer);
194195
void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struct *napi,
195196
struct sk_buff *msdu,
196197
struct hal_rx_desc_data *rx_info);

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,9 @@ struct hal_rx_desc_data {
738738
addr2_present:1,
739739
is_mcbc:1,
740740
seq_ctl_valid:1,
741-
fc_valid:1;
741+
fc_valid:1,
742+
is_to_ds:1,
743+
is_from_ds:1;
742744
u16 msdu_len;
743745
u16 peer_id;
744746
u16 seq_no;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6630,6 +6630,7 @@ static int ath12k_mac_sta_set_4addr(struct wiphy *wiphy, struct ath12k_sta *ahst
66306630
arsta->addr);
66316631
if (peer && peer->dp_peer) {
66326632
peer->dp_peer->ucast_ra_only = true;
6633+
peer->dp_peer->use_4addr = true;
66336634
} else {
66346635
spin_unlock_bh(&dp->dp_lock);
66356636
ath12k_warn(ar->ab, "failed to find DP peer for %pM\n",

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,9 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
255255
ar->hw_link_id);
256256
}
257257

258+
if (vif->type == NL80211_IFTYPE_AP && peer->dp_peer)
259+
peer->dp_peer->ucast_ra_only = true;
260+
258261
return ret;
259262
}
260263

drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,9 @@ static void ath12k_wifi7_dp_rx_h_csum_offload(struct sk_buff *msdu,
323323
CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
324324
}
325325

326-
static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
327-
struct sk_buff *msdu,
328-
struct hal_rx_desc_data *rx_info)
326+
static int ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
327+
struct sk_buff *msdu,
328+
struct hal_rx_desc_data *rx_info)
329329
{
330330
struct ath12k_skb_rxcb *rxcb;
331331
enum hal_encrypt_type enctype;
@@ -347,6 +347,18 @@ static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
347347

348348
peer = ath12k_dp_peer_find_by_peerid(dp_pdev, rxcb->peer_id);
349349
if (peer) {
350+
/*
351+
* Drop the 3-address multicast packet from 4-address
352+
* peer To avoid receiving the duplicate multicast packet
353+
* Specifically from AP interface in 3-address format
354+
*/
355+
if (rxcb->is_mcbc &&
356+
rx_info->decap_type == DP_RX_DECAP_TYPE_ETHERNET2_DIX) {
357+
if (peer->use_4addr &&
358+
!(rx_info->is_from_ds && rx_info->is_to_ds))
359+
return -EINVAL;
360+
}
361+
350362
/* resetting mcbc bit because mcbc packets are unicast
351363
* packets only for AP as STA sends unicast packets.
352364
*/
@@ -387,15 +399,18 @@ static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
387399
}
388400

389401
ath12k_wifi7_dp_rx_h_csum_offload(msdu, rx_info);
390-
ath12k_dp_rx_h_undecap(dp_pdev, msdu, enctype, is_decrypted, rx_info);
402+
ath12k_dp_rx_h_undecap(dp_pdev, msdu, enctype, is_decrypted, rx_info,
403+
peer);
391404

392405
if (!is_decrypted || rx_info->is_mcbc)
393-
return;
406+
return 0;
394407

395408
if (rx_info->decap_type != DP_RX_DECAP_TYPE_ETHERNET2_DIX) {
396409
hdr = (void *)msdu->data;
397410
hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
398411
}
412+
413+
return 0;
399414
}
400415

401416
static int ath12k_wifi7_dp_rx_msdu_coalesce(struct ath12k_hal *hal,
@@ -554,7 +569,9 @@ static int ath12k_wifi7_dp_rx_process_msdu(struct ath12k_pdev_dp *dp_pdev,
554569
}
555570

556571
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
557-
ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
572+
ret = ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
573+
if (ret)
574+
goto free_out;
558575

559576
rx_info->rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED;
560577

@@ -1035,7 +1052,7 @@ static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k_pdev_dp *dp_pdev,
10351052

10361053
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
10371054
ath12k_dp_rx_h_undecap(dp_pdev, msdu, HAL_ENCRYPT_TYPE_TKIP_MIC, true,
1038-
rx_info);
1055+
rx_info, NULL);
10391056
ieee80211_rx(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
10401057
return -EINVAL;
10411058
}
@@ -1590,6 +1607,7 @@ static int ath12k_wifi7_dp_rx_h_null_q_desc(struct ath12k_pdev_dp *dp_pdev,
15901607
u8 l3pad_bytes = rx_info->l3_pad_bytes;
15911608
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
15921609
u32 hal_rx_desc_sz = dp->ab->hal.hal_desc_sz;
1610+
int ret;
15931611

15941612
if (!rxcb->is_frag && ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE)) {
15951613
/* First buffer will be freed by the caller, so deduct it's length */
@@ -1634,7 +1652,9 @@ static int ath12k_wifi7_dp_rx_h_null_q_desc(struct ath12k_pdev_dp *dp_pdev,
16341652
return -EINVAL;
16351653

16361654
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
1637-
ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
1655+
ret = ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
1656+
if (ret)
1657+
return ret;
16381658

16391659
rxcb->tid = rx_info->tid;
16401660

@@ -1680,7 +1700,7 @@ static bool ath12k_wifi7_dp_rx_h_tkip_mic_err(struct ath12k_pdev_dp *dp_pdev,
16801700
RX_FLAG_DECRYPTED);
16811701

16821702
ath12k_dp_rx_h_undecap(dp_pdev, msdu, HAL_ENCRYPT_TYPE_TKIP_MIC, false,
1683-
rx_info);
1703+
rx_info, NULL);
16841704
return false;
16851705
}
16861706

drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,20 @@ static u8 ath12k_hal_rx_desc_get_l3_pad_bytes_qcc2072(struct hal_rx_desc *desc)
184184
RX_MSDU_END_INFO5_L3_HDR_PADDING);
185185
}
186186

187+
static inline
188+
u8 ath12k_wifi7_hal_rx_h_from_ds_qcc2072(struct hal_rx_desc *desc)
189+
{
190+
return le16_get_bits(desc->u.qcc2072.msdu_end.info5,
191+
RX_MSDU_END_INFO5_FROM_DS);
192+
}
193+
194+
static inline
195+
u8 ath12k_wifi7_hal_rx_h_to_ds_qcc2072(struct hal_rx_desc *desc)
196+
{
197+
return le16_get_bits(desc->u.qcc2072.msdu_end.info5,
198+
RX_MSDU_END_INFO5_TO_DS);
199+
}
200+
187201
static u32 ath12k_hal_rx_desc_get_mpdu_start_tag_qcc2072(struct hal_rx_desc *desc)
188202
{
189203
return le32_get_bits(desc->u.qcc2072.mpdu_start_tag,
@@ -397,6 +411,8 @@ static void ath12k_hal_extract_rx_desc_data_qcc2072(struct hal_rx_desc_data *rx_
397411
rx_desc_data->seq_no = ath12k_hal_rx_desc_get_mpdu_start_seq_no_qcc2072(rx_desc);
398412
rx_desc_data->msdu_len = ath12k_hal_rx_desc_get_msdu_len_qcc2072(ldesc);
399413
rx_desc_data->sgi = ath12k_hal_rx_desc_get_msdu_sgi_qcc2072(rx_desc);
414+
rx_desc_data->is_from_ds = ath12k_wifi7_hal_rx_h_from_ds_qcc2072(rx_desc);
415+
rx_desc_data->is_to_ds = ath12k_wifi7_hal_rx_h_to_ds_qcc2072(rx_desc);
400416
rx_desc_data->rate_mcs = ath12k_hal_rx_desc_get_msdu_rate_mcs_qcc2072(rx_desc);
401417
rx_desc_data->bw = ath12k_hal_rx_desc_get_msdu_rx_bw_qcc2072(rx_desc);
402418
rx_desc_data->phy_meta_data = ath12k_hal_rx_desc_get_msdu_freq_qcc2072(rx_desc);

drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,20 @@ u8 ath12k_hal_rx_desc_get_mpdu_tid_qcn9274(struct hal_rx_desc *desc)
699699
RX_MSDU_END_INFO5_TID);
700700
}
701701

702+
static inline
703+
u8 ath12k_wifi7_hal_rx_h_from_ds_qcn9274(struct hal_rx_desc *desc)
704+
{
705+
return le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
706+
RX_MSDU_END_INFO5_FROM_DS);
707+
}
708+
709+
static inline
710+
u8 ath12k_wifi7_hal_rx_h_to_ds_qcn9274(struct hal_rx_desc *desc)
711+
{
712+
return le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
713+
RX_MSDU_END_INFO5_TO_DS);
714+
}
715+
702716
static inline
703717
u16 ath12k_hal_rx_desc_get_mpdu_peer_id_qcn9274(struct hal_rx_desc *desc)
704718
{
@@ -914,6 +928,8 @@ void ath12k_hal_extract_rx_desc_data_qcn9274(struct hal_rx_desc_data *rx_desc_da
914928
rx_desc_data->seq_ctl_valid =
915929
ath12k_hal_rx_desc_get_mpdu_seq_ctl_vld_qcn9274(rx_desc);
916930
rx_desc_data->fc_valid = ath12k_hal_rx_desc_get_mpdu_fc_valid_qcn9274(rx_desc);
931+
rx_desc_data->is_from_ds = ath12k_wifi7_hal_rx_h_from_ds_qcn9274(rx_desc);
932+
rx_desc_data->is_to_ds = ath12k_wifi7_hal_rx_h_to_ds_qcn9274(rx_desc);
917933
rx_desc_data->seq_no = ath12k_hal_rx_desc_get_mpdu_start_seq_no_qcn9274(rx_desc);
918934
rx_desc_data->msdu_len = ath12k_hal_rx_desc_get_msdu_len_qcn9274(ldesc);
919935
rx_desc_data->sgi = ath12k_hal_rx_desc_get_msdu_sgi_qcn9274(rx_desc);

drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,20 @@ u8 ath12k_hal_rx_desc_get_l3_pad_bytes_wcn7850(struct hal_rx_desc *desc)
280280
RX_MSDU_END_INFO5_L3_HDR_PADDING);
281281
}
282282

283+
static inline
284+
u8 ath12k_wifi7_hal_rx_h_from_ds_wcn7850(struct hal_rx_desc *desc)
285+
{
286+
return le16_get_bits(desc->u.wcn7850.msdu_end.info5,
287+
RX_MSDU_END_INFO5_FROM_DS);
288+
}
289+
290+
static inline
291+
u8 ath12k_wifi7_hal_rx_h_to_ds_wcn7850(struct hal_rx_desc *desc)
292+
{
293+
return le16_get_bits(desc->u.wcn7850.msdu_end.info5,
294+
RX_MSDU_END_INFO5_TO_DS);
295+
}
296+
283297
static inline
284298
bool ath12k_hal_rx_desc_encrypt_valid_wcn7850(struct hal_rx_desc *desc)
285299
{
@@ -599,6 +613,8 @@ void ath12k_hal_extract_rx_desc_data_wcn7850(struct hal_rx_desc_data *rx_desc_da
599613
rx_desc_data->seq_no = ath12k_hal_rx_desc_get_mpdu_start_seq_no_wcn7850(rx_desc);
600614
rx_desc_data->msdu_len = ath12k_hal_rx_desc_get_msdu_len_wcn7850(ldesc);
601615
rx_desc_data->sgi = ath12k_hal_rx_desc_get_msdu_sgi_wcn7850(rx_desc);
616+
rx_desc_data->is_from_ds = ath12k_wifi7_hal_rx_h_from_ds_wcn7850(rx_desc);
617+
rx_desc_data->is_to_ds = ath12k_wifi7_hal_rx_h_to_ds_wcn7850(rx_desc);
602618
rx_desc_data->rate_mcs = ath12k_hal_rx_desc_get_msdu_rate_mcs_wcn7850(rx_desc);
603619
rx_desc_data->bw = ath12k_hal_rx_desc_get_msdu_rx_bw_wcn7850(rx_desc);
604620
rx_desc_data->phy_meta_data = ath12k_hal_rx_desc_get_msdu_freq_wcn7850(rx_desc);

0 commit comments

Comments
 (0)