2023-12-04 08:14:06

by Baochen Qiang

[permalink] [raw]
Subject: [PATCH v8 00/12] wifi: ath11k: add support for 6 GHz station for various modes : LPI, SP and VLP

This introduced some new concept:
power type of AP(STANDARD_POWER_AP, INDOOR_AP, VERY_LOW_POWER_AP)
power type of STATION(DEFAULT_CLIENT, SUBORDINATE_CLIENT)
power spectral density(psd)

This patchset is to implement the new rules for 6 GHz band in
ath11k.

ath11k parsed the reg rules from new WMI event
WMI_REG_CHAN_LIST_CC_EXT_EVENTID and parse the
transmit power envelope element in beacon of AP
and then set new WMI command WMI_VDEV_SET_TPC_POWER_CMDID
to firmware when connect to 6G AP, also support backward
compatibility with firmware which not support new wmi
cmd WMI_VDEV_SET_TPC_POWER_CMDID.

v8:
add my own s-o-b tag to each patch if not present. Also rebased to ToT.

v7: address review comments per Kalle, Jeff and Aditya. Also rebased to ToT.

v6: (NOT depends to any patch now)
1. The dependent patch "wifi: cfg80211: save power spectral density(psd) of regulatory rule"
has upstream to wireless-next https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/commit/?id=ddd7f45c899f7524bdbe6a32fe4906cde8b07b9b
The prerequisite-patch is cherry-pick from wireless-next
So add back the other patches in v3 since no dependency to cfg80211 public patch above now.
[v3,08/15] wifi: ath11k: save power spectral density(psd) of regulatory rule
[v3,09/15] wifi: ath11k: add parse of transmit power envelope element
[v3,10/15] wifi: ath11k: save max tx power in vdev start response event from firmware
[v3,11/15] wifi: ath11k: fill parameters for vdev_set_tpc_power wmi command
[v3,12/15] wifi: ath11k: add WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT service bit
[v3,13/15] wifi: ath11k: discard BSS_CHANGED_TXPOWER when EXT_TPC_REG_SUPPORT for 6 GHz
[v3,14/15] wifi: ath11k: add handler for WMI_VDEV_SET_TPC_POWER_CMDID
[v3,15/15] wifi: ath11k: send TPC power to firmware for 6 GHz station
2. rename some "6g" to "6ghz"
3. remove "static" for ath11k_reg_ap_pwr_convert()
4. add 20 Mhz check in ath11k_mac_get_eirp_power()
5. remove min_t() in ath11k_mac_fill_reg_tpc_info() for not is_tpe_present
6. rebased to ath-202309051328

link of v5:
[PATCH v5 0/5] fix wrong TX power and frequency in regdomain by dynamic switch 6 GHz reg rules of LPI/SP/VLP for station mode
https://lore.kernel.org/linux-wireless/[email protected]/

v5: change per Kalle and rebased to ath.git ath-202306211808
1. ath11k_ieee80211_ap_pwr_type_convert() to ath11k_reg_ap_pwr_convert()
2. used list_first_entry_or_null() and add comments
3. ath11k_dbg() to ath11k_warn()
4. ath11k_hw_supports_6g_cc_ext() to ath11k_mac_supports_6g_cc_ext()
5. add mesh in commit log

v4: (NOT depends to any patch now).
1. removed patches which depends on
wifi: cfg80211: save Power Spectral Density (PSD) of the regulatory rule
https://lore.kernel.org/linux-wireless/[email protected]/
removed:
[v3,08/15] wifi: ath11k: save power spectral density(psd) of regulatory rule
[v3,09/15] wifi: ath11k: add parse of transmit power envelope element
[v3,10/15] wifi: ath11k: save max tx power in vdev start response event from firmware
[v3,11/15] wifi: ath11k: fill parameters for vdev_set_tpc_power wmi command
[v3,12/15] wifi: ath11k: add WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT service bit
[v3,13/15] wifi: ath11k: discard BSS_CHANGED_TXPOWER when EXT_TPC_REG_SUPPORT for 6 GHz
[v3,14/15] wifi: ath11k: add handler for WMI_VDEV_SET_TPC_POWER_CMDID
[v3,15/15] wifi: ath11k: send TPC power to firmware for 6 GHz station

2. rebased to ath.git ath-202304281700

3. deleted "wifi: ath11k: Add support to parse new wmi event for 6 GHz regulatory" which is alreay upstream.

link of v3:
[v3,00/15] wifi: ath11k: add support for 6 GHz station for various modes : LPI, SP and VLP
https://patchwork.kernel.org/project/linux-wireless/cover/[email protected]/

v3:
1. added "ath11k: fix a possible dead lock caused by ab->base_lock".
3. deleted "ath11k: add support for extended wmi service bit" which is alreay upstream.

v2:
1. change some minor comments by Kalle.
2. rebased to ath.git ath-202112220603

Baochen Qiang (1):
wifi: ath11k: fix a possible dead lock caused by ab->base_lock

Wen Gong (11):
wifi: ath11k: add support to select 6 GHz regulatory type
wifi: ath11k: store cur_regulatory_info for each radio
wifi: ath11k: update regulatory rules when interface added
wifi: ath11k: update regulatory rules when connect to AP on 6 GHz band
for station
wifi: ath11k: save power spectral density(PSD) of regulatory rule
wifi: ath11k: add parse of transmit power envelope element
wifi: ath11k: save max tx power in vdev start response event from
firmware
wifi: ath11k: fill parameters for vdev set tpc power WMI command
wifi: ath11k: add WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT service bit
wifi: ath11k: add handler for WMI_VDEV_SET_TPC_POWER_CMDID
wifi: ath11k: discard BSS_CHANGED_TXPOWER when EXT_TPC_REG_SUPPORT for
6 GHz

drivers/net/wireless/ath/ath11k/core.h | 40 ++
drivers/net/wireless/ath/ath11k/mac.c | 516 ++++++++++++++++++++++++-
drivers/net/wireless/ath/ath11k/mac.h | 5 +-
drivers/net/wireless/ath/ath11k/reg.c | 89 ++++-
drivers/net/wireless/ath/ath11k/reg.h | 6 +-
drivers/net/wireless/ath/ath11k/wmi.c | 231 ++++++++---
drivers/net/wireless/ath/ath11k/wmi.h | 69 ++++
7 files changed, 882 insertions(+), 74 deletions(-)


base-commit: b648266cb860d3ea51f0a2b36d2ce4a9cec1ed16
--
2.25.1



2023-12-04 08:14:10

by Baochen Qiang

[permalink] [raw]
Subject: [PATCH v8 08/12] wifi: ath11k: save max tx power in vdev start response event from firmware

From: Wen Gong <[email protected]>

Save the max tx power received in the vdev start response event from
firmware. A subsequent patch will use this to calculate the final power
value for WMI_VDEV_SET_TPC_POWER_CMDID.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23

Signed-off-by: Wen Gong <[email protected]>
Acked-by: Jeff Johnson <[email protected]>
Signed-off-by: Baochen Qiang <[email protected]>
---
v8:
add s-o-b tag
v7:
no change.

drivers/net/wireless/ath/ath11k/core.h | 1 +
drivers/net/wireless/ath/ath11k/wmi.c | 3 ++-
drivers/net/wireless/ath/ath11k/wmi.h | 1 +
3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 7774e487abcf..bc125a2c1eac 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -777,6 +777,7 @@ struct ath11k {
/* protected by conf_mutex */
bool ps_state_enable;
bool ps_timekeeper_enable;
+ s8 max_allowed_tx_power;
};

