diff options
Diffstat (limited to 'package/kernel/mac80211/patches/380-0003-ath10k-debugfs-support-to-get-final-TPC-stats-for-10.patch')
-rw-r--r-- | package/kernel/mac80211/patches/380-0003-ath10k-debugfs-support-to-get-final-TPC-stats-for-10.patch | 824 |
1 files changed, 0 insertions, 824 deletions
diff --git a/package/kernel/mac80211/patches/380-0003-ath10k-debugfs-support-to-get-final-TPC-stats-for-10.patch b/package/kernel/mac80211/patches/380-0003-ath10k-debugfs-support-to-get-final-TPC-stats-for-10.patch deleted file mode 100644 index 2e828c4265..0000000000 --- a/package/kernel/mac80211/patches/380-0003-ath10k-debugfs-support-to-get-final-TPC-stats-for-10.patch +++ /dev/null @@ -1,824 +0,0 @@ -From bc64d05220f3e34cf432a166b83c8fff14cd7a3d Mon Sep 17 00:00:00 2001 -From: Maharaja Kennadyrajan <mkenna@codeaurora.org> -Date: Wed, 14 Mar 2018 12:14:08 +0200 -Subject: [PATCH] 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> ---- - drivers/net/wireless/ath/ath10k/core.h | 22 +++ - drivers/net/wireless/ath/ath10k/debug.c | 107 +++++++++++ - drivers/net/wireless/ath/ath10k/debug.h | 10 + - drivers/net/wireless/ath/ath10k/wmi-ops.h | 20 ++ - drivers/net/wireless/ath/ath10k/wmi.c | 308 ++++++++++++++++++++++++++++-- - drivers/net/wireless/ath/ath10k/wmi.h | 66 +++++++ - 6 files changed, 518 insertions(+), 15 deletions(-) - ---- a/drivers/net/wireless/ath/ath10k/core.h -+++ b/drivers/net/wireless/ath/ath10k/core.h -@@ -322,6 +322,27 @@ struct ath10k_tpc_stats { - struct ath10k_tpc_table tpc_table[WMI_TPC_FLAG]; - }; - -+struct ath10k_tpc_table_final { -+ u32 pream_idx[WMI_TPC_FINAL_RATE_MAX]; -+ u8 rate_code[WMI_TPC_FINAL_RATE_MAX]; -+ char tpc_value[WMI_TPC_FINAL_RATE_MAX][WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE]; -+}; -+ -+struct ath10k_tpc_stats_final { -+ u32 reg_domain; -+ u32 chan_freq; -+ u32 phy_mode; -+ u32 twice_antenna_reduction; -+ u32 twice_max_rd_power; -+ s32 twice_antenna_gain; -+ u32 power_limit; -+ u32 num_tx_chain; -+ u32 ctl; -+ u32 rate_max; -+ u8 flag[WMI_TPC_FLAG]; -+ struct ath10k_tpc_table_final tpc_table_final[WMI_TPC_FLAG]; -+}; -+ - struct ath10k_dfs_stats { - u32 phy_errors; - u32 pulses_total; -@@ -482,6 +503,7 @@ struct ath10k_debug { - - /* used for tpc-dump storage, protected by data-lock */ - struct ath10k_tpc_stats *tpc_stats; -+ struct ath10k_tpc_stats_final *tpc_stats_final; - - struct completion tpc_complete; - ---- a/drivers/net/wireless/ath/ath10k/debug.c -+++ b/drivers/net/wireless/ath/ath10k/debug.c -@@ -1737,6 +1737,19 @@ void ath10k_debug_tpc_stats_process(stru - spin_unlock_bh(&ar->data_lock); - } - -+void -+ath10k_debug_tpc_stats_final_process(struct ath10k *ar, -+ struct ath10k_tpc_stats_final *tpc_stats) -+{ -+ spin_lock_bh(&ar->data_lock); -+ -+ kfree(ar->debug.tpc_stats_final); -+ ar->debug.tpc_stats_final = tpc_stats; -+ complete(&ar->debug.tpc_complete); -+ -+ spin_unlock_bh(&ar->data_lock); -+} -+ - static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats, - unsigned int j, char *buf, size_t *len) - { -@@ -2400,6 +2413,95 @@ static const struct file_operations fops - .llseek = default_llseek, - }; - -+static int ath10k_debug_tpc_stats_final_request(struct ath10k *ar) -+{ -+ int ret; -+ unsigned long time_left; -+ -+ lockdep_assert_held(&ar->conf_mutex); -+ -+ reinit_completion(&ar->debug.tpc_complete); -+ -+ ret = ath10k_wmi_pdev_get_tpc_table_cmdid(ar, WMI_TPC_CONFIG_PARAM); -+ if (ret) { -+ ath10k_warn(ar, "failed to request tpc table cmdid: %d\n", ret); -+ return ret; -+ } -+ -+ time_left = wait_for_completion_timeout(&ar->debug.tpc_complete, -+ 1 * HZ); -+ if (time_left == 0) -+ return -ETIMEDOUT; -+ -+ return 0; -+} -+ -+static int ath10k_tpc_stats_final_open(struct inode *inode, struct file *file) -+{ -+ struct ath10k *ar = inode->i_private; -+ void *buf; -+ int ret; -+ -+ mutex_lock(&ar->conf_mutex); -+ -+ if (ar->state != ATH10K_STATE_ON) { -+ ret = -ENETDOWN; -+ goto err_unlock; -+ } -+ -+ buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE); -+ if (!buf) { -+ ret = -ENOMEM; -+ goto err_unlock; -+ } -+ -+ ret = ath10k_debug_tpc_stats_final_request(ar); -+ if (ret) { -+ ath10k_warn(ar, "failed to request tpc stats final: %d\n", -+ ret); -+ goto err_free; -+ } -+ -+ ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf); -+ file->private_data = buf; -+ -+ mutex_unlock(&ar->conf_mutex); -+ return 0; -+ -+err_free: -+ vfree(buf); -+ -+err_unlock: -+ mutex_unlock(&ar->conf_mutex); -+ return ret; -+} -+ -+static int ath10k_tpc_stats_final_release(struct inode *inode, -+ struct file *file) -+{ -+ vfree(file->private_data); -+ -+ return 0; -+} -+ -+static ssize_t ath10k_tpc_stats_final_read(struct file *file, -+ char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ const char *buf = file->private_data; -+ unsigned int len = strlen(buf); -+ -+ return simple_read_from_buffer(user_buf, count, ppos, buf, len); -+} -+ -+static const struct file_operations fops_tpc_stats_final = { -+ .open = ath10k_tpc_stats_final_open, -+ .release = ath10k_tpc_stats_final_release, -+ .read = ath10k_tpc_stats_final_read, -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+}; -+ - int ath10k_debug_create(struct ath10k *ar) - { - ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data)); -@@ -2525,6 +2627,11 @@ int ath10k_debug_register(struct ath10k - debugfs_create_file("fw_checksums", 0400, ar->debug.debugfs_phy, ar, - &fops_fw_checksums); - -+ if (test_bit(WMI_SERVICE_TPC_STATS_FINAL, ar->wmi.svc_map)) -+ debugfs_create_file("tpc_stats_final", 0400, -+ ar->debug.debugfs_phy, ar, -+ &fops_tpc_stats_final); -+ - return 0; - } - ---- a/drivers/net/wireless/ath/ath10k/debug.h -+++ b/drivers/net/wireless/ath/ath10k/debug.h -@@ -84,6 +84,9 @@ void ath10k_debug_unregister(struct ath1 - void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb); - void ath10k_debug_tpc_stats_process(struct ath10k *ar, - struct ath10k_tpc_stats *tpc_stats); -+void -+ath10k_debug_tpc_stats_final_process(struct ath10k *ar, -+ struct ath10k_tpc_stats_final *tpc_stats); - struct ath10k_fw_crash_data * - ath10k_debug_get_new_fw_crash_data(struct ath10k *ar); - -@@ -151,6 +154,13 @@ static inline void ath10k_debug_tpc_stat - { - kfree(tpc_stats); - } -+ -+static inline void -+ath10k_debug_tpc_stats_final_process(struct ath10k *ar, -+ struct ath10k_tpc_stats_final *tpc_stats) -+{ -+ kfree(tpc_stats); -+} - - static inline void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, - int len) ---- a/drivers/net/wireless/ath/ath10k/wmi-ops.h -+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h -@@ -197,6 +197,9 @@ struct wmi_ops { - (struct ath10k *ar, - enum wmi_bss_survey_req_type type); - struct sk_buff *(*gen_echo)(struct ath10k *ar, u32 value); -+ struct sk_buff *(*gen_pdev_get_tpc_table_cmdid)(struct ath10k *ar, -+ u32 param); -+ - }; - - int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); -@@ -1418,4 +1421,21 @@ ath10k_wmi_echo(struct ath10k *ar, u32 v - return ath10k_wmi_cmd_send(ar, skb, wmi->cmd->echo_cmdid); - } - -+static inline int -+ath10k_wmi_pdev_get_tpc_table_cmdid(struct ath10k *ar, u32 param) -+{ -+ struct sk_buff *skb; -+ -+ if (!ar->wmi.ops->gen_pdev_get_tpc_table_cmdid) -+ return -EOPNOTSUPP; -+ -+ skb = ar->wmi.ops->gen_pdev_get_tpc_table_cmdid(ar, param); -+ -+ if (IS_ERR(skb)) -+ return PTR_ERR(skb); -+ -+ return ath10k_wmi_cmd_send(ar, skb, -+ ar->wmi.cmd->pdev_get_tpc_table_cmdid); -+} -+ - #endif ---- a/drivers/net/wireless/ath/ath10k/wmi.c -+++ b/drivers/net/wireless/ath/ath10k/wmi.c -@@ -1,6 +1,7 @@ - /* - * Copyright (c) 2005-2011 Atheros Communications Inc. - * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. -+ * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above -@@ -196,6 +197,7 @@ static struct wmi_cmd_map wmi_cmd_map = - .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED, - .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED, - .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED, -+ .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED, - }; - - /* 10.X WMI cmd track */ -@@ -362,6 +364,7 @@ static struct wmi_cmd_map wmi_10x_cmd_ma - .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED, - .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED, - .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED, -+ .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED, - }; - - /* 10.2.4 WMI cmd track */ -@@ -528,6 +531,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd - .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED, - .pdev_bss_chan_info_request_cmdid = - WMI_10_2_PDEV_BSS_CHAN_INFO_REQUEST_CMDID, -+ .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED, - }; - - /* 10.4 WMI cmd track */ -@@ -1480,6 +1484,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_m - .pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED, - .pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED, - .pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED, -+ .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED, - }; - - static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = { -@@ -4313,19 +4318,11 @@ static void ath10k_tpc_config_disp_table - } - } - --void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb) -+void ath10k_wmi_tpc_config_get_rate_code(u8 *rate_code, u16 *pream_table, -+ u32 num_tx_chain) - { -- u32 i, j, pream_idx, num_tx_chain; -- u8 rate_code[WMI_TPC_RATE_MAX], rate_idx; -- u16 pream_table[WMI_TPC_PREAM_TABLE_MAX]; -- struct wmi_pdev_tpc_config_event *ev; -- struct ath10k_tpc_stats *tpc_stats; -- -- ev = (struct wmi_pdev_tpc_config_event *)skb->data; -- -- tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC); -- if (!tpc_stats) -- return; -+ u32 i, j, pream_idx; -+ u8 rate_idx; - - /* Create the rate code table based on the chains supported */ - rate_idx = 0; -@@ -4349,8 +4346,6 @@ void ath10k_wmi_event_pdev_tpc_config(st - pream_table[pream_idx] = rate_idx; - pream_idx++; - -- num_tx_chain = __le32_to_cpu(ev->num_tx_chain); -- - /* Fill HT20 rate code */ - for (i = 0; i < num_tx_chain; i++) { - for (j = 0; j < 8; j++) { -@@ -4374,7 +4369,7 @@ void ath10k_wmi_event_pdev_tpc_config(st - pream_idx++; - - /* Fill VHT20 rate code */ -- for (i = 0; i < __le32_to_cpu(ev->num_tx_chain); i++) { -+ for (i = 0; i < num_tx_chain; i++) { - for (j = 0; j < 10; j++) { - rate_code[rate_idx] = - ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT); -@@ -4418,6 +4413,26 @@ void ath10k_wmi_event_pdev_tpc_config(st - ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM); - - pream_table[pream_idx] = ATH10K_TPC_PREAM_TABLE_END; -+} -+ -+void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb) -+{ -+ u32 num_tx_chain; -+ u8 rate_code[WMI_TPC_RATE_MAX]; -+ u16 pream_table[WMI_TPC_PREAM_TABLE_MAX]; -+ struct wmi_pdev_tpc_config_event *ev; -+ struct ath10k_tpc_stats *tpc_stats; -+ -+ ev = (struct wmi_pdev_tpc_config_event *)skb->data; -+ -+ tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC); -+ if (!tpc_stats) -+ return; -+ -+ num_tx_chain = __le32_to_cpu(ev->num_tx_chain); -+ -+ ath10k_wmi_tpc_config_get_rate_code(rate_code, pream_table, -+ num_tx_chain); - - tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq); - tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode); -@@ -4457,6 +4472,246 @@ void ath10k_wmi_event_pdev_tpc_config(st - __le32_to_cpu(ev->rate_max)); - } - -+static u8 -+ath10k_wmi_tpc_final_get_rate(struct ath10k *ar, -+ struct wmi_pdev_tpc_final_table_event *ev, -+ u32 rate_idx, u32 num_chains, -+ u32 rate_code, u8 type, u32 pream_idx) -+{ -+ u8 tpc, num_streams, preamble, ch, stm_idx; -+ s8 pow_agcdd, pow_agstbc, pow_agtxbf; -+ int pream; -+ -+ num_streams = ATH10K_HW_NSS(rate_code); -+ preamble = ATH10K_HW_PREAMBLE(rate_code); -+ ch = num_chains - 1; -+ stm_idx = num_streams - 1; -+ pream = -1; -+ -+ if (__le32_to_cpu(ev->chan_freq) <= 2483) { -+ switch (pream_idx) { -+ case WMI_TPC_PREAM_2GHZ_CCK: -+ pream = 0; -+ break; -+ case WMI_TPC_PREAM_2GHZ_OFDM: -+ pream = 1; -+ break; -+ case WMI_TPC_PREAM_2GHZ_HT20: -+ case WMI_TPC_PREAM_2GHZ_VHT20: -+ pream = 2; -+ break; -+ case WMI_TPC_PREAM_2GHZ_HT40: -+ case WMI_TPC_PREAM_2GHZ_VHT40: -+ pream = 3; -+ break; -+ case WMI_TPC_PREAM_2GHZ_VHT80: -+ pream = 4; -+ break; -+ default: -+ pream = -1; -+ break; -+ } -+ } -+ -+ if (__le32_to_cpu(ev->chan_freq) >= 5180) { -+ switch (pream_idx) { -+ case WMI_TPC_PREAM_5GHZ_OFDM: -+ pream = 0; -+ break; -+ case WMI_TPC_PREAM_5GHZ_HT20: -+ case WMI_TPC_PREAM_5GHZ_VHT20: -+ pream = 1; -+ break; -+ case WMI_TPC_PREAM_5GHZ_HT40: -+ case WMI_TPC_PREAM_5GHZ_VHT40: -+ pream = 2; -+ break; -+ case WMI_TPC_PREAM_5GHZ_VHT80: -+ pream = 3; -+ break; -+ case WMI_TPC_PREAM_5GHZ_HTCUP: -+ pream = 4; -+ break; -+ default: -+ pream = -1; -+ break; -+ } -+ } -+ -+ if (pream == 4) -+ tpc = min_t(u8, ev->rates_array[rate_idx], -+ ev->max_reg_allow_pow[ch]); -+ else -+ tpc = min_t(u8, min_t(u8, ev->rates_array[rate_idx], -+ ev->max_reg_allow_pow[ch]), -+ ev->ctl_power_table[0][pream][stm_idx]); -+ -+ if (__le32_to_cpu(ev->num_tx_chain) <= 1) -+ goto out; -+ -+ if (preamble == WMI_RATE_PREAMBLE_CCK) -+ goto out; -+ -+ if (num_chains <= num_streams) -+ goto out; -+ -+ switch (type) { -+ case WMI_TPC_TABLE_TYPE_STBC: -+ pow_agstbc = ev->max_reg_allow_pow_agstbc[ch - 1][stm_idx]; -+ if (pream == 4) -+ tpc = min_t(u8, tpc, pow_agstbc); -+ else -+ tpc = min_t(u8, min_t(u8, tpc, pow_agstbc), -+ ev->ctl_power_table[0][pream][stm_idx]); -+ break; -+ case WMI_TPC_TABLE_TYPE_TXBF: -+ pow_agtxbf = ev->max_reg_allow_pow_agtxbf[ch - 1][stm_idx]; -+ if (pream == 4) -+ tpc = min_t(u8, tpc, pow_agtxbf); -+ else -+ tpc = min_t(u8, min_t(u8, tpc, pow_agtxbf), -+ ev->ctl_power_table[1][pream][stm_idx]); -+ break; -+ case WMI_TPC_TABLE_TYPE_CDD: -+ pow_agcdd = ev->max_reg_allow_pow_agcdd[ch - 1][stm_idx]; -+ if (pream == 4) -+ tpc = min_t(u8, tpc, pow_agcdd); -+ else -+ tpc = min_t(u8, min_t(u8, tpc, pow_agcdd), -+ ev->ctl_power_table[0][pream][stm_idx]); -+ break; -+ default: -+ ath10k_warn(ar, "unknown wmi tpc final table type: %d\n", type); -+ tpc = 0; -+ break; -+ } -+ -+out: -+ return tpc; -+} -+ -+static void -+ath10k_wmi_tpc_stats_final_disp_tables(struct ath10k *ar, -+ struct wmi_pdev_tpc_final_table_event *ev, -+ struct ath10k_tpc_stats_final *tpc_stats, -+ u8 *rate_code, u16 *pream_table, u8 type) -+{ -+ u32 i, j, pream_idx, flags; -+ u8 tpc[WMI_TPC_TX_N_CHAIN]; -+ char tpc_value[WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE]; -+ char buff[WMI_TPC_BUF_SIZE]; -+ -+ flags = __le32_to_cpu(ev->flags); -+ -+ switch (type) { -+ case WMI_TPC_TABLE_TYPE_CDD: -+ if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_CDD)) { -+ ath10k_dbg(ar, ATH10K_DBG_WMI, "CDD not supported\n"); -+ tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG; -+ return; -+ } -+ break; -+ case WMI_TPC_TABLE_TYPE_STBC: -+ if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_STBC)) { -+ ath10k_dbg(ar, ATH10K_DBG_WMI, "STBC not supported\n"); -+ tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG; -+ return; -+ } -+ break; -+ case WMI_TPC_TABLE_TYPE_TXBF: -+ if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_TXBF)) { -+ ath10k_dbg(ar, ATH10K_DBG_WMI, "TXBF not supported\n"); -+ tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG; -+ return; -+ } -+ break; -+ default: -+ ath10k_dbg(ar, ATH10K_DBG_WMI, -+ "invalid table type in wmi tpc event: %d\n", type); -+ return; -+ } -+ -+ pream_idx = 0; -+ for (i = 0; i < __le32_to_cpu(ev->rate_max); i++) { -+ memset(tpc_value, 0, sizeof(tpc_value)); -+ memset(buff, 0, sizeof(buff)); -+ if (i == pream_table[pream_idx]) -+ pream_idx++; -+ -+ for (j = 0; j < WMI_TPC_TX_N_CHAIN; j++) { -+ if (j >= __le32_to_cpu(ev->num_tx_chain)) -+ break; -+ -+ tpc[j] = ath10k_wmi_tpc_final_get_rate(ar, ev, i, j + 1, -+ rate_code[i], -+ type, pream_idx); -+ snprintf(buff, sizeof(buff), "%8d ", tpc[j]); -+ strncat(tpc_value, buff, strlen(buff)); -+ } -+ tpc_stats->tpc_table_final[type].pream_idx[i] = pream_idx; -+ tpc_stats->tpc_table_final[type].rate_code[i] = rate_code[i]; -+ memcpy(tpc_stats->tpc_table_final[type].tpc_value[i], -+ tpc_value, sizeof(tpc_value)); -+ } -+} -+ -+void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb) -+{ -+ u32 num_tx_chain; -+ u8 rate_code[WMI_TPC_FINAL_RATE_MAX]; -+ u16 pream_table[WMI_TPC_PREAM_TABLE_MAX]; -+ struct wmi_pdev_tpc_final_table_event *ev; -+ struct ath10k_tpc_stats_final *tpc_stats; -+ -+ ev = (struct wmi_pdev_tpc_final_table_event *)skb->data; -+ -+ tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC); -+ if (!tpc_stats) -+ return; -+ -+ num_tx_chain = __le32_to_cpu(ev->num_tx_chain); -+ -+ ath10k_wmi_tpc_config_get_rate_code(rate_code, pream_table, -+ num_tx_chain); -+ -+ tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq); -+ tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode); -+ tpc_stats->ctl = __le32_to_cpu(ev->ctl); -+ tpc_stats->reg_domain = __le32_to_cpu(ev->reg_domain); -+ tpc_stats->twice_antenna_gain = a_sle32_to_cpu(ev->twice_antenna_gain); -+ tpc_stats->twice_antenna_reduction = -+ __le32_to_cpu(ev->twice_antenna_reduction); -+ tpc_stats->power_limit = __le32_to_cpu(ev->power_limit); -+ tpc_stats->twice_max_rd_power = __le32_to_cpu(ev->twice_max_rd_power); -+ tpc_stats->num_tx_chain = __le32_to_cpu(ev->num_tx_chain); -+ tpc_stats->rate_max = __le32_to_cpu(ev->rate_max); -+ -+ ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats, -+ rate_code, pream_table, -+ WMI_TPC_TABLE_TYPE_CDD); -+ ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats, -+ rate_code, pream_table, -+ WMI_TPC_TABLE_TYPE_STBC); -+ ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats, -+ rate_code, pream_table, -+ WMI_TPC_TABLE_TYPE_TXBF); -+ -+ ath10k_debug_tpc_stats_final_process(ar, tpc_stats); -+ -+ ath10k_dbg(ar, ATH10K_DBG_WMI, -+ "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", -+ __le32_to_cpu(ev->chan_freq), -+ __le32_to_cpu(ev->phy_mode), -+ __le32_to_cpu(ev->ctl), -+ __le32_to_cpu(ev->reg_domain), -+ a_sle32_to_cpu(ev->twice_antenna_gain), -+ __le32_to_cpu(ev->twice_antenna_reduction), -+ __le32_to_cpu(ev->power_limit), -+ __le32_to_cpu(ev->twice_max_rd_power) / 2, -+ __le32_to_cpu(ev->num_tx_chain), -+ __le32_to_cpu(ev->rate_max)); -+} -+ - static void - ath10k_wmi_handle_tdls_peer_event(struct ath10k *ar, struct sk_buff *skb) - { -@@ -5550,6 +5805,9 @@ static void ath10k_wmi_10_4_op_rx(struct - case WMI_10_4_TDLS_PEER_EVENTID: - ath10k_wmi_handle_tdls_peer_event(ar, skb); - break; -+ case WMI_10_4_PDEV_TPC_TABLE_EVENTID: -+ ath10k_wmi_event_tpc_final_table(ar, skb); -+ break; - default: - ath10k_warn(ar, "Unknown eventid: %d\n", id); - break; -@@ -7990,6 +8248,24 @@ static u32 ath10k_wmi_prepare_peer_qos(u - } - - static struct sk_buff * -+ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid(struct ath10k *ar, u32 param) -+{ -+ struct wmi_pdev_get_tpc_table_cmd *cmd; -+ struct sk_buff *skb; -+ -+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); -+ if (!skb) -+ return ERR_PTR(-ENOMEM); -+ -+ cmd = (struct wmi_pdev_get_tpc_table_cmd *)skb->data; -+ cmd->param = __cpu_to_le32(param); -+ -+ ath10k_dbg(ar, ATH10K_DBG_WMI, -+ "wmi pdev get tpc table param:%d\n", param); -+ return skb; -+} -+ -+static struct sk_buff * - ath10k_wmi_10_4_gen_tdls_peer_update(struct ath10k *ar, - const struct wmi_tdls_peer_update_cmd_arg *arg, - const struct wmi_tdls_peer_capab_arg *cap, -@@ -8430,6 +8706,8 @@ static const struct wmi_ops wmi_10_4_ops - .ext_resource_config = ath10k_wmi_10_4_ext_resource_config, - .gen_update_fw_tdls_state = ath10k_wmi_10_4_gen_update_fw_tdls_state, - .gen_tdls_peer_update = ath10k_wmi_10_4_gen_tdls_peer_update, -+ .gen_pdev_get_tpc_table_cmdid = -+ ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid, - - /* shared with 10.2 */ - .pull_echo_ev = ath10k_wmi_op_pull_echo_ev, ---- a/drivers/net/wireless/ath/ath10k/wmi.h -+++ b/drivers/net/wireless/ath/ath10k/wmi.h -@@ -1,6 +1,7 @@ - /* - * Copyright (c) 2005-2011 Atheros Communications Inc. - * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. -+ * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above -@@ -197,6 +198,9 @@ enum wmi_service { - WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, - WMI_SERVICE_MGMT_TX_WMI, - WMI_SERVICE_TDLS_WIDER_BANDWIDTH, -+ WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, -+ WMI_SERVICE_HOST_DFS_CHECK_SUPPORT, -+ WMI_SERVICE_TPC_STATS_FINAL, - - /* keep last */ - WMI_SERVICE_MAX, -@@ -339,6 +343,9 @@ enum wmi_10_4_service { - WMI_10_4_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE, - WMI_10_4_SERVICE_TDLS_EXPLICIT_MODE_ONLY, - WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH, -+ WMI_10_4_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, -+ WMI_10_4_SERVICE_HOST_DFS_CHECK_SUPPORT, -+ WMI_10_4_SERVICE_TPC_STATS_FINAL, - }; - - static inline char *wmi_service_name(int service_id) -@@ -448,6 +455,9 @@ static inline char *wmi_service_name(int - SVCSTR(WMI_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE); - SVCSTR(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY); - SVCSTR(WMI_SERVICE_TDLS_WIDER_BANDWIDTH); -+ SVCSTR(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS); -+ SVCSTR(WMI_SERVICE_HOST_DFS_CHECK_SUPPORT); -+ SVCSTR(WMI_SERVICE_TPC_STATS_FINAL); - default: - return NULL; - } -@@ -746,6 +756,12 @@ static inline void wmi_10_4_svc_map(cons - WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, len); - SVCMAP(WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH, - WMI_SERVICE_TDLS_WIDER_BANDWIDTH, len); -+ SVCMAP(WMI_10_4_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, -+ WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, len); -+ SVCMAP(WMI_10_4_SERVICE_HOST_DFS_CHECK_SUPPORT, -+ WMI_SERVICE_HOST_DFS_CHECK_SUPPORT, len); -+ SVCMAP(WMI_10_4_SERVICE_TPC_STATS_FINAL, -+ WMI_SERVICE_TPC_STATS_FINAL, len); - } - - #undef SVCMAP -@@ -3992,10 +4008,12 @@ struct wmi_pdev_get_tpc_config_cmd { - - #define WMI_TPC_CONFIG_PARAM 1 - #define WMI_TPC_RATE_MAX 160 -+#define WMI_TPC_FINAL_RATE_MAX 240 - #define WMI_TPC_TX_N_CHAIN 4 - #define WMI_TPC_PREAM_TABLE_MAX 10 - #define WMI_TPC_FLAG 3 - #define WMI_TPC_BUF_SIZE 10 -+#define WMI_TPC_BEAMFORMING 2 - - enum wmi_tpc_table_type { - WMI_TPC_TABLE_TYPE_CDD = 0, -@@ -4038,6 +4056,51 @@ enum wmi_tp_scale { - WMI_TP_SCALE_SIZE = 5, /* max num of enum */ - }; - -+struct wmi_pdev_tpc_final_table_event { -+ __le32 reg_domain; -+ __le32 chan_freq; -+ __le32 phy_mode; -+ __le32 twice_antenna_reduction; -+ __le32 twice_max_rd_power; -+ a_sle32 twice_antenna_gain; -+ __le32 power_limit; -+ __le32 rate_max; -+ __le32 num_tx_chain; -+ __le32 ctl; -+ __le32 flags; -+ s8 max_reg_allow_pow[WMI_TPC_TX_N_CHAIN]; -+ s8 max_reg_allow_pow_agcdd[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN]; -+ s8 max_reg_allow_pow_agstbc[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN]; -+ s8 max_reg_allow_pow_agtxbf[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN]; -+ u8 rates_array[WMI_TPC_FINAL_RATE_MAX]; -+ u8 ctl_power_table[WMI_TPC_BEAMFORMING][WMI_TPC_TX_N_CHAIN] -+ [WMI_TPC_TX_N_CHAIN]; -+} __packed; -+ -+struct wmi_pdev_get_tpc_table_cmd { -+ __le32 param; -+} __packed; -+ -+enum wmi_tpc_pream_2ghz { -+ WMI_TPC_PREAM_2GHZ_CCK = 0, -+ WMI_TPC_PREAM_2GHZ_OFDM, -+ WMI_TPC_PREAM_2GHZ_HT20, -+ WMI_TPC_PREAM_2GHZ_HT40, -+ WMI_TPC_PREAM_2GHZ_VHT20, -+ WMI_TPC_PREAM_2GHZ_VHT40, -+ WMI_TPC_PREAM_2GHZ_VHT80, -+}; -+ -+enum wmi_tpc_pream_5ghz { -+ WMI_TPC_PREAM_5GHZ_OFDM = 1, -+ WMI_TPC_PREAM_5GHZ_HT20, -+ WMI_TPC_PREAM_5GHZ_HT40, -+ WMI_TPC_PREAM_5GHZ_VHT20, -+ WMI_TPC_PREAM_5GHZ_VHT40, -+ WMI_TPC_PREAM_5GHZ_VHT80, -+ WMI_TPC_PREAM_5GHZ_HTCUP, -+}; -+ - struct wmi_pdev_chanlist_update_event { - /* number of channels */ - __le32 num_chan; -@@ -6977,5 +7040,8 @@ void ath10k_wmi_10_4_op_fw_stats_fill(st - int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar, - enum wmi_vdev_subtype subtype); - int ath10k_wmi_barrier(struct ath10k *ar); -+void ath10k_wmi_tpc_config_get_rate_code(u8 *rate_code, u16 *pream_table, -+ u32 num_tx_chain); -+void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb); - - #endif /* _WMI_H_ */ |