| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1 | /****************************************************************************** | 
 | 2 |  * | 
 | 3 |  * GPL LICENSE SUMMARY | 
 | 4 |  * | 
| Reinette Chatre | 1f44780 | 2010-01-15 13:43:41 -0800 | [diff] [blame] | 5 |  * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 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: | 
| Winkler, Tomas | 759ef89 | 2008-12-09 11:28:58 -0800 | [diff] [blame] | 25 |  *  Intel Linux Wireless <ilw@linux.intel.com> | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 26 |  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | 
 | 27 |  *****************************************************************************/ | 
 | 28 |  | 
| Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 29 | #include <linux/slab.h> | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 30 | #include <linux/kernel.h> | 
 | 31 | #include <linux/module.h> | 
 | 32 | #include <linux/debugfs.h> | 
 | 33 |  | 
 | 34 | #include <linux/ieee80211.h> | 
 | 35 | #include <net/mac80211.h> | 
 | 36 |  | 
 | 37 |  | 
| Tomas Winkler | 3e0d4cb | 2008-04-24 11:55:38 -0700 | [diff] [blame] | 38 | #include "iwl-dev.h" | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 39 | #include "iwl-debug.h" | 
| Tomas Winkler | fee1247 | 2008-04-03 16:05:21 -0700 | [diff] [blame] | 40 | #include "iwl-core.h" | 
| Tomas Winkler | 3395f6e | 2008-03-25 16:33:37 -0700 | [diff] [blame] | 41 | #include "iwl-io.h" | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 42 |  | 
 | 43 | /* create and remove of files */ | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 44 | #define DEBUGFS_ADD_FILE(name, parent, mode) do {			\ | 
 | 45 | 	if (!debugfs_create_file(#name, mode, parent, priv,		\ | 
 | 46 | 				 &iwl_dbgfs_##name##_ops))		\ | 
 | 47 | 		goto err;						\ | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 48 | } while (0) | 
 | 49 |  | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 50 | #define DEBUGFS_ADD_BOOL(name, parent, ptr) do {			\ | 
 | 51 | 	struct dentry *__tmp;						\ | 
 | 52 | 	__tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR,		\ | 
 | 53 | 				    parent, ptr);			\ | 
 | 54 | 	if (IS_ERR(__tmp) || !__tmp)					\ | 
 | 55 | 		goto err;						\ | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 56 | } while (0) | 
 | 57 |  | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 58 | #define DEBUGFS_ADD_X32(name, parent, ptr) do {				\ | 
 | 59 | 	struct dentry *__tmp;						\ | 
 | 60 | 	__tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR,		\ | 
 | 61 | 				   parent, ptr);			\ | 
 | 62 | 	if (IS_ERR(__tmp) || !__tmp)					\ | 
 | 63 | 		goto err;						\ | 
| Tomas Winkler | 445c2df | 2008-05-15 13:54:16 +0800 | [diff] [blame] | 64 | } while (0) | 
 | 65 |  | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 66 | /* file operation */ | 
 | 67 | #define DEBUGFS_READ_FUNC(name)                                         \ | 
 | 68 | static ssize_t iwl_dbgfs_##name##_read(struct file *file,               \ | 
 | 69 | 					char __user *user_buf,          \ | 
 | 70 | 					size_t count, loff_t *ppos); | 
 | 71 |  | 
 | 72 | #define DEBUGFS_WRITE_FUNC(name)                                        \ | 
 | 73 | static ssize_t iwl_dbgfs_##name##_write(struct file *file,              \ | 
 | 74 | 					const char __user *user_buf,    \ | 
 | 75 | 					size_t count, loff_t *ppos); | 
 | 76 |  | 
 | 77 |  | 
 | 78 | static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) | 
 | 79 | { | 
 | 80 | 	file->private_data = inode->i_private; | 
 | 81 | 	return 0; | 
 | 82 | } | 
 | 83 |  | 
 | 84 | #define DEBUGFS_READ_FILE_OPS(name)                                     \ | 
 | 85 | 	DEBUGFS_READ_FUNC(name);                                        \ | 
 | 86 | static const struct file_operations iwl_dbgfs_##name##_ops = {          \ | 
 | 87 | 	.read = iwl_dbgfs_##name##_read,                       		\ | 
 | 88 | 	.open = iwl_dbgfs_open_file_generic,                    	\ | 
| Arnd Bergmann | 2b18ab36 | 2010-07-06 19:05:31 +0200 | [diff] [blame] | 89 | 	.llseek = generic_file_llseek,					\ | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 90 | }; | 
 | 91 |  | 
| Ester Kummer | 189a2b5 | 2008-05-15 13:54:18 +0800 | [diff] [blame] | 92 | #define DEBUGFS_WRITE_FILE_OPS(name)                                    \ | 
 | 93 | 	DEBUGFS_WRITE_FUNC(name);                                       \ | 
 | 94 | static const struct file_operations iwl_dbgfs_##name##_ops = {          \ | 
 | 95 | 	.write = iwl_dbgfs_##name##_write,                              \ | 
 | 96 | 	.open = iwl_dbgfs_open_file_generic,                    	\ | 
| Arnd Bergmann | 2b18ab36 | 2010-07-06 19:05:31 +0200 | [diff] [blame] | 97 | 	.llseek = generic_file_llseek,					\ | 
| Ester Kummer | 189a2b5 | 2008-05-15 13:54:18 +0800 | [diff] [blame] | 98 | }; | 
 | 99 |  | 
 | 100 |  | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 101 | #define DEBUGFS_READ_WRITE_FILE_OPS(name)                               \ | 
 | 102 | 	DEBUGFS_READ_FUNC(name);                                        \ | 
 | 103 | 	DEBUGFS_WRITE_FUNC(name);                                       \ | 
 | 104 | static const struct file_operations iwl_dbgfs_##name##_ops = {          \ | 
 | 105 | 	.write = iwl_dbgfs_##name##_write,                              \ | 
 | 106 | 	.read = iwl_dbgfs_##name##_read,                                \ | 
 | 107 | 	.open = iwl_dbgfs_open_file_generic,                            \ | 
| Arnd Bergmann | 2b18ab36 | 2010-07-06 19:05:31 +0200 | [diff] [blame] | 108 | 	.llseek = generic_file_llseek,					\ | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 109 | }; | 
 | 110 |  | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 111 | static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, | 
 | 112 | 						char __user *user_buf, | 
 | 113 | 						size_t count, loff_t *ppos) { | 
 | 114 |  | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 115 | 	struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 116 | 	char *buf; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 117 | 	int pos = 0; | 
 | 118 |  | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 119 | 	int cnt; | 
 | 120 | 	ssize_t ret; | 
| Wey-Yi Guy | 98a7b43 | 2009-11-13 11:56:31 -0800 | [diff] [blame] | 121 | 	const size_t bufsz = 100 + | 
 | 122 | 		sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 123 | 	buf = kzalloc(bufsz, GFP_KERNEL); | 
 | 124 | 	if (!buf) | 
 | 125 | 		return -ENOMEM; | 
 | 126 | 	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); | 
 | 127 | 	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { | 
 | 128 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
| Wey-Yi Guy | 98a7b43 | 2009-11-13 11:56:31 -0800 | [diff] [blame] | 129 | 				 "\t%25s\t\t: %u\n", | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 130 | 				 get_mgmt_string(cnt), | 
 | 131 | 				 priv->tx_stats.mgmt[cnt]); | 
 | 132 | 	} | 
 | 133 | 	pos += scnprintf(buf + pos, bufsz - pos, "Control\n"); | 
 | 134 | 	for (cnt = 0; cnt < CONTROL_MAX; cnt++) { | 
 | 135 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
| Wey-Yi Guy | 98a7b43 | 2009-11-13 11:56:31 -0800 | [diff] [blame] | 136 | 				 "\t%25s\t\t: %u\n", | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 137 | 				 get_ctrl_string(cnt), | 
 | 138 | 				 priv->tx_stats.ctrl[cnt]); | 
 | 139 | 	} | 
 | 140 | 	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); | 
 | 141 | 	pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", | 
 | 142 | 			 priv->tx_stats.data_cnt); | 
 | 143 | 	pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", | 
 | 144 | 			 priv->tx_stats.data_bytes); | 
 | 145 | 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 146 | 	kfree(buf); | 
 | 147 | 	return ret; | 
 | 148 | } | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 149 |  | 
| Wey-Yi Guy | 7163b8a | 2009-11-20 12:04:56 -0800 | [diff] [blame] | 150 | static ssize_t iwl_dbgfs_clear_traffic_statistics_write(struct file *file, | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 151 | 					const char __user *user_buf, | 
 | 152 | 					size_t count, loff_t *ppos) | 
 | 153 | { | 
 | 154 | 	struct iwl_priv *priv = file->private_data; | 
 | 155 | 	u32 clear_flag; | 
 | 156 | 	char buf[8]; | 
 | 157 | 	int buf_size; | 
 | 158 |  | 
 | 159 | 	memset(buf, 0, sizeof(buf)); | 
 | 160 | 	buf_size = min(count, sizeof(buf) -  1); | 
 | 161 | 	if (copy_from_user(buf, user_buf, buf_size)) | 
 | 162 | 		return -EFAULT; | 
 | 163 | 	if (sscanf(buf, "%x", &clear_flag) != 1) | 
 | 164 | 		return -EFAULT; | 
| Wey-Yi Guy | 7163b8a | 2009-11-20 12:04:56 -0800 | [diff] [blame] | 165 | 	iwl_clear_traffic_stats(priv); | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 166 |  | 
 | 167 | 	return count; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 168 | } | 
 | 169 |  | 
 | 170 | static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, | 
 | 171 | 						char __user *user_buf, | 
 | 172 | 						size_t count, loff_t *ppos) { | 
 | 173 |  | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 174 | 	struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 175 | 	char *buf; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 176 | 	int pos = 0; | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 177 | 	int cnt; | 
 | 178 | 	ssize_t ret; | 
 | 179 | 	const size_t bufsz = 100 + | 
| Wey-Yi Guy | 98a7b43 | 2009-11-13 11:56:31 -0800 | [diff] [blame] | 180 | 		sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 181 | 	buf = kzalloc(bufsz, GFP_KERNEL); | 
 | 182 | 	if (!buf) | 
 | 183 | 		return -ENOMEM; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 184 |  | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 185 | 	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); | 
 | 186 | 	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { | 
 | 187 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
| Wey-Yi Guy | 98a7b43 | 2009-11-13 11:56:31 -0800 | [diff] [blame] | 188 | 				 "\t%25s\t\t: %u\n", | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 189 | 				 get_mgmt_string(cnt), | 
 | 190 | 				 priv->rx_stats.mgmt[cnt]); | 
 | 191 | 	} | 
 | 192 | 	pos += scnprintf(buf + pos, bufsz - pos, "Control:\n"); | 
 | 193 | 	for (cnt = 0; cnt < CONTROL_MAX; cnt++) { | 
 | 194 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
| Wey-Yi Guy | 98a7b43 | 2009-11-13 11:56:31 -0800 | [diff] [blame] | 195 | 				 "\t%25s\t\t: %u\n", | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 196 | 				 get_ctrl_string(cnt), | 
 | 197 | 				 priv->rx_stats.ctrl[cnt]); | 
 | 198 | 	} | 
 | 199 | 	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); | 
 | 200 | 	pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", | 
 | 201 | 			 priv->rx_stats.data_cnt); | 
 | 202 | 	pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", | 
 | 203 | 			 priv->rx_stats.data_bytes); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 204 |  | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 205 | 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 206 | 	kfree(buf); | 
 | 207 | 	return ret; | 
 | 208 | } | 
 | 209 |  | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 210 | static ssize_t iwl_dbgfs_sram_read(struct file *file, | 
 | 211 | 					char __user *user_buf, | 
 | 212 | 					size_t count, loff_t *ppos) | 
 | 213 | { | 
| Jay Sternberg | 24834d2 | 2011-01-11 15:41:00 -0800 | [diff] [blame] | 214 | 	u32 val = 0; | 
| Wey-Yi Guy | 2943f13 | 2009-11-20 12:05:00 -0800 | [diff] [blame] | 215 | 	char *buf; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 216 | 	ssize_t ret; | 
| Jay Sternberg | 24834d2 | 2011-01-11 15:41:00 -0800 | [diff] [blame] | 217 | 	int i = 0; | 
 | 218 | 	bool device_format = false; | 
 | 219 | 	int offset = 0; | 
 | 220 | 	int len = 0; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 221 | 	int pos = 0; | 
| Jay Sternberg | 24834d2 | 2011-01-11 15:41:00 -0800 | [diff] [blame] | 222 | 	int sram; | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 223 | 	struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 2943f13 | 2009-11-20 12:05:00 -0800 | [diff] [blame] | 224 | 	size_t bufsz; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 225 |  | 
| Wey-Yi Guy | 5ade1e4 | 2009-11-20 12:05:04 -0800 | [diff] [blame] | 226 | 	/* default is to dump the entire data segment */ | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 227 | 	if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { | 
 | 228 | 		priv->dbgfs_sram_offset = 0x800000; | 
| Wey-Yi Guy | 5ade1e4 | 2009-11-20 12:05:04 -0800 | [diff] [blame] | 229 | 		if (priv->ucode_type == UCODE_INIT) | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 230 | 			priv->dbgfs_sram_len = priv->ucode_init_data.len; | 
| Wey-Yi Guy | 5ade1e4 | 2009-11-20 12:05:04 -0800 | [diff] [blame] | 231 | 		else | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 232 | 			priv->dbgfs_sram_len = priv->ucode_data.len; | 
| Wey-Yi Guy | 5ade1e4 | 2009-11-20 12:05:04 -0800 | [diff] [blame] | 233 | 	} | 
| Jay Sternberg | 24834d2 | 2011-01-11 15:41:00 -0800 | [diff] [blame] | 234 | 	len = priv->dbgfs_sram_len; | 
 | 235 |  | 
 | 236 | 	if (len == -4) { | 
 | 237 | 		device_format = true; | 
 | 238 | 		len = 4; | 
 | 239 | 	} | 
 | 240 |  | 
 | 241 | 	bufsz =  50 + len * 4; | 
| Wey-Yi Guy | 2943f13 | 2009-11-20 12:05:00 -0800 | [diff] [blame] | 242 | 	buf = kmalloc(bufsz, GFP_KERNEL); | 
 | 243 | 	if (!buf) | 
 | 244 | 		return -ENOMEM; | 
| Jay Sternberg | 24834d2 | 2011-01-11 15:41:00 -0800 | [diff] [blame] | 245 |  | 
| Wey-Yi Guy | 5ade1e4 | 2009-11-20 12:05:04 -0800 | [diff] [blame] | 246 | 	pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", | 
| Jay Sternberg | 24834d2 | 2011-01-11 15:41:00 -0800 | [diff] [blame] | 247 | 			 len); | 
| Wey-Yi Guy | 5ade1e4 | 2009-11-20 12:05:04 -0800 | [diff] [blame] | 248 | 	pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 249 | 			priv->dbgfs_sram_offset); | 
| Jay Sternberg | 24834d2 | 2011-01-11 15:41:00 -0800 | [diff] [blame] | 250 |  | 
 | 251 | 	/* adjust sram address since reads are only on even u32 boundaries */ | 
 | 252 | 	offset = priv->dbgfs_sram_offset & 0x3; | 
 | 253 | 	sram = priv->dbgfs_sram_offset & ~0x3; | 
 | 254 |  | 
 | 255 | 	/* read the first u32 from sram */ | 
 | 256 | 	val = iwl_read_targ_mem(priv, sram); | 
 | 257 |  | 
 | 258 | 	for (; len; len--) { | 
 | 259 | 		/* put the address at the start of every line */ | 
 | 260 | 		if (i == 0) | 
 | 261 | 			pos += scnprintf(buf + pos, bufsz - pos, | 
 | 262 | 				"%08X: ", sram + offset); | 
 | 263 |  | 
 | 264 | 		if (device_format) | 
 | 265 | 			pos += scnprintf(buf + pos, bufsz - pos, | 
 | 266 | 				"%02x", (val >> (8 * (3 - offset))) & 0xff); | 
 | 267 | 		else | 
 | 268 | 			pos += scnprintf(buf + pos, bufsz - pos, | 
 | 269 | 				"%02x ", (val >> (8 * offset)) & 0xff); | 
 | 270 |  | 
 | 271 | 		/* if all bytes processed, read the next u32 from sram */ | 
 | 272 | 		if (++offset == 4) { | 
 | 273 | 			sram += 4; | 
 | 274 | 			offset = 0; | 
 | 275 | 			val = iwl_read_targ_mem(priv, sram); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 276 | 		} | 
| Jay Sternberg | 24834d2 | 2011-01-11 15:41:00 -0800 | [diff] [blame] | 277 |  | 
 | 278 | 		/* put in extra spaces and split lines for human readability */ | 
 | 279 | 		if (++i == 16) { | 
 | 280 | 			i = 0; | 
| Wey-Yi Guy | 2943f13 | 2009-11-20 12:05:00 -0800 | [diff] [blame] | 281 | 			pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
| Jay Sternberg | 24834d2 | 2011-01-11 15:41:00 -0800 | [diff] [blame] | 282 | 		} else if (!(i & 7)) { | 
 | 283 | 			pos += scnprintf(buf + pos, bufsz - pos, "   "); | 
 | 284 | 		} else if (!(i & 3)) { | 
 | 285 | 			pos += scnprintf(buf + pos, bufsz - pos, " "); | 
 | 286 | 		} | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 287 | 	} | 
