blob: 6d836a26272fe7a7e4ab84c744111552c8d003b7 [file] [log] [blame]
Kalle Valo5e3dd152013-06-12 20:52:10 +03001/*
2 * Copyright (c) 2005-2011 Atheros Communications Inc.
Kalle Valo8b1083d2017-12-22 18:31:13 +02003 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
Kalle Valo5e3dd152013-06-12 20:52:10 +03004 *
5 * 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 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <linux/module.h>
19#include <linux/debugfs.h>
Ben Greear384914b2014-08-25 08:37:32 +030020#include <linux/vmalloc.h>
Kalle Valo3e580442015-11-25 15:38:34 +020021#include <linux/crc32.h>
22#include <linux/firmware.h>
Kalle Valo5e3dd152013-06-12 20:52:10 +030023
24#include "core.h"
25#include "debug.h"
Kalle Valo7869b4f2014-09-24 14:16:58 +030026#include "hif.h"
Michal Kaziord7579d12014-12-03 10:10:54 +020027#include "wmi-ops.h"
Kalle Valo5e3dd152013-06-12 20:52:10 +030028
Kalle Valoa3d135e2013-09-03 11:44:10 +030029/* ms */
30#define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
31
Marty Faltesekf67b107d2016-10-10 19:00:04 +030032#define ATH10K_DEBUG_CAL_DATA_LEN 12064
33
Joe Perchesbabcb3e2014-09-22 10:35:34 -070034void ath10k_info(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +030035{
36 struct va_format vaf = {
37 .fmt = fmt,
38 };
39 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +030040
41 va_start(args, fmt);
42 vaf.va = &args;
Joe Perchesbabcb3e2014-09-22 10:35:34 -070043 dev_info(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +030044 trace_ath10k_log_info(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +030045 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +030046}
47EXPORT_SYMBOL(ath10k_info);
48
Kalle Valo23f591e2015-11-25 15:38:27 +020049void ath10k_debug_print_hwfw_info(struct ath10k *ar)
Kalle Valo8a0c7972014-08-25 08:37:45 +030050{
Kalle Valo7ebf7212016-04-20 19:44:51 +030051 const struct firmware *firmware;
Michal Kazior84e3df62015-08-05 06:55:37 +020052 char fw_features[128] = {};
Michal Kazior8866c722016-03-17 10:52:08 +010053 u32 crc = 0;
Michal Kaziorb27bc5a2015-06-15 14:46:40 +030054
55 ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
56
Kalle Valo8605c022015-11-25 15:38:19 +020057 ath10k_info(ar, "%s target 0x%08x chip_id 0x%08x sub %04x:%04x",
Kalle Valo8a0c7972014-08-25 08:37:45 +030058 ar->hw_params.name,
59 ar->target_version,
60 ar->chip_id,
Kalle Valo8605c022015-11-25 15:38:19 +020061 ar->id.subsystem_vendor, ar->id.subsystem_device);
Kalle Valof0de90b2015-11-25 15:38:12 +020062
Kalle Valof0de90b2015-11-25 15:38:12 +020063 ath10k_info(ar, "kconfig debug %d debugfs %d tracing %d dfs %d testmode %d\n",
Masahiro Yamada97f26452016-08-03 13:45:50 -070064 IS_ENABLED(CONFIG_ATH10K_DEBUG),
65 IS_ENABLED(CONFIG_ATH10K_DEBUGFS),
66 IS_ENABLED(CONFIG_ATH10K_TRACING),
67 IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED),
68 IS_ENABLED(CONFIG_NL80211_TESTMODE));
Kalle Valof0de90b2015-11-25 15:38:12 +020069
Kalle Valo7ebf7212016-04-20 19:44:51 +030070 firmware = ar->normal_mode_fw.fw_file.firmware;
71 if (firmware)
72 crc = crc32_le(0, firmware->data, firmware->size);
Michal Kazior8866c722016-03-17 10:52:08 +010073
Kalle Valo3e580442015-11-25 15:38:34 +020074 ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n",
Kalle Valo23f591e2015-11-25 15:38:27 +020075 ar->hw->wiphy->fw_version,
76 ar->fw_api,
Kalle Valo3e580442015-11-25 15:38:34 +020077 fw_features,
Michal Kazior8866c722016-03-17 10:52:08 +010078 crc);
Kalle Valo23f591e2015-11-25 15:38:27 +020079}
80
81void ath10k_debug_print_board_info(struct ath10k *ar)
82{
83 char boardinfo[100];
84
85 if (ar->id.bmi_ids_valid)
86 scnprintf(boardinfo, sizeof(boardinfo), "%d:%d",
87 ar->id.bmi_chip_id, ar->id.bmi_board_id);
88 else
89 scnprintf(boardinfo, sizeof(boardinfo), "N/A");
90
Kalle Valo3e580442015-11-25 15:38:34 +020091 ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x",
Kalle Valo23f591e2015-11-25 15:38:27 +020092 ar->bd_api,
Kalle Valo3e580442015-11-25 15:38:34 +020093 boardinfo,
Kalle Valo7ebf7212016-04-20 19:44:51 +030094 crc32_le(0, ar->normal_mode_fw.board->data,
95 ar->normal_mode_fw.board->size));
Kalle Valo23f591e2015-11-25 15:38:27 +020096}
97
98void ath10k_debug_print_boot_info(struct ath10k *ar)
99{
Kalle Valof0de90b2015-11-25 15:38:12 +0200100 ath10k_info(ar, "htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d\n",
Kalle Valo8a0c7972014-08-25 08:37:45 +0300101 ar->htt.target_version_major,
Michal Kazior34b28b62014-09-23 10:22:52 +0200102 ar->htt.target_version_minor,
Kalle Valobf3c13a2016-04-20 19:45:33 +0300103 ar->normal_mode_fw.fw_file.wmi_op_version,
Kalle Valo77561f92016-04-20 19:45:47 +0300104 ar->normal_mode_fw.fw_file.htt_op_version,
Michal Kaziorcfd10612014-11-25 15:16:05 +0100105 ath10k_cal_mode_str(ar->cal_mode),
Michal Kaziorb27bc5a2015-06-15 14:46:40 +0300106 ar->max_num_stations,
David Liuccec9032015-07-24 20:25:32 +0300107 test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),
Kalle Valof0de90b2015-11-25 15:38:12 +0200108 !test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags));
Kalle Valo8a0c7972014-08-25 08:37:45 +0300109}
Kalle Valo23f591e2015-11-25 15:38:27 +0200110
111void ath10k_print_driver_info(struct ath10k *ar)
112{
113 ath10k_debug_print_hwfw_info(ar);
114 ath10k_debug_print_board_info(ar);
115 ath10k_debug_print_boot_info(ar);
116}
Kalle Valo8a0c7972014-08-25 08:37:45 +0300117EXPORT_SYMBOL(ath10k_print_driver_info);
118
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700119void ath10k_err(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300120{
121 struct va_format vaf = {
122 .fmt = fmt,
123 };
124 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300125
126 va_start(args, fmt);
127 vaf.va = &args;
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700128 dev_err(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300129 trace_ath10k_log_err(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300130 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300131}
132EXPORT_SYMBOL(ath10k_err);
133
Joe Perchesbabcb3e2014-09-22 10:35:34 -0700134void ath10k_warn(struct ath10k *ar, const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300135{
136 struct va_format vaf = {
137 .fmt = fmt,
138 };
139 va_list args;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300140
141 va_start(args, fmt);
142 vaf.va = &args;
Michal Kazior7aa7a722014-08-25 12:09:38 +0200143 dev_warn_ratelimited(ar->dev, "%pV", &vaf);
Michal Kaziord35a6c12014-09-02 11:00:21 +0300144 trace_ath10k_log_warn(ar, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300145
146 va_end(args);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300147}
148EXPORT_SYMBOL(ath10k_warn);
149
150#ifdef CONFIG_ATH10K_DEBUGFS
151
Kalle Valo5e3dd152013-06-12 20:52:10 +0300152static ssize_t ath10k_read_wmi_services(struct file *file,
153 char __user *user_buf,
154 size_t count, loff_t *ppos)
155{
156 struct ath10k *ar = file->private_data;
157 char *buf;
Tamizh chelvam75e0dde2017-07-03 11:02:36 +0530158 size_t len = 0, buf_len = 8192;
Michal Kaziorcff990c2014-08-04 09:18:33 +0300159 const char *name;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300160 ssize_t ret_cnt;
Michal Kaziorcff990c2014-08-04 09:18:33 +0300161 bool enabled;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300162 int i;
163
164 buf = kzalloc(buf_len, GFP_KERNEL);
165 if (!buf)
166 return -ENOMEM;
167
168 mutex_lock(&ar->conf_mutex);
169
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100170 spin_lock_bh(&ar->data_lock);
Michal Kaziorc4f8c832014-09-04 10:18:32 +0200171 for (i = 0; i < WMI_SERVICE_MAX; i++) {
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100172 enabled = test_bit(i, ar->wmi.svc_map);
Michal Kaziorcff990c2014-08-04 09:18:33 +0300173 name = wmi_service_name(i);
174
175 if (!name) {
176 if (enabled)
177 len += scnprintf(buf + len, buf_len - len,
178 "%-40s %s (bit %d)\n",
179 "unknown", "enabled", i);
180
181 continue;
182 }
Kalle Valo5e3dd152013-06-12 20:52:10 +0300183
184 len += scnprintf(buf + len, buf_len - len,
Michal Kaziorcff990c2014-08-04 09:18:33 +0300185 "%-40s %s\n",
186 name, enabled ? "enabled" : "-");
Kalle Valo5e3dd152013-06-12 20:52:10 +0300187 }
Michal Kazioracfe7ec2014-11-27 10:11:17 +0100188 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300189
190 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
191
192 mutex_unlock(&ar->conf_mutex);
193
194 kfree(buf);
195 return ret_cnt;
196}
197
198static const struct file_operations fops_wmi_services = {
199 .read = ath10k_read_wmi_services,
200 .open = simple_open,
201 .owner = THIS_MODULE,
202 .llseek = default_llseek,
203};
204
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530205static void ath10k_fw_stats_pdevs_free(struct list_head *head)
Michal Kazior53268492014-09-25 12:33:50 +0200206{
207 struct ath10k_fw_stats_pdev *i, *tmp;
208
209 list_for_each_entry_safe(i, tmp, head, list) {
210 list_del(&i->list);
211 kfree(i);
212 }
213}
214
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530215static void ath10k_fw_stats_vdevs_free(struct list_head *head)
Michal Kazior7b6b1532015-02-15 16:50:40 +0200216{
217 struct ath10k_fw_stats_vdev *i, *tmp;
218
219 list_for_each_entry_safe(i, tmp, head, list) {
220 list_del(&i->list);
221 kfree(i);
222 }
223}
224
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530225static void ath10k_fw_stats_peers_free(struct list_head *head)
Michal Kazior53268492014-09-25 12:33:50 +0200226{
227 struct ath10k_fw_stats_peer *i, *tmp;
228
229 list_for_each_entry_safe(i, tmp, head, list) {
230 list_del(&i->list);
231 kfree(i);
232 }
233}
234
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300235static void ath10k_fw_extd_stats_peers_free(struct list_head *head)
236{
237 struct ath10k_fw_extd_stats_peer *i, *tmp;
238
239 list_for_each_entry_safe(i, tmp, head, list) {
240 list_del(&i->list);
241 kfree(i);
242 }
243}
244
Michal Kazior53268492014-09-25 12:33:50 +0200245static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
246{
247 spin_lock_bh(&ar->data_lock);
248 ar->debug.fw_stats_done = false;
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300249 ar->debug.fw_stats.extended = false;
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530250 ath10k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
251 ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
252 ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300253 ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd);
Michal Kazior53268492014-09-25 12:33:50 +0200254 spin_unlock_bh(&ar->data_lock);
255}
256
Michal Kazior60ef4012014-09-25 12:33:48 +0200257void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300258{
Michal Kazior53268492014-09-25 12:33:50 +0200259 struct ath10k_fw_stats stats = {};
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +0530260 bool is_start, is_started, is_end;
Michal Kazior53268492014-09-25 12:33:50 +0200261 size_t num_peers;
Michal Kazior7b6b1532015-02-15 16:50:40 +0200262 size_t num_vdevs;
Michal Kaziord15fb522014-09-25 12:33:47 +0200263 int ret;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300264
Michal Kazior53268492014-09-25 12:33:50 +0200265 INIT_LIST_HEAD(&stats.pdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200266 INIT_LIST_HEAD(&stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200267 INIT_LIST_HEAD(&stats.peers);
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300268 INIT_LIST_HEAD(&stats.peers_extd);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300269
Michal Kazior53268492014-09-25 12:33:50 +0200270 spin_lock_bh(&ar->data_lock);
271 ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
Michal Kaziord15fb522014-09-25 12:33:47 +0200272 if (ret) {
273 ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
Raja Mani5db879a2015-07-09 14:19:43 +0530274 goto free;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300275 }
276
Michal Kazior53268492014-09-25 12:33:50 +0200277 /* Stat data may exceed htc-wmi buffer limit. In such case firmware
278 * splits the stats data and delivers it in a ping-pong fashion of
279 * request cmd-update event.
280 *
281 * However there is no explicit end-of-data. Instead start-of-data is
282 * used as an implicit one. This works as follows:
283 * a) discard stat update events until one with pdev stats is
284 * delivered - this skips session started at end of (b)
285 * b) consume stat update events until another one with pdev stats is
286 * delivered which is treated as end-of-data and is itself discarded
287 */
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +0530288 if (ath10k_peer_stats_enabled(ar))
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300289 ath10k_sta_update_rx_duration(ar, &stats);
Mohammed Shafi Shajakhan74135f52016-02-03 21:07:42 +0530290
Mohammed Shafi Shajakhane0b6ce02016-02-03 21:07:43 +0530291 if (ar->debug.fw_stats_done) {
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +0530292 if (!ath10k_peer_stats_enabled(ar))
Mohammed Shafi Shajakhane0b6ce02016-02-03 21:07:43 +0530293 ath10k_warn(ar, "received unsolicited stats update event\n");
294
Michal Kazior53268492014-09-25 12:33:50 +0200295 goto free;
296 }
297
Manikanta Pubbisettybc6f9ae2015-10-16 15:54:52 +0300298 num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers);
299 num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200300 is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
301 !list_empty(&stats.pdevs));
302 is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
303 !list_empty(&stats.pdevs));
304
305 if (is_start)
306 list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
307
308 if (is_end)
309 ar->debug.fw_stats_done = true;
310
311 is_started = !list_empty(&ar->debug.fw_stats.pdevs);
312
313 if (is_started && !is_end) {
314 if (num_peers >= ATH10K_MAX_NUM_PEER_IDS) {
315 /* Although this is unlikely impose a sane limit to
316 * prevent firmware from DoS-ing the host.
317 */
Mohammed Shafi Shajakhand57e7f22016-01-13 21:16:32 +0530318 ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
Christian Lamparterc1e33302016-12-05 22:52:45 +0100319 ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd);
Michal Kazior53268492014-09-25 12:33:50 +0200320 ath10k_warn(ar, "dropping fw peer stats\n");
321 goto free;
322 }
323
Michal Kazior7b6b1532015-02-15 16:50:40 +0200324 if (num_vdevs >= BITS_PER_LONG) {
Mohammed Shafi Shajakhand57e7f22016-01-13 21:16:32 +0530325 ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200326 ath10k_warn(ar, "dropping fw vdev stats\n");
327 goto free;
328 }
329
Christian Lamparterc1e33302016-12-05 22:52:45 +0100330 if (!list_empty(&stats.peers))
331 list_splice_tail_init(&stats.peers_extd,
332 &ar->debug.fw_stats.peers_extd);
333
Michal Kazior53268492014-09-25 12:33:50 +0200334 list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
Michal Kazior7b6b1532015-02-15 16:50:40 +0200335 list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +0200336 }
337
Michal Kazior60ef4012014-09-25 12:33:48 +0200338 complete(&ar->debug.fw_stats_complete);
Michal Kaziord15fb522014-09-25 12:33:47 +0200339
Michal Kazior53268492014-09-25 12:33:50 +0200340free:
341 /* In some cases lists have been spliced and cleared. Free up
342 * resources if that is not the case.
343 */
Mohammed Shafi Shajakhanb4619ea2016-01-13 21:16:31 +0530344 ath10k_fw_stats_pdevs_free(&stats.pdevs);
345 ath10k_fw_stats_vdevs_free(&stats.vdevs);
346 ath10k_fw_stats_peers_free(&stats.peers);
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +0300347 ath10k_fw_extd_stats_peers_free(&stats.peers_extd);
Michal Kazior53268492014-09-25 12:33:50 +0200348
Michal Kaziord15fb522014-09-25 12:33:47 +0200349 spin_unlock_bh(&ar->data_lock);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300350}
351
Michal Kazior53268492014-09-25 12:33:50 +0200352static int ath10k_debug_fw_stats_request(struct ath10k *ar)
Kalle Valo5e3dd152013-06-12 20:52:10 +0300353{
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300354 unsigned long timeout, time_left;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300355 int ret;
356
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200357 lockdep_assert_held(&ar->conf_mutex);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300358
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300359 timeout = jiffies + msecs_to_jiffies(1 * HZ);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300360
Michal Kazior53268492014-09-25 12:33:50 +0200361 ath10k_debug_fw_stats_reset(ar);
362
363 for (;;) {
364 if (time_after(jiffies, timeout))
365 return -ETIMEDOUT;
366
367 reinit_completion(&ar->debug.fw_stats_complete);
368
Yanbo Li6274cd42015-04-01 22:53:21 +0300369 ret = ath10k_wmi_request_stats(ar, ar->fw_stats_req_mask);
Michal Kazior53268492014-09-25 12:33:50 +0200370 if (ret) {
371 ath10k_warn(ar, "could not request stats (%d)\n", ret);
372 return ret;
373 }
374
Nicholas Mc Guire6e8d5432015-03-30 15:39:20 +0300375 time_left =
376 wait_for_completion_timeout(&ar->debug.fw_stats_complete,
377 1 * HZ);
378 if (!time_left)
Michal Kazior53268492014-09-25 12:33:50 +0200379 return -ETIMEDOUT;
380
381 spin_lock_bh(&ar->data_lock);
382 if (ar->debug.fw_stats_done) {
383 spin_unlock_bh(&ar->data_lock);
384 break;
385 }
386 spin_unlock_bh(&ar->data_lock);
387 }
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200388
389 return 0;
390}
391
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200392static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
393{
394 struct ath10k *ar = inode->i_private;
395 void *buf = NULL;
396 int ret;
Kalle Valo5e3dd152013-06-12 20:52:10 +0300397
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200398 mutex_lock(&ar->conf_mutex);
399
400 if (ar->state != ATH10K_STATE_ON) {
401 ret = -ENETDOWN;
402 goto err_unlock;
403 }
404
405 buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE);
406 if (!buf) {
407 ret = -ENOMEM;
408 goto err_unlock;
409 }
410
Michal Kazior53268492014-09-25 12:33:50 +0200411 ret = ath10k_debug_fw_stats_request(ar);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200412 if (ret) {
413 ath10k_warn(ar, "failed to request fw stats: %d\n", ret);
414 goto err_free;
415 }
416
Manikanta Pubbisettybc6f9ae2015-10-16 15:54:52 +0300417 ret = ath10k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
418 if (ret) {
419 ath10k_warn(ar, "failed to fill fw stats: %d\n", ret);
420 goto err_free;
421 }
422
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200423 file->private_data = buf;
424
Kalle Valo5e3dd152013-06-12 20:52:10 +0300425 mutex_unlock(&ar->conf_mutex);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200426 return 0;
427
428err_free:
429 vfree(buf);
430
431err_unlock:
432 mutex_unlock(&ar->conf_mutex);
433 return ret;
434}
435
436static int ath10k_fw_stats_release(struct inode *inode, struct file *file)
437{
438 vfree(file->private_data);
439
440 return 0;
441}
442
443static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
444 size_t count, loff_t *ppos)
445{
446 const char *buf = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +0200447 size_t len = strlen(buf);
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200448
449 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
Kalle Valo5e3dd152013-06-12 20:52:10 +0300450}
451
452static const struct file_operations fops_fw_stats = {
Michal Kaziorfb2e9c02014-09-25 12:33:49 +0200453 .open = ath10k_fw_stats_open,
454 .release = ath10k_fw_stats_release,
Michal Kazior60ef4012014-09-25 12:33:48 +0200455 .read = ath10k_fw_stats_read,
Kalle Valo5e3dd152013-06-12 20:52:10 +0300456 .owner = THIS_MODULE,
457 .llseek = default_llseek,
458};
459
Ben Greearf51dbe72014-09-29 14:41:46 +0300460static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,
461 char __user *user_buf,
462 size_t count, loff_t *ppos)
463{
464 struct ath10k *ar = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +0200465 int ret;
466 size_t len = 0, buf_len = 500;
Ben Greearf51dbe72014-09-29 14:41:46 +0300467 char *buf;
468
Ben Greearf51dbe72014-09-29 14:41:46 +0300469 buf = kmalloc(buf_len, GFP_KERNEL);
470 if (!buf)
471 return -ENOMEM;
472
473 spin_lock_bh(&ar->data_lock);
474
Ben Greearf51dbe72014-09-29 14:41:46 +0300475 len += scnprintf(buf + len, buf_len - len,
476 "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter);
477 len += scnprintf(buf + len, buf_len - len,
478 "fw_warm_reset_counter\t\t%d\n",
479 ar->stats.fw_warm_reset_counter);
480 len += scnprintf(buf + len, buf_len - len,
481 "fw_cold_reset_counter\t\t%d\n",
482 ar->stats.fw_cold_reset_counter);
483
484 spin_unlock_bh(&ar->data_lock);
485
486 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
487
488 kfree(buf);
489
490 return ret;
491}
492
493static const struct file_operations fops_fw_reset_stats = {
494 .open = simple_open,
495 .read = ath10k_debug_fw_reset_stats_read,
496 .owner = THIS_MODULE,
497 .llseek = default_llseek,
498};
499
Ben Greeard5aebc72014-09-10 18:59:28 +0300500/* This is a clean assert crash in firmware. */
501static int ath10k_debug_fw_assert(struct ath10k *ar)
502{
503 struct wmi_vdev_install_key_cmd *cmd;
504 struct sk_buff *skb;
505
506 skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);
507 if (!skb)
508 return -ENOMEM;
509
510 cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
511 memset(cmd, 0, sizeof(*cmd));
512
513 /* big enough number so that firmware asserts */
514 cmd->vdev_id = __cpu_to_le32(0x7ffe);
515
516 return ath10k_wmi_cmd_send(ar, skb,
517 ar->wmi.cmd->vdev_install_key_cmdid);
518}
519
Michal Kazior278c4a82013-07-22 14:08:51 +0200520static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
521 char __user *user_buf,
522 size_t count, loff_t *ppos)
523{
Kalle Valo75cb96d2014-09-14 12:50:44 +0300524 const char buf[] =
525 "To simulate firmware crash write one of the keywords to this file:\n"
526 "`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
527 "`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
Michal Kazior605cdba2014-10-28 10:34:37 +0100528 "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"
529 "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
Marek Puzyniak8c656992014-03-21 17:46:56 +0200530
Michal Kazior278c4a82013-07-22 14:08:51 +0200531 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
532}
533
Marek Puzyniak8c656992014-03-21 17:46:56 +0200534/* Simulate firmware crash:
535 * 'soft': Call wmi command causing firmware hang. This firmware hang is
536 * recoverable by warm firmware reset.
537 * 'hard': Force firmware crash by setting any vdev parameter for not allowed
538 * vdev id. This is hard firmware crash because it is recoverable only by cold
539 * firmware reset.
540 */
Michal Kazior278c4a82013-07-22 14:08:51 +0200541static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
542 const char __user *user_buf,
543 size_t count, loff_t *ppos)
544{
545 struct ath10k *ar = file->private_data;
Michael Meraa16703a2017-04-24 16:11:57 +0900546 char buf[32] = {0};
547 ssize_t rc;
Michal Kazior278c4a82013-07-22 14:08:51 +0200548 int ret;
549
Michael Meraa16703a2017-04-24 16:11:57 +0900550 /* filter partial writes and invalid commands */
551 if (*ppos != 0 || count >= sizeof(buf) || count == 0)
552 return -EINVAL;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200553
Michael Meraa16703a2017-04-24 16:11:57 +0900554 rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
555 if (rc < 0)
556 return rc;
Michal Kazior278c4a82013-07-22 14:08:51 +0200557
Mohammed Shafi Shajakhanf5e30752016-05-28 11:25:41 +0300558 /* drop the possible '\n' from the end */
Michael Meraa16703a2017-04-24 16:11:57 +0900559 if (buf[*ppos - 1] == '\n')
560 buf[*ppos - 1] = '\0';
Mohammed Shafi Shajakhanf5e30752016-05-28 11:25:41 +0300561
562 mutex_lock(&ar->conf_mutex);
563
Michal Kazior278c4a82013-07-22 14:08:51 +0200564 if (ar->state != ATH10K_STATE_ON &&
565 ar->state != ATH10K_STATE_RESTARTED) {
566 ret = -ENETDOWN;
567 goto exit;
568 }
569
Marek Puzyniak8c656992014-03-21 17:46:56 +0200570 if (!strcmp(buf, "soft")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200571 ath10k_info(ar, "simulating soft firmware crash\n");
Marek Puzyniak8c656992014-03-21 17:46:56 +0200572 ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
573 } else if (!strcmp(buf, "hard")) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200574 ath10k_info(ar, "simulating hard firmware crash\n");
Ben Greear611b3682014-07-25 11:56:40 +0300575 /* 0x7fff is vdev id, and it is always out of range for all
576 * firmware variants in order to force a firmware crash.
577 */
578 ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
Kalle Valo5b07e072014-09-14 12:50:06 +0300579 ar->wmi.vdev_param->rts_threshold,
580 0);
Ben Greeard5aebc72014-09-10 18:59:28 +0300581 } else if (!strcmp(buf, "assert")) {
582 ath10k_info(ar, "simulating firmware assert crash\n");
583 ret = ath10k_debug_fw_assert(ar);
Michal Kazior605cdba2014-10-28 10:34:37 +0100584 } else if (!strcmp(buf, "hw-restart")) {
585 ath10k_info(ar, "user requested hw restart\n");
586 queue_work(ar->workqueue, &ar->restart_work);
587 ret = 0;
Marek Puzyniak8c656992014-03-21 17:46:56 +0200588 } else {
589 ret = -EINVAL;
590 goto exit;
591 }
Michal Kazior278c4a82013-07-22 14:08:51 +0200592
Marek Puzyniak8c656992014-03-21 17:46:56 +0200593 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200594 ath10k_warn(ar, "failed to simulate firmware crash: %d\n", ret);
Marek Puzyniak8c656992014-03-21 17:46:56 +0200595 goto exit;
596 }
597
598 ret = count;
Michal Kazior278c4a82013-07-22 14:08:51 +0200599
600exit:
601 mutex_unlock(&ar->conf_mutex);
602 return ret;
603}
604
605static const struct file_operations fops_simulate_fw_crash = {
606 .read = ath10k_read_simulate_fw_crash,
607 .write = ath10k_write_simulate_fw_crash,
608 .open = simple_open,
609 .owner = THIS_MODULE,
610 .llseek = default_llseek,
611};
612
Kalle Valo763b8cd2013-09-01 11:22:21 +0300613static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf,
614 size_t count, loff_t *ppos)
615{
616 struct ath10k *ar = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +0200617 size_t len;
Kalle Valo763b8cd2013-09-01 11:22:21 +0300618 char buf[50];
619
620 len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id);
621
622 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
623}
624
625static const struct file_operations fops_chip_id = {
626 .read = ath10k_read_chip_id,
627 .open = simple_open,
628 .owner = THIS_MODULE,
629 .llseek = default_llseek,
630};
631
Yanbo Li077a3802014-11-25 12:24:33 +0200632static ssize_t ath10k_reg_addr_read(struct file *file,
633 char __user *user_buf,
634 size_t count, loff_t *ppos)
635{
636 struct ath10k *ar = file->private_data;
637 u8 buf[32];
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +0200638 size_t len = 0;
Yanbo Li077a3802014-11-25 12:24:33 +0200639 u32 reg_addr;
640
641 mutex_lock(&ar->conf_mutex);
642 reg_addr = ar->debug.reg_addr;
643 mutex_unlock(&ar->conf_mutex);
644
645 len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", reg_addr);
646
647 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
648}
649
650static ssize_t ath10k_reg_addr_write(struct file *file,
651 const char __user *user_buf,
652 size_t count, loff_t *ppos)
653{
654 struct ath10k *ar = file->private_data;
655 u32 reg_addr;
656 int ret;
657
658 ret = kstrtou32_from_user(user_buf, count, 0, &reg_addr);
659 if (ret)
660 return ret;
661
662 if (!IS_ALIGNED(reg_addr, 4))
663 return -EFAULT;
664
665 mutex_lock(&ar->conf_mutex);
666 ar->debug.reg_addr = reg_addr;
667 mutex_unlock(&ar->conf_mutex);
668
669 return count;
670}
671
672static const struct file_operations fops_reg_addr = {
673 .read = ath10k_reg_addr_read,
674 .write = ath10k_reg_addr_write,
675 .open = simple_open,
676 .owner = THIS_MODULE,
677 .llseek = default_llseek,
678};
679
680static ssize_t ath10k_reg_value_read(struct file *file,
681 char __user *user_buf,
682 size_t count, loff_t *ppos)
683{
684 struct ath10k *ar = file->private_data;
685 u8 buf[48];
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +0200686 size_t len;
Yanbo Li077a3802014-11-25 12:24:33 +0200687 u32 reg_addr, reg_val;
688 int ret;
689
690 mutex_lock(&ar->conf_mutex);
691
692 if (ar->state != ATH10K_STATE_ON &&
693 ar->state != ATH10K_STATE_UTF) {
694 ret = -ENETDOWN;
695 goto exit;
696 }
697
698 reg_addr = ar->debug.reg_addr;
699
700 reg_val = ath10k_hif_read32(ar, reg_addr);
701 len = scnprintf(buf, sizeof(buf), "0x%08x:0x%08x\n", reg_addr, reg_val);
702
703 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
704
705exit:
706 mutex_unlock(&ar->conf_mutex);
707
708 return ret;
709}
710
711static ssize_t ath10k_reg_value_write(struct file *file,
712 const char __user *user_buf,
713 size_t count, loff_t *ppos)
714{
715 struct ath10k *ar = file->private_data;
716 u32 reg_addr, reg_val;
717 int ret;
718
719 mutex_lock(&ar->conf_mutex);
720
721 if (ar->state != ATH10K_STATE_ON &&
722 ar->state != ATH10K_STATE_UTF) {
723 ret = -ENETDOWN;
724 goto exit;
725 }
726
727 reg_addr = ar->debug.reg_addr;
728
729 ret = kstrtou32_from_user(user_buf, count, 0, &reg_val);
730 if (ret)
731 goto exit;
732
733 ath10k_hif_write32(ar, reg_addr, reg_val);
734
735 ret = count;
736
737exit:
738 mutex_unlock(&ar->conf_mutex);
739
740 return ret;
741}
742
743static const struct file_operations fops_reg_value = {
744 .read = ath10k_reg_value_read,
745 .write = ath10k_reg_value_write,
746 .open = simple_open,
747 .owner = THIS_MODULE,
748 .llseek = default_llseek,
749};
750
Yanbo Li9f65ad22014-11-25 12:24:48 +0200751static ssize_t ath10k_mem_value_read(struct file *file,
752 char __user *user_buf,
753 size_t count, loff_t *ppos)
754{
755 struct ath10k *ar = file->private_data;
756 u8 *buf;
757 int ret;
758
759 if (*ppos < 0)
760 return -EINVAL;
761
762 if (!count)
763 return 0;
764
765 mutex_lock(&ar->conf_mutex);
766
767 buf = vmalloc(count);
768 if (!buf) {
769 ret = -ENOMEM;
770 goto exit;
771 }
772
773 if (ar->state != ATH10K_STATE_ON &&
774 ar->state != ATH10K_STATE_UTF) {
775 ret = -ENETDOWN;
776 goto exit;
777 }
778
779 ret = ath10k_hif_diag_read(ar, *ppos, buf, count);
780 if (ret) {
781 ath10k_warn(ar, "failed to read address 0x%08x via diagnose window fnrom debugfs: %d\n",
782 (u32)(*ppos), ret);
783 goto exit;
784 }
785
786 ret = copy_to_user(user_buf, buf, count);
787 if (ret) {
788 ret = -EFAULT;
789 goto exit;
790 }
791
792 count -= ret;
793 *ppos += count;
794 ret = count;
795
796exit:
797 vfree(buf);
798 mutex_unlock(&ar->conf_mutex);
799
800 return ret;
801}
802
803static ssize_t ath10k_mem_value_write(struct file *file,
804 const char __user *user_buf,
805 size_t count, loff_t *ppos)
806{
807 struct ath10k *ar = file->private_data;
808 u8 *buf;
809 int ret;
810
811 if (*ppos < 0)
812 return -EINVAL;
813
814 if (!count)
815 return 0;
816
817 mutex_lock(&ar->conf_mutex);
818
819 buf = vmalloc(count);
820 if (!buf) {
821 ret = -ENOMEM;
822 goto exit;
823 }
824
825 if (ar->state != ATH10K_STATE_ON &&
826 ar->state != ATH10K_STATE_UTF) {
827 ret = -ENETDOWN;
828 goto exit;
829 }
830
831 ret = copy_from_user(buf, user_buf, count);
832 if (ret) {
833 ret = -EFAULT;
834 goto exit;
835 }
836
837 ret = ath10k_hif_diag_write(ar, *ppos, buf, count);
838 if (ret) {
839 ath10k_warn(ar, "failed to write address 0x%08x via diagnose window from debugfs: %d\n",
840 (u32)(*ppos), ret);
841 goto exit;
842 }
843
844 *ppos += count;
845 ret = count;
846
847exit:
848 vfree(buf);
849 mutex_unlock(&ar->conf_mutex);
850
851 return ret;
852}
853
854static const struct file_operations fops_mem_value = {
855 .read = ath10k_mem_value_read,
856 .write = ath10k_mem_value_write,
857 .open = simple_open,
858 .owner = THIS_MODULE,
859 .llseek = default_llseek,
860};
861
Kalle Valoa3d135e2013-09-03 11:44:10 +0300862static int ath10k_debug_htt_stats_req(struct ath10k *ar)
863{
864 u64 cookie;
865 int ret;
866
867 lockdep_assert_held(&ar->conf_mutex);
868
869 if (ar->debug.htt_stats_mask == 0)
870 /* htt stats are disabled */
871 return 0;
872
873 if (ar->state != ATH10K_STATE_ON)
874 return 0;
875
876 cookie = get_jiffies_64();
877
878 ret = ath10k_htt_h2t_stats_req(&ar->htt, ar->debug.htt_stats_mask,
879 cookie);
880 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +0200881 ath10k_warn(ar, "failed to send htt stats request: %d\n", ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +0300882 return ret;
883 }
884
885 queue_delayed_work(ar->workqueue, &ar->debug.htt_stats_dwork,
886 msecs_to_jiffies(ATH10K_DEBUG_HTT_STATS_INTERVAL));
887
888 return 0;
889}
890
891static void ath10k_debug_htt_stats_dwork(struct work_struct *work)
892{
893 struct ath10k *ar = container_of(work, struct ath10k,
894 debug.htt_stats_dwork.work);
895
896 mutex_lock(&ar->conf_mutex);
897
898 ath10k_debug_htt_stats_req(ar);
899
900 mutex_unlock(&ar->conf_mutex);
901}
902
903static ssize_t ath10k_read_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +0300904 char __user *user_buf,
905 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +0300906{
907 struct ath10k *ar = file->private_data;
908 char buf[32];
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +0200909 size_t len;
Kalle Valoa3d135e2013-09-03 11:44:10 +0300910
911 len = scnprintf(buf, sizeof(buf), "%lu\n", ar->debug.htt_stats_mask);
912
913 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
914}
915
916static ssize_t ath10k_write_htt_stats_mask(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +0300917 const char __user *user_buf,
918 size_t count, loff_t *ppos)
Kalle Valoa3d135e2013-09-03 11:44:10 +0300919{
920 struct ath10k *ar = file->private_data;
921 unsigned long mask;
922 int ret;
923
924 ret = kstrtoul_from_user(user_buf, count, 0, &mask);
925 if (ret)
926 return ret;
927
928 /* max 8 bit masks (for now) */
929 if (mask > 0xff)
930 return -E2BIG;
931
932 mutex_lock(&ar->conf_mutex);
933
934 ar->debug.htt_stats_mask = mask;
935
936 ret = ath10k_debug_htt_stats_req(ar);
937 if (ret)
938 goto out;
939
940 ret = count;
941
942out:
943 mutex_unlock(&ar->conf_mutex);
944
945 return ret;
946}
947
948static const struct file_operations fops_htt_stats_mask = {
949 .read = ath10k_read_htt_stats_mask,
950 .write = ath10k_write_htt_stats_mask,
951 .open = simple_open,
952 .owner = THIS_MODULE,
953 .llseek = default_llseek,
954};
955
Janusz Dziedzicd3856232014-06-02 21:19:46 +0300956static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
957 char __user *user_buf,
958 size_t count, loff_t *ppos)
959{
960 struct ath10k *ar = file->private_data;
961 char buf[64];
Mohammed Shafi Shajakhan81ec3c02015-11-30 22:29:39 +0530962 u8 amsdu, ampdu;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +0200963 size_t len;
Janusz Dziedzicd3856232014-06-02 21:19:46 +0300964
965 mutex_lock(&ar->conf_mutex);
966
David Liuccec9032015-07-24 20:25:32 +0300967 amsdu = ar->htt.max_num_amsdu;
968 ampdu = ar->htt.max_num_ampdu;
Janusz Dziedzicd3856232014-06-02 21:19:46 +0300969 mutex_unlock(&ar->conf_mutex);
970
971 len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
972
973 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
974}
975
976static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
977 const char __user *user_buf,
978 size_t count, loff_t *ppos)
979{
980 struct ath10k *ar = file->private_data;
981 int res;
982 char buf[64];
983 unsigned int amsdu, ampdu;
984
985 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
986
987 /* make sure that buf is null terminated */
988 buf[sizeof(buf) - 1] = 0;
989
990 res = sscanf(buf, "%u %u", &amsdu, &ampdu);
991
992 if (res != 2)
993 return -EINVAL;
994
995 mutex_lock(&ar->conf_mutex);
996
997 res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);
998 if (res)
999 goto out;
1000
1001 res = count;
David Liuccec9032015-07-24 20:25:32 +03001002 ar->htt.max_num_amsdu = amsdu;
1003 ar->htt.max_num_ampdu = ampdu;
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001004
1005out:
1006 mutex_unlock(&ar->conf_mutex);
1007 return res;
1008}
1009
1010static const struct file_operations fops_htt_max_amsdu_ampdu = {
1011 .read = ath10k_read_htt_max_amsdu_ampdu,
1012 .write = ath10k_write_htt_max_amsdu_ampdu,
1013 .open = simple_open,
1014 .owner = THIS_MODULE,
1015 .llseek = default_llseek,
1016};
1017
Kalle Valof118a3e2014-01-03 12:59:31 +02001018static ssize_t ath10k_read_fw_dbglog(struct file *file,
Kalle Valo5b07e072014-09-14 12:50:06 +03001019 char __user *user_buf,
1020 size_t count, loff_t *ppos)
Kalle Valof118a3e2014-01-03 12:59:31 +02001021{
1022 struct ath10k *ar = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001023 size_t len;
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301024 char buf[96];
Kalle Valof118a3e2014-01-03 12:59:31 +02001025
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301026 len = scnprintf(buf, sizeof(buf), "0x%16llx %u\n",
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301027 ar->debug.fw_dbglog_mask, ar->debug.fw_dbglog_level);
Kalle Valof118a3e2014-01-03 12:59:31 +02001028
1029 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1030}
1031
1032static ssize_t ath10k_write_fw_dbglog(struct file *file,
1033 const char __user *user_buf,
1034 size_t count, loff_t *ppos)
1035{
1036 struct ath10k *ar = file->private_data;
Kalle Valof118a3e2014-01-03 12:59:31 +02001037 int ret;
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301038 char buf[96];
1039 unsigned int log_level;
1040 u64 mask;
Kalle Valof118a3e2014-01-03 12:59:31 +02001041
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301042 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
1043
1044 /* make sure that buf is null terminated */
1045 buf[sizeof(buf) - 1] = 0;
1046
Maharaja Kennadyrajanafcbc822016-08-23 15:35:36 +05301047 ret = sscanf(buf, "%llx %u", &mask, &log_level);
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301048
1049 if (!ret)
1050 return -EINVAL;
1051
1052 if (ret == 1)
1053 /* default if user did not specify */
1054 log_level = ATH10K_DBGLOG_LEVEL_WARN;
Kalle Valof118a3e2014-01-03 12:59:31 +02001055
1056 mutex_lock(&ar->conf_mutex);
1057
1058 ar->debug.fw_dbglog_mask = mask;
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301059 ar->debug.fw_dbglog_level = log_level;
Kalle Valof118a3e2014-01-03 12:59:31 +02001060
1061 if (ar->state == ATH10K_STATE_ON) {
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301062 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
1063 ar->debug.fw_dbglog_level);
Kalle Valof118a3e2014-01-03 12:59:31 +02001064 if (ret) {
Michal Kazior7aa7a722014-08-25 12:09:38 +02001065 ath10k_warn(ar, "dbglog cfg failed from debugfs: %d\n",
Kalle Valof118a3e2014-01-03 12:59:31 +02001066 ret);
1067 goto exit;
1068 }
1069 }
1070
1071 ret = count;
1072
1073exit:
1074 mutex_unlock(&ar->conf_mutex);
1075
1076 return ret;
1077}
1078
Ben Greear6cddcc72014-09-29 14:41:46 +03001079/* TODO: Would be nice to always support ethtool stats, would need to
1080 * move the stats storage out of ath10k_debug, or always have ath10k_debug
1081 * struct available..
1082 */
1083
1084/* This generally cooresponds to the debugfs fw_stats file */
1085static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
1086 "tx_pkts_nic",
1087 "tx_bytes_nic",
1088 "rx_pkts_nic",
1089 "rx_bytes_nic",
1090 "d_noise_floor",
1091 "d_cycle_count",
1092 "d_phy_error",
1093 "d_rts_bad",
1094 "d_rts_good",
1095 "d_tx_power", /* in .5 dbM I think */
1096 "d_rx_crc_err", /* fcs_bad */
1097 "d_no_beacon",
1098 "d_tx_mpdus_queued",
1099 "d_tx_msdu_queued",
1100 "d_tx_msdu_dropped",
1101 "d_local_enqued",
1102 "d_local_freed",
1103 "d_tx_ppdu_hw_queued",
1104 "d_tx_ppdu_reaped",
1105 "d_tx_fifo_underrun",
1106 "d_tx_ppdu_abort",
1107 "d_tx_mpdu_requed",
1108 "d_tx_excessive_retries",
1109 "d_tx_hw_rate",
1110 "d_tx_dropped_sw_retries",
1111 "d_tx_illegal_rate",
1112 "d_tx_continuous_xretries",
1113 "d_tx_timeout",
1114 "d_tx_mpdu_txop_limit",
1115 "d_pdev_resets",
1116 "d_rx_mid_ppdu_route_change",
1117 "d_rx_status",
1118 "d_rx_extra_frags_ring0",
1119 "d_rx_extra_frags_ring1",
1120 "d_rx_extra_frags_ring2",
1121 "d_rx_extra_frags_ring3",
1122 "d_rx_msdu_htt",
1123 "d_rx_mpdu_htt",
1124 "d_rx_msdu_stack",
1125 "d_rx_mpdu_stack",
1126 "d_rx_phy_err",
1127 "d_rx_phy_err_drops",
1128 "d_rx_mpdu_errors", /* FCS, MIC, ENC */
1129 "d_fw_crash_count",
1130 "d_fw_warm_reset_count",
1131 "d_fw_cold_reset_count",
1132};
1133
1134#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
1135
1136void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
1137 struct ieee80211_vif *vif,
1138 u32 sset, u8 *data)
1139{
1140 if (sset == ETH_SS_STATS)
1141 memcpy(data, *ath10k_gstrings_stats,
1142 sizeof(ath10k_gstrings_stats));
1143}
1144
1145int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
1146 struct ieee80211_vif *vif, int sset)
1147{
1148 if (sset == ETH_SS_STATS)
1149 return ATH10K_SSTATS_LEN;
1150
1151 return 0;
1152}
1153
1154void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
1155 struct ieee80211_vif *vif,
1156 struct ethtool_stats *stats, u64 *data)
1157{
1158 struct ath10k *ar = hw->priv;
1159 static const struct ath10k_fw_stats_pdev zero_stats = {};
1160 const struct ath10k_fw_stats_pdev *pdev_stats;
1161 int i = 0, ret;
1162
1163 mutex_lock(&ar->conf_mutex);
1164
1165 if (ar->state == ATH10K_STATE_ON) {
1166 ret = ath10k_debug_fw_stats_request(ar);
1167 if (ret) {
1168 /* just print a warning and try to use older results */
1169 ath10k_warn(ar,
1170 "failed to get fw stats for ethtool: %d\n",
1171 ret);
1172 }
1173 }
1174
1175 pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs,
1176 struct ath10k_fw_stats_pdev,
1177 list);
1178 if (!pdev_stats) {
1179 /* no results available so just return zeroes */
1180 pdev_stats = &zero_stats;
1181 }
1182
1183 spin_lock_bh(&ar->data_lock);
1184
1185 data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */
1186 data[i++] = 0; /* tx bytes */
1187 data[i++] = pdev_stats->htt_mpdus;
1188 data[i++] = 0; /* rx bytes */
1189 data[i++] = pdev_stats->ch_noise_floor;
1190 data[i++] = pdev_stats->cycle_count;
1191 data[i++] = pdev_stats->phy_err_count;
1192 data[i++] = pdev_stats->rts_bad;
1193 data[i++] = pdev_stats->rts_good;
1194 data[i++] = pdev_stats->chan_tx_power;
1195 data[i++] = pdev_stats->fcs_bad;
1196 data[i++] = pdev_stats->no_beacons;
1197 data[i++] = pdev_stats->mpdu_enqued;
1198 data[i++] = pdev_stats->msdu_enqued;
1199 data[i++] = pdev_stats->wmm_drop;
1200 data[i++] = pdev_stats->local_enqued;
1201 data[i++] = pdev_stats->local_freed;
1202 data[i++] = pdev_stats->hw_queued;
1203 data[i++] = pdev_stats->hw_reaped;
1204 data[i++] = pdev_stats->underrun;
1205 data[i++] = pdev_stats->tx_abort;
1206 data[i++] = pdev_stats->mpdus_requed;
1207 data[i++] = pdev_stats->tx_ko;
1208 data[i++] = pdev_stats->data_rc;
1209 data[i++] = pdev_stats->sw_retry_failure;
1210 data[i++] = pdev_stats->illgl_rate_phy_err;
1211 data[i++] = pdev_stats->pdev_cont_xretry;
1212 data[i++] = pdev_stats->pdev_tx_timeout;
1213 data[i++] = pdev_stats->txop_ovf;
1214 data[i++] = pdev_stats->pdev_resets;
1215 data[i++] = pdev_stats->mid_ppdu_route_change;
1216 data[i++] = pdev_stats->status_rcvd;
1217 data[i++] = pdev_stats->r0_frags;
1218 data[i++] = pdev_stats->r1_frags;
1219 data[i++] = pdev_stats->r2_frags;
1220 data[i++] = pdev_stats->r3_frags;
1221 data[i++] = pdev_stats->htt_msdus;
1222 data[i++] = pdev_stats->htt_mpdus;
1223 data[i++] = pdev_stats->loc_msdus;
1224 data[i++] = pdev_stats->loc_mpdus;
1225 data[i++] = pdev_stats->phy_errs;
1226 data[i++] = pdev_stats->phy_err_drop;
1227 data[i++] = pdev_stats->mpdu_errs;
1228 data[i++] = ar->stats.fw_crash_counter;
1229 data[i++] = ar->stats.fw_warm_reset_counter;
1230 data[i++] = ar->stats.fw_cold_reset_counter;
1231
1232 spin_unlock_bh(&ar->data_lock);
1233
1234 mutex_unlock(&ar->conf_mutex);
1235
1236 WARN_ON(i != ATH10K_SSTATS_LEN);
1237}
1238
Kalle Valof118a3e2014-01-03 12:59:31 +02001239static const struct file_operations fops_fw_dbglog = {
1240 .read = ath10k_read_fw_dbglog,
1241 .write = ath10k_write_fw_dbglog,
1242 .open = simple_open,
1243 .owner = THIS_MODULE,
1244 .llseek = default_llseek,
1245};
1246
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001247static int ath10k_debug_cal_data_fetch(struct ath10k *ar)
Kalle Valo7869b4f2014-09-24 14:16:58 +03001248{
Kalle Valo7869b4f2014-09-24 14:16:58 +03001249 u32 hi_addr;
1250 __le32 addr;
1251 int ret;
1252
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001253 lockdep_assert_held(&ar->conf_mutex);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001254
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001255 if (WARN_ON(ar->hw_params.cal_data_len > ATH10K_DEBUG_CAL_DATA_LEN))
1256 return -EINVAL;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001257
1258 hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
1259
1260 ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
1261 if (ret) {
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001262 ath10k_warn(ar, "failed to read hi_board_data address: %d\n",
1263 ret);
1264 return ret;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001265 }
1266
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001267 ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), ar->debug.cal_data,
Raja Mani0b8e3c42016-03-18 11:44:22 +02001268 ar->hw_params.cal_data_len);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001269 if (ret) {
1270 ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001271 return ret;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001272 }
1273
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001274 return 0;
1275}
Kalle Valo7869b4f2014-09-24 14:16:58 +03001276
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001277static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
1278{
1279 struct ath10k *ar = inode->i_private;
1280
1281 mutex_lock(&ar->conf_mutex);
1282
1283 if (ar->state == ATH10K_STATE_ON ||
1284 ar->state == ATH10K_STATE_UTF) {
1285 ath10k_debug_cal_data_fetch(ar);
1286 }
1287
1288 file->private_data = ar;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001289 mutex_unlock(&ar->conf_mutex);
1290
1291 return 0;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001292}
1293
1294static ssize_t ath10k_debug_cal_data_read(struct file *file,
1295 char __user *user_buf,
1296 size_t count, loff_t *ppos)
1297{
Raja Mani0b8e3c42016-03-18 11:44:22 +02001298 struct ath10k *ar = file->private_data;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001299
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001300 mutex_lock(&ar->conf_mutex);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001301
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001302 count = simple_read_from_buffer(user_buf, count, ppos,
1303 ar->debug.cal_data,
1304 ar->hw_params.cal_data_len);
Kalle Valo7869b4f2014-09-24 14:16:58 +03001305
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001306 mutex_unlock(&ar->conf_mutex);
1307
1308 return count;
Kalle Valo7869b4f2014-09-24 14:16:58 +03001309}
1310
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05301311static ssize_t ath10k_write_ani_enable(struct file *file,
1312 const char __user *user_buf,
1313 size_t count, loff_t *ppos)
1314{
1315 struct ath10k *ar = file->private_data;
1316 int ret;
1317 u8 enable;
1318
1319 if (kstrtou8_from_user(user_buf, count, 0, &enable))
1320 return -EINVAL;
1321
1322 mutex_lock(&ar->conf_mutex);
1323
1324 if (ar->ani_enabled == enable) {
1325 ret = count;
1326 goto exit;
1327 }
1328
1329 ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->ani_enable,
1330 enable);
1331 if (ret) {
1332 ath10k_warn(ar, "ani_enable failed from debugfs: %d\n", ret);
1333 goto exit;
1334 }
1335 ar->ani_enabled = enable;
1336
1337 ret = count;
1338
1339exit:
1340 mutex_unlock(&ar->conf_mutex);
1341
1342 return ret;
1343}
1344
1345static ssize_t ath10k_read_ani_enable(struct file *file, char __user *user_buf,
1346 size_t count, loff_t *ppos)
1347{
1348 struct ath10k *ar = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001349 size_t len;
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05301350 char buf[32];
1351
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001352 len = scnprintf(buf, sizeof(buf), "%d\n", ar->ani_enabled);
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05301353
1354 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1355}
1356
1357static const struct file_operations fops_ani_enable = {
1358 .read = ath10k_read_ani_enable,
1359 .write = ath10k_write_ani_enable,
1360 .open = simple_open,
1361 .owner = THIS_MODULE,
1362 .llseek = default_llseek,
1363};
1364
Kalle Valo7869b4f2014-09-24 14:16:58 +03001365static const struct file_operations fops_cal_data = {
1366 .open = ath10k_debug_cal_data_open,
1367 .read = ath10k_debug_cal_data_read,
Kalle Valo7869b4f2014-09-24 14:16:58 +03001368 .owner = THIS_MODULE,
1369 .llseek = default_llseek,
1370};
1371
Peter Oha7bd3e92014-12-02 13:07:14 +02001372static ssize_t ath10k_read_nf_cal_period(struct file *file,
1373 char __user *user_buf,
1374 size_t count, loff_t *ppos)
1375{
1376 struct ath10k *ar = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001377 size_t len;
Peter Oha7bd3e92014-12-02 13:07:14 +02001378 char buf[32];
1379
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001380 len = scnprintf(buf, sizeof(buf), "%d\n", ar->debug.nf_cal_period);
Peter Oha7bd3e92014-12-02 13:07:14 +02001381
1382 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1383}
1384
1385static ssize_t ath10k_write_nf_cal_period(struct file *file,
1386 const char __user *user_buf,
1387 size_t count, loff_t *ppos)
1388{
1389 struct ath10k *ar = file->private_data;
1390 unsigned long period;
1391 int ret;
1392
1393 ret = kstrtoul_from_user(user_buf, count, 0, &period);
1394 if (ret)
1395 return ret;
1396
1397 if (period > WMI_PDEV_PARAM_CAL_PERIOD_MAX)
1398 return -EINVAL;
1399
1400 /* there's no way to switch back to the firmware default */
1401 if (period == 0)
1402 return -EINVAL;
1403
1404 mutex_lock(&ar->conf_mutex);
1405
1406 ar->debug.nf_cal_period = period;
1407
1408 if (ar->state != ATH10K_STATE_ON) {
1409 /* firmware is not running, nothing else to do */
1410 ret = count;
1411 goto exit;
1412 }
1413
1414 ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->cal_period,
1415 ar->debug.nf_cal_period);
1416 if (ret) {
1417 ath10k_warn(ar, "cal period cfg failed from debugfs: %d\n",
1418 ret);
1419 goto exit;
1420 }
1421
1422 ret = count;
1423
1424exit:
1425 mutex_unlock(&ar->conf_mutex);
1426
1427 return ret;
1428}
1429
1430static const struct file_operations fops_nf_cal_period = {
1431 .read = ath10k_read_nf_cal_period,
1432 .write = ath10k_write_nf_cal_period,
1433 .open = simple_open,
1434 .owner = THIS_MODULE,
1435 .llseek = default_llseek,
1436};
1437
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001438#define ATH10K_TPC_CONFIG_BUF_SIZE (1024 * 1024)
1439
1440static int ath10k_debug_tpc_stats_request(struct ath10k *ar)
1441{
1442 int ret;
1443 unsigned long time_left;
1444
1445 lockdep_assert_held(&ar->conf_mutex);
1446
1447 reinit_completion(&ar->debug.tpc_complete);
1448
1449 ret = ath10k_wmi_pdev_get_tpc_config(ar, WMI_TPC_CONFIG_PARAM);
1450 if (ret) {
1451 ath10k_warn(ar, "failed to request tpc config: %d\n", ret);
1452 return ret;
1453 }
1454
1455 time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,
1456 1 * HZ);
1457 if (time_left == 0)
1458 return -ETIMEDOUT;
1459
1460 return 0;
1461}
1462
1463void ath10k_debug_tpc_stats_process(struct ath10k *ar,
1464 struct ath10k_tpc_stats *tpc_stats)
1465{
1466 spin_lock_bh(&ar->data_lock);
1467
1468 kfree(ar->debug.tpc_stats);
1469 ar->debug.tpc_stats = tpc_stats;
1470 complete(&ar->debug.tpc_complete);
1471
1472 spin_unlock_bh(&ar->data_lock);
1473}
1474
1475static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats,
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001476 unsigned int j, char *buf, size_t *len)
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001477{
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001478 int i;
1479 size_t buf_len;
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001480 static const char table_str[][5] = { "CDD",
1481 "STBC",
1482 "TXBF" };
1483 static const char pream_str[][6] = { "CCK",
1484 "OFDM",
1485 "HT20",
1486 "HT40",
1487 "VHT20",
1488 "VHT40",
1489 "VHT80",
1490 "HTCUP" };
1491
1492 buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
1493 *len += scnprintf(buf + *len, buf_len - *len,
1494 "********************************\n");
1495 *len += scnprintf(buf + *len, buf_len - *len,
1496 "******************* %s POWER TABLE ****************\n",
1497 table_str[j]);
1498 *len += scnprintf(buf + *len, buf_len - *len,
1499 "********************************\n");
1500 *len += scnprintf(buf + *len, buf_len - *len,
1501 "No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3\n");
1502
1503 for (i = 0; i < tpc_stats->rate_max; i++) {
1504 *len += scnprintf(buf + *len, buf_len - *len,
1505 "%8d %s 0x%2x %s\n", i,
1506 pream_str[tpc_stats->tpc_table[j].pream_idx[i]],
1507 tpc_stats->tpc_table[j].rate_code[i],
1508 tpc_stats->tpc_table[j].tpc_value[i]);
1509 }
1510
1511 *len += scnprintf(buf + *len, buf_len - *len,
1512 "***********************************\n");
1513}
1514
1515static void ath10k_tpc_stats_fill(struct ath10k *ar,
1516 struct ath10k_tpc_stats *tpc_stats,
1517 char *buf)
1518{
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001519 int j;
1520 size_t len, buf_len;
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001521
1522 len = 0;
1523 buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
1524
1525 spin_lock_bh(&ar->data_lock);
1526
1527 if (!tpc_stats) {
1528 ath10k_warn(ar, "failed to get tpc stats\n");
1529 goto unlock;
1530 }
1531
1532 len += scnprintf(buf + len, buf_len - len, "\n");
1533 len += scnprintf(buf + len, buf_len - len,
1534 "*************************************\n");
1535 len += scnprintf(buf + len, buf_len - len,
1536 "TPC config for channel %4d mode %d\n",
1537 tpc_stats->chan_freq,
1538 tpc_stats->phy_mode);
1539 len += scnprintf(buf + len, buf_len - len,
1540 "*************************************\n");
1541 len += scnprintf(buf + len, buf_len - len,
1542 "CTL = 0x%2x Reg. Domain = %2d\n",
1543 tpc_stats->ctl,
1544 tpc_stats->reg_domain);
1545 len += scnprintf(buf + len, buf_len - len,
1546 "Antenna Gain = %2d Reg. Max Antenna Gain = %2d\n",
1547 tpc_stats->twice_antenna_gain,
1548 tpc_stats->twice_antenna_reduction);
1549 len += scnprintf(buf + len, buf_len - len,
1550 "Power Limit = %2d Reg. Max Power = %2d\n",
1551 tpc_stats->power_limit,
1552 tpc_stats->twice_max_rd_power / 2);
1553 len += scnprintf(buf + len, buf_len - len,
1554 "Num tx chains = %2d Num supported rates = %2d\n",
1555 tpc_stats->num_tx_chain,
1556 tpc_stats->rate_max);
1557
Maharaja Kennadyrajane871fb62017-03-31 17:39:40 +05301558 for (j = 0; j < WMI_TPC_FLAG; j++) {
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001559 switch (j) {
1560 case WMI_TPC_TABLE_TYPE_CDD:
1561 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1562 len += scnprintf(buf + len, buf_len - len,
1563 "CDD not supported\n");
1564 break;
1565 }
1566
1567 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1568 break;
1569 case WMI_TPC_TABLE_TYPE_STBC:
1570 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1571 len += scnprintf(buf + len, buf_len - len,
1572 "STBC not supported\n");
1573 break;
1574 }
1575
1576 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1577 break;
1578 case WMI_TPC_TABLE_TYPE_TXBF:
1579 if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {
1580 len += scnprintf(buf + len, buf_len - len,
1581 "TXBF not supported\n***************************\n");
1582 break;
1583 }
1584
1585 ath10k_tpc_stats_print(tpc_stats, j, buf, &len);
1586 break;
1587 default:
1588 len += scnprintf(buf + len, buf_len - len,
1589 "Invalid Type\n");
1590 break;
1591 }
1592 }
1593
1594unlock:
1595 spin_unlock_bh(&ar->data_lock);
1596
1597 if (len >= buf_len)
1598 buf[len - 1] = 0;
1599 else
1600 buf[len] = 0;
1601}
1602
1603static int ath10k_tpc_stats_open(struct inode *inode, struct file *file)
1604{
1605 struct ath10k *ar = inode->i_private;
1606 void *buf = NULL;
1607 int ret;
1608
1609 mutex_lock(&ar->conf_mutex);
1610
1611 if (ar->state != ATH10K_STATE_ON) {
1612 ret = -ENETDOWN;
1613 goto err_unlock;
1614 }
1615
1616 buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);
1617 if (!buf) {
1618 ret = -ENOMEM;
1619 goto err_unlock;
1620 }
1621
1622 ret = ath10k_debug_tpc_stats_request(ar);
1623 if (ret) {
1624 ath10k_warn(ar, "failed to request tpc config stats: %d\n",
1625 ret);
1626 goto err_free;
1627 }
1628
1629 ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
1630 file->private_data = buf;
1631
1632 mutex_unlock(&ar->conf_mutex);
1633 return 0;
1634
1635err_free:
1636 vfree(buf);
1637
1638err_unlock:
1639 mutex_unlock(&ar->conf_mutex);
1640 return ret;
1641}
1642
1643static int ath10k_tpc_stats_release(struct inode *inode, struct file *file)
1644{
1645 vfree(file->private_data);
1646
1647 return 0;
1648}
1649
1650static ssize_t ath10k_tpc_stats_read(struct file *file, char __user *user_buf,
1651 size_t count, loff_t *ppos)
1652{
1653 const char *buf = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02001654 size_t len = strlen(buf);
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03001655
1656 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1657}
1658
1659static const struct file_operations fops_tpc_stats = {
1660 .open = ath10k_tpc_stats_open,
1661 .release = ath10k_tpc_stats_release,
1662 .read = ath10k_tpc_stats_read,
1663 .owner = THIS_MODULE,
1664 .llseek = default_llseek,
1665};
1666
Kalle Valodb66ea02013-09-03 11:44:03 +03001667int ath10k_debug_start(struct ath10k *ar)
1668{
Kalle Valoa3d135e2013-09-03 11:44:10 +03001669 int ret;
1670
Kalle Valo60631c52013-10-08 21:45:25 +03001671 lockdep_assert_held(&ar->conf_mutex);
1672
Kalle Valoa3d135e2013-09-03 11:44:10 +03001673 ret = ath10k_debug_htt_stats_req(ar);
1674 if (ret)
1675 /* continue normally anyway, this isn't serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001676 ath10k_warn(ar, "failed to start htt stats workqueue: %d\n",
1677 ret);
Kalle Valoa3d135e2013-09-03 11:44:10 +03001678
Kalle Valof118a3e2014-01-03 12:59:31 +02001679 if (ar->debug.fw_dbglog_mask) {
SenthilKumar Jegadeesan467210a2015-01-29 14:36:52 +05301680 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
1681 ATH10K_DBGLOG_LEVEL_WARN);
Kalle Valof118a3e2014-01-03 12:59:31 +02001682 if (ret)
1683 /* not serious */
Michal Kazior7aa7a722014-08-25 12:09:38 +02001684 ath10k_warn(ar, "failed to enable dbglog during start: %d",
Kalle Valof118a3e2014-01-03 12:59:31 +02001685 ret);
1686 }
1687
Anilkumar Kolli7f9befb2017-12-05 19:01:24 +05301688 if (ar->pktlog_filter) {
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001689 ret = ath10k_wmi_pdev_pktlog_enable(ar,
Anilkumar Kolli7f9befb2017-12-05 19:01:24 +05301690 ar->pktlog_filter);
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001691 if (ret)
1692 /* not serious */
1693 ath10k_warn(ar,
1694 "failed to enable pktlog filter %x: %d\n",
Anilkumar Kolli7f9befb2017-12-05 19:01:24 +05301695 ar->pktlog_filter, ret);
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001696 } else {
1697 ret = ath10k_wmi_pdev_pktlog_disable(ar);
1698 if (ret)
1699 /* not serious */
1700 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
1701 }
1702
Peter Oha7bd3e92014-12-02 13:07:14 +02001703 if (ar->debug.nf_cal_period) {
1704 ret = ath10k_wmi_pdev_set_param(ar,
1705 ar->wmi.pdev_param->cal_period,
1706 ar->debug.nf_cal_period);
1707 if (ret)
1708 /* not serious */
1709 ath10k_warn(ar, "cal period cfg failed from debug start: %d\n",
1710 ret);
1711 }
1712
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001713 return ret;
Kalle Valodb66ea02013-09-03 11:44:03 +03001714}
1715
1716void ath10k_debug_stop(struct ath10k *ar)
1717{
Kalle Valo60631c52013-10-08 21:45:25 +03001718 lockdep_assert_held(&ar->conf_mutex);
1719
Marty Faltesekf67b107d2016-10-10 19:00:04 +03001720 ath10k_debug_cal_data_fetch(ar);
1721
Kalle Valo60631c52013-10-08 21:45:25 +03001722 /* Must not use _sync to avoid deadlock, we do that in
1723 * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid
Marcin Rokickid6dfe25c2017-02-20 14:39:57 +01001724 * warning from del_timer().
1725 */
Kalle Valo60631c52013-10-08 21:45:25 +03001726 if (ar->debug.htt_stats_mask != 0)
1727 cancel_delayed_work(&ar->debug.htt_stats_dwork);
Janusz Dziedzicd3856232014-06-02 21:19:46 +03001728
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001729 ath10k_wmi_pdev_pktlog_disable(ar);
Kalle Valodb66ea02013-09-03 11:44:03 +03001730}
1731
Janusz Dziedzic9702c682013-11-20 09:59:41 +02001732static ssize_t ath10k_write_simulate_radar(struct file *file,
1733 const char __user *user_buf,
1734 size_t count, loff_t *ppos)
1735{
1736 struct ath10k *ar = file->private_data;
Mohammed Shafi Shajakhanca07baa2017-02-22 21:03:11 +05301737 struct ath10k_vif *arvif;
1738
1739 /* Just check for for the first vif alone, as all the vifs will be
1740 * sharing the same channel and if the channel is disabled, all the
1741 * vifs will share the same 'is_started' state.
1742 */
1743 arvif = list_first_entry(&ar->arvifs, typeof(*arvif), list);
1744 if (!arvif->is_started)
1745 return -EINVAL;
Janusz Dziedzic9702c682013-11-20 09:59:41 +02001746
1747 ieee80211_radar_detected(ar->hw);
1748
1749 return count;
1750}
1751
1752static const struct file_operations fops_simulate_radar = {
1753 .write = ath10k_write_simulate_radar,
1754 .open = simple_open,
1755 .owner = THIS_MODULE,
1756 .llseek = default_llseek,
1757};
1758
1759#define ATH10K_DFS_STAT(s, p) (\
1760 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
1761 ar->debug.dfs_stats.p))
1762
1763#define ATH10K_DFS_POOL_STAT(s, p) (\
1764 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
1765 ar->debug.dfs_pool_stats.p))
1766
1767static ssize_t ath10k_read_dfs_stats(struct file *file, char __user *user_buf,
1768 size_t count, loff_t *ppos)
1769{
1770 int retval = 0, len = 0;
1771 const int size = 8000;
1772 struct ath10k *ar = file->private_data;
1773 char *buf;
1774
1775 buf = kzalloc(size, GFP_KERNEL);
1776 if (buf == NULL)
1777 return -ENOMEM;
1778
1779 if (!ar->dfs_detector) {
1780 len += scnprintf(buf + len, size - len, "DFS not enabled\n");
1781 goto exit;
1782 }
1783
1784 ar->debug.dfs_pool_stats =
1785 ar->dfs_detector->get_stats(ar->dfs_detector);
1786
1787 len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n");
1788
1789 ATH10K_DFS_STAT("reported phy errors", phy_errors);
1790 ATH10K_DFS_STAT("pulse events reported", pulses_total);
1791 ATH10K_DFS_STAT("DFS pulses detected", pulses_detected);
1792 ATH10K_DFS_STAT("DFS pulses discarded", pulses_discarded);
1793 ATH10K_DFS_STAT("Radars detected", radar_detected);
1794
1795 len += scnprintf(buf + len, size - len, "Global Pool statistics:\n");
1796 ATH10K_DFS_POOL_STAT("Pool references", pool_reference);
1797 ATH10K_DFS_POOL_STAT("Pulses allocated", pulse_allocated);
1798 ATH10K_DFS_POOL_STAT("Pulses alloc error", pulse_alloc_error);
1799 ATH10K_DFS_POOL_STAT("Pulses in use", pulse_used);
1800 ATH10K_DFS_POOL_STAT("Seqs. allocated", pseq_allocated);
1801 ATH10K_DFS_POOL_STAT("Seqs. alloc error", pseq_alloc_error);
1802 ATH10K_DFS_POOL_STAT("Seqs. in use", pseq_used);
1803
1804exit:
1805 if (len > size)
1806 len = size;
1807
1808 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1809 kfree(buf);
1810
1811 return retval;
1812}
1813
1814static const struct file_operations fops_dfs_stats = {
1815 .read = ath10k_read_dfs_stats,
1816 .open = simple_open,
1817 .owner = THIS_MODULE,
1818 .llseek = default_llseek,
1819};
1820
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001821static ssize_t ath10k_write_pktlog_filter(struct file *file,
1822 const char __user *ubuf,
1823 size_t count, loff_t *ppos)
1824{
1825 struct ath10k *ar = file->private_data;
1826 u32 filter;
1827 int ret;
1828
1829 if (kstrtouint_from_user(ubuf, count, 0, &filter))
1830 return -EINVAL;
1831
1832 mutex_lock(&ar->conf_mutex);
1833
1834 if (ar->state != ATH10K_STATE_ON) {
Anilkumar Kolli7f9befb2017-12-05 19:01:24 +05301835 ar->pktlog_filter = filter;
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001836 ret = count;
1837 goto out;
1838 }
1839
Anilkumar Kolli7f9befb2017-12-05 19:01:24 +05301840 if (filter == ar->pktlog_filter) {
Anilkumar Kolli9ddc4862016-03-11 11:46:39 +05301841 ret = count;
1842 goto out;
1843 }
1844
1845 if (filter) {
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001846 ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
1847 if (ret) {
1848 ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
Anilkumar Kolli7f9befb2017-12-05 19:01:24 +05301849 ar->pktlog_filter, ret);
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001850 goto out;
1851 }
1852 } else {
1853 ret = ath10k_wmi_pdev_pktlog_disable(ar);
1854 if (ret) {
1855 ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
1856 goto out;
1857 }
1858 }
1859
Anilkumar Kolli7f9befb2017-12-05 19:01:24 +05301860 ar->pktlog_filter = filter;
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001861 ret = count;
1862
1863out:
1864 mutex_unlock(&ar->conf_mutex);
1865 return ret;
1866}
1867
1868static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf,
1869 size_t count, loff_t *ppos)
1870{
1871 char buf[32];
1872 struct ath10k *ar = file->private_data;
1873 int len = 0;
1874
1875 mutex_lock(&ar->conf_mutex);
1876 len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
Anilkumar Kolli7f9befb2017-12-05 19:01:24 +05301877 ar->pktlog_filter);
Rajkumar Manoharan90174452014-10-03 08:02:33 +03001878 mutex_unlock(&ar->conf_mutex);
1879
1880 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
1881}
1882
1883static const struct file_operations fops_pktlog_filter = {
1884 .read = ath10k_read_pktlog_filter,
1885 .write = ath10k_write_pktlog_filter,
1886 .open = simple_open
1887};
1888
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05301889static ssize_t ath10k_write_quiet_period(struct file *file,
1890 const char __user *ubuf,
1891 size_t count, loff_t *ppos)
1892{
1893 struct ath10k *ar = file->private_data;
1894 u32 period;
1895
1896 if (kstrtouint_from_user(ubuf, count, 0, &period))
1897 return -EINVAL;
1898
1899 if (period < ATH10K_QUIET_PERIOD_MIN) {
1900 ath10k_warn(ar, "Quiet period %u can not be lesser than 25ms\n",
1901 period);
1902 return -EINVAL;
1903 }
1904 mutex_lock(&ar->conf_mutex);
1905 ar->thermal.quiet_period = period;
Rajkumar Manoharan8515b5c2015-03-15 20:36:22 +05301906 ath10k_thermal_set_throttling(ar);
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05301907 mutex_unlock(&ar->conf_mutex);
1908
1909 return count;
1910}
1911
1912static ssize_t ath10k_read_quiet_period(struct file *file, char __user *ubuf,
1913 size_t count, loff_t *ppos)
1914{
1915 char buf[32];
1916 struct ath10k *ar = file->private_data;
1917 int len = 0;
1918
1919 mutex_lock(&ar->conf_mutex);
1920 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
1921 ar->thermal.quiet_period);
1922 mutex_unlock(&ar->conf_mutex);
1923
1924 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
1925}
1926
1927static const struct file_operations fops_quiet_period = {
1928 .read = ath10k_read_quiet_period,
1929 .write = ath10k_write_quiet_period,
1930 .open = simple_open
1931};
1932
Yanbo Li844fa572015-10-31 11:07:21 +02001933static ssize_t ath10k_write_btcoex(struct file *file,
1934 const char __user *ubuf,
1935 size_t count, loff_t *ppos)
1936{
1937 struct ath10k *ar = file->private_data;
1938 char buf[32];
1939 size_t buf_size;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05301940 int ret;
Yanbo Li844fa572015-10-31 11:07:21 +02001941 bool val;
Rajkumar Manoharan39136242016-05-27 20:15:59 +05301942 u32 pdev_param;
Yanbo Li844fa572015-10-31 11:07:21 +02001943
1944 buf_size = min(count, (sizeof(buf) - 1));
1945 if (copy_from_user(buf, ubuf, buf_size))
1946 return -EFAULT;
1947
1948 buf[buf_size] = '\0';
1949
1950 if (strtobool(buf, &val) != 0)
1951 return -EINVAL;
1952
1953 mutex_lock(&ar->conf_mutex);
1954
Mohammed Shafi Shajakhanc28e6f02016-02-23 12:58:36 +05301955 if (ar->state != ATH10K_STATE_ON &&
1956 ar->state != ATH10K_STATE_RESTARTED) {
1957 ret = -ENETDOWN;
1958 goto exit;
1959 }
1960
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05301961 if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val)) {
1962 ret = count;
Yanbo Li844fa572015-10-31 11:07:21 +02001963 goto exit;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05301964 }
Yanbo Li844fa572015-10-31 11:07:21 +02001965
Rajkumar Manoharan39136242016-05-27 20:15:59 +05301966 pdev_param = ar->wmi.pdev_param->enable_btcoex;
1967 if (test_bit(ATH10K_FW_FEATURE_BTCOEX_PARAM,
1968 ar->running_fw->fw_file.fw_features)) {
1969 ret = ath10k_wmi_pdev_set_param(ar, pdev_param, val);
1970 if (ret) {
1971 ath10k_warn(ar, "failed to enable btcoex: %d\n", ret);
1972 ret = count;
1973 goto exit;
1974 }
1975 } else {
1976 ath10k_info(ar, "restarting firmware due to btcoex change");
1977 queue_work(ar->workqueue, &ar->restart_work);
1978 }
1979
Yanbo Li844fa572015-10-31 11:07:21 +02001980 if (val)
1981 set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
1982 else
1983 clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
1984
Mohammed Shafi Shajakhanc28e6f02016-02-23 12:58:36 +05301985 ret = count;
Yanbo Li844fa572015-10-31 11:07:21 +02001986
1987exit:
1988 mutex_unlock(&ar->conf_mutex);
1989
Mohammed Shafi Shajakhanc28e6f02016-02-23 12:58:36 +05301990 return ret;
Yanbo Li844fa572015-10-31 11:07:21 +02001991}
1992
1993static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf,
1994 size_t count, loff_t *ppos)
1995{
1996 char buf[32];
1997 struct ath10k *ar = file->private_data;
1998 int len = 0;
1999
2000 mutex_lock(&ar->conf_mutex);
2001 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2002 test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags));
2003 mutex_unlock(&ar->conf_mutex);
2004
2005 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2006}
2007
2008static const struct file_operations fops_btcoex = {
2009 .read = ath10k_read_btcoex,
2010 .write = ath10k_write_btcoex,
2011 .open = simple_open
2012};
2013
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302014static ssize_t ath10k_write_peer_stats(struct file *file,
2015 const char __user *ubuf,
2016 size_t count, loff_t *ppos)
2017{
2018 struct ath10k *ar = file->private_data;
2019 char buf[32];
2020 size_t buf_size;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302021 int ret;
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302022 bool val;
2023
2024 buf_size = min(count, (sizeof(buf) - 1));
2025 if (copy_from_user(buf, ubuf, buf_size))
2026 return -EFAULT;
2027
2028 buf[buf_size] = '\0';
2029
2030 if (strtobool(buf, &val) != 0)
2031 return -EINVAL;
2032
2033 mutex_lock(&ar->conf_mutex);
2034
2035 if (ar->state != ATH10K_STATE_ON &&
2036 ar->state != ATH10K_STATE_RESTARTED) {
2037 ret = -ENETDOWN;
2038 goto exit;
2039 }
2040
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302041 if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val)) {
2042 ret = count;
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302043 goto exit;
Mohammed Shafi Shajakhan87be0542016-04-05 20:58:26 +05302044 }
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302045
2046 if (val)
2047 set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
2048 else
2049 clear_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
2050
2051 ath10k_info(ar, "restarting firmware due to Peer stats change");
2052
2053 queue_work(ar->workqueue, &ar->restart_work);
2054 ret = count;
2055
2056exit:
2057 mutex_unlock(&ar->conf_mutex);
2058 return ret;
2059}
2060
2061static ssize_t ath10k_read_peer_stats(struct file *file, char __user *ubuf,
2062 size_t count, loff_t *ppos)
2063
2064{
2065 char buf[32];
2066 struct ath10k *ar = file->private_data;
2067 int len = 0;
2068
2069 mutex_lock(&ar->conf_mutex);
2070 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
2071 test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags));
2072 mutex_unlock(&ar->conf_mutex);
2073
2074 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
2075}
2076
2077static const struct file_operations fops_peer_stats = {
2078 .read = ath10k_read_peer_stats,
2079 .write = ath10k_write_peer_stats,
2080 .open = simple_open
2081};
2082
Kalle Valo9e100c42015-11-25 15:38:41 +02002083static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
2084 char __user *user_buf,
2085 size_t count, loff_t *ppos)
2086{
2087 struct ath10k *ar = file->private_data;
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02002088 size_t len = 0, buf_len = 4096;
Kalle Valo9e100c42015-11-25 15:38:41 +02002089 ssize_t ret_cnt;
2090 char *buf;
2091
2092 buf = kzalloc(buf_len, GFP_KERNEL);
2093 if (!buf)
2094 return -ENOMEM;
2095
2096 mutex_lock(&ar->conf_mutex);
2097
Kalle Valo9e100c42015-11-25 15:38:41 +02002098 len += scnprintf(buf + len, buf_len - len,
2099 "firmware-N.bin\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002100 crc32_le(0, ar->normal_mode_fw.fw_file.firmware->data,
2101 ar->normal_mode_fw.fw_file.firmware->size));
Kalle Valo9e100c42015-11-25 15:38:41 +02002102 len += scnprintf(buf + len, buf_len - len,
2103 "athwlan\t\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002104 crc32_le(0, ar->normal_mode_fw.fw_file.firmware_data,
2105 ar->normal_mode_fw.fw_file.firmware_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002106 len += scnprintf(buf + len, buf_len - len,
2107 "otp\t\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002108 crc32_le(0, ar->normal_mode_fw.fw_file.otp_data,
2109 ar->normal_mode_fw.fw_file.otp_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002110 len += scnprintf(buf + len, buf_len - len,
2111 "codeswap\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002112 crc32_le(0, ar->normal_mode_fw.fw_file.codeswap_data,
2113 ar->normal_mode_fw.fw_file.codeswap_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002114 len += scnprintf(buf + len, buf_len - len,
2115 "board-N.bin\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002116 crc32_le(0, ar->normal_mode_fw.board->data,
2117 ar->normal_mode_fw.board->size));
Kalle Valo9e100c42015-11-25 15:38:41 +02002118 len += scnprintf(buf + len, buf_len - len,
2119 "board\t\t\t%08x\n",
Kalle Valo7ebf7212016-04-20 19:44:51 +03002120 crc32_le(0, ar->normal_mode_fw.board_data,
2121 ar->normal_mode_fw.board_len));
Kalle Valo9e100c42015-11-25 15:38:41 +02002122
2123 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
2124
2125 mutex_unlock(&ar->conf_mutex);
2126
2127 kfree(buf);
2128 return ret_cnt;
2129}
2130
2131static const struct file_operations fops_fw_checksums = {
2132 .read = ath10k_debug_fw_checksums_read,
2133 .open = simple_open,
2134 .owner = THIS_MODULE,
2135 .llseek = default_llseek,
2136};
2137
Kalle Valo5e3dd152013-06-12 20:52:10 +03002138int ath10k_debug_create(struct ath10k *ar)
2139{
Marty Faltesekf67b107d2016-10-10 19:00:04 +03002140 ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);
2141 if (!ar->debug.cal_data)
2142 return -ENOMEM;
2143
Michal Kazior53268492014-09-25 12:33:50 +02002144 INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
Michal Kazior7b6b1532015-02-15 16:50:40 +02002145 INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
Michal Kazior53268492014-09-25 12:33:50 +02002146 INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
Mohammed Shafi Shajakhan4a49ae92016-06-30 15:23:47 +03002147 INIT_LIST_HEAD(&ar->debug.fw_stats.peers_extd);
Michal Kazior53268492014-09-25 12:33:50 +02002148
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002149 return 0;
2150}
2151
2152void ath10k_debug_destroy(struct ath10k *ar)
2153{
Marty Faltesekf67b107d2016-10-10 19:00:04 +03002154 vfree(ar->debug.cal_data);
2155 ar->debug.cal_data = NULL;
2156
Michal Kazior53268492014-09-25 12:33:50 +02002157 ath10k_debug_fw_stats_reset(ar);
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002158
2159 kfree(ar->debug.tpc_stats);
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002160}
2161
2162int ath10k_debug_register(struct ath10k *ar)
2163{
Kalle Valo5e3dd152013-06-12 20:52:10 +03002164 ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
2165 ar->hw->wiphy->debugfsdir);
Michal Kazioradb43b22014-09-04 12:36:45 +02002166 if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
2167 if (IS_ERR(ar->debug.debugfs_phy))
2168 return PTR_ERR(ar->debug.debugfs_phy);
Kalle Valod8bb26b2014-09-14 12:50:33 +03002169
2170 return -ENOMEM;
Michal Kazioradb43b22014-09-04 12:36:45 +02002171 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03002172
Kalle Valoa3d135e2013-09-03 11:44:10 +03002173 INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
2174 ath10k_debug_htt_stats_dwork);
2175
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002176 init_completion(&ar->debug.tpc_complete);
Michal Kazior60ef4012014-09-25 12:33:48 +02002177 init_completion(&ar->debug.fw_stats_complete);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002178
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002179 debugfs_create_file("fw_stats", 0400, ar->debug.debugfs_phy, ar,
Kalle Valo5e3dd152013-06-12 20:52:10 +03002180 &fops_fw_stats);
2181
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002182 debugfs_create_file("fw_reset_stats", 0400, ar->debug.debugfs_phy, ar,
2183 &fops_fw_reset_stats);
Ben Greearf51dbe72014-09-29 14:41:46 +03002184
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002185 debugfs_create_file("wmi_services", 0400, ar->debug.debugfs_phy, ar,
Kalle Valo5e3dd152013-06-12 20:52:10 +03002186 &fops_wmi_services);
2187
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002188 debugfs_create_file("simulate_fw_crash", 0600, ar->debug.debugfs_phy, ar,
2189 &fops_simulate_fw_crash);
Michal Kazior278c4a82013-07-22 14:08:51 +02002190
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002191 debugfs_create_file("reg_addr", 0600, ar->debug.debugfs_phy, ar,
2192 &fops_reg_addr);
Yanbo Li077a3802014-11-25 12:24:33 +02002193
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002194 debugfs_create_file("reg_value", 0600, ar->debug.debugfs_phy, ar,
2195 &fops_reg_value);
Yanbo Li077a3802014-11-25 12:24:33 +02002196
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002197 debugfs_create_file("mem_value", 0600, ar->debug.debugfs_phy, ar,
2198 &fops_mem_value);
Yanbo Li9f65ad22014-11-25 12:24:48 +02002199
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002200 debugfs_create_file("chip_id", 0400, ar->debug.debugfs_phy, ar,
2201 &fops_chip_id);
Kalle Valo763b8cd2013-09-01 11:22:21 +03002202
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002203 debugfs_create_file("htt_stats_mask", 0600, ar->debug.debugfs_phy, ar,
2204 &fops_htt_stats_mask);
Kalle Valoa3d135e2013-09-03 11:44:10 +03002205
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002206 debugfs_create_file("htt_max_amsdu_ampdu", 0600, ar->debug.debugfs_phy, ar,
Janusz Dziedzicd3856232014-06-02 21:19:46 +03002207 &fops_htt_max_amsdu_ampdu);
2208
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002209 debugfs_create_file("fw_dbglog", 0600, ar->debug.debugfs_phy, ar,
2210 &fops_fw_dbglog);
Kalle Valof118a3e2014-01-03 12:59:31 +02002211
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002212 debugfs_create_file("cal_data", 0400, ar->debug.debugfs_phy, ar,
2213 &fops_cal_data);
Kalle Valo7869b4f2014-09-24 14:16:58 +03002214
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002215 debugfs_create_file("ani_enable", 0600, ar->debug.debugfs_phy, ar,
2216 &fops_ani_enable);
Ashok Raj Nagarajanb3e71d72015-03-19 16:38:00 +05302217
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002218 debugfs_create_file("nf_cal_period", 0600, ar->debug.debugfs_phy, ar,
2219 &fops_nf_cal_period);
Peter Oha7bd3e92014-12-02 13:07:14 +02002220
Masahiro Yamada97f26452016-08-03 13:45:50 -07002221 if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED)) {
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002222 debugfs_create_file("dfs_simulate_radar", 0200, ar->debug.debugfs_phy,
2223 ar, &fops_simulate_radar);
Janusz Dziedzic9702c682013-11-20 09:59:41 +02002224
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002225 debugfs_create_bool("dfs_block_radar_events", 0200,
Marek Puzyniak7d9b40b2013-11-20 10:00:28 +02002226 ar->debug.debugfs_phy,
2227 &ar->dfs_block_radar_events);
2228
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002229 debugfs_create_file("dfs_stats", 0400, ar->debug.debugfs_phy, ar,
Janusz Dziedzic9702c682013-11-20 09:59:41 +02002230 &fops_dfs_stats);
2231 }
2232
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002233 debugfs_create_file("pktlog_filter", 0644, ar->debug.debugfs_phy, ar,
2234 &fops_pktlog_filter);
Rajkumar Manoharan90174452014-10-03 08:02:33 +03002235
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002236 debugfs_create_file("quiet_period", 0644, ar->debug.debugfs_phy, ar,
2237 &fops_quiet_period);
Rajkumar Manoharan63fb32d2015-03-15 20:36:20 +05302238
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002239 debugfs_create_file("tpc_stats", 0400, ar->debug.debugfs_phy, ar,
2240 &fops_tpc_stats);
Maharaja Kennadyrajan29542662015-10-05 17:56:38 +03002241
Yanbo Li844fa572015-10-31 11:07:21 +02002242 if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002243 debugfs_create_file("btcoex", 0644, ar->debug.debugfs_phy, ar,
2244 &fops_btcoex);
Yanbo Li844fa572015-10-31 11:07:21 +02002245
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302246 if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map))
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002247 debugfs_create_file("peer_stats", 0644, ar->debug.debugfs_phy, ar,
Mohammed Shafi Shajakhancc61a1b2016-03-16 18:13:32 +05302248 &fops_peer_stats);
2249
Marcin Rokicki53c8d482017-02-20 14:40:27 +01002250 debugfs_create_file("fw_checksums", 0400, ar->debug.debugfs_phy, ar,
2251 &fops_fw_checksums);
Kalle Valo9e100c42015-11-25 15:38:41 +02002252
Kalle Valo5e3dd152013-06-12 20:52:10 +03002253 return 0;
2254}
Kalle Valodb66ea02013-09-03 11:44:03 +03002255
Michal Kaziore13cf7a2014-09-04 09:13:08 +02002256void ath10k_debug_unregister(struct ath10k *ar)
Kalle Valo60631c52013-10-08 21:45:25 +03002257{
2258 cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
2259}
2260
Kalle Valo5e3dd152013-06-12 20:52:10 +03002261#endif /* CONFIG_ATH10K_DEBUGFS */
2262
2263#ifdef CONFIG_ATH10K_DEBUG
Michal Kazior7aa7a722014-08-25 12:09:38 +02002264void ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
2265 const char *fmt, ...)
Kalle Valo5e3dd152013-06-12 20:52:10 +03002266{
2267 struct va_format vaf;
2268 va_list args;
2269
2270 va_start(args, fmt);
2271
2272 vaf.fmt = fmt;
2273 vaf.va = &args;
2274
2275 if (ath10k_debug_mask & mask)
Michal Kazior7aa7a722014-08-25 12:09:38 +02002276 dev_printk(KERN_DEBUG, ar->dev, "%pV", &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002277
Michal Kaziord35a6c12014-09-02 11:00:21 +03002278 trace_ath10k_log_dbg(ar, mask, &vaf);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002279
2280 va_end(args);
2281}
2282EXPORT_SYMBOL(ath10k_dbg);
2283
Michal Kazior7aa7a722014-08-25 12:09:38 +02002284void ath10k_dbg_dump(struct ath10k *ar,
2285 enum ath10k_debug_mask mask,
Kalle Valo5e3dd152013-06-12 20:52:10 +03002286 const char *msg, const char *prefix,
2287 const void *buf, size_t len)
2288{
Michal Kazior45724a82014-09-23 10:22:53 +02002289 char linebuf[256];
Amadeusz Sławiński182f1e52017-02-13 12:38:38 +02002290 size_t linebuflen;
Michal Kazior45724a82014-09-23 10:22:53 +02002291 const void *ptr;
2292
Kalle Valo5e3dd152013-06-12 20:52:10 +03002293 if (ath10k_debug_mask & mask) {
2294 if (msg)
Michal Kazior7aa7a722014-08-25 12:09:38 +02002295 ath10k_dbg(ar, mask, "%s\n", msg);
Kalle Valo5e3dd152013-06-12 20:52:10 +03002296
Michal Kazior45724a82014-09-23 10:22:53 +02002297 for (ptr = buf; (ptr - buf) < len; ptr += 16) {
2298 linebuflen = 0;
2299 linebuflen += scnprintf(linebuf + linebuflen,
2300 sizeof(linebuf) - linebuflen,
2301 "%s%08x: ",
2302 (prefix ? prefix : ""),
2303 (unsigned int)(ptr - buf));
2304 hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
2305 linebuf + linebuflen,
2306 sizeof(linebuf) - linebuflen, true);
2307 dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
2308 }
Kalle Valo5e3dd152013-06-12 20:52:10 +03002309 }
2310
2311 /* tracing code doesn't like null strings :/ */
Michal Kaziord35a6c12014-09-02 11:00:21 +03002312 trace_ath10k_log_dbg_dump(ar, msg ? msg : "", prefix ? prefix : "",
Kalle Valo5e3dd152013-06-12 20:52:10 +03002313 buf, len);
2314}
2315EXPORT_SYMBOL(ath10k_dbg_dump);
2316
2317#endif /* CONFIG_ATH10K_DEBUG */