1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/debugfs.h>
21
22#include "main.h"
23#include "11n.h"
24
25
26static struct dentry *mwifiex_dfs_dir;
27
28static char *bss_modes[] = {
29 "UNSPECIFIED",
30 "ADHOC",
31 "STATION",
32 "AP",
33 "AP_VLAN",
34 "WDS",
35 "MONITOR",
36 "MESH_POINT",
37 "P2P_CLIENT",
38 "P2P_GO",
39 "P2P_DEVICE",
40};
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73static ssize_t
74mwifiex_info_read(struct file *file, char __user *ubuf,
75 size_t count, loff_t *ppos)
76{
77 struct mwifiex_private *priv =
78 (struct mwifiex_private *) file->private_data;
79 struct net_device *netdev = priv->netdev;
80 struct netdev_hw_addr *ha;
81 struct netdev_queue *txq;
82 unsigned long page = get_zeroed_page(GFP_KERNEL);
83 char *p = (char *) page, fmt[64];
84 struct mwifiex_bss_info info;
85 ssize_t ret;
86 int i = 0;
87
88 if (!p)
89 return -ENOMEM;
90
91 memset(&info, 0, sizeof(info));
92 ret = mwifiex_get_bss_info(priv, &info);
93 if (ret)
94 goto free_and_exit;
95
96 mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1);
97
98 mwifiex_get_ver_ext(priv, 0);
99
100 p += sprintf(p, "driver_name = " "\"mwifiex\"\n");
101 p += sprintf(p, "driver_version = %s", fmt);
102 p += sprintf(p, "\nverext = %s", priv->version_str);
103 p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name);
104
105 if (info.bss_mode >= ARRAY_SIZE(bss_modes))
106 p += sprintf(p, "bss_mode=\"%d\"\n", info.bss_mode);
107 else
108 p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]);
109
110 p += sprintf(p, "media_state=\"%s\"\n",
111 (!priv->media_connected ? "Disconnected" : "Connected"));
112 p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr);
113
114 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
115 p += sprintf(p, "multicast_count=\"%d\"\n",
116 netdev_mc_count(netdev));
117 p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid);
118 p += sprintf(p, "bssid=\"%pM\"\n", info.bssid);
119 p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan);
120 p += sprintf(p, "country_code = \"%s\"\n", info.country_code);
121 p += sprintf(p, "region_code=\"0x%x\"\n",
122 priv->adapter->region_code);
123
124 netdev_for_each_mc_addr(ha, netdev)
125 p += sprintf(p, "multicast_address[%d]=\"%pM\"\n",
126 i++, ha->addr);
127 }
128
129 p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
130 p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes);
131 p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets);
132 p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets);
133 p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped);
134 p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped);
135 p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors);
136 p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
137 p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev))
138 ? "on" : "off"));
139 p += sprintf(p, "tx queue");
140 for (i = 0; i < netdev->num_tx_queues; i++) {
141 txq = netdev_get_tx_queue(netdev, i);
142 p += sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ?
143 "stopped" : "started");
144 }
145 p += sprintf(p, "\n");
146
147 ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
148 (unsigned long) p - page);
149
150free_and_exit:
151 free_page(page);
152 return ret;
153}
154
155
156
157
158
159
160
161
162
163
164static ssize_t
165mwifiex_device_dump_read(struct file *file, char __user *ubuf,
166 size_t count, loff_t *ppos)
167{
168 struct mwifiex_private *priv = file->private_data;
169
170 if (!priv->adapter->if_ops.device_dump)
171 return -EIO;
172
173 priv->adapter->if_ops.device_dump(priv->adapter);
174
175 return 0;
176}
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199static ssize_t
200mwifiex_getlog_read(struct file *file, char __user *ubuf,
201 size_t count, loff_t *ppos)
202{
203 struct mwifiex_private *priv =
204 (struct mwifiex_private *) file->private_data;
205 unsigned long page = get_zeroed_page(GFP_KERNEL);
206 char *p = (char *) page;
207 ssize_t ret;
208 struct mwifiex_ds_get_stats stats;
209
210 if (!p)
211 return -ENOMEM;
212
213 memset(&stats, 0, sizeof(stats));
214 ret = mwifiex_get_stats_info(priv, &stats);
215 if (ret)
216 goto free_and_exit;
217
218 p += sprintf(p, "\n"
219 "mcasttxframe %u\n"
220 "failed %u\n"
221 "retry %u\n"
222 "multiretry %u\n"
223 "framedup %u\n"
224 "rtssuccess %u\n"
225 "rtsfailure %u\n"
226 "ackfailure %u\n"
227 "rxfrag %u\n"
228 "mcastrxframe %u\n"
229 "fcserror %u\n"
230 "txframe %u\n"
231 "wepicverrcnt-1 %u\n"
232 "wepicverrcnt-2 %u\n"
233 "wepicverrcnt-3 %u\n"
234 "wepicverrcnt-4 %u\n"
235 "bcn_rcv_cnt %u\n"
236 "bcn_miss_cnt %u\n",
237 stats.mcast_tx_frame,
238 stats.failed,
239 stats.retry,
240 stats.multi_retry,
241 stats.frame_dup,
242 stats.rts_success,
243 stats.rts_failure,
244 stats.ack_failure,
245 stats.rx_frag,
246 stats.mcast_rx_frame,
247 stats.fcs_error,
248 stats.tx_frame,
249 stats.wep_icv_error[0],
250 stats.wep_icv_error[1],
251 stats.wep_icv_error[2],
252 stats.wep_icv_error[3],
253 stats.bcn_rcv_cnt,
254 stats.bcn_miss_cnt);
255
256
257 ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
258 (unsigned long) p - page);
259
260free_and_exit:
261 free_page(page);
262 return ret;
263}
264
265
266
267
268
269
270
271
272
273
274
275static ssize_t
276mwifiex_histogram_read(struct file *file, char __user *ubuf,
277 size_t count, loff_t *ppos)
278{
279 struct mwifiex_private *priv =
280 (struct mwifiex_private *)file->private_data;
281 ssize_t ret;
282 struct mwifiex_histogram_data *phist_data;
283 int i, value;
284 unsigned long page = get_zeroed_page(GFP_KERNEL);
285 char *p = (char *)page;
286
287 if (!p)
288 return -ENOMEM;
289
290 if (!priv || !priv->hist_data)
291 return -EFAULT;
292 phist_data = priv->hist_data;
293
294 p += sprintf(p, "\n"
295 "total samples = %d\n",
296 atomic_read(&phist_data->num_samples));
297
298 p += sprintf(p, "rx rates (in Mbps): 0=1M 1=2M");
299 p += sprintf(p, "2=5.5M 3=11M 4=6M 5=9M 6=12M\n");
300 p += sprintf(p, "7=18M 8=24M 9=36M 10=48M 11=54M");
301 p += sprintf(p, "12-27=MCS0-15(BW20) 28-43=MCS0-15(BW40)\n");
302
303 if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) {
304 p += sprintf(p, "44-53=MCS0-9(VHT:BW20)");
305 p += sprintf(p, "54-63=MCS0-9(VHT:BW40)");
306 p += sprintf(p, "64-73=MCS0-9(VHT:BW80)\n\n");
307 } else {
308 p += sprintf(p, "\n");
309 }
310
311 for (i = 0; i < MWIFIEX_MAX_RX_RATES; i++) {
312 value = atomic_read(&phist_data->rx_rate[i]);
313 if (value)
314 p += sprintf(p, "rx_rate[%02d] = %d\n", i, value);
315 }
316
317 if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) {
318 for (i = MWIFIEX_MAX_RX_RATES; i < MWIFIEX_MAX_AC_RX_RATES;
319 i++) {
320 value = atomic_read(&phist_data->rx_rate[i]);
321 if (value)
322 p += sprintf(p, "rx_rate[%02d] = %d\n",
323 i, value);
324 }
325 }
326
327 for (i = 0; i < MWIFIEX_MAX_SNR; i++) {
328 value = atomic_read(&phist_data->snr[i]);
329 if (value)
330 p += sprintf(p, "snr[%02ddB] = %d\n", i, value);
331 }
332 for (i = 0; i < MWIFIEX_MAX_NOISE_FLR; i++) {
333 value = atomic_read(&phist_data->noise_flr[i]);
334 if (value)
335 p += sprintf(p, "noise_flr[-%02ddBm] = %d\n",
336 (int)(i-128), value);
337 }
338 for (i = 0; i < MWIFIEX_MAX_SIG_STRENGTH; i++) {
339 value = atomic_read(&phist_data->sig_str[i]);
340 if (value)
341 p += sprintf(p, "sig_strength[-%02ddBm] = %d\n",
342 i, value);
343 }
344
345 ret = simple_read_from_buffer(ubuf, count, ppos, (char *)page,
346 (unsigned long)p - page);
347
348 return ret;
349}
350
351static ssize_t
352mwifiex_histogram_write(struct file *file, const char __user *ubuf,
353 size_t count, loff_t *ppos)
354{
355 struct mwifiex_private *priv = (void *)file->private_data;
356
357 if (priv && priv->hist_data)
358 mwifiex_hist_data_reset(priv);
359 return 0;
360}
361
362static struct mwifiex_debug_info info;
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411static ssize_t
412mwifiex_debug_read(struct file *file, char __user *ubuf,
413 size_t count, loff_t *ppos)
414{
415 struct mwifiex_private *priv =
416 (struct mwifiex_private *) file->private_data;
417 unsigned long page = get_zeroed_page(GFP_KERNEL);
418 char *p = (char *) page;
419 ssize_t ret;
420
421 if (!p)
422 return -ENOMEM;
423
424 ret = mwifiex_get_debug_info(priv, &info);
425 if (ret)
426 goto free_and_exit;
427
428 p += mwifiex_debug_info_to_buffer(priv, p, &info);
429
430 ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
431 (unsigned long) p - page);
432
433free_and_exit:
434 free_page(page);
435 return ret;
436}
437
438static u32 saved_reg_type, saved_reg_offset, saved_reg_value;
439
440
441
442
443
444
445
446
447static ssize_t
448mwifiex_regrdwr_write(struct file *file,
449 const char __user *ubuf, size_t count, loff_t *ppos)
450{
451 char *buf;
452 int ret;
453 u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX;
454
455 buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
456 if (IS_ERR(buf))
457 return PTR_ERR(buf);
458
459 sscanf(buf, "%u %x %x", ®_type, ®_offset, ®_value);
460
461 if (reg_type == 0 || reg_offset == 0) {
462 ret = -EINVAL;
463 goto done;
464 } else {
465 saved_reg_type = reg_type;
466 saved_reg_offset = reg_offset;
467 saved_reg_value = reg_value;
468 ret = count;
469 }
470done:
471 kfree(buf);
472 return ret;
473}
474
475
476
477
478
479
480
481
482static ssize_t
483mwifiex_regrdwr_read(struct file *file, char __user *ubuf,
484 size_t count, loff_t *ppos)
485{
486 struct mwifiex_private *priv =
487 (struct mwifiex_private *) file->private_data;
488 unsigned long addr = get_zeroed_page(GFP_KERNEL);
489 char *buf = (char *) addr;
490 int pos = 0, ret = 0;
491 u32 reg_value;
492
493 if (!buf)
494 return -ENOMEM;
495
496 if (!saved_reg_type) {
497
498 pos += snprintf(buf, PAGE_SIZE, "0");
499 goto done;
500 }
501
502 if (saved_reg_value != UINT_MAX) {
503 ret = mwifiex_reg_write(priv, saved_reg_type, saved_reg_offset,
504 saved_reg_value);
505
506 pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n",
507 saved_reg_type, saved_reg_offset,
508 saved_reg_value);
509
510 ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
511
512 goto done;
513 }
514
515 ret = mwifiex_reg_read(priv, saved_reg_type,
516 saved_reg_offset, ®_value);
517 if (ret) {
518 ret = -EINVAL;
519 goto done;
520 }
521
522 pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", saved_reg_type,
523 saved_reg_offset, reg_value);
524
525 ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
526
527done:
528 free_page(addr);
529 return ret;
530}
531
532
533
534
535
536static ssize_t
537mwifiex_debug_mask_read(struct file *file, char __user *ubuf,
538 size_t count, loff_t *ppos)
539{
540 struct mwifiex_private *priv =
541 (struct mwifiex_private *)file->private_data;
542 unsigned long page = get_zeroed_page(GFP_KERNEL);
543 char *buf = (char *)page;
544 size_t ret = 0;
545 int pos = 0;
546
547 if (!buf)
548 return -ENOMEM;
549
550 pos += snprintf(buf, PAGE_SIZE, "debug mask=0x%08x\n",
551 priv->adapter->debug_mask);
552 ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
553
554 free_page(page);
555 return ret;
556}
557
558
559
560
561
562static ssize_t
563mwifiex_debug_mask_write(struct file *file, const char __user *ubuf,
564 size_t count, loff_t *ppos)
565{
566 int ret;
567 unsigned long debug_mask;
568 struct mwifiex_private *priv = (void *)file->private_data;
569 char *buf;
570
571 buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
572 if (IS_ERR(buf))
573 return PTR_ERR(buf);
574
575 if (kstrtoul(buf, 0, &debug_mask)) {
576 ret = -EINVAL;
577 goto done;
578 }
579
580 priv->adapter->debug_mask = debug_mask;
581 ret = count;
582done:
583 kfree(buf);
584 return ret;
585}
586
587
588
589
590static ssize_t
591mwifiex_verext_write(struct file *file, const char __user *ubuf,
592 size_t count, loff_t *ppos)
593{
594 int ret;
595 u32 versionstrsel;
596 struct mwifiex_private *priv = (void *)file->private_data;
597 char buf[16];
598
599 memset(buf, 0, sizeof(buf));
600
601 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
602 return -EFAULT;
603
604 ret = kstrtou32(buf, 10, &versionstrsel);
605 if (ret)
606 return ret;
607
608 priv->versionstrsel = versionstrsel;
609
610 return count;
611}
612
613
614
615
616
617static ssize_t
618mwifiex_verext_read(struct file *file, char __user *ubuf,
619 size_t count, loff_t *ppos)
620{
621 struct mwifiex_private *priv =
622 (struct mwifiex_private *)file->private_data;
623 char buf[256];
624 int ret;
625
626 mwifiex_get_ver_ext(priv, priv->versionstrsel);
627 ret = snprintf(buf, sizeof(buf), "version string: %s\n",
628 priv->version_str);
629
630 return simple_read_from_buffer(ubuf, count, ppos, buf, ret);
631}
632
633
634
635
636
637static ssize_t
638mwifiex_memrw_write(struct file *file, const char __user *ubuf, size_t count,
639 loff_t *ppos)
640{
641 int ret;
642 char cmd;
643 struct mwifiex_ds_mem_rw mem_rw;
644 u16 cmd_action;
645 struct mwifiex_private *priv = (void *)file->private_data;
646 char *buf;
647
648 buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
649 if (IS_ERR(buf))
650 return PTR_ERR(buf);
651
652 ret = sscanf(buf, "%c %x %x", &cmd, &mem_rw.addr, &mem_rw.value);
653 if (ret != 3) {
654 ret = -EINVAL;
655 goto done;
656 }
657
658 if ((cmd == 'r') || (cmd == 'R')) {
659 cmd_action = HostCmd_ACT_GEN_GET;
660 mem_rw.value = 0;
661 } else if ((cmd == 'w') || (cmd == 'W')) {
662 cmd_action = HostCmd_ACT_GEN_SET;
663 } else {
664 ret = -EINVAL;
665 goto done;
666 }
667
668 memcpy(&priv->mem_rw, &mem_rw, sizeof(mem_rw));
669 if (mwifiex_send_cmd(priv, HostCmd_CMD_MEM_ACCESS, cmd_action, 0,
670 &mem_rw, true))
671 ret = -1;
672 else
673 ret = count;
674
675done:
676 kfree(buf);
677 return ret;
678}
679
680
681
682
683
684static ssize_t
685mwifiex_memrw_read(struct file *file, char __user *ubuf,
686 size_t count, loff_t *ppos)
687{
688 struct mwifiex_private *priv = (void *)file->private_data;
689 unsigned long addr = get_zeroed_page(GFP_KERNEL);
690 char *buf = (char *)addr;
691 int ret, pos = 0;
692
693 if (!buf)
694 return -ENOMEM;
695
696 pos += snprintf(buf, PAGE_SIZE, "0x%x 0x%x\n", priv->mem_rw.addr,
697 priv->mem_rw.value);
698 ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
699
700 free_page(addr);
701 return ret;
702}
703
704static u32 saved_offset = -1, saved_bytes = -1;
705
706
707
708
709
710
711
712
713static ssize_t
714mwifiex_rdeeprom_write(struct file *file,
715 const char __user *ubuf, size_t count, loff_t *ppos)
716{
717 char *buf;
718 int ret = 0;
719 int offset = -1, bytes = -1;
720
721 buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
722 if (IS_ERR(buf))
723 return PTR_ERR(buf);
724
725 sscanf(buf, "%d %d", &offset, &bytes);
726
727 if (offset == -1 || bytes == -1) {
728 ret = -EINVAL;
729 goto done;
730 } else {
731 saved_offset = offset;
732 saved_bytes = bytes;
733 ret = count;
734 }
735done:
736 kfree(buf);
737 return ret;
738}
739
740
741
742
743
744
745
746
747static ssize_t
748mwifiex_rdeeprom_read(struct file *file, char __user *ubuf,
749 size_t count, loff_t *ppos)
750{
751 struct mwifiex_private *priv =
752 (struct mwifiex_private *) file->private_data;
753 unsigned long addr = get_zeroed_page(GFP_KERNEL);
754 char *buf = (char *) addr;
755 int pos, ret, i;
756 u8 value[MAX_EEPROM_DATA];
757
758 if (!buf)
759 return -ENOMEM;
760
761 if (saved_offset == -1) {
762
763 pos = snprintf(buf, PAGE_SIZE, "0");
764 goto done;
765 }
766
767
768 ret = mwifiex_eeprom_read(priv, (u16) saved_offset,
769 (u16) saved_bytes, value);
770 if (ret) {
771 ret = -EINVAL;
772 goto out_free;
773 }
774
775 pos = snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes);
776
777 for (i = 0; i < saved_bytes; i++)
778 pos += scnprintf(buf + pos, PAGE_SIZE - pos, "%d ", value[i]);
779
780done:
781 ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
782out_free:
783 free_page(addr);
784 return ret;
785}
786
787
788
789
790static ssize_t
791mwifiex_hscfg_write(struct file *file, const char __user *ubuf,
792 size_t count, loff_t *ppos)
793{
794 struct mwifiex_private *priv = (void *)file->private_data;
795 char *buf;
796 int ret, arg_num;
797 struct mwifiex_ds_hs_cfg hscfg;
798 int conditions = HS_CFG_COND_DEF;
799 u32 gpio = HS_CFG_GPIO_DEF, gap = HS_CFG_GAP_DEF;
800
801 buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
802 if (IS_ERR(buf))
803 return PTR_ERR(buf);
804
805 arg_num = sscanf(buf, "%d %x %x", &conditions, &gpio, &gap);
806
807 memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg));
808
809 if (arg_num > 3) {
810 mwifiex_dbg(priv->adapter, ERROR,
811 "Too many arguments\n");
812 ret = -EINVAL;
813 goto done;
814 }
815
816 if (arg_num >= 1 && arg_num < 3)
817 mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
818 MWIFIEX_SYNC_CMD, &hscfg);
819
820 if (arg_num) {
821 if (conditions == HS_CFG_CANCEL) {
822 mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD);
823 ret = count;
824 goto done;
825 }
826 hscfg.conditions = conditions;
827 }
828 if (arg_num >= 2)
829 hscfg.gpio = gpio;
830 if (arg_num == 3)
831 hscfg.gap = gap;
832
833 hscfg.is_invoke_hostcmd = false;
834 mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
835 MWIFIEX_SYNC_CMD, &hscfg);
836
837 mwifiex_enable_hs(priv->adapter);
838 priv->adapter->hs_enabling = false;
839 ret = count;
840done:
841 kfree(buf);
842 return ret;
843}
844
845
846
847
848
849static ssize_t
850mwifiex_hscfg_read(struct file *file, char __user *ubuf,
851 size_t count, loff_t *ppos)
852{
853 struct mwifiex_private *priv = (void *)file->private_data;
854 unsigned long addr = get_zeroed_page(GFP_KERNEL);
855 char *buf = (char *)addr;
856 int pos, ret;
857 struct mwifiex_ds_hs_cfg hscfg;
858
859 if (!buf)
860 return -ENOMEM;
861
862 mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
863 MWIFIEX_SYNC_CMD, &hscfg);
864
865 pos = snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", hscfg.conditions,
866 hscfg.gpio, hscfg.gap);
867
868 ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
869
870 free_page(addr);
871 return ret;
872}
873
874static ssize_t
875mwifiex_timeshare_coex_read(struct file *file, char __user *ubuf,
876 size_t count, loff_t *ppos)
877{
878 struct mwifiex_private *priv = file->private_data;
879 char buf[3];
880 bool timeshare_coex;
881 int ret;
882 unsigned int len;
883
884 if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15)
885 return -EOPNOTSUPP;
886
887 ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX,
888 HostCmd_ACT_GEN_GET, 0, ×hare_coex, true);
889 if (ret)
890 return ret;
891
892 len = sprintf(buf, "%d\n", timeshare_coex);
893 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
894}
895
896static ssize_t
897mwifiex_timeshare_coex_write(struct file *file, const char __user *ubuf,
898 size_t count, loff_t *ppos)
899{
900 bool timeshare_coex;
901 struct mwifiex_private *priv = file->private_data;
902 char kbuf[16];
903 int ret;
904
905 if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15)
906 return -EOPNOTSUPP;
907
908 memset(kbuf, 0, sizeof(kbuf));
909
910 if (copy_from_user(&kbuf, ubuf, min_t(size_t, sizeof(kbuf) - 1, count)))
911 return -EFAULT;
912
913 if (strtobool(kbuf, ×hare_coex))
914 return -EINVAL;
915
916 ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX,
917 HostCmd_ACT_GEN_SET, 0, ×hare_coex, true);
918 if (ret)
919 return ret;
920 else
921 return count;
922}
923
924static ssize_t
925mwifiex_reset_write(struct file *file,
926 const char __user *ubuf, size_t count, loff_t *ppos)
927{
928 struct mwifiex_private *priv = file->private_data;
929 struct mwifiex_adapter *adapter = priv->adapter;
930 bool result;
931 int rc;
932
933 rc = kstrtobool_from_user(ubuf, count, &result);
934 if (rc)
935 return rc;
936
937 if (!result)
938 return -EINVAL;
939
940 if (adapter->if_ops.card_reset) {
941 dev_info(adapter->dev, "Resetting per request\n");
942 adapter->hw_status = MWIFIEX_HW_STATUS_RESET;
943 mwifiex_cancel_all_pending_cmd(adapter);
944 adapter->if_ops.card_reset(adapter);
945 }
946
947 return count;
948}
949
950#define MWIFIEX_DFS_ADD_FILE(name) do { \
951 if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir, \
952 priv, &mwifiex_dfs_##name##_fops)) \
953 return; \
954} while (0);
955
956#define MWIFIEX_DFS_FILE_OPS(name) \
957static const struct file_operations mwifiex_dfs_##name##_fops = { \
958 .read = mwifiex_##name##_read, \
959 .write = mwifiex_##name##_write, \
960 .open = simple_open, \
961};
962
963#define MWIFIEX_DFS_FILE_READ_OPS(name) \
964static const struct file_operations mwifiex_dfs_##name##_fops = { \
965 .read = mwifiex_##name##_read, \
966 .open = simple_open, \
967};
968
969#define MWIFIEX_DFS_FILE_WRITE_OPS(name) \
970static const struct file_operations mwifiex_dfs_##name##_fops = { \
971 .write = mwifiex_##name##_write, \
972 .open = simple_open, \
973};
974
975
976MWIFIEX_DFS_FILE_READ_OPS(info);
977MWIFIEX_DFS_FILE_READ_OPS(debug);
978MWIFIEX_DFS_FILE_READ_OPS(getlog);
979MWIFIEX_DFS_FILE_READ_OPS(device_dump);
980MWIFIEX_DFS_FILE_OPS(regrdwr);
981MWIFIEX_DFS_FILE_OPS(rdeeprom);
982MWIFIEX_DFS_FILE_OPS(memrw);
983MWIFIEX_DFS_FILE_OPS(hscfg);
984MWIFIEX_DFS_FILE_OPS(histogram);
985MWIFIEX_DFS_FILE_OPS(debug_mask);
986MWIFIEX_DFS_FILE_OPS(timeshare_coex);
987MWIFIEX_DFS_FILE_WRITE_OPS(reset);
988MWIFIEX_DFS_FILE_OPS(verext);
989
990
991
992
993void
994mwifiex_dev_debugfs_init(struct mwifiex_private *priv)
995{
996 if (!mwifiex_dfs_dir || !priv)
997 return;
998
999 priv->dfs_dev_dir = debugfs_create_dir(priv->netdev->name,
1000 mwifiex_dfs_dir);
1001
1002 if (!priv->dfs_dev_dir)
1003 return;
1004
1005 MWIFIEX_DFS_ADD_FILE(info);
1006 MWIFIEX_DFS_ADD_FILE(debug);
1007 MWIFIEX_DFS_ADD_FILE(getlog);
1008 MWIFIEX_DFS_ADD_FILE(regrdwr);
1009 MWIFIEX_DFS_ADD_FILE(rdeeprom);
1010 MWIFIEX_DFS_ADD_FILE(device_dump);
1011 MWIFIEX_DFS_ADD_FILE(memrw);
1012 MWIFIEX_DFS_ADD_FILE(hscfg);
1013 MWIFIEX_DFS_ADD_FILE(histogram);
1014 MWIFIEX_DFS_ADD_FILE(debug_mask);
1015 MWIFIEX_DFS_ADD_FILE(timeshare_coex);
1016 MWIFIEX_DFS_ADD_FILE(reset);
1017 MWIFIEX_DFS_ADD_FILE(verext);
1018}
1019
1020
1021
1022
1023void
1024mwifiex_dev_debugfs_remove(struct mwifiex_private *priv)
1025{
1026 if (!priv)
1027 return;
1028
1029 debugfs_remove_recursive(priv->dfs_dev_dir);
1030}
1031
1032
1033
1034
1035void
1036mwifiex_debugfs_init(void)
1037{
1038 if (!mwifiex_dfs_dir)
1039 mwifiex_dfs_dir = debugfs_create_dir("mwifiex", NULL);
1040}
1041
1042
1043
1044
1045void
1046mwifiex_debugfs_remove(void)
1047{
1048 if (mwifiex_dfs_dir)
1049 debugfs_remove(mwifiex_dfs_dir);
1050}
1051