1379 lines · 37.4 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/****************************************************************************** * * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * Contact Information: *  Intel Linux Wireless <ilw@linux.intel.com> * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *****************************************************************************/#include <linux/ieee80211.h>#include <linux/export.h>#include <net/mac80211.h> #include "common.h" static voidil_clear_traffic_stats(struct il_priv *il){	memset(&il->tx_stats, 0, sizeof(struct traffic_stats));	memset(&il->rx_stats, 0, sizeof(struct traffic_stats));} /* * il_update_stats function record all the MGMT, CTRL and DATA pkt for * both TX and Rx . Use debugfs to display the rx/rx_stats */voidil_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len){	struct traffic_stats *stats; 	if (is_tx)		stats = &il->tx_stats;	else		stats = &il->rx_stats; 	if (ieee80211_is_mgmt(fc)) {		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):			stats->mgmt[MANAGEMENT_ASSOC_REQ]++;			break;		case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):			stats->mgmt[MANAGEMENT_ASSOC_RESP]++;			break;		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):			stats->mgmt[MANAGEMENT_REASSOC_REQ]++;			break;		case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):			stats->mgmt[MANAGEMENT_REASSOC_RESP]++;			break;		case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):			stats->mgmt[MANAGEMENT_PROBE_REQ]++;			break;		case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):			stats->mgmt[MANAGEMENT_PROBE_RESP]++;			break;		case cpu_to_le16(IEEE80211_STYPE_BEACON):			stats->mgmt[MANAGEMENT_BEACON]++;			break;		case cpu_to_le16(IEEE80211_STYPE_ATIM):			stats->mgmt[MANAGEMENT_ATIM]++;			break;		case cpu_to_le16(IEEE80211_STYPE_DISASSOC):			stats->mgmt[MANAGEMENT_DISASSOC]++;			break;		case cpu_to_le16(IEEE80211_STYPE_AUTH):			stats->mgmt[MANAGEMENT_AUTH]++;			break;		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):			stats->mgmt[MANAGEMENT_DEAUTH]++;			break;		case cpu_to_le16(IEEE80211_STYPE_ACTION):			stats->mgmt[MANAGEMENT_ACTION]++;			break;		}	} else if (ieee80211_is_ctl(fc)) {		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {		case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):			stats->ctrl[CONTROL_BACK_REQ]++;			break;		case cpu_to_le16(IEEE80211_STYPE_BACK):			stats->ctrl[CONTROL_BACK]++;			break;		case cpu_to_le16(IEEE80211_STYPE_PSPOLL):			stats->ctrl[CONTROL_PSPOLL]++;			break;		case cpu_to_le16(IEEE80211_STYPE_RTS):			stats->ctrl[CONTROL_RTS]++;			break;		case cpu_to_le16(IEEE80211_STYPE_CTS):			stats->ctrl[CONTROL_CTS]++;			break;		case cpu_to_le16(IEEE80211_STYPE_ACK):			stats->ctrl[CONTROL_ACK]++;			break;		case cpu_to_le16(IEEE80211_STYPE_CFEND):			stats->ctrl[CONTROL_CFEND]++;			break;		case cpu_to_le16(IEEE80211_STYPE_CFENDACK):			stats->ctrl[CONTROL_CFENDACK]++;			break;		}	} else {		/* data */		stats->data_cnt++;		stats->data_bytes += len;	}}EXPORT_SYMBOL(il_update_stats); /* create and remove of files */#define DEBUGFS_ADD_FILE(name, parent, mode) do {			\	debugfs_create_file(#name, mode, parent, il,			\			    &il_dbgfs_##name##_ops);			\} while (0) #define DEBUGFS_ADD_BOOL(name, parent, ptr) do {			\	debugfs_create_bool(#name, 0600, parent, ptr);			\} while (0) /* file operation */#define DEBUGFS_READ_FUNC(name)                                         \static ssize_t il_dbgfs_##name##_read(struct file *file,               \					char __user *user_buf,          \					size_t count, loff_t *ppos); #define DEBUGFS_WRITE_FUNC(name)                                        \static ssize_t il_dbgfs_##name##_write(struct file *file,              \					const char __user *user_buf,    \					size_t count, loff_t *ppos);  #define DEBUGFS_READ_FILE_OPS(name)				\	DEBUGFS_READ_FUNC(name);				\static const struct file_operations il_dbgfs_##name##_ops = {	\	.read = il_dbgfs_##name##_read,				\	.open = simple_open,					\	.llseek = generic_file_llseek,				\}; #define DEBUGFS_WRITE_FILE_OPS(name)				\	DEBUGFS_WRITE_FUNC(name);				\static const struct file_operations il_dbgfs_##name##_ops = {	\	.write = il_dbgfs_##name##_write,			\	.open = simple_open,					\	.llseek = generic_file_llseek,				\}; #define DEBUGFS_READ_WRITE_FILE_OPS(name)			\	DEBUGFS_READ_FUNC(name);				\	DEBUGFS_WRITE_FUNC(name);				\static const struct file_operations il_dbgfs_##name##_ops = {	\	.write = il_dbgfs_##name##_write,			\	.read = il_dbgfs_##name##_read,				\	.open = simple_open,					\	.llseek = generic_file_llseek,				\}; static const char *il_get_mgmt_string(int cmd){	switch (cmd) {	IL_CMD(MANAGEMENT_ASSOC_REQ);	IL_CMD(MANAGEMENT_ASSOC_RESP);	IL_CMD(MANAGEMENT_REASSOC_REQ);	IL_CMD(MANAGEMENT_REASSOC_RESP);	IL_CMD(MANAGEMENT_PROBE_REQ);	IL_CMD(MANAGEMENT_PROBE_RESP);	IL_CMD(MANAGEMENT_BEACON);	IL_CMD(MANAGEMENT_ATIM);	IL_CMD(MANAGEMENT_DISASSOC);	IL_CMD(MANAGEMENT_AUTH);	IL_CMD(MANAGEMENT_DEAUTH);	IL_CMD(MANAGEMENT_ACTION);	default:		return "UNKNOWN"; 	}} static const char *il_get_ctrl_string(int cmd){	switch (cmd) {	IL_CMD(CONTROL_BACK_REQ);	IL_CMD(CONTROL_BACK);	IL_CMD(CONTROL_PSPOLL);	IL_CMD(CONTROL_RTS);	IL_CMD(CONTROL_CTS);	IL_CMD(CONTROL_ACK);	IL_CMD(CONTROL_CFEND);	IL_CMD(CONTROL_CFENDACK);	default:		return "UNKNOWN"; 	}} static ssize_til_dbgfs_tx_stats_read(struct file *file, char __user *user_buf, size_t count,		       loff_t *ppos){ 	struct il_priv *il = file->private_data;	char *buf;	int pos = 0; 	int cnt;	ssize_t ret;	const size_t bufsz =	    100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);	buf = kzalloc(bufsz, GFP_KERNEL);	if (!buf)		return -ENOMEM;	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {		pos +=		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",			      il_get_mgmt_string(cnt), il->tx_stats.mgmt[cnt]);	}	pos += scnprintf(buf + pos, bufsz - pos, "Control\n");	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {		pos +=		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",			      il_get_ctrl_string(cnt), il->tx_stats.ctrl[cnt]);	}	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");	pos +=	    scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",		      il->tx_stats.data_cnt);	pos +=	    scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",		      il->tx_stats.data_bytes);	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);	kfree(buf);	return ret;} static ssize_til_dbgfs_clear_traffic_stats_write(struct file *file,				   const char __user *user_buf, size_t count,				   loff_t *ppos){	struct il_priv *il = file->private_data;	u32 clear_flag;	char buf[8];	int buf_size; 	memset(buf, 0, sizeof(buf));	buf_size = min(count, sizeof(buf) - 1);	if (copy_from_user(buf, user_buf, buf_size))		return -EFAULT;	if (sscanf(buf, "%x", &clear_flag) != 1)		return -EFAULT;	il_clear_traffic_stats(il); 	return count;} static ssize_til_dbgfs_rx_stats_read(struct file *file, char __user *user_buf, size_t count,		       loff_t *ppos){ 	struct il_priv *il = file->private_data;	char *buf;	int pos = 0;	int cnt;	ssize_t ret;	const size_t bufsz =	    100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);	buf = kzalloc(bufsz, GFP_KERNEL);	if (!buf)		return -ENOMEM; 	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {		pos +=		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",			      il_get_mgmt_string(cnt), il->rx_stats.mgmt[cnt]);	}	pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {		pos +=		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",			      il_get_ctrl_string(cnt), il->rx_stats.ctrl[cnt]);	}	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");	pos +=	    scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",		      il->rx_stats.data_cnt);	pos +=	    scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",		      il->rx_stats.data_bytes); 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);	kfree(buf);	return ret;} #define BYTE1_MASK 0x000000ff;#define BYTE2_MASK 0x0000ffff;#define BYTE3_MASK 0x00ffffff;static ssize_til_dbgfs_sram_read(struct file *file, char __user *user_buf, size_t count,		   loff_t *ppos){	u32 val;	char *buf;	ssize_t ret;	int i;	int pos = 0;	struct il_priv *il = file->private_data;	size_t bufsz; 	/* default is to dump the entire data segment */	if (!il->dbgfs_sram_offset && !il->dbgfs_sram_len) {		il->dbgfs_sram_offset = 0x800000;		if (il->ucode_type == UCODE_INIT)			il->dbgfs_sram_len = il->ucode_init_data.len;		else			il->dbgfs_sram_len = il->ucode_data.len;	}	bufsz = 30 + il->dbgfs_sram_len * sizeof(char) * 10;	buf = kmalloc(bufsz, GFP_KERNEL);	if (!buf)		return -ENOMEM;	pos +=	    scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",		      il->dbgfs_sram_len);	pos +=	    scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",		      il->dbgfs_sram_offset);	for (i = il->dbgfs_sram_len; i > 0; i -= 4) {		val =		    il_read_targ_mem(il,				     il->dbgfs_sram_offset +				     il->dbgfs_sram_len - i);		if (i < 4) {			switch (i) {			case 1:				val &= BYTE1_MASK;				break;			case 2:				val &= BYTE2_MASK;				break;			case 3:				val &= BYTE3_MASK;				break;			}		}		if (!(i % 16))			pos += scnprintf(buf + pos, bufsz - pos, "\n");		pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);	}	pos += scnprintf(buf + pos, bufsz - pos, "\n"); 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);	kfree(buf);	return ret;} static ssize_til_dbgfs_sram_write(struct file *file, const char __user *user_buf,		    size_t count, loff_t *ppos){	struct il_priv *il = file->private_data;	char buf[64];	int buf_size;	u32 offset, len; 	memset(buf, 0, sizeof(buf));	buf_size = min(count, sizeof(buf) - 1);	if (copy_from_user(buf, user_buf, buf_size))		return -EFAULT; 	if (sscanf(buf, "%x,%x", &offset, &len) == 2) {		il->dbgfs_sram_offset = offset;		il->dbgfs_sram_len = len;	} else {		il->dbgfs_sram_offset = 0;		il->dbgfs_sram_len = 0;	} 	return count;} static ssize_til_dbgfs_stations_read(struct file *file, char __user *user_buf, size_t count,		       loff_t *ppos){	struct il_priv *il = file->private_data;	struct il_station_entry *station;	int max_sta = il->hw_params.max_stations;	char *buf;	int i, j, pos = 0;	ssize_t ret;	/* Add 30 for initial string */	const size_t bufsz = 30 + sizeof(char) * 500 * max_sta; 	buf = kmalloc(bufsz, GFP_KERNEL);	if (!buf)		return -ENOMEM; 	pos +=	    scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",		      il->num_stations); 	for (i = 0; i < max_sta; i++) {		station = &il->stations[i];		if (!station->used)			continue;		pos +=		    scnprintf(buf + pos, bufsz - pos,			      "station %d - addr: %pM, flags: %#x\n", i,			      station->sta.sta.addr,			      station->sta.station_flags_msk);		pos +=		    scnprintf(buf + pos, bufsz - pos,			      "TID\tseq_num\ttxq_id\tframes\ttfds\t");		pos +=		    scnprintf(buf + pos, bufsz - pos,			      "start_idx\tbitmap\t\t\trate_n_flags\n"); 		for (j = 0; j < MAX_TID_COUNT; j++) {			pos +=			    scnprintf(buf + pos, bufsz - pos,				      "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x",				      j, station->tid[j].seq_number,				      station->tid[j].agg.txq_id,				      station->tid[j].agg.frame_count,				      station->tid[j].tfds_in_queue,				      station->tid[j].agg.start_idx,				      station->tid[j].agg.bitmap,				      station->tid[j].agg.rate_n_flags); 			if (station->tid[j].agg.wait_for_ba)				pos +=				    scnprintf(buf + pos, bufsz - pos,					      " - waitforba");			pos += scnprintf(buf + pos, bufsz - pos, "\n");		} 		pos += scnprintf(buf + pos, bufsz - pos, "\n");	} 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);	kfree(buf);	return ret;} static ssize_til_dbgfs_nvm_read(struct file *file, char __user *user_buf, size_t count,		  loff_t *ppos){	ssize_t ret;	struct il_priv *il = file->private_data;	int pos = 0, ofs = 0, buf_size = 0;	const u8 *ptr;	char *buf;	u16 eeprom_ver;	size_t eeprom_len = il->cfg->eeprom_size;	buf_size = 4 * eeprom_len + 256; 	if (eeprom_len % 16) {		IL_ERR("NVM size is not multiple of 16.\n");		return -ENODATA;	} 	ptr = il->eeprom;	if (!ptr) {		IL_ERR("Invalid EEPROM memory\n");		return -ENOMEM;	} 	/* 4 characters for byte 0xYY */	buf = kzalloc(buf_size, GFP_KERNEL);	if (!buf) {		IL_ERR("Can not allocate Buffer\n");		return -ENOMEM;	}	eeprom_ver = il_eeprom_query16(il, EEPROM_VERSION);	pos +=	    scnprintf(buf + pos, buf_size - pos, "EEPROM " "version: 0x%x\n",		      eeprom_ver);	for (ofs = 0; ofs < eeprom_len; ofs += 16) {		pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x %16ph\n",				 ofs, ptr + ofs);	} 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);	kfree(buf);	return ret;} static ssize_til_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count,		       loff_t *ppos){	struct il_priv *il = file->private_data;

Lines 1–500 of 1379.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t