| Jay Sternberg | 24834d2 | 2011-01-11 15:41:00 -0800 | [diff] [blame] | 288 | 	if (i) | 
 | 289 | 		pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 290 |  | 
 | 291 | 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
| Wey-Yi Guy | 2943f13 | 2009-11-20 12:05:00 -0800 | [diff] [blame] | 292 | 	kfree(buf); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 293 | 	return ret; | 
 | 294 | } | 
 | 295 |  | 
 | 296 | static ssize_t iwl_dbgfs_sram_write(struct file *file, | 
 | 297 | 					const char __user *user_buf, | 
 | 298 | 					size_t count, loff_t *ppos) | 
 | 299 | { | 
 | 300 | 	struct iwl_priv *priv = file->private_data; | 
 | 301 | 	char buf[64]; | 
 | 302 | 	int buf_size; | 
 | 303 | 	u32 offset, len; | 
 | 304 |  | 
 | 305 | 	memset(buf, 0, sizeof(buf)); | 
 | 306 | 	buf_size = min(count, sizeof(buf) -  1); | 
 | 307 | 	if (copy_from_user(buf, user_buf, buf_size)) | 
 | 308 | 		return -EFAULT; | 
 | 309 |  | 
 | 310 | 	if (sscanf(buf, "%x,%x", &offset, &len) == 2) { | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 311 | 		priv->dbgfs_sram_offset = offset; | 
 | 312 | 		priv->dbgfs_sram_len = len; | 
| Jay Sternberg | 24834d2 | 2011-01-11 15:41:00 -0800 | [diff] [blame] | 313 | 	} else if (sscanf(buf, "%x", &offset) == 1) { | 
 | 314 | 		priv->dbgfs_sram_offset = offset; | 
 | 315 | 		priv->dbgfs_sram_len = -4; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 316 | 	} else { | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 317 | 		priv->dbgfs_sram_offset = 0; | 
 | 318 | 		priv->dbgfs_sram_len = 0; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 319 | 	} | 
 | 320 |  | 
 | 321 | 	return count; | 
 | 322 | } | 
 | 323 |  | 
 | 324 | static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | 
 | 325 | 					size_t count, loff_t *ppos) | 
 | 326 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 327 | 	struct iwl_priv *priv = file->private_data; | 
| Tomas Winkler | 6def976 | 2008-05-05 10:22:31 +0800 | [diff] [blame] | 328 | 	struct iwl_station_entry *station; | 
| Tomas Winkler | 5425e49 | 2008-04-15 16:01:38 -0700 | [diff] [blame] | 329 | 	int max_sta = priv->hw_params.max_stations; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 330 | 	char *buf; | 
 | 331 | 	int i, j, pos = 0; | 
 | 332 | 	ssize_t ret; | 
 | 333 | 	/* Add 30 for initial string */ | 
 | 334 | 	const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 335 |  | 
 | 336 | 	buf = kmalloc(bufsz, GFP_KERNEL); | 
| Tomas Winkler | 3ac7f14 | 2008-07-21 02:40:14 +0300 | [diff] [blame] | 337 | 	if (!buf) | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 338 | 		return -ENOMEM; | 
 | 339 |  | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 340 | 	pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n", | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 341 | 			priv->num_stations); | 
 | 342 |  | 
 | 343 | 	for (i = 0; i < max_sta; i++) { | 
 | 344 | 		station = &priv->stations[i]; | 
| Johannes Berg | da73511 | 2010-05-03 01:25:24 -0700 | [diff] [blame] | 345 | 		if (!station->used) | 
 | 346 | 			continue; | 
 | 347 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 348 | 				 "station %d - addr: %pM, flags: %#x\n", | 
 | 349 | 				 i, station->sta.sta.addr, | 
 | 350 | 				 station->sta.station_flags_msk); | 
 | 351 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 352 | 				"TID\tseq_num\ttxq_id\tframes\ttfds\t"); | 
 | 353 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 354 | 				"start_idx\tbitmap\t\t\trate_n_flags\n"); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 355 |  | 
| Johannes Berg | da73511 | 2010-05-03 01:25:24 -0700 | [diff] [blame] | 356 | 		for (j = 0; j < MAX_TID_COUNT; j++) { | 
 | 357 | 			pos += scnprintf(buf + pos, bufsz - pos, | 
 | 358 | 				"%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x", | 
 | 359 | 				j, station->tid[j].seq_number, | 
 | 360 | 				station->tid[j].agg.txq_id, | 
 | 361 | 				station->tid[j].agg.frame_count, | 
 | 362 | 				station->tid[j].tfds_in_queue, | 
 | 363 | 				station->tid[j].agg.start_idx, | 
 | 364 | 				station->tid[j].agg.bitmap, | 
 | 365 | 				station->tid[j].agg.rate_n_flags); | 
 | 366 |  | 
 | 367 | 			if (station->tid[j].agg.wait_for_ba) | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 368 | 				pos += scnprintf(buf + pos, bufsz - pos, | 
| Johannes Berg | da73511 | 2010-05-03 01:25:24 -0700 | [diff] [blame] | 369 | 						 " - waitforba"); | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 370 | 			pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 371 | 		} | 
| Johannes Berg | da73511 | 2010-05-03 01:25:24 -0700 | [diff] [blame] | 372 |  | 
 | 373 | 		pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 374 | 	} | 
 | 375 |  | 
 | 376 | 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 377 | 	kfree(buf); | 
 | 378 | 	return ret; | 
 | 379 | } | 
 | 380 |  | 
| Wey-Yi Guy | 0848e29 | 2009-05-22 11:01:46 -0700 | [diff] [blame] | 381 | static ssize_t iwl_dbgfs_nvm_read(struct file *file, | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 382 | 				       char __user *user_buf, | 
 | 383 | 				       size_t count, | 
 | 384 | 				       loff_t *ppos) | 
 | 385 | { | 
 | 386 | 	ssize_t ret; | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 387 | 	struct iwl_priv *priv = file->private_data; | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 388 | 	int pos = 0, ofs = 0, buf_size = 0; | 
 | 389 | 	const u8 *ptr; | 
 | 390 | 	char *buf; | 
| Wey-Yi Guy | e307ddc | 2009-09-11 10:38:16 -0700 | [diff] [blame] | 391 | 	u16 eeprom_ver; | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 392 | 	size_t eeprom_len = priv->cfg->base_params->eeprom_size; | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 393 | 	buf_size = 4 * eeprom_len + 256; | 
 | 394 |  | 
 | 395 | 	if (eeprom_len % 16) { | 
| Wey-Yi Guy | 0848e29 | 2009-05-22 11:01:46 -0700 | [diff] [blame] | 396 | 		IWL_ERR(priv, "NVM size is not multiple of 16.\n"); | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 397 | 		return -ENODATA; | 
 | 398 | 	} | 
 | 399 |  | 
| Julia Lawall | c37457e | 2009-08-03 11:11:45 +0200 | [diff] [blame] | 400 | 	ptr = priv->eeprom; | 
 | 401 | 	if (!ptr) { | 
 | 402 | 		IWL_ERR(priv, "Invalid EEPROM/OTP memory\n"); | 
 | 403 | 		return -ENOMEM; | 
 | 404 | 	} | 
 | 405 |  | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 406 | 	/* 4 characters for byte 0xYY */ | 
 | 407 | 	buf = kzalloc(buf_size, GFP_KERNEL); | 
 | 408 | 	if (!buf) { | 
| Winkler, Tomas | 15b1687 | 2008-12-19 10:37:33 +0800 | [diff] [blame] | 409 | 		IWL_ERR(priv, "Can not allocate Buffer\n"); | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 410 | 		return -ENOMEM; | 
 | 411 | 	} | 
| Wey-Yi Guy | e307ddc | 2009-09-11 10:38:16 -0700 | [diff] [blame] | 412 | 	eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | 
 | 413 | 	pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, " | 
 | 414 | 			"version: 0x%x\n", | 
| Wey-Yi Guy | 0848e29 | 2009-05-22 11:01:46 -0700 | [diff] [blame] | 415 | 			(priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | 
| Wey-Yi Guy | e307ddc | 2009-09-11 10:38:16 -0700 | [diff] [blame] | 416 | 			 ? "OTP" : "EEPROM", eeprom_ver); | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 417 | 	for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { | 
 | 418 | 		pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); | 
 | 419 | 		hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, | 
 | 420 | 				   buf_size - pos, 0); | 
| Reinette Chatre | 2fac971 | 2009-09-25 14:24:21 -0700 | [diff] [blame] | 421 | 		pos += strlen(buf + pos); | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 422 | 		if (buf_size - pos > 0) | 
 | 423 | 			buf[pos++] = '\n'; | 
 | 424 | 	} | 
 | 425 |  | 
 | 426 | 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 427 | 	kfree(buf); | 
 | 428 | 	return ret; | 
 | 429 | } | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 430 |  | 
| Wey-Yi Guy | b03d7d0 | 2009-12-14 14:12:20 -0800 | [diff] [blame] | 431 | static ssize_t iwl_dbgfs_log_event_read(struct file *file, | 
 | 432 | 					 char __user *user_buf, | 
 | 433 | 					 size_t count, loff_t *ppos) | 
 | 434 | { | 
 | 435 | 	struct iwl_priv *priv = file->private_data; | 
 | 436 | 	char *buf; | 
 | 437 | 	int pos = 0; | 
 | 438 | 	ssize_t ret = -ENOMEM; | 
 | 439 |  | 
| Wey-Yi Guy | 937c397 | 2010-01-15 13:43:36 -0800 | [diff] [blame] | 440 | 	ret = pos = priv->cfg->ops->lib->dump_nic_event_log( | 
 | 441 | 					priv, true, &buf, true); | 
 | 442 | 	if (buf) { | 
| Wey-Yi Guy | b03d7d0 | 2009-12-14 14:12:20 -0800 | [diff] [blame] | 443 | 		ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 444 | 		kfree(buf); | 
 | 445 | 	} | 
 | 446 | 	return ret; | 
 | 447 | } | 
 | 448 |  | 
| Ester Kummer | 189a2b5 | 2008-05-15 13:54:18 +0800 | [diff] [blame] | 449 | static ssize_t iwl_dbgfs_log_event_write(struct file *file, | 
 | 450 | 					const char __user *user_buf, | 
 | 451 | 					size_t count, loff_t *ppos) | 
 | 452 | { | 
 | 453 | 	struct iwl_priv *priv = file->private_data; | 
 | 454 | 	u32 event_log_flag; | 
 | 455 | 	char buf[8]; | 
 | 456 | 	int buf_size; | 
 | 457 |  | 
 | 458 | 	memset(buf, 0, sizeof(buf)); | 
 | 459 | 	buf_size = min(count, sizeof(buf) -  1); | 
 | 460 | 	if (copy_from_user(buf, user_buf, buf_size)) | 
 | 461 | 		return -EFAULT; | 
 | 462 | 	if (sscanf(buf, "%d", &event_log_flag) != 1) | 
 | 463 | 		return -EFAULT; | 
 | 464 | 	if (event_log_flag == 1) | 
| Wey-Yi Guy | b03d7d0 | 2009-12-14 14:12:20 -0800 | [diff] [blame] | 465 | 		priv->cfg->ops->lib->dump_nic_event_log(priv, true, | 
 | 466 | 							NULL, false); | 
| Ester Kummer | 189a2b5 | 2008-05-15 13:54:18 +0800 | [diff] [blame] | 467 |  | 
 | 468 | 	return count; | 
 | 469 | } | 
 | 470 |  | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 471 |  | 
 | 472 |  | 
 | 473 | static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | 
 | 474 | 				       size_t count, loff_t *ppos) | 
 | 475 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 476 | 	struct iwl_priv *priv = file->private_data; | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 477 | 	struct ieee80211_channel *channels = NULL; | 
 | 478 | 	const struct ieee80211_supported_band *supp_band = NULL; | 
 | 479 | 	int pos = 0, i, bufsz = PAGE_SIZE; | 
 | 480 | 	char *buf; | 
 | 481 | 	ssize_t ret; | 
 | 482 |  | 
 | 483 | 	if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) | 
 | 484 | 		return -EAGAIN; | 
 | 485 |  | 
 | 486 | 	buf = kzalloc(bufsz, GFP_KERNEL); | 
 | 487 | 	if (!buf) { | 
| Winkler, Tomas | 15b1687 | 2008-12-19 10:37:33 +0800 | [diff] [blame] | 488 | 		IWL_ERR(priv, "Can not allocate Buffer\n"); | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 489 | 		return -ENOMEM; | 
 | 490 | 	} | 
 | 491 |  | 
 | 492 | 	supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ); | 