struct ath11k_band_cap {
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 9a0568676a74..3f6026f5fab8 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -5033,6 +5033,7 @@ static int ath11k_pull_vdev_start_resp_tlv(struct ath11k_base *ab, struct sk_buf
vdev_rsp->mac_id = ev->mac_id;
vdev_rsp->cfgd_tx_streams = ev->cfgd_tx_streams;
vdev_rsp->cfgd_rx_streams = ev->cfgd_rx_streams;
+ vdev_rsp->max_allowed_tx_power = ev->max_allowed_tx_power;

kfree(tb);
return 0;
@@ -7427,7 +7428,7 @@ static void ath11k_vdev_start_resp_event(struct ath11k_base *ab, struct sk_buff
}

ar->last_wmi_vdev_start_status = 0;
-
+ ar->max_allowed_tx_power = vdev_start_resp.max_allowed_tx_power;
status = vdev_start_resp.status;

if (WARN_ON_ONCE(status)) {
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index fa85e6eb4ab4..a9a7d81236cb 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -4119,6 +4119,7 @@ struct wmi_vdev_start_resp_event {
};
u32 cfgd_tx_streams;
u32 cfgd_rx_streams;
+ s32 max_allowed_tx_power;
} __packed;

/* VDEV start response status codes */
--
2.25.1


2023-12-04 08:14:17

by Baochen Qiang

[permalink] [raw]
Subject: [PATCH v8 06/12] wifi: ath11k: save power spectral density(PSD) of regulatory rule

From: Wen Gong <[email protected]>

Save the power spectral density(PSD) report from firmware to struct
ieee80211_reg_rule.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23

Signed-off-by: Wen Gong <[email protected]>
Acked-by: Jeff Johnson <[email protected]>
Signed-off-by: Baochen Qiang <[email protected]>
---
v8:
no change.
v7:
1. s/psd/PSD/

drivers/net/wireless/ath/ath11k/reg.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c
index b860d2fd7e5c..f27cf5264678 100644
--- a/drivers/net/wireless/ath/ath11k/reg.c
+++ b/drivers/net/wireless/ath/ath11k/reg.c
@@ -424,6 +424,10 @@ static void ath11k_reg_intersect_rules(struct ieee80211_reg_rule *rule1,

/* Use the flags of both the rules */
new_rule->flags = rule1->flags | rule2->flags;
+ if ((rule1->flags & NL80211_RRF_PSD) && (rule2->flags & NL80211_RRF_PSD))
+ new_rule->psd = min_t(s8, rule1->psd, rule2->psd);
+ else
+ new_rule->flags &= ~NL80211_RRF_PSD;

/* To be safe, lts use the max cac timeout of both rules */
new_rule->dfs_cac_ms = max_t(u32, rule1->dfs_cac_ms,
@@ -527,13 +531,14 @@ ath11k_reg_adjust_bw(u16 start_freq, u16 end_freq, u16 max_bw)
static void
ath11k_reg_update_rule(struct ieee80211_reg_rule *reg_rule, u32 start_freq,
u32 end_freq, u32 bw, u32 ant_gain, u32 reg_pwr,
- u32 reg_flags)
+ s8 psd, u32 reg_flags)
{
reg_rule->freq_range.start_freq_khz = MHZ_TO_KHZ(start_freq);
reg_rule->freq_range.end_freq_khz = MHZ_TO_KHZ(end_freq);
reg_rule->freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw);
reg_rule->power_rule.max_antenna_gain = DBI_TO_MBI(ant_gain);
reg_rule->power_rule.max_eirp = DBM_TO_MBM(reg_pwr);
+ reg_rule->psd = psd;
reg_rule->flags = reg_flags;
}

@@ -563,7 +568,7 @@ ath11k_reg_update_weather_radar_band(struct ath11k_base *ab,
reg_rule->start_freq,
ETSI_WEATHER_RADAR_BAND_LOW, bw,
reg_rule->ant_gain, reg_rule->reg_power,
- flags);
+ reg_rule->psd_eirp, flags);

ath11k_dbg(ab, ATH11K_DBG_REG,
"\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n",
@@ -584,7 +589,7 @@ ath11k_reg_update_weather_radar_band(struct ath11k_base *ab,

ath11k_reg_update_rule(regd->reg_rules + i, start_freq,
end_freq, bw, reg_rule->ant_gain,
- reg_rule->reg_power, flags);
+ reg_rule->reg_power, reg_rule->psd_eirp, flags);

regd->reg_rules[i].dfs_cac_ms = ETSI_WEATHER_RADAR_BAND_CAC_TIMEOUT;

@@ -605,7 +610,7 @@ ath11k_reg_update_weather_radar_band(struct ath11k_base *ab,
ETSI_WEATHER_RADAR_BAND_HIGH,
reg_rule->end_freq, bw,
reg_rule->ant_gain, reg_rule->reg_power,
- flags);
+ reg_rule->psd_eirp, flags);

ath11k_dbg(ab, ATH11K_DBG_REG,
"\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n",
@@ -727,6 +732,8 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
reg_rule = reg_rule_6ghz + k++;
max_bw = min_t(u16, reg_rule->max_bw, max_bw_6ghz);
flags = NL80211_RRF_AUTO_BW;
+ if (reg_rule->psd_flag)
+ flags |= NL80211_RRF_PSD;
} else {
break;
}
@@ -738,7 +745,7 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
reg_rule->start_freq,
reg_rule->end_freq, max_bw,
reg_rule->ant_gain, reg_rule->reg_power,
- flags);
+ reg_rule->psd_eirp, flags);

