diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 990934ec92fca..eb066449a9895 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -525,6 +525,7 @@ struct ath12k_sta { u8 num_peer; enum ieee80211_sta_state state; + u16 tcl_metadata; }; #define ATH12K_HALF_20MHZ_BW 10 diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c index 5f3bd3b9a3e97..e7eea27cd8daf 100644 --- a/drivers/net/wireless/ath/ath12k/peer.c +++ b/drivers/net/wireless/ath/ath12k/peer.c @@ -216,6 +216,13 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, if (sta) { ahsta = ath12k_sta_to_ahsta(sta); + ahsta->tcl_metadata |= u32_encode_bits(0, HTT_TCL_META_DATA_TYPE) | + u32_encode_bits(peer->peer_id, + HTT_TCL_META_DATA_PEER_ID); + + /* set HTT extension valid bit to 0 by default */ + ahsta->tcl_metadata &= ~HTT_TCL_META_DATA_VALID_HTT; + arsta = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy, ahsta->link[link_id]); diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c index 629084aa36d85..e29c6b8e8e6c8 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c @@ -59,7 +59,7 @@ static int ath12k_wifi7_dp_prepare_htt_metadata(struct sk_buff *skb) /* TODO: Remove the export once this file is built with wifi7 ko */ int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *arvif, - struct sk_buff *skb, bool gsn_valid, int mcbc_gsn, + struct ath12k_sta *ahsta, struct sk_buff *skb, bool gsn_valid, int mcbc_gsn, bool is_mcast) { struct ath12k_dp *dp = dp_pdev->dp; @@ -123,7 +123,14 @@ int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *a dp_link_vif = ath12k_dp_vif_to_dp_link_vif(&ahvif->dp_vif, arvif->link_id); ti.bank_id = dp_link_vif->bank_id; - ti.meta_data_flags = dp_link_vif->tcl_metadata; + + if (ieee80211_has_a4(hdr->frame_control) && + is_multicast_ether_addr(hdr->addr3) && ahsta) { + ti.meta_data_flags = ahsta->tcl_metadata; + ti.flags0 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TO_FW); + } else { + ti.meta_data_flags = dp_link_vif->tcl_metadata; + } if (dp_vif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW && test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags)) { diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.h b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.h index 24cf7972d41ba..a3fe4e7cbfdff 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.h +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.h @@ -8,7 +8,7 @@ #define ATH12K_DP_TX_WIFI7_H int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *arvif, - struct sk_buff *skb, bool gsn_valid, int mcbc_gsn, + struct ath12k_sta *ahsta, struct sk_buff *skb, bool gsn_valid, int mcbc_gsn, bool is_mcast); void ath12k_wifi7_dp_tx_completion_handler(struct ath12k_dp *dp, int ring_id); u32 ath12k_wifi7_dp_tx_get_vdev_bank_config(struct ath12k_base *ab, diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c index df045ddf42da9..db85c94ece60a 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c @@ -768,6 +768,7 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_key_conf *key = info->control.hw_key; struct ieee80211_sta *sta = control->sta; + struct ath12k_sta *ahsta = sta ? ath12k_sta_to_ahsta(sta) : NULL; struct ath12k_link_vif *tmp_arvif; u32 info_flags = info->flags; struct sk_buff *msdu_copied; @@ -870,7 +871,7 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw, if (!vif->valid_links || !is_mcast || is_dvlan || (skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) || test_bit(ATH12K_FLAG_RAW_MODE, &ar->ab->dev_flags)) { - ret = ath12k_wifi7_dp_tx(dp_pdev, arvif, skb, false, 0, is_mcast); + ret = ath12k_wifi7_dp_tx(dp_pdev, arvif, ahsta, skb, false, 0, is_mcast); if (unlikely(ret)) { ath12k_warn(ar->ab, "failed to transmit frame %d\n", ret); ieee80211_free_txskb(ar->ah->hw, skb); @@ -939,7 +940,7 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw, spin_unlock_bh(&tmp_dp->dp_lock); skip_peer_find: - ret = ath12k_wifi7_dp_tx(tmp_dp_pdev, tmp_arvif, + ret = ath12k_wifi7_dp_tx(tmp_dp_pdev, tmp_arvif, NULL, msdu_copied, true, mcbc_gsn, is_mcast); if (unlikely(ret)) { if (ret == -ENOMEM) {