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