brintos

brintos / linux-shallow public Read only

0
0
Text · 63.9 KiB · 35bfe72 Raw
2709 lines · c
1// SPDX-License-Identifier: ISC2/*3 * Copyright (c) 2005-2011 Atheros Communications Inc.4 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.5 * Copyright (c) 2018, The Linux Foundation. All rights reserved.6 * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.7 */8 9#include <linux/module.h>10#include <linux/debugfs.h>11#include <linux/vmalloc.h>12#include <linux/crc32.h>13#include <linux/firmware.h>14#include <linux/kstrtox.h>15 16#include "core.h"17#include "debug.h"18#include "hif.h"19#include "wmi-ops.h"20 21/* ms */22#define ATH10K_DEBUG_HTT_STATS_INTERVAL 100023 24#define ATH10K_DEBUG_CAL_DATA_LEN 1206425 26void ath10k_info(struct ath10k *ar, const char *fmt, ...)27{28	struct va_format vaf = {29		.fmt = fmt,30	};31	va_list args;32 33	va_start(args, fmt);34	vaf.va = &args;35	dev_info(ar->dev, "%pV", &vaf);36	trace_ath10k_log_info(ar, &vaf);37	va_end(args);38}39EXPORT_SYMBOL(ath10k_info);40 41void ath10k_debug_print_hwfw_info(struct ath10k *ar)42{43	const struct firmware *firmware;44	char fw_features[128] = {};45	u32 crc = 0;46 47	ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));48 49	ath10k_info(ar, "%s target 0x%08x chip_id 0x%08x sub %04x:%04x",50		    ar->hw_params.name,51		    ar->target_version,52		    ar->bus_param.chip_id,53		    ar->id.subsystem_vendor, ar->id.subsystem_device);54 55	ath10k_info(ar, "kconfig debug %d debugfs %d tracing %d dfs %d testmode %d\n",56		    IS_ENABLED(CONFIG_ATH10K_DEBUG),57		    IS_ENABLED(CONFIG_ATH10K_DEBUGFS),58		    IS_ENABLED(CONFIG_ATH10K_TRACING),59		    IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED),60		    IS_ENABLED(CONFIG_NL80211_TESTMODE));61 62	firmware = ar->normal_mode_fw.fw_file.firmware;63	if (firmware)64		crc = crc32_le(0, firmware->data, firmware->size);65 66	ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n",67		    ar->hw->wiphy->fw_version,68		    ar->fw_api,69		    fw_features,70		    crc);71}72 73void ath10k_debug_print_board_info(struct ath10k *ar)74{75	char boardinfo[100];76	const struct firmware *board;77	u32 crc;78 79	if (ar->id.bmi_ids_valid)80		scnprintf(boardinfo, sizeof(boardinfo), "%d:%d",81			  ar->id.bmi_chip_id, ar->id.bmi_board_id);82	else83		scnprintf(boardinfo, sizeof(boardinfo), "N/A");84 85	board = ar->normal_mode_fw.board;86	if (!IS_ERR_OR_NULL(board))87		crc = crc32_le(0, board->data, board->size);88	else89		crc = 0;90 91	ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x",92		    ar->bd_api,93		    boardinfo,94		    crc);95}96 97void ath10k_debug_print_boot_info(struct ath10k *ar)98{99	ath10k_info(ar, "htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d\n",100		    ar->htt.target_version_major,101		    ar->htt.target_version_minor,102		    ar->normal_mode_fw.fw_file.wmi_op_version,103		    ar->normal_mode_fw.fw_file.htt_op_version,104		    ath10k_cal_mode_str(ar->cal_mode),105		    ar->max_num_stations,106		    test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),107		    !test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags));108}109 110void ath10k_print_driver_info(struct ath10k *ar)111{112	ath10k_debug_print_hwfw_info(ar);113	ath10k_debug_print_board_info(ar);114	ath10k_debug_print_boot_info(ar);115}116EXPORT_SYMBOL(ath10k_print_driver_info);117 118void ath10k_err(struct ath10k *ar, const char *fmt, ...)119{120	struct va_format vaf = {121		.fmt = fmt,122	};123	va_list args;124 125	va_start(args, fmt);126	vaf.va = &args;127	dev_err(ar->dev, "%pV", &vaf);128	trace_ath10k_log_err(ar, &vaf);129	va_end(args);130}131EXPORT_SYMBOL(ath10k_err);132 133void ath10k_warn(struct ath10k *ar, const char *fmt, ...)134{135	struct va_format vaf = {136		.fmt = fmt,137	};138	va_list args;139 140	va_start(args, fmt);141	vaf.va = &args;142	dev_warn_ratelimited(ar->dev, "%pV", &vaf);143	trace_ath10k_log_warn(ar, &vaf);144 145	va_end(args);146}147EXPORT_SYMBOL(ath10k_warn);148 149#ifdef CONFIG_ATH10K_DEBUGFS150 151static ssize_t ath10k_read_wmi_services(struct file *file,152					char __user *user_buf,153					size_t count, loff_t *ppos)154{155	struct ath10k *ar = file->private_data;156	char *buf;157	size_t len = 0, buf_len = 8192;158	const char *name;159	ssize_t ret_cnt;160	bool enabled;161	int i;162 163	buf = kzalloc(buf_len, GFP_KERNEL);164	if (!buf)165		return -ENOMEM;166 167	mutex_lock(&ar->conf_mutex);168 169	spin_lock_bh(&ar->data_lock);170	for (i = 0; i < WMI_SERVICE_MAX; i++) {171		enabled = test_bit(i, ar->wmi.svc_map);172		name = wmi_service_name(i);173 174		if (!name) {175			if (enabled)176				len += scnprintf(buf + len, buf_len - len,177						 "%-40s %s (bit %d)\n",178						 "unknown", "enabled", i);179 180			continue;181		}182 183		len += scnprintf(buf + len, buf_len - len,184				 "%-40s %s\n",185				 name, enabled ? "enabled" : "-");186	}187	spin_unlock_bh(&ar->data_lock);188 189	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);190 191	mutex_unlock(&ar->conf_mutex);192 193	kfree(buf);194	return ret_cnt;195}196 197static const struct file_operations fops_wmi_services = {198	.read = ath10k_read_wmi_services,199	.open = simple_open,200	.owner = THIS_MODULE,201	.llseek = default_llseek,202};203 204static void ath10k_fw_stats_pdevs_free(struct list_head *head)205{206	struct ath10k_fw_stats_pdev *i, *tmp;207 208	list_for_each_entry_safe(i, tmp, head, list) {209		list_del(&i->list);210		kfree(i);211	}212}213 214static void ath10k_fw_stats_vdevs_free(struct list_head *head)215{216	struct ath10k_fw_stats_vdev *i, *tmp;217 218	list_for_each_entry_safe(i, tmp, head, list) {219		list_del(&i->list);220		kfree(i);221	}222}223 224static void ath10k_fw_stats_peers_free(struct list_head *head)225{226	struct ath10k_fw_stats_peer *i, *tmp;227 228	list_for_each_entry_safe(i, tmp, head, list) {229		list_del(&i->list);230		kfree(i);231	}232}233 234static void ath10k_fw_extd_stats_peers_free(struct list_head *head)235{236	struct ath10k_fw_extd_stats_peer *i, *tmp;237 238	list_for_each_entry_safe(i, tmp, head, list) {239		list_del(&i->list);240		kfree(i);241	}242}243 244static void ath10k_debug_fw_stats_reset(struct ath10k *ar)245{246	spin_lock_bh(&ar->data_lock);247	ar->debug.fw_stats_done = false;248	ar->debug.fw_stats.extended = false;249	ath10k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);250	ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);251	ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);252	ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd);253	spin_unlock_bh(&ar->data_lock);254}255 256void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)257{258	struct ath10k_fw_stats stats = {};259	bool is_start, is_started, is_end;260	size_t num_peers;261	size_t num_vdevs;262	int ret;263 264	INIT_LIST_HEAD(&stats.pdevs);265	INIT_LIST_HEAD(&stats.vdevs);266	INIT_LIST_HEAD(&stats.peers);267	INIT_LIST_HEAD(&stats.peers_extd);268 269	spin_lock_bh(&ar->data_lock);270	ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);271	if (ret) {272		ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);273		goto free;274	}275 276	/* Stat data may exceed htc-wmi buffer limit. In such case firmware277	 * splits the stats data and delivers it in a ping-pong fashion of278	 * request cmd-update event.279	 *280	 * However there is no explicit end-of-data. Instead start-of-data is281	 * used as an implicit one. This works as follows:282	 *  a) discard stat update events until one with pdev stats is283	 *     delivered - this skips session started at end of (b)284	 *  b) consume stat update events until another one with pdev stats is285	 *     delivered which is treated as end-of-data and is itself discarded286	 */287	if (ath10k_peer_stats_enabled(ar))288		ath10k_sta_update_rx_duration(ar, &stats);289 290	if (ar->debug.fw_stats_done) {291		if (!ath10k_peer_stats_enabled(ar))292			ath10k_warn(ar, "received unsolicited stats update event\n");293 294		goto free;295	}296 297	num_peers = list_count_nodes(&ar->debug.fw_stats.peers);298	num_vdevs = list_count_nodes(&ar->debug.fw_stats.vdevs);299	is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&300		    !list_empty(&stats.pdevs));301	is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&302		  !list_empty(&stats.pdevs));303 304	if (is_start)305		list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);306 307	if (is_end)308		ar->debug.fw_stats_done = true;309 310	if (stats.extended)311		ar->debug.fw_stats.extended = true;312 313	is_started = !list_empty(&ar->debug.fw_stats.pdevs);314 315	if (is_started && !is_end) {316		if (num_peers >= ATH10K_MAX_NUM_PEER_IDS) {317			/* Although this is unlikely impose a sane limit to318			 * prevent firmware from DoS-ing the host.319			 */320			ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);321			ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd);322			ath10k_warn(ar, "dropping fw peer stats\n");323			goto free;324		}325 326		if (num_vdevs >= BITS_PER_LONG) {327			ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);328			ath10k_warn(ar, "dropping fw vdev stats\n");329			goto free;330		}331 332		if (!list_empty(&stats.peers))333			list_splice_tail_init(&stats.peers_extd,334					      &ar->debug.fw_stats.peers_extd);335 336		list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);337		list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);338	}339 340	complete(&ar->debug.fw_stats_complete);341 342free:343	/* In some cases lists have been spliced and cleared. Free up344	 * resources if that is not the case.345	 */346	ath10k_fw_stats_pdevs_free(&stats.pdevs);347	ath10k_fw_stats_vdevs_free(&stats.vdevs);348	ath10k_fw_stats_peers_free(&stats.peers);349	ath10k_fw_extd_stats_peers_free(&stats.peers_extd);350 351	spin_unlock_bh(&ar->data_lock);352}353 354int ath10k_debug_fw_stats_request(struct ath10k *ar)355{356	unsigned long timeout, time_left;357	int ret;358 359	lockdep_assert_held(&ar->conf_mutex);360 361	timeout = jiffies + msecs_to_jiffies(1 * HZ);362 363	ath10k_debug_fw_stats_reset(ar);364 365	for (;;) {366		if (time_after(jiffies, timeout))367			return -ETIMEDOUT;368 369		reinit_completion(&ar->debug.fw_stats_complete);370 371		ret = ath10k_wmi_request_stats(ar, ar->fw_stats_req_mask);372		if (ret) {373			ath10k_warn(ar, "could not request stats (%d)\n", ret);374			return ret;375		}376 377		time_left =378		wait_for_completion_timeout(&ar->debug.fw_stats_complete,379					    1 * HZ);380		if (!time_left)381			return -ETIMEDOUT;382 383		spin_lock_bh(&ar->data_lock);384		if (ar->debug.fw_stats_done) {385			spin_unlock_bh(&ar->data_lock);386			break;387		}388		spin_unlock_bh(&ar->data_lock);389	}390 391	return 0;392}393 394static int ath10k_fw_stats_open(struct inode *inode, struct file *file)395{396	struct ath10k *ar = inode->i_private;397	void *buf = NULL;398	int ret;399 400	mutex_lock(&ar->conf_mutex);401 402	if (ar->state != ATH10K_STATE_ON) {403		ret = -ENETDOWN;404		goto err_unlock;405	}406 407	buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE);408	if (!buf) {409		ret = -ENOMEM;410		goto err_unlock;411	}412 413	ret = ath10k_debug_fw_stats_request(ar);414	if (ret) {415		ath10k_warn(ar, "failed to request fw stats: %d\n", ret);416		goto err_free;417	}418 419	ret = ath10k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, buf);420	if (ret) {421		ath10k_warn(ar, "failed to fill fw stats: %d\n", ret);422		goto err_free;423	}424 425	file->private_data = buf;426 427	mutex_unlock(&ar->conf_mutex);428	return 0;429 430err_free:431	vfree(buf);432 433err_unlock:434	mutex_unlock(&ar->conf_mutex);435	return ret;436}437 438static int ath10k_fw_stats_release(struct inode *inode, struct file *file)439{440	vfree(file->private_data);441 442	return 0;443}444 445static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,446				    size_t count, loff_t *ppos)447{448	const char *buf = file->private_data;449	size_t len = strlen(buf);450 451	return simple_read_from_buffer(user_buf, count, ppos, buf, len);452}453 454static const struct file_operations fops_fw_stats = {455	.open = ath10k_fw_stats_open,456	.release = ath10k_fw_stats_release,457	.read = ath10k_fw_stats_read,458	.owner = THIS_MODULE,459	.llseek = default_llseek,460};461 462static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,463						char __user *user_buf,464						size_t count, loff_t *ppos)465{466	struct ath10k *ar = file->private_data;467	int ret;468	size_t len = 0, buf_len = 500;469	char *buf;470 471	buf = kmalloc(buf_len, GFP_KERNEL);472	if (!buf)473		return -ENOMEM;474 475	spin_lock_bh(&ar->data_lock);476 477	len += scnprintf(buf + len, buf_len - len,478			 "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter);479	len += scnprintf(buf + len, buf_len - len,480			 "fw_warm_reset_counter\t\t%d\n",481			 ar->stats.fw_warm_reset_counter);482	len += scnprintf(buf + len, buf_len - len,483			 "fw_cold_reset_counter\t\t%d\n",484			 ar->stats.fw_cold_reset_counter);485 486	spin_unlock_bh(&ar->data_lock);487 488	ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);489 490	kfree(buf);491 492	return ret;493}494 495static const struct file_operations fops_fw_reset_stats = {496	.open = simple_open,497	.read = ath10k_debug_fw_reset_stats_read,498	.owner = THIS_MODULE,499	.llseek = default_llseek,500};501 502/* This is a clean assert crash in firmware. */503static int ath10k_debug_fw_assert(struct ath10k *ar)504{505	struct wmi_vdev_install_key_cmd *cmd;506	struct sk_buff *skb;507 508	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);509	if (!skb)510		return -ENOMEM;511 512	cmd = (struct wmi_vdev_install_key_cmd *)skb->data;513	memset(cmd, 0, sizeof(*cmd));514 515	/* big enough number so that firmware asserts */516	cmd->vdev_id = __cpu_to_le32(0x7ffe);517 518	return ath10k_wmi_cmd_send(ar, skb,519				   ar->wmi.cmd->vdev_install_key_cmdid);520}521 522static ssize_t ath10k_read_simulate_fw_crash(struct file *file,523					     char __user *user_buf,524					     size_t count, loff_t *ppos)525{526	const char buf[] =527		"To simulate firmware crash write one of the keywords to this file:\n"528		"`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"529		"`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"530		"`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"531		"`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";532 533	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));534}535 536/* Simulate firmware crash:537 * 'soft': Call wmi command causing firmware hang. This firmware hang is538 * recoverable by warm firmware reset.539 * 'hard': Force firmware crash by setting any vdev parameter for not allowed540 * vdev id. This is hard firmware crash because it is recoverable only by cold541 * firmware reset.542 */543static ssize_t ath10k_write_simulate_fw_crash(struct file *file,544					      const char __user *user_buf,545					      size_t count, loff_t *ppos)546{547	struct ath10k *ar = file->private_data;548	char buf[32] = {0};549	ssize_t rc;550	int ret;551 552	/* filter partial writes and invalid commands */553	if (*ppos != 0 || count >= sizeof(buf) || count == 0)554		return -EINVAL;555 556	rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);557	if (rc < 0)558		return rc;559 560	/* drop the possible '\n' from the end */561	if (buf[*ppos - 1] == '\n')562		buf[*ppos - 1] = '\0';563 564	mutex_lock(&ar->conf_mutex);565 566	if (ar->state != ATH10K_STATE_ON &&567	    ar->state != ATH10K_STATE_RESTARTED) {568		ret = -ENETDOWN;569		goto exit;570	}571 572	if (!strcmp(buf, "soft")) {573		ath10k_info(ar, "simulating soft firmware crash\n");574		ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);575	} else if (!strcmp(buf, "hard")) {576		ath10k_info(ar, "simulating hard firmware crash\n");577		/* 0x7fff is vdev id, and it is always out of range for all578		 * firmware variants in order to force a firmware crash.579		 */580		ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,581						ar->wmi.vdev_param->rts_threshold,582						0);583	} else if (!strcmp(buf, "assert")) {584		ath10k_info(ar, "simulating firmware assert crash\n");585		ret = ath10k_debug_fw_assert(ar);586	} else if (!strcmp(buf, "hw-restart")) {587		ath10k_info(ar, "user requested hw restart\n");588		ath10k_core_start_recovery(ar);589		ret = 0;590	} else {591		ret = -EINVAL;592		goto exit;593	}594 595	if (ret) {596		ath10k_warn(ar, "failed to simulate firmware crash: %d\n", ret);597		goto exit;598	}599 600	ret = count;601 602exit:603	mutex_unlock(&ar->conf_mutex);604	return ret;605}606 607static const struct file_operations fops_simulate_fw_crash = {608	.read = ath10k_read_simulate_fw_crash,609	.write = ath10k_write_simulate_fw_crash,610	.open = simple_open,611	.owner = THIS_MODULE,612	.llseek = default_llseek,613};614 615static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf,616				   size_t count, loff_t *ppos)617{618	struct ath10k *ar = file->private_data;619	size_t len;620	char buf[50];621 622	len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->bus_param.chip_id);623 624	return simple_read_from_buffer(user_buf, count, ppos, buf, len);625}626 627static const struct file_operations fops_chip_id = {628	.read = ath10k_read_chip_id,629	.open = simple_open,630	.owner = THIS_MODULE,631	.llseek = default_llseek,632};633 634static ssize_t ath10k_reg_addr_read(struct file *file,635				    char __user *user_buf,636				    size_t count, loff_t *ppos)637{638	struct ath10k *ar = file->private_data;639	u8 buf[32];640	size_t len = 0;641	u32 reg_addr;642 643	mutex_lock(&ar->conf_mutex);644	reg_addr = ar->debug.reg_addr;645	mutex_unlock(&ar->conf_mutex);646 647	len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", reg_addr);648 649	return simple_read_from_buffer(user_buf, count, ppos, buf, len);650}651 652static ssize_t ath10k_reg_addr_write(struct file *file,653				     const char __user *user_buf,654				     size_t count, loff_t *ppos)655{656	struct ath10k *ar = file->private_data;657	u32 reg_addr;658	int ret;659 660	ret = kstrtou32_from_user(user_buf, count, 0, &reg_addr);661	if (ret)662		return ret;663 664	if (!IS_ALIGNED(reg_addr, 4))665		return -EFAULT;666 667	mutex_lock(&ar->conf_mutex);668	ar->debug.reg_addr = reg_addr;669	mutex_unlock(&ar->conf_mutex);670 671	return count;672}673 674static const struct file_operations fops_reg_addr = {675	.read = ath10k_reg_addr_read,676	.write = ath10k_reg_addr_write,677	.open = simple_open,678	.owner = THIS_MODULE,679	.llseek = default_llseek,680};681 682static ssize_t ath10k_reg_value_read(struct file *file,683				     char __user *user_buf,684				     size_t count, loff_t *ppos)685{686	struct ath10k *ar = file->private_data;687	u8 buf[48];688	size_t len;689	u32 reg_addr, reg_val;690	int ret;691 692	mutex_lock(&ar->conf_mutex);693 694	if (ar->state != ATH10K_STATE_ON &&695	    ar->state != ATH10K_STATE_UTF) {696		ret = -ENETDOWN;697		goto exit;698	}699 700	reg_addr = ar->debug.reg_addr;701 702	reg_val = ath10k_hif_read32(ar, reg_addr);703	len = scnprintf(buf, sizeof(buf), "0x%08x:0x%08x\n", reg_addr, reg_val);704 705	ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);706 707exit:708	mutex_unlock(&ar->conf_mutex);709 710	return ret;711}712 713static ssize_t ath10k_reg_value_write(struct file *file,714				      const char __user *user_buf,715				      size_t count, loff_t *ppos)716{717	struct ath10k *ar = file->private_data;718	u32 reg_addr, reg_val;719	int ret;720 721	mutex_lock(&ar->conf_mutex);722 723	if (ar->state != ATH10K_STATE_ON &&724	    ar->state != ATH10K_STATE_UTF) {725		ret = -ENETDOWN;726		goto exit;727	}728 729	reg_addr = ar->debug.reg_addr;730 731	ret = kstrtou32_from_user(user_buf, count, 0, &reg_val);732	if (ret)733		goto exit;734 735	ath10k_hif_write32(ar, reg_addr, reg_val);736 737	ret = count;738 739exit:740	mutex_unlock(&ar->conf_mutex);741 742	return ret;743}744 745static const struct file_operations fops_reg_value = {746	.read = ath10k_reg_value_read,747	.write = ath10k_reg_value_write,748	.open = simple_open,749	.owner = THIS_MODULE,750	.llseek = default_llseek,751};752 753static ssize_t ath10k_mem_value_read(struct file *file,754				     char __user *user_buf,755				     size_t count, loff_t *ppos)756{757	struct ath10k *ar = file->private_data;758	u8 *buf;759	int ret;760 761	if (*ppos < 0)762		return -EINVAL;763 764	if (!count)765		return 0;766 767	mutex_lock(&ar->conf_mutex);768 769	buf = vmalloc(count);770	if (!buf) {771		ret = -ENOMEM;772		goto exit;773	}774 775	if (ar->state != ATH10K_STATE_ON &&776	    ar->state != ATH10K_STATE_UTF) {777		ret = -ENETDOWN;778		goto exit;779	}780 781	ret = ath10k_hif_diag_read(ar, *ppos, buf, count);782	if (ret) {783		ath10k_warn(ar, "failed to read address 0x%08x via diagnose window from debugfs: %d\n",784			    (u32)(*ppos), ret);785		goto exit;786	}787 788	ret = copy_to_user(user_buf, buf, count);789	if (ret) {790		ret = -EFAULT;791		goto exit;792	}793 794	count -= ret;795	*ppos += count;796	ret = count;797 798exit:799	vfree(buf);800	mutex_unlock(&ar->conf_mutex);801 802	return ret;803}804 805static ssize_t ath10k_mem_value_write(struct file *file,806				      const char __user *user_buf,807				      size_t count, loff_t *ppos)808{809	struct ath10k *ar = file->private_data;810	u8 *buf;811	int ret;812 813	if (*ppos < 0)814		return -EINVAL;815 816	if (!count)817		return 0;818 819	mutex_lock(&ar->conf_mutex);820 821	buf = vmalloc(count);822	if (!buf) {823		ret = -ENOMEM;824		goto exit;825	}826 827	if (ar->state != ATH10K_STATE_ON &&828	    ar->state != ATH10K_STATE_UTF) {829		ret = -ENETDOWN;830		goto exit;831	}832 833	ret = copy_from_user(buf, user_buf, count);834	if (ret) {835		ret = -EFAULT;836		goto exit;837	}838 839	ret = ath10k_hif_diag_write(ar, *ppos, buf, count);840	if (ret) {841		ath10k_warn(ar, "failed to write address 0x%08x via diagnose window from debugfs: %d\n",842			    (u32)(*ppos), ret);843		goto exit;844	}845 846	*ppos += count;847	ret = count;848 849exit:850	vfree(buf);851	mutex_unlock(&ar->conf_mutex);852 853	return ret;854}855 856static const struct file_operations fops_mem_value = {857	.read = ath10k_mem_value_read,858	.write = ath10k_mem_value_write,859	.open = simple_open,860	.owner = THIS_MODULE,861	.llseek = default_llseek,862};863 864static int ath10k_debug_htt_stats_req(struct ath10k *ar)865{866	u64 cookie;867	int ret;868 869	lockdep_assert_held(&ar->conf_mutex);870 871	if (ar->debug.htt_stats_mask == 0)872		/* htt stats are disabled */873		return 0;874 875	if (ar->state != ATH10K_STATE_ON)876		return 0;877 878	cookie = get_jiffies_64();879 880	ret = ath10k_htt_h2t_stats_req(&ar->htt, ar->debug.htt_stats_mask,881				       ar->debug.reset_htt_stats, cookie);882	if (ret) {883		ath10k_warn(ar, "failed to send htt stats request: %d\n", ret);884		return ret;885	}886 887	queue_delayed_work(ar->workqueue, &ar->debug.htt_stats_dwork,888			   msecs_to_jiffies(ATH10K_DEBUG_HTT_STATS_INTERVAL));889 890	return 0;891}892 893static void ath10k_debug_htt_stats_dwork(struct work_struct *work)894{895	struct ath10k *ar = container_of(work, struct ath10k,896					 debug.htt_stats_dwork.work);897 898	mutex_lock(&ar->conf_mutex);899 900	ath10k_debug_htt_stats_req(ar);901 902	mutex_unlock(&ar->conf_mutex);903}904 905static ssize_t ath10k_read_htt_stats_mask(struct file *file,906					  char __user *user_buf,907					  size_t count, loff_t *ppos)908{909	struct ath10k *ar = file->private_data;910	char buf[32];911	size_t len;912 913	len = scnprintf(buf, sizeof(buf), "%lu\n", ar->debug.htt_stats_mask);914 915	return simple_read_from_buffer(user_buf, count, ppos, buf, len);916}917 918static ssize_t ath10k_write_htt_stats_mask(struct file *file,919					   const char __user *user_buf,920					   size_t count, loff_t *ppos)921{922	struct ath10k *ar = file->private_data;923	unsigned long mask;924	int ret;925 926	ret = kstrtoul_from_user(user_buf, count, 0, &mask);927	if (ret)928		return ret;929 930	/* max 17 bit masks (for now) */931	if (mask > HTT_STATS_BIT_MASK)932		return -E2BIG;933 934	mutex_lock(&ar->conf_mutex);935 936	ar->debug.htt_stats_mask = mask;937 938	ret = ath10k_debug_htt_stats_req(ar);939	if (ret)940		goto out;941 942	ret = count;943 944out:945	mutex_unlock(&ar->conf_mutex);946 947	return ret;948}949 950static const struct file_operations fops_htt_stats_mask = {951	.read = ath10k_read_htt_stats_mask,952	.write = ath10k_write_htt_stats_mask,953	.open = simple_open,954	.owner = THIS_MODULE,955	.llseek = default_llseek,956};957 958static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,959					       char __user *user_buf,960					       size_t count, loff_t *ppos)961{962	struct ath10k *ar = file->private_data;963	char buf[64];964	u8 amsdu, ampdu;965	size_t len;966 967	mutex_lock(&ar->conf_mutex);968 969	amsdu = ar->htt.max_num_amsdu;970	ampdu = ar->htt.max_num_ampdu;971	mutex_unlock(&ar->conf_mutex);972 973	len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);974 975	return simple_read_from_buffer(user_buf, count, ppos, buf, len);976}977 978static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,979						const char __user *user_buf,980						size_t count, loff_t *ppos)981{982	struct ath10k *ar = file->private_data;983	int res;984	char buf[64] = {0};985	unsigned int amsdu, ampdu;986 987	res = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,988				     user_buf, count);989	if (res <= 0)990		return res;991 992	res = sscanf(buf, "%u %u", &amsdu, &ampdu);993 994	if (res != 2)995		return -EINVAL;996 997	mutex_lock(&ar->conf_mutex);998 999	res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);1000	if (res)1001		goto out;1002 1003	res = count;1004	ar->htt.max_num_amsdu = amsdu;1005	ar->htt.max_num_ampdu = ampdu;1006 1007out:1008	mutex_unlock(&ar->conf_mutex);1009	return res;1010}1011 1012static const struct file_operations fops_htt_max_amsdu_ampdu = {1013	.read = ath10k_read_htt_max_amsdu_ampdu,1014	.write = ath10k_write_htt_max_amsdu_ampdu,1015	.open = simple_open,1016	.owner = THIS_MODULE,1017	.llseek = default_llseek,1018};1019 1020static ssize_t ath10k_read_fw_dbglog(struct file *file,1021				     char __user *user_buf,1022				     size_t count, loff_t *ppos)1023{1024	struct ath10k *ar = file->private_data;1025	size_t len;1026	char buf[96];1027 1028	len = scnprintf(buf, sizeof(buf), "0x%16llx %u\n",1029			ar->debug.fw_dbglog_mask, ar->debug.fw_dbglog_level);1030 1031	return simple_read_from_buffer(user_buf, count, ppos, buf, len);1032}1033 1034static ssize_t ath10k_write_fw_dbglog(struct file *file,1035				      const char __user *user_buf,1036				      size_t count, loff_t *ppos)1037{1038	struct ath10k *ar = file->private_data;1039	int ret;1040	char buf[96] = {0};1041	unsigned int log_level;1042	u64 mask;1043 1044	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,1045				     user_buf, count);1046	if (ret <= 0)1047		return ret;1048 1049	ret = sscanf(buf, "%llx %u", &mask, &log_level);1050 1051	if (!ret)1052		return -EINVAL;1053 1054	if (ret == 1)1055		/* default if user did not specify */1056		log_level = ATH10K_DBGLOG_LEVEL_WARN;1057 1058	mutex_lock(&ar->conf_mutex);1059 1060	ar->debug.fw_dbglog_mask = mask;1061	ar->debug.fw_dbglog_level = log_level;1062 1063	if (ar->state == ATH10K_STATE_ON) {1064		ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,1065					    ar->debug.fw_dbglog_level);1066		if (ret) {1067			ath10k_warn(ar, "dbglog cfg failed from debugfs: %d\n",1068				    ret);1069			goto exit;1070		}1071	}1072 1073	ret = count;1074 1075exit:1076	mutex_unlock(&ar->conf_mutex);1077 1078	return ret;1079}1080 1081/* TODO:  Would be nice to always support ethtool stats, would need to1082 * move the stats storage out of ath10k_debug, or always have ath10k_debug1083 * struct available..1084 */1085 1086/* This generally corresponds to the debugfs fw_stats file */1087static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {1088	"tx_pkts_nic",1089	"tx_bytes_nic",1090	"rx_pkts_nic",1091	"rx_bytes_nic",1092	"d_noise_floor",1093	"d_cycle_count",1094	"d_phy_error",1095	"d_rts_bad",1096	"d_rts_good",1097	"d_tx_power", /* in .5 dbM I think */1098	"d_rx_crc_err", /* fcs_bad */1099	"d_rx_crc_err_drop", /* frame with FCS error, dropped late in kernel */1100	"d_no_beacon",1101	"d_tx_mpdus_queued",1102	"d_tx_msdu_queued",1103	"d_tx_msdu_dropped",1104	"d_local_enqued",1105	"d_local_freed",1106	"d_tx_ppdu_hw_queued",1107	"d_tx_ppdu_reaped",1108	"d_tx_fifo_underrun",1109	"d_tx_ppdu_abort",1110	"d_tx_mpdu_requeued",1111	"d_tx_excessive_retries",1112	"d_tx_hw_rate",1113	"d_tx_dropped_sw_retries",1114	"d_tx_illegal_rate",1115	"d_tx_continuous_xretries",1116	"d_tx_timeout",1117	"d_tx_mpdu_txop_limit",1118	"d_pdev_resets",1119	"d_rx_mid_ppdu_route_change",1120	"d_rx_status",1121	"d_rx_extra_frags_ring0",1122	"d_rx_extra_frags_ring1",1123	"d_rx_extra_frags_ring2",1124	"d_rx_extra_frags_ring3",1125	"d_rx_msdu_htt",1126	"d_rx_mpdu_htt",1127	"d_rx_msdu_stack",1128	"d_rx_mpdu_stack",1129	"d_rx_phy_err",1130	"d_rx_phy_err_drops",1131	"d_rx_mpdu_errors", /* FCS, MIC, ENC */1132	"d_fw_crash_count",1133	"d_fw_warm_reset_count",1134	"d_fw_cold_reset_count",1135};1136 1137#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)1138 1139void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,1140				 struct ieee80211_vif *vif,1141				 u32 sset, u8 *data)1142{1143	if (sset == ETH_SS_STATS)1144		memcpy(data, ath10k_gstrings_stats,1145		       sizeof(ath10k_gstrings_stats));1146}1147 1148int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,1149				   struct ieee80211_vif *vif, int sset)1150{1151	if (sset == ETH_SS_STATS)1152		return ATH10K_SSTATS_LEN;1153 1154	return 0;1155}1156 1157void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,1158			       struct ieee80211_vif *vif,1159			       struct ethtool_stats *stats, u64 *data)1160{1161	struct ath10k *ar = hw->priv;1162	static const struct ath10k_fw_stats_pdev zero_stats = {};1163	const struct ath10k_fw_stats_pdev *pdev_stats;1164	int i = 0, ret;1165 1166	mutex_lock(&ar->conf_mutex);1167 1168	if (ar->state == ATH10K_STATE_ON) {1169		ret = ath10k_debug_fw_stats_request(ar);1170		if (ret) {1171			/* just print a warning and try to use older results */1172			ath10k_warn(ar,1173				    "failed to get fw stats for ethtool: %d\n",1174				    ret);1175		}1176	}1177 1178	pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs,1179					      struct ath10k_fw_stats_pdev,1180					      list);1181	if (!pdev_stats) {1182		/* no results available so just return zeroes */1183		pdev_stats = &zero_stats;1184	}1185 1186	spin_lock_bh(&ar->data_lock);1187 1188	data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */1189	data[i++] = 0; /* tx bytes */1190	data[i++] = pdev_stats->htt_mpdus;1191	data[i++] = 0; /* rx bytes */1192	data[i++] = pdev_stats->ch_noise_floor;1193	data[i++] = pdev_stats->cycle_count;1194	data[i++] = pdev_stats->phy_err_count;1195	data[i++] = pdev_stats->rts_bad;1196	data[i++] = pdev_stats->rts_good;1197	data[i++] = pdev_stats->chan_tx_power;1198	data[i++] = pdev_stats->fcs_bad;1199	data[i++] = ar->stats.rx_crc_err_drop;1200	data[i++] = pdev_stats->no_beacons;1201	data[i++] = pdev_stats->mpdu_enqued;1202	data[i++] = pdev_stats->msdu_enqued;1203	data[i++] = pdev_stats->wmm_drop;1204	data[i++] = pdev_stats->local_enqued;1205	data[i++] = pdev_stats->local_freed;1206	data[i++] = pdev_stats->hw_queued;1207	data[i++] = pdev_stats->hw_reaped;1208	data[i++] = pdev_stats->underrun;1209	data[i++] = pdev_stats->tx_abort;1210	data[i++] = pdev_stats->mpdus_requeued;1211	data[i++] = pdev_stats->tx_ko;1212	data[i++] = pdev_stats->data_rc;1213	data[i++] = pdev_stats->sw_retry_failure;1214	data[i++] = pdev_stats->illgl_rate_phy_err;1215	data[i++] = pdev_stats->pdev_cont_xretry;1216	data[i++] = pdev_stats->pdev_tx_timeout;1217	data[i++] = pdev_stats->txop_ovf;1218	data[i++] = pdev_stats->pdev_resets;1219	data[i++] = pdev_stats->mid_ppdu_route_change;1220	data[i++] = pdev_stats->status_rcvd;1221	data[i++] = pdev_stats->r0_frags;1222	data[i++] = pdev_stats->r1_frags;1223	data[i++] = pdev_stats->r2_frags;1224	data[i++] = pdev_stats->r3_frags;1225	data[i++] = pdev_stats->htt_msdus;1226	data[i++] = pdev_stats->htt_mpdus;1227	data[i++] = pdev_stats->loc_msdus;1228	data[i++] = pdev_stats->loc_mpdus;1229	data[i++] = pdev_stats->phy_errs;1230	data[i++] = pdev_stats->phy_err_drop;1231	data[i++] = pdev_stats->mpdu_errs;1232	data[i++] = ar->stats.fw_crash_counter;1233	data[i++] = ar->stats.fw_warm_reset_counter;1234	data[i++] = ar->stats.fw_cold_reset_counter;1235 1236	spin_unlock_bh(&ar->data_lock);1237 1238	mutex_unlock(&ar->conf_mutex);1239 1240	WARN_ON(i != ATH10K_SSTATS_LEN);1241}1242 1243static const struct file_operations fops_fw_dbglog = {1244	.read = ath10k_read_fw_dbglog,1245	.write = ath10k_write_fw_dbglog,1246	.open = simple_open,1247	.owner = THIS_MODULE,1248	.llseek = default_llseek,1249};1250 1251static int ath10k_debug_cal_data_fetch(struct ath10k *ar)1252{1253	u32 hi_addr;1254	__le32 addr;1255	int ret;1256 1257	lockdep_assert_held(&ar->conf_mutex);1258 1259	if (WARN_ON(ar->hw_params.cal_data_len > ATH10K_DEBUG_CAL_DATA_LEN))1260		return -EINVAL;1261 1262	if (ar->hw_params.cal_data_len == 0)1263		return -EOPNOTSUPP;1264 1265	hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));1266 1267	ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));1268	if (ret) {1269		ath10k_warn(ar, "failed to read hi_board_data address: %d\n",1270			    ret);1271		return ret;1272	}1273 1274	ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), ar->debug.cal_data,1275				   ar->hw_params.cal_data_len);1276	if (ret) {1277		ath10k_warn(ar, "failed to read calibration data: %d\n", ret);1278		return ret;1279	}1280 1281	return 0;1282}1283 1284static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)1285{1286	struct ath10k *ar = inode->i_private;1287 1288	mutex_lock(&ar->conf_mutex);1289 1290	if (ar->state == ATH10K_STATE_ON ||1291	    ar->state == ATH10K_STATE_UTF) {1292		ath10k_debug_cal_data_fetch(ar);1293	}1294 1295	file->private_data = ar;1296	mutex_unlock(&ar->conf_mutex);1297 1298	return 0;1299}1300 1301static ssize_t ath10k_debug_cal_data_read(struct file *file,1302					  char __user *user_buf,1303					  size_t count, loff_t *ppos)1304{1305	struct ath10k *ar = file->private_data;1306 1307	mutex_lock(&ar->conf_mutex);1308 1309	count = simple_read_from_buffer(user_buf, count, ppos,1310					ar->debug.cal_data,1311					ar->hw_params.cal_data_len);1312 1313	mutex_unlock(&ar->conf_mutex);1314 1315	return count;1316}1317 1318static ssize_t ath10k_write_ani_enable(struct file *file,1319				       const char __user *user_buf,1320				       size_t count, loff_t *ppos)1321{1322	struct ath10k *ar = file->private_data;1323	int ret;1324	u8 enable;1325 1326	if (kstrtou8_from_user(user_buf, count, 0, &enable))1327		return -EINVAL;1328 1329	mutex_lock(&ar->conf_mutex);1330 1331	if (ar->ani_enabled == enable) {1332		ret = count;1333		goto exit;1334	}1335 1336	ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->ani_enable,1337					enable);1338	if (ret) {1339		ath10k_warn(ar, "ani_enable failed from debugfs: %d\n", ret);1340		goto exit;1341	}1342	ar->ani_enabled = enable;1343 1344	ret = count;1345 1346exit:1347	mutex_unlock(&ar->conf_mutex);1348 1349	return ret;1350}1351 1352static ssize_t ath10k_read_ani_enable(struct file *file, char __user *user_buf,1353				      size_t count, loff_t *ppos)1354{1355	struct ath10k *ar = file->private_data;1356	size_t len;1357	char buf[32];1358 1359	len = scnprintf(buf, sizeof(buf), "%d\n", ar->ani_enabled);1360 1361	return simple_read_from_buffer(user_buf, count, ppos, buf, len);1362}1363 1364static const struct file_operations fops_ani_enable = {1365	.read = ath10k_read_ani_enable,1366	.write = ath10k_write_ani_enable,1367	.open = simple_open,1368	.owner = THIS_MODULE,1369	.llseek = default_llseek,1370};1371 1372static const struct file_operations fops_cal_data = {1373	.open = ath10k_debug_cal_data_open,1374	.read = ath10k_debug_cal_data_read,1375	.owner = THIS_MODULE,1376	.llseek = default_llseek,1377};1378 1379static ssize_t ath10k_read_nf_cal_period(struct file *file,1380					 char __user *user_buf,1381					 size_t count, loff_t *ppos)1382{1383	struct ath10k *ar = file->private_data;1384	size_t len;1385	char buf[32];1386 1387	len = scnprintf(buf, sizeof(buf), "%d\n", ar->debug.nf_cal_period);1388 1389	return simple_read_from_buffer(user_buf, count, ppos, buf, len);1390}1391 1392static ssize_t ath10k_write_nf_cal_period(struct file *file,1393					  const char __user *user_buf,1394					  size_t count, loff_t *ppos)1395{1396	struct ath10k *ar = file->private_data;1397	unsigned long period;1398	int ret;1399 1400	ret = kstrtoul_from_user(user_buf, count, 0, &period);1401	if (ret)1402		return ret;1403 1404	if (period > WMI_PDEV_PARAM_CAL_PERIOD_MAX)1405		return -EINVAL;1406 1407	/* there's no way to switch back to the firmware default */1408	if (period == 0)1409		return -EINVAL;1410 1411	mutex_lock(&ar->conf_mutex);1412 1413	ar->debug.nf_cal_period = period;1414 1415	if (ar->state != ATH10K_STATE_ON) {1416		/* firmware is not running, nothing else to do */1417		ret = count;1418		goto exit;1419	}1420 1421	ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->cal_period,1422					ar->debug.nf_cal_period);1423	if (ret) {1424		ath10k_warn(ar, "cal period cfg failed from debugfs: %d\n",1425			    ret);1426		goto exit;1427	}1428 1429	ret = count;1430 1431exit:1432	mutex_unlock(&ar->conf_mutex);1433 1434	return ret;1435}1436 1437static const struct file_operations fops_nf_cal_period = {1438	.read = ath10k_read_nf_cal_period,1439	.write = ath10k_write_nf_cal_period,1440	.open = simple_open,1441	.owner = THIS_MODULE,1442	.llseek = default_llseek,1443};1444 1445#define ATH10K_TPC_CONFIG_BUF_SIZE	(1024 * 1024)1446 1447static int ath10k_debug_tpc_stats_request(struct ath10k *ar)1448{1449	int ret;1450	unsigned long time_left;1451 1452	lockdep_assert_held(&ar->conf_mutex);1453 1454	reinit_completion(&ar->debug.tpc_complete);1455 1456	ret = ath10k_wmi_pdev_get_tpc_config(ar, WMI_TPC_CONFIG_PARAM);1457	if (ret) {1458		ath10k_warn(ar, "failed to request tpc config: %d\n", ret);1459		return ret;1460	}1461 1462	time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,1463						1 * HZ);1464	if (time_left == 0)1465		return -ETIMEDOUT;1466 1467	return 0;1468}1469 1470void ath10k_debug_tpc_stats_process(struct ath10k *ar,1471				    struct ath10k_tpc_stats *tpc_stats)1472{1473	spin_lock_bh(&ar->data_lock);1474 1475	kfree(ar->debug.tpc_stats);1476	ar->debug.tpc_stats = tpc_stats;1477	complete(&ar->debug.tpc_complete);1478 1479	spin_unlock_bh(&ar->data_lock);1480}1481 1482void1483ath10k_debug_tpc_stats_final_process(struct ath10k *ar,1484				     struct ath10k_tpc_stats_final *tpc_stats)1485{1486	spin_lock_bh(&ar->data_lock);1487 1488	kfree(ar->debug.tpc_stats_final);1489	ar->debug.tpc_stats_final = tpc_stats;1490	complete(&ar->debug.tpc_complete);1491 1492	spin_unlock_bh(&ar->data_lock);1493}1494 1495static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats,1496				   unsigned int j, char *buf, size_t *len)1497{1498	int i;1499	size_t buf_len;1500	static const char table_str[][5] = { "CDD",1501					     "STBC",1502					     "TXBF" };1503	static const char pream_str[][6] = { "CCK",1504					     "OFDM",1505					     "HT20",1506					     "HT40",1507					     "VHT20",1508					     "VHT40",1509					     "VHT80",1510					     "HTCUP" };1511 1512	buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;1513	*len += scnprintf(buf + *len, buf_len - *len,1514			  "********************************\n");1515	*len += scnprintf(buf + *len, buf_len - *len,1516			  "******************* %s POWER TABLE ****************\n",1517			  table_str[j]);1518	*len += scnprintf(buf + *len, buf_len - *len,1519			  "********************************\n");1520	*len += scnprintf(buf + *len, buf_len - *len,1521			  "No.  Preamble Rate_code ");1522 1523	for (i = 0; i < tpc_stats->num_tx_chain; i++)1524		*len += scnprintf(buf + *len, buf_len - *len,1525				  "tpc_value%d ", i);1526 1527	*len += scnprintf(buf + *len, buf_len - *len, "\n");1528 1529	for (i = 0; i < tpc_stats->rate_max; i++) {1530		*len += scnprintf(buf + *len, buf_len - *len,1531				  "%8d %s 0x%2x %s\n", i,1532				  pream_str[tpc_stats->tpc_table[j].pream_idx[i]],1533				  tpc_stats->tpc_table[j].rate_code[i],1534				  tpc_stats->tpc_table[j].tpc_value[i]);1535	}1536 1537	*len += scnprintf(buf + *len, buf_len - *len,1538			  "***********************************\n");1539}1540 1541static void ath10k_tpc_stats_fill(struct ath10k *ar,1542				  struct ath10k_tpc_stats *tpc_stats,1543				  char *buf)1544{1545	int j;1546	size_t len, buf_len;1547 1548	len = 0;1549	buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;1550 1551	spin_lock_bh(&ar->data_lock);1552 1553	if (!tpc_stats) {1554		ath10k_warn(ar, "failed to get tpc stats\n");1555		goto unlock;1556	}1557 1558	len += scnprintf(buf + len, buf_len - len, "\n");1559	len += scnprintf(buf + len, buf_len - len,1560			 "*************************************\n");1561	len += scnprintf(buf + len, buf_len - len,1562			 "TPC config for channel %4d mode %d\n",1563			 tpc_stats->chan_freq,1564			 tpc_stats->phy_mode);1565	len += scnprintf(buf + len, buf_len - len,1566			 "*************************************\n");1567	len += scnprintf(buf + len, buf_len - len,1568			 "CTL		=  0x%2x Reg. Domain		= %2d\n",1569			 tpc_stats->ctl,1570			 tpc_stats->reg_domain);1571	len += scnprintf(buf + len, buf_len - len,1572			 "Antenna Gain	= %2d Reg. Max Antenna Gain	=  %2d\n",1573			 tpc_stats->twice_antenna_gain,1574			 tpc_stats->twice_antenna_reduction);1575	len += scnprintf(buf + len, buf_len - len,1576			 "Power Limit	= %2d Reg. Max Power		= %2d\n",1577			 tpc_stats->power_limit,1578			 tpc_stats->twice_max_rd_power / 2);1579	len += scnprintf(buf + len, buf_len - len,1580			 "Num tx chains	= %2d Num supported rates	= %2d\n",1581			 tpc_stats->num_tx_chain,1582			 tpc_stats->rate_max);1583 1584	for (j = 0; j < WMI_TPC_FLAG; j++) {1585		switch (j) {1586		case WMI_TPC_TABLE_TYPE_CDD:1587			if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {1588				len += scnprintf(buf + len, buf_len - len,1589						 "CDD not supported\n");1590				break;1591			}1592 1593			ath10k_tpc_stats_print(tpc_stats, j, buf, &len);1594			break;1595		case WMI_TPC_TABLE_TYPE_STBC:1596			if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {1597				len += scnprintf(buf + len, buf_len - len,1598						 "STBC not supported\n");1599				break;1600			}1601 1602			ath10k_tpc_stats_print(tpc_stats, j, buf, &len);1603			break;1604		case WMI_TPC_TABLE_TYPE_TXBF:1605			if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) {1606				len += scnprintf(buf + len, buf_len - len,1607						 "TXBF not supported\n***************************\n");1608				break;1609			}1610 1611			ath10k_tpc_stats_print(tpc_stats, j, buf, &len);1612			break;1613		default:1614			len += scnprintf(buf + len, buf_len - len,1615					 "Invalid Type\n");1616			break;1617		}1618	}1619 1620unlock:1621	spin_unlock_bh(&ar->data_lock);1622 1623	if (len >= buf_len)1624		buf[len - 1] = 0;1625	else1626		buf[len] = 0;1627}1628 1629static int ath10k_tpc_stats_open(struct inode *inode, struct file *file)1630{1631	struct ath10k *ar = inode->i_private;1632	void *buf = NULL;1633	int ret;1634 1635	mutex_lock(&ar->conf_mutex);1636 1637	if (ar->state != ATH10K_STATE_ON) {1638		ret = -ENETDOWN;1639		goto err_unlock;1640	}1641 1642	buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);1643	if (!buf) {1644		ret = -ENOMEM;1645		goto err_unlock;1646	}1647 1648	ret = ath10k_debug_tpc_stats_request(ar);1649	if (ret) {1650		ath10k_warn(ar, "failed to request tpc config stats: %d\n",1651			    ret);1652		goto err_free;1653	}1654 1655	ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);1656	file->private_data = buf;1657 1658	mutex_unlock(&ar->conf_mutex);1659	return 0;1660 1661err_free:1662	vfree(buf);1663 1664err_unlock:1665	mutex_unlock(&ar->conf_mutex);1666	return ret;1667}1668 1669static int ath10k_tpc_stats_release(struct inode *inode, struct file *file)1670{1671	vfree(file->private_data);1672 1673	return 0;1674}1675 1676static ssize_t ath10k_tpc_stats_read(struct file *file, char __user *user_buf,1677				     size_t count, loff_t *ppos)1678{1679	const char *buf = file->private_data;1680	size_t len = strlen(buf);1681 1682	return simple_read_from_buffer(user_buf, count, ppos, buf, len);1683}1684 1685static const struct file_operations fops_tpc_stats = {1686	.open = ath10k_tpc_stats_open,1687	.release = ath10k_tpc_stats_release,1688	.read = ath10k_tpc_stats_read,1689	.owner = THIS_MODULE,1690	.llseek = default_llseek,1691};1692 1693int ath10k_debug_start(struct ath10k *ar)1694{1695	int ret;1696 1697	lockdep_assert_held(&ar->conf_mutex);1698 1699	ret = ath10k_debug_htt_stats_req(ar);1700	if (ret)1701		/* continue normally anyway, this isn't serious */1702		ath10k_warn(ar, "failed to start htt stats workqueue: %d\n",1703			    ret);1704 1705	if (ar->debug.fw_dbglog_mask) {1706		ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,1707					    ATH10K_DBGLOG_LEVEL_WARN);1708		if (ret)1709			/* not serious */1710			ath10k_warn(ar, "failed to enable dbglog during start: %d",1711				    ret);1712	}1713 1714	if (ar->pktlog_filter) {1715		ret = ath10k_wmi_pdev_pktlog_enable(ar,1716						    ar->pktlog_filter);1717		if (ret)1718			/* not serious */1719			ath10k_warn(ar,1720				    "failed to enable pktlog filter %x: %d\n",1721				    ar->pktlog_filter, ret);1722	} else {1723		ret = ath10k_wmi_pdev_pktlog_disable(ar);1724		if (ret)1725			/* not serious */1726			ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);1727	}1728 1729	if (ar->debug.nf_cal_period &&1730	    !test_bit(ATH10K_FW_FEATURE_NON_BMI,1731		      ar->normal_mode_fw.fw_file.fw_features)) {1732		ret = ath10k_wmi_pdev_set_param(ar,1733						ar->wmi.pdev_param->cal_period,1734						ar->debug.nf_cal_period);1735		if (ret)1736			/* not serious */1737			ath10k_warn(ar, "cal period cfg failed from debug start: %d\n",1738				    ret);1739	}1740 1741	return ret;1742}1743 1744void ath10k_debug_stop(struct ath10k *ar)1745{1746	lockdep_assert_held(&ar->conf_mutex);1747 1748	if (!test_bit(ATH10K_FW_FEATURE_NON_BMI,1749		      ar->normal_mode_fw.fw_file.fw_features))1750		ath10k_debug_cal_data_fetch(ar);1751 1752	/* Must not use _sync to avoid deadlock, we do that in1753	 * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid1754	 * warning from del_timer().1755	 */1756	if (ar->debug.htt_stats_mask != 0)1757		cancel_delayed_work(&ar->debug.htt_stats_dwork);1758 1759	ath10k_wmi_pdev_pktlog_disable(ar);1760}1761 1762static ssize_t ath10k_write_simulate_radar(struct file *file,1763					   const char __user *user_buf,1764					   size_t count, loff_t *ppos)1765{1766	struct ath10k *ar = file->private_data;1767	struct ath10k_vif *arvif;1768 1769	/* Just check for the first vif alone, as all the vifs will be1770	 * sharing the same channel and if the channel is disabled, all the1771	 * vifs will share the same 'is_started' state.1772	 */1773	arvif = list_first_entry(&ar->arvifs, typeof(*arvif), list);1774	if (!arvif->is_started)1775		return -EINVAL;1776 1777	ieee80211_radar_detected(ar->hw, NULL);1778 1779	return count;1780}1781 1782static const struct file_operations fops_simulate_radar = {1783	.write = ath10k_write_simulate_radar,1784	.open = simple_open,1785	.owner = THIS_MODULE,1786	.llseek = default_llseek,1787};1788 1789#define ATH10K_DFS_STAT(s, p) (\1790	len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \1791			 ar->debug.dfs_stats.p))1792 1793#define ATH10K_DFS_POOL_STAT(s, p) (\1794	len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \1795			 ar->debug.dfs_pool_stats.p))1796 1797static ssize_t ath10k_read_dfs_stats(struct file *file, char __user *user_buf,1798				     size_t count, loff_t *ppos)1799{1800	int retval = 0, len = 0;1801	const int size = 8000;1802	struct ath10k *ar = file->private_data;1803	char *buf;1804 1805	buf = kzalloc(size, GFP_KERNEL);1806	if (buf == NULL)1807		return -ENOMEM;1808 1809	if (!ar->dfs_detector) {1810		len += scnprintf(buf + len, size - len, "DFS not enabled\n");1811		goto exit;1812	}1813 1814	ar->debug.dfs_pool_stats =1815			ar->dfs_detector->get_stats(ar->dfs_detector);1816 1817	len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n");1818 1819	ATH10K_DFS_STAT("reported phy errors", phy_errors);1820	ATH10K_DFS_STAT("pulse events reported", pulses_total);1821	ATH10K_DFS_STAT("DFS pulses detected", pulses_detected);1822	ATH10K_DFS_STAT("DFS pulses discarded", pulses_discarded);1823	ATH10K_DFS_STAT("Radars detected", radar_detected);1824 1825	len += scnprintf(buf + len, size - len, "Global Pool statistics:\n");1826	ATH10K_DFS_POOL_STAT("Pool references", pool_reference);1827	ATH10K_DFS_POOL_STAT("Pulses allocated", pulse_allocated);1828	ATH10K_DFS_POOL_STAT("Pulses alloc error", pulse_alloc_error);1829	ATH10K_DFS_POOL_STAT("Pulses in use", pulse_used);1830	ATH10K_DFS_POOL_STAT("Seqs. allocated", pseq_allocated);1831	ATH10K_DFS_POOL_STAT("Seqs. alloc error", pseq_alloc_error);1832	ATH10K_DFS_POOL_STAT("Seqs. in use", pseq_used);1833 1834exit:1835	if (len > size)1836		len = size;1837 1838	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);1839	kfree(buf);1840 1841	return retval;1842}1843 1844static const struct file_operations fops_dfs_stats = {1845	.read = ath10k_read_dfs_stats,1846	.open = simple_open,1847	.owner = THIS_MODULE,1848	.llseek = default_llseek,1849};1850 1851static ssize_t ath10k_write_pktlog_filter(struct file *file,1852					  const char __user *ubuf,1853					  size_t count, loff_t *ppos)1854{1855	struct ath10k *ar = file->private_data;1856	u32 filter;1857	int ret;1858 1859	if (kstrtouint_from_user(ubuf, count, 0, &filter))1860		return -EINVAL;1861 1862	mutex_lock(&ar->conf_mutex);1863 1864	if (ar->state != ATH10K_STATE_ON) {1865		ar->pktlog_filter = filter;1866		ret = count;1867		goto out;1868	}1869 1870	if (filter == ar->pktlog_filter) {1871		ret = count;1872		goto out;1873	}1874 1875	if (filter) {1876		ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);1877		if (ret) {1878			ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",1879				    ar->pktlog_filter, ret);1880			goto out;1881		}1882	} else {1883		ret = ath10k_wmi_pdev_pktlog_disable(ar);1884		if (ret) {1885			ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);1886			goto out;1887		}1888	}1889 1890	ar->pktlog_filter = filter;1891	ret = count;1892 1893out:1894	mutex_unlock(&ar->conf_mutex);1895	return ret;1896}1897 1898static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf,1899					 size_t count, loff_t *ppos)1900{1901	char buf[32];1902	struct ath10k *ar = file->private_data;1903	int len = 0;1904 1905	mutex_lock(&ar->conf_mutex);1906	len = scnprintf(buf, sizeof(buf) - len, "%08x\n",1907			ar->pktlog_filter);1908	mutex_unlock(&ar->conf_mutex);1909 1910	return simple_read_from_buffer(ubuf, count, ppos, buf, len);1911}1912 1913static const struct file_operations fops_pktlog_filter = {1914	.read = ath10k_read_pktlog_filter,1915	.write = ath10k_write_pktlog_filter,1916	.open = simple_open1917};1918 1919static ssize_t ath10k_write_quiet_period(struct file *file,1920					 const char __user *ubuf,1921					 size_t count, loff_t *ppos)1922{1923	struct ath10k *ar = file->private_data;1924	u32 period;1925 1926	if (kstrtouint_from_user(ubuf, count, 0, &period))1927		return -EINVAL;1928 1929	if (period < ATH10K_QUIET_PERIOD_MIN) {1930		ath10k_warn(ar, "Quiet period %u can not be lesser than 25ms\n",1931			    period);1932		return -EINVAL;1933	}1934	mutex_lock(&ar->conf_mutex);1935	ar->thermal.quiet_period = period;1936	ath10k_thermal_set_throttling(ar);1937	mutex_unlock(&ar->conf_mutex);1938 1939	return count;1940}1941 1942static ssize_t ath10k_read_quiet_period(struct file *file, char __user *ubuf,1943					size_t count, loff_t *ppos)1944{1945	char buf[32];1946	struct ath10k *ar = file->private_data;1947	int len = 0;1948 1949	mutex_lock(&ar->conf_mutex);1950	len = scnprintf(buf, sizeof(buf) - len, "%d\n",1951			ar->thermal.quiet_period);1952	mutex_unlock(&ar->conf_mutex);1953 1954	return simple_read_from_buffer(ubuf, count, ppos, buf, len);1955}1956 1957static const struct file_operations fops_quiet_period = {1958	.read = ath10k_read_quiet_period,1959	.write = ath10k_write_quiet_period,1960	.open = simple_open1961};1962 1963static ssize_t ath10k_write_btcoex(struct file *file,1964				   const char __user *ubuf,1965				   size_t count, loff_t *ppos)1966{1967	struct ath10k *ar = file->private_data;1968	ssize_t ret;1969	bool val;1970	u32 pdev_param;1971 1972	ret = kstrtobool_from_user(ubuf, count, &val);1973	if (ret)1974		return ret;1975 1976	if (!ar->coex_support)1977		return -EOPNOTSUPP;1978 1979	mutex_lock(&ar->conf_mutex);1980 1981	if (ar->state != ATH10K_STATE_ON &&1982	    ar->state != ATH10K_STATE_RESTARTED) {1983		ret = -ENETDOWN;1984		goto exit;1985	}1986 1987	if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val)) {1988		ret = count;1989		goto exit;1990	}1991 1992	pdev_param = ar->wmi.pdev_param->enable_btcoex;1993	if (test_bit(ATH10K_FW_FEATURE_BTCOEX_PARAM,1994		     ar->running_fw->fw_file.fw_features)) {1995		ret = ath10k_wmi_pdev_set_param(ar, pdev_param, val);1996		if (ret) {1997			ath10k_warn(ar, "failed to enable btcoex: %zd\n", ret);1998			ret = count;1999			goto exit;2000		}2001	} else {2002		ath10k_info(ar, "restarting firmware due to btcoex change");2003		ath10k_core_start_recovery(ar);2004	}2005 2006	if (val)2007		set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);2008	else2009		clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);2010 2011	ret = count;2012 2013exit:2014	mutex_unlock(&ar->conf_mutex);2015 2016	return ret;2017}2018 2019static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf,2020				  size_t count, loff_t *ppos)2021{2022	char buf[32];2023	struct ath10k *ar = file->private_data;2024	int len = 0;2025 2026	mutex_lock(&ar->conf_mutex);2027	len = scnprintf(buf, sizeof(buf) - len, "%d\n",2028			test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags));2029	mutex_unlock(&ar->conf_mutex);2030 2031	return simple_read_from_buffer(ubuf, count, ppos, buf, len);2032}2033 2034static const struct file_operations fops_btcoex = {2035	.read = ath10k_read_btcoex,2036	.write = ath10k_write_btcoex,2037	.open = simple_open2038};2039 2040static ssize_t ath10k_write_enable_extd_tx_stats(struct file *file,2041						 const char __user *ubuf,2042						 size_t count, loff_t *ppos)2043{2044	struct ath10k *ar = file->private_data;2045	u32 filter;2046	int ret;2047 2048	if (kstrtouint_from_user(ubuf, count, 0, &filter))2049		return -EINVAL;2050 2051	mutex_lock(&ar->conf_mutex);2052 2053	if (ar->state != ATH10K_STATE_ON) {2054		ar->debug.enable_extd_tx_stats = filter;2055		ret = count;2056		goto out;2057	}2058 2059	if (filter == ar->debug.enable_extd_tx_stats) {2060		ret = count;2061		goto out;2062	}2063 2064	ar->debug.enable_extd_tx_stats = filter;2065	ret = count;2066 2067out:2068	mutex_unlock(&ar->conf_mutex);2069	return ret;2070}2071 2072static ssize_t ath10k_read_enable_extd_tx_stats(struct file *file,2073						char __user *ubuf,2074						size_t count, loff_t *ppos)2075 2076{2077	char buf[32];2078	struct ath10k *ar = file->private_data;2079	int len = 0;2080 2081	mutex_lock(&ar->conf_mutex);2082	len = scnprintf(buf, sizeof(buf) - len, "%08x\n",2083			ar->debug.enable_extd_tx_stats);2084	mutex_unlock(&ar->conf_mutex);2085 2086	return simple_read_from_buffer(ubuf, count, ppos, buf, len);2087}2088 2089static const struct file_operations fops_enable_extd_tx_stats = {2090	.read = ath10k_read_enable_extd_tx_stats,2091	.write = ath10k_write_enable_extd_tx_stats,2092	.open = simple_open2093};2094 2095static ssize_t ath10k_write_peer_stats(struct file *file,2096				       const char __user *ubuf,2097				       size_t count, loff_t *ppos)2098{2099	struct ath10k *ar = file->private_data;2100	ssize_t ret;2101	bool val;2102 2103	ret = kstrtobool_from_user(ubuf, count, &val);2104	if (ret)2105		return ret;2106 2107	mutex_lock(&ar->conf_mutex);2108 2109	if (ar->state != ATH10K_STATE_ON &&2110	    ar->state != ATH10K_STATE_RESTARTED) {2111		ret = -ENETDOWN;2112		goto exit;2113	}2114 2115	if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val)) {2116		ret = count;2117		goto exit;2118	}2119 2120	if (val)2121		set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);2122	else2123		clear_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);2124 2125	ath10k_info(ar, "restarting firmware due to Peer stats change");2126 2127	ath10k_core_start_recovery(ar);2128	ret = count;2129 2130exit:2131	mutex_unlock(&ar->conf_mutex);2132	return ret;2133}2134 2135static ssize_t ath10k_read_peer_stats(struct file *file, char __user *ubuf,2136				      size_t count, loff_t *ppos)2137 2138{2139	char buf[32];2140	struct ath10k *ar = file->private_data;2141	int len = 0;2142 2143	mutex_lock(&ar->conf_mutex);2144	len = scnprintf(buf, sizeof(buf) - len, "%d\n",2145			test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags));2146	mutex_unlock(&ar->conf_mutex);2147 2148	return simple_read_from_buffer(ubuf, count, ppos, buf, len);2149}2150 2151static const struct file_operations fops_peer_stats = {2152	.read = ath10k_read_peer_stats,2153	.write = ath10k_write_peer_stats,2154	.open = simple_open2155};2156 2157static ssize_t ath10k_debug_fw_checksums_read(struct file *file,2158					      char __user *user_buf,2159					      size_t count, loff_t *ppos)2160{2161	struct ath10k *ar = file->private_data;2162	size_t len = 0, buf_len = 4096;2163	ssize_t ret_cnt;2164	char *buf;2165 2166	buf = kzalloc(buf_len, GFP_KERNEL);2167	if (!buf)2168		return -ENOMEM;2169 2170	mutex_lock(&ar->conf_mutex);2171 2172	len += scnprintf(buf + len, buf_len - len,2173			 "firmware-N.bin\t\t%08x\n",2174			 crc32_le(0, ar->normal_mode_fw.fw_file.firmware->data,2175				  ar->normal_mode_fw.fw_file.firmware->size));2176	len += scnprintf(buf + len, buf_len - len,2177			 "athwlan\t\t\t%08x\n",2178			 crc32_le(0, ar->normal_mode_fw.fw_file.firmware_data,2179				  ar->normal_mode_fw.fw_file.firmware_len));2180	len += scnprintf(buf + len, buf_len - len,2181			 "otp\t\t\t%08x\n",2182			 crc32_le(0, ar->normal_mode_fw.fw_file.otp_data,2183				  ar->normal_mode_fw.fw_file.otp_len));2184	len += scnprintf(buf + len, buf_len - len,2185			 "codeswap\t\t%08x\n",2186			 crc32_le(0, ar->normal_mode_fw.fw_file.codeswap_data,2187				  ar->normal_mode_fw.fw_file.codeswap_len));2188	len += scnprintf(buf + len, buf_len - len,2189			 "board-N.bin\t\t%08x\n",2190			 crc32_le(0, ar->normal_mode_fw.board->data,2191				  ar->normal_mode_fw.board->size));2192	len += scnprintf(buf + len, buf_len - len,2193			 "board\t\t\t%08x\n",2194			 crc32_le(0, ar->normal_mode_fw.board_data,2195				  ar->normal_mode_fw.board_len));2196 2197	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);2198 2199	mutex_unlock(&ar->conf_mutex);2200 2201	kfree(buf);2202	return ret_cnt;2203}2204 2205static const struct file_operations fops_fw_checksums = {2206	.read = ath10k_debug_fw_checksums_read,2207	.open = simple_open,2208	.owner = THIS_MODULE,2209	.llseek = default_llseek,2210};2211 2212static ssize_t ath10k_sta_tid_stats_mask_read(struct file *file,2213					      char __user *user_buf,2214					      size_t count, loff_t *ppos)2215{2216	struct ath10k *ar = file->private_data;2217	char buf[32];2218	size_t len;2219 2220	len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->sta_tid_stats_mask);2221	return simple_read_from_buffer(user_buf, count, ppos, buf, len);2222}2223 2224static ssize_t ath10k_sta_tid_stats_mask_write(struct file *file,2225					       const char __user *user_buf,2226					       size_t count, loff_t *ppos)2227{2228	struct ath10k *ar = file->private_data;2229	ssize_t ret;2230	u32 mask;2231 2232	ret = kstrtoint_from_user(user_buf, count, 0, &mask);2233	if (ret)2234		return ret;2235 2236	ar->sta_tid_stats_mask = mask;2237 2238	return count;2239}2240 2241static const struct file_operations fops_sta_tid_stats_mask = {2242	.read = ath10k_sta_tid_stats_mask_read,2243	.write = ath10k_sta_tid_stats_mask_write,2244	.open = simple_open,2245	.owner = THIS_MODULE,2246	.llseek = default_llseek,2247};2248 2249static int ath10k_debug_tpc_stats_final_request(struct ath10k *ar)2250{2251	int ret;2252	unsigned long time_left;2253 2254	lockdep_assert_held(&ar->conf_mutex);2255 2256	reinit_completion(&ar->debug.tpc_complete);2257 2258	ret = ath10k_wmi_pdev_get_tpc_table_cmdid(ar, WMI_TPC_CONFIG_PARAM);2259	if (ret) {2260		ath10k_warn(ar, "failed to request tpc table cmdid: %d\n", ret);2261		return ret;2262	}2263 2264	time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,2265						1 * HZ);2266	if (time_left == 0)2267		return -ETIMEDOUT;2268 2269	return 0;2270}2271 2272static int ath10k_tpc_stats_final_open(struct inode *inode, struct file *file)2273{2274	struct ath10k *ar = inode->i_private;2275	void *buf;2276	int ret;2277 2278	mutex_lock(&ar->conf_mutex);2279 2280	if (ar->state != ATH10K_STATE_ON) {2281		ret = -ENETDOWN;2282		goto err_unlock;2283	}2284 2285	buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);2286	if (!buf) {2287		ret = -ENOMEM;2288		goto err_unlock;2289	}2290 2291	ret = ath10k_debug_tpc_stats_final_request(ar);2292	if (ret) {2293		ath10k_warn(ar, "failed to request tpc stats final: %d\n",2294			    ret);2295		goto err_free;2296	}2297 2298	ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);2299	file->private_data = buf;2300 2301	mutex_unlock(&ar->conf_mutex);2302	return 0;2303 2304err_free:2305	vfree(buf);2306 2307err_unlock:2308	mutex_unlock(&ar->conf_mutex);2309	return ret;2310}2311 2312static int ath10k_tpc_stats_final_release(struct inode *inode,2313					  struct file *file)2314{2315	vfree(file->private_data);2316 2317	return 0;2318}2319 2320static ssize_t ath10k_tpc_stats_final_read(struct file *file,2321					   char __user *user_buf,2322					   size_t count, loff_t *ppos)2323{2324	const char *buf = file->private_data;2325	unsigned int len = strlen(buf);2326 2327	return simple_read_from_buffer(user_buf, count, ppos, buf, len);2328}2329 2330static const struct file_operations fops_tpc_stats_final = {2331	.open = ath10k_tpc_stats_final_open,2332	.release = ath10k_tpc_stats_final_release,2333	.read = ath10k_tpc_stats_final_read,2334	.owner = THIS_MODULE,2335	.llseek = default_llseek,2336};2337 2338static ssize_t ath10k_write_warm_hw_reset(struct file *file,2339					  const char __user *user_buf,2340					  size_t count, loff_t *ppos)2341{2342	struct ath10k *ar = file->private_data;2343	int ret;2344	bool val;2345 2346	if (kstrtobool_from_user(user_buf, count, &val))2347		return -EFAULT;2348 2349	if (!val)2350		return -EINVAL;2351 2352	mutex_lock(&ar->conf_mutex);2353 2354	if (ar->state != ATH10K_STATE_ON) {2355		ret = -ENETDOWN;2356		goto exit;2357	}2358 2359	ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->pdev_reset,2360					WMI_RST_MODE_WARM_RESET);2361 2362	if (ret) {2363		ath10k_warn(ar, "failed to enable warm hw reset: %d\n", ret);2364		goto exit;2365	}2366 2367	ret = count;2368 2369exit:2370	mutex_unlock(&ar->conf_mutex);2371	return ret;2372}2373 2374static const struct file_operations fops_warm_hw_reset = {2375	.write = ath10k_write_warm_hw_reset,2376	.open = simple_open,2377	.owner = THIS_MODULE,2378	.llseek = default_llseek,2379};2380 2381static void ath10k_peer_ps_state_disable(void *data,2382					 struct ieee80211_sta *sta)2383{2384	struct ath10k *ar = data;2385	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;2386 2387	spin_lock_bh(&ar->data_lock);2388	arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;2389	spin_unlock_bh(&ar->data_lock);2390}2391 2392static ssize_t ath10k_write_ps_state_enable(struct file *file,2393					    const char __user *user_buf,2394					    size_t count, loff_t *ppos)2395{2396	struct ath10k *ar = file->private_data;2397	int ret;2398	u32 param;2399	u8 ps_state_enable;2400 2401	if (kstrtou8_from_user(user_buf, count, 0, &ps_state_enable))2402		return -EINVAL;2403 2404	if (ps_state_enable > 1)2405		return -EINVAL;2406 2407	mutex_lock(&ar->conf_mutex);2408 2409	if (ar->ps_state_enable == ps_state_enable) {2410		ret = count;2411		goto exit;2412	}2413 2414	param = ar->wmi.pdev_param->peer_sta_ps_statechg_enable;2415	ret = ath10k_wmi_pdev_set_param(ar, param, ps_state_enable);2416	if (ret) {2417		ath10k_warn(ar, "failed to enable ps_state_enable: %d\n",2418			    ret);2419		goto exit;2420	}2421	ar->ps_state_enable = ps_state_enable;2422 2423	if (!ar->ps_state_enable)2424		ieee80211_iterate_stations_atomic(ar->hw,2425						  ath10k_peer_ps_state_disable,2426						  ar);2427 2428	ret = count;2429 2430exit:2431	mutex_unlock(&ar->conf_mutex);2432 2433	return ret;2434}2435 2436static ssize_t ath10k_read_ps_state_enable(struct file *file,2437					   char __user *user_buf,2438					   size_t count, loff_t *ppos)2439{2440	struct ath10k *ar = file->private_data;2441	int len = 0;2442	char buf[32];2443 2444	mutex_lock(&ar->conf_mutex);2445	len = scnprintf(buf, sizeof(buf) - len, "%d\n",2446			ar->ps_state_enable);2447	mutex_unlock(&ar->conf_mutex);2448 2449	return simple_read_from_buffer(user_buf, count, ppos, buf, len);2450}2451 2452static const struct file_operations fops_ps_state_enable = {2453	.read = ath10k_read_ps_state_enable,2454	.write = ath10k_write_ps_state_enable,2455	.open = simple_open,2456	.owner = THIS_MODULE,2457	.llseek = default_llseek,2458};2459 2460static ssize_t ath10k_write_reset_htt_stats(struct file *file,2461					    const char __user *user_buf,2462					    size_t count, loff_t *ppos)2463{2464	struct ath10k *ar = file->private_data;2465	unsigned long reset;2466	int ret;2467 2468	ret = kstrtoul_from_user(user_buf, count, 0, &reset);2469	if (ret)2470		return ret;2471 2472	if (reset == 0 || reset > 0x1ffff)2473		return -EINVAL;2474 2475	mutex_lock(&ar->conf_mutex);2476 2477	ar->debug.reset_htt_stats = reset;2478 2479	ret = ath10k_debug_htt_stats_req(ar);2480	if (ret)2481		goto out;2482 2483	ar->debug.reset_htt_stats = 0;2484	ret = count;2485 2486out:2487	mutex_unlock(&ar->conf_mutex);2488	return ret;2489}2490 2491static const struct file_operations fops_reset_htt_stats = {2492	.write = ath10k_write_reset_htt_stats,2493	.owner = THIS_MODULE,2494	.open = simple_open,2495	.llseek = default_llseek,2496};2497 2498int ath10k_debug_create(struct ath10k *ar)2499{2500	ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);2501	if (!ar->debug.cal_data)2502		return -ENOMEM;2503 2504	INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);2505	INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);2506	INIT_LIST_HEAD(&ar->debug.fw_stats.peers);2507	INIT_LIST_HEAD(&ar->debug.fw_stats.peers_extd);2508 2509	return 0;2510}2511 2512void ath10k_debug_destroy(struct ath10k *ar)2513{2514	vfree(ar->debug.cal_data);2515	ar->debug.cal_data = NULL;2516 2517	ath10k_debug_fw_stats_reset(ar);2518 2519	kfree(ar->debug.tpc_stats);2520	kfree(ar->debug.tpc_stats_final);2521}2522 2523int ath10k_debug_register(struct ath10k *ar)2524{2525	ar->debug.debugfs_phy = debugfs_create_dir("ath10k",2526						   ar->hw->wiphy->debugfsdir);2527	if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {2528		if (IS_ERR(ar->debug.debugfs_phy))2529			return PTR_ERR(ar->debug.debugfs_phy);2530 2531		return -ENOMEM;2532	}2533 2534	INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,2535			  ath10k_debug_htt_stats_dwork);2536 2537	init_completion(&ar->debug.tpc_complete);2538	init_completion(&ar->debug.fw_stats_complete);2539 2540	debugfs_create_file("fw_stats", 0400, ar->debug.debugfs_phy, ar,2541			    &fops_fw_stats);2542 2543	debugfs_create_file("fw_reset_stats", 0400, ar->debug.debugfs_phy, ar,2544			    &fops_fw_reset_stats);2545 2546	debugfs_create_file("wmi_services", 0400, ar->debug.debugfs_phy, ar,2547			    &fops_wmi_services);2548 2549	debugfs_create_file("simulate_fw_crash", 0600, ar->debug.debugfs_phy, ar,2550			    &fops_simulate_fw_crash);2551 2552	debugfs_create_file("reg_addr", 0600, ar->debug.debugfs_phy, ar,2553			    &fops_reg_addr);2554 2555	debugfs_create_file("reg_value", 0600, ar->debug.debugfs_phy, ar,2556			    &fops_reg_value);2557 2558	debugfs_create_file("mem_value", 0600, ar->debug.debugfs_phy, ar,2559			    &fops_mem_value);2560 2561	debugfs_create_file("chip_id", 0400, ar->debug.debugfs_phy, ar,2562			    &fops_chip_id);2563 2564	debugfs_create_file("htt_stats_mask", 0600, ar->debug.debugfs_phy, ar,2565			    &fops_htt_stats_mask);2566 2567	debugfs_create_file("htt_max_amsdu_ampdu", 0600, ar->debug.debugfs_phy, ar,2568			    &fops_htt_max_amsdu_ampdu);2569 2570	debugfs_create_file("fw_dbglog", 0600, ar->debug.debugfs_phy, ar,2571			    &fops_fw_dbglog);2572 2573	if (!test_bit(ATH10K_FW_FEATURE_NON_BMI,2574		      ar->normal_mode_fw.fw_file.fw_features)) {2575		debugfs_create_file("cal_data", 0400, ar->debug.debugfs_phy, ar,2576				    &fops_cal_data);2577 2578		debugfs_create_file("nf_cal_period", 0600, ar->debug.debugfs_phy, ar,2579				    &fops_nf_cal_period);2580	}2581 2582	debugfs_create_file("ani_enable", 0600, ar->debug.debugfs_phy, ar,2583			    &fops_ani_enable);2584 2585	if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED)) {2586		debugfs_create_file("dfs_simulate_radar", 0200, ar->debug.debugfs_phy,2587				    ar, &fops_simulate_radar);2588 2589		debugfs_create_bool("dfs_block_radar_events", 0200,2590				    ar->debug.debugfs_phy,2591				    &ar->dfs_block_radar_events);2592 2593		debugfs_create_file("dfs_stats", 0400, ar->debug.debugfs_phy, ar,2594				    &fops_dfs_stats);2595	}2596 2597	debugfs_create_file("pktlog_filter", 0644, ar->debug.debugfs_phy, ar,2598			    &fops_pktlog_filter);2599 2600	if (test_bit(WMI_SERVICE_THERM_THROT, ar->wmi.svc_map))2601		debugfs_create_file("quiet_period", 0644, ar->debug.debugfs_phy, ar,2602				    &fops_quiet_period);2603 2604	debugfs_create_file("tpc_stats", 0400, ar->debug.debugfs_phy, ar,2605			    &fops_tpc_stats);2606 2607	if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))2608		debugfs_create_file("btcoex", 0644, ar->debug.debugfs_phy, ar,2609				    &fops_btcoex);2610 2611	if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) {2612		debugfs_create_file("peer_stats", 0644, ar->debug.debugfs_phy, ar,2613				    &fops_peer_stats);2614 2615		debugfs_create_file("enable_extd_tx_stats", 0644,2616				    ar->debug.debugfs_phy, ar,2617				    &fops_enable_extd_tx_stats);2618	}2619 2620	debugfs_create_file("fw_checksums", 0400, ar->debug.debugfs_phy, ar,2621			    &fops_fw_checksums);2622 2623	if (IS_ENABLED(CONFIG_MAC80211_DEBUGFS))2624		debugfs_create_file("sta_tid_stats_mask", 0600,2625				    ar->debug.debugfs_phy,2626				    ar, &fops_sta_tid_stats_mask);2627 2628	if (test_bit(WMI_SERVICE_TPC_STATS_FINAL, ar->wmi.svc_map))2629		debugfs_create_file("tpc_stats_final", 0400,2630				    ar->debug.debugfs_phy, ar,2631				    &fops_tpc_stats_final);2632 2633	if (test_bit(WMI_SERVICE_RESET_CHIP, ar->wmi.svc_map))2634		debugfs_create_file("warm_hw_reset", 0600,2635				    ar->debug.debugfs_phy, ar,2636				    &fops_warm_hw_reset);2637 2638	debugfs_create_file("ps_state_enable", 0600, ar->debug.debugfs_phy, ar,2639			    &fops_ps_state_enable);2640 2641	debugfs_create_file("reset_htt_stats", 0200, ar->debug.debugfs_phy, ar,2642			    &fops_reset_htt_stats);2643 2644	return 0;2645}2646 2647void ath10k_debug_unregister(struct ath10k *ar)2648{2649	cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);2650}2651 2652#endif /* CONFIG_ATH10K_DEBUGFS */2653 2654#ifdef CONFIG_ATH10K_DEBUG2655void __ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,2656		  const char *fmt, ...)2657{2658	struct va_format vaf;2659	va_list args;2660 2661	va_start(args, fmt);2662 2663	vaf.fmt = fmt;2664	vaf.va = &args;2665 2666	if (ath10k_debug_mask & mask)2667		dev_printk(KERN_DEBUG, ar->dev, "%pV", &vaf);2668 2669	trace_ath10k_log_dbg(ar, mask, &vaf);2670 2671	va_end(args);2672}2673EXPORT_SYMBOL(__ath10k_dbg);2674 2675void ath10k_dbg_dump(struct ath10k *ar,2676		     enum ath10k_debug_mask mask,2677		     const char *msg, const char *prefix,2678		     const void *buf, size_t len)2679{2680	char linebuf[256];2681	size_t linebuflen;2682	const void *ptr;2683 2684	if (ath10k_debug_mask & mask) {2685		if (msg)2686			__ath10k_dbg(ar, mask, "%s\n", msg);2687 2688		for (ptr = buf; (ptr - buf) < len; ptr += 16) {2689			linebuflen = 0;2690			linebuflen += scnprintf(linebuf + linebuflen,2691						sizeof(linebuf) - linebuflen,2692						"%s%08x: ",2693						(prefix ? prefix : ""),2694						(unsigned int)(ptr - buf));2695			hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,2696					   linebuf + linebuflen,2697					   sizeof(linebuf) - linebuflen, true);2698			dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);2699		}2700	}2701 2702	/* tracing code doesn't like null strings :/ */2703	trace_ath10k_log_dbg_dump(ar, msg ? msg : "", prefix ? prefix : "",2704				  buf, len);2705}2706EXPORT_SYMBOL(ath10k_dbg_dump);2707 2708#endif /* CONFIG_ATH10K_DEBUG */2709