| Wey-Yi Guy | a2e2322 | 2009-05-22 11:01:55 -0700 | [diff] [blame] | 493 | 	if (supp_band) { | 
 | 494 | 		channels = supp_band->channels; | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 495 |  | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 496 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
| Wey-Yi Guy | a2e2322 | 2009-05-22 11:01:55 -0700 | [diff] [blame] | 497 | 				"Displaying %d channels in 2.4GHz band 802.11bg):\n", | 
 | 498 | 				supp_band->n_channels); | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 499 |  | 
| Wey-Yi Guy | a2e2322 | 2009-05-22 11:01:55 -0700 | [diff] [blame] | 500 | 		for (i = 0; i < supp_band->n_channels; i++) | 
 | 501 | 			pos += scnprintf(buf + pos, bufsz - pos, | 
 | 502 | 					"%d: %ddBm: BSS%s%s, %s.\n", | 
| Shanyu Zhao | 81e9543 | 2010-07-28 13:40:27 -0700 | [diff] [blame] | 503 | 					channels[i].hw_value, | 
| Wey-Yi Guy | a2e2322 | 2009-05-22 11:01:55 -0700 | [diff] [blame] | 504 | 					channels[i].max_power, | 
 | 505 | 					channels[i].flags & IEEE80211_CHAN_RADAR ? | 
 | 506 | 					" (IEEE 802.11h required)" : "", | 
 | 507 | 					((channels[i].flags & IEEE80211_CHAN_NO_IBSS) | 
 | 508 | 					|| (channels[i].flags & | 
 | 509 | 					IEEE80211_CHAN_RADAR)) ? "" : | 
 | 510 | 					", IBSS", | 
 | 511 | 					channels[i].flags & | 
 | 512 | 					IEEE80211_CHAN_PASSIVE_SCAN ? | 
 | 513 | 					"passive only" : "active/passive"); | 
 | 514 | 	} | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 515 | 	supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); | 
| Wey-Yi Guy | a2e2322 | 2009-05-22 11:01:55 -0700 | [diff] [blame] | 516 | 	if (supp_band) { | 
 | 517 | 		channels = supp_band->channels; | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 518 |  | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 519 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
| Wey-Yi Guy | a2e2322 | 2009-05-22 11:01:55 -0700 | [diff] [blame] | 520 | 				"Displaying %d channels in 5.2GHz band (802.11a)\n", | 
 | 521 | 				supp_band->n_channels); | 
 | 522 |  | 
 | 523 | 		for (i = 0; i < supp_band->n_channels; i++) | 
 | 524 | 			pos += scnprintf(buf + pos, bufsz - pos, | 
 | 525 | 					"%d: %ddBm: BSS%s%s, %s.\n", | 
| Shanyu Zhao | 81e9543 | 2010-07-28 13:40:27 -0700 | [diff] [blame] | 526 | 					channels[i].hw_value, | 
| Wey-Yi Guy | a2e2322 | 2009-05-22 11:01:55 -0700 | [diff] [blame] | 527 | 					channels[i].max_power, | 
 | 528 | 					channels[i].flags & IEEE80211_CHAN_RADAR ? | 
 | 529 | 					" (IEEE 802.11h required)" : "", | 
 | 530 | 					((channels[i].flags & IEEE80211_CHAN_NO_IBSS) | 
 | 531 | 					|| (channels[i].flags & | 
 | 532 | 					IEEE80211_CHAN_RADAR)) ? "" : | 
 | 533 | 					", IBSS", | 
 | 534 | 					channels[i].flags & | 
 | 535 | 					IEEE80211_CHAN_PASSIVE_SCAN ? | 
 | 536 | 					"passive only" : "active/passive"); | 
 | 537 | 	} | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 538 | 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 539 | 	kfree(buf); | 
 | 540 | 	return ret; | 
 | 541 | } | 
 | 542 |  | 
| Wey-Yi Guy | 08df05a | 2009-03-24 10:02:54 -0700 | [diff] [blame] | 543 | static ssize_t iwl_dbgfs_status_read(struct file *file, | 
 | 544 | 						char __user *user_buf, | 
 | 545 | 						size_t count, loff_t *ppos) { | 
 | 546 |  | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 547 | 	struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 08df05a | 2009-03-24 10:02:54 -0700 | [diff] [blame] | 548 | 	char buf[512]; | 
 | 549 | 	int pos = 0; | 
 | 550 | 	const size_t bufsz = sizeof(buf); | 
 | 551 |  | 
 | 552 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", | 
 | 553 | 		test_bit(STATUS_HCMD_ACTIVE, &priv->status)); | 
| Wey-Yi Guy | 08df05a | 2009-03-24 10:02:54 -0700 | [diff] [blame] | 554 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", | 
 | 555 | 		test_bit(STATUS_INT_ENABLED, &priv->status)); | 
 | 556 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", | 
 | 557 | 		test_bit(STATUS_RF_KILL_HW, &priv->status)); | 
| Wey-Yi Guy | 7812b16 | 2009-10-02 13:43:58 -0700 | [diff] [blame] | 558 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n", | 
 | 559 | 		test_bit(STATUS_CT_KILL, &priv->status)); | 
| Wey-Yi Guy | 08df05a | 2009-03-24 10:02:54 -0700 | [diff] [blame] | 560 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", | 
 | 561 | 		test_bit(STATUS_INIT, &priv->status)); | 
 | 562 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", | 
 | 563 | 		test_bit(STATUS_ALIVE, &priv->status)); | 
 | 564 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", | 
 | 565 | 		test_bit(STATUS_READY, &priv->status)); | 
 | 566 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n", | 
 | 567 | 		test_bit(STATUS_TEMPERATURE, &priv->status)); | 
 | 568 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", | 
 | 569 | 		test_bit(STATUS_GEO_CONFIGURED, &priv->status)); | 
 | 570 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", | 
 | 571 | 		test_bit(STATUS_EXIT_PENDING, &priv->status)); | 
| Wey-Yi Guy | 08df05a | 2009-03-24 10:02:54 -0700 | [diff] [blame] | 572 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", | 
 | 573 | 		test_bit(STATUS_STATISTICS, &priv->status)); | 
 | 574 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", | 
 | 575 | 		test_bit(STATUS_SCANNING, &priv->status)); | 
 | 576 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n", | 
 | 577 | 		test_bit(STATUS_SCAN_ABORTING, &priv->status)); | 
 | 578 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n", | 
 | 579 | 		test_bit(STATUS_SCAN_HW, &priv->status)); | 
 | 580 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n", | 
 | 581 | 		test_bit(STATUS_POWER_PMI, &priv->status)); | 
 | 582 | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", | 
 | 583 | 		test_bit(STATUS_FW_ERROR, &priv->status)); | 
| Wey-Yi Guy | 08df05a | 2009-03-24 10:02:54 -0700 | [diff] [blame] | 584 | 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 585 | } | 
 | 586 |  | 
| Wey-Yi Guy | a83b914 | 2009-04-08 11:39:32 -0700 | [diff] [blame] | 587 | static ssize_t iwl_dbgfs_interrupt_read(struct file *file, | 
 | 588 | 					char __user *user_buf, | 
 | 589 | 					size_t count, loff_t *ppos) { | 
 | 590 |  | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 591 | 	struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | a83b914 | 2009-04-08 11:39:32 -0700 | [diff] [blame] | 592 | 	int pos = 0; | 
 | 593 | 	int cnt = 0; | 
 | 594 | 	char *buf; | 
 | 595 | 	int bufsz = 24 * 64; /* 24 items * 64 char per item */ | 
 | 596 | 	ssize_t ret; | 
 | 597 |  | 
 | 598 | 	buf = kzalloc(bufsz, GFP_KERNEL); | 
 | 599 | 	if (!buf) { | 
 | 600 | 		IWL_ERR(priv, "Can not allocate Buffer\n"); | 
 | 601 | 		return -ENOMEM; | 
 | 602 | 	} | 
 | 603 |  | 
 | 604 | 	pos += scnprintf(buf + pos, bufsz - pos, | 
 | 605 | 			"Interrupt Statistics Report:\n"); | 
 | 606 |  | 
 | 607 | 	pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", | 
 | 608 | 		priv->isr_stats.hw); | 
 | 609 | 	pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", | 
 | 610 | 		priv->isr_stats.sw); | 
| Wey-Yi Guy | 6e6ebf4 | 2010-08-27 10:41:37 -0700 | [diff] [blame] | 611 | 	if (priv->isr_stats.sw || priv->isr_stats.hw) { | 
| Wey-Yi Guy | a83b914 | 2009-04-08 11:39:32 -0700 | [diff] [blame] | 612 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 613 | 			"\tLast Restarting Code:  0x%X\n", | 
| Wey-Yi Guy | 6e6ebf4 | 2010-08-27 10:41:37 -0700 | [diff] [blame] | 614 | 			priv->isr_stats.err_code); | 
| Wey-Yi Guy | a83b914 | 2009-04-08 11:39:32 -0700 | [diff] [blame] | 615 | 	} | 
 | 616 | #ifdef CONFIG_IWLWIFI_DEBUG | 
 | 617 | 	pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", | 
 | 618 | 		priv->isr_stats.sch); | 
 | 619 | 	pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", | 
 | 620 | 		priv->isr_stats.alive); | 
 | 621 | #endif | 
 | 622 | 	pos += scnprintf(buf + pos, bufsz - pos, | 
 | 623 | 		"HW RF KILL switch toggled:\t %u\n", | 
 | 624 | 		priv->isr_stats.rfkill); | 
 | 625 |  | 
 | 626 | 	pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", | 
 | 627 | 		priv->isr_stats.ctkill); | 
 | 628 |  | 
 | 629 | 	pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", | 
 | 630 | 		priv->isr_stats.wakeup); | 
 | 631 |  | 
 | 632 | 	pos += scnprintf(buf + pos, bufsz - pos, | 
 | 633 | 		"Rx command responses:\t\t %u\n", | 
 | 634 | 		priv->isr_stats.rx); | 
 | 635 | 	for (cnt = 0; cnt < REPLY_MAX; cnt++) { | 
 | 636 | 		if (priv->isr_stats.rx_handlers[cnt] > 0) | 
 | 637 | 			pos += scnprintf(buf + pos, bufsz - pos, | 
 | 638 | 				"\tRx handler[%36s]:\t\t %u\n", | 
 | 639 | 				get_cmd_string(cnt), | 
 | 640 | 				priv->isr_stats.rx_handlers[cnt]); | 
 | 641 | 	} | 
 | 642 |  | 
 | 643 | 	pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", | 
 | 644 | 		priv->isr_stats.tx); | 
 | 645 |  | 
 | 646 | 	pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", | 
 | 647 | 		priv->isr_stats.unhandled); | 
 | 648 |  | 
 | 649 | 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 650 | 	kfree(buf); | 
 | 651 | 	return ret; | 
 | 652 | } | 
 | 653 |  | 
 | 654 | static ssize_t iwl_dbgfs_interrupt_write(struct file *file, | 
 | 655 | 					 const char __user *user_buf, | 
 | 656 | 					 size_t count, loff_t *ppos) | 
 | 657 | { | 
 | 658 | 	struct iwl_priv *priv = file->private_data; | 
 | 659 | 	char buf[8]; | 
 | 660 | 	int buf_size; | 
 | 661 | 	u32 reset_flag; | 
 | 662 |  | 
 | 663 | 	memset(buf, 0, sizeof(buf)); | 
 | 664 | 	buf_size = min(count, sizeof(buf) -  1); | 
 | 665 | 	if (copy_from_user(buf, user_buf, buf_size)) | 
 | 666 | 		return -EFAULT; | 
 | 667 | 	if (sscanf(buf, "%x", &reset_flag) != 1) | 
 | 668 | 		return -EFAULT; | 
 | 669 | 	if (reset_flag == 0) | 
 | 670 | 		iwl_clear_isr_stats(priv); | 
 | 671 |  | 
 | 672 | 	return count; | 
 | 673 | } | 
 | 674 |  | 
| Wey-Yi Guy | f5ad69f | 2009-07-09 10:33:36 -0700 | [diff] [blame] | 675 | static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, | 
 | 676 | 				       size_t count, loff_t *ppos) | 
 | 677 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 678 | 	struct iwl_priv *priv = file->private_data; | 
| Johannes Berg | 8dfdb9d | 2010-08-23 10:46:38 +0200 | [diff] [blame] | 679 | 	struct iwl_rxon_context *ctx; | 
| Wey-Yi Guy | f5ad69f | 2009-07-09 10:33:36 -0700 | [diff] [blame] | 680 | 	int pos = 0, i; | 
| Johannes Berg | 8dfdb9d | 2010-08-23 10:46:38 +0200 | [diff] [blame] | 681 | 	char buf[256 * NUM_IWL_RXON_CTX]; | 
| Wey-Yi Guy | f5ad69f | 2009-07-09 10:33:36 -0700 | [diff] [blame] | 682 | 	const size_t bufsz = sizeof(buf); | 
| Wey-Yi Guy | f5ad69f | 2009-07-09 10:33:36 -0700 | [diff] [blame] | 683 |  | 
| Johannes Berg | 8dfdb9d | 2010-08-23 10:46:38 +0200 | [diff] [blame] | 684 | 	for_each_context(priv, ctx) { | 
 | 685 | 		pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n", | 
 | 686 | 				 ctx->ctxid); | 
 | 687 | 		for (i = 0; i < AC_NUM; i++) { | 
 | 688 | 			pos += scnprintf(buf + pos, bufsz - pos, | 
 | 689 | 				"\tcw_min\tcw_max\taifsn\ttxop\n"); | 
 | 690 | 			pos += scnprintf(buf + pos, bufsz - pos, | 
| Wey-Yi Guy | f5ad69f | 2009-07-09 10:33:36 -0700 | [diff] [blame] | 691 | 				"AC[%d]\t%u\t%u\t%u\t%u\n", i, | 
| Johannes Berg | 8dfdb9d | 2010-08-23 10:46:38 +0200 | [diff] [blame] | 692 | 				ctx->qos_data.def_qos_parm.ac[i].cw_min, | 
 | 693 | 				ctx->qos_data.def_qos_parm.ac[i].cw_max, | 
 | 694 | 				ctx->qos_data.def_qos_parm.ac[i].aifsn, | 
 | 695 | 				ctx->qos_data.def_qos_parm.ac[i].edca_txop); | 
 | 696 | 		} | 
 | 697 | 		pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
