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