Linux Audio

Check our new training course

Loading...
v6.8
   1// SPDX-License-Identifier: GPL-2.0-only
   2/******************************************************************************
   3 *
 
 
   4 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
   5 *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
   6 * Contact Information:
   7 *  Intel Linux Wireless <ilw@linux.intel.com>
   8 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
   9 *****************************************************************************/
  10#include <linux/ieee80211.h>
  11#include <linux/export.h>
  12#include <net/mac80211.h>
  13
  14#include "common.h"
  15
  16static void
  17il_clear_traffic_stats(struct il_priv *il)
  18{
  19	memset(&il->tx_stats, 0, sizeof(struct traffic_stats));
  20	memset(&il->rx_stats, 0, sizeof(struct traffic_stats));
  21}
  22
  23/*
  24 * il_update_stats function record all the MGMT, CTRL and DATA pkt for
  25 * both TX and Rx . Use debugfs to display the rx/rx_stats
  26 */
  27void
  28il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len)
  29{
  30	struct traffic_stats *stats;
  31
  32	if (is_tx)
  33		stats = &il->tx_stats;
  34	else
  35		stats = &il->rx_stats;
  36
  37	if (ieee80211_is_mgmt(fc)) {
  38		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
  39		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
  40			stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
  41			break;
  42		case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
  43			stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
  44			break;
  45		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
  46			stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
  47			break;
  48		case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
  49			stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
  50			break;
  51		case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
  52			stats->mgmt[MANAGEMENT_PROBE_REQ]++;
  53			break;
  54		case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
  55			stats->mgmt[MANAGEMENT_PROBE_RESP]++;
  56			break;
  57		case cpu_to_le16(IEEE80211_STYPE_BEACON):
  58			stats->mgmt[MANAGEMENT_BEACON]++;
  59			break;
  60		case cpu_to_le16(IEEE80211_STYPE_ATIM):
  61			stats->mgmt[MANAGEMENT_ATIM]++;
  62			break;
  63		case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
  64			stats->mgmt[MANAGEMENT_DISASSOC]++;
  65			break;
  66		case cpu_to_le16(IEEE80211_STYPE_AUTH):
  67			stats->mgmt[MANAGEMENT_AUTH]++;
  68			break;
  69		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
  70			stats->mgmt[MANAGEMENT_DEAUTH]++;
  71			break;
  72		case cpu_to_le16(IEEE80211_STYPE_ACTION):
  73			stats->mgmt[MANAGEMENT_ACTION]++;
  74			break;
  75		}
  76	} else if (ieee80211_is_ctl(fc)) {
  77		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
  78		case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
  79			stats->ctrl[CONTROL_BACK_REQ]++;
  80			break;
  81		case cpu_to_le16(IEEE80211_STYPE_BACK):
  82			stats->ctrl[CONTROL_BACK]++;
  83			break;
  84		case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
  85			stats->ctrl[CONTROL_PSPOLL]++;
  86			break;
  87		case cpu_to_le16(IEEE80211_STYPE_RTS):
  88			stats->ctrl[CONTROL_RTS]++;
  89			break;
  90		case cpu_to_le16(IEEE80211_STYPE_CTS):
  91			stats->ctrl[CONTROL_CTS]++;
  92			break;
  93		case cpu_to_le16(IEEE80211_STYPE_ACK):
  94			stats->ctrl[CONTROL_ACK]++;
  95			break;
  96		case cpu_to_le16(IEEE80211_STYPE_CFEND):
  97			stats->ctrl[CONTROL_CFEND]++;
  98			break;
  99		case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
 100			stats->ctrl[CONTROL_CFENDACK]++;
 101			break;
 102		}
 103	} else {
 104		/* data */
 105		stats->data_cnt++;
 106		stats->data_bytes += len;
 107	}
 108}
 109EXPORT_SYMBOL(il_update_stats);
 110
 111/* create and remove of files */
 112#define DEBUGFS_ADD_FILE(name, parent, mode) do {			\
 113	debugfs_create_file(#name, mode, parent, il,			\
 114			    &il_dbgfs_##name##_ops);			\
 
 115} while (0)
 116
 117#define DEBUGFS_ADD_BOOL(name, parent, ptr) do {			\
 118	debugfs_create_bool(#name, 0600, parent, ptr);			\
 
 
 
 
 
 
 
 
 
 
 
 
 119} while (0)
 120
 121/* file operation */
 122#define DEBUGFS_READ_FUNC(name)                                         \
 123static ssize_t il_dbgfs_##name##_read(struct file *file,               \
 124					char __user *user_buf,          \
 125					size_t count, loff_t *ppos);
 126
 127#define DEBUGFS_WRITE_FUNC(name)                                        \
 128static ssize_t il_dbgfs_##name##_write(struct file *file,              \
 129					const char __user *user_buf,    \
 130					size_t count, loff_t *ppos);
 131
 132
 133#define DEBUGFS_READ_FILE_OPS(name)				\
 134	DEBUGFS_READ_FUNC(name);				\
 135static const struct file_operations il_dbgfs_##name##_ops = {	\
 136	.read = il_dbgfs_##name##_read,				\
 137	.open = simple_open,					\
 138	.llseek = generic_file_llseek,				\
 139};
 140
 141#define DEBUGFS_WRITE_FILE_OPS(name)				\
 142	DEBUGFS_WRITE_FUNC(name);				\
 143static const struct file_operations il_dbgfs_##name##_ops = {	\
 144	.write = il_dbgfs_##name##_write,			\
 145	.open = simple_open,					\
 146	.llseek = generic_file_llseek,				\
 147};
 148
 149#define DEBUGFS_READ_WRITE_FILE_OPS(name)			\
 150	DEBUGFS_READ_FUNC(name);				\
 151	DEBUGFS_WRITE_FUNC(name);				\
 152static const struct file_operations il_dbgfs_##name##_ops = {	\
 153	.write = il_dbgfs_##name##_write,			\
 154	.read = il_dbgfs_##name##_read,				\
 155	.open = simple_open,					\
 156	.llseek = generic_file_llseek,				\
 157};
 158
 159static const char *
 160il_get_mgmt_string(int cmd)
 161{
 162	switch (cmd) {
 163	IL_CMD(MANAGEMENT_ASSOC_REQ);
 164	IL_CMD(MANAGEMENT_ASSOC_RESP);
 165	IL_CMD(MANAGEMENT_REASSOC_REQ);
 166	IL_CMD(MANAGEMENT_REASSOC_RESP);
 167	IL_CMD(MANAGEMENT_PROBE_REQ);
 168	IL_CMD(MANAGEMENT_PROBE_RESP);
 169	IL_CMD(MANAGEMENT_BEACON);
 170	IL_CMD(MANAGEMENT_ATIM);
 171	IL_CMD(MANAGEMENT_DISASSOC);
 172	IL_CMD(MANAGEMENT_AUTH);
 173	IL_CMD(MANAGEMENT_DEAUTH);
 174	IL_CMD(MANAGEMENT_ACTION);
 175	default:
 176		return "UNKNOWN";
 177
 178	}
 179}
 180
 181static const char *
 182il_get_ctrl_string(int cmd)
 183{
 184	switch (cmd) {
 185	IL_CMD(CONTROL_BACK_REQ);
 186	IL_CMD(CONTROL_BACK);
 187	IL_CMD(CONTROL_PSPOLL);
 188	IL_CMD(CONTROL_RTS);
 189	IL_CMD(CONTROL_CTS);
 190	IL_CMD(CONTROL_ACK);
 191	IL_CMD(CONTROL_CFEND);
 192	IL_CMD(CONTROL_CFENDACK);
 193	default:
 194		return "UNKNOWN";
 195
 196	}
 197}
 198
 199static ssize_t
 200il_dbgfs_tx_stats_read(struct file *file, char __user *user_buf, size_t count,
 201		       loff_t *ppos)
 202{
 203
 204	struct il_priv *il = file->private_data;
 205	char *buf;
 206	int pos = 0;
 207
 208	int cnt;
 209	ssize_t ret;
 210	const size_t bufsz =
 211	    100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
 212	buf = kzalloc(bufsz, GFP_KERNEL);
 213	if (!buf)
 214		return -ENOMEM;
 215	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
 216	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
 217		pos +=
 218		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
 219			      il_get_mgmt_string(cnt), il->tx_stats.mgmt[cnt]);
 220	}
 221	pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
 222	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
 223		pos +=
 224		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
 225			      il_get_ctrl_string(cnt), il->tx_stats.ctrl[cnt]);
 226	}
 227	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
 228	pos +=
 229	    scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
 230		      il->tx_stats.data_cnt);
 231	pos +=
 232	    scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
 233		      il->tx_stats.data_bytes);
 234	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 235	kfree(buf);
 236	return ret;
 237}
 238
 239static ssize_t
 240il_dbgfs_clear_traffic_stats_write(struct file *file,
 241				   const char __user *user_buf, size_t count,
 242				   loff_t *ppos)
 243{
 244	struct il_priv *il = file->private_data;
 245	u32 clear_flag;
 246	char buf[8];
 247	int buf_size;
 248
 249	memset(buf, 0, sizeof(buf));
 250	buf_size = min(count, sizeof(buf) - 1);
 251	if (copy_from_user(buf, user_buf, buf_size))
 252		return -EFAULT;
 253	if (sscanf(buf, "%x", &clear_flag) != 1)
 254		return -EFAULT;
 255	il_clear_traffic_stats(il);
 256
 257	return count;
 258}
 259
 260static ssize_t
 261il_dbgfs_rx_stats_read(struct file *file, char __user *user_buf, size_t count,
 262		       loff_t *ppos)
 263{
 264
 265	struct il_priv *il = file->private_data;
 266	char *buf;
 267	int pos = 0;
 268	int cnt;
 269	ssize_t ret;
 270	const size_t bufsz =
 271	    100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
 272	buf = kzalloc(bufsz, GFP_KERNEL);
 273	if (!buf)
 274		return -ENOMEM;
 275
 276	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
 277	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
 278		pos +=
 279		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
 280			      il_get_mgmt_string(cnt), il->rx_stats.mgmt[cnt]);
 281	}
 282	pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
 283	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
 284		pos +=
 285		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
 286			      il_get_ctrl_string(cnt), il->rx_stats.ctrl[cnt]);
 287	}
 288	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
 289	pos +=
 290	    scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
 291		      il->rx_stats.data_cnt);
 292	pos +=
 293	    scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
 294		      il->rx_stats.data_bytes);
 295
 296	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 297	kfree(buf);
 298	return ret;
 299}
 300
 301#define BYTE1_MASK 0x000000ff;
 302#define BYTE2_MASK 0x0000ffff;
 303#define BYTE3_MASK 0x00ffffff;
 304static ssize_t
 305il_dbgfs_sram_read(struct file *file, char __user *user_buf, size_t count,
 306		   loff_t *ppos)
 307{
 308	u32 val;
 309	char *buf;
 310	ssize_t ret;
 311	int i;
 312	int pos = 0;
 313	struct il_priv *il = file->private_data;
 314	size_t bufsz;
 315
 316	/* default is to dump the entire data segment */
 317	if (!il->dbgfs_sram_offset && !il->dbgfs_sram_len) {
 318		il->dbgfs_sram_offset = 0x800000;
 319		if (il->ucode_type == UCODE_INIT)
 320			il->dbgfs_sram_len = il->ucode_init_data.len;
 321		else
 322			il->dbgfs_sram_len = il->ucode_data.len;
 323	}
 324	bufsz = 30 + il->dbgfs_sram_len * sizeof(char) * 10;
 325	buf = kmalloc(bufsz, GFP_KERNEL);
 326	if (!buf)
 327		return -ENOMEM;
 328	pos +=
 329	    scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
 330		      il->dbgfs_sram_len);
 331	pos +=
 332	    scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
 333		      il->dbgfs_sram_offset);
 334	for (i = il->dbgfs_sram_len; i > 0; i -= 4) {
 335		val =
 336		    il_read_targ_mem(il,
 337				     il->dbgfs_sram_offset +
 338				     il->dbgfs_sram_len - i);
 339		if (i < 4) {
 340			switch (i) {
 341			case 1:
 342				val &= BYTE1_MASK;
 343				break;
 344			case 2:
 345				val &= BYTE2_MASK;
 346				break;
 347			case 3:
 348				val &= BYTE3_MASK;
 349				break;
 350			}
 351		}
 352		if (!(i % 16))
 353			pos += scnprintf(buf + pos, bufsz - pos, "\n");
 354		pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
 355	}
 356	pos += scnprintf(buf + pos, bufsz - pos, "\n");
 357
 358	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 359	kfree(buf);
 360	return ret;
 361}
 362
 363static ssize_t
 364il_dbgfs_sram_write(struct file *file, const char __user *user_buf,
 365		    size_t count, loff_t *ppos)
 366{
 367	struct il_priv *il = file->private_data;
 368	char buf[64];
 369	int buf_size;
 370	u32 offset, len;
 371
 372	memset(buf, 0, sizeof(buf));
 373	buf_size = min(count, sizeof(buf) - 1);
 374	if (copy_from_user(buf, user_buf, buf_size))
 375		return -EFAULT;
 376
 377	if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
 378		il->dbgfs_sram_offset = offset;
 379		il->dbgfs_sram_len = len;
 380	} else {
 381		il->dbgfs_sram_offset = 0;
 382		il->dbgfs_sram_len = 0;
 383	}
 384
 385	return count;
 386}
 387
 388static ssize_t
 389il_dbgfs_stations_read(struct file *file, char __user *user_buf, size_t count,
 390		       loff_t *ppos)
 391{
 392	struct il_priv *il = file->private_data;
 393	struct il_station_entry *station;
 394	int max_sta = il->hw_params.max_stations;
 395	char *buf;
 396	int i, j, pos = 0;
 397	ssize_t ret;
 398	/* Add 30 for initial string */
 399	const size_t bufsz = 30 + sizeof(char) * 500 * (il->num_stations);
 400
 401	buf = kmalloc(bufsz, GFP_KERNEL);
 402	if (!buf)
 403		return -ENOMEM;
 404
 405	pos +=
 406	    scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
 407		      il->num_stations);
 408
 409	for (i = 0; i < max_sta; i++) {
 410		station = &il->stations[i];
 411		if (!station->used)
 412			continue;
 413		pos +=
 414		    scnprintf(buf + pos, bufsz - pos,
 415			      "station %d - addr: %pM, flags: %#x\n", i,
 416			      station->sta.sta.addr,
 417			      station->sta.station_flags_msk);
 418		pos +=
 419		    scnprintf(buf + pos, bufsz - pos,
 420			      "TID\tseq_num\ttxq_id\tframes\ttfds\t");
 421		pos +=
 422		    scnprintf(buf + pos, bufsz - pos,
 423			      "start_idx\tbitmap\t\t\trate_n_flags\n");
 424
 425		for (j = 0; j < MAX_TID_COUNT; j++) {
 426			pos +=
 427			    scnprintf(buf + pos, bufsz - pos,
 428				      "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x",
 429				      j, station->tid[j].seq_number,
 430				      station->tid[j].agg.txq_id,
 431				      station->tid[j].agg.frame_count,
 432				      station->tid[j].tfds_in_queue,
 433				      station->tid[j].agg.start_idx,
 434				      station->tid[j].agg.bitmap,
 435				      station->tid[j].agg.rate_n_flags);
 436
 437			if (station->tid[j].agg.wait_for_ba)
 438				pos +=
 439				    scnprintf(buf + pos, bufsz - pos,
 440					      " - waitforba");
 441			pos += scnprintf(buf + pos, bufsz - pos, "\n");
 442		}
 443
 444		pos += scnprintf(buf + pos, bufsz - pos, "\n");
 445	}
 446
 447	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 448	kfree(buf);
 449	return ret;
 450}
 451
 452static ssize_t
 453il_dbgfs_nvm_read(struct file *file, char __user *user_buf, size_t count,
 454		  loff_t *ppos)
 455{
 456	ssize_t ret;
 457	struct il_priv *il = file->private_data;
 458	int pos = 0, ofs = 0, buf_size = 0;
 459	const u8 *ptr;
 460	char *buf;
 461	u16 eeprom_ver;
 462	size_t eeprom_len = il->cfg->eeprom_size;
 463	buf_size = 4 * eeprom_len + 256;
 464
 465	if (eeprom_len % 16) {
 466		IL_ERR("NVM size is not multiple of 16.\n");
 467		return -ENODATA;
 468	}
 469
 470	ptr = il->eeprom;
 471	if (!ptr) {
 472		IL_ERR("Invalid EEPROM memory\n");
 473		return -ENOMEM;
 474	}
 475
 476	/* 4 characters for byte 0xYY */
 477	buf = kzalloc(buf_size, GFP_KERNEL);
 478	if (!buf) {
 479		IL_ERR("Can not allocate Buffer\n");
 480		return -ENOMEM;
 481	}
 482	eeprom_ver = il_eeprom_query16(il, EEPROM_VERSION);
 483	pos +=
 484	    scnprintf(buf + pos, buf_size - pos, "EEPROM " "version: 0x%x\n",
 485		      eeprom_ver);
 486	for (ofs = 0; ofs < eeprom_len; ofs += 16) {
 487		pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x %16ph\n",
 488				 ofs, ptr + ofs);
 489	}
 490
 491	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 492	kfree(buf);
 493	return ret;
 494}
 495
 496static ssize_t
 497il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count,
 498		       loff_t *ppos)
 499{
 500	struct il_priv *il = file->private_data;
 501	struct ieee80211_channel *channels = NULL;
 502	const struct ieee80211_supported_band *supp_band = NULL;
 503	int pos = 0, i, bufsz = PAGE_SIZE;
 504	char *buf;
 505	ssize_t ret;
 506
 507	if (!test_bit(S_GEO_CONFIGURED, &il->status))
 508		return -EAGAIN;
 509
 510	buf = kzalloc(bufsz, GFP_KERNEL);
 511	if (!buf) {
 512		IL_ERR("Can not allocate Buffer\n");
 513		return -ENOMEM;
 514	}
 515
 516	supp_band = il_get_hw_mode(il, NL80211_BAND_2GHZ);
 517	if (supp_band) {
 518		channels = supp_band->channels;
 519
 520		pos +=
 521		    scnprintf(buf + pos, bufsz - pos,
 522			      "Displaying %d channels in 2.4GHz band 802.11bg):\n",
 523			      supp_band->n_channels);
 524
 525		for (i = 0; i < supp_band->n_channels; i++)
 526			pos +=
 527			    scnprintf(buf + pos, bufsz - pos,
 528				      "%d: %ddBm: BSS%s%s, %s.\n",
 529				      channels[i].hw_value,
 530				      channels[i].max_power,
 531				      channels[i].
 532				      flags & IEEE80211_CHAN_RADAR ?
 533				      " (IEEE 802.11h required)" : "",
 534				      ((channels[i].
 535					flags & IEEE80211_CHAN_NO_IR) ||
 536				       (channels[i].
 537					flags & IEEE80211_CHAN_RADAR)) ? "" :
 538				      ", IBSS",
 539				      channels[i].
 540				      flags & IEEE80211_CHAN_NO_IR ?
 541				      "passive only" : "active/passive");
 542	}
 543	supp_band = il_get_hw_mode(il, NL80211_BAND_5GHZ);
 544	if (supp_band) {
 545		channels = supp_band->channels;
 546
 547		pos +=
 548		    scnprintf(buf + pos, bufsz - pos,
 549			      "Displaying %d channels in 5.2GHz band (802.11a)\n",
 550			      supp_band->n_channels);
 551
 552		for (i = 0; i < supp_band->n_channels; i++)
 553			pos +=
 554			    scnprintf(buf + pos, bufsz - pos,
 555				      "%d: %ddBm: BSS%s%s, %s.\n",
 556				      channels[i].hw_value,
 557				      channels[i].max_power,
 558				      channels[i].
 559				      flags & IEEE80211_CHAN_RADAR ?
 560				      " (IEEE 802.11h required)" : "",
 561				      ((channels[i].
 562					flags & IEEE80211_CHAN_NO_IR) ||
 563				       (channels[i].
 564					flags & IEEE80211_CHAN_RADAR)) ? "" :
 565				      ", IBSS",
 566				      channels[i].
 567				      flags & IEEE80211_CHAN_NO_IR ?
 568				      "passive only" : "active/passive");
 569	}
 570	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 571	kfree(buf);
 572	return ret;
 573}
 574
 575static ssize_t
 576il_dbgfs_status_read(struct file *file, char __user *user_buf, size_t count,
 577		     loff_t *ppos)
 578{
 579
 580	struct il_priv *il = file->private_data;
 581	char buf[512];
 582	int pos = 0;
 583	const size_t bufsz = sizeof(buf);
 584
 585	pos +=
 586	    scnprintf(buf + pos, bufsz - pos, "S_HCMD_ACTIVE:\t %d\n",
 587		      test_bit(S_HCMD_ACTIVE, &il->status));
 588	pos +=
 589	    scnprintf(buf + pos, bufsz - pos, "S_INT_ENABLED:\t %d\n",
 590		      test_bit(S_INT_ENABLED, &il->status));
 591	pos +=
 592	    scnprintf(buf + pos, bufsz - pos, "S_RFKILL:\t %d\n",
 593		      test_bit(S_RFKILL, &il->status));
 594	pos +=
 595	    scnprintf(buf + pos, bufsz - pos, "S_CT_KILL:\t\t %d\n",
 596		      test_bit(S_CT_KILL, &il->status));
 597	pos +=
 598	    scnprintf(buf + pos, bufsz - pos, "S_INIT:\t\t %d\n",
 599		      test_bit(S_INIT, &il->status));
 600	pos +=
 601	    scnprintf(buf + pos, bufsz - pos, "S_ALIVE:\t\t %d\n",
 602		      test_bit(S_ALIVE, &il->status));
 603	pos +=
 604	    scnprintf(buf + pos, bufsz - pos, "S_READY:\t\t %d\n",
 605		      test_bit(S_READY, &il->status));
 606	pos +=
 607	    scnprintf(buf + pos, bufsz - pos, "S_TEMPERATURE:\t %d\n",
 608		      test_bit(S_TEMPERATURE, &il->status));
 609	pos +=
 610	    scnprintf(buf + pos, bufsz - pos, "S_GEO_CONFIGURED:\t %d\n",
 611		      test_bit(S_GEO_CONFIGURED, &il->status));
 612	pos +=
 613	    scnprintf(buf + pos, bufsz - pos, "S_EXIT_PENDING:\t %d\n",
 614		      test_bit(S_EXIT_PENDING, &il->status));
 615	pos +=
 616	    scnprintf(buf + pos, bufsz - pos, "S_STATS:\t %d\n",
 617		      test_bit(S_STATS, &il->status));
 618	pos +=
 619	    scnprintf(buf + pos, bufsz - pos, "S_SCANNING:\t %d\n",
 620		      test_bit(S_SCANNING, &il->status));
 621	pos +=
 622	    scnprintf(buf + pos, bufsz - pos, "S_SCAN_ABORTING:\t %d\n",
 623		      test_bit(S_SCAN_ABORTING, &il->status));
 624	pos +=
 625	    scnprintf(buf + pos, bufsz - pos, "S_SCAN_HW:\t\t %d\n",
 626		      test_bit(S_SCAN_HW, &il->status));
 627	pos +=
 628	    scnprintf(buf + pos, bufsz - pos, "S_POWER_PMI:\t %d\n",
 629		      test_bit(S_POWER_PMI, &il->status));
 630	pos +=
 631	    scnprintf(buf + pos, bufsz - pos, "S_FW_ERROR:\t %d\n",
 632		      test_bit(S_FW_ERROR, &il->status));
 633	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 634}
 635
 636static ssize_t
 637il_dbgfs_interrupt_read(struct file *file, char __user *user_buf, size_t count,
 638			loff_t *ppos)
 639{
 640
 641	struct il_priv *il = file->private_data;
 642	int pos = 0;
 643	int cnt = 0;
 644	char *buf;
 645	int bufsz = 24 * 64;	/* 24 items * 64 char per item */
 646	ssize_t ret;
 647
 648	buf = kzalloc(bufsz, GFP_KERNEL);
 649	if (!buf) {
 650		IL_ERR("Can not allocate Buffer\n");
 651		return -ENOMEM;
 652	}
 653
 654	pos +=
 655	    scnprintf(buf + pos, bufsz - pos, "Interrupt Statistics Report:\n");
 656
 657	pos +=
 658	    scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
 659		      il->isr_stats.hw);
 660	pos +=
 661	    scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
 662		      il->isr_stats.sw);
 663	if (il->isr_stats.sw || il->isr_stats.hw) {
 664		pos +=
 665		    scnprintf(buf + pos, bufsz - pos,
 666			      "\tLast Restarting Code:  0x%X\n",
 667			      il->isr_stats.err_code);
 668	}
 669#ifdef CONFIG_IWLEGACY_DEBUG
 670	pos +=
 671	    scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
 672		      il->isr_stats.sch);
 673	pos +=
 674	    scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
 675		      il->isr_stats.alive);
 676#endif
 677	pos +=
 678	    scnprintf(buf + pos, bufsz - pos,
 679		      "HW RF KILL switch toggled:\t %u\n",
 680		      il->isr_stats.rfkill);
 681
 682	pos +=
 683	    scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
 684		      il->isr_stats.ctkill);
 685
 686	pos +=
 687	    scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
 688		      il->isr_stats.wakeup);
 689
 690	pos +=
 691	    scnprintf(buf + pos, bufsz - pos, "Rx command responses:\t\t %u\n",
 692		      il->isr_stats.rx);
 693	for (cnt = 0; cnt < IL_CN_MAX; cnt++) {
 694		if (il->isr_stats.handlers[cnt] > 0)
 695			pos +=
 696			    scnprintf(buf + pos, bufsz - pos,
 697				      "\tRx handler[%36s]:\t\t %u\n",
 698				      il_get_cmd_string(cnt),
 699				      il->isr_stats.handlers[cnt]);
 700	}
 701
 702	pos +=
 703	    scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
 704		      il->isr_stats.tx);
 705
 706	pos +=
 707	    scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
 708		      il->isr_stats.unhandled);
 709
 710	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 711	kfree(buf);
 712	return ret;
 713}
 714
 715static ssize_t
 716il_dbgfs_interrupt_write(struct file *file, const char __user *user_buf,
 717			 size_t count, loff_t *ppos)
 718{
 719	struct il_priv *il = file->private_data;
 720	char buf[8];
 721	int buf_size;
 722	u32 reset_flag;
 723
 724	memset(buf, 0, sizeof(buf));
 725	buf_size = min(count, sizeof(buf) - 1);
 726	if (copy_from_user(buf, user_buf, buf_size))
 727		return -EFAULT;
 728	if (sscanf(buf, "%x", &reset_flag) != 1)
 729		return -EFAULT;
 730	if (reset_flag == 0)
 731		il_clear_isr_stats(il);
 732
 733	return count;
 734}
 735
 736static ssize_t
 737il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count,
 738		  loff_t *ppos)
 739{
 740	struct il_priv *il = file->private_data;
 741	int pos = 0, i;
 742	char buf[256];
 743	const size_t bufsz = sizeof(buf);
 744
 745	for (i = 0; i < AC_NUM; i++) {
 746		pos +=
 747		    scnprintf(buf + pos, bufsz - pos,
 748			      "\tcw_min\tcw_max\taifsn\ttxop\n");
 749		pos +=
 750		    scnprintf(buf + pos, bufsz - pos,
 751			      "AC[%d]\t%u\t%u\t%u\t%u\n", i,
 752			      il->qos_data.def_qos_parm.ac[i].cw_min,
 753			      il->qos_data.def_qos_parm.ac[i].cw_max,
 754			      il->qos_data.def_qos_parm.ac[i].aifsn,
 755			      il->qos_data.def_qos_parm.ac[i].edca_txop);
 756	}
 757
 758	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 759}
 760
 761static ssize_t
 762il_dbgfs_disable_ht40_write(struct file *file, const char __user *user_buf,
 763			    size_t count, loff_t *ppos)
 764{
 765	struct il_priv *il = file->private_data;
 766	char buf[8];
 767	int buf_size;
 768	int ht40;
 769
 770	memset(buf, 0, sizeof(buf));
 771	buf_size = min(count, sizeof(buf) - 1);
 772	if (copy_from_user(buf, user_buf, buf_size))
 773		return -EFAULT;
 774	if (sscanf(buf, "%d", &ht40) != 1)
 775		return -EFAULT;
 776	if (!il_is_any_associated(il))
 777		il->disable_ht40 = ht40 ? true : false;
 778	else {
 779		IL_ERR("Sta associated with AP - "
 780		       "Change to 40MHz channel support is not allowed\n");
 781		return -EINVAL;
 782	}
 783
 784	return count;
 785}
 786
 787static ssize_t
 788il_dbgfs_disable_ht40_read(struct file *file, char __user *user_buf,
 789			   size_t count, loff_t *ppos)
 790{
 791	struct il_priv *il = file->private_data;
 792	char buf[100];
 793	int pos = 0;
 794	const size_t bufsz = sizeof(buf);
 795
 796	pos +=
 797	    scnprintf(buf + pos, bufsz - pos, "11n 40MHz Mode: %s\n",
 798		      il->disable_ht40 ? "Disabled" : "Enabled");
 799	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 800}
 801
 802DEBUGFS_READ_WRITE_FILE_OPS(sram);
 803DEBUGFS_READ_FILE_OPS(nvm);
 804DEBUGFS_READ_FILE_OPS(stations);
 805DEBUGFS_READ_FILE_OPS(channels);
 806DEBUGFS_READ_FILE_OPS(status);
 807DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
 808DEBUGFS_READ_FILE_OPS(qos);
 809DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
 810
 811static ssize_t
 812il_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count,
 813		       loff_t *ppos)
 814{
 815
 816	struct il_priv *il = file->private_data;
 817	struct il_tx_queue *txq;
 818	struct il_queue *q;
 819	char *buf;
 820	int pos = 0;
 821	int cnt;
 822	int ret;
 823	const size_t bufsz =
 824	    sizeof(char) * 64 * il->cfg->num_of_queues;
 825
 826	if (!il->txq) {
 827		IL_ERR("txq not ready\n");
 828		return -EAGAIN;
 829	}
 830	buf = kzalloc(bufsz, GFP_KERNEL);
 831	if (!buf)
 832		return -ENOMEM;
 833
 834	for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
 835		txq = &il->txq[cnt];
 836		q = &txq->q;
 837		pos +=
 838		    scnprintf(buf + pos, bufsz - pos,
 839			      "hwq %.2d: read=%u write=%u stop=%d"
 840			      " swq_id=%#.2x (ac %d/hwq %d)\n", cnt,
 841			      q->read_ptr, q->write_ptr,
 842			      !!test_bit(cnt, il->queue_stopped),
 843			      txq->swq_id, txq->swq_id & 3,
 844			      (txq->swq_id >> 2) & 0x1f);
 845		if (cnt >= 4)
 846			continue;
 847		/* for the ACs, display the stop count too */
 848		pos +=
 849		    scnprintf(buf + pos, bufsz - pos,
 850			      "        stop-count: %d\n",
 851			      atomic_read(&il->queue_stop_count[cnt]));
 852	}
 853	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 854	kfree(buf);
 855	return ret;
 856}
 857
 858static ssize_t
 859il_dbgfs_rx_queue_read(struct file *file, char __user *user_buf, size_t count,
 860		       loff_t *ppos)
 861{
 862
 863	struct il_priv *il = file->private_data;
 864	struct il_rx_queue *rxq = &il->rxq;
 865	char buf[256];
 866	int pos = 0;
 867	const size_t bufsz = sizeof(buf);
 868
 869	pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", rxq->read);
 870	pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", rxq->write);
 871	pos +=
 872	    scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
 873		      rxq->free_count);
 874	if (rxq->rb_stts) {
 875		pos +=
 876		    scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
 877			      le16_to_cpu(rxq->rb_stts->
 878					  closed_rb_num) & 0x0FFF);
 879	} else {
 880		pos +=
 881		    scnprintf(buf + pos, bufsz - pos,
 882			      "closed_rb_num: Not Allocated\n");
 883	}
 884	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 885}
 886
 887static ssize_t
 888il_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf,
 889			     size_t count, loff_t *ppos)
 890{
 891	struct il_priv *il = file->private_data;
 892
 893	return il->debugfs_ops->rx_stats_read(file, user_buf, count, ppos);
 894}
 895
 896static ssize_t
 897il_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf,
 898			     size_t count, loff_t *ppos)
 899{
 900	struct il_priv *il = file->private_data;
 901
 902	return il->debugfs_ops->tx_stats_read(file, user_buf, count, ppos);
 903}
 904
 905static ssize_t
 906il_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf,
 907				  size_t count, loff_t *ppos)
 908{
 909	struct il_priv *il = file->private_data;
 910
 911	return il->debugfs_ops->general_stats_read(file, user_buf, count, ppos);
 912}
 913
 914static ssize_t
 915il_dbgfs_sensitivity_read(struct file *file, char __user *user_buf,
 916			  size_t count, loff_t *ppos)
 917{
 918
 919	struct il_priv *il = file->private_data;
 920	int pos = 0;
 921	int cnt = 0;
 922	char *buf;
 923	int bufsz = sizeof(struct il_sensitivity_data) * 4 + 100;
 924	ssize_t ret;
 925	struct il_sensitivity_data *data;
 926
 927	data = &il->sensitivity_data;
 928	buf = kzalloc(bufsz, GFP_KERNEL);
 929	if (!buf) {
 930		IL_ERR("Can not allocate Buffer\n");
 931		return -ENOMEM;
 932	}
 933
 934	pos +=
 935	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
 936		      data->auto_corr_ofdm);
 937	pos +=
 938	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc:\t\t %u\n",
 939		      data->auto_corr_ofdm_mrc);
 940	pos +=
 941	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
 942		      data->auto_corr_ofdm_x1);
 943	pos +=
 944	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc_x1:\t\t %u\n",
 945		      data->auto_corr_ofdm_mrc_x1);
 946	pos +=
 947	    scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
 948		      data->auto_corr_cck);
 949	pos +=
 950	    scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
 951		      data->auto_corr_cck_mrc);
 952	pos +=
 953	    scnprintf(buf + pos, bufsz - pos,
 954		      "last_bad_plcp_cnt_ofdm:\t\t %u\n",
 955		      data->last_bad_plcp_cnt_ofdm);
 956	pos +=
 957	    scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
 958		      data->last_fa_cnt_ofdm);
 959	pos +=
 960	    scnprintf(buf + pos, bufsz - pos, "last_bad_plcp_cnt_cck:\t\t %u\n",
 961		      data->last_bad_plcp_cnt_cck);
 962	pos +=
 963	    scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
 964		      data->last_fa_cnt_cck);
 965	pos +=
 966	    scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
 967		      data->nrg_curr_state);
 968	pos +=
 969	    scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
 970		      data->nrg_prev_state);
 971	pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
 972	for (cnt = 0; cnt < 10; cnt++) {
 973		pos +=
 974		    scnprintf(buf + pos, bufsz - pos, " %u",
 975			      data->nrg_value[cnt]);
 976	}
 977	pos += scnprintf(buf + pos, bufsz - pos, "\n");
 978	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
 979	for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
 980		pos +=
 981		    scnprintf(buf + pos, bufsz - pos, " %u",
 982			      data->nrg_silence_rssi[cnt]);
 983	}
 984	pos += scnprintf(buf + pos, bufsz - pos, "\n");
 985	pos +=
 986	    scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
 987		      data->nrg_silence_ref);
 988	pos +=
 989	    scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
 990		      data->nrg_energy_idx);
 991	pos +=
 992	    scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
 993		      data->nrg_silence_idx);
 994	pos +=
 995	    scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
 996		      data->nrg_th_cck);
 997	pos +=
 998	    scnprintf(buf + pos, bufsz - pos,
 999		      "nrg_auto_corr_silence_diff:\t %u\n",
1000		      data->nrg_auto_corr_silence_diff);
1001	pos +=
1002	    scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
1003		      data->num_in_cck_no_fa);
1004	pos +=
1005	    scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
1006		      data->nrg_th_ofdm);
1007
1008	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1009	kfree(buf);
1010	return ret;
1011}
1012
1013static ssize_t
1014il_dbgfs_chain_noise_read(struct file *file, char __user *user_buf,
1015			  size_t count, loff_t *ppos)
1016{
1017
1018	struct il_priv *il = file->private_data;
1019	int pos = 0;
1020	int cnt = 0;
1021	char *buf;
1022	int bufsz = sizeof(struct il_chain_noise_data) * 4 + 100;
1023	ssize_t ret;
1024	struct il_chain_noise_data *data;
1025
1026	data = &il->chain_noise_data;
1027	buf = kzalloc(bufsz, GFP_KERNEL);
1028	if (!buf) {
1029		IL_ERR("Can not allocate Buffer\n");
1030		return -ENOMEM;
1031	}
1032
1033	pos +=
1034	    scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
1035		      data->active_chains);
1036	pos +=
1037	    scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
1038		      data->chain_noise_a);
1039	pos +=
1040	    scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
1041		      data->chain_noise_b);
1042	pos +=
1043	    scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
1044		      data->chain_noise_c);
1045	pos +=
1046	    scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
1047		      data->chain_signal_a);
1048	pos +=
1049	    scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
1050		      data->chain_signal_b);
1051	pos +=
1052	    scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
1053		      data->chain_signal_c);
1054	pos +=
1055	    scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
1056		      data->beacon_count);
1057
1058	pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
1059	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1060		pos +=
1061		    scnprintf(buf + pos, bufsz - pos, " %u",
1062			      data->disconn_array[cnt]);
1063	}
1064	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1065	pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
1066	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1067		pos +=
1068		    scnprintf(buf + pos, bufsz - pos, " %u",
1069			      data->delta_gain_code[cnt]);
1070	}
1071	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1072	pos +=
1073	    scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
1074		      data->radio_write);
1075	pos +=
1076	    scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
1077		      data->state);
1078
1079	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1080	kfree(buf);
1081	return ret;
1082}
1083
1084static ssize_t
1085il_dbgfs_power_save_status_read(struct file *file, char __user *user_buf,
1086				size_t count, loff_t *ppos)
1087{
1088	struct il_priv *il = file->private_data;
1089	char buf[60];
1090	int pos = 0;
1091	const size_t bufsz = sizeof(buf);
1092	u32 pwrsave_status;
1093
1094	pwrsave_status =
1095	    _il_rd(il, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK;
1096
1097	pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
1098	pos +=
1099	    scnprintf(buf + pos, bufsz - pos, "%s\n",
1100		      (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
1101		      (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
1102		      (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
1103		      "error");
1104
1105	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1106}
1107
1108static ssize_t
1109il_dbgfs_clear_ucode_stats_write(struct file *file,
1110				 const char __user *user_buf, size_t count,
1111				 loff_t *ppos)
1112{
1113	struct il_priv *il = file->private_data;
1114	char buf[8];
1115	int buf_size;
1116	int clear;
1117
1118	memset(buf, 0, sizeof(buf));
1119	buf_size = min(count, sizeof(buf) - 1);
1120	if (copy_from_user(buf, user_buf, buf_size))
1121		return -EFAULT;
1122	if (sscanf(buf, "%d", &clear) != 1)
1123		return -EFAULT;
1124
1125	/* make request to uCode to retrieve stats information */
1126	mutex_lock(&il->mutex);
1127	il_send_stats_request(il, CMD_SYNC, true);
1128	mutex_unlock(&il->mutex);
1129
1130	return count;
1131}
1132
1133static ssize_t
1134il_dbgfs_rxon_flags_read(struct file *file, char __user *user_buf,
1135			 size_t count, loff_t *ppos)
1136{
1137
1138	struct il_priv *il = file->private_data;
1139	int len = 0;
1140	char buf[20];
1141
1142	len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.flags));
1143	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1144}
1145
1146static ssize_t
1147il_dbgfs_rxon_filter_flags_read(struct file *file, char __user *user_buf,
1148				size_t count, loff_t *ppos)
1149{
1150
1151	struct il_priv *il = file->private_data;
1152	int len = 0;
1153	char buf[20];
1154
1155	len =
1156	    sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags));
1157	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1158}
1159
1160static ssize_t
1161il_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count,
1162		     loff_t *ppos)
1163{
1164	struct il_priv *il = file->private_data;
1165	char *buf;
1166	int pos = 0;
1167	ssize_t ret = -EFAULT;
1168
1169	if (il->ops->dump_fh) {
1170		ret = pos = il->ops->dump_fh(il, &buf, true);
1171		if (buf) {
1172			ret =
1173			    simple_read_from_buffer(user_buf, count, ppos, buf,
1174						    pos);
1175			kfree(buf);
1176		}
1177	}
1178
1179	return ret;
1180}
1181
1182static ssize_t
1183il_dbgfs_missed_beacon_read(struct file *file, char __user *user_buf,
1184			    size_t count, loff_t *ppos)
1185{
1186
1187	struct il_priv *il = file->private_data;
1188	int pos = 0;
1189	char buf[12];
1190	const size_t bufsz = sizeof(buf);
1191
1192	pos +=
1193	    scnprintf(buf + pos, bufsz - pos, "%d\n",
1194		      il->missed_beacon_threshold);
1195
1196	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1197}
1198
1199static ssize_t
1200il_dbgfs_missed_beacon_write(struct file *file, const char __user *user_buf,
1201			     size_t count, loff_t *ppos)
1202{
1203	struct il_priv *il = file->private_data;
1204	char buf[8];
1205	int buf_size;
1206	int missed;
1207
1208	memset(buf, 0, sizeof(buf));
1209	buf_size = min(count, sizeof(buf) - 1);
1210	if (copy_from_user(buf, user_buf, buf_size))
1211		return -EFAULT;
1212	if (sscanf(buf, "%d", &missed) != 1)
1213		return -EINVAL;
1214
1215	if (missed < IL_MISSED_BEACON_THRESHOLD_MIN ||
1216	    missed > IL_MISSED_BEACON_THRESHOLD_MAX)
1217		il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
1218	else
1219		il->missed_beacon_threshold = missed;
1220
1221	return count;
1222}
1223
1224static ssize_t
1225il_dbgfs_force_reset_read(struct file *file, char __user *user_buf,
1226			  size_t count, loff_t *ppos)
1227{
1228
1229	struct il_priv *il = file->private_data;
1230	int pos = 0;
1231	char buf[300];
1232	const size_t bufsz = sizeof(buf);
1233	struct il_force_reset *force_reset;
1234
1235	force_reset = &il->force_reset;
1236
1237	pos +=
1238	    scnprintf(buf + pos, bufsz - pos, "\tnumber of reset request: %d\n",
1239		      force_reset->reset_request_count);
1240	pos +=
1241	    scnprintf(buf + pos, bufsz - pos,
1242		      "\tnumber of reset request success: %d\n",
1243		      force_reset->reset_success_count);
1244	pos +=
1245	    scnprintf(buf + pos, bufsz - pos,
1246		      "\tnumber of reset request reject: %d\n",
1247		      force_reset->reset_reject_count);
1248	pos +=
1249	    scnprintf(buf + pos, bufsz - pos, "\treset duration: %lu\n",
1250		      force_reset->reset_duration);
1251
1252	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1253}
1254
1255static ssize_t
1256il_dbgfs_force_reset_write(struct file *file, const char __user *user_buf,
1257			   size_t count, loff_t *ppos)
1258{
1259
1260	int ret;
1261	struct il_priv *il = file->private_data;
1262
1263	ret = il_force_reset(il, true);
1264
1265	return ret ? ret : count;
1266}
1267
1268static ssize_t
1269il_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf,
1270			  size_t count, loff_t *ppos)
1271{
1272
1273	struct il_priv *il = file->private_data;
1274	char buf[8];
1275	int buf_size;
1276	int timeout;
1277
1278	memset(buf, 0, sizeof(buf));
1279	buf_size = min(count, sizeof(buf) - 1);
1280	if (copy_from_user(buf, user_buf, buf_size))
1281		return -EFAULT;
1282	if (sscanf(buf, "%d", &timeout) != 1)
1283		return -EINVAL;
1284	if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT)
1285		timeout = IL_DEF_WD_TIMEOUT;
1286
1287	il->cfg->wd_timeout = timeout;
1288	il_setup_watchdog(il);
1289	return count;
1290}
1291
1292DEBUGFS_READ_FILE_OPS(rx_stats);
1293DEBUGFS_READ_FILE_OPS(tx_stats);
1294DEBUGFS_READ_FILE_OPS(rx_queue);
1295DEBUGFS_READ_FILE_OPS(tx_queue);
1296DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
1297DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
1298DEBUGFS_READ_FILE_OPS(ucode_general_stats);
1299DEBUGFS_READ_FILE_OPS(sensitivity);
1300DEBUGFS_READ_FILE_OPS(chain_noise);
1301DEBUGFS_READ_FILE_OPS(power_save_status);
1302DEBUGFS_WRITE_FILE_OPS(clear_ucode_stats);
1303DEBUGFS_WRITE_FILE_OPS(clear_traffic_stats);
1304DEBUGFS_READ_FILE_OPS(fh_reg);
1305DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
1306DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
1307DEBUGFS_READ_FILE_OPS(rxon_flags);
1308DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
1309DEBUGFS_WRITE_FILE_OPS(wd_timeout);
1310
1311/*
1312 * Create the debugfs files and directories
1313 *
1314 */
1315void
1316il_dbgfs_register(struct il_priv *il, const char *name)
1317{
1318	struct dentry *phyd = il->hw->wiphy->debugfsdir;
1319	struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
1320
1321	dir_drv = debugfs_create_dir(name, phyd);
 
 
 
1322	il->debugfs_dir = dir_drv;
1323
1324	dir_data = debugfs_create_dir("data", dir_drv);
 
 
1325	dir_rf = debugfs_create_dir("rf", dir_drv);
 
 
1326	dir_debug = debugfs_create_dir("debug", dir_drv);
 
 
1327
1328	DEBUGFS_ADD_FILE(nvm, dir_data, 0400);
1329	DEBUGFS_ADD_FILE(sram, dir_data, 0600);
1330	DEBUGFS_ADD_FILE(stations, dir_data, 0400);
1331	DEBUGFS_ADD_FILE(channels, dir_data, 0400);
1332	DEBUGFS_ADD_FILE(status, dir_data, 0400);
1333	DEBUGFS_ADD_FILE(interrupt, dir_data, 0600);
1334	DEBUGFS_ADD_FILE(qos, dir_data, 0400);
1335	DEBUGFS_ADD_FILE(disable_ht40, dir_data, 0600);
1336	DEBUGFS_ADD_FILE(rx_stats, dir_debug, 0400);
1337	DEBUGFS_ADD_FILE(tx_stats, dir_debug, 0400);
1338	DEBUGFS_ADD_FILE(rx_queue, dir_debug, 0400);
1339	DEBUGFS_ADD_FILE(tx_queue, dir_debug, 0400);
1340	DEBUGFS_ADD_FILE(power_save_status, dir_debug, 0400);
1341	DEBUGFS_ADD_FILE(clear_ucode_stats, dir_debug, 0200);
1342	DEBUGFS_ADD_FILE(clear_traffic_stats, dir_debug, 0200);
1343	DEBUGFS_ADD_FILE(fh_reg, dir_debug, 0400);
1344	DEBUGFS_ADD_FILE(missed_beacon, dir_debug, 0200);
1345	DEBUGFS_ADD_FILE(force_reset, dir_debug, 0600);
1346	DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, 0400);
1347	DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, 0400);
1348	DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, 0400);
1349
1350	if (il->cfg->sensitivity_calib_by_driver)
1351		DEBUGFS_ADD_FILE(sensitivity, dir_debug, 0400);
1352	if (il->cfg->chain_noise_calib_by_driver)
1353		DEBUGFS_ADD_FILE(chain_noise, dir_debug, 0400);
1354	DEBUGFS_ADD_FILE(rxon_flags, dir_debug, 0200);
1355	DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, 0200);
1356	DEBUGFS_ADD_FILE(wd_timeout, dir_debug, 0200);
1357	if (il->cfg->sensitivity_calib_by_driver)
1358		DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
1359				 &il->disable_sens_cal);
1360	if (il->cfg->chain_noise_calib_by_driver)
1361		DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
1362				 &il->disable_chain_noise_cal);
1363	DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal);
 
 
 
 
 
 
1364}
1365EXPORT_SYMBOL(il_dbgfs_register);
1366
1367/*
1368 * Remove the debugfs files and directories
 
1369 */
1370void
1371il_dbgfs_unregister(struct il_priv *il)
1372{
1373	if (!il->debugfs_dir)
1374		return;
1375
1376	debugfs_remove_recursive(il->debugfs_dir);
1377	il->debugfs_dir = NULL;
1378}
1379EXPORT_SYMBOL(il_dbgfs_unregister);
v4.6
 
   1/******************************************************************************
   2 *
   3 * GPL LICENSE SUMMARY
   4 *
   5 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of version 2 of the GNU General Public License as
   9 * published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful, but
  12 * WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
  19 * USA
  20 *
  21 * The full GNU General Public License is included in this distribution
  22 * in the file called LICENSE.GPL.
  23 *
  24 * Contact Information:
  25 *  Intel Linux Wireless <ilw@linux.intel.com>
  26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  27 *****************************************************************************/
  28#include <linux/ieee80211.h>
  29#include <linux/export.h>
  30#include <net/mac80211.h>
  31
  32#include "common.h"
  33
  34static void
  35il_clear_traffic_stats(struct il_priv *il)
  36{
  37	memset(&il->tx_stats, 0, sizeof(struct traffic_stats));
  38	memset(&il->rx_stats, 0, sizeof(struct traffic_stats));
  39}
  40
  41/*
  42 * il_update_stats function record all the MGMT, CTRL and DATA pkt for
  43 * both TX and Rx . Use debugfs to display the rx/rx_stats
  44 */
  45void
  46il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len)
  47{
  48	struct traffic_stats *stats;
  49
  50	if (is_tx)
  51		stats = &il->tx_stats;
  52	else
  53		stats = &il->rx_stats;
  54
  55	if (ieee80211_is_mgmt(fc)) {
  56		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
  57		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
  58			stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
  59			break;
  60		case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
  61			stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
  62			break;
  63		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
  64			stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
  65			break;
  66		case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
  67			stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
  68			break;
  69		case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
  70			stats->mgmt[MANAGEMENT_PROBE_REQ]++;
  71			break;
  72		case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
  73			stats->mgmt[MANAGEMENT_PROBE_RESP]++;
  74			break;
  75		case cpu_to_le16(IEEE80211_STYPE_BEACON):
  76			stats->mgmt[MANAGEMENT_BEACON]++;
  77			break;
  78		case cpu_to_le16(IEEE80211_STYPE_ATIM):
  79			stats->mgmt[MANAGEMENT_ATIM]++;
  80			break;
  81		case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
  82			stats->mgmt[MANAGEMENT_DISASSOC]++;
  83			break;
  84		case cpu_to_le16(IEEE80211_STYPE_AUTH):
  85			stats->mgmt[MANAGEMENT_AUTH]++;
  86			break;
  87		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
  88			stats->mgmt[MANAGEMENT_DEAUTH]++;
  89			break;
  90		case cpu_to_le16(IEEE80211_STYPE_ACTION):
  91			stats->mgmt[MANAGEMENT_ACTION]++;
  92			break;
  93		}
  94	} else if (ieee80211_is_ctl(fc)) {
  95		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
  96		case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
  97			stats->ctrl[CONTROL_BACK_REQ]++;
  98			break;
  99		case cpu_to_le16(IEEE80211_STYPE_BACK):
 100			stats->ctrl[CONTROL_BACK]++;
 101			break;
 102		case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
 103			stats->ctrl[CONTROL_PSPOLL]++;
 104			break;
 105		case cpu_to_le16(IEEE80211_STYPE_RTS):
 106			stats->ctrl[CONTROL_RTS]++;
 107			break;
 108		case cpu_to_le16(IEEE80211_STYPE_CTS):
 109			stats->ctrl[CONTROL_CTS]++;
 110			break;
 111		case cpu_to_le16(IEEE80211_STYPE_ACK):
 112			stats->ctrl[CONTROL_ACK]++;
 113			break;
 114		case cpu_to_le16(IEEE80211_STYPE_CFEND):
 115			stats->ctrl[CONTROL_CFEND]++;
 116			break;
 117		case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
 118			stats->ctrl[CONTROL_CFENDACK]++;
 119			break;
 120		}
 121	} else {
 122		/* data */
 123		stats->data_cnt++;
 124		stats->data_bytes += len;
 125	}
 126}
 127EXPORT_SYMBOL(il_update_stats);
 128
 129/* create and remove of files */
 130#define DEBUGFS_ADD_FILE(name, parent, mode) do {			\
 131	if (!debugfs_create_file(#name, mode, parent, il,		\
 132			 &il_dbgfs_##name##_ops))		\
 133		goto err;						\
 134} while (0)
 135
 136#define DEBUGFS_ADD_BOOL(name, parent, ptr) do {			\
 137	struct dentry *__tmp;						\
 138	__tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR,		\
 139				    parent, ptr);			\
 140	if (IS_ERR(__tmp) || !__tmp)					\
 141		goto err;						\
 142} while (0)
 143
 144#define DEBUGFS_ADD_X32(name, parent, ptr) do {				\
 145	struct dentry *__tmp;						\
 146	__tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR,		\
 147				   parent, ptr);			\
 148	if (IS_ERR(__tmp) || !__tmp)					\
 149		goto err;						\
 150} while (0)
 151
 152/* file operation */
 153#define DEBUGFS_READ_FUNC(name)                                         \
 154static ssize_t il_dbgfs_##name##_read(struct file *file,               \
 155					char __user *user_buf,          \
 156					size_t count, loff_t *ppos);
 157
 158#define DEBUGFS_WRITE_FUNC(name)                                        \
 159static ssize_t il_dbgfs_##name##_write(struct file *file,              \
 160					const char __user *user_buf,    \
 161					size_t count, loff_t *ppos);
 162
 163
 164#define DEBUGFS_READ_FILE_OPS(name)				\
 165	DEBUGFS_READ_FUNC(name);				\
 166static const struct file_operations il_dbgfs_##name##_ops = {	\
 167	.read = il_dbgfs_##name##_read,				\
 168	.open = simple_open,					\
 169	.llseek = generic_file_llseek,				\
 170};
 171
 172#define DEBUGFS_WRITE_FILE_OPS(name)				\
 173	DEBUGFS_WRITE_FUNC(name);				\
 174static const struct file_operations il_dbgfs_##name##_ops = {	\
 175	.write = il_dbgfs_##name##_write,			\
 176	.open = simple_open,					\
 177	.llseek = generic_file_llseek,				\
 178};
 179
 180#define DEBUGFS_READ_WRITE_FILE_OPS(name)			\
 181	DEBUGFS_READ_FUNC(name);				\
 182	DEBUGFS_WRITE_FUNC(name);				\
 183static const struct file_operations il_dbgfs_##name##_ops = {	\
 184	.write = il_dbgfs_##name##_write,			\
 185	.read = il_dbgfs_##name##_read,				\
 186	.open = simple_open,					\
 187	.llseek = generic_file_llseek,				\
 188};
 189
 190static const char *
 191il_get_mgmt_string(int cmd)
 192{
 193	switch (cmd) {
 194	IL_CMD(MANAGEMENT_ASSOC_REQ);
 195	IL_CMD(MANAGEMENT_ASSOC_RESP);
 196	IL_CMD(MANAGEMENT_REASSOC_REQ);
 197	IL_CMD(MANAGEMENT_REASSOC_RESP);
 198	IL_CMD(MANAGEMENT_PROBE_REQ);
 199	IL_CMD(MANAGEMENT_PROBE_RESP);
 200	IL_CMD(MANAGEMENT_BEACON);
 201	IL_CMD(MANAGEMENT_ATIM);
 202	IL_CMD(MANAGEMENT_DISASSOC);
 203	IL_CMD(MANAGEMENT_AUTH);
 204	IL_CMD(MANAGEMENT_DEAUTH);
 205	IL_CMD(MANAGEMENT_ACTION);
 206	default:
 207		return "UNKNOWN";
 208
 209	}
 210}
 211
 212static const char *
 213il_get_ctrl_string(int cmd)
 214{
 215	switch (cmd) {
 216	IL_CMD(CONTROL_BACK_REQ);
 217	IL_CMD(CONTROL_BACK);
 218	IL_CMD(CONTROL_PSPOLL);
 219	IL_CMD(CONTROL_RTS);
 220	IL_CMD(CONTROL_CTS);
 221	IL_CMD(CONTROL_ACK);
 222	IL_CMD(CONTROL_CFEND);
 223	IL_CMD(CONTROL_CFENDACK);
 224	default:
 225		return "UNKNOWN";
 226
 227	}
 228}
 229
 230static ssize_t
 231il_dbgfs_tx_stats_read(struct file *file, char __user *user_buf, size_t count,
 232		       loff_t *ppos)
 233{
 234
 235	struct il_priv *il = file->private_data;
 236	char *buf;
 237	int pos = 0;
 238
 239	int cnt;
 240	ssize_t ret;
 241	const size_t bufsz =
 242	    100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
 243	buf = kzalloc(bufsz, GFP_KERNEL);
 244	if (!buf)
 245		return -ENOMEM;
 246	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
 247	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
 248		pos +=
 249		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
 250			      il_get_mgmt_string(cnt), il->tx_stats.mgmt[cnt]);
 251	}
 252	pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
 253	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
 254		pos +=
 255		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
 256			      il_get_ctrl_string(cnt), il->tx_stats.ctrl[cnt]);
 257	}
 258	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
 259	pos +=
 260	    scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
 261		      il->tx_stats.data_cnt);
 262	pos +=
 263	    scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
 264		      il->tx_stats.data_bytes);
 265	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 266	kfree(buf);
 267	return ret;
 268}
 269
 270static ssize_t
 271il_dbgfs_clear_traffic_stats_write(struct file *file,
 272				   const char __user *user_buf, size_t count,
 273				   loff_t *ppos)
 274{
 275	struct il_priv *il = file->private_data;
 276	u32 clear_flag;
 277	char buf[8];
 278	int buf_size;
 279
 280	memset(buf, 0, sizeof(buf));
 281	buf_size = min(count, sizeof(buf) - 1);
 282	if (copy_from_user(buf, user_buf, buf_size))
 283		return -EFAULT;
 284	if (sscanf(buf, "%x", &clear_flag) != 1)
 285		return -EFAULT;
 286	il_clear_traffic_stats(il);
 287
 288	return count;
 289}
 290
 291static ssize_t
 292il_dbgfs_rx_stats_read(struct file *file, char __user *user_buf, size_t count,
 293		       loff_t *ppos)
 294{
 295
 296	struct il_priv *il = file->private_data;
 297	char *buf;
 298	int pos = 0;
 299	int cnt;
 300	ssize_t ret;
 301	const size_t bufsz =
 302	    100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
 303	buf = kzalloc(bufsz, GFP_KERNEL);
 304	if (!buf)
 305		return -ENOMEM;
 306
 307	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
 308	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
 309		pos +=
 310		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
 311			      il_get_mgmt_string(cnt), il->rx_stats.mgmt[cnt]);
 312	}
 313	pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
 314	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
 315		pos +=
 316		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
 317			      il_get_ctrl_string(cnt), il->rx_stats.ctrl[cnt]);
 318	}
 319	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
 320	pos +=
 321	    scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
 322		      il->rx_stats.data_cnt);
 323	pos +=
 324	    scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
 325		      il->rx_stats.data_bytes);
 326
 327	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 328	kfree(buf);
 329	return ret;
 330}
 331
 332#define BYTE1_MASK 0x000000ff;
 333#define BYTE2_MASK 0x0000ffff;
 334#define BYTE3_MASK 0x00ffffff;
 335static ssize_t
 336il_dbgfs_sram_read(struct file *file, char __user *user_buf, size_t count,
 337		   loff_t *ppos)
 338{
 339	u32 val;
 340	char *buf;
 341	ssize_t ret;
 342	int i;
 343	int pos = 0;
 344	struct il_priv *il = file->private_data;
 345	size_t bufsz;
 346
 347	/* default is to dump the entire data segment */
 348	if (!il->dbgfs_sram_offset && !il->dbgfs_sram_len) {
 349		il->dbgfs_sram_offset = 0x800000;
 350		if (il->ucode_type == UCODE_INIT)
 351			il->dbgfs_sram_len = il->ucode_init_data.len;
 352		else
 353			il->dbgfs_sram_len = il->ucode_data.len;
 354	}
 355	bufsz = 30 + il->dbgfs_sram_len * sizeof(char) * 10;
 356	buf = kmalloc(bufsz, GFP_KERNEL);
 357	if (!buf)
 358		return -ENOMEM;
 359	pos +=
 360	    scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
 361		      il->dbgfs_sram_len);
 362	pos +=
 363	    scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
 364		      il->dbgfs_sram_offset);
 365	for (i = il->dbgfs_sram_len; i > 0; i -= 4) {
 366		val =
 367		    il_read_targ_mem(il,
 368				     il->dbgfs_sram_offset +
 369				     il->dbgfs_sram_len - i);
 370		if (i < 4) {
 371			switch (i) {
 372			case 1:
 373				val &= BYTE1_MASK;
 374				break;
 375			case 2:
 376				val &= BYTE2_MASK;
 377				break;
 378			case 3:
 379				val &= BYTE3_MASK;
 380				break;
 381			}
 382		}
 383		if (!(i % 16))
 384			pos += scnprintf(buf + pos, bufsz - pos, "\n");
 385		pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
 386	}
 387	pos += scnprintf(buf + pos, bufsz - pos, "\n");
 388
 389	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 390	kfree(buf);
 391	return ret;
 392}
 393
 394static ssize_t
 395il_dbgfs_sram_write(struct file *file, const char __user *user_buf,
 396		    size_t count, loff_t *ppos)
 397{
 398	struct il_priv *il = file->private_data;
 399	char buf[64];
 400	int buf_size;
 401	u32 offset, len;
 402
 403	memset(buf, 0, sizeof(buf));
 404	buf_size = min(count, sizeof(buf) - 1);
 405	if (copy_from_user(buf, user_buf, buf_size))
 406		return -EFAULT;
 407
 408	if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
 409		il->dbgfs_sram_offset = offset;
 410		il->dbgfs_sram_len = len;
 411	} else {
 412		il->dbgfs_sram_offset = 0;
 413		il->dbgfs_sram_len = 0;
 414	}
 415
 416	return count;
 417}
 418
 419static ssize_t
 420il_dbgfs_stations_read(struct file *file, char __user *user_buf, size_t count,
 421		       loff_t *ppos)
 422{
 423	struct il_priv *il = file->private_data;
 424	struct il_station_entry *station;
 425	int max_sta = il->hw_params.max_stations;
 426	char *buf;
 427	int i, j, pos = 0;
 428	ssize_t ret;
 429	/* Add 30 for initial string */
 430	const size_t bufsz = 30 + sizeof(char) * 500 * (il->num_stations);
 431
 432	buf = kmalloc(bufsz, GFP_KERNEL);
 433	if (!buf)
 434		return -ENOMEM;
 435
 436	pos +=
 437	    scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
 438		      il->num_stations);
 439
 440	for (i = 0; i < max_sta; i++) {
 441		station = &il->stations[i];
 442		if (!station->used)
 443			continue;
 444		pos +=
 445		    scnprintf(buf + pos, bufsz - pos,
 446			      "station %d - addr: %pM, flags: %#x\n", i,
 447			      station->sta.sta.addr,
 448			      station->sta.station_flags_msk);
 449		pos +=
 450		    scnprintf(buf + pos, bufsz - pos,
 451			      "TID\tseq_num\ttxq_id\tframes\ttfds\t");
 452		pos +=
 453		    scnprintf(buf + pos, bufsz - pos,
 454			      "start_idx\tbitmap\t\t\trate_n_flags\n");
 455
 456		for (j = 0; j < MAX_TID_COUNT; j++) {
 457			pos +=
 458			    scnprintf(buf + pos, bufsz - pos,
 459				      "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x",
 460				      j, station->tid[j].seq_number,
 461				      station->tid[j].agg.txq_id,
 462				      station->tid[j].agg.frame_count,
 463				      station->tid[j].tfds_in_queue,
 464				      station->tid[j].agg.start_idx,
 465				      station->tid[j].agg.bitmap,
 466				      station->tid[j].agg.rate_n_flags);
 467
 468			if (station->tid[j].agg.wait_for_ba)
 469				pos +=
 470				    scnprintf(buf + pos, bufsz - pos,
 471					      " - waitforba");
 472			pos += scnprintf(buf + pos, bufsz - pos, "\n");
 473		}
 474
 475		pos += scnprintf(buf + pos, bufsz - pos, "\n");
 476	}
 477
 478	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 479	kfree(buf);
 480	return ret;
 481}
 482
 483static ssize_t
 484il_dbgfs_nvm_read(struct file *file, char __user *user_buf, size_t count,
 485		  loff_t *ppos)
 486{
 487	ssize_t ret;
 488	struct il_priv *il = file->private_data;
 489	int pos = 0, ofs = 0, buf_size = 0;
 490	const u8 *ptr;
 491	char *buf;
 492	u16 eeprom_ver;
 493	size_t eeprom_len = il->cfg->eeprom_size;
 494	buf_size = 4 * eeprom_len + 256;
 495
 496	if (eeprom_len % 16) {
 497		IL_ERR("NVM size is not multiple of 16.\n");
 498		return -ENODATA;
 499	}
 500
 501	ptr = il->eeprom;
 502	if (!ptr) {
 503		IL_ERR("Invalid EEPROM memory\n");
 504		return -ENOMEM;
 505	}
 506
 507	/* 4 characters for byte 0xYY */
 508	buf = kzalloc(buf_size, GFP_KERNEL);
 509	if (!buf) {
 510		IL_ERR("Can not allocate Buffer\n");
 511		return -ENOMEM;
 512	}
 513	eeprom_ver = il_eeprom_query16(il, EEPROM_VERSION);
 514	pos +=
 515	    scnprintf(buf + pos, buf_size - pos, "EEPROM " "version: 0x%x\n",
 516		      eeprom_ver);
 517	for (ofs = 0; ofs < eeprom_len; ofs += 16) {
 518		pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x %16ph\n",
 519				 ofs, ptr + ofs);
 520	}
 521
 522	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 523	kfree(buf);
 524	return ret;
 525}
 526
 527static ssize_t
 528il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count,
 529		       loff_t *ppos)
 530{
 531	struct il_priv *il = file->private_data;
 532	struct ieee80211_channel *channels = NULL;
 533	const struct ieee80211_supported_band *supp_band = NULL;
 534	int pos = 0, i, bufsz = PAGE_SIZE;
 535	char *buf;
 536	ssize_t ret;
 537
 538	if (!test_bit(S_GEO_CONFIGURED, &il->status))
 539		return -EAGAIN;
 540
 541	buf = kzalloc(bufsz, GFP_KERNEL);
 542	if (!buf) {
 543		IL_ERR("Can not allocate Buffer\n");
 544		return -ENOMEM;
 545	}
 546
 547	supp_band = il_get_hw_mode(il, IEEE80211_BAND_2GHZ);
 548	if (supp_band) {
 549		channels = supp_band->channels;
 550
 551		pos +=
 552		    scnprintf(buf + pos, bufsz - pos,
 553			      "Displaying %d channels in 2.4GHz band 802.11bg):\n",
 554			      supp_band->n_channels);
 555
 556		for (i = 0; i < supp_band->n_channels; i++)
 557			pos +=
 558			    scnprintf(buf + pos, bufsz - pos,
 559				      "%d: %ddBm: BSS%s%s, %s.\n",
 560				      channels[i].hw_value,
 561				      channels[i].max_power,
 562				      channels[i].
 563				      flags & IEEE80211_CHAN_RADAR ?
 564				      " (IEEE 802.11h required)" : "",
 565				      ((channels[i].
 566					flags & IEEE80211_CHAN_NO_IR) ||
 567				       (channels[i].
 568					flags & IEEE80211_CHAN_RADAR)) ? "" :
 569				      ", IBSS",
 570				      channels[i].
 571				      flags & IEEE80211_CHAN_NO_IR ?
 572				      "passive only" : "active/passive");
 573	}
 574	supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ);
 575	if (supp_band) {
 576		channels = supp_band->channels;
 577
 578		pos +=
 579		    scnprintf(buf + pos, bufsz - pos,
 580			      "Displaying %d channels in 5.2GHz band (802.11a)\n",
 581			      supp_band->n_channels);
 582
 583		for (i = 0; i < supp_band->n_channels; i++)
 584			pos +=
 585			    scnprintf(buf + pos, bufsz - pos,
 586				      "%d: %ddBm: BSS%s%s, %s.\n",
 587				      channels[i].hw_value,
 588				      channels[i].max_power,
 589				      channels[i].
 590				      flags & IEEE80211_CHAN_RADAR ?
 591				      " (IEEE 802.11h required)" : "",
 592				      ((channels[i].
 593					flags & IEEE80211_CHAN_NO_IR) ||
 594				       (channels[i].
 595					flags & IEEE80211_CHAN_RADAR)) ? "" :
 596				      ", IBSS",
 597				      channels[i].
 598				      flags & IEEE80211_CHAN_NO_IR ?
 599				      "passive only" : "active/passive");
 600	}
 601	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 602	kfree(buf);
 603	return ret;
 604}
 605
 606static ssize_t
 607il_dbgfs_status_read(struct file *file, char __user *user_buf, size_t count,
 608		     loff_t *ppos)
 609{
 610
 611	struct il_priv *il = file->private_data;
 612	char buf[512];
 613	int pos = 0;
 614	const size_t bufsz = sizeof(buf);
 615
 616	pos +=
 617	    scnprintf(buf + pos, bufsz - pos, "S_HCMD_ACTIVE:\t %d\n",
 618		      test_bit(S_HCMD_ACTIVE, &il->status));
 619	pos +=
 620	    scnprintf(buf + pos, bufsz - pos, "S_INT_ENABLED:\t %d\n",
 621		      test_bit(S_INT_ENABLED, &il->status));
 622	pos +=
 623	    scnprintf(buf + pos, bufsz - pos, "S_RFKILL:\t %d\n",
 624		      test_bit(S_RFKILL, &il->status));
 625	pos +=
 626	    scnprintf(buf + pos, bufsz - pos, "S_CT_KILL:\t\t %d\n",
 627		      test_bit(S_CT_KILL, &il->status));
 628	pos +=
 629	    scnprintf(buf + pos, bufsz - pos, "S_INIT:\t\t %d\n",
 630		      test_bit(S_INIT, &il->status));
 631	pos +=
 632	    scnprintf(buf + pos, bufsz - pos, "S_ALIVE:\t\t %d\n",
 633		      test_bit(S_ALIVE, &il->status));
 634	pos +=
 635	    scnprintf(buf + pos, bufsz - pos, "S_READY:\t\t %d\n",
 636		      test_bit(S_READY, &il->status));
 637	pos +=
 638	    scnprintf(buf + pos, bufsz - pos, "S_TEMPERATURE:\t %d\n",
 639		      test_bit(S_TEMPERATURE, &il->status));
 640	pos +=
 641	    scnprintf(buf + pos, bufsz - pos, "S_GEO_CONFIGURED:\t %d\n",
 642		      test_bit(S_GEO_CONFIGURED, &il->status));
 643	pos +=
 644	    scnprintf(buf + pos, bufsz - pos, "S_EXIT_PENDING:\t %d\n",
 645		      test_bit(S_EXIT_PENDING, &il->status));
 646	pos +=
 647	    scnprintf(buf + pos, bufsz - pos, "S_STATS:\t %d\n",
 648		      test_bit(S_STATS, &il->status));
 649	pos +=
 650	    scnprintf(buf + pos, bufsz - pos, "S_SCANNING:\t %d\n",
 651		      test_bit(S_SCANNING, &il->status));
 652	pos +=
 653	    scnprintf(buf + pos, bufsz - pos, "S_SCAN_ABORTING:\t %d\n",
 654		      test_bit(S_SCAN_ABORTING, &il->status));
 655	pos +=
 656	    scnprintf(buf + pos, bufsz - pos, "S_SCAN_HW:\t\t %d\n",
 657		      test_bit(S_SCAN_HW, &il->status));
 658	pos +=
 659	    scnprintf(buf + pos, bufsz - pos, "S_POWER_PMI:\t %d\n",
 660		      test_bit(S_POWER_PMI, &il->status));
 661	pos +=
 662	    scnprintf(buf + pos, bufsz - pos, "S_FW_ERROR:\t %d\n",
 663		      test_bit(S_FW_ERROR, &il->status));
 664	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 665}
 666
 667static ssize_t
 668il_dbgfs_interrupt_read(struct file *file, char __user *user_buf, size_t count,
 669			loff_t *ppos)
 670{
 671
 672	struct il_priv *il = file->private_data;
 673	int pos = 0;
 674	int cnt = 0;
 675	char *buf;
 676	int bufsz = 24 * 64;	/* 24 items * 64 char per item */
 677	ssize_t ret;
 678
 679	buf = kzalloc(bufsz, GFP_KERNEL);
 680	if (!buf) {
 681		IL_ERR("Can not allocate Buffer\n");
 682		return -ENOMEM;
 683	}
 684
 685	pos +=
 686	    scnprintf(buf + pos, bufsz - pos, "Interrupt Statistics Report:\n");
 687
 688	pos +=
 689	    scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
 690		      il->isr_stats.hw);
 691	pos +=
 692	    scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
 693		      il->isr_stats.sw);
 694	if (il->isr_stats.sw || il->isr_stats.hw) {
 695		pos +=
 696		    scnprintf(buf + pos, bufsz - pos,
 697			      "\tLast Restarting Code:  0x%X\n",
 698			      il->isr_stats.err_code);
 699	}
 700#ifdef CONFIG_IWLEGACY_DEBUG
 701	pos +=
 702	    scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
 703		      il->isr_stats.sch);
 704	pos +=
 705	    scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
 706		      il->isr_stats.alive);
 707#endif
 708	pos +=
 709	    scnprintf(buf + pos, bufsz - pos,
 710		      "HW RF KILL switch toggled:\t %u\n",
 711		      il->isr_stats.rfkill);
 712
 713	pos +=
 714	    scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
 715		      il->isr_stats.ctkill);
 716
 717	pos +=
 718	    scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
 719		      il->isr_stats.wakeup);
 720
 721	pos +=
 722	    scnprintf(buf + pos, bufsz - pos, "Rx command responses:\t\t %u\n",
 723		      il->isr_stats.rx);
 724	for (cnt = 0; cnt < IL_CN_MAX; cnt++) {
 725		if (il->isr_stats.handlers[cnt] > 0)
 726			pos +=
 727			    scnprintf(buf + pos, bufsz - pos,
 728				      "\tRx handler[%36s]:\t\t %u\n",
 729				      il_get_cmd_string(cnt),
 730				      il->isr_stats.handlers[cnt]);
 731	}
 732
 733	pos +=
 734	    scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
 735		      il->isr_stats.tx);
 736
 737	pos +=
 738	    scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
 739		      il->isr_stats.unhandled);
 740
 741	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 742	kfree(buf);
 743	return ret;
 744}
 745
 746static ssize_t
 747il_dbgfs_interrupt_write(struct file *file, const char __user *user_buf,
 748			 size_t count, loff_t *ppos)
 749{
 750	struct il_priv *il = file->private_data;
 751	char buf[8];
 752	int buf_size;
 753	u32 reset_flag;
 754
 755	memset(buf, 0, sizeof(buf));
 756	buf_size = min(count, sizeof(buf) - 1);
 757	if (copy_from_user(buf, user_buf, buf_size))
 758		return -EFAULT;
 759	if (sscanf(buf, "%x", &reset_flag) != 1)
 760		return -EFAULT;
 761	if (reset_flag == 0)
 762		il_clear_isr_stats(il);
 763
 764	return count;
 765}
 766
 767static ssize_t
 768il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count,
 769		  loff_t *ppos)
 770{
 771	struct il_priv *il = file->private_data;
 772	int pos = 0, i;
 773	char buf[256];
 774	const size_t bufsz = sizeof(buf);
 775
 776	for (i = 0; i < AC_NUM; i++) {
 777		pos +=
 778		    scnprintf(buf + pos, bufsz - pos,
 779			      "\tcw_min\tcw_max\taifsn\ttxop\n");
 780		pos +=
 781		    scnprintf(buf + pos, bufsz - pos,
 782			      "AC[%d]\t%u\t%u\t%u\t%u\n", i,
 783			      il->qos_data.def_qos_parm.ac[i].cw_min,
 784			      il->qos_data.def_qos_parm.ac[i].cw_max,
 785			      il->qos_data.def_qos_parm.ac[i].aifsn,
 786			      il->qos_data.def_qos_parm.ac[i].edca_txop);
 787	}
 788
 789	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 790}
 791
 792static ssize_t
 793il_dbgfs_disable_ht40_write(struct file *file, const char __user *user_buf,
 794			    size_t count, loff_t *ppos)
 795{
 796	struct il_priv *il = file->private_data;
 797	char buf[8];
 798	int buf_size;
 799	int ht40;
 800
 801	memset(buf, 0, sizeof(buf));
 802	buf_size = min(count, sizeof(buf) - 1);
 803	if (copy_from_user(buf, user_buf, buf_size))
 804		return -EFAULT;
 805	if (sscanf(buf, "%d", &ht40) != 1)
 806		return -EFAULT;
 807	if (!il_is_any_associated(il))
 808		il->disable_ht40 = ht40 ? true : false;
 809	else {
 810		IL_ERR("Sta associated with AP - "
 811		       "Change to 40MHz channel support is not allowed\n");
 812		return -EINVAL;
 813	}
 814
 815	return count;
 816}
 817
 818static ssize_t
 819il_dbgfs_disable_ht40_read(struct file *file, char __user *user_buf,
 820			   size_t count, loff_t *ppos)
 821{
 822	struct il_priv *il = file->private_data;
 823	char buf[100];
 824	int pos = 0;
 825	const size_t bufsz = sizeof(buf);
 826
 827	pos +=
 828	    scnprintf(buf + pos, bufsz - pos, "11n 40MHz Mode: %s\n",
 829		      il->disable_ht40 ? "Disabled" : "Enabled");
 830	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 831}
 832
 833DEBUGFS_READ_WRITE_FILE_OPS(sram);
 834DEBUGFS_READ_FILE_OPS(nvm);
 835DEBUGFS_READ_FILE_OPS(stations);
 836DEBUGFS_READ_FILE_OPS(channels);
 837DEBUGFS_READ_FILE_OPS(status);
 838DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
 839DEBUGFS_READ_FILE_OPS(qos);
 840DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
 841
 842static ssize_t
 843il_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count,
 844		       loff_t *ppos)
 845{
 846
 847	struct il_priv *il = file->private_data;
 848	struct il_tx_queue *txq;
 849	struct il_queue *q;
 850	char *buf;
 851	int pos = 0;
 852	int cnt;
 853	int ret;
 854	const size_t bufsz =
 855	    sizeof(char) * 64 * il->cfg->num_of_queues;
 856
 857	if (!il->txq) {
 858		IL_ERR("txq not ready\n");
 859		return -EAGAIN;
 860	}
 861	buf = kzalloc(bufsz, GFP_KERNEL);
 862	if (!buf)
 863		return -ENOMEM;
 864
 865	for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
 866		txq = &il->txq[cnt];
 867		q = &txq->q;
 868		pos +=
 869		    scnprintf(buf + pos, bufsz - pos,
 870			      "hwq %.2d: read=%u write=%u stop=%d"
 871			      " swq_id=%#.2x (ac %d/hwq %d)\n", cnt,
 872			      q->read_ptr, q->write_ptr,
 873			      !!test_bit(cnt, il->queue_stopped),
 874			      txq->swq_id, txq->swq_id & 3,
 875			      (txq->swq_id >> 2) & 0x1f);
 876		if (cnt >= 4)
 877			continue;
 878		/* for the ACs, display the stop count too */
 879		pos +=
 880		    scnprintf(buf + pos, bufsz - pos,
 881			      "        stop-count: %d\n",
 882			      atomic_read(&il->queue_stop_count[cnt]));
 883	}
 884	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 885	kfree(buf);
 886	return ret;
 887}
 888
 889static ssize_t
 890il_dbgfs_rx_queue_read(struct file *file, char __user *user_buf, size_t count,
 891		       loff_t *ppos)
 892{
 893
 894	struct il_priv *il = file->private_data;
 895	struct il_rx_queue *rxq = &il->rxq;
 896	char buf[256];
 897	int pos = 0;
 898	const size_t bufsz = sizeof(buf);
 899
 900	pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", rxq->read);
 901	pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", rxq->write);
 902	pos +=
 903	    scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
 904		      rxq->free_count);
 905	if (rxq->rb_stts) {
 906		pos +=
 907		    scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
 908			      le16_to_cpu(rxq->rb_stts->
 909					  closed_rb_num) & 0x0FFF);
 910	} else {
 911		pos +=
 912		    scnprintf(buf + pos, bufsz - pos,
 913			      "closed_rb_num: Not Allocated\n");
 914	}
 915	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 916}
 917
 918static ssize_t
 919il_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf,
 920			     size_t count, loff_t *ppos)
 921{
 922	struct il_priv *il = file->private_data;
 923
 924	return il->debugfs_ops->rx_stats_read(file, user_buf, count, ppos);
 925}
 926
 927static ssize_t
 928il_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf,
 929			     size_t count, loff_t *ppos)
 930{
 931	struct il_priv *il = file->private_data;
 932
 933	return il->debugfs_ops->tx_stats_read(file, user_buf, count, ppos);
 934}
 935
 936static ssize_t
 937il_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf,
 938				  size_t count, loff_t *ppos)
 939{
 940	struct il_priv *il = file->private_data;
 941
 942	return il->debugfs_ops->general_stats_read(file, user_buf, count, ppos);
 943}
 944
 945static ssize_t
 946il_dbgfs_sensitivity_read(struct file *file, char __user *user_buf,
 947			  size_t count, loff_t *ppos)
 948{
 949
 950	struct il_priv *il = file->private_data;
 951	int pos = 0;
 952	int cnt = 0;
 953	char *buf;
 954	int bufsz = sizeof(struct il_sensitivity_data) * 4 + 100;
 955	ssize_t ret;
 956	struct il_sensitivity_data *data;
 957
 958	data = &il->sensitivity_data;
 959	buf = kzalloc(bufsz, GFP_KERNEL);
 960	if (!buf) {
 961		IL_ERR("Can not allocate Buffer\n");
 962		return -ENOMEM;
 963	}
 964
 965	pos +=
 966	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
 967		      data->auto_corr_ofdm);
 968	pos +=
 969	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc:\t\t %u\n",
 970		      data->auto_corr_ofdm_mrc);
 971	pos +=
 972	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
 973		      data->auto_corr_ofdm_x1);
 974	pos +=
 975	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc_x1:\t\t %u\n",
 976		      data->auto_corr_ofdm_mrc_x1);
 977	pos +=
 978	    scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
 979		      data->auto_corr_cck);
 980	pos +=
 981	    scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
 982		      data->auto_corr_cck_mrc);
 983	pos +=
 984	    scnprintf(buf + pos, bufsz - pos,
 985		      "last_bad_plcp_cnt_ofdm:\t\t %u\n",
 986		      data->last_bad_plcp_cnt_ofdm);
 987	pos +=
 988	    scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
 989		      data->last_fa_cnt_ofdm);
 990	pos +=
 991	    scnprintf(buf + pos, bufsz - pos, "last_bad_plcp_cnt_cck:\t\t %u\n",
 992		      data->last_bad_plcp_cnt_cck);
 993	pos +=
 994	    scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
 995		      data->last_fa_cnt_cck);
 996	pos +=
 997	    scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
 998		      data->nrg_curr_state);
 999	pos +=
1000	    scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
1001		      data->nrg_prev_state);
1002	pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
1003	for (cnt = 0; cnt < 10; cnt++) {
1004		pos +=
1005		    scnprintf(buf + pos, bufsz - pos, " %u",
1006			      data->nrg_value[cnt]);
1007	}
1008	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1009	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
1010	for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
1011		pos +=
1012		    scnprintf(buf + pos, bufsz - pos, " %u",
1013			      data->nrg_silence_rssi[cnt]);
1014	}
1015	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1016	pos +=
1017	    scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
1018		      data->nrg_silence_ref);
1019	pos +=
1020	    scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
1021		      data->nrg_energy_idx);
1022	pos +=
1023	    scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
1024		      data->nrg_silence_idx);
1025	pos +=
1026	    scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
1027		      data->nrg_th_cck);
1028	pos +=
1029	    scnprintf(buf + pos, bufsz - pos,
1030		      "nrg_auto_corr_silence_diff:\t %u\n",
1031		      data->nrg_auto_corr_silence_diff);
1032	pos +=
1033	    scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
1034		      data->num_in_cck_no_fa);
1035	pos +=
1036	    scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
1037		      data->nrg_th_ofdm);
1038
1039	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1040	kfree(buf);
1041	return ret;
1042}
1043
1044static ssize_t
1045il_dbgfs_chain_noise_read(struct file *file, char __user *user_buf,
1046			  size_t count, loff_t *ppos)
1047{
1048
1049	struct il_priv *il = file->private_data;
1050	int pos = 0;
1051	int cnt = 0;
1052	char *buf;
1053	int bufsz = sizeof(struct il_chain_noise_data) * 4 + 100;
1054	ssize_t ret;
1055	struct il_chain_noise_data *data;
1056
1057	data = &il->chain_noise_data;
1058	buf = kzalloc(bufsz, GFP_KERNEL);
1059	if (!buf) {
1060		IL_ERR("Can not allocate Buffer\n");
1061		return -ENOMEM;
1062	}
1063
1064	pos +=
1065	    scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
1066		      data->active_chains);
1067	pos +=
1068	    scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
1069		      data->chain_noise_a);
1070	pos +=
1071	    scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
1072		      data->chain_noise_b);
1073	pos +=
1074	    scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
1075		      data->chain_noise_c);
1076	pos +=
1077	    scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
1078		      data->chain_signal_a);
1079	pos +=
1080	    scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
1081		      data->chain_signal_b);
1082	pos +=
1083	    scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
1084		      data->chain_signal_c);
1085	pos +=
1086	    scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
1087		      data->beacon_count);
1088
1089	pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
1090	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1091		pos +=
1092		    scnprintf(buf + pos, bufsz - pos, " %u",
1093			      data->disconn_array[cnt]);
1094	}
1095	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1096	pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
1097	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1098		pos +=
1099		    scnprintf(buf + pos, bufsz - pos, " %u",
1100			      data->delta_gain_code[cnt]);
1101	}
1102	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1103	pos +=
1104	    scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
1105		      data->radio_write);
1106	pos +=
1107	    scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
1108		      data->state);
1109
1110	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1111	kfree(buf);
1112	return ret;
1113}
1114
1115static ssize_t
1116il_dbgfs_power_save_status_read(struct file *file, char __user *user_buf,
1117				size_t count, loff_t *ppos)
1118{
1119	struct il_priv *il = file->private_data;
1120	char buf[60];
1121	int pos = 0;
1122	const size_t bufsz = sizeof(buf);
1123	u32 pwrsave_status;
1124
1125	pwrsave_status =
1126	    _il_rd(il, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK;
1127
1128	pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
1129	pos +=
1130	    scnprintf(buf + pos, bufsz - pos, "%s\n",
1131		      (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
1132		      (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
1133		      (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
1134		      "error");
1135
1136	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1137}
1138
1139static ssize_t
1140il_dbgfs_clear_ucode_stats_write(struct file *file,
1141				 const char __user *user_buf, size_t count,
1142				 loff_t *ppos)
1143{
1144	struct il_priv *il = file->private_data;
1145	char buf[8];
1146	int buf_size;
1147	int clear;
1148
1149	memset(buf, 0, sizeof(buf));
1150	buf_size = min(count, sizeof(buf) - 1);
1151	if (copy_from_user(buf, user_buf, buf_size))
1152		return -EFAULT;
1153	if (sscanf(buf, "%d", &clear) != 1)
1154		return -EFAULT;
1155
1156	/* make request to uCode to retrieve stats information */
1157	mutex_lock(&il->mutex);
1158	il_send_stats_request(il, CMD_SYNC, true);
1159	mutex_unlock(&il->mutex);
1160
1161	return count;
1162}
1163
1164static ssize_t
1165il_dbgfs_rxon_flags_read(struct file *file, char __user *user_buf,
1166			 size_t count, loff_t *ppos)
1167{
1168
1169	struct il_priv *il = file->private_data;
1170	int len = 0;
1171	char buf[20];
1172
1173	len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.flags));
1174	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1175}
1176
1177static ssize_t
1178il_dbgfs_rxon_filter_flags_read(struct file *file, char __user *user_buf,
1179				size_t count, loff_t *ppos)
1180{
1181
1182	struct il_priv *il = file->private_data;
1183	int len = 0;
1184	char buf[20];
1185
1186	len =
1187	    sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags));
1188	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1189}
1190
1191static ssize_t
1192il_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count,
1193		     loff_t *ppos)
1194{
1195	struct il_priv *il = file->private_data;
1196	char *buf;
1197	int pos = 0;
1198	ssize_t ret = -EFAULT;
1199
1200	if (il->ops->dump_fh) {
1201		ret = pos = il->ops->dump_fh(il, &buf, true);
1202		if (buf) {
1203			ret =
1204			    simple_read_from_buffer(user_buf, count, ppos, buf,
1205						    pos);
1206			kfree(buf);
1207		}
1208	}
1209
1210	return ret;
1211}
1212
1213static ssize_t
1214il_dbgfs_missed_beacon_read(struct file *file, char __user *user_buf,
1215			    size_t count, loff_t *ppos)
1216{
1217
1218	struct il_priv *il = file->private_data;
1219	int pos = 0;
1220	char buf[12];
1221	const size_t bufsz = sizeof(buf);
1222
1223	pos +=
1224	    scnprintf(buf + pos, bufsz - pos, "%d\n",
1225		      il->missed_beacon_threshold);
1226
1227	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1228}
1229
1230static ssize_t
1231il_dbgfs_missed_beacon_write(struct file *file, const char __user *user_buf,
1232			     size_t count, loff_t *ppos)
1233{
1234	struct il_priv *il = file->private_data;
1235	char buf[8];
1236	int buf_size;
1237	int missed;
1238
1239	memset(buf, 0, sizeof(buf));
1240	buf_size = min(count, sizeof(buf) - 1);
1241	if (copy_from_user(buf, user_buf, buf_size))
1242		return -EFAULT;
1243	if (sscanf(buf, "%d", &missed) != 1)
1244		return -EINVAL;
1245
1246	if (missed < IL_MISSED_BEACON_THRESHOLD_MIN ||
1247	    missed > IL_MISSED_BEACON_THRESHOLD_MAX)
1248		il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
1249	else
1250		il->missed_beacon_threshold = missed;
1251
1252	return count;
1253}
1254
1255static ssize_t
1256il_dbgfs_force_reset_read(struct file *file, char __user *user_buf,
1257			  size_t count, loff_t *ppos)
1258{
1259
1260	struct il_priv *il = file->private_data;
1261	int pos = 0;
1262	char buf[300];
1263	const size_t bufsz = sizeof(buf);
1264	struct il_force_reset *force_reset;
1265
1266	force_reset = &il->force_reset;
1267
1268	pos +=
1269	    scnprintf(buf + pos, bufsz - pos, "\tnumber of reset request: %d\n",
1270		      force_reset->reset_request_count);
1271	pos +=
1272	    scnprintf(buf + pos, bufsz - pos,
1273		      "\tnumber of reset request success: %d\n",
1274		      force_reset->reset_success_count);
1275	pos +=
1276	    scnprintf(buf + pos, bufsz - pos,
1277		      "\tnumber of reset request reject: %d\n",
1278		      force_reset->reset_reject_count);
1279	pos +=
1280	    scnprintf(buf + pos, bufsz - pos, "\treset duration: %lu\n",
1281		      force_reset->reset_duration);
1282
1283	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1284}
1285
1286static ssize_t
1287il_dbgfs_force_reset_write(struct file *file, const char __user *user_buf,
1288			   size_t count, loff_t *ppos)
1289{
1290
1291	int ret;
1292	struct il_priv *il = file->private_data;
1293
1294	ret = il_force_reset(il, true);
1295
1296	return ret ? ret : count;
1297}
1298
1299static ssize_t
1300il_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf,
1301			  size_t count, loff_t *ppos)
1302{
1303
1304	struct il_priv *il = file->private_data;
1305	char buf[8];
1306	int buf_size;
1307	int timeout;
1308
1309	memset(buf, 0, sizeof(buf));
1310	buf_size = min(count, sizeof(buf) - 1);
1311	if (copy_from_user(buf, user_buf, buf_size))
1312		return -EFAULT;
1313	if (sscanf(buf, "%d", &timeout) != 1)
1314		return -EINVAL;
1315	if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT)
1316		timeout = IL_DEF_WD_TIMEOUT;
1317
1318	il->cfg->wd_timeout = timeout;
1319	il_setup_watchdog(il);
1320	return count;
1321}
1322
1323DEBUGFS_READ_FILE_OPS(rx_stats);
1324DEBUGFS_READ_FILE_OPS(tx_stats);
1325DEBUGFS_READ_FILE_OPS(rx_queue);
1326DEBUGFS_READ_FILE_OPS(tx_queue);
1327DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
1328DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
1329DEBUGFS_READ_FILE_OPS(ucode_general_stats);
1330DEBUGFS_READ_FILE_OPS(sensitivity);
1331DEBUGFS_READ_FILE_OPS(chain_noise);
1332DEBUGFS_READ_FILE_OPS(power_save_status);
1333DEBUGFS_WRITE_FILE_OPS(clear_ucode_stats);
1334DEBUGFS_WRITE_FILE_OPS(clear_traffic_stats);
1335DEBUGFS_READ_FILE_OPS(fh_reg);
1336DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
1337DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
1338DEBUGFS_READ_FILE_OPS(rxon_flags);
1339DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
1340DEBUGFS_WRITE_FILE_OPS(wd_timeout);
1341
1342/*
1343 * Create the debugfs files and directories
1344 *
1345 */
1346int
1347il_dbgfs_register(struct il_priv *il, const char *name)
1348{
1349	struct dentry *phyd = il->hw->wiphy->debugfsdir;
1350	struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
1351
1352	dir_drv = debugfs_create_dir(name, phyd);
1353	if (!dir_drv)
1354		return -ENOMEM;
1355
1356	il->debugfs_dir = dir_drv;
1357
1358	dir_data = debugfs_create_dir("data", dir_drv);
1359	if (!dir_data)
1360		goto err;
1361	dir_rf = debugfs_create_dir("rf", dir_drv);
1362	if (!dir_rf)
1363		goto err;
1364	dir_debug = debugfs_create_dir("debug", dir_drv);
1365	if (!dir_debug)
1366		goto err;
1367
1368	DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
1369	DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
1370	DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
1371	DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
1372	DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
1373	DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
1374	DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
1375	DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
1376	DEBUGFS_ADD_FILE(rx_stats, dir_debug, S_IRUSR);
1377	DEBUGFS_ADD_FILE(tx_stats, dir_debug, S_IRUSR);
1378	DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
1379	DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
1380	DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
1381	DEBUGFS_ADD_FILE(clear_ucode_stats, dir_debug, S_IWUSR);
1382	DEBUGFS_ADD_FILE(clear_traffic_stats, dir_debug, S_IWUSR);
1383	DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
1384	DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
1385	DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
1386	DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
1387	DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
1388	DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
1389
1390	if (il->cfg->sensitivity_calib_by_driver)
1391		DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
1392	if (il->cfg->chain_noise_calib_by_driver)
1393		DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
1394	DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
1395	DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
1396	DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
1397	if (il->cfg->sensitivity_calib_by_driver)
1398		DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
1399				 &il->disable_sens_cal);
1400	if (il->cfg->chain_noise_calib_by_driver)
1401		DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
1402				 &il->disable_chain_noise_cal);
1403	DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal);
1404	return 0;
1405
1406err:
1407	IL_ERR("Can't create the debugfs directory\n");
1408	il_dbgfs_unregister(il);
1409	return -ENOMEM;
1410}
1411EXPORT_SYMBOL(il_dbgfs_register);
1412
1413/**
1414 * Remove the debugfs files and directories
1415 *
1416 */
1417void
1418il_dbgfs_unregister(struct il_priv *il)
1419{
1420	if (!il->debugfs_dir)
1421		return;
1422
1423	debugfs_remove_recursive(il->debugfs_dir);
1424	il->debugfs_dir = NULL;
1425}
1426EXPORT_SYMBOL(il_dbgfs_unregister);