| Wey-Yi Guy | f5ad69f | 2009-07-09 10:33:36 -0700 | [diff] [blame] | 698 | 	} | 
| Wey-Yi Guy | 4967c31 | 2010-02-18 15:22:07 -0800 | [diff] [blame] | 699 | 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
| Wey-Yi Guy | f5ad69f | 2009-07-09 10:33:36 -0700 | [diff] [blame] | 700 | } | 
| Wey-Yi Guy | a83b914 | 2009-04-08 11:39:32 -0700 | [diff] [blame] | 701 |  | 
| Wey-Yi Guy | fbf3a2a | 2009-07-24 11:13:04 -0700 | [diff] [blame] | 702 | static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, | 
 | 703 | 				char __user *user_buf, | 
 | 704 | 				size_t count, loff_t *ppos) | 
 | 705 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 706 | 	struct iwl_priv *priv = file->private_data; | 
| Johannes Berg | 3ad3b92 | 2009-08-07 15:41:48 -0700 | [diff] [blame] | 707 | 	struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | 
| Wey-Yi Guy | fbf3a2a | 2009-07-24 11:13:04 -0700 | [diff] [blame] | 708 | 	struct iwl_tt_restriction *restriction; | 
 | 709 | 	char buf[100]; | 
 | 710 | 	int pos = 0; | 
 | 711 | 	const size_t bufsz = sizeof(buf); | 
| Wey-Yi Guy | fbf3a2a | 2009-07-24 11:13:04 -0700 | [diff] [blame] | 712 |  | 
 | 713 | 	pos += scnprintf(buf + pos, bufsz - pos, | 
 | 714 | 			"Thermal Throttling Mode: %s\n", | 
| Johannes Berg | 3ad3b92 | 2009-08-07 15:41:48 -0700 | [diff] [blame] | 715 | 			tt->advanced_tt ? "Advance" : "Legacy"); | 
| Wey-Yi Guy | fbf3a2a | 2009-07-24 11:13:04 -0700 | [diff] [blame] | 716 | 	pos += scnprintf(buf + pos, bufsz - pos, | 
 | 717 | 			"Thermal Throttling State: %d\n", | 
 | 718 | 			tt->state); | 
| Johannes Berg | 3ad3b92 | 2009-08-07 15:41:48 -0700 | [diff] [blame] | 719 | 	if (tt->advanced_tt) { | 
| Wey-Yi Guy | fbf3a2a | 2009-07-24 11:13:04 -0700 | [diff] [blame] | 720 | 		restriction = tt->restriction + tt->state; | 
 | 721 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 722 | 				"Tx mode: %d\n", | 
 | 723 | 				restriction->tx_stream); | 
 | 724 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 725 | 				"Rx mode: %d\n", | 
 | 726 | 				restriction->rx_stream); | 
 | 727 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 728 | 				"HT mode: %d\n", | 
 | 729 | 				restriction->is_ht); | 
 | 730 | 	} | 
| Wey-Yi Guy | 4967c31 | 2010-02-18 15:22:07 -0800 | [diff] [blame] | 731 | 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
| Wey-Yi Guy | fbf3a2a | 2009-07-24 11:13:04 -0700 | [diff] [blame] | 732 | } | 
 | 733 |  | 
| Wey-Yi Guy | 1e4247d | 2009-07-27 13:50:15 -0700 | [diff] [blame] | 734 | static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file, | 
 | 735 | 					 const char __user *user_buf, | 
 | 736 | 					 size_t count, loff_t *ppos) | 
 | 737 | { | 
 | 738 | 	struct iwl_priv *priv = file->private_data; | 
 | 739 | 	char buf[8]; | 
 | 740 | 	int buf_size; | 
 | 741 | 	int ht40; | 
 | 742 |  | 
 | 743 | 	memset(buf, 0, sizeof(buf)); | 
 | 744 | 	buf_size = min(count, sizeof(buf) -  1); | 
 | 745 | 	if (copy_from_user(buf, user_buf, buf_size)) | 
 | 746 | 		return -EFAULT; | 
 | 747 | 	if (sscanf(buf, "%d", &ht40) != 1) | 
 | 748 | 		return -EFAULT; | 
| Johannes Berg | 246ed35 | 2010-08-23 10:46:32 +0200 | [diff] [blame] | 749 | 	if (!iwl_is_any_associated(priv)) | 
| Wey-Yi Guy | 1e4247d | 2009-07-27 13:50:15 -0700 | [diff] [blame] | 750 | 		priv->disable_ht40 = ht40 ? true : false; | 
 | 751 | 	else { | 
 | 752 | 		IWL_ERR(priv, "Sta associated with AP - " | 
 | 753 | 			"Change to 40MHz channel support is not allowed\n"); | 
 | 754 | 		return -EINVAL; | 
 | 755 | 	} | 
 | 756 |  | 
 | 757 | 	return count; | 
 | 758 | } | 
 | 759 |  | 
 | 760 | static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file, | 
 | 761 | 					 char __user *user_buf, | 
 | 762 | 					 size_t count, loff_t *ppos) | 
 | 763 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 764 | 	struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 1e4247d | 2009-07-27 13:50:15 -0700 | [diff] [blame] | 765 | 	char buf[100]; | 
 | 766 | 	int pos = 0; | 
 | 767 | 	const size_t bufsz = sizeof(buf); | 
| Wey-Yi Guy | 1e4247d | 2009-07-27 13:50:15 -0700 | [diff] [blame] | 768 |  | 
 | 769 | 	pos += scnprintf(buf + pos, bufsz - pos, | 
 | 770 | 			"11n 40MHz Mode: %s\n", | 
 | 771 | 			priv->disable_ht40 ? "Disabled" : "Enabled"); | 
| Wey-Yi Guy | 4967c31 | 2010-02-18 15:22:07 -0800 | [diff] [blame] | 772 | 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
| Wey-Yi Guy | 1e4247d | 2009-07-27 13:50:15 -0700 | [diff] [blame] | 773 | } | 
 | 774 |  | 
| Johannes Berg | e312c24 | 2009-08-07 15:41:51 -0700 | [diff] [blame] | 775 | static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, | 
 | 776 | 						    const char __user *user_buf, | 
 | 777 | 						    size_t count, loff_t *ppos) | 
 | 778 | { | 
 | 779 | 	struct iwl_priv *priv = file->private_data; | 
 | 780 | 	char buf[8]; | 
 | 781 | 	int buf_size; | 
 | 782 | 	int value; | 
 | 783 |  | 
 | 784 | 	memset(buf, 0, sizeof(buf)); | 
 | 785 | 	buf_size = min(count, sizeof(buf) -  1); | 
 | 786 | 	if (copy_from_user(buf, user_buf, buf_size)) | 
 | 787 | 		return -EFAULT; | 
 | 788 |  | 
 | 789 | 	if (sscanf(buf, "%d", &value) != 1) | 
 | 790 | 		return -EINVAL; | 
 | 791 |  | 
 | 792 | 	/* | 
 | 793 | 	 * Our users expect 0 to be "CAM", but 0 isn't actually | 
 | 794 | 	 * valid here. However, let's not confuse them and present | 
 | 795 | 	 * IWL_POWER_INDEX_1 as "1", not "0". | 
 | 796 | 	 */ | 
| Reinette Chatre | 1a34c04 | 2009-10-09 13:20:25 -0700 | [diff] [blame] | 797 | 	if (value == 0) | 
 | 798 | 		return -EINVAL; | 
 | 799 | 	else if (value > 0) | 
| Johannes Berg | e312c24 | 2009-08-07 15:41:51 -0700 | [diff] [blame] | 800 | 		value -= 1; | 
 | 801 |  | 
 | 802 | 	if (value != -1 && (value < 0 || value >= IWL_POWER_NUM)) | 
 | 803 | 		return -EINVAL; | 
 | 804 |  | 
| Wey-Yi Guy | 4ad177b | 2009-10-16 14:25:58 -0700 | [diff] [blame] | 805 | 	if (!iwl_is_ready_rf(priv)) | 
 | 806 | 		return -EAGAIN; | 
 | 807 |  | 
| Johannes Berg | e312c24 | 2009-08-07 15:41:51 -0700 | [diff] [blame] | 808 | 	priv->power_data.debug_sleep_level_override = value; | 
 | 809 |  | 
| Reinette Chatre | d3a5719 | 2010-01-21 11:52:28 -0800 | [diff] [blame] | 810 | 	mutex_lock(&priv->mutex); | 
| Wey-Yi Guy | 4ad177b | 2009-10-16 14:25:58 -0700 | [diff] [blame] | 811 | 	iwl_power_update_mode(priv, true); | 
| Reinette Chatre | d3a5719 | 2010-01-21 11:52:28 -0800 | [diff] [blame] | 812 | 	mutex_unlock(&priv->mutex); | 
| Johannes Berg | e312c24 | 2009-08-07 15:41:51 -0700 | [diff] [blame] | 813 |  | 
 | 814 | 	return count; | 
 | 815 | } | 
 | 816 |  | 
 | 817 | static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file, | 
 | 818 | 						   char __user *user_buf, | 
 | 819 | 						   size_t count, loff_t *ppos) | 
 | 820 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 821 | 	struct iwl_priv *priv = file->private_data; | 
| Johannes Berg | e312c24 | 2009-08-07 15:41:51 -0700 | [diff] [blame] | 822 | 	char buf[10]; | 
 | 823 | 	int pos, value; | 
 | 824 | 	const size_t bufsz = sizeof(buf); | 
 | 825 |  | 
 | 826 | 	/* see the write function */ | 
 | 827 | 	value = priv->power_data.debug_sleep_level_override; | 
 | 828 | 	if (value >= 0) | 
 | 829 | 		value += 1; | 
 | 830 |  | 
 | 831 | 	pos = scnprintf(buf, bufsz, "%d\n", value); | 
 | 832 | 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 833 | } | 
 | 834 |  | 
 | 835 | static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, | 
 | 836 | 						    char __user *user_buf, | 
 | 837 | 						    size_t count, loff_t *ppos) | 
 | 838 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 839 | 	struct iwl_priv *priv = file->private_data; | 
| Johannes Berg | e312c24 | 2009-08-07 15:41:51 -0700 | [diff] [blame] | 840 | 	char buf[200]; | 
 | 841 | 	int pos = 0, i; | 
 | 842 | 	const size_t bufsz = sizeof(buf); | 
 | 843 | 	struct iwl_powertable_cmd *cmd = &priv->power_data.sleep_cmd; | 
 | 844 |  | 
 | 845 | 	pos += scnprintf(buf + pos, bufsz - pos, | 
 | 846 | 			 "flags: %#.2x\n", le16_to_cpu(cmd->flags)); | 
 | 847 | 	pos += scnprintf(buf + pos, bufsz - pos, | 
 | 848 | 			 "RX/TX timeout: %d/%d usec\n", | 
 | 849 | 			 le32_to_cpu(cmd->rx_data_timeout), | 
 | 850 | 			 le32_to_cpu(cmd->tx_data_timeout)); | 
 | 851 | 	for (i = 0; i < IWL_POWER_VEC_SIZE; i++) | 
 | 852 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 853 | 				 "sleep_interval[%d]: %d\n", i, | 
 | 854 | 				 le32_to_cpu(cmd->sleep_interval[i])); | 
 | 855 |  | 
 | 856 | 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 857 | } | 
 | 858 |  | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 859 | DEBUGFS_READ_WRITE_FILE_OPS(sram); | 
| Wey-Yi Guy | b03d7d0 | 2009-12-14 14:12:20 -0800 | [diff] [blame] | 860 | DEBUGFS_READ_WRITE_FILE_OPS(log_event); | 
| Wey-Yi Guy | 0848e29 | 2009-05-22 11:01:46 -0700 | [diff] [blame] | 861 | DEBUGFS_READ_FILE_OPS(nvm); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 862 | DEBUGFS_READ_FILE_OPS(stations); | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 863 | DEBUGFS_READ_FILE_OPS(channels); | 
| Wey-Yi Guy | 08df05a | 2009-03-24 10:02:54 -0700 | [diff] [blame] | 864 | DEBUGFS_READ_FILE_OPS(status); | 
| Wey-Yi Guy | a83b914 | 2009-04-08 11:39:32 -0700 | [diff] [blame] | 865 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); | 
| Wey-Yi Guy | f5ad69f | 2009-07-09 10:33:36 -0700 | [diff] [blame] | 866 | DEBUGFS_READ_FILE_OPS(qos); | 
| Wey-Yi Guy | fbf3a2a | 2009-07-24 11:13:04 -0700 | [diff] [blame] | 867 | DEBUGFS_READ_FILE_OPS(thermal_throttling); | 
| Wey-Yi Guy | 1e4247d | 2009-07-27 13:50:15 -0700 | [diff] [blame] | 868 | DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); | 
| Johannes Berg | e312c24 | 2009-08-07 15:41:51 -0700 | [diff] [blame] | 869 | DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); | 
 | 870 | DEBUGFS_READ_FILE_OPS(current_sleep_command); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 871 |  | 
