xref: /linux/drivers/net/wireless/ti/wlcore/debugfs.c (revision 1a2ac6d7ecdcde74a4e16f31de64124160fc7237)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * This file is part of wl1271
4  *
5  * Copyright (C) 2009 Nokia Corporation
6  *
7  * Contact: Luciano Coelho <luciano.coelho@nokia.com>
8  */
9 
10 #include "debugfs.h"
11 
12 #include <linux/skbuff.h>
13 #include <linux/slab.h>
14 #include <linux/module.h>
15 #include <linux/pm_runtime.h>
16 
17 #include "wlcore.h"
18 #include "debug.h"
19 #include "acx.h"
20 #include "ps.h"
21 #include "io.h"
22 #include "tx.h"
23 #include "hw_ops.h"
24 
25 /* ms */
26 #define WL1271_DEBUGFS_STATS_LIFETIME 1000
27 
28 #define WLCORE_MAX_BLOCK_SIZE ((size_t)(4*PAGE_SIZE))
29 
30 /* debugfs macros idea from mac80211 */
31 int wl1271_format_buffer(char __user *userbuf, size_t count,
32 			 loff_t *ppos, char *fmt, ...)
33 {
34 	va_list args;
35 	char buf[DEBUGFS_FORMAT_BUFFER_SIZE];
36 	int res;
37 
38 	va_start(args, fmt);
39 	res = vscnprintf(buf, sizeof(buf), fmt, args);
40 	va_end(args);
41 
42 	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
43 }
44 EXPORT_SYMBOL_GPL(wl1271_format_buffer);
45 
46 void wl1271_debugfs_update_stats(struct wl1271 *wl)
47 {
48 	int ret;
49 
50 	mutex_lock(&wl->mutex);
51 
52 	if (unlikely(wl->state != WLCORE_STATE_ON))
53 		goto out;
54 
55 	ret = pm_runtime_resume_and_get(wl->dev);
56 	if (ret < 0)
57 		goto out;
58 
59 	if (!wl->plt &&
60 	    time_after(jiffies, wl->stats.fw_stats_update +
61 		       msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) {
62 		wl1271_acx_statistics(wl, wl->stats.fw_stats);
63 		wl->stats.fw_stats_update = jiffies;
64 	}
65 
66 	pm_runtime_mark_last_busy(wl->dev);
67 	pm_runtime_put_autosuspend(wl->dev);
68 
69 out:
70 	mutex_unlock(&wl->mutex);
71 }
72 EXPORT_SYMBOL_GPL(wl1271_debugfs_update_stats);
73 
74 DEBUGFS_READONLY_FILE(retry_count, "%u", wl->stats.retry_count);
75 DEBUGFS_READONLY_FILE(excessive_retries, "%u",
76 		      wl->stats.excessive_retries);
77 
78 static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
79 				 size_t count, loff_t *ppos)
80 {
81 	struct wl1271 *wl = file->private_data;
82 	u32 queue_len;
83 	char buf[20];
84 	int res;
85 
86 	queue_len = wl1271_tx_total_queue_count(wl);
87 
88 	res = scnprintf(buf, sizeof(buf), "%u\n", queue_len);
89 	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
90 }
91 
92 static const struct file_operations tx_queue_len_ops = {
93 	.read = tx_queue_len_read,
94 	.open = simple_open,
95 	.llseek = default_llseek,
96 };
97 
98 static void chip_op_handler(struct wl1271 *wl, unsigned long value,
99 			    void *arg)
100 {
101 	int ret;
102 	int (*chip_op) (struct wl1271 *wl);
103 
104 	if (!arg) {
105 		wl1271_warning("debugfs chip_op_handler with no callback");
106 		return;
107 	}
108 
109 	ret = pm_runtime_resume_and_get(wl->dev);
110 	if (ret < 0)
111 		return;
112 
113 	chip_op = arg;
114 	chip_op(wl);
115 
116 	pm_runtime_mark_last_busy(wl->dev);
117 	pm_runtime_put_autosuspend(wl->dev);
118 }
119 
120 #define WL12XX_CONF_DEBUGFS(param, conf_sub_struct,			\
121 			    min_val, max_val, write_handler_locked,	\
122 			    write_handler_arg)				\
123 	static ssize_t param##_read(struct file *file,			\
124 				      char __user *user_buf,		\
125 				      size_t count, loff_t *ppos)	\
126 	{								\
127 	struct wl1271 *wl = file->private_data;				\
128 	return wl1271_format_buffer(user_buf, count,			\
129 				    ppos, "%d\n",			\
130 				    wl->conf.conf_sub_struct.param);	\
131 	}								\
132 									\
133 	static ssize_t param##_write(struct file *file,			\
134 				     const char __user *user_buf,	\
135 				     size_t count, loff_t *ppos)	\
136 	{								\
137 	struct wl1271 *wl = file->private_data;				\
138 	unsigned long value;						\
139 	int ret;							\
140 									\
141 	ret = kstrtoul_from_user(user_buf, count, 10, &value);		\
142 	if (ret < 0) {							\
143 		wl1271_warning("illegal value for " #param);		\
144 		return -EINVAL;						\
145 	}								\
146 									\
147 	if (value < min_val || value > max_val) {			\
148 		wl1271_warning(#param " is not in valid range");	\
149 		return -ERANGE;						\
150 	}								\
151 									\
152 	mutex_lock(&wl->mutex);						\
153 	wl->conf.conf_sub_struct.param = value;				\
154 									\
155 	write_handler_locked(wl, value, write_handler_arg);		\
156 									\
157 	mutex_unlock(&wl->mutex);					\
158 	return count;							\
159 	}								\
160 									\
161 	static const struct file_operations param##_ops = {		\
162 		.read = param##_read,					\
163 		.write = param##_write,					\
164 		.open = simple_open,					\
165 		.llseek = default_llseek,				\
166 	};
167 
168 WL12XX_CONF_DEBUGFS(irq_pkt_threshold, rx, 0, 65535,
169 		    chip_op_handler, wl1271_acx_init_rx_interrupt)
170 WL12XX_CONF_DEBUGFS(irq_blk_threshold, rx, 0, 65535,
171 		    chip_op_handler, wl1271_acx_init_rx_interrupt)
172 WL12XX_CONF_DEBUGFS(irq_timeout, rx, 0, 100,
173 		    chip_op_handler, wl1271_acx_init_rx_interrupt)
174 
175 static ssize_t gpio_power_read(struct file *file, char __user *user_buf,
176 			  size_t count, loff_t *ppos)
177 {
178 	struct wl1271 *wl = file->private_data;
179 	bool state = test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
180 
181 	int res;
182 	char buf[10];
183 
184 	res = scnprintf(buf, sizeof(buf), "%d\n", state);
185 
186 	return simple_read_from_buffer(user_buf, count, ppos, buf, res);
187 }
188 
189 static ssize_t gpio_power_write(struct file *file,
190 			   const char __user *user_buf,
191 			   size_t count, loff_t *ppos)
192 {
193 	struct wl1271 *wl = file->private_data;
194 	unsigned long value;
195 	int ret;
196 
197 	ret = kstrtoul_from_user(user_buf, count, 10, &value);
198 	if (ret < 0) {
199 		wl1271_warning("illegal value in gpio_power");
200 		return -EINVAL;
201 	}
202 
203 	mutex_lock(&wl->mutex);
204 
205 	if (value)
206 		wl1271_power_on(wl);
207 	else
208 		wl1271_power_off(wl);
209 
210 	mutex_unlock(&wl->mutex);
211 	return count;
212 }
213 
214 static const struct file_operations gpio_power_ops = {
215 	.read = gpio_power_read,
216 	.write = gpio_power_write,
217 	.open = simple_open,
218 	.llseek = default_llseek,
219 };
220 
221 static ssize_t start_recovery_write(struct file *file,
222 				    const char __user *user_buf,
223 				    size_t count, loff_t *ppos)
224 {
225 	struct wl1271 *wl = file->private_data;
226 
227 	mutex_lock(&wl->mutex);
228 	wl12xx_queue_recovery_work(wl);
229 	mutex_unlock(&wl->mutex);
230 
231 	return count;
232 }
233 
234 static const struct file_operations start_recovery_ops = {
235 	.write = start_recovery_write,
236 	.open = simple_open,
237 	.llseek = default_llseek,
238 };
239 
240 static ssize_t dynamic_ps_timeout_read(struct file *file, char __user *user_buf,
241 			  size_t count, loff_t *ppos)
242 {
243 	struct wl1271 *wl = file->private_data;
244 
245 	return wl1271_format_buffer(user_buf, count,
246 				    ppos, "%d\n",
247 				    wl->conf.conn.dynamic_ps_timeout);
248 }
249 
250 static ssize_t dynamic_ps_timeout_write(struct file *file,
251 				    const char __user *user_buf,
252 				    size_t count, loff_t *ppos)
253 {
254 	struct wl1271 *wl = file->private_data;
255 	struct wl12xx_vif *wlvif;
256 	unsigned long value;
257 	int ret;
258 
259 	ret = kstrtoul_from_user(user_buf, count, 10, &value);
260 	if (ret < 0) {
261 		wl1271_warning("illegal value in dynamic_ps");
262 		return -EINVAL;
263 	}
264 
265 	if (value < 1 || value > 65535) {
266 		wl1271_warning("dynamic_ps_timeout is not in valid range");
267 		return -ERANGE;
268 	}
269 
270 	mutex_lock(&wl->mutex);
271 
272 	wl->conf.conn.dynamic_ps_timeout = value;
273 
274 	if (unlikely(wl->state != WLCORE_STATE_ON))
275 		goto out;
276 
277 	ret = pm_runtime_resume_and_get(wl->dev);
278 	if (ret < 0)
279 		goto out;
280 
281 	/* In case we're already in PSM, trigger it again to set new timeout
282 	 * immediately without waiting for re-association
283 	 */
284 
285 	wl12xx_for_each_wlvif_sta(wl, wlvif) {
286 		if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags))
287 			wl1271_ps_set_mode(wl, wlvif, STATION_AUTO_PS_MODE);
288 	}
289 
290 	pm_runtime_mark_last_busy(wl->dev);
291 	pm_runtime_put_autosuspend(wl->dev);
292 
293 out:
294 	mutex_unlock(&wl->mutex);
295 	return count;
296 }
297 
298 static const struct file_operations dynamic_ps_timeout_ops = {
299 	.read = dynamic_ps_timeout_read,
300 	.write = dynamic_ps_timeout_write,
301 	.open = simple_open,
302 	.llseek = default_llseek,
303 };
304 
305 static ssize_t forced_ps_read(struct file *file, char __user *user_buf,
306 			  size_t count, loff_t *ppos)
307 {
308 	struct wl1271 *wl = file->private_data;
309 
310 	return wl1271_format_buffer(user_buf, count,
311 				    ppos, "%d\n",
312 				    wl->conf.conn.forced_ps);
313 }
314 
315 static ssize_t forced_ps_write(struct file *file,
316 				    const char __user *user_buf,
317 				    size_t count, loff_t *ppos)
318 {
319 	struct wl1271 *wl = file->private_data;
320 	struct wl12xx_vif *wlvif;
321 	unsigned long value;
322 	int ret, ps_mode;
323 
324 	ret = kstrtoul_from_user(user_buf, count, 10, &value);
325 	if (ret < 0) {
326 		wl1271_warning("illegal value in forced_ps");
327 		return -EINVAL;
328 	}
329 
330 	if (value != 1 && value != 0) {
331 		wl1271_warning("forced_ps should be either 0 or 1");
332 		return -ERANGE;
333 	}
334 
335 	mutex_lock(&wl->mutex);
336 
337 	if (wl->conf.conn.forced_ps == value)
338 		goto out;
339 
340 	wl->conf.conn.forced_ps = value;
341 
342 	if (unlikely(wl->state != WLCORE_STATE_ON))
343 		goto out;
344 
345 	ret = pm_runtime_resume_and_get(wl->dev);
346 	if (ret < 0)
347 		goto out;
348 
349 	/* In case we're already in PSM, trigger it again to switch mode
350 	 * immediately without waiting for re-association
351 	 */
352 
353 	ps_mode = value ? STATION_POWER_SAVE_MODE : STATION_AUTO_PS_MODE;
354 
355 	wl12xx_for_each_wlvif_sta(wl, wlvif) {
356 		if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags))
357 			wl1271_ps_set_mode(wl, wlvif, ps_mode);
358 	}
359 
360 	pm_runtime_mark_last_busy(wl->dev);
361 	pm_runtime_put_autosuspend(wl->dev);
362 
363 out:
364 	mutex_unlock(&wl->mutex);
365 	return count;
366 }
367 
368 static const struct file_operations forced_ps_ops = {
369 	.read = forced_ps_read,
370 	.write = forced_ps_write,
371 	.open = simple_open,
372 	.llseek = default_llseek,
373 };
374 
375 static ssize_t split_scan_timeout_read(struct file *file, char __user *user_buf,
376 			  size_t count, loff_t *ppos)
377 {
378 	struct wl1271 *wl = file->private_data;
379 
380 	return wl1271_format_buffer(user_buf, count,
381 				    ppos, "%d\n",
382 				    wl->conf.scan.split_scan_timeout / 1000);
383 }
384 
385 static ssize_t split_scan_timeout_write(struct file *file,
386 				    const char __user *user_buf,
387 				    size_t count, loff_t *ppos)
388 {
389 	struct wl1271 *wl = file->private_data;
390 	unsigned long value;
391 	int ret;
392 
393 	ret = kstrtoul_from_user(user_buf, count, 10, &value);
394 	if (ret < 0) {
395 		wl1271_warning("illegal value in split_scan_timeout");
396 		return -EINVAL;
397 	}
398 
399 	if (value == 0)
400 		wl1271_info("split scan will be disabled");
401 
402 	mutex_lock(&wl->mutex);
403 
404 	wl->conf.scan.split_scan_timeout = value * 1000;
405 
406 	mutex_unlock(&wl->mutex);
407 	return count;
408 }
409 
410 static const struct file_operations split_scan_timeout_ops = {
411 	.read = split_scan_timeout_read,
412 	.write = split_scan_timeout_write,
413 	.open = simple_open,
414 	.llseek = default_llseek,
415 };
416 
417 static ssize_t driver_state_read(struct file *file, char __user *user_buf,
418 				 size_t count, loff_t *ppos)
419 {
420 	struct wl1271 *wl = file->private_data;
421 	int res = 0;
422 	ssize_t ret;
423 	char *buf;
424 	struct wl12xx_vif *wlvif;
425 
426 #define DRIVER_STATE_BUF_LEN 1024
427 
428 	buf = kmalloc(DRIVER_STATE_BUF_LEN, GFP_KERNEL);
429 	if (!buf)
430 		return -ENOMEM;
431 
432 	mutex_lock(&wl->mutex);
433 
434 #define DRIVER_STATE_PRINT(x, fmt)   \
435 	(res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\
436 			  #x " = " fmt "\n", wl->x))
437 
438 #define DRIVER_STATE_PRINT_GENERIC(x, fmt, args...)   \
439 	(res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\
440 			  #x " = " fmt "\n", args))
441 
442 #define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld")
443 #define DRIVER_STATE_PRINT_INT(x)  DRIVER_STATE_PRINT(x, "%d")
444 #define DRIVER_STATE_PRINT_STR(x)  DRIVER_STATE_PRINT(x, "%s")
445 #define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx")
446 #define DRIVER_STATE_PRINT_HEX(x)  DRIVER_STATE_PRINT(x, "0x%x")
447 
448 	wl12xx_for_each_wlvif_sta(wl, wlvif) {
449 		if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
450 			continue;
451 
452 		DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel,
453 					   wlvif->p2p ? "P2P-CL" : "STA");
454 	}
455 
456 	wl12xx_for_each_wlvif_ap(wl, wlvif)
457 		DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel,
458 					   wlvif->p2p ? "P2P-GO" : "AP");
459 
460 	DRIVER_STATE_PRINT_INT(tx_blocks_available);
461 	DRIVER_STATE_PRINT_INT(tx_allocated_blocks);
462 	DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]);
463 	DRIVER_STATE_PRINT_INT(tx_allocated_pkts[1]);
464 	DRIVER_STATE_PRINT_INT(tx_allocated_pkts[2]);
465 	DRIVER_STATE_PRINT_INT(tx_allocated_pkts[3]);
466 	DRIVER_STATE_PRINT_INT(tx_frames_cnt);
467 	DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]);
468 	DRIVER_STATE_PRINT_INT(tx_queue_count[0]);
469 	DRIVER_STATE_PRINT_INT(tx_queue_count[1]);
470 	DRIVER_STATE_PRINT_INT(tx_queue_count[2]);
471 	DRIVER_STATE_PRINT_INT(tx_queue_count[3]);
472 	DRIVER_STATE_PRINT_INT(tx_packets_count);
473 	DRIVER_STATE_PRINT_INT(tx_results_count);
474 	DRIVER_STATE_PRINT_LHEX(flags);
475 	DRIVER_STATE_PRINT_INT(tx_blocks_freed);
476 	DRIVER_STATE_PRINT_INT(rx_counter);
477 	DRIVER_STATE_PRINT_INT(state);
478 	DRIVER_STATE_PRINT_INT(band);
479 	DRIVER_STATE_PRINT_INT(power_level);
480 	DRIVER_STATE_PRINT_INT(sg_enabled);
481 	DRIVER_STATE_PRINT_INT(enable_11a);
482 	DRIVER_STATE_PRINT_INT(noise);
483 	DRIVER_STATE_PRINT_LHEX(ap_fw_ps_map);
484 	DRIVER_STATE_PRINT_LHEX(ap_ps_map);
485 	DRIVER_STATE_PRINT_HEX(quirks);
486 	DRIVER_STATE_PRINT_HEX(irq);
487 	/* TODO: ref_clock and tcxo_clock were moved to wl12xx priv */
488 	DRIVER_STATE_PRINT_HEX(hw_pg_ver);
489 	DRIVER_STATE_PRINT_HEX(irq_flags);
490 	DRIVER_STATE_PRINT_HEX(chip.id);
491 	DRIVER_STATE_PRINT_STR(chip.fw_ver_str);
492 	DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str);
493 	DRIVER_STATE_PRINT_INT(recovery_count);
494 
495 #undef DRIVER_STATE_PRINT_INT
496 #undef DRIVER_STATE_PRINT_LONG
497 #undef DRIVER_STATE_PRINT_HEX
498 #undef DRIVER_STATE_PRINT_LHEX
499 #undef DRIVER_STATE_PRINT_STR
500 #undef DRIVER_STATE_PRINT
501 #undef DRIVER_STATE_BUF_LEN
502 
503 	mutex_unlock(&wl->mutex);
504 
505 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, res);
506 	kfree(buf);
507 	return ret;
508 }
509 
510 static const struct file_operations driver_state_ops = {
511 	.read = driver_state_read,
512 	.open = simple_open,
513 	.llseek = default_llseek,
514 };
515 
516 static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
517 				 size_t count, loff_t *ppos)
518 {
519 	struct wl1271 *wl = file->private_data;
520 	struct wl12xx_vif *wlvif;
521 	int ret, res = 0;
522 	const int buf_size = 4096;
523 	char *buf;
524 	char tmp_buf[64];
525 
526 	buf = kzalloc(buf_size, GFP_KERNEL);
527 	if (!buf)
528 		return -ENOMEM;
529 
530 	mutex_lock(&wl->mutex);
531 
532 #define VIF_STATE_PRINT(x, fmt)				\
533 	(res += scnprintf(buf + res, buf_size - res,	\
534 			  #x " = " fmt "\n", wlvif->x))
535 
536 #define VIF_STATE_PRINT_LONG(x)  VIF_STATE_PRINT(x, "%ld")
537 #define VIF_STATE_PRINT_INT(x)   VIF_STATE_PRINT(x, "%d")
538 #define VIF_STATE_PRINT_STR(x)   VIF_STATE_PRINT(x, "%s")
539 #define VIF_STATE_PRINT_LHEX(x)  VIF_STATE_PRINT(x, "0x%lx")
540 #define VIF_STATE_PRINT_LLHEX(x) VIF_STATE_PRINT(x, "0x%llx")
541 #define VIF_STATE_PRINT_HEX(x)   VIF_STATE_PRINT(x, "0x%x")
542 
543 #define VIF_STATE_PRINT_NSTR(x, len)				\
544 	do {							\
545 		memset(tmp_buf, 0, sizeof(tmp_buf));		\
546 		memcpy(tmp_buf, wlvif->x,			\
547 		       min_t(u8, len, sizeof(tmp_buf) - 1));	\
548 		res += scnprintf(buf + res, buf_size - res,	\
549 				 #x " = %s\n", tmp_buf);	\
550 	} while (0)
551 
552 	wl12xx_for_each_wlvif(wl, wlvif) {
553 		VIF_STATE_PRINT_INT(role_id);
554 		VIF_STATE_PRINT_INT(bss_type);
555 		VIF_STATE_PRINT_LHEX(flags);
556 		VIF_STATE_PRINT_INT(p2p);
557 		VIF_STATE_PRINT_INT(dev_role_id);
558 		VIF_STATE_PRINT_INT(dev_hlid);
559 
560 		if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
561 		    wlvif->bss_type == BSS_TYPE_IBSS) {
562 			VIF_STATE_PRINT_INT(sta.hlid);
563 			VIF_STATE_PRINT_INT(sta.basic_rate_idx);
564 			VIF_STATE_PRINT_INT(sta.ap_rate_idx);
565 			VIF_STATE_PRINT_INT(sta.p2p_rate_idx);
566 			VIF_STATE_PRINT_INT(sta.qos);
567 		} else {
568 			VIF_STATE_PRINT_INT(ap.global_hlid);
569 			VIF_STATE_PRINT_INT(ap.bcast_hlid);
570 			VIF_STATE_PRINT_LHEX(ap.sta_hlid_map[0]);
571 			VIF_STATE_PRINT_INT(ap.mgmt_rate_idx);
572 			VIF_STATE_PRINT_INT(ap.bcast_rate_idx);
573 			VIF_STATE_PRINT_INT(ap.ucast_rate_idx[0]);
574 			VIF_STATE_PRINT_INT(ap.ucast_rate_idx[1]);
575 			VIF_STATE_PRINT_INT(ap.ucast_rate_idx[2]);
576 			VIF_STATE_PRINT_INT(ap.ucast_rate_idx[3]);
577 		}
578 		VIF_STATE_PRINT_INT(last_tx_hlid);
579 		VIF_STATE_PRINT_INT(tx_queue_count[0]);
580 		VIF_STATE_PRINT_INT(tx_queue_count[1]);
581 		VIF_STATE_PRINT_INT(tx_queue_count[2]);
582 		VIF_STATE_PRINT_INT(tx_queue_count[3]);
583 		VIF_STATE_PRINT_LHEX(links_map[0]);
584 		VIF_STATE_PRINT_NSTR(ssid, wlvif->ssid_len);
585 		VIF_STATE_PRINT_INT(band);
586 		VIF_STATE_PRINT_INT(channel);
587 		VIF_STATE_PRINT_HEX(bitrate_masks[0]);
588 		VIF_STATE_PRINT_HEX(bitrate_masks[1]);
589 		VIF_STATE_PRINT_HEX(basic_rate_set);
590 		VIF_STATE_PRINT_HEX(basic_rate);
591 		VIF_STATE_PRINT_HEX(rate_set);
592 		VIF_STATE_PRINT_INT(beacon_int);
593 		VIF_STATE_PRINT_INT(default_key);
594 		VIF_STATE_PRINT_INT(aid);
595 		VIF_STATE_PRINT_INT(psm_entry_retry);
596 		VIF_STATE_PRINT_INT(power_level);
597 		VIF_STATE_PRINT_INT(rssi_thold);
598 		VIF_STATE_PRINT_INT(last_rssi_event);
599 		VIF_STATE_PRINT_INT(ba_support);
600 		VIF_STATE_PRINT_INT(ba_allowed);
601 		VIF_STATE_PRINT_LLHEX(total_freed_pkts);
602 	}
603 
604 #undef VIF_STATE_PRINT_INT
605 #undef VIF_STATE_PRINT_LONG
606 #undef VIF_STATE_PRINT_HEX
607 #undef VIF_STATE_PRINT_LHEX
608 #undef VIF_STATE_PRINT_LLHEX
609 #undef VIF_STATE_PRINT_STR
610 #undef VIF_STATE_PRINT_NSTR
611 #undef VIF_STATE_PRINT
612 
613 	mutex_unlock(&wl->mutex);
614 
615 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, res);
616 	kfree(buf);
617 	return ret;
618 }
619 
620 static const struct file_operations vifs_state_ops = {
621 	.read = vifs_state_read,
622 	.open = simple_open,
623 	.llseek = default_llseek,
624 };
625 
626 static ssize_t dtim_interval_read(struct file *file, char __user *user_buf,
627 				  size_t count, loff_t *ppos)
628 {
629 	struct wl1271 *wl = file->private_data;
630 	u8 value;
631 
632 	if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_DTIM ||
633 	    wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM)
634 		value = wl->conf.conn.listen_interval;
635 	else
636 		value = 0;
637 
638 	return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value);
639 }
640 
641 static ssize_t dtim_interval_write(struct file *file,
642 				   const char __user *user_buf,
643 				   size_t count, loff_t *ppos)
644 {
645 	struct wl1271 *wl = file->private_data;
646 	unsigned long value;
647 	int ret;
648 
649 	ret = kstrtoul_from_user(user_buf, count, 10, &value);
650 	if (ret < 0) {
651 		wl1271_warning("illegal value for dtim_interval");
652 		return -EINVAL;
653 	}
654 
655 	if (value < 1 || value > 10) {
656 		wl1271_warning("dtim value is not in valid range");
657 		return -ERANGE;
658 	}
659 
660 	mutex_lock(&wl->mutex);
661 
662 	wl->conf.conn.listen_interval = value;
663 	/* for some reason there are different event types for 1 and >1 */
664 	if (value == 1)
665 		wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_DTIM;
666 	else
667 		wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM;
668 
669 	/*
670 	 * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only
671 	 * take effect on the next time we enter psm.
672 	 */
673 	mutex_unlock(&wl->mutex);
674 	return count;
675 }
676 
677 static const struct file_operations dtim_interval_ops = {
678 	.read = dtim_interval_read,
679 	.write = dtim_interval_write,
680 	.open = simple_open,
681 	.llseek = default_llseek,
682 };
683 
684 
685 
686 static ssize_t suspend_dtim_interval_read(struct file *file,
687 					  char __user *user_buf,
688 					  size_t count, loff_t *ppos)
689 {
690 	struct wl1271 *wl = file->private_data;
691 	u8 value;
692 
693 	if (wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_DTIM ||
694 	    wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM)
695 		value = wl->conf.conn.suspend_listen_interval;
696 	else
697 		value = 0;
698 
699 	return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value);
700 }
701 
702 static ssize_t suspend_dtim_interval_write(struct file *file,
703 					   const char __user *user_buf,
704 					   size_t count, loff_t *ppos)
705 {
706 	struct wl1271 *wl = file->private_data;
707 	unsigned long value;
708 	int ret;
709 
710 	ret = kstrtoul_from_user(user_buf, count, 10, &value);
711 	if (ret < 0) {
712 		wl1271_warning("illegal value for suspend_dtim_interval");
713 		return -EINVAL;
714 	}
715 
716 	if (value < 1 || value > 10) {
717 		wl1271_warning("suspend_dtim value is not in valid range");
718 		return -ERANGE;
719 	}
720 
721 	mutex_lock(&wl->mutex);
722 
723 	wl->conf.conn.suspend_listen_interval = value;
724 	/* for some reason there are different event types for 1 and >1 */
725 	if (value == 1)
726 		wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_DTIM;
727 	else
728 		wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM;
729 
730 	mutex_unlock(&wl->mutex);
731 	return count;
732 }
733 
734 
735 static const struct file_operations suspend_dtim_interval_ops = {
736 	.read = suspend_dtim_interval_read,
737 	.write = suspend_dtim_interval_write,
738 	.open = simple_open,
739 	.llseek = default_llseek,
740 };
741 
742 static ssize_t beacon_interval_read(struct file *file, char __user *user_buf,
743 				    size_t count, loff_t *ppos)
744 {
745 	struct wl1271 *wl = file->private_data;
746 	u8 value;
747 
748 	if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_BEACON ||
749 	    wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_BEACONS)
750 		value = wl->conf.conn.listen_interval;
751 	else
752 		value = 0;
753 
754 	return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value);
755 }
756 
757 static ssize_t beacon_interval_write(struct file *file,
758 				     const char __user *user_buf,
759 				     size_t count, loff_t *ppos)
760 {
761 	struct wl1271 *wl = file->private_data;
762 	unsigned long value;
763 	int ret;
764 
765 	ret = kstrtoul_from_user(user_buf, count, 10, &value);
766 	if (ret < 0) {
767 		wl1271_warning("illegal value for beacon_interval");
768 		return -EINVAL;
769 	}
770 
771 	if (value < 1 || value > 255) {
772 		wl1271_warning("beacon interval value is not in valid range");
773 		return -ERANGE;
774 	}
775 
776 	mutex_lock(&wl->mutex);
777 
778 	wl->conf.conn.listen_interval = value;
779 	/* for some reason there are different event types for 1 and >1 */
780 	if (value == 1)
781 		wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_BEACON;
782 	else
783 		wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_BEACONS;
784 
785 	/*
786 	 * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only
787 	 * take effect on the next time we enter psm.
788 	 */
789 	mutex_unlock(&wl->mutex);
790 	return count;
791 }
792 
793 static const struct file_operations beacon_interval_ops = {
794 	.read = beacon_interval_read,
795 	.write = beacon_interval_write,
796 	.open = simple_open,
797 	.llseek = default_llseek,
798 };
799 
800 static ssize_t rx_streaming_interval_write(struct file *file,
801 			   const char __user *user_buf,
802 			   size_t count, loff_t *ppos)
803 {
804 	struct wl1271 *wl = file->private_data;
805 	struct wl12xx_vif *wlvif;
806 	unsigned long value;
807 	int ret;
808 
809 	ret = kstrtoul_from_user(user_buf, count, 10, &value);
810 	if (ret < 0) {
811 		wl1271_warning("illegal value in rx_streaming_interval!");
812 		return -EINVAL;
813 	}
814 
815 	/* valid values: 0, 10-100 */
816 	if (value && (value < 10 || value > 100)) {
817 		wl1271_warning("value is not in range!");
818 		return -ERANGE;
819 	}
820 
821 	mutex_lock(&wl->mutex);
822 
823 	wl->conf.rx_streaming.interval = value;
824 
825 	ret = pm_runtime_resume_and_get(wl->dev);
826 	if (ret < 0)
827 		goto out;
828 
829 	wl12xx_for_each_wlvif_sta(wl, wlvif) {
830 		wl1271_recalc_rx_streaming(wl, wlvif);
831 	}
832 
833 	pm_runtime_mark_last_busy(wl->dev);
834 	pm_runtime_put_autosuspend(wl->dev);
835 out:
836 	mutex_unlock(&wl->mutex);
837 	return count;
838 }
839 
840 static ssize_t rx_streaming_interval_read(struct file *file,
841 			    char __user *userbuf,
842 			    size_t count, loff_t *ppos)
843 {
844 	struct wl1271 *wl = file->private_data;
845 	return wl1271_format_buffer(userbuf, count, ppos,
846 				    "%d\n", wl->conf.rx_streaming.interval);
847 }
848 
849 static const struct file_operations rx_streaming_interval_ops = {
850 	.read = rx_streaming_interval_read,
851 	.write = rx_streaming_interval_write,
852 	.open = simple_open,
853 	.llseek = default_llseek,
854 };
855 
856 static ssize_t rx_streaming_always_write(struct file *file,
857 			   const char __user *user_buf,
858 			   size_t count, loff_t *ppos)
859 {
860 	struct wl1271 *wl = file->private_data;
861 	struct wl12xx_vif *wlvif;
862 	unsigned long value;
863 	int ret;
864 
865 	ret = kstrtoul_from_user(user_buf, count, 10, &value);
866 	if (ret < 0) {
867 		wl1271_warning("illegal value in rx_streaming_write!");
868 		return -EINVAL;
869 	}
870 
871 	/* valid values: 0, 10-100 */
872 	if (!(value == 0 || value == 1)) {
873 		wl1271_warning("value is not in valid!");
874 		return -EINVAL;
875 	}
876 
877 	mutex_lock(&wl->mutex);
878 
879 	wl->conf.rx_streaming.always = value;
880 
881 	ret = pm_runtime_resume_and_get(wl->dev);
882 	if (ret < 0)
883 		goto out;
884 
885 	wl12xx_for_each_wlvif_sta(wl, wlvif) {
886 		wl1271_recalc_rx_streaming(wl, wlvif);
887 	}
888 
889 	pm_runtime_mark_last_busy(wl->dev);
890 	pm_runtime_put_autosuspend(wl->dev);
891 out:
892 	mutex_unlock(&wl->mutex);
893 	return count;
894 }
895 
896 static ssize_t rx_streaming_always_read(struct file *file,
897 			    char __user *userbuf,
898 			    size_t count, loff_t *ppos)
899 {
900 	struct wl1271 *wl = file->private_data;
901 	return wl1271_format_buffer(userbuf, count, ppos,
902 				    "%d\n", wl->conf.rx_streaming.always);
903 }
904 
905 static const struct file_operations rx_streaming_always_ops = {
906 	.read = rx_streaming_always_read,
907 	.write = rx_streaming_always_write,
908 	.open = simple_open,
909 	.llseek = default_llseek,
910 };
911 
912 static ssize_t beacon_filtering_write(struct file *file,
913 				      const char __user *user_buf,
914 				      size_t count, loff_t *ppos)
915 {
916 	struct wl1271 *wl = file->private_data;
917 	struct wl12xx_vif *wlvif;
918 	unsigned long value;
919 	int ret;
920 
921 	ret = kstrtoul_from_user(user_buf, count, 0, &value);
922 	if (ret < 0) {
923 		wl1271_warning("illegal value for beacon_filtering!");
924 		return -EINVAL;
925 	}
926 
927 	mutex_lock(&wl->mutex);
928 
929 	ret = pm_runtime_resume_and_get(wl->dev);
930 	if (ret < 0)
931 		goto out;
932 
933 	wl12xx_for_each_wlvif(wl, wlvif) {
934 		ret = wl1271_acx_beacon_filter_opt(wl, wlvif, !!value);
935 	}
936 
937 	pm_runtime_mark_last_busy(wl->dev);
938 	pm_runtime_put_autosuspend(wl->dev);
939 out:
940 	mutex_unlock(&wl->mutex);
941 	return count;
942 }
943 
944 static const struct file_operations beacon_filtering_ops = {
945 	.write = beacon_filtering_write,
946 	.open = simple_open,
947 	.llseek = default_llseek,
948 };
949 
950 static ssize_t fw_stats_raw_read(struct file *file,
951 				 char __user *userbuf,
952 				 size_t count, loff_t *ppos)
953 {
954 	struct wl1271 *wl = file->private_data;
955 
956 	wl1271_debugfs_update_stats(wl);
957 
958 	return simple_read_from_buffer(userbuf, count, ppos,
959 				       wl->stats.fw_stats,
960 				       wl->stats.fw_stats_len);
961 }
962 
963 static const struct file_operations fw_stats_raw_ops = {
964 	.read = fw_stats_raw_read,
965 	.open = simple_open,
966 	.llseek = default_llseek,
967 };
968 
969 static ssize_t sleep_auth_read(struct file *file, char __user *user_buf,
970 			       size_t count, loff_t *ppos)
971 {
972 	struct wl1271 *wl = file->private_data;
973 
974 	return wl1271_format_buffer(user_buf, count,
975 				    ppos, "%d\n",
976 				    wl->sleep_auth);
977 }
978 
979 static ssize_t sleep_auth_write(struct file *file,
980 				const char __user *user_buf,
981 				size_t count, loff_t *ppos)
982 {
983 	struct wl1271 *wl = file->private_data;
984 	unsigned long value;
985 	int ret;
986 
987 	ret = kstrtoul_from_user(user_buf, count, 0, &value);
988 	if (ret < 0) {
989 		wl1271_warning("illegal value in sleep_auth");
990 		return -EINVAL;
991 	}
992 
993 	if (value > WL1271_PSM_MAX) {
994 		wl1271_warning("sleep_auth must be between 0 and %d",
995 			       WL1271_PSM_MAX);
996 		return -ERANGE;
997 	}
998 
999 	mutex_lock(&wl->mutex);
1000 
1001 	wl->conf.conn.sta_sleep_auth = value;
1002 
1003 	if (unlikely(wl->state != WLCORE_STATE_ON)) {
1004 		/* this will show up on "read" in case we are off */
1005 		wl->sleep_auth = value;
1006 		goto out;
1007 	}
1008 
1009 	ret = pm_runtime_resume_and_get(wl->dev);
1010 	if (ret < 0)
1011 		goto out;
1012 
1013 	ret = wl1271_acx_sleep_auth(wl, value);
1014 	if (ret < 0)
1015 		goto out_sleep;
1016 
1017 out_sleep:
1018 	pm_runtime_mark_last_busy(wl->dev);
1019 	pm_runtime_put_autosuspend(wl->dev);
1020 out:
1021 	mutex_unlock(&wl->mutex);
1022 	return count;
1023 }
1024 
1025 static const struct file_operations sleep_auth_ops = {
1026 	.read = sleep_auth_read,
1027 	.write = sleep_auth_write,
1028 	.open = simple_open,
1029 	.llseek = default_llseek,
1030 };
1031 
1032 static ssize_t dev_mem_read(struct file *file,
1033 	     char __user *user_buf, size_t count,
1034 	     loff_t *ppos)
1035 {
1036 	struct wl1271 *wl = file->private_data;
1037 	struct wlcore_partition_set part, old_part;
1038 	size_t bytes = count;
1039 	int ret;
1040 	char *buf;
1041 
1042 	/* only requests of dword-aligned size and offset are supported */
1043 	if (bytes % 4)
1044 		return -EINVAL;
1045 
1046 	if (*ppos % 4)
1047 		return -EINVAL;
1048 
1049 	/* function should return in reasonable time */
1050 	bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE);
1051 
1052 	if (bytes == 0)
1053 		return -EINVAL;
1054 
1055 	memset(&part, 0, sizeof(part));
1056 	part.mem.start = *ppos;
1057 	part.mem.size = bytes;
1058 
1059 	buf = kmalloc(bytes, GFP_KERNEL);
1060 	if (!buf)
1061 		return -ENOMEM;
1062 
1063 	mutex_lock(&wl->mutex);
1064 
1065 	if (unlikely(wl->state == WLCORE_STATE_OFF)) {
1066 		ret = -EFAULT;
1067 		goto skip_read;
1068 	}
1069 
1070 	/*
1071 	 * Don't fail if elp_wakeup returns an error, so the device's memory
1072 	 * could be read even if the FW crashed
1073 	 */
1074 	pm_runtime_get_sync(wl->dev);
1075 
1076 	/* store current partition and switch partition */
1077 	memcpy(&old_part, &wl->curr_part, sizeof(old_part));
1078 	ret = wlcore_set_partition(wl, &part);
1079 	if (ret < 0)
1080 		goto part_err;
1081 
1082 	ret = wlcore_raw_read(wl, 0, buf, bytes, false);
1083 	if (ret < 0)
1084 		goto read_err;
1085 
1086 read_err:
1087 	/* recover partition */
1088 	ret = wlcore_set_partition(wl, &old_part);
1089 	if (ret < 0)
1090 		goto part_err;
1091 
1092 part_err:
1093 	pm_runtime_mark_last_busy(wl->dev);
1094 	pm_runtime_put_autosuspend(wl->dev);
1095 
1096 skip_read:
1097 	mutex_unlock(&wl->mutex);
1098 
1099 	if (ret == 0) {
1100 		ret = copy_to_user(user_buf, buf, bytes);
1101 		if (ret < bytes) {
1102 			bytes -= ret;
1103 			*ppos += bytes;
1104 			ret = 0;
1105 		} else {
1106 			ret = -EFAULT;
1107 		}
1108 	}
1109 
1110 	kfree(buf);
1111 
1112 	return ((ret == 0) ? bytes : ret);
1113 }
1114 
1115 static ssize_t dev_mem_write(struct file *file, const char __user *user_buf,
1116 		size_t count, loff_t *ppos)
1117 {
1118 	struct wl1271 *wl = file->private_data;
1119 	struct wlcore_partition_set part, old_part;
1120 	size_t bytes = count;
1121 	int ret;
1122 	char *buf;
1123 
1124 	/* only requests of dword-aligned size and offset are supported */
1125 	if (bytes % 4)
1126 		return -EINVAL;
1127 
1128 	if (*ppos % 4)
1129 		return -EINVAL;
1130 
1131 	/* function should return in reasonable time */
1132 	bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE);
1133 
1134 	if (bytes == 0)
1135 		return -EINVAL;
1136 
1137 	memset(&part, 0, sizeof(part));
1138 	part.mem.start = *ppos;
1139 	part.mem.size = bytes;
1140 
1141 	buf = memdup_user(user_buf, bytes);
1142 	if (IS_ERR(buf))
1143 		return PTR_ERR(buf);
1144 
1145 	mutex_lock(&wl->mutex);
1146 
1147 	if (unlikely(wl->state == WLCORE_STATE_OFF)) {
1148 		ret = -EFAULT;
1149 		goto skip_write;
1150 	}
1151 
1152 	/*
1153 	 * Don't fail if elp_wakeup returns an error, so the device's memory
1154 	 * could be read even if the FW crashed
1155 	 */
1156 	pm_runtime_get_sync(wl->dev);
1157 
1158 	/* store current partition and switch partition */
1159 	memcpy(&old_part, &wl->curr_part, sizeof(old_part));
1160 	ret = wlcore_set_partition(wl, &part);
1161 	if (ret < 0)
1162 		goto part_err;
1163 
1164 	ret = wlcore_raw_write(wl, 0, buf, bytes, false);
1165 	if (ret < 0)
1166 		goto write_err;
1167 
1168 write_err:
1169 	/* recover partition */
1170 	ret = wlcore_set_partition(wl, &old_part);
1171 	if (ret < 0)
1172 		goto part_err;
1173 
1174 part_err:
1175 	pm_runtime_mark_last_busy(wl->dev);
1176 	pm_runtime_put_autosuspend(wl->dev);
1177 
1178 skip_write:
1179 	mutex_unlock(&wl->mutex);
1180 
1181 	if (ret == 0)
1182 		*ppos += bytes;
1183 
1184 	kfree(buf);
1185 
1186 	return ((ret == 0) ? bytes : ret);
1187 }
1188 
1189 static loff_t dev_mem_seek(struct file *file, loff_t offset, int orig)
1190 {
1191 	/* only requests of dword-aligned size and offset are supported */
1192 	if (offset % 4)
1193 		return -EINVAL;
1194 
1195 	return no_seek_end_llseek(file, offset, orig);
1196 }
1197 
1198 static const struct file_operations dev_mem_ops = {
1199 	.open = simple_open,
1200 	.read = dev_mem_read,
1201 	.write = dev_mem_write,
1202 	.llseek = dev_mem_seek,
1203 };
1204 
1205 static ssize_t fw_logger_read(struct file *file, char __user *user_buf,
1206 			      size_t count, loff_t *ppos)
1207 {
1208 	struct wl1271 *wl = file->private_data;
1209 
1210 	return wl1271_format_buffer(user_buf, count,
1211 					ppos, "%d\n",
1212 					wl->conf.fwlog.output);
1213 }
1214 
1215 static ssize_t fw_logger_write(struct file *file,
1216 			       const char __user *user_buf,
1217 			       size_t count, loff_t *ppos)
1218 {
1219 	struct wl1271 *wl = file->private_data;
1220 	unsigned long value;
1221 	int ret;
1222 
1223 	ret = kstrtoul_from_user(user_buf, count, 0, &value);
1224 	if (ret < 0) {
1225 		wl1271_warning("illegal value in fw_logger");
1226 		return -EINVAL;
1227 	}
1228 
1229 	if ((value > 2) || (value == 0)) {
1230 		wl1271_warning("fw_logger value must be 1-UART 2-SDIO");
1231 		return -ERANGE;
1232 	}
1233 
1234 	if (wl->conf.fwlog.output == 0) {
1235 		wl1271_warning("invalid operation - fw logger disabled by default, please change mode via wlconf");
1236 		return -EINVAL;
1237 	}
1238 
1239 	mutex_lock(&wl->mutex);
1240 	ret = pm_runtime_resume_and_get(wl->dev);
1241 	if (ret < 0) {
1242 		count = ret;
1243 		goto out;
1244 	}
1245 
1246 	wl->conf.fwlog.output = value;
1247 
1248 	ret = wl12xx_cmd_config_fwlog(wl);
1249 
1250 	pm_runtime_mark_last_busy(wl->dev);
1251 	pm_runtime_put_autosuspend(wl->dev);
1252 
1253 out:
1254 	mutex_unlock(&wl->mutex);
1255 	return count;
1256 }
1257 
1258 static const struct file_operations fw_logger_ops = {
1259 	.open = simple_open,
1260 	.read = fw_logger_read,
1261 	.write = fw_logger_write,
1262 	.llseek = default_llseek,
1263 };
1264 
1265 static void wl1271_debugfs_add_files(struct wl1271 *wl,
1266 				     struct dentry *rootdir)
1267 {
1268 	struct dentry *streaming;
1269 
1270 	DEBUGFS_ADD(tx_queue_len, rootdir);
1271 	DEBUGFS_ADD(retry_count, rootdir);
1272 	DEBUGFS_ADD(excessive_retries, rootdir);
1273 
1274 	DEBUGFS_ADD(gpio_power, rootdir);
1275 	DEBUGFS_ADD(start_recovery, rootdir);
1276 	DEBUGFS_ADD(driver_state, rootdir);
1277 	DEBUGFS_ADD(vifs_state, rootdir);
1278 	DEBUGFS_ADD(dtim_interval, rootdir);
1279 	DEBUGFS_ADD(suspend_dtim_interval, rootdir);
1280 	DEBUGFS_ADD(beacon_interval, rootdir);
1281 	DEBUGFS_ADD(beacon_filtering, rootdir);
1282 	DEBUGFS_ADD(dynamic_ps_timeout, rootdir);
1283 	DEBUGFS_ADD(forced_ps, rootdir);
1284 	DEBUGFS_ADD(split_scan_timeout, rootdir);
1285 	DEBUGFS_ADD(irq_pkt_threshold, rootdir);
1286 	DEBUGFS_ADD(irq_blk_threshold, rootdir);
1287 	DEBUGFS_ADD(irq_timeout, rootdir);
1288 	DEBUGFS_ADD(fw_stats_raw, rootdir);
1289 	DEBUGFS_ADD(sleep_auth, rootdir);
1290 	DEBUGFS_ADD(fw_logger, rootdir);
1291 
1292 	streaming = debugfs_create_dir("rx_streaming", rootdir);
1293 
1294 	DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming);
1295 	DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming);
1296 
1297 	DEBUGFS_ADD_PREFIX(dev, mem, rootdir);
1298 }
1299 
1300 void wl1271_debugfs_reset(struct wl1271 *wl)
1301 {
1302 	if (!wl->stats.fw_stats)
1303 		return;
1304 
1305 	memset(wl->stats.fw_stats, 0, wl->stats.fw_stats_len);
1306 	wl->stats.retry_count = 0;
1307 	wl->stats.excessive_retries = 0;
1308 }
1309 
1310 int wl1271_debugfs_init(struct wl1271 *wl)
1311 {
1312 	int ret;
1313 	struct dentry *rootdir;
1314 
1315 	rootdir = debugfs_create_dir(KBUILD_MODNAME,
1316 				     wl->hw->wiphy->debugfsdir);
1317 
1318 	wl->stats.fw_stats = kzalloc(wl->stats.fw_stats_len, GFP_KERNEL);
1319 	if (!wl->stats.fw_stats) {
1320 		ret = -ENOMEM;
1321 		goto out_remove;
1322 	}
1323 
1324 	wl->stats.fw_stats_update = jiffies;
1325 
1326 	wl1271_debugfs_add_files(wl, rootdir);
1327 
1328 	ret = wlcore_debugfs_init(wl, rootdir);
1329 	if (ret < 0)
1330 		goto out_exit;
1331 
1332 	goto out;
1333 
1334 out_exit:
1335 	wl1271_debugfs_exit(wl);
1336 
1337 out_remove:
1338 	debugfs_remove_recursive(rootdir);
1339 
1340 out:
1341 	return ret;
1342 }
1343 
1344 void wl1271_debugfs_exit(struct wl1271 *wl)
1345 {
1346 	kfree(wl->stats.fw_stats);
1347 	wl->stats.fw_stats = NULL;
1348 }
1349