1ad306d68SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
27ac9a364SKalle Valo /******************************************************************************
37ac9a364SKalle Valo  *
47ac9a364SKalle Valo  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
57ac9a364SKalle Valo  *
67ac9a364SKalle Valo  * Contact Information:
77ac9a364SKalle Valo  *  Intel Linux Wireless <ilw@linux.intel.com>
87ac9a364SKalle Valo  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
97ac9a364SKalle Valo  *****************************************************************************/
107ac9a364SKalle Valo #include <linux/ieee80211.h>
117ac9a364SKalle Valo #include <linux/export.h>
127ac9a364SKalle Valo #include <net/mac80211.h>
137ac9a364SKalle Valo 
147ac9a364SKalle Valo #include "common.h"
157ac9a364SKalle Valo 
167ac9a364SKalle Valo static void
il_clear_traffic_stats(struct il_priv * il)177ac9a364SKalle Valo il_clear_traffic_stats(struct il_priv *il)
187ac9a364SKalle Valo {
197ac9a364SKalle Valo 	memset(&il->tx_stats, 0, sizeof(struct traffic_stats));
207ac9a364SKalle Valo 	memset(&il->rx_stats, 0, sizeof(struct traffic_stats));
217ac9a364SKalle Valo }
227ac9a364SKalle Valo 
237ac9a364SKalle Valo /*
247ac9a364SKalle Valo  * il_update_stats function record all the MGMT, CTRL and DATA pkt for
257ac9a364SKalle Valo  * both TX and Rx . Use debugfs to display the rx/rx_stats
267ac9a364SKalle Valo  */
277ac9a364SKalle Valo void
il_update_stats(struct il_priv * il,bool is_tx,__le16 fc,u16 len)287ac9a364SKalle Valo il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len)
297ac9a364SKalle Valo {
307ac9a364SKalle Valo 	struct traffic_stats *stats;
317ac9a364SKalle Valo 
327ac9a364SKalle Valo 	if (is_tx)
337ac9a364SKalle Valo 		stats = &il->tx_stats;
347ac9a364SKalle Valo 	else
357ac9a364SKalle Valo 		stats = &il->rx_stats;
367ac9a364SKalle Valo 
377ac9a364SKalle Valo 	if (ieee80211_is_mgmt(fc)) {
387ac9a364SKalle Valo 		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
397ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
407ac9a364SKalle Valo 			stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
417ac9a364SKalle Valo 			break;
427ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
437ac9a364SKalle Valo 			stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
447ac9a364SKalle Valo 			break;
457ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
467ac9a364SKalle Valo 			stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
477ac9a364SKalle Valo 			break;
487ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
497ac9a364SKalle Valo 			stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
507ac9a364SKalle Valo 			break;
517ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
527ac9a364SKalle Valo 			stats->mgmt[MANAGEMENT_PROBE_REQ]++;
537ac9a364SKalle Valo 			break;
547ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
557ac9a364SKalle Valo 			stats->mgmt[MANAGEMENT_PROBE_RESP]++;
567ac9a364SKalle Valo 			break;
577ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_BEACON):
587ac9a364SKalle Valo 			stats->mgmt[MANAGEMENT_BEACON]++;
597ac9a364SKalle Valo 			break;
607ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_ATIM):
617ac9a364SKalle Valo 			stats->mgmt[MANAGEMENT_ATIM]++;
627ac9a364SKalle Valo 			break;
637ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
647ac9a364SKalle Valo 			stats->mgmt[MANAGEMENT_DISASSOC]++;
657ac9a364SKalle Valo 			break;
667ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_AUTH):
677ac9a364SKalle Valo 			stats->mgmt[MANAGEMENT_AUTH]++;
687ac9a364SKalle Valo 			break;
697ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
707ac9a364SKalle Valo 			stats->mgmt[MANAGEMENT_DEAUTH]++;
717ac9a364SKalle Valo 			break;
727ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_ACTION):
737ac9a364SKalle Valo 			stats->mgmt[MANAGEMENT_ACTION]++;
747ac9a364SKalle Valo 			break;
757ac9a364SKalle Valo 		}
767ac9a364SKalle Valo 	} else if (ieee80211_is_ctl(fc)) {
777ac9a364SKalle Valo 		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
787ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
797ac9a364SKalle Valo 			stats->ctrl[CONTROL_BACK_REQ]++;
807ac9a364SKalle Valo 			break;
817ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_BACK):
827ac9a364SKalle Valo 			stats->ctrl[CONTROL_BACK]++;
837ac9a364SKalle Valo 			break;
847ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
857ac9a364SKalle Valo 			stats->ctrl[CONTROL_PSPOLL]++;
867ac9a364SKalle Valo 			break;
877ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_RTS):
887ac9a364SKalle Valo 			stats->ctrl[CONTROL_RTS]++;
897ac9a364SKalle Valo 			break;
907ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_CTS):
917ac9a364SKalle Valo 			stats->ctrl[CONTROL_CTS]++;
927ac9a364SKalle Valo 			break;
937ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_ACK):
947ac9a364SKalle Valo 			stats->ctrl[CONTROL_ACK]++;
957ac9a364SKalle Valo 			break;
967ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_CFEND):
977ac9a364SKalle Valo 			stats->ctrl[CONTROL_CFEND]++;
987ac9a364SKalle Valo 			break;
997ac9a364SKalle Valo 		case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
1007ac9a364SKalle Valo 			stats->ctrl[CONTROL_CFENDACK]++;
1017ac9a364SKalle Valo 			break;
1027ac9a364SKalle Valo 		}
1037ac9a364SKalle Valo 	} else {
1047ac9a364SKalle Valo 		/* data */
1057ac9a364SKalle Valo 		stats->data_cnt++;
1067ac9a364SKalle Valo 		stats->data_bytes += len;
1077ac9a364SKalle Valo 	}
1087ac9a364SKalle Valo }
1097ac9a364SKalle Valo EXPORT_SYMBOL(il_update_stats);
1107ac9a364SKalle Valo 
1117ac9a364SKalle Valo /* create and remove of files */
1127ac9a364SKalle Valo #define DEBUGFS_ADD_FILE(name, parent, mode) do {			\
11371ee1284SGreg Kroah-Hartman 	debugfs_create_file(#name, mode, parent, il,			\
11471ee1284SGreg Kroah-Hartman 			    &il_dbgfs_##name##_ops);			\
1157ac9a364SKalle Valo } while (0)
1167ac9a364SKalle Valo 
1177ac9a364SKalle Valo #define DEBUGFS_ADD_BOOL(name, parent, ptr) do {			\
11871ee1284SGreg Kroah-Hartman 	debugfs_create_bool(#name, 0600, parent, ptr);			\
1197ac9a364SKalle Valo } while (0)
1207ac9a364SKalle Valo 
1217ac9a364SKalle Valo /* file operation */
1227ac9a364SKalle Valo #define DEBUGFS_READ_FUNC(name)                                         \
1237ac9a364SKalle Valo static ssize_t il_dbgfs_##name##_read(struct file *file,               \
1247ac9a364SKalle Valo 					char __user *user_buf,          \
1257ac9a364SKalle Valo 					size_t count, loff_t *ppos);
1267ac9a364SKalle Valo 
1277ac9a364SKalle Valo #define DEBUGFS_WRITE_FUNC(name)                                        \
1287ac9a364SKalle Valo static ssize_t il_dbgfs_##name##_write(struct file *file,              \
1297ac9a364SKalle Valo 					const char __user *user_buf,    \
1307ac9a364SKalle Valo 					size_t count, loff_t *ppos);
1317ac9a364SKalle Valo 
1327ac9a364SKalle Valo 
1337ac9a364SKalle Valo #define DEBUGFS_READ_FILE_OPS(name)				\
1347ac9a364SKalle Valo 	DEBUGFS_READ_FUNC(name);				\
1357ac9a364SKalle Valo static const struct file_operations il_dbgfs_##name##_ops = {	\
1367ac9a364SKalle Valo 	.read = il_dbgfs_##name##_read,				\
1377ac9a364SKalle Valo 	.open = simple_open,					\
1387ac9a364SKalle Valo 	.llseek = generic_file_llseek,				\
1397ac9a364SKalle Valo };
1407ac9a364SKalle Valo 
1417ac9a364SKalle Valo #define DEBUGFS_WRITE_FILE_OPS(name)				\
1427ac9a364SKalle Valo 	DEBUGFS_WRITE_FUNC(name);				\
1437ac9a364SKalle Valo static const struct file_operations il_dbgfs_##name##_ops = {	\
1447ac9a364SKalle Valo 	.write = il_dbgfs_##name##_write,			\
1457ac9a364SKalle Valo 	.open = simple_open,					\
1467ac9a364SKalle Valo 	.llseek = generic_file_llseek,				\
1477ac9a364SKalle Valo };
1487ac9a364SKalle Valo 
1497ac9a364SKalle Valo #define DEBUGFS_READ_WRITE_FILE_OPS(name)			\
1507ac9a364SKalle Valo 	DEBUGFS_READ_FUNC(name);				\
1517ac9a364SKalle Valo 	DEBUGFS_WRITE_FUNC(name);				\
1527ac9a364SKalle Valo static const struct file_operations il_dbgfs_##name##_ops = {	\
1537ac9a364SKalle Valo 	.write = il_dbgfs_##name##_write,			\
1547ac9a364SKalle Valo 	.read = il_dbgfs_##name##_read,				\
1557ac9a364SKalle Valo 	.open = simple_open,					\
1567ac9a364SKalle Valo 	.llseek = generic_file_llseek,				\
1577ac9a364SKalle Valo };
1587ac9a364SKalle Valo 
1597ac9a364SKalle Valo static const char *
il_get_mgmt_string(int cmd)1607ac9a364SKalle Valo il_get_mgmt_string(int cmd)
1617ac9a364SKalle Valo {
1627ac9a364SKalle Valo 	switch (cmd) {
1637ac9a364SKalle Valo 	IL_CMD(MANAGEMENT_ASSOC_REQ);
1647ac9a364SKalle Valo 	IL_CMD(MANAGEMENT_ASSOC_RESP);
1657ac9a364SKalle Valo 	IL_CMD(MANAGEMENT_REASSOC_REQ);
1667ac9a364SKalle Valo 	IL_CMD(MANAGEMENT_REASSOC_RESP);
1677ac9a364SKalle Valo 	IL_CMD(MANAGEMENT_PROBE_REQ);
1687ac9a364SKalle Valo 	IL_CMD(MANAGEMENT_PROBE_RESP);
1697ac9a364SKalle Valo 	IL_CMD(MANAGEMENT_BEACON);
1707ac9a364SKalle Valo 	IL_CMD(MANAGEMENT_ATIM);
1717ac9a364SKalle Valo 	IL_CMD(MANAGEMENT_DISASSOC);
1727ac9a364SKalle Valo 	IL_CMD(MANAGEMENT_AUTH);
1737ac9a364SKalle Valo 	IL_CMD(MANAGEMENT_DEAUTH);
1747ac9a364SKalle Valo 	IL_CMD(MANAGEMENT_ACTION);
1757ac9a364SKalle Valo 	default:
1767ac9a364SKalle Valo 		return "UNKNOWN";
1777ac9a364SKalle Valo 
1787ac9a364SKalle Valo 	}
1797ac9a364SKalle Valo }
1807ac9a364SKalle Valo 
1817ac9a364SKalle Valo static const char *
il_get_ctrl_string(int cmd)1827ac9a364SKalle Valo il_get_ctrl_string(int cmd)
1837ac9a364SKalle Valo {
1847ac9a364SKalle Valo 	switch (cmd) {
1857ac9a364SKalle Valo 	IL_CMD(CONTROL_BACK_REQ);
1867ac9a364SKalle Valo 	IL_CMD(CONTROL_BACK);
1877ac9a364SKalle Valo 	IL_CMD(CONTROL_PSPOLL);
1887ac9a364SKalle Valo 	IL_CMD(CONTROL_RTS);
1897ac9a364SKalle Valo 	IL_CMD(CONTROL_CTS);
1907ac9a364SKalle Valo 	IL_CMD(CONTROL_ACK);
1917ac9a364SKalle Valo 	IL_CMD(CONTROL_CFEND);
1927ac9a364SKalle Valo 	IL_CMD(CONTROL_CFENDACK);
1937ac9a364SKalle Valo 	default:
1947ac9a364SKalle Valo 		return "UNKNOWN";
1957ac9a364SKalle Valo 
1967ac9a364SKalle Valo 	}
1977ac9a364SKalle Valo }
1987ac9a364SKalle Valo 
1997ac9a364SKalle Valo static ssize_t
il_dbgfs_tx_stats_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)2007ac9a364SKalle Valo il_dbgfs_tx_stats_read(struct file *file, char __user *user_buf, size_t count,
2017ac9a364SKalle Valo 		       loff_t *ppos)
2027ac9a364SKalle Valo {
2037ac9a364SKalle Valo 
2047ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
2057ac9a364SKalle Valo 	char *buf;
2067ac9a364SKalle Valo 	int pos = 0;
2077ac9a364SKalle Valo 
2087ac9a364SKalle Valo 	int cnt;
2097ac9a364SKalle Valo 	ssize_t ret;
2107ac9a364SKalle Valo 	const size_t bufsz =
2117ac9a364SKalle Valo 	    100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
2127ac9a364SKalle Valo 	buf = kzalloc(bufsz, GFP_KERNEL);
2137ac9a364SKalle Valo 	if (!buf)
2147ac9a364SKalle Valo 		return -ENOMEM;
2157ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
2167ac9a364SKalle Valo 	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
2177ac9a364SKalle Valo 		pos +=
2187ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
2197ac9a364SKalle Valo 			      il_get_mgmt_string(cnt), il->tx_stats.mgmt[cnt]);
2207ac9a364SKalle Valo 	}
2217ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
2227ac9a364SKalle Valo 	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
2237ac9a364SKalle Valo 		pos +=
2247ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
2257ac9a364SKalle Valo 			      il_get_ctrl_string(cnt), il->tx_stats.ctrl[cnt]);
2267ac9a364SKalle Valo 	}
2277ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
2287ac9a364SKalle Valo 	pos +=
2297ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
2307ac9a364SKalle Valo 		      il->tx_stats.data_cnt);
2317ac9a364SKalle Valo 	pos +=
2327ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
2337ac9a364SKalle Valo 		      il->tx_stats.data_bytes);
2347ac9a364SKalle Valo 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2357ac9a364SKalle Valo 	kfree(buf);
2367ac9a364SKalle Valo 	return ret;
2377ac9a364SKalle Valo }
2387ac9a364SKalle Valo 
2397ac9a364SKalle Valo static ssize_t
il_dbgfs_clear_traffic_stats_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)2407ac9a364SKalle Valo il_dbgfs_clear_traffic_stats_write(struct file *file,
2417ac9a364SKalle Valo 				   const char __user *user_buf, size_t count,
2427ac9a364SKalle Valo 				   loff_t *ppos)
2437ac9a364SKalle Valo {
2447ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
2457ac9a364SKalle Valo 	u32 clear_flag;
2467ac9a364SKalle Valo 	char buf[8];
2477ac9a364SKalle Valo 	int buf_size;
2487ac9a364SKalle Valo 
2497ac9a364SKalle Valo 	memset(buf, 0, sizeof(buf));
2507ac9a364SKalle Valo 	buf_size = min(count, sizeof(buf) - 1);
2517ac9a364SKalle Valo 	if (copy_from_user(buf, user_buf, buf_size))
2527ac9a364SKalle Valo 		return -EFAULT;
2537ac9a364SKalle Valo 	if (sscanf(buf, "%x", &clear_flag) != 1)
2547ac9a364SKalle Valo 		return -EFAULT;
2557ac9a364SKalle Valo 	il_clear_traffic_stats(il);
2567ac9a364SKalle Valo 
2577ac9a364SKalle Valo 	return count;
2587ac9a364SKalle Valo }
2597ac9a364SKalle Valo 
2607ac9a364SKalle Valo static ssize_t
il_dbgfs_rx_stats_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)2617ac9a364SKalle Valo il_dbgfs_rx_stats_read(struct file *file, char __user *user_buf, size_t count,
2627ac9a364SKalle Valo 		       loff_t *ppos)
2637ac9a364SKalle Valo {
2647ac9a364SKalle Valo 
2657ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
2667ac9a364SKalle Valo 	char *buf;
2677ac9a364SKalle Valo 	int pos = 0;
2687ac9a364SKalle Valo 	int cnt;
2697ac9a364SKalle Valo 	ssize_t ret;
2707ac9a364SKalle Valo 	const size_t bufsz =
2717ac9a364SKalle Valo 	    100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
2727ac9a364SKalle Valo 	buf = kzalloc(bufsz, GFP_KERNEL);
2737ac9a364SKalle Valo 	if (!buf)
2747ac9a364SKalle Valo 		return -ENOMEM;
2757ac9a364SKalle Valo 
2767ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
2777ac9a364SKalle Valo 	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
2787ac9a364SKalle Valo 		pos +=
2797ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
2807ac9a364SKalle Valo 			      il_get_mgmt_string(cnt), il->rx_stats.mgmt[cnt]);
2817ac9a364SKalle Valo 	}
2827ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
2837ac9a364SKalle Valo 	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
2847ac9a364SKalle Valo 		pos +=
2857ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
2867ac9a364SKalle Valo 			      il_get_ctrl_string(cnt), il->rx_stats.ctrl[cnt]);
2877ac9a364SKalle Valo 	}
2887ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
2897ac9a364SKalle Valo 	pos +=
2907ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
2917ac9a364SKalle Valo 		      il->rx_stats.data_cnt);
2927ac9a364SKalle Valo 	pos +=
2937ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
2947ac9a364SKalle Valo 		      il->rx_stats.data_bytes);
2957ac9a364SKalle Valo 
2967ac9a364SKalle Valo 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2977ac9a364SKalle Valo 	kfree(buf);
2987ac9a364SKalle Valo 	return ret;
2997ac9a364SKalle Valo }
3007ac9a364SKalle Valo 
3017ac9a364SKalle Valo #define BYTE1_MASK 0x000000ff;
3027ac9a364SKalle Valo #define BYTE2_MASK 0x0000ffff;
3037ac9a364SKalle Valo #define BYTE3_MASK 0x00ffffff;
3047ac9a364SKalle Valo static ssize_t
il_dbgfs_sram_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)3057ac9a364SKalle Valo il_dbgfs_sram_read(struct file *file, char __user *user_buf, size_t count,
3067ac9a364SKalle Valo 		   loff_t *ppos)
3077ac9a364SKalle Valo {
3087ac9a364SKalle Valo 	u32 val;
3097ac9a364SKalle Valo 	char *buf;
3107ac9a364SKalle Valo 	ssize_t ret;
3117ac9a364SKalle Valo 	int i;
3127ac9a364SKalle Valo 	int pos = 0;
3137ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
3147ac9a364SKalle Valo 	size_t bufsz;
3157ac9a364SKalle Valo 
3167ac9a364SKalle Valo 	/* default is to dump the entire data segment */
3177ac9a364SKalle Valo 	if (!il->dbgfs_sram_offset && !il->dbgfs_sram_len) {
3187ac9a364SKalle Valo 		il->dbgfs_sram_offset = 0x800000;
3197ac9a364SKalle Valo 		if (il->ucode_type == UCODE_INIT)
3207ac9a364SKalle Valo 			il->dbgfs_sram_len = il->ucode_init_data.len;
3217ac9a364SKalle Valo 		else
3227ac9a364SKalle Valo 			il->dbgfs_sram_len = il->ucode_data.len;
3237ac9a364SKalle Valo 	}
3247ac9a364SKalle Valo 	bufsz = 30 + il->dbgfs_sram_len * sizeof(char) * 10;
3257ac9a364SKalle Valo 	buf = kmalloc(bufsz, GFP_KERNEL);
3267ac9a364SKalle Valo 	if (!buf)
3277ac9a364SKalle Valo 		return -ENOMEM;
3287ac9a364SKalle Valo 	pos +=
3297ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
3307ac9a364SKalle Valo 		      il->dbgfs_sram_len);
3317ac9a364SKalle Valo 	pos +=
3327ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
3337ac9a364SKalle Valo 		      il->dbgfs_sram_offset);
3347ac9a364SKalle Valo 	for (i = il->dbgfs_sram_len; i > 0; i -= 4) {
3357ac9a364SKalle Valo 		val =
3367ac9a364SKalle Valo 		    il_read_targ_mem(il,
3377ac9a364SKalle Valo 				     il->dbgfs_sram_offset +
3387ac9a364SKalle Valo 				     il->dbgfs_sram_len - i);
3397ac9a364SKalle Valo 		if (i < 4) {
3407ac9a364SKalle Valo 			switch (i) {
3417ac9a364SKalle Valo 			case 1:
3427ac9a364SKalle Valo 				val &= BYTE1_MASK;
3437ac9a364SKalle Valo 				break;
3447ac9a364SKalle Valo 			case 2:
3457ac9a364SKalle Valo 				val &= BYTE2_MASK;
3467ac9a364SKalle Valo 				break;
3477ac9a364SKalle Valo 			case 3:
3487ac9a364SKalle Valo 				val &= BYTE3_MASK;
3497ac9a364SKalle Valo 				break;
3507ac9a364SKalle Valo 			}
3517ac9a364SKalle Valo 		}
3527ac9a364SKalle Valo 		if (!(i % 16))
3537ac9a364SKalle Valo 			pos += scnprintf(buf + pos, bufsz - pos, "\n");
3547ac9a364SKalle Valo 		pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
3557ac9a364SKalle Valo 	}
3567ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "\n");
3577ac9a364SKalle Valo 
3587ac9a364SKalle Valo 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
3597ac9a364SKalle Valo 	kfree(buf);
3607ac9a364SKalle Valo 	return ret;
3617ac9a364SKalle Valo }
3627ac9a364SKalle Valo 
3637ac9a364SKalle Valo static ssize_t
il_dbgfs_sram_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)3647ac9a364SKalle Valo il_dbgfs_sram_write(struct file *file, const char __user *user_buf,
3657ac9a364SKalle Valo 		    size_t count, loff_t *ppos)
3667ac9a364SKalle Valo {
3677ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
3687ac9a364SKalle Valo 	char buf[64];
3697ac9a364SKalle Valo 	int buf_size;
3707ac9a364SKalle Valo 	u32 offset, len;
3717ac9a364SKalle Valo 
3727ac9a364SKalle Valo 	memset(buf, 0, sizeof(buf));
3737ac9a364SKalle Valo 	buf_size = min(count, sizeof(buf) - 1);
3747ac9a364SKalle Valo 	if (copy_from_user(buf, user_buf, buf_size))
3757ac9a364SKalle Valo 		return -EFAULT;
3767ac9a364SKalle Valo 
3777ac9a364SKalle Valo 	if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
3787ac9a364SKalle Valo 		il->dbgfs_sram_offset = offset;
3797ac9a364SKalle Valo 		il->dbgfs_sram_len = len;
3807ac9a364SKalle Valo 	} else {
3817ac9a364SKalle Valo 		il->dbgfs_sram_offset = 0;
3827ac9a364SKalle Valo 		il->dbgfs_sram_len = 0;
3837ac9a364SKalle Valo 	}
3847ac9a364SKalle Valo 
3857ac9a364SKalle Valo 	return count;
3867ac9a364SKalle Valo }
3877ac9a364SKalle Valo 
3887ac9a364SKalle Valo static ssize_t
il_dbgfs_stations_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)3897ac9a364SKalle Valo il_dbgfs_stations_read(struct file *file, char __user *user_buf, size_t count,
3907ac9a364SKalle Valo 		       loff_t *ppos)
3917ac9a364SKalle Valo {
3927ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
3937ac9a364SKalle Valo 	struct il_station_entry *station;
3947ac9a364SKalle Valo 	int max_sta = il->hw_params.max_stations;
3957ac9a364SKalle Valo 	char *buf;
3967ac9a364SKalle Valo 	int i, j, pos = 0;
3977ac9a364SKalle Valo 	ssize_t ret;
3987ac9a364SKalle Valo 	/* Add 30 for initial string */
3997ac9a364SKalle Valo 	const size_t bufsz = 30 + sizeof(char) * 500 * (il->num_stations);
4007ac9a364SKalle Valo 
4017ac9a364SKalle Valo 	buf = kmalloc(bufsz, GFP_KERNEL);
4027ac9a364SKalle Valo 	if (!buf)
4037ac9a364SKalle Valo 		return -ENOMEM;
4047ac9a364SKalle Valo 
4057ac9a364SKalle Valo 	pos +=
4067ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
4077ac9a364SKalle Valo 		      il->num_stations);
4087ac9a364SKalle Valo 
4097ac9a364SKalle Valo 	for (i = 0; i < max_sta; i++) {
4107ac9a364SKalle Valo 		station = &il->stations[i];
4117ac9a364SKalle Valo 		if (!station->used)
4127ac9a364SKalle Valo 			continue;
4137ac9a364SKalle Valo 		pos +=
4147ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos,
4157ac9a364SKalle Valo 			      "station %d - addr: %pM, flags: %#x\n", i,
4167ac9a364SKalle Valo 			      station->sta.sta.addr,
4177ac9a364SKalle Valo 			      station->sta.station_flags_msk);
4187ac9a364SKalle Valo 		pos +=
4197ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos,
4207ac9a364SKalle Valo 			      "TID\tseq_num\ttxq_id\tframes\ttfds\t");
4217ac9a364SKalle Valo 		pos +=
4227ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos,
4237ac9a364SKalle Valo 			      "start_idx\tbitmap\t\t\trate_n_flags\n");
4247ac9a364SKalle Valo 
4257ac9a364SKalle Valo 		for (j = 0; j < MAX_TID_COUNT; j++) {
4267ac9a364SKalle Valo 			pos +=
4277ac9a364SKalle Valo 			    scnprintf(buf + pos, bufsz - pos,
4287ac9a364SKalle Valo 				      "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x",
4297ac9a364SKalle Valo 				      j, station->tid[j].seq_number,
4307ac9a364SKalle Valo 				      station->tid[j].agg.txq_id,
4317ac9a364SKalle Valo 				      station->tid[j].agg.frame_count,
4327ac9a364SKalle Valo 				      station->tid[j].tfds_in_queue,
4337ac9a364SKalle Valo 				      station->tid[j].agg.start_idx,
4347ac9a364SKalle Valo 				      station->tid[j].agg.bitmap,
4357ac9a364SKalle Valo 				      station->tid[j].agg.rate_n_flags);
4367ac9a364SKalle Valo 
4377ac9a364SKalle Valo 			if (station->tid[j].agg.wait_for_ba)
4387ac9a364SKalle Valo 				pos +=
4397ac9a364SKalle Valo 				    scnprintf(buf + pos, bufsz - pos,
4407ac9a364SKalle Valo 					      " - waitforba");
4417ac9a364SKalle Valo 			pos += scnprintf(buf + pos, bufsz - pos, "\n");
4427ac9a364SKalle Valo 		}
4437ac9a364SKalle Valo 
4447ac9a364SKalle Valo 		pos += scnprintf(buf + pos, bufsz - pos, "\n");
4457ac9a364SKalle Valo 	}
4467ac9a364SKalle Valo 
4477ac9a364SKalle Valo 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
4487ac9a364SKalle Valo 	kfree(buf);
4497ac9a364SKalle Valo 	return ret;
4507ac9a364SKalle Valo }
4517ac9a364SKalle Valo 
4527ac9a364SKalle Valo static ssize_t
il_dbgfs_nvm_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)4537ac9a364SKalle Valo il_dbgfs_nvm_read(struct file *file, char __user *user_buf, size_t count,
4547ac9a364SKalle Valo 		  loff_t *ppos)
4557ac9a364SKalle Valo {
4567ac9a364SKalle Valo 	ssize_t ret;
4577ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
4587ac9a364SKalle Valo 	int pos = 0, ofs = 0, buf_size = 0;
4597ac9a364SKalle Valo 	const u8 *ptr;
4607ac9a364SKalle Valo 	char *buf;
4617ac9a364SKalle Valo 	u16 eeprom_ver;
4627ac9a364SKalle Valo 	size_t eeprom_len = il->cfg->eeprom_size;
4637ac9a364SKalle Valo 	buf_size = 4 * eeprom_len + 256;
4647ac9a364SKalle Valo 
4657ac9a364SKalle Valo 	if (eeprom_len % 16) {
4667ac9a364SKalle Valo 		IL_ERR("NVM size is not multiple of 16.\n");
4677ac9a364SKalle Valo 		return -ENODATA;
4687ac9a364SKalle Valo 	}
4697ac9a364SKalle Valo 
4707ac9a364SKalle Valo 	ptr = il->eeprom;
4717ac9a364SKalle Valo 	if (!ptr) {
4727ac9a364SKalle Valo 		IL_ERR("Invalid EEPROM memory\n");
4737ac9a364SKalle Valo 		return -ENOMEM;
4747ac9a364SKalle Valo 	}
4757ac9a364SKalle Valo 
4767ac9a364SKalle Valo 	/* 4 characters for byte 0xYY */
4777ac9a364SKalle Valo 	buf = kzalloc(buf_size, GFP_KERNEL);
4787ac9a364SKalle Valo 	if (!buf) {
4797ac9a364SKalle Valo 		IL_ERR("Can not allocate Buffer\n");
4807ac9a364SKalle Valo 		return -ENOMEM;
4817ac9a364SKalle Valo 	}
4827ac9a364SKalle Valo 	eeprom_ver = il_eeprom_query16(il, EEPROM_VERSION);
4837ac9a364SKalle Valo 	pos +=
4847ac9a364SKalle Valo 	    scnprintf(buf + pos, buf_size - pos, "EEPROM " "version: 0x%x\n",
4857ac9a364SKalle Valo 		      eeprom_ver);
4867ac9a364SKalle Valo 	for (ofs = 0; ofs < eeprom_len; ofs += 16) {
4877ac9a364SKalle Valo 		pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x %16ph\n",
4887ac9a364SKalle Valo 				 ofs, ptr + ofs);
4897ac9a364SKalle Valo 	}
4907ac9a364SKalle Valo 
4917ac9a364SKalle Valo 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
4927ac9a364SKalle Valo 	kfree(buf);
4937ac9a364SKalle Valo 	return ret;
4947ac9a364SKalle Valo }
4957ac9a364SKalle Valo 
4967ac9a364SKalle Valo static ssize_t
il_dbgfs_channels_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)4977ac9a364SKalle Valo il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count,
4987ac9a364SKalle Valo 		       loff_t *ppos)
4997ac9a364SKalle Valo {
5007ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
5017ac9a364SKalle Valo 	struct ieee80211_channel *channels = NULL;
5027ac9a364SKalle Valo 	const struct ieee80211_supported_band *supp_band = NULL;
5037ac9a364SKalle Valo 	int pos = 0, i, bufsz = PAGE_SIZE;
5047ac9a364SKalle Valo 	char *buf;
5057ac9a364SKalle Valo 	ssize_t ret;
5067ac9a364SKalle Valo 
5077ac9a364SKalle Valo 	if (!test_bit(S_GEO_CONFIGURED, &il->status))
5087ac9a364SKalle Valo 		return -EAGAIN;
5097ac9a364SKalle Valo 
5107ac9a364SKalle Valo 	buf = kzalloc(bufsz, GFP_KERNEL);
5117ac9a364SKalle Valo 	if (!buf) {
5127ac9a364SKalle Valo 		IL_ERR("Can not allocate Buffer\n");
5137ac9a364SKalle Valo 		return -ENOMEM;
5147ac9a364SKalle Valo 	}
5157ac9a364SKalle Valo 
51657fbcce3SJohannes Berg 	supp_band = il_get_hw_mode(il, NL80211_BAND_2GHZ);
5177ac9a364SKalle Valo 	if (supp_band) {
5187ac9a364SKalle Valo 		channels = supp_band->channels;
5197ac9a364SKalle Valo 
5207ac9a364SKalle Valo 		pos +=
5217ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos,
5227ac9a364SKalle Valo 			      "Displaying %d channels in 2.4GHz band 802.11bg):\n",
5237ac9a364SKalle Valo 			      supp_band->n_channels);
5247ac9a364SKalle Valo 
5257ac9a364SKalle Valo 		for (i = 0; i < supp_band->n_channels; i++)
5267ac9a364SKalle Valo 			pos +=
5277ac9a364SKalle Valo 			    scnprintf(buf + pos, bufsz - pos,
5287ac9a364SKalle Valo 				      "%d: %ddBm: BSS%s%s, %s.\n",
5297ac9a364SKalle Valo 				      channels[i].hw_value,
5307ac9a364SKalle Valo 				      channels[i].max_power,
5317ac9a364SKalle Valo 				      channels[i].
5327ac9a364SKalle Valo 				      flags & IEEE80211_CHAN_RADAR ?
5337ac9a364SKalle Valo 				      " (IEEE 802.11h required)" : "",
5347ac9a364SKalle Valo 				      ((channels[i].
5357ac9a364SKalle Valo 					flags & IEEE80211_CHAN_NO_IR) ||
5367ac9a364SKalle Valo 				       (channels[i].
5377ac9a364SKalle Valo 					flags & IEEE80211_CHAN_RADAR)) ? "" :
5387ac9a364SKalle Valo 				      ", IBSS",
5397ac9a364SKalle Valo 				      channels[i].
5407ac9a364SKalle Valo 				      flags & IEEE80211_CHAN_NO_IR ?
5417ac9a364SKalle Valo 				      "passive only" : "active/passive");
5427ac9a364SKalle Valo 	}
54357fbcce3SJohannes Berg 	supp_band = il_get_hw_mode(il, NL80211_BAND_5GHZ);
5447ac9a364SKalle Valo 	if (supp_band) {
5457ac9a364SKalle Valo 		channels = supp_band->channels;
5467ac9a364SKalle Valo 
5477ac9a364SKalle Valo 		pos +=
5487ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos,
5497ac9a364SKalle Valo 			      "Displaying %d channels in 5.2GHz band (802.11a)\n",
5507ac9a364SKalle Valo 			      supp_band->n_channels);
5517ac9a364SKalle Valo 
5527ac9a364SKalle Valo 		for (i = 0; i < supp_band->n_channels; i++)
5537ac9a364SKalle Valo 			pos +=
5547ac9a364SKalle Valo 			    scnprintf(buf + pos, bufsz - pos,
5557ac9a364SKalle Valo 				      "%d: %ddBm: BSS%s%s, %s.\n",
5567ac9a364SKalle Valo 				      channels[i].hw_value,
5577ac9a364SKalle Valo 				      channels[i].max_power,
5587ac9a364SKalle Valo 				      channels[i].
5597ac9a364SKalle Valo 				      flags & IEEE80211_CHAN_RADAR ?
5607ac9a364SKalle Valo 				      " (IEEE 802.11h required)" : "",
5617ac9a364SKalle Valo 				      ((channels[i].
5627ac9a364SKalle Valo 					flags & IEEE80211_CHAN_NO_IR) ||
5637ac9a364SKalle Valo 				       (channels[i].
5647ac9a364SKalle Valo 					flags & IEEE80211_CHAN_RADAR)) ? "" :
5657ac9a364SKalle Valo 				      ", IBSS",
5667ac9a364SKalle Valo 				      channels[i].
5677ac9a364SKalle Valo 				      flags & IEEE80211_CHAN_NO_IR ?
5687ac9a364SKalle Valo 				      "passive only" : "active/passive");
5697ac9a364SKalle Valo 	}
5707ac9a364SKalle Valo 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
5717ac9a364SKalle Valo 	kfree(buf);
5727ac9a364SKalle Valo 	return ret;
5737ac9a364SKalle Valo }
5747ac9a364SKalle Valo 
5757ac9a364SKalle Valo static ssize_t
il_dbgfs_status_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)5767ac9a364SKalle Valo il_dbgfs_status_read(struct file *file, char __user *user_buf, size_t count,
5777ac9a364SKalle Valo 		     loff_t *ppos)
5787ac9a364SKalle Valo {
5797ac9a364SKalle Valo 
5807ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
5817ac9a364SKalle Valo 	char buf[512];
5827ac9a364SKalle Valo 	int pos = 0;
5837ac9a364SKalle Valo 	const size_t bufsz = sizeof(buf);
5847ac9a364SKalle Valo 
5857ac9a364SKalle Valo 	pos +=
5867ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_HCMD_ACTIVE:\t %d\n",
5877ac9a364SKalle Valo 		      test_bit(S_HCMD_ACTIVE, &il->status));
5887ac9a364SKalle Valo 	pos +=
5897ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_INT_ENABLED:\t %d\n",
5907ac9a364SKalle Valo 		      test_bit(S_INT_ENABLED, &il->status));
5917ac9a364SKalle Valo 	pos +=
5927ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_RFKILL:\t %d\n",
5937ac9a364SKalle Valo 		      test_bit(S_RFKILL, &il->status));
5947ac9a364SKalle Valo 	pos +=
5957ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_CT_KILL:\t\t %d\n",
5967ac9a364SKalle Valo 		      test_bit(S_CT_KILL, &il->status));
5977ac9a364SKalle Valo 	pos +=
5987ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_INIT:\t\t %d\n",
5997ac9a364SKalle Valo 		      test_bit(S_INIT, &il->status));
6007ac9a364SKalle Valo 	pos +=
6017ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_ALIVE:\t\t %d\n",
6027ac9a364SKalle Valo 		      test_bit(S_ALIVE, &il->status));
6037ac9a364SKalle Valo 	pos +=
6047ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_READY:\t\t %d\n",
6057ac9a364SKalle Valo 		      test_bit(S_READY, &il->status));
6067ac9a364SKalle Valo 	pos +=
6077ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_TEMPERATURE:\t %d\n",
6087ac9a364SKalle Valo 		      test_bit(S_TEMPERATURE, &il->status));
6097ac9a364SKalle Valo 	pos +=
6107ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_GEO_CONFIGURED:\t %d\n",
6117ac9a364SKalle Valo 		      test_bit(S_GEO_CONFIGURED, &il->status));
6127ac9a364SKalle Valo 	pos +=
6137ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_EXIT_PENDING:\t %d\n",
6147ac9a364SKalle Valo 		      test_bit(S_EXIT_PENDING, &il->status));
6157ac9a364SKalle Valo 	pos +=
6167ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_STATS:\t %d\n",
6177ac9a364SKalle Valo 		      test_bit(S_STATS, &il->status));
6187ac9a364SKalle Valo 	pos +=
6197ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_SCANNING:\t %d\n",
6207ac9a364SKalle Valo 		      test_bit(S_SCANNING, &il->status));
6217ac9a364SKalle Valo 	pos +=
6227ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_SCAN_ABORTING:\t %d\n",
6237ac9a364SKalle Valo 		      test_bit(S_SCAN_ABORTING, &il->status));
6247ac9a364SKalle Valo 	pos +=
6257ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_SCAN_HW:\t\t %d\n",
6267ac9a364SKalle Valo 		      test_bit(S_SCAN_HW, &il->status));
6277ac9a364SKalle Valo 	pos +=
6287ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_POWER_PMI:\t %d\n",
6297ac9a364SKalle Valo 		      test_bit(S_POWER_PMI, &il->status));
6307ac9a364SKalle Valo 	pos +=
6317ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "S_FW_ERROR:\t %d\n",
6327ac9a364SKalle Valo 		      test_bit(S_FW_ERROR, &il->status));
6337ac9a364SKalle Valo 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
6347ac9a364SKalle Valo }
6357ac9a364SKalle Valo 
6367ac9a364SKalle Valo static ssize_t
il_dbgfs_interrupt_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)6377ac9a364SKalle Valo il_dbgfs_interrupt_read(struct file *file, char __user *user_buf, size_t count,
6387ac9a364SKalle Valo 			loff_t *ppos)
6397ac9a364SKalle Valo {
6407ac9a364SKalle Valo 
6417ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
6427ac9a364SKalle Valo 	int pos = 0;
6437ac9a364SKalle Valo 	int cnt = 0;
6447ac9a364SKalle Valo 	char *buf;
6457ac9a364SKalle Valo 	int bufsz = 24 * 64;	/* 24 items * 64 char per item */
6467ac9a364SKalle Valo 	ssize_t ret;
6477ac9a364SKalle Valo 
6487ac9a364SKalle Valo 	buf = kzalloc(bufsz, GFP_KERNEL);
6497ac9a364SKalle Valo 	if (!buf) {
6507ac9a364SKalle Valo 		IL_ERR("Can not allocate Buffer\n");
6517ac9a364SKalle Valo 		return -ENOMEM;
6527ac9a364SKalle Valo 	}
6537ac9a364SKalle Valo 
6547ac9a364SKalle Valo 	pos +=
6557ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "Interrupt Statistics Report:\n");
6567ac9a364SKalle Valo 
6577ac9a364SKalle Valo 	pos +=
6587ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
6597ac9a364SKalle Valo 		      il->isr_stats.hw);
6607ac9a364SKalle Valo 	pos +=
6617ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
6627ac9a364SKalle Valo 		      il->isr_stats.sw);
6637ac9a364SKalle Valo 	if (il->isr_stats.sw || il->isr_stats.hw) {
6647ac9a364SKalle Valo 		pos +=
6657ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos,
6667ac9a364SKalle Valo 			      "\tLast Restarting Code:  0x%X\n",
6677ac9a364SKalle Valo 			      il->isr_stats.err_code);
6687ac9a364SKalle Valo 	}
6697ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG
6707ac9a364SKalle Valo 	pos +=
6717ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
6727ac9a364SKalle Valo 		      il->isr_stats.sch);
6737ac9a364SKalle Valo 	pos +=
6747ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
6757ac9a364SKalle Valo 		      il->isr_stats.alive);
6767ac9a364SKalle Valo #endif
6777ac9a364SKalle Valo 	pos +=
6787ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos,
6797ac9a364SKalle Valo 		      "HW RF KILL switch toggled:\t %u\n",
6807ac9a364SKalle Valo 		      il->isr_stats.rfkill);
6817ac9a364SKalle Valo 
6827ac9a364SKalle Valo 	pos +=
6837ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
6847ac9a364SKalle Valo 		      il->isr_stats.ctkill);
6857ac9a364SKalle Valo 
6867ac9a364SKalle Valo 	pos +=
6877ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
6887ac9a364SKalle Valo 		      il->isr_stats.wakeup);
6897ac9a364SKalle Valo 
6907ac9a364SKalle Valo 	pos +=
6917ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "Rx command responses:\t\t %u\n",
6927ac9a364SKalle Valo 		      il->isr_stats.rx);
6937ac9a364SKalle Valo 	for (cnt = 0; cnt < IL_CN_MAX; cnt++) {
6947ac9a364SKalle Valo 		if (il->isr_stats.handlers[cnt] > 0)
6957ac9a364SKalle Valo 			pos +=
6967ac9a364SKalle Valo 			    scnprintf(buf + pos, bufsz - pos,
6977ac9a364SKalle Valo 				      "\tRx handler[%36s]:\t\t %u\n",
6987ac9a364SKalle Valo 				      il_get_cmd_string(cnt),
6997ac9a364SKalle Valo 				      il->isr_stats.handlers[cnt]);
7007ac9a364SKalle Valo 	}
7017ac9a364SKalle Valo 
7027ac9a364SKalle Valo 	pos +=
7037ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
7047ac9a364SKalle Valo 		      il->isr_stats.tx);
7057ac9a364SKalle Valo 
7067ac9a364SKalle Valo 	pos +=
7077ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
7087ac9a364SKalle Valo 		      il->isr_stats.unhandled);
7097ac9a364SKalle Valo 
7107ac9a364SKalle Valo 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
7117ac9a364SKalle Valo 	kfree(buf);
7127ac9a364SKalle Valo 	return ret;
7137ac9a364SKalle Valo }
7147ac9a364SKalle Valo 
7157ac9a364SKalle Valo static ssize_t
il_dbgfs_interrupt_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)7167ac9a364SKalle Valo il_dbgfs_interrupt_write(struct file *file, const char __user *user_buf,
7177ac9a364SKalle Valo 			 size_t count, loff_t *ppos)
7187ac9a364SKalle Valo {
7197ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
7207ac9a364SKalle Valo 	char buf[8];
7217ac9a364SKalle Valo 	int buf_size;
7227ac9a364SKalle Valo 	u32 reset_flag;
7237ac9a364SKalle Valo 
7247ac9a364SKalle Valo 	memset(buf, 0, sizeof(buf));
7257ac9a364SKalle Valo 	buf_size = min(count, sizeof(buf) - 1);
7267ac9a364SKalle Valo 	if (copy_from_user(buf, user_buf, buf_size))
7277ac9a364SKalle Valo 		return -EFAULT;
7287ac9a364SKalle Valo 	if (sscanf(buf, "%x", &reset_flag) != 1)
7297ac9a364SKalle Valo 		return -EFAULT;
7307ac9a364SKalle Valo 	if (reset_flag == 0)
7317ac9a364SKalle Valo 		il_clear_isr_stats(il);
7327ac9a364SKalle Valo 
7337ac9a364SKalle Valo 	return count;
7347ac9a364SKalle Valo }
7357ac9a364SKalle Valo 
7367ac9a364SKalle Valo static ssize_t
il_dbgfs_qos_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)7377ac9a364SKalle Valo il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count,
7387ac9a364SKalle Valo 		  loff_t *ppos)
7397ac9a364SKalle Valo {
7407ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
7417ac9a364SKalle Valo 	int pos = 0, i;
7427ac9a364SKalle Valo 	char buf[256];
7437ac9a364SKalle Valo 	const size_t bufsz = sizeof(buf);
7447ac9a364SKalle Valo 
7457ac9a364SKalle Valo 	for (i = 0; i < AC_NUM; i++) {
7467ac9a364SKalle Valo 		pos +=
7477ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos,
7487ac9a364SKalle Valo 			      "\tcw_min\tcw_max\taifsn\ttxop\n");
7497ac9a364SKalle Valo 		pos +=
7507ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos,
7517ac9a364SKalle Valo 			      "AC[%d]\t%u\t%u\t%u\t%u\n", i,
7527ac9a364SKalle Valo 			      il->qos_data.def_qos_parm.ac[i].cw_min,
7537ac9a364SKalle Valo 			      il->qos_data.def_qos_parm.ac[i].cw_max,
7547ac9a364SKalle Valo 			      il->qos_data.def_qos_parm.ac[i].aifsn,
7557ac9a364SKalle Valo 			      il->qos_data.def_qos_parm.ac[i].edca_txop);
7567ac9a364SKalle Valo 	}
7577ac9a364SKalle Valo 
7587ac9a364SKalle Valo 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
7597ac9a364SKalle Valo }
7607ac9a364SKalle Valo 
7617ac9a364SKalle Valo static ssize_t
il_dbgfs_disable_ht40_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)7627ac9a364SKalle Valo il_dbgfs_disable_ht40_write(struct file *file, const char __user *user_buf,
7637ac9a364SKalle Valo 			    size_t count, loff_t *ppos)
7647ac9a364SKalle Valo {
7657ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
7667ac9a364SKalle Valo 	char buf[8];
7677ac9a364SKalle Valo 	int buf_size;
7687ac9a364SKalle Valo 	int ht40;
7697ac9a364SKalle Valo 
7707ac9a364SKalle Valo 	memset(buf, 0, sizeof(buf));
7717ac9a364SKalle Valo 	buf_size = min(count, sizeof(buf) - 1);
7727ac9a364SKalle Valo 	if (copy_from_user(buf, user_buf, buf_size))
7737ac9a364SKalle Valo 		return -EFAULT;
7747ac9a364SKalle Valo 	if (sscanf(buf, "%d", &ht40) != 1)
7757ac9a364SKalle Valo 		return -EFAULT;
7767ac9a364SKalle Valo 	if (!il_is_any_associated(il))
7777ac9a364SKalle Valo 		il->disable_ht40 = ht40 ? true : false;
7787ac9a364SKalle Valo 	else {
7797ac9a364SKalle Valo 		IL_ERR("Sta associated with AP - "
7807ac9a364SKalle Valo 		       "Change to 40MHz channel support is not allowed\n");
7817ac9a364SKalle Valo 		return -EINVAL;
7827ac9a364SKalle Valo 	}
7837ac9a364SKalle Valo 
7847ac9a364SKalle Valo 	return count;
7857ac9a364SKalle Valo }
7867ac9a364SKalle Valo 
7877ac9a364SKalle Valo static ssize_t
il_dbgfs_disable_ht40_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)7887ac9a364SKalle Valo il_dbgfs_disable_ht40_read(struct file *file, char __user *user_buf,
7897ac9a364SKalle Valo 			   size_t count, loff_t *ppos)
7907ac9a364SKalle Valo {
7917ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
7927ac9a364SKalle Valo 	char buf[100];
7937ac9a364SKalle Valo 	int pos = 0;
7947ac9a364SKalle Valo 	const size_t bufsz = sizeof(buf);
7957ac9a364SKalle Valo 
7967ac9a364SKalle Valo 	pos +=
7977ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "11n 40MHz Mode: %s\n",
7987ac9a364SKalle Valo 		      il->disable_ht40 ? "Disabled" : "Enabled");
7997ac9a364SKalle Valo 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
8007ac9a364SKalle Valo }
8017ac9a364SKalle Valo 
8027ac9a364SKalle Valo DEBUGFS_READ_WRITE_FILE_OPS(sram);
8037ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(nvm);
8047ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(stations);
8057ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(channels);
8067ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(status);
8077ac9a364SKalle Valo DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
8087ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(qos);
8097ac9a364SKalle Valo DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
8107ac9a364SKalle Valo 
8117ac9a364SKalle Valo static ssize_t
il_dbgfs_tx_queue_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)8127ac9a364SKalle Valo il_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count,
8137ac9a364SKalle Valo 		       loff_t *ppos)
8147ac9a364SKalle Valo {
8157ac9a364SKalle Valo 
8167ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
8177ac9a364SKalle Valo 	struct il_tx_queue *txq;
8187ac9a364SKalle Valo 	struct il_queue *q;
8197ac9a364SKalle Valo 	char *buf;
8207ac9a364SKalle Valo 	int pos = 0;
8217ac9a364SKalle Valo 	int cnt;
8227ac9a364SKalle Valo 	int ret;
8237ac9a364SKalle Valo 	const size_t bufsz =
8247ac9a364SKalle Valo 	    sizeof(char) * 64 * il->cfg->num_of_queues;
8257ac9a364SKalle Valo 
8267ac9a364SKalle Valo 	if (!il->txq) {
8277ac9a364SKalle Valo 		IL_ERR("txq not ready\n");
8287ac9a364SKalle Valo 		return -EAGAIN;
8297ac9a364SKalle Valo 	}
8307ac9a364SKalle Valo 	buf = kzalloc(bufsz, GFP_KERNEL);
8317ac9a364SKalle Valo 	if (!buf)
8327ac9a364SKalle Valo 		return -ENOMEM;
8337ac9a364SKalle Valo 
8347ac9a364SKalle Valo 	for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
8357ac9a364SKalle Valo 		txq = &il->txq[cnt];
8367ac9a364SKalle Valo 		q = &txq->q;
8377ac9a364SKalle Valo 		pos +=
8387ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos,
8397ac9a364SKalle Valo 			      "hwq %.2d: read=%u write=%u stop=%d"
8407ac9a364SKalle Valo 			      " swq_id=%#.2x (ac %d/hwq %d)\n", cnt,
8417ac9a364SKalle Valo 			      q->read_ptr, q->write_ptr,
8427ac9a364SKalle Valo 			      !!test_bit(cnt, il->queue_stopped),
8437ac9a364SKalle Valo 			      txq->swq_id, txq->swq_id & 3,
8447ac9a364SKalle Valo 			      (txq->swq_id >> 2) & 0x1f);
8457ac9a364SKalle Valo 		if (cnt >= 4)
8467ac9a364SKalle Valo 			continue;
8477ac9a364SKalle Valo 		/* for the ACs, display the stop count too */
8487ac9a364SKalle Valo 		pos +=
8497ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos,
8507ac9a364SKalle Valo 			      "        stop-count: %d\n",
8517ac9a364SKalle Valo 			      atomic_read(&il->queue_stop_count[cnt]));
8527ac9a364SKalle Valo 	}
8537ac9a364SKalle Valo 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
8547ac9a364SKalle Valo 	kfree(buf);
8557ac9a364SKalle Valo 	return ret;
8567ac9a364SKalle Valo }
8577ac9a364SKalle Valo 
8587ac9a364SKalle Valo static ssize_t
il_dbgfs_rx_queue_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)8597ac9a364SKalle Valo il_dbgfs_rx_queue_read(struct file *file, char __user *user_buf, size_t count,
8607ac9a364SKalle Valo 		       loff_t *ppos)
8617ac9a364SKalle Valo {
8627ac9a364SKalle Valo 
8637ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
8647ac9a364SKalle Valo 	struct il_rx_queue *rxq = &il->rxq;
8657ac9a364SKalle Valo 	char buf[256];
8667ac9a364SKalle Valo 	int pos = 0;
8677ac9a364SKalle Valo 	const size_t bufsz = sizeof(buf);
8687ac9a364SKalle Valo 
8697ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", rxq->read);
8707ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", rxq->write);
8717ac9a364SKalle Valo 	pos +=
8727ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
8737ac9a364SKalle Valo 		      rxq->free_count);
8747ac9a364SKalle Valo 	if (rxq->rb_stts) {
8757ac9a364SKalle Valo 		pos +=
8767ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
8777ac9a364SKalle Valo 			      le16_to_cpu(rxq->rb_stts->
8787ac9a364SKalle Valo 					  closed_rb_num) & 0x0FFF);
8797ac9a364SKalle Valo 	} else {
8807ac9a364SKalle Valo 		pos +=
8817ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos,
8827ac9a364SKalle Valo 			      "closed_rb_num: Not Allocated\n");
8837ac9a364SKalle Valo 	}
8847ac9a364SKalle Valo 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
8857ac9a364SKalle Valo }
8867ac9a364SKalle Valo 
8877ac9a364SKalle Valo static ssize_t
il_dbgfs_ucode_rx_stats_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)8887ac9a364SKalle Valo il_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf,
8897ac9a364SKalle Valo 			     size_t count, loff_t *ppos)
8907ac9a364SKalle Valo {
8917ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
8927ac9a364SKalle Valo 
8937ac9a364SKalle Valo 	return il->debugfs_ops->rx_stats_read(file, user_buf, count, ppos);
8947ac9a364SKalle Valo }
8957ac9a364SKalle Valo 
8967ac9a364SKalle Valo static ssize_t
il_dbgfs_ucode_tx_stats_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)8977ac9a364SKalle Valo il_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf,
8987ac9a364SKalle Valo 			     size_t count, loff_t *ppos)
8997ac9a364SKalle Valo {
9007ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
9017ac9a364SKalle Valo 
9027ac9a364SKalle Valo 	return il->debugfs_ops->tx_stats_read(file, user_buf, count, ppos);
9037ac9a364SKalle Valo }
9047ac9a364SKalle Valo 
9057ac9a364SKalle Valo static ssize_t
il_dbgfs_ucode_general_stats_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)9067ac9a364SKalle Valo il_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf,
9077ac9a364SKalle Valo 				  size_t count, loff_t *ppos)
9087ac9a364SKalle Valo {
9097ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
9107ac9a364SKalle Valo 
9117ac9a364SKalle Valo 	return il->debugfs_ops->general_stats_read(file, user_buf, count, ppos);
9127ac9a364SKalle Valo }
9137ac9a364SKalle Valo 
9147ac9a364SKalle Valo static ssize_t
il_dbgfs_sensitivity_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)9157ac9a364SKalle Valo il_dbgfs_sensitivity_read(struct file *file, char __user *user_buf,
9167ac9a364SKalle Valo 			  size_t count, loff_t *ppos)
9177ac9a364SKalle Valo {
9187ac9a364SKalle Valo 
9197ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
9207ac9a364SKalle Valo 	int pos = 0;
9217ac9a364SKalle Valo 	int cnt = 0;
9227ac9a364SKalle Valo 	char *buf;
9237ac9a364SKalle Valo 	int bufsz = sizeof(struct il_sensitivity_data) * 4 + 100;
9247ac9a364SKalle Valo 	ssize_t ret;
9257ac9a364SKalle Valo 	struct il_sensitivity_data *data;
9267ac9a364SKalle Valo 
9277ac9a364SKalle Valo 	data = &il->sensitivity_data;
9287ac9a364SKalle Valo 	buf = kzalloc(bufsz, GFP_KERNEL);
9297ac9a364SKalle Valo 	if (!buf) {
9307ac9a364SKalle Valo 		IL_ERR("Can not allocate Buffer\n");
9317ac9a364SKalle Valo 		return -ENOMEM;
9327ac9a364SKalle Valo 	}
9337ac9a364SKalle Valo 
9347ac9a364SKalle Valo 	pos +=
9357ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
9367ac9a364SKalle Valo 		      data->auto_corr_ofdm);
9377ac9a364SKalle Valo 	pos +=
9387ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc:\t\t %u\n",
9397ac9a364SKalle Valo 		      data->auto_corr_ofdm_mrc);
9407ac9a364SKalle Valo 	pos +=
9417ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
9427ac9a364SKalle Valo 		      data->auto_corr_ofdm_x1);
9437ac9a364SKalle Valo 	pos +=
9447ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc_x1:\t\t %u\n",
9457ac9a364SKalle Valo 		      data->auto_corr_ofdm_mrc_x1);
9467ac9a364SKalle Valo 	pos +=
9477ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
9487ac9a364SKalle Valo 		      data->auto_corr_cck);
9497ac9a364SKalle Valo 	pos +=
9507ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
9517ac9a364SKalle Valo 		      data->auto_corr_cck_mrc);
9527ac9a364SKalle Valo 	pos +=
9537ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos,
9547ac9a364SKalle Valo 		      "last_bad_plcp_cnt_ofdm:\t\t %u\n",
9557ac9a364SKalle Valo 		      data->last_bad_plcp_cnt_ofdm);
9567ac9a364SKalle Valo 	pos +=
9577ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
9587ac9a364SKalle Valo 		      data->last_fa_cnt_ofdm);
9597ac9a364SKalle Valo 	pos +=
9607ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "last_bad_plcp_cnt_cck:\t\t %u\n",
9617ac9a364SKalle Valo 		      data->last_bad_plcp_cnt_cck);
9627ac9a364SKalle Valo 	pos +=
9637ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
9647ac9a364SKalle Valo 		      data->last_fa_cnt_cck);
9657ac9a364SKalle Valo 	pos +=
9667ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
9677ac9a364SKalle Valo 		      data->nrg_curr_state);
9687ac9a364SKalle Valo 	pos +=
9697ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
9707ac9a364SKalle Valo 		      data->nrg_prev_state);
9717ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
9727ac9a364SKalle Valo 	for (cnt = 0; cnt < 10; cnt++) {
9737ac9a364SKalle Valo 		pos +=
9747ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos, " %u",
9757ac9a364SKalle Valo 			      data->nrg_value[cnt]);
9767ac9a364SKalle Valo 	}
9777ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "\n");
9787ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
9797ac9a364SKalle Valo 	for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
9807ac9a364SKalle Valo 		pos +=
9817ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos, " %u",
9827ac9a364SKalle Valo 			      data->nrg_silence_rssi[cnt]);
9837ac9a364SKalle Valo 	}
9847ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "\n");
9857ac9a364SKalle Valo 	pos +=
9867ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
9877ac9a364SKalle Valo 		      data->nrg_silence_ref);
9887ac9a364SKalle Valo 	pos +=
9897ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
9907ac9a364SKalle Valo 		      data->nrg_energy_idx);
9917ac9a364SKalle Valo 	pos +=
9927ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
9937ac9a364SKalle Valo 		      data->nrg_silence_idx);
9947ac9a364SKalle Valo 	pos +=
9957ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
9967ac9a364SKalle Valo 		      data->nrg_th_cck);
9977ac9a364SKalle Valo 	pos +=
9987ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos,
9997ac9a364SKalle Valo 		      "nrg_auto_corr_silence_diff:\t %u\n",
10007ac9a364SKalle Valo 		      data->nrg_auto_corr_silence_diff);
10017ac9a364SKalle Valo 	pos +=
10027ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
10037ac9a364SKalle Valo 		      data->num_in_cck_no_fa);
10047ac9a364SKalle Valo 	pos +=
10057ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
10067ac9a364SKalle Valo 		      data->nrg_th_ofdm);
10077ac9a364SKalle Valo 
10087ac9a364SKalle Valo 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
10097ac9a364SKalle Valo 	kfree(buf);
10107ac9a364SKalle Valo 	return ret;
10117ac9a364SKalle Valo }
10127ac9a364SKalle Valo 
10137ac9a364SKalle Valo static ssize_t
il_dbgfs_chain_noise_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)10147ac9a364SKalle Valo il_dbgfs_chain_noise_read(struct file *file, char __user *user_buf,
10157ac9a364SKalle Valo 			  size_t count, loff_t *ppos)
10167ac9a364SKalle Valo {
10177ac9a364SKalle Valo 
10187ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
10197ac9a364SKalle Valo 	int pos = 0;
10207ac9a364SKalle Valo 	int cnt = 0;
10217ac9a364SKalle Valo 	char *buf;
10227ac9a364SKalle Valo 	int bufsz = sizeof(struct il_chain_noise_data) * 4 + 100;
10237ac9a364SKalle Valo 	ssize_t ret;
10247ac9a364SKalle Valo 	struct il_chain_noise_data *data;
10257ac9a364SKalle Valo 
10267ac9a364SKalle Valo 	data = &il->chain_noise_data;
10277ac9a364SKalle Valo 	buf = kzalloc(bufsz, GFP_KERNEL);
10287ac9a364SKalle Valo 	if (!buf) {
10297ac9a364SKalle Valo 		IL_ERR("Can not allocate Buffer\n");
10307ac9a364SKalle Valo 		return -ENOMEM;
10317ac9a364SKalle Valo 	}
10327ac9a364SKalle Valo 
10337ac9a364SKalle Valo 	pos +=
10347ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
10357ac9a364SKalle Valo 		      data->active_chains);
10367ac9a364SKalle Valo 	pos +=
10377ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
10387ac9a364SKalle Valo 		      data->chain_noise_a);
10397ac9a364SKalle Valo 	pos +=
10407ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
10417ac9a364SKalle Valo 		      data->chain_noise_b);
10427ac9a364SKalle Valo 	pos +=
10437ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
10447ac9a364SKalle Valo 		      data->chain_noise_c);
10457ac9a364SKalle Valo 	pos +=
10467ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
10477ac9a364SKalle Valo 		      data->chain_signal_a);
10487ac9a364SKalle Valo 	pos +=
10497ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
10507ac9a364SKalle Valo 		      data->chain_signal_b);
10517ac9a364SKalle Valo 	pos +=
10527ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
10537ac9a364SKalle Valo 		      data->chain_signal_c);
10547ac9a364SKalle Valo 	pos +=
10557ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
10567ac9a364SKalle Valo 		      data->beacon_count);
10577ac9a364SKalle Valo 
10587ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
10597ac9a364SKalle Valo 	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
10607ac9a364SKalle Valo 		pos +=
10617ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos, " %u",
10627ac9a364SKalle Valo 			      data->disconn_array[cnt]);
10637ac9a364SKalle Valo 	}
10647ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "\n");
10657ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
10667ac9a364SKalle Valo 	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
10677ac9a364SKalle Valo 		pos +=
10687ac9a364SKalle Valo 		    scnprintf(buf + pos, bufsz - pos, " %u",
10697ac9a364SKalle Valo 			      data->delta_gain_code[cnt]);
10707ac9a364SKalle Valo 	}
10717ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "\n");
10727ac9a364SKalle Valo 	pos +=
10737ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
10747ac9a364SKalle Valo 		      data->radio_write);
10757ac9a364SKalle Valo 	pos +=
10767ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
10777ac9a364SKalle Valo 		      data->state);
10787ac9a364SKalle Valo 
10797ac9a364SKalle Valo 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
10807ac9a364SKalle Valo 	kfree(buf);
10817ac9a364SKalle Valo 	return ret;
10827ac9a364SKalle Valo }
10837ac9a364SKalle Valo 
10847ac9a364SKalle Valo static ssize_t
il_dbgfs_power_save_status_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)10857ac9a364SKalle Valo il_dbgfs_power_save_status_read(struct file *file, char __user *user_buf,
10867ac9a364SKalle Valo 				size_t count, loff_t *ppos)
10877ac9a364SKalle Valo {
10887ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
10897ac9a364SKalle Valo 	char buf[60];
10907ac9a364SKalle Valo 	int pos = 0;
10917ac9a364SKalle Valo 	const size_t bufsz = sizeof(buf);
10927ac9a364SKalle Valo 	u32 pwrsave_status;
10937ac9a364SKalle Valo 
10947ac9a364SKalle Valo 	pwrsave_status =
10957ac9a364SKalle Valo 	    _il_rd(il, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK;
10967ac9a364SKalle Valo 
10977ac9a364SKalle Valo 	pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
10987ac9a364SKalle Valo 	pos +=
10997ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "%s\n",
11007ac9a364SKalle Valo 		      (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
11017ac9a364SKalle Valo 		      (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
11027ac9a364SKalle Valo 		      (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
11037ac9a364SKalle Valo 		      "error");
11047ac9a364SKalle Valo 
11057ac9a364SKalle Valo 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
11067ac9a364SKalle Valo }
11077ac9a364SKalle Valo 
11087ac9a364SKalle Valo static ssize_t
il_dbgfs_clear_ucode_stats_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)11097ac9a364SKalle Valo il_dbgfs_clear_ucode_stats_write(struct file *file,
11107ac9a364SKalle Valo 				 const char __user *user_buf, size_t count,
11117ac9a364SKalle Valo 				 loff_t *ppos)
11127ac9a364SKalle Valo {
11137ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
11147ac9a364SKalle Valo 	char buf[8];
11157ac9a364SKalle Valo 	int buf_size;
11167ac9a364SKalle Valo 	int clear;
11177ac9a364SKalle Valo 
11187ac9a364SKalle Valo 	memset(buf, 0, sizeof(buf));
11197ac9a364SKalle Valo 	buf_size = min(count, sizeof(buf) - 1);
11207ac9a364SKalle Valo 	if (copy_from_user(buf, user_buf, buf_size))
11217ac9a364SKalle Valo 		return -EFAULT;
11227ac9a364SKalle Valo 	if (sscanf(buf, "%d", &clear) != 1)
11237ac9a364SKalle Valo 		return -EFAULT;
11247ac9a364SKalle Valo 
11257ac9a364SKalle Valo 	/* make request to uCode to retrieve stats information */
11267ac9a364SKalle Valo 	mutex_lock(&il->mutex);
11277ac9a364SKalle Valo 	il_send_stats_request(il, CMD_SYNC, true);
11287ac9a364SKalle Valo 	mutex_unlock(&il->mutex);
11297ac9a364SKalle Valo 
11307ac9a364SKalle Valo 	return count;
11317ac9a364SKalle Valo }
11327ac9a364SKalle Valo 
11337ac9a364SKalle Valo static ssize_t
il_dbgfs_rxon_flags_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)11347ac9a364SKalle Valo il_dbgfs_rxon_flags_read(struct file *file, char __user *user_buf,
11357ac9a364SKalle Valo 			 size_t count, loff_t *ppos)
11367ac9a364SKalle Valo {
11377ac9a364SKalle Valo 
11387ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
11397ac9a364SKalle Valo 	int len = 0;
11407ac9a364SKalle Valo 	char buf[20];
11417ac9a364SKalle Valo 
11427ac9a364SKalle Valo 	len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.flags));
11437ac9a364SKalle Valo 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
11447ac9a364SKalle Valo }
11457ac9a364SKalle Valo 
11467ac9a364SKalle Valo static ssize_t
il_dbgfs_rxon_filter_flags_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)11477ac9a364SKalle Valo il_dbgfs_rxon_filter_flags_read(struct file *file, char __user *user_buf,
11487ac9a364SKalle Valo 				size_t count, loff_t *ppos)
11497ac9a364SKalle Valo {
11507ac9a364SKalle Valo 
11517ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
11527ac9a364SKalle Valo 	int len = 0;
11537ac9a364SKalle Valo 	char buf[20];
11547ac9a364SKalle Valo 
11557ac9a364SKalle Valo 	len =
11567ac9a364SKalle Valo 	    sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags));
11577ac9a364SKalle Valo 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
11587ac9a364SKalle Valo }
11597ac9a364SKalle Valo 
11607ac9a364SKalle Valo static ssize_t
il_dbgfs_fh_reg_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)11617ac9a364SKalle Valo il_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count,
11627ac9a364SKalle Valo 		     loff_t *ppos)
11637ac9a364SKalle Valo {
11647ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
11657ac9a364SKalle Valo 	char *buf;
11667ac9a364SKalle Valo 	int pos = 0;
11677ac9a364SKalle Valo 	ssize_t ret = -EFAULT;
11687ac9a364SKalle Valo 
11697ac9a364SKalle Valo 	if (il->ops->dump_fh) {
11707ac9a364SKalle Valo 		ret = pos = il->ops->dump_fh(il, &buf, true);
11717ac9a364SKalle Valo 		if (buf) {
11727ac9a364SKalle Valo 			ret =
11737ac9a364SKalle Valo 			    simple_read_from_buffer(user_buf, count, ppos, buf,
11747ac9a364SKalle Valo 						    pos);
11757ac9a364SKalle Valo 			kfree(buf);
11767ac9a364SKalle Valo 		}
11777ac9a364SKalle Valo 	}
11787ac9a364SKalle Valo 
11797ac9a364SKalle Valo 	return ret;
11807ac9a364SKalle Valo }
11817ac9a364SKalle Valo 
11827ac9a364SKalle Valo static ssize_t
il_dbgfs_missed_beacon_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)11837ac9a364SKalle Valo il_dbgfs_missed_beacon_read(struct file *file, char __user *user_buf,
11847ac9a364SKalle Valo 			    size_t count, loff_t *ppos)
11857ac9a364SKalle Valo {
11867ac9a364SKalle Valo 
11877ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
11887ac9a364SKalle Valo 	int pos = 0;
11897ac9a364SKalle Valo 	char buf[12];
11907ac9a364SKalle Valo 	const size_t bufsz = sizeof(buf);
11917ac9a364SKalle Valo 
11927ac9a364SKalle Valo 	pos +=
11937ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "%d\n",
11947ac9a364SKalle Valo 		      il->missed_beacon_threshold);
11957ac9a364SKalle Valo 
11967ac9a364SKalle Valo 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
11977ac9a364SKalle Valo }
11987ac9a364SKalle Valo 
11997ac9a364SKalle Valo static ssize_t
il_dbgfs_missed_beacon_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)12007ac9a364SKalle Valo il_dbgfs_missed_beacon_write(struct file *file, const char __user *user_buf,
12017ac9a364SKalle Valo 			     size_t count, loff_t *ppos)
12027ac9a364SKalle Valo {
12037ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
12047ac9a364SKalle Valo 	char buf[8];
12057ac9a364SKalle Valo 	int buf_size;
12067ac9a364SKalle Valo 	int missed;
12077ac9a364SKalle Valo 
12087ac9a364SKalle Valo 	memset(buf, 0, sizeof(buf));
12097ac9a364SKalle Valo 	buf_size = min(count, sizeof(buf) - 1);
12107ac9a364SKalle Valo 	if (copy_from_user(buf, user_buf, buf_size))
12117ac9a364SKalle Valo 		return -EFAULT;
12127ac9a364SKalle Valo 	if (sscanf(buf, "%d", &missed) != 1)
12137ac9a364SKalle Valo 		return -EINVAL;
12147ac9a364SKalle Valo 
12157ac9a364SKalle Valo 	if (missed < IL_MISSED_BEACON_THRESHOLD_MIN ||
12167ac9a364SKalle Valo 	    missed > IL_MISSED_BEACON_THRESHOLD_MAX)
12177ac9a364SKalle Valo 		il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
12187ac9a364SKalle Valo 	else
12197ac9a364SKalle Valo 		il->missed_beacon_threshold = missed;
12207ac9a364SKalle Valo 
12217ac9a364SKalle Valo 	return count;
12227ac9a364SKalle Valo }
12237ac9a364SKalle Valo 
12247ac9a364SKalle Valo static ssize_t
il_dbgfs_force_reset_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)12257ac9a364SKalle Valo il_dbgfs_force_reset_read(struct file *file, char __user *user_buf,
12267ac9a364SKalle Valo 			  size_t count, loff_t *ppos)
12277ac9a364SKalle Valo {
12287ac9a364SKalle Valo 
12297ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
12307ac9a364SKalle Valo 	int pos = 0;
12317ac9a364SKalle Valo 	char buf[300];
12327ac9a364SKalle Valo 	const size_t bufsz = sizeof(buf);
12337ac9a364SKalle Valo 	struct il_force_reset *force_reset;
12347ac9a364SKalle Valo 
12357ac9a364SKalle Valo 	force_reset = &il->force_reset;
12367ac9a364SKalle Valo 
12377ac9a364SKalle Valo 	pos +=
12387ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "\tnumber of reset request: %d\n",
12397ac9a364SKalle Valo 		      force_reset->reset_request_count);
12407ac9a364SKalle Valo 	pos +=
12417ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos,
12427ac9a364SKalle Valo 		      "\tnumber of reset request success: %d\n",
12437ac9a364SKalle Valo 		      force_reset->reset_success_count);
12447ac9a364SKalle Valo 	pos +=
12457ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos,
12467ac9a364SKalle Valo 		      "\tnumber of reset request reject: %d\n",
12477ac9a364SKalle Valo 		      force_reset->reset_reject_count);
12487ac9a364SKalle Valo 	pos +=
12497ac9a364SKalle Valo 	    scnprintf(buf + pos, bufsz - pos, "\treset duration: %lu\n",
12507ac9a364SKalle Valo 		      force_reset->reset_duration);
12517ac9a364SKalle Valo 
12527ac9a364SKalle Valo 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
12537ac9a364SKalle Valo }
12547ac9a364SKalle Valo 
12557ac9a364SKalle Valo static ssize_t
il_dbgfs_force_reset_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)12567ac9a364SKalle Valo il_dbgfs_force_reset_write(struct file *file, const char __user *user_buf,
12577ac9a364SKalle Valo 			   size_t count, loff_t *ppos)
12587ac9a364SKalle Valo {
12597ac9a364SKalle Valo 
12607ac9a364SKalle Valo 	int ret;
12617ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
12627ac9a364SKalle Valo 
12637ac9a364SKalle Valo 	ret = il_force_reset(il, true);
12647ac9a364SKalle Valo 
12657ac9a364SKalle Valo 	return ret ? ret : count;
12667ac9a364SKalle Valo }
12677ac9a364SKalle Valo 
12687ac9a364SKalle Valo static ssize_t
il_dbgfs_wd_timeout_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)12697ac9a364SKalle Valo il_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf,
12707ac9a364SKalle Valo 			  size_t count, loff_t *ppos)
12717ac9a364SKalle Valo {
12727ac9a364SKalle Valo 
12737ac9a364SKalle Valo 	struct il_priv *il = file->private_data;
12747ac9a364SKalle Valo 	char buf[8];
12757ac9a364SKalle Valo 	int buf_size;
12767ac9a364SKalle Valo 	int timeout;
12777ac9a364SKalle Valo 
12787ac9a364SKalle Valo 	memset(buf, 0, sizeof(buf));
12797ac9a364SKalle Valo 	buf_size = min(count, sizeof(buf) - 1);
12807ac9a364SKalle Valo 	if (copy_from_user(buf, user_buf, buf_size))
12817ac9a364SKalle Valo 		return -EFAULT;
12827ac9a364SKalle Valo 	if (sscanf(buf, "%d", &timeout) != 1)
12837ac9a364SKalle Valo 		return -EINVAL;
12847ac9a364SKalle Valo 	if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT)
12857ac9a364SKalle Valo 		timeout = IL_DEF_WD_TIMEOUT;
12867ac9a364SKalle Valo 
12877ac9a364SKalle Valo 	il->cfg->wd_timeout = timeout;
12887ac9a364SKalle Valo 	il_setup_watchdog(il);
12897ac9a364SKalle Valo 	return count;
12907ac9a364SKalle Valo }
12917ac9a364SKalle Valo 
12927ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(rx_stats);
12937ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(tx_stats);
12947ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(rx_queue);
12957ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(tx_queue);
12967ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
12977ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
12987ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(ucode_general_stats);
12997ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(sensitivity);
13007ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(chain_noise);
13017ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(power_save_status);
13027ac9a364SKalle Valo DEBUGFS_WRITE_FILE_OPS(clear_ucode_stats);
13037ac9a364SKalle Valo DEBUGFS_WRITE_FILE_OPS(clear_traffic_stats);
13047ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(fh_reg);
13057ac9a364SKalle Valo DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
13067ac9a364SKalle Valo DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
13077ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(rxon_flags);
13087ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
13097ac9a364SKalle Valo DEBUGFS_WRITE_FILE_OPS(wd_timeout);
13107ac9a364SKalle Valo 
13117ac9a364SKalle Valo /*
13127ac9a364SKalle Valo  * Create the debugfs files and directories
13137ac9a364SKalle Valo  *
13147ac9a364SKalle Valo  */
131571ee1284SGreg Kroah-Hartman void
il_dbgfs_register(struct il_priv * il,const char * name)13167ac9a364SKalle Valo il_dbgfs_register(struct il_priv *il, const char *name)
13177ac9a364SKalle Valo {
13187ac9a364SKalle Valo 	struct dentry *phyd = il->hw->wiphy->debugfsdir;
13197ac9a364SKalle Valo 	struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
13207ac9a364SKalle Valo 
13217ac9a364SKalle Valo 	dir_drv = debugfs_create_dir(name, phyd);
13227ac9a364SKalle Valo 	il->debugfs_dir = dir_drv;
13237ac9a364SKalle Valo 
13247ac9a364SKalle Valo 	dir_data = debugfs_create_dir("data", dir_drv);
13257ac9a364SKalle Valo 	dir_rf = debugfs_create_dir("rf", dir_drv);
13267ac9a364SKalle Valo 	dir_debug = debugfs_create_dir("debug", dir_drv);
13277ac9a364SKalle Valo 
13282ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(nvm, dir_data, 0400);
13292ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(sram, dir_data, 0600);
13302ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(stations, dir_data, 0400);
13312ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(channels, dir_data, 0400);
13322ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(status, dir_data, 0400);
13332ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(interrupt, dir_data, 0600);
13342ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(qos, dir_data, 0400);
13352ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(disable_ht40, dir_data, 0600);
13362ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(rx_stats, dir_debug, 0400);
13372ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(tx_stats, dir_debug, 0400);
13382ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(rx_queue, dir_debug, 0400);
13392ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(tx_queue, dir_debug, 0400);
13402ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(power_save_status, dir_debug, 0400);
13412ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(clear_ucode_stats, dir_debug, 0200);
13422ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(clear_traffic_stats, dir_debug, 0200);
13432ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(fh_reg, dir_debug, 0400);
13442ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(missed_beacon, dir_debug, 0200);
13452ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(force_reset, dir_debug, 0600);
13462ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, 0400);
13472ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, 0400);
13482ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, 0400);
13497ac9a364SKalle Valo 
13507ac9a364SKalle Valo 	if (il->cfg->sensitivity_calib_by_driver)
13512ef00c53SJoe Perches 		DEBUGFS_ADD_FILE(sensitivity, dir_debug, 0400);
13527ac9a364SKalle Valo 	if (il->cfg->chain_noise_calib_by_driver)
13532ef00c53SJoe Perches 		DEBUGFS_ADD_FILE(chain_noise, dir_debug, 0400);
13542ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(rxon_flags, dir_debug, 0200);
13552ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, 0200);
13562ef00c53SJoe Perches 	DEBUGFS_ADD_FILE(wd_timeout, dir_debug, 0200);
13577ac9a364SKalle Valo 	if (il->cfg->sensitivity_calib_by_driver)
13587ac9a364SKalle Valo 		DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
13597ac9a364SKalle Valo 				 &il->disable_sens_cal);
13607ac9a364SKalle Valo 	if (il->cfg->chain_noise_calib_by_driver)
13617ac9a364SKalle Valo 		DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
13627ac9a364SKalle Valo 				 &il->disable_chain_noise_cal);
13637ac9a364SKalle Valo 	DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal);
13647ac9a364SKalle Valo }
13657ac9a364SKalle Valo EXPORT_SYMBOL(il_dbgfs_register);
13667ac9a364SKalle Valo 
13676182abd8SLee Jones /*
13687ac9a364SKalle Valo  * Remove the debugfs files and directories
13697ac9a364SKalle Valo  */
13707ac9a364SKalle Valo void
il_dbgfs_unregister(struct il_priv * il)13717ac9a364SKalle Valo il_dbgfs_unregister(struct il_priv *il)
13727ac9a364SKalle Valo {
13737ac9a364SKalle Valo 	if (!il->debugfs_dir)
13747ac9a364SKalle Valo 		return;
13757ac9a364SKalle Valo 
13767ac9a364SKalle Valo 	debugfs_remove_recursive(il->debugfs_dir);
13777ac9a364SKalle Valo 	il->debugfs_dir = NULL;
13787ac9a364SKalle Valo }
13797ac9a364SKalle Valo EXPORT_SYMBOL(il_dbgfs_unregister);
1380