| Wey-Yi Guy | 20594eb | 2009-08-07 15:41:39 -0700 | [diff] [blame] | 872 | static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, | 
 | 873 | 					 char __user *user_buf, | 
 | 874 | 					 size_t count, loff_t *ppos) | 
 | 875 | { | 
 | 876 | 	struct iwl_priv *priv = file->private_data; | 
 | 877 | 	int pos = 0, ofs = 0; | 
 | 878 | 	int cnt = 0, entry; | 
 | 879 | 	struct iwl_tx_queue *txq; | 
 | 880 | 	struct iwl_queue *q; | 
 | 881 | 	struct iwl_rx_queue *rxq = &priv->rxq; | 
 | 882 | 	char *buf; | 
 | 883 | 	int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 884 | 		(priv->cfg->base_params->num_of_queues * 32 * 8) + 400; | 
| Wey-Yi Guy | 20594eb | 2009-08-07 15:41:39 -0700 | [diff] [blame] | 885 | 	const u8 *ptr; | 
 | 886 | 	ssize_t ret; | 
 | 887 |  | 
| Wey-Yi Guy | 88804e2 | 2009-10-09 13:20:28 -0700 | [diff] [blame] | 888 | 	if (!priv->txq) { | 
 | 889 | 		IWL_ERR(priv, "txq not ready\n"); | 
 | 890 | 		return -EAGAIN; | 
 | 891 | 	} | 
| Wey-Yi Guy | 20594eb | 2009-08-07 15:41:39 -0700 | [diff] [blame] | 892 | 	buf = kzalloc(bufsz, GFP_KERNEL); | 
 | 893 | 	if (!buf) { | 
 | 894 | 		IWL_ERR(priv, "Can not allocate buffer\n"); | 
 | 895 | 		return -ENOMEM; | 
 | 896 | 	} | 
 | 897 | 	pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); | 
 | 898 | 	for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { | 
 | 899 | 		txq = &priv->txq[cnt]; | 
 | 900 | 		q = &txq->q; | 
 | 901 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 902 | 				"q[%d]: read_ptr: %u, write_ptr: %u\n", | 
 | 903 | 				cnt, q->read_ptr, q->write_ptr); | 
 | 904 | 	} | 
 | 905 | 	if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) { | 
 | 906 | 		ptr = priv->tx_traffic; | 
 | 907 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 908 | 				"Tx Traffic idx: %u\n",	priv->tx_traffic_idx); | 
 | 909 | 		for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { | 
 | 910 | 			for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; | 
 | 911 | 			     entry++,  ofs += 16) { | 
 | 912 | 				pos += scnprintf(buf + pos, bufsz - pos, | 
 | 913 | 						"0x%.4x ", ofs); | 
 | 914 | 				hex_dump_to_buffer(ptr + ofs, 16, 16, 2, | 
 | 915 | 						   buf + pos, bufsz - pos, 0); | 
| Reinette Chatre | 2fac971 | 2009-09-25 14:24:21 -0700 | [diff] [blame] | 916 | 				pos += strlen(buf + pos); | 
| Wey-Yi Guy | 20594eb | 2009-08-07 15:41:39 -0700 | [diff] [blame] | 917 | 				if (bufsz - pos > 0) | 
 | 918 | 					buf[pos++] = '\n'; | 
 | 919 | 			} | 
 | 920 | 		} | 
 | 921 | 	} | 
 | 922 |  | 
 | 923 | 	pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n"); | 
 | 924 | 	pos += scnprintf(buf + pos, bufsz - pos, | 
 | 925 | 			"read: %u, write: %u\n", | 
 | 926 | 			 rxq->read, rxq->write); | 
 | 927 |  | 
 | 928 | 	if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) { | 
 | 929 | 		ptr = priv->rx_traffic; | 
 | 930 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 931 | 				"Rx Traffic idx: %u\n",	priv->rx_traffic_idx); | 
 | 932 | 		for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { | 
 | 933 | 			for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; | 
 | 934 | 			     entry++,  ofs += 16) { | 
 | 935 | 				pos += scnprintf(buf + pos, bufsz - pos, | 
 | 936 | 						"0x%.4x ", ofs); | 
 | 937 | 				hex_dump_to_buffer(ptr + ofs, 16, 16, 2, | 
 | 938 | 						   buf + pos, bufsz - pos, 0); | 
| Reinette Chatre | 2fac971 | 2009-09-25 14:24:21 -0700 | [diff] [blame] | 939 | 				pos += strlen(buf + pos); | 
| Wey-Yi Guy | 20594eb | 2009-08-07 15:41:39 -0700 | [diff] [blame] | 940 | 				if (bufsz - pos > 0) | 
 | 941 | 					buf[pos++] = '\n'; | 
 | 942 | 			} | 
 | 943 | 		} | 
 | 944 | 	} | 
 | 945 |  | 
 | 946 | 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 947 | 	kfree(buf); | 
 | 948 | 	return ret; | 
 | 949 | } | 
 | 950 |  | 
 | 951 | static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, | 
 | 952 | 					 const char __user *user_buf, | 
 | 953 | 					 size_t count, loff_t *ppos) | 
 | 954 | { | 
 | 955 | 	struct iwl_priv *priv = file->private_data; | 
 | 956 | 	char buf[8]; | 
 | 957 | 	int buf_size; | 
 | 958 | 	int traffic_log; | 
 | 959 |  | 
 | 960 | 	memset(buf, 0, sizeof(buf)); | 
 | 961 | 	buf_size = min(count, sizeof(buf) -  1); | 
 | 962 | 	if (copy_from_user(buf, user_buf, buf_size)) | 
 | 963 | 		return -EFAULT; | 
 | 964 | 	if (sscanf(buf, "%d", &traffic_log) != 1) | 
 | 965 | 		return -EFAULT; | 
 | 966 | 	if (traffic_log == 0) | 
 | 967 | 		iwl_reset_traffic_log(priv); | 
 | 968 |  | 
 | 969 | 	return count; | 
 | 970 | } | 
 | 971 |  | 
| Wey-Yi Guy | 141b03e | 2009-08-07 15:41:41 -0700 | [diff] [blame] | 972 | static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | 
 | 973 | 						char __user *user_buf, | 
 | 974 | 						size_t count, loff_t *ppos) { | 
 | 975 |  | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 976 | 	struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 141b03e | 2009-08-07 15:41:41 -0700 | [diff] [blame] | 977 | 	struct iwl_tx_queue *txq; | 
 | 978 | 	struct iwl_queue *q; | 
 | 979 | 	char *buf; | 
 | 980 | 	int pos = 0; | 
 | 981 | 	int cnt; | 
 | 982 | 	int ret; | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 983 | 	const size_t bufsz = sizeof(char) * 64 * | 
 | 984 | 				priv->cfg->base_params->num_of_queues; | 
| Wey-Yi Guy | 141b03e | 2009-08-07 15:41:41 -0700 | [diff] [blame] | 985 |  | 
| Wey-Yi Guy | 88804e2 | 2009-10-09 13:20:28 -0700 | [diff] [blame] | 986 | 	if (!priv->txq) { | 
 | 987 | 		IWL_ERR(priv, "txq not ready\n"); | 
 | 988 | 		return -EAGAIN; | 
 | 989 | 	} | 
| Wey-Yi Guy | 141b03e | 2009-08-07 15:41:41 -0700 | [diff] [blame] | 990 | 	buf = kzalloc(bufsz, GFP_KERNEL); | 
 | 991 | 	if (!buf) | 
 | 992 | 		return -ENOMEM; | 
 | 993 |  | 
 | 994 | 	for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { | 
 | 995 | 		txq = &priv->txq[cnt]; | 
 | 996 | 		q = &txq->q; | 
 | 997 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 998 | 				"hwq %.2d: read=%u write=%u stop=%d" | 
 | 999 | 				" swq_id=%#.2x (ac %d/hwq %d)\n", | 
 | 1000 | 				cnt, q->read_ptr, q->write_ptr, | 
 | 1001 | 				!!test_bit(cnt, priv->queue_stopped), | 
| Johannes Berg | ea9b307 | 2010-11-10 18:25:45 -0800 | [diff] [blame] | 1002 | 				txq->swq_id, txq->swq_id & 3, | 
 | 1003 | 				(txq->swq_id >> 2) & 0x1f); | 
| Wey-Yi Guy | 141b03e | 2009-08-07 15:41:41 -0700 | [diff] [blame] | 1004 | 		if (cnt >= 4) | 
 | 1005 | 			continue; | 
 | 1006 | 		/* for the ACs, display the stop count too */ | 
 | 1007 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 1008 | 				"        stop-count: %d\n", | 
 | 1009 | 				atomic_read(&priv->queue_stop_count[cnt])); | 
 | 1010 | 	} | 
 | 1011 | 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 1012 | 	kfree(buf); | 
 | 1013 | 	return ret; | 
 | 1014 | } | 
 | 1015 |  | 
 | 1016 | static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | 
 | 1017 | 						char __user *user_buf, | 
 | 1018 | 						size_t count, loff_t *ppos) { | 
 | 1019 |  | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 1020 | 	struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 141b03e | 2009-08-07 15:41:41 -0700 | [diff] [blame] | 1021 | 	struct iwl_rx_queue *rxq = &priv->rxq; | 
 | 1022 | 	char buf[256]; | 
 | 1023 | 	int pos = 0; | 
 | 1024 | 	const size_t bufsz = sizeof(buf); | 
 | 1025 |  | 
 | 1026 | 	pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", | 
 | 1027 | 						rxq->read); | 
 | 1028 | 	pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", | 
 | 1029 | 						rxq->write); | 
 | 1030 | 	pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", | 
 | 1031 | 						rxq->free_count); | 
| Dor Shaish | f5cc6a2 | 2010-06-01 00:04:08 -0700 | [diff] [blame] | 1032 | 	if (rxq->rb_stts) { | 
 | 1033 | 		pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", | 
| Wey-Yi Guy | 141b03e | 2009-08-07 15:41:41 -0700 | [diff] [blame] | 1034 | 			 le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF); | 
| Dor Shaish | f5cc6a2 | 2010-06-01 00:04:08 -0700 | [diff] [blame] | 1035 | 	} else { | 
 | 1036 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 1037 | 					"closed_rb_num: Not Allocated\n"); | 
 | 1038 | 	} | 
| Wey-Yi Guy | 141b03e | 2009-08-07 15:41:41 -0700 | [diff] [blame] | 1039 | 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 1040 | } | 
 | 1041 |  | 
| Wey-Yi Guy | e8fe59a | 2009-08-07 15:41:42 -0700 | [diff] [blame] | 1042 | static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, | 
 | 1043 | 					char __user *user_buf, | 
 | 1044 | 					size_t count, loff_t *ppos) | 
 | 1045 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 1046 | 	struct iwl_priv *priv = file->private_data; | 
| Abhijeet Kolekar | 17f36fc | 2010-04-16 10:03:54 -0700 | [diff] [blame] | 1047 | 	return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file, | 
 | 1048 | 			user_buf, count, ppos); | 
| Wey-Yi Guy | e8fe59a | 2009-08-07 15:41:42 -0700 | [diff] [blame] | 1049 | } | 
 | 1050 |  | 
 | 1051 | static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | 
 | 1052 | 					char __user *user_buf, | 
 | 1053 | 					size_t count, loff_t *ppos) | 
 | 1054 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 1055 | 	struct iwl_priv *priv = file->private_data; | 
| Abhijeet Kolekar | 17f36fc | 2010-04-16 10:03:54 -0700 | [diff] [blame] | 1056 | 	return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file, | 
 | 1057 | 			user_buf, count, ppos); | 
| Wey-Yi Guy | e8fe59a | 2009-08-07 15:41:42 -0700 | [diff] [blame] | 1058 | } | 
 | 1059 |  | 
 | 1060 | static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, | 
 | 1061 | 					char __user *user_buf, | 
 | 1062 | 					size_t count, loff_t *ppos) | 
 | 1063 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 1064 | 	struct iwl_priv *priv = file->private_data; | 
| Abhijeet Kolekar | 17f36fc | 2010-04-16 10:03:54 -0700 | [diff] [blame] | 1065 | 	return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file, | 
 | 1066 | 			user_buf, count, ppos); | 
| Wey-Yi Guy | e8fe59a | 2009-08-07 15:41:42 -0700 | [diff] [blame] | 1067 | } | 
 | 1068 |  | 
| Wey-Yi Guy | 5225935 | 2009-08-07 15:41:43 -0700 | [diff] [blame] | 1069 | static ssize_t iwl_dbgfs_sensitivity_read(struct file *file, | 
 | 1070 | 					char __user *user_buf, | 
 | 1071 | 					size_t count, loff_t *ppos) { | 
 | 1072 |  | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 1073 | 	struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 5225935 | 2009-08-07 15:41:43 -0700 | [diff] [blame] | 1074 | 	int pos = 0; | 
 | 1075 | 	int cnt = 0; | 
 | 1076 | 	char *buf; | 
 | 1077 | 	int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100; | 
 | 1078 | 	ssize_t ret; | 
 | 1079 | 	struct iwl_sensitivity_data *data; | 
 | 1080 |  | 
 | 1081 | 	data = &priv->sensitivity_data; | 
 | 1082 | 	buf = kzalloc(bufsz, GFP_KERNEL); | 
 | 1083 | 	if (!buf) { | 
 | 1084 | 		IWL_ERR(priv, "Can not allocate Buffer\n"); | 
 | 1085 | 		return -ENOMEM; | 
 | 1086 | 	} | 
 | 1087 |  | 
 | 1088 | 	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n", | 
 | 1089 | 			data->auto_corr_ofdm); | 
 | 1090 | 	pos += scnprintf(buf + pos, bufsz - pos, | 
 | 1091 | 			"auto_corr_ofdm_mrc:\t\t %u\n", | 
 | 1092 | 			data->auto_corr_ofdm_mrc); | 
 | 1093 | 	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n", | 
 | 1094 | 			data->auto_corr_ofdm_x1); | 
 | 1095 | 	pos += scnprintf(buf + pos, bufsz - pos, | 
 | 1096 | 			"auto_corr_ofdm_mrc_x1:\t\t %u\n", | 
 | 1097 | 			data->auto_corr_ofdm_mrc_x1); | 
 | 1098 | 	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n", | 
 | 1099 | 			data->auto_corr_cck); | 
 | 1100 | 	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n", | 
 | 1101 | 			data->auto_corr_cck_mrc); | 
 | 1102 | 	pos += scnprintf(buf + pos, bufsz - pos, | 
 | 1103 | 			"last_bad_plcp_cnt_ofdm:\t\t %u\n", | 
 | 1104 | 			data->last_bad_plcp_cnt_ofdm); | 
 | 1105 | 	pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n", | 
 | 1106 | 			data->last_fa_cnt_ofdm); | 
 | 1107 | 	pos += scnprintf(buf + pos, bufsz - pos, | 
 | 1108 | 			"last_bad_plcp_cnt_cck:\t\t %u\n", | 
 | 1109 | 			data->last_bad_plcp_cnt_cck); | 
 | 1110 | 	pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n", | 
 | 1111 | 			data->last_fa_cnt_cck); | 
 | 1112 | 	pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n", | 
 | 1113 | 			data->nrg_curr_state); | 
 | 1114 | 	pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n", | 
 | 1115 | 			data->nrg_prev_state); | 
 | 1116 | 	pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t"); | 
 | 1117 | 	for (cnt = 0; cnt < 10; cnt++) { | 
 | 1118 | 		pos += scnprintf(buf + pos, bufsz - pos, " %u", | 
 | 1119 | 				data->nrg_value[cnt]); | 
 | 1120 | 	} | 
 | 1121 | 	pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
 | 1122 | 	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t"); | 
 | 1123 | 	for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) { | 
 | 1124 | 		pos += scnprintf(buf + pos, bufsz - pos, " %u", | 
 | 1125 | 				data->nrg_silence_rssi[cnt]); | 
 | 1126 | 	} | 
 | 1127 | 	pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
 | 1128 | 	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n", | 
 | 1129 | 			data->nrg_silence_ref); | 
 | 1130 | 	pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n", | 
 | 1131 | 			data->nrg_energy_idx); | 
 | 1132 | 	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n", | 
 | 1133 | 			data->nrg_silence_idx); | 
 | 1134 | 	pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n", | 
 | 1135 | 			data->nrg_th_cck); | 
 | 1136 | 	pos += scnprintf(buf + pos, bufsz - pos, | 
 | 1137 | 			"nrg_auto_corr_silence_diff:\t %u\n", | 
 | 1138 | 			data->nrg_auto_corr_silence_diff); | 
 | 1139 | 	pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n", | 
 | 1140 | 			data->num_in_cck_no_fa); | 
 | 1141 | 	pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n", | 
 | 1142 | 			data->nrg_th_ofdm); | 
 | 1143 |  | 
 | 1144 | 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 1145 | 	kfree(buf); | 
 | 1146 | 	return ret; | 
 | 1147 | } | 
 | 1148 |  | 
 | 1149 |  | 
 | 1150 | static ssize_t iwl_dbgfs_chain_noise_read(struct file *file, | 
 | 1151 | 					char __user *user_buf, | 
 | 1152 | 					size_t count, loff_t *ppos) { | 
 | 1153 |  | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 1154 | 	struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 5225935 | 2009-08-07 15:41:43 -0700 | [diff] [blame] | 1155 | 	int pos = 0; | 
 | 1156 | 	int cnt = 0; | 
 | 1157 | 	char *buf; | 
 | 1158 | 	int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100; | 
 | 1159 | 	ssize_t ret; | 
 | 1160 | 	struct iwl_chain_noise_data *data; | 
 | 1161 |  | 
 | 1162 | 	data = &priv->chain_noise_data; | 
 | 1163 | 	buf = kzalloc(bufsz, GFP_KERNEL); | 
 | 1164 | 	if (!buf) { | 
 | 1165 | 		IWL_ERR(priv, "Can not allocate Buffer\n"); | 
 | 1166 | 		return -ENOMEM; | 
 | 1167 | 	} | 
 | 1168 |  | 
 | 1169 | 	pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n", | 
 | 1170 | 			data->active_chains); | 
 | 1171 | 	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n", | 
 | 1172 | 			data->chain_noise_a); | 
 | 1173 | 	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n", | 
 | 1174 | 			data->chain_noise_b); | 
 | 1175 | 	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n", | 
 | 1176 | 			data->chain_noise_c); | 
 | 1177 | 	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n", | 
 | 1178 | 			data->chain_signal_a); | 
 | 1179 | 	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n", | 
 | 1180 | 			data->chain_signal_b); | 
 | 1181 | 	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n", | 
 | 1182 | 			data->chain_signal_c); | 
 | 1183 | 	pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n", | 
 | 1184 | 			data->beacon_count); | 
 | 1185 |  | 
 | 1186 | 	pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t"); | 
 | 1187 | 	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { | 
 | 1188 | 		pos += scnprintf(buf + pos, bufsz - pos, " %u", | 
 | 1189 | 				data->disconn_array[cnt]); | 
 | 1190 | 	} | 
 | 1191 | 	pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
 | 1192 | 	pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t"); | 
 | 1193 | 	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { | 
 | 1194 | 		pos += scnprintf(buf + pos, bufsz - pos, " %u", | 
 | 1195 | 				data->delta_gain_code[cnt]); | 
 | 1196 | 	} | 
 | 1197 | 	pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
 | 1198 | 	pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n", | 
 | 1199 | 			data->radio_write); | 
 | 1200 | 	pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n", | 
 | 1201 | 			data->state); | 
 | 1202 |  | 
 | 1203 | 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 1204 | 	kfree(buf); | 
 | 1205 | 	return ret; | 
 | 1206 | } | 
 | 1207 |  | 
