2 * Linux cfg80211 Vendor Extension Code
4 * Copyright (C) 1999-2019, Broadcom.
6 * Unless you and Broadcom execute a separate written software license
7 * agreement governing use of this software, this software is licensed to you
8 * under the terms of the GNU General Public License version 2 (the "GPL"),
9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10 * following added to such license:
12 * As a special exception, the copyright holders of this software give you
13 * permission to link this software with independent modules, and to copy and
14 * distribute the resulting executable under terms of your choice, provided that
15 * you also meet, for each linked independent module, the terms and conditions of
16 * the license of that module. An independent module is a module which is not
17 * derived from this software. The special exception does not apply to any
18 * modifications of the software.
20 * Notwithstanding the above, under no circumstances may you combine this
21 * software in any way with any other Broadcom software provided under a license
22 * other than the GPL, without Broadcom's express prior written consent.
25 * <<Broadcom-WL-IPTag/Open:>>
27 * $Id: wl_cfgvendor.c 825970 2019-06-18 05:28:31Z $
31 * New vendor interface additon to nl80211/cfg80211 to allow vendors
32 * to implement proprietary features over the cfg80211 stack.
38 #include <linux/kernel.h>
39 #include <linux/vmalloc.h>
42 #include <bcmwifi_channels.h>
43 #include <bcmendian.h>
46 #include <linux/if_arp.h>
47 #include <asm/uaccess.h>
49 #include <dngl_stats.h>
51 #include <dhd_debug.h>
54 #include <wlioctl_utils.h>
55 #include <dhd_cfg80211.h>
58 #endif /* PNO_SUPPORT */
61 #endif /* RTT_SUPPORT */
64 #include <linux/kernel.h>
65 #include <linux/kthread.h>
66 #include <linux/netdevice.h>
67 #include <linux/sched.h>
68 #include <linux/etherdevice.h>
69 #include <linux/wireless.h>
70 #include <linux/ieee80211.h>
71 #include <linux/wait.h>
72 #include <net/cfg80211.h>
73 #include <net/rtnetlink.h>
76 #include <wldev_common.h>
77 #include <wl_cfg80211.h>
78 #include <wl_cfgp2p.h>
80 #include <wl_cfgnan.h>
82 #include <wl_android.h>
83 #include <wl_cfgvendor.h>
87 #include <brcm_nl80211.h>
90 wl_get_kernel_timestamp(void)
94 unsigned long rem_nsec
;
96 ts_nsec
= local_clock();
97 rem_nsec
= DIV_AND_MOD_U64_BY_U32(ts_nsec
, NSEC_PER_SEC
);
98 snprintf(buf
, sizeof(buf
), "%5lu.%06lu",
99 (unsigned long)ts_nsec
, rem_nsec
/ NSEC_PER_USEC
);
104 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
105 #if defined(WL_SUPP_EVENT)
107 wl_cfgvendor_send_supp_eventstring(const char *func_name
, const char *fmt
, ...)
109 char buf
[SUPP_LOG_LEN
] = {0};
110 struct bcm_cfg80211
*cfg
;
117 cfg
= wl_cfg80211_get_bcmcfg();
118 if (!cfg
|| !cfg
->wdev
) {
119 WL_DBG(("supp evt invalid arg\n"));
123 wiphy
= cfg
->wdev
->wiphy
;
124 prefix_len
= snprintf(buf
, SUPP_LOG_LEN
, "[DHD]<%s> %s: ",
125 wl_get_kernel_timestamp(), __func__
);
126 /* Remaining buffer len */
127 rem_len
= SUPP_LOG_LEN
- (prefix_len
+ 1);
128 /* Print the arg list on to the remaining part of the buffer */
130 len
= vsnprintf((buf
+ prefix_len
), rem_len
, fmt
, args
);
137 /* If return length is greater than buffer len,
138 * then its truncated buffer case.
143 /* Ensure the buffer is null terminated */
148 return wl_cfgvendor_send_async_event(wiphy
,
149 bcmcfg_to_prmry_ndev(cfg
), BRCM_VENDOR_EVENT_PRIV_STR
, buf
, len
);
153 wl_cfgvendor_notify_supp_event_str(const char *evt_name
, const char *fmt
, ...)
155 char buf
[SUPP_LOG_LEN
] = {0};
156 struct bcm_cfg80211
*cfg
;
163 cfg
= wl_cfg80211_get_bcmcfg();
164 if (!cfg
|| !cfg
->wdev
) {
165 WL_DBG(("supp evt invalid arg\n"));
168 wiphy
= cfg
->wdev
->wiphy
;
169 prefix_len
= snprintf(buf
, SUPP_LOG_LEN
, "%s ", evt_name
);
170 /* Remaining buffer len */
171 rem_len
= SUPP_LOG_LEN
- (prefix_len
+ 1);
172 /* Print the arg list on to the remaining part of the buffer */
174 len
= vsnprintf((buf
+ prefix_len
), rem_len
, fmt
, args
);
181 /* If return length is greater than buffer len,
182 * then its truncated buffer case.
187 /* Ensure the buffer is null terminated */
192 return wl_cfgvendor_send_async_event(wiphy
,
193 bcmcfg_to_prmry_ndev(cfg
), BRCM_VENDOR_EVENT_PRIV_STR
, buf
, len
);
195 #endif /* WL_SUPP_EVENT */
198 * This API is to be used for asynchronous vendor events. This
199 * shouldn't be used in response to a vendor command from its
200 * do_it handler context (instead wl_cfgvendor_send_cmd_reply should
203 int wl_cfgvendor_send_async_event(struct wiphy
*wiphy
,
204 struct net_device
*dev
, int event_id
, const void *data
, int len
)
209 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
211 /* Alloc the SKB for vendor_event */
212 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
213 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
214 skb
= cfg80211_vendor_event_alloc(wiphy
, ndev_to_wdev(dev
), len
, event_id
, kflags
);
216 skb
= cfg80211_vendor_event_alloc(wiphy
, len
, event_id
, kflags
);
217 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
218 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
220 WL_ERR(("skb alloc failed"));
224 /* Push the data to the skb */
225 nla_put_nohdr(skb
, len
, data
);
227 cfg80211_vendor_event(skb
, kflags
);
233 wl_cfgvendor_send_cmd_reply(struct wiphy
*wiphy
,
234 const void *data
, int len
)
239 /* Alloc the SKB for vendor_event */
240 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, len
);
241 if (unlikely(!skb
)) {
242 WL_ERR(("skb alloc failed"));
247 /* Push the data to the skb */
248 nla_put_nohdr(skb
, len
, data
);
249 err
= cfg80211_vendor_cmd_reply(skb
);
251 WL_DBG(("wl_cfgvendor_send_cmd_reply status %d", err
));
256 wl_cfgvendor_get_feature_set(struct wiphy
*wiphy
,
257 struct wireless_dev
*wdev
, const void *data
, int len
)
260 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
263 reply
= dhd_dev_get_feature_set(bcmcfg_to_prmry_ndev(cfg
));
265 err
= wl_cfgvendor_send_cmd_reply(wiphy
, &reply
, sizeof(int));
267 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
273 wl_cfgvendor_get_feature_set_matrix(struct wiphy
*wiphy
,
274 struct wireless_dev
*wdev
, const void *data
, int len
)
277 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
282 mem_needed
= VENDOR_REPLY_OVERHEAD
+
283 (ATTRIBUTE_U32_LEN
* MAX_FEATURE_SET_CONCURRRENT_GROUPS
) + ATTRIBUTE_U32_LEN
;
285 /* Alloc the SKB for vendor_event */
286 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
287 if (unlikely(!skb
)) {
288 WL_ERR(("skb alloc failed"));
293 err
= nla_put_u32(skb
, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET
,
294 MAX_FEATURE_SET_CONCURRRENT_GROUPS
);
299 for (i
= 0; i
< MAX_FEATURE_SET_CONCURRRENT_GROUPS
; i
++) {
300 reply
= dhd_dev_get_feature_set_matrix(bcmcfg_to_prmry_ndev(cfg
), i
);
301 if (reply
!= WIFI_FEATURE_INVALID
) {
302 err
= nla_put_u32(skb
, ANDR_WIFI_ATTRIBUTE_FEATURE_SET
,
311 err
= cfg80211_vendor_cmd_reply(skb
);
314 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
321 wl_cfgvendor_set_rand_mac_oui(struct wiphy
*wiphy
,
322 struct wireless_dev
*wdev
, const void *data
, int len
)
325 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
329 WL_ERR(("data is not available\n"));
334 WL_ERR(("invalid len %d\n", len
));
338 type
= nla_type(data
);
340 if (type
== ANDR_WIFI_ATTRIBUTE_RANDOM_MAC_OUI
) {
341 if (nla_len(data
) != DOT11_OUI_LEN
) {
342 WL_ERR(("nla_len not matched.\n"));
345 err
= dhd_dev_cfg_rand_mac_oui(bcmcfg_to_prmry_ndev(cfg
), nla_data(data
));
348 WL_ERR(("Bad OUI, could not set:%d \n", err
));
353 #ifdef CUSTOM_FORCE_NODFS_FLAG
355 wl_cfgvendor_set_nodfs_flag(struct wiphy
*wiphy
,
356 struct wireless_dev
*wdev
, const void *data
, int len
)
359 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
364 WL_ERR(("data is not available\n"));
369 WL_ERR(("invalid len %d\n", len
));
373 type
= nla_type(data
);
374 if (type
== ANDR_WIFI_ATTRIBUTE_NODFS_SET
) {
375 nodfs
= nla_get_u32(data
);
376 err
= dhd_dev_set_nodfs(bcmcfg_to_prmry_ndev(cfg
), nodfs
);
381 #endif /* CUSTOM_FORCE_NODFS_FLAG */
384 wl_cfgvendor_set_country(struct wiphy
*wiphy
,
385 struct wireless_dev
*wdev
, const void *data
, int len
)
387 int err
= BCME_ERROR
, rem
, type
;
388 char country_code
[WLC_CNTRY_BUF_SZ
] = {0};
389 const struct nlattr
*iter
;
390 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
391 struct net_device
*primary_ndev
= bcmcfg_to_prmry_ndev(cfg
);
393 nla_for_each_attr(iter
, data
, len
, rem
) {
394 type
= nla_type(iter
);
396 case ANDR_WIFI_ATTRIBUTE_COUNTRY
:
397 err
= memcpy_s(country_code
, WLC_CNTRY_BUF_SZ
,
398 nla_data(iter
), nla_len(iter
));
400 WL_ERR(("Failed to copy country code: %d\n", err
));
405 WL_ERR(("Unknown type: %d\n", type
));
409 /* country code is unique for dongle..hence using primary interface. */
410 err
= wl_cfg80211_set_country_code(primary_ndev
, country_code
, true, true, -1);
412 WL_ERR(("Set country failed ret:%d\n", err
));
420 wl_cfgvendor_send_hotlist_event(struct wiphy
*wiphy
,
421 struct net_device
*dev
, void *data
, int len
, wl_vendor_event_t event
)
426 int malloc_len
, total
, iter_cnt_to_send
, cnt
;
427 gscan_results_cache_t
*cache
= (gscan_results_cache_t
*)data
;
429 total
= len
/sizeof(wifi_gscan_result_t
);
431 malloc_len
= (total
* sizeof(wifi_gscan_result_t
)) + VENDOR_DATA_OVERHEAD
;
432 if (malloc_len
> NLMSG_DEFAULT_SIZE
) {
433 malloc_len
= NLMSG_DEFAULT_SIZE
;
436 (malloc_len
- VENDOR_DATA_OVERHEAD
)/sizeof(wifi_gscan_result_t
);
437 total
= total
- iter_cnt_to_send
;
439 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
441 /* Alloc the SKB for vendor_event */
442 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
443 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
444 skb
= cfg80211_vendor_event_alloc(wiphy
, ndev_to_wdev(dev
),
445 malloc_len
, event
, kflags
);
447 skb
= cfg80211_vendor_event_alloc(wiphy
, malloc_len
, event
, kflags
);
448 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
449 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
451 WL_ERR(("skb alloc failed"));
455 while (cache
&& iter_cnt_to_send
) {
456 ptr
= (const void *) &cache
->results
[cache
->tot_consumed
];
458 if (iter_cnt_to_send
< (cache
->tot_count
- cache
->tot_consumed
)) {
459 cnt
= iter_cnt_to_send
;
461 cnt
= (cache
->tot_count
- cache
->tot_consumed
);
464 iter_cnt_to_send
-= cnt
;
465 cache
->tot_consumed
+= cnt
;
466 /* Push the data to the skb */
467 nla_append(skb
, cnt
* sizeof(wifi_gscan_result_t
), ptr
);
468 if (cache
->tot_consumed
== cache
->tot_count
) {
474 cfg80211_vendor_event(skb
, kflags
);
481 wl_cfgvendor_gscan_get_capabilities(struct wiphy
*wiphy
,
482 struct wireless_dev
*wdev
, const void *data
, int len
)
485 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
486 dhd_pno_gscan_capabilities_t
*reply
= NULL
;
487 uint32 reply_len
= 0;
489 reply
= dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg
),
490 DHD_PNO_GET_CAPABILITIES
, NULL
, &reply_len
);
492 WL_ERR(("Could not get capabilities\n"));
497 err
= wl_cfgvendor_send_cmd_reply(wiphy
, reply
, reply_len
);
499 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
502 MFREE(cfg
->osh
, reply
, reply_len
);
507 wl_cfgvendor_gscan_get_batch_results(struct wiphy
*wiphy
,
508 struct wireless_dev
*wdev
, const void *data
, int len
)
511 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
512 gscan_results_cache_t
*results
, *iter
;
513 uint32 reply_len
, is_done
= 1;
514 int32 mem_needed
, num_results_iter
;
515 wifi_gscan_result_t
*ptr
;
516 uint16 num_scan_ids
, num_results
;
518 struct nlattr
*scan_hdr
, *complete_flag
;
520 err
= dhd_dev_wait_batch_results_complete(bcmcfg_to_prmry_ndev(cfg
));
524 err
= dhd_dev_pno_lock_access_batch_results(bcmcfg_to_prmry_ndev(cfg
));
525 if (err
!= BCME_OK
) {
526 WL_ERR(("Can't obtain lock to access batch results %d\n", err
));
529 results
= dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg
),
530 DHD_PNO_GET_BATCH_RESULTS
, NULL
, &reply_len
);
533 WL_ERR(("No results to send %d\n", err
));
534 err
= wl_cfgvendor_send_cmd_reply(wiphy
, results
, 0);
537 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
538 dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg
));
541 num_scan_ids
= reply_len
& 0xFFFF;
542 num_results
= (reply_len
& 0xFFFF0000) >> 16;
543 mem_needed
= (num_results
* sizeof(wifi_gscan_result_t
)) +
544 (num_scan_ids
* GSCAN_BATCH_RESULT_HDR_LEN
) +
545 VENDOR_REPLY_OVERHEAD
+ SCAN_RESULTS_COMPLETE_FLAG_LEN
;
547 if (mem_needed
> (int32
)NLMSG_DEFAULT_SIZE
) {
548 mem_needed
= (int32
)NLMSG_DEFAULT_SIZE
;
551 WL_TRACE(("is_done %d mem_needed %d max_mem %d\n", is_done
, mem_needed
,
552 (int)NLMSG_DEFAULT_SIZE
));
553 /* Alloc the SKB for vendor_event */
554 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
555 if (unlikely(!skb
)) {
556 WL_ERR(("skb alloc failed"));
557 dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg
));
561 complete_flag
= nla_reserve(skb
, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE
,
564 if (unlikely(!complete_flag
)) {
565 WL_ERR(("complete_flag could not be reserved"));
567 dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg
));
570 mem_needed
= mem_needed
- (SCAN_RESULTS_COMPLETE_FLAG_LEN
+ VENDOR_REPLY_OVERHEAD
);
573 num_results_iter
= (mem_needed
- (int32
)GSCAN_BATCH_RESULT_HDR_LEN
);
574 num_results_iter
/= (int32
)sizeof(wifi_gscan_result_t
);
575 if (num_results_iter
<= 0 ||
576 ((iter
->tot_count
- iter
->tot_consumed
) > num_results_iter
)) {
579 scan_hdr
= nla_nest_start(skb
, GSCAN_ATTRIBUTE_SCAN_RESULTS
);
580 /* no more room? we are done then (for now) */
581 if (scan_hdr
== NULL
) {
585 err
= nla_put_u32(skb
, GSCAN_ATTRIBUTE_SCAN_ID
, iter
->scan_id
);
589 err
= nla_put_u8(skb
, GSCAN_ATTRIBUTE_SCAN_FLAGS
, iter
->flag
);
593 err
= nla_put_u32(skb
, GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK
, iter
->scan_ch_bucket
);
597 num_results_iter
= iter
->tot_count
- iter
->tot_consumed
;
599 err
= nla_put_u32(skb
, GSCAN_ATTRIBUTE_NUM_OF_RESULTS
, num_results_iter
);
603 if (num_results_iter
) {
604 ptr
= &iter
->results
[iter
->tot_consumed
];
605 err
= nla_put(skb
, GSCAN_ATTRIBUTE_SCAN_RESULTS
,
606 num_results_iter
* sizeof(wifi_gscan_result_t
), ptr
);
610 iter
->tot_consumed
+= num_results_iter
;
612 nla_nest_end(skb
, scan_hdr
);
613 mem_needed
-= GSCAN_BATCH_RESULT_HDR_LEN
+
614 (num_results_iter
* sizeof(wifi_gscan_result_t
));
617 /* Cleans up consumed results and returns TRUE if all results are consumed */
618 is_done
= dhd_dev_gscan_batch_cache_cleanup(bcmcfg_to_prmry_ndev(cfg
));
619 memcpy(nla_data(complete_flag
), &is_done
, sizeof(is_done
));
620 dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg
));
621 return cfg80211_vendor_cmd_reply(skb
);
623 /* Free up consumed results which will now not be sent */
624 (void)dhd_dev_gscan_batch_cache_cleanup(bcmcfg_to_prmry_ndev(cfg
));
626 dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg
));
631 wl_cfgvendor_initiate_gscan(struct wiphy
*wiphy
,
632 struct wireless_dev
*wdev
, const void *data
, int len
)
635 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
639 const struct nlattr
*iter
;
641 nla_for_each_attr(iter
, data
, len
, tmp
) {
642 type
= nla_type(iter
);
643 if (type
== GSCAN_ATTRIBUTE_ENABLE_FEATURE
)
644 run
= nla_get_u32(iter
);
645 else if (type
== GSCAN_ATTRIBUTE_FLUSH_FEATURE
)
646 flush
= nla_get_u32(iter
);
650 err
= dhd_dev_pno_run_gscan(bcmcfg_to_prmry_ndev(cfg
), run
, flush
);
653 WL_ERR(("Could not run gscan:%d \n", err
));
663 wl_cfgvendor_enable_full_scan_result(struct wiphy
*wiphy
,
664 struct wireless_dev
*wdev
, const void *data
, int len
)
667 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
669 bool real_time
= FALSE
;
672 WL_ERR(("data is not available\n"));
677 WL_ERR(("invalid len %d\n", len
));
681 type
= nla_type(data
);
683 if (type
== GSCAN_ATTRIBUTE_ENABLE_FULL_SCAN_RESULTS
) {
684 real_time
= nla_get_u32(data
);
686 err
= dhd_dev_pno_enable_full_scan_result(bcmcfg_to_prmry_ndev(cfg
), real_time
);
689 WL_ERR(("Could not run gscan:%d \n", err
));
700 wl_cfgvendor_set_scan_cfg_bucket(const struct nlattr
*prev
,
701 gscan_scan_params_t
*scan_param
, int num
)
703 struct dhd_pno_gscan_channel_bucket
*ch_bucket
;
705 int type
, err
= 0, rem
;
706 const struct nlattr
*cur
, *next
;
708 nla_for_each_nested(cur
, prev
, rem
) {
709 type
= nla_type(cur
);
710 ch_bucket
= scan_param
->channel_bucket
;
712 case GSCAN_ATTRIBUTE_BUCKET_ID
:
714 case GSCAN_ATTRIBUTE_BUCKET_PERIOD
:
715 if (nla_len(cur
) != sizeof(uint32
)) {
720 ch_bucket
[num
].bucket_freq_multiple
=
721 nla_get_u32(cur
) / MSEC_PER_SEC
;
723 case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS
:
724 if (nla_len(cur
) != sizeof(uint32
)) {
728 ch_bucket
[num
].num_channels
= nla_get_u32(cur
);
729 if (ch_bucket
[num
].num_channels
>
730 GSCAN_MAX_CHANNELS_IN_BUCKET
) {
731 WL_ERR(("channel range:%d,bucket:%d\n",
732 ch_bucket
[num
].num_channels
,
738 case GSCAN_ATTRIBUTE_BUCKET_CHANNELS
:
739 nla_for_each_nested(next
, cur
, rem
) {
740 if (k
>= GSCAN_MAX_CHANNELS_IN_BUCKET
)
742 if (nla_len(next
) != sizeof(uint32
)) {
746 ch_bucket
[num
].chan_list
[k
] = nla_get_u32(next
);
750 case GSCAN_ATTRIBUTE_BUCKETS_BAND
:
751 if (nla_len(cur
) != sizeof(uint32
)) {
755 ch_bucket
[num
].band
= (uint16
)nla_get_u32(cur
);
757 case GSCAN_ATTRIBUTE_REPORT_EVENTS
:
758 if (nla_len(cur
) != sizeof(uint32
)) {
762 ch_bucket
[num
].report_flag
= (uint8
)nla_get_u32(cur
);
764 case GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT
:
765 if (nla_len(cur
) != sizeof(uint32
)) {
769 ch_bucket
[num
].repeat
= (uint16
)nla_get_u32(cur
);
771 case GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD
:
772 if (nla_len(cur
) != sizeof(uint32
)) {
776 ch_bucket
[num
].bucket_max_multiple
=
777 nla_get_u32(cur
) / MSEC_PER_SEC
;
780 WL_ERR(("unknown attr type:%d\n", type
));
791 wl_cfgvendor_set_scan_cfg(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
792 const void *data
, int len
)
795 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
796 gscan_scan_params_t
*scan_param
;
799 const struct nlattr
*iter
;
801 scan_param
= (gscan_scan_params_t
*)MALLOCZ(cfg
->osh
,
802 sizeof(gscan_scan_params_t
));
804 WL_ERR(("Could not set GSCAN scan cfg, mem alloc failure\n"));
810 scan_param
->scan_fr
= PNO_SCAN_MIN_FW_SEC
;
811 nla_for_each_attr(iter
, data
, len
, tmp
) {
812 type
= nla_type(iter
);
814 if (j
>= GSCAN_MAX_CH_BUCKETS
) {
819 case GSCAN_ATTRIBUTE_BASE_PERIOD
:
820 if (nla_len(iter
) != sizeof(uint32
)) {
824 scan_param
->scan_fr
= nla_get_u32(iter
) / MSEC_PER_SEC
;
826 case GSCAN_ATTRIBUTE_NUM_BUCKETS
:
827 if (nla_len(iter
) != sizeof(uint32
)) {
831 scan_param
->nchannel_buckets
= nla_get_u32(iter
);
832 if (scan_param
->nchannel_buckets
>=
833 GSCAN_MAX_CH_BUCKETS
) {
834 WL_ERR(("ncha_buck out of range %d\n",
835 scan_param
->nchannel_buckets
));
840 case GSCAN_ATTRIBUTE_CH_BUCKET_1
:
841 case GSCAN_ATTRIBUTE_CH_BUCKET_2
:
842 case GSCAN_ATTRIBUTE_CH_BUCKET_3
:
843 case GSCAN_ATTRIBUTE_CH_BUCKET_4
:
844 case GSCAN_ATTRIBUTE_CH_BUCKET_5
:
845 case GSCAN_ATTRIBUTE_CH_BUCKET_6
:
846 case GSCAN_ATTRIBUTE_CH_BUCKET_7
:
847 err
= wl_cfgvendor_set_scan_cfg_bucket(iter
, scan_param
, j
);
849 WL_ERR(("set_scan_cfg_buck error:%d\n", err
));
855 WL_ERR(("Unknown type %d\n", type
));
861 err
= dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
862 DHD_PNO_SCAN_CFG_ID
, scan_param
, FALSE
);
865 WL_ERR(("Could not set GSCAN scan cfg\n"));
870 MFREE(cfg
->osh
, scan_param
, sizeof(gscan_scan_params_t
));
876 wl_cfgvendor_hotlist_cfg(struct wiphy
*wiphy
,
877 struct wireless_dev
*wdev
, const void *data
, int len
)
880 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
881 gscan_hotlist_scan_params_t
*hotlist_params
;
882 int tmp
, tmp1
, tmp2
, type
, j
= 0, dummy
;
883 const struct nlattr
*outer
, *inner
= NULL
, *iter
;
885 struct bssid_t
*pbssid
;
887 BCM_REFERENCE(dummy
);
889 if (len
< sizeof(*hotlist_params
) || len
>= WLC_IOCTL_MAXLEN
) {
890 WL_ERR(("buffer length :%d wrong - bail out.\n", len
));
894 hotlist_params
= (gscan_hotlist_scan_params_t
*)MALLOCZ(cfg
->osh
,
895 sizeof(*hotlist_params
)
896 + (sizeof(struct bssid_t
) * (PFN_SWC_MAX_NUM_APS
- 1)));
898 if (!hotlist_params
) {
899 WL_ERR(("Cannot Malloc memory.\n"));
903 hotlist_params
->lost_ap_window
= GSCAN_LOST_AP_WINDOW_DEFAULT
;
905 nla_for_each_attr(iter
, data
, len
, tmp2
) {
906 type
= nla_type(iter
);
908 case GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT
:
909 if (nla_len(iter
) != sizeof(uint32
)) {
910 WL_DBG(("type:%d length:%d not matching.\n",
911 type
, nla_len(iter
)));
915 hotlist_params
->nbssid
= (uint16
)nla_get_u32(iter
);
916 if ((hotlist_params
->nbssid
== 0) ||
917 (hotlist_params
->nbssid
> PFN_SWC_MAX_NUM_APS
)) {
918 WL_ERR(("nbssid:%d exceed limit.\n",
919 hotlist_params
->nbssid
));
924 case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS
:
925 if (hotlist_params
->nbssid
== 0) {
926 WL_ERR(("nbssid not retrieved.\n"));
930 pbssid
= hotlist_params
->bssid
;
931 nla_for_each_nested(outer
, iter
, tmp
) {
932 if (j
>= hotlist_params
->nbssid
)
934 nla_for_each_nested(inner
, outer
, tmp1
) {
935 type
= nla_type(inner
);
938 case GSCAN_ATTRIBUTE_BSSID
:
939 if (nla_len(inner
) != sizeof(pbssid
[j
].macaddr
)) {
940 WL_ERR(("type:%d length:%d not matching.\n",
941 type
, nla_len(inner
)));
946 &(pbssid
[j
].macaddr
),
948 sizeof(pbssid
[j
].macaddr
));
950 case GSCAN_ATTRIBUTE_RSSI_LOW
:
951 if (nla_len(inner
) != sizeof(uint8
)) {
952 WL_ERR(("type:%d length:%d not matching.\n",
953 type
, nla_len(inner
)));
957 pbssid
[j
].rssi_reporting_threshold
=
958 (int8
)nla_get_u8(inner
);
960 case GSCAN_ATTRIBUTE_RSSI_HIGH
:
961 if (nla_len(inner
) != sizeof(uint8
)) {
962 WL_ERR(("type:%d length:%d not matching.\n",
963 type
, nla_len(inner
)));
967 dummy
= (int8
)nla_get_u8(inner
);
968 WL_DBG(("dummy %d\n", dummy
));
971 WL_ERR(("ATTR unknown %d\n", type
));
978 if (j
!= hotlist_params
->nbssid
) {
979 WL_ERR(("bssid_cnt:%d != nbssid:%d.\n", j
,
980 hotlist_params
->nbssid
));
985 case GSCAN_ATTRIBUTE_HOTLIST_FLUSH
:
986 if (nla_len(iter
) != sizeof(uint8
)) {
987 WL_ERR(("type:%d length:%d not matching.\n",
988 type
, nla_len(iter
)));
992 flush
= nla_get_u8(iter
);
994 case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE
:
995 if (nla_len(iter
) != sizeof(uint32
)) {
996 WL_ERR(("type:%d length:%d not matching.\n",
997 type
, nla_len(iter
)));
1001 hotlist_params
->lost_ap_window
= (uint16
)nla_get_u32(iter
);
1004 WL_ERR(("Unknown type %d\n", type
));
1011 if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
1012 DHD_PNO_GEOFENCE_SCAN_CFG_ID
, hotlist_params
, flush
) < 0) {
1013 WL_ERR(("Could not set GSCAN HOTLIST cfg error: %d\n", err
));
1018 MFREE(cfg
->osh
, hotlist_params
, sizeof(*hotlist_params
)
1019 + (sizeof(struct bssid_t
) * (PFN_SWC_MAX_NUM_APS
- 1)));
1023 static int wl_cfgvendor_epno_cfg(struct wiphy
*wiphy
,
1024 struct wireless_dev
*wdev
, const void *data
, int len
)
1027 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1028 dhd_pno_ssid_t
*ssid_elem
= NULL
;
1029 int tmp
, tmp1
, tmp2
, type
= 0, num
= 0;
1030 const struct nlattr
*outer
, *inner
, *iter
;
1031 uint8 flush
= FALSE
, i
= 0;
1032 wl_ssid_ext_params_t params
;
1034 nla_for_each_attr(iter
, data
, len
, tmp2
) {
1035 type
= nla_type(iter
);
1037 case GSCAN_ATTRIBUTE_EPNO_SSID_LIST
:
1038 nla_for_each_nested(outer
, iter
, tmp
) {
1039 ssid_elem
= (dhd_pno_ssid_t
*)
1040 dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg
),
1041 DHD_PNO_GET_NEW_EPNO_SSID_ELEM
,
1044 WL_ERR(("Failed to get SSID LIST buffer\n"));
1049 nla_for_each_nested(inner
, outer
, tmp1
) {
1050 type
= nla_type(inner
);
1053 case GSCAN_ATTRIBUTE_EPNO_SSID
:
1054 memcpy(ssid_elem
->SSID
,
1056 DOT11_MAX_SSID_LEN
);
1058 case GSCAN_ATTRIBUTE_EPNO_SSID_LEN
:
1059 ssid_elem
->SSID_len
=
1061 if (ssid_elem
->SSID_len
>
1062 DOT11_MAX_SSID_LEN
) {
1065 ssid_elem
->SSID_len
));
1067 MFREE(cfg
->osh
, ssid_elem
,
1072 case GSCAN_ATTRIBUTE_EPNO_FLAGS
:
1076 ((ssid_elem
->flags
&
1077 DHD_EPNO_HIDDEN_SSID
) != 0);
1079 case GSCAN_ATTRIBUTE_EPNO_AUTH
:
1080 ssid_elem
->wpa_auth
=
1085 if (!ssid_elem
->SSID_len
) {
1086 WL_ERR(("Broadcast SSID is illegal for ePNO\n"));
1088 MFREE(cfg
->osh
, ssid_elem
, num
);
1091 dhd_pno_translate_epno_fw_flags(&ssid_elem
->flags
);
1092 dhd_pno_set_epno_auth_flag(&ssid_elem
->wpa_auth
);
1093 MFREE(cfg
->osh
, ssid_elem
, num
);
1096 case GSCAN_ATTRIBUTE_EPNO_SSID_NUM
:
1097 num
= nla_get_u8(iter
);
1099 case GSCAN_ATTRIBUTE_EPNO_FLUSH
:
1100 flush
= (bool)nla_get_u32(iter
);
1101 /* Flush attribute is expected before any ssid attribute */
1103 WL_ERR(("Bad attributes\n"));
1107 /* Need to flush driver and FW cfg */
1108 dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
1109 DHD_PNO_EPNO_CFG_ID
, NULL
, flush
);
1110 dhd_dev_flush_fw_epno(bcmcfg_to_prmry_ndev(cfg
));
1112 case GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR
:
1113 params
.min5G_rssi
= nla_get_s8(iter
);
1115 case GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR
:
1116 params
.min2G_rssi
= nla_get_s8(iter
);
1118 case GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX
:
1119 params
.init_score_max
= nla_get_s16(iter
);
1121 case GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS
:
1122 params
.cur_bssid_bonus
= nla_get_s16(iter
);
1124 case GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS
:
1125 params
.same_ssid_bonus
= nla_get_s16(iter
);
1127 case GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS
:
1128 params
.secure_bonus
= nla_get_s16(iter
);
1130 case GSCAN_ATTRIBUTE_EPNO_5G_BONUS
:
1131 params
.band_5g_bonus
= nla_get_s16(iter
);
1134 WL_ERR(("%s: No such attribute %d\n", __FUNCTION__
, type
));
1140 WL_ERR(("%s: num_ssid %d does not match ssids sent %d\n", __FUNCTION__
,
1145 /* Flush all configs if error condition */
1147 dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
1148 DHD_PNO_EPNO_CFG_ID
, NULL
, TRUE
);
1149 dhd_dev_flush_fw_epno(bcmcfg_to_prmry_ndev(cfg
));
1150 } else if (type
!= GSCAN_ATTRIBUTE_EPNO_FLUSH
) {
1151 /* If the last attribute was FLUSH, nothing else to do */
1152 dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
1153 DHD_PNO_EPNO_PARAMS_ID
, ¶ms
, FALSE
);
1154 err
= dhd_dev_set_epno(bcmcfg_to_prmry_ndev(cfg
));
1160 wl_cfgvendor_set_batch_scan_cfg(struct wiphy
*wiphy
,
1161 struct wireless_dev
*wdev
, const void *data
, int len
)
1163 int err
= 0, tmp
, type
;
1164 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1165 gscan_batch_params_t batch_param
;
1166 const struct nlattr
*iter
;
1168 batch_param
.mscan
= batch_param
.bestn
= 0;
1169 batch_param
.buffer_threshold
= GSCAN_BATCH_NO_THR_SET
;
1171 nla_for_each_attr(iter
, data
, len
, tmp
) {
1172 type
= nla_type(iter
);
1175 case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN
:
1176 batch_param
.bestn
= nla_get_u32(iter
);
1178 case GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE
:
1179 batch_param
.mscan
= nla_get_u32(iter
);
1181 case GSCAN_ATTRIBUTE_REPORT_THRESHOLD
:
1182 batch_param
.buffer_threshold
= nla_get_u32(iter
);
1185 WL_ERR(("Unknown type %d\n", type
));
1190 if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
1191 DHD_PNO_BATCH_SCAN_CFG_ID
, &batch_param
, FALSE
) < 0) {
1192 WL_ERR(("Could not set batch cfg\n"));
1200 #endif /* GSCAN_SUPPORT */
1201 #if defined(GSCAN_SUPPORT) || defined(DHD_GET_VALID_CHANNELS)
1203 wl_cfgvendor_gscan_get_channel_list(struct wiphy
*wiphy
,
1204 struct wireless_dev
*wdev
, const void *data
, int len
)
1206 int err
= 0, type
, band
;
1207 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1208 uint16
*reply
= NULL
;
1209 uint32 reply_len
= 0, num_channels
, mem_needed
;
1210 struct sk_buff
*skb
;
1212 struct net_device
*ndev
= wdev
->netdev
;
1215 WL_ERR(("ndev null\n"));
1219 dhdp
= wl_cfg80211_get_dhdp(ndev
);
1221 WL_ERR(("dhdp null\n"));
1226 WL_ERR(("data is not available\n"));
1231 WL_ERR(("invalid len %d\n", len
));
1235 type
= nla_type(data
);
1236 if (type
== GSCAN_ATTRIBUTE_BAND
) {
1237 band
= nla_get_u32(data
);
1242 reply
= dhd_pno_get_gscan(dhdp
,
1243 DHD_PNO_GET_CHANNEL_LIST
, &band
, &reply_len
);
1245 WL_ERR(("Could not get channel list\n"));
1249 num_channels
= reply_len
/ sizeof(uint32
);
1250 mem_needed
= reply_len
+ VENDOR_REPLY_OVERHEAD
+ (ATTRIBUTE_U32_LEN
* 2);
1252 /* Alloc the SKB for vendor_event */
1253 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
1254 if (unlikely(!skb
)) {
1255 WL_ERR(("skb alloc failed"));
1260 nla_put_u32(skb
, GSCAN_ATTRIBUTE_NUM_CHANNELS
, num_channels
);
1261 nla_put(skb
, GSCAN_ATTRIBUTE_CHANNEL_LIST
, reply_len
, reply
);
1263 err
= cfg80211_vendor_cmd_reply(skb
);
1265 if (unlikely(err
)) {
1266 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
1269 MFREE(cfg
->osh
, reply
, reply_len
);
1272 #endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */
1274 #ifdef RSSI_MONITOR_SUPPORT
1275 static int wl_cfgvendor_set_rssi_monitor(struct wiphy
*wiphy
,
1276 struct wireless_dev
*wdev
, const void *data
, int len
)
1278 int err
= 0, tmp
, type
, start
= 0;
1279 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1280 int8 max_rssi
= 0, min_rssi
= 0;
1281 const struct nlattr
*iter
;
1283 nla_for_each_attr(iter
, data
, len
, tmp
) {
1284 type
= nla_type(iter
);
1286 case RSSI_MONITOR_ATTRIBUTE_MAX_RSSI
:
1287 max_rssi
= (int8
) nla_get_u32(iter
);
1289 case RSSI_MONITOR_ATTRIBUTE_MIN_RSSI
:
1290 min_rssi
= (int8
) nla_get_u32(iter
);
1292 case RSSI_MONITOR_ATTRIBUTE_START
:
1293 start
= nla_get_u32(iter
);
1297 if (dhd_dev_set_rssi_monitor_cfg(bcmcfg_to_prmry_ndev(cfg
),
1298 start
, max_rssi
, min_rssi
) < 0) {
1299 WL_ERR(("Could not set rssi monitor cfg\n"));
1304 #endif /* RSSI_MONITOR_SUPPORT */
1306 #ifdef DHD_WAKE_STATUS
1308 wl_cfgvendor_get_wake_reason_stats(struct wiphy
*wiphy
,
1309 struct wireless_dev
*wdev
, const void *data
, int len
)
1311 struct net_device
*ndev
= wdev_to_ndev(wdev
);
1312 wake_counts_t
*pwake_count_info
;
1313 int ret
, mem_needed
;
1314 #if defined(DHD_DEBUG) && defined(DHD_WAKE_EVENT_STATUS)
1316 #endif /* DHD_DEBUG && DHD_WAKE_EVENT_STATUS */
1317 struct sk_buff
*skb
= NULL
;
1318 dhd_pub_t
*dhdp
= wl_cfg80211_get_dhdp(ndev
);
1320 WL_DBG(("Recv get wake status info cmd.\n"));
1322 pwake_count_info
= dhd_get_wakecount(dhdp
);
1323 mem_needed
= VENDOR_REPLY_OVERHEAD
+ (ATTRIBUTE_U32_LEN
* 20) +
1324 (WLC_E_LAST
* sizeof(uint
));
1326 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
1327 if (unlikely(!skb
)) {
1328 WL_ERR(("%s: can't allocate %d bytes\n", __FUNCTION__
, mem_needed
));
1332 #ifdef DHD_WAKE_EVENT_STATUS
1333 WL_ERR(("pwake_count_info->rcwake %d\n", pwake_count_info
->rcwake
));
1334 ret
= nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT
, pwake_count_info
->rcwake
);
1335 if (unlikely(ret
)) {
1336 WL_ERR(("Failed to put Total count of CMD event, ret=%d\n", ret
));
1339 ret
= nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT_USED
, WLC_E_LAST
);
1340 if (unlikely(ret
)) {
1341 WL_ERR(("Failed to put Max count of event used, ret=%d\n", ret
));
1344 ret
= nla_put(skb
, WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE
, (WLC_E_LAST
* sizeof(uint
)),
1345 pwake_count_info
->rc_event
);
1346 if (unlikely(ret
)) {
1347 WL_ERR(("Failed to put Event wake data, ret=%d\n", ret
));
1351 for (flowid
= 0; flowid
< WLC_E_LAST
; flowid
++) {
1352 if (pwake_count_info
->rc_event
[flowid
] != 0) {
1353 WL_ERR((" %s = %u\n", bcmevent_get_name(flowid
),
1354 pwake_count_info
->rc_event
[flowid
]));
1357 #endif /* DHD_DEBUG */
1358 #endif /* DHD_WAKE_EVENT_STATUS */
1359 #ifdef DHD_WAKE_RX_STATUS
1360 WL_ERR(("pwake_count_info->rxwake %d\n", pwake_count_info
->rxwake
));
1361 ret
= nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE
, pwake_count_info
->rxwake
);
1362 if (unlikely(ret
)) {
1363 WL_ERR(("Failed to put Total Wake due RX data, ret=%d\n", ret
));
1366 ret
= nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT
, pwake_count_info
->rx_ucast
);
1367 if (unlikely(ret
)) {
1368 WL_ERR(("Failed to put Total wake due to RX unicast, ret=%d\n", ret
));
1371 ret
= nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT
, pwake_count_info
->rx_mcast
);
1372 if (unlikely(ret
)) {
1373 WL_ERR(("Failed to put Total wake due RX multicast, ret=%d\n", ret
));
1376 ret
= nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT
, pwake_count_info
->rx_bcast
);
1377 if (unlikely(ret
)) {
1378 WL_ERR(("Failed to put Total wake due to RX broadcast, ret=%d\n", ret
));
1381 ret
= nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT
, pwake_count_info
->rx_arp
);
1382 if (unlikely(ret
)) {
1383 WL_ERR(("Failed to put Total wake due to ICMP pkt, ret=%d\n", ret
));
1386 ret
= nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT
, pwake_count_info
->rx_icmpv6
);
1387 if (unlikely(ret
)) {
1388 WL_ERR(("Failed to put Total wake due ICMPV6 pkt, ret=%d\n", ret
));
1391 ret
= nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA
, pwake_count_info
->rx_icmpv6_ra
);
1392 if (unlikely(ret
)) {
1393 WL_ERR(("Failed to put Total wake due to ICMPV6_RA, ret=%d\n", ret
));
1396 ret
= nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA
, pwake_count_info
->rx_icmpv6_na
);
1397 if (unlikely(ret
)) {
1398 WL_ERR(("Failed to put Total wake due to ICMPV6_NA, ret=%d\n", ret
));
1401 ret
= nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS
, pwake_count_info
->rx_icmpv6_ns
);
1402 if (unlikely(ret
)) {
1403 WL_ERR(("Failed to put Total wake due to ICMPV6_NS, ret=%d\n", ret
));
1406 ret
= nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT
,
1407 pwake_count_info
->rx_multi_ipv4
);
1408 if (unlikely(ret
)) {
1409 WL_ERR(("Failed to put Total wake due to RX IPV4 MULTICAST, ret=%d\n", ret
));
1412 ret
= nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT
,
1413 pwake_count_info
->rx_multi_ipv6
);
1414 if (unlikely(ret
)) {
1415 WL_ERR(("Failed to put Total wake due to RX IPV6 MULTICAST, ret=%d\n", ret
));
1418 ret
= nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT
,
1419 pwake_count_info
->rx_multi_other
);
1420 if (unlikely(ret
)) {
1421 WL_ERR(("Failed to put Total wake due to Other RX Multicast, ret=%d\n", ret
));
1424 #endif /* #ifdef DHD_WAKE_RX_STATUS */
1425 ret
= cfg80211_vendor_cmd_reply(skb
);
1426 if (unlikely(ret
)) {
1427 WL_ERR(("Vendor cmd reply for -get wake status failed:%d \n", ret
));
1429 /* On cfg80211_vendor_cmd_reply() skb is consumed and freed in case of success or failure */
1433 /* Free skb memory */
1439 #endif /* DHD_WAKE_STATUS */
1441 #ifdef DHDTCPACK_SUPPRESS
1443 wl_cfgvendor_set_tcpack_sup_mode(struct wiphy
*wiphy
,
1444 struct wireless_dev
*wdev
, const void *data
, int len
)
1446 int err
= BCME_OK
, type
;
1447 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1448 struct net_device
*ndev
= wdev_to_wlc_ndev(wdev
, cfg
);
1452 WL_ERR(("data is not available\n"));
1458 WL_ERR(("Length of the nlattr is not valid len : %d\n", len
));
1463 type
= nla_type(data
);
1464 if (type
== ANDR_WIFI_ATTRIBUTE_TCPACK_SUP_VALUE
) {
1465 enable
= (uint8
) nla_get_u32(data
);
1466 err
= dhd_dev_set_tcpack_sup_mode_cfg(ndev
, enable
);
1467 if (unlikely(err
)) {
1468 WL_ERR(("Could not set TCP Ack Suppress mode cfg: %d\n", err
));
1477 #endif /* DHDTCPACK_SUPPRESS */
1479 #if defined(WL_CFG80211) && defined(DHD_FILE_DUMP_EVENT)
1481 wl_cfgvendor_notify_dump_completion(struct wiphy
*wiphy
,
1482 struct wireless_dev
*wdev
, const void *data
, int len
)
1484 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1485 dhd_pub_t
*dhd_pub
= cfg
->pub
;
1486 unsigned long flags
= 0;
1488 WL_INFORM(("%s, [DUMP] received file dump notification from HAL\n", __FUNCTION__
));
1490 DHD_GENERAL_LOCK(dhd_pub
, flags
);
1491 /* call wmb() to synchronize with the previous memory operations */
1493 DHD_BUS_BUSY_CLEAR_IN_HALDUMP(dhd_pub
);
1494 /* Call another wmb() to make sure wait_for_dump_completion value
1495 * gets updated before waking up waiting context.
1498 dhd_os_busbusy_wake(dhd_pub
);
1499 DHD_GENERAL_UNLOCK(dhd_pub
, flags
);
1503 #endif /* WL_CFG80211 && DHD_FILE_DUMP_EVENT */
1505 #if defined(WL_CFG80211)
1507 wl_cfgvendor_set_hal_started(struct wiphy
*wiphy
,
1508 struct wireless_dev
*wdev
, const void *data
, int len
)
1510 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1511 WL_INFORM(("%s,[DUMP] HAL STARTED\n", __FUNCTION__
));
1513 cfg
->hal_started
= true;
1518 wl_cfgvendor_stop_hal(struct wiphy
*wiphy
,
1519 struct wireless_dev
*wdev
, const void *data
, int len
)
1521 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1522 WL_INFORM(("%s,[DUMP] HAL STOPPED\n", __FUNCTION__
));
1524 cfg
->hal_started
= false;
1527 #endif /* WL_CFG80211 */
1531 wl_cfgvendor_rtt_evt(void *ctx
, void *rtt_data
)
1533 struct wireless_dev
*wdev
= (struct wireless_dev
*)ctx
;
1534 struct wiphy
*wiphy
;
1535 struct sk_buff
*skb
= NULL
;
1536 uint32 evt_complete
= 0;
1538 rtt_result_t
*rtt_result
;
1539 rtt_results_header_t
*rtt_header
;
1540 struct list_head
*rtt_cache_list
;
1541 struct nlattr
*rtt_nl_hdr
;
1543 wiphy
= wdev
->wiphy
;
1546 /* Push the data to the skb */
1548 WL_ERR(("rtt_data is NULL\n"));
1551 rtt_cache_list
= (struct list_head
*)rtt_data
;
1552 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
1553 if (list_empty(rtt_cache_list
)) {
1554 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
1555 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1556 skb
= cfg80211_vendor_event_alloc(wiphy
, NULL
, 100,
1557 GOOGLE_RTT_COMPLETE_EVENT
, kflags
);
1559 skb
= cfg80211_vendor_event_alloc(wiphy
, 100, GOOGLE_RTT_COMPLETE_EVENT
, kflags
);
1560 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
1561 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
1563 WL_ERR(("skb alloc failed"));
1567 ret
= nla_put_u32(skb
, RTT_ATTRIBUTE_RESULTS_COMPLETE
, evt_complete
);
1569 WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULTS_COMPLETE\n"));
1572 cfg80211_vendor_event(skb
, kflags
);
1575 GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
1576 list_for_each_entry(rtt_header
, rtt_cache_list
, list
) {
1577 /* Alloc the SKB for vendor_event */
1578 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
1579 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1580 skb
= cfg80211_vendor_event_alloc(wiphy
, NULL
, rtt_header
->result_tot_len
+ 100,
1581 GOOGLE_RTT_COMPLETE_EVENT
, kflags
);
1583 skb
= cfg80211_vendor_event_alloc(wiphy
, rtt_header
->result_tot_len
+ 100,
1584 GOOGLE_RTT_COMPLETE_EVENT
, kflags
);
1585 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
1586 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
1588 WL_ERR(("skb alloc failed"));
1591 if (list_is_last(&rtt_header
->list
, rtt_cache_list
)) {
1594 ret
= nla_put_u32(skb
, RTT_ATTRIBUTE_RESULTS_COMPLETE
, evt_complete
);
1596 WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULTS_COMPLETE\n"));
1599 rtt_nl_hdr
= nla_nest_start(skb
, RTT_ATTRIBUTE_RESULTS_PER_TARGET
);
1601 WL_ERR(("rtt_nl_hdr is NULL\n"));
1602 dev_kfree_skb_any(skb
);
1605 ret
= nla_put(skb
, RTT_ATTRIBUTE_TARGET_MAC
, ETHER_ADDR_LEN
,
1606 &rtt_header
->peer_mac
);
1608 WL_ERR(("Failed to put RTT_ATTRIBUTE_TARGET_MAC, ret:%d\n", ret
));
1611 ret
= nla_put_u32(skb
, RTT_ATTRIBUTE_RESULT_CNT
, rtt_header
->result_cnt
);
1613 WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULT_CNT, ret:%d\n", ret
));
1616 list_for_each_entry(rtt_result
, &rtt_header
->result_list
, list
) {
1617 ret
= nla_put(skb
, RTT_ATTRIBUTE_RESULT
,
1618 rtt_result
->report_len
, &rtt_result
->report
);
1620 WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULT, ret:%d\n", ret
));
1623 ret
= nla_put(skb
, RTT_ATTRIBUTE_RESULT_DETAIL
,
1624 rtt_result
->detail_len
, &rtt_result
->rtt_detail
);
1626 WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULT_DETAIL, ret:%d\n",
1631 nla_nest_end(skb
, rtt_nl_hdr
);
1632 cfg80211_vendor_event(skb
, kflags
);
1634 GCC_DIAGNOSTIC_POP();
1639 /* Free skb memory */
1646 wl_cfgvendor_rtt_set_config(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1647 const void *data
, int len
) {
1648 int err
= 0, rem
, rem1
, rem2
, type
;
1650 rtt_config_params_t rtt_param
;
1651 rtt_target_info_t
* rtt_target
= NULL
;
1652 const struct nlattr
*iter
, *iter1
, *iter2
;
1653 int8 eabuf
[ETHER_ADDR_STR_LEN
];
1654 int8 chanbuf
[CHANSPEC_STR_LEN
];
1655 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1656 rtt_capabilities_t capability
;
1658 bzero(&rtt_param
, sizeof(rtt_param
));
1661 err
= dhd_dev_rtt_register_noti_callback(wdev
->netdev
, wdev
, wl_cfgvendor_rtt_evt
);
1663 WL_ERR(("failed to register rtt_noti_callback\n"));
1666 err
= dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg
), &capability
);
1668 WL_ERR(("failed to get the capability\n"));
1673 WL_ERR(("Length of the nlattr is not valid len : %d\n", len
));
1677 nla_for_each_attr(iter
, data
, len
, rem
) {
1678 type
= nla_type(iter
);
1680 case RTT_ATTRIBUTE_TARGET_CNT
:
1681 if (target_cnt
!= 0) {
1682 WL_ERR(("attempt to overwrite target_cnt"));
1686 target_cnt
= nla_get_u8(iter
);
1687 if ((target_cnt
<= 0) || (target_cnt
> RTT_MAX_TARGET_CNT
)) {
1688 WL_ERR(("target_cnt is not valid : %d\n",
1693 rtt_param
.rtt_target_cnt
= target_cnt
;
1695 rtt_param
.target_info
= (rtt_target_info_t
*)MALLOCZ(cfg
->osh
,
1696 TARGET_INFO_SIZE(target_cnt
));
1697 if (rtt_param
.target_info
== NULL
) {
1698 WL_ERR(("failed to allocate target info for (%d)\n", target_cnt
));
1703 case RTT_ATTRIBUTE_TARGET_INFO
:
1704 /* Added this variable for safe check to avoid crash
1705 * incase the caller did not respect the order
1707 if (rtt_param
.target_info
== NULL
) {
1708 WL_ERR(("rtt_target_info is NULL\n"));
1712 rtt_target
= rtt_param
.target_info
;
1713 nla_for_each_nested(iter1
, iter
, rem1
) {
1714 if ((uint8
*)rtt_target
>= ((uint8
*)rtt_param
.target_info
+
1715 TARGET_INFO_SIZE(target_cnt
))) {
1716 WL_ERR(("rtt_target increased over its max size"));
1720 nla_for_each_nested(iter2
, iter1
, rem2
) {
1721 type
= nla_type(iter2
);
1723 case RTT_ATTRIBUTE_TARGET_MAC
:
1724 if (nla_len(iter2
) != ETHER_ADDR_LEN
) {
1725 WL_ERR(("mac_addr length not match\n"));
1729 memcpy(&rtt_target
->addr
, nla_data(iter2
),
1732 case RTT_ATTRIBUTE_TARGET_TYPE
:
1733 rtt_target
->type
= nla_get_u8(iter2
);
1734 if (rtt_target
->type
== RTT_INVALID
||
1735 (rtt_target
->type
== RTT_ONE_WAY
&&
1736 !capability
.rtt_one_sided_supported
)) {
1737 WL_ERR(("doesn't support RTT type"
1744 case RTT_ATTRIBUTE_TARGET_PEER
:
1745 rtt_target
->peer
= nla_get_u8(iter2
);
1747 case RTT_ATTRIBUTE_TARGET_CHAN
:
1748 memcpy(&rtt_target
->channel
, nla_data(iter2
),
1749 sizeof(rtt_target
->channel
));
1751 case RTT_ATTRIBUTE_TARGET_PERIOD
:
1752 rtt_target
->burst_period
= nla_get_u32(iter2
);
1753 if (rtt_target
->burst_period
< 32) {
1755 rtt_target
->burst_period
*= 100;
1757 WL_ERR(("%d value must in (0-31)\n",
1758 rtt_target
->burst_period
));
1763 case RTT_ATTRIBUTE_TARGET_NUM_BURST
:
1764 rtt_target
->num_burst
= nla_get_u32(iter2
);
1765 if (rtt_target
->num_burst
> 16) {
1766 WL_ERR(("%d value must in (0-15)\n",
1767 rtt_target
->num_burst
));
1771 rtt_target
->num_burst
= BIT(rtt_target
->num_burst
);
1773 case RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST
:
1774 rtt_target
->num_frames_per_burst
=
1777 case RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM
:
1778 rtt_target
->num_retries_per_ftm
=
1781 case RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR
:
1782 rtt_target
->num_retries_per_ftmr
=
1784 if (rtt_target
->num_retries_per_ftmr
> 3) {
1785 WL_ERR(("%d value must in (0-3)\n",
1786 rtt_target
->num_retries_per_ftmr
));
1791 case RTT_ATTRIBUTE_TARGET_LCI
:
1792 rtt_target
->LCI_request
= nla_get_u8(iter2
);
1794 case RTT_ATTRIBUTE_TARGET_LCR
:
1795 rtt_target
->LCI_request
= nla_get_u8(iter2
);
1797 case RTT_ATTRIBUTE_TARGET_BURST_DURATION
:
1798 if ((nla_get_u32(iter2
) > 1 &&
1799 nla_get_u32(iter2
) < 12)) {
1800 rtt_target
->burst_duration
=
1801 dhd_rtt_idx_to_burst_duration(
1802 nla_get_u32(iter2
));
1803 } else if (nla_get_u32(iter2
) == 15) {
1804 /* use default value */
1805 rtt_target
->burst_duration
= 0;
1807 WL_ERR(("%d value must in (2-11) or 15\n",
1808 nla_get_u32(iter2
)));
1813 case RTT_ATTRIBUTE_TARGET_BW
:
1814 rtt_target
->bw
= nla_get_u8(iter2
);
1816 case RTT_ATTRIBUTE_TARGET_PREAMBLE
:
1817 rtt_target
->preamble
= nla_get_u8(iter2
);
1821 /* convert to chanspec value */
1822 rtt_target
->chanspec
=
1823 dhd_rtt_convert_to_chspec(rtt_target
->channel
);
1824 if (rtt_target
->chanspec
== 0) {
1825 WL_ERR(("Channel is not valid \n"));
1829 WL_INFORM_MEM(("Target addr %s, Channel : %s for RTT \n",
1830 bcm_ether_ntoa((const struct ether_addr
*)&rtt_target
->addr
,
1832 wf_chspec_ntoa(rtt_target
->chanspec
, chanbuf
)));
1838 WL_DBG(("leave :target_cnt : %d\n", rtt_param
.rtt_target_cnt
));
1839 if (dhd_dev_rtt_set_cfg(bcmcfg_to_prmry_ndev(cfg
), &rtt_param
) < 0) {
1840 WL_ERR(("Could not set RTT configuration\n"));
1844 /* free the target info list */
1845 if (rtt_param
.target_info
) {
1846 MFREE(cfg
->osh
, rtt_param
.target_info
,
1847 TARGET_INFO_SIZE(target_cnt
));
1853 wl_cfgvendor_rtt_cancel_config(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1854 const void *data
, int len
)
1856 int err
= 0, rem
, type
, target_cnt
= 0;
1858 const struct nlattr
*iter
;
1859 struct ether_addr
*mac_list
= NULL
;
1860 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1863 WL_ERR(("Length of nlattr is not valid len : %d\n", len
));
1867 nla_for_each_attr(iter
, data
, len
, rem
) {
1868 type
= nla_type(iter
);
1870 case RTT_ATTRIBUTE_TARGET_CNT
:
1871 if (mac_list
!= NULL
) {
1872 WL_ERR(("mac_list is not NULL\n"));
1876 target_cnt
= nla_get_u8(iter
);
1877 if ((target_cnt
> 0) && (target_cnt
< RTT_MAX_TARGET_CNT
)) {
1878 mac_list
= (struct ether_addr
*)MALLOCZ(cfg
->osh
,
1879 target_cnt
* ETHER_ADDR_LEN
);
1880 if (mac_list
== NULL
) {
1881 WL_ERR(("failed to allocate mem for mac list\n"));
1886 /* cancel the current whole RTT process */
1890 case RTT_ATTRIBUTE_TARGET_MAC
:
1891 if (mac_list
== NULL
) {
1892 WL_ERR(("ATTRIBUTE_TARGET_CNT not found before "
1893 " ATTRIBUTE_TARGET_MAC\n"));
1898 if (target_idx
>= target_cnt
) {
1899 WL_ERR(("More TARGET_MAC entries found, "
1900 "expected TARGET_CNT:%d\n", target_cnt
));
1905 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
1906 WL_ERR(("Invalid TARGET_MAC ATTR len :%d\n", nla_len(iter
)));
1911 memcpy(&mac_list
[target_idx
], nla_data(iter
), ETHER_ADDR_LEN
);
1916 WL_ERR(("Uknown type : %d\n", type
));
1922 if (mac_list
&& dhd_dev_rtt_cancel_cfg(
1923 bcmcfg_to_prmry_ndev(cfg
), mac_list
, target_cnt
) < 0) {
1924 WL_ERR(("Could not cancel RTT configuration\n"));
1930 MFREE(cfg
->osh
, mac_list
, target_cnt
* ETHER_ADDR_LEN
);
1936 wl_cfgvendor_rtt_get_capability(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1937 const void *data
, int len
)
1940 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1941 rtt_capabilities_t capability
;
1943 err
= dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg
), &capability
);
1944 if (unlikely(err
)) {
1945 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
1948 err
= wl_cfgvendor_send_cmd_reply(wiphy
, &capability
, sizeof(capability
));
1950 if (unlikely(err
)) {
1951 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
1957 get_responder_info(struct bcm_cfg80211
*cfg
,
1958 struct wifi_rtt_responder
*responder_info
)
1961 rtt_capabilities_t capability
;
1962 err
= dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg
), &capability
);
1963 if (unlikely(err
)) {
1964 WL_ERR(("Could not get responder capability:%d \n", err
));
1967 if (capability
.preamble_support
& RTT_PREAMBLE_VHT
) {
1968 responder_info
->preamble
|= RTT_PREAMBLE_VHT
;
1970 if (capability
.preamble_support
& RTT_PREAMBLE_HT
) {
1971 responder_info
->preamble
|= RTT_PREAMBLE_HT
;
1973 err
= dhd_dev_rtt_avail_channel(bcmcfg_to_prmry_ndev(cfg
), &(responder_info
->channel
));
1974 if (unlikely(err
)) {
1975 WL_ERR(("Could not get available channel:%d \n", err
));
1981 wl_cfgvendor_rtt_get_responder_info(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1982 const void *data
, int len
)
1985 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1986 wifi_rtt_responder_t responder_info
;
1988 WL_DBG(("Recv -get_avail_ch command \n"));
1990 bzero(&responder_info
, sizeof(responder_info
));
1991 err
= get_responder_info(cfg
, &responder_info
);
1992 if (unlikely(err
)) {
1993 WL_ERR(("Failed to get responder info:%d \n", err
));
1996 err
= wl_cfgvendor_send_cmd_reply(wiphy
, &responder_info
, sizeof(responder_info
));
1997 if (unlikely(err
)) {
1998 WL_ERR(("Vendor cmd reply for -get_avail_ch failed ret:%d \n", err
));
2004 wl_cfgvendor_rtt_set_responder(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
2005 const void *data
, int len
)
2008 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2009 struct net_device
*ndev
= wdev_to_wlc_ndev(wdev
, cfg
);
2010 wifi_rtt_responder_t responder_info
;
2012 WL_DBG(("Recv rtt -enable_resp cmd.\n"));
2014 bzero(&responder_info
, sizeof(responder_info
));
2017 *Passing channel as NULL until implementation
2018 *to get chan info from upper layers is donex
2020 err
= dhd_dev_rtt_enable_responder(ndev
, NULL
);
2021 if (unlikely(err
)) {
2022 WL_ERR(("Could not enable responder ret:%d \n", err
));
2025 err
= get_responder_info(cfg
, &responder_info
);
2026 if (unlikely(err
)) {
2027 WL_ERR(("Failed to get responder info:%d \n", err
));
2028 dhd_dev_rtt_cancel_responder(ndev
);
2032 err
= wl_cfgvendor_send_cmd_reply(wiphy
, &responder_info
, sizeof(responder_info
));
2033 if (unlikely(err
)) {
2034 WL_ERR(("Vendor cmd reply for -enable_resp failed ret:%d \n", err
));
2040 wl_cfgvendor_rtt_cancel_responder(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
2041 const void *data
, int len
)
2044 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2046 WL_DBG(("Recv rtt -cancel_resp cmd \n"));
2048 err
= dhd_dev_rtt_cancel_responder(bcmcfg_to_prmry_ndev(cfg
));
2049 if (unlikely(err
)) {
2050 WL_ERR(("Vendor cmd -cancel_resp failed ret:%d \n", err
));
2054 #endif /* RTT_SUPPORT */
2056 #ifdef GSCAN_SUPPORT
2057 static int wl_cfgvendor_enable_lazy_roam(struct wiphy
*wiphy
,
2058 struct wireless_dev
*wdev
, const void *data
, int len
)
2061 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2063 uint32 lazy_roam_enable_flag
;
2066 WL_ERR(("data is not available\n"));
2071 WL_ERR(("invaild len %d\n", len
));
2075 type
= nla_type(data
);
2077 if (type
== GSCAN_ATTRIBUTE_LAZY_ROAM_ENABLE
) {
2078 lazy_roam_enable_flag
= nla_get_u32(data
);
2080 err
= dhd_dev_lazy_roam_enable(bcmcfg_to_prmry_ndev(cfg
),
2081 lazy_roam_enable_flag
);
2083 WL_ERR(("Could not enable lazy roam:%d \n", err
));
2089 static int wl_cfgvendor_set_lazy_roam_cfg(struct wiphy
*wiphy
,
2090 struct wireless_dev
*wdev
, const void *data
, int len
)
2092 int err
= 0, tmp
, type
;
2093 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2094 wlc_roam_exp_params_t roam_param
;
2095 const struct nlattr
*iter
;
2097 bzero(&roam_param
, sizeof(roam_param
));
2099 nla_for_each_attr(iter
, data
, len
, tmp
) {
2100 type
= nla_type(iter
);
2102 case GSCAN_ATTRIBUTE_A_BAND_BOOST_THRESHOLD
:
2103 roam_param
.a_band_boost_threshold
= nla_get_u32(iter
);
2105 case GSCAN_ATTRIBUTE_A_BAND_PENALTY_THRESHOLD
:
2106 roam_param
.a_band_penalty_threshold
= nla_get_u32(iter
);
2108 case GSCAN_ATTRIBUTE_A_BAND_BOOST_FACTOR
:
2109 roam_param
.a_band_boost_factor
= nla_get_u32(iter
);
2111 case GSCAN_ATTRIBUTE_A_BAND_PENALTY_FACTOR
:
2112 roam_param
.a_band_penalty_factor
= nla_get_u32(iter
);
2114 case GSCAN_ATTRIBUTE_A_BAND_MAX_BOOST
:
2115 roam_param
.a_band_max_boost
= nla_get_u32(iter
);
2117 case GSCAN_ATTRIBUTE_LAZY_ROAM_HYSTERESIS
:
2118 roam_param
.cur_bssid_boost
= nla_get_u32(iter
);
2120 case GSCAN_ATTRIBUTE_ALERT_ROAM_RSSI_TRIGGER
:
2121 roam_param
.alert_roam_trigger_threshold
= nla_get_u32(iter
);
2126 if (dhd_dev_set_lazy_roam_cfg(bcmcfg_to_prmry_ndev(cfg
), &roam_param
) < 0) {
2127 WL_ERR(("Could not set batch cfg\n"));
2133 /* small helper function */
2134 static wl_bssid_pref_cfg_t
*
2135 create_bssid_pref_cfg(struct bcm_cfg80211
*cfg
, uint32 num
, uint32
*buf_len
)
2137 wl_bssid_pref_cfg_t
*bssid_pref
;
2139 *buf_len
= sizeof(wl_bssid_pref_cfg_t
);
2141 *buf_len
+= (num
- 1) * sizeof(wl_bssid_pref_list_t
);
2143 bssid_pref
= (wl_bssid_pref_cfg_t
*)MALLOC(cfg
->osh
, *buf_len
);
2149 wl_cfgvendor_set_bssid_pref(struct wiphy
*wiphy
,
2150 struct wireless_dev
*wdev
, const void *data
, int len
)
2153 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2154 wl_bssid_pref_cfg_t
*bssid_pref
= NULL
;
2155 wl_bssid_pref_list_t
*bssids
;
2156 int tmp
, tmp1
, tmp2
, type
;
2157 const struct nlattr
*outer
, *inner
, *iter
;
2158 uint32 flush
= 0, num
= 0, buf_len
= 0;
2159 uint8 bssid_found
= 0, rssi_found
= 0;
2161 /* Assumption: NUM attribute must come first */
2162 nla_for_each_attr(iter
, data
, len
, tmp2
) {
2163 type
= nla_type(iter
);
2165 case GSCAN_ATTRIBUTE_NUM_BSSID
:
2167 WL_ERR(("attempt overide bssid num.\n"));
2171 if (nla_len(iter
) != sizeof(uint32
)) {
2172 WL_ERR(("nla_len not match\n"));
2176 num
= nla_get_u32(iter
);
2177 if (num
== 0 || num
> MAX_BSSID_PREF_LIST_NUM
) {
2178 WL_ERR(("wrong BSSID num:%d\n", num
));
2182 if ((bssid_pref
= create_bssid_pref_cfg(cfg
, num
, &buf_len
))
2184 WL_ERR(("Can't malloc memory\n"));
2189 case GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH
:
2190 if (nla_len(iter
) != sizeof(uint32
)) {
2191 WL_ERR(("nla_len not match\n"));
2195 flush
= nla_get_u32(iter
);
2197 WL_ERR(("wrong flush value\n"));
2202 case GSCAN_ATTRIBUTE_BSSID_PREF_LIST
:
2203 if (!num
|| !bssid_pref
) {
2204 WL_ERR(("bssid list count not set\n"));
2208 bssid_pref
->count
= 0;
2209 bssids
= bssid_pref
->bssids
;
2210 nla_for_each_nested(outer
, iter
, tmp
) {
2211 if (bssid_pref
->count
>= num
) {
2212 WL_ERR(("too many bssid list\n"));
2218 nla_for_each_nested(inner
, outer
, tmp1
) {
2219 type
= nla_type(inner
);
2221 case GSCAN_ATTRIBUTE_BSSID_PREF
:
2222 if (nla_len(inner
) != ETHER_ADDR_LEN
) {
2223 WL_ERR(("nla_len not match.\n"));
2227 memcpy(&(bssids
[bssid_pref
->count
].bssid
),
2228 nla_data(inner
), ETHER_ADDR_LEN
);
2229 /* not used for now */
2230 bssids
[bssid_pref
->count
].flags
= 0;
2233 case GSCAN_ATTRIBUTE_RSSI_MODIFIER
:
2234 if (nla_len(inner
) != sizeof(uint32
)) {
2235 WL_ERR(("nla_len not match.\n"));
2239 bssids
[bssid_pref
->count
].rssi_factor
=
2240 (int8
) nla_get_u32(inner
);
2244 WL_ERR(("wrong type:%d\n", type
));
2248 if (bssid_found
&& rssi_found
) {
2252 bssid_pref
->count
++;
2256 WL_ERR(("%s: No such attribute %d\n", __FUNCTION__
, type
));
2262 /* What if only flush is desired? */
2264 if ((bssid_pref
= create_bssid_pref_cfg(cfg
, 0, &buf_len
)) == NULL
) {
2265 WL_ERR(("%s: Can't malloc memory\n", __FUNCTION__
));
2269 bssid_pref
->count
= 0;
2275 err
= dhd_dev_set_lazy_roam_bssid_pref(bcmcfg_to_prmry_ndev(cfg
),
2279 MFREE(cfg
->osh
, bssid_pref
, buf_len
);
2283 #endif /* GSCAN_SUPPORT */
2284 #if defined(GSCAN_SUPPORT) || defined(ROAMEXP_SUPPORT)
2286 wl_cfgvendor_set_bssid_blacklist(struct wiphy
*wiphy
,
2287 struct wireless_dev
*wdev
, const void *data
, int len
)
2289 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2290 maclist_t
*blacklist
= NULL
;
2293 const struct nlattr
*iter
;
2294 uint32 mem_needed
= 0, flush
= 0, num
= 0;
2296 /* Assumption: NUM attribute must come first */
2297 nla_for_each_attr(iter
, data
, len
, tmp
) {
2298 type
= nla_type(iter
);
2300 case GSCAN_ATTRIBUTE_NUM_BSSID
:
2302 WL_ERR(("attempt to change BSSID num\n"));
2306 if (nla_len(iter
) != sizeof(uint32
)) {
2307 WL_ERR(("not matching nla_len.\n"));
2311 num
= nla_get_u32(iter
);
2312 if (num
== 0 || num
> MAX_BSSID_BLACKLIST_NUM
) {
2313 WL_ERR(("wrong BSSID count:%d\n", num
));
2318 mem_needed
= OFFSETOF(maclist_t
, ea
) +
2319 sizeof(struct ether_addr
) * (num
);
2320 blacklist
= (maclist_t
*)
2321 MALLOCZ(cfg
->osh
, mem_needed
);
2323 WL_ERR(("MALLOCZ failed.\n"));
2329 case GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH
:
2330 if (nla_len(iter
) != sizeof(uint32
)) {
2331 WL_ERR(("not matching nla_len.\n"));
2335 flush
= nla_get_u32(iter
);
2337 WL_ERR(("flush arg is worng:%d\n", flush
));
2342 case GSCAN_ATTRIBUTE_BLACKLIST_BSSID
:
2343 if (num
== 0 || !blacklist
) {
2344 WL_ERR(("number of BSSIDs not received.\n"));
2348 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
2349 WL_ERR(("not matching nla_len.\n"));
2353 if (blacklist
->count
>= num
) {
2354 WL_ERR(("too many BSSIDs than expected:%d\n",
2359 memcpy(&(blacklist
->ea
[blacklist
->count
]), nla_data(iter
),
2364 WL_ERR(("No such attribute:%d\n", type
));
2369 if (blacklist
&& (blacklist
->count
!= num
)) {
2370 WL_ERR(("not matching bssid count:%d to expected:%d\n",
2371 blacklist
->count
, num
));
2376 err
= dhd_dev_set_blacklist_bssid(bcmcfg_to_prmry_ndev(cfg
),
2377 blacklist
, mem_needed
, flush
);
2379 MFREE(cfg
->osh
, blacklist
, mem_needed
);
2384 wl_cfgvendor_set_ssid_whitelist(struct wiphy
*wiphy
,
2385 struct wireless_dev
*wdev
, const void *data
, int len
)
2388 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2389 wl_ssid_whitelist_t
*ssid_whitelist
= NULL
;
2390 wlc_ssid_t
*ssid_elem
;
2391 int tmp
, tmp1
, mem_needed
= 0, type
;
2392 const struct nlattr
*iter
, *iter1
;
2393 uint32 flush
= 0, num
= 0;
2396 /* Assumption: NUM attribute must come first */
2397 nla_for_each_attr(iter
, data
, len
, tmp
) {
2398 type
= nla_type(iter
);
2400 case GSCAN_ATTRIBUTE_NUM_WL_SSID
:
2402 WL_ERR(("try to change SSID num\n"));
2406 if (nla_len(iter
) != sizeof(uint32
)) {
2407 WL_ERR(("not matching nla_len.\n"));
2411 num
= nla_get_u32(iter
);
2412 if (num
== 0 || num
> MAX_SSID_WHITELIST_NUM
) {
2413 WL_ERR(("wrong SSID count:%d\n", num
));
2417 mem_needed
= sizeof(wl_ssid_whitelist_t
) +
2418 sizeof(wlc_ssid_t
) * num
;
2419 ssid_whitelist
= (wl_ssid_whitelist_t
*)
2420 MALLOCZ(cfg
->osh
, mem_needed
);
2421 if (ssid_whitelist
== NULL
) {
2422 WL_ERR(("failed to alloc mem\n"));
2427 case GSCAN_ATTRIBUTE_WL_SSID_FLUSH
:
2428 if (nla_len(iter
) != sizeof(uint32
)) {
2429 WL_ERR(("not matching nla_len.\n"));
2433 flush
= nla_get_u32(iter
);
2435 WL_ERR(("flush arg worng:%d\n", flush
));
2440 case GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM
:
2441 if (!num
|| !ssid_whitelist
) {
2442 WL_ERR(("num ssid is not set!\n"));
2446 if (ssid_whitelist
->ssid_count
>= num
) {
2447 WL_ERR(("too many SSIDs:%d\n",
2448 ssid_whitelist
->ssid_count
));
2453 ssid_elem
= &ssid_whitelist
->ssids
[
2454 ssid_whitelist
->ssid_count
];
2456 nla_for_each_nested(iter1
, iter
, tmp1
) {
2457 type
= nla_type(iter1
);
2459 case GSCAN_ATTRIBUTE_WL_SSID_LEN
:
2460 if (nla_len(iter1
) != sizeof(uint32
)) {
2461 WL_ERR(("not match nla_len\n"));
2465 ssid_elem
->SSID_len
= nla_get_u32(iter1
);
2466 if (ssid_elem
->SSID_len
>
2467 DOT11_MAX_SSID_LEN
) {
2468 WL_ERR(("wrong SSID len:%d\n",
2469 ssid_elem
->SSID_len
));
2474 case GSCAN_ATTRIBUTE_WHITELIST_SSID
:
2475 if (ssid_elem
->SSID_len
== 0) {
2476 WL_ERR(("SSID_len not received\n"));
2480 if (nla_len(iter1
) != ssid_elem
->SSID_len
) {
2481 WL_ERR(("not match nla_len\n"));
2485 memcpy(ssid_elem
->SSID
, nla_data(iter1
),
2486 ssid_elem
->SSID_len
);
2491 ssid_whitelist
->ssid_count
++;
2497 WL_ERR(("No such attribute: %d\n", type
));
2502 if (ssid_whitelist
&& (ssid_whitelist
->ssid_count
!= num
)) {
2503 WL_ERR(("not matching ssid count:%d to expected:%d\n",
2504 ssid_whitelist
->ssid_count
, num
));
2508 err
= dhd_dev_set_whitelist_ssid(bcmcfg_to_prmry_ndev(cfg
),
2509 ssid_whitelist
, mem_needed
, flush
);
2510 if (err
== BCME_UNSUPPORTED
) {
2511 /* If firmware doesn't support feature, ignore the error
2512 * Android framework doesn't populate/use whitelist ssids
2513 * as of now, but invokes whitelist as part of roam config
2514 * API. so this handler cannot be compiled out. but its
2517 WL_ERR(("whilelist ssid not supported. Ignore."));
2521 MFREE(cfg
->osh
, ssid_whitelist
, mem_needed
);
2524 #endif /* GSCAN_SUPPORT || ROAMEXP_SUPPORT */
2526 #ifdef ROAMEXP_SUPPORT
2528 FW_ROAMING_ENABLE
= 1,
2532 } fw_roaming_state_t
;
2535 wl_cfgvendor_set_fw_roaming_state(struct wiphy
*wiphy
,
2536 struct wireless_dev
*wdev
, const void *data
, int len
)
2538 fw_roaming_state_t requested_roaming_state
;
2543 WL_ERR(("data is not available\n"));
2548 WL_ERR(("invalid len %d\n", len
));
2552 /* Get the requested fw roaming state */
2553 type
= nla_type(data
);
2554 if (type
!= GSCAN_ATTRIBUTE_ROAM_STATE_SET
) {
2555 WL_ERR(("%s: Invalid attribute %d\n", __FUNCTION__
, type
));
2559 requested_roaming_state
= nla_get_u32(data
);
2560 WL_INFORM(("setting FW roaming state to %d\n", requested_roaming_state
));
2562 if ((requested_roaming_state
== FW_ROAMING_ENABLE
) ||
2563 (requested_roaming_state
== FW_ROAMING_RESUME
)) {
2564 err
= wldev_iovar_setint(wdev_to_ndev(wdev
), "roam_off", FALSE
);
2565 } else if ((requested_roaming_state
== FW_ROAMING_DISABLE
) ||
2566 (requested_roaming_state
== FW_ROAMING_PAUSE
)) {
2567 err
= wldev_iovar_setint(wdev_to_ndev(wdev
), "roam_off", TRUE
);
2576 wl_cfgvendor_fw_roam_get_capability(struct wiphy
*wiphy
,
2577 struct wireless_dev
*wdev
, const void *data
, int len
)
2580 wifi_roaming_capabilities_t roaming_capability
;
2582 /* Update max number of blacklist bssids supported */
2583 roaming_capability
.max_blacklist_size
= MAX_BSSID_BLACKLIST_NUM
;
2584 roaming_capability
.max_whitelist_size
= MAX_SSID_WHITELIST_NUM
;
2585 err
= wl_cfgvendor_send_cmd_reply(wiphy
, &roaming_capability
,
2586 sizeof(roaming_capability
));
2587 if (unlikely(err
)) {
2588 WL_ERR(("Vendor cmd reply for fw roam capability failed ret:%d \n", err
));
2593 #endif /* ROAMEXP_SUPPORT */
2596 wl_cfgvendor_priv_string_handler(struct wiphy
*wiphy
,
2597 struct wireless_dev
*wdev
, const void *data
, int len
)
2599 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2601 int ret_len
= 0, payload
= 0, msglen
;
2602 const struct bcm_nlmsg_hdr
*nlioc
= data
;
2603 void *buf
= NULL
, *cur
;
2604 int maxmsglen
= PAGE_SIZE
- 0x100;
2605 struct sk_buff
*reply
;
2606 dhd_pub_t
*dhdp
= wl_cfg80211_get_dhdp(wdev
->netdev
);
2608 /* send to dongle only if we are not waiting for reload already */
2609 if (dhdp
&& dhdp
->hang_was_sent
) {
2610 WL_INFORM(("Bus down. HANG was sent up earlier\n"));
2611 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp
, DHD_EVENT_TIMEOUT_MS
);
2612 DHD_OS_WAKE_UNLOCK(dhdp
);
2613 return OSL_ERROR(BCME_DONGLE_DOWN
);
2617 WL_ERR(("data is not available\n"));
2622 WL_ERR(("invalid len %d\n", len
));
2626 WL_DBG(("entry: cmd = %d\n", nlioc
->cmd
));
2628 if (nlioc
->offset
!= sizeof(struct bcm_nlmsg_hdr
) ||
2629 len
<= sizeof(struct bcm_nlmsg_hdr
)) {
2630 WL_ERR(("invalid offset %d\n", nlioc
->offset
));
2633 len
-= sizeof(struct bcm_nlmsg_hdr
);
2634 ret_len
= nlioc
->len
;
2635 if (ret_len
> 0 || len
> 0) {
2636 if (len
>= DHD_IOCTL_MAXLEN
) {
2637 WL_ERR(("oversize input buffer %d\n", len
));
2638 len
= DHD_IOCTL_MAXLEN
- 1;
2640 if (ret_len
>= DHD_IOCTL_MAXLEN
) {
2641 WL_ERR(("oversize return buffer %d\n", ret_len
));
2642 ret_len
= DHD_IOCTL_MAXLEN
- 1;
2645 payload
= max(ret_len
, len
) + 1;
2646 buf
= vzalloc(payload
);
2650 GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
2651 memcpy(buf
, (void *)((char *)nlioc
+ nlioc
->offset
), len
);
2652 GCC_DIAGNOSTIC_POP();
2653 *((char *)buf
+ len
) = '\0';
2656 ret
= dhd_cfgvendor_priv_string_handler(cfg
, wdev
, nlioc
, buf
);
2658 WL_ERR(("dhd_cfgvendor returned error %d", ret
));
2663 while (ret_len
> 0) {
2664 msglen
= ret_len
> maxmsglen
? maxmsglen
: ret_len
;
2666 payload
= msglen
+ sizeof(msglen
);
2667 reply
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, payload
);
2669 WL_ERR(("Failed to allocate reply msg\n"));
2674 if (nla_put(reply
, BCM_NLATTR_DATA
, msglen
, cur
) ||
2675 nla_put_u16(reply
, BCM_NLATTR_LEN
, msglen
)) {
2681 ret
= cfg80211_vendor_cmd_reply(reply
);
2683 WL_ERR(("testmode reply failed:%d\n", ret
));
2686 cur
= (void *)((char *)cur
+ msglen
);
2693 wl_cfgvendor_get_ndev(struct bcm_cfg80211
*cfg
, struct wireless_dev
*wdev
,
2694 const char *data
, unsigned long int *out_addr
)
2697 char ifname
[IFNAMSIZ
+ 1] = {0};
2698 struct net_info
*iter
, *next
;
2699 struct net_device
*ndev
= NULL
;
2701 *out_addr
= (unsigned long int) data
; /* point to command str by default */
2703 /* check whether ifname=<ifname> is provided in the command */
2704 pos
= strstr(data
, "ifname=");
2706 pos
+= strlen("ifname=");
2707 pos1
= strstr(pos
, " ");
2709 WL_ERR(("command format error \n"));
2713 ifname_len
= pos1
- pos
;
2714 if (memcpy_s(ifname
, (sizeof(ifname
) - 1), pos
, ifname_len
) != BCME_OK
) {
2715 WL_ERR(("Failed to copy data. len: %ld\n", ifname_len
));
2718 GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
2719 for_each_ndev(cfg
, iter
, next
) {
2721 if (strncmp(iter
->ndev
->name
, ifname
,
2722 strlen(iter
->ndev
->name
)) == 0) {
2723 /* matching ifname found */
2724 WL_DBG(("matching interface (%s) found ndev:%p \n",
2725 iter
->ndev
->name
, iter
->ndev
));
2726 *out_addr
= (unsigned long int)(pos1
+ 1);
2727 /* Returns the command portion after ifname=<name> */
2732 GCC_DIAGNOSTIC_POP();
2733 WL_ERR(("Couldn't find ifname:%s in the netinfo list \n",
2738 /* If ifname=<name> arg is not provided, use default ndev */
2739 ndev
= wdev
->netdev
? wdev
->netdev
: bcmcfg_to_prmry_ndev(cfg
);
2740 WL_DBG(("Using default ndev (%s) \n", ndev
->name
));
2746 wl_cfgvendor_set_sae_password(struct wiphy
*wiphy
,
2747 struct wireless_dev
*wdev
, const void *data
, int len
)
2750 struct net_device
*net
= wdev
->netdev
;
2751 struct bcm_cfg80211
*cfg
= wl_get_cfg(net
);
2755 /* clear the content of pmk structure before usage */
2756 (void)memset_s(&pmk
, sizeof(wsec_pmk_t
), 0x0, sizeof(wsec_pmk_t
));
2758 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, net
->ieee80211_ptr
)) < 0) {
2759 WL_ERR(("Find p2p index from wdev(%p) failed\n", net
->ieee80211_ptr
));
2763 if ((len
< WSEC_MIN_PSK_LEN
) || (len
>= WSEC_MAX_PASSPHRASE_LEN
)) {
2764 WL_ERR(("Invalid passphrase length %d..should be >= 8 and < 256\n",
2769 /* Set AUTH to SAE */
2770 err
= wldev_iovar_setint_bsscfg(net
, "wpa_auth", WPA3_AUTH_SAE_PSK
, bssidx
);
2771 if (unlikely(err
)) {
2772 WL_ERR(("could not set wpa_auth (0x%x)\n", err
));
2775 pmk
.key_len
= htod16(len
);
2776 bcopy((const u8
*)data
, pmk
.key
, len
);
2777 pmk
.flags
= htod16(WSEC_PASSPHRASE
);
2779 err
= wldev_ioctl_set(net
, WLC_SET_WSEC_PMK
, &pmk
, sizeof(pmk
));
2781 WL_ERR(("\n failed to set pmk %d\n", err
));
2784 WL_MEM(("sae passphrase set successfully\n"));
2791 #ifdef BCM_PRIV_CMD_SUPPORT
2792 /* strlen("ifname=") + IFNAMESIZE + strlen(" ") + '\0' */
2793 #define ANDROID_PRIV_CMD_IF_PREFIX_LEN (7 + IFNAMSIZ + 2)
2794 /* Max length for the reply buffer. For BRCM_ATTR_DRIVER_CMD, the reply
2795 * would be a formatted string and reply buf would be the size of the
2798 #define WL_DRIVER_PRIV_CMD_LEN 512
2800 wl_cfgvendor_priv_bcm_handler(struct wiphy
*wiphy
,
2801 struct wireless_dev
*wdev
, const void *data
, int len
)
2803 const struct nlattr
*iter
;
2805 int data_len
= 0, cmd_len
= 0, tmp
= 0, type
= 0;
2806 struct net_device
*ndev
= wdev
->netdev
;
2808 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2810 struct net_device
*net
= NULL
;
2811 unsigned long int cmd_out
= 0;
2812 #if defined(WL_ANDROID_PRIV_CMD_OVER_NL80211)
2813 u32 cmd_buf_len
= WL_DRIVER_PRIV_CMD_LEN
;
2814 char cmd_prefix
[ANDROID_PRIV_CMD_IF_PREFIX_LEN
+ 1] = {0};
2815 char *cmd_buf
= NULL
;
2818 #endif /* WL_ANDROID_PRIV_CMD_OVER_NL80211 && OEM_ANDROID */
2820 WL_DBG(("%s: Enter \n", __func__
));
2822 /* hold wake lock */
2823 net_os_wake_lock(ndev
);
2825 nla_for_each_attr(iter
, data
, len
, tmp
) {
2826 type
= nla_type(iter
);
2827 cmd
= nla_data(iter
);
2828 cmd_len
= nla_len(iter
);
2830 WL_DBG(("%s: type: %d cmd_len:%d cmd_ptr:%p \n", __func__
, type
, cmd_len
, cmd
));
2831 if (!cmd
|| !cmd_len
) {
2832 WL_ERR(("Invalid cmd data \n"));
2837 #if defined(WL_ANDROID_PRIV_CMD_OVER_NL80211)
2838 if (type
== BRCM_ATTR_DRIVER_CMD
) {
2839 if ((cmd_len
>= WL_DRIVER_PRIV_CMD_LEN
) ||
2840 (cmd_len
< ANDROID_PRIV_CMD_IF_PREFIX_LEN
)) {
2841 WL_ERR(("Unexpected command length (%u)."
2842 "Ignore the command\n", cmd_len
));
2847 /* check whether there is any ifname prefix provided */
2848 if (memcpy_s(cmd_prefix
, (sizeof(cmd_prefix
) - 1),
2849 cmd
, ANDROID_PRIV_CMD_IF_PREFIX_LEN
) != BCME_OK
) {
2850 WL_ERR(("memcpy failed for cmd buffer. len:%d\n", cmd_len
));
2855 net
= wl_cfgvendor_get_ndev(cfg
, wdev
, cmd_prefix
, &cmd_out
);
2856 if (!cmd_out
|| !net
) {
2857 WL_ERR(("ndev not found\n"));
2862 /* find offset of the command */
2863 current_pos
= (char *)cmd_out
;
2864 cmd_offset
= current_pos
- cmd_prefix
;
2866 if (!current_pos
|| (cmd_offset
) > ANDROID_PRIV_CMD_IF_PREFIX_LEN
) {
2867 WL_ERR(("Invalid len cmd_offset: %u \n", cmd_offset
));
2872 /* Private command data in expected to be in str format. To ensure that
2873 * the data is null terminated, copy to a local buffer before use
2875 cmd_buf
= (char *)MALLOCZ(cfg
->osh
, cmd_buf_len
);
2877 WL_ERR(("memory alloc failed for %u \n", cmd_buf_len
));
2882 /* Point to the start of command */
2883 if (memcpy_s(cmd_buf
, (WL_DRIVER_PRIV_CMD_LEN
- 1),
2884 (const void *)(cmd
+ cmd_offset
),
2885 (cmd_len
- cmd_offset
- 1)) != BCME_OK
) {
2886 WL_ERR(("memcpy failed for cmd buffer. len:%d\n", cmd_len
));
2890 cmd_buf
[WL_DRIVER_PRIV_CMD_LEN
- 1] = '\0';
2892 WL_DBG(("vendor_command: %s len: %u \n", cmd_buf
, cmd_buf_len
));
2893 bytes_written
= wl_handle_private_cmd(net
, cmd_buf
, cmd_buf_len
);
2894 WL_DBG(("bytes_written: %d \n", bytes_written
));
2895 if (bytes_written
== 0) {
2896 snprintf(cmd_buf
, cmd_buf_len
, "%s", "OK");
2897 data_len
= sizeof("OK");
2898 } else if (bytes_written
> 0) {
2899 if (bytes_written
>= (cmd_buf_len
- 1)) {
2905 data_len
= bytes_written
;
2907 /* -ve return value. Propagate the error back */
2908 err
= bytes_written
;
2911 if ((data_len
> 0) && (data_len
< (cmd_buf_len
- 1)) && cmd_buf
) {
2912 err
= wl_cfgvendor_send_cmd_reply(wiphy
, cmd_buf
, data_len
);
2913 if (unlikely(err
)) {
2914 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
2916 WL_DBG(("Vendor Command reply sent successfully!\n"));
2919 /* No data to be sent back as reply */
2920 WL_ERR(("Vendor_cmd: No reply expected. data_len:%u cmd_buf %p \n",
2921 data_len
, cmd_buf
));
2925 #endif /* WL_ANDROID_PRIV_CMD_OVER_NL80211 && OEM_ANDROID */
2929 #if defined(WL_ANDROID_PRIV_CMD_OVER_NL80211)
2931 MFREE(cfg
->osh
, cmd_buf
, cmd_buf_len
);
2933 #endif /* WL_ANDROID_PRIV_CMD_OVER_NL80211 && OEM_ANDROID */
2934 net_os_wake_unlock(ndev
);
2937 #endif /* BCM_PRIV_CMD_SUPPORT */
2940 static const char *nan_attr_to_str(u16 cmd
)
2943 C2S(NAN_ATTRIBUTE_HEADER
)
2944 C2S(NAN_ATTRIBUTE_HANDLE
)
2945 C2S(NAN_ATTRIBUTE_TRANSAC_ID
)
2946 C2S(NAN_ATTRIBUTE_2G_SUPPORT
)
2947 C2S(NAN_ATTRIBUTE_SDF_2G_SUPPORT
)
2948 C2S(NAN_ATTRIBUTE_SDF_5G_SUPPORT
)
2949 C2S(NAN_ATTRIBUTE_5G_SUPPORT
)
2950 C2S(NAN_ATTRIBUTE_SYNC_DISC_2G_BEACON
)
2951 C2S(NAN_ATTRIBUTE_SYNC_DISC_5G_BEACON
)
2952 C2S(NAN_ATTRIBUTE_CLUSTER_LOW
)
2953 C2S(NAN_ATTRIBUTE_CLUSTER_HIGH
)
2954 C2S(NAN_ATTRIBUTE_SID_BEACON
)
2955 C2S(NAN_ATTRIBUTE_RSSI_CLOSE
)
2956 C2S(NAN_ATTRIBUTE_RSSI_MIDDLE
)
2957 C2S(NAN_ATTRIBUTE_RSSI_PROXIMITY
)
2958 C2S(NAN_ATTRIBUTE_RSSI_CLOSE_5G
)
2959 C2S(NAN_ATTRIBUTE_RSSI_MIDDLE_5G
)
2960 C2S(NAN_ATTRIBUTE_RSSI_PROXIMITY_5G
)
2961 C2S(NAN_ATTRIBUTE_HOP_COUNT_LIMIT
)
2962 C2S(NAN_ATTRIBUTE_RANDOM_TIME
)
2963 C2S(NAN_ATTRIBUTE_MASTER_PREF
)
2964 C2S(NAN_ATTRIBUTE_PERIODIC_SCAN_INTERVAL
)
2965 C2S(NAN_ATTRIBUTE_PUBLISH_ID
)
2966 C2S(NAN_ATTRIBUTE_TTL
)
2967 C2S(NAN_ATTRIBUTE_PERIOD
)
2968 C2S(NAN_ATTRIBUTE_REPLIED_EVENT_FLAG
)
2969 C2S(NAN_ATTRIBUTE_PUBLISH_TYPE
)
2970 C2S(NAN_ATTRIBUTE_TX_TYPE
)
2971 C2S(NAN_ATTRIBUTE_PUBLISH_COUNT
)
2972 C2S(NAN_ATTRIBUTE_SERVICE_NAME_LEN
)
2973 C2S(NAN_ATTRIBUTE_SERVICE_NAME
)
2974 C2S(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
)
2975 C2S(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
)
2976 C2S(NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN
)
2977 C2S(NAN_ATTRIBUTE_RX_MATCH_FILTER
)
2978 C2S(NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN
)
2979 C2S(NAN_ATTRIBUTE_TX_MATCH_FILTER
)
2980 C2S(NAN_ATTRIBUTE_SUBSCRIBE_ID
)
2981 C2S(NAN_ATTRIBUTE_SUBSCRIBE_TYPE
)
2982 C2S(NAN_ATTRIBUTE_SERVICERESPONSEFILTER
)
2983 C2S(NAN_ATTRIBUTE_SERVICERESPONSEINCLUDE
)
2984 C2S(NAN_ATTRIBUTE_USESERVICERESPONSEFILTER
)
2985 C2S(NAN_ATTRIBUTE_SSIREQUIREDFORMATCHINDICATION
)
2986 C2S(NAN_ATTRIBUTE_SUBSCRIBE_MATCH
)
2987 C2S(NAN_ATTRIBUTE_SUBSCRIBE_COUNT
)
2988 C2S(NAN_ATTRIBUTE_MAC_ADDR
)
2989 C2S(NAN_ATTRIBUTE_MAC_ADDR_LIST
)
2990 C2S(NAN_ATTRIBUTE_MAC_ADDR_LIST_NUM_ENTRIES
)
2991 C2S(NAN_ATTRIBUTE_PUBLISH_MATCH
)
2992 C2S(NAN_ATTRIBUTE_ENABLE_STATUS
)
2993 C2S(NAN_ATTRIBUTE_JOIN_STATUS
)
2994 C2S(NAN_ATTRIBUTE_ROLE
)
2995 C2S(NAN_ATTRIBUTE_MASTER_RANK
)
2996 C2S(NAN_ATTRIBUTE_ANCHOR_MASTER_RANK
)
2997 C2S(NAN_ATTRIBUTE_CNT_PEND_TXFRM
)
2998 C2S(NAN_ATTRIBUTE_CNT_BCN_TX
)
2999 C2S(NAN_ATTRIBUTE_CNT_BCN_RX
)
3000 C2S(NAN_ATTRIBUTE_CNT_SVC_DISC_TX
)
3001 C2S(NAN_ATTRIBUTE_CNT_SVC_DISC_RX
)
3002 C2S(NAN_ATTRIBUTE_AMBTT
)
3003 C2S(NAN_ATTRIBUTE_CLUSTER_ID
)
3004 C2S(NAN_ATTRIBUTE_INST_ID
)
3005 C2S(NAN_ATTRIBUTE_OUI
)
3006 C2S(NAN_ATTRIBUTE_STATUS
)
3007 C2S(NAN_ATTRIBUTE_DE_EVENT_TYPE
)
3008 C2S(NAN_ATTRIBUTE_MERGE
)
3009 C2S(NAN_ATTRIBUTE_IFACE
)
3010 C2S(NAN_ATTRIBUTE_CHANNEL
)
3011 C2S(NAN_ATTRIBUTE_24G_CHANNEL
)
3012 C2S(NAN_ATTRIBUTE_5G_CHANNEL
)
3013 C2S(NAN_ATTRIBUTE_PEER_ID
)
3014 C2S(NAN_ATTRIBUTE_NDP_ID
)
3015 C2S(NAN_ATTRIBUTE_SECURITY
)
3016 C2S(NAN_ATTRIBUTE_QOS
)
3017 C2S(NAN_ATTRIBUTE_RSP_CODE
)
3018 C2S(NAN_ATTRIBUTE_INST_COUNT
)
3019 C2S(NAN_ATTRIBUTE_PEER_DISC_MAC_ADDR
)
3020 C2S(NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR
)
3021 C2S(NAN_ATTRIBUTE_IF_ADDR
)
3022 C2S(NAN_ATTRIBUTE_WARMUP_TIME
)
3023 C2S(NAN_ATTRIBUTE_RECV_IND_CFG
)
3024 C2S(NAN_ATTRIBUTE_CONNMAP
)
3025 C2S(NAN_ATTRIBUTE_DWELL_TIME
)
3026 C2S(NAN_ATTRIBUTE_SCAN_PERIOD
)
3027 C2S(NAN_ATTRIBUTE_RSSI_WINDOW_SIZE
)
3028 C2S(NAN_ATTRIBUTE_CONF_CLUSTER_VAL
)
3029 C2S(NAN_ATTRIBUTE_CIPHER_SUITE_TYPE
)
3030 C2S(NAN_ATTRIBUTE_KEY_TYPE
)
3031 C2S(NAN_ATTRIBUTE_KEY_LEN
)
3032 C2S(NAN_ATTRIBUTE_SCID
)
3033 C2S(NAN_ATTRIBUTE_SCID_LEN
)
3034 C2S(NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP
)
3035 C2S(NAN_ATTRIBUTE_SDE_CONTROL_SECURITY
)
3036 C2S(NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE
)
3037 C2S(NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT
)
3038 C2S(NAN_ATTRIBUTE_NO_CONFIG_AVAIL
)
3039 C2S(NAN_ATTRIBUTE_2G_AWAKE_DW
)
3040 C2S(NAN_ATTRIBUTE_5G_AWAKE_DW
)
3041 C2S(NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG
)
3042 C2S(NAN_ATTRIBUTE_KEY_DATA
)
3043 C2S(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN
)
3044 C2S(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO
)
3045 C2S(NAN_ATTRIBUTE_REASON
)
3046 C2S(NAN_ATTRIBUTE_DISC_IND_CFG
)
3047 C2S(NAN_ATTRIBUTE_DWELL_TIME_5G
)
3048 C2S(NAN_ATTRIBUTE_SCAN_PERIOD_5G
)
3049 C2S(NAN_ATTRIBUTE_SUB_SID_BEACON
)
3051 return "NAN_ATTRIBUTE_UNKNOWN";
3055 nan_hal_status_t nan_status_reasonstr_map
[] = {
3056 {NAN_STATUS_SUCCESS
, "NAN status success"},
3057 {NAN_STATUS_INTERNAL_FAILURE
, "NAN Discovery engine failure"},
3058 {NAN_STATUS_PROTOCOL_FAILURE
, "protocol failure"},
3059 {NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID
, "invalid pub_sub ID"},
3060 {NAN_STATUS_NO_RESOURCE_AVAILABLE
, "No space available"},
3061 {NAN_STATUS_INVALID_PARAM
, "invalid param"},
3062 {NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID
, "invalid req inst id"},
3063 {NAN_STATUS_INVALID_NDP_ID
, "invalid ndp id"},
3064 {NAN_STATUS_NAN_NOT_ALLOWED
, "Nan not allowed"},
3065 {NAN_STATUS_NO_OTA_ACK
, "No OTA ack"},
3066 {NAN_STATUS_ALREADY_ENABLED
, "NAN is Already enabled"},
3067 {NAN_STATUS_FOLLOWUP_QUEUE_FULL
, "Follow-up queue full"},
3068 {NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED
, "unsupported concurrency"},
3072 wl_cfgvendor_add_nan_reason_str(nan_status_type_t status
, nan_hal_resp_t
*nan_req_resp
)
3075 int num
= (int)(sizeof(nan_status_reasonstr_map
)/sizeof(nan_status_reasonstr_map
[0]));
3076 for (i
= 0; i
< num
; i
++) {
3077 if (nan_status_reasonstr_map
[i
].status
== status
) {
3078 strlcpy(nan_req_resp
->nan_reason
, nan_status_reasonstr_map
[i
].nan_reason
,
3079 sizeof(nan_status_reasonstr_map
[i
].nan_reason
));
3086 wl_cfgvendor_brcm_to_nanhal_status(int32 vendor_status
)
3088 nan_status_type_t hal_status
;
3089 switch (vendor_status
) {
3091 hal_status
= NAN_STATUS_SUCCESS
;
3095 hal_status
= NAN_STATUS_NAN_NOT_ALLOWED
;
3099 case BCME_UNSUPPORTED
:
3100 case BCME_USAGE_ERROR
:
3102 hal_status
= NAN_STATUS_INVALID_PARAM
;
3105 case BCME_NORESOURCE
:
3106 case WL_NAN_E_SVC_SUB_LIST_FULL
:
3107 hal_status
= NAN_STATUS_NO_RESOURCE_AVAILABLE
;
3109 case WL_NAN_E_SD_TX_LIST_FULL
:
3110 hal_status
= NAN_STATUS_FOLLOWUP_QUEUE_FULL
;
3112 case WL_NAN_E_BAD_INSTANCE
:
3113 hal_status
= NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID
;
3116 WL_ERR(("%s Unknown vendor status, status = %d\n",
3117 __func__
, vendor_status
));
3119 hal_status
= NAN_STATUS_INTERNAL_FAILURE
;
3125 wl_cfgvendor_nan_cmd_reply(struct wiphy
*wiphy
, int nan_cmd
,
3126 nan_hal_resp_t
*nan_req_resp
, int ret
, int nan_cmd_status
)
3130 nan_req_resp
->subcmd
= nan_cmd
;
3131 if (ret
== BCME_OK
) {
3132 nan_reply
= nan_cmd_status
;
3136 nan_req_resp
->status
= wl_cfgvendor_brcm_to_nanhal_status(nan_reply
);
3137 nan_req_resp
->value
= ret
;
3138 err
= wl_cfgvendor_send_cmd_reply(wiphy
, nan_req_resp
,
3139 sizeof(*nan_req_resp
));
3140 /* giving more prio to ret than err */
3141 return (ret
== 0) ? err
: ret
;
3145 wl_cfgvendor_free_disc_cmd_data(struct bcm_cfg80211
*cfg
,
3146 nan_discover_cmd_data_t
*cmd_data
)
3149 WL_ERR(("Cmd_data is null\n"));
3152 if (cmd_data
->svc_info
.data
) {
3153 MFREE(cfg
->osh
, cmd_data
->svc_info
.data
, cmd_data
->svc_info
.dlen
);
3155 if (cmd_data
->svc_hash
.data
) {
3156 MFREE(cfg
->osh
, cmd_data
->svc_hash
.data
, cmd_data
->svc_hash
.dlen
);
3158 if (cmd_data
->rx_match
.data
) {
3159 MFREE(cfg
->osh
, cmd_data
->rx_match
.data
, cmd_data
->rx_match
.dlen
);
3161 if (cmd_data
->tx_match
.data
) {
3162 MFREE(cfg
->osh
, cmd_data
->tx_match
.data
, cmd_data
->tx_match
.dlen
);
3164 if (cmd_data
->mac_list
.list
) {
3165 MFREE(cfg
->osh
, cmd_data
->mac_list
.list
,
3166 cmd_data
->mac_list
.num_mac_addr
* ETHER_ADDR_LEN
);
3168 if (cmd_data
->key
.data
) {
3169 MFREE(cfg
->osh
, cmd_data
->key
.data
, NAN_MAX_PMK_LEN
);
3171 if (cmd_data
->sde_svc_info
.data
) {
3172 MFREE(cfg
->osh
, cmd_data
->sde_svc_info
.data
, cmd_data
->sde_svc_info
.dlen
);
3174 MFREE(cfg
->osh
, cmd_data
, sizeof(*cmd_data
));
3178 wl_cfgvendor_free_dp_cmd_data(struct bcm_cfg80211
*cfg
,
3179 nan_datapath_cmd_data_t
*cmd_data
)
3182 WL_ERR(("Cmd_data is null\n"));
3185 if (cmd_data
->svc_hash
.data
) {
3186 MFREE(cfg
->osh
, cmd_data
->svc_hash
.data
, cmd_data
->svc_hash
.dlen
);
3188 if (cmd_data
->svc_info
.data
) {
3189 MFREE(cfg
->osh
, cmd_data
->svc_info
.data
, cmd_data
->svc_info
.dlen
);
3191 if (cmd_data
->key
.data
) {
3192 MFREE(cfg
->osh
, cmd_data
->key
.data
, NAN_MAX_PMK_LEN
);
3194 MFREE(cfg
->osh
, cmd_data
, sizeof(*cmd_data
));
3197 #define WL_NAN_EVENT_MAX_BUF 256
3198 #ifdef WL_NAN_DISC_CACHE
3200 wl_cfgvendor_nan_parse_dp_sec_info_args(struct wiphy
*wiphy
,
3201 const void *buf
, int len
, nan_datapath_sec_info_cmd_data_t
*cmd_data
)
3206 const struct nlattr
*iter
;
3210 nla_for_each_attr(iter
, buf
, len
, rem
) {
3211 attr_type
= nla_type(iter
);
3212 WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type
), attr_type
));
3214 switch (attr_type
) {
3215 case NAN_ATTRIBUTE_MAC_ADDR
:
3216 ret
= memcpy_s((char*)&cmd_data
->mac_addr
, ETHER_ADDR_LEN
,
3217 (char*)nla_data(iter
), nla_len(iter
));
3218 if (ret
!= BCME_OK
) {
3219 WL_ERR(("Failed to copy mac addr\n"));
3223 case NAN_ATTRIBUTE_PUBLISH_ID
:
3224 cmd_data
->pub_id
= nla_get_u16(iter
);
3226 case NAN_ATTRIBUTE_NDP_ID
:
3227 cmd_data
->ndp_instance_id
= nla_get_u32(iter
);
3230 WL_ERR(("%s: Unknown type, %d\n", __FUNCTION__
, attr_type
));
3235 /* We need to call set_config_handler b/f calling start enable TBD */
3239 #endif /* WL_NAN_DISC_CACHE */
3241 int8 chanbuf
[CHANSPEC_STR_LEN
];
3243 wl_cfgvendor_nan_parse_datapath_args(struct wiphy
*wiphy
,
3244 const void *buf
, int len
, nan_datapath_cmd_data_t
*cmd_data
)
3249 const struct nlattr
*iter
;
3250 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3255 nla_for_each_attr(iter
, buf
, len
, rem
) {
3256 attr_type
= nla_type(iter
);
3257 WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type
), attr_type
));
3259 switch (attr_type
) {
3260 case NAN_ATTRIBUTE_NDP_ID
:
3261 if (nla_len(iter
) != sizeof(uint32
)) {
3265 cmd_data
->ndp_instance_id
= nla_get_u32(iter
);
3267 case NAN_ATTRIBUTE_IFACE
:
3268 if (nla_len(iter
) >= sizeof(cmd_data
->ndp_iface
)) {
3269 WL_ERR(("iface_name len wrong:%d\n", nla_len(iter
)));
3273 strlcpy((char *)cmd_data
->ndp_iface
, (char *)nla_data(iter
),
3276 case NAN_ATTRIBUTE_SECURITY
:
3277 if (nla_len(iter
) != sizeof(uint8
)) {
3281 cmd_data
->ndp_cfg
.security_cfg
= nla_get_u8(iter
);
3283 case NAN_ATTRIBUTE_QOS
:
3284 if (nla_len(iter
) != sizeof(uint8
)) {
3288 cmd_data
->ndp_cfg
.qos_cfg
= nla_get_u8(iter
);
3290 case NAN_ATTRIBUTE_RSP_CODE
:
3291 if (nla_len(iter
) != sizeof(uint8
)) {
3295 cmd_data
->rsp_code
= nla_get_u8(iter
);
3297 case NAN_ATTRIBUTE_INST_COUNT
:
3298 if (nla_len(iter
) != sizeof(uint8
)) {
3302 cmd_data
->num_ndp_instances
= nla_get_u8(iter
);
3304 case NAN_ATTRIBUTE_PEER_DISC_MAC_ADDR
:
3305 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
3309 ret
= memcpy_s((char*)&cmd_data
->peer_disc_mac_addr
,
3310 ETHER_ADDR_LEN
, (char*)nla_data(iter
), nla_len(iter
));
3311 if (ret
!= BCME_OK
) {
3312 WL_ERR(("Failed to copy peer_disc_mac_addr\n"));
3316 case NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR
:
3317 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
3321 ret
= memcpy_s((char*)&cmd_data
->peer_ndi_mac_addr
,
3322 ETHER_ADDR_LEN
, (char*)nla_data(iter
), nla_len(iter
));
3323 if (ret
!= BCME_OK
) {
3324 WL_ERR(("Failed to copy peer_ndi_mac_addr\n"));
3328 case NAN_ATTRIBUTE_MAC_ADDR
:
3329 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
3333 ret
= memcpy_s((char*)&cmd_data
->mac_addr
, ETHER_ADDR_LEN
,
3334 (char*)nla_data(iter
), nla_len(iter
));
3335 if (ret
!= BCME_OK
) {
3336 WL_ERR(("Failed to copy mac_addr\n"));
3340 case NAN_ATTRIBUTE_IF_ADDR
:
3341 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
3345 ret
= memcpy_s((char*)&cmd_data
->if_addr
, ETHER_ADDR_LEN
,
3346 (char*)nla_data(iter
), nla_len(iter
));
3347 if (ret
!= BCME_OK
) {
3348 WL_ERR(("Failed to copy if_addr\n"));
3352 case NAN_ATTRIBUTE_ENTRY_CONTROL
:
3353 if (nla_len(iter
) != sizeof(uint8
)) {
3357 cmd_data
->avail_params
.duration
= nla_get_u8(iter
);
3359 case NAN_ATTRIBUTE_AVAIL_BIT_MAP
:
3360 if (nla_len(iter
) != sizeof(uint32
)) {
3364 cmd_data
->avail_params
.bmap
= nla_get_u32(iter
);
3366 case NAN_ATTRIBUTE_CHANNEL
: {
3367 if (nla_len(iter
) != sizeof(uint32
)) {
3371 /* take the default channel start_factor frequency */
3372 chan
= wf_mhz2channel((uint
)nla_get_u32(iter
), 0);
3373 if (chan
<= CH_MAX_2G_CHANNEL
) {
3374 cmd_data
->avail_params
.chanspec
[0] =
3375 wf_channel2chspec(chan
, WL_CHANSPEC_BW_20
);
3377 cmd_data
->avail_params
.chanspec
[0] =
3378 wf_channel2chspec(chan
, WL_CHANSPEC_BW_80
);
3380 if (cmd_data
->avail_params
.chanspec
[0] == 0) {
3381 WL_ERR(("Channel is not valid \n"));
3385 WL_TRACE(("valid chanspec, chanspec = 0x%04x \n",
3386 cmd_data
->avail_params
.chanspec
[0]));
3389 case NAN_ATTRIBUTE_NO_CONFIG_AVAIL
:
3390 if (nla_len(iter
) != sizeof(uint8
)) {
3394 cmd_data
->avail_params
.no_config_avail
= (bool)nla_get_u8(iter
);
3396 case NAN_ATTRIBUTE_SERVICE_NAME_LEN
: {
3397 if (nla_len(iter
) != sizeof(uint16
)) {
3401 if (cmd_data
->svc_hash
.dlen
) {
3402 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3406 cmd_data
->svc_hash
.dlen
= nla_get_u16(iter
);
3407 if (cmd_data
->svc_hash
.dlen
!= WL_NAN_SVC_HASH_LEN
) {
3408 WL_ERR(("invalid svc_hash length = %u\n", cmd_data
->svc_hash
.dlen
));
3414 case NAN_ATTRIBUTE_SERVICE_NAME
:
3415 if ((!cmd_data
->svc_hash
.dlen
) ||
3416 (nla_len(iter
) != cmd_data
->svc_hash
.dlen
)) {
3417 WL_ERR(("invalid svc_hash length = %d,%d\n",
3418 cmd_data
->svc_hash
.dlen
, nla_len(iter
)));
3422 if (cmd_data
->svc_hash
.data
) {
3423 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3427 cmd_data
->svc_hash
.data
=
3428 MALLOCZ(cfg
->osh
, cmd_data
->svc_hash
.dlen
);
3429 if (!cmd_data
->svc_hash
.data
) {
3430 WL_ERR(("failed to allocate svc_hash data, len=%d\n",
3431 cmd_data
->svc_hash
.dlen
));
3435 ret
= memcpy_s(cmd_data
->svc_hash
.data
, cmd_data
->svc_hash
.dlen
,
3436 nla_data(iter
), nla_len(iter
));
3437 if (ret
!= BCME_OK
) {
3438 WL_ERR(("Failed to copy svc hash data\n"));
3442 case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
:
3443 if (nla_len(iter
) != sizeof(uint16
)) {
3447 if (cmd_data
->svc_info
.dlen
) {
3448 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3452 cmd_data
->svc_info
.dlen
= nla_get_u16(iter
);
3453 if (cmd_data
->svc_info
.dlen
> MAX_APP_INFO_LEN
) {
3454 WL_ERR_RLMT(("Not allowed beyond :%d\n", MAX_APP_INFO_LEN
));
3459 case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
:
3460 if ((!cmd_data
->svc_info
.dlen
) ||
3461 (nla_len(iter
) != cmd_data
->svc_info
.dlen
)) {
3462 WL_ERR(("failed to allocate svc info by invalid len=%d,%d\n",
3463 cmd_data
->svc_info
.dlen
, nla_len(iter
)));
3467 if (cmd_data
->svc_info
.data
) {
3468 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3472 cmd_data
->svc_info
.data
= MALLOCZ(cfg
->osh
, cmd_data
->svc_info
.dlen
);
3473 if (cmd_data
->svc_info
.data
== NULL
) {
3474 WL_ERR(("failed to allocate svc info data, len=%d\n",
3475 cmd_data
->svc_info
.dlen
));
3479 ret
= memcpy_s(cmd_data
->svc_info
.data
, cmd_data
->svc_info
.dlen
,
3480 nla_data(iter
), nla_len(iter
));
3481 if (ret
!= BCME_OK
) {
3482 WL_ERR(("Failed to copy svc info\n"));
3486 case NAN_ATTRIBUTE_PUBLISH_ID
:
3487 if (nla_len(iter
) != sizeof(uint32
)) {
3491 cmd_data
->pub_id
= nla_get_u32(iter
);
3493 case NAN_ATTRIBUTE_CIPHER_SUITE_TYPE
:
3494 if (nla_len(iter
) != sizeof(uint8
)) {
3498 cmd_data
->csid
= nla_get_u8(iter
);
3499 WL_TRACE(("CSID = %u\n", cmd_data
->csid
));
3501 case NAN_ATTRIBUTE_KEY_TYPE
:
3502 if (nla_len(iter
) != sizeof(uint8
)) {
3506 cmd_data
->key_type
= nla_get_u8(iter
);
3507 WL_TRACE(("Key Type = %u\n", cmd_data
->key_type
));
3509 case NAN_ATTRIBUTE_KEY_LEN
:
3510 if (nla_len(iter
) != sizeof(uint32
)) {
3514 if (cmd_data
->key
.dlen
) {
3515 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3519 cmd_data
->key
.dlen
= nla_get_u32(iter
);
3520 if ((!cmd_data
->key
.dlen
) || (cmd_data
->key
.dlen
> WL_NAN_NCS_SK_PMK_LEN
)) {
3521 WL_ERR(("invalid key length = %u\n", cmd_data
->key
.dlen
));
3525 WL_TRACE(("valid key length = %u\n", cmd_data
->key
.dlen
));
3527 case NAN_ATTRIBUTE_KEY_DATA
:
3528 if ((!cmd_data
->key
.dlen
) ||
3529 (nla_len(iter
) != cmd_data
->key
.dlen
)) {
3530 WL_ERR(("failed to allocate key data by invalid len=%d,%d\n",
3531 cmd_data
->key
.dlen
, nla_len(iter
)));
3535 if (cmd_data
->key
.data
) {
3536 WL_ERR(("trying to overwrite key data.\n"));
3541 cmd_data
->key
.data
= MALLOCZ(cfg
->osh
, NAN_MAX_PMK_LEN
);
3542 if (cmd_data
->key
.data
== NULL
) {
3543 WL_ERR(("failed to allocate key data, len=%d\n",
3544 cmd_data
->key
.dlen
));
3548 ret
= memcpy_s(cmd_data
->key
.data
, NAN_MAX_PMK_LEN
,
3549 nla_data(iter
), nla_len(iter
));
3550 if (ret
!= BCME_OK
) {
3551 WL_ERR(("Failed to key data\n"));
3557 WL_ERR(("Unknown type, %d\n", attr_type
));
3563 /* We need to call set_config_handler b/f calling start enable TBD */
3569 wl_cfgvendor_nan_parse_discover_args(struct wiphy
*wiphy
,
3570 const void *buf
, int len
, nan_discover_cmd_data_t
*cmd_data
)
3575 const struct nlattr
*iter
;
3576 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3583 nla_for_each_attr(iter
, buf
, len
, rem
) {
3584 attr_type
= nla_type(iter
);
3585 WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type
), attr_type
));
3587 switch (attr_type
) {
3588 case NAN_ATTRIBUTE_TRANSAC_ID
:
3589 if (nla_len(iter
) != sizeof(uint16
)) {
3593 cmd_data
->token
= nla_get_u16(iter
);
3595 case NAN_ATTRIBUTE_PERIODIC_SCAN_INTERVAL
:
3598 /* Nan Publish/Subscribe request Attributes */
3599 case NAN_ATTRIBUTE_PUBLISH_ID
:
3600 if (nla_len(iter
) != sizeof(uint16
)) {
3604 cmd_data
->pub_id
= nla_get_u16(iter
);
3605 cmd_data
->local_id
= cmd_data
->pub_id
;
3607 case NAN_ATTRIBUTE_MAC_ADDR
:
3608 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
3612 ret
= memcpy_s((char*)&cmd_data
->mac_addr
, ETHER_ADDR_LEN
,
3613 (char*)nla_data(iter
), nla_len(iter
));
3614 if (ret
!= BCME_OK
) {
3615 WL_ERR(("Failed to copy mac addr\n"));
3619 case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
:
3620 if (nla_len(iter
) != sizeof(uint16
)) {
3624 if (cmd_data
->svc_info
.dlen
) {
3625 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3629 cmd_data
->svc_info
.dlen
= nla_get_u16(iter
);
3630 if (cmd_data
->svc_info
.dlen
> NAN_MAX_SERVICE_SPECIFIC_INFO_LEN
) {
3631 WL_ERR_RLMT(("Not allowed beyond :%d\n",
3632 NAN_MAX_SERVICE_SPECIFIC_INFO_LEN
));
3637 case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
:
3638 if ((!cmd_data
->svc_info
.dlen
) ||
3639 (nla_len(iter
) != cmd_data
->svc_info
.dlen
)) {
3640 WL_ERR(("failed to allocate svc info by invalid len=%d,%d\n",
3641 cmd_data
->svc_info
.dlen
, nla_len(iter
)));
3645 if (cmd_data
->svc_info
.data
) {
3646 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3651 cmd_data
->svc_info
.data
= MALLOCZ(cfg
->osh
, cmd_data
->svc_info
.dlen
);
3652 if (cmd_data
->svc_info
.data
== NULL
) {
3653 WL_ERR(("failed to allocate svc info data, len=%d\n",
3654 cmd_data
->svc_info
.dlen
));
3658 ret
= memcpy_s(cmd_data
->svc_info
.data
, cmd_data
->svc_info
.dlen
,
3659 nla_data(iter
), nla_len(iter
));
3660 if (ret
!= BCME_OK
) {
3661 WL_ERR(("Failed to copy svc info\n"));
3665 case NAN_ATTRIBUTE_SUBSCRIBE_ID
:
3666 if (nla_len(iter
) != sizeof(uint16
)) {
3670 cmd_data
->sub_id
= nla_get_u16(iter
);
3671 cmd_data
->local_id
= cmd_data
->sub_id
;
3673 case NAN_ATTRIBUTE_SUBSCRIBE_TYPE
:
3674 if (nla_len(iter
) != sizeof(uint8
)) {
3678 cmd_data
->flags
|= nla_get_u8(iter
) ? WL_NAN_SUB_ACTIVE
: 0;
3680 case NAN_ATTRIBUTE_PUBLISH_COUNT
:
3681 if (nla_len(iter
) != sizeof(uint8
)) {
3685 cmd_data
->life_count
= nla_get_u8(iter
);
3687 case NAN_ATTRIBUTE_PUBLISH_TYPE
: {
3688 if (nla_len(iter
) != sizeof(uint8
)) {
3692 val_u8
= nla_get_u8(iter
);
3694 cmd_data
->flags
|= WL_NAN_PUB_UNSOLICIT
;
3695 } else if (val_u8
== 1) {
3696 cmd_data
->flags
|= WL_NAN_PUB_SOLICIT
;
3698 cmd_data
->flags
|= WL_NAN_PUB_BOTH
;
3702 case NAN_ATTRIBUTE_PERIOD
: {
3703 if (nla_len(iter
) != sizeof(uint16
)) {
3707 if (nla_get_u16(iter
) > NAN_MAX_AWAKE_DW_INTERVAL
) {
3708 WL_ERR(("Invalid/Out of bound value = %u\n", nla_get_u16(iter
)));
3712 if (nla_get_u16(iter
)) {
3713 cmd_data
->period
= 1 << (nla_get_u16(iter
)-1);
3717 case NAN_ATTRIBUTE_REPLIED_EVENT_FLAG
:
3719 case NAN_ATTRIBUTE_TTL
:
3720 if (nla_len(iter
) != sizeof(uint16
)) {
3724 cmd_data
->ttl
= nla_get_u16(iter
);
3726 case NAN_ATTRIBUTE_SERVICE_NAME_LEN
: {
3727 if (nla_len(iter
) != sizeof(uint16
)) {
3731 if (cmd_data
->svc_hash
.dlen
) {
3732 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3737 cmd_data
->svc_hash
.dlen
= nla_get_u16(iter
);
3738 if (cmd_data
->svc_hash
.dlen
!= WL_NAN_SVC_HASH_LEN
) {
3739 WL_ERR(("invalid svc_hash length = %u\n", cmd_data
->svc_hash
.dlen
));
3745 case NAN_ATTRIBUTE_SERVICE_NAME
:
3746 if ((!cmd_data
->svc_hash
.dlen
) ||
3747 (nla_len(iter
) != cmd_data
->svc_hash
.dlen
)) {
3748 WL_ERR(("invalid svc_hash length = %d,%d\n",
3749 cmd_data
->svc_hash
.dlen
, nla_len(iter
)));
3753 if (cmd_data
->svc_hash
.data
) {
3754 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3759 cmd_data
->svc_hash
.data
=
3760 MALLOCZ(cfg
->osh
, cmd_data
->svc_hash
.dlen
);
3761 if (!cmd_data
->svc_hash
.data
) {
3762 WL_ERR(("failed to allocate svc_hash data, len=%d\n",
3763 cmd_data
->svc_hash
.dlen
));
3767 ret
= memcpy_s(cmd_data
->svc_hash
.data
, cmd_data
->svc_hash
.dlen
,
3768 nla_data(iter
), nla_len(iter
));
3769 if (ret
!= BCME_OK
) {
3770 WL_ERR(("Failed to copy svc hash data\n"));
3774 case NAN_ATTRIBUTE_PEER_ID
:
3775 if (nla_len(iter
) != sizeof(uint32
)) {
3779 cmd_data
->remote_id
= nla_get_u32(iter
);
3781 case NAN_ATTRIBUTE_INST_ID
:
3782 if (nla_len(iter
) != sizeof(uint16
)) {
3786 cmd_data
->local_id
= nla_get_u16(iter
);
3788 case NAN_ATTRIBUTE_SUBSCRIBE_COUNT
:
3789 if (nla_len(iter
) != sizeof(uint8
)) {
3793 cmd_data
->life_count
= nla_get_u8(iter
);
3795 case NAN_ATTRIBUTE_SSIREQUIREDFORMATCHINDICATION
: {
3796 if (nla_len(iter
) != sizeof(uint8
)) {
3800 bit_flag
= (u32
)nla_get_u8(iter
);
3802 bit_flag
? WL_NAN_SUB_MATCH_IF_SVC_INFO
: 0;
3805 case NAN_ATTRIBUTE_SUBSCRIBE_MATCH
:
3806 case NAN_ATTRIBUTE_PUBLISH_MATCH
: {
3807 if (nla_len(iter
) != sizeof(uint8
)) {
3811 flag_match
= nla_get_u8(iter
);
3813 switch (flag_match
) {
3814 case NAN_MATCH_ALG_MATCH_CONTINUOUS
:
3815 /* Default fw behaviour, no need to set explicitly */
3817 case NAN_MATCH_ALG_MATCH_ONCE
:
3818 cmd_data
->flags
|= WL_NAN_MATCH_ONCE
;
3820 case NAN_MATCH_ALG_MATCH_NEVER
:
3821 cmd_data
->flags
|= WL_NAN_MATCH_NEVER
;
3824 WL_ERR(("invalid nan match alg = %u\n", flag_match
));
3830 case NAN_ATTRIBUTE_SERVICERESPONSEFILTER
:
3831 if (nla_len(iter
) != sizeof(uint8
)) {
3835 cmd_data
->srf_type
= nla_get_u8(iter
);
3837 case NAN_ATTRIBUTE_SERVICERESPONSEINCLUDE
:
3838 if (nla_len(iter
) != sizeof(uint8
)) {
3842 cmd_data
->srf_include
= nla_get_u8(iter
);
3844 case NAN_ATTRIBUTE_USESERVICERESPONSEFILTER
:
3845 if (nla_len(iter
) != sizeof(uint8
)) {
3849 cmd_data
->use_srf
= nla_get_u8(iter
);
3851 case NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN
:
3852 if (nla_len(iter
) != sizeof(uint16
)) {
3856 if (cmd_data
->rx_match
.dlen
) {
3857 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3861 cmd_data
->rx_match
.dlen
= nla_get_u16(iter
);
3862 if (cmd_data
->rx_match
.dlen
> MAX_MATCH_FILTER_LEN
) {
3864 WL_ERR_RLMT(("Not allowed beyond %d\n", MAX_MATCH_FILTER_LEN
));
3868 case NAN_ATTRIBUTE_RX_MATCH_FILTER
:
3869 if ((!cmd_data
->rx_match
.dlen
) ||
3870 (nla_len(iter
) != cmd_data
->rx_match
.dlen
)) {
3871 WL_ERR(("RX match filter len wrong:%d,%d\n",
3872 cmd_data
->rx_match
.dlen
, nla_len(iter
)));
3876 if (cmd_data
->rx_match
.data
) {
3877 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3881 cmd_data
->rx_match
.data
=
3882 MALLOCZ(cfg
->osh
, cmd_data
->rx_match
.dlen
);
3883 if (cmd_data
->rx_match
.data
== NULL
) {
3884 WL_ERR(("failed to allocate LEN=[%u]\n",
3885 cmd_data
->rx_match
.dlen
));
3889 ret
= memcpy_s(cmd_data
->rx_match
.data
, cmd_data
->rx_match
.dlen
,
3890 nla_data(iter
), nla_len(iter
));
3891 if (ret
!= BCME_OK
) {
3892 WL_ERR(("Failed to copy rx match data\n"));
3896 case NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN
:
3897 if (nla_len(iter
) != sizeof(uint16
)) {
3901 if (cmd_data
->tx_match
.dlen
) {
3902 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3906 cmd_data
->tx_match
.dlen
= nla_get_u16(iter
);
3907 if (cmd_data
->tx_match
.dlen
> MAX_MATCH_FILTER_LEN
) {
3909 WL_ERR_RLMT(("Not allowed beyond %d\n", MAX_MATCH_FILTER_LEN
));
3913 case NAN_ATTRIBUTE_TX_MATCH_FILTER
:
3914 if ((!cmd_data
->tx_match
.dlen
) ||
3915 (nla_len(iter
) != cmd_data
->tx_match
.dlen
)) {
3916 WL_ERR(("TX match filter len wrong:%d,%d\n",
3917 cmd_data
->tx_match
.dlen
, nla_len(iter
)));
3921 if (cmd_data
->tx_match
.data
) {
3922 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3926 cmd_data
->tx_match
.data
=
3927 MALLOCZ(cfg
->osh
, cmd_data
->tx_match
.dlen
);
3928 if (cmd_data
->tx_match
.data
== NULL
) {
3929 WL_ERR(("failed to allocate LEN=[%u]\n",
3930 cmd_data
->tx_match
.dlen
));
3934 ret
= memcpy_s(cmd_data
->tx_match
.data
, cmd_data
->tx_match
.dlen
,
3935 nla_data(iter
), nla_len(iter
));
3936 if (ret
!= BCME_OK
) {
3937 WL_ERR(("Failed to copy tx match data\n"));
3941 case NAN_ATTRIBUTE_MAC_ADDR_LIST_NUM_ENTRIES
:
3942 if (nla_len(iter
) != sizeof(uint16
)) {
3946 if (cmd_data
->mac_list
.num_mac_addr
) {
3947 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3951 cmd_data
->mac_list
.num_mac_addr
= nla_get_u16(iter
);
3953 case NAN_ATTRIBUTE_MAC_ADDR_LIST
:
3954 if ((!cmd_data
->mac_list
.num_mac_addr
) ||
3955 (nla_len(iter
) != (cmd_data
->mac_list
.num_mac_addr
* ETHER_ADDR_LEN
))) {
3956 WL_ERR(("wrong mac list len:%d,%d\n",
3957 cmd_data
->mac_list
.num_mac_addr
, nla_len(iter
)));
3961 if (cmd_data
->mac_list
.list
) {
3962 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3966 cmd_data
->mac_list
.list
=
3967 MALLOCZ(cfg
->osh
, (cmd_data
->mac_list
.num_mac_addr
3969 if (cmd_data
->mac_list
.list
== NULL
) {
3970 WL_ERR(("failed to allocate LEN=[%u]\n",
3971 (cmd_data
->mac_list
.num_mac_addr
* ETHER_ADDR_LEN
)));
3975 ret
= memcpy_s(cmd_data
->mac_list
.list
,
3976 (cmd_data
->mac_list
.num_mac_addr
* ETHER_ADDR_LEN
),
3977 nla_data(iter
), nla_len(iter
));
3978 if (ret
!= BCME_OK
) {
3979 WL_ERR(("Failed to copy list of mac addresses\n"));
3983 case NAN_ATTRIBUTE_TX_TYPE
:
3984 if (nla_len(iter
) != sizeof(uint8
)) {
3988 val_u8
= nla_get_u8(iter
);
3990 cmd_data
->flags
|= WL_NAN_PUB_BCAST
;
3991 WL_TRACE(("NAN_ATTRIBUTE_TX_TYPE: flags=NAN_PUB_BCAST\n"));
3994 case NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP
:
3995 if (nla_len(iter
) != sizeof(uint8
)) {
3999 if (nla_get_u8(iter
) == 1) {
4000 cmd_data
->sde_control_flag
4001 |= NAN_SDE_CF_DP_REQUIRED
;
4005 case NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT
:
4006 if (nla_len(iter
) != sizeof(uint8
)) {
4010 cmd_data
->sde_control_config
= TRUE
;
4011 if (nla_get_u8(iter
) == 1) {
4012 cmd_data
->sde_control_flag
4013 |= NAN_SDE_CF_RANGING_REQUIRED
;
4017 case NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE
:
4018 if (nla_len(iter
) != sizeof(uint8
)) {
4022 if (nla_get_u8(iter
) == 1) {
4023 cmd_data
->sde_control_flag
4024 |= NAN_SDE_CF_MULTICAST_TYPE
;
4028 case NAN_ATTRIBUTE_SDE_CONTROL_SECURITY
:
4029 if (nla_len(iter
) != sizeof(uint8
)) {
4033 if (nla_get_u8(iter
) == 1) {
4034 cmd_data
->sde_control_flag
4035 |= NAN_SDE_CF_SECURITY_REQUIRED
;
4039 case NAN_ATTRIBUTE_RECV_IND_CFG
:
4040 if (nla_len(iter
) != sizeof(uint8
)) {
4044 cmd_data
->recv_ind_flag
= nla_get_u8(iter
);
4046 case NAN_ATTRIBUTE_CIPHER_SUITE_TYPE
:
4047 if (nla_len(iter
) != sizeof(uint8
)) {
4051 cmd_data
->csid
= nla_get_u8(iter
);
4052 WL_TRACE(("CSID = %u\n", cmd_data
->csid
));
4054 case NAN_ATTRIBUTE_KEY_TYPE
:
4055 if (nla_len(iter
) != sizeof(uint8
)) {
4059 cmd_data
->key_type
= nla_get_u8(iter
);
4060 WL_TRACE(("Key Type = %u\n", cmd_data
->key_type
));
4062 case NAN_ATTRIBUTE_KEY_LEN
:
4063 if (nla_len(iter
) != sizeof(uint32
)) {
4067 if (cmd_data
->key
.dlen
) {
4068 WL_ERR(("trying to overwrite:%d\n", attr_type
));
4072 cmd_data
->key
.dlen
= nla_get_u32(iter
);
4073 if ((!cmd_data
->key
.dlen
) || (cmd_data
->key
.dlen
> WL_NAN_NCS_SK_PMK_LEN
)) {
4074 WL_ERR(("invalid key length = %u\n",
4075 cmd_data
->key
.dlen
));
4078 WL_TRACE(("valid key length = %u\n", cmd_data
->key
.dlen
));
4080 case NAN_ATTRIBUTE_KEY_DATA
:
4081 if (!cmd_data
->key
.dlen
||
4082 (nla_len(iter
) != cmd_data
->key
.dlen
)) {
4083 WL_ERR(("failed to allocate key data by invalid len=%d,%d\n",
4084 cmd_data
->key
.dlen
, nla_len(iter
)));
4088 if (cmd_data
->key
.data
) {
4089 WL_ERR(("trying to overwrite:%d\n", attr_type
));
4094 cmd_data
->key
.data
= MALLOCZ(cfg
->osh
, NAN_MAX_PMK_LEN
);
4095 if (cmd_data
->key
.data
== NULL
) {
4096 WL_ERR(("failed to allocate key data, len=%d\n",
4097 cmd_data
->key
.dlen
));
4101 ret
= memcpy_s(cmd_data
->key
.data
, NAN_MAX_PMK_LEN
,
4102 nla_data(iter
), nla_len(iter
));
4103 if (ret
!= BCME_OK
) {
4104 WL_ERR(("Failed to key data\n"));
4108 case NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG
:
4109 if (nla_len(iter
) != sizeof(uint8
)) {
4113 if (nla_get_u8(iter
) == 1) {
4115 WL_NAN_RANGE_LIMITED
;
4119 case NAN_ATTRIBUTE_DISC_IND_CFG
:
4120 if (nla_len(iter
) != sizeof(uint8
)) {
4124 cmd_data
->disc_ind_cfg
= nla_get_u8(iter
);
4126 case NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN
:
4127 if (nla_len(iter
) != sizeof(uint16
)) {
4131 if (cmd_data
->sde_svc_info
.dlen
) {
4132 WL_ERR(("trying to overwrite:%d\n", attr_type
));
4136 cmd_data
->sde_svc_info
.dlen
= nla_get_u16(iter
);
4137 if (cmd_data
->sde_svc_info
.dlen
> MAX_SDEA_SVC_INFO_LEN
) {
4139 WL_ERR_RLMT(("Not allowed beyond %d\n", MAX_SDEA_SVC_INFO_LEN
));
4143 case NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO
:
4144 if ((!cmd_data
->sde_svc_info
.dlen
) ||
4145 (nla_len(iter
) != cmd_data
->sde_svc_info
.dlen
)) {
4146 WL_ERR(("wrong sdea info len:%d,%d\n",
4147 cmd_data
->sde_svc_info
.dlen
, nla_len(iter
)));
4151 if (cmd_data
->sde_svc_info
.data
) {
4152 WL_ERR(("trying to overwrite:%d\n", attr_type
));
4156 cmd_data
->sde_svc_info
.data
= MALLOCZ(cfg
->osh
,
4157 cmd_data
->sde_svc_info
.dlen
);
4158 if (cmd_data
->sde_svc_info
.data
== NULL
) {
4159 WL_ERR(("failed to allocate svc info data, len=%d\n",
4160 cmd_data
->sde_svc_info
.dlen
));
4164 ret
= memcpy_s(cmd_data
->sde_svc_info
.data
,
4165 cmd_data
->sde_svc_info
.dlen
,
4166 nla_data(iter
), nla_len(iter
));
4167 if (ret
!= BCME_OK
) {
4168 WL_ERR(("Failed to sdea info data\n"));
4172 case NAN_ATTRIBUTE_SECURITY
:
4173 if (nla_len(iter
) != sizeof(uint8
)) {
4177 cmd_data
->ndp_cfg
.security_cfg
= nla_get_u8(iter
);
4179 case NAN_ATTRIBUTE_RANGING_INTERVAL
:
4180 if (nla_len(iter
) != sizeof(uint32
)) {
4184 cmd_data
->ranging_intvl_msec
= nla_get_u32(iter
);
4186 case NAN_ATTRIBUTE_RANGING_INGRESS_LIMIT
:
4187 if (nla_len(iter
) != sizeof(uint32
)) {
4191 cmd_data
->ingress_limit
= nla_get_u32(iter
);
4193 case NAN_ATTRIBUTE_RANGING_EGRESS_LIMIT
:
4194 if (nla_len(iter
) != sizeof(uint32
)) {
4198 cmd_data
->egress_limit
= nla_get_u32(iter
);
4200 case NAN_ATTRIBUTE_RANGING_INDICATION
:
4201 if (nla_len(iter
) != sizeof(uint32
)) {
4205 cmd_data
->ranging_indication
= nla_get_u32(iter
);
4207 /* Nan accept policy: Per service basis policy
4208 * Based on this policy(ALL/NONE), responder side
4209 * will send ACCEPT/REJECT
4211 case NAN_ATTRIBUTE_SVC_RESPONDER_POLICY
:
4212 if (nla_len(iter
) != sizeof(uint8
)) {
4216 cmd_data
->service_responder_policy
= nla_get_u8(iter
);
4219 WL_ERR(("Unknown type, %d\n", attr_type
));
4225 /* We need to call set_config_handler b/f calling start enable TBD */
4231 wl_cfgvendor_nan_parse_args(struct wiphy
*wiphy
, const void *buf
,
4232 int len
, nan_config_cmd_data_t
*cmd_data
, uint32
*nan_attr_mask
)
4237 const struct nlattr
*iter
;
4238 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4240 u8 sid_beacon
= 0, sub_sid_beacon
= 0;
4244 nla_for_each_attr(iter
, buf
, len
, rem
) {
4245 attr_type
= nla_type(iter
);
4246 WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type
), attr_type
));
4248 switch (attr_type
) {
4249 /* NAN Enable request attributes */
4250 case NAN_ATTRIBUTE_2G_SUPPORT
:{
4251 if (nla_len(iter
) != sizeof(uint8
)) {
4255 cmd_data
->support_2g
= nla_get_u8(iter
);
4256 *nan_attr_mask
|= NAN_ATTR_SUPPORT_2G_CONFIG
;
4259 case NAN_ATTRIBUTE_5G_SUPPORT
:{
4260 if (nla_len(iter
) != sizeof(uint8
)) {
4264 cmd_data
->support_5g
= nla_get_u8(iter
);
4265 *nan_attr_mask
|= NAN_ATTR_SUPPORT_5G_CONFIG
;
4268 case NAN_ATTRIBUTE_CLUSTER_LOW
: {
4269 if (nla_len(iter
) != sizeof(uint16
)) {
4273 cmd_data
->clus_id
.octet
[5] = nla_get_u16(iter
);
4276 case NAN_ATTRIBUTE_CLUSTER_HIGH
: {
4277 if (nla_len(iter
) != sizeof(uint16
)) {
4281 cmd_data
->clus_id
.octet
[4] = nla_get_u16(iter
);
4284 case NAN_ATTRIBUTE_SID_BEACON
: {
4285 if (nla_len(iter
) != sizeof(uint8
)) {
4289 sid_beacon
= nla_get_u8(iter
);
4290 cmd_data
->sid_beacon
.sid_enable
= (sid_beacon
& 0x01);
4291 if (cmd_data
->sid_beacon
.sid_enable
) {
4292 cmd_data
->sid_beacon
.sid_count
= (sid_beacon
>> 1);
4293 *nan_attr_mask
|= NAN_ATTR_SID_BEACON_CONFIG
;
4297 case NAN_ATTRIBUTE_SUB_SID_BEACON
: {
4298 if (nla_len(iter
) != sizeof(uint8
)) {
4302 sub_sid_beacon
= nla_get_u8(iter
);
4303 cmd_data
->sid_beacon
.sub_sid_enable
= (sub_sid_beacon
& 0x01);
4304 if (cmd_data
->sid_beacon
.sub_sid_enable
) {
4305 cmd_data
->sid_beacon
.sub_sid_count
= (sub_sid_beacon
>> 1);
4306 *nan_attr_mask
|= NAN_ATTR_SUB_SID_BEACON_CONFIG
;
4310 case NAN_ATTRIBUTE_SYNC_DISC_2G_BEACON
:
4311 if (nla_len(iter
) != sizeof(uint8
)) {
4315 cmd_data
->beacon_2g_val
= nla_get_u8(iter
);
4316 *nan_attr_mask
|= NAN_ATTR_SYNC_DISC_2G_BEACON_CONFIG
;
4318 case NAN_ATTRIBUTE_SYNC_DISC_5G_BEACON
:
4319 if (nla_len(iter
) != sizeof(uint8
)) {
4323 cmd_data
->beacon_5g_val
= nla_get_u8(iter
);
4324 *nan_attr_mask
|= NAN_ATTR_SYNC_DISC_5G_BEACON_CONFIG
;
4326 case NAN_ATTRIBUTE_SDF_2G_SUPPORT
:
4327 if (nla_len(iter
) != sizeof(uint8
)) {
4331 cmd_data
->sdf_2g_val
= nla_get_u8(iter
);
4332 *nan_attr_mask
|= NAN_ATTR_SDF_2G_SUPPORT_CONFIG
;
4334 case NAN_ATTRIBUTE_SDF_5G_SUPPORT
:
4335 if (nla_len(iter
) != sizeof(uint8
)) {
4339 cmd_data
->sdf_5g_val
= nla_get_u8(iter
);
4340 *nan_attr_mask
|= NAN_ATTR_SDF_5G_SUPPORT_CONFIG
;
4342 case NAN_ATTRIBUTE_HOP_COUNT_LIMIT
:
4343 if (nla_len(iter
) != sizeof(uint8
)) {
4347 cmd_data
->hop_count_limit
= nla_get_u8(iter
);
4348 *nan_attr_mask
|= NAN_ATTR_HOP_COUNT_LIMIT_CONFIG
;
4350 case NAN_ATTRIBUTE_RANDOM_TIME
:
4351 if (nla_len(iter
) != sizeof(uint8
)) {
4355 cmd_data
->metrics
.random_factor
= nla_get_u8(iter
);
4356 *nan_attr_mask
|= NAN_ATTR_RAND_FACTOR_CONFIG
;
4358 case NAN_ATTRIBUTE_MASTER_PREF
:
4359 if (nla_len(iter
) != sizeof(uint8
)) {
4363 cmd_data
->metrics
.master_pref
= nla_get_u8(iter
);
4365 case NAN_ATTRIBUTE_OUI
:
4366 if (nla_len(iter
) != sizeof(uint32
)) {
4370 cmd_data
->nan_oui
= nla_get_u32(iter
);
4371 *nan_attr_mask
|= NAN_ATTR_OUI_CONFIG
;
4372 WL_TRACE(("nan_oui=%d\n", cmd_data
->nan_oui
));
4374 case NAN_ATTRIBUTE_WARMUP_TIME
:
4375 if (nla_len(iter
) != sizeof(uint16
)) {
4379 cmd_data
->warmup_time
= nla_get_u16(iter
);
4381 case NAN_ATTRIBUTE_AMBTT
:
4382 case NAN_ATTRIBUTE_MASTER_RANK
:
4383 WL_DBG(("Unhandled attribute, %d\n", attr_type
));
4385 case NAN_ATTRIBUTE_CHANNEL
: {
4386 if (nla_len(iter
) != sizeof(uint32
)) {
4390 /* take the default channel start_factor frequency */
4391 chan
= wf_mhz2channel((uint
)nla_get_u32(iter
), 0);
4392 if (chan
<= CH_MAX_2G_CHANNEL
) {
4393 cmd_data
->chanspec
[0] = wf_channel2chspec(chan
, WL_CHANSPEC_BW_20
);
4395 cmd_data
->chanspec
[0] = wf_channel2chspec(chan
, WL_CHANSPEC_BW_80
);
4397 if (cmd_data
->chanspec
[0] == 0) {
4398 WL_ERR(("Channel is not valid \n"));
4402 WL_TRACE(("valid chanspec, chanspec = 0x%04x \n",
4403 cmd_data
->chanspec
[0]));
4406 case NAN_ATTRIBUTE_24G_CHANNEL
: {
4407 if (nla_len(iter
) != sizeof(uint32
)) {
4411 /* take the default channel start_factor frequency */
4412 chan
= wf_mhz2channel((uint
)nla_get_u32(iter
), 0);
4414 cmd_data
->chanspec
[1] = wf_channel2chspec(chan
, WL_CHANSPEC_BW_20
);
4415 if (cmd_data
->chanspec
[1] == 0) {
4416 WL_ERR((" 2.4GHz Channel is not valid \n"));
4420 *nan_attr_mask
|= NAN_ATTR_2G_CHAN_CONFIG
;
4421 WL_TRACE(("valid 2.4GHz chanspec, chanspec = 0x%04x \n",
4422 cmd_data
->chanspec
[1]));
4425 case NAN_ATTRIBUTE_5G_CHANNEL
: {
4426 if (nla_len(iter
) != sizeof(uint32
)) {
4430 /* take the default channel start_factor frequency */
4431 chan
= wf_mhz2channel((uint
)nla_get_u32(iter
), 0);
4433 cmd_data
->chanspec
[2] = wf_channel2chspec(chan
, WL_CHANSPEC_BW_20
);
4434 if (cmd_data
->chanspec
[2] == 0) {
4435 WL_ERR((" 5GHz Channel is not valid \n"));
4439 *nan_attr_mask
|= NAN_ATTR_5G_CHAN_CONFIG
;
4440 WL_TRACE(("valid 5GHz chanspec, chanspec = 0x%04x \n",
4441 cmd_data
->chanspec
[2]));
4444 case NAN_ATTRIBUTE_CONF_CLUSTER_VAL
:
4445 if (nla_len(iter
) != sizeof(uint8
)) {
4449 cmd_data
->config_cluster_val
= nla_get_u8(iter
);
4450 *nan_attr_mask
|= NAN_ATTR_CLUSTER_VAL_CONFIG
;
4452 case NAN_ATTRIBUTE_DWELL_TIME
:
4453 if (nla_len(iter
) != sizeof(uint8
)) {
4457 cmd_data
->dwell_time
[0] = nla_get_u8(iter
);
4458 *nan_attr_mask
|= NAN_ATTR_2G_DWELL_TIME_CONFIG
;
4460 case NAN_ATTRIBUTE_SCAN_PERIOD
:
4461 if (nla_len(iter
) != sizeof(uint16
)) {
4465 cmd_data
->scan_period
[0] = nla_get_u16(iter
);
4466 *nan_attr_mask
|= NAN_ATTR_2G_SCAN_PERIOD_CONFIG
;
4468 case NAN_ATTRIBUTE_DWELL_TIME_5G
:
4469 if (nla_len(iter
) != sizeof(uint8
)) {
4473 cmd_data
->dwell_time
[1] = nla_get_u8(iter
);
4474 *nan_attr_mask
|= NAN_ATTR_5G_DWELL_TIME_CONFIG
;
4476 case NAN_ATTRIBUTE_SCAN_PERIOD_5G
:
4477 if (nla_len(iter
) != sizeof(uint16
)) {
4481 cmd_data
->scan_period
[1] = nla_get_u16(iter
);
4482 *nan_attr_mask
|= NAN_ATTR_5G_SCAN_PERIOD_CONFIG
;
4484 case NAN_ATTRIBUTE_AVAIL_BIT_MAP
:
4485 if (nla_len(iter
) != sizeof(uint32
)) {
4489 cmd_data
->bmap
= nla_get_u32(iter
);
4491 case NAN_ATTRIBUTE_ENTRY_CONTROL
:
4492 if (nla_len(iter
) != sizeof(uint8
)) {
4496 cmd_data
->avail_params
.duration
= nla_get_u8(iter
);
4498 case NAN_ATTRIBUTE_RSSI_CLOSE
:
4499 if (nla_len(iter
) != sizeof(uint8
)) {
4503 cmd_data
->rssi_attr
.rssi_close_2dot4g_val
= nla_get_s8(iter
);
4504 *nan_attr_mask
|= NAN_ATTR_RSSI_CLOSE_CONFIG
;
4506 case NAN_ATTRIBUTE_RSSI_MIDDLE
:
4507 if (nla_len(iter
) != sizeof(uint8
)) {
4511 cmd_data
->rssi_attr
.rssi_middle_2dot4g_val
= nla_get_s8(iter
);
4512 *nan_attr_mask
|= NAN_ATTR_RSSI_MIDDLE_2G_CONFIG
;
4514 case NAN_ATTRIBUTE_RSSI_PROXIMITY
:
4515 if (nla_len(iter
) != sizeof(uint8
)) {
4519 cmd_data
->rssi_attr
.rssi_proximity_2dot4g_val
= nla_get_s8(iter
);
4520 *nan_attr_mask
|= NAN_ATTR_RSSI_PROXIMITY_2G_CONFIG
;
4522 case NAN_ATTRIBUTE_RSSI_CLOSE_5G
:
4523 if (nla_len(iter
) != sizeof(uint8
)) {
4527 cmd_data
->rssi_attr
.rssi_close_5g_val
= nla_get_s8(iter
);
4528 *nan_attr_mask
|= NAN_ATTR_RSSI_CLOSE_5G_CONFIG
;
4530 case NAN_ATTRIBUTE_RSSI_MIDDLE_5G
:
4531 if (nla_len(iter
) != sizeof(uint8
)) {
4535 cmd_data
->rssi_attr
.rssi_middle_5g_val
= nla_get_s8(iter
);
4536 *nan_attr_mask
|= NAN_ATTR_RSSI_MIDDLE_5G_CONFIG
;
4538 case NAN_ATTRIBUTE_RSSI_PROXIMITY_5G
:
4539 if (nla_len(iter
) != sizeof(uint8
)) {
4543 cmd_data
->rssi_attr
.rssi_proximity_5g_val
= nla_get_s8(iter
);
4544 *nan_attr_mask
|= NAN_ATTR_RSSI_PROXIMITY_5G_CONFIG
;
4546 case NAN_ATTRIBUTE_RSSI_WINDOW_SIZE
:
4547 if (nla_len(iter
) != sizeof(uint8
)) {
4551 cmd_data
->rssi_attr
.rssi_window_size
= nla_get_u8(iter
);
4552 *nan_attr_mask
|= NAN_ATTR_RSSI_WINDOW_SIZE_CONFIG
;
4554 case NAN_ATTRIBUTE_CIPHER_SUITE_TYPE
:
4555 if (nla_len(iter
) != sizeof(uint8
)) {
4559 cmd_data
->csid
= nla_get_u8(iter
);
4560 WL_TRACE(("CSID = %u\n", cmd_data
->csid
));
4562 case NAN_ATTRIBUTE_SCID_LEN
:
4563 if (nla_len(iter
) != sizeof(uint32
)) {
4567 if (cmd_data
->scid
.dlen
) {
4568 WL_ERR(("trying to overwrite:%d\n", attr_type
));
4572 cmd_data
->scid
.dlen
= nla_get_u32(iter
);
4573 if (cmd_data
->scid
.dlen
> MAX_SCID_LEN
) {
4575 WL_ERR_RLMT(("Not allowed beyond %d\n", MAX_SCID_LEN
));
4578 WL_TRACE(("valid scid length = %u\n", cmd_data
->scid
.dlen
));
4580 case NAN_ATTRIBUTE_SCID
:
4581 if (!cmd_data
->scid
.dlen
|| (nla_len(iter
) != cmd_data
->scid
.dlen
)) {
4582 WL_ERR(("wrong scid len:%d,%d\n", cmd_data
->scid
.dlen
,
4587 if (cmd_data
->scid
.data
) {
4588 WL_ERR(("trying to overwrite:%d\n", attr_type
));
4593 cmd_data
->scid
.data
= MALLOCZ(cfg
->osh
, cmd_data
->scid
.dlen
);
4594 if (cmd_data
->scid
.data
== NULL
) {
4595 WL_ERR(("failed to allocate scid, len=%d\n",
4596 cmd_data
->scid
.dlen
));
4600 ret
= memcpy_s(cmd_data
->scid
.data
, cmd_data
->scid
.dlen
,
4601 nla_data(iter
), nla_len(iter
));
4602 if (ret
!= BCME_OK
) {
4603 WL_ERR(("Failed to scid data\n"));
4607 case NAN_ATTRIBUTE_2G_AWAKE_DW
:
4608 if (nla_len(iter
) != sizeof(uint32
)) {
4612 if (nla_get_u32(iter
) > NAN_MAX_AWAKE_DW_INTERVAL
) {
4613 WL_ERR(("%s: Invalid/Out of bound value = %u\n",
4614 __FUNCTION__
, nla_get_u32(iter
)));
4618 if (nla_get_u32(iter
)) {
4619 cmd_data
->awake_dws
.dw_interval_2g
=
4620 1 << (nla_get_u32(iter
)-1);
4622 *nan_attr_mask
|= NAN_ATTR_2G_DW_CONFIG
;
4624 case NAN_ATTRIBUTE_5G_AWAKE_DW
:
4625 if (nla_len(iter
) != sizeof(uint32
)) {
4629 if (nla_get_u32(iter
) > NAN_MAX_AWAKE_DW_INTERVAL
) {
4630 WL_ERR(("%s: Invalid/Out of bound value = %u\n",
4631 __FUNCTION__
, nla_get_u32(iter
)));
4635 if (nla_get_u32(iter
)) {
4636 cmd_data
->awake_dws
.dw_interval_5g
=
4637 1 << (nla_get_u32(iter
)-1);
4639 *nan_attr_mask
|= NAN_ATTR_5G_DW_CONFIG
;
4641 case NAN_ATTRIBUTE_DISC_IND_CFG
:
4642 if (nla_len(iter
) != sizeof(uint8
)) {
4646 cmd_data
->disc_ind_cfg
= nla_get_u8(iter
);
4648 case NAN_ATTRIBUTE_MAC_ADDR
:
4649 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
4653 ret
= memcpy_s((char*)&cmd_data
->mac_addr
, ETHER_ADDR_LEN
,
4654 (char*)nla_data(iter
), nla_len(iter
));
4655 if (ret
!= BCME_OK
) {
4656 WL_ERR(("Failed to copy mac addr\n"));
4660 case NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL
:
4661 if (nla_len(iter
) != sizeof(uint32
)) {
4665 cmd_data
->nmi_rand_intvl
= nla_get_u8(iter
);
4666 if (cmd_data
->nmi_rand_intvl
> 0) {
4667 cfg
->nancfg
.mac_rand
= true;
4669 cfg
->nancfg
.mac_rand
= false;
4673 WL_ERR(("%s: Unknown type, %d\n", __FUNCTION__
, attr_type
));
4680 /* We need to call set_config_handler b/f calling start enable TBD */
4683 WL_ERR(("%s: Failed to parse attribute %d ret %d",
4684 __FUNCTION__
, attr_type
, ret
));
4691 wl_cfgvendor_nan_dp_estb_event_data_filler(struct sk_buff
*msg
,
4692 nan_event_data_t
*event_data
) {
4694 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_NDP_ID
, event_data
->ndp_id
);
4695 if (unlikely(ret
)) {
4696 WL_ERR(("Failed to put NDP ID, ret=%d\n", ret
));
4700 * NDI mac address of the peer
4701 * (required to derive target ipv6 address)
4703 ret
= nla_put(msg
, NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR
, ETH_ALEN
,
4704 event_data
->responder_ndi
.octet
);
4705 if (unlikely(ret
)) {
4706 WL_ERR(("Failed to put resp ndi, ret=%d\n", ret
));
4709 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_RSP_CODE
, event_data
->status
);
4710 if (unlikely(ret
)) {
4711 WL_ERR(("Failed to put response code, ret=%d\n", ret
));
4714 if (event_data
->svc_info
.dlen
&& event_data
->svc_info
.data
) {
4715 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
,
4716 event_data
->svc_info
.dlen
);
4717 if (unlikely(ret
)) {
4718 WL_ERR(("Failed to put svc info len, ret=%d\n", ret
));
4721 ret
= nla_put(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
,
4722 event_data
->svc_info
.dlen
, event_data
->svc_info
.data
);
4723 if (unlikely(ret
)) {
4724 WL_ERR(("Failed to put svc info, ret=%d\n", ret
));
4733 wl_cfgvendor_nan_dp_ind_event_data_filler(struct sk_buff
*msg
,
4734 nan_event_data_t
*event_data
) {
4737 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_PUBLISH_ID
,
4738 event_data
->pub_id
);
4739 if (unlikely(ret
)) {
4740 WL_ERR(("Failed to put pub ID, ret=%d\n", ret
));
4743 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_NDP_ID
, event_data
->ndp_id
);
4744 if (unlikely(ret
)) {
4745 WL_ERR(("Failed to put NDP ID, ret=%d\n", ret
));
4748 /* Discovery MAC addr of the peer/initiator */
4749 ret
= nla_put(msg
, NAN_ATTRIBUTE_MAC_ADDR
, ETH_ALEN
,
4750 event_data
->remote_nmi
.octet
);
4751 if (unlikely(ret
)) {
4752 WL_ERR(("Failed to put remote NMI, ret=%d\n", ret
));
4755 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_SECURITY
, event_data
->security
);
4756 if (unlikely(ret
)) {
4757 WL_ERR(("Failed to put security, ret=%d\n", ret
));
4760 if (event_data
->svc_info
.dlen
&& event_data
->svc_info
.data
) {
4761 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
,
4762 event_data
->svc_info
.dlen
);
4763 if (unlikely(ret
)) {
4764 WL_ERR(("Failed to put svc info len, ret=%d\n", ret
));
4767 ret
= nla_put(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
,
4768 event_data
->svc_info
.dlen
, event_data
->svc_info
.data
);
4769 if (unlikely(ret
)) {
4770 WL_ERR(("Failed to put svc info, ret=%d\n", ret
));
4780 wl_cfgvendor_nan_tx_followup_ind_event_data_filler(struct sk_buff
*msg
,
4781 nan_event_data_t
*event_data
) {
4783 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_TRANSAC_ID
, event_data
->token
);
4784 if (unlikely(ret
)) {
4785 WL_ERR(("Failed to put transaction id, ret=%d\n", ret
));
4788 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_HANDLE
, event_data
->local_inst_id
);
4789 if (unlikely(ret
)) {
4790 WL_ERR(("Failed to put handle, ret=%d\n", ret
));
4793 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_STATUS
, event_data
->status
);
4794 if (unlikely(ret
)) {
4795 WL_ERR(("Failed to put nan status, ret=%d\n", ret
));
4798 if (event_data
->status
== NAN_STATUS_SUCCESS
) {
4799 ret
= nla_put(msg
, NAN_ATTRIBUTE_REASON
,
4800 strlen("NAN_STATUS_SUCCESS"), event_data
->nan_reason
);
4801 if (unlikely(ret
)) {
4802 WL_ERR(("Failed to put nan reason, ret=%d\n", ret
));
4806 ret
= nla_put(msg
, NAN_ATTRIBUTE_REASON
,
4807 strlen("NAN_STATUS_NO_OTA_ACK"), event_data
->nan_reason
);
4808 if (unlikely(ret
)) {
4809 WL_ERR(("Failed to put nan reason, ret=%d\n", ret
));
4818 wl_cfgvendor_nan_svc_terminate_event_filler(struct sk_buff
*msg
,
4819 struct bcm_cfg80211
*cfg
, int event_id
, nan_event_data_t
*event_data
) {
4821 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_HANDLE
, event_data
->local_inst_id
);
4822 if (unlikely(ret
)) {
4823 WL_ERR(("Failed to put handle, ret=%d\n", ret
));
4827 if (event_id
== GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED
) {
4828 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SUBSCRIBE_ID
,
4829 event_data
->local_inst_id
);
4830 if (unlikely(ret
)) {
4831 WL_ERR(("Failed to put local inst id, ret=%d\n", ret
));
4835 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_PUBLISH_ID
,
4836 event_data
->local_inst_id
);
4837 if (unlikely(ret
)) {
4838 WL_ERR(("Failed to put local inst id, ret=%d\n", ret
));
4842 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_STATUS
, event_data
->status
);
4843 if (unlikely(ret
)) {
4844 WL_ERR(("Failed to put status, ret=%d\n", ret
));
4847 if (event_data
->status
== NAN_STATUS_SUCCESS
) {
4848 ret
= nla_put(msg
, NAN_ATTRIBUTE_REASON
,
4849 strlen("NAN_STATUS_SUCCESS"), event_data
->nan_reason
);
4850 if (unlikely(ret
)) {
4851 WL_ERR(("Failed to put nan reason, ret=%d\n", ret
));
4855 ret
= nla_put(msg
, NAN_ATTRIBUTE_REASON
,
4856 strlen("NAN_STATUS_INTERNAL_FAILURE"), event_data
->nan_reason
);
4857 if (unlikely(ret
)) {
4858 WL_ERR(("Failed to put nan reason, ret=%d\n", ret
));
4863 ret
= wl_cfgnan_remove_inst_id(cfg
, event_data
->local_inst_id
);
4865 WL_ERR(("failed to free svc instance-id[%d], ret=%d, event_id = %d\n",
4866 event_data
->local_inst_id
, ret
, event_id
));
4874 wl_cfgvendor_nan_opt_params_filler(struct sk_buff
*msg
,
4875 nan_event_data_t
*event_data
) {
4877 /* service specific info data */
4878 if (event_data
->svc_info
.dlen
&& event_data
->svc_info
.data
) {
4879 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
,
4880 event_data
->svc_info
.dlen
);
4881 if (unlikely(ret
)) {
4882 WL_ERR(("Failed to put svc info len, ret=%d\n", ret
));
4885 ret
= nla_put(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
,
4886 event_data
->svc_info
.dlen
, event_data
->svc_info
.data
);
4887 if (unlikely(ret
)) {
4888 WL_ERR(("Failed to put svc info, ret=%d\n", ret
));
4891 WL_TRACE(("svc info len = %d\n", event_data
->svc_info
.dlen
));
4894 /* sdea service specific info data */
4895 if (event_data
->sde_svc_info
.dlen
&& event_data
->sde_svc_info
.data
) {
4896 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN
,
4897 event_data
->sde_svc_info
.dlen
);
4898 if (unlikely(ret
)) {
4899 WL_ERR(("Failed to put sdea svc info len, ret=%d\n", ret
));
4902 ret
= nla_put(msg
, NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO
,
4903 event_data
->sde_svc_info
.dlen
,
4904 event_data
->sde_svc_info
.data
);
4905 if (unlikely(ret
)) {
4906 WL_ERR(("Failed to put sdea svc info, ret=%d\n", ret
));
4909 WL_TRACE(("sdea svc info len = %d\n", event_data
->sde_svc_info
.dlen
));
4911 /* service control discovery range limit */
4914 /* service control binding bitmap */
4921 wl_cfgvendor_nan_tx_followup_event_filler(struct sk_buff
*msg
,
4922 nan_event_data_t
*event_data
) {
4924 /* In followup pkt, instance id and requestor instance id are configured
4925 * from the transmitter perspective. As the event is processed with the
4926 * role of receiver, the local handle should use requestor instance
4929 WL_TRACE(("handle=%d\n", event_data
->requestor_id
));
4930 WL_TRACE(("inst id (local id)=%d\n", event_data
->local_inst_id
));
4931 WL_TRACE(("peer id (remote id)=%d\n", event_data
->requestor_id
));
4932 WL_TRACE(("peer mac addr=" MACDBG
"\n",
4933 MAC2STRDBG(event_data
->remote_nmi
.octet
)));
4934 WL_TRACE(("peer rssi: %d\n", event_data
->fup_rssi
));
4935 WL_TRACE(("attribute no: %d\n", event_data
->attr_num
));
4936 WL_TRACE(("attribute len: %d\n", event_data
->attr_list_len
));
4938 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_HANDLE
, event_data
->requestor_id
);
4939 if (unlikely(ret
)) {
4940 WL_ERR(("Failed to put handle, ret=%d\n", ret
));
4943 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_INST_ID
, event_data
->local_inst_id
);
4944 if (unlikely(ret
)) {
4945 WL_ERR(("Failed to put local inst id, ret=%d\n", ret
));
4948 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_PEER_ID
, event_data
->requestor_id
);
4949 if (unlikely(ret
)) {
4950 WL_ERR(("Failed to put requestor inst id, ret=%d\n", ret
));
4953 ret
= nla_put(msg
, NAN_ATTRIBUTE_MAC_ADDR
, ETHER_ADDR_LEN
,
4954 event_data
->remote_nmi
.octet
);
4955 if (unlikely(ret
)) {
4956 WL_ERR(("Failed to put remote nmi, ret=%d\n", ret
));
4959 ret
= nla_put_s8(msg
, NAN_ATTRIBUTE_RSSI_PROXIMITY
,
4960 event_data
->fup_rssi
);
4961 if (unlikely(ret
)) {
4962 WL_ERR(("Failed to put fup rssi, ret=%d\n", ret
));
4970 wl_cfgvendor_nan_sub_match_event_filler(struct sk_buff
*msg
,
4971 nan_event_data_t
*event_data
) {
4973 WL_TRACE(("handle (sub_id)=%d\n", event_data
->sub_id
));
4974 WL_TRACE(("pub id=%d\n", event_data
->pub_id
));
4975 WL_TRACE(("sub id=%d\n", event_data
->sub_id
));
4976 WL_TRACE(("pub mac addr=" MACDBG
"\n",
4977 MAC2STRDBG(event_data
->remote_nmi
.octet
)));
4978 WL_TRACE(("attr no: %d\n", event_data
->attr_num
));
4979 WL_TRACE(("attr len: %d\n", event_data
->attr_list_len
));
4981 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_HANDLE
, event_data
->sub_id
);
4982 if (unlikely(ret
)) {
4983 WL_ERR(("Failed to put handle, ret=%d\n", ret
));
4986 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_PUBLISH_ID
, event_data
->pub_id
);
4987 if (unlikely(ret
)) {
4988 WL_ERR(("Failed to put pub id, ret=%d\n", ret
));
4991 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SUBSCRIBE_ID
, event_data
->sub_id
);
4992 if (unlikely(ret
)) {
4993 WL_ERR(("Failed to put Sub Id, ret=%d\n", ret
));
4996 ret
= nla_put(msg
, NAN_ATTRIBUTE_MAC_ADDR
, ETHER_ADDR_LEN
,
4997 event_data
->remote_nmi
.octet
);
4998 if (unlikely(ret
)) {
4999 WL_ERR(("Failed to put remote NMI, ret=%d\n", ret
));
5002 if (event_data
->publish_rssi
) {
5003 event_data
->publish_rssi
= -event_data
->publish_rssi
;
5004 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_RSSI_PROXIMITY
,
5005 event_data
->publish_rssi
);
5006 if (unlikely(ret
)) {
5007 WL_ERR(("Failed to put publish rssi, ret=%d\n", ret
));
5011 if (event_data
->ranging_result_present
) {
5012 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_RANGING_INDICATION
,
5013 event_data
->ranging_ind
);
5014 if (unlikely(ret
)) {
5015 WL_ERR(("Failed to put ranging ind, ret=%d\n", ret
));
5018 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_RANGING_RESULT
,
5019 event_data
->range_measurement_cm
);
5020 if (unlikely(ret
)) {
5021 WL_ERR(("Failed to put range measurement cm, ret=%d\n",
5027 * handling optional service control, service response filter
5029 if (event_data
->tx_match_filter
.dlen
&& event_data
->tx_match_filter
.data
) {
5030 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN
,
5031 event_data
->tx_match_filter
.dlen
);
5032 if (unlikely(ret
)) {
5033 WL_ERR(("Failed to put tx match filter len, ret=%d\n",
5037 ret
= nla_put(msg
, NAN_ATTRIBUTE_TX_MATCH_FILTER
,
5038 event_data
->tx_match_filter
.dlen
,
5039 event_data
->tx_match_filter
.data
);
5040 if (unlikely(ret
)) {
5041 WL_ERR(("Failed to put tx match filter data, ret=%d\n",
5045 WL_TRACE(("tx matching filter (%d):\n",
5046 event_data
->tx_match_filter
.dlen
));
5054 wl_cfgvendor_nan_de_event_filler(struct sk_buff
*msg
, nan_event_data_t
*event_data
)
5057 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_ENABLE_STATUS
, event_data
->enabled
);
5058 if (unlikely(ret
)) {
5059 WL_ERR(("Failed to put event_data->enabled, ret=%d\n", ret
));
5062 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_DE_EVENT_TYPE
,
5063 event_data
->nan_de_evt_type
);
5064 if (unlikely(ret
)) {
5065 WL_ERR(("Failed to put nan_de_evt_type, ret=%d\n", ret
));
5068 ret
= nla_put(msg
, NAN_ATTRIBUTE_CLUSTER_ID
, ETH_ALEN
,
5069 event_data
->clus_id
.octet
);
5070 if (unlikely(ret
)) {
5071 WL_ERR(("Failed to put clust id, ret=%d\n", ret
));
5074 /* OOB tests requires local nmi */
5075 ret
= nla_put(msg
, NAN_ATTRIBUTE_MAC_ADDR
, ETH_ALEN
,
5076 event_data
->local_nmi
.octet
);
5077 if (unlikely(ret
)) {
5078 WL_ERR(("Failed to put NMI, ret=%d\n", ret
));
5087 wl_cfgvendor_send_as_rtt_legacy_event(struct wiphy
*wiphy
, struct net_device
*dev
,
5088 wl_nan_ev_rng_rpt_ind_t
*range_res
, uint32 status
)
5091 gfp_t kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
5092 rtt_report_t
*report
= NULL
;
5093 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5094 struct sk_buff
*msg
= NULL
;
5095 struct nlattr
*rtt_nl_hdr
;
5099 report
= MALLOCZ(cfg
->osh
, sizeof(*report
));
5101 WL_ERR(("%s: memory allocation failed\n", __func__
));
5106 report
->distance
= range_res
->dist_mm
/10;
5107 ret
= memcpy_s(&report
->addr
, ETHER_ADDR_LEN
,
5108 &range_res
->peer_m_addr
, ETHER_ADDR_LEN
);
5109 if (ret
!= BCME_OK
) {
5110 WL_ERR(("Failed to copy peer_m_addr\n"));
5114 report
->status
= (rtt_reason_t
)status
;
5115 report
->type
= RTT_TWO_WAY
;
5117 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
5118 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
5119 msg
= cfg80211_vendor_event_alloc(wiphy
, NULL
, 100,
5120 GOOGLE_RTT_COMPLETE_EVENT
, kflags
);
5122 msg
= cfg80211_vendor_event_alloc(wiphy
, 100, GOOGLE_RTT_COMPLETE_EVENT
, kflags
);
5123 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
5124 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
5126 WL_ERR(("%s: fail to allocate skb for vendor event\n", __FUNCTION__
));
5131 ret
= nla_put_u32(msg
, RTT_ATTRIBUTE_RESULTS_COMPLETE
, 1);
5133 WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULTS_COMPLETE\n"));
5136 rtt_nl_hdr
= nla_nest_start(msg
, RTT_ATTRIBUTE_RESULTS_PER_TARGET
);
5138 WL_ERR(("rtt_nl_hdr is NULL\n"));
5142 ret
= nla_put(msg
, RTT_ATTRIBUTE_TARGET_MAC
, ETHER_ADDR_LEN
, &report
->addr
);
5144 WL_ERR(("Failed to put RTT_ATTRIBUTE_TARGET_MAC\n"));
5147 ret
= nla_put_u32(msg
, RTT_ATTRIBUTE_RESULT_CNT
, 1);
5149 WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULT_CNT\n"));
5152 ret
= nla_put(msg
, RTT_ATTRIBUTE_RESULT
,
5153 sizeof(*report
), report
);
5155 WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULTS\n"));
5158 nla_nest_end(msg
, rtt_nl_hdr
);
5159 cfg80211_vendor_event(msg
, kflags
);
5161 MFREE(cfg
->osh
, report
, sizeof(*report
));
5167 dev_kfree_skb_any(msg
);
5168 WL_ERR(("Failed to send event GOOGLE_RTT_COMPLETE_EVENT,"
5169 " -- Free skb, ret = %d\n", ret
));
5171 MFREE(cfg
->osh
, report
, sizeof(*report
));
5175 #endif /* RTT_SUPPORT */
5178 wl_cfgvendor_send_nan_async_resp(struct wiphy
*wiphy
, struct net_device
*dev
,
5179 int event_id
, u8
* nan_req_resp
, u16 len
)
5182 int buf_len
= NAN_EVENT_BUFFER_SIZE_LARGE
;
5183 gfp_t kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
5185 struct sk_buff
*msg
;
5189 /* Allocate the skb for vendor event */
5190 msg
= CFG80211_VENDOR_EVENT_ALLOC(wiphy
, ndev_to_wdev(dev
), buf_len
,
5193 WL_ERR(("%s: fail to allocate skb for vendor event\n", __FUNCTION__
));
5197 ret
= nla_put(msg
, NAN_ATTRIBUTE_CMD_RESP_DATA
,
5198 len
, (u8
*)nan_req_resp
);
5199 if (unlikely(ret
)) {
5200 WL_ERR(("Failed to put resp data, ret=%d\n",
5204 WL_DBG(("Event sent up to hal, event_id = %d, ret = %d\n",
5206 cfg80211_vendor_event(msg
, kflags
);
5211 dev_kfree_skb_any(msg
);
5212 WL_ERR(("Event not implemented or unknown -- Free skb, event_id = %d, ret = %d\n",
5219 wl_cfgvendor_nan_send_async_disable_resp(struct wireless_dev
*wdev
)
5222 struct wiphy
*wiphy
= wdev
->wiphy
;
5223 nan_hal_resp_t nan_req_resp
;
5224 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
5225 nan_req_resp
.status
= NAN_STATUS_SUCCESS
;
5226 nan_req_resp
.value
= BCME_OK
;
5228 ret
= wl_cfgvendor_send_nan_async_resp(wiphy
, wdev
->netdev
,
5229 NAN_ASYNC_RESPONSE_DISABLED
, (u8
*)&nan_req_resp
, sizeof(nan_req_resp
));
5230 WL_INFORM_MEM(("[NAN] Disable done\n"));
5235 wl_cfgvendor_send_nan_event(struct wiphy
*wiphy
, struct net_device
*dev
,
5236 int event_id
, nan_event_data_t
*event_data
)
5239 int buf_len
= NAN_EVENT_BUFFER_SIZE_LARGE
;
5240 gfp_t kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
5242 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5243 struct sk_buff
*msg
;
5247 /* Allocate the skb for vendor event */
5248 msg
= CFG80211_VENDOR_EVENT_ALLOC(wiphy
, ndev_to_wdev(dev
), buf_len
,
5251 WL_ERR(("%s: fail to allocate skb for vendor event\n", __FUNCTION__
));
5256 case GOOGLE_NAN_EVENT_DE_EVENT
: {
5257 WL_INFORM_MEM(("[NAN] GOOGLE_NAN_DE_EVENT cluster id=" MACDBG
"nmi= " MACDBG
"\n",
5258 MAC2STRDBG(event_data
->clus_id
.octet
),
5259 MAC2STRDBG(event_data
->local_nmi
.octet
)));
5260 ret
= wl_cfgvendor_nan_de_event_filler(msg
, event_data
);
5261 if (unlikely(ret
)) {
5262 WL_ERR(("Failed to fill de event data, ret=%d\n", ret
));
5267 case GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH
:
5268 case GOOGLE_NAN_EVENT_FOLLOWUP
: {
5269 if (event_id
== GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH
) {
5270 WL_DBG(("GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH\n"));
5271 ret
= wl_cfgvendor_nan_sub_match_event_filler(msg
, event_data
);
5272 if (unlikely(ret
)) {
5273 WL_ERR(("Failed to fill sub match event data, ret=%d\n", ret
));
5276 } else if (event_id
== GOOGLE_NAN_EVENT_FOLLOWUP
) {
5277 WL_DBG(("GOOGLE_NAN_EVENT_FOLLOWUP\n"));
5278 ret
= wl_cfgvendor_nan_tx_followup_event_filler(msg
, event_data
);
5279 if (unlikely(ret
)) {
5280 WL_ERR(("Failed to fill sub match event data, ret=%d\n", ret
));
5284 ret
= wl_cfgvendor_nan_opt_params_filler(msg
, event_data
);
5285 if (unlikely(ret
)) {
5286 WL_ERR(("Failed to fill sub match event data, ret=%d\n", ret
));
5292 case GOOGLE_NAN_EVENT_DISABLED
: {
5293 WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DISABLED\n"));
5294 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_HANDLE
, 0);
5295 if (unlikely(ret
)) {
5296 WL_ERR(("Failed to put handle, ret=%d\n", ret
));
5299 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_STATUS
, event_data
->status
);
5300 if (unlikely(ret
)) {
5301 WL_ERR(("Failed to put status, ret=%d\n", ret
));
5304 ret
= nla_put(msg
, NAN_ATTRIBUTE_REASON
,
5305 strlen("NAN_STATUS_SUCCESS"), event_data
->nan_reason
);
5306 if (unlikely(ret
)) {
5307 WL_ERR(("Failed to put reason code, ret=%d\n", ret
));
5313 case GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED
:
5314 case GOOGLE_NAN_EVENT_PUBLISH_TERMINATED
: {
5315 WL_DBG(("GOOGLE_NAN_SVC_TERMINATED, %d\n", event_id
));
5316 ret
= wl_cfgvendor_nan_svc_terminate_event_filler(msg
, cfg
, event_id
, event_data
);
5317 if (unlikely(ret
)) {
5318 WL_ERR(("Failed to fill svc terminate event data, ret=%d\n", ret
));
5324 case GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND
: {
5325 WL_DBG(("GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND %d\n",
5326 GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND
));
5327 ret
= wl_cfgvendor_nan_tx_followup_ind_event_data_filler(msg
, event_data
);
5328 if (unlikely(ret
)) {
5329 WL_ERR(("Failed to fill tx follow up ind event data, ret=%d\n", ret
));
5336 case GOOGLE_NAN_EVENT_DATA_REQUEST
: {
5337 WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DATA_REQUEST\n"));
5338 ret
= wl_cfgvendor_nan_dp_ind_event_data_filler(msg
, event_data
);
5339 if (unlikely(ret
)) {
5340 WL_ERR(("Failed to fill dp ind event data, ret=%d\n", ret
));
5346 case GOOGLE_NAN_EVENT_DATA_CONFIRMATION
: {
5347 WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DATA_CONFIRMATION\n"));
5349 ret
= wl_cfgvendor_nan_dp_estb_event_data_filler(msg
, event_data
);
5350 if (unlikely(ret
)) {
5351 WL_ERR(("Failed to fill dp estb event data, ret=%d\n", ret
));
5357 case GOOGLE_NAN_EVENT_DATA_END
: {
5358 WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DATA_END\n"));
5359 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_INST_COUNT
, 1);
5360 if (unlikely(ret
)) {
5361 WL_ERR(("Failed to put inst count, ret=%d\n", ret
));
5364 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_NDP_ID
, event_data
->ndp_id
);
5365 if (unlikely(ret
)) {
5366 WL_ERR(("Failed to put ndp id, ret=%d\n", ret
));
5376 cfg80211_vendor_event(msg
, kflags
);
5381 dev_kfree_skb_any(msg
);
5382 WL_ERR(("Event not implemented or unknown -- Free skb, event_id = %d, ret = %d\n",
5389 wl_cfgvendor_nan_req_subscribe(struct wiphy
*wiphy
,
5390 struct wireless_dev
*wdev
, const void * data
, int len
)
5393 nan_discover_cmd_data_t
*cmd_data
= NULL
;
5394 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5395 nan_hal_resp_t nan_req_resp
;
5398 /* Blocking Subscribe if NAN is not enable */
5399 if (!cfg
->nan_enable
) {
5400 WL_ERR(("nan is not enabled, subscribe blocked\n"));
5404 cmd_data
= (nan_discover_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5406 WL_ERR(("%s: memory allocation failed\n", __func__
));
5411 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
5412 ret
= wl_cfgvendor_nan_parse_discover_args(wiphy
, data
, len
, cmd_data
);
5414 WL_ERR(("failed to parse nan disc vendor args, ret = %d\n", ret
));
5418 if (cmd_data
->sub_id
== 0) {
5419 ret
= wl_cfgnan_generate_inst_id(cfg
, &cmd_data
->sub_id
);
5421 WL_ERR(("failed to generate instance-id for subscribe\n"));
5425 cmd_data
->svc_update
= true;
5428 ret
= wl_cfgnan_subscribe_handler(wdev
->netdev
, cfg
, cmd_data
);
5429 if (unlikely(ret
) || unlikely(cmd_data
->status
)) {
5430 WL_ERR(("failed to subscribe error[%d], status = [%d]\n",
5431 ret
, cmd_data
->status
));
5432 wl_cfgnan_remove_inst_id(cfg
, cmd_data
->sub_id
);
5436 WL_DBG(("subscriber instance id=%d\n", cmd_data
->sub_id
));
5438 if (cmd_data
->status
== WL_NAN_E_OK
) {
5439 nan_req_resp
.instance_id
= cmd_data
->sub_id
;
5441 nan_req_resp
.instance_id
= 0;
5444 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_REQUEST_SUBSCRIBE
,
5445 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5446 wl_cfgvendor_free_disc_cmd_data(cfg
, cmd_data
);
5452 wl_cfgvendor_nan_req_publish(struct wiphy
*wiphy
,
5453 struct wireless_dev
*wdev
, const void * data
, int len
)
5456 nan_discover_cmd_data_t
*cmd_data
= NULL
;
5457 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5458 nan_hal_resp_t nan_req_resp
;
5461 /* Blocking Publish if NAN is not enable */
5462 if (!cfg
->nan_enable
) {
5463 WL_ERR(("nan is not enabled publish blocked\n"));
5467 cmd_data
= (nan_discover_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5469 WL_ERR(("%s: memory allocation failed\n", __func__
));
5474 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
5475 ret
= wl_cfgvendor_nan_parse_discover_args(wiphy
, data
, len
, cmd_data
);
5477 WL_ERR(("failed to parse nan disc vendor args, ret = %d\n", ret
));
5481 if (cmd_data
->pub_id
== 0) {
5482 ret
= wl_cfgnan_generate_inst_id(cfg
, &cmd_data
->pub_id
);
5484 WL_ERR(("failed to generate instance-id for publisher\n"));
5488 cmd_data
->svc_update
= true;
5491 ret
= wl_cfgnan_publish_handler(wdev
->netdev
, cfg
, cmd_data
);
5492 if (unlikely(ret
) || unlikely(cmd_data
->status
)) {
5493 WL_ERR(("failed to publish error[%d], status[%d]\n",
5494 ret
, cmd_data
->status
));
5495 wl_cfgnan_remove_inst_id(cfg
, cmd_data
->pub_id
);
5499 WL_DBG(("publisher instance id=%d\n", cmd_data
->pub_id
));
5501 if (cmd_data
->status
== WL_NAN_E_OK
) {
5502 nan_req_resp
.instance_id
= cmd_data
->pub_id
;
5504 nan_req_resp
.instance_id
= 0;
5507 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_REQUEST_PUBLISH
,
5508 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5509 wl_cfgvendor_free_disc_cmd_data(cfg
, cmd_data
);
5515 wl_cfgvendor_nan_start_handler(struct wiphy
*wiphy
,
5516 struct wireless_dev
*wdev
, const void *data
, int len
)
5519 nan_config_cmd_data_t
*cmd_data
;
5520 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5521 nan_hal_resp_t nan_req_resp
;
5522 uint32 nan_attr_mask
= 0;
5524 cmd_data
= (nan_config_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5526 WL_ERR(("%s: memory allocation failed\n", __func__
));
5532 if (cfg
->nan_enable
) {
5533 WL_ERR(("nan is already enabled\n"));
5537 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
5539 cmd_data
->sid_beacon
.sid_enable
= NAN_SID_ENABLE_FLAG_INVALID
; /* Setting to some default */
5540 cmd_data
->sid_beacon
.sid_count
= NAN_SID_BEACON_COUNT_INVALID
; /* Setting to some default */
5542 ret
= wl_cfgvendor_nan_parse_args(wiphy
, data
, len
, cmd_data
, &nan_attr_mask
);
5544 WL_ERR(("failed to parse nan vendor args, ret %d\n", ret
));
5548 ret
= wl_cfgnan_start_handler(wdev
->netdev
, cfg
, cmd_data
, nan_attr_mask
);
5550 WL_ERR(("failed to start nan error[%d]\n", ret
));
5553 /* Initializing Instance Id List */
5554 bzero(cfg
->nan_inst_ctrl
, NAN_ID_CTRL_SIZE
* sizeof(nan_svc_inst_t
));
5556 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_ENABLE
,
5557 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5559 if (cmd_data
->scid
.data
) {
5560 MFREE(cfg
->osh
, cmd_data
->scid
.data
, cmd_data
->scid
.dlen
);
5561 cmd_data
->scid
.dlen
= 0;
5563 MFREE(cfg
->osh
, cmd_data
, sizeof(*cmd_data
));
5570 wl_cfgvendor_terminate_dp_rng_sessions(struct bcm_cfg80211
*cfg
,
5571 struct wireless_dev
*wdev
, bool *ssn_exists
)
5575 int status
= BCME_ERROR
;
5576 nan_ranging_inst_t
*ranging_inst
= NULL
;
5578 /* Cleanup active Data Paths If any */
5579 for (i
= 0; i
< NAN_MAX_NDP_PEER
; i
++) {
5580 if (cfg
->nancfg
.ndp_id
[i
]) {
5582 WL_DBG(("Found entry of ndp id = [%d], end dp associated to it\n",
5583 cfg
->nancfg
.ndp_id
[i
]));
5584 wl_cfgnan_data_path_end_handler(wdev
->netdev
, cfg
,
5585 cfg
->nancfg
.ndp_id
[i
], &status
);
5589 /* Cancel ranging sessiosns */
5590 for (i
= 0; i
< NAN_MAX_RANGING_INST
; i
++) {
5591 ranging_inst
= &cfg
->nan_ranging_info
[i
];
5592 if (ranging_inst
->range_id
) {
5594 ret
= wl_cfgnan_cancel_ranging(bcmcfg_to_prmry_ndev(cfg
), cfg
,
5595 ranging_inst
->range_id
,
5596 NAN_RNG_TERM_FLAG_NONE
, &status
);
5597 if (unlikely(ret
) || unlikely(status
)) {
5598 WL_ERR(("nan range cancel failed ret = %d status = %d\n",
5607 wl_cfgvendor_nan_stop_handler(struct wiphy
*wiphy
,
5608 struct wireless_dev
*wdev
, const void * data
, int len
)
5611 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5612 nan_hal_resp_t nan_req_resp
;
5613 bool ssn_exists
= false;
5617 if (!cfg
->nan_init_state
) {
5618 WL_ERR(("nan is not initialized/nmi doesnt exists\n"));
5623 mutex_lock(&cfg
->if_sync
);
5624 if (cfg
->nan_enable
) {
5625 cfg
->nancfg
.disable_reason
= NAN_USER_INITIATED
;
5626 wl_cfgvendor_terminate_dp_rng_sessions(cfg
, wdev
, &ssn_exists
);
5627 if (ssn_exists
== true) {
5629 * Schedule nan disable with 4sec delay to make sure
5630 * fw cleans any active Data paths and
5631 * notifies the peer about the dp session terminations
5633 WL_INFORM_MEM(("Schedule Nan Disable Req, with 4sec\n"));
5634 schedule_delayed_work(&cfg
->nan_disable
,
5635 msecs_to_jiffies(NAN_DISABLE_CMD_DELAY_TIMER
));
5637 ret
= wl_cfgnan_disable(cfg
);
5639 WL_ERR(("failed to disable nan, error[%d]\n", ret
));
5643 mutex_unlock(&cfg
->if_sync
);
5644 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
5651 wl_cfgvendor_nan_config_handler(struct wiphy
*wiphy
,
5652 struct wireless_dev
*wdev
, const void *data
, int len
)
5655 nan_config_cmd_data_t
*cmd_data
;
5656 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5657 nan_hal_resp_t nan_req_resp
;
5658 uint32 nan_attr_mask
= 0;
5660 cmd_data
= MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5662 WL_ERR(("%s: memory allocation failed\n", __func__
));
5668 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
5670 cmd_data
->avail_params
.duration
= NAN_BAND_INVALID
; /* Setting to some default */
5671 cmd_data
->sid_beacon
.sid_enable
= NAN_SID_ENABLE_FLAG_INVALID
; /* Setting to some default */
5672 cmd_data
->sid_beacon
.sid_count
= NAN_SID_BEACON_COUNT_INVALID
; /* Setting to some default */
5674 ret
= wl_cfgvendor_nan_parse_args(wiphy
, data
, len
, cmd_data
, &nan_attr_mask
);
5676 WL_ERR(("failed to parse nan vendor args, ret = %d\n", ret
));
5680 ret
= wl_cfgnan_config_handler(wdev
->netdev
, cfg
, cmd_data
, nan_attr_mask
);
5682 WL_ERR(("failed in config request, nan error[%d]\n", ret
));
5686 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_CONFIG
,
5687 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5689 if (cmd_data
->scid
.data
) {
5690 MFREE(cfg
->osh
, cmd_data
->scid
.data
, cmd_data
->scid
.dlen
);
5691 cmd_data
->scid
.dlen
= 0;
5693 MFREE(cfg
->osh
, cmd_data
, sizeof(*cmd_data
));
5700 wl_cfgvendor_nan_cancel_publish(struct wiphy
*wiphy
,
5701 struct wireless_dev
*wdev
, const void * data
, int len
)
5704 nan_discover_cmd_data_t
*cmd_data
= NULL
;
5705 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5706 nan_hal_resp_t nan_req_resp
;
5708 /* Blocking Cancel_Publish if NAN is not enable */
5709 if (!cfg
->nan_enable
) {
5710 WL_ERR(("nan is not enabled, cancel publish blocked\n"));
5714 cmd_data
= (nan_discover_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5716 WL_ERR(("%s: memory allocation failed\n", __func__
));
5722 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
5724 ret
= wl_cfgvendor_nan_parse_discover_args(wiphy
, data
, len
, cmd_data
);
5726 WL_ERR(("failed to parse nan disc vendor args, ret= %d\n", ret
));
5729 nan_req_resp
.instance_id
= cmd_data
->pub_id
;
5730 WL_INFORM_MEM(("[NAN] cancel publish instance_id=%d\n", cmd_data
->pub_id
));
5732 ret
= wl_cfgnan_cancel_pub_handler(wdev
->netdev
, cfg
, cmd_data
);
5734 WL_ERR(("failed to cancel publish nan instance-id[%d] error[%d]\n",
5735 cmd_data
->pub_id
, ret
));
5739 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_CANCEL_PUBLISH
,
5740 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5741 wl_cfgvendor_free_disc_cmd_data(cfg
, cmd_data
);
5747 wl_cfgvendor_nan_cancel_subscribe(struct wiphy
*wiphy
,
5748 struct wireless_dev
*wdev
, const void * data
, int len
)
5751 nan_discover_cmd_data_t
*cmd_data
= NULL
;
5752 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5753 nan_hal_resp_t nan_req_resp
;
5755 /* Blocking Cancel_Subscribe if NAN is not enableb */
5756 if (!cfg
->nan_enable
) {
5757 WL_ERR(("nan is not enabled, cancel subscribe blocked\n"));
5761 cmd_data
= MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5763 WL_ERR(("%s: memory allocation failed\n", __func__
));
5769 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
5771 ret
= wl_cfgvendor_nan_parse_discover_args(wiphy
, data
, len
, cmd_data
);
5773 WL_ERR(("failed to parse nan disc vendor args, ret= %d\n", ret
));
5776 nan_req_resp
.instance_id
= cmd_data
->sub_id
;
5777 WL_INFORM_MEM(("[NAN] cancel subscribe instance_id=%d\n", cmd_data
->sub_id
));
5779 ret
= wl_cfgnan_cancel_sub_handler(wdev
->netdev
, cfg
, cmd_data
);
5781 WL_ERR(("failed to cancel subscribe nan instance-id[%d] error[%d]\n",
5782 cmd_data
->sub_id
, ret
));
5786 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_CANCEL_SUBSCRIBE
,
5787 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5788 wl_cfgvendor_free_disc_cmd_data(cfg
, cmd_data
);
5794 wl_cfgvendor_nan_transmit(struct wiphy
*wiphy
,
5795 struct wireless_dev
*wdev
, const void * data
, int len
)
5798 nan_discover_cmd_data_t
*cmd_data
= NULL
;
5799 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5800 nan_hal_resp_t nan_req_resp
;
5802 /* Blocking Transmit if NAN is not enable */
5803 if (!cfg
->nan_enable
) {
5804 WL_ERR(("nan is not enabled, transmit blocked\n"));
5808 cmd_data
= (nan_discover_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5810 WL_ERR(("%s: memory allocation failed\n", __func__
));
5816 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
5818 ret
= wl_cfgvendor_nan_parse_discover_args(wiphy
, data
, len
, cmd_data
);
5820 WL_ERR(("failed to parse nan disc vendor args, ret= %d\n", ret
));
5823 nan_req_resp
.instance_id
= cmd_data
->local_id
;
5824 ret
= wl_cfgnan_transmit_handler(wdev
->netdev
, cfg
, cmd_data
);
5826 WL_ERR(("failed to transmit-followup nan error[%d]\n", ret
));
5830 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_TRANSMIT
,
5831 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5832 wl_cfgvendor_free_disc_cmd_data(cfg
, cmd_data
);
5838 wl_cfgvendor_nan_get_capablities(struct wiphy
*wiphy
,
5839 struct wireless_dev
*wdev
, const void * data
, int len
)
5842 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5843 nan_hal_resp_t nan_req_resp
;
5847 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
5848 ret
= wl_cfgnan_get_capablities_handler(wdev
->netdev
, cfg
, &nan_req_resp
.capabilities
);
5850 WL_ERR(("Could not get capabilities\n"));
5855 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_GET_CAPABILITIES
,
5856 &nan_req_resp
, ret
, BCME_OK
);
5862 wl_cfgvendor_nan_data_path_iface_create(struct wiphy
*wiphy
,
5863 struct wireless_dev
*wdev
, const void * data
, int len
)
5866 nan_datapath_cmd_data_t
*cmd_data
= NULL
;
5867 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5868 nan_hal_resp_t nan_req_resp
;
5869 dhd_pub_t
*dhdp
= wl_cfg80211_get_dhdp(wdev
->netdev
);
5871 if (!cfg
->nan_init_state
) {
5872 WL_ERR(("%s: NAN is not inited or Device doesn't support NAN \n", __func__
));
5877 cmd_data
= (nan_datapath_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5879 WL_ERR(("%s: memory allocation failed\n", __func__
));
5885 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
5887 ret
= wl_cfgvendor_nan_parse_datapath_args(wiphy
, data
, len
, cmd_data
);
5889 WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret
));
5893 if (cfg
->nan_enable
) { /* new framework Impl, iface create called after nan enab */
5894 ret
= wl_cfgnan_data_path_iface_create_delete_handler(wdev
->netdev
,
5895 cfg
, cmd_data
->ndp_iface
,
5896 NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE
, dhdp
->up
);
5897 if (ret
!= BCME_OK
) {
5898 WL_ERR(("failed to create iface, ret = %d\n", ret
));
5903 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE
,
5904 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5905 wl_cfgvendor_free_dp_cmd_data(cfg
, cmd_data
);
5911 wl_cfgvendor_nan_data_path_iface_delete(struct wiphy
*wiphy
,
5912 struct wireless_dev
*wdev
, const void * data
, int len
)
5915 nan_datapath_cmd_data_t
*cmd_data
= NULL
;
5916 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5917 nan_hal_resp_t nan_req_resp
;
5918 dhd_pub_t
*dhdp
= wl_cfg80211_get_dhdp(wdev
->netdev
);
5920 if (cfg
->nan_init_state
== false) {
5921 WL_ERR(("%s: NAN is not inited or Device doesn't support NAN \n", __func__
));
5922 /* Deinit has taken care of cleaing the virtual iface */
5928 cmd_data
= (nan_datapath_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5930 WL_ERR(("%s: memory allocation failed\n", __func__
));
5934 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
5935 ret
= wl_cfgvendor_nan_parse_datapath_args(wiphy
, data
, len
, cmd_data
);
5937 WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret
));
5941 ret
= wl_cfgnan_data_path_iface_create_delete_handler(wdev
->netdev
, cfg
,
5942 (char*)cmd_data
->ndp_iface
,
5943 NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE
, dhdp
->up
);
5945 WL_ERR(("failed to delete ndp iface [%d]\n", ret
));
5949 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE
,
5950 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5951 wl_cfgvendor_free_dp_cmd_data(cfg
, cmd_data
);
5957 wl_cfgvendor_nan_data_path_request(struct wiphy
*wiphy
,
5958 struct wireless_dev
*wdev
, const void * data
, int len
)
5961 nan_datapath_cmd_data_t
*cmd_data
= NULL
;
5962 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5963 nan_hal_resp_t nan_req_resp
;
5964 uint8 ndp_instance_id
= 0;
5966 if (!cfg
->nan_enable
) {
5967 WL_ERR(("nan is not enabled, nan data path request blocked\n"));
5973 cmd_data
= (nan_datapath_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5975 WL_ERR(("%s: memory allocation failed\n", __func__
));
5980 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
5981 ret
= wl_cfgvendor_nan_parse_datapath_args(wiphy
, data
, len
, cmd_data
);
5983 WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret
));
5987 ret
= wl_cfgnan_data_path_request_handler(wdev
->netdev
, cfg
,
5988 cmd_data
, &ndp_instance_id
);
5990 WL_ERR(("failed to request nan data path [%d]\n", ret
));
5994 if (cmd_data
->status
== BCME_OK
) {
5995 nan_req_resp
.ndp_instance_id
= cmd_data
->ndp_instance_id
;
5997 nan_req_resp
.ndp_instance_id
= 0;
6000 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_REQUEST
,
6001 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
6002 wl_cfgvendor_free_dp_cmd_data(cfg
, cmd_data
);
6008 wl_cfgvendor_nan_data_path_response(struct wiphy
*wiphy
,
6009 struct wireless_dev
*wdev
, const void * data
, int len
)
6012 nan_datapath_cmd_data_t
*cmd_data
= NULL
;
6013 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6014 nan_hal_resp_t nan_req_resp
;
6016 if (!cfg
->nan_enable
) {
6017 WL_ERR(("nan is not enabled, nan data path response blocked\n"));
6022 cmd_data
= (nan_datapath_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
6024 WL_ERR(("%s: memory allocation failed\n", __func__
));
6029 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
6030 ret
= wl_cfgvendor_nan_parse_datapath_args(wiphy
, data
, len
, cmd_data
);
6032 WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret
));
6035 ret
= wl_cfgnan_data_path_response_handler(wdev
->netdev
, cfg
, cmd_data
);
6037 WL_ERR(("failed to response nan data path [%d]\n", ret
));
6041 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_RESPONSE
,
6042 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
6043 wl_cfgvendor_free_dp_cmd_data(cfg
, cmd_data
);
6049 wl_cfgvendor_nan_data_path_end(struct wiphy
*wiphy
,
6050 struct wireless_dev
*wdev
, const void * data
, int len
)
6053 nan_datapath_cmd_data_t
*cmd_data
= NULL
;
6054 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6055 nan_hal_resp_t nan_req_resp
;
6056 int status
= BCME_ERROR
;
6059 if (!cfg
->nan_enable
) {
6060 WL_ERR(("nan is not enabled, nan data path end blocked\n"));
6064 cmd_data
= (nan_datapath_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
6066 WL_ERR(("%s: memory allocation failed\n", __func__
));
6071 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
6072 ret
= wl_cfgvendor_nan_parse_datapath_args(wiphy
, data
, len
, cmd_data
);
6074 WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret
));
6077 ret
= wl_cfgnan_data_path_end_handler(wdev
->netdev
, cfg
,
6078 cmd_data
->ndp_instance_id
, &status
);
6080 WL_ERR(("failed to end nan data path [%d]\n", ret
));
6084 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_END
,
6085 &nan_req_resp
, ret
, cmd_data
? status
: BCME_OK
);
6086 wl_cfgvendor_free_dp_cmd_data(cfg
, cmd_data
);
6091 #ifdef WL_NAN_DISC_CACHE
6093 wl_cfgvendor_nan_data_path_sec_info(struct wiphy
*wiphy
,
6094 struct wireless_dev
*wdev
, const void *data
, int len
)
6097 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6098 nan_hal_resp_t nan_req_resp
;
6099 nan_datapath_sec_info_cmd_data_t
*cmd_data
= NULL
;
6100 dhd_pub_t
*dhdp
= wl_cfg80211_get_dhdp(wdev
->netdev
);
6103 if (!cfg
->nan_enable
) {
6104 WL_ERR(("nan is not enabled\n"));
6105 ret
= BCME_UNSUPPORTED
;
6108 cmd_data
= MALLOCZ(dhdp
->osh
, sizeof(*cmd_data
));
6110 WL_ERR(("%s: memory allocation failed\n", __func__
));
6115 ret
= wl_cfgvendor_nan_parse_dp_sec_info_args(wiphy
, data
, len
, cmd_data
);
6117 WL_ERR(("failed to parse sec info args\n"));
6121 bzero(&nan_req_resp
, sizeof(nan_req_resp
));
6122 ret
= wl_cfgnan_sec_info_handler(cfg
, cmd_data
, &nan_req_resp
);
6124 WL_ERR(("failed to retrieve svc hash/pub nmi error[%d]\n", ret
));
6128 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_SEC_INFO
,
6129 &nan_req_resp
, ret
, BCME_OK
);
6131 MFREE(dhdp
->osh
, cmd_data
, sizeof(*cmd_data
));
6136 #endif /* WL_NAN_DISC_CACHE */
6139 wl_cfgvendor_nan_version_info(struct wiphy
*wiphy
,
6140 struct wireless_dev
*wdev
, const void *data
, int len
)
6143 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6144 uint32 version
= NAN_HAL_VERSION_1
;
6147 WL_DBG(("Enter %s version %d\n", __FUNCTION__
, version
));
6148 ret
= wl_cfgvendor_send_cmd_reply(wiphy
, &version
, sizeof(version
));
6154 #ifdef LINKSTAT_SUPPORT
6159 #define HEADER_SIZE sizeof(ver_len)
6161 static int wl_cfgvendor_lstats_get_bcn_mbss(char *buf
, uint32
*rxbeaconmbss
)
6163 wl_cnt_info_t
*cbuf
= (wl_cnt_info_t
*)buf
;
6166 if ((cnt
= (const void *)bcm_get_data_from_xtlv_buf(cbuf
->data
, cbuf
->datalen
,
6167 WL_CNT_XTLV_CNTV_LE10_UCODE
, NULL
, BCM_XTLV_OPTION_ALIGN32
)) != NULL
) {
6168 *rxbeaconmbss
= ((const wl_cnt_v_le10_mcst_t
*)cnt
)->rxbeaconmbss
;
6169 } else if ((cnt
= (const void *)bcm_get_data_from_xtlv_buf(cbuf
->data
, cbuf
->datalen
,
6170 WL_CNT_XTLV_LT40_UCODE_V1
, NULL
, BCM_XTLV_OPTION_ALIGN32
)) != NULL
) {
6171 *rxbeaconmbss
= ((const wl_cnt_lt40mcst_v1_t
*)cnt
)->rxbeaconmbss
;
6172 } else if ((cnt
= (const void *)bcm_get_data_from_xtlv_buf(cbuf
->data
, cbuf
->datalen
,
6173 WL_CNT_XTLV_GE40_UCODE_V1
, NULL
, BCM_XTLV_OPTION_ALIGN32
)) != NULL
) {
6174 *rxbeaconmbss
= ((const wl_cnt_ge40mcst_v1_t
*)cnt
)->rxbeaconmbss
;
6175 } else if ((cnt
= (const void *)bcm_get_data_from_xtlv_buf(cbuf
->data
, cbuf
->datalen
,
6176 WL_CNT_XTLV_GE80_UCODE_V1
, NULL
, BCM_XTLV_OPTION_ALIGN32
)) != NULL
) {
6177 *rxbeaconmbss
= ((const wl_cnt_ge80mcst_v1_t
*)cnt
)->rxbeaconmbss
;
6180 return BCME_NOTFOUND
;
6186 static int wl_cfgvendor_lstats_get_info(struct wiphy
*wiphy
,
6187 struct wireless_dev
*wdev
, const void *data
, int len
)
6189 static char iovar_buf
[WLC_IOCTL_MAXLEN
];
6190 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6192 wifi_radio_stat
*radio
;
6193 wifi_radio_stat_h radio_h
;
6194 wl_wme_cnt_t
*wl_wme_cnt
;
6195 const wl_cnt_wlc_t
*wlc_cnt
;
6197 char *output
= NULL
;
6198 char *outdata
= NULL
;
6199 wifi_rate_stat_v1
*p_wifi_rate_stat_v1
= NULL
;
6200 wifi_rate_stat
*p_wifi_rate_stat
= NULL
;
6202 uint32 rxbeaconmbss
;
6203 wifi_iface_stat iface
;
6204 wlc_rev_info_t revinfo
;
6205 #ifdef CONFIG_COMPAT
6206 compat_wifi_iface_stat compat_iface
;
6207 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0))
6208 int compat_task_state
= in_compat_syscall();
6210 int compat_task_state
= is_compat_task();
6212 #endif /* CONFIG_COMPAT */
6214 WL_INFORM_MEM(("%s: Enter \n", __func__
));
6215 RETURN_EIO_IF_NOT_UP(cfg
);
6217 /* Get the device rev info */
6218 bzero(&revinfo
, sizeof(revinfo
));
6219 err
= wldev_ioctl_get(bcmcfg_to_prmry_ndev(cfg
), WLC_GET_REVINFO
, &revinfo
,
6221 if (err
!= BCME_OK
) {
6225 outdata
= (void *)MALLOCZ(cfg
->osh
, WLC_IOCTL_MAXLEN
);
6226 if (outdata
== NULL
) {
6227 WL_ERR(("%s: alloc failed\n", __func__
));
6231 bzero(&scbval
, sizeof(scb_val_t
));
6232 bzero(outdata
, WLC_IOCTL_MAXLEN
);
6235 err
= wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg
), "radiostat", NULL
, 0,
6236 iovar_buf
, WLC_IOCTL_MAXLEN
, NULL
);
6237 if (err
!= BCME_OK
&& err
!= BCME_UNSUPPORTED
) {
6238 WL_ERR(("error (%d) - size = %zu\n", err
, sizeof(wifi_radio_stat
)));
6241 radio
= (wifi_radio_stat
*)iovar_buf
;
6243 bzero(&radio_h
, sizeof(wifi_radio_stat_h
));
6244 radio_h
.on_time
= radio
->on_time
;
6245 radio_h
.tx_time
= radio
->tx_time
;
6246 radio_h
.rx_time
= radio
->rx_time
;
6247 radio_h
.on_time_scan
= radio
->on_time_scan
;
6248 radio_h
.on_time_nbd
= radio
->on_time_nbd
;
6249 radio_h
.on_time_gscan
= radio
->on_time_gscan
;
6250 radio_h
.on_time_roam_scan
= radio
->on_time_roam_scan
;
6251 radio_h
.on_time_pno_scan
= radio
->on_time_pno_scan
;
6252 radio_h
.on_time_hs20
= radio
->on_time_hs20
;
6253 radio_h
.num_channels
= NUM_CHAN
;
6255 memcpy(output
, &radio_h
, sizeof(wifi_radio_stat_h
));
6257 output
+= sizeof(wifi_radio_stat_h
);
6258 output
+= (NUM_CHAN
* sizeof(wifi_channel_stat
));
6260 err
= wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg
), "wme_counters", NULL
, 0,
6261 iovar_buf
, WLC_IOCTL_MAXLEN
, NULL
);
6262 if (unlikely(err
)) {
6263 WL_ERR(("error (%d)\n", err
));
6266 wl_wme_cnt
= (wl_wme_cnt_t
*)iovar_buf
;
6268 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VO
].ac
, WIFI_AC_VO
);
6269 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VO
].tx_mpdu
, wl_wme_cnt
->tx
[AC_VO
].packets
);
6270 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VO
].rx_mpdu
, wl_wme_cnt
->rx
[AC_VO
].packets
);
6271 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VO
].mpdu_lost
,
6272 wl_wme_cnt
->tx_failed
[WIFI_AC_VO
].packets
);
6274 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VI
].ac
, WIFI_AC_VI
);
6275 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VI
].tx_mpdu
, wl_wme_cnt
->tx
[AC_VI
].packets
);
6276 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VI
].rx_mpdu
, wl_wme_cnt
->rx
[AC_VI
].packets
);
6277 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VI
].mpdu_lost
,
6278 wl_wme_cnt
->tx_failed
[WIFI_AC_VI
].packets
);
6280 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BE
].ac
, WIFI_AC_BE
);
6281 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BE
].tx_mpdu
, wl_wme_cnt
->tx
[AC_BE
].packets
);
6282 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BE
].rx_mpdu
, wl_wme_cnt
->rx
[AC_BE
].packets
);
6283 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BE
].mpdu_lost
,
6284 wl_wme_cnt
->tx_failed
[WIFI_AC_BE
].packets
);
6286 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BK
].ac
, WIFI_AC_BK
);
6287 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BK
].tx_mpdu
, wl_wme_cnt
->tx
[AC_BK
].packets
);
6288 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BK
].rx_mpdu
, wl_wme_cnt
->rx
[AC_BK
].packets
);
6289 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BK
].mpdu_lost
,
6290 wl_wme_cnt
->tx_failed
[WIFI_AC_BK
].packets
);
6292 err
= wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg
), "counters", NULL
, 0,
6293 iovar_buf
, WLC_IOCTL_MAXLEN
, NULL
);
6294 if (unlikely(err
)) {
6295 WL_ERR(("error (%d) - size = %zu\n", err
, sizeof(wl_cnt_wlc_t
)));
6299 CHK_CNTBUF_DATALEN(iovar_buf
, WLC_IOCTL_MAXLEN
);
6300 /* Translate traditional (ver <= 10) counters struct to new xtlv type struct */
6301 err
= wl_cntbuf_to_xtlv_format(NULL
, iovar_buf
, WLC_IOCTL_MAXLEN
, revinfo
.corerev
);
6302 if (err
!= BCME_OK
) {
6303 WL_ERR(("%s wl_cntbuf_to_xtlv_format ERR %d\n",
6304 __FUNCTION__
, err
));
6308 if (!(wlc_cnt
= GET_WLCCNT_FROM_CNTBUF(iovar_buf
))) {
6309 WL_ERR(("%s wlc_cnt NULL!\n", __FUNCTION__
));
6314 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BE
].retries
, wlc_cnt
->txretry
);
6316 err
= wl_cfgvendor_lstats_get_bcn_mbss(iovar_buf
, &rxbeaconmbss
);
6317 if (unlikely(err
)) {
6318 WL_ERR(("get_bcn_mbss error (%d)\n", err
));
6322 err
= wldev_get_rssi(bcmcfg_to_prmry_ndev(cfg
), &scbval
);
6323 if (unlikely(err
)) {
6324 WL_ERR(("get_rssi error (%d)\n", err
));
6328 COMPAT_ASSIGN_VALUE(iface
, beacon_rx
, rxbeaconmbss
);
6329 COMPAT_ASSIGN_VALUE(iface
, rssi_mgmt
, scbval
.val
);
6330 COMPAT_ASSIGN_VALUE(iface
, num_peers
, NUM_PEER
);
6331 COMPAT_ASSIGN_VALUE(iface
, peer_info
->num_rate
, NUM_RATE
);
6333 #ifdef CONFIG_COMPAT
6334 if (compat_task_state
) {
6335 memcpy(output
, &compat_iface
, sizeof(compat_iface
));
6336 output
+= (sizeof(compat_iface
) - sizeof(wifi_rate_stat
));
6338 #endif /* CONFIG_COMPAT */
6340 memcpy(output
, &iface
, sizeof(iface
));
6341 output
+= (sizeof(iface
) - sizeof(wifi_rate_stat
));
6344 err
= wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg
), "ratestat", NULL
, 0,
6345 iovar_buf
, WLC_IOCTL_MAXLEN
, NULL
);
6346 if (err
!= BCME_OK
&& err
!= BCME_UNSUPPORTED
) {
6347 WL_ERR(("error (%d) - size = %zu\n", err
, NUM_RATE
*sizeof(wifi_rate_stat
)));
6350 for (i
= 0; i
< NUM_RATE
; i
++) {
6352 (wifi_rate_stat
*)(iovar_buf
+ i
*sizeof(wifi_rate_stat
));
6353 p_wifi_rate_stat_v1
= (wifi_rate_stat_v1
*)output
;
6354 p_wifi_rate_stat_v1
->rate
.preamble
= p_wifi_rate_stat
->rate
.preamble
;
6355 p_wifi_rate_stat_v1
->rate
.nss
= p_wifi_rate_stat
->rate
.nss
;
6356 p_wifi_rate_stat_v1
->rate
.bw
= p_wifi_rate_stat
->rate
.bw
;
6357 p_wifi_rate_stat_v1
->rate
.rateMcsIdx
= p_wifi_rate_stat
->rate
.rateMcsIdx
;
6358 p_wifi_rate_stat_v1
->rate
.reserved
= p_wifi_rate_stat
->rate
.reserved
;
6359 p_wifi_rate_stat_v1
->rate
.bitrate
= p_wifi_rate_stat
->rate
.bitrate
;
6360 p_wifi_rate_stat_v1
->tx_mpdu
= p_wifi_rate_stat
->tx_mpdu
;
6361 p_wifi_rate_stat_v1
->rx_mpdu
= p_wifi_rate_stat
->rx_mpdu
;
6362 p_wifi_rate_stat_v1
->mpdu_lost
= p_wifi_rate_stat
->mpdu_lost
;
6363 p_wifi_rate_stat_v1
->retries
= p_wifi_rate_stat
->retries
;
6364 p_wifi_rate_stat_v1
->retries_short
= p_wifi_rate_stat
->retries_short
;
6365 p_wifi_rate_stat_v1
->retries_long
= p_wifi_rate_stat
->retries_long
;
6366 output
= (char *) &(p_wifi_rate_stat_v1
->retries_long
);
6367 output
+= sizeof(p_wifi_rate_stat_v1
->retries_long
);
6370 total_len
= sizeof(wifi_radio_stat_h
) +
6371 NUM_CHAN
* sizeof(wifi_channel_stat
);
6373 #ifdef CONFIG_COMPAT
6374 if (compat_task_state
) {
6375 total_len
+= sizeof(compat_wifi_iface_stat
);
6377 #endif /* CONFIG_COMPAT */
6379 total_len
+= sizeof(wifi_iface_stat
);
6382 total_len
= total_len
- sizeof(wifi_peer_info
) +
6383 NUM_PEER
* (sizeof(wifi_peer_info
) - sizeof(wifi_rate_stat_v1
) +
6384 NUM_RATE
* sizeof(wifi_rate_stat_v1
));
6386 if (total_len
> WLC_IOCTL_MAXLEN
) {
6387 WL_ERR(("Error! total_len:%d is unexpected value\n", total_len
));
6391 err
= wl_cfgvendor_send_cmd_reply(wiphy
, outdata
, total_len
);
6394 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
6398 MFREE(cfg
->osh
, outdata
, WLC_IOCTL_MAXLEN
);
6402 #endif /* LINKSTAT_SUPPORT */
6406 wl_cfgvendor_get_buf_data(const struct nlattr
*iter
, struct buf_data
**buf
)
6410 if (nla_len(iter
) != sizeof(struct buf_data
)) {
6411 WL_ERR(("Invalid len : %d\n", nla_len(iter
)));
6414 (*buf
) = (struct buf_data
*)nla_data(iter
);
6415 if (!(*buf
) || (((*buf
)->len
) <= 0) || !((*buf
)->data_buf
[0])) {
6416 WL_ERR(("Invalid buffer\n"));
6423 wl_cfgvendor_dbg_file_dump(struct wiphy
*wiphy
,
6424 struct wireless_dev
*wdev
, const void *data
, int len
)
6426 int ret
= BCME_OK
, rem
, type
= 0;
6427 const struct nlattr
*iter
;
6428 char *mem_buf
= NULL
;
6429 struct sk_buff
*skb
= NULL
;
6430 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6431 struct buf_data
*buf
;
6434 /* Alloc the SKB for vendor_event */
6435 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, CFG80211_VENDOR_CMD_REPLY_SKB_SZ
);
6437 WL_ERR(("skb allocation is failed\n"));
6441 WL_ERR(("%s\n", __FUNCTION__
));
6442 nla_for_each_attr(iter
, data
, len
, rem
) {
6443 type
= nla_type(iter
);
6444 ret
= wl_cfgvendor_get_buf_data(iter
, &buf
);
6448 case DUMP_BUF_ATTR_MEMDUMP
:
6449 ret
= dhd_os_get_socram_dump(bcmcfg_to_prmry_ndev(cfg
), &mem_buf
,
6450 (uint32
*)(&(buf
->len
)));
6452 WL_ERR(("failed to get_socram_dump : %d\n", ret
));
6455 ret
= dhd_export_debug_data(mem_buf
, NULL
, buf
->data_buf
[0],
6456 (int)buf
->len
, &pos
);
6459 case DUMP_BUF_ATTR_TIMESTAMP
:
6460 ret
= dhd_print_time_str(buf
->data_buf
[0], NULL
,
6461 (uint32
)buf
->len
, &pos
);
6463 #ifdef EWP_ECNTRS_LOGGING
6464 case DUMP_BUF_ATTR_ECNTRS
:
6465 ret
= dhd_print_ecntrs_data(bcmcfg_to_prmry_ndev(cfg
), NULL
,
6466 buf
->data_buf
[0], NULL
, (uint32
)buf
->len
, &pos
);
6468 #endif /* EWP_ECNTRS_LOGGING */
6469 #ifdef DHD_STATUS_LOGGING
6470 case DUMP_BUF_ATTR_STATUS_LOG
:
6471 ret
= dhd_print_status_log_data(bcmcfg_to_prmry_ndev(cfg
), NULL
,
6472 buf
->data_buf
[0], NULL
, (uint32
)buf
->len
, &pos
);
6474 #endif /* DHD_STATUS_LOGGING */
6475 #ifdef EWP_RTT_LOGGING
6476 case DUMP_BUF_ATTR_RTT_LOG
:
6477 ret
= dhd_print_rtt_data(bcmcfg_to_prmry_ndev(cfg
), NULL
,
6478 buf
->data_buf
[0], NULL
, (uint32
)buf
->len
, &pos
);
6480 #endif /* EWP_RTT_LOGGING */
6481 case DUMP_BUF_ATTR_DHD_DUMP
:
6482 ret
= dhd_print_dump_data(bcmcfg_to_prmry_ndev(cfg
), NULL
,
6483 buf
->data_buf
[0], NULL
, (uint32
)buf
->len
, &pos
);
6485 #if defined(BCMPCIE)
6486 case DUMP_BUF_ATTR_EXT_TRAP
:
6487 ret
= dhd_print_ext_trap_data(bcmcfg_to_prmry_ndev(cfg
), NULL
,
6488 buf
->data_buf
[0], NULL
, (uint32
)buf
->len
, &pos
);
6490 #endif /* BCMPCIE */
6491 #if defined(DHD_FW_COREDUMP) && defined(DNGL_EVENT_SUPPORT)
6492 case DUMP_BUF_ATTR_HEALTH_CHK
:
6493 ret
= dhd_print_health_chk_data(bcmcfg_to_prmry_ndev(cfg
), NULL
,
6494 buf
->data_buf
[0], NULL
, (uint32
)buf
->len
, &pos
);
6497 case DUMP_BUF_ATTR_COOKIE
:
6498 ret
= dhd_print_cookie_data(bcmcfg_to_prmry_ndev(cfg
), NULL
,
6499 buf
->data_buf
[0], NULL
, (uint32
)buf
->len
, &pos
);
6501 #ifdef DHD_DUMP_PCIE_RINGS
6502 case DUMP_BUF_ATTR_FLOWRING_DUMP
:
6503 ret
= dhd_print_flowring_data(bcmcfg_to_prmry_ndev(cfg
), NULL
,
6504 buf
->data_buf
[0], NULL
, (uint32
)buf
->len
, &pos
);
6507 case DUMP_BUF_ATTR_GENERAL_LOG
:
6508 ret
= dhd_get_dld_log_dump(bcmcfg_to_prmry_ndev(cfg
), NULL
,
6509 buf
->data_buf
[0], NULL
, (uint32
)buf
->len
,
6510 DLD_BUF_TYPE_GENERAL
, &pos
);
6513 case DUMP_BUF_ATTR_PRESERVE_LOG
:
6514 ret
= dhd_get_dld_log_dump(bcmcfg_to_prmry_ndev(cfg
), NULL
,
6515 buf
->data_buf
[0], NULL
, (uint32
)buf
->len
,
6516 DLD_BUF_TYPE_PRESERVE
, &pos
);
6519 case DUMP_BUF_ATTR_SPECIAL_LOG
:
6520 ret
= dhd_get_dld_log_dump(bcmcfg_to_prmry_ndev(cfg
), NULL
,
6521 buf
->data_buf
[0], NULL
, (uint32
)buf
->len
,
6522 DLD_BUF_TYPE_SPECIAL
, &pos
);
6524 #ifdef DHD_SSSR_DUMP
6525 case DUMP_BUF_ATTR_SSSR_C0_D11_BEFORE
:
6526 ret
= dhd_sssr_dump_d11_buf_before(bcmcfg_to_prmry_ndev(cfg
),
6527 buf
->data_buf
[0], (uint32
)buf
->len
, 0);
6530 case DUMP_BUF_ATTR_SSSR_C0_D11_AFTER
:
6531 ret
= dhd_sssr_dump_d11_buf_after(bcmcfg_to_prmry_ndev(cfg
),
6532 buf
->data_buf
[0], (uint32
)buf
->len
, 0);
6535 case DUMP_BUF_ATTR_SSSR_C1_D11_BEFORE
:
6536 ret
= dhd_sssr_dump_d11_buf_before(bcmcfg_to_prmry_ndev(cfg
),
6537 buf
->data_buf
[0], (uint32
)buf
->len
, 1);
6540 case DUMP_BUF_ATTR_SSSR_C1_D11_AFTER
:
6541 ret
= dhd_sssr_dump_d11_buf_after(bcmcfg_to_prmry_ndev(cfg
),
6542 buf
->data_buf
[0], (uint32
)buf
->len
, 1);
6545 case DUMP_BUF_ATTR_SSSR_DIG_BEFORE
:
6546 ret
= dhd_sssr_dump_dig_buf_before(bcmcfg_to_prmry_ndev(cfg
),
6547 buf
->data_buf
[0], (uint32
)buf
->len
);
6550 case DUMP_BUF_ATTR_SSSR_DIG_AFTER
:
6551 ret
= dhd_sssr_dump_dig_buf_after(bcmcfg_to_prmry_ndev(cfg
),
6552 buf
->data_buf
[0], (uint32
)buf
->len
);
6554 #endif /* DHD_SSSR_DUMP */
6555 #ifdef DNGL_AXI_ERROR_LOGGING
6556 case DUMP_BUF_ATTR_AXI_ERROR
:
6557 ret
= dhd_os_get_axi_error_dump(bcmcfg_to_prmry_ndev(cfg
),
6558 buf
->data_buf
[0], (uint32
)buf
->len
);
6560 #endif /* DNGL_AXI_ERROR_LOGGING */
6562 WL_ERR(("Unknown type: %d\n", type
));
6571 ret
= nla_put_u32(skb
, type
, (uint32
)(ret
));
6573 WL_ERR(("Failed to put type, ret:%d\n", ret
));
6576 ret
= cfg80211_vendor_cmd_reply(skb
);
6578 WL_ERR(("Vendor Command reply failed ret:%d \n", ret
));
6583 /* Free skb memory */
6588 #endif /* DHD_LOG_DUMP */
6592 wl_cfgvendor_dbg_trigger_mem_dump(struct wiphy
*wiphy
,
6593 struct wireless_dev
*wdev
, const void *data
, int len
)
6597 struct sk_buff
*skb
= NULL
;
6598 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6599 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
6601 WL_ERR(("wl_cfgvendor_dbg_trigger_mem_dump %d\n", __LINE__
));
6603 dhdp
->memdump_type
= DUMP_TYPE_CFG_VENDOR_TRIGGERED
;
6604 ret
= dhd_os_socram_dump(bcmcfg_to_prmry_ndev(cfg
), &alloc_len
);
6606 WL_ERR(("failed to call dhd_os_socram_dump : %d\n", ret
));
6609 /* Alloc the SKB for vendor_event */
6610 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, CFG80211_VENDOR_CMD_REPLY_SKB_SZ
);
6612 WL_ERR(("skb allocation is failed\n"));
6616 ret
= nla_put_u32(skb
, DEBUG_ATTRIBUTE_FW_DUMP_LEN
, alloc_len
);
6618 if (unlikely(ret
)) {
6619 WL_ERR(("Failed to put fw dump length, ret=%d\n", ret
));
6623 ret
= cfg80211_vendor_cmd_reply(skb
);
6626 WL_ERR(("Vendor Command reply failed ret:%d \n", ret
));
6631 /* Free skb memory */
6639 wl_cfgvendor_dbg_get_mem_dump(struct wiphy
*wiphy
,
6640 struct wireless_dev
*wdev
, const void *data
, int len
)
6642 int ret
= BCME_OK
, rem
, type
;
6644 uintptr_t user_buf
= (uintptr_t)NULL
;
6645 const struct nlattr
*iter
;
6646 char *mem_buf
= NULL
;
6647 struct sk_buff
*skb
= NULL
;
6648 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6650 nla_for_each_attr(iter
, data
, len
, rem
) {
6651 type
= nla_type(iter
);
6653 case DEBUG_ATTRIBUTE_FW_DUMP_LEN
:
6654 /* Check if the iter is valid and
6655 * buffer length is not already initialized.
6657 if ((nla_len(iter
) == sizeof(uint32
)) &&
6659 buf_len
= nla_get_u32(iter
);
6669 case DEBUG_ATTRIBUTE_FW_DUMP_DATA
:
6670 if (nla_len(iter
) != sizeof(uint64
)) {
6671 WL_ERR(("Invalid len\n"));
6675 user_buf
= (uintptr_t)nla_get_u64(iter
);
6682 WL_ERR(("Unknown type: %d\n", type
));
6687 if (buf_len
> 0 && user_buf
) {
6688 mem_buf
= vmalloc(buf_len
);
6690 WL_ERR(("failed to allocate mem_buf with size : %d\n", buf_len
));
6694 ret
= dhd_os_get_socram_dump(bcmcfg_to_prmry_ndev(cfg
), &mem_buf
, &buf_len
);
6696 WL_ERR(("failed to get_socram_dump : %d\n", ret
));
6699 #ifdef CONFIG_COMPAT
6700 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0))
6701 if (in_compat_syscall())
6703 if (is_compat_task())
6704 #endif /* LINUX_VER >= 4.6 */
6706 void * usr_ptr
= compat_ptr((uintptr_t) user_buf
);
6707 ret
= copy_to_user(usr_ptr
, mem_buf
, buf_len
);
6709 WL_ERR(("failed to copy memdump into user buffer : %d\n", ret
));
6714 #endif /* CONFIG_COMPAT */
6716 ret
= copy_to_user((void*)user_buf
, mem_buf
, buf_len
);
6718 WL_ERR(("failed to copy memdump into user buffer : %d\n", ret
));
6722 /* Alloc the SKB for vendor_event */
6723 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, CFG80211_VENDOR_CMD_REPLY_SKB_SZ
);
6725 WL_ERR(("skb allocation is failed\n"));
6729 /* Indicate the memdump is succesfully copied */
6730 ret
= nla_put(skb
, DEBUG_ATTRIBUTE_FW_DUMP_DATA
, sizeof(ret
), &ret
);
6732 WL_ERR(("Failed to put DEBUG_ATTRIBUTE_FW_DUMP_DATA, ret:%d\n", ret
));
6736 ret
= cfg80211_vendor_cmd_reply(skb
);
6739 WL_ERR(("Vendor Command reply failed ret:%d \n", ret
));
6746 /* Free skb memory */
6754 static int wl_cfgvendor_dbg_start_logging(struct wiphy
*wiphy
,
6755 struct wireless_dev
*wdev
, const void *data
, int len
)
6757 int ret
= BCME_OK
, rem
, type
;
6758 char ring_name
[DBGRING_NAME_MAX
] = {0};
6759 int log_level
= 0, flags
= 0, time_intval
= 0, threshold
= 0;
6760 const struct nlattr
*iter
;
6761 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6762 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6763 nla_for_each_attr(iter
, data
, len
, rem
) {
6764 type
= nla_type(iter
);
6766 case DEBUG_ATTRIBUTE_RING_NAME
:
6767 strncpy(ring_name
, nla_data(iter
),
6768 MIN(sizeof(ring_name
) -1, nla_len(iter
)));
6770 case DEBUG_ATTRIBUTE_LOG_LEVEL
:
6771 log_level
= nla_get_u32(iter
);
6773 case DEBUG_ATTRIBUTE_RING_FLAGS
:
6774 flags
= nla_get_u32(iter
);
6776 case DEBUG_ATTRIBUTE_LOG_TIME_INTVAL
:
6777 time_intval
= nla_get_u32(iter
);
6779 case DEBUG_ATTRIBUTE_LOG_MIN_DATA_SIZE
:
6780 threshold
= nla_get_u32(iter
);
6783 WL_ERR(("Unknown type: %d\n", type
));
6789 ret
= dhd_os_start_logging(dhd_pub
, ring_name
, log_level
, flags
, time_intval
, threshold
);
6791 WL_ERR(("start_logging is failed ret: %d\n", ret
));
6797 static int wl_cfgvendor_dbg_reset_logging(struct wiphy
*wiphy
,
6798 struct wireless_dev
*wdev
, const void *data
, int len
)
6801 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6802 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6804 ret
= dhd_os_reset_logging(dhd_pub
);
6806 WL_ERR(("reset logging is failed ret: %d\n", ret
));
6812 static int wl_cfgvendor_dbg_get_ring_status(struct wiphy
*wiphy
,
6813 struct wireless_dev
*wdev
, const void *data
, int len
)
6818 struct sk_buff
*skb
;
6819 dhd_dbg_ring_status_t dbg_ring_status
[DEBUG_RING_ID_MAX
];
6820 dhd_dbg_ring_status_t ring_status
;
6821 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6822 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6823 bzero(dbg_ring_status
, DBG_RING_STATUS_SIZE
* DEBUG_RING_ID_MAX
);
6825 for (ring_id
= DEBUG_RING_ID_INVALID
+ 1; ring_id
< DEBUG_RING_ID_MAX
; ring_id
++) {
6826 ret
= dhd_os_get_ring_status(dhd_pub
, ring_id
, &ring_status
);
6827 if (ret
== BCME_NOTFOUND
) {
6828 WL_DBG(("The ring (%d) is not found \n", ring_id
));
6829 } else if (ret
== BCME_OK
) {
6830 dbg_ring_status
[ring_cnt
++] = ring_status
;
6833 /* Alloc the SKB for vendor_event */
6834 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
,
6835 nla_total_size(DBG_RING_STATUS_SIZE
) * ring_cnt
+ nla_total_size(sizeof(ring_cnt
)));
6837 WL_ERR(("skb allocation is failed\n"));
6842 /* Ignore return of nla_put_u32 and nla_put since the skb allocated
6843 * above has a requested size for all payload
6845 (void)nla_put_u32(skb
, DEBUG_ATTRIBUTE_RING_NUM
, ring_cnt
);
6846 for (i
= 0; i
< ring_cnt
; i
++) {
6847 (void)nla_put(skb
, DEBUG_ATTRIBUTE_RING_STATUS
, DBG_RING_STATUS_SIZE
,
6848 &dbg_ring_status
[i
]);
6850 ret
= cfg80211_vendor_cmd_reply(skb
);
6853 WL_ERR(("Vendor Command reply failed ret:%d \n", ret
));
6859 static int wl_cfgvendor_dbg_get_ring_data(struct wiphy
*wiphy
,
6860 struct wireless_dev
*wdev
, const void *data
, int len
)
6862 int ret
= BCME_OK
, rem
, type
;
6863 char ring_name
[DBGRING_NAME_MAX
] = {0};
6864 const struct nlattr
*iter
;
6865 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6866 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6868 nla_for_each_attr(iter
, data
, len
, rem
) {
6869 type
= nla_type(iter
);
6871 case DEBUG_ATTRIBUTE_RING_NAME
:
6872 strlcpy(ring_name
, nla_data(iter
), sizeof(ring_name
));
6875 WL_ERR(("Unknown type: %d\n", type
));
6880 ret
= dhd_os_trigger_get_ring_data(dhd_pub
, ring_name
);
6882 WL_ERR(("trigger_get_data failed ret:%d\n", ret
));
6887 #endif /* DEBUGABILITY */
6889 static int wl_cfgvendor_dbg_get_feature(struct wiphy
*wiphy
,
6890 struct wireless_dev
*wdev
, const void *data
, int len
)
6893 u32 supported_features
= 0;
6894 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6895 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6897 ret
= dhd_os_dbg_get_feature(dhd_pub
, &supported_features
);
6899 WL_ERR(("dbg_get_feature failed ret:%d\n", ret
));
6902 ret
= wl_cfgvendor_send_cmd_reply(wiphy
, &supported_features
,
6903 sizeof(supported_features
));
6905 WL_ERR(("wl_cfgvendor_send_cmd_reply failed ret:%d\n", ret
));
6913 static void wl_cfgvendor_dbg_ring_send_evt(void *ctx
,
6914 const int ring_id
, const void *data
, const uint32 len
,
6915 const dhd_dbg_ring_status_t ring_status
)
6917 struct net_device
*ndev
= ctx
;
6918 struct wiphy
*wiphy
;
6920 struct sk_buff
*skb
;
6922 WL_ERR(("ndev is NULL\n"));
6925 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
6926 wiphy
= ndev
->ieee80211_ptr
->wiphy
;
6927 /* Alloc the SKB for vendor_event */
6928 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
6929 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
6930 skb
= cfg80211_vendor_event_alloc(wiphy
, NULL
, len
+ 100,
6931 GOOGLE_DEBUG_RING_EVENT
, kflags
);
6933 skb
= cfg80211_vendor_event_alloc(wiphy
, len
+ 100,
6934 GOOGLE_DEBUG_RING_EVENT
, kflags
);
6935 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
6936 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
6938 WL_ERR(("skb alloc failed"));
6941 nla_put(skb
, DEBUG_ATTRIBUTE_RING_STATUS
, sizeof(ring_status
), &ring_status
);
6942 nla_put(skb
, DEBUG_ATTRIBUTE_RING_DATA
, len
, data
);
6943 cfg80211_vendor_event(skb
, kflags
);
6945 #endif /* DEBUGABILITY */
6948 static int wl_cfgvendor_nla_put_sssr_dump_data(struct sk_buff
*skb
,
6949 struct net_device
*ndev
)
6952 #ifdef DHD_SSSR_DUMP
6953 uint32 arr_len
[DUMP_SSSR_ATTR_COUNT
];
6955 #endif /* DHD_SSSR_DUMP */
6956 char memdump_path
[MEMDUMP_PATH_LEN
];
6958 dhd_get_memdump_filename(ndev
, memdump_path
, MEMDUMP_PATH_LEN
,
6959 "sssr_dump_core_0_before_SR");
6960 ret
= nla_put_string(skb
, DUMP_FILENAME_ATTR_SSSR_CORE_0_BEFORE_DUMP
, memdump_path
);
6961 if (unlikely(ret
)) {
6962 WL_ERR(("Failed to nla put sssr core 0 before dump path, ret=%d\n", ret
));
6966 dhd_get_memdump_filename(ndev
, memdump_path
, MEMDUMP_PATH_LEN
,
6967 "sssr_dump_core_0_after_SR");
6968 ret
= nla_put_string(skb
, DUMP_FILENAME_ATTR_SSSR_CORE_0_AFTER_DUMP
, memdump_path
);
6969 if (unlikely(ret
)) {
6970 WL_ERR(("Failed to nla put sssr core 1 after dump path, ret=%d\n", ret
));
6974 dhd_get_memdump_filename(ndev
, memdump_path
, MEMDUMP_PATH_LEN
,
6975 "sssr_dump_core_1_before_SR");
6976 ret
= nla_put_string(skb
, DUMP_FILENAME_ATTR_SSSR_CORE_1_BEFORE_DUMP
, memdump_path
);
6977 if (unlikely(ret
)) {
6978 WL_ERR(("Failed to nla put sssr core 1 before dump path, ret=%d\n", ret
));
6982 dhd_get_memdump_filename(ndev
, memdump_path
, MEMDUMP_PATH_LEN
,
6983 "sssr_dump_core_1_after_SR");
6984 ret
= nla_put_string(skb
, DUMP_FILENAME_ATTR_SSSR_CORE_1_AFTER_DUMP
, memdump_path
);
6985 if (unlikely(ret
)) {
6986 WL_ERR(("Failed to nla put sssr core 1 after dump path, ret=%d\n", ret
));
6990 dhd_get_memdump_filename(ndev
, memdump_path
, MEMDUMP_PATH_LEN
,
6991 "sssr_dump_dig_before_SR");
6992 ret
= nla_put_string(skb
, DUMP_FILENAME_ATTR_SSSR_DIG_BEFORE_DUMP
, memdump_path
);
6993 if (unlikely(ret
)) {
6994 WL_ERR(("Failed to nla put sssr dig before dump path, ret=%d\n", ret
));
6998 dhd_get_memdump_filename(ndev
, memdump_path
, MEMDUMP_PATH_LEN
,
6999 "sssr_dump_dig_after_SR");
7000 ret
= nla_put_string(skb
, DUMP_FILENAME_ATTR_SSSR_DIG_AFTER_DUMP
, memdump_path
);
7001 if (unlikely(ret
)) {
7002 WL_ERR(("Failed to nla put sssr dig after dump path, ret=%d\n", ret
));
7006 #ifdef DHD_SSSR_DUMP
7007 memset(arr_len
, 0, sizeof(arr_len
));
7008 dhd_nla_put_sssr_dump_len(ndev
, arr_len
);
7010 for (i
= 0, j
= DUMP_SSSR_ATTR_START
; i
< DUMP_SSSR_ATTR_COUNT
; i
++, j
++) {
7012 ret
= nla_put_u32(skb
, j
, arr_len
[i
]);
7013 if (unlikely(ret
)) {
7014 WL_ERR(("Failed to nla put sssr dump len, ret=%d\n", ret
));
7019 #endif /* DHD_SSSR_DUMP */
7025 static int wl_cfgvendor_nla_put_debug_dump_data(struct sk_buff
*skb
,
7026 struct net_device
*ndev
)
7030 char dump_path
[128];
7032 ret
= dhd_get_debug_dump_file_name(ndev
, NULL
, dump_path
, sizeof(dump_path
));
7034 WL_ERR(("%s: Failed to get debug dump filename\n", __FUNCTION__
));
7037 ret
= nla_put_string(skb
, DUMP_FILENAME_ATTR_DEBUG_DUMP
, dump_path
);
7038 if (unlikely(ret
)) {
7039 WL_ERR(("Failed to nla put debug dump path, ret=%d\n", ret
));
7042 WL_ERR(("debug_dump path = %s%s\n", dump_path
, FILE_NAME_HAL_TAG
));
7043 wl_print_verinfo(wl_get_cfg(ndev
));
7045 len
= dhd_get_time_str_len();
7047 ret
= nla_put_u32(skb
, DUMP_LEN_ATTR_TIMESTAMP
, len
);
7048 if (unlikely(ret
)) {
7049 WL_ERR(("Failed to nla put time stamp length, ret=%d\n", ret
));
7054 len
= dhd_get_dld_len(DLD_BUF_TYPE_GENERAL
);
7056 ret
= nla_put_u32(skb
, DUMP_LEN_ATTR_GENERAL_LOG
, len
);
7057 if (unlikely(ret
)) {
7058 WL_ERR(("Failed to nla put general log length, ret=%d\n", ret
));
7062 #ifdef EWP_ECNTRS_LOGGING
7063 len
= dhd_get_ecntrs_len(ndev
, NULL
);
7065 ret
= nla_put_u32(skb
, DUMP_LEN_ATTR_ECNTRS
, len
);
7066 if (unlikely(ret
)) {
7067 WL_ERR(("Failed to nla put ecntrs length, ret=%d\n", ret
));
7071 #endif /* EWP_ECNTRS_LOGGING */
7072 len
= dhd_get_dld_len(DLD_BUF_TYPE_SPECIAL
);
7074 ret
= nla_put_u32(skb
, DUMP_LEN_ATTR_SPECIAL_LOG
, len
);
7075 if (unlikely(ret
)) {
7076 WL_ERR(("Failed to nla put special log length, ret=%d\n", ret
));
7080 len
= dhd_get_dhd_dump_len(ndev
, NULL
);
7082 ret
= nla_put_u32(skb
, DUMP_LEN_ATTR_DHD_DUMP
, len
);
7083 if (unlikely(ret
)) {
7084 WL_ERR(("Failed to nla put dhd dump length, ret=%d\n", ret
));
7089 #if defined(BCMPCIE)
7090 len
= dhd_get_ext_trap_len(ndev
, NULL
);
7092 ret
= nla_put_u32(skb
, DUMP_LEN_ATTR_EXT_TRAP
, len
);
7093 if (unlikely(ret
)) {
7094 WL_ERR(("Failed to nla put ext trap length, ret=%d\n", ret
));
7098 #endif /* BCMPCIE */
7100 #if defined(DHD_FW_COREDUMP) && defined(DNGL_EVENT_SUPPORT)
7101 len
= dhd_get_health_chk_len(ndev
, NULL
);
7103 ret
= nla_put_u32(skb
, DUMP_LEN_ATTR_HEALTH_CHK
, len
);
7104 if (unlikely(ret
)) {
7105 WL_ERR(("Failed to nla put health check length, ret=%d\n", ret
));
7111 len
= dhd_get_dld_len(DLD_BUF_TYPE_PRESERVE
);
7113 ret
= nla_put_u32(skb
, DUMP_LEN_ATTR_PRESERVE_LOG
, len
);
7114 if (unlikely(ret
)) {
7115 WL_ERR(("Failed to nla put preserve log length, ret=%d\n", ret
));
7120 len
= dhd_get_cookie_log_len(ndev
, NULL
);
7122 ret
= nla_put_u32(skb
, DUMP_LEN_ATTR_COOKIE
, len
);
7123 if (unlikely(ret
)) {
7124 WL_ERR(("Failed to nla put cookie length, ret=%d\n", ret
));
7128 #ifdef DHD_DUMP_PCIE_RINGS
7129 len
= dhd_get_flowring_len(ndev
, NULL
);
7131 ret
= nla_put_u32(skb
, DUMP_LEN_ATTR_FLOWRING_DUMP
, len
);
7132 if (unlikely(ret
)) {
7133 WL_ERR(("Failed to nla put flowring dump length, ret=%d\n", ret
));
7138 #ifdef DHD_STATUS_LOGGING
7139 len
= dhd_get_status_log_len(ndev
, NULL
);
7141 ret
= nla_put_u32(skb
, DUMP_LEN_ATTR_STATUS_LOG
, len
);
7142 if (unlikely(ret
)) {
7143 WL_ERR(("Failed to nla put status log length, ret=%d\n", ret
));
7147 #endif /* DHD_STATUS_LOGGING */
7148 #ifdef EWP_RTT_LOGGING
7149 len
= dhd_get_rtt_len(ndev
, NULL
);
7151 ret
= nla_put_u32(skb
, DUMP_LEN_ATTR_RTT_LOG
, len
);
7152 if (unlikely(ret
)) {
7153 WL_ERR(("Failed to nla put rtt log length, ret=%d\n", ret
));
7157 #endif /* EWP_RTT_LOGGING */
7161 #ifdef DNGL_AXI_ERROR_LOGGING
7162 static void wl_cfgvendor_nla_put_axi_error_data(struct sk_buff
*skb
,
7163 struct net_device
*ndev
)
7166 char axierrordump_path
[MEMDUMP_PATH_LEN
];
7167 int dumpsize
= dhd_os_get_axi_error_dump_size(ndev
);
7168 if (dumpsize
<= 0) {
7169 WL_ERR(("Failed to calcuate axi error dump len\n"));
7172 dhd_os_get_axi_error_filename(ndev
, axierrordump_path
, MEMDUMP_PATH_LEN
);
7173 ret
= nla_put_string(skb
, DUMP_FILENAME_ATTR_AXI_ERROR_DUMP
, axierrordump_path
);
7175 WL_ERR(("Failed to put filename\n"));
7178 ret
= nla_put_u32(skb
, DUMP_LEN_ATTR_AXI_ERROR
, dumpsize
);
7180 WL_ERR(("Failed to put filesize\n"));
7184 #endif /* DNGL_AXI_ERROR_LOGGING */
7186 static int wl_cfgvendor_nla_put_memdump_data(struct sk_buff
*skb
,
7187 struct net_device
*ndev
, const uint32 fw_len
)
7189 char memdump_path
[MEMDUMP_PATH_LEN
];
7192 dhd_get_memdump_filename(ndev
, memdump_path
, MEMDUMP_PATH_LEN
, "mem_dump");
7193 ret
= nla_put_string(skb
, DUMP_FILENAME_ATTR_MEM_DUMP
, memdump_path
);
7194 if (unlikely(ret
)) {
7195 WL_ERR(("Failed to nla put mem dump path, ret=%d\n", ret
));
7198 ret
= nla_put_u32(skb
, DUMP_LEN_ATTR_MEMDUMP
, fw_len
);
7199 if (unlikely(ret
)) {
7200 WL_ERR(("Failed to nla put mem dump length, ret=%d\n", ret
));
7208 static void wl_cfgvendor_dbg_send_file_dump_evt(void *ctx
, const void *data
,
7209 const uint32 len
, const uint32 fw_len
)
7211 struct net_device
*ndev
= ctx
;
7212 struct wiphy
*wiphy
;
7214 struct sk_buff
*skb
= NULL
;
7215 struct bcm_cfg80211
*cfg
;
7220 WL_ERR(("ndev is NULL\n"));
7224 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
7225 wiphy
= ndev
->ieee80211_ptr
->wiphy
;
7226 /* Alloc the SKB for vendor_event */
7227 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
7228 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
7229 skb
= cfg80211_vendor_event_alloc(wiphy
, NULL
, len
+ CFG80211_VENDOR_EVT_SKB_SZ
,
7230 GOOGLE_FILE_DUMP_EVENT
, kflags
);
7232 skb
= cfg80211_vendor_event_alloc(wiphy
, len
+ CFG80211_VENDOR_EVT_SKB_SZ
,
7233 GOOGLE_FILE_DUMP_EVENT
, kflags
);
7234 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
7235 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
7237 WL_ERR(("skb alloc failed"));
7241 cfg
= wiphy_priv(wiphy
);
7243 #ifdef DNGL_AXI_ERROR_LOGGING
7244 if (dhd_pub
->smmu_fault_occurred
) {
7245 wl_cfgvendor_nla_put_axi_error_data(skb
, ndev
);
7247 #endif /* DNGL_AXI_ERROR_LOGGING */
7248 #ifdef DHD_FW_COREDUMP
7249 if (dhd_pub
->memdump_enabled
|| (dhd_pub
->memdump_type
== DUMP_TYPE_BY_SYSDUMP
))
7251 if ((dhd_pub
->memdump_type
== DUMP_TYPE_BY_SYSDUMP
))
7254 if (((ret
= wl_cfgvendor_nla_put_memdump_data(skb
, ndev
, fw_len
)) < 0) ||
7255 ((ret
= wl_cfgvendor_nla_put_debug_dump_data(skb
, ndev
)) < 0) ||
7256 ((ret
= wl_cfgvendor_nla_put_sssr_dump_data(skb
, ndev
)) < 0)) {
7257 WL_ERR(("nla put failed\n"));
7261 /* TODO : Similar to above function add for debug_dump, sssr_dump, and pktlog also. */
7262 cfg80211_vendor_event(skb
, kflags
);
7266 dev_kfree_skb_any(skb
);
7269 #endif /* DHD_LOG_DUMP */
7271 static int wl_cfgvendor_dbg_get_version(struct wiphy
*wiphy
,
7272 struct wireless_dev
*wdev
, const void *data
, int len
)
7274 int ret
= BCME_OK
, rem
, type
;
7276 bool dhd_ver
= FALSE
;
7278 const struct nlattr
*iter
;
7279 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7281 buf_ptr
= (char *)MALLOCZ(cfg
->osh
, buf_len
);
7283 WL_ERR(("failed to allocate the buffer for version n"));
7287 nla_for_each_attr(iter
, data
, len
, rem
) {
7288 type
= nla_type(iter
);
7290 case DEBUG_ATTRIBUTE_GET_DRIVER
:
7293 case DEBUG_ATTRIBUTE_GET_FW
:
7297 WL_ERR(("Unknown type: %d\n", type
));
7302 ret
= dhd_os_get_version(bcmcfg_to_prmry_ndev(cfg
), dhd_ver
, &buf_ptr
, buf_len
);
7304 WL_ERR(("failed to get the version %d\n", ret
));
7307 ret
= wl_cfgvendor_send_cmd_reply(wiphy
, buf_ptr
, strlen(buf_ptr
));
7309 MFREE(cfg
->osh
, buf_ptr
, buf_len
);
7314 static int wl_cfgvendor_dbg_start_pkt_fate_monitoring(struct wiphy
*wiphy
,
7315 struct wireless_dev
*wdev
, const void *data
, int len
)
7317 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7318 dhd_pub_t
*dhd_pub
= cfg
->pub
;
7321 ret
= dhd_os_dbg_attach_pkt_monitor(dhd_pub
);
7322 if (unlikely(ret
)) {
7323 WL_ERR(("failed to start pkt fate monitoring, ret=%d", ret
));
7329 typedef int (*dbg_mon_get_pkts_t
) (dhd_pub_t
*dhdp
, void __user
*user_buf
,
7330 uint16 req_count
, uint16
*resp_count
);
7332 static int __wl_cfgvendor_dbg_get_pkt_fates(struct wiphy
*wiphy
,
7333 const void *data
, int len
, dbg_mon_get_pkts_t dbg_mon_get_pkts
)
7335 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7336 dhd_pub_t
*dhd_pub
= cfg
->pub
;
7337 struct sk_buff
*skb
= NULL
;
7338 const struct nlattr
*iter
;
7339 void __user
*user_buf
= NULL
;
7340 uint16 req_count
= 0, resp_count
= 0;
7341 int ret
, tmp
, type
, mem_needed
;
7343 nla_for_each_attr(iter
, data
, len
, tmp
) {
7344 type
= nla_type(iter
);
7346 case DEBUG_ATTRIBUTE_PKT_FATE_NUM
:
7347 req_count
= nla_get_u32(iter
);
7349 case DEBUG_ATTRIBUTE_PKT_FATE_DATA
:
7350 user_buf
= (void __user
*)(unsigned long) nla_get_u64(iter
);
7353 WL_ERR(("%s: no such attribute %d\n", __FUNCTION__
, type
));
7359 if (!req_count
|| !user_buf
) {
7360 WL_ERR(("%s: invalid request, user_buf=%p, req_count=%u\n",
7361 __FUNCTION__
, user_buf
, req_count
));
7366 ret
= dbg_mon_get_pkts(dhd_pub
, user_buf
, req_count
, &resp_count
);
7367 if (unlikely(ret
)) {
7368 WL_ERR(("failed to get packets, ret:%d \n", ret
));
7372 mem_needed
= VENDOR_REPLY_OVERHEAD
+ ATTRIBUTE_U32_LEN
;
7373 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
7374 if (unlikely(!skb
)) {
7375 WL_ERR(("skb alloc failed"));
7380 ret
= nla_put_u32(skb
, DEBUG_ATTRIBUTE_PKT_FATE_NUM
, resp_count
);
7382 WL_ERR(("Failed to put DEBUG_ATTRIBUTE_PKT_FATE_NUM, ret:%d\n", ret
));
7386 ret
= cfg80211_vendor_cmd_reply(skb
);
7387 if (unlikely(ret
)) {
7388 WL_ERR(("vendor Command reply failed ret:%d \n", ret
));
7393 /* Free skb memory */
7400 static int wl_cfgvendor_dbg_get_tx_pkt_fates(struct wiphy
*wiphy
,
7401 struct wireless_dev
*wdev
, const void *data
, int len
)
7405 ret
= __wl_cfgvendor_dbg_get_pkt_fates(wiphy
, data
, len
,
7406 dhd_os_dbg_monitor_get_tx_pkts
);
7407 if (unlikely(ret
)) {
7408 WL_ERR(("failed to get tx packets, ret:%d \n", ret
));
7414 static int wl_cfgvendor_dbg_get_rx_pkt_fates(struct wiphy
*wiphy
,
7415 struct wireless_dev
*wdev
, const void *data
, int len
)
7419 ret
= __wl_cfgvendor_dbg_get_pkt_fates(wiphy
, data
, len
,
7420 dhd_os_dbg_monitor_get_rx_pkts
);
7421 if (unlikely(ret
)) {
7422 WL_ERR(("failed to get rx packets, ret:%d \n", ret
));
7427 #endif /* DBG_PKT_MON */
7430 static int wl_cfgvendor_start_mkeep_alive(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
7431 const void *data
, int len
)
7433 /* max size of IP packet for keep alive */
7434 const int MKEEP_ALIVE_IP_PKT_MAX
= 256;
7436 int ret
= BCME_OK
, rem
, type
;
7437 uint8 mkeep_alive_id
= 0;
7438 uint8
*ip_pkt
= NULL
;
7439 uint16 ip_pkt_len
= 0;
7440 uint8 src_mac
[ETHER_ADDR_LEN
];
7441 uint8 dst_mac
[ETHER_ADDR_LEN
];
7442 uint32 period_msec
= 0;
7443 const struct nlattr
*iter
;
7444 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7445 dhd_pub_t
*dhd_pub
= cfg
->pub
;
7447 nla_for_each_attr(iter
, data
, len
, rem
) {
7448 type
= nla_type(iter
);
7450 case MKEEP_ALIVE_ATTRIBUTE_ID
:
7451 mkeep_alive_id
= nla_get_u8(iter
);
7453 case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN
:
7454 ip_pkt_len
= nla_get_u16(iter
);
7455 if (ip_pkt_len
> MKEEP_ALIVE_IP_PKT_MAX
) {
7460 case MKEEP_ALIVE_ATTRIBUTE_IP_PKT
:
7463 WL_ERR(("ip_pkt already allocated\n"));
7468 WL_ERR(("ip packet length is 0\n"));
7471 ip_pkt
= (u8
*)MALLOCZ(cfg
->osh
, ip_pkt_len
);
7472 if (ip_pkt
== NULL
) {
7474 WL_ERR(("Failed to allocate mem for ip packet\n"));
7477 memcpy(ip_pkt
, (u8
*)nla_data(iter
), ip_pkt_len
);
7479 case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR
:
7480 memcpy(src_mac
, nla_data(iter
), ETHER_ADDR_LEN
);
7482 case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR
:
7483 memcpy(dst_mac
, nla_data(iter
), ETHER_ADDR_LEN
);
7485 case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC
:
7486 period_msec
= nla_get_u32(iter
);
7489 WL_ERR(("Unknown type: %d\n", type
));
7495 if (ip_pkt
== NULL
) {
7497 WL_ERR(("ip packet is NULL\n"));
7501 ret
= dhd_dev_start_mkeep_alive(dhd_pub
, mkeep_alive_id
, ip_pkt
, ip_pkt_len
, src_mac
,
7502 dst_mac
, period_msec
);
7504 WL_ERR(("start_mkeep_alive is failed ret: %d\n", ret
));
7509 MFREE(cfg
->osh
, ip_pkt
, ip_pkt_len
);
7515 static int wl_cfgvendor_stop_mkeep_alive(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
7516 const void *data
, int len
)
7518 int ret
= BCME_OK
, rem
, type
;
7519 uint8 mkeep_alive_id
= 0;
7520 const struct nlattr
*iter
;
7521 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7522 dhd_pub_t
*dhd_pub
= cfg
->pub
;
7524 nla_for_each_attr(iter
, data
, len
, rem
) {
7525 type
= nla_type(iter
);
7527 case MKEEP_ALIVE_ATTRIBUTE_ID
:
7528 mkeep_alive_id
= nla_get_u8(iter
);
7531 WL_ERR(("Unknown type: %d\n", type
));
7537 ret
= dhd_dev_stop_mkeep_alive(dhd_pub
, mkeep_alive_id
);
7539 WL_ERR(("stop_mkeep_alive is failed ret: %d\n", ret
));
7544 #endif /* KEEP_ALIVE */
7546 #if defined(PKT_FILTER_SUPPORT) && defined(APF)
7548 wl_cfgvendor_apf_get_capabilities(struct wiphy
*wiphy
,
7549 struct wireless_dev
*wdev
, const void *data
, int len
)
7551 struct net_device
*ndev
= wdev_to_ndev(wdev
);
7552 struct sk_buff
*skb
= NULL
;
7553 int ret
, ver
, max_len
, mem_needed
;
7557 ret
= dhd_dev_apf_get_version(ndev
, &ver
);
7558 if (unlikely(ret
)) {
7559 WL_ERR(("APF get version failed, ret=%d\n", ret
));
7563 /* APF memory size limit */
7565 ret
= dhd_dev_apf_get_max_len(ndev
, &max_len
);
7566 if (unlikely(ret
)) {
7567 WL_ERR(("APF get maximum length failed, ret=%d\n", ret
));
7571 mem_needed
= VENDOR_REPLY_OVERHEAD
+ (ATTRIBUTE_U32_LEN
* 2);
7573 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
7574 if (unlikely(!skb
)) {
7575 WL_ERR(("%s: can't allocate %d bytes\n", __FUNCTION__
, mem_needed
));
7579 ret
= nla_put_u32(skb
, APF_ATTRIBUTE_VERSION
, ver
);
7581 WL_ERR(("Failed to put APF_ATTRIBUTE_VERSION, ret:%d\n", ret
));
7584 ret
= nla_put_u32(skb
, APF_ATTRIBUTE_MAX_LEN
, max_len
);
7586 WL_ERR(("Failed to put APF_ATTRIBUTE_MAX_LEN, ret:%d\n", ret
));
7590 ret
= cfg80211_vendor_cmd_reply(skb
);
7591 if (unlikely(ret
)) {
7592 WL_ERR(("vendor command reply failed, ret=%d\n", ret
));
7596 /* Free skb memory */
7602 wl_cfgvendor_apf_set_filter(struct wiphy
*wiphy
,
7603 struct wireless_dev
*wdev
, const void *data
, int len
)
7605 struct net_device
*ndev
= wdev_to_ndev(wdev
);
7606 const struct nlattr
*iter
;
7608 u32 program_len
= 0;
7610 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7613 WL_ERR(("Invalid len: %d\n", len
));
7617 nla_for_each_attr(iter
, data
, len
, tmp
) {
7618 type
= nla_type(iter
);
7620 case APF_ATTRIBUTE_PROGRAM_LEN
:
7621 /* check if the iter value is valid and program_len
7622 * is not already initialized.
7624 if (nla_len(iter
) == sizeof(uint32
) && !program_len
) {
7625 program_len
= nla_get_u32(iter
);
7631 if (program_len
> WL_APF_PROGRAM_MAX_SIZE
) {
7632 WL_ERR(("program len is more than expected len\n"));
7637 if (unlikely(!program_len
)) {
7638 WL_ERR(("zero program length\n"));
7643 case APF_ATTRIBUTE_PROGRAM
:
7644 if (unlikely(program
)) {
7645 WL_ERR(("program already allocated\n"));
7649 if (unlikely(!program_len
)) {
7650 WL_ERR(("program len is not set\n"));
7654 if (nla_len(iter
) != program_len
) {
7655 WL_ERR(("program_len is not same\n"));
7659 program
= MALLOCZ(cfg
->osh
, program_len
);
7660 if (unlikely(!program
)) {
7661 WL_ERR(("%s: can't allocate %d bytes\n",
7662 __FUNCTION__
, program_len
));
7666 memcpy(program
, (u8
*)nla_data(iter
), program_len
);
7669 WL_ERR(("%s: no such attribute %d\n", __FUNCTION__
, type
));
7675 ret
= dhd_dev_apf_add_filter(ndev
, program
, program_len
);
7679 MFREE(cfg
->osh
, program
, program_len
);
7683 #endif /* PKT_FILTER_SUPPORT && APF */
7685 #ifdef NDO_CONFIG_SUPPORT
7686 static int wl_cfgvendor_configure_nd_offload(struct wiphy
*wiphy
,
7687 struct wireless_dev
*wdev
, const void *data
, int len
)
7689 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7690 const struct nlattr
*iter
;
7691 int ret
= BCME_OK
, rem
, type
;
7694 nla_for_each_attr(iter
, data
, len
, rem
) {
7695 type
= nla_type(iter
);
7697 case ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE
:
7698 enable
= nla_get_u8(iter
);
7701 WL_ERR(("Unknown type: %d\n", type
));
7707 ret
= dhd_dev_ndo_cfg(bcmcfg_to_prmry_ndev(cfg
), enable
);
7709 WL_ERR(("dhd_dev_ndo_cfg() failed: %d\n", ret
));
7715 #endif /* NDO_CONFIG_SUPPORT */
7717 /* for kernel >= 4.13 NL80211 wl_cfg80211_set_pmk have to be used. */
7718 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0))
7719 static int wl_cfgvendor_set_pmk(struct wiphy
*wiphy
,
7720 struct wireless_dev
*wdev
, const void *data
, int len
)
7724 const struct nlattr
*iter
;
7726 struct net_device
*ndev
= wdev_to_ndev(wdev
);
7727 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7728 struct wl_security
*sec
;
7730 nla_for_each_attr(iter
, data
, len
, rem
) {
7731 type
= nla_type(iter
);
7733 case BRCM_ATTR_DRIVER_KEY_PMK
:
7734 if (nla_len(iter
) > sizeof(pmk
.key
)) {
7739 pmk
.key_len
= htod16(nla_len(iter
));
7740 bcopy((uint8
*)nla_data(iter
), pmk
.key
, len
);
7743 WL_ERR(("Unknown type: %d\n", type
));
7749 sec
= wl_read_prof(cfg
, ndev
, WL_PROF_SEC
);
7750 if ((sec
->wpa_auth
== WLAN_AKM_SUITE_8021X
) ||
7751 (sec
->wpa_auth
== WL_AKM_SUITE_SHA256_1X
)) {
7752 ret
= wldev_iovar_setbuf(ndev
, "okc_info_pmk", pmk
.key
, pmk
.key_len
, cfg
->ioctl_buf
,
7753 WLC_IOCTL_SMLEN
, &cfg
->ioctl_buf_sync
);
7755 /* could fail in case that 'okc' is not supported */
7756 WL_INFORM_MEM(("okc_info_pmk failed, err=%d (ignore)\n", ret
));
7760 ret
= wldev_ioctl_set(ndev
, WLC_SET_WSEC_PMK
, &pmk
, sizeof(pmk
));
7761 WL_INFORM_MEM(("IOVAR set_pmk ret:%d", ret
));
7765 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) */
7767 static int wl_cfgvendor_get_driver_feature(struct wiphy
*wiphy
,
7768 struct wireless_dev
*wdev
, const void *data
, int len
)
7771 u8 supported
[(BRCM_WLAN_VENDOR_FEATURES_MAX
/ 8) + 1] = {0};
7772 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7773 dhd_pub_t
*dhd_pub
= cfg
->pub
;
7774 struct sk_buff
*skb
;
7777 mem_needed
= VENDOR_REPLY_OVERHEAD
+ NLA_HDRLEN
+ sizeof(supported
);
7779 BCM_REFERENCE(dhd_pub
);
7781 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0))
7782 if (FW_SUPPORTED(dhd_pub
, idsup
)) {
7783 ret
= wl_features_set(supported
, sizeof(supported
),
7784 BRCM_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD
);
7786 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) */
7788 /* Alloc the SKB for vendor_event */
7789 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
7790 if (unlikely(!skb
)) {
7791 WL_ERR(("skb alloc failed"));
7796 ret
= nla_put(skb
, BRCM_ATTR_DRIVER_FEATURE_FLAGS
, sizeof(supported
), supported
);
7801 ret
= cfg80211_vendor_cmd_reply(skb
);
7806 static const struct wiphy_vendor_command wl_vendor_cmds
[] = {
7809 .vendor_id
= OUI_BRCM
,
7810 .subcmd
= BRCM_VENDOR_SCMD_PRIV_STR
7812 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7813 .doit
= wl_cfgvendor_priv_string_handler
7815 #ifdef BCM_PRIV_CMD_SUPPORT
7818 .vendor_id
= OUI_BRCM
,
7819 .subcmd
= BRCM_VENDOR_SCMD_BCM_STR
7821 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7822 .doit
= wl_cfgvendor_priv_bcm_handler
7824 #endif /* BCM_PRIV_CMD_SUPPORT */
7828 .vendor_id
= OUI_BRCM
,
7829 .subcmd
= BRCM_VENDOR_SCMD_BCM_PSK
7831 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7832 .doit
= wl_cfgvendor_set_sae_password
7835 #ifdef GSCAN_SUPPORT
7838 .vendor_id
= OUI_GOOGLE
,
7839 .subcmd
= GSCAN_SUBCMD_GET_CAPABILITIES
7841 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7842 .doit
= wl_cfgvendor_gscan_get_capabilities
7846 .vendor_id
= OUI_GOOGLE
,
7847 .subcmd
= GSCAN_SUBCMD_SET_CONFIG
7849 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7850 .doit
= wl_cfgvendor_set_scan_cfg
7854 .vendor_id
= OUI_GOOGLE
,
7855 .subcmd
= GSCAN_SUBCMD_SET_SCAN_CONFIG
7857 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7858 .doit
= wl_cfgvendor_set_batch_scan_cfg
7862 .vendor_id
= OUI_GOOGLE
,
7863 .subcmd
= GSCAN_SUBCMD_ENABLE_GSCAN
7865 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7866 .doit
= wl_cfgvendor_initiate_gscan
7870 .vendor_id
= OUI_GOOGLE
,
7871 .subcmd
= GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
7873 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7874 .doit
= wl_cfgvendor_enable_full_scan_result
7878 .vendor_id
= OUI_GOOGLE
,
7879 .subcmd
= GSCAN_SUBCMD_SET_HOTLIST
7881 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7882 .doit
= wl_cfgvendor_hotlist_cfg
7886 .vendor_id
= OUI_GOOGLE
,
7887 .subcmd
= GSCAN_SUBCMD_GET_SCAN_RESULTS
7889 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7890 .doit
= wl_cfgvendor_gscan_get_batch_results
7892 #endif /* GSCAN_SUPPORT */
7893 #if defined(GSCAN_SUPPORT) || defined(DHD_GET_VALID_CHANNELS)
7896 .vendor_id
= OUI_GOOGLE
,
7897 .subcmd
= GSCAN_SUBCMD_GET_CHANNEL_LIST
7899 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7900 .doit
= wl_cfgvendor_gscan_get_channel_list
7902 #endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */
7906 .vendor_id
= OUI_GOOGLE
,
7907 .subcmd
= RTT_SUBCMD_SET_CONFIG
7909 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7910 .doit
= wl_cfgvendor_rtt_set_config
7914 .vendor_id
= OUI_GOOGLE
,
7915 .subcmd
= RTT_SUBCMD_CANCEL_CONFIG
7917 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7918 .doit
= wl_cfgvendor_rtt_cancel_config
7922 .vendor_id
= OUI_GOOGLE
,
7923 .subcmd
= RTT_SUBCMD_GETCAPABILITY
7925 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7926 .doit
= wl_cfgvendor_rtt_get_capability
7930 .vendor_id
= OUI_GOOGLE
,
7931 .subcmd
= RTT_SUBCMD_GETAVAILCHANNEL
7933 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7934 .doit
= wl_cfgvendor_rtt_get_responder_info
7938 .vendor_id
= OUI_GOOGLE
,
7939 .subcmd
= RTT_SUBCMD_SET_RESPONDER
7941 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7942 .doit
= wl_cfgvendor_rtt_set_responder
7946 .vendor_id
= OUI_GOOGLE
,
7947 .subcmd
= RTT_SUBCMD_CANCEL_RESPONDER
7949 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7950 .doit
= wl_cfgvendor_rtt_cancel_responder
7952 #endif /* RTT_SUPPORT */
7955 .vendor_id
= OUI_GOOGLE
,
7956 .subcmd
= ANDR_WIFI_SUBCMD_GET_FEATURE_SET
7958 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7959 .doit
= wl_cfgvendor_get_feature_set
7963 .vendor_id
= OUI_GOOGLE
,
7964 .subcmd
= ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX
7966 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7967 .doit
= wl_cfgvendor_get_feature_set_matrix
7971 .vendor_id
= OUI_GOOGLE
,
7972 .subcmd
= ANDR_WIFI_RANDOM_MAC_OUI
7974 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7975 .doit
= wl_cfgvendor_set_rand_mac_oui
7977 #ifdef CUSTOM_FORCE_NODFS_FLAG
7980 .vendor_id
= OUI_GOOGLE
,
7981 .subcmd
= ANDR_WIFI_NODFS_CHANNELS
7983 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7984 .doit
= wl_cfgvendor_set_nodfs_flag
7986 #endif /* CUSTOM_FORCE_NODFS_FLAG */
7989 .vendor_id
= OUI_GOOGLE
,
7990 .subcmd
= ANDR_WIFI_SET_COUNTRY
7992 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7993 .doit
= wl_cfgvendor_set_country
7995 #ifdef LINKSTAT_SUPPORT
7998 .vendor_id
= OUI_GOOGLE
,
7999 .subcmd
= LSTATS_SUBCMD_GET_INFO
8001 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8002 .doit
= wl_cfgvendor_lstats_get_info
8004 #endif /* LINKSTAT_SUPPORT */
8006 #ifdef GSCAN_SUPPORT
8009 .vendor_id
= OUI_GOOGLE
,
8010 .subcmd
= GSCAN_SUBCMD_SET_EPNO_SSID
8012 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8013 .doit
= wl_cfgvendor_epno_cfg
8018 .vendor_id
= OUI_GOOGLE
,
8019 .subcmd
= WIFI_SUBCMD_SET_LAZY_ROAM_PARAMS
8021 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8022 .doit
= wl_cfgvendor_set_lazy_roam_cfg
8027 .vendor_id
= OUI_GOOGLE
,
8028 .subcmd
= WIFI_SUBCMD_ENABLE_LAZY_ROAM
8030 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8031 .doit
= wl_cfgvendor_enable_lazy_roam
8036 .vendor_id
= OUI_GOOGLE
,
8037 .subcmd
= WIFI_SUBCMD_SET_BSSID_PREF
8039 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8040 .doit
= wl_cfgvendor_set_bssid_pref
8043 #endif /* GSCAN_SUPPORT */
8044 #if defined(GSCAN_SUPPORT) || defined(ROAMEXP_SUPPORT)
8047 .vendor_id
= OUI_GOOGLE
,
8048 .subcmd
= WIFI_SUBCMD_SET_SSID_WHITELIST
8050 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8051 .doit
= wl_cfgvendor_set_ssid_whitelist
8056 .vendor_id
= OUI_GOOGLE
,
8057 .subcmd
= WIFI_SUBCMD_SET_BSSID_BLACKLIST
8059 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8060 .doit
= wl_cfgvendor_set_bssid_blacklist
8062 #endif /* GSCAN_SUPPORT || ROAMEXP_SUPPORT */
8063 #ifdef ROAMEXP_SUPPORT
8066 .vendor_id
= OUI_GOOGLE
,
8067 .subcmd
= WIFI_SUBCMD_FW_ROAM_POLICY
8069 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8070 .doit
= wl_cfgvendor_set_fw_roaming_state
8074 .vendor_id
= OUI_GOOGLE
,
8075 .subcmd
= WIFI_SUBCMD_ROAM_CAPABILITY
8077 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8078 .doit
= wl_cfgvendor_fw_roam_get_capability
8080 #endif /* ROAMEXP_SUPPORT */
8083 .vendor_id
= OUI_GOOGLE
,
8084 .subcmd
= DEBUG_GET_VER
8086 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8087 .doit
= wl_cfgvendor_dbg_get_version
8092 .vendor_id
= OUI_GOOGLE
,
8093 .subcmd
= DEBUG_GET_FILE_DUMP_BUF
8095 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8096 .doit
= wl_cfgvendor_dbg_file_dump
8098 #endif /* DHD_LOG_DUMP */
8103 .vendor_id
= OUI_GOOGLE
,
8104 .subcmd
= DEBUG_TRIGGER_MEM_DUMP
8106 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8107 .doit
= wl_cfgvendor_dbg_trigger_mem_dump
8111 .vendor_id
= OUI_GOOGLE
,
8112 .subcmd
= DEBUG_GET_MEM_DUMP
8114 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8115 .doit
= wl_cfgvendor_dbg_get_mem_dump
8119 .vendor_id
= OUI_GOOGLE
,
8120 .subcmd
= DEBUG_START_LOGGING
8122 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8123 .doit
= wl_cfgvendor_dbg_start_logging
8127 .vendor_id
= OUI_GOOGLE
,
8128 .subcmd
= DEBUG_RESET_LOGGING
8130 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8131 .doit
= wl_cfgvendor_dbg_reset_logging
8135 .vendor_id
= OUI_GOOGLE
,
8136 .subcmd
= DEBUG_GET_RING_STATUS
8138 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8139 .doit
= wl_cfgvendor_dbg_get_ring_status
8143 .vendor_id
= OUI_GOOGLE
,
8144 .subcmd
= DEBUG_GET_RING_DATA
8146 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8147 .doit
= wl_cfgvendor_dbg_get_ring_data
8149 #endif /* DEBUGABILITY */
8152 .vendor_id
= OUI_GOOGLE
,
8153 .subcmd
= DEBUG_GET_FEATURE
8155 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8156 .doit
= wl_cfgvendor_dbg_get_feature
8161 .vendor_id
= OUI_GOOGLE
,
8162 .subcmd
= DEBUG_START_PKT_FATE_MONITORING
8164 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8165 .doit
= wl_cfgvendor_dbg_start_pkt_fate_monitoring
8169 .vendor_id
= OUI_GOOGLE
,
8170 .subcmd
= DEBUG_GET_TX_PKT_FATES
8172 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8173 .doit
= wl_cfgvendor_dbg_get_tx_pkt_fates
8177 .vendor_id
= OUI_GOOGLE
,
8178 .subcmd
= DEBUG_GET_RX_PKT_FATES
8180 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8181 .doit
= wl_cfgvendor_dbg_get_rx_pkt_fates
8183 #endif /* DBG_PKT_MON */
8187 .vendor_id
= OUI_GOOGLE
,
8188 .subcmd
= WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE
8190 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8191 .doit
= wl_cfgvendor_start_mkeep_alive
8195 .vendor_id
= OUI_GOOGLE
,
8196 .subcmd
= WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE
8198 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8199 .doit
= wl_cfgvendor_stop_mkeep_alive
8201 #endif /* KEEP_ALIVE */
8205 .vendor_id
= OUI_GOOGLE
,
8206 .subcmd
= NAN_WIFI_SUBCMD_ENABLE
8208 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8209 .doit
= wl_cfgvendor_nan_start_handler
8213 .vendor_id
= OUI_GOOGLE
,
8214 .subcmd
= NAN_WIFI_SUBCMD_DISABLE
8216 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8217 .doit
= wl_cfgvendor_nan_stop_handler
8221 .vendor_id
= OUI_GOOGLE
,
8222 .subcmd
= NAN_WIFI_SUBCMD_CONFIG
8224 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8225 .doit
= wl_cfgvendor_nan_config_handler
8229 .vendor_id
= OUI_GOOGLE
,
8230 .subcmd
= NAN_WIFI_SUBCMD_REQUEST_PUBLISH
8232 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8233 .doit
= wl_cfgvendor_nan_req_publish
8237 .vendor_id
= OUI_GOOGLE
,
8238 .subcmd
= NAN_WIFI_SUBCMD_REQUEST_SUBSCRIBE
8240 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8241 .doit
= wl_cfgvendor_nan_req_subscribe
8245 .vendor_id
= OUI_GOOGLE
,
8246 .subcmd
= NAN_WIFI_SUBCMD_CANCEL_PUBLISH
8248 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8249 .doit
= wl_cfgvendor_nan_cancel_publish
8253 .vendor_id
= OUI_GOOGLE
,
8254 .subcmd
= NAN_WIFI_SUBCMD_CANCEL_SUBSCRIBE
8256 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8257 .doit
= wl_cfgvendor_nan_cancel_subscribe
8261 .vendor_id
= OUI_GOOGLE
,
8262 .subcmd
= NAN_WIFI_SUBCMD_TRANSMIT
8264 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8265 .doit
= wl_cfgvendor_nan_transmit
8269 .vendor_id
= OUI_GOOGLE
,
8270 .subcmd
= NAN_WIFI_SUBCMD_GET_CAPABILITIES
8272 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8273 .doit
= wl_cfgvendor_nan_get_capablities
8278 .vendor_id
= OUI_GOOGLE
,
8279 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE
8281 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8282 .doit
= wl_cfgvendor_nan_data_path_iface_create
8286 .vendor_id
= OUI_GOOGLE
,
8287 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE
8289 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8290 .doit
= wl_cfgvendor_nan_data_path_iface_delete
8294 .vendor_id
= OUI_GOOGLE
,
8295 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_REQUEST
8297 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8298 .doit
= wl_cfgvendor_nan_data_path_request
8302 .vendor_id
= OUI_GOOGLE
,
8303 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_RESPONSE
8305 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8306 .doit
= wl_cfgvendor_nan_data_path_response
8310 .vendor_id
= OUI_GOOGLE
,
8311 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_END
8313 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8314 .doit
= wl_cfgvendor_nan_data_path_end
8316 #ifdef WL_NAN_DISC_CACHE
8319 .vendor_id
= OUI_GOOGLE
,
8320 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_SEC_INFO
8322 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8323 .doit
= wl_cfgvendor_nan_data_path_sec_info
8325 #endif /* WL_NAN_DISC_CACHE */
8328 .vendor_id
= OUI_GOOGLE
,
8329 .subcmd
= NAN_WIFI_SUBCMD_VERSION_INFO
8331 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8332 .doit
= wl_cfgvendor_nan_version_info
8335 #if defined(PKT_FILTER_SUPPORT) && defined(APF)
8338 .vendor_id
= OUI_GOOGLE
,
8339 .subcmd
= APF_SUBCMD_GET_CAPABILITIES
8341 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8342 .doit
= wl_cfgvendor_apf_get_capabilities
8347 .vendor_id
= OUI_GOOGLE
,
8348 .subcmd
= APF_SUBCMD_SET_FILTER
8350 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8351 .doit
= wl_cfgvendor_apf_set_filter
8353 #endif /* PKT_FILTER_SUPPORT && APF */
8354 #ifdef NDO_CONFIG_SUPPORT
8357 .vendor_id
= OUI_GOOGLE
,
8358 .subcmd
= WIFI_SUBCMD_CONFIG_ND_OFFLOAD
8360 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8361 .doit
= wl_cfgvendor_configure_nd_offload
8363 #endif /* NDO_CONFIG_SUPPORT */
8364 #ifdef RSSI_MONITOR_SUPPORT
8367 .vendor_id
= OUI_GOOGLE
,
8368 .subcmd
= WIFI_SUBCMD_SET_RSSI_MONITOR
8370 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8371 .doit
= wl_cfgvendor_set_rssi_monitor
8373 #endif /* RSSI_MONITOR_SUPPORT */
8374 #ifdef DHD_WAKE_STATUS
8377 .vendor_id
= OUI_GOOGLE
,
8378 .subcmd
= DEBUG_GET_WAKE_REASON_STATS
8380 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8381 .doit
= wl_cfgvendor_get_wake_reason_stats
8383 #endif /* DHD_WAKE_STATUS */
8384 #ifdef DHDTCPACK_SUPPRESS
8387 .vendor_id
= OUI_GOOGLE
,
8388 .subcmd
= WIFI_SUBCMD_CONFIG_TCPACK_SUP
8390 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8391 .doit
= wl_cfgvendor_set_tcpack_sup_mode
8393 #endif /* DHDTCPACK_SUPPRESS */
8394 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0))
8397 .vendor_id
= OUI_BRCM
,
8398 .subcmd
= BRCM_VENDOR_SCMD_SET_PMK
8400 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8401 .doit
= wl_cfgvendor_set_pmk
8403 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) */
8406 .vendor_id
= OUI_BRCM
,
8407 .subcmd
= BRCM_VENDOR_SCMD_GET_FEATURES
8409 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8410 .doit
= wl_cfgvendor_get_driver_feature
8412 #if defined(WL_CFG80211) && defined(DHD_FILE_DUMP_EVENT)
8415 .vendor_id
= OUI_GOOGLE
,
8416 .subcmd
= DEBUG_FILE_DUMP_DONE_IND
8418 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8419 .doit
= wl_cfgvendor_notify_dump_completion
8421 #endif /* WL_CFG80211 && DHD_FILE_DUMP_EVENT */
8422 #if defined(WL_CFG80211)
8425 .vendor_id
= OUI_GOOGLE
,
8426 .subcmd
= DEBUG_SET_HAL_START
8428 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8429 .doit
= wl_cfgvendor_set_hal_started
8433 .vendor_id
= OUI_GOOGLE
,
8434 .subcmd
= DEBUG_SET_HAL_STOP
8436 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
8437 .doit
= wl_cfgvendor_stop_hal
8439 #endif /* WL_CFG80211 */
8442 static const struct nl80211_vendor_cmd_info wl_vendor_events
[] = {
8443 { OUI_BRCM
, BRCM_VENDOR_EVENT_UNSPEC
},
8444 { OUI_BRCM
, BRCM_VENDOR_EVENT_PRIV_STR
},
8445 { OUI_GOOGLE
, GOOGLE_GSCAN_SIGNIFICANT_EVENT
},
8446 { OUI_GOOGLE
, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT
},
8447 { OUI_GOOGLE
, GOOGLE_GSCAN_BATCH_SCAN_EVENT
},
8448 { OUI_GOOGLE
, GOOGLE_SCAN_FULL_RESULTS_EVENT
},
8449 { OUI_GOOGLE
, GOOGLE_RTT_COMPLETE_EVENT
},
8450 { OUI_GOOGLE
, GOOGLE_SCAN_COMPLETE_EVENT
},
8451 { OUI_GOOGLE
, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT
},
8452 { OUI_GOOGLE
, GOOGLE_SCAN_EPNO_EVENT
},
8453 { OUI_GOOGLE
, GOOGLE_DEBUG_RING_EVENT
},
8454 { OUI_GOOGLE
, GOOGLE_FW_DUMP_EVENT
},
8455 { OUI_GOOGLE
, GOOGLE_PNO_HOTSPOT_FOUND_EVENT
},
8456 { OUI_GOOGLE
, GOOGLE_RSSI_MONITOR_EVENT
},
8457 { OUI_GOOGLE
, GOOGLE_MKEEP_ALIVE_EVENT
},
8458 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_ENABLED
},
8459 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_DISABLED
},
8460 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH
},
8461 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_REPLIED
},
8462 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_PUBLISH_TERMINATED
},
8463 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED
},
8464 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_DE_EVENT
},
8465 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_FOLLOWUP
},
8466 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND
},
8467 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_DATA_REQUEST
},
8468 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_DATA_CONFIRMATION
},
8469 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_DATA_END
},
8470 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_BEACON
},
8471 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_SDF
},
8472 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_TCA
},
8473 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_SUBSCRIBE_UNMATCH
},
8474 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_UNKNOWN
},
8475 { OUI_GOOGLE
, GOOGLE_ROAM_EVENT_START
},
8476 { OUI_BRCM
, BRCM_VENDOR_EVENT_HANGED
},
8477 { OUI_BRCM
, BRCM_VENDOR_EVENT_SAE_KEY
},
8478 { OUI_BRCM
, BRCM_VENDOR_EVENT_BEACON_RECV
},
8479 { OUI_BRCM
, BRCM_VENDOR_EVENT_PORT_AUTHORIZED
},
8480 { OUI_GOOGLE
, GOOGLE_FILE_DUMP_EVENT
},
8481 { OUI_BRCM
, BRCM_VENDOR_EVENT_CU
},
8482 { OUI_BRCM
, BRCM_VENDOR_EVENT_WIPS
},
8483 { OUI_GOOGLE
, NAN_ASYNC_RESPONSE_DISABLED
}
8486 int wl_cfgvendor_attach(struct wiphy
*wiphy
, dhd_pub_t
*dhd
)
8489 WL_INFORM_MEM(("Vendor: Register BRCM cfg80211 vendor cmd(0x%x) interface \n",
8490 NL80211_CMD_VENDOR
));
8492 wiphy
->vendor_commands
= wl_vendor_cmds
;
8493 wiphy
->n_vendor_commands
= ARRAY_SIZE(wl_vendor_cmds
);
8494 wiphy
->vendor_events
= wl_vendor_events
;
8495 wiphy
->n_vendor_events
= ARRAY_SIZE(wl_vendor_events
);
8498 dhd_os_dbg_register_callback(FW_VERBOSE_RING_ID
, wl_cfgvendor_dbg_ring_send_evt
);
8499 dhd_os_dbg_register_callback(DHD_EVENT_RING_ID
, wl_cfgvendor_dbg_ring_send_evt
);
8500 #endif /* DEBUGABILITY */
8502 dhd_os_dbg_register_urgent_notifier(dhd
, wl_cfgvendor_dbg_send_file_dump_evt
);
8503 #endif /* DHD_LOG_DUMP */
8508 int wl_cfgvendor_detach(struct wiphy
*wiphy
)
8510 WL_INFORM_MEM(("Vendor: Unregister BRCM cfg80211 vendor interface \n"));
8512 wiphy
->vendor_commands
= NULL
;
8513 wiphy
->vendor_events
= NULL
;
8514 wiphy
->n_vendor_commands
= 0;
8515 wiphy
->n_vendor_events
= 0;
8519 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */