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