| Wey-Yi Guy | c09430a | 2009-10-16 14:25:50 -0700 | [diff] [blame] | 1208 | static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, | 
 | 1209 | 						    char __user *user_buf, | 
 | 1210 | 						    size_t count, loff_t *ppos) | 
 | 1211 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 1212 | 	struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | c09430a | 2009-10-16 14:25:50 -0700 | [diff] [blame] | 1213 | 	char buf[60]; | 
 | 1214 | 	int pos = 0; | 
 | 1215 | 	const size_t bufsz = sizeof(buf); | 
 | 1216 | 	u32 pwrsave_status; | 
 | 1217 |  | 
 | 1218 | 	pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) & | 
 | 1219 | 			CSR_GP_REG_POWER_SAVE_STATUS_MSK; | 
 | 1220 |  | 
 | 1221 | 	pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); | 
 | 1222 | 	pos += scnprintf(buf + pos, bufsz - pos, "%s\n", | 
 | 1223 | 		(pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" : | 
 | 1224 | 		(pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" : | 
 | 1225 | 		(pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" : | 
 | 1226 | 		"error"); | 
 | 1227 |  | 
 | 1228 | 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 1229 | } | 
 | 1230 |  | 
| Wey-Yi Guy | 7163b8a | 2009-11-20 12:04:56 -0800 | [diff] [blame] | 1231 | static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file, | 
| Wey-Yi Guy | ef8d552 | 2009-11-13 11:56:28 -0800 | [diff] [blame] | 1232 | 					 const char __user *user_buf, | 
 | 1233 | 					 size_t count, loff_t *ppos) | 
 | 1234 | { | 
 | 1235 | 	struct iwl_priv *priv = file->private_data; | 
 | 1236 | 	char buf[8]; | 
 | 1237 | 	int buf_size; | 
 | 1238 | 	int clear; | 
 | 1239 |  | 
 | 1240 | 	memset(buf, 0, sizeof(buf)); | 
 | 1241 | 	buf_size = min(count, sizeof(buf) -  1); | 
 | 1242 | 	if (copy_from_user(buf, user_buf, buf_size)) | 
 | 1243 | 		return -EFAULT; | 
 | 1244 | 	if (sscanf(buf, "%d", &clear) != 1) | 
 | 1245 | 		return -EFAULT; | 
 | 1246 |  | 
 | 1247 | 	/* make request to uCode to retrieve statistics information */ | 
 | 1248 | 	mutex_lock(&priv->mutex); | 
 | 1249 | 	iwl_send_statistics_request(priv, CMD_SYNC, true); | 
 | 1250 | 	mutex_unlock(&priv->mutex); | 
 | 1251 |  | 
 | 1252 | 	return count; | 
 | 1253 | } | 
 | 1254 |  | 
| Wey-Yi Guy | 696bdee | 2009-12-10 14:37:25 -0800 | [diff] [blame] | 1255 | static ssize_t iwl_dbgfs_csr_write(struct file *file, | 
 | 1256 | 					 const char __user *user_buf, | 
 | 1257 | 					 size_t count, loff_t *ppos) | 
 | 1258 | { | 
 | 1259 | 	struct iwl_priv *priv = file->private_data; | 
 | 1260 | 	char buf[8]; | 
 | 1261 | 	int buf_size; | 
 | 1262 | 	int csr; | 
 | 1263 |  | 
 | 1264 | 	memset(buf, 0, sizeof(buf)); | 
 | 1265 | 	buf_size = min(count, sizeof(buf) -  1); | 
 | 1266 | 	if (copy_from_user(buf, user_buf, buf_size)) | 
 | 1267 | 		return -EFAULT; | 
 | 1268 | 	if (sscanf(buf, "%d", &csr) != 1) | 
 | 1269 | 		return -EFAULT; | 
 | 1270 |  | 
 | 1271 | 	if (priv->cfg->ops->lib->dump_csr) | 
 | 1272 | 		priv->cfg->ops->lib->dump_csr(priv); | 
 | 1273 |  | 
 | 1274 | 	return count; | 
 | 1275 | } | 
 | 1276 |  | 
| Wey-Yi Guy | a9e1cb6 | 2009-12-10 14:37:26 -0800 | [diff] [blame] | 1277 | static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, | 
 | 1278 | 					char __user *user_buf, | 
 | 1279 | 					size_t count, loff_t *ppos) { | 
 | 1280 |  | 
| Joe Perches | 5767430 | 2010-07-12 13:50:06 -0700 | [diff] [blame] | 1281 | 	struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | a9e1cb6 | 2009-12-10 14:37:26 -0800 | [diff] [blame] | 1282 | 	int pos = 0; | 
 | 1283 | 	char buf[128]; | 
 | 1284 | 	const size_t bufsz = sizeof(buf); | 
| Wey-Yi Guy | a9e1cb6 | 2009-12-10 14:37:26 -0800 | [diff] [blame] | 1285 |  | 
 | 1286 | 	pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n", | 
 | 1287 | 			priv->event_log.ucode_trace ? "On" : "Off"); | 
 | 1288 | 	pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n", | 
 | 1289 | 			priv->event_log.non_wraps_count); | 
 | 1290 | 	pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n", | 
 | 1291 | 			priv->event_log.wraps_once_count); | 
 | 1292 | 	pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n", | 
 | 1293 | 			priv->event_log.wraps_more_count); | 
 | 1294 |  | 
| Wey-Yi Guy | 4967c31 | 2010-02-18 15:22:07 -0800 | [diff] [blame] | 1295 | 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
| Wey-Yi Guy | a9e1cb6 | 2009-12-10 14:37:26 -0800 | [diff] [blame] | 1296 | } | 
 | 1297 |  | 
 | 1298 | static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, | 
 | 1299 | 					 const char __user *user_buf, | 
 | 1300 | 					 size_t count, loff_t *ppos) | 
 | 1301 | { | 
 | 1302 | 	struct iwl_priv *priv = file->private_data; | 
 | 1303 | 	char buf[8]; | 
 | 1304 | 	int buf_size; | 
 | 1305 | 	int trace; | 
 | 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", &trace) != 1) | 
 | 1312 | 		return -EFAULT; | 
 | 1313 |  | 
 | 1314 | 	if (trace) { | 
 | 1315 | 		priv->event_log.ucode_trace = true; | 
 | 1316 | 		/* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */ | 
 | 1317 | 		mod_timer(&priv->ucode_trace, | 
 | 1318 | 			jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD)); | 
 | 1319 | 	} else { | 
 | 1320 | 		priv->event_log.ucode_trace = false; | 
 | 1321 | 		del_timer_sync(&priv->ucode_trace); | 
 | 1322 | 	} | 
 | 1323 |  | 
 | 1324 | 	return count; | 
 | 1325 | } | 
 | 1326 |  | 
| Johannes Berg | 6098720 | 2010-02-18 00:36:07 -0800 | [diff] [blame] | 1327 | static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file, | 
 | 1328 | 					 char __user *user_buf, | 
 | 1329 | 					 size_t count, loff_t *ppos) { | 
 | 1330 |  | 
| Joe Perches | 5767430 | 2010-07-12 13:50:06 -0700 | [diff] [blame] | 1331 | 	struct iwl_priv *priv = file->private_data; | 
| Johannes Berg | 6098720 | 2010-02-18 00:36:07 -0800 | [diff] [blame] | 1332 | 	int len = 0; | 
 | 1333 | 	char buf[20]; | 
 | 1334 |  | 
| Johannes Berg | 246ed35 | 2010-08-23 10:46:32 +0200 | [diff] [blame] | 1335 | 	len = sprintf(buf, "0x%04X\n", | 
 | 1336 | 		le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.flags)); | 
| Johannes Berg | 6098720 | 2010-02-18 00:36:07 -0800 | [diff] [blame] | 1337 | 	return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 
 | 1338 | } | 
 | 1339 |  | 
 | 1340 | static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file, | 
 | 1341 | 						char __user *user_buf, | 
 | 1342 | 						size_t count, loff_t *ppos) { | 
 | 1343 |  | 
| Joe Perches | 5767430 | 2010-07-12 13:50:06 -0700 | [diff] [blame] | 1344 | 	struct iwl_priv *priv = file->private_data; | 
| Johannes Berg | 6098720 | 2010-02-18 00:36:07 -0800 | [diff] [blame] | 1345 | 	int len = 0; | 
 | 1346 | 	char buf[20]; | 
 | 1347 |  | 
 | 1348 | 	len = sprintf(buf, "0x%04X\n", | 
| Johannes Berg | 246ed35 | 2010-08-23 10:46:32 +0200 | [diff] [blame] | 1349 | 		le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags)); | 
| Johannes Berg | 6098720 | 2010-02-18 00:36:07 -0800 | [diff] [blame] | 1350 | 	return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 
 | 1351 | } | 
 | 1352 |  | 
| Wey-Yi Guy | 1b3eb82 | 2010-01-15 13:43:39 -0800 | [diff] [blame] | 1353 | static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, | 
 | 1354 | 					 char __user *user_buf, | 
 | 1355 | 					 size_t count, loff_t *ppos) | 
 | 1356 | { | 
| Joe Perches | 5767430 | 2010-07-12 13:50:06 -0700 | [diff] [blame] | 1357 | 	struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 1b3eb82 | 2010-01-15 13:43:39 -0800 | [diff] [blame] | 1358 | 	char *buf; | 
 | 1359 | 	int pos = 0; | 
 | 1360 | 	ssize_t ret = -EFAULT; | 
 | 1361 |  | 
 | 1362 | 	if (priv->cfg->ops->lib->dump_fh) { | 
 | 1363 | 		ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true); | 
 | 1364 | 		if (buf) { | 
 | 1365 | 			ret = simple_read_from_buffer(user_buf, | 
 | 1366 | 						      count, ppos, buf, pos); | 
 | 1367 | 			kfree(buf); | 
 | 1368 | 		} | 
 | 1369 | 	} | 
 | 1370 |  | 
 | 1371 | 	return ret; | 
 | 1372 | } | 
 | 1373 |  | 
| Wey-Yi Guy | a13d276 | 2010-01-22 14:22:42 -0800 | [diff] [blame] | 1374 | static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file, | 
 | 1375 | 					char __user *user_buf, | 
 | 1376 | 					size_t count, loff_t *ppos) { | 
 | 1377 |  | 
 | 1378 | 	struct iwl_priv *priv = file->private_data; | 
 | 1379 | 	int pos = 0; | 
 | 1380 | 	char buf[12]; | 
 | 1381 | 	const size_t bufsz = sizeof(buf); | 
| Wey-Yi Guy | a13d276 | 2010-01-22 14:22:42 -0800 | [diff] [blame] | 1382 |  | 
 | 1383 | 	pos += scnprintf(buf + pos, bufsz - pos, "%d\n", | 
 | 1384 | 			priv->missed_beacon_threshold); | 
 | 1385 |  | 
| Wey-Yi Guy | 4967c31 | 2010-02-18 15:22:07 -0800 | [diff] [blame] | 1386 | 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
| Wey-Yi Guy | a13d276 | 2010-01-22 14:22:42 -0800 | [diff] [blame] | 1387 | } | 
 | 1388 |  | 
 | 1389 | static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, | 
 | 1390 | 					 const char __user *user_buf, | 
 | 1391 | 					 size_t count, loff_t *ppos) | 
 | 1392 | { | 
 | 1393 | 	struct iwl_priv *priv = file->private_data; | 
 | 1394 | 	char buf[8]; | 
 | 1395 | 	int buf_size; | 
 | 1396 | 	int missed; | 
 | 1397 |  | 
 | 1398 | 	memset(buf, 0, sizeof(buf)); | 
 | 1399 | 	buf_size = min(count, sizeof(buf) -  1); | 
 | 1400 | 	if (copy_from_user(buf, user_buf, buf_size)) | 
 | 1401 | 		return -EFAULT; | 
 | 1402 | 	if (sscanf(buf, "%d", &missed) != 1) | 
 | 1403 | 		return -EINVAL; | 
 | 1404 |  | 
 | 1405 | 	if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN || | 
 | 1406 | 	    missed > IWL_MISSED_BEACON_THRESHOLD_MAX) | 
 | 1407 | 		priv->missed_beacon_threshold = | 
 | 1408 | 			IWL_MISSED_BEACON_THRESHOLD_DEF; | 
 | 1409 | 	else | 
 | 1410 | 		priv->missed_beacon_threshold = missed; | 
 | 1411 |  | 
 | 1412 | 	return count; | 
 | 1413 | } | 
 | 1414 |  | 
