diff options
author | Kalle Valo <kvalo@codeaurora.org> | 2021-02-11 20:44:32 +0200 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2021-02-11 20:44:32 +0200 |
commit | 16ad7b4b4f4a9d6a6452778c913205cb1591218e (patch) | |
tree | 5d18bd0035bdd1bbb67de1b3092326655c9e6674 /drivers/net/wireless | |
parent | 30357f6a47e0ce05c872fa4afacb4eb6092e57bc (diff) | |
parent | d5395a54865963089792f241756a7562d18262a1 (diff) |
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for v5.12. Major changes:
wil6210
* add support for extended DMG MCS 12.1 rate
Diffstat (limited to 'drivers/net/wireless')
31 files changed, 577 insertions, 69 deletions
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 997c1c80aba7..0af787f49b33 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -34,6 +34,7 @@ enum ath10k_debug_mask { ATH10K_DBG_USB_BULK = 0x00080000, ATH10K_DBG_SNOC = 0x00100000, ATH10K_DBG_QMI = 0x00200000, + ATH10K_DBG_STA = 0x00400000, ATH10K_DBG_ANY = 0xffffffff, }; diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 77f4d27e9d07..d6b8bdcef416 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -569,6 +569,8 @@ void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) desc_hdr = (struct htt_data_tx_desc *) (skb->data + sizeof(*htt_hdr)); flags1 = __le16_to_cpu(desc_hdr->flags1); + skb_pull(skb, sizeof(struct htt_cmd_hdr)); + skb_pull(skb, sizeof(struct htt_data_tx_desc)); } } diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index d403c9fd4980..bb6c5ee43ac0 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4115,9 +4115,8 @@ void ath10k_offchan_tx_work(struct work_struct *work) spin_unlock_bh(&ar->data_lock); if (peer) - /* FIXME: should this use ath10k_warn()? */ - ath10k_dbg(ar, ATH10K_DBG_MAC, "peer %pM on vdev %d already present\n", - peer_addr, vdev_id); + ath10k_warn(ar, "peer %pM on vdev %d already present\n", + peer_addr, vdev_id); if (!peer) { ret = ath10k_peer_create(ar, NULL, NULL, vdev_id, @@ -6667,7 +6666,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk) enum wmi_phy_mode mode; mode = chan_to_phymode(&def); - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM peer bw %d phymode %d\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "mac update sta %pM peer bw %d phymode %d\n", sta->addr, bw, mode); err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, @@ -6686,7 +6685,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk) } if (changed & IEEE80211_RC_NSS_CHANGED) { - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM nss %d\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "mac update sta %pM nss %d\n", sta->addr, nss); err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, @@ -6697,7 +6696,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk) } if (changed & IEEE80211_RC_SMPS_CHANGED) { - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM smps %d\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "mac update sta %pM smps %d\n", sta->addr, smps); err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, @@ -6708,7 +6707,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk) } if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) { - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "mac update sta %pM supp rates\n", sta->addr); err = ath10k_station_assoc(ar, arvif->vif, sta, true); @@ -7404,7 +7403,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, enum wmi_peer_type peer_type = WMI_PEER_TYPE_DEFAULT; u32 num_tdls_stations; - ath10k_dbg(ar, ATH10K_DBG_MAC, + ath10k_dbg(ar, ATH10K_DBG_STA, "mac vdev %d peer create %pM (new sta) sta %d / %d peer %d / %d\n", arvif->vdev_id, sta->addr, ar->num_stations + 1, ar->max_num_stations, @@ -7504,7 +7503,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, /* * Existing station deletion. */ - ath10k_dbg(ar, ATH10K_DBG_MAC, + ath10k_dbg(ar, ATH10K_DBG_STA, "mac vdev %d peer delete %pM sta %pK (sta gone)\n", arvif->vdev_id, sta->addr, sta); @@ -7576,7 +7575,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, /* * New association. */ - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM associated\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "mac sta %pM associated\n", sta->addr); ret = ath10k_station_assoc(ar, vif, sta, false); @@ -7589,7 +7588,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, /* * Tdls station authorized. */ - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac tdls sta %pM authorized\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "mac tdls sta %pM authorized\n", sta->addr); ret = ath10k_station_assoc(ar, vif, sta, false); @@ -7612,7 +7611,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, /* * Disassociation. */ - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM disassociated\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "mac sta %pM disassociated\n", sta->addr); ret = ath10k_station_disassoc(ar, vif, sta); @@ -8429,7 +8428,7 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw, return; } - ath10k_dbg(ar, ATH10K_DBG_MAC, + ath10k_dbg(ar, ATH10K_DBG_STA, "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n", sta->addr, changed, sta->bandwidth, sta->rx_nss, sta->smps_mode); @@ -9219,7 +9218,9 @@ static void ath10k_sta_statistics(struct ieee80211_hw *hw, if (!ath10k_peer_stats_enabled(ar)) return; + mutex_lock(&ar->conf_mutex); ath10k_debug_fw_stats_request(ar); + mutex_unlock(&ar->conf_mutex); sinfo->rx_duration = arsta->rx_duration; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION); diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 72d64af8e229..d97b33f789e4 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -240,8 +240,10 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16 __le32_to_cpu(stat->last_tx_rate_code), __le32_to_cpu(stat->last_tx_bitrate_kbps)); + rcu_read_lock(); sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL); if (!sta) { + rcu_read_unlock(); ath10k_warn(ar, "not found station for peer stats\n"); return -EINVAL; } @@ -251,6 +253,7 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16 arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps); arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code); arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps); + rcu_read_unlock(); return 0; } @@ -573,13 +576,13 @@ static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb) case WMI_TDLS_TEARDOWN_REASON_TX: case WMI_TDLS_TEARDOWN_REASON_RSSI: case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT: + rcu_read_lock(); station = ieee80211_find_sta_by_ifaddr(ar->hw, ev->peer_macaddr.addr, NULL); if (!station) { ath10k_warn(ar, "did not find station from tdls peer event"); - kfree(tb); - return; + goto exit; } arvif = ath10k_get_arvif(ar, __le32_to_cpu(ev->vdev_id)); ieee80211_tdls_oper_request( @@ -590,6 +593,9 @@ static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb) ); break; } + +exit: + rcu_read_unlock(); kfree(tb); } diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 29f64315a3b5..d48b922215eb 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -3497,7 +3497,7 @@ void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar, struct sk_buff *skb) return; } - ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event peer sta kickout %pM\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "wmi event peer sta kickout %pM\n", arg.mac_addr); rcu_read_lock(); @@ -7506,7 +7506,7 @@ ath10k_wmi_op_gen_set_sta_ps(struct ath10k *ar, u32 vdev_id, cmd->param_id = __cpu_to_le32(param_id); cmd->param_value = __cpu_to_le32(value); - ath10k_dbg(ar, ATH10K_DBG_WMI, + ath10k_dbg(ar, ATH10K_DBG_STA, "wmi sta ps param vdev_id 0x%x param %d value %d\n", vdev_id, param_id, value); return skb; diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 9db375b193de..8d29845774df 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -200,6 +200,7 @@ struct ath11k_vif { u32 beacon_interval; u32 dtim_period; u16 ast_hash; + u16 ast_idx; u16 tcl_metadata; u8 hal_addr_search_flags; u8 search_type; diff --git a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c index 9191ffa081c2..e13684343ec3 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c +++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c @@ -3845,6 +3845,18 @@ htt_print_pdev_obss_pd_stats_tlv_v(const void *tag_buf, htt_stats_buf->num_obss_tx_ppdu_success); len += HTT_DBG_OUT(buf + len, buf_len - len, "OBSS Tx failures PPDU = %u\n", htt_stats_buf->num_obss_tx_ppdu_failure); + len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG Opportunities = %u\n", + htt_stats_buf->num_non_srg_opportunities); + len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG tried PPDU = %u\n", + htt_stats_buf->num_non_srg_ppdu_tried); + len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG success PPDU = %u\n", + htt_stats_buf->num_non_srg_ppdu_success); + len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG Opportunies = %u\n", + htt_stats_buf->num_srg_opportunities); + len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG tried PPDU = %u\n", + htt_stats_buf->num_srg_ppdu_tried); + len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG success PPDU = %u\n", + htt_stats_buf->num_srg_ppdu_success); if (len >= buf_len) buf[buf_len - 1] = 0; diff --git a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h index 74b2086eed9d..567a26d485a9 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h +++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h @@ -1656,8 +1656,19 @@ struct htt_tx_sounding_stats_tlv { }; struct htt_pdev_obss_pd_stats_tlv { - u32 num_obss_tx_ppdu_success; - u32 num_obss_tx_ppdu_failure; + u32 num_obss_tx_ppdu_success; + u32 num_obss_tx_ppdu_failure; + u32 num_sr_tx_transmissions; + u32 num_spatial_reuse_opportunities; + u32 num_non_srg_opportunities; + u32 num_non_srg_ppdu_tried; + u32 num_non_srg_ppdu_success; + u32 num_srg_opportunities; + u32 num_srg_ppdu_tried; + u32 num_srg_ppdu_success; + u32 num_psr_opportunities; + u32 num_psr_ppdu_tried; + u32 num_psr_ppdu_success; }; struct htt_ring_backpressure_stats_tlv { diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 859cfcabceb5..850ad38b888f 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -1652,6 +1652,7 @@ void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab, u8 mac_addr[ETH_ALEN]; u16 peer_mac_h16; u16 ast_hash; + u16 hw_peer_id; ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "dp_htt rx msg type :0x%0x\n", type); @@ -1672,7 +1673,7 @@ void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab, resp->peer_map_ev.info1); ath11k_dp_get_mac_addr(resp->peer_map_ev.mac_addr_l32, peer_mac_h16, mac_addr); - ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, 0); + ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, 0, 0); break; case HTT_T2H_MSG_TYPE_PEER_MAP2: vdev_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO_VDEV_ID, @@ -1685,7 +1686,10 @@ void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab, peer_mac_h16, mac_addr); ast_hash = FIELD_GET(HTT_T2H_PEER_MAP_INFO2_AST_HASH_VAL, resp->peer_map_ev.info2); - ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash); + hw_peer_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO1_HW_PEER_ID, + resp->peer_map_ev.info1); + ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash, + hw_peer_id); break; case HTT_T2H_MSG_TYPE_PEER_UNMAP: case HTT_T2H_MSG_TYPE_PEER_UNMAP2: diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c index 6a3fcea6c233..1a0b9be9ce6a 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -165,6 +165,7 @@ tcl_ring_sel: ti.pkt_offset = 0; ti.lmac_id = ar->lmac_id; ti.bss_ast_hash = arvif->ast_hash; + ti.bss_ast_idx = arvif->ast_idx; ti.dscp_tid_tbl_idx = 0; if (skb->ip_summed == CHECKSUM_PARTIAL && diff --git a/drivers/net/wireless/ath/ath11k/hal_tx.c b/drivers/net/wireless/ath/ath11k/hal_tx.c index a755aa86c5de..569e790d83a1 100644 --- a/drivers/net/wireless/ath/ath11k/hal_tx.c +++ b/drivers/net/wireless/ath/ath11k/hal_tx.c @@ -71,6 +71,8 @@ void ath11k_hal_tx_cmd_desc_setup(struct ath11k_base *ab, void *cmd, tcl_cmd->info3 = FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_DSCP_TID_TABLE_IDX, ti->dscp_tid_tbl_idx) | FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_SEARCH_INDEX, + ti->bss_ast_idx) | + FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_CACHE_SET_NUM, ti->bss_ast_hash); tcl_cmd->info4 = 0; } diff --git a/drivers/net/wireless/ath/ath11k/hal_tx.h b/drivers/net/wireless/ath/ath11k/hal_tx.h index d4760a20fdac..c291e59c3ca6 100644 --- a/drivers/net/wireless/ath/ath11k/hal_tx.h +++ b/drivers/net/wireless/ath/ath11k/hal_tx.h @@ -29,6 +29,7 @@ struct hal_tx_info { u32 flags1; /* %HAL_TCL_DATA_CMD_INFO2_ */ u16 addr_search_flags; /* %HAL_TCL_DATA_CMD_INFO0_ADDR(X/Y)_ */ u16 bss_ast_hash; + u16 bss_ast_idx; u8 tid; u8 search_type; /* %HAL_TX_ADDR_SEARCH_ */ u8 lmac_id; diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 288720c5ab01..b391169576e2 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -1871,6 +1871,158 @@ static int ath11k_mac_fils_discovery(struct ath11k_vif *arvif, return ret; } +static int ath11k_mac_config_obss_pd(struct ath11k *ar, + struct ieee80211_he_obss_pd *he_obss_pd) +{ + u32 bitmap[2], param_id, param_val, pdev_id; + int ret; + s8 non_srg_th = 0, srg_th = 0; + + pdev_id = ar->pdev->pdev_id; + + /* Set and enable SRG/non-SRG OBSS PD Threshold */ + param_id = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD; + if (test_bit(ATH11K_FLAG_MONITOR_ENABLED, &ar->monitor_flags)) { + ret = ath11k_wmi_pdev_set_param(ar, param_id, 0, pdev_id); + if (ret) + ath11k_warn(ar->ab, + "failed to set obss_pd_threshold for pdev: %u\n", + pdev_id); + return ret; + } + + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, + "mac obss pd sr_ctrl %x non_srg_thres %u srg_max %u\n", + he_obss_pd->sr_ctrl, he_obss_pd->non_srg_max_offset, + he_obss_pd->max_offset); + + param_val = 0; + + if (he_obss_pd->sr_ctrl & + IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED) { + non_srg_th = ATH11K_OBSS_PD_MAX_THRESHOLD; + } else { + if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT) + non_srg_th = (ATH11K_OBSS_PD_MAX_THRESHOLD + + he_obss_pd->non_srg_max_offset); + else + non_srg_th = ATH11K_OBSS_PD_NON_SRG_MAX_THRESHOLD; + + param_val |= ATH11K_OBSS_PD_NON_SRG_EN; + } + + if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) { + srg_th = ATH11K_OBSS_PD_MAX_THRESHOLD + he_obss_pd->max_offset; + param_val |= ATH11K_OBSS_PD_SRG_EN; + } + + if (test_bit(WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT, + ar->ab->wmi_ab.svc_map)) { + param_val |= ATH11K_OBSS_PD_THRESHOLD_IN_DBM; + param_val |= FIELD_PREP(GENMASK(15, 8), srg_th); + } else { + non_srg_th -= ATH11K_DEFAULT_NOISE_FLOOR; + /* SRG not supported and threshold in dB */ + param_val &= ~(ATH11K_OBSS_PD_SRG_EN | + ATH11K_OBSS_PD_THRESHOLD_IN_DBM); + } + + param_val |= (non_srg_th & GENMASK(7, 0)); + ret = ath11k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id); + if (ret) { + ath11k_warn(ar->ab, + "failed to set obss_pd_threshold for pdev: %u\n", + pdev_id); + return ret; + } + + /* Enable OBSS PD for all access category */ + param_id = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC; + param_val = 0xf; + ret = ath11k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id); + if (ret) { + ath11k_warn(ar->ab, + "failed to set obss_pd_per_ac for pdev: %u\n", + pdev_id); + return ret; + } + + /* Set SR Prohibit */ + param_id = WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT; + param_val = !!(he_obss_pd->sr_ctrl & + IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED); + ret = ath11k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id); + if (ret) { + ath11k_warn(ar->ab, "failed to set sr_prohibit for pdev: %u\n", + pdev_id); + return ret; + } + + if (!test_bit(WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT, + ar->ab->wmi_ab.svc_map)) + return 0; + + /* Set SRG BSS Color Bitmap */ + memcpy(bitmap, he_obss_pd->bss_color_bitmap, sizeof(bitmap)); + ret = ath11k_wmi_pdev_set_srg_bss_color_bitmap(ar, bitmap); + if (ret) { + ath11k_warn(ar->ab, + "failed to set bss_color_bitmap for pdev: %u\n", + pdev_id); + return ret; + } + + /* Set SRG Partial BSSID Bitmap */ + memcpy(bitmap, he_obss_pd->partial_bssid_bitmap, sizeof(bitmap)); + ret = ath11k_wmi_pdev_set_srg_patial_bssid_bitmap(ar, bitmap); + if (ret) { + ath11k_warn(ar->ab, + "failed to set partial_bssid_bitmap for pdev: %u\n", + pdev_id); + return ret; + } + + memset(bitmap, 0xff, sizeof(bitmap)); + + /* Enable all BSS Colors for SRG */ + ret = ath11k_wmi_pdev_srg_obss_color_enable_bitmap(ar, bitmap); + if (ret) { + ath11k_warn(ar->ab, + "failed to set srg_color_en_bitmap pdev: %u\n", + pdev_id); + return ret; + } + + /* Enable all patial BSSID mask for SRG */ + ret = ath11k_wmi_pdev_srg_obss_bssid_enable_bitmap(ar, bitmap); + if (ret) { + ath11k_warn(ar->ab, + "failed to set srg_bssid_en_bitmap pdev: %u\n", + pdev_id); + return ret; + } + + /* Enable all BSS Colors for non-SRG */ + ret = ath11k_wmi_pdev_non_srg_obss_color_enable_bitmap(ar, bitmap); + if (ret) { + ath11k_warn(ar->ab, + "failed to set non_srg_color_en_bitmap pdev: %u\n", + pdev_id); + return ret; + } + + /* Enable all patial BSSID mask for non-SRG */ + ret = ath11k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(ar, bitmap); + if (ret) { + ath11k_warn(ar->ab, + "failed to set non_srg_bssid_en_bitmap pdev: %u\n", + pdev_id); + return ret; + } + + return 0; +} + static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, @@ -2114,8 +2266,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_HE_OBSS_PD) - ath11k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id, - &info->he_obss_pd); + ath11k_mac_config_obss_pd(ar, &info->he_obss_pd); if (changed & BSS_CHANGED_HE_BSS_COLOR) { if (vif->type == NL80211_IFTYPE_AP) { @@ -4248,11 +4399,6 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw) /* Configure the hash seed for hash based reo dest ring selection */ ath11k_wmi_pdev_lro_cfg(ar, ar->pdev->pdev_id); - mutex_unlock(&ar->conf_mutex); - - rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], - &ab->pdevs[ar->pdev_idx]); - /* allow device to enter IMPS */ if (ab->hw_params.idle_ps) { ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_IDLE_PS_CONFIG, @@ -4262,6 +4408,12 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw) goto err; } } + + mutex_unlock(&ar->conf_mutex); + + rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], + &ab->pdevs[ar->pdev_idx]); + return 0; err: diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h index 597104a9078d..455577905505 100644 --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h @@ -116,6 +116,12 @@ struct ath11k_generic_iter { #define ATH11K_CHAN_WIDTH_NUM 8 +#define ATH11K_OBSS_PD_MAX_THRESHOLD -82 +#define ATH11K_OBSS_PD_NON_SRG_MAX_THRESHOLD -62 +#define ATH11K_OBSS_PD_THRESHOLD_IN_DBM BIT(29) +#define ATH11K_OBSS_PD_SRG_EN BIT(30) +#define ATH11K_OBSS_PD_NON_SRG_EN BIT(31) + extern const struct htt_rx_ring_tlv_filter ath11k_mac_mon_status_filter_default; void ath11k_mac_destroy(struct ath11k_base *ab); diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c index 78478b2b3ba5..d14416816acc 100644 --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -1086,8 +1086,6 @@ static int ath11k_pci_probe(struct pci_dev *pdev, u32 soc_hw_version, soc_hw_version_major, soc_hw_version_minor; int ret; - dev_warn(&pdev->dev, "WARNING: ath11k PCI support is experimental!\n"); - ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI, &ath11k_pci_bus_params); if (!ab) { diff --git a/drivers/net/wireless/ath/ath11k/peer.c b/drivers/net/wireless/ath/ath11k/peer.c index b69e7ebfa930..f49abefa9618 100644 --- a/drivers/net/wireless/ath/ath11k/peer.c +++ b/drivers/net/wireless/ath/ath11k/peer.c @@ -118,7 +118,7 @@ exit: } void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id, - u8 *mac_addr, u16 ast_hash) + u8 *mac_addr, u16 ast_hash, u16 hw_peer_id) { struct ath11k_peer *peer; @@ -132,6 +132,7 @@ void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id, peer->vdev_id = vdev_id; peer->peer_id = peer_id; peer->ast_hash = ast_hash; + peer->hw_peer_id = hw_peer_id; ether_addr_copy(peer->addr, mac_addr); list_add(&peer->list, &ab->peers); wake_up(&ab->peer_mapping_wq); @@ -309,7 +310,11 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, peer->pdev_idx = ar->pdev_idx; peer->sta = sta; - arvif->ast_hash = peer->ast_hash; + + if (arvif->vif->type == NL80211_IFTYPE_STATION) { + arvif->ast_hash = peer->ast_hash; + arvif->ast_idx = peer->hw_peer_id; + } peer->sec_type = HAL_ENCRYPT_TYPE_OPEN; peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN; diff --git a/drivers/net/wireless/ath/ath11k/peer.h b/drivers/net/wireless/ath/ath11k/peer.h index 8553ed061aea..619db001be8e 100644 --- a/drivers/net/wireless/ath/ath11k/peer.h +++ b/drivers/net/wireless/ath/ath11k/peer.h @@ -14,6 +14,7 @@ struct ath11k_peer { int peer_id; u16 ast_hash; u8 pdev_idx; + u16 hw_peer_id; /* protected by ab->data_lock */ struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; @@ -31,7 +32,7 @@ struct ath11k_peer { void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id); void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id, - u8 *mac_addr, u16 ast_hash); + u8 *mac_addr, u16 ast_hash, u16 hw_peer_id); struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id, const u8 *addr); struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab, diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index 0db623ff4bb9..1aca841cd147 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -1686,6 +1686,11 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab) req->mem_seg[i].addr = ab->qmi.target_mem[i].paddr; req->mem_seg[i].size = ab->qmi.target_mem[i].size; req->mem_seg[i].type = ab->qmi.target_mem[i].type; + ath11k_dbg(ab, ATH11K_DBG_QMI, + "qmi req mem_seg[%d] 0x%llx %u %u\n", i, + ab->qmi.target_mem[i].paddr, + ab->qmi.target_mem[i].size, + ab->qmi.target_mem[i].type); } } diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index 2e6ce28ecc8d..cccfd3bd4d27 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -2971,6 +2971,233 @@ ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id, } int +ath11k_wmi_pdev_set_srg_bss_color_bitmap(struct ath11k *ar, u32 *bitmap) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_ab->ab; + struct wmi_pdev_obss_pd_bitmap_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + cmd->pdev_id = ar->pdev->pdev_id; + memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "obss pd pdev_id %d bss color bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID); + if (ret) { + ath11k_warn(ab, + "failed to send WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID"); + dev_kfree_skb(skb); + } + + return ret; +} + +int +ath11k_wmi_pdev_set_srg_patial_bssid_bitmap(struct ath11k *ar, u32 *bitmap) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_ab->ab; + struct wmi_pdev_obss_pd_bitmap_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data; + cmd->tlv_header = + FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + cmd->pdev_id = ar->pdev->pdev_id; + memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "obss pd pdev_id %d partial bssid bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID); + if (ret) { + ath11k_warn(ab, + "failed to send WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID"); + dev_kfree_skb(skb); + } + + return ret; +} + +int +ath11k_wmi_pdev_srg_obss_color_enable_bitmap(struct ath11k *ar, u32 *bitmap) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_ab->ab; + struct wmi_pdev_obss_pd_bitmap_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data; + cmd->tlv_header = + FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_PDEV_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + cmd->pdev_id = ar->pdev->pdev_id; + memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "obss pd srg pdev_id %d bss color enable bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID); + if (ret) { + ath11k_warn(ab, + "failed to send WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID"); + dev_kfree_skb(skb); + } + + return ret; +} + +int +ath11k_wmi_pdev_srg_obss_bssid_enable_bitmap(struct ath11k *ar, u32 *bitmap) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_ab->ab; + struct wmi_pdev_obss_pd_bitmap_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data; + cmd->tlv_header = + FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + cmd->pdev_id = ar->pdev->pdev_id; + memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "obss pd srg pdev_id %d bssid enable bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID); + if (ret) { + ath11k_warn(ab, + "failed to send WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID"); + dev_kfree_skb(skb); + } + + return ret; +} + +int +ath11k_wmi_pdev_non_srg_obss_color_enable_bitmap(struct ath11k *ar, u32 *bitmap) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_ab->ab; + struct wmi_pdev_obss_pd_bitmap_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data; + cmd->tlv_header = + FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + cmd->pdev_id = ar->pdev->pdev_id; + memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "obss pd non_srg pdev_id %d bss color enable bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID); + if (ret) { + ath11k_warn(ab, + "failed to send WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID"); + dev_kfree_skb(skb); + } + + return ret; +} + +int +ath11k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(struct ath11k *ar, u32 *bitmap) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_ab->ab; + struct wmi_pdev_obss_pd_bitmap_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data; + cmd->tlv_header = + FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + cmd->pdev_id = ar->pdev->pdev_id; + memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "obss pd non_srg pdev_id %d bssid enable bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID); + if (ret) { + ath11k_warn(ab, + "failed to send WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID"); + dev_kfree_skb(skb); + } + + return ret; +} + +int ath11k_wmi_send_obss_color_collision_cfg_cmd(struct ath11k *ar, u32 vdev_id, u8 bss_color, u32 period, bool enable) diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index 993674228c9e..3ade1ddd35c9 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -257,6 +257,16 @@ enum wmi_tlv_cmd_id { WMI_PDEV_DMA_RING_CFG_REQ_CMDID, WMI_PDEV_HE_TB_ACTION_FRM_CMDID, WMI_PDEV_PKTLOG_FILTER_CMDID, + WMI_PDEV_SET_RAP_CONFIG_CMDID, + WMI_PDEV_DSM_FILTER_CMDID, + WMI_PDEV_FRAME_INJECT_CMDID, + WMI_PDEV_TBTT_OFFSET_SYNC_CMDID, + WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID, + WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID, + WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID, + WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID, + WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID, + WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID, WMI_VDEV_CREATE_CMDID = WMI_TLV_CMD(WMI_GRP_VDEV), WMI_VDEV_DELETE_CMDID, WMI_VDEV_START_REQUEST_CMDID, @@ -919,6 +929,9 @@ enum wmi_tlv_pdev_param { WMI_PDEV_PARAM_RADIO_CHAN_STATS_ENABLE, WMI_PDEV_PARAM_RADIO_DIAGNOSIS_ENABLE, WMI_PDEV_PARAM_MESH_MCAST_ENABLE, + WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD = 0xbc, + WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC = 0xbe, + WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT = 0xc6, }; enum wmi_tlv_vdev_param { @@ -1812,10 +1825,15 @@ enum wmi_tlv_tag { WMI_TAG_NDP_CHANNEL_INFO, WMI_TAG_NDP_CMD, WMI_TAG_NDP_EVENT, - /* TODO add all the missing cmds */ WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD = 0x301, WMI_TAG_PDEV_PEER_PKTLOG_FILTER_INFO, WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344, + WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD = 0x37b, + WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD, + WMI_TAG_PDEV_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD = 0x381, + WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, + WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD, + WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, WMI_TAG_MAX }; @@ -2039,6 +2057,7 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET = 213, WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219, WMI_TLV_SERVICE_EXT2_MSG = 220, + WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249, WMI_MAX_EXT_SERVICE }; @@ -4781,6 +4800,12 @@ struct wmi_obss_spatial_reuse_params_cmd { u32 vdev_id; } __packed; +struct wmi_pdev_obss_pd_bitmap_cmd { + u32 tlv_header; + u32 pdev_id; + u32 bitmap[2]; +} __packed; + #define ATH11K_BSS_COLOR_COLLISION_SCAN_PERIOD_MS 200 #define ATH11K_OBSS_COLOR_COLLISION_DETECTION_DISABLE 0 #define ATH11K_OBSS_COLOR_COLLISION_DETECTION 1 @@ -5316,6 +5341,16 @@ int ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id); int ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id); int ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id, struct ieee80211_he_obss_pd *he_obss_pd); +int ath11k_wmi_pdev_set_srg_bss_color_bitmap(struct ath11k *ar, u32 *bitmap); +int ath11k_wmi_pdev_set_srg_patial_bssid_bitmap(struct ath11k *ar, u32 *bitmap); +int ath11k_wmi_pdev_srg_obss_color_enable_bitmap(struct ath11k *ar, + u32 *bitmap); +int ath11k_wmi_pdev_srg_obss_bssid_enable_bitmap(struct ath11k *ar, + u32 *bitmap); +int ath11k_wmi_pdev_non_srg_obss_color_enable_bitmap(struct ath11k *ar, + u32 *bitmap); +int ath11k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(struct ath11k *ar, + u32 *bitmap); int ath11k_wmi_send_obss_color_collision_cfg_cmd(struct ath11k *ar, u32 vdev_id, u8 bss_color, u32 period, bool enable); diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 017a43bc400c..4c81b1d7f417 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1223,8 +1223,11 @@ static ssize_t write_file_nf_override(struct file *file, ah->nf_override = val; - if (ah->curchan) + if (ah->curchan) { + ath9k_ps_wakeup(sc); ath9k_hw_loadnf(ah, ah->curchan); + ath9k_ps_restore(sc); + } return count; } diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h index 56999a3b9d3b..4a500095555c 100644 --- a/drivers/net/wireless/ath/carl9170/fwcmd.h +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h @@ -240,7 +240,7 @@ struct carl9170_cmd { struct carl9170_bcn_ctrl_cmd bcn_ctrl; struct carl9170_rx_filter_cmd rx_filter; u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; - } __packed; + } __packed __aligned(4); } __packed __aligned(4); #define CARL9170_TX_STATUS_QUEUE 3 diff --git a/drivers/net/wireless/ath/carl9170/wlan.h b/drivers/net/wireless/ath/carl9170/wlan.h index ea17995b32f4..bb73553fd7c2 100644 --- a/drivers/net/wireless/ath/carl9170/wlan.h +++ b/drivers/net/wireless/ath/carl9170/wlan.h @@ -367,27 +367,27 @@ struct ar9170_rx_macstatus { struct ar9170_rx_frame_single { struct ar9170_rx_head phy_head; - struct ieee80211_hdr i3e; + struct ieee80211_hdr i3e __packed __aligned(2); struct ar9170_rx_phystatus phy_tail; struct ar9170_rx_macstatus macstatus; -} __packed; +}; struct ar9170_rx_frame_head { struct ar9170_rx_head phy_head; - struct ieee80211_hdr i3e; + struct ieee80211_hdr i3e __packed __aligned(2); struct ar9170_rx_macstatus macstatus; -} __packed; +}; struct ar9170_rx_frame_middle { - struct ieee80211_hdr i3e; + struct ieee80211_hdr i3e __packed __aligned(2); struct ar9170_rx_macstatus macstatus; -} __packed; +}; struct ar9170_rx_frame_tail { - struct ieee80211_hdr i3e; + struct ieee80211_hdr i3e __packed __aligned(2); struct ar9170_rx_phystatus phy_tail; struct ar9170_rx_macstatus macstatus; -} __packed; +}; struct ar9170_rx_frame { union { @@ -395,8 +395,8 @@ struct ar9170_rx_frame { struct ar9170_rx_frame_head head; struct ar9170_rx_frame_middle middle; struct ar9170_rx_frame_tail tail; - } __packed; -} __packed; + }; +}; static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t) { diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 5867bd9c2f64..afb4877eaad8 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -1140,7 +1140,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, session); break; case IEEE80211_AMPDU_RX_STOP: - wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv)); + wcn36xx_smd_del_ba(wcn, tid, 0, get_sta_index(vif, sta_priv)); break; case IEEE80211_AMPDU_TX_START: spin_lock_bh(&sta_priv->ampdu_lock); @@ -1164,6 +1164,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_NONE; spin_unlock_bh(&sta_priv->ampdu_lock); + wcn36xx_smd_del_ba(wcn, tid, 1, get_sta_index(vif, sta_priv)); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; default: diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 28d3ee3ad4b9..d0c3a1557e8d 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -2466,7 +2466,7 @@ out: return ret; } -int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index) +int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 direction, u8 sta_index) { struct wcn36xx_hal_del_ba_req_msg msg_body; int ret; @@ -2476,7 +2476,7 @@ int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index) msg_body.sta_index = sta_index; msg_body.tid = tid; - msg_body.direction = 0; + msg_body.direction = direction; PREPARE_HAL_BUF(wcn->hal_buf, msg_body); ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h index b1d8083d9d9d..462860572e1f 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.h +++ b/drivers/net/wireless/ath/wcn36xx/smd.h @@ -135,7 +135,7 @@ int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, u8 direction, u8 sta_index); int wcn36xx_smd_add_ba(struct wcn36xx *wcn, u8 session_id); -int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index); +int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 direction, u8 sta_index); int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u8 session_id); int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value); diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 60bba5b491e0..6746fd206d2a 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -441,7 +441,9 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, } __packed reply; struct wil_net_stats *stats = &wil->sta[cid].stats; int rc; - u8 txflag = RATE_INFO_FLAGS_DMG; + u8 tx_mcs, rx_mcs; + u8 tx_rate_flag = RATE_INFO_FLAGS_DMG; + u8 rx_rate_flag = RATE_INFO_FLAGS_DMG; memset(&reply, 0, sizeof(reply)); @@ -451,13 +453,15 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, if (rc) return rc; + tx_mcs = le16_to_cpu(reply.evt.bf_mcs); + wil_dbg_wmi(wil, "Link status for CID %d MID %d: {\n" - " MCS %d TSF 0x%016llx\n" + " MCS %s TSF 0x%016llx\n" " BF status 0x%08x RSSI %d SQI %d%%\n" " Tx Tpt %d goodput %d Rx goodput %d\n" " Sectors(rx:tx) my %d:%d peer %d:%d\n" " Tx mode %d}\n", - cid, vif->mid, le16_to_cpu(reply.evt.bf_mcs), + cid, vif->mid, WIL_EXTENDED_MCS_CHECK(tx_mcs), le64_to_cpu(reply.evt.tsf), reply.evt.status, reply.evt.rssi, reply.evt.sqi, @@ -481,12 +485,30 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC) | BIT_ULL(NL80211_STA_INFO_TX_FAILED); - if (wil->use_enhanced_dma_hw && reply.evt.tx_mode != WMI_TX_MODE_DMG) - txflag = RATE_INFO_FLAGS_EDMG; + if (wil->use_enhanced_dma_hw && reply.evt.tx_mode != WMI_TX_MODE_DMG) { + tx_rate_flag = RATE_INFO_FLAGS_EDMG; + rx_rate_flag = RATE_INFO_FLAGS_EDMG; + } + + rx_mcs = stats->last_mcs_rx; + + /* check extended MCS (12.1) and convert it into + * base MCS (7) + EXTENDED_SC_DMG flag + */ + if (tx_mcs == WIL_EXTENDED_MCS_26) { + tx_rate_flag = RATE_INFO_FLAGS_EXTENDED_SC_DMG; + tx_mcs = WIL_BASE_MCS_FOR_EXTENDED_26; + } + if (rx_mcs == WIL_EXTENDED_MCS_26) { + rx_rate_flag = RATE_INFO_FLAGS_EXTENDED_SC_DMG; + rx_mcs = WIL_BASE_MCS_FOR_EXTENDED_26; + } + + sinfo->txrate.flags = tx_rate_flag; + sinfo->rxrate.flags = rx_rate_flag; + sinfo->txrate.mcs = tx_mcs; + sinfo->rxrate.mcs = rx_mcs; - sinfo->txrate.flags = txflag; - sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs); - sinfo->rxrate.mcs = stats->last_mcs_rx; sinfo->txrate.n_bonded_ch = wil_tx_cb_mode_to_n_bonded(reply.evt.tx_mode); sinfo->rxrate.n_bonded_ch = diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 2d618f90afa7..4c944e595978 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1294,6 +1294,7 @@ static int bf_show(struct seq_file *s, void *data) for (i = 0; i < wil->max_assoc_sta; i++) { u32 status; + u8 bf_mcs; cmd.cid = i; rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid, @@ -1305,9 +1306,10 @@ static int bf_show(struct seq_file *s, void *data) continue; status = le32_to_cpu(reply.evt.status); + bf_mcs = le16_to_cpu(reply.evt.bf_mcs); seq_printf(s, "CID %d {\n" " TSF = 0x%016llx\n" - " TxMCS = %2d TxTpt = %4d\n" + " TxMCS = %s TxTpt = %4d\n" " SQI = %4d\n" " RSSI = %4d\n" " Status = 0x%08x %s\n" @@ -1316,7 +1318,7 @@ static int bf_show(struct seq_file *s, void *data) "}\n", i, le64_to_cpu(reply.evt.tsf), - le16_to_cpu(reply.evt.bf_mcs), + WIL_EXTENDED_MCS_CHECK(bf_mcs), le32_to_cpu(reply.evt.tx_tpt), reply.evt.sqi, reply.evt.rssi, @@ -1443,8 +1445,10 @@ static int link_show(struct seq_file *s, void *data) if (rc) goto out; - seq_printf(s, " Tx_mcs = %d\n", sinfo->txrate.mcs); - seq_printf(s, " Rx_mcs = %d\n", sinfo->rxrate.mcs); + seq_printf(s, " Tx_mcs = %s\n", + WIL_EXTENDED_MCS_CHECK(sinfo->txrate.mcs)); + seq_printf(s, " Rx_mcs = %s\n", + WIL_EXTENDED_MCS_CHECK(sinfo->rxrate.mcs)); seq_printf(s, " SQ = %d\n", sinfo->signal); } else { seq_puts(s, " INVALID MID\n"); @@ -1848,7 +1852,7 @@ static void wil_link_stats_print_basic(struct wil6210_vif *vif, snprintf(per, sizeof(per), "%d%%", basic->per_average); seq_printf(s, "CID %d {\n" - "\tTxMCS %d TxTpt %d\n" + "\tTxMCS %s TxTpt %d\n" "\tGoodput(rx:tx) %d:%d\n" "\tRxBcastFrames %d\n" "\tRSSI %d SQI %d SNR %d PER %s\n" @@ -1856,7 +1860,8 @@ static void wil_link_stats_print_basic(struct wil6210_vif *vif, "\tSectors(rx:tx) my %d:%d peer %d:%d\n" "}\n", basic->cid, - basic->bf_mcs, le32_to_cpu(basic->tx_tpt), + WIL_EXTENDED_MCS_CHECK(basic->bf_mcs), + le32_to_cpu(basic->tx_tpt), le32_to_cpu(basic->rx_goodput), le32_to_cpu(basic->tx_goodput), le32_to_cpu(basic->rx_bcast_frames), diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c index 8ca2ce51c83e..201c8c35e0c9 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.c +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c @@ -1026,6 +1026,8 @@ skipping: stats->last_mcs_rx = wil_rx_status_get_mcs(msg); if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs)) stats->rx_per_mcs[stats->last_mcs_rx]++; + else if (stats->last_mcs_rx == WIL_EXTENDED_MCS_26) + stats->rx_per_mcs[WIL_BASE_MCS_FOR_EXTENDED_26]++; stats->last_cb_mode_rx = wil_rx_status_get_cb_mode(msg); } diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 5dc881d3c057..30392eb1cbbd 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -89,6 +89,9 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) #define WIL_MAX_AGG_WSIZE_64 (64) /* FW/HW limit */ #define WIL6210_MAX_STATUS_RINGS (8) #define WIL_WMI_CALL_GENERAL_TO_MS 100 +#define WIL_EXTENDED_MCS_26 (26) /* FW reports MCS 12.1 to driver as "26" */ +#define WIL_BASE_MCS_FOR_EXTENDED_26 (7) /* MCS 7 is base MCS for MCS 12.1 */ +#define WIL_EXTENDED_MCS_CHECK(x) (((x) == WIL_EXTENDED_MCS_26) ? "12.1" : #x) /* Hardware offload block adds the following: * 26 bytes - 3-address QoS data header diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 8699f8279a8b..823ec6e78a22 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -851,9 +851,9 @@ static void wmi_evt_rx_mgmt(struct wil6210_vif *vif, int id, void *d, int len) d_status = le16_to_cpu(data->info.status); fc = rx_mgmt_frame->frame_control; - wil_dbg_wmi(wil, "MGMT Rx: channel %d MCS %d RSSI %d SQI %d%%\n", - data->info.channel, data->info.mcs, data->info.rssi, - data->info.sqi); + wil_dbg_wmi(wil, "MGMT Rx: channel %d MCS %s RSSI %d SQI %d%%\n", + data->info.channel, WIL_EXTENDED_MCS_CHECK(data->info.mcs), + data->info.rssi, data->info.sqi); wil_dbg_wmi(wil, "status 0x%04x len %d fc 0x%04x\n", d_status, d_len, le16_to_cpu(fc)); wil_dbg_wmi(wil, "qid %d mid %d cid %d\n", @@ -1422,8 +1422,9 @@ wmi_evt_sched_scan_result(struct wil6210_vif *vif, int id, void *d, int len) else signal = data->info.sqi; - wil_dbg_wmi(wil, "sched scan result: channel %d MCS %d RSSI %d\n", - data->info.channel, data->info.mcs, data->info.rssi); + wil_dbg_wmi(wil, "sched scan result: channel %d MCS %s RSSI %d\n", + data->info.channel, WIL_EXTENDED_MCS_CHECK(data->info.mcs), + data->info.rssi); wil_dbg_wmi(wil, "len %d qid %d mid %d cid %d\n", d_len, data->info.qid, data->info.mid, data->info.cid); wil_hex_dump_wmi("PROBE ", DUMP_PREFIX_OFFSET, 16, 1, rx_mgmt_frame, |