diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c index f7f0f613b393..b5a0ba149a28 100644 --- a/drivers/net/wireless/ath/ath12k/peer.c +++ b/drivers/net/wireless/ath/ath12k/peer.c @@ -220,10 +220,9 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, ahsta->link[link_id]); /* TODO: Split DP related field usage to DP peer structure */ arsta->tcl_metadata = u16_encode_bits(0, HTT_TCL_META_DATA_TYPE) | - u16_encode_bits(peer->peer_id, - HTT_TCL_META_DATA_PEER_ID) | - u16_encode_bits(0, - HTT_TCL_META_DATA_VALID_HTT); + u16_encode_bits(peer->peer_id, + HTT_TCL_META_DATA_PEER_ID) | + u16_encode_bits(0, HTT_TCL_META_DATA_VALID_HTT); arsta->ast_hash = peer->ast_hash; arsta->ast_idx = peer->hw_peer_id; peer->link_id = arsta->link_id; diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index d9f1b4615575..84a31b953db8 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -4194,6 +4194,10 @@ ath12k_wmi_copy_resource_config(struct ath12k_base *ab, wmi_cfg->ema_max_profile_period = cpu_to_le32(tg_cfg->ema_max_profile_period); wmi_cfg->flags2 |= cpu_to_le32(WMI_RSRC_CFG_FLAGS2_CALC_NEXT_DTIM_COUNT_SET | WMI_RSRC_CFG_FLAGS2_FW_AST_INDICATION_DISABLE); + + if (tg_cfg->is_wds_null_frame_supported) + wmi_cfg->flags2 |= + cpu_to_le32(WMI_RSRC_CFG_FLAGS2_WDS_NULL_FRAME_SUPPORT); } static int ath12k_init_cmd_send(struct ath12k_wmi_pdev *wmi, @@ -4403,6 +4407,9 @@ int ath12k_wmi_cmd_init(struct ath12k_base *ab) ab->wmi_ab.svc_map)) arg.res_cfg.is_reg_cc_ext_event_supported = true; + if (test_bit(WMI_TLV_SERVICE_WDS_NULL_FRAME_SUPPORT, ab->wmi_ab.svc_map)) + arg.res_cfg.is_wds_null_frame_supported = true; + ab->hw_params->wmi_init(ab, &arg.res_cfg); ab->wow.wmi_conf_rx_decap_mode = arg.res_cfg.rx_decap_mode; @@ -7224,7 +7231,11 @@ static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb) struct ath12k_wmi_mgmt_rx_arg rx_ev = {}; struct ath12k *ar; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + struct ieee80211_sta *pubsta = NULL; + struct ath12k_dp_link_peer *peer; struct ieee80211_hdr *hdr; + bool is_4addr_null_pkt; + struct ath12k_dp *dp; u16 fc; struct ieee80211_supported_band *sband; s32 noise_floor; @@ -7299,6 +7310,38 @@ static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb) hdr = (struct ieee80211_hdr *)skb->data; fc = le16_to_cpu(hdr->frame_control); + is_4addr_null_pkt = (ieee80211_is_nullfunc(hdr->frame_control) || + ieee80211_is_qos_nullfunc(hdr->frame_control)) && + ieee80211_has_a4(hdr->frame_control); + + /* + * Add check to drop frames other than 4-address NULL frame. Since + * firmware sends all NULL frames in this path (3-address and 4-address) + */ + if (ieee80211_is_data(hdr->frame_control) && !is_4addr_null_pkt) { + dev_kfree_skb(skb); + goto exit; + } + + if (is_4addr_null_pkt) { + dp = ath12k_ab_to_dp(ar->ab); + spin_lock_bh(&dp->dp_lock); + peer = ath12k_dp_link_peer_find_by_pdev_and_addr(dp, ar->pdev_idx, + hdr->addr2); + if (!peer) { + spin_unlock_bh(&dp->dp_lock); + dev_kfree_skb(skb); + goto exit; + } + pubsta = peer->sta; + if (pubsta && pubsta->valid_links) { + status->link_valid = 1; + status->link_id = peer->link_id; + } + spin_unlock_bh(&dp->dp_lock); + goto send_rx; + } + /* Firmware is guaranteed to report all essential management frames via * WMI while it can deliver some extra via HTT. Since there can be * duplicates split the reporting wrt monitor/sniffing. @@ -7322,6 +7365,7 @@ static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb) if (ieee80211_is_beacon(hdr->frame_control)) ath12k_mac_handle_beacon(ar, skb); +send_rx: ath12k_dbg(ab, ATH12K_DBG_MGMT, "event mgmt rx skb %p len %d ftype %02x stype %02x\n", skb, skb->len, diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index 13d82f706d79..c452e3d57a29 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -2278,6 +2278,7 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT = 365, WMI_TLV_SERVICE_THERM_THROT_POUT_REDUCTION = 410, + WMI_TLV_SERVICE_WDS_NULL_FRAME_SUPPORT = 421, WMI_TLV_SERVICE_IS_TARGET_IPA = 425, WMI_TLV_SERVICE_THERM_THROT_TX_CHAIN_MASK = 426, WMI_TLV_SERVICE_THERM_THROT_5_LEVELS = 429, @@ -2511,6 +2512,7 @@ struct ath12k_wmi_resource_config_arg { u32 ema_max_vap_cnt; u32 ema_max_profile_period; bool is_reg_cc_ext_event_supported; + bool is_wds_null_frame_supported; }; struct ath12k_wmi_init_cmd_arg { @@ -2568,6 +2570,7 @@ struct wmi_init_cmd { #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) #define WMI_RSRC_CFG_FLAGS2_CALC_NEXT_DTIM_COUNT_SET BIT(9) #define WMI_RSRC_CFG_FLAGS2_FW_AST_INDICATION_DISABLE BIT(18) +#define WMI_RSRC_CFG_FLAGS2_WDS_NULL_FRAME_SUPPORT BIT(22) #define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18) struct ath12k_wmi_resource_config_params {