| Trieu 'Andrew' Nguyen | 3e4fb5f | 2010-01-22 14:22:46 -0800 | [diff] [blame] | 1415 | static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, | 
 | 1416 | 					char __user *user_buf, | 
 | 1417 | 					size_t count, loff_t *ppos) { | 
 | 1418 |  | 
| Joe Perches | 5767430 | 2010-07-12 13:50:06 -0700 | [diff] [blame] | 1419 | 	struct iwl_priv *priv = file->private_data; | 
| Trieu 'Andrew' Nguyen | 3e4fb5f | 2010-01-22 14:22:46 -0800 | [diff] [blame] | 1420 | 	int pos = 0; | 
 | 1421 | 	char buf[12]; | 
 | 1422 | 	const size_t bufsz = sizeof(buf); | 
| Trieu 'Andrew' Nguyen | 3e4fb5f | 2010-01-22 14:22:46 -0800 | [diff] [blame] | 1423 |  | 
 | 1424 | 	pos += scnprintf(buf + pos, bufsz - pos, "%u\n", | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1425 | 			priv->cfg->base_params->plcp_delta_threshold); | 
| Trieu 'Andrew' Nguyen | 3e4fb5f | 2010-01-22 14:22:46 -0800 | [diff] [blame] | 1426 |  | 
| Wey-Yi Guy | 4967c31 | 2010-02-18 15:22:07 -0800 | [diff] [blame] | 1427 | 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
| Trieu 'Andrew' Nguyen | 3e4fb5f | 2010-01-22 14:22:46 -0800 | [diff] [blame] | 1428 | } | 
 | 1429 |  | 
 | 1430 | static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, | 
 | 1431 | 					const char __user *user_buf, | 
 | 1432 | 					size_t count, loff_t *ppos) { | 
 | 1433 |  | 
 | 1434 | 	struct iwl_priv *priv = file->private_data; | 
 | 1435 | 	char buf[8]; | 
 | 1436 | 	int buf_size; | 
 | 1437 | 	int plcp; | 
 | 1438 |  | 
 | 1439 | 	memset(buf, 0, sizeof(buf)); | 
 | 1440 | 	buf_size = min(count, sizeof(buf) -  1); | 
 | 1441 | 	if (copy_from_user(buf, user_buf, buf_size)) | 
 | 1442 | 		return -EFAULT; | 
 | 1443 | 	if (sscanf(buf, "%d", &plcp) != 1) | 
 | 1444 | 		return -EINVAL; | 
| Wey-Yi Guy | 680788a | 2010-06-17 15:25:00 -0700 | [diff] [blame] | 1445 | 	if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) || | 
| Trieu 'Andrew' Nguyen | 3e4fb5f | 2010-01-22 14:22:46 -0800 | [diff] [blame] | 1446 | 		(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX)) | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1447 | 		priv->cfg->base_params->plcp_delta_threshold = | 
| Wey-Yi Guy | 680788a | 2010-06-17 15:25:00 -0700 | [diff] [blame] | 1448 | 			IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE; | 
| Trieu 'Andrew' Nguyen | 3e4fb5f | 2010-01-22 14:22:46 -0800 | [diff] [blame] | 1449 | 	else | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1450 | 		priv->cfg->base_params->plcp_delta_threshold = plcp; | 
| Trieu 'Andrew' Nguyen | 3e4fb5f | 2010-01-22 14:22:46 -0800 | [diff] [blame] | 1451 | 	return count; | 
 | 1452 | } | 
 | 1453 |  | 
| Wey-Yi Guy | 528c312 | 2010-02-18 22:03:07 -0800 | [diff] [blame] | 1454 | static ssize_t iwl_dbgfs_force_reset_read(struct file *file, | 
 | 1455 | 					char __user *user_buf, | 
 | 1456 | 					size_t count, loff_t *ppos) { | 
 | 1457 |  | 
 | 1458 | 	struct iwl_priv *priv = file->private_data; | 
 | 1459 | 	int i, pos = 0; | 
 | 1460 | 	char buf[300]; | 
 | 1461 | 	const size_t bufsz = sizeof(buf); | 
 | 1462 | 	struct iwl_force_reset *force_reset; | 
 | 1463 |  | 
 | 1464 | 	for (i = 0; i < IWL_MAX_FORCE_RESET; i++) { | 
 | 1465 | 		force_reset = &priv->force_reset[i]; | 
 | 1466 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 1467 | 				"Force reset method %d\n", i); | 
 | 1468 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 1469 | 				"\tnumber of reset request: %d\n", | 
 | 1470 | 				force_reset->reset_request_count); | 
 | 1471 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 1472 | 				"\tnumber of reset request success: %d\n", | 
 | 1473 | 				force_reset->reset_success_count); | 
 | 1474 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 1475 | 				"\tnumber of reset request reject: %d\n", | 
 | 1476 | 				force_reset->reset_reject_count); | 
 | 1477 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 1478 | 				"\treset duration: %lu\n", | 
 | 1479 | 				force_reset->reset_duration); | 
 | 1480 | 	} | 
 | 1481 | 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 1482 | } | 
 | 1483 |  | 
| Wey-Yi Guy | 04cafd7 | 2010-02-03 11:47:20 -0800 | [diff] [blame] | 1484 | static ssize_t iwl_dbgfs_force_reset_write(struct file *file, | 
 | 1485 | 					const char __user *user_buf, | 
 | 1486 | 					size_t count, loff_t *ppos) { | 
 | 1487 |  | 
 | 1488 | 	struct iwl_priv *priv = file->private_data; | 
 | 1489 | 	char buf[8]; | 
 | 1490 | 	int buf_size; | 
 | 1491 | 	int reset, ret; | 
 | 1492 |  | 
 | 1493 | 	memset(buf, 0, sizeof(buf)); | 
 | 1494 | 	buf_size = min(count, sizeof(buf) -  1); | 
 | 1495 | 	if (copy_from_user(buf, user_buf, buf_size)) | 
 | 1496 | 		return -EFAULT; | 
 | 1497 | 	if (sscanf(buf, "%d", &reset) != 1) | 
 | 1498 | 		return -EINVAL; | 
 | 1499 | 	switch (reset) { | 
 | 1500 | 	case IWL_RF_RESET: | 
 | 1501 | 	case IWL_FW_RESET: | 
| Wey-Yi Guy | c04f9f2 | 2010-06-21 16:52:55 -0700 | [diff] [blame] | 1502 | 		ret = iwl_force_reset(priv, reset, true); | 
| Wey-Yi Guy | 04cafd7 | 2010-02-03 11:47:20 -0800 | [diff] [blame] | 1503 | 		break; | 
 | 1504 | 	default: | 
 | 1505 | 		return -EINVAL; | 
 | 1506 | 	} | 
 | 1507 | 	return ret ? ret : count; | 
 | 1508 | } | 
 | 1509 |  | 
| Wey-Yi Guy | 4bf49a9 | 2010-06-24 13:18:36 -0700 | [diff] [blame] | 1510 | static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file, | 
 | 1511 | 					const char __user *user_buf, | 
 | 1512 | 					size_t count, loff_t *ppos) { | 
 | 1513 |  | 
 | 1514 | 	struct iwl_priv *priv = file->private_data; | 
 | 1515 | 	char buf[8]; | 
 | 1516 | 	int buf_size; | 
 | 1517 | 	int flush; | 
 | 1518 |  | 
 | 1519 | 	memset(buf, 0, sizeof(buf)); | 
 | 1520 | 	buf_size = min(count, sizeof(buf) -  1); | 
 | 1521 | 	if (copy_from_user(buf, user_buf, buf_size)) | 
 | 1522 | 		return -EFAULT; | 
 | 1523 | 	if (sscanf(buf, "%d", &flush) != 1) | 
 | 1524 | 		return -EINVAL; | 
 | 1525 |  | 
 | 1526 | 	if (iwl_is_rfkill(priv)) | 
 | 1527 | 		return -EFAULT; | 
 | 1528 |  | 
 | 1529 | 	priv->cfg->ops->lib->dev_txfifo_flush(priv, IWL_DROP_ALL); | 
 | 1530 |  | 
 | 1531 | 	return count; | 
 | 1532 | } | 
 | 1533 |  | 
| Wey-Yi Guy | ffb7d89 | 2010-07-14 08:09:55 -0700 | [diff] [blame] | 1534 | static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, | 
 | 1535 | 					char __user *user_buf, | 
 | 1536 | 					size_t count, loff_t *ppos) | 
 | 1537 | { | 
 | 1538 | 	struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 
 | 1539 |  | 
 | 1540 | 	return priv->cfg->ops->lib->debugfs_ops.bt_stats_read(file, | 
 | 1541 | 			user_buf, count, ppos); | 
 | 1542 | } | 
 | 1543 |  | 
| Stanislaw Gruszka | 22de94d | 2010-12-03 15:41:48 +0100 | [diff] [blame] | 1544 | static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file, | 
| Wey-Yi Guy | 7bdc473 | 2010-08-23 07:57:07 -0700 | [diff] [blame] | 1545 | 					const char __user *user_buf, | 
 | 1546 | 					size_t count, loff_t *ppos) { | 
 | 1547 |  | 
 | 1548 | 	struct iwl_priv *priv = file->private_data; | 
 | 1549 | 	char buf[8]; | 
 | 1550 | 	int buf_size; | 
| Stanislaw Gruszka | 22de94d | 2010-12-03 15:41:48 +0100 | [diff] [blame] | 1551 | 	int timeout; | 
| Wey-Yi Guy | 7bdc473 | 2010-08-23 07:57:07 -0700 | [diff] [blame] | 1552 |  | 
 | 1553 | 	memset(buf, 0, sizeof(buf)); | 
 | 1554 | 	buf_size = min(count, sizeof(buf) -  1); | 
 | 1555 | 	if (copy_from_user(buf, user_buf, buf_size)) | 
 | 1556 | 		return -EFAULT; | 
| Stanislaw Gruszka | 22de94d | 2010-12-03 15:41:48 +0100 | [diff] [blame] | 1557 | 	if (sscanf(buf, "%d", &timeout) != 1) | 
| Wey-Yi Guy | 7bdc473 | 2010-08-23 07:57:07 -0700 | [diff] [blame] | 1558 | 		return -EINVAL; | 
| Stanislaw Gruszka | 22de94d | 2010-12-03 15:41:48 +0100 | [diff] [blame] | 1559 | 	if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT) | 
 | 1560 | 		timeout = IWL_DEF_WD_TIMEOUT; | 
| Wey-Yi Guy | 7bdc473 | 2010-08-23 07:57:07 -0700 | [diff] [blame] | 1561 |  | 
| Stanislaw Gruszka | 22de94d | 2010-12-03 15:41:48 +0100 | [diff] [blame] | 1562 | 	priv->cfg->base_params->wd_timeout = timeout; | 
 | 1563 | 	iwl_setup_watchdog(priv); | 
| Wey-Yi Guy | 7bdc473 | 2010-08-23 07:57:07 -0700 | [diff] [blame] | 1564 | 	return count; | 
 | 1565 | } | 
 | 1566 |  | 
| Wey-Yi Guy | befe8c4 | 2010-08-23 07:57:16 -0700 | [diff] [blame] | 1567 | static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file, | 
 | 1568 | 					char __user *user_buf, | 
 | 1569 | 					size_t count, loff_t *ppos) { | 
 | 1570 |  | 
 | 1571 | 	struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 
 | 1572 | 	int pos = 0; | 
 | 1573 | 	char buf[200]; | 
 | 1574 | 	const size_t bufsz = sizeof(buf); | 
 | 1575 | 	ssize_t ret; | 
 | 1576 |  | 
| Wey-Yi Guy | f21dd00 | 2010-12-08 15:34:52 -0800 | [diff] [blame] | 1577 | 	if (!priv->bt_enable_flag) { | 
 | 1578 | 		pos += scnprintf(buf + pos, bufsz - pos, "BT coex disabled\n"); | 
 | 1579 | 		ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 1580 | 		return ret; | 
 | 1581 | 	} | 
 | 1582 | 	pos += scnprintf(buf + pos, bufsz - pos, "BT enable flag: 0x%x\n", | 
 | 1583 | 		priv->bt_enable_flag); | 
| Wey-Yi Guy | befe8c4 | 2010-08-23 07:57:16 -0700 | [diff] [blame] | 1584 | 	pos += scnprintf(buf + pos, bufsz - pos, "BT in %s mode\n", | 
 | 1585 | 		priv->bt_full_concurrent ? "full concurrency" : "3-wire"); | 
 | 1586 | 	pos += scnprintf(buf + pos, bufsz - pos, "BT status: %s, " | 
 | 1587 | 			 "last traffic notif: %d\n", | 
| Wey-Yi Guy | 66e863a5 | 2010-11-08 14:54:37 -0800 | [diff] [blame] | 1588 | 		priv->bt_status ? "On" : "Off", priv->last_bt_traffic_load); | 
| Wey-Yi Guy | befe8c4 | 2010-08-23 07:57:16 -0700 | [diff] [blame] | 1589 | 	pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, " | 
 | 1590 | 			 "sco_active: %d, kill_ack_mask: %x, " | 
 | 1591 | 			 "kill_cts_mask: %x\n", | 
 | 1592 | 		priv->bt_ch_announce, priv->bt_sco_active, | 
 | 1593 | 		priv->kill_ack_mask, priv->kill_cts_mask); | 
 | 1594 |  | 
 | 1595 | 	pos += scnprintf(buf + pos, bufsz - pos, "bluetooth traffic load: "); | 
 | 1596 | 	switch (priv->bt_traffic_load) { | 
 | 1597 | 	case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | 
 | 1598 | 		pos += scnprintf(buf + pos, bufsz - pos, "Continuous\n"); | 
 | 1599 | 		break; | 
 | 1600 | 	case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: | 
 | 1601 | 		pos += scnprintf(buf + pos, bufsz - pos, "High\n"); | 
 | 1602 | 		break; | 
 | 1603 | 	case IWL_BT_COEX_TRAFFIC_LOAD_LOW: | 
 | 1604 | 		pos += scnprintf(buf + pos, bufsz - pos, "Low\n"); | 
 | 1605 | 		break; | 
 | 1606 | 	case IWL_BT_COEX_TRAFFIC_LOAD_NONE: | 
 | 1607 | 	default: | 
 | 1608 | 		pos += scnprintf(buf + pos, bufsz - pos, "None\n"); | 
 | 1609 | 		break; | 
 | 1610 | 	} | 
 | 1611 |  | 
 | 1612 | 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 1613 | 	return ret; | 
 | 1614 | } | 
 | 1615 |  | 
