Message ID | 1553856587-21611-1-git-send-email-bpothuno@codeaurora.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v4,1/3] cfg80211: Add support to set tx power for a station associated | expand |
On Fri, Mar 29, 2019 at 04:19:47PM +0530, Balaji Pothunoori wrote: > From: Ashok Raj Nagarajan <arnagara@codeaurora.org> > > This patch will add the support to control the transmit power for traffic > to a station associated with the AP. > > Underlying firmware will enforce that the maximum tx power will be based > on the regulatory requirements. If the user given transmit power is greater > than the allowed tx power in the given channel, then the firmware will use > the maximum tx power in the same channel. > > When 0 is sent to the firmware as tx power, it will revert to the default > tx power for the station. > > Tested Hardware : QCA9984 > Tested Firmware : 10.4-3.9.0.1-00013 I tried this on qca9984 with 10.4-3.9.0.2-00040, which claims to support this feature, and it didn't seem to work: - with global tx power limit set to 30 dBm, I started an iperf from station A -> B - while iperf underway, I did tcpdump on a monitor on B and looked at signal level in radiotap, in this case around -75 dBm - on A, changed the per-sta txpwr limit for B to something (tried as low as 1 dBm). verified via printk that it went through to the driver / firmware command and reported no error -> result: signal level unchanged - on A, changed the global tx power limit to 1 dBm -> result: signal level dropped to ~ -95 dBm Reading the description above, now I'm wondering if the txpower is max(sta-power,global-power)? If so, that seems a bit unintuitive to me, or at least isn't what I hoped for. I'd prefer to have per-sta power setting override the global power.
Bob Copeland <me@bobcopeland.com> writes: > On Fri, Mar 29, 2019 at 04:19:47PM +0530, Balaji Pothunoori wrote: >> From: Ashok Raj Nagarajan <arnagara@codeaurora.org> >> >> This patch will add the support to control the transmit power for traffic >> to a station associated with the AP. >> >> Underlying firmware will enforce that the maximum tx power will be based >> on the regulatory requirements. If the user given transmit power is greater >> than the allowed tx power in the given channel, then the firmware will use >> the maximum tx power in the same channel. >> >> When 0 is sent to the firmware as tx power, it will revert to the default >> tx power for the station. >> >> Tested Hardware : QCA9984 >> Tested Firmware : 10.4-3.9.0.1-00013 > > I tried this on qca9984 with 10.4-3.9.0.2-00040, which claims to support > this feature, and it didn't seem to work: > > - with global tx power limit set to 30 dBm, I started an iperf from station > A -> B > > - while iperf underway, I did tcpdump on a monitor on B and looked at signal > level in radiotap, in this case around -75 dBm > > - on A, changed the per-sta txpwr limit for B to something (tried as low as > 1 dBm). verified via printk that it went through to the driver / firmware > command and reported no error > -> result: signal level unchanged > > - on A, changed the global tx power limit to 1 dBm > -> result: signal level dropped to ~ -95 dBm > > Reading the description above, now I'm wondering if the txpower is > max(sta-power,global-power)? If so, that seems a bit unintuitive to me, > or at least isn't what I hoped for. I'd prefer to have per-sta power > setting override the global power. Balaji, please reply to Bob's questions. I missed this thread while applying v5, sorry Bob.
On Wed, Sep 18, 2019 at 04:41:54PM +0300, Kalle Valo wrote: > Bob Copeland <me@bobcopeland.com> writes: > > - on A, changed the global tx power limit to 1 dBm > > -> result: signal level dropped to ~ -95 dBm > > > > Reading the description above, now I'm wondering if the txpower is > > max(sta-power,global-power)? If so, that seems a bit unintuitive to me, > > or at least isn't what I hoped for. I'd prefer to have per-sta power > > setting override the global power. > > Balaji, please reply to Bob's questions. I missed this thread while > applying v5, sorry Bob. Just to follow-up, I ran more experiments since writing the above email and it didn't look like it was doing max() either -- at least on my hardware/firmware combo it had no effect at all that I could tell. I did verify that the wmi update went through to the firmware. I can't remember now, but I may have been testing mesh mode in case that makes a difference.
On 2019-09-19 05:51, Bob Copeland wrote: > On Wed, Sep 18, 2019 at 04:41:54PM +0300, Kalle Valo wrote: >> Bob Copeland <me@bobcopeland.com> writes: >> > - on A, changed the global tx power limit to 1 dBm >> > -> result: signal level dropped to ~ -95 dBm >> > >> > Reading the description above, now I'm wondering if the txpower is >> > max(sta-power,global-power)? If so, that seems a bit unintuitive to me, >> > or at least isn't what I hoped for. I'd prefer to have per-sta power >> > setting override the global power. >> >> Balaji, please reply to Bob's questions. I missed this thread while >> applying v5, sorry Bob. > > Just to follow-up, I ran more experiments since writing the above > email and it didn't look like it was doing max() either -- at least > on my hardware/firmware combo it had no effect at all that I could > tell. > For QCA9984 allowed tx power range values from 6 to 23, Same info mentioned in : https://patchwork.kernel.org/patch/10968517/ > I did verify that the wmi update went through to the firmware. > > I can't remember now, but I may have been testing mesh mode in case > that makes a difference. We gave fix for tx power configuration in firmware 10.4-3.9.0.2-00046 . Can you try with that ? Regards, Balaji.
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index db78e85..2e43d8d 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -71,6 +71,9 @@ struct ath10k_pktlog_hdr { /* FIXME: How to calculate the buffer size sanely? */ #define ATH10K_FW_STATS_BUF_SIZE (1024 * 1024) +#define ATH10K_TX_POWER_MAX_VAL 70 +#define ATH10K_TX_POWER_MIN_VAL 0 + extern unsigned int ath10k_debug_mask; __printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...); diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index b73c23d..d6ed452 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6350,6 +6350,41 @@ static void ath10k_mac_dec_num_stations(struct ath10k_vif *arvif, ar->num_stations--; } +static int ath10k_sta_set_txpwr(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif = (void *)vif->drv_priv; + int ret = 0; + s16 txpwr; + + if (sta->txpwr.type == NL80211_TX_POWER_AUTOMATIC) { + txpwr = 0; + } else { + txpwr = sta->txpwr.power; + if (!txpwr) + return -EINVAL; + } + + if (txpwr > ATH10K_TX_POWER_MAX_VAL || txpwr < ATH10K_TX_POWER_MIN_VAL) + return -EINVAL; + + mutex_lock(&ar->conf_mutex); + + ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, + WMI_PEER_USE_FIXED_PWR, txpwr); + if (ret) { + ath10k_warn(ar, "failed to set tx power for station ret: %d\n", + ret); + goto out; + } + +out: + mutex_unlock(&ar->conf_mutex); + return ret; +} + static int ath10k_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -8007,6 +8042,7 @@ static const struct ieee80211_ops ath10k_ops = { .set_key = ath10k_set_key, .set_default_unicast_key = ath10k_set_default_unicast_key, .sta_state = ath10k_sta_state, + .sta_set_txpwr = ath10k_sta_set_txpwr, .conf_tx = ath10k_conf_tx, .remain_on_channel = ath10k_remain_on_channel, .cancel_remain_on_channel = ath10k_cancel_remain_on_channel, @@ -8695,6 +8731,9 @@ int ath10k_mac_register(struct ath10k *ar) wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER); + if (test_bit(WMI_SERVICE_TX_PWR_PER_PEER, ar->wmi.svc_map)) + wiphy_ext_feature_set(ar->hw->wiphy, + NL80211_EXT_FEATURE_STA_TX_PWR); /* * on LL hardware queues are managed entirely by the FW * so we only advertise to mac we can do the queues thing diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index e1c40bb..c071563 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -200,6 +200,7 @@ enum wmi_service { WMI_SERVICE_RTT_RESPONDER_ROLE, WMI_SERVICE_PER_PACKET_SW_ENCRYPT, WMI_SERVICE_REPORT_AIRTIME, + WMI_SERVICE_TX_PWR_PER_PEER, /* Remember to add the new value to wmi_service_name()! */ @@ -367,6 +368,7 @@ enum wmi_10_4_service { WMI_10_4_SERVICE_RTT_RESPONDER_ROLE, WMI_10_4_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT, WMI_10_4_SERVICE_REPORT_AIRTIME, + WMI_10_4_SERVICE_TX_PWR_PER_PEER, }; static inline char *wmi_service_name(enum wmi_service service_id) @@ -491,6 +493,7 @@ static inline char *wmi_service_name(enum wmi_service service_id) SVCSTR(WMI_SERVICE_RTT_RESPONDER_ROLE); SVCSTR(WMI_SERVICE_PER_PACKET_SW_ENCRYPT); SVCSTR(WMI_SERVICE_REPORT_AIRTIME); + SVCSTR(WMI_SERVICE_TX_PWR_PER_PEER); case WMI_SERVICE_MAX: return NULL; @@ -818,6 +821,8 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out, WMI_SERVICE_PER_PACKET_SW_ENCRYPT, len); SVCMAP(WMI_10_4_SERVICE_REPORT_AIRTIME, WMI_SERVICE_REPORT_AIRTIME, len); + SVCMAP(WMI_10_4_SERVICE_TX_PWR_PER_PEER, + WMI_SERVICE_TX_PWR_PER_PEER, len); } #undef SVCMAP @@ -6261,6 +6266,7 @@ enum wmi_peer_param { WMI_PEER_USE_4ADDR = 0x6, WMI_PEER_DEBUG = 0xa, WMI_PEER_PHYMODE = 0xd, + WMI_PEER_USE_FIXED_PWR = 0x8, WMI_PEER_DUMMY_VAR = 0xff, /* dummy parameter for STA PS workaround */ };