mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 14:33:24 -04:00
wifi: ath12k: Advertise multicast Ethernet encapsulation offload support
Advertise IEEE80211_OFFLOAD_ENCAP_MCAST to inform mac80211 that multicast frame encapsulation is handled in hardware. This allows mac80211 to pass Ethernet-formatted multicast frames directly to the driver. In ath12k_wifi7_mac_op_tx(), refine the logic that selects the MLO multicast replication path. Add a sta pointer check so that only unicast Hardware-encap frames use the direct transmit path, while multicast Hardware-encap frames fall through to the MLO replication loop and are transmitted on each active link. In the MLO replication loop, use skb_clone() for Hardware-encap frames. These frames are already in Ethernet format and do not require 802.11 link address rewriting by ath12k_mlo_mcast_update_tx_link_address(). 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/20260623100501.2100119-1-tamizh.raja@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
This commit is contained in:
committed by
Jeff Johnson
parent
784f7dabf5
commit
e47d6c9bb4
@@ -10117,7 +10117,8 @@ static void ath12k_mac_update_vif_offload(struct ath12k_link_vif *arvif)
|
||||
if (vif->type != NL80211_IFTYPE_STATION &&
|
||||
vif->type != NL80211_IFTYPE_AP)
|
||||
vif->offload_flags &= ~(IEEE80211_OFFLOAD_ENCAP_ENABLED |
|
||||
IEEE80211_OFFLOAD_DECAP_ENABLED);
|
||||
IEEE80211_OFFLOAD_DECAP_ENABLED |
|
||||
IEEE80211_OFFLOAD_ENCAP_MCAST);
|
||||
|
||||
if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) {
|
||||
ahvif->dp_vif.tx_encap_type = ATH12K_HW_TXRX_ETHERNET;
|
||||
@@ -10136,6 +10137,9 @@ static void ath12k_mac_update_vif_offload(struct ath12k_link_vif *arvif)
|
||||
vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
|
||||
}
|
||||
|
||||
if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
|
||||
vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_MCAST;
|
||||
|
||||
param_id = WMI_VDEV_PARAM_RX_DECAP_TYPE;
|
||||
if (vif->offload_flags & IEEE80211_OFFLOAD_DECAP_ENABLED)
|
||||
param_value = ATH12K_HW_TXRX_ETHERNET;
|
||||
|
||||
@@ -903,6 +903,7 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw,
|
||||
struct ethhdr *eth;
|
||||
bool is_prb_rsp;
|
||||
u16 mcbc_gsn;
|
||||
u8 cb_flags;
|
||||
u8 link_id;
|
||||
int ret;
|
||||
struct ath12k_dp *tmp_dp;
|
||||
@@ -996,8 +997,13 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw,
|
||||
ieee80211_has_protected(hdr->frame_control))
|
||||
is_dvlan = true;
|
||||
|
||||
/*
|
||||
* Add a sta pointer check to differentiate multicast encapsulation
|
||||
* offload packets, as the ATH12K_SKB_HW_80211_ENCAP flag is also set
|
||||
* for such packets.
|
||||
*/
|
||||
if (!vif->valid_links || !is_mcast || is_dvlan ||
|
||||
(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) ||
|
||||
((skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) && sta) ||
|
||||
test_bit(ATH12K_FLAG_RAW_MODE, &ar->ab->dev_flags)) {
|
||||
ret = ath12k_wifi7_dp_tx(dp_pdev, arvif, arsta, skb, false, 0, is_mcast);
|
||||
if (unlikely(ret)) {
|
||||
@@ -1009,6 +1015,7 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw,
|
||||
mcbc_gsn = atomic_inc_return(&ahvif->dp_vif.mcbc_gsn) & 0xfff;
|
||||
|
||||
links_map = ahvif->links_map;
|
||||
cb_flags = skb_cb->flags;
|
||||
for_each_set_bit(link_id, &links_map,
|
||||
IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
tmp_arvif = rcu_dereference(ahvif->link[link_id]);
|
||||
@@ -1016,21 +1023,45 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw,
|
||||
continue;
|
||||
|
||||
tmp_ar = tmp_arvif->ar;
|
||||
tmp_dp_pdev = ath12k_dp_to_pdev_dp(tmp_ar->ab->dp,
|
||||
tmp_dp = ath12k_ab_to_dp(tmp_ar->ab);
|
||||
tmp_dp_pdev = ath12k_dp_to_pdev_dp(tmp_dp,
|
||||
tmp_ar->pdev_idx);
|
||||
if (!tmp_dp_pdev)
|
||||
continue;
|
||||
msdu_copied = skb_copy(skb, GFP_ATOMIC);
|
||||
if (!msdu_copied) {
|
||||
ath12k_err(ar->ab,
|
||||
"skb copy failure link_id 0x%X vdevid 0x%X\n",
|
||||
link_id, tmp_arvif->vdev_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
ath12k_mlo_mcast_update_tx_link_address(vif, link_id,
|
||||
msdu_copied,
|
||||
info_flags);
|
||||
if (cb_flags & ATH12K_SKB_HW_80211_ENCAP) {
|
||||
/*
|
||||
* skb->data may be modified for the iova_mask devices.
|
||||
* It is better to use skb_copy() for such devices
|
||||
* to avoid any potential skb corruption related issues.
|
||||
*/
|
||||
if (tmp_dp->hw_params->iova_mask)
|
||||
msdu_copied = skb_copy(skb, GFP_ATOMIC);
|
||||
else
|
||||
/*
|
||||
* ath12k_wifi7_dp_tx() should treat cloned HW-encap
|
||||
* Ethernet multicast frames as read-only.
|
||||
*/
|
||||
msdu_copied = skb_clone(skb, GFP_ATOMIC);
|
||||
if (!msdu_copied) {
|
||||
ath12k_err(ar->ab,
|
||||
"skb copy/clone failure link_id 0x%X vdevid 0x%X\n",
|
||||
link_id, tmp_arvif->vdev_id);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
msdu_copied = skb_copy(skb, GFP_ATOMIC);
|
||||
if (!msdu_copied) {
|
||||
ath12k_err(ar->ab,
|
||||
"skb copy failure link_id 0x%X vdevid 0x%X\n",
|
||||
link_id, tmp_arvif->vdev_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
ath12k_mlo_mcast_update_tx_link_address(vif, link_id,
|
||||
msdu_copied,
|
||||
info_flags);
|
||||
}
|
||||
|
||||
skb_cb = ATH12K_SKB_CB(msdu_copied);
|
||||
skb_cb->link_id = link_id;
|
||||
@@ -1046,7 +1077,6 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw,
|
||||
if (unlikely(!ahvif->dp_vif.key_cipher))
|
||||
goto skip_peer_find;
|
||||
|
||||
tmp_dp = ath12k_ab_to_dp(tmp_ar->ab);
|
||||
spin_lock_bh(&tmp_dp->dp_lock);
|
||||
peer = ath12k_dp_link_peer_find_by_addr(tmp_dp,
|
||||
tmp_arvif->bssid);
|
||||
@@ -1065,11 +1095,16 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw,
|
||||
skb_cb->cipher = key->cipher;
|
||||
skb_cb->flags |= ATH12K_SKB_CIPHER_SET;
|
||||
|
||||
if (skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP)
|
||||
goto skip_fctl_protected_check;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)msdu_copied->data;
|
||||
if (!ieee80211_has_protected(hdr->frame_control))
|
||||
hdr->frame_control |=
|
||||
cpu_to_le16(IEEE80211_FCTL_PROTECTED);
|
||||
}
|
||||
|
||||
skip_fctl_protected_check:
|
||||
spin_unlock_bh(&tmp_dp->dp_lock);
|
||||
|
||||
skip_peer_find:
|
||||
|
||||
Reference in New Issue
Block a user