2 * Broadcom Dongle Host Driver (DHD), Linux-specific network interface
3 * Basically selected code segments from usb-cdc.c and usb-rndis.c
5 * Copyright (C) 1999-2019, Broadcom.
7 * Unless you and Broadcom execute a separate written software license
8 * agreement governing use of this software, this software is licensed to you
9 * under the terms of the GNU General Public License version 2 (the "GPL"),
10 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
11 * following added to such license:
13 * As a special exception, the copyright holders of this software give you
14 * permission to link this software with independent modules, and to copy and
15 * distribute the resulting executable under terms of your choice, provided that
16 * you also meet, for each linked independent module, the terms and conditions of
17 * the license of that module. An independent module is a module which is not
18 * derived from this software. The special exception does not apply to any
19 * modifications of the software.
21 * Notwithstanding the above, under no circumstances may you combine this
22 * software in any way with any other Broadcom software provided under a license
23 * other than the GPL, without Broadcom's express prior written consent.
26 * <<Broadcom-WL-IPTag/Open:>>
28 * $Id: dhd_linux_exportfs.c 793750 2018-12-11 02:12:38Z $
30 #include <linux/kobject.h>
31 #include <linux/proc_fs.h>
32 #include <linux/sysfs.h>
35 #include <dhd_linux_priv.h>
36 #ifdef DHD_ADPS_BAM_EXPORT
40 /* ----------------------------------------------------------------------------
41 * Infrastructure code for sysfs interface support for DHD
43 * What is sysfs interface?
44 * https://www.kernel.org/doc/Documentation/filesystems/sysfs.txt
46 * Why sysfs interface?
47 * This is the Linux standard way of changing/configuring Run Time parameters
48 * for a driver. We can use this interface to control "linux" specific driver
51 * -----------------------------------------------------------------------------
54 #if defined(DHD_TRACE_WAKE_LOCK)
55 extern atomic_t trace_wklock_onoff
;
57 /* Function to show the history buffer */
59 show_wklock_trace(struct dhd_info
*dev
, char *buf
)
62 dhd_info_t
*dhd
= (dhd_info_t
*)dev
;
67 dhd_wk_lock_stats_dump(&dhd
->pub
);
71 /* Function to enable/disable wakelock trace */
73 wklock_trace_onoff(struct dhd_info
*dev
, const char *buf
, size_t count
)
76 dhd_info_t
*dhd
= (dhd_info_t
*)dev
;
79 onoff
= bcm_strtoul(buf
, NULL
, 10);
80 if (onoff
!= 0 && onoff
!= 1) {
84 atomic_set(&trace_wklock_onoff
, onoff
);
85 if (atomic_read(&trace_wklock_onoff
)) {
86 printk("ENABLE WAKLOCK TRACE\n");
88 printk("DISABLE WAKELOCK TRACE\n");
91 return (ssize_t
)(onoff
+1);
93 #endif /* DHD_TRACE_WAKE_LOCK */
95 #if defined(DHD_LB_TXP)
97 show_lbtxp(struct dhd_info
*dev
, char *buf
)
101 dhd_info_t
*dhd
= (dhd_info_t
*)dev
;
103 onoff
= atomic_read(&dhd
->lb_txp_active
);
104 ret
= scnprintf(buf
, PAGE_SIZE
- 1, "%lu \n",
110 lbtxp_onoff(struct dhd_info
*dev
, const char *buf
, size_t count
)
113 dhd_info_t
*dhd
= (dhd_info_t
*)dev
;
116 onoff
= bcm_strtoul(buf
, NULL
, 10);
118 sscanf(buf
, "%lu", &onoff
);
119 if (onoff
!= 0 && onoff
!= 1) {
122 atomic_set(&dhd
->lb_txp_active
, onoff
);
124 /* Since the scheme is changed clear the counters */
125 for (i
= 0; i
< NR_CPUS
; i
++) {
126 DHD_LB_STATS_CLR(dhd
->txp_percpu_run_cnt
[i
]);
127 DHD_LB_STATS_CLR(dhd
->tx_start_percpu_run_cnt
[i
]);
133 #endif /* DHD_LB_TXP */
135 #if defined(DHD_LB_RXP)
137 show_lbrxp(struct dhd_info
*dev
, char *buf
)
141 dhd_info_t
*dhd
= (dhd_info_t
*)dev
;
143 onoff
= atomic_read(&dhd
->lb_rxp_active
);
144 ret
= scnprintf(buf
, PAGE_SIZE
- 1, "%lu \n",
150 lbrxp_onoff(struct dhd_info
*dev
, const char *buf
, size_t count
)
153 dhd_info_t
*dhd
= (dhd_info_t
*)dev
;
156 onoff
= bcm_strtoul(buf
, NULL
, 10);
158 sscanf(buf
, "%lu", &onoff
);
159 if (onoff
!= 0 && onoff
!= 1) {
162 atomic_set(&dhd
->lb_rxp_active
, onoff
);
164 /* Since the scheme is changed clear the counters */
165 for (i
= 0; i
< NR_CPUS
; i
++) {
166 DHD_LB_STATS_CLR(dhd
->napi_percpu_run_cnt
[i
]);
167 for (j
= 0; j
< HIST_BIN_SIZE
; j
++) {
168 DHD_LB_STATS_CLR(dhd
->napi_rx_hist
[j
][i
]);
174 #endif /* DHD_LB_RXP */
177 * Generic Attribute Structure for DHD.
178 * If we have to add a new sysfs entry under /sys/bcm-dhd/, we have
179 * to instantiate an object of type dhd_attr, populate it with
180 * the required show/store functions (ex:- dhd_attr_cpumask_primary)
181 * and add the object to default_attrs[] array, that gets registered
182 * to the kobject of dhd (named bcm-dhd).
186 struct attribute attr
;
187 ssize_t(*show
)(struct dhd_info
*, char *);
188 ssize_t(*store
)(struct dhd_info
*, const char *, size_t count
);
191 #if defined(DHD_TRACE_WAKE_LOCK)
192 static struct dhd_attr dhd_attr_wklock
=
193 __ATTR(wklock_trace
, 0660, show_wklock_trace
, wklock_trace_onoff
);
194 #endif /* defined(DHD_TRACE_WAKE_LOCK */
196 #if defined(DHD_LB_TXP)
197 static struct dhd_attr dhd_attr_lbtxp
=
198 __ATTR(lbtxp
, 0660, show_lbtxp
, lbtxp_onoff
);
199 #endif /* DHD_LB_TXP */
201 #if defined(DHD_LB_RXP)
202 static struct dhd_attr dhd_attr_lbrxp
=
203 __ATTR(lbrxp
, 0660, show_lbrxp
, lbrxp_onoff
);
204 #endif /* DHD_LB_RXP */
206 /* Attribute object that gets registered with "bcm-dhd" kobject tree */
207 static struct attribute
*default_attrs
[] = {
208 #if defined(DHD_TRACE_WAKE_LOCK)
209 &dhd_attr_wklock
.attr
,
211 #if defined(DHD_LB_TXP)
212 &dhd_attr_lbtxp
.attr
,
213 #endif /* DHD_LB_TXP */
214 #if defined(DHD_LB_RXP)
215 &dhd_attr_lbrxp
.attr
,
216 #endif /* DHD_LB_RXP */
220 #define to_dhd(k) container_of(k, struct dhd_info, dhd_kobj)
221 #define to_attr(a) container_of(a, struct dhd_attr, attr)
224 * bcm-dhd kobject show function, the "attr" attribute specifices to which
225 * node under "bcm-dhd" the show function is called.
227 static ssize_t
dhd_show(struct kobject
*kobj
, struct attribute
*attr
, char *buf
)
229 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
230 #pragma GCC diagnostic push
231 #pragma GCC diagnostic ignored "-Wcast-qual"
233 dhd_info_t
*dhd
= to_dhd(kobj
);
234 struct dhd_attr
*d_attr
= to_attr(attr
);
235 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
236 #pragma GCC diagnostic pop
241 ret
= d_attr
->show(dhd
, buf
);
249 * bcm-dhd kobject show function, the "attr" attribute specifices to which
250 * node under "bcm-dhd" the store function is called.
252 static ssize_t
dhd_store(struct kobject
*kobj
, struct attribute
*attr
,
253 const char *buf
, size_t count
)
255 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
256 #pragma GCC diagnostic push
257 #pragma GCC diagnostic ignored "-Wcast-qual"
259 dhd_info_t
*dhd
= to_dhd(kobj
);
260 struct dhd_attr
*d_attr
= to_attr(attr
);
261 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
262 #pragma GCC diagnostic pop
267 ret
= d_attr
->store(dhd
, buf
, count
);
275 static struct sysfs_ops dhd_sysfs_ops
= {
280 static struct kobj_type dhd_ktype
= {
281 .sysfs_ops
= &dhd_sysfs_ops
,
282 .default_attrs
= default_attrs
,
285 #ifdef DHD_MAC_ADDR_EXPORT
286 struct ether_addr sysfs_mac_addr
;
288 show_mac_addr(struct dhd_info
*dev
, char *buf
)
292 ret
= scnprintf(buf
, PAGE_SIZE
- 1, MACF
,
293 (uint32
)sysfs_mac_addr
.octet
[0], (uint32
)sysfs_mac_addr
.octet
[1],
294 (uint32
)sysfs_mac_addr
.octet
[2], (uint32
)sysfs_mac_addr
.octet
[3],
295 (uint32
)sysfs_mac_addr
.octet
[4], (uint32
)sysfs_mac_addr
.octet
[5]);
301 set_mac_addr(struct dhd_info
*dev
, const char *buf
, size_t count
)
303 if (!bcm_ether_atoe(buf
, &sysfs_mac_addr
)) {
304 DHD_ERROR(("Invalid Mac Address \n"));
308 DHD_ERROR(("Mac Address set with "MACDBG
"\n", MAC2STRDBG(&sysfs_mac_addr
)));
313 static struct dhd_attr dhd_attr_cntl_macaddr
=
314 __ATTR(mac_addr
, 0660, show_mac_addr
, set_mac_addr
);
315 #endif /* DHD_MAC_ADDR_EXPORT */
317 #ifdef DHD_FW_COREDUMP
319 #ifdef CUSTOMER_HW4_DEBUG
320 #define MEMDUMPINFO PLATFORM_PATH".memdump.info"
321 #elif (defined(BOARD_PANDA) || defined(__ARM_ARCH_7A__))
322 #define MEMDUMPINFO "/data/misc/wifi/.memdump.info"
324 #define MEMDUMPINFO_LIVE "/installmedia/.memdump.info"
325 #define MEMDUMPINFO_INST "/data/.memdump.info"
326 #define MEMDUMPINFO MEMDUMPINFO_LIVE
327 #endif /* CUSTOMER_HW4_DEBUG */
330 get_mem_val_from_file(void)
332 struct file
*fp
= NULL
;
333 uint32 mem_val
= DUMP_MEMFILE_MAX
;
334 char *p_mem_val
= NULL
;
335 char *filepath
= MEMDUMPINFO
;
338 /* Read memdump info from the file */
339 fp
= filp_open(filepath
, O_RDONLY
, 0);
341 DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__
, filepath
));
342 #if defined(CONFIG_X86)
343 /* Check if it is Live Brix Image */
344 if (strcmp(filepath
, MEMDUMPINFO_LIVE
) != 0) {
347 /* Try if it is Installed Brix Image */
348 filepath
= MEMDUMPINFO_INST
;
349 DHD_ERROR(("%s: Try File [%s]\n", __FUNCTION__
, filepath
));
350 fp
= filp_open(filepath
, O_RDONLY
, 0);
352 DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__
, filepath
));
355 #else /* Non Brix Android platform */
357 #endif /* CONFIG_X86 && OEM_ANDROID */
360 /* Handle success case */
361 ret
= kernel_read(fp
, 0, (char *)&mem_val
, sizeof(uint32
));
363 DHD_ERROR(("%s: File read error, ret=%d\n", __FUNCTION__
, ret
));
364 filp_close(fp
, NULL
);
368 p_mem_val
= (char*)&mem_val
;
369 p_mem_val
[sizeof(uint32
) - 1] = '\0';
370 mem_val
= bcm_atoi(p_mem_val
);
372 filp_close(fp
, NULL
);
378 void dhd_get_memdump_info(dhd_pub_t
*dhd
)
380 #ifndef DHD_EXPORT_CNTL_FILE
381 uint32 mem_val
= DUMP_MEMFILE_MAX
;
383 mem_val
= get_mem_val_from_file();
384 if (mem_val
!= DUMP_MEMFILE_MAX
)
385 dhd
->memdump_enabled
= mem_val
;
386 #ifdef DHD_INIT_DEFAULT_MEMDUMP
387 if (mem_val
== 0 || mem_val
== DUMP_MEMFILE_MAX
)
388 mem_val
= DUMP_MEMFILE_BUGON
;
389 #endif /* DHD_INIT_DEFAULT_MEMDUMP */
391 #ifdef DHD_INIT_DEFAULT_MEMDUMP
392 if (dhd
->memdump_enabled
== 0 || dhd
->memdump_enabled
== DUMP_MEMFILE_MAX
)
393 dhd
->memdump_enabled
= DUMP_MEMFILE_BUGON
;
394 #endif /* DHD_INIT_DEFAULT_MEMDUMP */
395 #endif /* !DHD_EXPORT_CNTL_FILE */
396 DHD_ERROR(("%s: MEMDUMP ENABLED = %d\n", __FUNCTION__
, dhd
->memdump_enabled
));
399 #ifdef DHD_EXPORT_CNTL_FILE
401 show_memdump_info(struct dhd_info
*dev
, char *buf
)
407 DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__
));
412 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%u\n", dhdp
->memdump_enabled
);
417 set_memdump_info(struct dhd_info
*dev
, const char *buf
, size_t count
)
419 unsigned long memval
;
423 DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__
));
428 memval
= bcm_strtoul(buf
, NULL
, 10);
429 sscanf(buf
, "%lu", &memval
);
431 dhdp
->memdump_enabled
= (uint32
)memval
;
433 DHD_ERROR(("%s: MEMDUMP ENABLED = %iu\n", __FUNCTION__
, dhdp
->memdump_enabled
));
437 static struct dhd_attr dhd_attr_cntl_memdump
=
438 __ATTR(memdump
, 0660, show_memdump_info
, set_memdump_info
);
439 #endif /* DHD_EXPORT_CNTL_FILE */
440 #endif /* DHD_FW_COREDUMP */
443 #ifdef CUSTOMER_HW4_DEBUG
444 #define ASSERTINFO PLATFORM_PATH".assert.info"
446 #define ASSERTINFO "/installmedia/.assert.info"
447 #endif /* CUSTOMER_HW4_DEBUG */
449 get_assert_val_from_file(void)
451 struct file
*fp
= NULL
;
452 char *filepath
= ASSERTINFO
;
453 char *p_mem_val
= NULL
;
457 * Read assert info from the file
458 * 0: Trigger Kernel crash by panic()
459 * 1: Print out the logs and don't trigger Kernel panic. (default)
460 * 2: Trigger Kernel crash by BUG()
461 * File doesn't exist: Keep default value (1).
463 fp
= filp_open(filepath
, O_RDONLY
, 0);
465 DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__
, filepath
));
467 int ret
= kernel_read(fp
, 0, (char *)&mem_val
, sizeof(uint32
));
469 DHD_ERROR(("%s: File read error, ret=%d\n", __FUNCTION__
, ret
));
471 p_mem_val
= (char *)&mem_val
;
472 p_mem_val
[sizeof(uint32
) - 1] = '\0';
473 mem_val
= bcm_atoi(p_mem_val
);
474 DHD_ERROR(("%s: ASSERT ENABLED = %d\n", __FUNCTION__
, mem_val
));
476 filp_close(fp
, NULL
);
479 #ifdef CUSTOERM_HW4_DEBUG
480 mem_val
= (mem_val
>= 0) ? mem_val
: 1;
482 mem_val
= (mem_val
>= 0) ? mem_val
: 0;
483 #endif /* CUSTOMER_HW4_DEBUG */
487 void dhd_get_assert_info(dhd_pub_t
*dhd
)
489 #ifndef DHD_EXPORT_CNTL_FILE
492 mem_val
= get_assert_val_from_file();
494 g_assert_type
= mem_val
;
495 #endif /* !DHD_EXPORT_CNTL_FILE */
498 #ifdef DHD_EXPORT_CNTL_FILE
500 show_assert_info(struct dhd_info
*dev
, char *buf
)
505 DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__
));
509 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%d\n", g_assert_type
);
515 set_assert_info(struct dhd_info
*dev
, const char *buf
, size_t count
)
517 unsigned long assert_val
;
519 assert_val
= bcm_strtoul(buf
, NULL
, 10);
520 sscanf(buf
, "%lu", &assert_val
);
522 g_assert_type
= (uint32
)assert_val
;
524 DHD_ERROR(("%s: ASSERT ENABLED = %lu\n", __FUNCTION__
, assert_val
));
529 static struct dhd_attr dhd_attr_cntl_assert
=
530 __ATTR(assert, 0660, show_assert_info
, set_assert_info
);
531 #endif /* DHD_EXPORT_CNTL_FILE */
532 #endif /* BCMASSERT_LOG */
534 #ifdef DHD_EXPORT_CNTL_FILE
535 #if defined(WRITE_WLANINFO)
537 show_wifiver_info(struct dhd_info
*dev
, char *buf
)
541 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%s", version_info
);
546 set_wifiver_info(struct dhd_info
*dev
, const char *buf
, size_t count
)
548 DHD_ERROR(("Do not set version info\n"));
552 static struct dhd_attr dhd_attr_cntl_wifiver
=
553 __ATTR(wifiver
, 0660, show_wifiver_info
, set_wifiver_info
);
554 #endif /* WRITE_WLANINFO */
556 #if defined(USE_CID_CHECK)
557 char cidinfostr
[MAX_VNAME_LEN
];
560 show_cid_info(struct dhd_info
*dev
, char *buf
)
564 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%s", cidinfostr
);
569 set_cid_info(struct dhd_info
*dev
, const char *buf
, size_t count
)
571 int len
= strlen(buf
) + 1;
573 maxstrsz
= MAX_VNAME_LEN
;
575 scnprintf(cidinfostr
, ((len
> maxstrsz
) ? maxstrsz
: len
), "%s", buf
);
576 DHD_INFO(("%s : CID info string\n", cidinfostr
));
580 static struct dhd_attr dhd_attr_cntl_cidinfo
=
581 __ATTR(cid
, 0660, show_cid_info
, set_cid_info
);
582 #endif /* USE_CID_CHECK */
584 #if defined(GEN_SOFTAP_INFO_FILE)
585 char softapinfostr
[SOFTAP_INFO_BUF_SZ
];
587 show_softap_info(struct dhd_info
*dev
, char *buf
)
591 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%s", softapinfostr
);
596 set_softap_info(struct dhd_info
*dev
, const char *buf
, size_t count
)
598 DHD_ERROR(("Do not set sofap related info\n"));
602 static struct dhd_attr dhd_attr_cntl_softapinfo
=
603 __ATTR(softap
, 0660, show_softap_info
, set_softap_info
);
604 #endif /* GEN_SOFTAP_INFO_FILE */
606 #if defined(MIMO_ANT_SETTING)
607 unsigned long antsel
;
610 show_ant_info(struct dhd_info
*dev
, char *buf
)
614 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%lu\n", antsel
);
619 set_ant_info(struct dhd_info
*dev
, const char *buf
, size_t count
)
621 unsigned long ant_val
;
623 ant_val
= bcm_strtoul(buf
, NULL
, 10);
624 sscanf(buf
, "%lu", &ant_val
);
628 * 0 - Not set, handle same as file not exist
631 DHD_ERROR(("[WIFI_SEC] %s: Set Invalid value %lu \n",
632 __FUNCTION__
, ant_val
));
637 DHD_ERROR(("[WIFI_SEC] %s: Set Antinfo val = %lu \n", __FUNCTION__
, antsel
));
641 static struct dhd_attr dhd_attr_cntl_antinfo
=
642 __ATTR(ant
, 0660, show_ant_info
, set_ant_info
);
643 #endif /* MIMO_ANT_SETTING */
645 #ifdef DHD_PM_CONTROL_FROM_FILE
646 extern bool g_pm_control
;
647 extern uint32 pmmode_val
;
649 show_pm_info(struct dhd_info
*dev
, char *buf
)
654 ret
= scnprintf(buf
, PAGE_SIZE
-1, "PM mode is not set\n");
656 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%u\n", pmmode_val
);
662 set_pm_info(struct dhd_info
*dev
, const char *buf
, size_t count
)
664 unsigned long pm_val
;
666 pm_val
= bcm_strtoul(buf
, NULL
, 10);
667 sscanf(buf
, "%lu", &pm_val
);
670 DHD_ERROR(("[WIFI_SEC] %s: Set Invalid value %lu \n",
671 __FUNCTION__
, pm_val
));
678 g_pm_control
= FALSE
;
681 pmmode_val
= (uint32
)pm_val
;
682 DHD_ERROR(("[WIFI_SEC] %s: Set pminfo val = %u\n", __FUNCTION__
, pmmode_val
));
686 static struct dhd_attr dhd_attr_cntl_pminfo
=
687 __ATTR(pm
, 0660, show_pm_info
, set_pm_info
);
688 #endif /* DHD_PM_CONTROL_FROM_FILE */
690 #ifdef LOGTRACE_FROM_FILE
691 unsigned long logtrace_val
= 1;
694 show_logtrace_info(struct dhd_info
*dev
, char *buf
)
698 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%lu\n", logtrace_val
);
703 set_logtrace_info(struct dhd_info
*dev
, const char *buf
, size_t count
)
707 onoff
= bcm_strtoul(buf
, NULL
, 10);
708 sscanf(buf
, "%lu", &onoff
);
711 DHD_ERROR(("[WIFI_SEC] %s: Set Invalid value %lu \n",
712 __FUNCTION__
, onoff
));
716 logtrace_val
= onoff
;
717 DHD_ERROR(("[WIFI_SEC] %s: LOGTRACE On/Off from sysfs = %lu\n",
718 __FUNCTION__
, logtrace_val
));
722 static struct dhd_attr dhd_attr_cntl_logtraceinfo
=
723 __ATTR(logtrace
, 0660, show_logtrace_info
, set_logtrace_info
);
724 #endif /* LOGTRACE_FROM_FILE */
726 #ifdef USE_WFA_CERT_CONF
728 uint32 bus_txglom
= VALUENOTSET
;
731 show_bustxglom(struct dhd_info
*dev
, char *buf
)
735 if (bus_txglom
== VALUENOTSET
) {
736 ret
= scnprintf(buf
, PAGE_SIZE
- 1, "%s\n", "bustxglom not set from sysfs");
738 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%u\n", bus_txglom
);
744 set_bustxglom(struct dhd_info
*dev
, const char *buf
, size_t count
)
748 onoff
= (uint32
)bcm_atoi(buf
);
749 sscanf(buf
, "%u", &onoff
);
752 DHD_ERROR(("[WIFI_SEC] %s: Set Invalid value %u \n",
753 __FUNCTION__
, onoff
));
758 DHD_ERROR(("[WIFI_SEC] %s: BUS TXGLOM On/Off from sysfs = %u\n",
759 __FUNCTION__
, bus_txglom
));
763 static struct dhd_attr dhd_attr_cntl_bustxglom
=
764 __ATTR(bustxglom
, 0660, show_bustxglom
, set_bustxglom
);
767 #if defined(ROAM_ENABLE) || defined(DISABLE_BUILTIN_ROAM)
768 uint32 roam_off
= VALUENOTSET
;
771 show_roamoff(struct dhd_info
*dev
, char *buf
)
775 if (roam_off
== VALUENOTSET
) {
776 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%s\n", "roam_off not set from sysfs");
778 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%u\n", roam_off
);
784 set_roamoff(struct dhd_info
*dev
, const char *buf
, size_t count
)
788 onoff
= bcm_atoi(buf
);
789 sscanf(buf
, "%u", &onoff
);
792 DHD_ERROR(("[WIFI_SEC] %s: Set Invalid value %u \n",
793 __FUNCTION__
, onoff
));
798 DHD_ERROR(("[WIFI_SEC] %s: ROAM On/Off from sysfs = %u\n",
799 __FUNCTION__
, roam_off
));
803 static struct dhd_attr dhd_attr_cntl_roamoff
=
804 __ATTR(roamoff
, 0660, show_roamoff
, set_roamoff
);
805 #endif /* ROAM_ENABLE || DISABLE_BUILTIN_ROAM */
807 #ifdef USE_WL_FRAMEBURST
808 uint32 frameburst
= VALUENOTSET
;
811 show_frameburst(struct dhd_info
*dev
, char *buf
)
815 if (frameburst
== VALUENOTSET
) {
816 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%s\n", "frameburst not set from sysfs");
818 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%u\n", frameburst
);
824 set_frameburst(struct dhd_info
*dev
, const char *buf
, size_t count
)
828 onoff
= bcm_atoi(buf
);
829 sscanf(buf
, "%u", &onoff
);
832 DHD_ERROR(("[WIFI_SEC] %s: Set Invalid value %u \n",
833 __FUNCTION__
, onoff
));
838 DHD_ERROR(("[WIFI_SEC] %s: FRAMEBURST On/Off from sysfs = %u\n",
839 __FUNCTION__
, frameburst
));
843 static struct dhd_attr dhd_attr_cntl_frameburst
=
844 __ATTR(frameburst
, 0660, show_frameburst
, set_frameburst
);
845 #endif /* USE_WL_FRAMEBURST */
848 uint32 txbf
= VALUENOTSET
;
851 show_txbf(struct dhd_info
*dev
, char *buf
)
855 if (txbf
== VALUENOTSET
) {
856 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%s\n", "txbf not set from sysfs");
858 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%u\n", txbf
);
864 set_txbf(struct dhd_info
*dev
, const char *buf
, size_t count
)
868 onoff
= bcm_atoi(buf
);
869 sscanf(buf
, "%u", &onoff
);
872 DHD_ERROR(("[WIFI_SEC] %s: Set Invalid value %u \n",
873 __FUNCTION__
, onoff
));
878 DHD_ERROR(("[WIFI_SEC] %s: FRAMEBURST On/Off from sysfs = %u\n",
879 __FUNCTION__
, txbf
));
883 static struct dhd_attr dhd_attr_cntl_txbf
=
884 __ATTR(txbf
, 0660, show_txbf
, set_txbf
);
885 #endif /* USE_WL_TXBF */
888 uint32 proptx
= VALUENOTSET
;
891 show_proptx(struct dhd_info
*dev
, char *buf
)
895 if (proptx
== VALUENOTSET
) {
896 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%s\n", "proptx not set from sysfs");
898 ret
= scnprintf(buf
, PAGE_SIZE
-1, "%u\n", proptx
);
904 set_proptx(struct dhd_info
*dev
, const char *buf
, size_t count
)
908 onoff
= bcm_strtoul(buf
, NULL
, 10);
909 sscanf(buf
, "%u", &onoff
);
912 DHD_ERROR(("[WIFI_SEC] %s: Set Invalid value %u \n",
913 __FUNCTION__
, onoff
));
918 DHD_ERROR(("[WIFI_SEC] %s: FRAMEBURST On/Off from sysfs = %u\n",
919 __FUNCTION__
, txbf
));
923 static struct dhd_attr dhd_attr_cntl_proptx
=
924 __ATTR(proptx
, 0660, show_proptx
, set_proptx
);
926 #endif /* PROP_TXSTATUS */
927 #endif /* USE_WFA_CERT_CONF */
928 #endif /* DHD_EXPORT_CNTL_FILE */
930 #if defined(DHD_ADPS_BAM_EXPORT) && defined(WL_BAM)
931 #define BAD_AP_MAC_ADDR_ELEMENT_NUM 6
932 wl_bad_ap_mngr_t
*g_bad_ap_mngr
= NULL
;
935 show_adps_bam_list(struct dhd_info
*dev
, char *buf
)
940 wl_bad_ap_info_t
*bad_ap
;
941 wl_bad_ap_info_entry_t
*entry
;
943 if (g_bad_ap_mngr
== NULL
)
946 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
947 #pragma GCC diagnostic push
948 #pragma GCC diagnostic ignored "-Wcast-qual"
950 list_for_each_entry(entry
, &g_bad_ap_mngr
->list
, list
) {
951 bad_ap
= &entry
->bad_ap
;
953 ret
= scnprintf(buf
+ offset
, PAGE_SIZE
- 1, MACF
"\n",
954 bad_ap
->bssid
.octet
[0], bad_ap
->bssid
.octet
[1],
955 bad_ap
->bssid
.octet
[2], bad_ap
->bssid
.octet
[3],
956 bad_ap
->bssid
.octet
[4], bad_ap
->bssid
.octet
[5]);
960 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
961 #pragma GCC diagnostic pop
968 store_adps_bam_list(struct dhd_info
*dev
, const char *buf
, size_t count
)
974 wl_bad_ap_info_t bad_ap
;
976 if (g_bad_ap_mngr
== NULL
)
982 ret
= sscanf(buf
+ offset
, MACF
"\n",
983 (uint32
*)&bad_ap
.bssid
.octet
[0], (uint32
*)&bad_ap
.bssid
.octet
[1],
984 (uint32
*)&bad_ap
.bssid
.octet
[2], (uint32
*)&bad_ap
.bssid
.octet
[3],
985 (uint32
*)&bad_ap
.bssid
.octet
[4], (uint32
*)&bad_ap
.bssid
.octet
[5]);
986 if (ret
!= BAD_AP_MAC_ADDR_ELEMENT_NUM
) {
987 DHD_ERROR(("%s - fail to parse bad ap data\n", __FUNCTION__
));
991 ret
= wl_bad_ap_mngr_add(g_bad_ap_mngr
, &bad_ap
);
995 ret
= snprintf(tmp
, ARRAYSIZE(tmp
), MACF
"\n",
996 bad_ap
.bssid
.octet
[0], bad_ap
.bssid
.octet
[1],
997 bad_ap
.bssid
.octet
[2], bad_ap
.bssid
.octet
[3],
998 bad_ap
.bssid
.octet
[4], bad_ap
.bssid
.octet
[5]);
1000 DHD_ERROR(("%s - fail to get bad ap data length(%d)\n", __FUNCTION__
, ret
));
1011 static struct dhd_attr dhd_attr_adps_bam
=
1012 __ATTR(bad_ap_list
, 0660, show_adps_bam_list
, store_adps_bam_list
);
1013 #endif /* DHD_ADPS_BAM_EXPORT && WL_BAM */
1015 /* Attribute object that gets registered with "wifi" kobject tree */
1016 static struct attribute
*control_file_attrs
[] = {
1017 #ifdef DHD_MAC_ADDR_EXPORT
1018 &dhd_attr_cntl_macaddr
.attr
,
1019 #endif /* DHD_MAC_ADDR_EXPORT */
1020 #ifdef DHD_EXPORT_CNTL_FILE
1021 #ifdef DHD_FW_COREDUMP
1022 &dhd_attr_cntl_memdump
.attr
,
1023 #endif /* DHD_FW_COREDUMP */
1024 #ifdef BCMASSERT_LOG
1025 &dhd_attr_cntl_assert
.attr
,
1026 #endif /* BCMASSERT_LOG */
1027 #ifdef WRITE_WLANINFO
1028 &dhd_attr_cntl_wifiver
.attr
,
1029 #endif /* WRITE_WLANINFO */
1030 #ifdef USE_CID_CHECK
1031 &dhd_attr_cntl_cidinfo
.attr
,
1032 #endif /* USE_CID_CHECK */
1033 #ifdef GEN_SOFTAP_INFO_FILE
1034 &dhd_attr_cntl_softapinfo
.attr
,
1035 #endif /* GEN_SOFTAP_INFO_FILE */
1036 #ifdef MIMO_ANT_SETTING
1037 &dhd_attr_cntl_antinfo
.attr
,
1038 #endif /* MIMO_ANT_SETTING */
1039 #ifdef DHD_PM_CONTROL_FROM_FILE
1040 &dhd_attr_cntl_pminfo
.attr
,
1041 #endif /* DHD_PM_CONTROL_FROM_FILE */
1042 #ifdef LOGTRACE_FROM_FILE
1043 &dhd_attr_cntl_logtraceinfo
.attr
,
1044 #endif /* LOGTRACE_FROM_FILE */
1045 #ifdef USE_WFA_CERT_CONF
1047 &dhd_attr_cntl_bustxglom
.attr
,
1048 #endif /* BCMSDIO */
1049 &dhd_attr_cntl_roamoff
.attr
,
1050 #ifdef USE_WL_FRAMEBURST
1051 &dhd_attr_cntl_frameburst
.attr
,
1052 #endif /* USE_WL_FRAMEBURST */
1054 &dhd_attr_cntl_txbf
.attr
,
1055 #endif /* USE_WL_TXBF */
1056 #ifdef PROP_TXSTATUS
1057 &dhd_attr_cntl_proptx
.attr
,
1058 #endif /* PROP_TXSTATUS */
1059 #endif /* USE_WFA_CERT_CONF */
1060 #endif /* DHD_EXPORT_CNTL_FILE */
1061 #ifdef DHD_ADPS_BAM_EXPORT
1062 &dhd_attr_adps_bam
.attr
,
1063 #endif /* DHD_ADPS_BAM_EXPORT */
1067 #define to_cntl_dhd(k) container_of(k, struct dhd_info, dhd_conf_file_kobj)
1070 * wifi kobject show function, the "attr" attribute specifices to which
1071 * node under "sys/wifi" the show function is called.
1073 static ssize_t
dhd_cntl_show(struct kobject
*kobj
, struct attribute
*attr
, char *buf
)
1075 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
1076 #pragma GCC diagnostic push
1077 #pragma GCC diagnostic ignored "-Wcast-qual"
1079 dhd_info_t
*dhd
= to_cntl_dhd(kobj
);
1080 struct dhd_attr
*d_attr
= to_attr(attr
);
1081 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
1082 #pragma GCC diagnostic pop
1087 ret
= d_attr
->show(dhd
, buf
);
1095 * wifi kobject show function, the "attr" attribute specifices to which
1096 * node under "sys/wifi" the store function is called.
1098 static ssize_t
dhd_cntl_store(struct kobject
*kobj
, struct attribute
*attr
,
1099 const char *buf
, size_t count
)
1101 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
1102 #pragma GCC diagnostic push
1103 #pragma GCC diagnostic ignored "-Wcast-qual"
1105 dhd_info_t
*dhd
= to_cntl_dhd(kobj
);
1106 struct dhd_attr
*d_attr
= to_attr(attr
);
1107 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
1108 #pragma GCC diagnostic pop
1113 ret
= d_attr
->store(dhd
, buf
, count
);
1121 static struct sysfs_ops dhd_sysfs_cntl_ops
= {
1122 .show
= dhd_cntl_show
,
1123 .store
= dhd_cntl_store
,
1126 static struct kobj_type dhd_cntl_file_ktype
= {
1127 .sysfs_ops
= &dhd_sysfs_cntl_ops
,
1128 .default_attrs
= control_file_attrs
,
1131 /* Create a kobject and attach to sysfs interface */
1132 int dhd_sysfs_init(dhd_info_t
*dhd
)
1137 DHD_ERROR(("%s(): dhd is NULL \r\n", __FUNCTION__
));
1141 /* Initialize the kobject */
1142 ret
= kobject_init_and_add(&dhd
->dhd_kobj
, &dhd_ktype
, NULL
, "bcm-dhd");
1144 kobject_put(&dhd
->dhd_kobj
);
1145 DHD_ERROR(("%s(): Unable to allocate kobject \r\n", __FUNCTION__
));
1148 ret
= kobject_init_and_add(&dhd
->dhd_conf_file_kobj
, &dhd_cntl_file_ktype
, NULL
, "wifi");
1150 kobject_put(&dhd
->dhd_conf_file_kobj
);
1151 DHD_ERROR(("%s(): Unable to allocate kobject \r\n", __FUNCTION__
));
1156 * We are always responsible for sending the uevent that the kobject
1157 * was added to the system.
1159 kobject_uevent(&dhd
->dhd_kobj
, KOBJ_ADD
);
1160 kobject_uevent(&dhd
->dhd_conf_file_kobj
, KOBJ_ADD
);
1165 /* Done with the kobject and detach the sysfs interface */
1166 void dhd_sysfs_exit(dhd_info_t
*dhd
)
1169 DHD_ERROR(("%s(): dhd is NULL \r\n", __FUNCTION__
));
1173 /* Releae the kobject */
1174 kobject_put(&dhd
->dhd_kobj
);
1175 kobject_put(&dhd
->dhd_conf_file_kobj
);