| Wey-Yi Guy | c6abdc0 | 2010-09-01 17:10:51 -0700 | [diff] [blame] | 1616 | static ssize_t iwl_dbgfs_protection_mode_read(struct file *file, | 
 | 1617 | 					char __user *user_buf, | 
 | 1618 | 					size_t count, loff_t *ppos) | 
 | 1619 | { | 
 | 1620 | 	struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 
 | 1621 |  | 
 | 1622 | 	int pos = 0; | 
 | 1623 | 	char buf[40]; | 
 | 1624 | 	const size_t bufsz = sizeof(buf); | 
 | 1625 |  | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1626 | 	if (priv->cfg->ht_params) | 
 | 1627 | 		pos += scnprintf(buf + pos, bufsz - pos, | 
 | 1628 | 			 "use %s for aggregation\n", | 
 | 1629 | 			 (priv->cfg->ht_params->use_rts_for_aggregation) ? | 
 | 1630 | 				"rts/cts" : "cts-to-self"); | 
 | 1631 | 	else | 
 | 1632 | 		pos += scnprintf(buf + pos, bufsz - pos, "N/A"); | 
 | 1633 |  | 
| Wey-Yi Guy | c6abdc0 | 2010-09-01 17:10:51 -0700 | [diff] [blame] | 1634 | 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
 | 1635 | } | 
 | 1636 |  | 
 | 1637 | static ssize_t iwl_dbgfs_protection_mode_write(struct file *file, | 
 | 1638 | 					const char __user *user_buf, | 
 | 1639 | 					size_t count, loff_t *ppos) { | 
 | 1640 |  | 
 | 1641 | 	struct iwl_priv *priv = file->private_data; | 
 | 1642 | 	char buf[8]; | 
 | 1643 | 	int buf_size; | 
 | 1644 | 	int rts; | 
 | 1645 |  | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1646 | 	if (!priv->cfg->ht_params) | 
 | 1647 | 		return -EINVAL; | 
 | 1648 |  | 
| Wey-Yi Guy | c6abdc0 | 2010-09-01 17:10:51 -0700 | [diff] [blame] | 1649 | 	memset(buf, 0, sizeof(buf)); | 
 | 1650 | 	buf_size = min(count, sizeof(buf) -  1); | 
 | 1651 | 	if (copy_from_user(buf, user_buf, buf_size)) | 
 | 1652 | 		return -EFAULT; | 
 | 1653 | 	if (sscanf(buf, "%d", &rts) != 1) | 
 | 1654 | 		return -EINVAL; | 
 | 1655 | 	if (rts) | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1656 | 		priv->cfg->ht_params->use_rts_for_aggregation = true; | 
| Wey-Yi Guy | c6abdc0 | 2010-09-01 17:10:51 -0700 | [diff] [blame] | 1657 | 	else | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1658 | 		priv->cfg->ht_params->use_rts_for_aggregation = false; | 
| Wey-Yi Guy | c6abdc0 | 2010-09-01 17:10:51 -0700 | [diff] [blame] | 1659 | 	return count; | 
 | 1660 | } | 
 | 1661 |  | 
| Wey-Yi Guy | 54a9aa6 | 2010-09-05 10:49:42 -0700 | [diff] [blame] | 1662 | static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file, | 
 | 1663 | 					char __user *user_buf, | 
 | 1664 | 					size_t count, loff_t *ppos) | 
 | 1665 | { | 
 | 1666 | 	struct iwl_priv *priv = file->private_data; | 
 | 1667 |  | 
 | 1668 | 	if (priv->cfg->ops->lib->debugfs_ops.reply_tx_error) | 
 | 1669 | 		return priv->cfg->ops->lib->debugfs_ops.reply_tx_error( | 
 | 1670 | 			file, user_buf, count, ppos); | 
 | 1671 | 	else | 
 | 1672 | 		return -ENODATA; | 
 | 1673 | } | 
| Wey-Yi Guy | 7163b8a | 2009-11-20 12:04:56 -0800 | [diff] [blame] | 1674 | DEBUGFS_READ_FILE_OPS(rx_statistics); | 
 | 1675 | DEBUGFS_READ_FILE_OPS(tx_statistics); | 
| Wey-Yi Guy | 20594eb | 2009-08-07 15:41:39 -0700 | [diff] [blame] | 1676 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | 
| Wey-Yi Guy | 141b03e | 2009-08-07 15:41:41 -0700 | [diff] [blame] | 1677 | DEBUGFS_READ_FILE_OPS(rx_queue); | 
 | 1678 | DEBUGFS_READ_FILE_OPS(tx_queue); | 
| Wey-Yi Guy | e8fe59a | 2009-08-07 15:41:42 -0700 | [diff] [blame] | 1679 | DEBUGFS_READ_FILE_OPS(ucode_rx_stats); | 
 | 1680 | DEBUGFS_READ_FILE_OPS(ucode_tx_stats); | 
 | 1681 | DEBUGFS_READ_FILE_OPS(ucode_general_stats); | 
| Wey-Yi Guy | 5225935 | 2009-08-07 15:41:43 -0700 | [diff] [blame] | 1682 | DEBUGFS_READ_FILE_OPS(sensitivity); | 
 | 1683 | DEBUGFS_READ_FILE_OPS(chain_noise); | 
| Wey-Yi Guy | c09430a | 2009-10-16 14:25:50 -0700 | [diff] [blame] | 1684 | DEBUGFS_READ_FILE_OPS(power_save_status); | 
| Wey-Yi Guy | 7163b8a | 2009-11-20 12:04:56 -0800 | [diff] [blame] | 1685 | DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); | 
 | 1686 | DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); | 
| Wey-Yi Guy | 696bdee | 2009-12-10 14:37:25 -0800 | [diff] [blame] | 1687 | DEBUGFS_WRITE_FILE_OPS(csr); | 
| Wey-Yi Guy | a9e1cb6 | 2009-12-10 14:37:26 -0800 | [diff] [blame] | 1688 | DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); | 
| Wey-Yi Guy | 1b3eb82 | 2010-01-15 13:43:39 -0800 | [diff] [blame] | 1689 | DEBUGFS_READ_FILE_OPS(fh_reg); | 
| Wey-Yi Guy | a13d276 | 2010-01-22 14:22:42 -0800 | [diff] [blame] | 1690 | DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); | 
| Trieu 'Andrew' Nguyen | 3e4fb5f | 2010-01-22 14:22:46 -0800 | [diff] [blame] | 1691 | DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); | 
| Wey-Yi Guy | 528c312 | 2010-02-18 22:03:07 -0800 | [diff] [blame] | 1692 | DEBUGFS_READ_WRITE_FILE_OPS(force_reset); | 
| Johannes Berg | 6098720 | 2010-02-18 00:36:07 -0800 | [diff] [blame] | 1693 | DEBUGFS_READ_FILE_OPS(rxon_flags); | 
 | 1694 | DEBUGFS_READ_FILE_OPS(rxon_filter_flags); | 
| Wey-Yi Guy | 4bf49a9 | 2010-06-24 13:18:36 -0700 | [diff] [blame] | 1695 | DEBUGFS_WRITE_FILE_OPS(txfifo_flush); | 
| Wey-Yi Guy | ffb7d89 | 2010-07-14 08:09:55 -0700 | [diff] [blame] | 1696 | DEBUGFS_READ_FILE_OPS(ucode_bt_stats); | 
| Stanislaw Gruszka | 22de94d | 2010-12-03 15:41:48 +0100 | [diff] [blame] | 1697 | DEBUGFS_WRITE_FILE_OPS(wd_timeout); | 
| Wey-Yi Guy | befe8c4 | 2010-08-23 07:57:16 -0700 | [diff] [blame] | 1698 | DEBUGFS_READ_FILE_OPS(bt_traffic); | 
| Wey-Yi Guy | c6abdc0 | 2010-09-01 17:10:51 -0700 | [diff] [blame] | 1699 | DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); | 
| Wey-Yi Guy | 54a9aa6 | 2010-09-05 10:49:42 -0700 | [diff] [blame] | 1700 | DEBUGFS_READ_FILE_OPS(reply_tx_error); | 
| Wey-Yi Guy | 20594eb | 2009-08-07 15:41:39 -0700 | [diff] [blame] | 1701 |  | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1702 | /* | 
 | 1703 |  * Create the debugfs files and directories | 
 | 1704 |  * | 
 | 1705 |  */ | 
 | 1706 | int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | 
 | 1707 | { | 
| Zhu Yi | 95b1a82 | 2008-05-29 16:34:50 +0800 | [diff] [blame] | 1708 | 	struct dentry *phyd = priv->hw->wiphy->debugfsdir; | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1709 | 	struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1710 |  | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1711 | 	dir_drv = debugfs_create_dir(name, phyd); | 
 | 1712 | 	if (!dir_drv) | 
 | 1713 | 		return -ENOMEM; | 
 | 1714 |  | 
 | 1715 | 	priv->debugfs_dir = dir_drv; | 
 | 1716 |  | 
 | 1717 | 	dir_data = debugfs_create_dir("data", dir_drv); | 
 | 1718 | 	if (!dir_data) | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1719 | 		goto err; | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1720 | 	dir_rf = debugfs_create_dir("rf", dir_drv); | 
 | 1721 | 	if (!dir_rf) | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1722 | 		goto err; | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1723 | 	dir_debug = debugfs_create_dir("debug", dir_drv); | 
 | 1724 | 	if (!dir_debug) | 
 | 1725 | 		goto err; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1726 |  | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1727 | 	DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); | 
 | 1728 | 	DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); | 
 | 1729 | 	DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR); | 
 | 1730 | 	DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); | 
 | 1731 | 	DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); | 
 | 1732 | 	DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); | 
 | 1733 | 	DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); | 
 | 1734 | 	DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1735 | 	if (!priv->cfg->base_params->broken_powersave) { | 
| Wey-Yi Guy | 381733c | 2010-04-25 09:39:46 -0700 | [diff] [blame] | 1736 | 		DEBUGFS_ADD_FILE(sleep_level_override, dir_data, | 
 | 1737 | 				 S_IWUSR | S_IRUSR); | 
 | 1738 | 		DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); | 
 | 1739 | 	} | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1740 | 	DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR); | 
 | 1741 | 	DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); | 
 | 1742 | 	DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); | 
 | 1743 | 	DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); | 
 | 1744 | 	DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); | 
 | 1745 | 	DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); | 
 | 1746 | 	DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1747 | 	DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); | 
 | 1748 | 	DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); | 
 | 1749 | 	DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); | 
 | 1750 | 	DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR); | 
 | 1751 | 	DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); | 
 | 1752 | 	DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1753 | 	DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); | 
| Wey-Yi Guy | 528c312 | 2010-02-18 22:03:07 -0800 | [diff] [blame] | 1754 | 	DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); | 
| Abhijeet Kolekar | b8c7626 | 2010-04-08 15:29:07 -0700 | [diff] [blame] | 1755 | 	DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); | 
 | 1756 | 	DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); | 
 | 1757 | 	DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); | 
| Wey-Yi Guy | 4bf49a9 | 2010-06-24 13:18:36 -0700 | [diff] [blame] | 1758 | 	if (priv->cfg->ops->lib->dev_txfifo_flush) | 
 | 1759 | 		DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR); | 
| Wey-Yi Guy | c6abdc0 | 2010-09-01 17:10:51 -0700 | [diff] [blame] | 1760 | 	DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR); | 
| Abhijeet Kolekar | b8c7626 | 2010-04-08 15:29:07 -0700 | [diff] [blame] | 1761 |  | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1762 | 	if (priv->cfg->base_params->sensitivity_calib_by_driver) | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1763 | 		DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1764 | 	if (priv->cfg->base_params->chain_noise_calib_by_driver) | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1765 | 		DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1766 | 	if (priv->cfg->base_params->ucode_tracing) | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1767 | 		DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1768 | 	if (priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics) | 
| Wey-Yi Guy | ffb7d89 | 2010-07-14 08:09:55 -0700 | [diff] [blame] | 1769 | 		DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); | 
| Wey-Yi Guy | 54a9aa6 | 2010-09-05 10:49:42 -0700 | [diff] [blame] | 1770 | 	DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR); | 
| Johannes Berg | 6098720 | 2010-02-18 00:36:07 -0800 | [diff] [blame] | 1771 | 	DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); | 
 | 1772 | 	DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); | 
| Stanislaw Gruszka | 22de94d | 2010-12-03 15:41:48 +0100 | [diff] [blame] | 1773 | 	DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1774 | 	if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) | 
| Wey-Yi Guy | befe8c4 | 2010-08-23 07:57:16 -0700 | [diff] [blame] | 1775 | 		DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1776 | 	if (priv->cfg->base_params->sensitivity_calib_by_driver) | 
| Wey-Yi Guy | 65d1f89 | 2010-04-25 15:41:43 -0700 | [diff] [blame] | 1777 | 		DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, | 
 | 1778 | 				 &priv->disable_sens_cal); | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1779 | 	if (priv->cfg->base_params->chain_noise_calib_by_driver) | 
| Wey-Yi Guy | 65d1f89 | 2010-04-25 15:41:43 -0700 | [diff] [blame] | 1780 | 		DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, | 
 | 1781 | 				 &priv->disable_chain_noise_cal); | 
| Wey-Yi Guy | 7cb1b08 | 2010-10-06 08:10:00 -0700 | [diff] [blame] | 1782 | 	if (priv->cfg->base_params->tx_power_by_driver) | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1783 | 		DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, | 
| Wey-Yi Guy | 030b865 | 2009-06-12 13:22:55 -0700 | [diff] [blame] | 1784 | 				&priv->disable_tx_power_cal); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1785 | 	return 0; | 
 | 1786 |  | 
 | 1787 | err: | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1788 | 	IWL_ERR(priv, "Can't create the debugfs directory\n"); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1789 | 	iwl_dbgfs_unregister(priv); | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1790 | 	return -ENOMEM; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1791 | } | 
 | 1792 | EXPORT_SYMBOL(iwl_dbgfs_register); | 
 | 1793 |  | 
 | 1794 | /** | 
 | 1795 |  * Remove the debugfs files and directories | 
 | 1796 |  * | 
 | 1797 |  */ | 
 | 1798 | void iwl_dbgfs_unregister(struct iwl_priv *priv) | 
 | 1799 | { | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1800 | 	if (!priv->debugfs_dir) | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1801 | 		return; | 
 | 1802 |  | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1803 | 	debugfs_remove_recursive(priv->debugfs_dir); | 
 | 1804 | 	priv->debugfs_dir = NULL; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1805 | } | 
 | 1806 | EXPORT_SYMBOL(iwl_dbgfs_unregister); | 
 | 1807 |  | 
 | 1808 |  | 
| Tomas Winkler | 445c2df | 2008-05-15 13:54:16 +0800 | [diff] [blame] | 1809 |  |