mirror of
https://github.com/torvalds/linux.git
synced 2026-10-11 21:07:03 +02: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:
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 &&
|
if (vif->type != NL80211_IFTYPE_STATION &&
|
||||||
vif->type != NL80211_IFTYPE_AP)
|
vif->type != NL80211_IFTYPE_AP)
|
||||||
vif->offload_flags &= ~(IEEE80211_OFFLOAD_ENCAP_ENABLED |
|
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) {
|
if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) {
|
||||||
ahvif->dp_vif.tx_encap_type = ATH12K_HW_TXRX_ETHERNET;
|
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;
|
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;
|
param_id = WMI_VDEV_PARAM_RX_DECAP_TYPE;
|
||||||
if (vif->offload_flags & IEEE80211_OFFLOAD_DECAP_ENABLED)
|
if (vif->offload_flags & IEEE80211_OFFLOAD_DECAP_ENABLED)
|
||||||
param_value = ATH12K_HW_TXRX_ETHERNET;
|
param_value = ATH12K_HW_TXRX_ETHERNET;
|
||||||
|
|
|
||||||
|
|
@ -903,6 +903,7 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw,
|
||||||
struct ethhdr *eth;
|
struct ethhdr *eth;
|
||||||
bool is_prb_rsp;
|
bool is_prb_rsp;
|
||||||
u16 mcbc_gsn;
|
u16 mcbc_gsn;
|
||||||
|
u8 cb_flags;
|
||||||
u8 link_id;
|
u8 link_id;
|
||||||
int ret;
|
int ret;
|
||||||
struct ath12k_dp *tmp_dp;
|
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))
|
ieee80211_has_protected(hdr->frame_control))
|
||||||
is_dvlan = true;
|
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 ||
|
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)) {
|
test_bit(ATH12K_FLAG_RAW_MODE, &ar->ab->dev_flags)) {
|
||||||
ret = ath12k_wifi7_dp_tx(dp_pdev, arvif, arsta, skb, false, 0, is_mcast);
|
ret = ath12k_wifi7_dp_tx(dp_pdev, arvif, arsta, skb, false, 0, is_mcast);
|
||||||
if (unlikely(ret)) {
|
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;
|
mcbc_gsn = atomic_inc_return(&ahvif->dp_vif.mcbc_gsn) & 0xfff;
|
||||||
|
|
||||||
links_map = ahvif->links_map;
|
links_map = ahvif->links_map;
|
||||||
|
cb_flags = skb_cb->flags;
|
||||||
for_each_set_bit(link_id, &links_map,
|
for_each_set_bit(link_id, &links_map,
|
||||||
IEEE80211_MLD_MAX_NUM_LINKS) {
|
IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||||
tmp_arvif = rcu_dereference(ahvif->link[link_id]);
|
tmp_arvif = rcu_dereference(ahvif->link[link_id]);
|
||||||
|
|
@ -1016,21 +1023,45 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tmp_ar = tmp_arvif->ar;
|
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);
|
tmp_ar->pdev_idx);
|
||||||
if (!tmp_dp_pdev)
|
if (!tmp_dp_pdev)
|
||||||
continue;
|
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,
|
if (cb_flags & ATH12K_SKB_HW_80211_ENCAP) {
|
||||||
msdu_copied,
|
/*
|
||||||
info_flags);
|
* 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 = ATH12K_SKB_CB(msdu_copied);
|
||||||
skb_cb->link_id = link_id;
|
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))
|
if (unlikely(!ahvif->dp_vif.key_cipher))
|
||||||
goto skip_peer_find;
|
goto skip_peer_find;
|
||||||
|
|
||||||
tmp_dp = ath12k_ab_to_dp(tmp_ar->ab);
|
|
||||||
spin_lock_bh(&tmp_dp->dp_lock);
|
spin_lock_bh(&tmp_dp->dp_lock);
|
||||||
peer = ath12k_dp_link_peer_find_by_addr(tmp_dp,
|
peer = ath12k_dp_link_peer_find_by_addr(tmp_dp,
|
||||||
tmp_arvif->bssid);
|
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->cipher = key->cipher;
|
||||||
skb_cb->flags |= ATH12K_SKB_CIPHER_SET;
|
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;
|
hdr = (struct ieee80211_hdr *)msdu_copied->data;
|
||||||
if (!ieee80211_has_protected(hdr->frame_control))
|
if (!ieee80211_has_protected(hdr->frame_control))
|
||||||
hdr->frame_control |=
|
hdr->frame_control |=
|
||||||
cpu_to_le16(IEEE80211_FCTL_PROTECTED);
|
cpu_to_le16(IEEE80211_FCTL_PROTECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skip_fctl_protected_check:
|
||||||
spin_unlock_bh(&tmp_dp->dp_lock);
|
spin_unlock_bh(&tmp_dp->dp_lock);
|
||||||
|
|
||||||
skip_peer_find:
|
skip_peer_find:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user