diff options
author | Stanislaw Gruszka <sgruszka@redhat.com> | 2011-11-15 08:24:36 -0500 |
---|---|---|
committer | Stanislaw Gruszka <sgruszka@redhat.com> | 2011-11-15 08:24:36 -0500 |
commit | f19ab370a7ba40570dcdb2c0c3cdaa8c20efde97 (patch) | |
tree | e7a20c7cc380dd3671e2e53db6d5b8cadea1cb16 /drivers/net/wireless/iwlegacy/debug.c | |
parent | eac3b2127749af8ba033a755efdc0d4b43167906 (diff) |
iwlegacy: rename iwl-debug.c to debug.c
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Diffstat (limited to 'drivers/net/wireless/iwlegacy/debug.c')
-rw-r--r-- | drivers/net/wireless/iwlegacy/debug.c | 1309 |
1 files changed, 1309 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlegacy/debug.c b/drivers/net/wireless/iwlegacy/debug.c new file mode 100644 index 000000000000..62292a68567d --- /dev/null +++ b/drivers/net/wireless/iwlegacy/debug.c | |||
@@ -0,0 +1,1309 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | #include <linux/ieee80211.h> | ||
29 | #include <net/mac80211.h> | ||
30 | |||
31 | |||
32 | #include "iwl-debug.h" | ||
33 | #include "common.h" | ||
34 | |||
35 | /* create and remove of files */ | ||
36 | #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ | ||
37 | if (!debugfs_create_file(#name, mode, parent, il, \ | ||
38 | &il_dbgfs_##name##_ops)) \ | ||
39 | goto err; \ | ||
40 | } while (0) | ||
41 | |||
42 | #define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ | ||
43 | struct dentry *__tmp; \ | ||
44 | __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ | ||
45 | parent, ptr); \ | ||
46 | if (IS_ERR(__tmp) || !__tmp) \ | ||
47 | goto err; \ | ||
48 | } while (0) | ||
49 | |||
50 | #define DEBUGFS_ADD_X32(name, parent, ptr) do { \ | ||
51 | struct dentry *__tmp; \ | ||
52 | __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \ | ||
53 | parent, ptr); \ | ||
54 | if (IS_ERR(__tmp) || !__tmp) \ | ||
55 | goto err; \ | ||
56 | } while (0) | ||
57 | |||
58 | /* file operation */ | ||
59 | #define DEBUGFS_READ_FUNC(name) \ | ||
60 | static ssize_t il_dbgfs_##name##_read(struct file *file, \ | ||
61 | char __user *user_buf, \ | ||
62 | size_t count, loff_t *ppos); | ||
63 | |||
64 | #define DEBUGFS_WRITE_FUNC(name) \ | ||
65 | static ssize_t il_dbgfs_##name##_write(struct file *file, \ | ||
66 | const char __user *user_buf, \ | ||
67 | size_t count, loff_t *ppos); | ||
68 | |||
69 | |||
70 | static int | ||
71 | il_dbgfs_open_file_generic(struct inode *inode, struct file *file) | ||
72 | { | ||
73 | file->private_data = inode->i_private; | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | #define DEBUGFS_READ_FILE_OPS(name) \ | ||
78 | DEBUGFS_READ_FUNC(name); \ | ||
79 | static const struct file_operations il_dbgfs_##name##_ops = { \ | ||
80 | .read = il_dbgfs_##name##_read, \ | ||
81 | .open = il_dbgfs_open_file_generic, \ | ||
82 | .llseek = generic_file_llseek, \ | ||
83 | }; | ||
84 | |||
85 | #define DEBUGFS_WRITE_FILE_OPS(name) \ | ||
86 | DEBUGFS_WRITE_FUNC(name); \ | ||
87 | static const struct file_operations il_dbgfs_##name##_ops = { \ | ||
88 | .write = il_dbgfs_##name##_write, \ | ||
89 | .open = il_dbgfs_open_file_generic, \ | ||
90 | .llseek = generic_file_llseek, \ | ||
91 | }; | ||
92 | |||
93 | #define DEBUGFS_READ_WRITE_FILE_OPS(name) \ | ||
94 | DEBUGFS_READ_FUNC(name); \ | ||
95 | DEBUGFS_WRITE_FUNC(name); \ | ||
96 | static const struct file_operations il_dbgfs_##name##_ops = { \ | ||
97 | .write = il_dbgfs_##name##_write, \ | ||
98 | .read = il_dbgfs_##name##_read, \ | ||
99 | .open = il_dbgfs_open_file_generic, \ | ||
100 | .llseek = generic_file_llseek, \ | ||
101 | }; | ||
102 | |||
103 | static ssize_t il_dbgfs_tx_stats_read(struct file *file, | ||
104 | char __user *user_buf, | ||
105 | size_t count, loff_t *ppos) { | ||
106 | |||
107 | struct il_priv *il = file->private_data; | ||
108 | char *buf; | ||
109 | int pos = 0; | ||
110 | |||
111 | int cnt; | ||
112 | ssize_t ret; | ||
113 | const size_t bufsz = 100 + | ||
114 | sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); | ||
115 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
116 | if (!buf) | ||
117 | return -ENOMEM; | ||
118 | pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); | ||
119 | for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { | ||
120 | pos += scnprintf(buf + pos, bufsz - pos, | ||
121 | "\t%25s\t\t: %u\n", | ||
122 | il_get_mgmt_string(cnt), | ||
123 | il->tx_stats.mgmt[cnt]); | ||
124 | } | ||
125 | pos += scnprintf(buf + pos, bufsz - pos, "Control\n"); | ||
126 | for (cnt = 0; cnt < CONTROL_MAX; cnt++) { | ||
127 | pos += scnprintf(buf + pos, bufsz - pos, | ||
128 | "\t%25s\t\t: %u\n", | ||
129 | il_get_ctrl_string(cnt), | ||
130 | il->tx_stats.ctrl[cnt]); | ||
131 | } | ||
132 | pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); | ||
133 | pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", | ||
134 | il->tx_stats.data_cnt); | ||
135 | pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", | ||
136 | il->tx_stats.data_bytes); | ||
137 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
138 | kfree(buf); | ||
139 | return ret; | ||
140 | } | ||
141 | |||
142 | static ssize_t | ||
143 | il_dbgfs_clear_traffic_stats_write(struct file *file, | ||
144 | const char __user *user_buf, | ||
145 | size_t count, loff_t *ppos) | ||
146 | { | ||
147 | struct il_priv *il = file->private_data; | ||
148 | u32 clear_flag; | ||
149 | char buf[8]; | ||
150 | int buf_size; | ||
151 | |||
152 | memset(buf, 0, sizeof(buf)); | ||
153 | buf_size = min(count, sizeof(buf) - 1); | ||
154 | if (copy_from_user(buf, user_buf, buf_size)) | ||
155 | return -EFAULT; | ||
156 | if (sscanf(buf, "%x", &clear_flag) != 1) | ||
157 | return -EFAULT; | ||
158 | il_clear_traffic_stats(il); | ||
159 | |||
160 | return count; | ||
161 | } | ||
162 | |||
163 | static ssize_t il_dbgfs_rx_stats_read(struct file *file, | ||
164 | char __user *user_buf, | ||
165 | size_t count, loff_t *ppos) { | ||
166 | |||
167 | struct il_priv *il = file->private_data; | ||
168 | char *buf; | ||
169 | int pos = 0; | ||
170 | int cnt; | ||
171 | ssize_t ret; | ||
172 | const size_t bufsz = 100 + | ||
173 | sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); | ||
174 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
175 | if (!buf) | ||
176 | return -ENOMEM; | ||
177 | |||
178 | pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); | ||
179 | for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { | ||
180 | pos += scnprintf(buf + pos, bufsz - pos, | ||
181 | "\t%25s\t\t: %u\n", | ||
182 | il_get_mgmt_string(cnt), | ||
183 | il->rx_stats.mgmt[cnt]); | ||
184 | } | ||
185 | pos += scnprintf(buf + pos, bufsz - pos, "Control:\n"); | ||
186 | for (cnt = 0; cnt < CONTROL_MAX; cnt++) { | ||
187 | pos += scnprintf(buf + pos, bufsz - pos, | ||
188 | "\t%25s\t\t: %u\n", | ||
189 | il_get_ctrl_string(cnt), | ||
190 | il->rx_stats.ctrl[cnt]); | ||
191 | } | ||
192 | pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); | ||
193 | pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", | ||
194 | il->rx_stats.data_cnt); | ||
195 | pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", | ||
196 | il->rx_stats.data_bytes); | ||
197 | |||
198 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
199 | kfree(buf); | ||
200 | return ret; | ||
201 | } | ||
202 | |||
203 | #define BYTE1_MASK 0x000000ff; | ||
204 | #define BYTE2_MASK 0x0000ffff; | ||
205 | #define BYTE3_MASK 0x00ffffff; | ||
206 | static ssize_t il_dbgfs_sram_read(struct file *file, | ||
207 | char __user *user_buf, | ||
208 | size_t count, loff_t *ppos) | ||
209 | { | ||
210 | u32 val; | ||
211 | char *buf; | ||
212 | ssize_t ret; | ||
213 | int i; | ||
214 | int pos = 0; | ||
215 | struct il_priv *il = file->private_data; | ||
216 | size_t bufsz; | ||
217 | |||
218 | /* default is to dump the entire data segment */ | ||
219 | if (!il->dbgfs_sram_offset && !il->dbgfs_sram_len) { | ||
220 | il->dbgfs_sram_offset = 0x800000; | ||
221 | if (il->ucode_type == UCODE_INIT) | ||
222 | il->dbgfs_sram_len = il->ucode_init_data.len; | ||
223 | else | ||
224 | il->dbgfs_sram_len = il->ucode_data.len; | ||
225 | } | ||
226 | bufsz = 30 + il->dbgfs_sram_len * sizeof(char) * 10; | ||
227 | buf = kmalloc(bufsz, GFP_KERNEL); | ||
228 | if (!buf) | ||
229 | return -ENOMEM; | ||
230 | pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", | ||
231 | il->dbgfs_sram_len); | ||
232 | pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", | ||
233 | il->dbgfs_sram_offset); | ||
234 | for (i = il->dbgfs_sram_len; i > 0; i -= 4) { | ||
235 | val = il_read_targ_mem(il, il->dbgfs_sram_offset + \ | ||
236 | il->dbgfs_sram_len - i); | ||
237 | if (i < 4) { | ||
238 | switch (i) { | ||
239 | case 1: | ||
240 | val &= BYTE1_MASK; | ||
241 | break; | ||
242 | case 2: | ||
243 | val &= BYTE2_MASK; | ||
244 | break; | ||
245 | case 3: | ||
246 | val &= BYTE3_MASK; | ||
247 | break; | ||
248 | } | ||
249 | } | ||
250 | if (!(i % 16)) | ||
251 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
252 | pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); | ||
253 | } | ||
254 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
255 | |||
256 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
257 | kfree(buf); | ||
258 | return ret; | ||
259 | } | ||
260 | |||
261 | static ssize_t il_dbgfs_sram_write(struct file *file, | ||
262 | const char __user *user_buf, | ||
263 | size_t count, loff_t *ppos) | ||
264 | { | ||
265 | struct il_priv *il = file->private_data; | ||
266 | char buf[64]; | ||
267 | int buf_size; | ||
268 | u32 offset, len; | ||
269 | |||
270 | memset(buf, 0, sizeof(buf)); | ||
271 | buf_size = min(count, sizeof(buf) - 1); | ||
272 | if (copy_from_user(buf, user_buf, buf_size)) | ||
273 | return -EFAULT; | ||
274 | |||
275 | if (sscanf(buf, "%x,%x", &offset, &len) == 2) { | ||
276 | il->dbgfs_sram_offset = offset; | ||
277 | il->dbgfs_sram_len = len; | ||
278 | } else { | ||
279 | il->dbgfs_sram_offset = 0; | ||
280 | il->dbgfs_sram_len = 0; | ||
281 | } | ||
282 | |||
283 | return count; | ||
284 | } | ||
285 | |||
286 | static ssize_t | ||
287 | il_dbgfs_stations_read(struct file *file, char __user *user_buf, | ||
288 | size_t count, loff_t *ppos) | ||
289 | { | ||
290 | struct il_priv *il = file->private_data; | ||
291 | struct il_station_entry *station; | ||
292 | int max_sta = il->hw_params.max_stations; | ||
293 | char *buf; | ||
294 | int i, j, pos = 0; | ||
295 | ssize_t ret; | ||
296 | /* Add 30 for initial string */ | ||
297 | const size_t bufsz = 30 + sizeof(char) * 500 * (il->num_stations); | ||
298 | |||
299 | buf = kmalloc(bufsz, GFP_KERNEL); | ||
300 | if (!buf) | ||
301 | return -ENOMEM; | ||
302 | |||
303 | pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n", | ||
304 | il->num_stations); | ||
305 | |||
306 | for (i = 0; i < max_sta; i++) { | ||
307 | station = &il->stations[i]; | ||
308 | if (!station->used) | ||
309 | continue; | ||
310 | pos += scnprintf(buf + pos, bufsz - pos, | ||
311 | "station %d - addr: %pM, flags: %#x\n", | ||
312 | i, station->sta.sta.addr, | ||
313 | station->sta.station_flags_msk); | ||
314 | pos += scnprintf(buf + pos, bufsz - pos, | ||
315 | "TID\tseq_num\ttxq_id\tframes\ttfds\t"); | ||
316 | pos += scnprintf(buf + pos, bufsz - pos, | ||
317 | "start_idx\tbitmap\t\t\trate_n_flags\n"); | ||
318 | |||
319 | for (j = 0; j < MAX_TID_COUNT; j++) { | ||
320 | pos += scnprintf(buf + pos, bufsz - pos, | ||
321 | "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x", | ||
322 | j, station->tid[j].seq_number, | ||
323 | station->tid[j].agg.txq_id, | ||
324 | station->tid[j].agg.frame_count, | ||
325 | station->tid[j].tfds_in_queue, | ||
326 | station->tid[j].agg.start_idx, | ||
327 | station->tid[j].agg.bitmap, | ||
328 | station->tid[j].agg.rate_n_flags); | ||
329 | |||
330 | if (station->tid[j].agg.wait_for_ba) | ||
331 | pos += scnprintf(buf + pos, bufsz - pos, | ||
332 | " - waitforba"); | ||
333 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
334 | } | ||
335 | |||
336 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
337 | } | ||
338 | |||
339 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
340 | kfree(buf); | ||
341 | return ret; | ||
342 | } | ||
343 | |||
344 | static ssize_t il_dbgfs_nvm_read(struct file *file, | ||
345 | char __user *user_buf, | ||
346 | size_t count, | ||
347 | loff_t *ppos) | ||
348 | { | ||
349 | ssize_t ret; | ||
350 | struct il_priv *il = file->private_data; | ||
351 | int pos = 0, ofs = 0, buf_size = 0; | ||
352 | const u8 *ptr; | ||
353 | char *buf; | ||
354 | u16 eeprom_ver; | ||
355 | size_t eeprom_len = il->cfg->base_params->eeprom_size; | ||
356 | buf_size = 4 * eeprom_len + 256; | ||
357 | |||
358 | if (eeprom_len % 16) { | ||
359 | IL_ERR("NVM size is not multiple of 16.\n"); | ||
360 | return -ENODATA; | ||
361 | } | ||
362 | |||
363 | ptr = il->eeprom; | ||
364 | if (!ptr) { | ||
365 | IL_ERR("Invalid EEPROM memory\n"); | ||
366 | return -ENOMEM; | ||
367 | } | ||
368 | |||
369 | /* 4 characters for byte 0xYY */ | ||
370 | buf = kzalloc(buf_size, GFP_KERNEL); | ||
371 | if (!buf) { | ||
372 | IL_ERR("Can not allocate Buffer\n"); | ||
373 | return -ENOMEM; | ||
374 | } | ||
375 | eeprom_ver = il_eeprom_query16(il, EEPROM_VERSION); | ||
376 | pos += scnprintf(buf + pos, buf_size - pos, "EEPROM " | ||
377 | "version: 0x%x\n", eeprom_ver); | ||
378 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { | ||
379 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); | ||
380 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, | ||
381 | buf_size - pos, 0); | ||
382 | pos += strlen(buf + pos); | ||
383 | if (buf_size - pos > 0) | ||
384 | buf[pos++] = '\n'; | ||
385 | } | ||
386 | |||
387 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
388 | kfree(buf); | ||
389 | return ret; | ||
390 | } | ||
391 | |||
392 | static ssize_t | ||
393 | il_dbgfs_channels_read(struct file *file, char __user *user_buf, | ||
394 | size_t count, loff_t *ppos) | ||
395 | { | ||
396 | struct il_priv *il = file->private_data; | ||
397 | struct ieee80211_channel *channels = NULL; | ||
398 | const struct ieee80211_supported_band *supp_band = NULL; | ||
399 | int pos = 0, i, bufsz = PAGE_SIZE; | ||
400 | char *buf; | ||
401 | ssize_t ret; | ||
402 | |||
403 | if (!test_bit(S_GEO_CONFIGURED, &il->status)) | ||
404 | return -EAGAIN; | ||
405 | |||
406 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
407 | if (!buf) { | ||
408 | IL_ERR("Can not allocate Buffer\n"); | ||
409 | return -ENOMEM; | ||
410 | } | ||
411 | |||
412 | supp_band = il_get_hw_mode(il, IEEE80211_BAND_2GHZ); | ||
413 | if (supp_band) { | ||
414 | channels = supp_band->channels; | ||
415 | |||
416 | pos += scnprintf(buf + pos, bufsz - pos, | ||
417 | "Displaying %d channels in 2.4GHz band 802.11bg):\n", | ||
418 | supp_band->n_channels); | ||
419 | |||
420 | for (i = 0; i < supp_band->n_channels; i++) | ||
421 | pos += scnprintf(buf + pos, bufsz - pos, | ||
422 | "%d: %ddBm: BSS%s%s, %s.\n", | ||
423 | channels[i].hw_value, | ||
424 | channels[i].max_power, | ||
425 | channels[i].flags & IEEE80211_CHAN_RADAR ? | ||
426 | " (IEEE 802.11h required)" : "", | ||
427 | ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) | ||
428 | || (channels[i].flags & | ||
429 | IEEE80211_CHAN_RADAR)) ? "" : | ||
430 | ", IBSS", | ||
431 | channels[i].flags & | ||
432 | IEEE80211_CHAN_PASSIVE_SCAN ? | ||
433 | "passive only" : "active/passive"); | ||
434 | } | ||
435 | supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ); | ||
436 | if (supp_band) { | ||
437 | channels = supp_band->channels; | ||
438 | |||
439 | pos += scnprintf(buf + pos, bufsz - pos, | ||
440 | "Displaying %d channels in 5.2GHz band (802.11a)\n", | ||
441 | supp_band->n_channels); | ||
442 | |||
443 | for (i = 0; i < supp_band->n_channels; i++) | ||
444 | pos += scnprintf(buf + pos, bufsz - pos, | ||
445 | "%d: %ddBm: BSS%s%s, %s.\n", | ||
446 | channels[i].hw_value, | ||
447 | channels[i].max_power, | ||
448 | channels[i].flags & IEEE80211_CHAN_RADAR ? | ||
449 | " (IEEE 802.11h required)" : "", | ||
450 | ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) | ||
451 | || (channels[i].flags & | ||
452 | IEEE80211_CHAN_RADAR)) ? "" : | ||
453 | ", IBSS", | ||
454 | channels[i].flags & | ||
455 | IEEE80211_CHAN_PASSIVE_SCAN ? | ||
456 | "passive only" : "active/passive"); | ||
457 | } | ||
458 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
459 | kfree(buf); | ||
460 | return ret; | ||
461 | } | ||
462 | |||
463 | static ssize_t il_dbgfs_status_read(struct file *file, | ||
464 | char __user *user_buf, | ||
465 | size_t count, loff_t *ppos) { | ||
466 | |||
467 | struct il_priv *il = file->private_data; | ||
468 | char buf[512]; | ||
469 | int pos = 0; | ||
470 | const size_t bufsz = sizeof(buf); | ||
471 | |||
472 | pos += scnprintf(buf + pos, bufsz - pos, "S_HCMD_ACTIVE:\t %d\n", | ||
473 | test_bit(S_HCMD_ACTIVE, &il->status)); | ||
474 | pos += scnprintf(buf + pos, bufsz - pos, "S_INT_ENABLED:\t %d\n", | ||
475 | test_bit(S_INT_ENABLED, &il->status)); | ||
476 | pos += scnprintf(buf + pos, bufsz - pos, "S_RF_KILL_HW:\t %d\n", | ||
477 | test_bit(S_RF_KILL_HW, &il->status)); | ||
478 | pos += scnprintf(buf + pos, bufsz - pos, "S_CT_KILL:\t\t %d\n", | ||
479 | test_bit(S_CT_KILL, &il->status)); | ||
480 | pos += scnprintf(buf + pos, bufsz - pos, "S_INIT:\t\t %d\n", | ||
481 | test_bit(S_INIT, &il->status)); | ||
482 | pos += scnprintf(buf + pos, bufsz - pos, "S_ALIVE:\t\t %d\n", | ||
483 | test_bit(S_ALIVE, &il->status)); | ||
484 | pos += scnprintf(buf + pos, bufsz - pos, "S_READY:\t\t %d\n", | ||
485 | test_bit(S_READY, &il->status)); | ||
486 | pos += scnprintf(buf + pos, bufsz - pos, "S_TEMPERATURE:\t %d\n", | ||
487 | test_bit(S_TEMPERATURE, &il->status)); | ||
488 | pos += scnprintf(buf + pos, bufsz - pos, "S_GEO_CONFIGURED:\t %d\n", | ||
489 | test_bit(S_GEO_CONFIGURED, &il->status)); | ||
490 | pos += scnprintf(buf + pos, bufsz - pos, "S_EXIT_PENDING:\t %d\n", | ||
491 | test_bit(S_EXIT_PENDING, &il->status)); | ||
492 | pos += scnprintf(buf + pos, bufsz - pos, "S_STATS:\t %d\n", | ||
493 | test_bit(S_STATS, &il->status)); | ||
494 | pos += scnprintf(buf + pos, bufsz - pos, "S_SCANNING:\t %d\n", | ||
495 | test_bit(S_SCANNING, &il->status)); | ||
496 | pos += scnprintf(buf + pos, bufsz - pos, "S_SCAN_ABORTING:\t %d\n", | ||
497 | test_bit(S_SCAN_ABORTING, &il->status)); | ||
498 | pos += scnprintf(buf + pos, bufsz - pos, "S_SCAN_HW:\t\t %d\n", | ||
499 | test_bit(S_SCAN_HW, &il->status)); | ||
500 | pos += scnprintf(buf + pos, bufsz - pos, "S_POWER_PMI:\t %d\n", | ||
501 | test_bit(S_POWER_PMI, &il->status)); | ||
502 | pos += scnprintf(buf + pos, bufsz - pos, "S_FW_ERROR:\t %d\n", | ||
503 | test_bit(S_FW_ERROR, &il->status)); | ||
504 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
505 | } | ||
506 | |||
507 | static ssize_t il_dbgfs_interrupt_read(struct file *file, | ||
508 | char __user *user_buf, | ||
509 | size_t count, loff_t *ppos) { | ||
510 | |||
511 | struct il_priv *il = file->private_data; | ||
512 | int pos = 0; | ||
513 | int cnt = 0; | ||
514 | char *buf; | ||
515 | int bufsz = 24 * 64; /* 24 items * 64 char per item */ | ||
516 | ssize_t ret; | ||
517 | |||
518 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
519 | if (!buf) { | ||
520 | IL_ERR("Can not allocate Buffer\n"); | ||
521 | return -ENOMEM; | ||
522 | } | ||
523 | |||
524 | pos += scnprintf(buf + pos, bufsz - pos, | ||
525 | "Interrupt Statistics Report:\n"); | ||
526 | |||
527 | pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", | ||
528 | il->isr_stats.hw); | ||
529 | pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", | ||
530 | il->isr_stats.sw); | ||
531 | if (il->isr_stats.sw || il->isr_stats.hw) { | ||
532 | pos += scnprintf(buf + pos, bufsz - pos, | ||
533 | "\tLast Restarting Code: 0x%X\n", | ||
534 | il->isr_stats.err_code); | ||
535 | } | ||
536 | #ifdef CONFIG_IWLEGACY_DEBUG | ||
537 | pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", | ||
538 | il->isr_stats.sch); | ||
539 | pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", | ||
540 | il->isr_stats.alive); | ||
541 | #endif | ||
542 | pos += scnprintf(buf + pos, bufsz - pos, | ||
543 | "HW RF KILL switch toggled:\t %u\n", | ||
544 | il->isr_stats.rfkill); | ||
545 | |||
546 | pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", | ||
547 | il->isr_stats.ctkill); | ||
548 | |||
549 | pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", | ||
550 | il->isr_stats.wakeup); | ||
551 | |||
552 | pos += scnprintf(buf + pos, bufsz - pos, | ||
553 | "Rx command responses:\t\t %u\n", | ||
554 | il->isr_stats.rx); | ||
555 | for (cnt = 0; cnt < IL_CN_MAX; cnt++) { | ||
556 | if (il->isr_stats.handlers[cnt] > 0) | ||
557 | pos += scnprintf(buf + pos, bufsz - pos, | ||
558 | "\tRx handler[%36s]:\t\t %u\n", | ||
559 | il_get_cmd_string(cnt), | ||
560 | il->isr_stats.handlers[cnt]); | ||
561 | } | ||
562 | |||
563 | pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", | ||
564 | il->isr_stats.tx); | ||
565 | |||
566 | pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", | ||
567 | il->isr_stats.unhandled); | ||
568 | |||
569 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
570 | kfree(buf); | ||
571 | return ret; | ||
572 | } | ||
573 | |||
574 | static ssize_t il_dbgfs_interrupt_write(struct file *file, | ||
575 | const char __user *user_buf, | ||
576 | size_t count, loff_t *ppos) | ||
577 | { | ||
578 | struct il_priv *il = file->private_data; | ||
579 | char buf[8]; | ||
580 | int buf_size; | ||
581 | u32 reset_flag; | ||
582 | |||
583 | memset(buf, 0, sizeof(buf)); | ||
584 | buf_size = min(count, sizeof(buf) - 1); | ||
585 | if (copy_from_user(buf, user_buf, buf_size)) | ||
586 | return -EFAULT; | ||
587 | if (sscanf(buf, "%x", &reset_flag) != 1) | ||
588 | return -EFAULT; | ||
589 | if (reset_flag == 0) | ||
590 | il_clear_isr_stats(il); | ||
591 | |||
592 | return count; | ||
593 | } | ||
594 | |||
595 | static ssize_t | ||
596 | il_dbgfs_qos_read(struct file *file, char __user *user_buf, | ||
597 | size_t count, loff_t *ppos) | ||
598 | { | ||
599 | struct il_priv *il = file->private_data; | ||
600 | struct il_rxon_context *ctx = &il->ctx; | ||
601 | int pos = 0, i; | ||
602 | char buf[256]; | ||
603 | const size_t bufsz = sizeof(buf); | ||
604 | |||
605 | pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n", | ||
606 | ctx->ctxid); | ||
607 | for (i = 0; i < AC_NUM; i++) { | ||
608 | pos += scnprintf(buf + pos, bufsz - pos, | ||
609 | "\tcw_min\tcw_max\taifsn\ttxop\n"); | ||
610 | pos += scnprintf(buf + pos, bufsz - pos, | ||
611 | "AC[%d]\t%u\t%u\t%u\t%u\n", i, | ||
612 | ctx->qos_data.def_qos_parm.ac[i].cw_min, | ||
613 | ctx->qos_data.def_qos_parm.ac[i].cw_max, | ||
614 | ctx->qos_data.def_qos_parm.ac[i].aifsn, | ||
615 | ctx->qos_data.def_qos_parm.ac[i].edca_txop); | ||
616 | } | ||
617 | |||
618 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
619 | } | ||
620 | |||
621 | static ssize_t il_dbgfs_disable_ht40_write(struct file *file, | ||
622 | const char __user *user_buf, | ||
623 | size_t count, loff_t *ppos) | ||
624 | { | ||
625 | struct il_priv *il = file->private_data; | ||
626 | char buf[8]; | ||
627 | int buf_size; | ||
628 | int ht40; | ||
629 | |||
630 | memset(buf, 0, sizeof(buf)); | ||
631 | buf_size = min(count, sizeof(buf) - 1); | ||
632 | if (copy_from_user(buf, user_buf, buf_size)) | ||
633 | return -EFAULT; | ||
634 | if (sscanf(buf, "%d", &ht40) != 1) | ||
635 | return -EFAULT; | ||
636 | if (!il_is_any_associated(il)) | ||
637 | il->disable_ht40 = ht40 ? true : false; | ||
638 | else { | ||
639 | IL_ERR("Sta associated with AP - " | ||
640 | "Change to 40MHz channel support is not allowed\n"); | ||
641 | return -EINVAL; | ||
642 | } | ||
643 | |||
644 | return count; | ||
645 | } | ||
646 | |||
647 | static ssize_t il_dbgfs_disable_ht40_read(struct file *file, | ||
648 | char __user *user_buf, | ||
649 | size_t count, loff_t *ppos) | ||
650 | { | ||
651 | struct il_priv *il = file->private_data; | ||
652 | char buf[100]; | ||
653 | int pos = 0; | ||
654 | const size_t bufsz = sizeof(buf); | ||
655 | |||
656 | pos += scnprintf(buf + pos, bufsz - pos, | ||
657 | "11n 40MHz Mode: %s\n", | ||
658 | il->disable_ht40 ? "Disabled" : "Enabled"); | ||
659 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
660 | } | ||
661 | |||
662 | DEBUGFS_READ_WRITE_FILE_OPS(sram); | ||
663 | DEBUGFS_READ_FILE_OPS(nvm); | ||
664 | DEBUGFS_READ_FILE_OPS(stations); | ||
665 | DEBUGFS_READ_FILE_OPS(channels); | ||
666 | DEBUGFS_READ_FILE_OPS(status); | ||
667 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); | ||
668 | DEBUGFS_READ_FILE_OPS(qos); | ||
669 | DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); | ||
670 | |||
671 | static ssize_t il_dbgfs_traffic_log_read(struct file *file, | ||
672 | char __user *user_buf, | ||
673 | size_t count, loff_t *ppos) | ||
674 | { | ||
675 | struct il_priv *il = file->private_data; | ||
676 | int pos = 0, ofs = 0; | ||
677 | int cnt = 0, entry; | ||
678 | struct il_tx_queue *txq; | ||
679 | struct il_queue *q; | ||
680 | struct il_rx_queue *rxq = &il->rxq; | ||
681 | char *buf; | ||
682 | int bufsz = ((IL_TRAFFIC_ENTRIES * IL_TRAFFIC_ENTRY_SIZE * 64) * 2) + | ||
683 | (il->cfg->base_params->num_of_queues * 32 * 8) + 400; | ||
684 | const u8 *ptr; | ||
685 | ssize_t ret; | ||
686 | |||
687 | if (!il->txq) { | ||
688 | IL_ERR("txq not ready\n"); | ||
689 | return -EAGAIN; | ||
690 | } | ||
691 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
692 | if (!buf) { | ||
693 | IL_ERR("Can not allocate buffer\n"); | ||
694 | return -ENOMEM; | ||
695 | } | ||
696 | pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); | ||
697 | for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) { | ||
698 | txq = &il->txq[cnt]; | ||
699 | q = &txq->q; | ||
700 | pos += scnprintf(buf + pos, bufsz - pos, | ||
701 | "q[%d]: read_ptr: %u, write_ptr: %u\n", | ||
702 | cnt, q->read_ptr, q->write_ptr); | ||
703 | } | ||
704 | if (il->tx_traffic && (il_debug_level & IL_DL_TX)) { | ||
705 | ptr = il->tx_traffic; | ||
706 | pos += scnprintf(buf + pos, bufsz - pos, | ||
707 | "Tx Traffic idx: %u\n", il->tx_traffic_idx); | ||
708 | for (cnt = 0, ofs = 0; cnt < IL_TRAFFIC_ENTRIES; cnt++) { | ||
709 | for (entry = 0; entry < IL_TRAFFIC_ENTRY_SIZE / 16; | ||
710 | entry++, ofs += 16) { | ||
711 | pos += scnprintf(buf + pos, bufsz - pos, | ||
712 | "0x%.4x ", ofs); | ||
713 | hex_dump_to_buffer(ptr + ofs, 16, 16, 2, | ||
714 | buf + pos, bufsz - pos, 0); | ||
715 | pos += strlen(buf + pos); | ||
716 | if (bufsz - pos > 0) | ||
717 | buf[pos++] = '\n'; | ||
718 | } | ||
719 | } | ||
720 | } | ||
721 | |||
722 | pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n"); | ||
723 | pos += scnprintf(buf + pos, bufsz - pos, | ||
724 | "read: %u, write: %u\n", | ||
725 | rxq->read, rxq->write); | ||
726 | |||
727 | if (il->rx_traffic && (il_debug_level & IL_DL_RX)) { | ||
728 | ptr = il->rx_traffic; | ||
729 | pos += scnprintf(buf + pos, bufsz - pos, | ||
730 | "Rx Traffic idx: %u\n", il->rx_traffic_idx); | ||
731 | for (cnt = 0, ofs = 0; cnt < IL_TRAFFIC_ENTRIES; cnt++) { | ||
732 | for (entry = 0; entry < IL_TRAFFIC_ENTRY_SIZE / 16; | ||
733 | entry++, ofs += 16) { | ||
734 | pos += scnprintf(buf + pos, bufsz - pos, | ||
735 | "0x%.4x ", ofs); | ||
736 | hex_dump_to_buffer(ptr + ofs, 16, 16, 2, | ||
737 | buf + pos, bufsz - pos, 0); | ||
738 | pos += strlen(buf + pos); | ||
739 | if (bufsz - pos > 0) | ||
740 | buf[pos++] = '\n'; | ||
741 | } | ||
742 | } | ||
743 | } | ||
744 | |||
745 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
746 | kfree(buf); | ||
747 | return ret; | ||
748 | } | ||
749 | |||
750 | static ssize_t il_dbgfs_traffic_log_write(struct file *file, | ||
751 | const char __user *user_buf, | ||
752 | size_t count, loff_t *ppos) | ||
753 | { | ||
754 | struct il_priv *il = file->private_data; | ||
755 | char buf[8]; | ||
756 | int buf_size; | ||
757 | int traffic_log; | ||
758 | |||
759 | memset(buf, 0, sizeof(buf)); | ||
760 | buf_size = min(count, sizeof(buf) - 1); | ||
761 | if (copy_from_user(buf, user_buf, buf_size)) | ||
762 | return -EFAULT; | ||
763 | if (sscanf(buf, "%d", &traffic_log) != 1) | ||
764 | return -EFAULT; | ||
765 | if (traffic_log == 0) | ||
766 | il_reset_traffic_log(il); | ||
767 | |||
768 | return count; | ||
769 | } | ||
770 | |||
771 | static ssize_t il_dbgfs_tx_queue_read(struct file *file, | ||
772 | char __user *user_buf, | ||
773 | size_t count, loff_t *ppos) { | ||
774 | |||
775 | struct il_priv *il = file->private_data; | ||
776 | struct il_tx_queue *txq; | ||
777 | struct il_queue *q; | ||
778 | char *buf; | ||
779 | int pos = 0; | ||
780 | int cnt; | ||
781 | int ret; | ||
782 | const size_t bufsz = sizeof(char) * 64 * | ||
783 | il->cfg->base_params->num_of_queues; | ||
784 | |||
785 | if (!il->txq) { | ||
786 | IL_ERR("txq not ready\n"); | ||
787 | return -EAGAIN; | ||
788 | } | ||
789 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
790 | if (!buf) | ||
791 | return -ENOMEM; | ||
792 | |||
793 | for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) { | ||
794 | txq = &il->txq[cnt]; | ||
795 | q = &txq->q; | ||
796 | pos += scnprintf(buf + pos, bufsz - pos, | ||
797 | "hwq %.2d: read=%u write=%u stop=%d" | ||
798 | " swq_id=%#.2x (ac %d/hwq %d)\n", | ||
799 | cnt, q->read_ptr, q->write_ptr, | ||
800 | !!test_bit(cnt, il->queue_stopped), | ||
801 | txq->swq_id, txq->swq_id & 3, | ||
802 | (txq->swq_id >> 2) & 0x1f); | ||
803 | if (cnt >= 4) | ||
804 | continue; | ||
805 | /* for the ACs, display the stop count too */ | ||
806 | pos += scnprintf(buf + pos, bufsz - pos, | ||
807 | " stop-count: %d\n", | ||
808 | atomic_read(&il->queue_stop_count[cnt])); | ||
809 | } | ||
810 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
811 | kfree(buf); | ||
812 | return ret; | ||
813 | } | ||
814 | |||
815 | static ssize_t il_dbgfs_rx_queue_read(struct file *file, | ||
816 | char __user *user_buf, | ||
817 | size_t count, loff_t *ppos) { | ||
818 | |||
819 | struct il_priv *il = file->private_data; | ||
820 | struct il_rx_queue *rxq = &il->rxq; | ||
821 | char buf[256]; | ||
822 | int pos = 0; | ||
823 | const size_t bufsz = sizeof(buf); | ||
824 | |||
825 | pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", | ||
826 | rxq->read); | ||
827 | pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", | ||
828 | rxq->write); | ||
829 | pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", | ||
830 | rxq->free_count); | ||
831 | if (rxq->rb_stts) { | ||
832 | pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", | ||
833 | le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); | ||
834 | } else { | ||
835 | pos += scnprintf(buf + pos, bufsz - pos, | ||
836 | "closed_rb_num: Not Allocated\n"); | ||
837 | } | ||
838 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
839 | } | ||
840 | |||
841 | static ssize_t il_dbgfs_ucode_rx_stats_read(struct file *file, | ||
842 | char __user *user_buf, | ||
843 | size_t count, loff_t *ppos) | ||
844 | { | ||
845 | struct il_priv *il = file->private_data; | ||
846 | return il->cfg->ops->lib->debugfs_ops.rx_stats_read(file, | ||
847 | user_buf, count, ppos); | ||
848 | } | ||
849 | |||
850 | static ssize_t il_dbgfs_ucode_tx_stats_read(struct file *file, | ||
851 | char __user *user_buf, | ||
852 | size_t count, loff_t *ppos) | ||
853 | { | ||
854 | struct il_priv *il = file->private_data; | ||
855 | return il->cfg->ops->lib->debugfs_ops.tx_stats_read(file, | ||
856 | user_buf, count, ppos); | ||
857 | } | ||
858 | |||
859 | static ssize_t il_dbgfs_ucode_general_stats_read(struct file *file, | ||
860 | char __user *user_buf, | ||
861 | size_t count, loff_t *ppos) | ||
862 | { | ||
863 | struct il_priv *il = file->private_data; | ||
864 | return il->cfg->ops->lib->debugfs_ops.general_stats_read(file, | ||
865 | user_buf, count, ppos); | ||
866 | } | ||
867 | |||
868 | static ssize_t il_dbgfs_sensitivity_read(struct file *file, | ||
869 | char __user *user_buf, | ||
870 | size_t count, loff_t *ppos) { | ||
871 | |||
872 | struct il_priv *il = file->private_data; | ||
873 | int pos = 0; | ||
874 | int cnt = 0; | ||
875 | char *buf; | ||
876 | int bufsz = sizeof(struct il_sensitivity_data) * 4 + 100; | ||
877 | ssize_t ret; | ||
878 | struct il_sensitivity_data *data; | ||
879 | |||
880 | data = &il->sensitivity_data; | ||
881 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
882 | if (!buf) { | ||
883 | IL_ERR("Can not allocate Buffer\n"); | ||
884 | return -ENOMEM; | ||
885 | } | ||
886 | |||
887 | pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n", | ||
888 | data->auto_corr_ofdm); | ||
889 | pos += scnprintf(buf + pos, bufsz - pos, | ||
890 | "auto_corr_ofdm_mrc:\t\t %u\n", | ||
891 | data->auto_corr_ofdm_mrc); | ||
892 | pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n", | ||
893 | data->auto_corr_ofdm_x1); | ||
894 | pos += scnprintf(buf + pos, bufsz - pos, | ||
895 | "auto_corr_ofdm_mrc_x1:\t\t %u\n", | ||
896 | data->auto_corr_ofdm_mrc_x1); | ||
897 | pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n", | ||
898 | data->auto_corr_cck); | ||
899 | pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n", | ||
900 | data->auto_corr_cck_mrc); | ||
901 | pos += scnprintf(buf + pos, bufsz - pos, | ||
902 | "last_bad_plcp_cnt_ofdm:\t\t %u\n", | ||
903 | data->last_bad_plcp_cnt_ofdm); | ||
904 | pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n", | ||
905 | data->last_fa_cnt_ofdm); | ||
906 | pos += scnprintf(buf + pos, bufsz - pos, | ||
907 | "last_bad_plcp_cnt_cck:\t\t %u\n", | ||
908 | data->last_bad_plcp_cnt_cck); | ||
909 | pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n", | ||
910 | data->last_fa_cnt_cck); | ||
911 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n", | ||
912 | data->nrg_curr_state); | ||
913 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n", | ||
914 | data->nrg_prev_state); | ||
915 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t"); | ||
916 | for (cnt = 0; cnt < 10; cnt++) { | ||
917 | pos += scnprintf(buf + pos, bufsz - pos, " %u", | ||
918 | data->nrg_value[cnt]); | ||
919 | } | ||
920 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
921 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t"); | ||
922 | for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) { | ||
923 | pos += scnprintf(buf + pos, bufsz - pos, " %u", | ||
924 | data->nrg_silence_rssi[cnt]); | ||
925 | } | ||
926 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
927 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n", | ||
928 | data->nrg_silence_ref); | ||
929 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n", | ||
930 | data->nrg_energy_idx); | ||
931 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n", | ||
932 | data->nrg_silence_idx); | ||
933 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n", | ||
934 | data->nrg_th_cck); | ||
935 | pos += scnprintf(buf + pos, bufsz - pos, | ||
936 | "nrg_auto_corr_silence_diff:\t %u\n", | ||
937 | data->nrg_auto_corr_silence_diff); | ||
938 | pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n", | ||
939 | data->num_in_cck_no_fa); | ||
940 | pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n", | ||
941 | data->nrg_th_ofdm); | ||
942 | |||
943 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
944 | kfree(buf); | ||
945 | return ret; | ||
946 | } | ||
947 | |||
948 | |||
949 | static ssize_t il_dbgfs_chain_noise_read(struct file *file, | ||
950 | char __user *user_buf, | ||
951 | size_t count, loff_t *ppos) { | ||
952 | |||
953 | struct il_priv *il = file->private_data; | ||
954 | int pos = 0; | ||
955 | int cnt = 0; | ||
956 | char *buf; | ||
957 | int bufsz = sizeof(struct il_chain_noise_data) * 4 + 100; | ||
958 | ssize_t ret; | ||
959 | struct il_chain_noise_data *data; | ||
960 | |||
961 | data = &il->chain_noise_data; | ||
962 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
963 | if (!buf) { | ||
964 | IL_ERR("Can not allocate Buffer\n"); | ||
965 | return -ENOMEM; | ||
966 | } | ||
967 | |||
968 | pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n", | ||
969 | data->active_chains); | ||
970 | pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n", | ||
971 | data->chain_noise_a); | ||
972 | pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n", | ||
973 | data->chain_noise_b); | ||
974 | pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n", | ||
975 | data->chain_noise_c); | ||
976 | pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n", | ||
977 | data->chain_signal_a); | ||
978 | pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n", | ||
979 | data->chain_signal_b); | ||
980 | pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n", | ||
981 | data->chain_signal_c); | ||
982 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n", | ||
983 | data->beacon_count); | ||
984 | |||
985 | pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t"); | ||
986 | for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { | ||
987 | pos += scnprintf(buf + pos, bufsz - pos, " %u", | ||
988 | data->disconn_array[cnt]); | ||
989 | } | ||
990 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
991 | pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t"); | ||
992 | for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { | ||
993 | pos += scnprintf(buf + pos, bufsz - pos, " %u", | ||
994 | data->delta_gain_code[cnt]); | ||
995 | } | ||
996 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
997 | pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n", | ||
998 | data->radio_write); | ||
999 | pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n", | ||
1000 | data->state); | ||
1001 | |||
1002 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1003 | kfree(buf); | ||
1004 | return ret; | ||
1005 | } | ||
1006 | |||
1007 | static ssize_t il_dbgfs_power_save_status_read(struct file *file, | ||
1008 | char __user *user_buf, | ||
1009 | size_t count, loff_t *ppos) | ||
1010 | { | ||
1011 | struct il_priv *il = file->private_data; | ||
1012 | char buf[60]; | ||
1013 | int pos = 0; | ||
1014 | const size_t bufsz = sizeof(buf); | ||
1015 | u32 pwrsave_status; | ||
1016 | |||
1017 | pwrsave_status = _il_rd(il, CSR_GP_CNTRL) & | ||
1018 | CSR_GP_REG_POWER_SAVE_STATUS_MSK; | ||
1019 | |||
1020 | pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); | ||
1021 | pos += scnprintf(buf + pos, bufsz - pos, "%s\n", | ||
1022 | (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" : | ||
1023 | (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" : | ||
1024 | (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" : | ||
1025 | "error"); | ||
1026 | |||
1027 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1028 | } | ||
1029 | |||
1030 | static ssize_t il_dbgfs_clear_ucode_stats_write(struct file *file, | ||
1031 | const char __user *user_buf, | ||
1032 | size_t count, loff_t *ppos) | ||
1033 | { | ||
1034 | struct il_priv *il = file->private_data; | ||
1035 | char buf[8]; | ||
1036 | int buf_size; | ||
1037 | int clear; | ||
1038 | |||
1039 | memset(buf, 0, sizeof(buf)); | ||
1040 | buf_size = min(count, sizeof(buf) - 1); | ||
1041 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1042 | return -EFAULT; | ||
1043 | if (sscanf(buf, "%d", &clear) != 1) | ||
1044 | return -EFAULT; | ||
1045 | |||
1046 | /* make request to uCode to retrieve stats information */ | ||
1047 | mutex_lock(&il->mutex); | ||
1048 | il_send_stats_request(il, CMD_SYNC, true); | ||
1049 | mutex_unlock(&il->mutex); | ||
1050 | |||
1051 | return count; | ||
1052 | } | ||
1053 | |||
1054 | static ssize_t il_dbgfs_rxon_flags_read(struct file *file, | ||
1055 | char __user *user_buf, | ||
1056 | size_t count, loff_t *ppos) { | ||
1057 | |||
1058 | struct il_priv *il = file->private_data; | ||
1059 | int len = 0; | ||
1060 | char buf[20]; | ||
1061 | |||
1062 | len = sprintf(buf, "0x%04X\n", | ||
1063 | le32_to_cpu(il->ctx.active.flags)); | ||
1064 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1065 | } | ||
1066 | |||
1067 | static ssize_t il_dbgfs_rxon_filter_flags_read(struct file *file, | ||
1068 | char __user *user_buf, | ||
1069 | size_t count, loff_t *ppos) { | ||
1070 | |||
1071 | struct il_priv *il = file->private_data; | ||
1072 | int len = 0; | ||
1073 | char buf[20]; | ||
1074 | |||
1075 | len = sprintf(buf, "0x%04X\n", | ||
1076 | le32_to_cpu(il->ctx.active.filter_flags)); | ||
1077 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1078 | } | ||
1079 | |||
1080 | static ssize_t il_dbgfs_fh_reg_read(struct file *file, | ||
1081 | char __user *user_buf, | ||
1082 | size_t count, loff_t *ppos) | ||
1083 | { | ||
1084 | struct il_priv *il = file->private_data; | ||
1085 | char *buf; | ||
1086 | int pos = 0; | ||
1087 | ssize_t ret = -EFAULT; | ||
1088 | |||
1089 | if (il->cfg->ops->lib->dump_fh) { | ||
1090 | ret = pos = il->cfg->ops->lib->dump_fh(il, &buf, true); | ||
1091 | if (buf) { | ||
1092 | ret = simple_read_from_buffer(user_buf, | ||
1093 | count, ppos, buf, pos); | ||
1094 | kfree(buf); | ||
1095 | } | ||
1096 | } | ||
1097 | |||
1098 | return ret; | ||
1099 | } | ||
1100 | |||
1101 | static ssize_t il_dbgfs_missed_beacon_read(struct file *file, | ||
1102 | char __user *user_buf, | ||
1103 | size_t count, loff_t *ppos) { | ||
1104 | |||
1105 | struct il_priv *il = file->private_data; | ||
1106 | int pos = 0; | ||
1107 | char buf[12]; | ||
1108 | const size_t bufsz = sizeof(buf); | ||
1109 | |||
1110 | pos += scnprintf(buf + pos, bufsz - pos, "%d\n", | ||
1111 | il->missed_beacon_threshold); | ||
1112 | |||
1113 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1114 | } | ||
1115 | |||
1116 | static ssize_t il_dbgfs_missed_beacon_write(struct file *file, | ||
1117 | const char __user *user_buf, | ||
1118 | size_t count, loff_t *ppos) | ||
1119 | { | ||
1120 | struct il_priv *il = file->private_data; | ||
1121 | char buf[8]; | ||
1122 | int buf_size; | ||
1123 | int missed; | ||
1124 | |||
1125 | memset(buf, 0, sizeof(buf)); | ||
1126 | buf_size = min(count, sizeof(buf) - 1); | ||
1127 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1128 | return -EFAULT; | ||
1129 | if (sscanf(buf, "%d", &missed) != 1) | ||
1130 | return -EINVAL; | ||
1131 | |||
1132 | if (missed < IL_MISSED_BEACON_THRESHOLD_MIN || | ||
1133 | missed > IL_MISSED_BEACON_THRESHOLD_MAX) | ||
1134 | il->missed_beacon_threshold = | ||
1135 | IL_MISSED_BEACON_THRESHOLD_DEF; | ||
1136 | else | ||
1137 | il->missed_beacon_threshold = missed; | ||
1138 | |||
1139 | return count; | ||
1140 | } | ||
1141 | |||
1142 | static ssize_t il_dbgfs_force_reset_read(struct file *file, | ||
1143 | char __user *user_buf, | ||
1144 | size_t count, loff_t *ppos) { | ||
1145 | |||
1146 | struct il_priv *il = file->private_data; | ||
1147 | int pos = 0; | ||
1148 | char buf[300]; | ||
1149 | const size_t bufsz = sizeof(buf); | ||
1150 | struct il_force_reset *force_reset; | ||
1151 | |||
1152 | force_reset = &il->force_reset; | ||
1153 | |||
1154 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1155 | "\tnumber of reset request: %d\n", | ||
1156 | force_reset->reset_request_count); | ||
1157 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1158 | "\tnumber of reset request success: %d\n", | ||
1159 | force_reset->reset_success_count); | ||
1160 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1161 | "\tnumber of reset request reject: %d\n", | ||
1162 | force_reset->reset_reject_count); | ||
1163 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1164 | "\treset duration: %lu\n", | ||
1165 | force_reset->reset_duration); | ||
1166 | |||
1167 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1168 | } | ||
1169 | |||
1170 | static ssize_t il_dbgfs_force_reset_write(struct file *file, | ||
1171 | const char __user *user_buf, | ||
1172 | size_t count, loff_t *ppos) { | ||
1173 | |||
1174 | int ret; | ||
1175 | struct il_priv *il = file->private_data; | ||
1176 | |||
1177 | ret = il_force_reset(il, true); | ||
1178 | |||
1179 | return ret ? ret : count; | ||
1180 | } | ||
1181 | |||
1182 | static ssize_t il_dbgfs_wd_timeout_write(struct file *file, | ||
1183 | const char __user *user_buf, | ||
1184 | size_t count, loff_t *ppos) { | ||
1185 | |||
1186 | struct il_priv *il = file->private_data; | ||
1187 | char buf[8]; | ||
1188 | int buf_size; | ||
1189 | int timeout; | ||
1190 | |||
1191 | memset(buf, 0, sizeof(buf)); | ||
1192 | buf_size = min(count, sizeof(buf) - 1); | ||
1193 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1194 | return -EFAULT; | ||
1195 | if (sscanf(buf, "%d", &timeout) != 1) | ||
1196 | return -EINVAL; | ||
1197 | if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT) | ||
1198 | timeout = IL_DEF_WD_TIMEOUT; | ||
1199 | |||
1200 | il->cfg->base_params->wd_timeout = timeout; | ||
1201 | il_setup_watchdog(il); | ||
1202 | return count; | ||
1203 | } | ||
1204 | |||
1205 | DEBUGFS_READ_FILE_OPS(rx_stats); | ||
1206 | DEBUGFS_READ_FILE_OPS(tx_stats); | ||
1207 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | ||
1208 | DEBUGFS_READ_FILE_OPS(rx_queue); | ||
1209 | DEBUGFS_READ_FILE_OPS(tx_queue); | ||
1210 | DEBUGFS_READ_FILE_OPS(ucode_rx_stats); | ||
1211 | DEBUGFS_READ_FILE_OPS(ucode_tx_stats); | ||
1212 | DEBUGFS_READ_FILE_OPS(ucode_general_stats); | ||
1213 | DEBUGFS_READ_FILE_OPS(sensitivity); | ||
1214 | DEBUGFS_READ_FILE_OPS(chain_noise); | ||
1215 | DEBUGFS_READ_FILE_OPS(power_save_status); | ||
1216 | DEBUGFS_WRITE_FILE_OPS(clear_ucode_stats); | ||
1217 | DEBUGFS_WRITE_FILE_OPS(clear_traffic_stats); | ||
1218 | DEBUGFS_READ_FILE_OPS(fh_reg); | ||
1219 | DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); | ||
1220 | DEBUGFS_READ_WRITE_FILE_OPS(force_reset); | ||
1221 | DEBUGFS_READ_FILE_OPS(rxon_flags); | ||
1222 | DEBUGFS_READ_FILE_OPS(rxon_filter_flags); | ||
1223 | DEBUGFS_WRITE_FILE_OPS(wd_timeout); | ||
1224 | |||
1225 | /* | ||
1226 | * Create the debugfs files and directories | ||
1227 | * | ||
1228 | */ | ||
1229 | int il_dbgfs_register(struct il_priv *il, const char *name) | ||
1230 | { | ||
1231 | struct dentry *phyd = il->hw->wiphy->debugfsdir; | ||
1232 | struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug; | ||
1233 | |||
1234 | dir_drv = debugfs_create_dir(name, phyd); | ||
1235 | if (!dir_drv) | ||
1236 | return -ENOMEM; | ||
1237 | |||
1238 | il->debugfs_dir = dir_drv; | ||
1239 | |||
1240 | dir_data = debugfs_create_dir("data", dir_drv); | ||
1241 | if (!dir_data) | ||
1242 | goto err; | ||
1243 | dir_rf = debugfs_create_dir("rf", dir_drv); | ||
1244 | if (!dir_rf) | ||
1245 | goto err; | ||
1246 | dir_debug = debugfs_create_dir("debug", dir_drv); | ||
1247 | if (!dir_debug) | ||
1248 | goto err; | ||
1249 | |||
1250 | DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); | ||
1251 | DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); | ||
1252 | DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); | ||
1253 | DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); | ||
1254 | DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); | ||
1255 | DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); | ||
1256 | DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); | ||
1257 | DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); | ||
1258 | DEBUGFS_ADD_FILE(rx_stats, dir_debug, S_IRUSR); | ||
1259 | DEBUGFS_ADD_FILE(tx_stats, dir_debug, S_IRUSR); | ||
1260 | DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); | ||
1261 | DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); | ||
1262 | DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); | ||
1263 | DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); | ||
1264 | DEBUGFS_ADD_FILE(clear_ucode_stats, dir_debug, S_IWUSR); | ||
1265 | DEBUGFS_ADD_FILE(clear_traffic_stats, dir_debug, S_IWUSR); | ||
1266 | DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); | ||
1267 | DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); | ||
1268 | DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); | ||
1269 | DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); | ||
1270 | DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); | ||
1271 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); | ||
1272 | |||
1273 | if (il->cfg->base_params->sensitivity_calib_by_driver) | ||
1274 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); | ||
1275 | if (il->cfg->base_params->chain_noise_calib_by_driver) | ||
1276 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); | ||
1277 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); | ||
1278 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); | ||
1279 | DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); | ||
1280 | if (il->cfg->base_params->sensitivity_calib_by_driver) | ||
1281 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, | ||
1282 | &il->disable_sens_cal); | ||
1283 | if (il->cfg->base_params->chain_noise_calib_by_driver) | ||
1284 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, | ||
1285 | &il->disable_chain_noise_cal); | ||
1286 | DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, | ||
1287 | &il->disable_tx_power_cal); | ||
1288 | return 0; | ||
1289 | |||
1290 | err: | ||
1291 | IL_ERR("Can't create the debugfs directory\n"); | ||
1292 | il_dbgfs_unregister(il); | ||
1293 | return -ENOMEM; | ||
1294 | } | ||
1295 | EXPORT_SYMBOL(il_dbgfs_register); | ||
1296 | |||
1297 | /** | ||
1298 | * Remove the debugfs files and directories | ||
1299 | * | ||
1300 | */ | ||
1301 | void il_dbgfs_unregister(struct il_priv *il) | ||
1302 | { | ||
1303 | if (!il->debugfs_dir) | ||
1304 | return; | ||
1305 | |||
1306 | debugfs_remove_recursive(il->debugfs_dir); | ||
1307 | il->debugfs_dir = NULL; | ||
1308 | } | ||
1309 | EXPORT_SYMBOL(il_dbgfs_unregister); | ||