/* Update dfs cac timeout if the dfs domain is ETSI and the
* new rule covers weather radar band.
--
2.25.1


2023-12-04 08:14:23

by Baochen Qiang

[permalink] [raw]
Subject: [PATCH v8 07/12] wifi: ath11k: add parse of transmit power envelope element

From: Wen Gong <[email protected]>

The transmit power envelope element has some fields for power, ath11k
should parse it according to IEEE Std 802.11ax™‐2021.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23

Signed-off-by: Wen Gong <[email protected]>
Acked-by: Jeff Johnson <[email protected]>
Signed-off-by: Baochen Qiang <[email protected]>
---
v8:
add s-o-b tag
v7:
no change.

drivers/net/wireless/ath/ath11k/core.h | 38 +++++
drivers/net/wireless/ath/ath11k/mac.c | 185 +++++++++++++++++++++++++
2 files changed, 223 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index cc91f7d3ca8e..7774e487abcf 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -314,6 +314,43 @@ struct ath11k_rekey_data {
bool enable_offload;
};

+/**
+ * struct chan_power_info - TPE containing power info per channel chunk
+ * @chan_cfreq: channel center freq (MHz)
+ * e.g.
+ * channel 37/20 MHz, it is 6135
+ * channel 37/40 MHz, it is 6125
+ * channel 37/80 MHz, it is 6145
+ * channel 37/160 MHz, it is 6185
+ * @tx_power: transmit power (dBm)
+ */
+struct chan_power_info {
+ u16 chan_cfreq;
+ s8 tx_power;
+};
+
+/**
+ * struct reg_tpc_power_info - regulatory TPC power info
+ * @is_psd_power: is PSD power or not
+ * @eirp_power: Maximum EIRP power (dBm), valid only if power is PSD
+ * @ap_power_type: type of power (SP/LPI/VLP)
+ * @num_pwr_levels: number of power levels
+ * @reg_max: Array of maximum TX power (dBm) per PSD value
+ * @ap_constraint_power: AP constraint power (dBm)
+ * @tpe: TPE values processed from TPE IE
+ * @chan_power_info: power info to send to firmware
+ */
+struct ath11k_reg_tpc_power_info {
+ bool is_psd_power;
+ u8 eirp_power;
+ enum wmi_reg_6ghz_ap_type ap_power_type;
+ u8 num_pwr_levels;
+ u8 reg_max[IEEE80211_MAX_NUM_PWR_LEVEL];
+ u8 ap_constraint_power;
+ s8 tpe[IEEE80211_MAX_NUM_PWR_LEVEL];
+ struct chan_power_info chan_power_info[IEEE80211_MAX_NUM_PWR_LEVEL];
+};
+
struct ath11k_vif {
u32 vdev_id;
enum wmi_vdev_type vdev_type;
@@ -372,6 +409,7 @@ struct ath11k_vif {
#ifdef CONFIG_ATH11K_DEBUGFS
struct dentry *debugfs_twt;
#endif /* CONFIG_ATH11K_DEBUGFS */
+ struct ath11k_reg_tpc_power_info reg_tpc_info;
};

struct ath11k_vif_iter {
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index b6ca6fb801f8..7707aec48c1d 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -7602,6 +7602,189 @@ static int ath11k_start_vdev_delay(struct ieee80211_hw *hw,
return 0;
}

+static u8 ath11k_mac_get_tpe_count(u8 txpwr_intrprt, u8 txpwr_cnt)
+{
+ switch (txpwr_intrprt) {
+ /* Refer "Table 9-276-Meaning of Maximum Transmit Power Count subfield
+ * if the Maximum Transmit Power Interpretation subfield is 0 or 2" of
+ * "IEEE Std 802.11ax 2021".
+ */
+ case IEEE80211_TPE_LOCAL_EIRP:
+ case IEEE80211_TPE_REG_CLIENT_EIRP:
+ txpwr_cnt = txpwr_cnt <= 3 ? txpwr_cnt : 3;
+ txpwr_cnt = txpwr_cnt + 1;
+ break;
+ /* Refer "Table 9-277-Meaning of Maximum Transmit Power Count subfield
+ * if Maximum Transmit Power Interpretation subfield is 1 or 3" of
+ * "IEEE Std 802.11ax 2021".
+ */
+ case IEEE80211_TPE_LOCAL_EIRP_PSD:
+ case IEEE80211_TPE_REG_CLIENT_EIRP_PSD:
+ txpwr_cnt = txpwr_cnt <= 4 ? txpwr_cnt : 4;
+ txpwr_cnt = txpwr_cnt ? (BIT(txpwr_cnt - 1)) : 1;
+ break;
+ }
+
+ return txpwr_cnt;
+}
+
+static u8 ath11k_mac_get_num_pwr_levels(struct cfg80211_chan_def *chan_def)
+{
+ if (chan_def->chan->flags & IEEE80211_CHAN_PSD) {
+ switch (chan_def->width) {
+ case NL80211_CHAN_WIDTH_20:
+ return 1;
+ case NL80211_CHAN_WIDTH_40:
+ return 2;
+ case NL80211_CHAN_WIDTH_80:
+ return 4;
+ case NL80211_CHAN_WIDTH_80P80:
+ case NL80211_CHAN_WIDTH_160:
+ return 8;
+ default:
+ return 1;
+ }
+ } else {
+ switch (chan_def->width) {
+ case NL80211_CHAN_WIDTH_20:
+ return 1;
+ case NL80211_CHAN_WIDTH_40:
+ return 2;
+ case NL80211_CHAN_WIDTH_80:
+ return 3;
+ case NL80211_CHAN_WIDTH_80P80:
+ case NL80211_CHAN_WIDTH_160:
+ return 4;
+ default:
+ return 1;
+ }
+ }
+}
+
+static void ath11k_mac_parse_tx_pwr_env(struct ath11k *ar,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *ctx)
+{
+ struct ath11k_base *ab = ar->ab;
+ struct ath11k_vif *arvif = (void *)vif->drv_priv;
+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+ struct ieee80211_tx_pwr_env *single_tpe;
+ enum wmi_reg_6ghz_client_type client_type;
+ struct cur_regulatory_info *reg_info;
+ int i;
+ u8 pwr_count, pwr_interpret, pwr_category;
+ u8 psd_index = 0, non_psd_index = 0, local_tpe_count = 0, reg_tpe_count = 0;
+ bool use_local_tpe, non_psd_set = false, psd_set = false;
+
+ reg_info = &ab->reg_info_store[ar->pdev_idx];
+ client_type = reg_info->client_type;
+
+ for (i = 0; i < bss_conf->tx_pwr_env_num; i++) {
+ single_tpe = &bss_conf->tx_pwr_env[i];
+ pwr_category = u8_get_bits(single_tpe->tx_power_info,
+ IEEE80211_TX_PWR_ENV_INFO_CATEGORY);
+ pwr_interpret = u8_get_bits(single_tpe->tx_power_info,
+ IEEE80211_TX_PWR_ENV_INFO_INTERPRET);
+
+ if (pwr_category == client_type) {
+ if (pwr_interpret == IEEE80211_TPE_LOCAL_EIRP ||
+ pwr_interpret == IEEE80211_TPE_LOCAL_EIRP_PSD)
+ local_tpe_count++;
+ else if (pwr_interpret == IEEE80211_TPE_REG_CLIENT_EIRP ||
+ pwr_interpret == IEEE80211_TPE_REG_CLIENT_EIRP_PSD)
+ reg_tpe_count++;
+ }
+ }
+
+ if (!reg_tpe_count && !local_tpe_count) {
+ ath11k_warn(ab,
+ "no transmit power envelope match client power type %d\n",
+ client_type);
+ return;
+ } else if (!reg_tpe_count) {
+ use_local_tpe = true;
+ } else {
+ use_local_tpe = false;
+ }
+
+ for (i = 0; i < bss_conf->tx_pwr_env_num; i++) {
+ single_tpe = &bss_conf->tx_pwr_env[i];
+ pwr_category = u8_get_bits(single_tpe->tx_power_info,
+ IEEE80211_TX_PWR_ENV_INFO_CATEGORY);
+ pwr_interpret = u8_get_bits(single_tpe->tx_power_info,
+ IEEE80211_TX_PWR_ENV_INFO_INTERPRET);
+
+ if (pwr_category != client_type)
+ continue;
+
+ /* get local transmit power envelope */
+ if (use_local_tpe) {
+ if (pwr_interpret == IEEE80211_TPE_LOCAL_EIRP) {
+ non_psd_index = i;
+ non_psd_set = true;
+ } else if (pwr_interpret == IEEE80211_TPE_LOCAL_EIRP_PSD) {
+ psd_index = i;
+ psd_set = true;
+ }
+ /* get regulatory transmit power envelope */
+ } else {
+ if (pwr_interpret == IEEE80211_TPE_REG_CLIENT_EIRP) {
+ non_psd_index = i;
+ non_psd_set = true;
+ } else if (pwr_interpret == IEEE80211_TPE_REG_CLIENT_EIRP_PSD) {
+ psd_index = i;
+ psd_set = true;
+ }
+ }
+ }
+
+ if (non_psd_set && !psd_set) {
+ single_tpe = &bss_conf->tx_pwr_env[non_psd_index];
+ pwr_count = u8_get_bits(single_tpe->tx_power_info,
+ IEEE80211_TX_PWR_ENV_INFO_COUNT);
+ pwr_interpret = u8_get_bits(single_tpe->tx_power_info,
+ IEEE80211_TX_PWR_ENV_INFO_INTERPRET);
+ arvif->reg_tpc_info.is_psd_power = false;
+ arvif->reg_tpc_info.eirp_power = 0;
+
+ arvif->reg_tpc_info.num_pwr_levels =
+ ath11k_mac_get_tpe_count(pwr_interpret, pwr_count);
+ for (i = 0; i < arvif->reg_tpc_info.num_pwr_levels; i++) {
+ ath11k_dbg(ab, ATH11K_DBG_MAC,
+ "non PSD power[%d] : %d\n",
+ i, single_tpe->tx_power[i]);
+ arvif->reg_tpc_info.tpe[i] = single_tpe->tx_power[i] / 2;
+ }
+ }
+
+ if (psd_set) {
+ single_tpe = &bss_conf->tx_pwr_env[psd_index];
+ pwr_count = u8_get_bits(single_tpe->tx_power_info,
+ IEEE80211_TX_PWR_ENV_INFO_COUNT);
+ pwr_interpret = u8_get_bits(single_tpe->tx_power_info,
+ IEEE80211_TX_PWR_ENV_INFO_INTERPRET);
+ arvif->reg_tpc_info.is_psd_power = true;
+
+ if (pwr_count == 0) {
+ ath11k_dbg(ab, ATH11K_DBG_MAC,
+ "TPE PSD power : %d\n", single_tpe->tx_power[0]);
+ arvif->reg_tpc_info.num_pwr_levels =
+ ath11k_mac_get_num_pwr_levels(&ctx->def);
+ for (i = 0; i < arvif->reg_tpc_info.num_pwr_levels; i++)
+ arvif->reg_tpc_info.tpe[i] = single_tpe->tx_power[0] / 2;
+ } else {
+ arvif->reg_tpc_info.num_pwr_levels =
+ ath11k_mac_get_tpe_count(pwr_interpret, pwr_count);
+ for (i = 0; i < arvif->reg_tpc_info.num_pwr_levels; i++) {
+ ath11k_dbg(ab, ATH11K_DBG_MAC,
+ "TPE PSD power[%d] : %d\n",
+ i, single_tpe->tx_power[i]);
+ arvif->reg_tpc_info.tpe[i] = single_tpe->tx_power[i] / 2;
+ }
+ }
+ }
+}
+
static int
ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -7634,6 +7817,8 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
goto out;
}
ath11k_reg_handle_chan_list(ab, reg_info, power_type);
+
+ ath11k_mac_parse_tx_pwr_env(ar, vif, ctx);
}

/* for QCA6390 bss peer must be created before vdev_start */
--
2.25.1


2023-12-04 08:14:30

by Baochen Qiang

[permalink] [raw]
Subject: [PATCH v8 10/12] wifi: ath11k: add WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT service bit

From: Wen Gong <[email protected]>

Firmware advertises support for SERVICE_EXT_TPC_REG via a WMI service bit.
Add the definition of this service bit so that a subsequent patch can
check whether or not firmware supports this service.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23

Signed-off-by: Wen Gong <[email protected]>
Acked-by: Jeff Johnson <[email protected]>
Signed-off-by: Baochen Qiang <[email protected]>
---
v8:
add s-o-b tag.
v7:
no change.

drivers/net/wireless/ath/ath11k/wmi.h | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index a9a7d81236cb..7e416e09aa5f 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -2114,6 +2114,7 @@ enum wmi_tlv_service {
/* The second 128 bits */
WMI_MAX_EXT_SERVICE = 256,
WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL = 265,
+ WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT = 280,
WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
WMI_TLV_SERVICE_BIOS_SAR_SUPPORT = 326,
WMI_TLV_SERVICE_SUPPORT_11D_FOR_HOST_SCAN = 357,
--
2.25.1


2023-12-04 08:14:31

by Baochen Qiang

[permalink] [raw]
Subject: [PATCH v8 09/12] wifi: ath11k: fill parameters for vdev set tpc power WMI command

From: Wen Gong <[email protected]>

Prepare the parameters which are needed for WMI command WMI_VDEV_SET_TPC_POWER_CMDID.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23

Signed-off-by: Wen Gong <[email protected]>
Acked-by: Jeff Johnson <[email protected]>
Signed-off-by: Baochen Qiang <[email protected]>
---
v8:
no change.
v7:
1. s/is/are/
2. remove oper_freq since not used.
3. remove repeated word: 'the'.

drivers/net/wireless/ath/ath11k/mac.c | 276 ++++++++++++++++++++++++++
drivers/net/wireless/ath/ath11k/mac.h | 3 +
2 files changed, 279 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 7707aec48c1d..2520f78c9c0b 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -7661,6 +7661,282 @@ static u8 ath11k_mac_get_num_pwr_levels(struct cfg80211_chan_def *chan_def)
}
}

+static u16 ath11k_mac_get_6ghz_start_frequency(struct cfg80211_chan_def *chan_def)
+{
+ u16 diff_seq;
+
+ /* It is to get the lowest channel number's center frequency of the chan.
+ * For example,
+ * bandwidth=40 MHz, center frequency is 5965, lowest channel is 1
+ * with center frequency 5955, its diff is 5965 - 5955 = 10.
+ * bandwidth=80 MHz, center frequency is 5985, lowest channel is 1
+ * with center frequency 5955, its diff is 5985 - 5955 = 30.
+ * bandwidth=160 MHz, center frequency is 6025, lowest channel is 1
+ * with center frequency 5955, its diff is 6025 - 5955 = 70.
+ */
+ switch (chan_def->width) {
+ case NL80211_CHAN_WIDTH_160:
+ diff_seq = 70;
+ break;
+ case NL80211_CHAN_WIDTH_80:
+ case NL80211_CHAN_WIDTH_80P80:
+ diff_seq = 30;
+ break;
+ case NL80211_CHAN_WIDTH_40:
+ diff_seq = 10;
+ break;
+ default:
+ diff_seq = 0;
+ }
+
+ return chan_def->center_freq1 - diff_seq;
+}
+
+static u16 ath11k_mac_get_seg_freq(struct cfg80211_chan_def *chan_def,
+ u16 start_seq, u8 seq)
+{
+ u16 seg_seq;
+
+ /* It is to get the center frequency of the specific bandwidth.
+ * start_seq means the lowest channel number's center frequency.
+ * seq 0/1/2/3 means 20 MHz/40 MHz/80 MHz/160 MHz&80P80.
+ * For example,
+ * lowest channel is 1, its center frequency 5955,
+ * center frequency is 5955 when bandwidth=20 MHz, its diff is 5955 - 5955 = 0.
+ * lowest channel is 1, its center frequency 5955,
+ * center frequency is 5965 when bandwidth=40 MHz, its diff is 5965 - 5955 = 10.
+ * lowest channel is 1, its center frequency 5955,
+ * center frequency is 5985 when bandwidth=80 MHz, its diff is 5985 - 5955 = 30.
+ * lowest channel is 1, its center frequency 5955,
+ * center frequency is 6025 when bandwidth=160 MHz, its diff is 6025 - 5955 = 70.
+ */
+ if (chan_def->width == NL80211_CHAN_WIDTH_80P80 && seq == 3)
+ return chan_def->center_freq2;
+
+ seg_seq = 10 * (BIT(seq) - 1);
+ return seg_seq + start_seq;
+}
+
+static void ath11k_mac_get_psd_channel(struct ath11k *ar,
+ u16 step_freq,
+ u16 *start_freq,
+ u16 *center_freq,
+ u8 i,
+ struct ieee80211_channel **temp_chan,
+ s8 *tx_power)
+{
+ /* It is to get the center frequency for each 20 MHz.
+ * For example, if the chan is 160 MHz and center frequency is 6025,
+ * then it include 8 channels, they are 1/5/9/13/17/21/25/29,
+ * channel number 1's center frequency is 5955, it is parameter start_freq.
+ * parameter i is the step of the 8 channels. i is 0~7 for the 8 channels.
+ * the channel 1/5/9/13/17/21/25/29 maps i=0/1/2/3/4/5/6/7,
+ * and maps its center frequency is 5955/5975/5995/6015/6035/6055/6075/6095,
+ * the gap is 20 for each channel, parameter step_freq means the gap.
+ * after get the center frequency of each channel, it is easy to find the
+ * struct ieee80211_channel of it and get the max_reg_power.
+ */
+ *center_freq = *start_freq + i * step_freq;
+ *temp_chan = ieee80211_get_channel(ar->hw->wiphy, *center_freq);
+ *tx_power = (*temp_chan)->max_reg_power;
+}
+
+static void ath11k_mac_get_eirp_power(struct ath11k *ar,
+ u16 *start_freq,
+ u16 *center_freq,
+ u8 i,
+ struct ieee80211_channel **temp_chan,
+ struct cfg80211_chan_def *def,
+ s8 *tx_power)
+{
+ /* It is to get the center frequency for 20 MHz/40 MHz/80 MHz/
+ * 160 MHz&80P80 bandwidth, and then plus 10 to the center frequency,
+ * it is the center frequency of a channel number.
+ * For example, when configured channel number is 1.
+ * center frequency is 5965 when bandwidth=40 MHz, after plus 10, it is 5975,
+ * then it is channel number 5.
+ * center frequency is 5985 when bandwidth=80 MHz, after plus 10, it is 5995,
+ * then it is channel number 9.
+ * center frequency is 6025 when bandwidth=160 MHz, after plus 10, it is 6035,
+ * then it is channel number 17.
+ * after get the center frequency of each channel, it is easy to find the
+ * struct ieee80211_channel of it and get the max_reg_power.
+ */
+ *center_freq = ath11k_mac_get_seg_freq(def, *start_freq, i);
+
+ /* For the 20 MHz, its center frequency is same with same channel */
+ if (i != 0)
+ *center_freq += 10;
+
+ *temp_chan = ieee80211_get_channel(ar->hw->wiphy, *center_freq);
+ *tx_power = (*temp_chan)->max_reg_power;
+}
+
+void ath11k_mac_fill_reg_tpc_info(struct ath11k *ar,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *ctx)
+{
+ struct ath11k_base *ab = ar->ab;
+ struct ath11k_vif *arvif = (void *)vif->drv_priv;
+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+ struct ath11k_reg_tpc_power_info *reg_tpc_info = &arvif->reg_tpc_info;
+ 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[IEEE80211_MAX_NUM_PWR_LEVEL],
+ psd_power, tx_power, eirp_power;
+ u16 start_freq, center_freq;
+
+ chan = ctx->def.chan;
+ start_freq = ath11k_mac_get_6ghz_start_frequency(&ctx->def);
+ pwr_reduction = bss_conf->pwr_reduction;
+
+ if (arvif->reg_tpc_info.num_pwr_levels) {
+ is_tpe_present = true;
+ num_pwr_levels = arvif->reg_tpc_info.num_pwr_levels;
+ } else {
+ num_pwr_levels = ath11k_mac_get_num_pwr_levels(&ctx->def);
+ }
+
+ for (pwr_lvl_idx = 0; pwr_lvl_idx < num_pwr_levels; pwr_lvl_idx++) {
+ /* STA received TPE IE*/
+ if (is_tpe_present) {
+ /* local power is PSD power*/
+ if (chan->flags & IEEE80211_CHAN_PSD) {
+ /* Connecting AP is psd power */
+ if (reg_tpc_info->is_psd_power) {
+ is_psd_power = true;
+ ath11k_mac_get_psd_channel(ar, 20,
+ &start_freq,
+ &center_freq,
+ pwr_lvl_idx,
+ &temp_chan,
+ &tx_power);
+ psd_power = temp_chan->psd;
+ eirp_power = tx_power;
+ max_tx_power[pwr_lvl_idx] =
+ min_t(s8,
+ psd_power,
+ reg_tpc_info->tpe[pwr_lvl_idx]);
+ /* Connecting AP is not psd power */
+ } else {
+ ath11k_mac_get_eirp_power(ar,
+ &start_freq,
+ &center_freq,
+ pwr_lvl_idx,
+ &temp_chan,
+ &ctx->def,
+ &tx_power);
+ psd_power = temp_chan->psd;
+ /* convert psd power to EIRP power based
+ * on channel width
+ */
+ tx_power =
+ min_t(s8, tx_power,
+ psd_power + 13 + pwr_lvl_idx * 3);
+ max_tx_power[pwr_lvl_idx] =
+ min_t(s8,
+ tx_power,
+ reg_tpc_info->tpe[pwr_lvl_idx]);
+ }
+ /* local power is not PSD power */
+ } else {
+ /* Connecting AP is psd power */
+ if (reg_tpc_info->is_psd_power) {
+ is_psd_power = true;
+ ath11k_mac_get_psd_channel(ar, 20,
+ &start_freq,
+ &center_freq,
+ pwr_lvl_idx,
+ &temp_chan,
+ &tx_power);
+ eirp_power = tx_power;
+ max_tx_power[pwr_lvl_idx] =
+ reg_tpc_info->tpe[pwr_lvl_idx];
+ /* Connecting AP is not psd power */
+ } else {
+ ath11k_mac_get_eirp_power(ar,
+ &start_freq,
+ &center_freq,
+ pwr_lvl_idx,
+ &temp_chan,
+ &ctx->def,
+ &tx_power);
+ max_tx_power[pwr_lvl_idx] =
+ min_t(s8,
+ tx_power,
+ reg_tpc_info->tpe[pwr_lvl_idx]);
+ }
+ }
+ /* STA not received TPE IE */
+ } else {
+ /* local power is PSD power*/
+ if (chan->flags & IEEE80211_CHAN_PSD) {
+ is_psd_power = true;
+ ath11k_mac_get_psd_channel(ar, 20,
+ &start_freq,
+ &center_freq,
+ pwr_lvl_idx,
+ &temp_chan,
+ &tx_power);
+ psd_power = temp_chan->psd;
+ eirp_power = tx_power;
+ max_tx_power[pwr_lvl_idx] = psd_power;
+ } else {
+ ath11k_mac_get_eirp_power(ar,
+ &start_freq,
+ &center_freq,
+ pwr_lvl_idx,
+ &temp_chan,
+ &ctx->def,
+ &tx_power);
+ max_tx_power[pwr_lvl_idx] = tx_power;
+ }
+ }
+
+ if (is_psd_power) {
+ /* If AP local power constraint is present */
+ if (pwr_reduction)
+ eirp_power = eirp_power - pwr_reduction;
+
+ /* If firmware updated max tx power is non zero, then take
+ * the min of firmware updated ap tx power
+ * and max power derived from above mentioned parameters.
+ */
+ ath11k_dbg(ab, ATH11K_DBG_MAC,
+ "eirp power : %d firmware report power : %d\n",
+ eirp_power, ar->max_allowed_tx_power);
+ if (ar->max_allowed_tx_power)
+ eirp_power = min_t(s8,
+ eirp_power,
+ ar->max_allowed_tx_power);
+ } else {
+ /* If AP local power constraint is present */
+ if (pwr_reduction)
+ max_tx_power[pwr_lvl_idx] =
+ max_tx_power[pwr_lvl_idx] - pwr_reduction;
+ /* If firmware updated max tx power is non zero, then take
+ * the min of firmware updated ap tx power
+ * and max power derived from above mentioned parameters.
+ */
+ if (ar->max_allowed_tx_power)
+ max_tx_power[pwr_lvl_idx] =
+ min_t(s8,
+ max_tx_power[pwr_lvl_idx],
+ ar->max_allowed_tx_power);
+ }
+ reg_tpc_info->chan_power_info[pwr_lvl_idx].chan_cfreq = center_freq;
+ reg_tpc_info->chan_power_info[pwr_lvl_idx].tx_power =
+ max_tx_power[pwr_lvl_idx];
+ }
+
+ reg_tpc_info->num_pwr_levels = num_pwr_levels;
+ reg_tpc_info->is_psd_power = is_psd_power;
+ reg_tpc_info->eirp_power = eirp_power;
+ reg_tpc_info->ap_power_type =
+ ath11k_reg_ap_pwr_convert(vif->bss_conf.power_type);
+}
+
static void ath11k_mac_parse_tx_pwr_env(struct ath11k *ar,
struct ieee80211_vif *vif,
struct ieee80211_chanctx_conf *ctx)
diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h
index 498e537cd695..13b92b468832 100644
--- a/drivers/net/wireless/ath/ath11k/mac.h
+++ b/drivers/net/wireless/ath/ath11k/mac.h
@@ -174,4 +174,7 @@ int ath11k_mac_wait_tx_complete(struct ath11k *ar);
int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif,
enum wmi_sta_keepalive_method method,
u32 interval);
+void ath11k_mac_fill_reg_tpc_info(struct ath11k *ar,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *ctx);
#endif
--
2.25.1


2023-12-04 08:14:40

by Baochen Qiang

[permalink] [raw]
Subject: [PATCH v8 12/12] wifi: ath11k: discard BSS_CHANGED_TXPOWER when EXT_TPC_REG_SUPPORT for 6 GHz

From: Wen Gong <[email protected]>

When station is connected to a 6 GHz AP, it has 2 ways to configure
the power limit to firmware. The first way is to send 2 WMI commands
WMI_PDEV_PARAM_TXPOWER_LIMIT2G/WMI_PDEV_PARAM_TXPOWER_LIMIT5G to
firmware, the second way is to send WMI_VDEV_SET_TPC_POWER_CMDID to
firmware which include more parameters for power control.

When firmware support SERVICE_EXT_TPC_REG, it means firmware support
the second way for WMI_VDEV_SET_TPC_POWER_CMDID, then ath11k discard
BSS_CHANGED_TXPOWER flag from mac80211 which is used to the first way
for 6 GHz band and select the second way.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23

Signed-off-by: Wen Gong <[email protected]>
Signed-off-by: Baochen Qiang <[email protected]>
---
v8:
no change.
v7:
1. squash original patch 11 and patch 13.
2. s/wmi command/WMI commands/
3. s/way/ways/
4. add TODO tag for CSA.

drivers/net/wireless/ath/ath11k/mac.c | 33 +++++++++++++++++++++++----
1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 2520f78c9c0b..254cb0427d12 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -3397,6 +3397,18 @@ static int ath11k_mac_config_obss_pd(struct ath11k *ar,
return 0;
}

+static bool ath11k_mac_supports_station_tpc(struct ath11k *ar,
+ struct ath11k_vif *arvif,
+ const struct cfg80211_chan_def *chandef)
+{
+ return ath11k_wmi_supports_6ghz_cc_ext(ar) &&
+ test_bit(WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT, ar->ab->wmi_ab.svc_map) &&
+ arvif->vdev_type == WMI_VDEV_TYPE_STA &&
+ arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE &&
+ chandef->chan &&
+ chandef->chan->band == NL80211_BAND_6GHZ;
+}
+
static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info,
@@ -3596,9 +3608,13 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_TXPOWER) {
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev_id %i txpower %d\n",
arvif->vdev_id, info->txpower);
-
- arvif->txpower = info->txpower;
- ath11k_mac_txpower_recalc(ar);
+ if (ath11k_mac_supports_station_tpc(ar, arvif, &info->chandef)) {
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
+ "discard tx power, change to set TPC power\n");
+ } else {
+ arvif->txpower = info->txpower;
+ ath11k_mac_txpower_recalc(ar);
+ }
}

if (changed & BSS_CHANGED_PS &&
@@ -7279,6 +7295,15 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
return ret;
}

+ /* TODO: For now we only set TPC power here. However when
+ * channel changes, say CSA, it should be updated again.
+ */
+ if (ath11k_mac_supports_station_tpc(ar, arvif, chandef)) {
+ ath11k_mac_fill_reg_tpc_info(ar, arvif->vif, &arvif->chanctx);
+ ath11k_wmi_send_vdev_set_tpc_power(ar, arvif->vdev_id,
+ &arvif->reg_tpc_info);
+ }
+
if (!restart)
ar->num_started_vdevs++;

@@ -8093,7 +8118,7 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
goto out;
}
ath11k_reg_handle_chan_list(ab, reg_info, power_type);
-
+ arvif->chanctx = *ctx;
ath11k_mac_parse_tx_pwr_env(ar, vif, ctx);
}

--
2.25.1


2023-12-04 08:14:45

by Baochen Qiang

[permalink] [raw]
Subject: [PATCH v8 11/12] wifi: ath11k: add handler for WMI_VDEV_SET_TPC_POWER_CMDID

From: Wen Gong <[email protected]>

Add the handler for WMI_VDEV_SET_TPC_POWER_CMDID, it is for 6 GHz band.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23

Signed-off-by: Wen Gong <[email protected]>
Signed-off-by: Baochen Qiang <[email protected]>
---
v8:
no change.
v7:
1. move this patch ahead.

drivers/net/wireless/ath/ath11k/wmi.c | 63 +++++++++++++++++++++++++++
drivers/net/wireless/ath/ath11k/wmi.h | 61 ++++++++++++++++++++++++++
2 files changed, 124 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 3f6026f5fab8..d725d18182e3 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -2379,6 +2379,69 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,
return ret;
}

+int ath11k_wmi_send_vdev_set_tpc_power(struct ath11k *ar,
+ u32 vdev_id,
+ struct ath11k_reg_tpc_power_info *param)
+{
+ struct ath11k_pdev_wmi *wmi = ar->wmi;
+ struct wmi_vdev_set_tpc_power_cmd *cmd;
+ struct wmi_vdev_ch_power_info *ch;
+ struct sk_buff *skb;
+ struct wmi_tlv *tlv;
+ u8 *ptr;
+ int i, ret, len, array_len;
+
+ array_len = sizeof(*ch) * param->num_pwr_levels;
+ len = sizeof(*cmd) + TLV_HDR_SIZE + array_len;
+
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
+ if (!skb)
+ return -ENOMEM;
+
+ ptr = skb->data;
+
+ cmd = (struct wmi_vdev_set_tpc_power_cmd *)ptr;
+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_VDEV_SET_TPC_POWER_CMD) |
+ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
+ cmd->vdev_id = vdev_id;
+ cmd->psd_power = param->is_psd_power;
+ cmd->eirp_power = param->eirp_power;
+ cmd->power_type_6ghz = param->ap_power_type;
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "wmi tpc vdev id %d is psd power %d eirp power %d 6 GHz power type %d\n",
+ vdev_id, param->is_psd_power, param->eirp_power, param->ap_power_type);
+
+ ptr += sizeof(*cmd);
+ tlv = (struct wmi_tlv *)ptr;
+ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) |
+ FIELD_PREP(WMI_TLV_LEN, array_len);
+
+ ptr += TLV_HDR_SIZE;
+ ch = (struct wmi_vdev_ch_power_info *)ptr;
+
+ for (i = 0; i < param->num_pwr_levels; i++, ch++) {
+ ch->tlv_header = FIELD_PREP(WMI_TLV_TAG,
+ WMI_TAG_VDEV_CH_POWER_INFO) |
+ FIELD_PREP(WMI_TLV_LEN,
+ sizeof(*ch) - TLV_HDR_SIZE);
+
+ ch->chan_cfreq = param->chan_power_info[i].chan_cfreq;
+ ch->tx_power = param->chan_power_info[i].tx_power;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "wmi tpc chan freq %d TX power %d\n",
+ ch->chan_cfreq, ch->tx_power);
+ }
+
+ ret = ath11k_wmi_cmd_send(wmi, skb,
+ WMI_VDEV_SET_TPC_POWER_CMDID);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to send WMI_VDEV_SET_TPC_POWER_CMDID\n");
+ dev_kfree_skb(skb);
+ }
+ return ret;
+}
+
int ath11k_wmi_send_scan_stop_cmd(struct ath11k *ar,
struct scan_cancel_param *param)
{
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index 7e416e09aa5f..ec6580ece3c0 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -15,6 +15,7 @@ struct ath11k;
struct ath11k_fw_stats;
struct ath11k_fw_dbglog;
struct ath11k_vif;
+struct ath11k_reg_tpc_power_info;

#define PSOC_HOST_MAX_NUM_SS (8)

@@ -327,6 +328,36 @@ enum wmi_tlv_cmd_id {
WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID,
WMI_VDEV_ENCRYPT_DECRYPT_DATA_REQ_CMDID,
WMI_VDEV_ADD_MAC_ADDR_TO_RX_FILTER_CMDID,
+ /** WMI commands related to dbg arp stats */
+ WMI_VDEV_SET_ARP_STAT_CMDID,
+ WMI_VDEV_GET_ARP_STAT_CMDID,
+ /** get tx power for the current vdev */
+ WMI_VDEV_GET_TX_POWER_CMDID,
+ /* limit STA offchannel activity */
+ WMI_VDEV_LIMIT_OFFCHAN_CMDID,
+ /** To set custom software retries per-AC for vdev */
+ WMI_VDEV_SET_CUSTOM_SW_RETRY_TH_CMDID,
+ /** To set chainmask configuration for vdev */
+ WMI_VDEV_CHAINMASK_CONFIG_CMDID,
+ WMI_VDEV_GET_BCN_RECEPTION_STATS_CMDID,
+ /* request LTE-Coex info */
+ WMI_VDEV_GET_MWS_COEX_INFO_CMDID,
+ /** delete all peer (excluding bss peer) */
+ WMI_VDEV_DELETE_ALL_PEER_CMDID,
+ /* To set bss max idle time related parameters */
+ WMI_VDEV_BSS_MAX_IDLE_TIME_CMDID,
+ /** Indicates firmware to trigger Audio sync */
+ WMI_VDEV_AUDIO_SYNC_TRIGGER_CMDID,
+ /** Gives Qtimer value to firmware */
+ WMI_VDEV_AUDIO_SYNC_QTIMER_CMDID,
+ /** Preferred channel list for each vdev */
+ WMI_VDEV_SET_PCL_CMDID,
+ /** VDEV_GET_BIG_DATA_CMD IS DEPRECATED - DO NOT USE */
+ WMI_VDEV_GET_BIG_DATA_CMDID,
+ /** Get per vdev BIG DATA stats phase 2 */
+ WMI_VDEV_GET_BIG_DATA_P2_CMDID,
+ /** set TPC PSD/non-PSD power */
+ WMI_VDEV_SET_TPC_POWER_CMDID,
WMI_PEER_CREATE_CMDID = WMI_TLV_CMD(WMI_GRP_PEER),
WMI_PEER_DELETE_CMDID,
WMI_PEER_FLUSH_TIDS_CMDID,
@@ -1880,6 +1911,8 @@ enum wmi_tlv_tag {
WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD,
WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9,
WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT,
+ WMI_TAG_VDEV_SET_TPC_POWER_CMD = 0x3B5,
+ WMI_TAG_VDEV_CH_POWER_INFO,
WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD = 0x3D8,
WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD,
WMI_TAG_MAX
@@ -3169,6 +3202,31 @@ struct wlan_ssid {
u8 ssid[WLAN_SSID_MAX_LEN];
};

+struct wmi_vdev_ch_power_info {
+ u32 tlv_header;
+ u32 chan_cfreq; /* Channel center frequency (MHz) */
+ /* Unit: dBm, either PSD/EIRP power for this frequency or
+ * incremental for non-PSD BW
+ */
+ u32 tx_power;
+} __packed;
+
+struct wmi_vdev_set_tpc_power_cmd {
+ u32 tlv_header;
+ u32 vdev_id;
+ u32 psd_power; /* Value: 0 or 1, is PSD power or not */
+ u32 eirp_power; /* Maximum EIRP power (dBm units), valid only if power is PSD */
+ u32 power_type_6ghz; /* Type: WMI_6GHZ_REG_TYPE, used for halphy CTL lookup */
+ /* This fixed_param TLV is followed by the below TLVs:
+ * num_pwr_levels of wmi_vdev_ch_power_info
+ * For PSD power, it is the PSD/EIRP power of the frequency (20 MHz chunks).
+ * For non-PSD power, the power values are for 20, 40, and till
+ * BSS BW power levels.
+ * The num_pwr_levels will be checked by sw how many elements present
+ * in the variable-length array.
+ */
+} __packed;
+
#define WMI_IE_BITMAP_SIZE 8

/* prefix used by scan requestor ids on the host */
@@ -6488,4 +6546,7 @@ int ath11k_reg_handle_chan_list(struct ath11k_base *ab,
struct cur_regulatory_info *reg_info,
enum ieee80211_ap_reg_power power_type);
bool ath11k_wmi_supports_6ghz_cc_ext(struct ath11k *ar);
+int ath11k_wmi_send_vdev_set_tpc_power(struct ath11k *ar,
+ u32 vdev_id,
+ struct ath11k_reg_tpc_power_info *param);
#endif
--
2.25.1


2023-12-04 08:42:32

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v8 00/12] wifi: ath11k: add support for 6 GHz station for various modes : LPI, SP and VLP

Baochen Qiang <[email protected]> writes:

> This introduced some new concept:
> power type of AP(STANDARD_POWER_AP, INDOOR_AP, VERY_LOW_POWER_AP)
> power type of STATION(DEFAULT_CLIENT, SUBORDINATE_CLIENT)
> power spectral density(psd)
>
> This patchset is to implement the new rules for 6 GHz band in
> ath11k.
>

[...]

> v7: address review comments per Kalle, Jeff and Aditya. Also rebased to ToT.

Just a small comment that most important is to list here the changes you
made, not who provided reviewed comments. But no need to resend because
of this.

--
https://patchwork.kernel.org/project/linux-wireless/list/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

2023-12-04 15:53:37

by Aditya Kumar Singh

[permalink] [raw]
Subject: Re: [PATCH v8 12/12] wifi: ath11k: discard BSS_CHANGED_TXPOWER when EXT_TPC_REG_SUPPORT for 6 GHz

On 12/4/23 13:43, Baochen Qiang wrote:
> From: Wen Gong <[email protected]>
>
> When station is connected to a 6 GHz AP, it has 2 ways to configure
> the power limit to firmware. The first way is to send 2 WMI commands
> WMI_PDEV_PARAM_TXPOWER_LIMIT2G/WMI_PDEV_PARAM_TXPOWER_LIMIT5G to
> firmware, the second way is to send WMI_VDEV_SET_TPC_POWER_CMDID to
> firmware which include more parameters for power control.
>
> When firmware support SERVICE_EXT_TPC_REG, it means firmware support
> the second way for WMI_VDEV_SET_TPC_POWER_CMDID, then ath11k discard
> BSS_CHANGED_TXPOWER flag from mac80211 which is used to the first way
> for 6 GHz band and select the second way.
>
> Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23
>
> Signed-off-by: Wen Gong <[email protected]>
> Signed-off-by: Baochen Qiang <[email protected]>
> ---
...snip...
> @@ -3596,9 +3608,13 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
> if (changed & BSS_CHANGED_TXPOWER) {
> ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev_id %i txpower %d\n",
> arvif->vdev_id, info->txpower);
> -
> - arvif->txpower = info->txpower;
> - ath11k_mac_txpower_recalc(ar);
> + if (ath11k_mac_supports_station_tpc(ar, arvif, &info->chandef)) {
> + ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
> + "discard tx power, change to set TPC power\n");
> + } else {
> + arvif->txpower = info->txpower;
> + ath11k_mac_txpower_recalc(ar);
> + }

Could you check v6 once? I remember Wen told he would drop this check
and let FW take the min value. If we do like this, then user could not
set his own desired value even if that is well inside the reg limits.


2023-12-06 05:34:40

by Baochen Qiang

[permalink] [raw]
Subject: Re: [PATCH v8 12/12] wifi: ath11k: discard BSS_CHANGED_TXPOWER when EXT_TPC_REG_SUPPORT for 6 GHz



On 12/4/2023 11:53 PM, Aditya Kumar Singh wrote:
> On 12/4/23 13:43, Baochen Qiang wrote:
>> From: Wen Gong <[email protected]>
>>
>> When station is connected to a 6 GHz AP, it has 2 ways to configure
>> the power limit to firmware. The first way is to send 2 WMI commands
>> WMI_PDEV_PARAM_TXPOWER_LIMIT2G/WMI_PDEV_PARAM_TXPOWER_LIMIT5G to
>> firmware, the second way is to send WMI_VDEV_SET_TPC_POWER_CMDID to
>> firmware which include more parameters for power control.
>>
>> When firmware support SERVICE_EXT_TPC_REG, it means firmware support
>> the second way for WMI_VDEV_SET_TPC_POWER_CMDID, then ath11k discard
>> BSS_CHANGED_TXPOWER flag from mac80211 which is used to the first way
>> for 6 GHz band and select the second way.
>>
>> Tested-on: WCN6855 hw2.0 PCI
>> WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23
>>
>> Signed-off-by: Wen Gong <[email protected]>
>> Signed-off-by: Baochen Qiang <[email protected]>
>> ---
> ...snip...
>> @@ -3596,9 +3608,13 @@ static void
>> ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
>>       if (changed & BSS_CHANGED_TXPOWER) {
>>           ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev_id %i txpower %d\n",
>>                  arvif->vdev_id, info->txpower);
>> -
>> -        arvif->txpower = info->txpower;
>> -        ath11k_mac_txpower_recalc(ar);
>> +        if (ath11k_mac_supports_station_tpc(ar, arvif,
>> &info->chandef)) {
>> +            ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
>> +                   "discard tx power, change to set TPC power\n");
>> +        } else {
>> +            arvif->txpower = info->txpower;
>> +            ath11k_mac_txpower_recalc(ar);
>> +        }
>
> Could you check v6 once? I remember Wen told he would drop this check
> and let FW take the min value. If we do like this, then user could not
> set his own desired value even if that is well inside the reg limits.
I did notice this comment in V6, but came out of a different opinion: it
is OK to discard the TX power here, because that will be sent to
firmware using WMI_VDEV_SET_TPC_POWER_CMDID command in another patch.
Please correct me if wrong.

>

2023-12-07 03:32:01

by Aditya Kumar Singh

[permalink] [raw]
Subject: Re: [PATCH v8 12/12] wifi: ath11k: discard BSS_CHANGED_TXPOWER when EXT_TPC_REG_SUPPORT for 6 GHz

On 12/6/23 11:04, Baochen Qiang wrote:
>
>
> On 12/4/2023 11:53 PM, Aditya Kumar Singh wrote:
>> On 12/4/23 13:43, Baochen Qiang wrote:
>>> From: Wen Gong <[email protected]>
>>>
>>> When station is connected to a 6 GHz AP, it has 2 ways to configure
>>> the power limit to firmware. The first way is to send 2 WMI commands
>>> WMI_PDEV_PARAM_TXPOWER_LIMIT2G/WMI_PDEV_PARAM_TXPOWER_LIMIT5G to
>>> firmware, the second way is to send WMI_VDEV_SET_TPC_POWER_CMDID to
>>> firmware which include more parameters for power control.
>>>
>>> When firmware support SERVICE_EXT_TPC_REG, it means firmware support
>>> the second way for WMI_VDEV_SET_TPC_POWER_CMDID, then ath11k discard
>>> BSS_CHANGED_TXPOWER flag from mac80211 which is used to the first way
>>> for 6 GHz band and select the second way.
>>>
>>> Tested-on: WCN6855 hw2.0 PCI
>>> WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23
>>>
>>> Signed-off-by: Wen Gong <[email protected]>
>>> Signed-off-by: Baochen Qiang <[email protected]>
>>> ---
>> ...snip...
>>> @@ -3596,9 +3608,13 @@ static void
>>> ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
>>>       if (changed & BSS_CHANGED_TXPOWER) {
>>>           ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev_id %i txpower %d\n",
>>>                  arvif->vdev_id, info->txpower);
>>> -
>>> -        arvif->txpower = info->txpower;
>>> -        ath11k_mac_txpower_recalc(ar);
>>> +        if (ath11k_mac_supports_station_tpc(ar, arvif,
>>> &info->chandef)) {
>>> +            ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
>>> +                   "discard tx power, change to set TPC power\n");
>>> +        } else {
>>> +            arvif->txpower = info->txpower;
>>> +            ath11k_mac_txpower_recalc(ar);
>>> +        }
>>
>> Could you check v6 once? I remember Wen told he would drop this check
>> and let FW take the min value. If we do like this, then user could not
>> set his own desired value even if that is well inside the reg limits.
> I did notice this comment in V6, but came out of a different opinion: it
> is OK to discard the TX power here, because that will be sent to
> firmware using WMI_VDEV_SET_TPC_POWER_CMDID command in another patch.
> Please correct me if wrong.
Yeah that is correct but applies only during initial bring up. What if
after client gets connected and user still wants to lower power level by
giving command "iw wlanX set txpower fixed 1000" something like this?
This time again it will be ignored but it won't be sent to FW.


2023-12-11 02:26:17

by Baochen Qiang

[permalink] [raw]
Subject: Re: [PATCH v8 12/12] wifi: ath11k: discard BSS_CHANGED_TXPOWER when EXT_TPC_REG_SUPPORT for 6 GHz



On 12/7/2023 11:31 AM, Aditya Kumar Singh wrote:
> On 12/6/23 11:04, Baochen Qiang wrote:
>>
>>
>> On 12/4/2023 11:53 PM, Aditya Kumar Singh wrote:
>>> On 12/4/23 13:43, Baochen Qiang wrote:
>>>> From: Wen Gong <[email protected]>
>>>>
>>>> When station is connected to a 6 GHz AP, it has 2 ways to configure
>>>> the power limit to firmware. The first way is to send 2 WMI commands
>>>> WMI_PDEV_PARAM_TXPOWER_LIMIT2G/WMI_PDEV_PARAM_TXPOWER_LIMIT5G to
>>>> firmware, the second way is to send WMI_VDEV_SET_TPC_POWER_CMDID to
>>>> firmware which include more parameters for power control.
>>>>
>>>> When firmware support SERVICE_EXT_TPC_REG, it means firmware support
>>>> the second way for WMI_VDEV_SET_TPC_POWER_CMDID, then ath11k discard
>>>> BSS_CHANGED_TXPOWER flag from mac80211 which is used to the first way
>>>> for 6 GHz band and select the second way.
>>>>
>>>> Tested-on: WCN6855 hw2.0 PCI
>>>> WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23
>>>>
>>>> Signed-off-by: Wen Gong <[email protected]>
>>>> Signed-off-by: Baochen Qiang <[email protected]>
>>>> ---
>>> ...snip...
>>>> @@ -3596,9 +3608,13 @@ static void
>>>> ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
>>>>       if (changed & BSS_CHANGED_TXPOWER) {
>>>>           ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev_id %i txpower %d\n",
>>>>                  arvif->vdev_id, info->txpower);
>>>> -
>>>> -        arvif->txpower = info->txpower;
>>>> -        ath11k_mac_txpower_recalc(ar);
>>>> +        if (ath11k_mac_supports_station_tpc(ar, arvif,
>>>> &info->chandef)) {
>>>> +            ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
>>>> +                   "discard tx power, change to set TPC power\n");
>>>> +        } else {
>>>> +            arvif->txpower = info->txpower;
>>>> +            ath11k_mac_txpower_recalc(ar);
>>>> +        }
>>>
>>> Could you check v6 once? I remember Wen told he would drop this check
>>> and let FW take the min value. If we do like this, then user could
>>> not set his own desired value even if that is well inside the reg
>>> limits.
>> I did notice this comment in V6, but came out of a different opinion:
>> it is OK to discard the TX power here, because that will be sent to
>> firmware using WMI_VDEV_SET_TPC_POWER_CMDID command in another patch.
>> Please correct me if wrong.
> Yeah that is correct but applies only during initial bring up. What if
> after client gets connected and user still wants to lower power level by
> giving command "iw wlanX set txpower fixed 1000" something like this?
> This time again it will be ignored but it won't be sent to FW.
Exactly, will drop this patch in V9.
>