diff mbox series

[v4,3/3] ath10k: add support for controlling tx power to a station

Message ID 1553856587-21611-1-git-send-email-bpothuno@codeaurora.org (mailing list archive)
State Superseded
Delegated to: Kalle Valo
Headers show
Series [v4,1/3] cfg80211: Add support to set tx power for a station associated | expand

Commit Message

Balaji Pothunoori March 29, 2019, 10:49 a.m. UTC
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

Co-developed-by: Balaji Pothunoori <bpothuno@codeaurora.org>
Signed-off-by: Ashok Raj Nagarajan <arnagara@codeaurora.org>
Signed-off-by: Balaji Pothunoori <bpothuno@codeaurora.org>
---
v2: removed mBm to dBm conversion
v3: rebased wmi.h changes
v4: no changes, rebased 

 drivers/net/wireless/ath/ath10k/debug.h |  3 +++
 drivers/net/wireless/ath/ath10k/mac.c   | 39 +++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/wmi.h   |  6 +++++
 3 files changed, 48 insertions(+)

Comments

Bob Copeland April 2, 2019, 10:37 p.m. UTC | #1
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.
Kalle Valo Sept. 18, 2019, 1:41 p.m. UTC | #2
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.
Bob Copeland Sept. 19, 2019, 12:21 a.m. UTC | #3
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.
Balaji Pothunoori Sept. 19, 2019, 8:04 a.m. UTC | #4
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 mbox series

Patch

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 */
 };