| 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" | 
| Wey-Yi Guy | 5225935 | 2009-08-07 15:41:43 -0700 | [diff] [blame] | 42 | #include "iwl-calib.h" | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 43 |  | 
|  | 44 | /* create and remove of files */ | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 45 | #define DEBUGFS_ADD_FILE(name, parent, mode) do {			\ | 
|  | 46 | if (!debugfs_create_file(#name, mode, parent, priv,		\ | 
|  | 47 | &iwl_dbgfs_##name##_ops))		\ | 
|  | 48 | goto err;						\ | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 49 | } while (0) | 
|  | 50 |  | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 51 | #define DEBUGFS_ADD_BOOL(name, parent, ptr) do {			\ | 
|  | 52 | struct dentry *__tmp;						\ | 
|  | 53 | __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR,		\ | 
|  | 54 | parent, ptr);			\ | 
|  | 55 | if (IS_ERR(__tmp) || !__tmp)					\ | 
|  | 56 | goto err;						\ | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 57 | } while (0) | 
|  | 58 |  | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 59 | #define DEBUGFS_ADD_X32(name, parent, ptr) do {				\ | 
|  | 60 | struct dentry *__tmp;						\ | 
|  | 61 | __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR,		\ | 
|  | 62 | parent, ptr);			\ | 
|  | 63 | if (IS_ERR(__tmp) || !__tmp)					\ | 
|  | 64 | goto err;						\ | 
| Tomas Winkler | 445c2df | 2008-05-15 13:54:16 +0800 | [diff] [blame] | 65 | } while (0) | 
|  | 66 |  | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 67 | /* file operation */ | 
|  | 68 | #define DEBUGFS_READ_FUNC(name)                                         \ | 
|  | 69 | static ssize_t iwl_dbgfs_##name##_read(struct file *file,               \ | 
|  | 70 | char __user *user_buf,          \ | 
|  | 71 | size_t count, loff_t *ppos); | 
|  | 72 |  | 
|  | 73 | #define DEBUGFS_WRITE_FUNC(name)                                        \ | 
|  | 74 | static ssize_t iwl_dbgfs_##name##_write(struct file *file,              \ | 
|  | 75 | const char __user *user_buf,    \ | 
|  | 76 | size_t count, loff_t *ppos); | 
|  | 77 |  | 
|  | 78 |  | 
|  | 79 | static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) | 
|  | 80 | { | 
|  | 81 | file->private_data = inode->i_private; | 
|  | 82 | return 0; | 
|  | 83 | } | 
|  | 84 |  | 
|  | 85 | #define DEBUGFS_READ_FILE_OPS(name)                                     \ | 
|  | 86 | DEBUGFS_READ_FUNC(name);                                        \ | 
|  | 87 | static const struct file_operations iwl_dbgfs_##name##_ops = {          \ | 
|  | 88 | .read = iwl_dbgfs_##name##_read,                       		\ | 
|  | 89 | .open = iwl_dbgfs_open_file_generic,                    	\ | 
|  | 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,                    	\ | 
|  | 97 | }; | 
|  | 98 |  | 
|  | 99 |  | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 100 | #define DEBUGFS_READ_WRITE_FILE_OPS(name)                               \ | 
|  | 101 | DEBUGFS_READ_FUNC(name);                                        \ | 
|  | 102 | DEBUGFS_WRITE_FUNC(name);                                       \ | 
|  | 103 | static const struct file_operations iwl_dbgfs_##name##_ops = {          \ | 
|  | 104 | .write = iwl_dbgfs_##name##_write,                              \ | 
|  | 105 | .read = iwl_dbgfs_##name##_read,                                \ | 
|  | 106 | .open = iwl_dbgfs_open_file_generic,                            \ | 
|  | 107 | }; | 
|  | 108 |  | 
| Abhijeet Kolekar | b8c7626 | 2010-04-08 15:29:07 -0700 | [diff] [blame] | 109 | int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) | 
|  | 110 | { | 
|  | 111 | int p = 0; | 
|  | 112 |  | 
|  | 113 | p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", | 
|  | 114 | le32_to_cpu(priv->statistics.flag)); | 
|  | 115 | if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK) | 
|  | 116 | p += scnprintf(buf + p, bufsz - p, | 
|  | 117 | "\tStatistics have been cleared\n"); | 
|  | 118 | p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", | 
|  | 119 | (le32_to_cpu(priv->statistics.flag) & | 
|  | 120 | UCODE_STATISTICS_FREQUENCY_MSK) | 
|  | 121 | ? "2.4 GHz" : "5.2 GHz"); | 
|  | 122 | p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", | 
|  | 123 | (le32_to_cpu(priv->statistics.flag) & | 
|  | 124 | UCODE_STATISTICS_NARROW_BAND_MSK) | 
|  | 125 | ? "enabled" : "disabled"); | 
|  | 126 | return p; | 
|  | 127 | } | 
|  | 128 | EXPORT_SYMBOL(iwl_dbgfs_statistics_flag); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 129 |  | 
|  | 130 | static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, | 
|  | 131 | char __user *user_buf, | 
|  | 132 | size_t count, loff_t *ppos) { | 
|  | 133 |  | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 134 | struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 135 | char *buf; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 136 | int pos = 0; | 
|  | 137 |  | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 138 | int cnt; | 
|  | 139 | ssize_t ret; | 
| Wey-Yi Guy | 98a7b43 | 2009-11-13 11:56:31 -0800 | [diff] [blame] | 140 | const size_t bufsz = 100 + | 
|  | 141 | sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 142 | buf = kzalloc(bufsz, GFP_KERNEL); | 
|  | 143 | if (!buf) | 
|  | 144 | return -ENOMEM; | 
|  | 145 | pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); | 
|  | 146 | for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { | 
|  | 147 | pos += scnprintf(buf + pos, bufsz - pos, | 
| Wey-Yi Guy | 98a7b43 | 2009-11-13 11:56:31 -0800 | [diff] [blame] | 148 | "\t%25s\t\t: %u\n", | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 149 | get_mgmt_string(cnt), | 
|  | 150 | priv->tx_stats.mgmt[cnt]); | 
|  | 151 | } | 
|  | 152 | pos += scnprintf(buf + pos, bufsz - pos, "Control\n"); | 
|  | 153 | for (cnt = 0; cnt < CONTROL_MAX; cnt++) { | 
|  | 154 | pos += scnprintf(buf + pos, bufsz - pos, | 
| Wey-Yi Guy | 98a7b43 | 2009-11-13 11:56:31 -0800 | [diff] [blame] | 155 | "\t%25s\t\t: %u\n", | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 156 | get_ctrl_string(cnt), | 
|  | 157 | priv->tx_stats.ctrl[cnt]); | 
|  | 158 | } | 
|  | 159 | pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); | 
|  | 160 | pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", | 
|  | 161 | priv->tx_stats.data_cnt); | 
|  | 162 | pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", | 
|  | 163 | priv->tx_stats.data_bytes); | 
|  | 164 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
|  | 165 | kfree(buf); | 
|  | 166 | return ret; | 
|  | 167 | } | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 168 |  | 
| Wey-Yi Guy | 7163b8a | 2009-11-20 12:04:56 -0800 | [diff] [blame] | 169 | 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] | 170 | const char __user *user_buf, | 
|  | 171 | size_t count, loff_t *ppos) | 
|  | 172 | { | 
|  | 173 | struct iwl_priv *priv = file->private_data; | 
|  | 174 | u32 clear_flag; | 
|  | 175 | char buf[8]; | 
|  | 176 | int buf_size; | 
|  | 177 |  | 
|  | 178 | memset(buf, 0, sizeof(buf)); | 
|  | 179 | buf_size = min(count, sizeof(buf) -  1); | 
|  | 180 | if (copy_from_user(buf, user_buf, buf_size)) | 
|  | 181 | return -EFAULT; | 
|  | 182 | if (sscanf(buf, "%x", &clear_flag) != 1) | 
|  | 183 | return -EFAULT; | 
| Wey-Yi Guy | 7163b8a | 2009-11-20 12:04:56 -0800 | [diff] [blame] | 184 | iwl_clear_traffic_stats(priv); | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 185 |  | 
|  | 186 | return count; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 187 | } | 
|  | 188 |  | 
|  | 189 | static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, | 
|  | 190 | char __user *user_buf, | 
|  | 191 | size_t count, loff_t *ppos) { | 
|  | 192 |  | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 193 | struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 194 | char *buf; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 195 | int pos = 0; | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 196 | int cnt; | 
|  | 197 | ssize_t ret; | 
|  | 198 | const size_t bufsz = 100 + | 
| Wey-Yi Guy | 98a7b43 | 2009-11-13 11:56:31 -0800 | [diff] [blame] | 199 | sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 200 | buf = kzalloc(bufsz, GFP_KERNEL); | 
|  | 201 | if (!buf) | 
|  | 202 | return -ENOMEM; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 203 |  | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 204 | pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); | 
|  | 205 | for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { | 
|  | 206 | pos += scnprintf(buf + pos, bufsz - pos, | 
| Wey-Yi Guy | 98a7b43 | 2009-11-13 11:56:31 -0800 | [diff] [blame] | 207 | "\t%25s\t\t: %u\n", | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 208 | get_mgmt_string(cnt), | 
|  | 209 | priv->rx_stats.mgmt[cnt]); | 
|  | 210 | } | 
|  | 211 | pos += scnprintf(buf + pos, bufsz - pos, "Control:\n"); | 
|  | 212 | for (cnt = 0; cnt < CONTROL_MAX; cnt++) { | 
|  | 213 | pos += scnprintf(buf + pos, bufsz - pos, | 
| Wey-Yi Guy | 98a7b43 | 2009-11-13 11:56:31 -0800 | [diff] [blame] | 214 | "\t%25s\t\t: %u\n", | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 215 | get_ctrl_string(cnt), | 
|  | 216 | priv->rx_stats.ctrl[cnt]); | 
|  | 217 | } | 
|  | 218 | pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); | 
|  | 219 | pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", | 
|  | 220 | priv->rx_stats.data_cnt); | 
|  | 221 | pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", | 
|  | 222 | priv->rx_stats.data_bytes); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 223 |  | 
| Wey-Yi Guy | 22fdf3c | 2009-08-07 15:41:40 -0700 | [diff] [blame] | 224 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
|  | 225 | kfree(buf); | 
|  | 226 | return ret; | 
|  | 227 | } | 
|  | 228 |  | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 229 | #define BYTE1_MASK 0x000000ff; | 
|  | 230 | #define BYTE2_MASK 0x0000ffff; | 
|  | 231 | #define BYTE3_MASK 0x00ffffff; | 
|  | 232 | static ssize_t iwl_dbgfs_sram_read(struct file *file, | 
|  | 233 | char __user *user_buf, | 
|  | 234 | size_t count, loff_t *ppos) | 
|  | 235 | { | 
|  | 236 | u32 val; | 
| Wey-Yi Guy | 2943f13 | 2009-11-20 12:05:00 -0800 | [diff] [blame] | 237 | char *buf; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 238 | ssize_t ret; | 
|  | 239 | int i; | 
|  | 240 | int pos = 0; | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 241 | struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 2943f13 | 2009-11-20 12:05:00 -0800 | [diff] [blame] | 242 | size_t bufsz; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 243 |  | 
| Wey-Yi Guy | 5ade1e4 | 2009-11-20 12:05:04 -0800 | [diff] [blame] | 244 | /* default is to dump the entire data segment */ | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 245 | if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { | 
|  | 246 | priv->dbgfs_sram_offset = 0x800000; | 
| Wey-Yi Guy | 5ade1e4 | 2009-11-20 12:05:04 -0800 | [diff] [blame] | 247 | if (priv->ucode_type == UCODE_INIT) | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 248 | priv->dbgfs_sram_len = priv->ucode_init_data.len; | 
| Wey-Yi Guy | 5ade1e4 | 2009-11-20 12:05:04 -0800 | [diff] [blame] | 249 | else | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 250 | priv->dbgfs_sram_len = priv->ucode_data.len; | 
| Wey-Yi Guy | 5ade1e4 | 2009-11-20 12:05:04 -0800 | [diff] [blame] | 251 | } | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 252 | bufsz =  30 + priv->dbgfs_sram_len * sizeof(char) * 10; | 
| Wey-Yi Guy | 2943f13 | 2009-11-20 12:05:00 -0800 | [diff] [blame] | 253 | buf = kmalloc(bufsz, GFP_KERNEL); | 
|  | 254 | if (!buf) | 
|  | 255 | return -ENOMEM; | 
| Wey-Yi Guy | 5ade1e4 | 2009-11-20 12:05:04 -0800 | [diff] [blame] | 256 | pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 257 | priv->dbgfs_sram_len); | 
| Wey-Yi Guy | 5ade1e4 | 2009-11-20 12:05:04 -0800 | [diff] [blame] | 258 | pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 259 | priv->dbgfs_sram_offset); | 
|  | 260 | for (i = priv->dbgfs_sram_len; i > 0; i -= 4) { | 
|  | 261 | val = iwl_read_targ_mem(priv, priv->dbgfs_sram_offset + \ | 
|  | 262 | priv->dbgfs_sram_len - i); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 263 | if (i < 4) { | 
|  | 264 | switch (i) { | 
|  | 265 | case 1: | 
|  | 266 | val &= BYTE1_MASK; | 
|  | 267 | break; | 
|  | 268 | case 2: | 
|  | 269 | val &= BYTE2_MASK; | 
|  | 270 | break; | 
|  | 271 | case 3: | 
|  | 272 | val &= BYTE3_MASK; | 
|  | 273 | break; | 
|  | 274 | } | 
|  | 275 | } | 
| Wey-Yi Guy | 2943f13 | 2009-11-20 12:05:00 -0800 | [diff] [blame] | 276 | if (!(i % 16)) | 
|  | 277 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 278 | pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 279 | } | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 280 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 281 |  | 
|  | 282 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
| Wey-Yi Guy | 2943f13 | 2009-11-20 12:05:00 -0800 | [diff] [blame] | 283 | kfree(buf); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 284 | return ret; | 
|  | 285 | } | 
|  | 286 |  | 
|  | 287 | static ssize_t iwl_dbgfs_sram_write(struct file *file, | 
|  | 288 | const char __user *user_buf, | 
|  | 289 | size_t count, loff_t *ppos) | 
|  | 290 | { | 
|  | 291 | struct iwl_priv *priv = file->private_data; | 
|  | 292 | char buf[64]; | 
|  | 293 | int buf_size; | 
|  | 294 | u32 offset, len; | 
|  | 295 |  | 
|  | 296 | memset(buf, 0, sizeof(buf)); | 
|  | 297 | buf_size = min(count, sizeof(buf) -  1); | 
|  | 298 | if (copy_from_user(buf, user_buf, buf_size)) | 
|  | 299 | return -EFAULT; | 
|  | 300 |  | 
|  | 301 | if (sscanf(buf, "%x,%x", &offset, &len) == 2) { | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 302 | priv->dbgfs_sram_offset = offset; | 
|  | 303 | priv->dbgfs_sram_len = len; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 304 | } else { | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 305 | priv->dbgfs_sram_offset = 0; | 
|  | 306 | priv->dbgfs_sram_len = 0; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 307 | } | 
|  | 308 |  | 
|  | 309 | return count; | 
|  | 310 | } | 
|  | 311 |  | 
|  | 312 | static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | 
|  | 313 | size_t count, loff_t *ppos) | 
|  | 314 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 315 | struct iwl_priv *priv = file->private_data; | 
| Tomas Winkler | 6def976 | 2008-05-05 10:22:31 +0800 | [diff] [blame] | 316 | struct iwl_station_entry *station; | 
| Tomas Winkler | 5425e49 | 2008-04-15 16:01:38 -0700 | [diff] [blame] | 317 | int max_sta = priv->hw_params.max_stations; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 318 | char *buf; | 
|  | 319 | int i, j, pos = 0; | 
|  | 320 | ssize_t ret; | 
|  | 321 | /* Add 30 for initial string */ | 
|  | 322 | const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 323 |  | 
|  | 324 | buf = kmalloc(bufsz, GFP_KERNEL); | 
| Tomas Winkler | 3ac7f14 | 2008-07-21 02:40:14 +0300 | [diff] [blame] | 325 | if (!buf) | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 326 | return -ENOMEM; | 
|  | 327 |  | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 328 | pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n", | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 329 | priv->num_stations); | 
|  | 330 |  | 
|  | 331 | for (i = 0; i < max_sta; i++) { | 
|  | 332 | station = &priv->stations[i]; | 
|  | 333 | if (station->used) { | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 334 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 335 | "station %d:\ngeneral data:\n", i+1); | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 336 | pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n", | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 337 | station->sta.sta.sta_id); | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 338 | pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n", | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 339 | station->sta.mode); | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 340 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 341 | "flags: 0x%x\n", | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 342 | station->sta.station_flags_msk); | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 343 | pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n"); | 
|  | 344 | pos += scnprintf(buf + pos, bufsz - pos, | 
| David S. Miller | 344234d | 2008-04-19 18:09:39 -0700 | [diff] [blame] | 345 | "seq_num\t\ttxq_id"); | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 346 | pos += scnprintf(buf + pos, bufsz - pos, | 
| David S. Miller | 344234d | 2008-04-19 18:09:39 -0700 | [diff] [blame] | 347 | "\tframe_count\twait_for_ba\t"); | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 348 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 349 | "start_idx\tbitmap0\t"); | 
|  | 350 | pos += scnprintf(buf + pos, bufsz - pos, | 
| David S. Miller | 344234d | 2008-04-19 18:09:39 -0700 | [diff] [blame] | 351 | "bitmap1\trate_n_flags"); | 
| David S. Miller | 344234d | 2008-04-19 18:09:39 -0700 | [diff] [blame] | 352 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 353 |  | 
|  | 354 | for (j = 0; j < MAX_TID_COUNT; j++) { | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 355 | pos += scnprintf(buf + pos, bufsz - pos, | 
| David S. Miller | 344234d | 2008-04-19 18:09:39 -0700 | [diff] [blame] | 356 | "[%d]:\t\t%u", j, | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 357 | station->tid[j].seq_number); | 
|  | 358 | pos += scnprintf(buf + pos, bufsz - pos, | 
| David S. Miller | 344234d | 2008-04-19 18:09:39 -0700 | [diff] [blame] | 359 | "\t%u\t\t%u\t\t%u\t\t", | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 360 | station->tid[j].agg.txq_id, | 
|  | 361 | station->tid[j].agg.frame_count, | 
|  | 362 | station->tid[j].agg.wait_for_ba); | 
| Abhijeet Kolekar | db0589f | 2008-04-14 21:16:04 -0700 | [diff] [blame] | 363 | pos += scnprintf(buf + pos, bufsz - pos, | 
| David S. Miller | 344234d | 2008-04-19 18:09:39 -0700 | [diff] [blame] | 364 | "%u\t%llu\t%u", | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 365 | station->tid[j].agg.start_idx, | 
| John W. Linville | 1678859 | 2008-04-01 20:59:32 -0400 | [diff] [blame] | 366 | (unsigned long long)station->tid[j].agg.bitmap, | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 367 | station->tid[j].agg.rate_n_flags); | 
| David S. Miller | 344234d | 2008-04-19 18:09:39 -0700 | [diff] [blame] | 368 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 369 | } | 
| 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 | } | 
|  | 372 | } | 
|  | 373 |  | 
|  | 374 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
|  | 375 | kfree(buf); | 
|  | 376 | return ret; | 
|  | 377 | } | 
|  | 378 |  | 
| Wey-Yi Guy | 0848e29 | 2009-05-22 11:01:46 -0700 | [diff] [blame] | 379 | static ssize_t iwl_dbgfs_nvm_read(struct file *file, | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 380 | char __user *user_buf, | 
|  | 381 | size_t count, | 
|  | 382 | loff_t *ppos) | 
|  | 383 | { | 
|  | 384 | ssize_t ret; | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 385 | struct iwl_priv *priv = file->private_data; | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 386 | int pos = 0, ofs = 0, buf_size = 0; | 
|  | 387 | const u8 *ptr; | 
|  | 388 | char *buf; | 
| Wey-Yi Guy | e307ddc | 2009-09-11 10:38:16 -0700 | [diff] [blame] | 389 | u16 eeprom_ver; | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 390 | size_t eeprom_len = priv->cfg->eeprom_size; | 
|  | 391 | buf_size = 4 * eeprom_len + 256; | 
|  | 392 |  | 
|  | 393 | if (eeprom_len % 16) { | 
| Wey-Yi Guy | 0848e29 | 2009-05-22 11:01:46 -0700 | [diff] [blame] | 394 | IWL_ERR(priv, "NVM size is not multiple of 16.\n"); | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 395 | return -ENODATA; | 
|  | 396 | } | 
|  | 397 |  | 
| Julia Lawall | c37457e | 2009-08-03 11:11:45 +0200 | [diff] [blame] | 398 | ptr = priv->eeprom; | 
|  | 399 | if (!ptr) { | 
|  | 400 | IWL_ERR(priv, "Invalid EEPROM/OTP memory\n"); | 
|  | 401 | return -ENOMEM; | 
|  | 402 | } | 
|  | 403 |  | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 404 | /* 4 characters for byte 0xYY */ | 
|  | 405 | buf = kzalloc(buf_size, GFP_KERNEL); | 
|  | 406 | if (!buf) { | 
| Winkler, Tomas | 15b1687 | 2008-12-19 10:37:33 +0800 | [diff] [blame] | 407 | IWL_ERR(priv, "Can not allocate Buffer\n"); | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 408 | return -ENOMEM; | 
|  | 409 | } | 
| Wey-Yi Guy | e307ddc | 2009-09-11 10:38:16 -0700 | [diff] [blame] | 410 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | 
|  | 411 | pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, " | 
|  | 412 | "version: 0x%x\n", | 
| Wey-Yi Guy | 0848e29 | 2009-05-22 11:01:46 -0700 | [diff] [blame] | 413 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | 
| Wey-Yi Guy | e307ddc | 2009-09-11 10:38:16 -0700 | [diff] [blame] | 414 | ? "OTP" : "EEPROM", eeprom_ver); | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 415 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { | 
|  | 416 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); | 
|  | 417 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, | 
|  | 418 | buf_size - pos, 0); | 
| Reinette Chatre | 2fac971 | 2009-09-25 14:24:21 -0700 | [diff] [blame] | 419 | pos += strlen(buf + pos); | 
| Tomas Winkler | 8dd266e | 2008-05-05 10:22:32 +0800 | [diff] [blame] | 420 | if (buf_size - pos > 0) | 
|  | 421 | buf[pos++] = '\n'; | 
|  | 422 | } | 
|  | 423 |  | 
|  | 424 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
|  | 425 | kfree(buf); | 
|  | 426 | return ret; | 
|  | 427 | } | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 428 |  | 
| Wey-Yi Guy | b03d7d0 | 2009-12-14 14:12:20 -0800 | [diff] [blame] | 429 | static ssize_t iwl_dbgfs_log_event_read(struct file *file, | 
|  | 430 | char __user *user_buf, | 
|  | 431 | size_t count, loff_t *ppos) | 
|  | 432 | { | 
|  | 433 | struct iwl_priv *priv = file->private_data; | 
|  | 434 | char *buf; | 
|  | 435 | int pos = 0; | 
|  | 436 | ssize_t ret = -ENOMEM; | 
|  | 437 |  | 
| Wey-Yi Guy | 937c397 | 2010-01-15 13:43:36 -0800 | [diff] [blame] | 438 | ret = pos = priv->cfg->ops->lib->dump_nic_event_log( | 
|  | 439 | priv, true, &buf, true); | 
|  | 440 | if (buf) { | 
| Wey-Yi Guy | b03d7d0 | 2009-12-14 14:12:20 -0800 | [diff] [blame] | 441 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
|  | 442 | kfree(buf); | 
|  | 443 | } | 
|  | 444 | return ret; | 
|  | 445 | } | 
|  | 446 |  | 
| Ester Kummer | 189a2b5 | 2008-05-15 13:54:18 +0800 | [diff] [blame] | 447 | static ssize_t iwl_dbgfs_log_event_write(struct file *file, | 
|  | 448 | const char __user *user_buf, | 
|  | 449 | size_t count, loff_t *ppos) | 
|  | 450 | { | 
|  | 451 | struct iwl_priv *priv = file->private_data; | 
|  | 452 | u32 event_log_flag; | 
|  | 453 | char buf[8]; | 
|  | 454 | int buf_size; | 
|  | 455 |  | 
|  | 456 | memset(buf, 0, sizeof(buf)); | 
|  | 457 | buf_size = min(count, sizeof(buf) -  1); | 
|  | 458 | if (copy_from_user(buf, user_buf, buf_size)) | 
|  | 459 | return -EFAULT; | 
|  | 460 | if (sscanf(buf, "%d", &event_log_flag) != 1) | 
|  | 461 | return -EFAULT; | 
|  | 462 | if (event_log_flag == 1) | 
| Wey-Yi Guy | b03d7d0 | 2009-12-14 14:12:20 -0800 | [diff] [blame] | 463 | priv->cfg->ops->lib->dump_nic_event_log(priv, true, | 
|  | 464 | NULL, false); | 
| Ester Kummer | 189a2b5 | 2008-05-15 13:54:18 +0800 | [diff] [blame] | 465 |  | 
|  | 466 | return count; | 
|  | 467 | } | 
|  | 468 |  | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 469 |  | 
|  | 470 |  | 
|  | 471 | static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | 
|  | 472 | size_t count, loff_t *ppos) | 
|  | 473 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 474 | struct iwl_priv *priv = file->private_data; | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 475 | struct ieee80211_channel *channels = NULL; | 
|  | 476 | const struct ieee80211_supported_band *supp_band = NULL; | 
|  | 477 | int pos = 0, i, bufsz = PAGE_SIZE; | 
|  | 478 | char *buf; | 
|  | 479 | ssize_t ret; | 
|  | 480 |  | 
|  | 481 | if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) | 
|  | 482 | return -EAGAIN; | 
|  | 483 |  | 
|  | 484 | buf = kzalloc(bufsz, GFP_KERNEL); | 
|  | 485 | if (!buf) { | 
| Winkler, Tomas | 15b1687 | 2008-12-19 10:37:33 +0800 | [diff] [blame] | 486 | IWL_ERR(priv, "Can not allocate Buffer\n"); | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 487 | return -ENOMEM; | 
|  | 488 | } | 
|  | 489 |  | 
|  | 490 | supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ); | 
| Wey-Yi Guy | a2e2322 | 2009-05-22 11:01:55 -0700 | [diff] [blame] | 491 | if (supp_band) { | 
|  | 492 | channels = supp_band->channels; | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 493 |  | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 494 | pos += scnprintf(buf + pos, bufsz - pos, | 
| Wey-Yi Guy | a2e2322 | 2009-05-22 11:01:55 -0700 | [diff] [blame] | 495 | "Displaying %d channels in 2.4GHz band 802.11bg):\n", | 
|  | 496 | supp_band->n_channels); | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 497 |  | 
| Wey-Yi Guy | a2e2322 | 2009-05-22 11:01:55 -0700 | [diff] [blame] | 498 | for (i = 0; i < supp_band->n_channels; i++) | 
|  | 499 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 500 | "%d: %ddBm: BSS%s%s, %s.\n", | 
|  | 501 | ieee80211_frequency_to_channel( | 
|  | 502 | channels[i].center_freq), | 
|  | 503 | channels[i].max_power, | 
|  | 504 | channels[i].flags & IEEE80211_CHAN_RADAR ? | 
|  | 505 | " (IEEE 802.11h required)" : "", | 
|  | 506 | ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) | 
|  | 507 | || (channels[i].flags & | 
|  | 508 | IEEE80211_CHAN_RADAR)) ? "" : | 
|  | 509 | ", IBSS", | 
|  | 510 | channels[i].flags & | 
|  | 511 | IEEE80211_CHAN_PASSIVE_SCAN ? | 
|  | 512 | "passive only" : "active/passive"); | 
|  | 513 | } | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 514 | supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); | 
| Wey-Yi Guy | a2e2322 | 2009-05-22 11:01:55 -0700 | [diff] [blame] | 515 | if (supp_band) { | 
|  | 516 | channels = supp_band->channels; | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 517 |  | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 518 | pos += scnprintf(buf + pos, bufsz - pos, | 
| Wey-Yi Guy | a2e2322 | 2009-05-22 11:01:55 -0700 | [diff] [blame] | 519 | "Displaying %d channels in 5.2GHz band (802.11a)\n", | 
|  | 520 | supp_band->n_channels); | 
|  | 521 |  | 
|  | 522 | for (i = 0; i < supp_band->n_channels; i++) | 
|  | 523 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 524 | "%d: %ddBm: BSS%s%s, %s.\n", | 
|  | 525 | ieee80211_frequency_to_channel( | 
|  | 526 | channels[i].center_freq), | 
|  | 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); | 
|  | 611 | if (priv->isr_stats.sw > 0) { | 
|  | 612 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 613 | "\tLast Restarting Code:  0x%X\n", | 
|  | 614 | priv->isr_stats.sw_err); | 
|  | 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; | 
| Wey-Yi Guy | f5ad69f | 2009-07-09 10:33:36 -0700 | [diff] [blame] | 679 | int pos = 0, i; | 
|  | 680 | char buf[256]; | 
|  | 681 | const size_t bufsz = sizeof(buf); | 
| Wey-Yi Guy | f5ad69f | 2009-07-09 10:33:36 -0700 | [diff] [blame] | 682 |  | 
|  | 683 | for (i = 0; i < AC_NUM; i++) { | 
|  | 684 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 685 | "\tcw_min\tcw_max\taifsn\ttxop\n"); | 
|  | 686 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 687 | "AC[%d]\t%u\t%u\t%u\t%u\n", i, | 
|  | 688 | priv->qos_data.def_qos_parm.ac[i].cw_min, | 
|  | 689 | priv->qos_data.def_qos_parm.ac[i].cw_max, | 
|  | 690 | priv->qos_data.def_qos_parm.ac[i].aifsn, | 
|  | 691 | priv->qos_data.def_qos_parm.ac[i].edca_txop); | 
|  | 692 | } | 
| Wey-Yi Guy | 4967c31 | 2010-02-18 15:22:07 -0800 | [diff] [blame] | 693 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
| Wey-Yi Guy | f5ad69f | 2009-07-09 10:33:36 -0700 | [diff] [blame] | 694 | } | 
| Wey-Yi Guy | a83b914 | 2009-04-08 11:39:32 -0700 | [diff] [blame] | 695 |  | 
| Wey-Yi Guy | a283c01 | 2009-07-17 09:30:19 -0700 | [diff] [blame] | 696 | static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, | 
|  | 697 | size_t count, loff_t *ppos) | 
|  | 698 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 699 | struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | a283c01 | 2009-07-17 09:30:19 -0700 | [diff] [blame] | 700 | int pos = 0; | 
|  | 701 | char buf[256]; | 
|  | 702 | const size_t bufsz = sizeof(buf); | 
| Wey-Yi Guy | a283c01 | 2009-07-17 09:30:19 -0700 | [diff] [blame] | 703 |  | 
|  | 704 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 705 | "allow blinking: %s\n", | 
|  | 706 | (priv->allow_blinking) ? "True" : "False"); | 
|  | 707 | if (priv->allow_blinking) { | 
|  | 708 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 709 | "Led blinking rate: %u\n", | 
|  | 710 | priv->last_blink_rate); | 
|  | 711 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 712 | "Last blink time: %lu\n", | 
|  | 713 | priv->last_blink_time); | 
|  | 714 | } | 
|  | 715 |  | 
| Wey-Yi Guy | 4967c31 | 2010-02-18 15:22:07 -0800 | [diff] [blame] | 716 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
| Wey-Yi Guy | a283c01 | 2009-07-17 09:30:19 -0700 | [diff] [blame] | 717 | } | 
| Wey-Yi Guy | a283c01 | 2009-07-17 09:30:19 -0700 | [diff] [blame] | 718 |  | 
| Wey-Yi Guy | fbf3a2a | 2009-07-24 11:13:04 -0700 | [diff] [blame] | 719 | static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, | 
|  | 720 | char __user *user_buf, | 
|  | 721 | size_t count, loff_t *ppos) | 
|  | 722 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 723 | struct iwl_priv *priv = file->private_data; | 
| Johannes Berg | 3ad3b92 | 2009-08-07 15:41:48 -0700 | [diff] [blame] | 724 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | 
| Wey-Yi Guy | fbf3a2a | 2009-07-24 11:13:04 -0700 | [diff] [blame] | 725 | struct iwl_tt_restriction *restriction; | 
|  | 726 | char buf[100]; | 
|  | 727 | int pos = 0; | 
|  | 728 | const size_t bufsz = sizeof(buf); | 
| Wey-Yi Guy | fbf3a2a | 2009-07-24 11:13:04 -0700 | [diff] [blame] | 729 |  | 
|  | 730 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 731 | "Thermal Throttling Mode: %s\n", | 
| Johannes Berg | 3ad3b92 | 2009-08-07 15:41:48 -0700 | [diff] [blame] | 732 | tt->advanced_tt ? "Advance" : "Legacy"); | 
| Wey-Yi Guy | fbf3a2a | 2009-07-24 11:13:04 -0700 | [diff] [blame] | 733 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 734 | "Thermal Throttling State: %d\n", | 
|  | 735 | tt->state); | 
| Johannes Berg | 3ad3b92 | 2009-08-07 15:41:48 -0700 | [diff] [blame] | 736 | if (tt->advanced_tt) { | 
| Wey-Yi Guy | fbf3a2a | 2009-07-24 11:13:04 -0700 | [diff] [blame] | 737 | restriction = tt->restriction + tt->state; | 
|  | 738 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 739 | "Tx mode: %d\n", | 
|  | 740 | restriction->tx_stream); | 
|  | 741 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 742 | "Rx mode: %d\n", | 
|  | 743 | restriction->rx_stream); | 
|  | 744 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 745 | "HT mode: %d\n", | 
|  | 746 | restriction->is_ht); | 
|  | 747 | } | 
| Wey-Yi Guy | 4967c31 | 2010-02-18 15:22:07 -0800 | [diff] [blame] | 748 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
| Wey-Yi Guy | fbf3a2a | 2009-07-24 11:13:04 -0700 | [diff] [blame] | 749 | } | 
|  | 750 |  | 
| Wey-Yi Guy | 1e4247d | 2009-07-27 13:50:15 -0700 | [diff] [blame] | 751 | static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file, | 
|  | 752 | const char __user *user_buf, | 
|  | 753 | size_t count, loff_t *ppos) | 
|  | 754 | { | 
|  | 755 | struct iwl_priv *priv = file->private_data; | 
|  | 756 | char buf[8]; | 
|  | 757 | int buf_size; | 
|  | 758 | int ht40; | 
|  | 759 |  | 
|  | 760 | memset(buf, 0, sizeof(buf)); | 
|  | 761 | buf_size = min(count, sizeof(buf) -  1); | 
|  | 762 | if (copy_from_user(buf, user_buf, buf_size)) | 
|  | 763 | return -EFAULT; | 
|  | 764 | if (sscanf(buf, "%d", &ht40) != 1) | 
|  | 765 | return -EFAULT; | 
|  | 766 | if (!iwl_is_associated(priv)) | 
|  | 767 | priv->disable_ht40 = ht40 ? true : false; | 
|  | 768 | else { | 
|  | 769 | IWL_ERR(priv, "Sta associated with AP - " | 
|  | 770 | "Change to 40MHz channel support is not allowed\n"); | 
|  | 771 | return -EINVAL; | 
|  | 772 | } | 
|  | 773 |  | 
|  | 774 | return count; | 
|  | 775 | } | 
|  | 776 |  | 
|  | 777 | static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file, | 
|  | 778 | char __user *user_buf, | 
|  | 779 | size_t count, loff_t *ppos) | 
|  | 780 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 781 | struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 1e4247d | 2009-07-27 13:50:15 -0700 | [diff] [blame] | 782 | char buf[100]; | 
|  | 783 | int pos = 0; | 
|  | 784 | const size_t bufsz = sizeof(buf); | 
| Wey-Yi Guy | 1e4247d | 2009-07-27 13:50:15 -0700 | [diff] [blame] | 785 |  | 
|  | 786 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 787 | "11n 40MHz Mode: %s\n", | 
|  | 788 | priv->disable_ht40 ? "Disabled" : "Enabled"); | 
| Wey-Yi Guy | 4967c31 | 2010-02-18 15:22:07 -0800 | [diff] [blame] | 789 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
| Wey-Yi Guy | 1e4247d | 2009-07-27 13:50:15 -0700 | [diff] [blame] | 790 | } | 
|  | 791 |  | 
| Johannes Berg | e312c24 | 2009-08-07 15:41:51 -0700 | [diff] [blame] | 792 | static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, | 
|  | 793 | const char __user *user_buf, | 
|  | 794 | size_t count, loff_t *ppos) | 
|  | 795 | { | 
|  | 796 | struct iwl_priv *priv = file->private_data; | 
|  | 797 | char buf[8]; | 
|  | 798 | int buf_size; | 
|  | 799 | int value; | 
|  | 800 |  | 
|  | 801 | memset(buf, 0, sizeof(buf)); | 
|  | 802 | buf_size = min(count, sizeof(buf) -  1); | 
|  | 803 | if (copy_from_user(buf, user_buf, buf_size)) | 
|  | 804 | return -EFAULT; | 
|  | 805 |  | 
|  | 806 | if (sscanf(buf, "%d", &value) != 1) | 
|  | 807 | return -EINVAL; | 
|  | 808 |  | 
|  | 809 | /* | 
|  | 810 | * Our users expect 0 to be "CAM", but 0 isn't actually | 
|  | 811 | * valid here. However, let's not confuse them and present | 
|  | 812 | * IWL_POWER_INDEX_1 as "1", not "0". | 
|  | 813 | */ | 
| Reinette Chatre | 1a34c04 | 2009-10-09 13:20:25 -0700 | [diff] [blame] | 814 | if (value == 0) | 
|  | 815 | return -EINVAL; | 
|  | 816 | else if (value > 0) | 
| Johannes Berg | e312c24 | 2009-08-07 15:41:51 -0700 | [diff] [blame] | 817 | value -= 1; | 
|  | 818 |  | 
|  | 819 | if (value != -1 && (value < 0 || value >= IWL_POWER_NUM)) | 
|  | 820 | return -EINVAL; | 
|  | 821 |  | 
| Wey-Yi Guy | 4ad177b | 2009-10-16 14:25:58 -0700 | [diff] [blame] | 822 | if (!iwl_is_ready_rf(priv)) | 
|  | 823 | return -EAGAIN; | 
|  | 824 |  | 
| Johannes Berg | e312c24 | 2009-08-07 15:41:51 -0700 | [diff] [blame] | 825 | priv->power_data.debug_sleep_level_override = value; | 
|  | 826 |  | 
| Reinette Chatre | d3a5719 | 2010-01-21 11:52:28 -0800 | [diff] [blame] | 827 | mutex_lock(&priv->mutex); | 
| Wey-Yi Guy | 4ad177b | 2009-10-16 14:25:58 -0700 | [diff] [blame] | 828 | iwl_power_update_mode(priv, true); | 
| Reinette Chatre | d3a5719 | 2010-01-21 11:52:28 -0800 | [diff] [blame] | 829 | mutex_unlock(&priv->mutex); | 
| Johannes Berg | e312c24 | 2009-08-07 15:41:51 -0700 | [diff] [blame] | 830 |  | 
|  | 831 | return count; | 
|  | 832 | } | 
|  | 833 |  | 
|  | 834 | static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file, | 
|  | 835 | char __user *user_buf, | 
|  | 836 | size_t count, loff_t *ppos) | 
|  | 837 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 838 | struct iwl_priv *priv = file->private_data; | 
| Johannes Berg | e312c24 | 2009-08-07 15:41:51 -0700 | [diff] [blame] | 839 | char buf[10]; | 
|  | 840 | int pos, value; | 
|  | 841 | const size_t bufsz = sizeof(buf); | 
|  | 842 |  | 
|  | 843 | /* see the write function */ | 
|  | 844 | value = priv->power_data.debug_sleep_level_override; | 
|  | 845 | if (value >= 0) | 
|  | 846 | value += 1; | 
|  | 847 |  | 
|  | 848 | pos = scnprintf(buf, bufsz, "%d\n", value); | 
|  | 849 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
|  | 850 | } | 
|  | 851 |  | 
|  | 852 | static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, | 
|  | 853 | char __user *user_buf, | 
|  | 854 | size_t count, loff_t *ppos) | 
|  | 855 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 856 | struct iwl_priv *priv = file->private_data; | 
| Johannes Berg | e312c24 | 2009-08-07 15:41:51 -0700 | [diff] [blame] | 857 | char buf[200]; | 
|  | 858 | int pos = 0, i; | 
|  | 859 | const size_t bufsz = sizeof(buf); | 
|  | 860 | struct iwl_powertable_cmd *cmd = &priv->power_data.sleep_cmd; | 
|  | 861 |  | 
|  | 862 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 863 | "flags: %#.2x\n", le16_to_cpu(cmd->flags)); | 
|  | 864 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 865 | "RX/TX timeout: %d/%d usec\n", | 
|  | 866 | le32_to_cpu(cmd->rx_data_timeout), | 
|  | 867 | le32_to_cpu(cmd->tx_data_timeout)); | 
|  | 868 | for (i = 0; i < IWL_POWER_VEC_SIZE; i++) | 
|  | 869 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 870 | "sleep_interval[%d]: %d\n", i, | 
|  | 871 | le32_to_cpu(cmd->sleep_interval[i])); | 
|  | 872 |  | 
|  | 873 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
|  | 874 | } | 
|  | 875 |  | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 876 | DEBUGFS_READ_WRITE_FILE_OPS(sram); | 
| Wey-Yi Guy | b03d7d0 | 2009-12-14 14:12:20 -0800 | [diff] [blame] | 877 | DEBUGFS_READ_WRITE_FILE_OPS(log_event); | 
| Wey-Yi Guy | 0848e29 | 2009-05-22 11:01:46 -0700 | [diff] [blame] | 878 | DEBUGFS_READ_FILE_OPS(nvm); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 879 | DEBUGFS_READ_FILE_OPS(stations); | 
| Winkler, Tomas | d366df5 | 2008-12-02 12:14:01 -0800 | [diff] [blame] | 880 | DEBUGFS_READ_FILE_OPS(channels); | 
| Wey-Yi Guy | 08df05a | 2009-03-24 10:02:54 -0700 | [diff] [blame] | 881 | DEBUGFS_READ_FILE_OPS(status); | 
| Wey-Yi Guy | a83b914 | 2009-04-08 11:39:32 -0700 | [diff] [blame] | 882 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); | 
| Wey-Yi Guy | f5ad69f | 2009-07-09 10:33:36 -0700 | [diff] [blame] | 883 | DEBUGFS_READ_FILE_OPS(qos); | 
| Wey-Yi Guy | a283c01 | 2009-07-17 09:30:19 -0700 | [diff] [blame] | 884 | DEBUGFS_READ_FILE_OPS(led); | 
| Wey-Yi Guy | fbf3a2a | 2009-07-24 11:13:04 -0700 | [diff] [blame] | 885 | DEBUGFS_READ_FILE_OPS(thermal_throttling); | 
| Wey-Yi Guy | 1e4247d | 2009-07-27 13:50:15 -0700 | [diff] [blame] | 886 | DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); | 
| Johannes Berg | e312c24 | 2009-08-07 15:41:51 -0700 | [diff] [blame] | 887 | DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); | 
|  | 888 | DEBUGFS_READ_FILE_OPS(current_sleep_command); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 889 |  | 
| Wey-Yi Guy | 20594eb | 2009-08-07 15:41:39 -0700 | [diff] [blame] | 890 | static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, | 
|  | 891 | char __user *user_buf, | 
|  | 892 | size_t count, loff_t *ppos) | 
|  | 893 | { | 
|  | 894 | struct iwl_priv *priv = file->private_data; | 
|  | 895 | int pos = 0, ofs = 0; | 
|  | 896 | int cnt = 0, entry; | 
|  | 897 | struct iwl_tx_queue *txq; | 
|  | 898 | struct iwl_queue *q; | 
|  | 899 | struct iwl_rx_queue *rxq = &priv->rxq; | 
|  | 900 | char *buf; | 
|  | 901 | int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + | 
| Wey-Yi Guy | 88804e2 | 2009-10-09 13:20:28 -0700 | [diff] [blame] | 902 | (priv->cfg->num_of_queues * 32 * 8) + 400; | 
| Wey-Yi Guy | 20594eb | 2009-08-07 15:41:39 -0700 | [diff] [blame] | 903 | const u8 *ptr; | 
|  | 904 | ssize_t ret; | 
|  | 905 |  | 
| Wey-Yi Guy | 88804e2 | 2009-10-09 13:20:28 -0700 | [diff] [blame] | 906 | if (!priv->txq) { | 
|  | 907 | IWL_ERR(priv, "txq not ready\n"); | 
|  | 908 | return -EAGAIN; | 
|  | 909 | } | 
| Wey-Yi Guy | 20594eb | 2009-08-07 15:41:39 -0700 | [diff] [blame] | 910 | buf = kzalloc(bufsz, GFP_KERNEL); | 
|  | 911 | if (!buf) { | 
|  | 912 | IWL_ERR(priv, "Can not allocate buffer\n"); | 
|  | 913 | return -ENOMEM; | 
|  | 914 | } | 
|  | 915 | pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); | 
|  | 916 | for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { | 
|  | 917 | txq = &priv->txq[cnt]; | 
|  | 918 | q = &txq->q; | 
|  | 919 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 920 | "q[%d]: read_ptr: %u, write_ptr: %u\n", | 
|  | 921 | cnt, q->read_ptr, q->write_ptr); | 
|  | 922 | } | 
|  | 923 | if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) { | 
|  | 924 | ptr = priv->tx_traffic; | 
|  | 925 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 926 | "Tx Traffic idx: %u\n",	priv->tx_traffic_idx); | 
|  | 927 | for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { | 
|  | 928 | for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; | 
|  | 929 | entry++,  ofs += 16) { | 
|  | 930 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 931 | "0x%.4x ", ofs); | 
|  | 932 | hex_dump_to_buffer(ptr + ofs, 16, 16, 2, | 
|  | 933 | buf + pos, bufsz - pos, 0); | 
| Reinette Chatre | 2fac971 | 2009-09-25 14:24:21 -0700 | [diff] [blame] | 934 | pos += strlen(buf + pos); | 
| Wey-Yi Guy | 20594eb | 2009-08-07 15:41:39 -0700 | [diff] [blame] | 935 | if (bufsz - pos > 0) | 
|  | 936 | buf[pos++] = '\n'; | 
|  | 937 | } | 
|  | 938 | } | 
|  | 939 | } | 
|  | 940 |  | 
|  | 941 | pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n"); | 
|  | 942 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 943 | "read: %u, write: %u\n", | 
|  | 944 | rxq->read, rxq->write); | 
|  | 945 |  | 
|  | 946 | if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) { | 
|  | 947 | ptr = priv->rx_traffic; | 
|  | 948 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 949 | "Rx Traffic idx: %u\n",	priv->rx_traffic_idx); | 
|  | 950 | for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { | 
|  | 951 | for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; | 
|  | 952 | entry++,  ofs += 16) { | 
|  | 953 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 954 | "0x%.4x ", ofs); | 
|  | 955 | hex_dump_to_buffer(ptr + ofs, 16, 16, 2, | 
|  | 956 | buf + pos, bufsz - pos, 0); | 
| Reinette Chatre | 2fac971 | 2009-09-25 14:24:21 -0700 | [diff] [blame] | 957 | pos += strlen(buf + pos); | 
| Wey-Yi Guy | 20594eb | 2009-08-07 15:41:39 -0700 | [diff] [blame] | 958 | if (bufsz - pos > 0) | 
|  | 959 | buf[pos++] = '\n'; | 
|  | 960 | } | 
|  | 961 | } | 
|  | 962 | } | 
|  | 963 |  | 
|  | 964 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
|  | 965 | kfree(buf); | 
|  | 966 | return ret; | 
|  | 967 | } | 
|  | 968 |  | 
|  | 969 | static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, | 
|  | 970 | const char __user *user_buf, | 
|  | 971 | size_t count, loff_t *ppos) | 
|  | 972 | { | 
|  | 973 | struct iwl_priv *priv = file->private_data; | 
|  | 974 | char buf[8]; | 
|  | 975 | int buf_size; | 
|  | 976 | int traffic_log; | 
|  | 977 |  | 
|  | 978 | memset(buf, 0, sizeof(buf)); | 
|  | 979 | buf_size = min(count, sizeof(buf) -  1); | 
|  | 980 | if (copy_from_user(buf, user_buf, buf_size)) | 
|  | 981 | return -EFAULT; | 
|  | 982 | if (sscanf(buf, "%d", &traffic_log) != 1) | 
|  | 983 | return -EFAULT; | 
|  | 984 | if (traffic_log == 0) | 
|  | 985 | iwl_reset_traffic_log(priv); | 
|  | 986 |  | 
|  | 987 | return count; | 
|  | 988 | } | 
|  | 989 |  | 
| Wey-Yi Guy | 141b03e | 2009-08-07 15:41:41 -0700 | [diff] [blame] | 990 | static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | 
|  | 991 | char __user *user_buf, | 
|  | 992 | size_t count, loff_t *ppos) { | 
|  | 993 |  | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 994 | struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 141b03e | 2009-08-07 15:41:41 -0700 | [diff] [blame] | 995 | struct iwl_tx_queue *txq; | 
|  | 996 | struct iwl_queue *q; | 
|  | 997 | char *buf; | 
|  | 998 | int pos = 0; | 
|  | 999 | int cnt; | 
|  | 1000 | int ret; | 
| Wey-Yi Guy | d23db55 | 2009-11-20 12:04:59 -0800 | [diff] [blame] | 1001 | const size_t bufsz = sizeof(char) * 64 * priv->cfg->num_of_queues; | 
| Wey-Yi Guy | 141b03e | 2009-08-07 15:41:41 -0700 | [diff] [blame] | 1002 |  | 
| Wey-Yi Guy | 88804e2 | 2009-10-09 13:20:28 -0700 | [diff] [blame] | 1003 | if (!priv->txq) { | 
|  | 1004 | IWL_ERR(priv, "txq not ready\n"); | 
|  | 1005 | return -EAGAIN; | 
|  | 1006 | } | 
| Wey-Yi Guy | 141b03e | 2009-08-07 15:41:41 -0700 | [diff] [blame] | 1007 | buf = kzalloc(bufsz, GFP_KERNEL); | 
|  | 1008 | if (!buf) | 
|  | 1009 | return -ENOMEM; | 
|  | 1010 |  | 
|  | 1011 | for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { | 
|  | 1012 | txq = &priv->txq[cnt]; | 
|  | 1013 | q = &txq->q; | 
|  | 1014 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 1015 | "hwq %.2d: read=%u write=%u stop=%d" | 
|  | 1016 | " swq_id=%#.2x (ac %d/hwq %d)\n", | 
|  | 1017 | cnt, q->read_ptr, q->write_ptr, | 
|  | 1018 | !!test_bit(cnt, priv->queue_stopped), | 
|  | 1019 | txq->swq_id, | 
|  | 1020 | txq->swq_id & 0x80 ? txq->swq_id & 3 : | 
|  | 1021 | txq->swq_id, | 
|  | 1022 | txq->swq_id & 0x80 ? (txq->swq_id >> 2) & | 
|  | 1023 | 0x1f : txq->swq_id); | 
|  | 1024 | if (cnt >= 4) | 
|  | 1025 | continue; | 
|  | 1026 | /* for the ACs, display the stop count too */ | 
|  | 1027 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 1028 | "        stop-count: %d\n", | 
|  | 1029 | atomic_read(&priv->queue_stop_count[cnt])); | 
|  | 1030 | } | 
|  | 1031 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
|  | 1032 | kfree(buf); | 
|  | 1033 | return ret; | 
|  | 1034 | } | 
|  | 1035 |  | 
|  | 1036 | static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | 
|  | 1037 | char __user *user_buf, | 
|  | 1038 | size_t count, loff_t *ppos) { | 
|  | 1039 |  | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 1040 | struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 141b03e | 2009-08-07 15:41:41 -0700 | [diff] [blame] | 1041 | struct iwl_rx_queue *rxq = &priv->rxq; | 
|  | 1042 | char buf[256]; | 
|  | 1043 | int pos = 0; | 
|  | 1044 | const size_t bufsz = sizeof(buf); | 
|  | 1045 |  | 
|  | 1046 | pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", | 
|  | 1047 | rxq->read); | 
|  | 1048 | pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", | 
|  | 1049 | rxq->write); | 
|  | 1050 | pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", | 
|  | 1051 | rxq->free_count); | 
|  | 1052 | pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", | 
|  | 1053 | le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF); | 
|  | 1054 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
|  | 1055 | } | 
|  | 1056 |  | 
| Wey-Yi Guy | e8fe59a | 2009-08-07 15:41:42 -0700 | [diff] [blame] | 1057 | static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, | 
|  | 1058 | char __user *user_buf, | 
|  | 1059 | size_t count, loff_t *ppos) | 
|  | 1060 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 1061 | struct iwl_priv *priv = file->private_data; | 
| Abhijeet Kolekar | 17f36fc | 2010-04-16 10:03:54 -0700 | [diff] [blame] | 1062 | return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file, | 
|  | 1063 | user_buf, count, ppos); | 
| Wey-Yi Guy | e8fe59a | 2009-08-07 15:41:42 -0700 | [diff] [blame] | 1064 | } | 
|  | 1065 |  | 
|  | 1066 | static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | 
|  | 1067 | char __user *user_buf, | 
|  | 1068 | size_t count, loff_t *ppos) | 
|  | 1069 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 1070 | struct iwl_priv *priv = file->private_data; | 
| Abhijeet Kolekar | 17f36fc | 2010-04-16 10:03:54 -0700 | [diff] [blame] | 1071 | return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file, | 
|  | 1072 | user_buf, count, ppos); | 
| Wey-Yi Guy | e8fe59a | 2009-08-07 15:41:42 -0700 | [diff] [blame] | 1073 | } | 
|  | 1074 |  | 
|  | 1075 | static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, | 
|  | 1076 | char __user *user_buf, | 
|  | 1077 | size_t count, loff_t *ppos) | 
|  | 1078 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 1079 | struct iwl_priv *priv = file->private_data; | 
| Abhijeet Kolekar | 17f36fc | 2010-04-16 10:03:54 -0700 | [diff] [blame] | 1080 | return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file, | 
|  | 1081 | user_buf, count, ppos); | 
| Wey-Yi Guy | e8fe59a | 2009-08-07 15:41:42 -0700 | [diff] [blame] | 1082 | } | 
|  | 1083 |  | 
| Wey-Yi Guy | 5225935 | 2009-08-07 15:41:43 -0700 | [diff] [blame] | 1084 | static ssize_t iwl_dbgfs_sensitivity_read(struct file *file, | 
|  | 1085 | char __user *user_buf, | 
|  | 1086 | size_t count, loff_t *ppos) { | 
|  | 1087 |  | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 1088 | struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 5225935 | 2009-08-07 15:41:43 -0700 | [diff] [blame] | 1089 | int pos = 0; | 
|  | 1090 | int cnt = 0; | 
|  | 1091 | char *buf; | 
|  | 1092 | int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100; | 
|  | 1093 | ssize_t ret; | 
|  | 1094 | struct iwl_sensitivity_data *data; | 
|  | 1095 |  | 
|  | 1096 | data = &priv->sensitivity_data; | 
|  | 1097 | buf = kzalloc(bufsz, GFP_KERNEL); | 
|  | 1098 | if (!buf) { | 
|  | 1099 | IWL_ERR(priv, "Can not allocate Buffer\n"); | 
|  | 1100 | return -ENOMEM; | 
|  | 1101 | } | 
|  | 1102 |  | 
|  | 1103 | pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n", | 
|  | 1104 | data->auto_corr_ofdm); | 
|  | 1105 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 1106 | "auto_corr_ofdm_mrc:\t\t %u\n", | 
|  | 1107 | data->auto_corr_ofdm_mrc); | 
|  | 1108 | pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n", | 
|  | 1109 | data->auto_corr_ofdm_x1); | 
|  | 1110 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 1111 | "auto_corr_ofdm_mrc_x1:\t\t %u\n", | 
|  | 1112 | data->auto_corr_ofdm_mrc_x1); | 
|  | 1113 | pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n", | 
|  | 1114 | data->auto_corr_cck); | 
|  | 1115 | pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n", | 
|  | 1116 | data->auto_corr_cck_mrc); | 
|  | 1117 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 1118 | "last_bad_plcp_cnt_ofdm:\t\t %u\n", | 
|  | 1119 | data->last_bad_plcp_cnt_ofdm); | 
|  | 1120 | pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n", | 
|  | 1121 | data->last_fa_cnt_ofdm); | 
|  | 1122 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 1123 | "last_bad_plcp_cnt_cck:\t\t %u\n", | 
|  | 1124 | data->last_bad_plcp_cnt_cck); | 
|  | 1125 | pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n", | 
|  | 1126 | data->last_fa_cnt_cck); | 
|  | 1127 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n", | 
|  | 1128 | data->nrg_curr_state); | 
|  | 1129 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n", | 
|  | 1130 | data->nrg_prev_state); | 
|  | 1131 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t"); | 
|  | 1132 | for (cnt = 0; cnt < 10; cnt++) { | 
|  | 1133 | pos += scnprintf(buf + pos, bufsz - pos, " %u", | 
|  | 1134 | data->nrg_value[cnt]); | 
|  | 1135 | } | 
|  | 1136 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
|  | 1137 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t"); | 
|  | 1138 | for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) { | 
|  | 1139 | pos += scnprintf(buf + pos, bufsz - pos, " %u", | 
|  | 1140 | data->nrg_silence_rssi[cnt]); | 
|  | 1141 | } | 
|  | 1142 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
|  | 1143 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n", | 
|  | 1144 | data->nrg_silence_ref); | 
|  | 1145 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n", | 
|  | 1146 | data->nrg_energy_idx); | 
|  | 1147 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n", | 
|  | 1148 | data->nrg_silence_idx); | 
|  | 1149 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n", | 
|  | 1150 | data->nrg_th_cck); | 
|  | 1151 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 1152 | "nrg_auto_corr_silence_diff:\t %u\n", | 
|  | 1153 | data->nrg_auto_corr_silence_diff); | 
|  | 1154 | pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n", | 
|  | 1155 | data->num_in_cck_no_fa); | 
|  | 1156 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n", | 
|  | 1157 | data->nrg_th_ofdm); | 
|  | 1158 |  | 
|  | 1159 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
|  | 1160 | kfree(buf); | 
|  | 1161 | return ret; | 
|  | 1162 | } | 
|  | 1163 |  | 
|  | 1164 |  | 
|  | 1165 | static ssize_t iwl_dbgfs_chain_noise_read(struct file *file, | 
|  | 1166 | char __user *user_buf, | 
|  | 1167 | size_t count, loff_t *ppos) { | 
|  | 1168 |  | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 1169 | struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | 5225935 | 2009-08-07 15:41:43 -0700 | [diff] [blame] | 1170 | int pos = 0; | 
|  | 1171 | int cnt = 0; | 
|  | 1172 | char *buf; | 
|  | 1173 | int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100; | 
|  | 1174 | ssize_t ret; | 
|  | 1175 | struct iwl_chain_noise_data *data; | 
|  | 1176 |  | 
|  | 1177 | data = &priv->chain_noise_data; | 
|  | 1178 | buf = kzalloc(bufsz, GFP_KERNEL); | 
|  | 1179 | if (!buf) { | 
|  | 1180 | IWL_ERR(priv, "Can not allocate Buffer\n"); | 
|  | 1181 | return -ENOMEM; | 
|  | 1182 | } | 
|  | 1183 |  | 
|  | 1184 | pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n", | 
|  | 1185 | data->active_chains); | 
|  | 1186 | pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n", | 
|  | 1187 | data->chain_noise_a); | 
|  | 1188 | pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n", | 
|  | 1189 | data->chain_noise_b); | 
|  | 1190 | pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n", | 
|  | 1191 | data->chain_noise_c); | 
|  | 1192 | pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n", | 
|  | 1193 | data->chain_signal_a); | 
|  | 1194 | pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n", | 
|  | 1195 | data->chain_signal_b); | 
|  | 1196 | pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n", | 
|  | 1197 | data->chain_signal_c); | 
|  | 1198 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n", | 
|  | 1199 | data->beacon_count); | 
|  | 1200 |  | 
|  | 1201 | pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t"); | 
|  | 1202 | for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { | 
|  | 1203 | pos += scnprintf(buf + pos, bufsz - pos, " %u", | 
|  | 1204 | data->disconn_array[cnt]); | 
|  | 1205 | } | 
|  | 1206 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
|  | 1207 | pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t"); | 
|  | 1208 | for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { | 
|  | 1209 | pos += scnprintf(buf + pos, bufsz - pos, " %u", | 
|  | 1210 | data->delta_gain_code[cnt]); | 
|  | 1211 | } | 
|  | 1212 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 
|  | 1213 | pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n", | 
|  | 1214 | data->radio_write); | 
|  | 1215 | pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n", | 
|  | 1216 | data->state); | 
|  | 1217 |  | 
|  | 1218 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
|  | 1219 | kfree(buf); | 
|  | 1220 | return ret; | 
|  | 1221 | } | 
|  | 1222 |  | 
| Wey-Yi Guy | c09430a | 2009-10-16 14:25:50 -0700 | [diff] [blame] | 1223 | static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, | 
|  | 1224 | char __user *user_buf, | 
|  | 1225 | size_t count, loff_t *ppos) | 
|  | 1226 | { | 
| H Hartley Sweeten | 28f63a4 | 2010-01-08 16:14:10 -0700 | [diff] [blame] | 1227 | struct iwl_priv *priv = file->private_data; | 
| Wey-Yi Guy | c09430a | 2009-10-16 14:25:50 -0700 | [diff] [blame] | 1228 | char buf[60]; | 
|  | 1229 | int pos = 0; | 
|  | 1230 | const size_t bufsz = sizeof(buf); | 
|  | 1231 | u32 pwrsave_status; | 
|  | 1232 |  | 
|  | 1233 | pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) & | 
|  | 1234 | CSR_GP_REG_POWER_SAVE_STATUS_MSK; | 
|  | 1235 |  | 
|  | 1236 | pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); | 
|  | 1237 | pos += scnprintf(buf + pos, bufsz - pos, "%s\n", | 
|  | 1238 | (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" : | 
|  | 1239 | (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" : | 
|  | 1240 | (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" : | 
|  | 1241 | "error"); | 
|  | 1242 |  | 
|  | 1243 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
|  | 1244 | } | 
|  | 1245 |  | 
| Wey-Yi Guy | 7163b8a | 2009-11-20 12:04:56 -0800 | [diff] [blame] | 1246 | 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] | 1247 | const char __user *user_buf, | 
|  | 1248 | size_t count, loff_t *ppos) | 
|  | 1249 | { | 
|  | 1250 | struct iwl_priv *priv = file->private_data; | 
|  | 1251 | char buf[8]; | 
|  | 1252 | int buf_size; | 
|  | 1253 | int clear; | 
|  | 1254 |  | 
|  | 1255 | memset(buf, 0, sizeof(buf)); | 
|  | 1256 | buf_size = min(count, sizeof(buf) -  1); | 
|  | 1257 | if (copy_from_user(buf, user_buf, buf_size)) | 
|  | 1258 | return -EFAULT; | 
|  | 1259 | if (sscanf(buf, "%d", &clear) != 1) | 
|  | 1260 | return -EFAULT; | 
|  | 1261 |  | 
|  | 1262 | /* make request to uCode to retrieve statistics information */ | 
|  | 1263 | mutex_lock(&priv->mutex); | 
|  | 1264 | iwl_send_statistics_request(priv, CMD_SYNC, true); | 
|  | 1265 | mutex_unlock(&priv->mutex); | 
|  | 1266 |  | 
|  | 1267 | return count; | 
|  | 1268 | } | 
|  | 1269 |  | 
| Wey-Yi Guy | 696bdee | 2009-12-10 14:37:25 -0800 | [diff] [blame] | 1270 | static ssize_t iwl_dbgfs_csr_write(struct file *file, | 
|  | 1271 | const char __user *user_buf, | 
|  | 1272 | size_t count, loff_t *ppos) | 
|  | 1273 | { | 
|  | 1274 | struct iwl_priv *priv = file->private_data; | 
|  | 1275 | char buf[8]; | 
|  | 1276 | int buf_size; | 
|  | 1277 | int csr; | 
|  | 1278 |  | 
|  | 1279 | memset(buf, 0, sizeof(buf)); | 
|  | 1280 | buf_size = min(count, sizeof(buf) -  1); | 
|  | 1281 | if (copy_from_user(buf, user_buf, buf_size)) | 
|  | 1282 | return -EFAULT; | 
|  | 1283 | if (sscanf(buf, "%d", &csr) != 1) | 
|  | 1284 | return -EFAULT; | 
|  | 1285 |  | 
|  | 1286 | if (priv->cfg->ops->lib->dump_csr) | 
|  | 1287 | priv->cfg->ops->lib->dump_csr(priv); | 
|  | 1288 |  | 
|  | 1289 | return count; | 
|  | 1290 | } | 
|  | 1291 |  | 
| Wey-Yi Guy | a9e1cb6 | 2009-12-10 14:37:26 -0800 | [diff] [blame] | 1292 | static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, | 
|  | 1293 | char __user *user_buf, | 
|  | 1294 | size_t count, loff_t *ppos) { | 
|  | 1295 |  | 
|  | 1296 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 
|  | 1297 | int pos = 0; | 
|  | 1298 | char buf[128]; | 
|  | 1299 | const size_t bufsz = sizeof(buf); | 
| Wey-Yi Guy | a9e1cb6 | 2009-12-10 14:37:26 -0800 | [diff] [blame] | 1300 |  | 
|  | 1301 | pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n", | 
|  | 1302 | priv->event_log.ucode_trace ? "On" : "Off"); | 
|  | 1303 | pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n", | 
|  | 1304 | priv->event_log.non_wraps_count); | 
|  | 1305 | pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n", | 
|  | 1306 | priv->event_log.wraps_once_count); | 
|  | 1307 | pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n", | 
|  | 1308 | priv->event_log.wraps_more_count); | 
|  | 1309 |  | 
| Wey-Yi Guy | 4967c31 | 2010-02-18 15:22:07 -0800 | [diff] [blame] | 1310 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
| Wey-Yi Guy | a9e1cb6 | 2009-12-10 14:37:26 -0800 | [diff] [blame] | 1311 | } | 
|  | 1312 |  | 
|  | 1313 | static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, | 
|  | 1314 | const char __user *user_buf, | 
|  | 1315 | size_t count, loff_t *ppos) | 
|  | 1316 | { | 
|  | 1317 | struct iwl_priv *priv = file->private_data; | 
|  | 1318 | char buf[8]; | 
|  | 1319 | int buf_size; | 
|  | 1320 | int trace; | 
|  | 1321 |  | 
|  | 1322 | memset(buf, 0, sizeof(buf)); | 
|  | 1323 | buf_size = min(count, sizeof(buf) -  1); | 
|  | 1324 | if (copy_from_user(buf, user_buf, buf_size)) | 
|  | 1325 | return -EFAULT; | 
|  | 1326 | if (sscanf(buf, "%d", &trace) != 1) | 
|  | 1327 | return -EFAULT; | 
|  | 1328 |  | 
|  | 1329 | if (trace) { | 
|  | 1330 | priv->event_log.ucode_trace = true; | 
|  | 1331 | /* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */ | 
|  | 1332 | mod_timer(&priv->ucode_trace, | 
|  | 1333 | jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD)); | 
|  | 1334 | } else { | 
|  | 1335 | priv->event_log.ucode_trace = false; | 
|  | 1336 | del_timer_sync(&priv->ucode_trace); | 
|  | 1337 | } | 
|  | 1338 |  | 
|  | 1339 | return count; | 
|  | 1340 | } | 
|  | 1341 |  | 
| Johannes Berg | 6098720 | 2010-02-18 00:36:07 -0800 | [diff] [blame] | 1342 | static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file, | 
|  | 1343 | char __user *user_buf, | 
|  | 1344 | size_t count, loff_t *ppos) { | 
|  | 1345 |  | 
|  | 1346 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 
|  | 1347 | int len = 0; | 
|  | 1348 | char buf[20]; | 
|  | 1349 |  | 
|  | 1350 | len = sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active_rxon.flags)); | 
|  | 1351 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 
|  | 1352 | } | 
|  | 1353 |  | 
|  | 1354 | static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file, | 
|  | 1355 | char __user *user_buf, | 
|  | 1356 | size_t count, loff_t *ppos) { | 
|  | 1357 |  | 
|  | 1358 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 
|  | 1359 | int len = 0; | 
|  | 1360 | char buf[20]; | 
|  | 1361 |  | 
|  | 1362 | len = sprintf(buf, "0x%04X\n", | 
|  | 1363 | le32_to_cpu(priv->active_rxon.filter_flags)); | 
|  | 1364 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 
|  | 1365 | } | 
|  | 1366 |  | 
| Wey-Yi Guy | 1b3eb82 | 2010-01-15 13:43:39 -0800 | [diff] [blame] | 1367 | static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, | 
|  | 1368 | char __user *user_buf, | 
|  | 1369 | size_t count, loff_t *ppos) | 
|  | 1370 | { | 
|  | 1371 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 
|  | 1372 | char *buf; | 
|  | 1373 | int pos = 0; | 
|  | 1374 | ssize_t ret = -EFAULT; | 
|  | 1375 |  | 
|  | 1376 | if (priv->cfg->ops->lib->dump_fh) { | 
|  | 1377 | ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true); | 
|  | 1378 | if (buf) { | 
|  | 1379 | ret = simple_read_from_buffer(user_buf, | 
|  | 1380 | count, ppos, buf, pos); | 
|  | 1381 | kfree(buf); | 
|  | 1382 | } | 
|  | 1383 | } | 
|  | 1384 |  | 
|  | 1385 | return ret; | 
|  | 1386 | } | 
|  | 1387 |  | 
| Wey-Yi Guy | a13d276 | 2010-01-22 14:22:42 -0800 | [diff] [blame] | 1388 | static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file, | 
|  | 1389 | char __user *user_buf, | 
|  | 1390 | size_t count, loff_t *ppos) { | 
|  | 1391 |  | 
|  | 1392 | struct iwl_priv *priv = file->private_data; | 
|  | 1393 | int pos = 0; | 
|  | 1394 | char buf[12]; | 
|  | 1395 | const size_t bufsz = sizeof(buf); | 
| Wey-Yi Guy | a13d276 | 2010-01-22 14:22:42 -0800 | [diff] [blame] | 1396 |  | 
|  | 1397 | pos += scnprintf(buf + pos, bufsz - pos, "%d\n", | 
|  | 1398 | priv->missed_beacon_threshold); | 
|  | 1399 |  | 
| Wey-Yi Guy | 4967c31 | 2010-02-18 15:22:07 -0800 | [diff] [blame] | 1400 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
| Wey-Yi Guy | a13d276 | 2010-01-22 14:22:42 -0800 | [diff] [blame] | 1401 | } | 
|  | 1402 |  | 
|  | 1403 | static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, | 
|  | 1404 | const char __user *user_buf, | 
|  | 1405 | size_t count, loff_t *ppos) | 
|  | 1406 | { | 
|  | 1407 | struct iwl_priv *priv = file->private_data; | 
|  | 1408 | char buf[8]; | 
|  | 1409 | int buf_size; | 
|  | 1410 | int missed; | 
|  | 1411 |  | 
|  | 1412 | memset(buf, 0, sizeof(buf)); | 
|  | 1413 | buf_size = min(count, sizeof(buf) -  1); | 
|  | 1414 | if (copy_from_user(buf, user_buf, buf_size)) | 
|  | 1415 | return -EFAULT; | 
|  | 1416 | if (sscanf(buf, "%d", &missed) != 1) | 
|  | 1417 | return -EINVAL; | 
|  | 1418 |  | 
|  | 1419 | if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN || | 
|  | 1420 | missed > IWL_MISSED_BEACON_THRESHOLD_MAX) | 
|  | 1421 | priv->missed_beacon_threshold = | 
|  | 1422 | IWL_MISSED_BEACON_THRESHOLD_DEF; | 
|  | 1423 | else | 
|  | 1424 | priv->missed_beacon_threshold = missed; | 
|  | 1425 |  | 
|  | 1426 | return count; | 
|  | 1427 | } | 
|  | 1428 |  | 
| Trieu 'Andrew' Nguyen | 3e4fb5f | 2010-01-22 14:22:46 -0800 | [diff] [blame] | 1429 | static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, | 
|  | 1430 | char __user *user_buf, | 
|  | 1431 | size_t count, loff_t *ppos) { | 
|  | 1432 |  | 
|  | 1433 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 
|  | 1434 | int pos = 0; | 
|  | 1435 | char buf[12]; | 
|  | 1436 | const size_t bufsz = sizeof(buf); | 
| Trieu 'Andrew' Nguyen | 3e4fb5f | 2010-01-22 14:22:46 -0800 | [diff] [blame] | 1437 |  | 
|  | 1438 | pos += scnprintf(buf + pos, bufsz - pos, "%u\n", | 
|  | 1439 | priv->cfg->plcp_delta_threshold); | 
|  | 1440 |  | 
| Wey-Yi Guy | 4967c31 | 2010-02-18 15:22:07 -0800 | [diff] [blame] | 1441 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
| Trieu 'Andrew' Nguyen | 3e4fb5f | 2010-01-22 14:22:46 -0800 | [diff] [blame] | 1442 | } | 
|  | 1443 |  | 
|  | 1444 | static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, | 
|  | 1445 | const char __user *user_buf, | 
|  | 1446 | size_t count, loff_t *ppos) { | 
|  | 1447 |  | 
|  | 1448 | struct iwl_priv *priv = file->private_data; | 
|  | 1449 | char buf[8]; | 
|  | 1450 | int buf_size; | 
|  | 1451 | int plcp; | 
|  | 1452 |  | 
|  | 1453 | memset(buf, 0, sizeof(buf)); | 
|  | 1454 | buf_size = min(count, sizeof(buf) -  1); | 
|  | 1455 | if (copy_from_user(buf, user_buf, buf_size)) | 
|  | 1456 | return -EFAULT; | 
|  | 1457 | if (sscanf(buf, "%d", &plcp) != 1) | 
|  | 1458 | return -EINVAL; | 
|  | 1459 | if ((plcp <= IWL_MAX_PLCP_ERR_THRESHOLD_MIN) || | 
|  | 1460 | (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX)) | 
|  | 1461 | priv->cfg->plcp_delta_threshold = | 
|  | 1462 | IWL_MAX_PLCP_ERR_THRESHOLD_DEF; | 
|  | 1463 | else | 
|  | 1464 | priv->cfg->plcp_delta_threshold = plcp; | 
|  | 1465 | return count; | 
|  | 1466 | } | 
|  | 1467 |  | 
| Wey-Yi Guy | 528c312 | 2010-02-18 22:03:07 -0800 | [diff] [blame] | 1468 | static ssize_t iwl_dbgfs_force_reset_read(struct file *file, | 
|  | 1469 | char __user *user_buf, | 
|  | 1470 | size_t count, loff_t *ppos) { | 
|  | 1471 |  | 
|  | 1472 | struct iwl_priv *priv = file->private_data; | 
|  | 1473 | int i, pos = 0; | 
|  | 1474 | char buf[300]; | 
|  | 1475 | const size_t bufsz = sizeof(buf); | 
|  | 1476 | struct iwl_force_reset *force_reset; | 
|  | 1477 |  | 
|  | 1478 | for (i = 0; i < IWL_MAX_FORCE_RESET; i++) { | 
|  | 1479 | force_reset = &priv->force_reset[i]; | 
|  | 1480 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 1481 | "Force reset method %d\n", i); | 
|  | 1482 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 1483 | "\tnumber of reset request: %d\n", | 
|  | 1484 | force_reset->reset_request_count); | 
|  | 1485 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 1486 | "\tnumber of reset request success: %d\n", | 
|  | 1487 | force_reset->reset_success_count); | 
|  | 1488 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 1489 | "\tnumber of reset request reject: %d\n", | 
|  | 1490 | force_reset->reset_reject_count); | 
|  | 1491 | pos += scnprintf(buf + pos, bufsz - pos, | 
|  | 1492 | "\treset duration: %lu\n", | 
|  | 1493 | force_reset->reset_duration); | 
|  | 1494 | } | 
|  | 1495 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 
|  | 1496 | } | 
|  | 1497 |  | 
| Wey-Yi Guy | 04cafd7 | 2010-02-03 11:47:20 -0800 | [diff] [blame] | 1498 | static ssize_t iwl_dbgfs_force_reset_write(struct file *file, | 
|  | 1499 | const char __user *user_buf, | 
|  | 1500 | size_t count, loff_t *ppos) { | 
|  | 1501 |  | 
|  | 1502 | struct iwl_priv *priv = file->private_data; | 
|  | 1503 | char buf[8]; | 
|  | 1504 | int buf_size; | 
|  | 1505 | int reset, ret; | 
|  | 1506 |  | 
|  | 1507 | memset(buf, 0, sizeof(buf)); | 
|  | 1508 | buf_size = min(count, sizeof(buf) -  1); | 
|  | 1509 | if (copy_from_user(buf, user_buf, buf_size)) | 
|  | 1510 | return -EFAULT; | 
|  | 1511 | if (sscanf(buf, "%d", &reset) != 1) | 
|  | 1512 | return -EINVAL; | 
|  | 1513 | switch (reset) { | 
|  | 1514 | case IWL_RF_RESET: | 
|  | 1515 | case IWL_FW_RESET: | 
|  | 1516 | ret = iwl_force_reset(priv, reset); | 
|  | 1517 | break; | 
|  | 1518 | default: | 
|  | 1519 | return -EINVAL; | 
|  | 1520 | } | 
|  | 1521 | return ret ? ret : count; | 
|  | 1522 | } | 
|  | 1523 |  | 
| Wey-Yi Guy | 7163b8a | 2009-11-20 12:04:56 -0800 | [diff] [blame] | 1524 | DEBUGFS_READ_FILE_OPS(rx_statistics); | 
|  | 1525 | DEBUGFS_READ_FILE_OPS(tx_statistics); | 
| Wey-Yi Guy | 20594eb | 2009-08-07 15:41:39 -0700 | [diff] [blame] | 1526 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | 
| Wey-Yi Guy | 141b03e | 2009-08-07 15:41:41 -0700 | [diff] [blame] | 1527 | DEBUGFS_READ_FILE_OPS(rx_queue); | 
|  | 1528 | DEBUGFS_READ_FILE_OPS(tx_queue); | 
| Wey-Yi Guy | e8fe59a | 2009-08-07 15:41:42 -0700 | [diff] [blame] | 1529 | DEBUGFS_READ_FILE_OPS(ucode_rx_stats); | 
|  | 1530 | DEBUGFS_READ_FILE_OPS(ucode_tx_stats); | 
|  | 1531 | DEBUGFS_READ_FILE_OPS(ucode_general_stats); | 
| Wey-Yi Guy | 5225935 | 2009-08-07 15:41:43 -0700 | [diff] [blame] | 1532 | DEBUGFS_READ_FILE_OPS(sensitivity); | 
|  | 1533 | DEBUGFS_READ_FILE_OPS(chain_noise); | 
| Wey-Yi Guy | c09430a | 2009-10-16 14:25:50 -0700 | [diff] [blame] | 1534 | DEBUGFS_READ_FILE_OPS(power_save_status); | 
| Wey-Yi Guy | 7163b8a | 2009-11-20 12:04:56 -0800 | [diff] [blame] | 1535 | DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); | 
|  | 1536 | DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); | 
| Wey-Yi Guy | 696bdee | 2009-12-10 14:37:25 -0800 | [diff] [blame] | 1537 | DEBUGFS_WRITE_FILE_OPS(csr); | 
| Wey-Yi Guy | a9e1cb6 | 2009-12-10 14:37:26 -0800 | [diff] [blame] | 1538 | DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); | 
| Wey-Yi Guy | 1b3eb82 | 2010-01-15 13:43:39 -0800 | [diff] [blame] | 1539 | DEBUGFS_READ_FILE_OPS(fh_reg); | 
| Wey-Yi Guy | a13d276 | 2010-01-22 14:22:42 -0800 | [diff] [blame] | 1540 | DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); | 
| Trieu 'Andrew' Nguyen | 3e4fb5f | 2010-01-22 14:22:46 -0800 | [diff] [blame] | 1541 | DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); | 
| Wey-Yi Guy | 528c312 | 2010-02-18 22:03:07 -0800 | [diff] [blame] | 1542 | DEBUGFS_READ_WRITE_FILE_OPS(force_reset); | 
| Johannes Berg | 6098720 | 2010-02-18 00:36:07 -0800 | [diff] [blame] | 1543 | DEBUGFS_READ_FILE_OPS(rxon_flags); | 
|  | 1544 | DEBUGFS_READ_FILE_OPS(rxon_filter_flags); | 
| Wey-Yi Guy | 20594eb | 2009-08-07 15:41:39 -0700 | [diff] [blame] | 1545 |  | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1546 | /* | 
|  | 1547 | * Create the debugfs files and directories | 
|  | 1548 | * | 
|  | 1549 | */ | 
|  | 1550 | int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | 
|  | 1551 | { | 
| Zhu Yi | 95b1a82 | 2008-05-29 16:34:50 +0800 | [diff] [blame] | 1552 | struct dentry *phyd = priv->hw->wiphy->debugfsdir; | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1553 | struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1554 |  | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1555 | dir_drv = debugfs_create_dir(name, phyd); | 
|  | 1556 | if (!dir_drv) | 
|  | 1557 | return -ENOMEM; | 
|  | 1558 |  | 
|  | 1559 | priv->debugfs_dir = dir_drv; | 
|  | 1560 |  | 
|  | 1561 | dir_data = debugfs_create_dir("data", dir_drv); | 
|  | 1562 | if (!dir_data) | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1563 | goto err; | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1564 | dir_rf = debugfs_create_dir("rf", dir_drv); | 
|  | 1565 | if (!dir_rf) | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1566 | goto err; | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1567 | dir_debug = debugfs_create_dir("debug", dir_drv); | 
|  | 1568 | if (!dir_debug) | 
|  | 1569 | goto err; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1570 |  | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1571 | DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); | 
|  | 1572 | DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); | 
|  | 1573 | DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR); | 
|  | 1574 | DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); | 
|  | 1575 | DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); | 
|  | 1576 | DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); | 
|  | 1577 | DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); | 
|  | 1578 | DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); | 
|  | 1579 | DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR); | 
| Wey-Yi Guy | 381733c | 2010-04-25 09:39:46 -0700 | [diff] [blame] | 1580 | if (!priv->cfg->broken_powersave) { | 
|  | 1581 | DEBUGFS_ADD_FILE(sleep_level_override, dir_data, | 
|  | 1582 | S_IWUSR | S_IRUSR); | 
|  | 1583 | DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); | 
|  | 1584 | } | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1585 | DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR); | 
|  | 1586 | DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); | 
|  | 1587 | DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); | 
|  | 1588 | DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); | 
|  | 1589 | DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); | 
|  | 1590 | DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); | 
|  | 1591 | DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1592 | DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); | 
|  | 1593 | DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); | 
|  | 1594 | DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); | 
|  | 1595 | DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR); | 
|  | 1596 | DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); | 
|  | 1597 | DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1598 | DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); | 
| Wey-Yi Guy | 528c312 | 2010-02-18 22:03:07 -0800 | [diff] [blame] | 1599 | DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); | 
| Abhijeet Kolekar | b8c7626 | 2010-04-08 15:29:07 -0700 | [diff] [blame] | 1600 | DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); | 
|  | 1601 | DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); | 
|  | 1602 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); | 
|  | 1603 |  | 
| Wey-Yi Guy | 65d1f89 | 2010-04-25 15:41:43 -0700 | [diff] [blame] | 1604 | if (priv->cfg->sensitivity_calib_by_driver) | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1605 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); | 
| Wey-Yi Guy | 65d1f89 | 2010-04-25 15:41:43 -0700 | [diff] [blame] | 1606 | if (priv->cfg->chain_noise_calib_by_driver) | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1607 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); | 
| Wey-Yi Guy | 6e5c800 | 2010-04-27 14:00:28 -0700 | [diff] [blame] | 1608 | if (priv->cfg->ucode_tracing) | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1609 | DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); | 
| Johannes Berg | 6098720 | 2010-02-18 00:36:07 -0800 | [diff] [blame] | 1610 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); | 
|  | 1611 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); | 
| Wey-Yi Guy | 65d1f89 | 2010-04-25 15:41:43 -0700 | [diff] [blame] | 1612 | if (priv->cfg->sensitivity_calib_by_driver) | 
|  | 1613 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, | 
|  | 1614 | &priv->disable_sens_cal); | 
|  | 1615 | if (priv->cfg->chain_noise_calib_by_driver) | 
|  | 1616 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, | 
|  | 1617 | &priv->disable_chain_noise_cal); | 
| Wey-Yi Guy | 4e7033e | 2010-04-27 14:33:33 -0700 | [diff] [blame] | 1618 | if (priv->cfg->tx_power_by_driver) | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1619 | DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, | 
| Wey-Yi Guy | 030b865 | 2009-06-12 13:22:55 -0700 | [diff] [blame] | 1620 | &priv->disable_tx_power_cal); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1621 | return 0; | 
|  | 1622 |  | 
|  | 1623 | err: | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1624 | IWL_ERR(priv, "Can't create the debugfs directory\n"); | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1625 | iwl_dbgfs_unregister(priv); | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1626 | return -ENOMEM; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1627 | } | 
|  | 1628 | EXPORT_SYMBOL(iwl_dbgfs_register); | 
|  | 1629 |  | 
|  | 1630 | /** | 
|  | 1631 | * Remove the debugfs files and directories | 
|  | 1632 | * | 
|  | 1633 | */ | 
|  | 1634 | void iwl_dbgfs_unregister(struct iwl_priv *priv) | 
|  | 1635 | { | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1636 | if (!priv->debugfs_dir) | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1637 | return; | 
|  | 1638 |  | 
| Johannes Berg | 4c84a8f | 2010-01-22 14:22:54 -0800 | [diff] [blame] | 1639 | debugfs_remove_recursive(priv->debugfs_dir); | 
|  | 1640 | priv->debugfs_dir = NULL; | 
| Tomas Winkler | 712b6cf | 2008-03-12 16:58:52 -0700 | [diff] [blame] | 1641 | } | 
|  | 1642 | EXPORT_SYMBOL(iwl_dbgfs_unregister); | 
|  | 1643 |  | 
|  | 1644 |  | 
| Tomas Winkler | 445c2df | 2008-05-15 13:54:16 +0800 | [diff] [blame] | 1645 |  |