mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
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>
This commit is contained in:
parent
6d0572f615
commit
f818260ac6
|
|
@ -143,6 +143,8 @@ struct ath12k_dp_peer {
|
|||
struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS];
|
||||
struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1];
|
||||
struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1];
|
||||
|
||||
bool use_4addr;
|
||||
};
|
||||
|
||||
struct ath12k_dp_link_peer *
|
||||
|
|
|
|||
|
|
@ -1142,7 +1142,8 @@ static void ath12k_dp_rx_h_undecap_eth(struct ath12k_pdev_dp *dp_pdev,
|
|||
void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
|
||||
enum hal_encrypt_type enctype,
|
||||
bool decrypted,
|
||||
struct hal_rx_desc_data *rx_info)
|
||||
struct hal_rx_desc_data *rx_info,
|
||||
struct ath12k_dp_peer *peer)
|
||||
{
|
||||
enum ath12k_dp_rx_decap_type decap_type = rx_info->decap_type;
|
||||
struct ethhdr *ehdr;
|
||||
|
|
@ -1166,6 +1167,13 @@ void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu
|
|||
break;
|
||||
}
|
||||
|
||||
if (peer && !peer->use_4addr &&
|
||||
rx_info->is_from_ds && rx_info->is_to_ds) {
|
||||
ath12k_dp_rx_h_undecap_eth(dp_pdev, msdu, enctype, rx_info,
|
||||
decap_type);
|
||||
break;
|
||||
}
|
||||
|
||||
/* PN for mcast packets will be validated in mac80211;
|
||||
* remove eth header and add 802.11 header.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -190,7 +190,8 @@ void ath12k_dp_extract_rx_desc_data(struct ath12k_hal *hal,
|
|||
void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
|
||||
enum hal_encrypt_type enctype,
|
||||
bool decrypted,
|
||||
struct hal_rx_desc_data *rx_info);
|
||||
struct hal_rx_desc_data *rx_info,
|
||||
struct ath12k_dp_peer *peer);
|
||||
void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struct *napi,
|
||||
struct sk_buff *msdu,
|
||||
struct hal_rx_desc_data *rx_info);
|
||||
|
|
|
|||
|
|
@ -738,7 +738,9 @@ struct hal_rx_desc_data {
|
|||
addr2_present:1,
|
||||
is_mcbc:1,
|
||||
seq_ctl_valid:1,
|
||||
fc_valid:1;
|
||||
fc_valid:1,
|
||||
is_to_ds:1,
|
||||
is_from_ds:1;
|
||||
u16 msdu_len;
|
||||
u16 peer_id;
|
||||
u16 seq_no;
|
||||
|
|
|
|||
|
|
@ -6630,6 +6630,7 @@ static int ath12k_mac_sta_set_4addr(struct wiphy *wiphy, struct ath12k_sta *ahst
|
|||
arsta->addr);
|
||||
if (peer && peer->dp_peer) {
|
||||
peer->dp_peer->ucast_ra_only = true;
|
||||
peer->dp_peer->use_4addr = true;
|
||||
} else {
|
||||
spin_unlock_bh(&dp->dp_lock);
|
||||
ath12k_warn(ar->ab, "failed to find DP peer for %pM\n",
|
||||
|
|
|
|||
|
|
@ -255,6 +255,9 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
|
|||
ar->hw_link_id);
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP && peer->dp_peer)
|
||||
peer->dp_peer->ucast_ra_only = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -323,9 +323,9 @@ static void ath12k_wifi7_dp_rx_h_csum_offload(struct sk_buff *msdu,
|
|||
CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
|
||||
}
|
||||
|
||||
static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
|
||||
struct sk_buff *msdu,
|
||||
struct hal_rx_desc_data *rx_info)
|
||||
static int ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
|
||||
struct sk_buff *msdu,
|
||||
struct hal_rx_desc_data *rx_info)
|
||||
{
|
||||
struct ath12k_skb_rxcb *rxcb;
|
||||
enum hal_encrypt_type enctype;
|
||||
|
|
@ -347,6 +347,18 @@ static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
|
|||
|
||||
peer = ath12k_dp_peer_find_by_peerid(dp_pdev, rxcb->peer_id);
|
||||
if (peer) {
|
||||
/*
|
||||
* Drop the 3-address multicast packet from 4-address
|
||||
* peer To avoid receiving the duplicate multicast packet
|
||||
* Specifically from AP interface in 3-address format
|
||||
*/
|
||||
if (rxcb->is_mcbc &&
|
||||
rx_info->decap_type == DP_RX_DECAP_TYPE_ETHERNET2_DIX) {
|
||||
if (peer->use_4addr &&
|
||||
!(rx_info->is_from_ds && rx_info->is_to_ds))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* resetting mcbc bit because mcbc packets are unicast
|
||||
* packets only for AP as STA sends unicast packets.
|
||||
*/
|
||||
|
|
@ -387,15 +399,18 @@ static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
|
|||
}
|
||||
|
||||
ath12k_wifi7_dp_rx_h_csum_offload(msdu, rx_info);
|
||||
ath12k_dp_rx_h_undecap(dp_pdev, msdu, enctype, is_decrypted, rx_info);
|
||||
ath12k_dp_rx_h_undecap(dp_pdev, msdu, enctype, is_decrypted, rx_info,
|
||||
peer);
|
||||
|
||||
if (!is_decrypted || rx_info->is_mcbc)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (rx_info->decap_type != DP_RX_DECAP_TYPE_ETHERNET2_DIX) {
|
||||
hdr = (void *)msdu->data;
|
||||
hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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,
|
|||
}
|
||||
|
||||
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
|
||||
ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
|
||||
ret = ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
|
||||
if (ret)
|
||||
goto free_out;
|
||||
|
||||
rx_info->rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED;
|
||||
|
||||
|
|
@ -1035,7 +1052,7 @@ static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k_pdev_dp *dp_pdev,
|
|||
|
||||
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
|
||||
ath12k_dp_rx_h_undecap(dp_pdev, msdu, HAL_ENCRYPT_TYPE_TKIP_MIC, true,
|
||||
rx_info);
|
||||
rx_info, NULL);
|
||||
ieee80211_rx(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -1590,6 +1607,7 @@ static int ath12k_wifi7_dp_rx_h_null_q_desc(struct ath12k_pdev_dp *dp_pdev,
|
|||
u8 l3pad_bytes = rx_info->l3_pad_bytes;
|
||||
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
u32 hal_rx_desc_sz = dp->ab->hal.hal_desc_sz;
|
||||
int ret;
|
||||
|
||||
if (!rxcb->is_frag && ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE)) {
|
||||
/* 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,
|
|||
return -EINVAL;
|
||||
|
||||
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
|
||||
ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
|
||||
ret = ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rxcb->tid = rx_info->tid;
|
||||
|
||||
|
|
@ -1680,7 +1700,7 @@ static bool ath12k_wifi7_dp_rx_h_tkip_mic_err(struct ath12k_pdev_dp *dp_pdev,
|
|||
RX_FLAG_DECRYPTED);
|
||||
|
||||
ath12k_dp_rx_h_undecap(dp_pdev, msdu, HAL_ENCRYPT_TYPE_TKIP_MIC, false,
|
||||
rx_info);
|
||||
rx_info, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -184,6 +184,20 @@ static u8 ath12k_hal_rx_desc_get_l3_pad_bytes_qcc2072(struct hal_rx_desc *desc)
|
|||
RX_MSDU_END_INFO5_L3_HDR_PADDING);
|
||||
}
|
||||
|
||||
static inline
|
||||
u8 ath12k_wifi7_hal_rx_h_from_ds_qcc2072(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le16_get_bits(desc->u.qcc2072.msdu_end.info5,
|
||||
RX_MSDU_END_INFO5_FROM_DS);
|
||||
}
|
||||
|
||||
static inline
|
||||
u8 ath12k_wifi7_hal_rx_h_to_ds_qcc2072(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le16_get_bits(desc->u.qcc2072.msdu_end.info5,
|
||||
RX_MSDU_END_INFO5_TO_DS);
|
||||
}
|
||||
|
||||
static u32 ath12k_hal_rx_desc_get_mpdu_start_tag_qcc2072(struct hal_rx_desc *desc)
|
||||
{
|
||||
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_
|
|||
rx_desc_data->seq_no = ath12k_hal_rx_desc_get_mpdu_start_seq_no_qcc2072(rx_desc);
|
||||
rx_desc_data->msdu_len = ath12k_hal_rx_desc_get_msdu_len_qcc2072(ldesc);
|
||||
rx_desc_data->sgi = ath12k_hal_rx_desc_get_msdu_sgi_qcc2072(rx_desc);
|
||||
rx_desc_data->is_from_ds = ath12k_wifi7_hal_rx_h_from_ds_qcc2072(rx_desc);
|
||||
rx_desc_data->is_to_ds = ath12k_wifi7_hal_rx_h_to_ds_qcc2072(rx_desc);
|
||||
rx_desc_data->rate_mcs = ath12k_hal_rx_desc_get_msdu_rate_mcs_qcc2072(rx_desc);
|
||||
rx_desc_data->bw = ath12k_hal_rx_desc_get_msdu_rx_bw_qcc2072(rx_desc);
|
||||
rx_desc_data->phy_meta_data = ath12k_hal_rx_desc_get_msdu_freq_qcc2072(rx_desc);
|
||||
|
|
|
|||
|
|
@ -699,6 +699,20 @@ u8 ath12k_hal_rx_desc_get_mpdu_tid_qcn9274(struct hal_rx_desc *desc)
|
|||
RX_MSDU_END_INFO5_TID);
|
||||
}
|
||||
|
||||
static inline
|
||||
u8 ath12k_wifi7_hal_rx_h_from_ds_qcn9274(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
|
||||
RX_MSDU_END_INFO5_FROM_DS);
|
||||
}
|
||||
|
||||
static inline
|
||||
u8 ath12k_wifi7_hal_rx_h_to_ds_qcn9274(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
|
||||
RX_MSDU_END_INFO5_TO_DS);
|
||||
}
|
||||
|
||||
static inline
|
||||
u16 ath12k_hal_rx_desc_get_mpdu_peer_id_qcn9274(struct hal_rx_desc *desc)
|
||||
{
|
||||
|
|
@ -914,6 +928,8 @@ void ath12k_hal_extract_rx_desc_data_qcn9274(struct hal_rx_desc_data *rx_desc_da
|
|||
rx_desc_data->seq_ctl_valid =
|
||||
ath12k_hal_rx_desc_get_mpdu_seq_ctl_vld_qcn9274(rx_desc);
|
||||
rx_desc_data->fc_valid = ath12k_hal_rx_desc_get_mpdu_fc_valid_qcn9274(rx_desc);
|
||||
rx_desc_data->is_from_ds = ath12k_wifi7_hal_rx_h_from_ds_qcn9274(rx_desc);
|
||||
rx_desc_data->is_to_ds = ath12k_wifi7_hal_rx_h_to_ds_qcn9274(rx_desc);
|
||||
rx_desc_data->seq_no = ath12k_hal_rx_desc_get_mpdu_start_seq_no_qcn9274(rx_desc);
|
||||
rx_desc_data->msdu_len = ath12k_hal_rx_desc_get_msdu_len_qcn9274(ldesc);
|
||||
rx_desc_data->sgi = ath12k_hal_rx_desc_get_msdu_sgi_qcn9274(rx_desc);
|
||||
|
|
|
|||
|
|
@ -280,6 +280,20 @@ u8 ath12k_hal_rx_desc_get_l3_pad_bytes_wcn7850(struct hal_rx_desc *desc)
|
|||
RX_MSDU_END_INFO5_L3_HDR_PADDING);
|
||||
}
|
||||
|
||||
static inline
|
||||
u8 ath12k_wifi7_hal_rx_h_from_ds_wcn7850(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le16_get_bits(desc->u.wcn7850.msdu_end.info5,
|
||||
RX_MSDU_END_INFO5_FROM_DS);
|
||||
}
|
||||
|
||||
static inline
|
||||
u8 ath12k_wifi7_hal_rx_h_to_ds_wcn7850(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le16_get_bits(desc->u.wcn7850.msdu_end.info5,
|
||||
RX_MSDU_END_INFO5_TO_DS);
|
||||
}
|
||||
|
||||
static inline
|
||||
bool ath12k_hal_rx_desc_encrypt_valid_wcn7850(struct hal_rx_desc *desc)
|
||||
{
|
||||
|
|
@ -599,6 +613,8 @@ void ath12k_hal_extract_rx_desc_data_wcn7850(struct hal_rx_desc_data *rx_desc_da
|
|||
rx_desc_data->seq_no = ath12k_hal_rx_desc_get_mpdu_start_seq_no_wcn7850(rx_desc);
|
||||
rx_desc_data->msdu_len = ath12k_hal_rx_desc_get_msdu_len_wcn7850(ldesc);
|
||||
rx_desc_data->sgi = ath12k_hal_rx_desc_get_msdu_sgi_wcn7850(rx_desc);
|
||||
rx_desc_data->is_from_ds = ath12k_wifi7_hal_rx_h_from_ds_wcn7850(rx_desc);
|
||||
rx_desc_data->is_to_ds = ath12k_wifi7_hal_rx_h_to_ds_wcn7850(rx_desc);
|
||||
rx_desc_data->rate_mcs = ath12k_hal_rx_desc_get_msdu_rate_mcs_wcn7850(rx_desc);
|
||||
rx_desc_data->bw = ath12k_hal_rx_desc_get_msdu_rx_bw_wcn7850(rx_desc);
|
||||
rx_desc_data->phy_meta_data = ath12k_hal_rx_desc_get_msdu_freq_wcn7850(rx_desc);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user