Commit db6d9e9e authored by Ben Greear's avatar Ben Greear Committed by Johannes Berg

mac80211: Fix setting txpower to zero

With multiple VIFS ath10k, and probably others, tries to find the
minimum txpower for all vifs and uses that when setting txpower in
the firmware.

If a second vif is added and starts to scan, it's txpower is not
initialized yet and it set to zero.

ath10k had a patch to ignore zero values, but then it is impossible
to actually set txpower to zero.

So, instead initialize the txpower to INT_MIN in mac80211, and let
drivers know that means the power has not been set and so should
be ignored.

This should fix regression in:

commit 88407beb
Author: Ryan Hsu <ryanhsu@qca.qualcomm.com>
Date:   Tue Dec 13 14:55:19 2016 -0800

    ath10k: fix incorrect txpower set by P2P_DEVICE interface

Tested on ath10k 9984 with ath10k-ct firmware.
Signed-off-by: default avatarBen Greear <greearb@candelatech.com>
Link: https://lore.kernel.org/r/20191217183057.24586-1-greearb@candelatech.comSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 9b125c27
...@@ -5103,7 +5103,8 @@ static int ath10k_mac_txpower_recalc(struct ath10k *ar) ...@@ -5103,7 +5103,8 @@ static int ath10k_mac_txpower_recalc(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
list_for_each_entry(arvif, &ar->arvifs, list) { list_for_each_entry(arvif, &ar->arvifs, list) {
if (arvif->txpower <= 0) /* txpower not initialized yet? */
if (arvif->txpower == INT_MIN)
continue; continue;
if (txpower == -1) if (txpower == -1)
......
...@@ -1196,6 +1196,9 @@ static void ath9k_tpc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) ...@@ -1196,6 +1196,9 @@ static void ath9k_tpc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{ {
int *power = data; int *power = data;
if (vif->bss_conf.txpower == INT_MIN)
return;
if (*power < vif->bss_conf.txpower) if (*power < vif->bss_conf.txpower)
*power = vif->bss_conf.txpower; *power = vif->bss_conf.txpower;
} }
......
...@@ -2095,10 +2095,13 @@ static void setup_frame_info(struct ieee80211_hw *hw, ...@@ -2095,10 +2095,13 @@ static void setup_frame_info(struct ieee80211_hw *hw,
if (tx_info->control.vif) { if (tx_info->control.vif) {
struct ieee80211_vif *vif = tx_info->control.vif; struct ieee80211_vif *vif = tx_info->control.vif;
if (vif->bss_conf.txpower == INT_MIN)
goto nonvifpower;
txpower = 2 * vif->bss_conf.txpower; txpower = 2 * vif->bss_conf.txpower;
} else { } else {
struct ath_softc *sc = hw->priv; struct ath_softc *sc;
nonvifpower:
sc = hw->priv;
txpower = sc->cur_chan->cur_txpower; txpower = sc->cur_chan->cur_txpower;
} }
......
...@@ -574,7 +574,7 @@ struct ieee80211_ftm_responder_params { ...@@ -574,7 +574,7 @@ struct ieee80211_ftm_responder_params {
* @ssid: The SSID of the current vif. Valid in AP and IBSS mode. * @ssid: The SSID of the current vif. Valid in AP and IBSS mode.
* @ssid_len: Length of SSID given in @ssid. * @ssid_len: Length of SSID given in @ssid.
* @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode. * @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
* @txpower: TX power in dBm * @txpower: TX power in dBm. INT_MIN means not configured.
* @txpower_type: TX power adjustment used to control per packet Transmit * @txpower_type: TX power adjustment used to control per packet Transmit
* Power Control (TPC) in lower driver for the current vif. In particular * Power Control (TPC) in lower driver for the current vif. In particular
* TPC is enabled if value passed in %txpower_type is * TPC is enabled if value passed in %txpower_type is
......
...@@ -1465,6 +1465,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, ...@@ -1465,6 +1465,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
sdata->control_port_no_encrypt = false; sdata->control_port_no_encrypt = false;
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
sdata->vif.bss_conf.idle = true; sdata->vif.bss_conf.idle = true;
sdata->vif.bss_conf.txpower = INT_MIN; /* unset */
sdata->noack_map = 0; sdata->noack_map = 0;
sdata->hw_80211_encap = false; sdata->hw_80211_encap = false;
......
...@@ -146,6 +146,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) ...@@ -146,6 +146,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
continue; continue;
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
continue; continue;
if (sdata->vif.bss_conf.txpower == INT_MIN)
continue;
power = min(power, sdata->vif.bss_conf.txpower); power = min(power, sdata->vif.bss_conf.txpower);
} }
rcu_read_unlock(); rcu_read_unlock();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment