aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaharaja Kennadyrajan <mkenna@codeaurora.org>2018-03-14 06:14:08 -0400
committerKalle Valo <kvalo@codeaurora.org>2018-03-26 11:08:56 -0400
commitbc64d05220f3e34cf432a166b83c8fff14cd7a3d (patch)
treea24aa520e64a468251560ded2be042442a95492f
parentcaee728ab761fa1255ff636aec13c87a3d01364d (diff)
ath10k: debugfs support to get final TPC stats for 10.4 variants
Export the final Transmit Power Control (TPC) value, which is the minimum of control power and existing TPC value to user space via a new debugfs file "tpc_stats_final" to help with debugging. It works with the new wmi cmd and event introduced in 10.4 firmware branch. WMI command ID: WMI_PDEV_GET_TPC_TABLE_CMDID WMI event ID: WMI_PDEV_TPC_TABLE_EVENTID cat /sys/kernel/debug/ieee80211/phyX/ath10k/tpc_stats_final $ cat /sys/kernel/debug/ieee80211/phyX/ath10k/tpc_stats_final TPC config for channel 5180 mode 10 CTL = 0x 0 Reg. Domain = 58 Antenna Gain = 0 Reg. Max Antenna Gain = 0 Power Limit = 60 Reg. Max Power = 60 Num tx chains = 2 Num supported rates = 109 ******************* CDD POWER TABLE **************** No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3 0 CCK 0x40 0 0 1 CCK 0x41 0 0 [...] 107 HTCUP 0x 0 46 46 108 HTCUP 0x 0 46 46 ******************* STBC POWER TABLE **************** No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3 0 CCK 0x40 0 0 1 CCK 0x41 0 0 [...] 107 HTCUP 0x 0 46 46 108 HTCUP 0x 0 46 46 *********************************** TXBF not supported ********************************** The existing tpc_stats debugfs file provides the dump which is minimum of target power and regulatory domain. cat /sys/kernel/debug/ieee80211/phyX/ath10k/tpc_stats Hardware_used: QCA4019 Firmware version: firmware-5.bin_10.4-3.0-00209 Signed-off-by: Maharaja Kennadyrajan <mkenna@codeaurora.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h22
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c107
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.h10
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-ops.h20
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c308
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h66
6 files changed, 518 insertions, 15 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index c624b96f8b84..73712c830be7 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -325,6 +325,27 @@ struct ath10k_tpc_stats {
325 struct ath10k_tpc_table tpc_table[WMI_TPC_FLAG]; 325 struct ath10k_tpc_table tpc_table[WMI_TPC_FLAG];
326}; 326};
327 327
328struct ath10k_tpc_table_final {
329 u32 pream_idx[WMI_TPC_FINAL_RATE_MAX];
330 u8 rate_code[WMI_TPC_FINAL_RATE_MAX];
331 char tpc_value[WMI_TPC_FINAL_RATE_MAX][WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE];
332};
333
334struct ath10k_tpc_stats_final {
335 u32 reg_domain;
336 u32 chan_freq;
337 u32 phy_mode;
338 u32 twice_antenna_reduction;
339 u32 twice_max_rd_power;
340 s32 twice_antenna_gain;
341 u32 power_limit;
342 u32 num_tx_chain;
343 u32 ctl;
344 u32 rate_max;
345 u8 flag[WMI_TPC_FLAG];
346 struct ath10k_tpc_table_final tpc_table_final[WMI_TPC_FLAG];
347};
348
328struct ath10k_dfs_stats { 349struct ath10k_dfs_stats {
329 u32 phy_errors; 350 u32 phy_errors;
330 u32 pulses_total; 351 u32 pulses_total;
@@ -530,6 +551,7 @@ struct ath10k_debug {
530 551
531 /* used for tpc-dump storage, protected by data-lock */ 552 /* used for tpc-dump storage, protected by data-lock */
532 struct ath10k_tpc_stats *tpc_stats; 553 struct ath10k_tpc_stats *tpc_stats;
554 struct ath10k_tpc_stats_final *tpc_stats_final;
533 555
534 struct completion tpc_complete; 556 struct completion tpc_complete;
535 557
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 1b9c092d210f..bac832ce1873 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1480,6 +1480,19 @@ void ath10k_debug_tpc_stats_process(struct ath10k *ar,
1480 spin_unlock_bh(&ar->data_lock); 1480 spin_unlock_bh(&ar->data_lock);
1481} 1481}
1482 1482
1483void
1484ath10k_debug_tpc_stats_final_process(struct ath10k *ar,
1485 struct ath10k_tpc_stats_final *tpc_stats)
1486{
1487 spin_lock_bh(&ar->data_lock);
1488
1489 kfree(ar->debug.tpc_stats_final);
1490 ar->debug.tpc_stats_final = tpc_stats;
1491 complete(&ar->debug.tpc_complete);
1492
1493 spin_unlock_bh(&ar->data_lock);
1494}
1495
1483static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats, 1496static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats,
1484 unsigned int j, char *buf, size_t *len) 1497 unsigned int j, char *buf, size_t *len)
1485{ 1498{
@@ -2185,6 +2198,95 @@ static const struct file_operations fops_sta_tid_stats_mask = {
2185 .llseek = default_llseek, 2198 .llseek = default_llseek,
2186}; 2199};
2187 2200
2201static int ath10k_debug_tpc_stats_final_request(struct ath10k *ar)
2202{
2203 int ret;
2204 unsigned long time_left;
2205
2206 lockdep_assert_held(&ar->conf_mutex);
2207
2208 reinit_completion(&ar->debug.tpc_complete);
2209
2210 ret = ath10k_wmi_pdev_get_tpc_table_cmdid(ar, WMI_TPC_CONFIG_PARAM);
2211 if (ret) {
2212 ath10k_warn(ar, "failed to request tpc table cmdid: %d\n", ret);
2213 return ret;
2214 }
2215
2216 time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,
2217 1 * HZ);
2218 if (time_left == 0)
2219 return -ETIMEDOUT;
2220
2221 return 0;
2222}
2223
2224static int ath10k_tpc_stats_final_open(struct inode *inode, struct file *file)
2225{
2226 struct ath10k *ar = inode->i_private;
2227 void *buf;
2228 int ret;
2229
2230 mutex_lock(&ar->conf_mutex);
2231
2232 if (ar->state != ATH10K_STATE_ON) {
2233 ret = -ENETDOWN;
2234 goto err_unlock;
2235 }
2236
2237 buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);
2238 if (!buf) {
2239 ret = -ENOMEM;
2240 goto err_unlock;
2241 }
2242
2243 ret = ath10k_debug_tpc_stats_final_request(ar);
2244 if (ret) {
2245 ath10k_warn(ar, "failed to request tpc stats final: %d\n",
2246 ret);
2247 goto err_free;
2248 }
2249
2250 ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
2251 file->private_data = buf;
2252
2253 mutex_unlock(&ar->conf_mutex);
2254 return 0;
2255
2256err_free:
2257 vfree(buf);
2258
2259err_unlock:
2260 mutex_unlock(&ar->conf_mutex);
2261 return ret;
2262}
2263
2264static int ath10k_tpc_stats_final_release(struct inode *inode,
2265 struct file *file)
2266{
2267 vfree(file->private_data);
2268
2269 return 0;
2270}
2271
2272static ssize_t ath10k_tpc_stats_final_read(struct file *file,
2273 char __user *user_buf,
2274 size_t count, loff_t *ppos)
2275{
2276 const char *buf = file->private_data;
2277 unsigned int len = strlen(buf);
2278
2279 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
2280}
2281
2282static const struct file_operations fops_tpc_stats_final = {
2283 .open = ath10k_tpc_stats_final_open,
2284 .release = ath10k_tpc_stats_final_release,
2285 .read = ath10k_tpc_stats_final_read,
2286 .owner = THIS_MODULE,
2287 .llseek = default_llseek,
2288};
2289
2188int ath10k_debug_create(struct ath10k *ar) 2290int ath10k_debug_create(struct ath10k *ar)
2189{ 2291{
2190 ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN); 2292 ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);
@@ -2305,6 +2407,11 @@ int ath10k_debug_register(struct ath10k *ar)
2305 ar->debug.debugfs_phy, 2407 ar->debug.debugfs_phy,
2306 ar, &fops_sta_tid_stats_mask); 2408 ar, &fops_sta_tid_stats_mask);
2307 2409
2410 if (test_bit(WMI_SERVICE_TPC_STATS_FINAL, ar->wmi.svc_map))
2411 debugfs_create_file("tpc_stats_final", 0400,
2412 ar->debug.debugfs_phy, ar,
2413 &fops_tpc_stats_final);
2414
2308 return 0; 2415 return 0;
2309} 2416}
2310 2417
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 7ebb9b1e7e69..0afca5c106b6 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -102,6 +102,9 @@ void ath10k_debug_unregister(struct ath10k *ar);
102void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb); 102void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb);
103void ath10k_debug_tpc_stats_process(struct ath10k *ar, 103void ath10k_debug_tpc_stats_process(struct ath10k *ar,
104 struct ath10k_tpc_stats *tpc_stats); 104 struct ath10k_tpc_stats *tpc_stats);
105void
106ath10k_debug_tpc_stats_final_process(struct ath10k *ar,
107 struct ath10k_tpc_stats_final *tpc_stats);
105void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len); 108void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len);
106 109
107#define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++) 110#define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
@@ -165,6 +168,13 @@ static inline void ath10k_debug_tpc_stats_process(struct ath10k *ar,
165 kfree(tpc_stats); 168 kfree(tpc_stats);
166} 169}
167 170
171static inline void
172ath10k_debug_tpc_stats_final_process(struct ath10k *ar,
173 struct ath10k_tpc_stats_final *tpc_stats)
174{
175 kfree(tpc_stats);
176}
177
168static inline void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, 178static inline void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer,
169 int len) 179 int len)
170{ 180{
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
index 89d230bc9f6e..c35e45340b4f 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
@@ -201,6 +201,9 @@ struct wmi_ops {
201 (struct ath10k *ar, 201 (struct ath10k *ar,
202 enum wmi_bss_survey_req_type type); 202 enum wmi_bss_survey_req_type type);
203 struct sk_buff *(*gen_echo)(struct ath10k *ar, u32 value); 203 struct sk_buff *(*gen_echo)(struct ath10k *ar, u32 value);
204 struct sk_buff *(*gen_pdev_get_tpc_table_cmdid)(struct ath10k *ar,
205 u32 param);
206
204}; 207};
205 208
206int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); 209int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
@@ -1445,4 +1448,21 @@ ath10k_wmi_echo(struct ath10k *ar, u32 value)
1445 return ath10k_wmi_cmd_send(ar, skb, wmi->cmd->echo_cmdid); 1448 return ath10k_wmi_cmd_send(ar, skb, wmi->cmd->echo_cmdid);
1446} 1449}
1447 1450
1451static inline int
1452ath10k_wmi_pdev_get_tpc_table_cmdid(struct ath10k *ar, u32 param)
1453{
1454 struct sk_buff *skb;
1455
1456 if (!ar->wmi.ops->gen_pdev_get_tpc_table_cmdid)
1457 return -EOPNOTSUPP;
1458
1459 skb = ar->wmi.ops->gen_pdev_get_tpc_table_cmdid(ar, param);
1460
1461 if (IS_ERR(skb))
1462 return PTR_ERR(skb);
1463
1464 return ath10k_wmi_cmd_send(ar, skb,
1465 ar->wmi.cmd->pdev_get_tpc_table_cmdid);
1466}
1467
1448#endif 1468#endif
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 58dc2189ba49..77c6bc671f32 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * Copyright (c) 2005-2011 Atheros Communications Inc. 2 * Copyright (c) 2005-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. 3 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
4 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
4 * 5 *
5 * Permission to use, copy, modify, and/or distribute this software for any 6 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above 7 * purpose with or without fee is hereby granted, provided that the above
@@ -196,6 +197,7 @@ static struct wmi_cmd_map wmi_cmd_map = {
196 .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED, 197 .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED,
197 .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED, 198 .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
198 .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED, 199 .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED,
200 .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
199}; 201};
200 202
201/* 10.X WMI cmd track */ 203/* 10.X WMI cmd track */
@@ -362,6 +364,7 @@ static struct wmi_cmd_map wmi_10x_cmd_map = {
362 .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED, 364 .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED,
363 .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED, 365 .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
364 .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED, 366 .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED,
367 .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
365}; 368};
366 369
367/* 10.2.4 WMI cmd track */ 370/* 10.2.4 WMI cmd track */
@@ -528,6 +531,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd_map = {
528 .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED, 531 .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
529 .pdev_bss_chan_info_request_cmdid = 532 .pdev_bss_chan_info_request_cmdid =
530 WMI_10_2_PDEV_BSS_CHAN_INFO_REQUEST_CMDID, 533 WMI_10_2_PDEV_BSS_CHAN_INFO_REQUEST_CMDID,
534 .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
531}; 535};
532 536
533/* 10.4 WMI cmd track */ 537/* 10.4 WMI cmd track */
@@ -1480,6 +1484,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = {
1480 .pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED, 1484 .pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED,
1481 .pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED, 1485 .pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED,
1482 .pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED, 1486 .pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED,
1487 .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
1483}; 1488};
1484 1489
1485static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = { 1490static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
@@ -4313,19 +4318,11 @@ static void ath10k_tpc_config_disp_tables(struct ath10k *ar,
4313 } 4318 }
4314} 4319}
4315 4320
4316void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb) 4321void ath10k_wmi_tpc_config_get_rate_code(u8 *rate_code, u16 *pream_table,
4322 u32 num_tx_chain)
4317{ 4323{
4318 u32 i, j, pream_idx, num_tx_chain; 4324 u32 i, j, pream_idx;
4319 u8 rate_code[WMI_TPC_RATE_MAX], rate_idx; 4325 u8 rate_idx;
4320 u16 pream_table[WMI_TPC_PREAM_TABLE_MAX];
4321 struct wmi_pdev_tpc_config_event *ev;
4322 struct ath10k_tpc_stats *tpc_stats;
4323
4324 ev = (struct wmi_pdev_tpc_config_event *)skb->data;
4325
4326 tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
4327 if (!tpc_stats)
4328 return;
4329 4326
4330 /* Create the rate code table based on the chains supported */ 4327 /* Create the rate code table based on the chains supported */
4331 rate_idx = 0; 4328 rate_idx = 0;
@@ -4349,8 +4346,6 @@ void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
4349 pream_table[pream_idx] = rate_idx; 4346 pream_table[pream_idx] = rate_idx;
4350 pream_idx++; 4347 pream_idx++;
4351 4348
4352 num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
4353
4354 /* Fill HT20 rate code */ 4349 /* Fill HT20 rate code */
4355 for (i = 0; i < num_tx_chain; i++) { 4350 for (i = 0; i < num_tx_chain; i++) {
4356 for (j = 0; j < 8; j++) { 4351 for (j = 0; j < 8; j++) {
@@ -4374,7 +4369,7 @@ void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
4374 pream_idx++; 4369 pream_idx++;
4375 4370
4376 /* Fill VHT20 rate code */ 4371 /* Fill VHT20 rate code */
4377 for (i = 0; i < __le32_to_cpu(ev->num_tx_chain); i++) { 4372 for (i = 0; i < num_tx_chain; i++) {
4378 for (j = 0; j < 10; j++) { 4373 for (j = 0; j < 10; j++) {
4379 rate_code[rate_idx] = 4374 rate_code[rate_idx] =
4380 ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT); 4375 ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT);
@@ -4418,6 +4413,26 @@ void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
4418 ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM); 4413 ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM);
4419 4414
4420 pream_table[pream_idx] = ATH10K_TPC_PREAM_TABLE_END; 4415 pream_table[pream_idx] = ATH10K_TPC_PREAM_TABLE_END;
4416}
4417
4418void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
4419{
4420 u32 num_tx_chain;
4421 u8 rate_code[WMI_TPC_RATE_MAX];
4422 u16 pream_table[WMI_TPC_PREAM_TABLE_MAX];
4423 struct wmi_pdev_tpc_config_event *ev;
4424 struct ath10k_tpc_stats *tpc_stats;
4425
4426 ev = (struct wmi_pdev_tpc_config_event *)skb->data;
4427
4428 tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
4429 if (!tpc_stats)
4430 return;
4431
4432 num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
4433
4434 ath10k_wmi_tpc_config_get_rate_code(rate_code, pream_table,
4435 num_tx_chain);
4421 4436
4422 tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq); 4437 tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq);
4423 tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode); 4438 tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode);
@@ -4457,6 +4472,246 @@ void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
4457 __le32_to_cpu(ev->rate_max)); 4472 __le32_to_cpu(ev->rate_max));
4458} 4473}
4459 4474
4475static u8
4476ath10k_wmi_tpc_final_get_rate(struct ath10k *ar,
4477 struct wmi_pdev_tpc_final_table_event *ev,
4478 u32 rate_idx, u32 num_chains,
4479 u32 rate_code, u8 type, u32 pream_idx)
4480{
4481 u8 tpc, num_streams, preamble, ch, stm_idx;
4482 s8 pow_agcdd, pow_agstbc, pow_agtxbf;
4483 int pream;
4484
4485 num_streams = ATH10K_HW_NSS(rate_code);
4486 preamble = ATH10K_HW_PREAMBLE(rate_code);
4487 ch = num_chains - 1;
4488 stm_idx = num_streams - 1;
4489 pream = -1;
4490
4491 if (__le32_to_cpu(ev->chan_freq) <= 2483) {
4492 switch (pream_idx) {
4493 case WMI_TPC_PREAM_2GHZ_CCK:
4494 pream = 0;
4495 break;
4496 case WMI_TPC_PREAM_2GHZ_OFDM:
4497 pream = 1;
4498 break;
4499 case WMI_TPC_PREAM_2GHZ_HT20:
4500 case WMI_TPC_PREAM_2GHZ_VHT20:
4501 pream = 2;
4502 break;
4503 case WMI_TPC_PREAM_2GHZ_HT40:
4504 case WMI_TPC_PREAM_2GHZ_VHT40:
4505 pream = 3;
4506 break;
4507 case WMI_TPC_PREAM_2GHZ_VHT80:
4508 pream = 4;
4509 break;
4510 default:
4511 pream = -1;
4512 break;
4513 }
4514 }
4515
4516 if (__le32_to_cpu(ev->chan_freq) >= 5180) {
4517 switch (pream_idx) {
4518 case WMI_TPC_PREAM_5GHZ_OFDM:
4519 pream = 0;
4520 break;
4521 case WMI_TPC_PREAM_5GHZ_HT20:
4522 case WMI_TPC_PREAM_5GHZ_VHT20:
4523 pream = 1;
4524 break;
4525 case WMI_TPC_PREAM_5GHZ_HT40:
4526 case WMI_TPC_PREAM_5GHZ_VHT40:
4527 pream = 2;
4528 break;
4529 case WMI_TPC_PREAM_5GHZ_VHT80:
4530 pream = 3;
4531 break;
4532 case WMI_TPC_PREAM_5GHZ_HTCUP:
4533 pream = 4;
4534 break;
4535 default:
4536 pream = -1;
4537 break;
4538 }
4539 }
4540
4541 if (pream == 4)
4542 tpc = min_t(u8, ev->rates_array[rate_idx],
4543 ev->max_reg_allow_pow[ch]);
4544 else
4545 tpc = min_t(u8, min_t(u8, ev->rates_array[rate_idx],
4546 ev->max_reg_allow_pow[ch]),
4547 ev->ctl_power_table[0][pream][stm_idx]);
4548
4549 if (__le32_to_cpu(ev->num_tx_chain) <= 1)
4550 goto out;
4551
4552 if (preamble == WMI_RATE_PREAMBLE_CCK)
4553 goto out;
4554
4555 if (num_chains <= num_streams)
4556 goto out;
4557
4558 switch (type) {
4559 case WMI_TPC_TABLE_TYPE_STBC:
4560 pow_agstbc = ev->max_reg_allow_pow_agstbc[ch - 1][stm_idx];
4561 if (pream == 4)
4562 tpc = min_t(u8, tpc, pow_agstbc);
4563 else
4564 tpc = min_t(u8, min_t(u8, tpc, pow_agstbc),
4565 ev->ctl_power_table[0][pream][stm_idx]);
4566 break;
4567 case WMI_TPC_TABLE_TYPE_TXBF:
4568 pow_agtxbf = ev->max_reg_allow_pow_agtxbf[ch - 1][stm_idx];
4569 if (pream == 4)
4570 tpc = min_t(u8, tpc, pow_agtxbf);
4571 else
4572 tpc = min_t(u8, min_t(u8, tpc, pow_agtxbf),
4573 ev->ctl_power_table[1][pream][stm_idx]);
4574 break;
4575 case WMI_TPC_TABLE_TYPE_CDD:
4576 pow_agcdd = ev->max_reg_allow_pow_agcdd[ch - 1][stm_idx];
4577 if (pream == 4)
4578 tpc = min_t(u8, tpc, pow_agcdd);
4579 else
4580 tpc = min_t(u8, min_t(u8, tpc, pow_agcdd),
4581 ev->ctl_power_table[0][pream][stm_idx]);
4582 break;
4583 default:
4584 ath10k_warn(ar, "unknown wmi tpc final table type: %d\n", type);
4585 tpc = 0;
4586 break;
4587 }
4588
4589out:
4590 return tpc;
4591}
4592
4593static void
4594ath10k_wmi_tpc_stats_final_disp_tables(struct ath10k *ar,
4595 struct wmi_pdev_tpc_final_table_event *ev,
4596 struct ath10k_tpc_stats_final *tpc_stats,
4597 u8 *rate_code, u16 *pream_table, u8 type)
4598{
4599 u32 i, j, pream_idx, flags;
4600 u8 tpc[WMI_TPC_TX_N_CHAIN];
4601 char tpc_value[WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE];
4602 char buff[WMI_TPC_BUF_SIZE];
4603
4604 flags = __le32_to_cpu(ev->flags);
4605
4606 switch (type) {
4607 case WMI_TPC_TABLE_TYPE_CDD:
4608 if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_CDD)) {
4609 ath10k_dbg(ar, ATH10K_DBG_WMI, "CDD not supported\n");
4610 tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG;
4611 return;
4612 }
4613 break;
4614 case WMI_TPC_TABLE_TYPE_STBC:
4615 if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_STBC)) {
4616 ath10k_dbg(ar, ATH10K_DBG_WMI, "STBC not supported\n");
4617 tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG;
4618 return;
4619 }
4620 break;
4621 case WMI_TPC_TABLE_TYPE_TXBF:
4622 if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_TXBF)) {
4623 ath10k_dbg(ar, ATH10K_DBG_WMI, "TXBF not supported\n");
4624 tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG;
4625 return;
4626 }
4627 break;
4628 default:
4629 ath10k_dbg(ar, ATH10K_DBG_WMI,
4630 "invalid table type in wmi tpc event: %d\n", type);
4631 return;
4632 }
4633
4634 pream_idx = 0;
4635 for (i = 0; i < __le32_to_cpu(ev->rate_max); i++) {
4636 memset(tpc_value, 0, sizeof(tpc_value));
4637 memset(buff, 0, sizeof(buff));
4638 if (i == pream_table[pream_idx])
4639 pream_idx++;
4640
4641 for (j = 0; j < WMI_TPC_TX_N_CHAIN; j++) {
4642 if (j >= __le32_to_cpu(ev->num_tx_chain))
4643 break;
4644
4645 tpc[j] = ath10k_wmi_tpc_final_get_rate(ar, ev, i, j + 1,
4646 rate_code[i],
4647 type, pream_idx);
4648 snprintf(buff, sizeof(buff), "%8d ", tpc[j]);
4649 strncat(tpc_value, buff, strlen(buff));
4650 }
4651 tpc_stats->tpc_table_final[type].pream_idx[i] = pream_idx;
4652 tpc_stats->tpc_table_final[type].rate_code[i] = rate_code[i];
4653 memcpy(tpc_stats->tpc_table_final[type].tpc_value[i],
4654 tpc_value, sizeof(tpc_value));
4655 }
4656}
4657
4658void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb)
4659{
4660 u32 num_tx_chain;
4661 u8 rate_code[WMI_TPC_FINAL_RATE_MAX];
4662 u16 pream_table[WMI_TPC_PREAM_TABLE_MAX];
4663 struct wmi_pdev_tpc_final_table_event *ev;
4664 struct ath10k_tpc_stats_final *tpc_stats;
4665
4666 ev = (struct wmi_pdev_tpc_final_table_event *)skb->data;
4667
4668 tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
4669 if (!tpc_stats)
4670 return;
4671
4672 num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
4673
4674 ath10k_wmi_tpc_config_get_rate_code(rate_code, pream_table,
4675 num_tx_chain);
4676
4677 tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq);
4678 tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode);
4679 tpc_stats->ctl = __le32_to_cpu(ev->ctl);
4680 tpc_stats->reg_domain = __le32_to_cpu(ev->reg_domain);
4681 tpc_stats->twice_antenna_gain = a_sle32_to_cpu(ev->twice_antenna_gain);
4682 tpc_stats->twice_antenna_reduction =
4683 __le32_to_cpu(ev->twice_antenna_reduction);
4684 tpc_stats->power_limit = __le32_to_cpu(ev->power_limit);
4685 tpc_stats->twice_max_rd_power = __le32_to_cpu(ev->twice_max_rd_power);
4686 tpc_stats->num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
4687 tpc_stats->rate_max = __le32_to_cpu(ev->rate_max);
4688
4689 ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats,
4690 rate_code, pream_table,
4691 WMI_TPC_TABLE_TYPE_CDD);
4692 ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats,
4693 rate_code, pream_table,
4694 WMI_TPC_TABLE_TYPE_STBC);
4695 ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats,
4696 rate_code, pream_table,
4697 WMI_TPC_TABLE_TYPE_TXBF);
4698
4699 ath10k_debug_tpc_stats_final_process(ar, tpc_stats);
4700
4701 ath10k_dbg(ar, ATH10K_DBG_WMI,
4702 "wmi event tpc final table channel %d mode %d ctl %d regd %d gain %d %d limit %d max_power %d tx_chanins %d rates %d\n",
4703 __le32_to_cpu(ev->chan_freq),
4704 __le32_to_cpu(ev->phy_mode),
4705 __le32_to_cpu(ev->ctl),
4706 __le32_to_cpu(ev->reg_domain),
4707 a_sle32_to_cpu(ev->twice_antenna_gain),
4708 __le32_to_cpu(ev->twice_antenna_reduction),
4709 __le32_to_cpu(ev->power_limit),
4710 __le32_to_cpu(ev->twice_max_rd_power) / 2,
4711 __le32_to_cpu(ev->num_tx_chain),
4712 __le32_to_cpu(ev->rate_max));
4713}
4714
4460static void 4715static void
4461ath10k_wmi_handle_tdls_peer_event(struct ath10k *ar, struct sk_buff *skb) 4716ath10k_wmi_handle_tdls_peer_event(struct ath10k *ar, struct sk_buff *skb)
4462{ 4717{
@@ -5549,6 +5804,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
5549 case WMI_10_4_TDLS_PEER_EVENTID: 5804 case WMI_10_4_TDLS_PEER_EVENTID:
5550 ath10k_wmi_handle_tdls_peer_event(ar, skb); 5805 ath10k_wmi_handle_tdls_peer_event(ar, skb);
5551 break; 5806 break;
5807 case WMI_10_4_PDEV_TPC_TABLE_EVENTID:
5808 ath10k_wmi_event_tpc_final_table(ar, skb);
5809 break;
5552 default: 5810 default:
5553 ath10k_warn(ar, "Unknown eventid: %d\n", id); 5811 ath10k_warn(ar, "Unknown eventid: %d\n", id);
5554 break; 5812 break;
@@ -7990,6 +8248,24 @@ static u32 ath10k_wmi_prepare_peer_qos(u8 uapsd_queues, u8 sp)
7990} 8248}
7991 8249
7992static struct sk_buff * 8250static struct sk_buff *
8251ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid(struct ath10k *ar, u32 param)
8252{
8253 struct wmi_pdev_get_tpc_table_cmd *cmd;
8254 struct sk_buff *skb;
8255
8256 skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
8257 if (!skb)
8258 return ERR_PTR(-ENOMEM);
8259
8260 cmd = (struct wmi_pdev_get_tpc_table_cmd *)skb->data;
8261 cmd->param = __cpu_to_le32(param);
8262
8263 ath10k_dbg(ar, ATH10K_DBG_WMI,
8264 "wmi pdev get tpc table param:%d\n", param);
8265 return skb;
8266}
8267
8268static struct sk_buff *
7993ath10k_wmi_10_4_gen_tdls_peer_update(struct ath10k *ar, 8269ath10k_wmi_10_4_gen_tdls_peer_update(struct ath10k *ar,
7994 const struct wmi_tdls_peer_update_cmd_arg *arg, 8270 const struct wmi_tdls_peer_update_cmd_arg *arg,
7995 const struct wmi_tdls_peer_capab_arg *cap, 8271 const struct wmi_tdls_peer_capab_arg *cap,
@@ -8430,6 +8706,8 @@ static const struct wmi_ops wmi_10_4_ops = {
8430 .ext_resource_config = ath10k_wmi_10_4_ext_resource_config, 8706 .ext_resource_config = ath10k_wmi_10_4_ext_resource_config,
8431 .gen_update_fw_tdls_state = ath10k_wmi_10_4_gen_update_fw_tdls_state, 8707 .gen_update_fw_tdls_state = ath10k_wmi_10_4_gen_update_fw_tdls_state,
8432 .gen_tdls_peer_update = ath10k_wmi_10_4_gen_tdls_peer_update, 8708 .gen_tdls_peer_update = ath10k_wmi_10_4_gen_tdls_peer_update,
8709 .gen_pdev_get_tpc_table_cmdid =
8710 ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid,
8433 8711
8434 /* shared with 10.2 */ 8712 /* shared with 10.2 */
8435 .pull_echo_ev = ath10k_wmi_op_pull_echo_ev, 8713 .pull_echo_ev = ath10k_wmi_op_pull_echo_ev,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index c7b30ed9015d..c8fc45d8090e 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -1,6 +1,7 @@
1/* 1/*
2 * Copyright (c) 2005-2011 Atheros Communications Inc. 2 * Copyright (c) 2005-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. 3 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
4 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
4 * 5 *
5 * Permission to use, copy, modify, and/or distribute this software for any 6 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above 7 * purpose with or without fee is hereby granted, provided that the above
@@ -197,6 +198,9 @@ enum wmi_service {
197 WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, 198 WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY,
198 WMI_SERVICE_MGMT_TX_WMI, 199 WMI_SERVICE_MGMT_TX_WMI,
199 WMI_SERVICE_TDLS_WIDER_BANDWIDTH, 200 WMI_SERVICE_TDLS_WIDER_BANDWIDTH,
201 WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS,
202 WMI_SERVICE_HOST_DFS_CHECK_SUPPORT,
203 WMI_SERVICE_TPC_STATS_FINAL,
200 204
201 /* keep last */ 205 /* keep last */
202 WMI_SERVICE_MAX, 206 WMI_SERVICE_MAX,
@@ -339,6 +343,9 @@ enum wmi_10_4_service {
339 WMI_10_4_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE, 343 WMI_10_4_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE,
340 WMI_10_4_SERVICE_TDLS_EXPLICIT_MODE_ONLY, 344 WMI_10_4_SERVICE_TDLS_EXPLICIT_MODE_ONLY,
341 WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH, 345 WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH,
346 WMI_10_4_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS,
347 WMI_10_4_SERVICE_HOST_DFS_CHECK_SUPPORT,
348 WMI_10_4_SERVICE_TPC_STATS_FINAL,
342}; 349};
343 350
344static inline char *wmi_service_name(int service_id) 351static inline char *wmi_service_name(int service_id)
@@ -448,6 +455,9 @@ static inline char *wmi_service_name(int service_id)
448 SVCSTR(WMI_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE); 455 SVCSTR(WMI_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE);
449 SVCSTR(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY); 456 SVCSTR(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY);
450 SVCSTR(WMI_SERVICE_TDLS_WIDER_BANDWIDTH); 457 SVCSTR(WMI_SERVICE_TDLS_WIDER_BANDWIDTH);
458 SVCSTR(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS);
459 SVCSTR(WMI_SERVICE_HOST_DFS_CHECK_SUPPORT);
460 SVCSTR(WMI_SERVICE_TPC_STATS_FINAL);
451 default: 461 default:
452 return NULL; 462 return NULL;
453 } 463 }
@@ -746,6 +756,12 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
746 WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, len); 756 WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, len);
747 SVCMAP(WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH, 757 SVCMAP(WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH,
748 WMI_SERVICE_TDLS_WIDER_BANDWIDTH, len); 758 WMI_SERVICE_TDLS_WIDER_BANDWIDTH, len);
759 SVCMAP(WMI_10_4_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS,
760 WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, len);
761 SVCMAP(WMI_10_4_SERVICE_HOST_DFS_CHECK_SUPPORT,
762 WMI_SERVICE_HOST_DFS_CHECK_SUPPORT, len);
763 SVCMAP(WMI_10_4_SERVICE_TPC_STATS_FINAL,
764 WMI_SERVICE_TPC_STATS_FINAL, len);
749} 765}
750 766
751#undef SVCMAP 767#undef SVCMAP
@@ -3993,10 +4009,12 @@ struct wmi_pdev_get_tpc_config_cmd {
3993 4009
3994#define WMI_TPC_CONFIG_PARAM 1 4010#define WMI_TPC_CONFIG_PARAM 1
3995#define WMI_TPC_RATE_MAX 160 4011#define WMI_TPC_RATE_MAX 160
4012#define WMI_TPC_FINAL_RATE_MAX 240
3996#define WMI_TPC_TX_N_CHAIN 4 4013#define WMI_TPC_TX_N_CHAIN 4
3997#define WMI_TPC_PREAM_TABLE_MAX 10 4014#define WMI_TPC_PREAM_TABLE_MAX 10
3998#define WMI_TPC_FLAG 3 4015#define WMI_TPC_FLAG 3
3999#define WMI_TPC_BUF_SIZE 10 4016#define WMI_TPC_BUF_SIZE 10
4017#define WMI_TPC_BEAMFORMING 2
4000 4018
4001enum wmi_tpc_table_type { 4019enum wmi_tpc_table_type {
4002 WMI_TPC_TABLE_TYPE_CDD = 0, 4020 WMI_TPC_TABLE_TYPE_CDD = 0,
@@ -4039,6 +4057,51 @@ enum wmi_tp_scale {
4039 WMI_TP_SCALE_SIZE = 5, /* max num of enum */ 4057 WMI_TP_SCALE_SIZE = 5, /* max num of enum */
4040}; 4058};
4041 4059
4060struct wmi_pdev_tpc_final_table_event {
4061 __le32 reg_domain;
4062 __le32 chan_freq;
4063 __le32 phy_mode;
4064 __le32 twice_antenna_reduction;
4065 __le32 twice_max_rd_power;
4066 a_sle32 twice_antenna_gain;
4067 __le32 power_limit;
4068 __le32 rate_max;
4069 __le32 num_tx_chain;
4070 __le32 ctl;
4071 __le32 flags;
4072 s8 max_reg_allow_pow[WMI_TPC_TX_N_CHAIN];
4073 s8 max_reg_allow_pow_agcdd[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN];
4074 s8 max_reg_allow_pow_agstbc[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN];
4075 s8 max_reg_allow_pow_agtxbf[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN];
4076 u8 rates_array[WMI_TPC_FINAL_RATE_MAX];
4077 u8 ctl_power_table[WMI_TPC_BEAMFORMING][WMI_TPC_TX_N_CHAIN]
4078 [WMI_TPC_TX_N_CHAIN];
4079} __packed;
4080
4081struct wmi_pdev_get_tpc_table_cmd {
4082 __le32 param;
4083} __packed;
4084
4085enum wmi_tpc_pream_2ghz {
4086 WMI_TPC_PREAM_2GHZ_CCK = 0,
4087 WMI_TPC_PREAM_2GHZ_OFDM,
4088 WMI_TPC_PREAM_2GHZ_HT20,
4089 WMI_TPC_PREAM_2GHZ_HT40,
4090 WMI_TPC_PREAM_2GHZ_VHT20,
4091 WMI_TPC_PREAM_2GHZ_VHT40,
4092 WMI_TPC_PREAM_2GHZ_VHT80,
4093};
4094
4095enum wmi_tpc_pream_5ghz {
4096 WMI_TPC_PREAM_5GHZ_OFDM = 1,
4097 WMI_TPC_PREAM_5GHZ_HT20,
4098 WMI_TPC_PREAM_5GHZ_HT40,
4099 WMI_TPC_PREAM_5GHZ_VHT20,
4100 WMI_TPC_PREAM_5GHZ_VHT40,
4101 WMI_TPC_PREAM_5GHZ_VHT80,
4102 WMI_TPC_PREAM_5GHZ_HTCUP,
4103};
4104
4042struct wmi_pdev_chanlist_update_event { 4105struct wmi_pdev_chanlist_update_event {
4043 /* number of channels */ 4106 /* number of channels */
4044 __le32 num_chan; 4107 __le32 num_chan;
@@ -6979,5 +7042,8 @@ void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
6979int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar, 7042int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar,
6980 enum wmi_vdev_subtype subtype); 7043 enum wmi_vdev_subtype subtype);
6981int ath10k_wmi_barrier(struct ath10k *ar); 7044int ath10k_wmi_barrier(struct ath10k *ar);
7045void ath10k_wmi_tpc_config_get_rate_code(u8 *rate_code, u16 *pream_table,
7046 u32 num_tx_chain);
7047void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb);
6982 7048
6983#endif /* _WMI_H_ */ 7049#endif /* _WMI_H_ */