diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath12k/mac.c')
-rw-r--r-- | drivers/net/wireless/ath/ath12k/mac.c | 117 |
1 files changed, 85 insertions, 32 deletions
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 3a3965b79942..1d7b60aa5cb0 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include <net/mac80211.h> @@ -1822,22 +1822,16 @@ void ath12k_mac_handle_beacon(struct ath12k *ar, struct sk_buff *skb) skb); } -static void ath12k_mac_handle_beacon_miss_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) +void ath12k_mac_handle_beacon_miss(struct ath12k *ar, + struct ath12k_link_vif *arvif) { - u32 *vdev_id = data; - struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); - struct ath12k_link_vif *arvif = &ahvif->deflink; - struct ieee80211_hw *hw; - - if (!arvif->is_created || arvif->vdev_id != *vdev_id) - return; + struct ieee80211_hw *hw = ath12k_ar_to_hw(ar); + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); - if (!arvif->is_up) + if (!(arvif->is_created && arvif->is_up)) return; ieee80211_beacon_loss(vif); - hw = ath12k_ar_to_hw(arvif->ar); /* Firmware doesn't report beacon loss events repeatedly. If AP probe * (done by mac80211) succeeds but beacons do not resume then it @@ -1848,14 +1842,6 @@ static void ath12k_mac_handle_beacon_miss_iter(void *data, u8 *mac, ATH12K_CONNECTION_LOSS_HZ); } -void ath12k_mac_handle_beacon_miss(struct ath12k *ar, u32 vdev_id) -{ - ieee80211_iterate_active_interfaces_atomic(ath12k_ar_to_hw(ar), - IEEE80211_IFACE_ITER_NORMAL, - ath12k_mac_handle_beacon_miss_iter, - &vdev_id); -} - static void ath12k_mac_vif_sta_connection_loss_work(struct work_struct *work) { struct ath12k_link_vif *arvif = container_of(work, struct ath12k_link_vif, @@ -9860,6 +9846,7 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif) param_id = WMI_VDEV_PARAM_RTS_THRESHOLD; param_value = hw->wiphy->rts_threshold; + ar->rts_threshold = param_value; ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param_id, param_value); if (ret) { @@ -11240,8 +11227,8 @@ void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, struct ieee80211_channel *chan, *temp_chan; u8 pwr_lvl_idx, num_pwr_levels, pwr_reduction; bool is_psd_power = false, is_tpe_present = false; - s8 max_tx_power[ATH12K_NUM_PWR_LEVELS], - psd_power, tx_power, eirp_power; + s8 max_tx_power[ATH12K_NUM_PWR_LEVELS], psd_power, tx_power; + s8 eirp_power = 0; struct ath12k_vif *ahvif = arvif->ahvif; u16 start_freq, center_freq; u8 reg_6ghz_power_mode; @@ -11447,8 +11434,10 @@ static void ath12k_mac_parse_tx_pwr_env(struct ath12k *ar, tpc_info->num_pwr_levels = max(local_psd->count, reg_psd->count); - if (tpc_info->num_pwr_levels > ATH12K_NUM_PWR_LEVELS) - tpc_info->num_pwr_levels = ATH12K_NUM_PWR_LEVELS; + tpc_info->num_pwr_levels = + min3(tpc_info->num_pwr_levels, + IEEE80211_TPE_PSD_ENTRIES_320MHZ, + ATH12K_NUM_PWR_LEVELS); for (i = 0; i < tpc_info->num_pwr_levels; i++) { tpc_info->tpe[i] = min(local_psd->power[i], @@ -11463,8 +11452,10 @@ static void ath12k_mac_parse_tx_pwr_env(struct ath12k *ar, tpc_info->num_pwr_levels = max(local_non_psd->count, reg_non_psd->count); - if (tpc_info->num_pwr_levels > ATH12K_NUM_PWR_LEVELS) - tpc_info->num_pwr_levels = ATH12K_NUM_PWR_LEVELS; + tpc_info->num_pwr_levels = + min3(tpc_info->num_pwr_levels, + IEEE80211_TPE_EIRP_ENTRIES_320MHZ, + ATH12K_NUM_PWR_LEVELS); for (i = 0; i < tpc_info->num_pwr_levels; i++) { tpc_info->tpe[i] = min(local_non_psd->power[i], @@ -11687,16 +11678,32 @@ static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx, u32 value) { struct ath12k_hw *ah = ath12k_hw_to_ah(hw); + struct wiphy *wiphy = hw->wiphy; struct ath12k *ar; - int param_id = WMI_VDEV_PARAM_RTS_THRESHOLD, ret = 0, i; + int param_id = WMI_VDEV_PARAM_RTS_THRESHOLD; + int ret = 0, ret_err, i; lockdep_assert_wiphy(hw->wiphy); - /* Currently we set the rts threshold value to all the vifs across - * all radios of the single wiphy. - * TODO Once support for vif specific RTS threshold in mac80211 is - * available, ath12k can make use of it. - */ + if (radio_idx >= wiphy->n_radio || radio_idx < -1) + return -EINVAL; + + if (radio_idx != -1) { + /* Update RTS threshold in specified radio */ + ar = ath12k_ah_to_ar(ah, radio_idx); + ret = ath12k_set_vdev_param_to_all_vifs(ar, param_id, value); + if (ret) { + ath12k_warn(ar->ab, + "failed to set RTS config for all vdevs of pdev %d", + ar->pdev->pdev_id); + return ret; + } + + ar->rts_threshold = value; + return 0; + } + + /* Radio_index passed is -1, so set RTS threshold for all radios. */ for_each_ar(ah, ar, i) { ret = ath12k_set_vdev_param_to_all_vifs(ar, param_id, value); if (ret) { @@ -11705,6 +11712,25 @@ static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, break; } } + if (!ret) { + /* Setting new RTS threshold for vdevs of all radios passed, so update + * the RTS threshold value for all radios + */ + for_each_ar(ah, ar, i) + ar->rts_threshold = value; + return 0; + } + + /* RTS threshold config failed, revert to the previous RTS threshold */ + for (i = i - 1; i >= 0; i--) { + ar = ath12k_ah_to_ar(ah, i); + ret_err = ath12k_set_vdev_param_to_all_vifs(ar, param_id, + ar->rts_threshold); + if (ret_err) + ath12k_warn(ar->ab, + "failed to restore RTS threshold for all vdevs of pdev %d", + ar->pdev->pdev_id); + } return ret; } @@ -12610,6 +12636,27 @@ static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx, return 0; } +static void ath12k_mac_put_chain_rssi(struct station_info *sinfo, + struct ath12k_link_sta *arsta) +{ + s8 rssi; + int i; + + for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) { + sinfo->chains &= ~BIT(i); + rssi = arsta->chain_signal[i]; + + if (rssi != ATH12K_DEFAULT_NOISE_FLOOR && + rssi != ATH12K_INVALID_RSSI_FULL && + rssi != ATH12K_INVALID_RSSI_EMPTY && + rssi != 0) { + sinfo->chain_signal[i] = rssi; + sinfo->chains |= BIT(i); + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL); + } + } +} + static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -12667,6 +12714,12 @@ static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw, !(ath12k_mac_get_fw_stats(ar, ¶ms))) signal = arsta->rssi_beacon; + params.stats_id = WMI_REQUEST_RSSI_PER_CHAIN_STAT; + if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) && + ahsta->ahvif->vdev_type == WMI_VDEV_TYPE_STA && + !(ath12k_mac_get_fw_stats(ar, ¶ms))) + ath12k_mac_put_chain_rssi(sinfo, arsta); + spin_lock_bh(&ar->data_lock); noise_floor = ath12k_pdev_get_noise_floor(ar); spin_unlock_bh(&ar->data_lock); |