blob: e79794a7e326eaa4e0820ea556e5c28a4fbdaa84 [file] [log] [blame]
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001/******************************************************************************
2 *
3 * GPL LICENSE SUMMARY
4 *
5 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
19 * USA
20 *
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
23 *
24 * Contact Information:
25 * Intel Linux Wireless <ilw@linux.intel.com>
26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27 *****************************************************************************/
28#include <linux/ieee80211.h>
29#include <net/mac80211.h>
30
Stanislaw Gruszka98613be2011-11-15 14:19:34 +010031#include "common.h"
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080032
33/* create and remove of files */
34#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +020035 if (!debugfs_create_file(#name, mode, parent, il, \
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020036 &il_dbgfs_##name##_ops)) \
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080037 goto err; \
38} while (0)
39
40#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \
41 struct dentry *__tmp; \
42 __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \
43 parent, ptr); \
44 if (IS_ERR(__tmp) || !__tmp) \
45 goto err; \
46} while (0)
47
48#define DEBUGFS_ADD_X32(name, parent, ptr) do { \
49 struct dentry *__tmp; \
50 __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \
51 parent, ptr); \
52 if (IS_ERR(__tmp) || !__tmp) \
53 goto err; \
54} while (0)
55
56/* file operation */
57#define DEBUGFS_READ_FUNC(name) \
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020058static ssize_t il_dbgfs_##name##_read(struct file *file, \
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080059 char __user *user_buf, \
60 size_t count, loff_t *ppos);
61
62#define DEBUGFS_WRITE_FUNC(name) \
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020063static ssize_t il_dbgfs_##name##_write(struct file *file, \
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080064 const char __user *user_buf, \
65 size_t count, loff_t *ppos);
66
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080067static int
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020068il_dbgfs_open_file_generic(struct inode *inode, struct file *file)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080069{
70 file->private_data = inode->i_private;
71 return 0;
72}
73
74#define DEBUGFS_READ_FILE_OPS(name) \
75 DEBUGFS_READ_FUNC(name); \
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020076static const struct file_operations il_dbgfs_##name##_ops = { \
77 .read = il_dbgfs_##name##_read, \
78 .open = il_dbgfs_open_file_generic, \
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080079 .llseek = generic_file_llseek, \
80};
81
82#define DEBUGFS_WRITE_FILE_OPS(name) \
83 DEBUGFS_WRITE_FUNC(name); \
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020084static const struct file_operations il_dbgfs_##name##_ops = { \
85 .write = il_dbgfs_##name##_write, \
86 .open = il_dbgfs_open_file_generic, \
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080087 .llseek = generic_file_llseek, \
88};
89
90#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
91 DEBUGFS_READ_FUNC(name); \
92 DEBUGFS_WRITE_FUNC(name); \
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020093static const struct file_operations il_dbgfs_##name##_ops = { \
94 .write = il_dbgfs_##name##_write, \
95 .read = il_dbgfs_##name##_read, \
96 .open = il_dbgfs_open_file_generic, \
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080097 .llseek = generic_file_llseek, \
98};
99
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100100static ssize_t
101il_dbgfs_tx_stats_read(struct file *file, char __user * user_buf, size_t count,
102 loff_t * ppos)
103{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800104
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200105 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800106 char *buf;
107 int pos = 0;
108
109 int cnt;
110 ssize_t ret;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100111 const size_t bufsz =
112 100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800113 buf = kzalloc(bufsz, GFP_KERNEL);
114 if (!buf)
115 return -ENOMEM;
116 pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
117 for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100118 pos +=
119 scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
120 il_get_mgmt_string(cnt), il->tx_stats.mgmt[cnt]);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800121 }
122 pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
123 for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100124 pos +=
125 scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
126 il_get_ctrl_string(cnt), il->tx_stats.ctrl[cnt]);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800127 }
128 pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100129 pos +=
130 scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
131 il->tx_stats.data_cnt);
132 pos +=
133 scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
134 il->tx_stats.data_bytes);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800135 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
136 kfree(buf);
137 return ret;
138}
139
140static ssize_t
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +0200141il_dbgfs_clear_traffic_stats_write(struct file *file,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100142 const char __user * user_buf, size_t count,
143 loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800144{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200145 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800146 u32 clear_flag;
147 char buf[8];
148 int buf_size;
149
150 memset(buf, 0, sizeof(buf));
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100151 buf_size = min(count, sizeof(buf) - 1);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800152 if (copy_from_user(buf, user_buf, buf_size))
153 return -EFAULT;
154 if (sscanf(buf, "%x", &clear_flag) != 1)
155 return -EFAULT;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200156 il_clear_traffic_stats(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800157
158 return count;
159}
160
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100161static ssize_t
162il_dbgfs_rx_stats_read(struct file *file, char __user * user_buf, size_t count,
163 loff_t * ppos)
164{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800165
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200166 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800167 char *buf;
168 int pos = 0;
169 int cnt;
170 ssize_t ret;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100171 const size_t bufsz =
172 100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800173 buf = kzalloc(bufsz, GFP_KERNEL);
174 if (!buf)
175 return -ENOMEM;
176
177 pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
178 for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100179 pos +=
180 scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
181 il_get_mgmt_string(cnt), il->rx_stats.mgmt[cnt]);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800182 }
183 pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
184 for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100185 pos +=
186 scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
187 il_get_ctrl_string(cnt), il->rx_stats.ctrl[cnt]);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800188 }
189 pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100190 pos +=
191 scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
192 il->rx_stats.data_cnt);
193 pos +=
194 scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
195 il->rx_stats.data_bytes);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800196
197 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
198 kfree(buf);
199 return ret;
200}
201
202#define BYTE1_MASK 0x000000ff;
203#define BYTE2_MASK 0x0000ffff;
204#define BYTE3_MASK 0x00ffffff;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100205static ssize_t
206il_dbgfs_sram_read(struct file *file, char __user * user_buf, size_t count,
207 loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800208{
209 u32 val;
210 char *buf;
211 ssize_t ret;
212 int i;
213 int pos = 0;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200214 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800215 size_t bufsz;
216
217 /* default is to dump the entire data segment */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200218 if (!il->dbgfs_sram_offset && !il->dbgfs_sram_len) {
219 il->dbgfs_sram_offset = 0x800000;
220 if (il->ucode_type == UCODE_INIT)
221 il->dbgfs_sram_len = il->ucode_init_data.len;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800222 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200223 il->dbgfs_sram_len = il->ucode_data.len;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800224 }
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100225 bufsz = 30 + il->dbgfs_sram_len * sizeof(char) * 10;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800226 buf = kmalloc(bufsz, GFP_KERNEL);
227 if (!buf)
228 return -ENOMEM;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100229 pos +=
230 scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
231 il->dbgfs_sram_len);
232 pos +=
233 scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
234 il->dbgfs_sram_offset);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200235 for (i = il->dbgfs_sram_len; i > 0; i -= 4) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100236 val =
237 il_read_targ_mem(il,
238 il->dbgfs_sram_offset +
239 il->dbgfs_sram_len - i);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800240 if (i < 4) {
241 switch (i) {
242 case 1:
243 val &= BYTE1_MASK;
244 break;
245 case 2:
246 val &= BYTE2_MASK;
247 break;
248 case 3:
249 val &= BYTE3_MASK;
250 break;
251 }
252 }
253 if (!(i % 16))
254 pos += scnprintf(buf + pos, bufsz - pos, "\n");
255 pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
256 }
257 pos += scnprintf(buf + pos, bufsz - pos, "\n");
258
259 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
260 kfree(buf);
261 return ret;
262}
263
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100264static ssize_t
265il_dbgfs_sram_write(struct file *file, const char __user * user_buf,
266 size_t count, loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800267{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200268 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800269 char buf[64];
270 int buf_size;
271 u32 offset, len;
272
273 memset(buf, 0, sizeof(buf));
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100274 buf_size = min(count, sizeof(buf) - 1);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800275 if (copy_from_user(buf, user_buf, buf_size))
276 return -EFAULT;
277
278 if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200279 il->dbgfs_sram_offset = offset;
280 il->dbgfs_sram_len = len;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800281 } else {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200282 il->dbgfs_sram_offset = 0;
283 il->dbgfs_sram_len = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800284 }
285
286 return count;
287}
288
289static ssize_t
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100290il_dbgfs_stations_read(struct file *file, char __user * user_buf, size_t count,
291 loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800292{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200293 struct il_priv *il = file->private_data;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200294 struct il_station_entry *station;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200295 int max_sta = il->hw_params.max_stations;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800296 char *buf;
297 int i, j, pos = 0;
298 ssize_t ret;
299 /* Add 30 for initial string */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200300 const size_t bufsz = 30 + sizeof(char) * 500 * (il->num_stations);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800301
302 buf = kmalloc(bufsz, GFP_KERNEL);
303 if (!buf)
304 return -ENOMEM;
305
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100306 pos +=
307 scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
308 il->num_stations);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800309
310 for (i = 0; i < max_sta; i++) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200311 station = &il->stations[i];
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800312 if (!station->used)
313 continue;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100314 pos +=
315 scnprintf(buf + pos, bufsz - pos,
316 "station %d - addr: %pM, flags: %#x\n", i,
317 station->sta.sta.addr,
318 station->sta.station_flags_msk);
319 pos +=
320 scnprintf(buf + pos, bufsz - pos,
321 "TID\tseq_num\ttxq_id\tframes\ttfds\t");
322 pos +=
323 scnprintf(buf + pos, bufsz - pos,
324 "start_idx\tbitmap\t\t\trate_n_flags\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800325
326 for (j = 0; j < MAX_TID_COUNT; j++) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100327 pos +=
328 scnprintf(buf + pos, bufsz - pos,
329 "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x",
330 j, station->tid[j].seq_number,
331 station->tid[j].agg.txq_id,
332 station->tid[j].agg.frame_count,
333 station->tid[j].tfds_in_queue,
334 station->tid[j].agg.start_idx,
335 station->tid[j].agg.bitmap,
336 station->tid[j].agg.rate_n_flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800337
338 if (station->tid[j].agg.wait_for_ba)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100339 pos +=
340 scnprintf(buf + pos, bufsz - pos,
341 " - waitforba");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800342 pos += scnprintf(buf + pos, bufsz - pos, "\n");
343 }
344
345 pos += scnprintf(buf + pos, bufsz - pos, "\n");
346 }
347
348 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
349 kfree(buf);
350 return ret;
351}
352
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100353static ssize_t
354il_dbgfs_nvm_read(struct file *file, char __user * user_buf, size_t count,
355 loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800356{
357 ssize_t ret;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200358 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800359 int pos = 0, ofs = 0, buf_size = 0;
360 const u8 *ptr;
361 char *buf;
362 u16 eeprom_ver;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200363 size_t eeprom_len = il->cfg->base_params->eeprom_size;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800364 buf_size = 4 * eeprom_len + 256;
365
366 if (eeprom_len % 16) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200367 IL_ERR("NVM size is not multiple of 16.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800368 return -ENODATA;
369 }
370
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200371 ptr = il->eeprom;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800372 if (!ptr) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200373 IL_ERR("Invalid EEPROM memory\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800374 return -ENOMEM;
375 }
376
377 /* 4 characters for byte 0xYY */
378 buf = kzalloc(buf_size, GFP_KERNEL);
379 if (!buf) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200380 IL_ERR("Can not allocate Buffer\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800381 return -ENOMEM;
382 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200383 eeprom_ver = il_eeprom_query16(il, EEPROM_VERSION);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100384 pos +=
385 scnprintf(buf + pos, buf_size - pos, "EEPROM " "version: 0x%x\n",
386 eeprom_ver);
387 for (ofs = 0; ofs < eeprom_len; ofs += 16) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800388 pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100389 hex_dump_to_buffer(ptr + ofs, 16, 16, 2, buf + pos,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800390 buf_size - pos, 0);
391 pos += strlen(buf + pos);
392 if (buf_size - pos > 0)
393 buf[pos++] = '\n';
394 }
395
396 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
397 kfree(buf);
398 return ret;
399}
400
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800401static ssize_t
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100402il_dbgfs_channels_read(struct file *file, char __user * user_buf, size_t count,
403 loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800404{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200405 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800406 struct ieee80211_channel *channels = NULL;
407 const struct ieee80211_supported_band *supp_band = NULL;
408 int pos = 0, i, bufsz = PAGE_SIZE;
409 char *buf;
410 ssize_t ret;
411
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +0100412 if (!test_bit(S_GEO_CONFIGURED, &il->status))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800413 return -EAGAIN;
414
415 buf = kzalloc(bufsz, GFP_KERNEL);
416 if (!buf) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200417 IL_ERR("Can not allocate Buffer\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800418 return -ENOMEM;
419 }
420
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200421 supp_band = il_get_hw_mode(il, IEEE80211_BAND_2GHZ);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800422 if (supp_band) {
423 channels = supp_band->channels;
424
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100425 pos +=
426 scnprintf(buf + pos, bufsz - pos,
427 "Displaying %d channels in 2.4GHz band 802.11bg):\n",
428 supp_band->n_channels);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800429
430 for (i = 0; i < supp_band->n_channels; i++)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100431 pos +=
432 scnprintf(buf + pos, bufsz - pos,
433 "%d: %ddBm: BSS%s%s, %s.\n",
434 channels[i].hw_value,
435 channels[i].max_power,
436 channels[i].
437 flags & IEEE80211_CHAN_RADAR ?
438 " (IEEE 802.11h required)" : "",
439 ((channels[i].
440 flags & IEEE80211_CHAN_NO_IBSS) ||
441 (channels[i].
442 flags & IEEE80211_CHAN_RADAR)) ? "" :
443 ", IBSS",
444 channels[i].
445 flags & IEEE80211_CHAN_PASSIVE_SCAN ?
446 "passive only" : "active/passive");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800447 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200448 supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800449 if (supp_band) {
450 channels = supp_band->channels;
451
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100452 pos +=
453 scnprintf(buf + pos, bufsz - pos,
454 "Displaying %d channels in 5.2GHz band (802.11a)\n",
455 supp_band->n_channels);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800456
457 for (i = 0; i < supp_band->n_channels; i++)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100458 pos +=
459 scnprintf(buf + pos, bufsz - pos,
460 "%d: %ddBm: BSS%s%s, %s.\n",
461 channels[i].hw_value,
462 channels[i].max_power,
463 channels[i].
464 flags & IEEE80211_CHAN_RADAR ?
465 " (IEEE 802.11h required)" : "",
466 ((channels[i].
467 flags & IEEE80211_CHAN_NO_IBSS) ||
468 (channels[i].
469 flags & IEEE80211_CHAN_RADAR)) ? "" :
470 ", IBSS",
471 channels[i].
472 flags & IEEE80211_CHAN_PASSIVE_SCAN ?
473 "passive only" : "active/passive");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800474 }
475 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
476 kfree(buf);
477 return ret;
478}
479
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100480static ssize_t
481il_dbgfs_status_read(struct file *file, char __user * user_buf, size_t count,
482 loff_t * ppos)
483{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800484
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200485 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800486 char buf[512];
487 int pos = 0;
488 const size_t bufsz = sizeof(buf);
489
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100490 pos +=
491 scnprintf(buf + pos, bufsz - pos, "S_HCMD_ACTIVE:\t %d\n",
492 test_bit(S_HCMD_ACTIVE, &il->status));
493 pos +=
494 scnprintf(buf + pos, bufsz - pos, "S_INT_ENABLED:\t %d\n",
495 test_bit(S_INT_ENABLED, &il->status));
496 pos +=
497 scnprintf(buf + pos, bufsz - pos, "S_RF_KILL_HW:\t %d\n",
498 test_bit(S_RF_KILL_HW, &il->status));
499 pos +=
500 scnprintf(buf + pos, bufsz - pos, "S_CT_KILL:\t\t %d\n",
501 test_bit(S_CT_KILL, &il->status));
502 pos +=
503 scnprintf(buf + pos, bufsz - pos, "S_INIT:\t\t %d\n",
504 test_bit(S_INIT, &il->status));
505 pos +=
506 scnprintf(buf + pos, bufsz - pos, "S_ALIVE:\t\t %d\n",
507 test_bit(S_ALIVE, &il->status));
508 pos +=
509 scnprintf(buf + pos, bufsz - pos, "S_READY:\t\t %d\n",
510 test_bit(S_READY, &il->status));
511 pos +=
512 scnprintf(buf + pos, bufsz - pos, "S_TEMPERATURE:\t %d\n",
513 test_bit(S_TEMPERATURE, &il->status));
514 pos +=
515 scnprintf(buf + pos, bufsz - pos, "S_GEO_CONFIGURED:\t %d\n",
516 test_bit(S_GEO_CONFIGURED, &il->status));
517 pos +=
518 scnprintf(buf + pos, bufsz - pos, "S_EXIT_PENDING:\t %d\n",
519 test_bit(S_EXIT_PENDING, &il->status));
520 pos +=
521 scnprintf(buf + pos, bufsz - pos, "S_STATS:\t %d\n",
522 test_bit(S_STATS, &il->status));
523 pos +=
524 scnprintf(buf + pos, bufsz - pos, "S_SCANNING:\t %d\n",
525 test_bit(S_SCANNING, &il->status));
526 pos +=
527 scnprintf(buf + pos, bufsz - pos, "S_SCAN_ABORTING:\t %d\n",
528 test_bit(S_SCAN_ABORTING, &il->status));
529 pos +=
530 scnprintf(buf + pos, bufsz - pos, "S_SCAN_HW:\t\t %d\n",
531 test_bit(S_SCAN_HW, &il->status));
532 pos +=
533 scnprintf(buf + pos, bufsz - pos, "S_POWER_PMI:\t %d\n",
534 test_bit(S_POWER_PMI, &il->status));
535 pos +=
536 scnprintf(buf + pos, bufsz - pos, "S_FW_ERROR:\t %d\n",
537 test_bit(S_FW_ERROR, &il->status));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800538 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
539}
540
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100541static ssize_t
542il_dbgfs_interrupt_read(struct file *file, char __user * user_buf, size_t count,
543 loff_t * ppos)
544{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800545
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200546 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800547 int pos = 0;
548 int cnt = 0;
549 char *buf;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100550 int bufsz = 24 * 64; /* 24 items * 64 char per item */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800551 ssize_t ret;
552
553 buf = kzalloc(bufsz, GFP_KERNEL);
554 if (!buf) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200555 IL_ERR("Can not allocate Buffer\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800556 return -ENOMEM;
557 }
558
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100559 pos +=
560 scnprintf(buf + pos, bufsz - pos, "Interrupt Statistics Report:\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800561
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100562 pos +=
563 scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
564 il->isr_stats.hw);
565 pos +=
566 scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
567 il->isr_stats.sw);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200568 if (il->isr_stats.sw || il->isr_stats.hw) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100569 pos +=
570 scnprintf(buf + pos, bufsz - pos,
571 "\tLast Restarting Code: 0x%X\n",
572 il->isr_stats.err_code);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800573 }
Stanislaw Gruszkad3175162011-11-15 11:25:42 +0100574#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100575 pos +=
576 scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
577 il->isr_stats.sch);
578 pos +=
579 scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
580 il->isr_stats.alive);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800581#endif
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100582 pos +=
583 scnprintf(buf + pos, bufsz - pos,
584 "HW RF KILL switch toggled:\t %u\n",
585 il->isr_stats.rfkill);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800586
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100587 pos +=
588 scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
589 il->isr_stats.ctkill);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800590
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100591 pos +=
592 scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
593 il->isr_stats.wakeup);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800594
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100595 pos +=
596 scnprintf(buf + pos, bufsz - pos, "Rx command responses:\t\t %u\n",
597 il->isr_stats.rx);
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200598 for (cnt = 0; cnt < IL_CN_MAX; cnt++) {
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +0200599 if (il->isr_stats.handlers[cnt] > 0)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100600 pos +=
601 scnprintf(buf + pos, bufsz - pos,
602 "\tRx handler[%36s]:\t\t %u\n",
603 il_get_cmd_string(cnt),
604 il->isr_stats.handlers[cnt]);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800605 }
606
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100607 pos +=
608 scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
609 il->isr_stats.tx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800610
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100611 pos +=
612 scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
613 il->isr_stats.unhandled);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800614
615 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
616 kfree(buf);
617 return ret;
618}
619
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100620static ssize_t
621il_dbgfs_interrupt_write(struct file *file, const char __user * user_buf,
622 size_t count, loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800623{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200624 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800625 char buf[8];
626 int buf_size;
627 u32 reset_flag;
628
629 memset(buf, 0, sizeof(buf));
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100630 buf_size = min(count, sizeof(buf) - 1);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800631 if (copy_from_user(buf, user_buf, buf_size))
632 return -EFAULT;
633 if (sscanf(buf, "%x", &reset_flag) != 1)
634 return -EFAULT;
635 if (reset_flag == 0)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200636 il_clear_isr_stats(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800637
638 return count;
639}
640
641static ssize_t
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100642il_dbgfs_qos_read(struct file *file, char __user * user_buf, size_t count,
643 loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800644{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200645 struct il_priv *il = file->private_data;
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +0200646 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800647 int pos = 0, i;
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +0100648 char buf[256];
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800649 const size_t bufsz = sizeof(buf);
650
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100651 pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n", ctx->ctxid);
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +0200652 for (i = 0; i < AC_NUM; i++) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100653 pos +=
654 scnprintf(buf + pos, bufsz - pos,
655 "\tcw_min\tcw_max\taifsn\ttxop\n");
656 pos +=
657 scnprintf(buf + pos, bufsz - pos,
658 "AC[%d]\t%u\t%u\t%u\t%u\n", i,
659 ctx->qos_data.def_qos_parm.ac[i].cw_min,
660 ctx->qos_data.def_qos_parm.ac[i].cw_max,
661 ctx->qos_data.def_qos_parm.ac[i].aifsn,
662 ctx->qos_data.def_qos_parm.ac[i].edca_txop);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800663 }
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +0200664
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800665 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
666}
667
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100668static ssize_t
669il_dbgfs_disable_ht40_write(struct file *file, const char __user * user_buf,
670 size_t count, loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800671{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200672 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800673 char buf[8];
674 int buf_size;
675 int ht40;
676
677 memset(buf, 0, sizeof(buf));
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100678 buf_size = min(count, sizeof(buf) - 1);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800679 if (copy_from_user(buf, user_buf, buf_size))
680 return -EFAULT;
681 if (sscanf(buf, "%d", &ht40) != 1)
682 return -EFAULT;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200683 if (!il_is_any_associated(il))
684 il->disable_ht40 = ht40 ? true : false;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800685 else {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200686 IL_ERR("Sta associated with AP - "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100687 "Change to 40MHz channel support is not allowed\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800688 return -EINVAL;
689 }
690
691 return count;
692}
693
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100694static ssize_t
695il_dbgfs_disable_ht40_read(struct file *file, char __user * user_buf,
696 size_t count, loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800697{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200698 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800699 char buf[100];
700 int pos = 0;
701 const size_t bufsz = sizeof(buf);
702
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100703 pos +=
704 scnprintf(buf + pos, bufsz - pos, "11n 40MHz Mode: %s\n",
705 il->disable_ht40 ? "Disabled" : "Enabled");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800706 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
707}
708
709DEBUGFS_READ_WRITE_FILE_OPS(sram);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800710DEBUGFS_READ_FILE_OPS(nvm);
711DEBUGFS_READ_FILE_OPS(stations);
712DEBUGFS_READ_FILE_OPS(channels);
713DEBUGFS_READ_FILE_OPS(status);
714DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
715DEBUGFS_READ_FILE_OPS(qos);
716DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
717
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100718static ssize_t
719il_dbgfs_traffic_log_read(struct file *file, char __user * user_buf,
720 size_t count, loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800721{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200722 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800723 int pos = 0, ofs = 0;
724 int cnt = 0, entry;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200725 struct il_tx_queue *txq;
726 struct il_queue *q;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200727 struct il_rx_queue *rxq = &il->rxq;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800728 char *buf;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100729 int bufsz =
730 ((IL_TRAFFIC_ENTRIES * IL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
731 (il->cfg->base_params->num_of_queues * 32 * 8) + 400;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800732 const u8 *ptr;
733 ssize_t ret;
734
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200735 if (!il->txq) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200736 IL_ERR("txq not ready\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800737 return -EAGAIN;
738 }
739 buf = kzalloc(bufsz, GFP_KERNEL);
740 if (!buf) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200741 IL_ERR("Can not allocate buffer\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800742 return -ENOMEM;
743 }
744 pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200745 for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
746 txq = &il->txq[cnt];
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800747 q = &txq->q;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100748 pos +=
749 scnprintf(buf + pos, bufsz - pos,
750 "q[%d]: read_ptr: %u, write_ptr: %u\n", cnt,
751 q->read_ptr, q->write_ptr);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800752 }
Stanislaw Gruszkad2ddf622011-08-16 14:17:04 +0200753 if (il->tx_traffic && (il_debug_level & IL_DL_TX)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200754 ptr = il->tx_traffic;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100755 pos +=
756 scnprintf(buf + pos, bufsz - pos, "Tx Traffic idx: %u\n",
757 il->tx_traffic_idx);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200758 for (cnt = 0, ofs = 0; cnt < IL_TRAFFIC_ENTRIES; cnt++) {
759 for (entry = 0; entry < IL_TRAFFIC_ENTRY_SIZE / 16;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100760 entry++, ofs += 16) {
761 pos +=
762 scnprintf(buf + pos, bufsz - pos, "0x%.4x ",
763 ofs);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800764 hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
765 buf + pos, bufsz - pos, 0);
766 pos += strlen(buf + pos);
767 if (bufsz - pos > 0)
768 buf[pos++] = '\n';
769 }
770 }
771 }
772
773 pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100774 pos +=
775 scnprintf(buf + pos, bufsz - pos, "read: %u, write: %u\n",
776 rxq->read, rxq->write);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800777
Stanislaw Gruszkad2ddf622011-08-16 14:17:04 +0200778 if (il->rx_traffic && (il_debug_level & IL_DL_RX)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200779 ptr = il->rx_traffic;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100780 pos +=
781 scnprintf(buf + pos, bufsz - pos, "Rx Traffic idx: %u\n",
782 il->rx_traffic_idx);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200783 for (cnt = 0, ofs = 0; cnt < IL_TRAFFIC_ENTRIES; cnt++) {
784 for (entry = 0; entry < IL_TRAFFIC_ENTRY_SIZE / 16;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100785 entry++, ofs += 16) {
786 pos +=
787 scnprintf(buf + pos, bufsz - pos, "0x%.4x ",
788 ofs);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800789 hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
790 buf + pos, bufsz - pos, 0);
791 pos += strlen(buf + pos);
792 if (bufsz - pos > 0)
793 buf[pos++] = '\n';
794 }
795 }
796 }
797
798 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
799 kfree(buf);
800 return ret;
801}
802
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100803static ssize_t
804il_dbgfs_traffic_log_write(struct file *file, const char __user * user_buf,
805 size_t count, loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800806{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200807 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800808 char buf[8];
809 int buf_size;
810 int traffic_log;
811
812 memset(buf, 0, sizeof(buf));
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100813 buf_size = min(count, sizeof(buf) - 1);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800814 if (copy_from_user(buf, user_buf, buf_size))
815 return -EFAULT;
816 if (sscanf(buf, "%d", &traffic_log) != 1)
817 return -EFAULT;
818 if (traffic_log == 0)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200819 il_reset_traffic_log(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800820
821 return count;
822}
823
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100824static ssize_t
825il_dbgfs_tx_queue_read(struct file *file, char __user * user_buf, size_t count,
826 loff_t * ppos)
827{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800828
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200829 struct il_priv *il = file->private_data;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200830 struct il_tx_queue *txq;
831 struct il_queue *q;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800832 char *buf;
833 int pos = 0;
834 int cnt;
835 int ret;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100836 const size_t bufsz =
837 sizeof(char) * 64 * il->cfg->base_params->num_of_queues;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800838
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200839 if (!il->txq) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200840 IL_ERR("txq not ready\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800841 return -EAGAIN;
842 }
843 buf = kzalloc(bufsz, GFP_KERNEL);
844 if (!buf)
845 return -ENOMEM;
846
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200847 for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
848 txq = &il->txq[cnt];
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800849 q = &txq->q;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100850 pos +=
851 scnprintf(buf + pos, bufsz - pos,
852 "hwq %.2d: read=%u write=%u stop=%d"
853 " swq_id=%#.2x (ac %d/hwq %d)\n", cnt,
854 q->read_ptr, q->write_ptr, !!test_bit(cnt,
855 il->
856 queue_stopped),
857 txq->swq_id, txq->swq_id & 3,
858 (txq->swq_id >> 2) & 0x1f);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800859 if (cnt >= 4)
860 continue;
861 /* for the ACs, display the stop count too */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100862 pos +=
863 scnprintf(buf + pos, bufsz - pos,
864 " stop-count: %d\n",
865 atomic_read(&il->queue_stop_count[cnt]));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800866 }
867 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
868 kfree(buf);
869 return ret;
870}
871
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100872static ssize_t
873il_dbgfs_rx_queue_read(struct file *file, char __user * user_buf, size_t count,
874 loff_t * ppos)
875{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800876
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200877 struct il_priv *il = file->private_data;
878 struct il_rx_queue *rxq = &il->rxq;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800879 char buf[256];
880 int pos = 0;
881 const size_t bufsz = sizeof(buf);
882
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100883 pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", rxq->read);
884 pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", rxq->write);
885 pos +=
886 scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
887 rxq->free_count);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800888 if (rxq->rb_stts) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100889 pos +=
890 scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
891 le16_to_cpu(rxq->rb_stts->
892 closed_rb_num) & 0x0FFF);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800893 } else {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100894 pos +=
895 scnprintf(buf + pos, bufsz - pos,
896 "closed_rb_num: Not Allocated\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800897 }
898 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
899}
900
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100901static ssize_t
902il_dbgfs_ucode_rx_stats_read(struct file *file, char __user * user_buf,
903 size_t count, loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800904{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200905 struct il_priv *il = file->private_data;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100906 return il->cfg->ops->lib->debugfs_ops.rx_stats_read(file, user_buf,
907 count, ppos);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800908}
909
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100910static ssize_t
911il_dbgfs_ucode_tx_stats_read(struct file *file, char __user * user_buf,
912 size_t count, loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800913{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200914 struct il_priv *il = file->private_data;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100915 return il->cfg->ops->lib->debugfs_ops.tx_stats_read(file, user_buf,
916 count, ppos);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800917}
918
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100919static ssize_t
920il_dbgfs_ucode_general_stats_read(struct file *file, char __user * user_buf,
921 size_t count, loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800922{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200923 struct il_priv *il = file->private_data;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100924 return il->cfg->ops->lib->debugfs_ops.general_stats_read(file, user_buf,
925 count, ppos);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800926}
927
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100928static ssize_t
929il_dbgfs_sensitivity_read(struct file *file, char __user * user_buf,
930 size_t count, loff_t * ppos)
931{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800932
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200933 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800934 int pos = 0;
935 int cnt = 0;
936 char *buf;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200937 int bufsz = sizeof(struct il_sensitivity_data) * 4 + 100;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800938 ssize_t ret;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200939 struct il_sensitivity_data *data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800940
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200941 data = &il->sensitivity_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800942 buf = kzalloc(bufsz, GFP_KERNEL);
943 if (!buf) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200944 IL_ERR("Can not allocate Buffer\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800945 return -ENOMEM;
946 }
947
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100948 pos +=
949 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
950 data->auto_corr_ofdm);
951 pos +=
952 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc:\t\t %u\n",
953 data->auto_corr_ofdm_mrc);
954 pos +=
955 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
956 data->auto_corr_ofdm_x1);
957 pos +=
958 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc_x1:\t\t %u\n",
959 data->auto_corr_ofdm_mrc_x1);
960 pos +=
961 scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
962 data->auto_corr_cck);
963 pos +=
964 scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
965 data->auto_corr_cck_mrc);
966 pos +=
967 scnprintf(buf + pos, bufsz - pos,
968 "last_bad_plcp_cnt_ofdm:\t\t %u\n",
969 data->last_bad_plcp_cnt_ofdm);
970 pos +=
971 scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
972 data->last_fa_cnt_ofdm);
973 pos +=
974 scnprintf(buf + pos, bufsz - pos, "last_bad_plcp_cnt_cck:\t\t %u\n",
975 data->last_bad_plcp_cnt_cck);
976 pos +=
977 scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
978 data->last_fa_cnt_cck);
979 pos +=
980 scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
981 data->nrg_curr_state);
982 pos +=
983 scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
984 data->nrg_prev_state);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800985 pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
986 for (cnt = 0; cnt < 10; cnt++) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100987 pos +=
988 scnprintf(buf + pos, bufsz - pos, " %u",
989 data->nrg_value[cnt]);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800990 }
991 pos += scnprintf(buf + pos, bufsz - pos, "\n");
992 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
993 for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100994 pos +=
995 scnprintf(buf + pos, bufsz - pos, " %u",
996 data->nrg_silence_rssi[cnt]);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800997 }
998 pos += scnprintf(buf + pos, bufsz - pos, "\n");
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100999 pos +=
1000 scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
1001 data->nrg_silence_ref);
1002 pos +=
1003 scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
1004 data->nrg_energy_idx);
1005 pos +=
1006 scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
1007 data->nrg_silence_idx);
1008 pos +=
1009 scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
1010 data->nrg_th_cck);
1011 pos +=
1012 scnprintf(buf + pos, bufsz - pos,
1013 "nrg_auto_corr_silence_diff:\t %u\n",
1014 data->nrg_auto_corr_silence_diff);
1015 pos +=
1016 scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
1017 data->num_in_cck_no_fa);
1018 pos +=
1019 scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
1020 data->nrg_th_ofdm);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001021
1022 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1023 kfree(buf);
1024 return ret;
1025}
1026
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001027static ssize_t
1028il_dbgfs_chain_noise_read(struct file *file, char __user * user_buf,
1029 size_t count, loff_t * ppos)
1030{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001031
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001032 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001033 int pos = 0;
1034 int cnt = 0;
1035 char *buf;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001036 int bufsz = sizeof(struct il_chain_noise_data) * 4 + 100;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001037 ssize_t ret;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001038 struct il_chain_noise_data *data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001039
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001040 data = &il->chain_noise_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001041 buf = kzalloc(bufsz, GFP_KERNEL);
1042 if (!buf) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001043 IL_ERR("Can not allocate Buffer\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001044 return -ENOMEM;
1045 }
1046
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001047 pos +=
1048 scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
1049 data->active_chains);
1050 pos +=
1051 scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
1052 data->chain_noise_a);
1053 pos +=
1054 scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
1055 data->chain_noise_b);
1056 pos +=
1057 scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
1058 data->chain_noise_c);
1059 pos +=
1060 scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
1061 data->chain_signal_a);
1062 pos +=
1063 scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
1064 data->chain_signal_b);
1065 pos +=
1066 scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
1067 data->chain_signal_c);
1068 pos +=
1069 scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
1070 data->beacon_count);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001071
1072 pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
1073 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001074 pos +=
1075 scnprintf(buf + pos, bufsz - pos, " %u",
1076 data->disconn_array[cnt]);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001077 }
1078 pos += scnprintf(buf + pos, bufsz - pos, "\n");
1079 pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
1080 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001081 pos +=
1082 scnprintf(buf + pos, bufsz - pos, " %u",
1083 data->delta_gain_code[cnt]);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001084 }
1085 pos += scnprintf(buf + pos, bufsz - pos, "\n");
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001086 pos +=
1087 scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
1088 data->radio_write);
1089 pos +=
1090 scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
1091 data->state);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001092
1093 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1094 kfree(buf);
1095 return ret;
1096}
1097
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001098static ssize_t
1099il_dbgfs_power_save_status_read(struct file *file, char __user * user_buf,
1100 size_t count, loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001101{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001102 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001103 char buf[60];
1104 int pos = 0;
1105 const size_t bufsz = sizeof(buf);
1106 u32 pwrsave_status;
1107
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001108 pwrsave_status =
1109 _il_rd(il, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001110
1111 pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001112 pos +=
1113 scnprintf(buf + pos, bufsz - pos, "%s\n",
1114 (pwrsave_status ==
1115 CSR_GP_REG_NO_POWER_SAVE) ? "none" : (pwrsave_status ==
1116 CSR_GP_REG_MAC_POWER_SAVE)
1117 ? "MAC" : (pwrsave_status ==
1118 CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" : "error");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001119
1120 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1121}
1122
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001123static ssize_t
1124il_dbgfs_clear_ucode_stats_write(struct file *file,
1125 const char __user * user_buf, size_t count,
1126 loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001127{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001128 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001129 char buf[8];
1130 int buf_size;
1131 int clear;
1132
1133 memset(buf, 0, sizeof(buf));
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001134 buf_size = min(count, sizeof(buf) - 1);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001135 if (copy_from_user(buf, user_buf, buf_size))
1136 return -EFAULT;
1137 if (sscanf(buf, "%d", &clear) != 1)
1138 return -EFAULT;
1139
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02001140 /* make request to uCode to retrieve stats information */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001141 mutex_lock(&il->mutex);
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02001142 il_send_stats_request(il, CMD_SYNC, true);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001143 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001144
1145 return count;
1146}
1147
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001148static ssize_t
1149il_dbgfs_rxon_flags_read(struct file *file, char __user * user_buf,
1150 size_t count, loff_t * ppos)
1151{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001152
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001153 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001154 int len = 0;
1155 char buf[20];
1156
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001157 len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->ctx.active.flags));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001158 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1159}
1160
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001161static ssize_t
1162il_dbgfs_rxon_filter_flags_read(struct file *file, char __user * user_buf,
1163 size_t count, loff_t * ppos)
1164{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001165
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001166 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001167 int len = 0;
1168 char buf[20];
1169
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001170 len =
1171 sprintf(buf, "0x%04X\n", le32_to_cpu(il->ctx.active.filter_flags));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001172 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1173}
1174
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001175static ssize_t
1176il_dbgfs_fh_reg_read(struct file *file, char __user * user_buf, size_t count,
1177 loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001178{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001179 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001180 char *buf;
1181 int pos = 0;
1182 ssize_t ret = -EFAULT;
1183
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001184 if (il->cfg->ops->lib->dump_fh) {
1185 ret = pos = il->cfg->ops->lib->dump_fh(il, &buf, true);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001186 if (buf) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001187 ret =
1188 simple_read_from_buffer(user_buf, count, ppos, buf,
1189 pos);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001190 kfree(buf);
1191 }
1192 }
1193
1194 return ret;
1195}
1196
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001197static ssize_t
1198il_dbgfs_missed_beacon_read(struct file *file, char __user * user_buf,
1199 size_t count, loff_t * ppos)
1200{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001201
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001202 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001203 int pos = 0;
1204 char buf[12];
1205 const size_t bufsz = sizeof(buf);
1206
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001207 pos +=
1208 scnprintf(buf + pos, bufsz - pos, "%d\n",
1209 il->missed_beacon_threshold);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001210
1211 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1212}
1213
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001214static ssize_t
1215il_dbgfs_missed_beacon_write(struct file *file, const char __user * user_buf,
1216 size_t count, loff_t * ppos)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001217{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001218 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001219 char buf[8];
1220 int buf_size;
1221 int missed;
1222
1223 memset(buf, 0, sizeof(buf));
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001224 buf_size = min(count, sizeof(buf) - 1);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001225 if (copy_from_user(buf, user_buf, buf_size))
1226 return -EFAULT;
1227 if (sscanf(buf, "%d", &missed) != 1)
1228 return -EINVAL;
1229
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001230 if (missed < IL_MISSED_BEACON_THRESHOLD_MIN ||
1231 missed > IL_MISSED_BEACON_THRESHOLD_MAX)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001232 il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001233 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001234 il->missed_beacon_threshold = missed;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001235
1236 return count;
1237}
1238
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001239static ssize_t
1240il_dbgfs_force_reset_read(struct file *file, char __user * user_buf,
1241 size_t count, loff_t * ppos)
1242{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001243
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001244 struct il_priv *il = file->private_data;
Stanislaw Gruszkadd6d2a82011-06-08 15:28:26 +02001245 int pos = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001246 char buf[300];
1247 const size_t bufsz = sizeof(buf);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001248 struct il_force_reset *force_reset;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001249
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001250 force_reset = &il->force_reset;
Stanislaw Gruszkadd6d2a82011-06-08 15:28:26 +02001251
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001252 pos +=
1253 scnprintf(buf + pos, bufsz - pos, "\tnumber of reset request: %d\n",
1254 force_reset->reset_request_count);
1255 pos +=
1256 scnprintf(buf + pos, bufsz - pos,
1257 "\tnumber of reset request success: %d\n",
1258 force_reset->reset_success_count);
1259 pos +=
1260 scnprintf(buf + pos, bufsz - pos,
1261 "\tnumber of reset request reject: %d\n",
1262 force_reset->reset_reject_count);
1263 pos +=
1264 scnprintf(buf + pos, bufsz - pos, "\treset duration: %lu\n",
1265 force_reset->reset_duration);
Stanislaw Gruszkadd6d2a82011-06-08 15:28:26 +02001266
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001267 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1268}
1269
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001270static ssize_t
1271il_dbgfs_force_reset_write(struct file *file, const char __user * user_buf,
1272 size_t count, loff_t * ppos)
1273{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001274
Stanislaw Gruszkadd6d2a82011-06-08 15:28:26 +02001275 int ret;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001276 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001277
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001278 ret = il_force_reset(il, true);
Stanislaw Gruszkadd6d2a82011-06-08 15:28:26 +02001279
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001280 return ret ? ret : count;
1281}
1282
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001283static ssize_t
1284il_dbgfs_wd_timeout_write(struct file *file, const char __user * user_buf,
1285 size_t count, loff_t * ppos)
1286{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001287
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001288 struct il_priv *il = file->private_data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001289 char buf[8];
1290 int buf_size;
1291 int timeout;
1292
1293 memset(buf, 0, sizeof(buf));
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001294 buf_size = min(count, sizeof(buf) - 1);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001295 if (copy_from_user(buf, user_buf, buf_size))
1296 return -EFAULT;
1297 if (sscanf(buf, "%d", &timeout) != 1)
1298 return -EINVAL;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001299 if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT)
1300 timeout = IL_DEF_WD_TIMEOUT;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001301
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001302 il->cfg->base_params->wd_timeout = timeout;
1303 il_setup_watchdog(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001304 return count;
1305}
1306
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02001307DEBUGFS_READ_FILE_OPS(rx_stats);
1308DEBUGFS_READ_FILE_OPS(tx_stats);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001309DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
1310DEBUGFS_READ_FILE_OPS(rx_queue);
1311DEBUGFS_READ_FILE_OPS(tx_queue);
1312DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
1313DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
1314DEBUGFS_READ_FILE_OPS(ucode_general_stats);
1315DEBUGFS_READ_FILE_OPS(sensitivity);
1316DEBUGFS_READ_FILE_OPS(chain_noise);
1317DEBUGFS_READ_FILE_OPS(power_save_status);
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02001318DEBUGFS_WRITE_FILE_OPS(clear_ucode_stats);
1319DEBUGFS_WRITE_FILE_OPS(clear_traffic_stats);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001320DEBUGFS_READ_FILE_OPS(fh_reg);
1321DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001322DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
1323DEBUGFS_READ_FILE_OPS(rxon_flags);
1324DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
1325DEBUGFS_WRITE_FILE_OPS(wd_timeout);
1326
1327/*
1328 * Create the debugfs files and directories
1329 *
1330 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001331int
1332il_dbgfs_register(struct il_priv *il, const char *name)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001333{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001334 struct dentry *phyd = il->hw->wiphy->debugfsdir;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001335 struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
1336
1337 dir_drv = debugfs_create_dir(name, phyd);
1338 if (!dir_drv)
1339 return -ENOMEM;
1340
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001341 il->debugfs_dir = dir_drv;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001342
1343 dir_data = debugfs_create_dir("data", dir_drv);
1344 if (!dir_data)
1345 goto err;
1346 dir_rf = debugfs_create_dir("rf", dir_drv);
1347 if (!dir_rf)
1348 goto err;
1349 dir_debug = debugfs_create_dir("debug", dir_drv);
1350 if (!dir_debug)
1351 goto err;
1352
1353 DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
1354 DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001355 DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
1356 DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
1357 DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
1358 DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
1359 DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
1360 DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02001361 DEBUGFS_ADD_FILE(rx_stats, dir_debug, S_IRUSR);
1362 DEBUGFS_ADD_FILE(tx_stats, dir_debug, S_IRUSR);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001363 DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
1364 DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
1365 DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
1366 DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02001367 DEBUGFS_ADD_FILE(clear_ucode_stats, dir_debug, S_IWUSR);
1368 DEBUGFS_ADD_FILE(clear_traffic_stats, dir_debug, S_IWUSR);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001369 DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
1370 DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001371 DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
1372 DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
1373 DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
1374 DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
1375
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001376 if (il->cfg->base_params->sensitivity_calib_by_driver)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001377 DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001378 if (il->cfg->base_params->chain_noise_calib_by_driver)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001379 DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001380 DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
1381 DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
1382 DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001383 if (il->cfg->base_params->sensitivity_calib_by_driver)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001384 DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001385 &il->disable_sens_cal);
1386 if (il->cfg->base_params->chain_noise_calib_by_driver)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001387 DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001388 &il->disable_chain_noise_cal);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001389 DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001390 return 0;
1391
1392err:
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001393 IL_ERR("Can't create the debugfs directory\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001394 il_dbgfs_unregister(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001395 return -ENOMEM;
1396}
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001397
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001398EXPORT_SYMBOL(il_dbgfs_register);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001399
1400/**
1401 * Remove the debugfs files and directories
1402 *
1403 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001404void
1405il_dbgfs_unregister(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001406{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001407 if (!il->debugfs_dir)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001408 return;
1409
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001410 debugfs_remove_recursive(il->debugfs_dir);
1411 il->debugfs_dir = NULL;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001412}
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001413
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001414EXPORT_SYMBOL(il_dbgfs_unregister);