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