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