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