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 818247 2019-05-07 04:15:13Z $
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
);
151 #endif /* WL_SUPP_EVENT */
154 * This API is to be used for asynchronous vendor events. This
155 * shouldn't be used in response to a vendor command from its
156 * do_it handler context (instead wl_cfgvendor_send_cmd_reply should
159 int wl_cfgvendor_send_async_event(struct wiphy
*wiphy
,
160 struct net_device
*dev
, int event_id
, const void *data
, int len
)
165 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
167 /* Alloc the SKB for vendor_event */
168 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
169 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
170 skb
= cfg80211_vendor_event_alloc(wiphy
, ndev_to_wdev(dev
), len
, event_id
, kflags
);
172 skb
= cfg80211_vendor_event_alloc(wiphy
, len
, event_id
, kflags
);
173 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
174 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
176 WL_ERR(("skb alloc failed"));
180 /* Push the data to the skb */
181 nla_put_nohdr(skb
, len
, data
);
183 cfg80211_vendor_event(skb
, kflags
);
189 wl_cfgvendor_send_cmd_reply(struct wiphy
*wiphy
,
190 const void *data
, int len
)
195 /* Alloc the SKB for vendor_event */
196 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, len
);
197 if (unlikely(!skb
)) {
198 WL_ERR(("skb alloc failed"));
203 /* Push the data to the skb */
204 nla_put_nohdr(skb
, len
, data
);
205 err
= cfg80211_vendor_cmd_reply(skb
);
207 WL_DBG(("wl_cfgvendor_send_cmd_reply status %d", err
));
212 wl_cfgvendor_get_feature_set(struct wiphy
*wiphy
,
213 struct wireless_dev
*wdev
, const void *data
, int len
)
216 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
219 reply
= dhd_dev_get_feature_set(bcmcfg_to_prmry_ndev(cfg
));
221 err
= wl_cfgvendor_send_cmd_reply(wiphy
, &reply
, sizeof(int));
223 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
229 wl_cfgvendor_get_feature_set_matrix(struct wiphy
*wiphy
,
230 struct wireless_dev
*wdev
, const void *data
, int len
)
233 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
238 mem_needed
= VENDOR_REPLY_OVERHEAD
+
239 (ATTRIBUTE_U32_LEN
* MAX_FEATURE_SET_CONCURRRENT_GROUPS
) + ATTRIBUTE_U32_LEN
;
241 /* Alloc the SKB for vendor_event */
242 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
243 if (unlikely(!skb
)) {
244 WL_ERR(("skb alloc failed"));
249 nla_put_u32(skb
, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET
, MAX_FEATURE_SET_CONCURRRENT_GROUPS
);
250 for (i
= 0; i
< MAX_FEATURE_SET_CONCURRRENT_GROUPS
; i
++) {
251 reply
= dhd_dev_get_feature_set_matrix(bcmcfg_to_prmry_ndev(cfg
), i
);
252 if (reply
!= WIFI_FEATURE_INVALID
) {
253 nla_put_u32(skb
, ANDR_WIFI_ATTRIBUTE_FEATURE_SET
, reply
);
257 err
= cfg80211_vendor_cmd_reply(skb
);
260 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
267 wl_cfgvendor_set_rand_mac_oui(struct wiphy
*wiphy
,
268 struct wireless_dev
*wdev
, const void *data
, int len
)
271 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
275 WL_ERR(("data is not available\n"));
280 WL_ERR(("invalid len %d\n", len
));
284 type
= nla_type(data
);
286 if (type
== ANDR_WIFI_ATTRIBUTE_RANDOM_MAC_OUI
) {
287 if (nla_len(data
) != DOT11_OUI_LEN
) {
288 WL_ERR(("nla_len not matched.\n"));
291 err
= dhd_dev_cfg_rand_mac_oui(bcmcfg_to_prmry_ndev(cfg
), nla_data(data
));
294 WL_ERR(("Bad OUI, could not set:%d \n", err
));
299 #ifdef CUSTOM_FORCE_NODFS_FLAG
301 wl_cfgvendor_set_nodfs_flag(struct wiphy
*wiphy
,
302 struct wireless_dev
*wdev
, const void *data
, int len
)
305 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
310 WL_ERR(("data is not available\n"));
315 WL_ERR(("invalid len %d\n", len
));
319 type
= nla_type(data
);
320 if (type
== ANDR_WIFI_ATTRIBUTE_NODFS_SET
) {
321 nodfs
= nla_get_u32(data
);
322 err
= dhd_dev_set_nodfs(bcmcfg_to_prmry_ndev(cfg
), nodfs
);
327 #endif /* CUSTOM_FORCE_NODFS_FLAG */
330 wl_cfgvendor_set_country(struct wiphy
*wiphy
,
331 struct wireless_dev
*wdev
, const void *data
, int len
)
333 int err
= BCME_ERROR
, rem
, type
;
334 char country_code
[WLC_CNTRY_BUF_SZ
] = {0};
335 const struct nlattr
*iter
;
336 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
337 struct net_device
*primary_ndev
= bcmcfg_to_prmry_ndev(cfg
);
339 nla_for_each_attr(iter
, data
, len
, rem
) {
340 type
= nla_type(iter
);
342 case ANDR_WIFI_ATTRIBUTE_COUNTRY
:
343 memcpy(country_code
, nla_data(iter
),
344 MIN(nla_len(iter
), WLC_CNTRY_BUF_SZ
));
347 WL_ERR(("Unknown type: %d\n", type
));
352 /* country code is unique for dongle..hence using primary interface. */
353 err
= wldev_set_country(primary_ndev
, country_code
, true, true, -1);
355 WL_ERR(("Set country failed ret:%d\n", err
));
363 wl_cfgvendor_send_hotlist_event(struct wiphy
*wiphy
,
364 struct net_device
*dev
, void *data
, int len
, wl_vendor_event_t event
)
369 int malloc_len
, total
, iter_cnt_to_send
, cnt
;
370 gscan_results_cache_t
*cache
= (gscan_results_cache_t
*)data
;
372 total
= len
/sizeof(wifi_gscan_result_t
);
374 malloc_len
= (total
* sizeof(wifi_gscan_result_t
)) + VENDOR_DATA_OVERHEAD
;
375 if (malloc_len
> NLMSG_DEFAULT_SIZE
) {
376 malloc_len
= NLMSG_DEFAULT_SIZE
;
379 (malloc_len
- VENDOR_DATA_OVERHEAD
)/sizeof(wifi_gscan_result_t
);
380 total
= total
- iter_cnt_to_send
;
382 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
384 /* Alloc the SKB for vendor_event */
385 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
386 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
387 skb
= cfg80211_vendor_event_alloc(wiphy
, ndev_to_wdev(dev
),
388 malloc_len
, event
, kflags
);
390 skb
= cfg80211_vendor_event_alloc(wiphy
, malloc_len
, event
, kflags
);
391 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
392 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
394 WL_ERR(("skb alloc failed"));
398 while (cache
&& iter_cnt_to_send
) {
399 ptr
= (const void *) &cache
->results
[cache
->tot_consumed
];
401 if (iter_cnt_to_send
< (cache
->tot_count
- cache
->tot_consumed
)) {
402 cnt
= iter_cnt_to_send
;
404 cnt
= (cache
->tot_count
- cache
->tot_consumed
);
407 iter_cnt_to_send
-= cnt
;
408 cache
->tot_consumed
+= cnt
;
409 /* Push the data to the skb */
410 nla_append(skb
, cnt
* sizeof(wifi_gscan_result_t
), ptr
);
411 if (cache
->tot_consumed
== cache
->tot_count
) {
417 cfg80211_vendor_event(skb
, kflags
);
424 wl_cfgvendor_gscan_get_capabilities(struct wiphy
*wiphy
,
425 struct wireless_dev
*wdev
, const void *data
, int len
)
428 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
429 dhd_pno_gscan_capabilities_t
*reply
= NULL
;
430 uint32 reply_len
= 0;
432 reply
= dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg
),
433 DHD_PNO_GET_CAPABILITIES
, NULL
, &reply_len
);
435 WL_ERR(("Could not get capabilities\n"));
440 err
= wl_cfgvendor_send_cmd_reply(wiphy
, reply
, reply_len
);
443 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
446 MFREE(cfg
->osh
, reply
, reply_len
);
451 wl_cfgvendor_gscan_get_batch_results(struct wiphy
*wiphy
,
452 struct wireless_dev
*wdev
, const void *data
, int len
)
455 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
456 gscan_results_cache_t
*results
, *iter
;
457 uint32 reply_len
, is_done
= 1;
458 int32 mem_needed
, num_results_iter
;
459 wifi_gscan_result_t
*ptr
;
460 uint16 num_scan_ids
, num_results
;
462 struct nlattr
*scan_hdr
, *complete_flag
;
464 err
= dhd_dev_wait_batch_results_complete(bcmcfg_to_prmry_ndev(cfg
));
468 err
= dhd_dev_pno_lock_access_batch_results(bcmcfg_to_prmry_ndev(cfg
));
469 if (err
!= BCME_OK
) {
470 WL_ERR(("Can't obtain lock to access batch results %d\n", err
));
473 results
= dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg
),
474 DHD_PNO_GET_BATCH_RESULTS
, NULL
, &reply_len
);
476 WL_ERR(("No results to send %d\n", err
));
477 err
= wl_cfgvendor_send_cmd_reply(wiphy
, results
, 0);
480 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
481 dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg
));
484 num_scan_ids
= reply_len
& 0xFFFF;
485 num_results
= (reply_len
& 0xFFFF0000) >> 16;
486 mem_needed
= (num_results
* sizeof(wifi_gscan_result_t
)) +
487 (num_scan_ids
* GSCAN_BATCH_RESULT_HDR_LEN
) +
488 VENDOR_REPLY_OVERHEAD
+ SCAN_RESULTS_COMPLETE_FLAG_LEN
;
490 if (mem_needed
> (int32
)NLMSG_DEFAULT_SIZE
) {
491 mem_needed
= (int32
)NLMSG_DEFAULT_SIZE
;
494 WL_TRACE(("is_done %d mem_needed %d max_mem %d\n", is_done
, mem_needed
,
495 (int)NLMSG_DEFAULT_SIZE
));
496 /* Alloc the SKB for vendor_event */
497 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
498 if (unlikely(!skb
)) {
499 WL_ERR(("skb alloc failed"));
500 dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg
));
504 complete_flag
= nla_reserve(skb
, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE
,
506 mem_needed
= mem_needed
- (SCAN_RESULTS_COMPLETE_FLAG_LEN
+ VENDOR_REPLY_OVERHEAD
);
509 num_results_iter
= (mem_needed
- (int32
)GSCAN_BATCH_RESULT_HDR_LEN
);
510 num_results_iter
/= (int32
)sizeof(wifi_gscan_result_t
);
511 if (num_results_iter
<= 0 ||
512 ((iter
->tot_count
- iter
->tot_consumed
) > num_results_iter
)) {
515 scan_hdr
= nla_nest_start(skb
, GSCAN_ATTRIBUTE_SCAN_RESULTS
);
516 /* no more room? we are done then (for now) */
517 if (scan_hdr
== NULL
) {
521 nla_put_u32(skb
, GSCAN_ATTRIBUTE_SCAN_ID
, iter
->scan_id
);
522 nla_put_u8(skb
, GSCAN_ATTRIBUTE_SCAN_FLAGS
, iter
->flag
);
523 nla_put_u32(skb
, GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK
, iter
->scan_ch_bucket
);
525 num_results_iter
= iter
->tot_count
- iter
->tot_consumed
;
527 nla_put_u32(skb
, GSCAN_ATTRIBUTE_NUM_OF_RESULTS
, num_results_iter
);
528 if (num_results_iter
) {
529 ptr
= &iter
->results
[iter
->tot_consumed
];
530 iter
->tot_consumed
+= num_results_iter
;
531 nla_put(skb
, GSCAN_ATTRIBUTE_SCAN_RESULTS
,
532 num_results_iter
* sizeof(wifi_gscan_result_t
), ptr
);
534 nla_nest_end(skb
, scan_hdr
);
535 mem_needed
-= GSCAN_BATCH_RESULT_HDR_LEN
+
536 (num_results_iter
* sizeof(wifi_gscan_result_t
));
539 MFREE(cfg
->osh
, results
, reply_len
);
540 /* Returns TRUE if all result consumed */
541 is_done
= dhd_dev_gscan_batch_cache_cleanup(bcmcfg_to_prmry_ndev(cfg
));
542 memcpy(nla_data(complete_flag
), &is_done
, sizeof(is_done
));
543 dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg
));
544 return cfg80211_vendor_cmd_reply(skb
);
548 wl_cfgvendor_initiate_gscan(struct wiphy
*wiphy
,
549 struct wireless_dev
*wdev
, const void *data
, int len
)
552 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
556 const struct nlattr
*iter
;
558 nla_for_each_attr(iter
, data
, len
, tmp
) {
559 type
= nla_type(iter
);
560 if (type
== GSCAN_ATTRIBUTE_ENABLE_FEATURE
)
561 run
= nla_get_u32(iter
);
562 else if (type
== GSCAN_ATTRIBUTE_FLUSH_FEATURE
)
563 flush
= nla_get_u32(iter
);
567 err
= dhd_dev_pno_run_gscan(bcmcfg_to_prmry_ndev(cfg
), run
, flush
);
570 WL_ERR(("Could not run gscan:%d \n", err
));
580 wl_cfgvendor_enable_full_scan_result(struct wiphy
*wiphy
,
581 struct wireless_dev
*wdev
, const void *data
, int len
)
584 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
586 bool real_time
= FALSE
;
589 WL_ERR(("data is not available\n"));
594 WL_ERR(("invalid len %d\n", len
));
598 type
= nla_type(data
);
600 if (type
== GSCAN_ATTRIBUTE_ENABLE_FULL_SCAN_RESULTS
) {
601 real_time
= nla_get_u32(data
);
603 err
= dhd_dev_pno_enable_full_scan_result(bcmcfg_to_prmry_ndev(cfg
), real_time
);
606 WL_ERR(("Could not run gscan:%d \n", err
));
617 wl_cfgvendor_set_scan_cfg_bucket(const struct nlattr
*prev
,
618 gscan_scan_params_t
*scan_param
, int num
)
620 struct dhd_pno_gscan_channel_bucket
*ch_bucket
;
622 int type
, err
= 0, rem
;
623 const struct nlattr
*cur
, *next
;
625 nla_for_each_nested(cur
, prev
, rem
) {
626 type
= nla_type(cur
);
627 ch_bucket
= scan_param
->channel_bucket
;
629 case GSCAN_ATTRIBUTE_BUCKET_ID
:
631 case GSCAN_ATTRIBUTE_BUCKET_PERIOD
:
632 if (nla_len(cur
) != sizeof(uint32
)) {
637 ch_bucket
[num
].bucket_freq_multiple
=
638 nla_get_u32(cur
) / MSEC_PER_SEC
;
640 case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS
:
641 if (nla_len(cur
) != sizeof(uint32
)) {
645 ch_bucket
[num
].num_channels
= nla_get_u32(cur
);
646 if (ch_bucket
[num
].num_channels
>
647 GSCAN_MAX_CHANNELS_IN_BUCKET
) {
648 WL_ERR(("channel range:%d,bucket:%d\n",
649 ch_bucket
[num
].num_channels
,
655 case GSCAN_ATTRIBUTE_BUCKET_CHANNELS
:
656 nla_for_each_nested(next
, cur
, rem
) {
657 if (k
>= GSCAN_MAX_CHANNELS_IN_BUCKET
)
659 if (nla_len(next
) != sizeof(uint32
)) {
663 ch_bucket
[num
].chan_list
[k
] = nla_get_u32(next
);
667 case GSCAN_ATTRIBUTE_BUCKETS_BAND
:
668 if (nla_len(cur
) != sizeof(uint32
)) {
672 ch_bucket
[num
].band
= (uint16
)nla_get_u32(cur
);
674 case GSCAN_ATTRIBUTE_REPORT_EVENTS
:
675 if (nla_len(cur
) != sizeof(uint32
)) {
679 ch_bucket
[num
].report_flag
= (uint8
)nla_get_u32(cur
);
681 case GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT
:
682 if (nla_len(cur
) != sizeof(uint32
)) {
686 ch_bucket
[num
].repeat
= (uint16
)nla_get_u32(cur
);
688 case GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD
:
689 if (nla_len(cur
) != sizeof(uint32
)) {
693 ch_bucket
[num
].bucket_max_multiple
=
694 nla_get_u32(cur
) / MSEC_PER_SEC
;
697 WL_ERR(("unknown attr type:%d\n", type
));
708 wl_cfgvendor_set_scan_cfg(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
709 const void *data
, int len
)
712 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
713 gscan_scan_params_t
*scan_param
;
716 const struct nlattr
*iter
;
718 scan_param
= (gscan_scan_params_t
*)MALLOCZ(cfg
->osh
,
719 sizeof(gscan_scan_params_t
));
721 WL_ERR(("Could not set GSCAN scan cfg, mem alloc failure\n"));
727 scan_param
->scan_fr
= PNO_SCAN_MIN_FW_SEC
;
728 nla_for_each_attr(iter
, data
, len
, tmp
) {
729 type
= nla_type(iter
);
731 if (j
>= GSCAN_MAX_CH_BUCKETS
) {
736 case GSCAN_ATTRIBUTE_BASE_PERIOD
:
737 if (nla_len(iter
) != sizeof(uint32
)) {
741 scan_param
->scan_fr
= nla_get_u32(iter
) / MSEC_PER_SEC
;
743 case GSCAN_ATTRIBUTE_NUM_BUCKETS
:
744 if (nla_len(iter
) != sizeof(uint32
)) {
748 scan_param
->nchannel_buckets
= nla_get_u32(iter
);
749 if (scan_param
->nchannel_buckets
>=
750 GSCAN_MAX_CH_BUCKETS
) {
751 WL_ERR(("ncha_buck out of range %d\n",
752 scan_param
->nchannel_buckets
));
757 case GSCAN_ATTRIBUTE_CH_BUCKET_1
:
758 case GSCAN_ATTRIBUTE_CH_BUCKET_2
:
759 case GSCAN_ATTRIBUTE_CH_BUCKET_3
:
760 case GSCAN_ATTRIBUTE_CH_BUCKET_4
:
761 case GSCAN_ATTRIBUTE_CH_BUCKET_5
:
762 case GSCAN_ATTRIBUTE_CH_BUCKET_6
:
763 case GSCAN_ATTRIBUTE_CH_BUCKET_7
:
764 err
= wl_cfgvendor_set_scan_cfg_bucket(iter
, scan_param
, j
);
766 WL_ERR(("set_scan_cfg_buck error:%d\n", err
));
772 WL_ERR(("Unknown type %d\n", type
));
778 err
= dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
779 DHD_PNO_SCAN_CFG_ID
, scan_param
, FALSE
);
782 WL_ERR(("Could not set GSCAN scan cfg\n"));
787 MFREE(cfg
->osh
, scan_param
, sizeof(gscan_scan_params_t
));
793 wl_cfgvendor_hotlist_cfg(struct wiphy
*wiphy
,
794 struct wireless_dev
*wdev
, const void *data
, int len
)
797 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
798 gscan_hotlist_scan_params_t
*hotlist_params
;
799 int tmp
, tmp1
, tmp2
, type
, j
= 0, dummy
;
800 const struct nlattr
*outer
, *inner
= NULL
, *iter
;
802 struct bssid_t
*pbssid
;
804 BCM_REFERENCE(dummy
);
806 if (len
< sizeof(*hotlist_params
) || len
>= WLC_IOCTL_MAXLEN
) {
807 WL_ERR(("buffer length :%d wrong - bail out.\n", len
));
811 hotlist_params
= (gscan_hotlist_scan_params_t
*)MALLOCZ(cfg
->osh
,
812 sizeof(*hotlist_params
)
813 + (sizeof(struct bssid_t
) * (PFN_SWC_MAX_NUM_APS
- 1)));
815 if (!hotlist_params
) {
816 WL_ERR(("Cannot Malloc memory.\n"));
820 hotlist_params
->lost_ap_window
= GSCAN_LOST_AP_WINDOW_DEFAULT
;
822 nla_for_each_attr(iter
, data
, len
, tmp2
) {
823 type
= nla_type(iter
);
825 case GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT
:
826 if (nla_len(iter
) != sizeof(uint32
)) {
827 WL_DBG(("type:%d length:%d not matching.\n",
828 type
, nla_len(iter
)));
832 hotlist_params
->nbssid
= (uint16
)nla_get_u32(iter
);
833 if ((hotlist_params
->nbssid
== 0) ||
834 (hotlist_params
->nbssid
> PFN_SWC_MAX_NUM_APS
)) {
835 WL_ERR(("nbssid:%d exceed limit.\n",
836 hotlist_params
->nbssid
));
841 case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS
:
842 if (hotlist_params
->nbssid
== 0) {
843 WL_ERR(("nbssid not retrieved.\n"));
847 pbssid
= hotlist_params
->bssid
;
848 nla_for_each_nested(outer
, iter
, tmp
) {
849 if (j
>= hotlist_params
->nbssid
)
851 nla_for_each_nested(inner
, outer
, tmp1
) {
852 type
= nla_type(inner
);
855 case GSCAN_ATTRIBUTE_BSSID
:
856 if (nla_len(inner
) != sizeof(pbssid
[j
].macaddr
)) {
857 WL_ERR(("type:%d length:%d not matching.\n",
858 type
, nla_len(inner
)));
863 &(pbssid
[j
].macaddr
),
865 sizeof(pbssid
[j
].macaddr
));
867 case GSCAN_ATTRIBUTE_RSSI_LOW
:
868 if (nla_len(inner
) != sizeof(uint8
)) {
869 WL_ERR(("type:%d length:%d not matching.\n",
870 type
, nla_len(inner
)));
874 pbssid
[j
].rssi_reporting_threshold
=
875 (int8
)nla_get_u8(inner
);
877 case GSCAN_ATTRIBUTE_RSSI_HIGH
:
878 if (nla_len(inner
) != sizeof(uint8
)) {
879 WL_ERR(("type:%d length:%d not matching.\n",
880 type
, nla_len(inner
)));
884 dummy
= (int8
)nla_get_u8(inner
);
885 WL_DBG(("dummy %d\n", dummy
));
888 WL_ERR(("ATTR unknown %d\n", type
));
895 if (j
!= hotlist_params
->nbssid
) {
896 WL_ERR(("bssid_cnt:%d != nbssid:%d.\n", j
,
897 hotlist_params
->nbssid
));
902 case GSCAN_ATTRIBUTE_HOTLIST_FLUSH
:
903 if (nla_len(iter
) != sizeof(uint8
)) {
904 WL_ERR(("type:%d length:%d not matching.\n",
905 type
, nla_len(iter
)));
909 flush
= nla_get_u8(iter
);
911 case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE
:
912 if (nla_len(iter
) != sizeof(uint32
)) {
913 WL_ERR(("type:%d length:%d not matching.\n",
914 type
, nla_len(iter
)));
918 hotlist_params
->lost_ap_window
= (uint16
)nla_get_u32(iter
);
921 WL_ERR(("Unknown type %d\n", type
));
928 if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
929 DHD_PNO_GEOFENCE_SCAN_CFG_ID
, hotlist_params
, flush
) < 0) {
930 WL_ERR(("Could not set GSCAN HOTLIST cfg error: %d\n", err
));
935 MFREE(cfg
->osh
, hotlist_params
, sizeof(*hotlist_params
)
936 + (sizeof(struct bssid_t
) * (PFN_SWC_MAX_NUM_APS
- 1)));
940 static int wl_cfgvendor_epno_cfg(struct wiphy
*wiphy
,
941 struct wireless_dev
*wdev
, const void *data
, int len
)
944 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
945 dhd_pno_ssid_t
*ssid_elem
= NULL
;
946 int tmp
, tmp1
, tmp2
, type
= 0, num
= 0;
947 const struct nlattr
*outer
, *inner
, *iter
;
948 uint8 flush
= FALSE
, i
= 0;
949 wl_ssid_ext_params_t params
;
951 nla_for_each_attr(iter
, data
, len
, tmp2
) {
952 type
= nla_type(iter
);
954 case GSCAN_ATTRIBUTE_EPNO_SSID_LIST
:
955 nla_for_each_nested(outer
, iter
, tmp
) {
956 ssid_elem
= (dhd_pno_ssid_t
*)
957 dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg
),
958 DHD_PNO_GET_NEW_EPNO_SSID_ELEM
,
961 WL_ERR(("Failed to get SSID LIST buffer\n"));
966 nla_for_each_nested(inner
, outer
, tmp1
) {
967 type
= nla_type(inner
);
970 case GSCAN_ATTRIBUTE_EPNO_SSID
:
971 memcpy(ssid_elem
->SSID
,
975 case GSCAN_ATTRIBUTE_EPNO_SSID_LEN
:
976 ssid_elem
->SSID_len
=
978 if (ssid_elem
->SSID_len
>
979 DOT11_MAX_SSID_LEN
) {
982 ssid_elem
->SSID_len
));
984 MFREE(cfg
->osh
, ssid_elem
,
989 case GSCAN_ATTRIBUTE_EPNO_FLAGS
:
994 DHD_EPNO_HIDDEN_SSID
) != 0);
996 case GSCAN_ATTRIBUTE_EPNO_AUTH
:
997 ssid_elem
->wpa_auth
=
1002 if (!ssid_elem
->SSID_len
) {
1003 WL_ERR(("Broadcast SSID is illegal for ePNO\n"));
1005 MFREE(cfg
->osh
, ssid_elem
, num
);
1008 dhd_pno_translate_epno_fw_flags(&ssid_elem
->flags
);
1009 dhd_pno_set_epno_auth_flag(&ssid_elem
->wpa_auth
);
1010 MFREE(cfg
->osh
, ssid_elem
, num
);
1013 case GSCAN_ATTRIBUTE_EPNO_SSID_NUM
:
1014 num
= nla_get_u8(iter
);
1016 case GSCAN_ATTRIBUTE_EPNO_FLUSH
:
1017 flush
= (bool)nla_get_u32(iter
);
1018 /* Flush attribute is expected before any ssid attribute */
1020 WL_ERR(("Bad attributes\n"));
1024 /* Need to flush driver and FW cfg */
1025 dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
1026 DHD_PNO_EPNO_CFG_ID
, NULL
, flush
);
1027 dhd_dev_flush_fw_epno(bcmcfg_to_prmry_ndev(cfg
));
1029 case GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR
:
1030 params
.min5G_rssi
= nla_get_s8(iter
);
1032 case GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR
:
1033 params
.min2G_rssi
= nla_get_s8(iter
);
1035 case GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX
:
1036 params
.init_score_max
= nla_get_s16(iter
);
1038 case GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS
:
1039 params
.cur_bssid_bonus
= nla_get_s16(iter
);
1041 case GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS
:
1042 params
.same_ssid_bonus
= nla_get_s16(iter
);
1044 case GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS
:
1045 params
.secure_bonus
= nla_get_s16(iter
);
1047 case GSCAN_ATTRIBUTE_EPNO_5G_BONUS
:
1048 params
.band_5g_bonus
= nla_get_s16(iter
);
1051 WL_ERR(("%s: No such attribute %d\n", __FUNCTION__
, type
));
1057 WL_ERR(("%s: num_ssid %d does not match ssids sent %d\n", __FUNCTION__
,
1062 /* Flush all configs if error condition */
1064 dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
1065 DHD_PNO_EPNO_CFG_ID
, NULL
, TRUE
);
1066 dhd_dev_flush_fw_epno(bcmcfg_to_prmry_ndev(cfg
));
1067 } else if (type
!= GSCAN_ATTRIBUTE_EPNO_FLUSH
) {
1068 /* If the last attribute was FLUSH, nothing else to do */
1069 dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
1070 DHD_PNO_EPNO_PARAMS_ID
, ¶ms
, FALSE
);
1071 err
= dhd_dev_set_epno(bcmcfg_to_prmry_ndev(cfg
));
1077 wl_cfgvendor_set_batch_scan_cfg(struct wiphy
*wiphy
,
1078 struct wireless_dev
*wdev
, const void *data
, int len
)
1080 int err
= 0, tmp
, type
;
1081 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1082 gscan_batch_params_t batch_param
;
1083 const struct nlattr
*iter
;
1085 batch_param
.mscan
= batch_param
.bestn
= 0;
1086 batch_param
.buffer_threshold
= GSCAN_BATCH_NO_THR_SET
;
1088 nla_for_each_attr(iter
, data
, len
, tmp
) {
1089 type
= nla_type(iter
);
1092 case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN
:
1093 batch_param
.bestn
= nla_get_u32(iter
);
1095 case GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE
:
1096 batch_param
.mscan
= nla_get_u32(iter
);
1098 case GSCAN_ATTRIBUTE_REPORT_THRESHOLD
:
1099 batch_param
.buffer_threshold
= nla_get_u32(iter
);
1102 WL_ERR(("Unknown type %d\n", type
));
1107 if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
1108 DHD_PNO_BATCH_SCAN_CFG_ID
, &batch_param
, FALSE
) < 0) {
1109 WL_ERR(("Could not set batch cfg\n"));
1117 #endif /* GSCAN_SUPPORT */
1118 #if defined(GSCAN_SUPPORT) || defined(DHD_GET_VALID_CHANNELS)
1120 wl_cfgvendor_gscan_get_channel_list(struct wiphy
*wiphy
,
1121 struct wireless_dev
*wdev
, const void *data
, int len
)
1123 int err
= 0, type
, band
;
1124 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1125 uint16
*reply
= NULL
;
1126 uint32 reply_len
= 0, num_channels
, mem_needed
;
1127 struct sk_buff
*skb
;
1130 WL_ERR(("data is not available\n"));
1135 WL_ERR(("invalid len %d\n", len
));
1139 type
= nla_type(data
);
1141 if (type
== GSCAN_ATTRIBUTE_BAND
) {
1142 band
= nla_get_u32(data
);
1147 reply
= dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg
),
1148 DHD_PNO_GET_CHANNEL_LIST
, &band
, &reply_len
);
1151 WL_ERR(("Could not get channel list\n"));
1155 num_channels
= reply_len
/ sizeof(uint32
);
1156 mem_needed
= reply_len
+ VENDOR_REPLY_OVERHEAD
+ (ATTRIBUTE_U32_LEN
* 2);
1158 /* Alloc the SKB for vendor_event */
1159 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
1160 if (unlikely(!skb
)) {
1161 WL_ERR(("skb alloc failed"));
1166 nla_put_u32(skb
, GSCAN_ATTRIBUTE_NUM_CHANNELS
, num_channels
);
1167 nla_put(skb
, GSCAN_ATTRIBUTE_CHANNEL_LIST
, reply_len
, reply
);
1169 err
= cfg80211_vendor_cmd_reply(skb
);
1171 if (unlikely(err
)) {
1172 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
1175 MFREE(cfg
->osh
, reply
, reply_len
);
1178 #endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */
1180 #ifdef RSSI_MONITOR_SUPPORT
1181 static int wl_cfgvendor_set_rssi_monitor(struct wiphy
*wiphy
,
1182 struct wireless_dev
*wdev
, const void *data
, int len
)
1184 int err
= 0, tmp
, type
, start
= 0;
1185 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1186 int8 max_rssi
= 0, min_rssi
= 0;
1187 const struct nlattr
*iter
;
1189 nla_for_each_attr(iter
, data
, len
, tmp
) {
1190 type
= nla_type(iter
);
1192 case RSSI_MONITOR_ATTRIBUTE_MAX_RSSI
:
1193 max_rssi
= (int8
) nla_get_u32(iter
);
1195 case RSSI_MONITOR_ATTRIBUTE_MIN_RSSI
:
1196 min_rssi
= (int8
) nla_get_u32(iter
);
1198 case RSSI_MONITOR_ATTRIBUTE_START
:
1199 start
= nla_get_u32(iter
);
1203 if (dhd_dev_set_rssi_monitor_cfg(bcmcfg_to_prmry_ndev(cfg
),
1204 start
, max_rssi
, min_rssi
) < 0) {
1205 WL_ERR(("Could not set rssi monitor cfg\n"));
1210 #endif /* RSSI_MONITOR_SUPPORT */
1212 #ifdef DHDTCPACK_SUPPRESS
1214 wl_cfgvendor_set_tcpack_sup_mode(struct wiphy
*wiphy
,
1215 struct wireless_dev
*wdev
, const void *data
, int len
)
1217 int err
= BCME_OK
, type
;
1218 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1219 struct net_device
*ndev
= wdev_to_wlc_ndev(wdev
, cfg
);
1223 WL_ERR(("data is not available\n"));
1229 WL_ERR(("Length of the nlattr is not valid len : %d\n", len
));
1234 type
= nla_type(data
);
1235 if (type
== ANDR_WIFI_ATTRIBUTE_TCPACK_SUP_VALUE
) {
1236 enable
= (uint8
)nla_get_u32(data
);
1237 err
= dhd_dev_set_tcpack_sup_mode_cfg(ndev
, enable
);
1238 if (unlikely(err
)) {
1239 WL_ERR(("Could not set TCP Ack Suppress mode cfg: %d\n", err
));
1248 #endif /* DHDTCPACK_SUPPRESS */
1250 #ifdef DHD_WAKE_STATUS
1252 wl_cfgvendor_get_wake_reason_stats(struct wiphy
*wiphy
,
1253 struct wireless_dev
*wdev
, const void *data
, int len
)
1255 struct net_device
*ndev
= wdev_to_ndev(wdev
);
1256 wake_counts_t
*pwake_count_info
;
1257 int ret
, mem_needed
;
1258 #if defined(DHD_DEBUG) && defined(DHD_WAKE_EVENT_STATUS)
1260 #endif /* DHD_DEBUG && DHD_WAKE_EVENT_STATUS */
1261 struct sk_buff
*skb
;
1262 dhd_pub_t
*dhdp
= wl_cfg80211_get_dhdp(ndev
);
1264 WL_DBG(("Recv get wake status info cmd.\n"));
1266 pwake_count_info
= dhd_get_wakecount(dhdp
);
1267 mem_needed
= VENDOR_REPLY_OVERHEAD
+ (ATTRIBUTE_U32_LEN
* 20) +
1268 (WLC_E_LAST
* sizeof(uint
));
1270 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
1271 if (unlikely(!skb
)) {
1272 WL_ERR(("%s: can't allocate %d bytes\n", __FUNCTION__
, mem_needed
));
1276 #ifdef DHD_WAKE_EVENT_STATUS
1277 WL_ERR(("pwake_count_info->rcwake %d\n", pwake_count_info
->rcwake
));
1278 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT
, pwake_count_info
->rcwake
);
1279 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT_USED
, WLC_E_LAST
);
1280 nla_put(skb
, WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE
, (WLC_E_LAST
* sizeof(uint
)),
1281 pwake_count_info
->rc_event
);
1283 for (flowid
= 0; flowid
< WLC_E_LAST
; flowid
++) {
1284 if (pwake_count_info
->rc_event
[flowid
] != 0) {
1285 WL_ERR((" %s = %u\n", bcmevent_get_name(flowid
),
1286 pwake_count_info
->rc_event
[flowid
]));
1289 #endif /* DHD_DEBUG */
1290 #endif /* DHD_WAKE_EVENT_STATUS */
1291 #ifdef DHD_WAKE_RX_STATUS
1292 WL_ERR(("pwake_count_info->rxwake %d\n", pwake_count_info
->rxwake
));
1293 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE
, pwake_count_info
->rxwake
);
1294 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT
, pwake_count_info
->rx_ucast
);
1295 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT
, pwake_count_info
->rx_mcast
);
1296 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT
, pwake_count_info
->rx_bcast
);
1297 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT
, pwake_count_info
->rx_arp
);
1298 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT
, pwake_count_info
->rx_icmpv6
);
1299 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA
, pwake_count_info
->rx_icmpv6_ra
);
1300 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA
, pwake_count_info
->rx_icmpv6_na
);
1301 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS
, pwake_count_info
->rx_icmpv6_ns
);
1302 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT
,
1303 pwake_count_info
->rx_multi_ipv4
);
1304 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT
,
1305 pwake_count_info
->rx_multi_ipv6
);
1306 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT
,
1307 pwake_count_info
->rx_multi_other
);
1308 #endif /* #ifdef DHD_WAKE_RX_STATUS */
1309 ret
= cfg80211_vendor_cmd_reply(skb
);
1310 if (unlikely(ret
)) {
1311 WL_ERR(("Vendor cmd reply for -get wake status failed:%d \n", ret
));
1316 #endif /* DHD_WAKE_STATUS */
1320 wl_cfgvendor_rtt_evt(void *ctx
, void *rtt_data
)
1322 struct wireless_dev
*wdev
= (struct wireless_dev
*)ctx
;
1323 struct wiphy
*wiphy
;
1324 struct sk_buff
*skb
;
1325 uint32 evt_complete
= 0;
1327 rtt_result_t
*rtt_result
;
1328 rtt_results_header_t
*rtt_header
;
1329 struct list_head
*rtt_cache_list
;
1330 struct nlattr
*rtt_nl_hdr
;
1331 wiphy
= wdev
->wiphy
;
1334 /* Push the data to the skb */
1336 WL_ERR(("rtt_data is NULL\n"));
1339 rtt_cache_list
= (struct list_head
*)rtt_data
;
1340 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
1341 if (list_empty(rtt_cache_list
)) {
1342 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
1343 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1344 skb
= cfg80211_vendor_event_alloc(wiphy
, NULL
, 100,
1345 GOOGLE_RTT_COMPLETE_EVENT
, kflags
);
1347 skb
= cfg80211_vendor_event_alloc(wiphy
, 100, GOOGLE_RTT_COMPLETE_EVENT
, kflags
);
1348 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
1349 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
1351 WL_ERR(("skb alloc failed"));
1355 nla_put_u32(skb
, RTT_ATTRIBUTE_RESULTS_COMPLETE
, evt_complete
);
1356 cfg80211_vendor_event(skb
, kflags
);
1359 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
1360 #pragma GCC diagnostic push
1361 #pragma GCC diagnostic ignored "-Wcast-qual"
1363 list_for_each_entry(rtt_header
, rtt_cache_list
, list
) {
1364 /* Alloc the SKB for vendor_event */
1365 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
1366 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1367 skb
= cfg80211_vendor_event_alloc(wiphy
, NULL
, rtt_header
->result_tot_len
+ 100,
1368 GOOGLE_RTT_COMPLETE_EVENT
, kflags
);
1370 skb
= cfg80211_vendor_event_alloc(wiphy
, rtt_header
->result_tot_len
+ 100,
1371 GOOGLE_RTT_COMPLETE_EVENT
, kflags
);
1372 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
1373 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
1375 WL_ERR(("skb alloc failed"));
1378 if (list_is_last(&rtt_header
->list
, rtt_cache_list
)) {
1381 nla_put_u32(skb
, RTT_ATTRIBUTE_RESULTS_COMPLETE
, evt_complete
);
1382 rtt_nl_hdr
= nla_nest_start(skb
, RTT_ATTRIBUTE_RESULTS_PER_TARGET
);
1384 WL_ERR(("rtt_nl_hdr is NULL\n"));
1387 nla_put(skb
, RTT_ATTRIBUTE_TARGET_MAC
, ETHER_ADDR_LEN
, &rtt_header
->peer_mac
);
1388 nla_put_u32(skb
, RTT_ATTRIBUTE_RESULT_CNT
, rtt_header
->result_cnt
);
1389 list_for_each_entry(rtt_result
, &rtt_header
->result_list
, list
) {
1390 nla_put(skb
, RTT_ATTRIBUTE_RESULT
,
1391 rtt_result
->report_len
, &rtt_result
->report
);
1393 nla_nest_end(skb
, rtt_nl_hdr
);
1394 cfg80211_vendor_event(skb
, kflags
);
1396 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
1397 #pragma GCC diagnostic pop
1402 wl_cfgvendor_rtt_set_config(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1403 const void *data
, int len
) {
1404 int err
= 0, rem
, rem1
, rem2
, type
;
1406 rtt_config_params_t rtt_param
;
1407 rtt_target_info_t
* rtt_target
= NULL
;
1408 const struct nlattr
*iter
, *iter1
, *iter2
;
1409 int8 eabuf
[ETHER_ADDR_STR_LEN
];
1410 int8 chanbuf
[CHANSPEC_STR_LEN
];
1411 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1412 rtt_capabilities_t capability
;
1414 memset(&rtt_param
, 0, sizeof(rtt_param
));
1417 err
= dhd_dev_rtt_register_noti_callback(wdev
->netdev
, wdev
, wl_cfgvendor_rtt_evt
);
1419 WL_ERR(("failed to register rtt_noti_callback\n"));
1422 err
= dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg
), &capability
);
1424 WL_ERR(("failed to get the capability\n"));
1429 WL_ERR(("Length of the nlattr is not valid len : %d\n", len
));
1433 nla_for_each_attr(iter
, data
, len
, rem
) {
1434 type
= nla_type(iter
);
1436 case RTT_ATTRIBUTE_TARGET_CNT
:
1437 target_cnt
= nla_get_u8(iter
);
1438 if ((target_cnt
<= 0) || (target_cnt
> RTT_MAX_TARGET_CNT
)) {
1439 WL_ERR(("target_cnt is not valid : %d\n",
1444 rtt_param
.rtt_target_cnt
= target_cnt
;
1446 rtt_param
.target_info
= (rtt_target_info_t
*)MALLOCZ(cfg
->osh
,
1447 TARGET_INFO_SIZE(target_cnt
));
1448 if (rtt_param
.target_info
== NULL
) {
1449 WL_ERR(("failed to allocate target info for (%d)\n", target_cnt
));
1454 case RTT_ATTRIBUTE_TARGET_INFO
:
1455 /* Added this variable for safe check to avoid crash
1456 * incase the caller did not respect the order
1458 if (rtt_param
.target_info
== NULL
) {
1459 WL_ERR(("rtt_target_info is NULL\n"));
1463 rtt_target
= rtt_param
.target_info
;
1464 nla_for_each_nested(iter1
, iter
, rem1
) {
1465 nla_for_each_nested(iter2
, iter1
, rem2
) {
1466 type
= nla_type(iter2
);
1468 case RTT_ATTRIBUTE_TARGET_MAC
:
1469 memcpy(&rtt_target
->addr
, nla_data(iter2
),
1472 case RTT_ATTRIBUTE_TARGET_TYPE
:
1473 rtt_target
->type
= nla_get_u8(iter2
);
1474 if (rtt_target
->type
== RTT_INVALID
||
1475 (rtt_target
->type
== RTT_ONE_WAY
&&
1476 !capability
.rtt_one_sided_supported
)) {
1477 WL_ERR(("doesn't support RTT type"
1484 case RTT_ATTRIBUTE_TARGET_PEER
:
1485 rtt_target
->peer
= nla_get_u8(iter2
);
1487 case RTT_ATTRIBUTE_TARGET_CHAN
:
1488 memcpy(&rtt_target
->channel
, nla_data(iter2
),
1489 sizeof(rtt_target
->channel
));
1491 case RTT_ATTRIBUTE_TARGET_PERIOD
:
1492 rtt_target
->burst_period
= nla_get_u32(iter2
);
1493 if (rtt_target
->burst_period
< 32) {
1495 rtt_target
->burst_period
*= 100;
1497 WL_ERR(("%d value must in (0-31)\n",
1498 rtt_target
->burst_period
));
1503 case RTT_ATTRIBUTE_TARGET_NUM_BURST
:
1504 rtt_target
->num_burst
= nla_get_u32(iter2
);
1505 if (rtt_target
->num_burst
> 16) {
1506 WL_ERR(("%d value must in (0-15)\n",
1507 rtt_target
->num_burst
));
1511 rtt_target
->num_burst
= BIT(rtt_target
->num_burst
);
1513 case RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST
:
1514 rtt_target
->num_frames_per_burst
=
1517 case RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM
:
1518 rtt_target
->num_retries_per_ftm
=
1521 case RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR
:
1522 rtt_target
->num_retries_per_ftmr
=
1524 if (rtt_target
->num_retries_per_ftmr
> 3) {
1525 WL_ERR(("%d value must in (0-3)\n",
1526 rtt_target
->num_retries_per_ftmr
));
1531 case RTT_ATTRIBUTE_TARGET_LCI
:
1532 rtt_target
->LCI_request
= nla_get_u8(iter2
);
1534 case RTT_ATTRIBUTE_TARGET_LCR
:
1535 rtt_target
->LCI_request
= nla_get_u8(iter2
);
1537 case RTT_ATTRIBUTE_TARGET_BURST_DURATION
:
1538 if ((nla_get_u32(iter2
) > 1 &&
1539 nla_get_u32(iter2
) < 12)) {
1540 rtt_target
->burst_duration
=
1541 dhd_rtt_idx_to_burst_duration(
1542 nla_get_u32(iter2
));
1543 } else if (nla_get_u32(iter2
) == 15) {
1544 /* use default value */
1545 rtt_target
->burst_duration
= 0;
1547 WL_ERR(("%d value must in (2-11) or 15\n",
1548 nla_get_u32(iter2
)));
1553 case RTT_ATTRIBUTE_TARGET_BW
:
1554 rtt_target
->bw
= nla_get_u8(iter2
);
1556 case RTT_ATTRIBUTE_TARGET_PREAMBLE
:
1557 rtt_target
->preamble
= nla_get_u8(iter2
);
1561 /* convert to chanspec value */
1562 rtt_target
->chanspec
=
1563 dhd_rtt_convert_to_chspec(rtt_target
->channel
);
1564 if (rtt_target
->chanspec
== 0) {
1565 WL_ERR(("Channel is not valid \n"));
1569 WL_INFORM_MEM(("Target addr %s, Channel : %s for RTT \n",
1570 bcm_ether_ntoa((const struct ether_addr
*)&rtt_target
->addr
,
1572 wf_chspec_ntoa(rtt_target
->chanspec
, chanbuf
)));
1578 WL_DBG(("leave :target_cnt : %d\n", rtt_param
.rtt_target_cnt
));
1579 if (dhd_dev_rtt_set_cfg(bcmcfg_to_prmry_ndev(cfg
), &rtt_param
) < 0) {
1580 WL_ERR(("Could not set RTT configuration\n"));
1584 /* free the target info list */
1585 if (rtt_param
.target_info
) {
1586 MFREE(cfg
->osh
, rtt_param
.target_info
,
1587 TARGET_INFO_SIZE(target_cnt
));
1588 rtt_param
.target_info
= NULL
;
1594 wl_cfgvendor_rtt_cancel_config(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1595 const void *data
, int len
)
1597 int err
= 0, rem
, type
, target_cnt
= 0;
1599 const struct nlattr
*iter
;
1600 struct ether_addr
*mac_list
= NULL
;
1601 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1604 WL_ERR(("Length of nlattr is not valid len : %d\n", len
));
1608 nla_for_each_attr(iter
, data
, len
, rem
) {
1609 type
= nla_type(iter
);
1611 case RTT_ATTRIBUTE_TARGET_CNT
:
1612 if (mac_list
!= NULL
) {
1613 WL_ERR(("mac_list is not NULL\n"));
1617 target_cnt
= nla_get_u8(iter
);
1618 if ((target_cnt
> 0) && (target_cnt
< RTT_MAX_TARGET_CNT
)) {
1619 mac_list
= (struct ether_addr
*)MALLOCZ(cfg
->osh
,
1620 target_cnt
* ETHER_ADDR_LEN
);
1621 if (mac_list
== NULL
) {
1622 WL_ERR(("failed to allocate mem for mac list\n"));
1627 /* cancel the current whole RTT process */
1631 case RTT_ATTRIBUTE_TARGET_MAC
:
1632 if (mac_list
== NULL
) {
1633 WL_ERR(("ATTRIBUTE_TARGET_CNT not found before "
1634 " ATTRIBUTE_TARGET_MAC\n"));
1639 if (target_idx
>= target_cnt
) {
1640 WL_ERR(("More TARGET_MAC entries found, "
1641 "expected TARGET_CNT:%d\n", target_cnt
));
1646 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
1647 WL_ERR(("Invalid TARGET_MAC ATTR len :%d\n", nla_len(iter
)));
1652 memcpy(&mac_list
[target_idx
], nla_data(iter
), ETHER_ADDR_LEN
);
1657 WL_ERR(("Uknown type : %d\n", type
));
1663 if (dhd_dev_rtt_cancel_cfg(bcmcfg_to_prmry_ndev(cfg
), mac_list
, target_cnt
) < 0) {
1664 WL_ERR(("Could not cancel RTT configuration\n"));
1670 MFREE(cfg
->osh
, mac_list
, target_cnt
* ETHER_ADDR_LEN
);
1676 wl_cfgvendor_rtt_get_capability(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1677 const void *data
, int len
)
1680 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1681 rtt_capabilities_t capability
;
1683 err
= dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg
), &capability
);
1684 if (unlikely(err
)) {
1685 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
1688 err
= wl_cfgvendor_send_cmd_reply(wiphy
, &capability
, sizeof(capability
));
1690 if (unlikely(err
)) {
1691 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
1697 get_responder_info(struct bcm_cfg80211
*cfg
,
1698 struct wifi_rtt_responder
*responder_info
)
1701 rtt_capabilities_t capability
;
1702 err
= dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg
), &capability
);
1703 if (unlikely(err
)) {
1704 WL_ERR(("Could not get responder capability:%d \n", err
));
1707 if (capability
.preamble_support
& RTT_PREAMBLE_VHT
) {
1708 responder_info
->preamble
|= RTT_PREAMBLE_VHT
;
1710 if (capability
.preamble_support
& RTT_PREAMBLE_HT
) {
1711 responder_info
->preamble
|= RTT_PREAMBLE_HT
;
1713 err
= dhd_dev_rtt_avail_channel(bcmcfg_to_prmry_ndev(cfg
), &(responder_info
->channel
));
1714 if (unlikely(err
)) {
1715 WL_ERR(("Could not get available channel:%d \n", err
));
1721 wl_cfgvendor_rtt_get_responder_info(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1722 const void *data
, int len
)
1725 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1726 wifi_rtt_responder_t responder_info
;
1728 WL_DBG(("Recv -get_avail_ch command \n"));
1730 memset(&responder_info
, 0, sizeof(responder_info
));
1731 err
= get_responder_info(cfg
, &responder_info
);
1732 if (unlikely(err
)) {
1733 WL_ERR(("Failed to get responder info:%d \n", err
));
1736 err
= wl_cfgvendor_send_cmd_reply(wiphy
, &responder_info
, sizeof(responder_info
));
1737 if (unlikely(err
)) {
1738 WL_ERR(("Vendor cmd reply for -get_avail_ch failed ret:%d \n", err
));
1744 wl_cfgvendor_rtt_set_responder(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1745 const void *data
, int len
)
1748 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1749 struct net_device
*ndev
= wdev_to_wlc_ndev(wdev
, cfg
);
1750 wifi_rtt_responder_t responder_info
;
1752 WL_DBG(("Recv rtt -enable_resp cmd.\n"));
1754 memset(&responder_info
, 0, sizeof(responder_info
));
1757 *Passing channel as NULL until implementation
1758 *to get chan info from upper layers is donex
1760 err
= dhd_dev_rtt_enable_responder(ndev
, NULL
);
1761 if (unlikely(err
)) {
1762 WL_ERR(("Could not enable responder ret:%d \n", err
));
1765 err
= get_responder_info(cfg
, &responder_info
);
1766 if (unlikely(err
)) {
1767 WL_ERR(("Failed to get responder info:%d \n", err
));
1768 dhd_dev_rtt_cancel_responder(ndev
);
1772 err
= wl_cfgvendor_send_cmd_reply(wiphy
, &responder_info
, sizeof(responder_info
));
1773 if (unlikely(err
)) {
1774 WL_ERR(("Vendor cmd reply for -enable_resp failed ret:%d \n", err
));
1780 wl_cfgvendor_rtt_cancel_responder(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1781 const void *data
, int len
)
1784 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1786 WL_DBG(("Recv rtt -cancel_resp cmd \n"));
1788 err
= dhd_dev_rtt_cancel_responder(bcmcfg_to_prmry_ndev(cfg
));
1789 if (unlikely(err
)) {
1790 WL_ERR(("Vendor cmd -cancel_resp failed ret:%d \n", err
));
1794 #endif /* RTT_SUPPORT */
1796 #ifdef GSCAN_SUPPORT
1797 static int wl_cfgvendor_enable_lazy_roam(struct wiphy
*wiphy
,
1798 struct wireless_dev
*wdev
, const void *data
, int len
)
1801 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1803 uint32 lazy_roam_enable_flag
;
1806 WL_ERR(("data is not available\n"));
1811 WL_ERR(("invaild len %d\n", len
));
1815 type
= nla_type(data
);
1817 if (type
== GSCAN_ATTRIBUTE_LAZY_ROAM_ENABLE
) {
1818 lazy_roam_enable_flag
= nla_get_u32(data
);
1820 err
= dhd_dev_lazy_roam_enable(bcmcfg_to_prmry_ndev(cfg
),
1821 lazy_roam_enable_flag
);
1823 WL_ERR(("Could not enable lazy roam:%d \n", err
));
1829 static int wl_cfgvendor_set_lazy_roam_cfg(struct wiphy
*wiphy
,
1830 struct wireless_dev
*wdev
, const void *data
, int len
)
1832 int err
= 0, tmp
, type
;
1833 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1834 wlc_roam_exp_params_t roam_param
;
1835 const struct nlattr
*iter
;
1837 memset(&roam_param
, 0, sizeof(roam_param
));
1839 nla_for_each_attr(iter
, data
, len
, tmp
) {
1840 type
= nla_type(iter
);
1842 case GSCAN_ATTRIBUTE_A_BAND_BOOST_THRESHOLD
:
1843 roam_param
.a_band_boost_threshold
= nla_get_u32(iter
);
1845 case GSCAN_ATTRIBUTE_A_BAND_PENALTY_THRESHOLD
:
1846 roam_param
.a_band_penalty_threshold
= nla_get_u32(iter
);
1848 case GSCAN_ATTRIBUTE_A_BAND_BOOST_FACTOR
:
1849 roam_param
.a_band_boost_factor
= nla_get_u32(iter
);
1851 case GSCAN_ATTRIBUTE_A_BAND_PENALTY_FACTOR
:
1852 roam_param
.a_band_penalty_factor
= nla_get_u32(iter
);
1854 case GSCAN_ATTRIBUTE_A_BAND_MAX_BOOST
:
1855 roam_param
.a_band_max_boost
= nla_get_u32(iter
);
1857 case GSCAN_ATTRIBUTE_LAZY_ROAM_HYSTERESIS
:
1858 roam_param
.cur_bssid_boost
= nla_get_u32(iter
);
1860 case GSCAN_ATTRIBUTE_ALERT_ROAM_RSSI_TRIGGER
:
1861 roam_param
.alert_roam_trigger_threshold
= nla_get_u32(iter
);
1866 if (dhd_dev_set_lazy_roam_cfg(bcmcfg_to_prmry_ndev(cfg
), &roam_param
) < 0) {
1867 WL_ERR(("Could not set batch cfg\n"));
1873 /* small helper function */
1874 static wl_bssid_pref_cfg_t
*
1875 create_bssid_pref_cfg(struct bcm_cfg80211
*cfg
, uint32 num
, uint32
*buf_len
)
1877 wl_bssid_pref_cfg_t
*bssid_pref
;
1879 *buf_len
= sizeof(wl_bssid_pref_cfg_t
);
1881 *buf_len
+= (num
- 1) * sizeof(wl_bssid_pref_list_t
);
1883 bssid_pref
= (wl_bssid_pref_cfg_t
*)MALLOC(cfg
->osh
, *buf_len
);
1889 wl_cfgvendor_set_bssid_pref(struct wiphy
*wiphy
,
1890 struct wireless_dev
*wdev
, const void *data
, int len
)
1893 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1894 wl_bssid_pref_cfg_t
*bssid_pref
= NULL
;
1895 wl_bssid_pref_list_t
*bssids
;
1896 int tmp
, tmp1
, tmp2
, type
;
1897 const struct nlattr
*outer
, *inner
, *iter
;
1898 uint32 flush
= 0, num
= 0, buf_len
= 0;
1899 uint8 bssid_found
= 0, rssi_found
= 0;
1901 /* Assumption: NUM attribute must come first */
1902 nla_for_each_attr(iter
, data
, len
, tmp2
) {
1903 type
= nla_type(iter
);
1905 case GSCAN_ATTRIBUTE_NUM_BSSID
:
1907 WL_ERR(("attempt overide bssid num.\n"));
1911 if (nla_len(iter
) != sizeof(uint32
)) {
1912 WL_ERR(("nla_len not match\n"));
1916 num
= nla_get_u32(iter
);
1917 if (num
== 0 || num
> MAX_BSSID_PREF_LIST_NUM
) {
1918 WL_ERR(("wrong BSSID num:%d\n", num
));
1922 if ((bssid_pref
= create_bssid_pref_cfg(cfg
, num
, &buf_len
))
1924 WL_ERR(("Can't malloc memory\n"));
1929 case GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH
:
1930 if (nla_len(iter
) != sizeof(uint32
)) {
1931 WL_ERR(("nla_len not match\n"));
1935 flush
= nla_get_u32(iter
);
1937 WL_ERR(("wrong flush value\n"));
1942 case GSCAN_ATTRIBUTE_BSSID_PREF_LIST
:
1943 if (!num
|| !bssid_pref
) {
1944 WL_ERR(("bssid list count not set\n"));
1948 bssid_pref
->count
= 0;
1949 bssids
= bssid_pref
->bssids
;
1950 nla_for_each_nested(outer
, iter
, tmp
) {
1951 if (bssid_pref
->count
>= num
) {
1952 WL_ERR(("too many bssid list\n"));
1958 nla_for_each_nested(inner
, outer
, tmp1
) {
1959 type
= nla_type(inner
);
1961 case GSCAN_ATTRIBUTE_BSSID_PREF
:
1962 if (nla_len(inner
) != ETHER_ADDR_LEN
) {
1963 WL_ERR(("nla_len not match.\n"));
1967 memcpy(&(bssids
[bssid_pref
->count
].bssid
),
1968 nla_data(inner
), ETHER_ADDR_LEN
);
1969 /* not used for now */
1970 bssids
[bssid_pref
->count
].flags
= 0;
1973 case GSCAN_ATTRIBUTE_RSSI_MODIFIER
:
1974 if (nla_len(inner
) != sizeof(uint32
)) {
1975 WL_ERR(("nla_len not match.\n"));
1979 bssids
[bssid_pref
->count
].rssi_factor
=
1980 (int8
) nla_get_u32(inner
);
1984 WL_ERR(("wrong type:%d\n", type
));
1988 if (bssid_found
&& rssi_found
) {
1992 bssid_pref
->count
++;
1996 WL_ERR(("%s: No such attribute %d\n", __FUNCTION__
, type
));
2002 /* What if only flush is desired? */
2004 if ((bssid_pref
= create_bssid_pref_cfg(cfg
, 0, &buf_len
)) == NULL
) {
2005 WL_ERR(("%s: Can't malloc memory\n", __FUNCTION__
));
2009 bssid_pref
->count
= 0;
2015 err
= dhd_dev_set_lazy_roam_bssid_pref(bcmcfg_to_prmry_ndev(cfg
),
2019 MFREE(cfg
->osh
, bssid_pref
, buf_len
);
2023 #endif /* GSCAN_SUPPORT */
2024 #if defined(GSCAN_SUPPORT) || defined(ROAMEXP_SUPPORT)
2026 wl_cfgvendor_set_bssid_blacklist(struct wiphy
*wiphy
,
2027 struct wireless_dev
*wdev
, const void *data
, int len
)
2029 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2030 maclist_t
*blacklist
= NULL
;
2033 const struct nlattr
*iter
;
2034 uint32 mem_needed
= 0, flush
= 0, num
= 0;
2036 /* Assumption: NUM attribute must come first */
2037 nla_for_each_attr(iter
, data
, len
, tmp
) {
2038 type
= nla_type(iter
);
2040 case GSCAN_ATTRIBUTE_NUM_BSSID
:
2042 WL_ERR(("attempt to change BSSID num\n"));
2046 if (nla_len(iter
) != sizeof(uint32
)) {
2047 WL_ERR(("not matching nla_len.\n"));
2051 num
= nla_get_u32(iter
);
2052 if (num
== 0 || num
> MAX_BSSID_BLACKLIST_NUM
) {
2053 WL_ERR(("wrong BSSID count:%d\n", num
));
2058 mem_needed
= OFFSETOF(maclist_t
, ea
) +
2059 sizeof(struct ether_addr
) * (num
);
2060 blacklist
= (maclist_t
*)
2061 MALLOCZ(cfg
->osh
, mem_needed
);
2063 WL_ERR(("MALLOCZ failed.\n"));
2069 case GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH
:
2070 if (nla_len(iter
) != sizeof(uint32
)) {
2071 WL_ERR(("not matching nla_len.\n"));
2075 flush
= nla_get_u32(iter
);
2077 WL_ERR(("flush arg is worng:%d\n", flush
));
2082 case GSCAN_ATTRIBUTE_BLACKLIST_BSSID
:
2083 if (num
== 0 || !blacklist
) {
2084 WL_ERR(("number of BSSIDs not received.\n"));
2088 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
2089 WL_ERR(("not matching nla_len.\n"));
2093 if (blacklist
->count
>= num
) {
2094 WL_ERR(("too many BSSIDs than expected:%d\n",
2099 memcpy(&(blacklist
->ea
[blacklist
->count
]), nla_data(iter
),
2104 WL_ERR(("No such attribute:%d\n", type
));
2109 if (blacklist
&& (blacklist
->count
!= num
)) {
2110 WL_ERR(("not matching bssid count:%d to expected:%d\n",
2111 blacklist
->count
, num
));
2116 err
= dhd_dev_set_blacklist_bssid(bcmcfg_to_prmry_ndev(cfg
),
2117 blacklist
, mem_needed
, flush
);
2119 MFREE(cfg
->osh
, blacklist
, mem_needed
);
2124 wl_cfgvendor_set_ssid_whitelist(struct wiphy
*wiphy
,
2125 struct wireless_dev
*wdev
, const void *data
, int len
)
2128 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2129 wl_ssid_whitelist_t
*ssid_whitelist
= NULL
;
2130 wlc_ssid_t
*ssid_elem
;
2131 int tmp
, tmp1
, mem_needed
= 0, type
;
2132 const struct nlattr
*iter
, *iter1
;
2133 uint32 flush
= 0, num
= 0;
2136 /* Assumption: NUM attribute must come first */
2137 nla_for_each_attr(iter
, data
, len
, tmp
) {
2138 type
= nla_type(iter
);
2140 case GSCAN_ATTRIBUTE_NUM_WL_SSID
:
2142 WL_ERR(("try to change SSID num\n"));
2146 if (nla_len(iter
) != sizeof(uint32
)) {
2147 WL_ERR(("not matching nla_len.\n"));
2151 num
= nla_get_u32(iter
);
2152 if (num
== 0 || num
> MAX_SSID_WHITELIST_NUM
) {
2153 WL_ERR(("wrong SSID count:%d\n", num
));
2157 mem_needed
= sizeof(wl_ssid_whitelist_t
) +
2158 sizeof(wlc_ssid_t
) * num
;
2159 ssid_whitelist
= (wl_ssid_whitelist_t
*)
2160 MALLOCZ(cfg
->osh
, mem_needed
);
2161 if (ssid_whitelist
== NULL
) {
2162 WL_ERR(("failed to alloc mem\n"));
2167 case GSCAN_ATTRIBUTE_WL_SSID_FLUSH
:
2168 if (nla_len(iter
) != sizeof(uint32
)) {
2169 WL_ERR(("not matching nla_len.\n"));
2173 flush
= nla_get_u32(iter
);
2175 WL_ERR(("flush arg worng:%d\n", flush
));
2180 case GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM
:
2181 if (!num
|| !ssid_whitelist
) {
2182 WL_ERR(("num ssid is not set!\n"));
2186 if (ssid_whitelist
->ssid_count
>= num
) {
2187 WL_ERR(("too many SSIDs:%d\n",
2188 ssid_whitelist
->ssid_count
));
2193 ssid_elem
= &ssid_whitelist
->ssids
[
2194 ssid_whitelist
->ssid_count
];
2196 nla_for_each_nested(iter1
, iter
, tmp1
) {
2197 type
= nla_type(iter1
);
2199 case GSCAN_ATTRIBUTE_WL_SSID_LEN
:
2200 if (nla_len(iter1
) != sizeof(uint32
)) {
2201 WL_ERR(("not match nla_len\n"));
2205 ssid_elem
->SSID_len
= nla_get_u32(iter1
);
2206 if (ssid_elem
->SSID_len
>
2207 DOT11_MAX_SSID_LEN
) {
2208 WL_ERR(("wrong SSID len:%d\n",
2209 ssid_elem
->SSID_len
));
2214 case GSCAN_ATTRIBUTE_WHITELIST_SSID
:
2215 if (ssid_elem
->SSID_len
== 0) {
2216 WL_ERR(("SSID_len not received\n"));
2220 if (nla_len(iter1
) != ssid_elem
->SSID_len
) {
2221 WL_ERR(("not match nla_len\n"));
2225 memcpy(ssid_elem
->SSID
, nla_data(iter1
),
2226 ssid_elem
->SSID_len
);
2231 ssid_whitelist
->ssid_count
++;
2237 WL_ERR(("No such attribute: %d\n", type
));
2242 if (ssid_whitelist
&& (ssid_whitelist
->ssid_count
!= num
)) {
2243 WL_ERR(("not matching ssid count:%d to expected:%d\n",
2244 ssid_whitelist
->ssid_count
, num
));
2247 err
= dhd_dev_set_whitelist_ssid(bcmcfg_to_prmry_ndev(cfg
),
2248 ssid_whitelist
, mem_needed
, flush
);
2250 MFREE(cfg
->osh
, ssid_whitelist
, mem_needed
);
2253 #endif /* GSCAN_SUPPORT || ROAMEXP_SUPPORT */
2255 #ifdef ROAMEXP_SUPPORT
2257 FW_ROAMING_ENABLE
= 1,
2261 } fw_roaming_state_t
;
2264 wl_cfgvendor_set_fw_roaming_state(struct wiphy
*wiphy
,
2265 struct wireless_dev
*wdev
, const void *data
, int len
)
2267 fw_roaming_state_t requested_roaming_state
;
2272 WL_ERR(("data is not available\n"));
2277 WL_ERR(("invalid len %d\n", len
));
2281 /* Get the requested fw roaming state */
2282 type
= nla_type(data
);
2283 if (type
!= GSCAN_ATTRIBUTE_ROAM_STATE_SET
) {
2284 WL_ERR(("%s: Invalid attribute %d\n", __FUNCTION__
, type
));
2288 requested_roaming_state
= nla_get_u32(data
);
2289 WL_INFORM(("setting FW roaming state to %d\n", requested_roaming_state
));
2291 if ((requested_roaming_state
== FW_ROAMING_ENABLE
) ||
2292 (requested_roaming_state
== FW_ROAMING_RESUME
)) {
2293 err
= wldev_iovar_setint(wdev_to_ndev(wdev
), "roam_off", FALSE
);
2294 } else if ((requested_roaming_state
== FW_ROAMING_DISABLE
) ||
2295 (requested_roaming_state
== FW_ROAMING_PAUSE
)) {
2296 err
= wldev_iovar_setint(wdev_to_ndev(wdev
), "roam_off", TRUE
);
2305 wl_cfgvendor_fw_roam_get_capability(struct wiphy
*wiphy
,
2306 struct wireless_dev
*wdev
, const void *data
, int len
)
2309 wifi_roaming_capabilities_t roaming_capability
;
2311 /* Update max number of blacklist bssids supported */
2312 roaming_capability
.max_blacklist_size
= MAX_BSSID_BLACKLIST_NUM
;
2313 roaming_capability
.max_whitelist_size
= MAX_SSID_WHITELIST_NUM
;
2314 err
= wl_cfgvendor_send_cmd_reply(wiphy
, &roaming_capability
,
2315 sizeof(roaming_capability
));
2316 if (unlikely(err
)) {
2317 WL_ERR(("Vendor cmd reply for fw roam capability failed ret:%d \n", err
));
2322 #endif /* ROAMEXP_SUPPORT */
2325 wl_cfgvendor_priv_string_handler(struct wiphy
*wiphy
,
2326 struct wireless_dev
*wdev
, const void *data
, int len
)
2328 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2330 int ret_len
= 0, payload
= 0, msglen
;
2331 const struct bcm_nlmsg_hdr
*nlioc
= data
;
2332 void *buf
= NULL
, *cur
;
2333 int maxmsglen
= PAGE_SIZE
- 0x100;
2334 struct sk_buff
*reply
;
2335 dhd_pub_t
*dhdp
= wl_cfg80211_get_dhdp(wdev
->netdev
);
2337 /* send to dongle only if we are not waiting for reload already */
2338 if (dhdp
&& dhdp
->hang_was_sent
) {
2339 WL_INFORM(("Bus down. HANG was sent up earlier\n"));
2340 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp
, DHD_EVENT_TIMEOUT_MS
);
2341 DHD_OS_WAKE_UNLOCK(dhdp
);
2342 return OSL_ERROR(BCME_DONGLE_DOWN
);
2346 WL_ERR(("data is not available\n"));
2351 WL_ERR(("invalid len %d\n", len
));
2355 WL_DBG(("entry: cmd = %d\n", nlioc
->cmd
));
2357 if (nlioc
->offset
!= sizeof(struct bcm_nlmsg_hdr
) ||
2358 len
<= sizeof(struct bcm_nlmsg_hdr
)) {
2359 WL_ERR(("invalid offset %d\n", nlioc
->offset
));
2362 len
-= sizeof(struct bcm_nlmsg_hdr
);
2363 ret_len
= nlioc
->len
;
2364 if (ret_len
> 0 || len
> 0) {
2365 if (len
>= DHD_IOCTL_MAXLEN
) {
2366 WL_ERR(("oversize input buffer %d\n", len
));
2367 len
= DHD_IOCTL_MAXLEN
- 1;
2369 if (ret_len
>= DHD_IOCTL_MAXLEN
) {
2370 WL_ERR(("oversize return buffer %d\n", ret_len
));
2371 ret_len
= DHD_IOCTL_MAXLEN
- 1;
2374 payload
= max(ret_len
, len
) + 1;
2375 buf
= vzalloc(payload
);
2379 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
2380 #pragma GCC diagnostic push
2381 #pragma GCC diagnostic ignored "-Wcast-qual"
2383 memcpy(buf
, (void *)((char *)nlioc
+ nlioc
->offset
), len
);
2384 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
2385 #pragma GCC diagnostic pop
2387 *((char *)buf
+ len
) = '\0';
2390 ret
= dhd_cfgvendor_priv_string_handler(cfg
, wdev
, nlioc
, buf
);
2392 WL_ERR(("dhd_cfgvendor returned error %d", ret
));
2397 while (ret_len
> 0) {
2398 msglen
= ret_len
> maxmsglen
? maxmsglen
: ret_len
;
2400 payload
= msglen
+ sizeof(msglen
);
2401 reply
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, payload
);
2403 WL_ERR(("Failed to allocate reply msg\n"));
2408 if (nla_put(reply
, BCM_NLATTR_DATA
, msglen
, cur
) ||
2409 nla_put_u16(reply
, BCM_NLATTR_LEN
, msglen
)) {
2415 ret
= cfg80211_vendor_cmd_reply(reply
);
2417 WL_ERR(("testmode reply failed:%d\n", ret
));
2420 cur
= (void *)((char *)cur
+ msglen
);
2427 wl_cfgvendor_get_ndev(struct bcm_cfg80211
*cfg
, struct wireless_dev
*wdev
,
2428 const char *data
, unsigned long int *out_addr
)
2431 char ifname
[IFNAMSIZ
+ 1] = {0};
2432 struct net_info
*iter
, *next
;
2433 struct net_device
*ndev
= NULL
;
2435 *out_addr
= (unsigned long int) data
; /* point to command str by default */
2437 /* check whether ifname=<ifname> is provided in the command */
2438 pos
= strstr(data
, "ifname=");
2440 pos
+= strlen("ifname=");
2441 pos1
= strstr(pos
, " ");
2443 WL_ERR(("command format error \n"));
2447 ifname_len
= pos1
- pos
;
2448 if (memcpy(ifname
, pos
, ifname_len
) != BCME_OK
) {
2449 WL_ERR(("Failed to copy data. len: %d\n", ifname_len
));
2452 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
2453 #pragma GCC diagnostic push
2454 #pragma GCC diagnostic ignored "-Wcast-qual"
2456 for_each_ndev(cfg
, iter
, next
) {
2458 if (strncmp(iter
->ndev
->name
, ifname
,
2459 strlen(iter
->ndev
->name
)) == 0) {
2460 /* matching ifname found */
2461 WL_DBG(("matching interface (%s) found ndev:%p \n",
2462 iter
->ndev
->name
, iter
->ndev
));
2463 *out_addr
= (unsigned long int)(pos1
+ 1);
2464 /* Returns the command portion after ifname=<name> */
2469 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
2470 #pragma GCC diagnostic pop
2472 WL_ERR(("Couldn't find ifname:%s in the netinfo list \n",
2477 /* If ifname=<name> arg is not provided, use default ndev */
2478 ndev
= wdev
->netdev
? wdev
->netdev
: bcmcfg_to_prmry_ndev(cfg
);
2479 WL_DBG(("Using default ndev (%s) \n", ndev
->name
));
2483 /* Max length for the reply buffer. For BRCM_ATTR_DRIVER_CMD, the reply
2484 * would be a formatted string and reply buf would be the size of the
2487 #define WL_DRIVER_PRIV_CMD_LEN 512
2489 #ifdef BCM_PRIV_CMD_SUPPORT
2490 /* strlen("ifname=") + IFNAMESIZE + strlen(" ") + '\0' */
2491 #define ANDROID_PRIV_CMD_IF_PREFIX_LEN (7 + IFNAMSIZ + 2)
2493 wl_cfgvendor_priv_bcm_handler(struct wiphy
*wiphy
,
2494 struct wireless_dev
*wdev
, const void *data
, int len
)
2496 const struct nlattr
*iter
;
2498 int data_len
= 0, cmd_len
= 0, tmp
= 0, type
= 0;
2499 struct net_device
*ndev
= wdev
->netdev
;
2500 char *reply_buf
= NULL
;
2502 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2504 struct net_device
*net
= NULL
;
2505 unsigned long int cmd_out
= 0;
2506 u32 reply_len
= WL_DRIVER_PRIV_CMD_LEN
;
2508 WL_DBG(("%s: Enter \n", __func__
));
2510 /* hold wake lock */
2511 net_os_wake_lock(ndev
);
2513 nla_for_each_attr(iter
, data
, len
, tmp
) {
2514 type
= nla_type(iter
);
2515 cmd
= nla_data(iter
);
2516 cmd_len
= nla_len(iter
);
2518 WL_DBG(("%s: type: %d cmd_len:%d cmd_ptr:%p \n", __func__
, type
, cmd_len
, cmd
));
2519 if (!cmd
|| !cmd_len
) {
2520 WL_ERR(("Invalid cmd data \n"));
2525 #if defined(WL_ANDROID_PRIV_CMD_OVER_NL80211)
2526 if (type
== BRCM_ATTR_DRIVER_CMD
) {
2527 if ((cmd_len
>= WL_DRIVER_PRIV_CMD_LEN
) ||
2528 (cmd_len
< ANDROID_PRIV_CMD_IF_PREFIX_LEN
)) {
2529 WL_ERR(("Unexpected command length (%u). Ignore the command\n",
2535 /* check whether there is any ifname prefix provided */
2536 if (memcpy(cmd_prefix
, cmd
, ANDROID_PRIV_CMD_IF_PREFIX_LEN
) != BCME_OK
) {
2537 WL_ERR(("memcpy failed for cmd buffer. len:%d\n", cmd_len
));
2542 net
= wl_cfgvendor_get_ndev(cfg
, wdev
, cmd_prefix
, &cmd_out
);
2543 if (!cmd_out
|| !net
) {
2544 WL_ERR(("ndev not found\n"));
2549 /* find offset of the command */
2550 current_pos
= (char *)cmd_out
;
2551 cmd_offset
= current_pos
- cmd_prefix
;
2553 if (!current_pos
|| (cmd_offset
) > ANDROID_PRIV_CMD_IF_PREFIX_LEN
) {
2554 WL_ERR(("Invalid len cmd_offset: %u \n", cmd_offset
));
2559 /* Private command data in expected to be in str format. To ensure that
2560 * the data is null terminated, copy to a local buffer before use
2562 cmd_buf
= (char *)MALLOCZ(cfg
->osh
, cmd_buf_len
);
2564 WL_ERR(("memory alloc failed for %u \n", cmd_buf_len
));
2569 /* Point to the start of command */
2570 if (memcpy(cmd_buf
, (const void *)(cmd
+ cmd_offset
),
2571 (cmd_len
- cmd_offset
- 1)) != BCME_OK
) {
2572 WL_ERR(("memcpy failed for cmd buffer. len:%d\n", cmd_len
));
2576 cmd_buf
[WL_DRIVER_PRIV_CMD_LEN
- 1] = '\0';
2578 WL_DBG(("vendor_command: %s len: %u \n", cmd_buf
, cmd_buf_len
));
2579 bytes_written
= wl_handle_private_cmd(net
, cmd_buf
, cmd_buf_len
);
2580 WL_DBG(("bytes_written: %d \n", bytes_written
));
2581 if (bytes_written
== 0) {
2582 snprintf(cmd_buf
, cmd_buf_len
, "%s", "OK");
2583 data_len
= strlen("OK");
2584 } else if (bytes_written
> 0) {
2585 if (bytes_written
>= (cmd_buf_len
- 1)) {
2591 data_len
= bytes_written
;
2593 /* -ve return value. Propagate the error back */
2594 err
= bytes_written
;
2597 if ((data_len
> 0) && (data_len
< (cmd_buf_len
- 1)) && cmd_buf
) {
2598 err
= wl_cfgvendor_send_cmd_reply(wiphy
, cmd_buf
, data_len
+1);
2599 if (unlikely(err
)) {
2600 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
2602 WL_DBG(("Vendor Command reply sent successfully!\n"));
2605 /* No data to be sent back as reply */
2606 WL_ERR(("Vendor_cmd: No reply expected. data_len:%u cmd_buf %p \n",
2607 data_len
, cmd_buf
));
2611 #endif /* WL_ANDROID_PRIV_CMD_OVER_NL80211 && OEM_ANDROID */
2615 #if defined(WL_ANDROID_PRIV_CMD_OVER_NL80211)
2617 MFREE(cfg
->osh
, cmd_buf
, cmd_buf_len
);
2619 #endif /* WL_ANDROID_PRIV_CMD_OVER_NL80211 && OEM_ANDROID */
2620 net_os_wake_unlock(ndev
);
2623 #endif /* BCM_PRIV_CMD_SUPPORT */
2626 static const char *nan_attr_to_str(u16 cmd
)
2629 C2S(NAN_ATTRIBUTE_HEADER
)
2630 C2S(NAN_ATTRIBUTE_HANDLE
)
2631 C2S(NAN_ATTRIBUTE_TRANSAC_ID
)
2632 C2S(NAN_ATTRIBUTE_2G_SUPPORT
)
2633 C2S(NAN_ATTRIBUTE_SDF_2G_SUPPORT
)
2634 C2S(NAN_ATTRIBUTE_SDF_5G_SUPPORT
)
2635 C2S(NAN_ATTRIBUTE_5G_SUPPORT
)
2636 C2S(NAN_ATTRIBUTE_SYNC_DISC_2G_BEACON
)
2637 C2S(NAN_ATTRIBUTE_SYNC_DISC_5G_BEACON
)
2638 C2S(NAN_ATTRIBUTE_CLUSTER_LOW
)
2639 C2S(NAN_ATTRIBUTE_CLUSTER_HIGH
)
2640 C2S(NAN_ATTRIBUTE_SID_BEACON
)
2641 C2S(NAN_ATTRIBUTE_RSSI_CLOSE
)
2642 C2S(NAN_ATTRIBUTE_RSSI_MIDDLE
)
2643 C2S(NAN_ATTRIBUTE_RSSI_PROXIMITY
)
2644 C2S(NAN_ATTRIBUTE_RSSI_CLOSE_5G
)
2645 C2S(NAN_ATTRIBUTE_RSSI_MIDDLE_5G
)
2646 C2S(NAN_ATTRIBUTE_RSSI_PROXIMITY_5G
)
2647 C2S(NAN_ATTRIBUTE_HOP_COUNT_LIMIT
)
2648 C2S(NAN_ATTRIBUTE_RANDOM_TIME
)
2649 C2S(NAN_ATTRIBUTE_MASTER_PREF
)
2650 C2S(NAN_ATTRIBUTE_PERIODIC_SCAN_INTERVAL
)
2651 C2S(NAN_ATTRIBUTE_PUBLISH_ID
)
2652 C2S(NAN_ATTRIBUTE_TTL
)
2653 C2S(NAN_ATTRIBUTE_PERIOD
)
2654 C2S(NAN_ATTRIBUTE_REPLIED_EVENT_FLAG
)
2655 C2S(NAN_ATTRIBUTE_PUBLISH_TYPE
)
2656 C2S(NAN_ATTRIBUTE_TX_TYPE
)
2657 C2S(NAN_ATTRIBUTE_PUBLISH_COUNT
)
2658 C2S(NAN_ATTRIBUTE_SERVICE_NAME_LEN
)
2659 C2S(NAN_ATTRIBUTE_SERVICE_NAME
)
2660 C2S(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
)
2661 C2S(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
)
2662 C2S(NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN
)
2663 C2S(NAN_ATTRIBUTE_RX_MATCH_FILTER
)
2664 C2S(NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN
)
2665 C2S(NAN_ATTRIBUTE_TX_MATCH_FILTER
)
2666 C2S(NAN_ATTRIBUTE_SUBSCRIBE_ID
)
2667 C2S(NAN_ATTRIBUTE_SUBSCRIBE_TYPE
)
2668 C2S(NAN_ATTRIBUTE_SERVICERESPONSEFILTER
)
2669 C2S(NAN_ATTRIBUTE_SERVICERESPONSEINCLUDE
)
2670 C2S(NAN_ATTRIBUTE_USESERVICERESPONSEFILTER
)
2671 C2S(NAN_ATTRIBUTE_SSIREQUIREDFORMATCHINDICATION
)
2672 C2S(NAN_ATTRIBUTE_SUBSCRIBE_MATCH
)
2673 C2S(NAN_ATTRIBUTE_SUBSCRIBE_COUNT
)
2674 C2S(NAN_ATTRIBUTE_MAC_ADDR
)
2675 C2S(NAN_ATTRIBUTE_MAC_ADDR_LIST
)
2676 C2S(NAN_ATTRIBUTE_MAC_ADDR_LIST_NUM_ENTRIES
)
2677 C2S(NAN_ATTRIBUTE_PUBLISH_MATCH
)
2678 C2S(NAN_ATTRIBUTE_ENABLE_STATUS
)
2679 C2S(NAN_ATTRIBUTE_JOIN_STATUS
)
2680 C2S(NAN_ATTRIBUTE_ROLE
)
2681 C2S(NAN_ATTRIBUTE_MASTER_RANK
)
2682 C2S(NAN_ATTRIBUTE_ANCHOR_MASTER_RANK
)
2683 C2S(NAN_ATTRIBUTE_CNT_PEND_TXFRM
)
2684 C2S(NAN_ATTRIBUTE_CNT_BCN_TX
)
2685 C2S(NAN_ATTRIBUTE_CNT_BCN_RX
)
2686 C2S(NAN_ATTRIBUTE_CNT_SVC_DISC_TX
)
2687 C2S(NAN_ATTRIBUTE_CNT_SVC_DISC_RX
)
2688 C2S(NAN_ATTRIBUTE_AMBTT
)
2689 C2S(NAN_ATTRIBUTE_CLUSTER_ID
)
2690 C2S(NAN_ATTRIBUTE_INST_ID
)
2691 C2S(NAN_ATTRIBUTE_OUI
)
2692 C2S(NAN_ATTRIBUTE_STATUS
)
2693 C2S(NAN_ATTRIBUTE_DE_EVENT_TYPE
)
2694 C2S(NAN_ATTRIBUTE_MERGE
)
2695 C2S(NAN_ATTRIBUTE_IFACE
)
2696 C2S(NAN_ATTRIBUTE_CHANNEL
)
2697 C2S(NAN_ATTRIBUTE_24G_CHANNEL
)
2698 C2S(NAN_ATTRIBUTE_5G_CHANNEL
)
2699 C2S(NAN_ATTRIBUTE_PEER_ID
)
2700 C2S(NAN_ATTRIBUTE_NDP_ID
)
2701 C2S(NAN_ATTRIBUTE_SECURITY
)
2702 C2S(NAN_ATTRIBUTE_QOS
)
2703 C2S(NAN_ATTRIBUTE_RSP_CODE
)
2704 C2S(NAN_ATTRIBUTE_INST_COUNT
)
2705 C2S(NAN_ATTRIBUTE_PEER_DISC_MAC_ADDR
)
2706 C2S(NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR
)
2707 C2S(NAN_ATTRIBUTE_IF_ADDR
)
2708 C2S(NAN_ATTRIBUTE_WARMUP_TIME
)
2709 C2S(NAN_ATTRIBUTE_RECV_IND_CFG
)
2710 C2S(NAN_ATTRIBUTE_CONNMAP
)
2711 C2S(NAN_ATTRIBUTE_DWELL_TIME
)
2712 C2S(NAN_ATTRIBUTE_SCAN_PERIOD
)
2713 C2S(NAN_ATTRIBUTE_RSSI_WINDOW_SIZE
)
2714 C2S(NAN_ATTRIBUTE_CONF_CLUSTER_VAL
)
2715 C2S(NAN_ATTRIBUTE_CIPHER_SUITE_TYPE
)
2716 C2S(NAN_ATTRIBUTE_KEY_TYPE
)
2717 C2S(NAN_ATTRIBUTE_KEY_LEN
)
2718 C2S(NAN_ATTRIBUTE_SCID
)
2719 C2S(NAN_ATTRIBUTE_SCID_LEN
)
2720 C2S(NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP
)
2721 C2S(NAN_ATTRIBUTE_SDE_CONTROL_SECURITY
)
2722 C2S(NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE
)
2723 C2S(NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT
)
2724 C2S(NAN_ATTRIBUTE_NO_CONFIG_AVAIL
)
2725 C2S(NAN_ATTRIBUTE_2G_AWAKE_DW
)
2726 C2S(NAN_ATTRIBUTE_5G_AWAKE_DW
)
2727 C2S(NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG
)
2728 C2S(NAN_ATTRIBUTE_KEY_DATA
)
2729 C2S(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN
)
2730 C2S(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO
)
2731 C2S(NAN_ATTRIBUTE_REASON
)
2732 C2S(NAN_ATTRIBUTE_DISC_IND_CFG
)
2733 C2S(NAN_ATTRIBUTE_DWELL_TIME_5G
)
2734 C2S(NAN_ATTRIBUTE_SCAN_PERIOD_5G
)
2735 C2S(NAN_ATTRIBUTE_SUB_SID_BEACON
)
2737 return "NAN_ATTRIBUTE_UNKNOWN";
2741 nan_hal_status_t nan_status_reasonstr_map
[] = {
2742 {NAN_STATUS_SUCCESS
, "NAN status success"},
2743 {NAN_STATUS_INTERNAL_FAILURE
, "NAN Discovery engine failure"},
2744 {NAN_STATUS_PROTOCOL_FAILURE
, "protocol failure"},
2745 {NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID
, "invalid pub_sub ID"},
2746 {NAN_STATUS_NO_RESOURCE_AVAILABLE
, "No space available"},
2747 {NAN_STATUS_INVALID_PARAM
, "invalid param"},
2748 {NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID
, "invalid req inst id"},
2749 {NAN_STATUS_INVALID_NDP_ID
, "invalid ndp id"},
2750 {NAN_STATUS_NAN_NOT_ALLOWED
, "Nan not allowed"},
2751 {NAN_STATUS_NO_OTA_ACK
, "No OTA ack"},
2752 {NAN_STATUS_ALREADY_ENABLED
, "NAN is Already enabled"},
2753 {NAN_STATUS_FOLLOWUP_QUEUE_FULL
, "Follow-up queue full"},
2754 {NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED
, "unsupported concurrency"},
2758 wl_cfgvendor_add_nan_reason_str(nan_status_type_t status
, nan_hal_resp_t
*nan_req_resp
)
2761 int num
= (int)(sizeof(nan_status_reasonstr_map
)/sizeof(nan_status_reasonstr_map
[0]));
2762 for (i
= 0; i
< num
; i
++) {
2763 if (nan_status_reasonstr_map
[i
].status
== status
) {
2764 strlcpy(nan_req_resp
->nan_reason
, nan_status_reasonstr_map
[i
].nan_reason
,
2765 sizeof(nan_status_reasonstr_map
[i
].nan_reason
));
2772 wl_cfgvendor_brcm_to_nanhal_status(int32 vendor_status
)
2774 nan_status_type_t hal_status
;
2775 switch (vendor_status
) {
2777 hal_status
= NAN_STATUS_SUCCESS
;
2781 hal_status
= NAN_STATUS_NAN_NOT_ALLOWED
;
2785 case BCME_UNSUPPORTED
:
2786 case BCME_USAGE_ERROR
:
2788 hal_status
= NAN_STATUS_INVALID_PARAM
;
2791 case BCME_NORESOURCE
:
2792 case WL_NAN_E_SVC_SUB_LIST_FULL
:
2793 hal_status
= NAN_STATUS_NO_RESOURCE_AVAILABLE
;
2795 case WL_NAN_E_SD_TX_LIST_FULL
:
2796 hal_status
= NAN_STATUS_FOLLOWUP_QUEUE_FULL
;
2798 case WL_NAN_E_BAD_INSTANCE
:
2799 hal_status
= NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID
;
2802 WL_ERR(("%s Unknown vendor status, status = %d\n",
2803 __func__
, vendor_status
));
2805 hal_status
= NAN_STATUS_INTERNAL_FAILURE
;
2811 wl_cfgvendor_nan_cmd_reply(struct wiphy
*wiphy
, int nan_cmd
,
2812 nan_hal_resp_t
*nan_req_resp
, int ret
, int nan_cmd_status
)
2816 nan_req_resp
->subcmd
= nan_cmd
;
2817 if (ret
== BCME_OK
) {
2818 nan_reply
= nan_cmd_status
;
2822 nan_req_resp
->status
= wl_cfgvendor_brcm_to_nanhal_status(nan_reply
);
2823 nan_req_resp
->value
= ret
;
2824 err
= wl_cfgvendor_send_cmd_reply(wiphy
, nan_req_resp
,
2825 sizeof(*nan_req_resp
));
2826 /* giving more prio to ret than err */
2827 return (ret
== 0) ? err
: ret
;
2831 wl_cfgvendor_free_disc_cmd_data(struct bcm_cfg80211
*cfg
,
2832 nan_discover_cmd_data_t
*cmd_data
)
2835 WL_ERR(("Cmd_data is null\n"));
2838 if (cmd_data
->svc_info
.data
) {
2839 MFREE(cfg
->osh
, cmd_data
->svc_info
.data
, cmd_data
->svc_info
.dlen
);
2841 if (cmd_data
->svc_hash
.data
) {
2842 MFREE(cfg
->osh
, cmd_data
->svc_hash
.data
, cmd_data
->svc_hash
.dlen
);
2844 if (cmd_data
->rx_match
.data
) {
2845 MFREE(cfg
->osh
, cmd_data
->rx_match
.data
, cmd_data
->rx_match
.dlen
);
2847 if (cmd_data
->tx_match
.data
) {
2848 MFREE(cfg
->osh
, cmd_data
->tx_match
.data
, cmd_data
->tx_match
.dlen
);
2850 if (cmd_data
->mac_list
.list
) {
2851 MFREE(cfg
->osh
, cmd_data
->mac_list
.list
,
2852 cmd_data
->mac_list
.num_mac_addr
* ETHER_ADDR_LEN
);
2854 if (cmd_data
->key
.data
) {
2855 MFREE(cfg
->osh
, cmd_data
->key
.data
, NAN_MAX_PMK_LEN
);
2857 if (cmd_data
->sde_svc_info
.data
) {
2858 MFREE(cfg
->osh
, cmd_data
->sde_svc_info
.data
, cmd_data
->sde_svc_info
.dlen
);
2860 MFREE(cfg
->osh
, cmd_data
, sizeof(*cmd_data
));
2864 wl_cfgvendor_free_dp_cmd_data(struct bcm_cfg80211
*cfg
,
2865 nan_datapath_cmd_data_t
*cmd_data
)
2868 WL_ERR(("Cmd_data is null\n"));
2871 if (cmd_data
->svc_hash
.data
) {
2872 MFREE(cfg
->osh
, cmd_data
->svc_hash
.data
, cmd_data
->svc_hash
.dlen
);
2874 if (cmd_data
->svc_info
.data
) {
2875 MFREE(cfg
->osh
, cmd_data
->svc_info
.data
, cmd_data
->svc_info
.dlen
);
2877 if (cmd_data
->key
.data
) {
2878 MFREE(cfg
->osh
, cmd_data
->key
.data
, NAN_MAX_PMK_LEN
);
2880 MFREE(cfg
->osh
, cmd_data
, sizeof(*cmd_data
));
2883 #define WL_NAN_EVENT_MAX_BUF 256
2884 #ifdef WL_NAN_DISC_CACHE
2886 wl_cfgvendor_nan_parse_dp_sec_info_args(struct wiphy
*wiphy
,
2887 const void *buf
, int len
, nan_datapath_sec_info_cmd_data_t
*cmd_data
)
2892 const struct nlattr
*iter
;
2896 nla_for_each_attr(iter
, buf
, len
, rem
) {
2897 attr_type
= nla_type(iter
);
2898 WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type
), attr_type
));
2900 switch (attr_type
) {
2901 case NAN_ATTRIBUTE_MAC_ADDR
:
2902 memcpy((char*)&cmd_data
->mac_addr
, (char*)nla_data(iter
),
2905 case NAN_ATTRIBUTE_PUBLISH_ID
:
2906 cmd_data
->pub_id
= nla_get_u16(iter
);
2908 case NAN_ATTRIBUTE_NDP_ID
:
2909 cmd_data
->ndp_instance_id
= nla_get_u32(iter
);
2912 WL_ERR(("%s: Unknown type, %d\n", __FUNCTION__
, attr_type
));
2917 /* We need to call set_config_handler b/f calling start enable TBD */
2921 #endif /* WL_NAN_DISC_CACHE */
2923 int8 chanbuf
[CHANSPEC_STR_LEN
];
2925 wl_cfgvendor_nan_parse_datapath_args(struct wiphy
*wiphy
,
2926 const void *buf
, int len
, nan_datapath_cmd_data_t
*cmd_data
)
2931 const struct nlattr
*iter
;
2932 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2937 nla_for_each_attr(iter
, buf
, len
, rem
) {
2938 attr_type
= nla_type(iter
);
2939 WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type
), attr_type
));
2941 switch (attr_type
) {
2942 case NAN_ATTRIBUTE_NDP_ID
:
2943 if (nla_len(iter
) != sizeof(uint32
)) {
2947 cmd_data
->ndp_instance_id
= nla_get_u32(iter
);
2949 case NAN_ATTRIBUTE_IFACE
:
2950 if (nla_len(iter
) >= sizeof(cmd_data
->ndp_iface
)) {
2951 WL_ERR(("iface_name len wrong:%d\n", nla_len(iter
)));
2955 strlcpy((char *)cmd_data
->ndp_iface
, (char *)nla_data(iter
),
2958 case NAN_ATTRIBUTE_SECURITY
:
2959 if (nla_len(iter
) != sizeof(uint8
)) {
2963 cmd_data
->ndp_cfg
.security_cfg
= nla_get_u8(iter
);
2965 case NAN_ATTRIBUTE_QOS
:
2966 if (nla_len(iter
) != sizeof(uint8
)) {
2970 cmd_data
->ndp_cfg
.qos_cfg
= nla_get_u8(iter
);
2972 case NAN_ATTRIBUTE_RSP_CODE
:
2973 if (nla_len(iter
) != sizeof(uint8
)) {
2977 cmd_data
->rsp_code
= nla_get_u8(iter
);
2979 case NAN_ATTRIBUTE_INST_COUNT
:
2980 if (nla_len(iter
) != sizeof(uint8
)) {
2984 cmd_data
->num_ndp_instances
= nla_get_u8(iter
);
2986 case NAN_ATTRIBUTE_PEER_DISC_MAC_ADDR
:
2987 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
2991 memcpy((char*)&cmd_data
->peer_disc_mac_addr
,
2992 (char*)nla_data(iter
), ETHER_ADDR_LEN
);
2994 case NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR
:
2995 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
2999 memcpy((char*)&cmd_data
->peer_ndi_mac_addr
,
3000 (char*)nla_data(iter
), ETHER_ADDR_LEN
);
3002 case NAN_ATTRIBUTE_MAC_ADDR
:
3003 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
3007 memcpy((char*)&cmd_data
->mac_addr
, (char*)nla_data(iter
),
3010 case NAN_ATTRIBUTE_IF_ADDR
:
3011 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
3015 memcpy((char*)&cmd_data
->if_addr
, (char*)nla_data(iter
),
3018 case NAN_ATTRIBUTE_ENTRY_CONTROL
:
3019 if (nla_len(iter
) != sizeof(uint8
)) {
3023 cmd_data
->avail_params
.duration
= nla_get_u8(iter
);
3025 case NAN_ATTRIBUTE_AVAIL_BIT_MAP
:
3026 if (nla_len(iter
) != sizeof(uint32
)) {
3030 cmd_data
->avail_params
.bmap
= nla_get_u32(iter
);
3032 case NAN_ATTRIBUTE_CHANNEL
: {
3033 if (nla_len(iter
) != sizeof(uint32
)) {
3037 /* take the default channel start_factor frequency */
3038 chan
= wf_mhz2channel((uint
)nla_get_u32(iter
), 0);
3039 if (chan
<= CH_MAX_2G_CHANNEL
) {
3040 cmd_data
->avail_params
.chanspec
[0] =
3041 wf_channel2chspec(chan
, WL_CHANSPEC_BW_20
);
3043 cmd_data
->avail_params
.chanspec
[0] =
3044 wf_channel2chspec(chan
, WL_CHANSPEC_BW_80
);
3046 if (cmd_data
->avail_params
.chanspec
[0] == 0) {
3047 WL_ERR(("Channel is not valid \n"));
3051 WL_TRACE(("valid chanspec, chanspec = 0x%04x \n",
3052 cmd_data
->avail_params
.chanspec
[0]));
3055 case NAN_ATTRIBUTE_NO_CONFIG_AVAIL
:
3056 if (nla_len(iter
) != sizeof(uint8
)) {
3060 cmd_data
->avail_params
.no_config_avail
= (bool)nla_get_u8(iter
);
3062 case NAN_ATTRIBUTE_SERVICE_NAME_LEN
: {
3063 if (nla_len(iter
) != sizeof(uint16
)) {
3067 if (cmd_data
->svc_hash
.dlen
) {
3068 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3072 cmd_data
->svc_hash
.dlen
= nla_get_u16(iter
);
3073 if (cmd_data
->svc_hash
.dlen
!= WL_NAN_SVC_HASH_LEN
) {
3074 WL_ERR(("invalid svc_hash length = %u\n", cmd_data
->svc_hash
.dlen
));
3080 case NAN_ATTRIBUTE_SERVICE_NAME
:
3081 if ((!cmd_data
->svc_hash
.dlen
) ||
3082 (nla_len(iter
) != cmd_data
->svc_hash
.dlen
)) {
3083 WL_ERR(("invalid svc_hash length = %d,%d\n",
3084 cmd_data
->svc_hash
.dlen
, nla_len(iter
)));
3088 if (cmd_data
->svc_hash
.data
) {
3089 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3093 cmd_data
->svc_hash
.data
=
3094 MALLOCZ(cfg
->osh
, cmd_data
->svc_hash
.dlen
);
3095 if (!cmd_data
->svc_hash
.data
) {
3096 WL_ERR(("failed to allocate svc_hash data, len=%d\n",
3097 cmd_data
->svc_hash
.dlen
));
3101 memcpy(cmd_data
->svc_hash
.data
, nla_data(iter
),
3102 cmd_data
->svc_hash
.dlen
);
3104 case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
:
3105 if (nla_len(iter
) != sizeof(uint16
)) {
3109 if (cmd_data
->svc_info
.dlen
) {
3110 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3114 cmd_data
->svc_info
.dlen
= nla_get_u16(iter
);
3115 if (cmd_data
->svc_info
.dlen
> MAX_APP_INFO_LEN
) {
3116 WL_ERR(("Not allowed beyond :%d\n", MAX_APP_INFO_LEN
));
3121 case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
:
3122 if ((!cmd_data
->svc_info
.dlen
) ||
3123 (nla_len(iter
) != cmd_data
->svc_info
.dlen
)) {
3124 WL_ERR(("failed to allocate svc info by invalid len=%d,%d\n",
3125 cmd_data
->svc_info
.dlen
, nla_len(iter
)));
3129 if (cmd_data
->svc_info
.data
) {
3130 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3134 cmd_data
->svc_info
.data
= MALLOCZ(cfg
->osh
, cmd_data
->svc_info
.dlen
);
3135 if (cmd_data
->svc_info
.data
== NULL
) {
3136 WL_ERR(("failed to allocate svc info data, len=%d\n",
3137 cmd_data
->svc_info
.dlen
));
3141 memcpy(cmd_data
->svc_info
.data
,
3142 nla_data(iter
), cmd_data
->svc_info
.dlen
);
3144 case NAN_ATTRIBUTE_PUBLISH_ID
:
3145 if (nla_len(iter
) != sizeof(uint32
)) {
3149 cmd_data
->pub_id
= nla_get_u32(iter
);
3151 case NAN_ATTRIBUTE_CIPHER_SUITE_TYPE
:
3152 if (nla_len(iter
) != sizeof(uint8
)) {
3156 cmd_data
->csid
= nla_get_u8(iter
);
3157 WL_TRACE(("CSID = %u\n", cmd_data
->csid
));
3159 case NAN_ATTRIBUTE_KEY_TYPE
:
3160 if (nla_len(iter
) != sizeof(uint8
)) {
3164 cmd_data
->key_type
= nla_get_u8(iter
);
3165 WL_TRACE(("Key Type = %u\n", cmd_data
->key_type
));
3167 case NAN_ATTRIBUTE_KEY_LEN
:
3168 if (nla_len(iter
) != sizeof(uint32
)) {
3172 if (cmd_data
->key
.dlen
) {
3173 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3177 cmd_data
->key
.dlen
= nla_get_u32(iter
);
3178 if ((!cmd_data
->key
.dlen
) || (cmd_data
->key
.dlen
> WL_NAN_NCS_SK_PMK_LEN
)) {
3179 WL_ERR(("invalid key length = %u\n", cmd_data
->key
.dlen
));
3183 WL_TRACE(("valid key length = %u\n", cmd_data
->key
.dlen
));
3185 case NAN_ATTRIBUTE_KEY_DATA
:
3186 if ((!cmd_data
->key
.dlen
) ||
3187 (nla_len(iter
) != cmd_data
->key
.dlen
)) {
3188 WL_ERR(("failed to allocate key data by invalid len=%d,%d\n",
3189 cmd_data
->key
.dlen
, nla_len(iter
)));
3193 if (cmd_data
->key
.data
) {
3194 WL_ERR(("trying to overwrite key data.\n"));
3199 cmd_data
->key
.data
= MALLOCZ(cfg
->osh
, NAN_MAX_PMK_LEN
);
3200 if (cmd_data
->key
.data
== NULL
) {
3201 WL_ERR(("failed to allocate key data, len=%d\n",
3202 cmd_data
->key
.dlen
));
3206 memcpy(cmd_data
->key
.data
, nla_data(iter
),
3207 MIN(cmd_data
->key
.dlen
, NAN_MAX_PMK_LEN
));
3211 WL_ERR(("Unknown type, %d\n", attr_type
));
3217 /* We need to call set_config_handler b/f calling start enable TBD */
3223 wl_cfgvendor_nan_parse_discover_args(struct wiphy
*wiphy
,
3224 const void *buf
, int len
, nan_discover_cmd_data_t
*cmd_data
)
3229 const struct nlattr
*iter
;
3230 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3237 nla_for_each_attr(iter
, buf
, len
, rem
) {
3238 attr_type
= nla_type(iter
);
3239 WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type
), attr_type
));
3241 switch (attr_type
) {
3242 case NAN_ATTRIBUTE_TRANSAC_ID
:
3243 if (nla_len(iter
) != sizeof(uint16
)) {
3247 cmd_data
->token
= nla_get_u16(iter
);
3249 case NAN_ATTRIBUTE_PERIODIC_SCAN_INTERVAL
:
3252 /* Nan Publish/Subscribe request Attributes */
3253 case NAN_ATTRIBUTE_PUBLISH_ID
:
3254 if (nla_len(iter
) != sizeof(uint16
)) {
3258 cmd_data
->pub_id
= nla_get_u16(iter
);
3259 cmd_data
->local_id
= cmd_data
->pub_id
;
3261 case NAN_ATTRIBUTE_MAC_ADDR
:
3262 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
3266 memcpy((char*)&cmd_data
->mac_addr
, (char*)nla_data(iter
),
3269 case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
:
3270 if (nla_len(iter
) != sizeof(uint16
)) {
3274 if (cmd_data
->svc_info
.dlen
) {
3275 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3279 cmd_data
->svc_info
.dlen
= nla_get_u16(iter
);
3280 if (cmd_data
->svc_info
.dlen
> NAN_MAX_SERVICE_SPECIFIC_INFO_LEN
) {
3281 WL_ERR(("Not allowed beyond :%d\n",
3282 NAN_MAX_SERVICE_SPECIFIC_INFO_LEN
));
3287 case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
:
3288 if ((!cmd_data
->svc_info
.dlen
) ||
3289 (nla_len(iter
) != cmd_data
->svc_info
.dlen
)) {
3290 WL_ERR(("failed to allocate svc info by invalid len=%d,%d\n",
3291 cmd_data
->svc_info
.dlen
, nla_len(iter
)));
3295 if (cmd_data
->svc_info
.data
) {
3296 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3301 cmd_data
->svc_info
.data
= MALLOCZ(cfg
->osh
, cmd_data
->svc_info
.dlen
);
3302 if (cmd_data
->svc_info
.data
== NULL
) {
3303 WL_ERR(("failed to allocate svc info data, len=%d\n",
3304 cmd_data
->svc_info
.dlen
));
3308 memcpy(cmd_data
->svc_info
.data
,
3309 nla_data(iter
), cmd_data
->svc_info
.dlen
);
3311 case NAN_ATTRIBUTE_SUBSCRIBE_ID
:
3312 if (nla_len(iter
) != sizeof(uint16
)) {
3316 cmd_data
->sub_id
= nla_get_u16(iter
);
3317 cmd_data
->local_id
= cmd_data
->sub_id
;
3319 case NAN_ATTRIBUTE_SUBSCRIBE_TYPE
:
3320 if (nla_len(iter
) != sizeof(uint8
)) {
3324 cmd_data
->flags
|= nla_get_u8(iter
) ? WL_NAN_SUB_ACTIVE
: 0;
3326 case NAN_ATTRIBUTE_PUBLISH_COUNT
:
3327 if (nla_len(iter
) != sizeof(uint8
)) {
3331 cmd_data
->life_count
= nla_get_u8(iter
);
3333 case NAN_ATTRIBUTE_PUBLISH_TYPE
: {
3334 if (nla_len(iter
) != sizeof(uint8
)) {
3338 val_u8
= nla_get_u8(iter
);
3340 cmd_data
->flags
|= WL_NAN_PUB_UNSOLICIT
;
3341 } else if (val_u8
== 1) {
3342 cmd_data
->flags
|= WL_NAN_PUB_SOLICIT
;
3344 cmd_data
->flags
|= WL_NAN_PUB_BOTH
;
3348 case NAN_ATTRIBUTE_PERIOD
: {
3349 if (nla_len(iter
) != sizeof(uint16
)) {
3353 if (nla_get_u16(iter
) > NAN_MAX_AWAKE_DW_INTERVAL
) {
3354 WL_ERR(("Invalid/Out of bound value = %u\n", nla_get_u16(iter
)));
3358 if (nla_get_u16(iter
)) {
3359 cmd_data
->period
= 1 << (nla_get_u16(iter
)-1);
3363 case NAN_ATTRIBUTE_REPLIED_EVENT_FLAG
:
3365 case NAN_ATTRIBUTE_TTL
:
3366 if (nla_len(iter
) != sizeof(uint16
)) {
3370 cmd_data
->ttl
= nla_get_u16(iter
);
3372 case NAN_ATTRIBUTE_SERVICE_NAME_LEN
: {
3373 if (nla_len(iter
) != sizeof(uint16
)) {
3377 if (cmd_data
->svc_hash
.dlen
) {
3378 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3383 cmd_data
->svc_hash
.dlen
= nla_get_u16(iter
);
3384 if (cmd_data
->svc_hash
.dlen
!= WL_NAN_SVC_HASH_LEN
) {
3385 WL_ERR(("invalid svc_hash length = %u\n", cmd_data
->svc_hash
.dlen
));
3391 case NAN_ATTRIBUTE_SERVICE_NAME
:
3392 if ((!cmd_data
->svc_hash
.dlen
) ||
3393 (nla_len(iter
) != cmd_data
->svc_hash
.dlen
)) {
3394 WL_ERR(("invalid svc_hash length = %d,%d\n",
3395 cmd_data
->svc_hash
.dlen
, nla_len(iter
)));
3399 if (cmd_data
->svc_hash
.data
) {
3400 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3405 cmd_data
->svc_hash
.data
=
3406 MALLOCZ(cfg
->osh
, cmd_data
->svc_hash
.dlen
);
3407 if (!cmd_data
->svc_hash
.data
) {
3408 WL_ERR(("failed to allocate svc_hash data, len=%d\n",
3409 cmd_data
->svc_hash
.dlen
));
3413 memcpy(cmd_data
->svc_hash
.data
, nla_data(iter
),
3414 cmd_data
->svc_hash
.dlen
);
3416 case NAN_ATTRIBUTE_PEER_ID
:
3417 if (nla_len(iter
) != sizeof(uint32
)) {
3421 cmd_data
->remote_id
= nla_get_u32(iter
);
3423 case NAN_ATTRIBUTE_INST_ID
:
3424 if (nla_len(iter
) != sizeof(uint16
)) {
3428 cmd_data
->local_id
= nla_get_u16(iter
);
3430 case NAN_ATTRIBUTE_SUBSCRIBE_COUNT
:
3431 if (nla_len(iter
) != sizeof(uint8
)) {
3435 cmd_data
->life_count
= nla_get_u8(iter
);
3437 case NAN_ATTRIBUTE_SSIREQUIREDFORMATCHINDICATION
: {
3438 if (nla_len(iter
) != sizeof(uint8
)) {
3442 bit_flag
= (u32
)nla_get_u8(iter
);
3444 bit_flag
? WL_NAN_SUB_MATCH_IF_SVC_INFO
: 0;
3447 case NAN_ATTRIBUTE_SUBSCRIBE_MATCH
:
3448 case NAN_ATTRIBUTE_PUBLISH_MATCH
: {
3449 if (nla_len(iter
) != sizeof(uint8
)) {
3453 flag_match
= nla_get_u8(iter
);
3455 switch (flag_match
) {
3456 case NAN_MATCH_ALG_MATCH_CONTINUOUS
:
3457 /* Default fw behaviour, no need to set explicitly */
3459 case NAN_MATCH_ALG_MATCH_ONCE
:
3460 cmd_data
->flags
|= WL_NAN_MATCH_ONCE
;
3462 case NAN_MATCH_ALG_MATCH_NEVER
:
3463 cmd_data
->flags
|= WL_NAN_MATCH_NEVER
;
3466 WL_ERR(("invalid nan match alg = %u\n", flag_match
));
3472 case NAN_ATTRIBUTE_SERVICERESPONSEFILTER
:
3473 if (nla_len(iter
) != sizeof(uint8
)) {
3477 cmd_data
->srf_type
= nla_get_u8(iter
);
3479 case NAN_ATTRIBUTE_SERVICERESPONSEINCLUDE
:
3480 if (nla_len(iter
) != sizeof(uint8
)) {
3484 cmd_data
->srf_include
= nla_get_u8(iter
);
3486 case NAN_ATTRIBUTE_USESERVICERESPONSEFILTER
:
3487 if (nla_len(iter
) != sizeof(uint8
)) {
3491 cmd_data
->use_srf
= nla_get_u8(iter
);
3493 case NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN
:
3494 if (nla_len(iter
) != sizeof(uint16
)) {
3498 if (cmd_data
->rx_match
.dlen
) {
3499 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3503 cmd_data
->rx_match
.dlen
= nla_get_u16(iter
);
3504 if (cmd_data
->rx_match
.dlen
> MAX_MATCH_FILTER_LEN
) {
3506 WL_ERR(("Not allowed beyond %d\n", MAX_MATCH_FILTER_LEN
));
3510 case NAN_ATTRIBUTE_RX_MATCH_FILTER
:
3511 if ((!cmd_data
->rx_match
.dlen
) ||
3512 (nla_len(iter
) != cmd_data
->rx_match
.dlen
)) {
3513 WL_ERR(("RX match filter len wrong:%d,%d\n",
3514 cmd_data
->rx_match
.dlen
, nla_len(iter
)));
3518 if (cmd_data
->rx_match
.data
) {
3519 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3523 cmd_data
->rx_match
.data
=
3524 MALLOCZ(cfg
->osh
, cmd_data
->rx_match
.dlen
);
3525 if (cmd_data
->rx_match
.data
== NULL
) {
3526 WL_ERR(("failed to allocate LEN=[%u]\n",
3527 cmd_data
->rx_match
.dlen
));
3531 memcpy(cmd_data
->rx_match
.data
, nla_data(iter
),
3532 cmd_data
->rx_match
.dlen
);
3534 case NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN
:
3535 if (nla_len(iter
) != sizeof(uint16
)) {
3539 if (cmd_data
->tx_match
.dlen
) {
3540 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3544 cmd_data
->tx_match
.dlen
= nla_get_u16(iter
);
3545 if (cmd_data
->tx_match
.dlen
> MAX_MATCH_FILTER_LEN
) {
3547 WL_ERR(("Not allowed beyond %d\n", MAX_MATCH_FILTER_LEN
));
3551 case NAN_ATTRIBUTE_TX_MATCH_FILTER
:
3552 if ((!cmd_data
->tx_match
.dlen
) ||
3553 (nla_len(iter
) != cmd_data
->tx_match
.dlen
)) {
3554 WL_ERR(("TX match filter len wrong:%d,%d\n",
3555 cmd_data
->tx_match
.dlen
, nla_len(iter
)));
3559 if (cmd_data
->tx_match
.data
) {
3560 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3564 cmd_data
->tx_match
.data
=
3565 MALLOCZ(cfg
->osh
, cmd_data
->tx_match
.dlen
);
3566 if (cmd_data
->tx_match
.data
== NULL
) {
3567 WL_ERR(("failed to allocate LEN=[%u]\n",
3568 cmd_data
->tx_match
.dlen
));
3572 memcpy(cmd_data
->tx_match
.data
, nla_data(iter
),
3573 cmd_data
->tx_match
.dlen
);
3575 case NAN_ATTRIBUTE_MAC_ADDR_LIST_NUM_ENTRIES
:
3576 if (nla_len(iter
) != sizeof(uint16
)) {
3580 if (cmd_data
->mac_list
.num_mac_addr
) {
3581 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3585 cmd_data
->mac_list
.num_mac_addr
= nla_get_u16(iter
);
3587 case NAN_ATTRIBUTE_MAC_ADDR_LIST
:
3588 if ((!cmd_data
->mac_list
.num_mac_addr
) ||
3589 (nla_len(iter
) != (cmd_data
->mac_list
.num_mac_addr
* ETHER_ADDR_LEN
))) {
3590 WL_ERR(("wrong mac list len:%d,%d\n",
3591 cmd_data
->mac_list
.num_mac_addr
, nla_len(iter
)));
3595 if (cmd_data
->mac_list
.list
) {
3596 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3600 cmd_data
->mac_list
.list
=
3601 MALLOCZ(cfg
->osh
, (cmd_data
->mac_list
.num_mac_addr
3603 if (cmd_data
->mac_list
.list
== NULL
) {
3604 WL_ERR(("failed to allocate LEN=[%u]\n",
3605 (cmd_data
->mac_list
.num_mac_addr
* ETHER_ADDR_LEN
)));
3609 memcpy(cmd_data
->mac_list
.list
, nla_data(iter
),
3610 (cmd_data
->mac_list
.num_mac_addr
* ETHER_ADDR_LEN
));
3612 case NAN_ATTRIBUTE_TX_TYPE
:
3613 if (nla_len(iter
) != sizeof(uint8
)) {
3617 val_u8
= nla_get_u8(iter
);
3619 cmd_data
->flags
|= WL_NAN_PUB_BCAST
;
3620 WL_TRACE(("NAN_ATTRIBUTE_TX_TYPE: flags=NAN_PUB_BCAST\n"));
3623 case NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP
:
3624 if (nla_len(iter
) != sizeof(uint8
)) {
3628 if (nla_get_u8(iter
) == 1) {
3629 cmd_data
->sde_control_flag
3630 |= NAN_SDE_CF_DP_REQUIRED
;
3634 case NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT
:
3635 if (nla_len(iter
) != sizeof(uint8
)) {
3639 if (nla_get_u8(iter
) == 1) {
3640 cmd_data
->sde_control_flag
3641 |= NAN_SDE_CF_RANGING_REQUIRED
;
3645 case NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE
:
3646 if (nla_len(iter
) != sizeof(uint8
)) {
3650 if (nla_get_u8(iter
) == 1) {
3651 cmd_data
->sde_control_flag
3652 |= NAN_SDE_CF_MULTICAST_TYPE
;
3656 case NAN_ATTRIBUTE_SDE_CONTROL_SECURITY
:
3657 if (nla_len(iter
) != sizeof(uint8
)) {
3661 if (nla_get_u8(iter
) == 1) {
3662 cmd_data
->sde_control_flag
3663 |= NAN_SDE_CF_SECURITY_REQUIRED
;
3667 case NAN_ATTRIBUTE_RECV_IND_CFG
:
3668 if (nla_len(iter
) != sizeof(uint8
)) {
3672 cmd_data
->recv_ind_flag
= nla_get_u8(iter
);
3674 case NAN_ATTRIBUTE_CIPHER_SUITE_TYPE
:
3675 if (nla_len(iter
) != sizeof(uint8
)) {
3679 cmd_data
->csid
= nla_get_u8(iter
);
3680 WL_TRACE(("CSID = %u\n", cmd_data
->csid
));
3682 case NAN_ATTRIBUTE_KEY_TYPE
:
3683 if (nla_len(iter
) != sizeof(uint8
)) {
3687 cmd_data
->key_type
= nla_get_u8(iter
);
3688 WL_TRACE(("Key Type = %u\n", cmd_data
->key_type
));
3690 case NAN_ATTRIBUTE_KEY_LEN
:
3691 if (nla_len(iter
) != sizeof(uint32
)) {
3695 if (cmd_data
->key
.dlen
) {
3696 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3700 cmd_data
->key
.dlen
= nla_get_u32(iter
);
3701 if ((!cmd_data
->key
.dlen
) || (cmd_data
->key
.dlen
> WL_NAN_NCS_SK_PMK_LEN
)) {
3702 WL_ERR(("invalid key length = %u\n",
3703 cmd_data
->key
.dlen
));
3706 WL_TRACE(("valid key length = %u\n", cmd_data
->key
.dlen
));
3708 case NAN_ATTRIBUTE_KEY_DATA
:
3709 if (!cmd_data
->key
.dlen
||
3710 (nla_len(iter
) != cmd_data
->key
.dlen
)) {
3711 WL_ERR(("failed to allocate key data by invalid len=%d,%d\n",
3712 cmd_data
->key
.dlen
, nla_len(iter
)));
3716 if (cmd_data
->key
.data
) {
3717 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3722 cmd_data
->key
.data
= MALLOCZ(cfg
->osh
, NAN_MAX_PMK_LEN
);
3723 if (cmd_data
->key
.data
== NULL
) {
3724 WL_ERR(("failed to allocate key data, len=%d\n",
3725 cmd_data
->key
.dlen
));
3729 memcpy(cmd_data
->key
.data
, nla_data(iter
),
3730 MIN(cmd_data
->key
.dlen
, NAN_MAX_PMK_LEN
));
3732 case NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG
:
3733 if (nla_len(iter
) != sizeof(uint8
)) {
3737 if (nla_get_u8(iter
) == 1) {
3739 WL_NAN_RANGE_LIMITED
;
3743 case NAN_ATTRIBUTE_DISC_IND_CFG
:
3744 if (nla_len(iter
) != sizeof(uint8
)) {
3748 cmd_data
->disc_ind_cfg
= nla_get_u8(iter
);
3750 case NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN
:
3751 if (nla_len(iter
) != sizeof(uint16
)) {
3755 if (cmd_data
->sde_svc_info
.dlen
) {
3756 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3760 cmd_data
->sde_svc_info
.dlen
= nla_get_u16(iter
);
3761 if (cmd_data
->sde_svc_info
.dlen
> MAX_SDEA_SVC_INFO_LEN
) {
3763 WL_ERR(("Not allowed beyond %d\n", MAX_SDEA_SVC_INFO_LEN
));
3767 case NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO
:
3768 if ((!cmd_data
->sde_svc_info
.dlen
) ||
3769 (nla_len(iter
) != cmd_data
->sde_svc_info
.dlen
)) {
3770 WL_ERR(("wrong sdea info len:%d,%d\n",
3771 cmd_data
->sde_svc_info
.dlen
, nla_len(iter
)));
3775 if (cmd_data
->sde_svc_info
.data
) {
3776 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3780 cmd_data
->sde_svc_info
.data
= MALLOCZ(cfg
->osh
,
3781 cmd_data
->sde_svc_info
.dlen
);
3782 if (cmd_data
->sde_svc_info
.data
== NULL
) {
3783 WL_ERR(("failed to allocate svc info data, len=%d\n",
3784 cmd_data
->sde_svc_info
.dlen
));
3788 memcpy(cmd_data
->sde_svc_info
.data
,
3789 nla_data(iter
), cmd_data
->sde_svc_info
.dlen
);
3791 case NAN_ATTRIBUTE_SECURITY
:
3792 if (nla_len(iter
) != sizeof(uint8
)) {
3796 cmd_data
->ndp_cfg
.security_cfg
= nla_get_u8(iter
);
3798 case NAN_ATTRIBUTE_RANGING_INTERVAL
:
3799 if (nla_len(iter
) != sizeof(uint32
)) {
3803 cmd_data
->ranging_intvl_msec
= nla_get_u32(iter
);
3805 case NAN_ATTRIBUTE_RANGING_INGRESS_LIMIT
:
3806 if (nla_len(iter
) != sizeof(uint32
)) {
3810 cmd_data
->ingress_limit
= nla_get_u32(iter
);
3812 case NAN_ATTRIBUTE_RANGING_EGRESS_LIMIT
:
3813 if (nla_len(iter
) != sizeof(uint32
)) {
3817 cmd_data
->egress_limit
= nla_get_u32(iter
);
3819 case NAN_ATTRIBUTE_RANGING_INDICATION
:
3820 if (nla_len(iter
) != sizeof(uint32
)) {
3824 cmd_data
->ranging_indication
= nla_get_u32(iter
);
3826 /* Nan accept policy: Per service basis policy
3827 * Based on this policy(ALL/NONE), responder side
3828 * will send ACCEPT/REJECT
3830 case NAN_ATTRIBUTE_SVC_RESPONDER_POLICY
:
3831 if (nla_len(iter
) != sizeof(uint8
)) {
3835 cmd_data
->service_responder_policy
= nla_get_u8(iter
);
3838 WL_ERR(("Unknown type, %d\n", attr_type
));
3844 /* We need to call set_config_handler b/f calling start enable TBD */
3850 wl_cfgvendor_nan_parse_args(struct wiphy
*wiphy
, const void *buf
,
3851 int len
, nan_config_cmd_data_t
*cmd_data
, uint32
*nan_attr_mask
)
3856 const struct nlattr
*iter
;
3857 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3859 u8 sid_beacon
= 0, sub_sid_beacon
= 0;
3863 nla_for_each_attr(iter
, buf
, len
, rem
) {
3864 attr_type
= nla_type(iter
);
3865 WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type
), attr_type
));
3867 switch (attr_type
) {
3868 /* NAN Enable request attributes */
3869 case NAN_ATTRIBUTE_2G_SUPPORT
:{
3870 if (nla_len(iter
) != sizeof(uint8
)) {
3874 cmd_data
->support_2g
= nla_get_u8(iter
);
3875 *nan_attr_mask
|= NAN_ATTR_SUPPORT_2G_CONFIG
;
3878 case NAN_ATTRIBUTE_5G_SUPPORT
:{
3879 if (nla_len(iter
) != sizeof(uint8
)) {
3883 cmd_data
->support_5g
= nla_get_u8(iter
);
3884 *nan_attr_mask
|= NAN_ATTR_SUPPORT_5G_CONFIG
;
3887 case NAN_ATTRIBUTE_CLUSTER_LOW
: {
3888 if (nla_len(iter
) != sizeof(uint16
)) {
3892 cmd_data
->clus_id
.octet
[5] = nla_get_u16(iter
);
3895 case NAN_ATTRIBUTE_CLUSTER_HIGH
: {
3896 if (nla_len(iter
) != sizeof(uint16
)) {
3900 cmd_data
->clus_id
.octet
[4] = nla_get_u16(iter
);
3903 case NAN_ATTRIBUTE_SID_BEACON
: {
3904 if (nla_len(iter
) != sizeof(uint8
)) {
3908 sid_beacon
= nla_get_u8(iter
);
3909 cmd_data
->sid_beacon
.sid_enable
= (sid_beacon
& 0x01);
3910 if (cmd_data
->sid_beacon
.sid_enable
) {
3911 cmd_data
->sid_beacon
.sid_count
= (sid_beacon
>> 1);
3912 *nan_attr_mask
|= NAN_ATTR_SID_BEACON_CONFIG
;
3916 case NAN_ATTRIBUTE_SUB_SID_BEACON
: {
3917 if (nla_len(iter
) != sizeof(uint8
)) {
3921 sub_sid_beacon
= nla_get_u8(iter
);
3922 cmd_data
->sid_beacon
.sub_sid_enable
= (sub_sid_beacon
& 0x01);
3923 if (cmd_data
->sid_beacon
.sub_sid_enable
) {
3924 cmd_data
->sid_beacon
.sub_sid_count
= (sub_sid_beacon
>> 1);
3925 *nan_attr_mask
|= NAN_ATTR_SUB_SID_BEACON_CONFIG
;
3929 case NAN_ATTRIBUTE_SYNC_DISC_2G_BEACON
:
3930 if (nla_len(iter
) != sizeof(uint8
)) {
3934 cmd_data
->beacon_2g_val
= nla_get_u8(iter
);
3935 *nan_attr_mask
|= NAN_ATTR_SYNC_DISC_2G_BEACON_CONFIG
;
3937 case NAN_ATTRIBUTE_SYNC_DISC_5G_BEACON
:
3938 if (nla_len(iter
) != sizeof(uint8
)) {
3942 cmd_data
->beacon_5g_val
= nla_get_u8(iter
);
3943 *nan_attr_mask
|= NAN_ATTR_SYNC_DISC_5G_BEACON_CONFIG
;
3945 case NAN_ATTRIBUTE_SDF_2G_SUPPORT
:
3946 if (nla_len(iter
) != sizeof(uint8
)) {
3950 cmd_data
->sdf_2g_val
= nla_get_u8(iter
);
3951 *nan_attr_mask
|= NAN_ATTR_SDF_2G_SUPPORT_CONFIG
;
3953 case NAN_ATTRIBUTE_SDF_5G_SUPPORT
:
3954 if (nla_len(iter
) != sizeof(uint8
)) {
3958 cmd_data
->sdf_5g_val
= nla_get_u8(iter
);
3959 *nan_attr_mask
|= NAN_ATTR_SDF_5G_SUPPORT_CONFIG
;
3961 case NAN_ATTRIBUTE_HOP_COUNT_LIMIT
:
3962 if (nla_len(iter
) != sizeof(uint8
)) {
3966 cmd_data
->hop_count_limit
= nla_get_u8(iter
);
3967 *nan_attr_mask
|= NAN_ATTR_HOP_COUNT_LIMIT_CONFIG
;
3969 case NAN_ATTRIBUTE_RANDOM_TIME
:
3970 if (nla_len(iter
) != sizeof(uint8
)) {
3974 cmd_data
->metrics
.random_factor
= nla_get_u8(iter
);
3975 *nan_attr_mask
|= NAN_ATTR_RAND_FACTOR_CONFIG
;
3977 case NAN_ATTRIBUTE_MASTER_PREF
:
3978 if (nla_len(iter
) != sizeof(uint8
)) {
3982 cmd_data
->metrics
.master_pref
= nla_get_u8(iter
);
3984 case NAN_ATTRIBUTE_OUI
:
3985 if (nla_len(iter
) != sizeof(uint32
)) {
3989 cmd_data
->nan_oui
= nla_get_u32(iter
);
3990 *nan_attr_mask
|= NAN_ATTR_OUI_CONFIG
;
3991 WL_TRACE(("nan_oui=%d\n", cmd_data
->nan_oui
));
3993 case NAN_ATTRIBUTE_WARMUP_TIME
:
3994 if (nla_len(iter
) != sizeof(uint16
)) {
3998 cmd_data
->warmup_time
= nla_get_u16(iter
);
4000 case NAN_ATTRIBUTE_AMBTT
:
4001 case NAN_ATTRIBUTE_MASTER_RANK
:
4002 WL_DBG(("Unhandled attribute, %d\n", attr_type
));
4004 case NAN_ATTRIBUTE_CHANNEL
: {
4005 if (nla_len(iter
) != sizeof(uint32
)) {
4009 /* take the default channel start_factor frequency */
4010 chan
= wf_mhz2channel((uint
)nla_get_u32(iter
), 0);
4011 if (chan
<= CH_MAX_2G_CHANNEL
) {
4012 cmd_data
->chanspec
[0] = wf_channel2chspec(chan
, WL_CHANSPEC_BW_20
);
4014 cmd_data
->chanspec
[0] = wf_channel2chspec(chan
, WL_CHANSPEC_BW_80
);
4016 if (cmd_data
->chanspec
[0] == 0) {
4017 WL_ERR(("Channel is not valid \n"));
4021 WL_TRACE(("valid chanspec, chanspec = 0x%04x \n",
4022 cmd_data
->chanspec
[0]));
4025 case NAN_ATTRIBUTE_24G_CHANNEL
: {
4026 if (nla_len(iter
) != sizeof(uint32
)) {
4030 /* take the default channel start_factor frequency */
4031 chan
= wf_mhz2channel((uint
)nla_get_u32(iter
), 0);
4033 cmd_data
->chanspec
[1] = wf_channel2chspec(chan
, WL_CHANSPEC_BW_20
);
4034 if (cmd_data
->chanspec
[1] == 0) {
4035 WL_ERR((" 2.4GHz Channel is not valid \n"));
4039 *nan_attr_mask
|= NAN_ATTR_2G_CHAN_CONFIG
;
4040 WL_TRACE(("valid 2.4GHz chanspec, chanspec = 0x%04x \n",
4041 cmd_data
->chanspec
[1]));
4044 case NAN_ATTRIBUTE_5G_CHANNEL
: {
4045 if (nla_len(iter
) != sizeof(uint32
)) {
4049 /* take the default channel start_factor frequency */
4050 chan
= wf_mhz2channel((uint
)nla_get_u32(iter
), 0);
4052 cmd_data
->chanspec
[2] = wf_channel2chspec(chan
, WL_CHANSPEC_BW_20
);
4053 if (cmd_data
->chanspec
[2] == 0) {
4054 WL_ERR((" 5GHz Channel is not valid \n"));
4058 *nan_attr_mask
|= NAN_ATTR_5G_CHAN_CONFIG
;
4059 WL_TRACE(("valid 5GHz chanspec, chanspec = 0x%04x \n",
4060 cmd_data
->chanspec
[2]));
4063 case NAN_ATTRIBUTE_CONF_CLUSTER_VAL
:
4064 if (nla_len(iter
) != sizeof(uint8
)) {
4068 cmd_data
->config_cluster_val
= nla_get_u8(iter
);
4069 *nan_attr_mask
|= NAN_ATTR_CLUSTER_VAL_CONFIG
;
4071 case NAN_ATTRIBUTE_DWELL_TIME
:
4072 if (nla_len(iter
) != sizeof(uint8
)) {
4076 cmd_data
->dwell_time
[0] = nla_get_u8(iter
);
4077 *nan_attr_mask
|= NAN_ATTR_2G_DWELL_TIME_CONFIG
;
4079 case NAN_ATTRIBUTE_SCAN_PERIOD
:
4080 if (nla_len(iter
) != sizeof(uint16
)) {
4084 cmd_data
->scan_period
[0] = nla_get_u16(iter
);
4085 *nan_attr_mask
|= NAN_ATTR_2G_SCAN_PERIOD_CONFIG
;
4087 case NAN_ATTRIBUTE_DWELL_TIME_5G
:
4088 if (nla_len(iter
) != sizeof(uint8
)) {
4092 cmd_data
->dwell_time
[1] = nla_get_u8(iter
);
4093 *nan_attr_mask
|= NAN_ATTR_5G_DWELL_TIME_CONFIG
;
4095 case NAN_ATTRIBUTE_SCAN_PERIOD_5G
:
4096 if (nla_len(iter
) != sizeof(uint16
)) {
4100 cmd_data
->scan_period
[1] = nla_get_u16(iter
);
4101 *nan_attr_mask
|= NAN_ATTR_5G_SCAN_PERIOD_CONFIG
;
4103 case NAN_ATTRIBUTE_AVAIL_BIT_MAP
:
4104 if (nla_len(iter
) != sizeof(uint32
)) {
4108 cmd_data
->bmap
= nla_get_u32(iter
);
4110 case NAN_ATTRIBUTE_ENTRY_CONTROL
:
4111 if (nla_len(iter
) != sizeof(uint8
)) {
4115 cmd_data
->avail_params
.duration
= nla_get_u8(iter
);
4117 case NAN_ATTRIBUTE_RSSI_CLOSE
:
4118 if (nla_len(iter
) != sizeof(uint8
)) {
4122 cmd_data
->rssi_attr
.rssi_close_2dot4g_val
= nla_get_s8(iter
);
4123 *nan_attr_mask
|= NAN_ATTR_RSSI_CLOSE_CONFIG
;
4125 case NAN_ATTRIBUTE_RSSI_MIDDLE
:
4126 if (nla_len(iter
) != sizeof(uint8
)) {
4130 cmd_data
->rssi_attr
.rssi_middle_2dot4g_val
= nla_get_s8(iter
);
4131 *nan_attr_mask
|= NAN_ATTR_RSSI_MIDDLE_2G_CONFIG
;
4133 case NAN_ATTRIBUTE_RSSI_PROXIMITY
:
4134 if (nla_len(iter
) != sizeof(uint8
)) {
4138 cmd_data
->rssi_attr
.rssi_proximity_2dot4g_val
= nla_get_s8(iter
);
4139 *nan_attr_mask
|= NAN_ATTR_RSSI_PROXIMITY_2G_CONFIG
;
4141 case NAN_ATTRIBUTE_RSSI_CLOSE_5G
:
4142 if (nla_len(iter
) != sizeof(uint8
)) {
4146 cmd_data
->rssi_attr
.rssi_close_5g_val
= nla_get_s8(iter
);
4147 *nan_attr_mask
|= NAN_ATTR_RSSI_CLOSE_5G_CONFIG
;
4149 case NAN_ATTRIBUTE_RSSI_MIDDLE_5G
:
4150 if (nla_len(iter
) != sizeof(uint8
)) {
4154 cmd_data
->rssi_attr
.rssi_middle_5g_val
= nla_get_s8(iter
);
4155 *nan_attr_mask
|= NAN_ATTR_RSSI_MIDDLE_5G_CONFIG
;
4157 case NAN_ATTRIBUTE_RSSI_PROXIMITY_5G
:
4158 if (nla_len(iter
) != sizeof(uint8
)) {
4162 cmd_data
->rssi_attr
.rssi_proximity_5g_val
= nla_get_s8(iter
);
4163 *nan_attr_mask
|= NAN_ATTR_RSSI_PROXIMITY_5G_CONFIG
;
4165 case NAN_ATTRIBUTE_RSSI_WINDOW_SIZE
:
4166 if (nla_len(iter
) != sizeof(uint8
)) {
4170 cmd_data
->rssi_attr
.rssi_window_size
= nla_get_u8(iter
);
4171 *nan_attr_mask
|= NAN_ATTR_RSSI_WINDOW_SIZE_CONFIG
;
4173 case NAN_ATTRIBUTE_CIPHER_SUITE_TYPE
:
4174 if (nla_len(iter
) != sizeof(uint8
)) {
4178 cmd_data
->csid
= nla_get_u8(iter
);
4179 WL_TRACE(("CSID = %u\n", cmd_data
->csid
));
4181 case NAN_ATTRIBUTE_SCID_LEN
:
4182 if (nla_len(iter
) != sizeof(uint32
)) {
4186 if (cmd_data
->scid
.dlen
) {
4187 WL_ERR(("trying to overwrite:%d\n", attr_type
));
4191 cmd_data
->scid
.dlen
= nla_get_u32(iter
);
4192 if (cmd_data
->scid
.dlen
> MAX_SCID_LEN
) {
4194 WL_ERR(("Not allowed beyond %d\n", MAX_SCID_LEN
));
4197 WL_TRACE(("valid scid length = %u\n", cmd_data
->scid
.dlen
));
4199 case NAN_ATTRIBUTE_SCID
:
4200 if (!cmd_data
->scid
.dlen
|| (nla_len(iter
) != cmd_data
->scid
.dlen
)) {
4201 WL_ERR(("wrong scid len:%d,%d\n", cmd_data
->scid
.dlen
,
4206 if (cmd_data
->scid
.data
) {
4207 WL_ERR(("trying to overwrite:%d\n", attr_type
));
4211 cmd_data
->scid
.data
= MALLOCZ(cfg
->osh
, cmd_data
->scid
.dlen
);
4212 if (cmd_data
->scid
.data
== NULL
) {
4213 WL_ERR(("failed to allocate scid, len=%d\n",
4214 cmd_data
->scid
.dlen
));
4218 memcpy(cmd_data
->scid
.data
, nla_data(iter
), cmd_data
->scid
.dlen
);
4220 case NAN_ATTRIBUTE_2G_AWAKE_DW
:
4221 if (nla_len(iter
) != sizeof(uint32
)) {
4225 if (nla_get_u32(iter
) > NAN_MAX_AWAKE_DW_INTERVAL
) {
4226 WL_ERR(("%s: Invalid/Out of bound value = %u\n",
4227 __FUNCTION__
, nla_get_u32(iter
)));
4231 if (nla_get_u32(iter
)) {
4232 cmd_data
->awake_dws
.dw_interval_2g
=
4233 1 << (nla_get_u32(iter
)-1);
4235 *nan_attr_mask
|= NAN_ATTR_2G_DW_CONFIG
;
4237 case NAN_ATTRIBUTE_5G_AWAKE_DW
:
4238 if (nla_len(iter
) != sizeof(uint32
)) {
4242 if (nla_get_u32(iter
) > NAN_MAX_AWAKE_DW_INTERVAL
) {
4243 WL_ERR(("%s: Invalid/Out of bound value = %u\n",
4244 __FUNCTION__
, nla_get_u32(iter
)));
4248 if (nla_get_u32(iter
)) {
4249 cmd_data
->awake_dws
.dw_interval_5g
=
4250 1 << (nla_get_u32(iter
)-1);
4252 *nan_attr_mask
|= NAN_ATTR_5G_DW_CONFIG
;
4254 case NAN_ATTRIBUTE_DISC_IND_CFG
:
4255 if (nla_len(iter
) != sizeof(uint8
)) {
4259 cmd_data
->disc_ind_cfg
= nla_get_u8(iter
);
4261 case NAN_ATTRIBUTE_MAC_ADDR
:
4262 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
4266 memcpy((char*)&cmd_data
->mac_addr
, (char*)nla_data(iter
),
4269 case NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL
:
4270 if (nla_len(iter
) != sizeof(uint32
)) {
4274 cmd_data
->nmi_rand_intvl
= nla_get_u8(iter
);
4275 if (cmd_data
->nmi_rand_intvl
> 0) {
4276 cfg
->nancfg
.mac_rand
= true;
4278 cfg
->nancfg
.mac_rand
= false;
4282 WL_ERR(("%s: Unknown type, %d\n", __FUNCTION__
, attr_type
));
4289 /* We need to call set_config_handler b/f calling start enable TBD */
4292 WL_ERR(("%s: Failed to parse attribute %d ret %d",
4293 __FUNCTION__
, attr_type
, ret
));
4300 wl_cfgvendor_nan_dp_estb_event_data_filler(struct sk_buff
*msg
,
4301 nan_event_data_t
*event_data
) {
4303 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_NDP_ID
, event_data
->ndp_id
);
4304 if (unlikely(ret
)) {
4305 WL_ERR(("Failed to put NDP ID, ret=%d\n", ret
));
4309 * NDI mac address of the peer
4310 * (required to derive target ipv6 address)
4312 ret
= nla_put(msg
, NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR
, ETH_ALEN
,
4313 event_data
->responder_ndi
.octet
);
4314 if (unlikely(ret
)) {
4315 WL_ERR(("Failed to put resp ndi, ret=%d\n", ret
));
4318 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_RSP_CODE
, event_data
->status
);
4319 if (unlikely(ret
)) {
4320 WL_ERR(("Failed to put response code, ret=%d\n", ret
));
4323 if (event_data
->svc_info
.dlen
&& event_data
->svc_info
.data
) {
4324 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
,
4325 event_data
->svc_info
.dlen
);
4326 if (unlikely(ret
)) {
4327 WL_ERR(("Failed to put svc info len, ret=%d\n", ret
));
4330 ret
= nla_put(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
,
4331 event_data
->svc_info
.dlen
, event_data
->svc_info
.data
);
4332 if (unlikely(ret
)) {
4333 WL_ERR(("Failed to put svc info, ret=%d\n", ret
));
4342 wl_cfgvendor_nan_dp_ind_event_data_filler(struct sk_buff
*msg
,
4343 nan_event_data_t
*event_data
) {
4346 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_PUBLISH_ID
,
4347 event_data
->pub_id
);
4348 if (unlikely(ret
)) {
4349 WL_ERR(("Failed to put pub ID, ret=%d\n", ret
));
4352 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_NDP_ID
, event_data
->ndp_id
);
4353 if (unlikely(ret
)) {
4354 WL_ERR(("Failed to put NDP ID, ret=%d\n", ret
));
4357 /* Discovery MAC addr of the peer/initiator */
4358 ret
= nla_put(msg
, NAN_ATTRIBUTE_MAC_ADDR
, ETH_ALEN
,
4359 event_data
->remote_nmi
.octet
);
4360 if (unlikely(ret
)) {
4361 WL_ERR(("Failed to put remote NMI, ret=%d\n", ret
));
4364 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_SECURITY
, event_data
->security
);
4365 if (unlikely(ret
)) {
4366 WL_ERR(("Failed to put security, ret=%d\n", ret
));
4369 if (event_data
->svc_info
.dlen
&& event_data
->svc_info
.data
) {
4370 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
,
4371 event_data
->svc_info
.dlen
);
4372 if (unlikely(ret
)) {
4373 WL_ERR(("Failed to put svc info len, ret=%d\n", ret
));
4376 ret
= nla_put(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
,
4377 event_data
->svc_info
.dlen
, event_data
->svc_info
.data
);
4378 if (unlikely(ret
)) {
4379 WL_ERR(("Failed to put svc info, ret=%d\n", ret
));
4389 wl_cfgvendor_nan_tx_followup_ind_event_data_filler(struct sk_buff
*msg
,
4390 nan_event_data_t
*event_data
) {
4392 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_TRANSAC_ID
, event_data
->token
);
4393 if (unlikely(ret
)) {
4394 WL_ERR(("Failed to put transaction id, ret=%d\n", ret
));
4397 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_HANDLE
, event_data
->local_inst_id
);
4398 if (unlikely(ret
)) {
4399 WL_ERR(("Failed to put handle, ret=%d\n", ret
));
4402 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_STATUS
, event_data
->status
);
4403 if (unlikely(ret
)) {
4404 WL_ERR(("Failed to put nan status, ret=%d\n", ret
));
4407 if (event_data
->status
== NAN_STATUS_SUCCESS
) {
4408 ret
= nla_put(msg
, NAN_ATTRIBUTE_REASON
,
4409 strlen("NAN_STATUS_SUCCESS"), event_data
->nan_reason
);
4410 if (unlikely(ret
)) {
4411 WL_ERR(("Failed to put nan reason, ret=%d\n", ret
));
4415 ret
= nla_put(msg
, NAN_ATTRIBUTE_REASON
,
4416 strlen("NAN_STATUS_NO_OTA_ACK"), event_data
->nan_reason
);
4417 if (unlikely(ret
)) {
4418 WL_ERR(("Failed to put nan reason, ret=%d\n", ret
));
4427 wl_cfgvendor_nan_svc_terminate_event_filler(struct sk_buff
*msg
,
4428 struct bcm_cfg80211
*cfg
, int event_id
, nan_event_data_t
*event_data
) {
4430 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_HANDLE
, event_data
->local_inst_id
);
4431 if (unlikely(ret
)) {
4432 WL_ERR(("Failed to put handle, ret=%d\n", ret
));
4436 if (event_id
== GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED
) {
4437 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SUBSCRIBE_ID
,
4438 event_data
->local_inst_id
);
4439 if (unlikely(ret
)) {
4440 WL_ERR(("Failed to put local inst id, ret=%d\n", ret
));
4444 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_PUBLISH_ID
,
4445 event_data
->local_inst_id
);
4446 if (unlikely(ret
)) {
4447 WL_ERR(("Failed to put local inst id, ret=%d\n", ret
));
4451 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_STATUS
, event_data
->status
);
4452 if (unlikely(ret
)) {
4453 WL_ERR(("Failed to put status, ret=%d\n", ret
));
4456 if (event_data
->status
== NAN_STATUS_SUCCESS
) {
4457 ret
= nla_put(msg
, NAN_ATTRIBUTE_REASON
,
4458 strlen("NAN_STATUS_SUCCESS"), event_data
->nan_reason
);
4459 if (unlikely(ret
)) {
4460 WL_ERR(("Failed to put nan reason, ret=%d\n", ret
));
4464 ret
= nla_put(msg
, NAN_ATTRIBUTE_REASON
,
4465 strlen("NAN_STATUS_INTERNAL_FAILURE"), event_data
->nan_reason
);
4466 if (unlikely(ret
)) {
4467 WL_ERR(("Failed to put nan reason, ret=%d\n", ret
));
4472 ret
= wl_cfgnan_remove_inst_id(cfg
, event_data
->local_inst_id
);
4474 WL_ERR(("failed to free svc instance-id[%d], ret=%d, event_id = %d\n",
4475 event_data
->local_inst_id
, ret
, event_id
));
4483 wl_cfgvendor_nan_opt_params_filler(struct sk_buff
*msg
,
4484 nan_event_data_t
*event_data
) {
4486 /* service specific info data */
4487 if (event_data
->svc_info
.dlen
&& event_data
->svc_info
.data
) {
4488 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
,
4489 event_data
->svc_info
.dlen
);
4490 if (unlikely(ret
)) {
4491 WL_ERR(("Failed to put svc info len, ret=%d\n", ret
));
4494 ret
= nla_put(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
,
4495 event_data
->svc_info
.dlen
, event_data
->svc_info
.data
);
4496 if (unlikely(ret
)) {
4497 WL_ERR(("Failed to put svc info, ret=%d\n", ret
));
4500 WL_TRACE(("svc info len = %d\n", event_data
->svc_info
.dlen
));
4503 /* sdea service specific info data */
4504 if (event_data
->sde_svc_info
.dlen
&& event_data
->sde_svc_info
.data
) {
4505 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN
,
4506 event_data
->sde_svc_info
.dlen
);
4507 if (unlikely(ret
)) {
4508 WL_ERR(("Failed to put sdea svc info len, ret=%d\n", ret
));
4511 ret
= nla_put(msg
, NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO
,
4512 event_data
->sde_svc_info
.dlen
,
4513 event_data
->sde_svc_info
.data
);
4514 if (unlikely(ret
)) {
4515 WL_ERR(("Failed to put sdea svc info, ret=%d\n", ret
));
4518 WL_TRACE(("sdea svc info len = %d\n", event_data
->sde_svc_info
.dlen
));
4520 /* service control discovery range limit */
4523 /* service control binding bitmap */
4530 wl_cfgvendor_nan_tx_followup_event_filler(struct sk_buff
*msg
,
4531 nan_event_data_t
*event_data
) {
4533 /* In followup pkt, instance id and requestor instance id are configured
4534 * from the transmitter perspective. As the event is processed with the
4535 * role of receiver, the local handle should use requestor instance
4538 WL_TRACE(("handle=%d\n", event_data
->requestor_id
));
4539 WL_TRACE(("inst id (local id)=%d\n", event_data
->local_inst_id
));
4540 WL_TRACE(("peer id (remote id)=%d\n", event_data
->requestor_id
));
4541 WL_TRACE(("peer mac addr=" MACDBG
"\n",
4542 MAC2STRDBG(event_data
->remote_nmi
.octet
)));
4543 WL_TRACE(("peer rssi: %d\n", event_data
->fup_rssi
));
4544 WL_TRACE(("attribute no: %d\n", event_data
->attr_num
));
4545 WL_TRACE(("attribute len: %d\n", event_data
->attr_list_len
));
4547 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_HANDLE
, event_data
->requestor_id
);
4548 if (unlikely(ret
)) {
4549 WL_ERR(("Failed to put handle, ret=%d\n", ret
));
4552 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_INST_ID
, event_data
->local_inst_id
);
4553 if (unlikely(ret
)) {
4554 WL_ERR(("Failed to put local inst id, ret=%d\n", ret
));
4557 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_PEER_ID
, event_data
->requestor_id
);
4558 if (unlikely(ret
)) {
4559 WL_ERR(("Failed to put requestor inst id, ret=%d\n", ret
));
4562 ret
= nla_put(msg
, NAN_ATTRIBUTE_MAC_ADDR
, ETHER_ADDR_LEN
,
4563 event_data
->remote_nmi
.octet
);
4564 if (unlikely(ret
)) {
4565 WL_ERR(("Failed to put remote nmi, ret=%d\n", ret
));
4568 ret
= nla_put_s8(msg
, NAN_ATTRIBUTE_RSSI_PROXIMITY
,
4569 event_data
->fup_rssi
);
4570 if (unlikely(ret
)) {
4571 WL_ERR(("Failed to put fup rssi, ret=%d\n", ret
));
4579 wl_cfgvendor_nan_sub_match_event_filler(struct sk_buff
*msg
,
4580 nan_event_data_t
*event_data
) {
4582 WL_TRACE(("handle (sub_id)=%d\n", event_data
->sub_id
));
4583 WL_TRACE(("pub id=%d\n", event_data
->pub_id
));
4584 WL_TRACE(("sub id=%d\n", event_data
->sub_id
));
4585 WL_TRACE(("pub mac addr=" MACDBG
"\n",
4586 MAC2STRDBG(event_data
->remote_nmi
.octet
)));
4587 WL_TRACE(("attr no: %d\n", event_data
->attr_num
));
4588 WL_TRACE(("attr len: %d\n", event_data
->attr_list_len
));
4590 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_HANDLE
, event_data
->sub_id
);
4591 if (unlikely(ret
)) {
4592 WL_ERR(("Failed to put handle, ret=%d\n", ret
));
4595 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_PUBLISH_ID
, event_data
->pub_id
);
4596 if (unlikely(ret
)) {
4597 WL_ERR(("Failed to put pub id, ret=%d\n", ret
));
4600 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SUBSCRIBE_ID
, event_data
->sub_id
);
4601 if (unlikely(ret
)) {
4602 WL_ERR(("Failed to put Sub Id, ret=%d\n", ret
));
4605 ret
= nla_put(msg
, NAN_ATTRIBUTE_MAC_ADDR
, ETHER_ADDR_LEN
,
4606 event_data
->remote_nmi
.octet
);
4607 if (unlikely(ret
)) {
4608 WL_ERR(("Failed to put remote NMI, ret=%d\n", ret
));
4611 if (event_data
->publish_rssi
) {
4612 event_data
->publish_rssi
= -event_data
->publish_rssi
;
4613 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_RSSI_PROXIMITY
,
4614 event_data
->publish_rssi
);
4615 if (unlikely(ret
)) {
4616 WL_ERR(("Failed to put publish rssi, ret=%d\n", ret
));
4620 if (event_data
->ranging_result_present
) {
4621 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_RANGING_INDICATION
,
4622 event_data
->ranging_ind
);
4623 if (unlikely(ret
)) {
4624 WL_ERR(("Failed to put ranging ind, ret=%d\n", ret
));
4627 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_RANGING_RESULT
,
4628 event_data
->range_measurement_cm
);
4629 if (unlikely(ret
)) {
4630 WL_ERR(("Failed to put range measurement cm, ret=%d\n",
4636 * handling optional service control, service response filter
4638 if (event_data
->tx_match_filter
.dlen
&& event_data
->tx_match_filter
.data
) {
4639 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN
,
4640 event_data
->tx_match_filter
.dlen
);
4641 if (unlikely(ret
)) {
4642 WL_ERR(("Failed to put tx match filter len, ret=%d\n",
4646 ret
= nla_put(msg
, NAN_ATTRIBUTE_TX_MATCH_FILTER
,
4647 event_data
->tx_match_filter
.dlen
,
4648 event_data
->tx_match_filter
.data
);
4649 if (unlikely(ret
)) {
4650 WL_ERR(("Failed to put tx match filter data, ret=%d\n",
4654 WL_TRACE(("tx matching filter (%d):\n",
4655 event_data
->tx_match_filter
.dlen
));
4663 wl_cfgvendor_nan_de_event_filler(struct sk_buff
*msg
, nan_event_data_t
*event_data
)
4666 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_ENABLE_STATUS
, event_data
->enabled
);
4667 if (unlikely(ret
)) {
4668 WL_ERR(("Failed to put event_data->enabled, ret=%d\n", ret
));
4671 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_DE_EVENT_TYPE
,
4672 event_data
->nan_de_evt_type
);
4673 if (unlikely(ret
)) {
4674 WL_ERR(("Failed to put nan_de_evt_type, ret=%d\n", ret
));
4677 ret
= nla_put(msg
, NAN_ATTRIBUTE_CLUSTER_ID
, ETH_ALEN
,
4678 event_data
->clus_id
.octet
);
4679 if (unlikely(ret
)) {
4680 WL_ERR(("Failed to put clust id, ret=%d\n", ret
));
4683 /* OOB tests requires local nmi */
4684 ret
= nla_put(msg
, NAN_ATTRIBUTE_MAC_ADDR
, ETH_ALEN
,
4685 event_data
->local_nmi
.octet
);
4686 if (unlikely(ret
)) {
4687 WL_ERR(("Failed to put NMI, ret=%d\n", ret
));
4695 wl_cfgvendor_send_nan_event(struct wiphy
*wiphy
, struct net_device
*dev
,
4696 int event_id
, nan_event_data_t
*event_data
)
4699 int buf_len
= NAN_EVENT_BUFFER_SIZE_LARGE
;
4700 gfp_t kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
4702 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4703 struct sk_buff
*msg
;
4707 /* Allocate the skb for vendor event */
4708 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
4709 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
4710 msg
= cfg80211_vendor_event_alloc(wiphy
, ndev_to_wdev(dev
), buf_len
, event_id
, kflags
);
4712 msg
= cfg80211_vendor_event_alloc(wiphy
, buf_len
, event_id
, kflags
);
4713 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
4714 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
4717 WL_ERR(("%s: fail to allocate skb for vendor event\n", __FUNCTION__
));
4722 case GOOGLE_NAN_EVENT_DE_EVENT
: {
4723 WL_INFORM_MEM(("[NAN] GOOGLE_NAN_DE_EVENT cluster id=" MACDBG
"nmi= " MACDBG
"\n",
4724 MAC2STRDBG(event_data
->clus_id
.octet
),
4725 MAC2STRDBG(event_data
->local_nmi
.octet
)));
4726 ret
= wl_cfgvendor_nan_de_event_filler(msg
, event_data
);
4727 if (unlikely(ret
)) {
4728 WL_ERR(("Failed to fill de event data, ret=%d\n", ret
));
4733 case GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH
:
4734 case GOOGLE_NAN_EVENT_FOLLOWUP
: {
4735 if (event_id
== GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH
) {
4736 WL_DBG(("GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH\n"));
4737 ret
= wl_cfgvendor_nan_sub_match_event_filler(msg
, event_data
);
4738 if (unlikely(ret
)) {
4739 WL_ERR(("Failed to fill sub match event data, ret=%d\n", ret
));
4742 } else if (event_id
== GOOGLE_NAN_EVENT_FOLLOWUP
) {
4743 WL_DBG(("GOOGLE_NAN_EVENT_FOLLOWUP\n"));
4744 ret
= wl_cfgvendor_nan_tx_followup_event_filler(msg
, event_data
);
4745 if (unlikely(ret
)) {
4746 WL_ERR(("Failed to fill sub match event data, ret=%d\n", ret
));
4750 ret
= wl_cfgvendor_nan_opt_params_filler(msg
, event_data
);
4751 if (unlikely(ret
)) {
4752 WL_ERR(("Failed to fill sub match event data, ret=%d\n", ret
));
4758 case GOOGLE_NAN_EVENT_DISABLED
: {
4759 WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DISABLED\n"));
4760 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_HANDLE
, 0);
4761 if (unlikely(ret
)) {
4762 WL_ERR(("Failed to put handle, ret=%d\n", ret
));
4765 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_STATUS
, event_data
->status
);
4766 if (unlikely(ret
)) {
4767 WL_ERR(("Failed to put status, ret=%d\n", ret
));
4770 ret
= nla_put(msg
, NAN_ATTRIBUTE_REASON
,
4771 strlen("NAN_STATUS_SUCCESS"), event_data
->nan_reason
);
4772 if (unlikely(ret
)) {
4773 WL_ERR(("Failed to put reason code, ret=%d\n", ret
));
4779 case GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED
:
4780 case GOOGLE_NAN_EVENT_PUBLISH_TERMINATED
: {
4781 WL_DBG(("GOOGLE_NAN_SVC_TERMINATED, %d\n", event_id
));
4782 ret
= wl_cfgvendor_nan_svc_terminate_event_filler(msg
, cfg
, event_id
, event_data
);
4783 if (unlikely(ret
)) {
4784 WL_ERR(("Failed to fill svc terminate event data, ret=%d\n", ret
));
4790 case GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND
: {
4791 WL_DBG(("GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND %d\n",
4792 GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND
));
4793 ret
= wl_cfgvendor_nan_tx_followup_ind_event_data_filler(msg
, event_data
);
4794 if (unlikely(ret
)) {
4795 WL_ERR(("Failed to fill tx follow up ind event data, ret=%d\n", ret
));
4802 case GOOGLE_NAN_EVENT_DATA_REQUEST
: {
4803 WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DATA_REQUEST\n"));
4804 ret
= wl_cfgvendor_nan_dp_ind_event_data_filler(msg
, event_data
);
4805 if (unlikely(ret
)) {
4806 WL_ERR(("Failed to fill dp ind event data, ret=%d\n", ret
));
4812 case GOOGLE_NAN_EVENT_DATA_CONFIRMATION
: {
4813 WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DATA_CONFIRMATION\n"));
4815 ret
= wl_cfgvendor_nan_dp_estb_event_data_filler(msg
, event_data
);
4816 if (unlikely(ret
)) {
4817 WL_ERR(("Failed to fill dp estb event data, ret=%d\n", ret
));
4823 case GOOGLE_NAN_EVENT_DATA_END
: {
4824 WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DATA_END\n"));
4825 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_INST_COUNT
, 1);
4826 if (unlikely(ret
)) {
4827 WL_ERR(("Failed to put inst count, ret=%d\n", ret
));
4830 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_NDP_ID
, event_data
->ndp_id
);
4831 if (unlikely(ret
)) {
4832 WL_ERR(("Failed to put ndp id, ret=%d\n", ret
));
4842 cfg80211_vendor_event(msg
, kflags
);
4847 dev_kfree_skb_any(msg
);
4848 WL_ERR(("Event not implemented or unknown -- Free skb, event_id = %d, ret = %d\n",
4855 wl_cfgvendor_nan_req_subscribe(struct wiphy
*wiphy
,
4856 struct wireless_dev
*wdev
, const void * data
, int len
)
4859 nan_discover_cmd_data_t
*cmd_data
= NULL
;
4860 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4861 nan_hal_resp_t nan_req_resp
;
4864 /* Blocking Subscribe if NAN is not enable */
4865 if (!cfg
->nan_enable
) {
4866 WL_ERR(("nan is not enabled, subscribe blocked\n"));
4870 cmd_data
= (nan_discover_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
4872 WL_ERR(("%s: memory allocation failed\n", __func__
));
4877 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
4878 ret
= wl_cfgvendor_nan_parse_discover_args(wiphy
, data
, len
, cmd_data
);
4880 WL_ERR(("failed to parse nan disc vendor args, ret = %d\n", ret
));
4884 if (cmd_data
->sub_id
== 0) {
4885 ret
= wl_cfgnan_generate_inst_id(cfg
, &cmd_data
->sub_id
);
4887 WL_ERR(("failed to generate instance-id for subscribe\n"));
4891 cmd_data
->svc_update
= true;
4894 ret
= wl_cfgnan_subscribe_handler(wdev
->netdev
, cfg
, cmd_data
);
4895 if (unlikely(ret
) || unlikely(cmd_data
->status
)) {
4896 WL_ERR(("failed to subscribe error[%d], status = [%d]\n",
4897 ret
, cmd_data
->status
));
4898 wl_cfgnan_remove_inst_id(cfg
, cmd_data
->sub_id
);
4902 WL_DBG(("subscriber instance id=%d\n", cmd_data
->sub_id
));
4904 if (cmd_data
->status
== WL_NAN_E_OK
) {
4905 nan_req_resp
.instance_id
= cmd_data
->sub_id
;
4907 nan_req_resp
.instance_id
= 0;
4910 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_REQUEST_SUBSCRIBE
,
4911 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
4912 wl_cfgvendor_free_disc_cmd_data(cfg
, cmd_data
);
4918 wl_cfgvendor_nan_req_publish(struct wiphy
*wiphy
,
4919 struct wireless_dev
*wdev
, const void * data
, int len
)
4922 nan_discover_cmd_data_t
*cmd_data
= NULL
;
4923 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4924 nan_hal_resp_t nan_req_resp
;
4927 /* Blocking Publish if NAN is not enable */
4928 if (!cfg
->nan_enable
) {
4929 WL_ERR(("nan is not enabled publish blocked\n"));
4933 cmd_data
= (nan_discover_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
4935 WL_ERR(("%s: memory allocation failed\n", __func__
));
4940 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
4941 ret
= wl_cfgvendor_nan_parse_discover_args(wiphy
, data
, len
, cmd_data
);
4943 WL_ERR(("failed to parse nan disc vendor args, ret = %d\n", ret
));
4947 if (cmd_data
->pub_id
== 0) {
4948 ret
= wl_cfgnan_generate_inst_id(cfg
, &cmd_data
->pub_id
);
4950 WL_ERR(("failed to generate instance-id for publisher\n"));
4954 cmd_data
->svc_update
= true;
4957 ret
= wl_cfgnan_publish_handler(wdev
->netdev
, cfg
, cmd_data
);
4958 if (unlikely(ret
) || unlikely(cmd_data
->status
)) {
4959 WL_ERR(("failed to publish error[%d], status[%d]\n",
4960 ret
, cmd_data
->status
));
4961 wl_cfgnan_remove_inst_id(cfg
, cmd_data
->pub_id
);
4965 WL_DBG(("publisher instance id=%d\n", cmd_data
->pub_id
));
4967 if (cmd_data
->status
== WL_NAN_E_OK
) {
4968 nan_req_resp
.instance_id
= cmd_data
->pub_id
;
4970 nan_req_resp
.instance_id
= 0;
4973 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_REQUEST_PUBLISH
,
4974 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
4975 wl_cfgvendor_free_disc_cmd_data(cfg
, cmd_data
);
4981 wl_cfgvendor_nan_start_handler(struct wiphy
*wiphy
,
4982 struct wireless_dev
*wdev
, const void *data
, int len
)
4985 nan_config_cmd_data_t
*cmd_data
;
4986 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4987 nan_hal_resp_t nan_req_resp
;
4988 uint32 nan_attr_mask
= 0;
4990 cmd_data
= (nan_config_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
4992 WL_ERR(("%s: memory allocation failed\n", __func__
));
4998 if (cfg
->nan_enable
) {
4999 WL_ERR(("nan is already enabled\n"));
5004 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5006 cmd_data
->sid_beacon
.sid_enable
= NAN_SID_ENABLE_FLAG_INVALID
; /* Setting to some default */
5007 cmd_data
->sid_beacon
.sid_count
= NAN_SID_BEACON_COUNT_INVALID
; /* Setting to some default */
5009 ret
= wl_cfgvendor_nan_parse_args(wiphy
, data
, len
, cmd_data
, &nan_attr_mask
);
5011 WL_ERR(("failed to parse nan vendor args, ret %d\n", ret
));
5015 ret
= wl_cfgnan_start_handler(wdev
->netdev
, cfg
, cmd_data
, nan_attr_mask
);
5017 WL_ERR(("failed to start nan error[%d]\n", ret
));
5020 /* Initializing Instance Id List */
5021 memset(cfg
->nan_inst_ctrl
, 0, NAN_ID_CTRL_SIZE
* sizeof(nan_svc_inst_t
));
5023 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_ENABLE
,
5024 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5026 if (cmd_data
->scid
.data
) {
5027 MFREE(cfg
->osh
, cmd_data
->scid
.data
, cmd_data
->scid
.dlen
);
5028 cmd_data
->scid
.dlen
= 0;
5030 MFREE(cfg
->osh
, cmd_data
, sizeof(*cmd_data
));
5037 wl_cfgvendor_nan_stop_handler(struct wiphy
*wiphy
,
5038 struct wireless_dev
*wdev
, const void * data
, int len
)
5041 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5042 nan_hal_resp_t nan_req_resp
;
5045 if (!cfg
->nan_init_state
) {
5046 WL_ERR(("nan is not initialized/nmi doesnt exists\n"));
5051 if (cfg
->nan_enable
) {
5052 ret
= wl_cfgnan_disable(cfg
, NAN_USER_INITIATED
);
5054 WL_ERR(("failed to disable nan, error[%d]\n", ret
));
5057 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5059 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DISABLE
,
5060 &nan_req_resp
, ret
, BCME_OK
);
5066 wl_cfgvendor_nan_config_handler(struct wiphy
*wiphy
,
5067 struct wireless_dev
*wdev
, const void *data
, int len
)
5070 nan_config_cmd_data_t
*cmd_data
;
5071 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5072 nan_hal_resp_t nan_req_resp
;
5073 uint32 nan_attr_mask
= 0;
5075 cmd_data
= MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5077 WL_ERR(("%s: memory allocation failed\n", __func__
));
5082 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5084 cmd_data
->avail_params
.duration
= NAN_BAND_INVALID
; /* Setting to some default */
5085 cmd_data
->sid_beacon
.sid_enable
= NAN_SID_ENABLE_FLAG_INVALID
; /* Setting to some default */
5086 cmd_data
->sid_beacon
.sid_count
= NAN_SID_BEACON_COUNT_INVALID
; /* Setting to some default */
5088 ret
= wl_cfgvendor_nan_parse_args(wiphy
, data
, len
, cmd_data
, &nan_attr_mask
);
5090 WL_ERR(("failed to parse nan vendor args, ret = %d\n", ret
));
5094 ret
= wl_cfgnan_config_handler(wdev
->netdev
, cfg
, cmd_data
, nan_attr_mask
);
5096 WL_ERR(("failed in config request, nan error[%d]\n", ret
));
5100 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_CONFIG
,
5101 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5103 if (cmd_data
->scid
.data
) {
5104 MFREE(cfg
->osh
, cmd_data
->scid
.data
, cmd_data
->scid
.dlen
);
5105 cmd_data
->scid
.dlen
= 0;
5107 MFREE(cfg
->osh
, cmd_data
, sizeof(*cmd_data
));
5114 wl_cfgvendor_nan_cancel_publish(struct wiphy
*wiphy
,
5115 struct wireless_dev
*wdev
, const void * data
, int len
)
5118 nan_discover_cmd_data_t
*cmd_data
= NULL
;
5119 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5120 nan_hal_resp_t nan_req_resp
;
5122 /* Blocking Cancel_Publish if NAN is not enable */
5123 if (!cfg
->nan_enable
) {
5124 WL_ERR(("nan is not enabled, cancel publish blocked\n"));
5128 cmd_data
= (nan_discover_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5130 WL_ERR(("%s: memory allocation failed\n", __func__
));
5136 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5138 ret
= wl_cfgvendor_nan_parse_discover_args(wiphy
, data
, len
, cmd_data
);
5140 WL_ERR(("failed to parse nan disc vendor args, ret= %d\n", ret
));
5143 nan_req_resp
.instance_id
= cmd_data
->pub_id
;
5144 WL_INFORM_MEM(("[NAN] cancel publish instance_id=%d\n", cmd_data
->pub_id
));
5146 ret
= wl_cfgnan_cancel_pub_handler(wdev
->netdev
, cfg
, cmd_data
);
5148 WL_ERR(("failed to cancel publish nan instance-id[%d] error[%d]\n",
5149 cmd_data
->pub_id
, ret
));
5153 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_CANCEL_PUBLISH
,
5154 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5155 wl_cfgvendor_free_disc_cmd_data(cfg
, cmd_data
);
5161 wl_cfgvendor_nan_cancel_subscribe(struct wiphy
*wiphy
,
5162 struct wireless_dev
*wdev
, const void * data
, int len
)
5165 nan_discover_cmd_data_t
*cmd_data
= NULL
;
5166 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5167 nan_hal_resp_t nan_req_resp
;
5169 /* Blocking Cancel_Subscribe if NAN is not enableb */
5170 if (!cfg
->nan_enable
) {
5171 WL_ERR(("nan is not enabled, cancel subscribe blocked\n"));
5175 cmd_data
= MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5177 WL_ERR(("%s: memory allocation failed\n", __func__
));
5183 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5185 ret
= wl_cfgvendor_nan_parse_discover_args(wiphy
, data
, len
, cmd_data
);
5187 WL_ERR(("failed to parse nan disc vendor args, ret= %d\n", ret
));
5190 nan_req_resp
.instance_id
= cmd_data
->sub_id
;
5191 WL_INFORM_MEM(("[NAN] cancel subscribe instance_id=%d\n", cmd_data
->sub_id
));
5193 ret
= wl_cfgnan_cancel_sub_handler(wdev
->netdev
, cfg
, cmd_data
);
5195 WL_ERR(("failed to cancel subscribe nan instance-id[%d] error[%d]\n",
5196 cmd_data
->sub_id
, ret
));
5200 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_CANCEL_SUBSCRIBE
,
5201 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5202 wl_cfgvendor_free_disc_cmd_data(cfg
, cmd_data
);
5208 wl_cfgvendor_nan_transmit(struct wiphy
*wiphy
,
5209 struct wireless_dev
*wdev
, const void * data
, int len
)
5212 nan_discover_cmd_data_t
*cmd_data
= NULL
;
5213 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5214 nan_hal_resp_t nan_req_resp
;
5216 /* Blocking Transmit if NAN is not enable */
5217 if (!cfg
->nan_enable
) {
5218 WL_ERR(("nan is not enabled, transmit blocked\n"));
5222 cmd_data
= (nan_discover_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5224 WL_ERR(("%s: memory allocation failed\n", __func__
));
5230 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5232 ret
= wl_cfgvendor_nan_parse_discover_args(wiphy
, data
, len
, cmd_data
);
5234 WL_ERR(("failed to parse nan disc vendor args, ret= %d\n", ret
));
5237 nan_req_resp
.instance_id
= cmd_data
->local_id
;
5238 ret
= wl_cfgnan_transmit_handler(wdev
->netdev
, cfg
, cmd_data
);
5240 WL_ERR(("failed to transmit-followup nan error[%d]\n", ret
));
5244 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_TRANSMIT
,
5245 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5246 wl_cfgvendor_free_disc_cmd_data(cfg
, cmd_data
);
5252 wl_cfgvendor_nan_get_capablities(struct wiphy
*wiphy
,
5253 struct wireless_dev
*wdev
, const void * data
, int len
)
5256 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5257 nan_hal_resp_t nan_req_resp
;
5261 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5263 ret
= wl_cfgnan_get_capablities_handler(wdev
->netdev
, cfg
, &nan_req_resp
.capabilities
);
5265 WL_ERR(("Could not get capabilities\n"));
5270 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_GET_CAPABILITIES
,
5271 &nan_req_resp
, ret
, BCME_OK
);
5272 wl_cfgvendor_send_cmd_reply(wiphy
, &nan_req_resp
, sizeof(nan_req_resp
));
5279 wl_cfgvendor_nan_data_path_iface_create(struct wiphy
*wiphy
,
5280 struct wireless_dev
*wdev
, const void * data
, int len
)
5284 nan_datapath_cmd_data_t
*cmd_data
= NULL
;
5285 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5286 nan_hal_resp_t nan_req_resp
;
5287 dhd_pub_t
*dhdp
= wl_cfg80211_get_dhdp(wdev
->netdev
);
5289 if (!cfg
->nan_init_state
) {
5290 WL_ERR(("%s: NAN is not inited or Device doesn't support NAN \n", __func__
));
5295 cmd_data
= (nan_datapath_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5297 WL_ERR(("%s: memory allocation failed\n", __func__
));
5303 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5305 ret
= wl_cfgvendor_nan_parse_datapath_args(wiphy
, data
, len
, cmd_data
);
5307 WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret
));
5311 /* Store the iface name to pub data so that it can be used
5314 if ((idx
= wl_cfgnan_get_ndi_idx(cfg
)) < 0) {
5315 WL_ERR(("No free idx for NAN NDI\n"));
5318 wl_cfgnan_add_ndi_data(cfg
, idx
, (char*)cmd_data
->ndp_iface
);
5319 if (cfg
->nan_enable
) { /* new framework Impl, iface create called after nan enab */
5320 wl_cfgnan_data_path_iface_create_delete_handler(wdev
->netdev
,
5321 cfg
, cmd_data
->ndp_iface
,
5322 NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE
, dhdp
->up
);
5323 cfg
->nancfg
.ndi
[idx
].created
= true;
5326 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE
,
5327 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5328 wl_cfgvendor_free_dp_cmd_data(cfg
, cmd_data
);
5334 wl_cfgvendor_nan_data_path_iface_delete(struct wiphy
*wiphy
,
5335 struct wireless_dev
*wdev
, const void * data
, int len
)
5338 nan_datapath_cmd_data_t
*cmd_data
= NULL
;
5339 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5340 nan_hal_resp_t nan_req_resp
;
5341 dhd_pub_t
*dhdp
= wl_cfg80211_get_dhdp(wdev
->netdev
);
5343 if (!cfg
->nan_init_state
) {
5344 WL_ERR(("%s: NAN is not inited or Device doesn't support NAN \n", __func__
));
5345 /* Deinit has taken care of cleaing the virtual iface */
5351 cmd_data
= (nan_datapath_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5353 WL_ERR(("%s: memory allocation failed\n", __func__
));
5357 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5358 ret
= wl_cfgvendor_nan_parse_datapath_args(wiphy
, data
, len
, cmd_data
);
5360 WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret
));
5364 ret
= wl_cfgnan_data_path_iface_create_delete_handler(wdev
->netdev
, cfg
,
5365 (char*)cmd_data
->ndp_iface
,
5366 NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE
, dhdp
->up
);
5368 if (ret
== -ENODEV
) {
5369 if (wl_cfgnan_get_ndi_data(cfg
, (char*)cmd_data
->ndp_iface
) != NULL
) {
5370 /* NDIs have been removed by the NAN disable command */
5371 WL_DBG(("NDI removed by nan_disable\n"));
5375 WL_ERR(("failed to delete ndp iface [%d]\n", ret
));
5380 if (cfg
->nan_init_state
) {
5381 /* After successful delete of interface, clear up the ndi data */
5382 if (wl_cfgnan_del_ndi_data(cfg
, (char*)cmd_data
->ndp_iface
) < 0) {
5383 WL_ERR(("Failed to find matching data for ndi:%s\n",
5384 (char*)cmd_data
->ndp_iface
));
5388 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE
,
5389 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5390 wl_cfgvendor_free_dp_cmd_data(cfg
, cmd_data
);
5396 wl_cfgvendor_nan_data_path_request(struct wiphy
*wiphy
,
5397 struct wireless_dev
*wdev
, const void * data
, int len
)
5400 nan_datapath_cmd_data_t
*cmd_data
= NULL
;
5401 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5402 nan_hal_resp_t nan_req_resp
;
5403 uint8 ndp_instance_id
= 0;
5405 if (!cfg
->nan_enable
) {
5406 WL_ERR(("nan is not enabled, nan data path request blocked\n"));
5412 cmd_data
= (nan_datapath_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5414 WL_ERR(("%s: memory allocation failed\n", __func__
));
5419 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5420 ret
= wl_cfgvendor_nan_parse_datapath_args(wiphy
, data
, len
, cmd_data
);
5422 WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret
));
5426 ret
= wl_cfgnan_data_path_request_handler(wdev
->netdev
, cfg
,
5427 cmd_data
, &ndp_instance_id
);
5429 WL_ERR(("failed to request nan data path [%d]\n", ret
));
5433 if (cmd_data
->status
== BCME_OK
) {
5434 nan_req_resp
.ndp_instance_id
= cmd_data
->ndp_instance_id
;
5436 nan_req_resp
.ndp_instance_id
= 0;
5439 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_REQUEST
,
5440 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5441 wl_cfgvendor_free_dp_cmd_data(cfg
, cmd_data
);
5447 wl_cfgvendor_nan_data_path_response(struct wiphy
*wiphy
,
5448 struct wireless_dev
*wdev
, const void * data
, int len
)
5451 nan_datapath_cmd_data_t
*cmd_data
= NULL
;
5452 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5453 nan_hal_resp_t nan_req_resp
;
5455 if (!cfg
->nan_enable
) {
5456 WL_ERR(("nan is not enabled, nan data path response blocked\n"));
5461 cmd_data
= (nan_datapath_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5463 WL_ERR(("%s: memory allocation failed\n", __func__
));
5468 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5469 ret
= wl_cfgvendor_nan_parse_datapath_args(wiphy
, data
, len
, cmd_data
);
5471 WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret
));
5474 ret
= wl_cfgnan_data_path_response_handler(wdev
->netdev
, cfg
, cmd_data
);
5476 WL_ERR(("failed to response nan data path [%d]\n", ret
));
5480 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_RESPONSE
,
5481 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5482 wl_cfgvendor_free_dp_cmd_data(cfg
, cmd_data
);
5488 wl_cfgvendor_nan_data_path_end(struct wiphy
*wiphy
,
5489 struct wireless_dev
*wdev
, const void * data
, int len
)
5492 nan_datapath_cmd_data_t
*cmd_data
= NULL
;
5493 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5494 nan_hal_resp_t nan_req_resp
;
5497 if (!cfg
->nan_enable
) {
5498 WL_ERR(("nan is not enabled, nan data path end blocked\n"));
5502 cmd_data
= (nan_datapath_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5504 WL_ERR(("%s: memory allocation failed\n", __func__
));
5509 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5510 ret
= wl_cfgvendor_nan_parse_datapath_args(wiphy
, data
, len
, cmd_data
);
5512 WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret
));
5515 ret
= wl_cfgnan_data_path_end_handler(wdev
->netdev
, cfg
, cmd_data
);
5517 WL_ERR(("failed to end nan data path [%d]\n", ret
));
5521 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_END
,
5522 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5523 wl_cfgvendor_free_dp_cmd_data(cfg
, cmd_data
);
5528 #ifdef WL_NAN_DISC_CACHE
5530 wl_cfgvendor_nan_data_path_sec_info(struct wiphy
*wiphy
,
5531 struct wireless_dev
*wdev
, const void *data
, int len
)
5534 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5535 nan_hal_resp_t nan_req_resp
;
5536 nan_datapath_sec_info_cmd_data_t
*cmd_data
= NULL
;
5537 dhd_pub_t
*dhdp
= wl_cfg80211_get_dhdp(wdev
->netdev
);
5540 if (!cfg
->nan_enable
) {
5541 WL_ERR(("nan is not enabled\n"));
5542 ret
= BCME_UNSUPPORTED
;
5545 cmd_data
= MALLOCZ(dhdp
->osh
, sizeof(*cmd_data
));
5547 WL_ERR(("%s: memory allocation failed\n", __func__
));
5552 ret
= wl_cfgvendor_nan_parse_dp_sec_info_args(wiphy
, data
, len
, cmd_data
);
5554 WL_ERR(("failed to parse sec info args\n"));
5557 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5558 ret
= wl_cfgnan_sec_info_handler(cfg
, cmd_data
, &nan_req_resp
);
5560 WL_ERR(("failed to retrieve svc hash/pub nmi error[%d]\n", ret
));
5564 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_SEC_INFO
,
5565 &nan_req_resp
, ret
, BCME_OK
);
5567 MFREE(dhdp
->osh
, cmd_data
, sizeof(*cmd_data
));
5572 #endif /* WL_NAN_DISC_CACHE */
5575 wl_cfgvendor_nan_version_info(struct wiphy
*wiphy
,
5576 struct wireless_dev
*wdev
, const void *data
, int len
)
5579 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5580 uint32 version
= NAN_HAL_VERSION_1
;
5583 WL_DBG(("Enter %s version %d\n", __FUNCTION__
, version
));
5584 ret
= wl_cfgvendor_send_cmd_reply(wiphy
, &version
, sizeof(version
));
5590 #ifdef LINKSTAT_SUPPORT
5595 #define HEADER_SIZE sizeof(ver_len)
5597 static int wl_cfgvendor_lstats_get_bcn_mbss(char *buf
, uint32
*rxbeaconmbss
)
5599 wl_cnt_info_t
*cbuf
= (wl_cnt_info_t
*)buf
;
5602 if ((cnt
= (const void *)bcm_get_data_from_xtlv_buf(cbuf
->data
, cbuf
->datalen
,
5603 WL_CNT_XTLV_CNTV_LE10_UCODE
, NULL
, BCM_XTLV_OPTION_ALIGN32
)) != NULL
) {
5604 *rxbeaconmbss
= ((const wl_cnt_v_le10_mcst_t
*)cnt
)->rxbeaconmbss
;
5605 } else if ((cnt
= (const void *)bcm_get_data_from_xtlv_buf(cbuf
->data
, cbuf
->datalen
,
5606 WL_CNT_XTLV_LT40_UCODE_V1
, NULL
, BCM_XTLV_OPTION_ALIGN32
)) != NULL
) {
5607 *rxbeaconmbss
= ((const wl_cnt_lt40mcst_v1_t
*)cnt
)->rxbeaconmbss
;
5608 } else if ((cnt
= (const void *)bcm_get_data_from_xtlv_buf(cbuf
->data
, cbuf
->datalen
,
5609 WL_CNT_XTLV_GE40_UCODE_V1
, NULL
, BCM_XTLV_OPTION_ALIGN32
)) != NULL
) {
5610 *rxbeaconmbss
= ((const wl_cnt_ge40mcst_v1_t
*)cnt
)->rxbeaconmbss
;
5611 } else if ((cnt
= (const void *)bcm_get_data_from_xtlv_buf(cbuf
->data
, cbuf
->datalen
,
5612 WL_CNT_XTLV_GE80_UCODE_V1
, NULL
, BCM_XTLV_OPTION_ALIGN32
)) != NULL
) {
5613 *rxbeaconmbss
= ((const wl_cnt_ge80mcst_v1_t
*)cnt
)->rxbeaconmbss
;
5616 return BCME_NOTFOUND
;
5622 static int wl_cfgvendor_lstats_get_info(struct wiphy
*wiphy
,
5623 struct wireless_dev
*wdev
, const void *data
, int len
)
5625 static char iovar_buf
[WLC_IOCTL_MAXLEN
];
5626 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5628 wifi_radio_stat
*radio
;
5629 wifi_radio_stat_h radio_h
;
5630 wl_wme_cnt_t
*wl_wme_cnt
;
5631 const wl_cnt_wlc_t
*wlc_cnt
;
5633 char *output
= NULL
;
5634 char *outdata
= NULL
;
5635 wifi_rate_stat_v1
*p_wifi_rate_stat_v1
= NULL
;
5636 wifi_rate_stat
*p_wifi_rate_stat
= NULL
;
5638 uint32 rxbeaconmbss
;
5639 wifi_iface_stat iface
;
5640 wlc_rev_info_t revinfo
;
5641 #ifdef CONFIG_COMPAT
5642 compat_wifi_iface_stat compat_iface
;
5643 int compat_task_state
= is_compat_task();
5644 #endif /* CONFIG_COMPAT */
5646 WL_INFORM_MEM(("%s: Enter \n", __func__
));
5647 RETURN_EIO_IF_NOT_UP(cfg
);
5649 /* Get the device rev info */
5650 memset(&revinfo
, 0, sizeof(revinfo
));
5651 err
= wldev_ioctl_get(bcmcfg_to_prmry_ndev(cfg
), WLC_GET_REVINFO
, &revinfo
,
5653 if (err
!= BCME_OK
) {
5657 outdata
= (void *)MALLOCZ(cfg
->osh
, WLC_IOCTL_MAXLEN
);
5658 if (outdata
== NULL
) {
5659 WL_ERR(("%s: alloc failed\n", __func__
));
5663 memset(&scbval
, 0, sizeof(scb_val_t
));
5664 memset(outdata
, 0, WLC_IOCTL_MAXLEN
);
5667 err
= wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg
), "radiostat", NULL
, 0,
5668 iovar_buf
, WLC_IOCTL_MAXLEN
, NULL
);
5669 if (err
!= BCME_OK
&& err
!= BCME_UNSUPPORTED
) {
5670 WL_ERR(("error (%d) - size = %zu\n", err
, sizeof(wifi_radio_stat
)));
5673 radio
= (wifi_radio_stat
*)iovar_buf
;
5675 memset(&radio_h
, 0, sizeof(wifi_radio_stat_h
));
5676 radio_h
.on_time
= radio
->on_time
;
5677 radio_h
.tx_time
= radio
->tx_time
;
5678 radio_h
.rx_time
= radio
->rx_time
;
5679 radio_h
.on_time_scan
= radio
->on_time_scan
;
5680 radio_h
.on_time_nbd
= radio
->on_time_nbd
;
5681 radio_h
.on_time_gscan
= radio
->on_time_gscan
;
5682 radio_h
.on_time_roam_scan
= radio
->on_time_roam_scan
;
5683 radio_h
.on_time_pno_scan
= radio
->on_time_pno_scan
;
5684 radio_h
.on_time_hs20
= radio
->on_time_hs20
;
5685 radio_h
.num_channels
= NUM_CHAN
;
5687 memcpy(output
, &radio_h
, sizeof(wifi_radio_stat_h
));
5689 output
+= sizeof(wifi_radio_stat_h
);
5690 output
+= (NUM_CHAN
* sizeof(wifi_channel_stat
));
5692 err
= wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg
), "wme_counters", NULL
, 0,
5693 iovar_buf
, WLC_IOCTL_MAXLEN
, NULL
);
5694 if (unlikely(err
)) {
5695 WL_ERR(("error (%d)\n", err
));
5698 wl_wme_cnt
= (wl_wme_cnt_t
*)iovar_buf
;
5700 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VO
].ac
, WIFI_AC_VO
);
5701 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VO
].tx_mpdu
, wl_wme_cnt
->tx
[AC_VO
].packets
);
5702 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VO
].rx_mpdu
, wl_wme_cnt
->rx
[AC_VO
].packets
);
5703 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VO
].mpdu_lost
,
5704 wl_wme_cnt
->tx_failed
[WIFI_AC_VO
].packets
);
5706 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VI
].ac
, WIFI_AC_VI
);
5707 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VI
].tx_mpdu
, wl_wme_cnt
->tx
[AC_VI
].packets
);
5708 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VI
].rx_mpdu
, wl_wme_cnt
->rx
[AC_VI
].packets
);
5709 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VI
].mpdu_lost
,
5710 wl_wme_cnt
->tx_failed
[WIFI_AC_VI
].packets
);
5712 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BE
].ac
, WIFI_AC_BE
);
5713 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BE
].tx_mpdu
, wl_wme_cnt
->tx
[AC_BE
].packets
);
5714 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BE
].rx_mpdu
, wl_wme_cnt
->rx
[AC_BE
].packets
);
5715 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BE
].mpdu_lost
,
5716 wl_wme_cnt
->tx_failed
[WIFI_AC_BE
].packets
);
5718 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BK
].ac
, WIFI_AC_BK
);
5719 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BK
].tx_mpdu
, wl_wme_cnt
->tx
[AC_BK
].packets
);
5720 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BK
].rx_mpdu
, wl_wme_cnt
->rx
[AC_BK
].packets
);
5721 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BK
].mpdu_lost
,
5722 wl_wme_cnt
->tx_failed
[WIFI_AC_BK
].packets
);
5724 err
= wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg
), "counters", NULL
, 0,
5725 iovar_buf
, WLC_IOCTL_MAXLEN
, NULL
);
5726 if (unlikely(err
)) {
5727 WL_ERR(("error (%d) - size = %zu\n", err
, sizeof(wl_cnt_wlc_t
)));
5731 CHK_CNTBUF_DATALEN(iovar_buf
, WLC_IOCTL_MAXLEN
);
5732 /* Translate traditional (ver <= 10) counters struct to new xtlv type struct */
5733 err
= wl_cntbuf_to_xtlv_format(NULL
, iovar_buf
, WLC_IOCTL_MAXLEN
, revinfo
.corerev
);
5734 if (err
!= BCME_OK
) {
5735 WL_ERR(("%s wl_cntbuf_to_xtlv_format ERR %d\n",
5736 __FUNCTION__
, err
));
5740 if (!(wlc_cnt
= GET_WLCCNT_FROM_CNTBUF(iovar_buf
))) {
5741 WL_ERR(("%s wlc_cnt NULL!\n", __FUNCTION__
));
5746 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BE
].retries
, wlc_cnt
->txretry
);
5748 err
= wl_cfgvendor_lstats_get_bcn_mbss(iovar_buf
, &rxbeaconmbss
);
5749 if (unlikely(err
)) {
5750 WL_ERR(("get_bcn_mbss error (%d)\n", err
));
5754 err
= wldev_get_rssi(bcmcfg_to_prmry_ndev(cfg
), &scbval
);
5755 if (unlikely(err
)) {
5756 WL_ERR(("get_rssi error (%d)\n", err
));
5760 COMPAT_ASSIGN_VALUE(iface
, beacon_rx
, rxbeaconmbss
);
5761 COMPAT_ASSIGN_VALUE(iface
, rssi_mgmt
, scbval
.val
);
5762 COMPAT_ASSIGN_VALUE(iface
, num_peers
, NUM_PEER
);
5763 COMPAT_ASSIGN_VALUE(iface
, peer_info
->num_rate
, NUM_RATE
);
5765 #ifdef CONFIG_COMPAT
5766 if (compat_task_state
) {
5767 memcpy(output
, &compat_iface
, sizeof(compat_iface
));
5768 output
+= (sizeof(compat_iface
) - sizeof(wifi_rate_stat
));
5770 #endif /* CONFIG_COMPAT */
5772 memcpy(output
, &iface
, sizeof(iface
));
5773 output
+= (sizeof(iface
) - sizeof(wifi_rate_stat
));
5776 err
= wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg
), "ratestat", NULL
, 0,
5777 iovar_buf
, WLC_IOCTL_MAXLEN
, NULL
);
5778 if (err
!= BCME_OK
&& err
!= BCME_UNSUPPORTED
) {
5779 WL_ERR(("error (%d) - size = %zu\n", err
, NUM_RATE
*sizeof(wifi_rate_stat
)));
5782 for (i
= 0; i
< NUM_RATE
; i
++) {
5784 (wifi_rate_stat
*)(iovar_buf
+ i
*sizeof(wifi_rate_stat
));
5785 p_wifi_rate_stat_v1
= (wifi_rate_stat_v1
*)output
;
5786 p_wifi_rate_stat_v1
->rate
.preamble
= p_wifi_rate_stat
->rate
.preamble
;
5787 p_wifi_rate_stat_v1
->rate
.nss
= p_wifi_rate_stat
->rate
.nss
;
5788 p_wifi_rate_stat_v1
->rate
.bw
= p_wifi_rate_stat
->rate
.bw
;
5789 p_wifi_rate_stat_v1
->rate
.rateMcsIdx
= p_wifi_rate_stat
->rate
.rateMcsIdx
;
5790 p_wifi_rate_stat_v1
->rate
.reserved
= p_wifi_rate_stat
->rate
.reserved
;
5791 p_wifi_rate_stat_v1
->rate
.bitrate
= p_wifi_rate_stat
->rate
.bitrate
;
5792 p_wifi_rate_stat_v1
->tx_mpdu
= p_wifi_rate_stat
->tx_mpdu
;
5793 p_wifi_rate_stat_v1
->rx_mpdu
= p_wifi_rate_stat
->rx_mpdu
;
5794 p_wifi_rate_stat_v1
->mpdu_lost
= p_wifi_rate_stat
->mpdu_lost
;
5795 p_wifi_rate_stat_v1
->retries
= p_wifi_rate_stat
->retries
;
5796 p_wifi_rate_stat_v1
->retries_short
= p_wifi_rate_stat
->retries_short
;
5797 p_wifi_rate_stat_v1
->retries_long
= p_wifi_rate_stat
->retries_long
;
5798 output
= (char *) &(p_wifi_rate_stat_v1
->retries_long
);
5799 output
+= sizeof(p_wifi_rate_stat_v1
->retries_long
);
5802 total_len
= sizeof(wifi_radio_stat_h
) +
5803 NUM_CHAN
* sizeof(wifi_channel_stat
);
5805 #ifdef CONFIG_COMPAT
5806 if (compat_task_state
) {
5807 total_len
+= sizeof(compat_wifi_iface_stat
);
5809 #endif /* CONFIG_COMPAT */
5811 total_len
+= sizeof(wifi_iface_stat
);
5814 total_len
= total_len
- sizeof(wifi_peer_info
) +
5815 NUM_PEER
* (sizeof(wifi_peer_info
) - sizeof(wifi_rate_stat_v1
) +
5816 NUM_RATE
* sizeof(wifi_rate_stat_v1
));
5818 if (total_len
> WLC_IOCTL_MAXLEN
) {
5819 WL_ERR(("Error! total_len:%d is unexpected value\n", total_len
));
5823 err
= wl_cfgvendor_send_cmd_reply(wiphy
, outdata
, total_len
);
5826 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
5830 MFREE(cfg
->osh
, outdata
, WLC_IOCTL_MAXLEN
);
5834 #endif /* LINKSTAT_SUPPORT */
5837 static int wl_cfgvendor_dbg_start_logging(struct wiphy
*wiphy
,
5838 struct wireless_dev
*wdev
, const void *data
, int len
)
5840 int ret
= BCME_OK
, rem
, type
;
5841 char ring_name
[DBGRING_NAME_MAX
] = {0};
5842 int log_level
= 0, flags
= 0, time_intval
= 0, threshold
= 0;
5843 const struct nlattr
*iter
;
5844 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5845 dhd_pub_t
*dhd_pub
= cfg
->pub
;
5846 nla_for_each_attr(iter
, data
, len
, rem
) {
5847 type
= nla_type(iter
);
5849 case DEBUG_ATTRIBUTE_RING_NAME
:
5850 strncpy(ring_name
, nla_data(iter
),
5851 MIN(sizeof(ring_name
) -1, nla_len(iter
)));
5853 case DEBUG_ATTRIBUTE_LOG_LEVEL
:
5854 log_level
= nla_get_u32(iter
);
5856 case DEBUG_ATTRIBUTE_RING_FLAGS
:
5857 flags
= nla_get_u32(iter
);
5859 case DEBUG_ATTRIBUTE_LOG_TIME_INTVAL
:
5860 time_intval
= nla_get_u32(iter
);
5862 case DEBUG_ATTRIBUTE_LOG_MIN_DATA_SIZE
:
5863 threshold
= nla_get_u32(iter
);
5866 WL_ERR(("Unknown type: %d\n", type
));
5872 ret
= dhd_os_start_logging(dhd_pub
, ring_name
, log_level
, flags
, time_intval
, threshold
);
5874 WL_ERR(("start_logging is failed ret: %d\n", ret
));
5880 static int wl_cfgvendor_dbg_reset_logging(struct wiphy
*wiphy
,
5881 struct wireless_dev
*wdev
, const void *data
, int len
)
5884 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5885 dhd_pub_t
*dhd_pub
= cfg
->pub
;
5887 ret
= dhd_os_reset_logging(dhd_pub
);
5889 WL_ERR(("reset logging is failed ret: %d\n", ret
));
5896 wl_cfgvendor_dbg_trigger_mem_dump(struct wiphy
*wiphy
,
5897 struct wireless_dev
*wdev
, const void *data
, int len
)
5901 struct sk_buff
*skb
;
5902 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5903 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
5905 dhdp
->memdump_type
= DUMP_TYPE_CFG_VENDOR_TRIGGERED
;
5906 ret
= dhd_os_socram_dump(bcmcfg_to_prmry_ndev(cfg
), &alloc_len
);
5908 WL_ERR(("failed to call dhd_os_socram_dump : %d\n", ret
));
5911 /* Alloc the SKB for vendor_event */
5912 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, 100);
5914 WL_ERR(("skb allocation is failed\n"));
5918 nla_put_u32(skb
, DEBUG_ATTRIBUTE_FW_DUMP_LEN
, alloc_len
);
5920 ret
= cfg80211_vendor_cmd_reply(skb
);
5923 WL_ERR(("Vendor Command reply failed ret:%d \n", ret
));
5931 wl_cfgvendor_dbg_get_mem_dump(struct wiphy
*wiphy
,
5932 struct wireless_dev
*wdev
, const void *data
, int len
)
5934 int ret
= BCME_OK
, rem
, type
;
5936 uintptr_t user_buf
= (uintptr_t)NULL
;
5937 const struct nlattr
*iter
;
5938 char *mem_buf
= NULL
;
5939 struct sk_buff
*skb
;
5940 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5942 nla_for_each_attr(iter
, data
, len
, rem
) {
5943 type
= nla_type(iter
);
5945 case DEBUG_ATTRIBUTE_FW_DUMP_LEN
:
5946 /* Check if the iter is valid and
5947 * buffer length is not already initialized.
5949 if ((nla_len(iter
) == sizeof(uint32
)) &&
5951 buf_len
= nla_get_u32(iter
);
5961 case DEBUG_ATTRIBUTE_FW_DUMP_DATA
:
5962 if (nla_len(iter
) != sizeof(uint64
)) {
5963 WL_ERR(("Invalid len\n"));
5967 user_buf
= (uintptr_t)nla_get_u64(iter
);
5974 WL_ERR(("Unknown type: %d\n", type
));
5979 if (buf_len
> 0 && user_buf
) {
5980 mem_buf
= vmalloc(buf_len
);
5982 WL_ERR(("failed to allocate mem_buf with size : %d\n", buf_len
));
5986 ret
= dhd_os_get_socram_dump(bcmcfg_to_prmry_ndev(cfg
), &mem_buf
, &buf_len
);
5988 WL_ERR(("failed to get_socram_dump : %d\n", ret
));
5991 #ifdef CONFIG_COMPAT
5992 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0))
5993 if (in_compat_syscall()) {
5995 if (is_compat_task()) {
5996 #endif /* LINUX_VER >= 4.6 */
5997 void * usr_ptr
= compat_ptr((uintptr_t) user_buf
);
5998 ret
= copy_to_user(usr_ptr
, mem_buf
, buf_len
);
6000 WL_ERR(("failed to copy memdump into user buffer : %d\n", ret
));
6005 #endif /* CONFIG_COMPAT */
6007 ret
= copy_to_user((void*)user_buf
, mem_buf
, buf_len
);
6009 WL_ERR(("failed to copy memdump into user buffer : %d\n", ret
));
6013 /* Alloc the SKB for vendor_event */
6014 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, 100);
6016 WL_ERR(("skb allocation is failed\n"));
6020 /* Indicate the memdump is succesfully copied */
6021 nla_put(skb
, DEBUG_ATTRIBUTE_FW_DUMP_DATA
, sizeof(ret
), &ret
);
6023 ret
= cfg80211_vendor_cmd_reply(skb
);
6026 WL_ERR(("Vendor Command reply failed ret:%d \n", ret
));
6036 static int wl_cfgvendor_dbg_get_ring_status(struct wiphy
*wiphy
,
6037 struct wireless_dev
*wdev
, const void *data
, int len
)
6042 struct sk_buff
*skb
;
6043 dhd_dbg_ring_status_t dbg_ring_status
[DEBUG_RING_ID_MAX
];
6044 dhd_dbg_ring_status_t ring_status
;
6045 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6046 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6047 memset(dbg_ring_status
, 0, DBG_RING_STATUS_SIZE
* DEBUG_RING_ID_MAX
);
6049 for (ring_id
= DEBUG_RING_ID_INVALID
+ 1; ring_id
< DEBUG_RING_ID_MAX
; ring_id
++) {
6050 ret
= dhd_os_get_ring_status(dhd_pub
, ring_id
, &ring_status
);
6051 if (ret
== BCME_NOTFOUND
) {
6052 WL_DBG(("The ring (%d) is not found \n", ring_id
));
6053 } else if (ret
== BCME_OK
) {
6054 dbg_ring_status
[ring_cnt
++] = ring_status
;
6057 /* Alloc the SKB for vendor_event */
6058 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
,
6059 (DBG_RING_STATUS_SIZE
* ring_cnt
) + 100);
6061 WL_ERR(("skb allocation is failed\n"));
6066 nla_put_u32(skb
, DEBUG_ATTRIBUTE_RING_NUM
, ring_cnt
);
6067 for (i
= 0; i
< ring_cnt
; i
++) {
6068 nla_put(skb
, DEBUG_ATTRIBUTE_RING_STATUS
, DBG_RING_STATUS_SIZE
,
6069 &dbg_ring_status
[i
]);
6071 ret
= cfg80211_vendor_cmd_reply(skb
);
6074 WL_ERR(("Vendor Command reply failed ret:%d \n", ret
));
6080 static int wl_cfgvendor_dbg_get_ring_data(struct wiphy
*wiphy
,
6081 struct wireless_dev
*wdev
, const void *data
, int len
)
6083 int ret
= BCME_OK
, rem
, type
;
6084 char ring_name
[DBGRING_NAME_MAX
] = {0};
6085 const struct nlattr
*iter
;
6086 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6087 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6089 nla_for_each_attr(iter
, data
, len
, rem
) {
6090 type
= nla_type(iter
);
6092 case DEBUG_ATTRIBUTE_RING_NAME
:
6093 strncpy(ring_name
, nla_data(iter
),
6094 MIN(sizeof(ring_name
) -1, nla_len(iter
)));
6097 WL_ERR(("Unknown type: %d\n", type
));
6102 ret
= dhd_os_trigger_get_ring_data(dhd_pub
, ring_name
);
6104 WL_ERR(("trigger_get_data failed ret:%d\n", ret
));
6109 #endif /* DEBUGABILITY */
6111 static int wl_cfgvendor_dbg_get_feature(struct wiphy
*wiphy
,
6112 struct wireless_dev
*wdev
, const void *data
, int len
)
6115 u32 supported_features
= 0;
6116 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6117 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6119 ret
= dhd_os_dbg_get_feature(dhd_pub
, &supported_features
);
6121 WL_ERR(("dbg_get_feature failed ret:%d\n", ret
));
6124 ret
= wl_cfgvendor_send_cmd_reply(wiphy
, &supported_features
,
6125 sizeof(supported_features
));
6131 static void wl_cfgvendor_dbg_ring_send_evt(void *ctx
,
6132 const int ring_id
, const void *data
, const uint32 len
,
6133 const dhd_dbg_ring_status_t ring_status
)
6135 struct net_device
*ndev
= ctx
;
6136 struct wiphy
*wiphy
;
6138 struct sk_buff
*skb
;
6140 WL_ERR(("ndev is NULL\n"));
6143 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
6144 wiphy
= ndev
->ieee80211_ptr
->wiphy
;
6145 /* Alloc the SKB for vendor_event */
6146 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
6147 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
6148 skb
= cfg80211_vendor_event_alloc(wiphy
, NULL
, len
+ 100,
6149 GOOGLE_DEBUG_RING_EVENT
, kflags
);
6151 skb
= cfg80211_vendor_event_alloc(wiphy
, len
+ 100,
6152 GOOGLE_DEBUG_RING_EVENT
, kflags
);
6153 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
6154 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
6156 WL_ERR(("skb alloc failed"));
6159 nla_put(skb
, DEBUG_ATTRIBUTE_RING_STATUS
, sizeof(ring_status
), &ring_status
);
6160 nla_put(skb
, DEBUG_ATTRIBUTE_RING_DATA
, len
, data
);
6161 cfg80211_vendor_event(skb
, kflags
);
6164 static void wl_cfgvendor_dbg_send_urgent_evt(void *ctx
, const void *data
,
6165 const uint32 len
, const uint32 fw_len
)
6167 struct net_device
*ndev
= ctx
;
6168 struct wiphy
*wiphy
;
6170 struct sk_buff
*skb
;
6172 WL_ERR(("ndev is NULL\n"));
6175 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
6176 wiphy
= ndev
->ieee80211_ptr
->wiphy
;
6177 /* Alloc the SKB for vendor_event */
6178 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
6179 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
6180 skb
= cfg80211_vendor_event_alloc(wiphy
, NULL
, len
+ 100,
6181 GOOGLE_FW_DUMP_EVENT
, kflags
);
6183 skb
= cfg80211_vendor_event_alloc(wiphy
, len
+ 100,
6184 GOOGLE_FW_DUMP_EVENT
, kflags
);
6185 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
6186 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
6188 WL_ERR(("skb alloc failed"));
6191 nla_put_u32(skb
, DEBUG_ATTRIBUTE_FW_DUMP_LEN
, fw_len
);
6192 nla_put(skb
, DEBUG_ATTRIBUTE_RING_DATA
, len
, data
);
6193 cfg80211_vendor_event(skb
, kflags
);
6195 #endif /* DEBUGABILITY */
6197 static int wl_cfgvendor_dbg_get_version(struct wiphy
*wiphy
,
6198 struct wireless_dev
*wdev
, const void *data
, int len
)
6200 int ret
= BCME_OK
, rem
, type
;
6202 bool dhd_ver
= FALSE
;
6204 const struct nlattr
*iter
;
6205 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6207 buf_ptr
= (char *)MALLOCZ(cfg
->osh
, buf_len
);
6209 WL_ERR(("failed to allocate the buffer for version n"));
6213 nla_for_each_attr(iter
, data
, len
, rem
) {
6214 type
= nla_type(iter
);
6216 case DEBUG_ATTRIBUTE_GET_DRIVER
:
6219 case DEBUG_ATTRIBUTE_GET_FW
:
6223 WL_ERR(("Unknown type: %d\n", type
));
6228 ret
= dhd_os_get_version(bcmcfg_to_prmry_ndev(cfg
), dhd_ver
, &buf_ptr
, buf_len
);
6230 WL_ERR(("failed to get the version %d\n", ret
));
6233 ret
= wl_cfgvendor_send_cmd_reply(wiphy
, buf_ptr
, strlen(buf_ptr
));
6235 MFREE(cfg
->osh
, buf_ptr
, buf_len
);
6240 static int wl_cfgvendor_dbg_start_pkt_fate_monitoring(struct wiphy
*wiphy
,
6241 struct wireless_dev
*wdev
, const void *data
, int len
)
6243 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6244 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6247 ret
= dhd_os_dbg_attach_pkt_monitor(dhd_pub
);
6248 if (unlikely(ret
)) {
6249 WL_ERR(("failed to start pkt fate monitoring, ret=%d", ret
));
6255 typedef int (*dbg_mon_get_pkts_t
) (dhd_pub_t
*dhdp
, void __user
*user_buf
,
6256 uint16 req_count
, uint16
*resp_count
);
6258 static int __wl_cfgvendor_dbg_get_pkt_fates(struct wiphy
*wiphy
,
6259 const void *data
, int len
, dbg_mon_get_pkts_t dbg_mon_get_pkts
)
6261 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6262 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6263 struct sk_buff
*skb
= NULL
;
6264 const struct nlattr
*iter
;
6265 void __user
*user_buf
= NULL
;
6266 uint16 req_count
= 0, resp_count
= 0;
6267 int ret
, tmp
, type
, mem_needed
;
6269 nla_for_each_attr(iter
, data
, len
, tmp
) {
6270 type
= nla_type(iter
);
6272 case DEBUG_ATTRIBUTE_PKT_FATE_NUM
:
6273 req_count
= nla_get_u32(iter
);
6275 case DEBUG_ATTRIBUTE_PKT_FATE_DATA
:
6276 user_buf
= (void __user
*)(unsigned long) nla_get_u64(iter
);
6279 WL_ERR(("%s: no such attribute %d\n", __FUNCTION__
, type
));
6285 if (!req_count
|| !user_buf
) {
6286 WL_ERR(("%s: invalid request, user_buf=%p, req_count=%u\n",
6287 __FUNCTION__
, user_buf
, req_count
));
6292 ret
= dbg_mon_get_pkts(dhd_pub
, user_buf
, req_count
, &resp_count
);
6293 if (unlikely(ret
)) {
6294 WL_ERR(("failed to get packets, ret:%d \n", ret
));
6298 mem_needed
= VENDOR_REPLY_OVERHEAD
+ ATTRIBUTE_U32_LEN
;
6299 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
6300 if (unlikely(!skb
)) {
6301 WL_ERR(("skb alloc failed"));
6306 nla_put_u32(skb
, DEBUG_ATTRIBUTE_PKT_FATE_NUM
, resp_count
);
6308 ret
= cfg80211_vendor_cmd_reply(skb
);
6309 if (unlikely(ret
)) {
6310 WL_ERR(("vendor Command reply failed ret:%d \n", ret
));
6317 static int wl_cfgvendor_dbg_get_tx_pkt_fates(struct wiphy
*wiphy
,
6318 struct wireless_dev
*wdev
, const void *data
, int len
)
6322 ret
= __wl_cfgvendor_dbg_get_pkt_fates(wiphy
, data
, len
,
6323 dhd_os_dbg_monitor_get_tx_pkts
);
6324 if (unlikely(ret
)) {
6325 WL_ERR(("failed to get tx packets, ret:%d \n", ret
));
6331 static int wl_cfgvendor_dbg_get_rx_pkt_fates(struct wiphy
*wiphy
,
6332 struct wireless_dev
*wdev
, const void *data
, int len
)
6336 ret
= __wl_cfgvendor_dbg_get_pkt_fates(wiphy
, data
, len
,
6337 dhd_os_dbg_monitor_get_rx_pkts
);
6338 if (unlikely(ret
)) {
6339 WL_ERR(("failed to get rx packets, ret:%d \n", ret
));
6344 #endif /* DBG_PKT_MON */
6347 static int wl_cfgvendor_start_mkeep_alive(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
6348 const void *data
, int len
)
6350 /* max size of IP packet for keep alive */
6351 const int MKEEP_ALIVE_IP_PKT_MAX
= 256;
6353 int ret
= BCME_OK
, rem
, type
;
6354 uint8 mkeep_alive_id
= 0;
6355 uint8
*ip_pkt
= NULL
;
6356 uint16 ip_pkt_len
= 0;
6357 uint8 src_mac
[ETHER_ADDR_LEN
];
6358 uint8 dst_mac
[ETHER_ADDR_LEN
];
6359 uint32 period_msec
= 0;
6360 const struct nlattr
*iter
;
6361 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6362 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6364 nla_for_each_attr(iter
, data
, len
, rem
) {
6365 type
= nla_type(iter
);
6367 case MKEEP_ALIVE_ATTRIBUTE_ID
:
6368 mkeep_alive_id
= nla_get_u8(iter
);
6370 case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN
:
6371 ip_pkt_len
= nla_get_u16(iter
);
6372 if (ip_pkt_len
> MKEEP_ALIVE_IP_PKT_MAX
) {
6377 case MKEEP_ALIVE_ATTRIBUTE_IP_PKT
:
6380 WL_ERR(("ip_pkt already allocated\n"));
6385 WL_ERR(("ip packet length is 0\n"));
6388 ip_pkt
= (u8
*)MALLOCZ(cfg
->osh
, ip_pkt_len
);
6389 if (ip_pkt
== NULL
) {
6391 WL_ERR(("Failed to allocate mem for ip packet\n"));
6394 memcpy(ip_pkt
, (u8
*)nla_data(iter
), ip_pkt_len
);
6396 case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR
:
6397 memcpy(src_mac
, nla_data(iter
), ETHER_ADDR_LEN
);
6399 case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR
:
6400 memcpy(dst_mac
, nla_data(iter
), ETHER_ADDR_LEN
);
6402 case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC
:
6403 period_msec
= nla_get_u32(iter
);
6406 WL_ERR(("Unknown type: %d\n", type
));
6412 if (ip_pkt
== NULL
) {
6414 WL_ERR(("ip packet is NULL\n"));
6418 ret
= dhd_dev_start_mkeep_alive(dhd_pub
, mkeep_alive_id
, ip_pkt
, ip_pkt_len
, src_mac
,
6419 dst_mac
, period_msec
);
6421 WL_ERR(("start_mkeep_alive is failed ret: %d\n", ret
));
6426 MFREE(cfg
->osh
, ip_pkt
, ip_pkt_len
);
6432 static int wl_cfgvendor_stop_mkeep_alive(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
6433 const void *data
, int len
)
6435 int ret
= BCME_OK
, rem
, type
;
6436 uint8 mkeep_alive_id
= 0;
6437 const struct nlattr
*iter
;
6438 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6439 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6441 nla_for_each_attr(iter
, data
, len
, rem
) {
6442 type
= nla_type(iter
);
6444 case MKEEP_ALIVE_ATTRIBUTE_ID
:
6445 mkeep_alive_id
= nla_get_u8(iter
);
6448 WL_ERR(("Unknown type: %d\n", type
));
6454 ret
= dhd_dev_stop_mkeep_alive(dhd_pub
, mkeep_alive_id
);
6456 WL_ERR(("stop_mkeep_alive is failed ret: %d\n", ret
));
6461 #endif /* KEEP_ALIVE */
6463 #if defined(PKT_FILTER_SUPPORT) && defined(APF)
6465 wl_cfgvendor_apf_get_capabilities(struct wiphy
*wiphy
,
6466 struct wireless_dev
*wdev
, const void *data
, int len
)
6468 struct net_device
*ndev
= wdev_to_ndev(wdev
);
6469 struct sk_buff
*skb
;
6470 int ret
, ver
, max_len
, mem_needed
;
6474 ret
= dhd_dev_apf_get_version(ndev
, &ver
);
6475 if (unlikely(ret
)) {
6476 WL_ERR(("APF get version failed, ret=%d\n", ret
));
6480 /* APF memory size limit */
6482 ret
= dhd_dev_apf_get_max_len(ndev
, &max_len
);
6483 if (unlikely(ret
)) {
6484 WL_ERR(("APF get maximum length failed, ret=%d\n", ret
));
6488 mem_needed
= VENDOR_REPLY_OVERHEAD
+ (ATTRIBUTE_U32_LEN
* 2);
6490 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
6491 if (unlikely(!skb
)) {
6492 WL_ERR(("%s: can't allocate %d bytes\n", __FUNCTION__
, mem_needed
));
6496 nla_put_u32(skb
, APF_ATTRIBUTE_VERSION
, ver
);
6497 nla_put_u32(skb
, APF_ATTRIBUTE_MAX_LEN
, max_len
);
6499 ret
= cfg80211_vendor_cmd_reply(skb
);
6500 if (unlikely(ret
)) {
6501 WL_ERR(("vendor command reply failed, ret=%d\n", ret
));
6508 wl_cfgvendor_apf_set_filter(struct wiphy
*wiphy
,
6509 struct wireless_dev
*wdev
, const void *data
, int len
)
6511 struct net_device
*ndev
= wdev_to_ndev(wdev
);
6512 const struct nlattr
*iter
;
6514 u32 program_len
= 0;
6516 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6519 WL_ERR(("Invalid len: %d\n", len
));
6523 nla_for_each_attr(iter
, data
, len
, tmp
) {
6524 type
= nla_type(iter
);
6526 case APF_ATTRIBUTE_PROGRAM_LEN
:
6527 /* check if the iter value is valid and program_len
6528 * is not already initialized.
6530 if (nla_len(iter
) == sizeof(uint32
) && !program_len
) {
6531 program_len
= nla_get_u32(iter
);
6537 if (program_len
> WL_APF_PROGRAM_MAX_SIZE
) {
6538 WL_ERR(("program len is more than expected len\n"));
6543 if (unlikely(!program_len
)) {
6544 WL_ERR(("zero program length\n"));
6549 case APF_ATTRIBUTE_PROGRAM
:
6550 if (unlikely(program
)) {
6551 WL_ERR(("program already allocated\n"));
6555 if (unlikely(!program_len
)) {
6556 WL_ERR(("program len is not set\n"));
6560 if (nla_len(iter
) != program_len
) {
6561 WL_ERR(("program_len is not same\n"));
6565 program
= MALLOCZ(cfg
->osh
, program_len
);
6566 if (unlikely(!program
)) {
6567 WL_ERR(("%s: can't allocate %d bytes\n",
6568 __FUNCTION__
, program_len
));
6572 memcpy(program
, (u8
*)nla_data(iter
), program_len
);
6575 WL_ERR(("%s: no such attribute %d\n", __FUNCTION__
, type
));
6581 ret
= dhd_dev_apf_add_filter(ndev
, program
, program_len
);
6585 MFREE(cfg
->osh
, program
, program_len
);
6589 #endif /* PKT_FILTER_SUPPORT && APF */
6591 #ifdef NDO_CONFIG_SUPPORT
6592 static int wl_cfgvendor_configure_nd_offload(struct wiphy
*wiphy
,
6593 struct wireless_dev
*wdev
, const void *data
, int len
)
6595 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6596 const struct nlattr
*iter
;
6597 int ret
= BCME_OK
, rem
, type
;
6600 nla_for_each_attr(iter
, data
, len
, rem
) {
6601 type
= nla_type(iter
);
6603 case ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE
:
6604 enable
= nla_get_u8(iter
);
6607 WL_ERR(("Unknown type: %d\n", type
));
6613 ret
= dhd_dev_ndo_cfg(bcmcfg_to_prmry_ndev(cfg
), enable
);
6615 WL_ERR(("dhd_dev_ndo_cfg() failed: %d\n", ret
));
6621 #endif /* NDO_CONFIG_SUPPORT */
6623 static const struct wiphy_vendor_command wl_vendor_cmds
[] = {
6626 .vendor_id
= OUI_BRCM
,
6627 .subcmd
= BRCM_VENDOR_SCMD_PRIV_STR
6629 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6630 .doit
= wl_cfgvendor_priv_string_handler
6632 #ifdef BCM_PRIV_CMD_SUPPORT
6635 .vendor_id
= OUI_BRCM
,
6636 .subcmd
= BRCM_VENDOR_SCMD_BCM_STR
6638 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6639 .doit
= wl_cfgvendor_priv_bcm_handler
6641 #endif /* BCM_PRIV_CMD_SUPPORT */
6642 #ifdef GSCAN_SUPPORT
6645 .vendor_id
= OUI_GOOGLE
,
6646 .subcmd
= GSCAN_SUBCMD_GET_CAPABILITIES
6648 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6649 .doit
= wl_cfgvendor_gscan_get_capabilities
6653 .vendor_id
= OUI_GOOGLE
,
6654 .subcmd
= GSCAN_SUBCMD_SET_CONFIG
6656 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6657 .doit
= wl_cfgvendor_set_scan_cfg
6661 .vendor_id
= OUI_GOOGLE
,
6662 .subcmd
= GSCAN_SUBCMD_SET_SCAN_CONFIG
6664 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6665 .doit
= wl_cfgvendor_set_batch_scan_cfg
6669 .vendor_id
= OUI_GOOGLE
,
6670 .subcmd
= GSCAN_SUBCMD_ENABLE_GSCAN
6672 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6673 .doit
= wl_cfgvendor_initiate_gscan
6677 .vendor_id
= OUI_GOOGLE
,
6678 .subcmd
= GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
6680 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6681 .doit
= wl_cfgvendor_enable_full_scan_result
6685 .vendor_id
= OUI_GOOGLE
,
6686 .subcmd
= GSCAN_SUBCMD_SET_HOTLIST
6688 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6689 .doit
= wl_cfgvendor_hotlist_cfg
6693 .vendor_id
= OUI_GOOGLE
,
6694 .subcmd
= GSCAN_SUBCMD_GET_SCAN_RESULTS
6696 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6697 .doit
= wl_cfgvendor_gscan_get_batch_results
6699 #endif /* GSCAN_SUPPORT */
6700 #if defined(GSCAN_SUPPORT) || defined(DHD_GET_VALID_CHANNELS)
6703 .vendor_id
= OUI_GOOGLE
,
6704 .subcmd
= GSCAN_SUBCMD_GET_CHANNEL_LIST
6706 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6707 .doit
= wl_cfgvendor_gscan_get_channel_list
6709 #endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */
6713 .vendor_id
= OUI_GOOGLE
,
6714 .subcmd
= RTT_SUBCMD_SET_CONFIG
6716 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6717 .doit
= wl_cfgvendor_rtt_set_config
6721 .vendor_id
= OUI_GOOGLE
,
6722 .subcmd
= RTT_SUBCMD_CANCEL_CONFIG
6724 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6725 .doit
= wl_cfgvendor_rtt_cancel_config
6729 .vendor_id
= OUI_GOOGLE
,
6730 .subcmd
= RTT_SUBCMD_GETCAPABILITY
6732 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6733 .doit
= wl_cfgvendor_rtt_get_capability
6737 .vendor_id
= OUI_GOOGLE
,
6738 .subcmd
= RTT_SUBCMD_GETAVAILCHANNEL
6740 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6741 .doit
= wl_cfgvendor_rtt_get_responder_info
6745 .vendor_id
= OUI_GOOGLE
,
6746 .subcmd
= RTT_SUBCMD_SET_RESPONDER
6748 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6749 .doit
= wl_cfgvendor_rtt_set_responder
6753 .vendor_id
= OUI_GOOGLE
,
6754 .subcmd
= RTT_SUBCMD_CANCEL_RESPONDER
6756 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6757 .doit
= wl_cfgvendor_rtt_cancel_responder
6759 #endif /* RTT_SUPPORT */
6762 .vendor_id
= OUI_GOOGLE
,
6763 .subcmd
= ANDR_WIFI_SUBCMD_GET_FEATURE_SET
6765 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6766 .doit
= wl_cfgvendor_get_feature_set
6770 .vendor_id
= OUI_GOOGLE
,
6771 .subcmd
= ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX
6773 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6774 .doit
= wl_cfgvendor_get_feature_set_matrix
6778 .vendor_id
= OUI_GOOGLE
,
6779 .subcmd
= ANDR_WIFI_RANDOM_MAC_OUI
6781 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6782 .doit
= wl_cfgvendor_set_rand_mac_oui
6784 #ifdef CUSTOM_FORCE_NODFS_FLAG
6787 .vendor_id
= OUI_GOOGLE
,
6788 .subcmd
= ANDR_WIFI_NODFS_CHANNELS
6790 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6791 .doit
= wl_cfgvendor_set_nodfs_flag
6793 #endif /* CUSTOM_FORCE_NODFS_FLAG */
6796 .vendor_id
= OUI_GOOGLE
,
6797 .subcmd
= ANDR_WIFI_SET_COUNTRY
6799 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6800 .doit
= wl_cfgvendor_set_country
6802 #ifdef LINKSTAT_SUPPORT
6805 .vendor_id
= OUI_GOOGLE
,
6806 .subcmd
= LSTATS_SUBCMD_GET_INFO
6808 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6809 .doit
= wl_cfgvendor_lstats_get_info
6811 #endif /* LINKSTAT_SUPPORT */
6813 #ifdef GSCAN_SUPPORT
6816 .vendor_id
= OUI_GOOGLE
,
6817 .subcmd
= GSCAN_SUBCMD_SET_EPNO_SSID
6819 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6820 .doit
= wl_cfgvendor_epno_cfg
6825 .vendor_id
= OUI_GOOGLE
,
6826 .subcmd
= WIFI_SUBCMD_SET_LAZY_ROAM_PARAMS
6828 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6829 .doit
= wl_cfgvendor_set_lazy_roam_cfg
6834 .vendor_id
= OUI_GOOGLE
,
6835 .subcmd
= WIFI_SUBCMD_ENABLE_LAZY_ROAM
6837 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6838 .doit
= wl_cfgvendor_enable_lazy_roam
6843 .vendor_id
= OUI_GOOGLE
,
6844 .subcmd
= WIFI_SUBCMD_SET_BSSID_PREF
6846 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6847 .doit
= wl_cfgvendor_set_bssid_pref
6850 #endif /* GSCAN_SUPPORT */
6851 #if defined(GSCAN_SUPPORT) || defined(ROAMEXP_SUPPORT)
6854 .vendor_id
= OUI_GOOGLE
,
6855 .subcmd
= WIFI_SUBCMD_SET_SSID_WHITELIST
6857 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6858 .doit
= wl_cfgvendor_set_ssid_whitelist
6863 .vendor_id
= OUI_GOOGLE
,
6864 .subcmd
= WIFI_SUBCMD_SET_BSSID_BLACKLIST
6866 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6867 .doit
= wl_cfgvendor_set_bssid_blacklist
6869 #endif /* GSCAN_SUPPORT || ROAMEXP_SUPPORT */
6870 #ifdef ROAMEXP_SUPPORT
6873 .vendor_id
= OUI_GOOGLE
,
6874 .subcmd
= WIFI_SUBCMD_FW_ROAM_POLICY
6876 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6877 .doit
= wl_cfgvendor_set_fw_roaming_state
6881 .vendor_id
= OUI_GOOGLE
,
6882 .subcmd
= WIFI_SUBCMD_ROAM_CAPABILITY
6884 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6885 .doit
= wl_cfgvendor_fw_roam_get_capability
6887 #endif /* ROAMEXP_SUPPORT */
6890 .vendor_id
= OUI_GOOGLE
,
6891 .subcmd
= DEBUG_GET_VER
6893 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6894 .doit
= wl_cfgvendor_dbg_get_version
6899 .vendor_id
= OUI_GOOGLE
,
6900 .subcmd
= DEBUG_START_LOGGING
6902 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6903 .doit
= wl_cfgvendor_dbg_start_logging
6907 .vendor_id
= OUI_GOOGLE
,
6908 .subcmd
= DEBUG_RESET_LOGGING
6910 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6911 .doit
= wl_cfgvendor_dbg_reset_logging
6915 .vendor_id
= OUI_GOOGLE
,
6916 .subcmd
= DEBUG_TRIGGER_MEM_DUMP
6918 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6919 .doit
= wl_cfgvendor_dbg_trigger_mem_dump
6923 .vendor_id
= OUI_GOOGLE
,
6924 .subcmd
= DEBUG_GET_MEM_DUMP
6926 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6927 .doit
= wl_cfgvendor_dbg_get_mem_dump
6931 .vendor_id
= OUI_GOOGLE
,
6932 .subcmd
= DEBUG_GET_RING_STATUS
6934 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6935 .doit
= wl_cfgvendor_dbg_get_ring_status
6939 .vendor_id
= OUI_GOOGLE
,
6940 .subcmd
= DEBUG_GET_RING_DATA
6942 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6943 .doit
= wl_cfgvendor_dbg_get_ring_data
6945 #endif /* DEBUGABILITY */
6948 .vendor_id
= OUI_GOOGLE
,
6949 .subcmd
= DEBUG_GET_FEATURE
6951 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6952 .doit
= wl_cfgvendor_dbg_get_feature
6957 .vendor_id
= OUI_GOOGLE
,
6958 .subcmd
= DEBUG_START_PKT_FATE_MONITORING
6960 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6961 .doit
= wl_cfgvendor_dbg_start_pkt_fate_monitoring
6965 .vendor_id
= OUI_GOOGLE
,
6966 .subcmd
= DEBUG_GET_TX_PKT_FATES
6968 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6969 .doit
= wl_cfgvendor_dbg_get_tx_pkt_fates
6973 .vendor_id
= OUI_GOOGLE
,
6974 .subcmd
= DEBUG_GET_RX_PKT_FATES
6976 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6977 .doit
= wl_cfgvendor_dbg_get_rx_pkt_fates
6979 #endif /* DBG_PKT_MON */
6983 .vendor_id
= OUI_GOOGLE
,
6984 .subcmd
= WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE
6986 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6987 .doit
= wl_cfgvendor_start_mkeep_alive
6991 .vendor_id
= OUI_GOOGLE
,
6992 .subcmd
= WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE
6994 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6995 .doit
= wl_cfgvendor_stop_mkeep_alive
6997 #endif /* KEEP_ALIVE */
7001 .vendor_id
= OUI_GOOGLE
,
7002 .subcmd
= NAN_WIFI_SUBCMD_ENABLE
7004 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7005 .doit
= wl_cfgvendor_nan_start_handler
7009 .vendor_id
= OUI_GOOGLE
,
7010 .subcmd
= NAN_WIFI_SUBCMD_DISABLE
7012 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7013 .doit
= wl_cfgvendor_nan_stop_handler
7017 .vendor_id
= OUI_GOOGLE
,
7018 .subcmd
= NAN_WIFI_SUBCMD_CONFIG
7020 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7021 .doit
= wl_cfgvendor_nan_config_handler
7025 .vendor_id
= OUI_GOOGLE
,
7026 .subcmd
= NAN_WIFI_SUBCMD_REQUEST_PUBLISH
7028 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7029 .doit
= wl_cfgvendor_nan_req_publish
7033 .vendor_id
= OUI_GOOGLE
,
7034 .subcmd
= NAN_WIFI_SUBCMD_REQUEST_SUBSCRIBE
7036 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7037 .doit
= wl_cfgvendor_nan_req_subscribe
7041 .vendor_id
= OUI_GOOGLE
,
7042 .subcmd
= NAN_WIFI_SUBCMD_CANCEL_PUBLISH
7044 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7045 .doit
= wl_cfgvendor_nan_cancel_publish
7049 .vendor_id
= OUI_GOOGLE
,
7050 .subcmd
= NAN_WIFI_SUBCMD_CANCEL_SUBSCRIBE
7052 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7053 .doit
= wl_cfgvendor_nan_cancel_subscribe
7057 .vendor_id
= OUI_GOOGLE
,
7058 .subcmd
= NAN_WIFI_SUBCMD_TRANSMIT
7060 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7061 .doit
= wl_cfgvendor_nan_transmit
7065 .vendor_id
= OUI_GOOGLE
,
7066 .subcmd
= NAN_WIFI_SUBCMD_GET_CAPABILITIES
7068 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7069 .doit
= wl_cfgvendor_nan_get_capablities
7074 .vendor_id
= OUI_GOOGLE
,
7075 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE
7077 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7078 .doit
= wl_cfgvendor_nan_data_path_iface_create
7082 .vendor_id
= OUI_GOOGLE
,
7083 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE
7085 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7086 .doit
= wl_cfgvendor_nan_data_path_iface_delete
7090 .vendor_id
= OUI_GOOGLE
,
7091 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_REQUEST
7093 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7094 .doit
= wl_cfgvendor_nan_data_path_request
7098 .vendor_id
= OUI_GOOGLE
,
7099 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_RESPONSE
7101 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7102 .doit
= wl_cfgvendor_nan_data_path_response
7106 .vendor_id
= OUI_GOOGLE
,
7107 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_END
7109 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7110 .doit
= wl_cfgvendor_nan_data_path_end
7112 #ifdef WL_NAN_DISC_CACHE
7115 .vendor_id
= OUI_GOOGLE
,
7116 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_SEC_INFO
7118 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7119 .doit
= wl_cfgvendor_nan_data_path_sec_info
7121 #endif /* WL_NAN_DISC_CACHE */
7124 .vendor_id
= OUI_GOOGLE
,
7125 .subcmd
= NAN_WIFI_SUBCMD_VERSION_INFO
7127 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7128 .doit
= wl_cfgvendor_nan_version_info
7131 #if defined(PKT_FILTER_SUPPORT) && defined(APF)
7134 .vendor_id
= OUI_GOOGLE
,
7135 .subcmd
= APF_SUBCMD_GET_CAPABILITIES
7137 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7138 .doit
= wl_cfgvendor_apf_get_capabilities
7143 .vendor_id
= OUI_GOOGLE
,
7144 .subcmd
= APF_SUBCMD_SET_FILTER
7146 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7147 .doit
= wl_cfgvendor_apf_set_filter
7149 #endif /* PKT_FILTER_SUPPORT && APF */
7150 #ifdef NDO_CONFIG_SUPPORT
7153 .vendor_id
= OUI_GOOGLE
,
7154 .subcmd
= WIFI_SUBCMD_CONFIG_ND_OFFLOAD
7156 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7157 .doit
= wl_cfgvendor_configure_nd_offload
7159 #endif /* NDO_CONFIG_SUPPORT */
7160 #ifdef RSSI_MONITOR_SUPPORT
7163 .vendor_id
= OUI_GOOGLE
,
7164 .subcmd
= WIFI_SUBCMD_SET_RSSI_MONITOR
7166 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7167 .doit
= wl_cfgvendor_set_rssi_monitor
7169 #endif /* RSSI_MONITOR_SUPPORT */
7170 #ifdef DHDTCPACK_SUPPRESS
7173 .vendor_id
= OUI_GOOGLE
,
7174 .subcmd
= WIFI_SUBCMD_CONFIG_TCPACK_SUP
7176 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7177 .doit
= wl_cfgvendor_set_tcpack_sup_mode
7179 #endif /* DHDTCPACK_SUPPRESS */
7180 #ifdef DHD_WAKE_STATUS
7183 .vendor_id
= OUI_GOOGLE
,
7184 .subcmd
= DEBUG_GET_WAKE_REASON_STATS
7186 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7187 .doit
= wl_cfgvendor_get_wake_reason_stats
7189 #endif /* DHD_WAKE_STATUS */
7192 static const struct nl80211_vendor_cmd_info wl_vendor_events
[] = {
7193 { OUI_BRCM
, BRCM_VENDOR_EVENT_UNSPEC
},
7194 { OUI_BRCM
, BRCM_VENDOR_EVENT_PRIV_STR
},
7195 { OUI_GOOGLE
, GOOGLE_GSCAN_SIGNIFICANT_EVENT
},
7196 { OUI_GOOGLE
, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT
},
7197 { OUI_GOOGLE
, GOOGLE_GSCAN_BATCH_SCAN_EVENT
},
7198 { OUI_GOOGLE
, GOOGLE_SCAN_FULL_RESULTS_EVENT
},
7199 { OUI_GOOGLE
, GOOGLE_RTT_COMPLETE_EVENT
},
7200 { OUI_GOOGLE
, GOOGLE_SCAN_COMPLETE_EVENT
},
7201 { OUI_GOOGLE
, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT
},
7202 { OUI_GOOGLE
, GOOGLE_SCAN_EPNO_EVENT
},
7203 { OUI_GOOGLE
, GOOGLE_DEBUG_RING_EVENT
},
7204 { OUI_GOOGLE
, GOOGLE_FW_DUMP_EVENT
},
7205 { OUI_GOOGLE
, GOOGLE_PNO_HOTSPOT_FOUND_EVENT
},
7206 { OUI_GOOGLE
, GOOGLE_RSSI_MONITOR_EVENT
},
7207 { OUI_GOOGLE
, GOOGLE_MKEEP_ALIVE_EVENT
},
7208 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_ENABLED
},
7209 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_DISABLED
},
7210 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH
},
7211 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_REPLIED
},
7212 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_PUBLISH_TERMINATED
},
7213 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED
},
7214 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_DE_EVENT
},
7215 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_FOLLOWUP
},
7216 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND
},
7217 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_DATA_REQUEST
},
7218 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_DATA_CONFIRMATION
},
7219 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_DATA_END
},
7220 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_BEACON
},
7221 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_SDF
},
7222 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_TCA
},
7223 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_SUBSCRIBE_UNMATCH
},
7224 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_UNKNOWN
},
7225 { OUI_GOOGLE
, GOOGLE_ROAM_EVENT_START
},
7226 { OUI_BRCM
, BRCM_VENDOR_EVENT_HANGED
},
7227 { OUI_BRCM
, BRCM_VENDOR_EVENT_SAE_KEY
},
7228 { OUI_BRCM
, BRCM_VENDOR_EVENT_BEACON_RECV
}
7231 int wl_cfgvendor_attach(struct wiphy
*wiphy
, dhd_pub_t
*dhd
)
7234 WL_INFORM_MEM(("Vendor: Register BRCM cfg80211 vendor cmd(0x%x) interface \n",
7235 NL80211_CMD_VENDOR
));
7237 wiphy
->vendor_commands
= wl_vendor_cmds
;
7238 wiphy
->n_vendor_commands
= ARRAY_SIZE(wl_vendor_cmds
);
7239 wiphy
->vendor_events
= wl_vendor_events
;
7240 wiphy
->n_vendor_events
= ARRAY_SIZE(wl_vendor_events
);
7243 dhd_os_dbg_register_callback(FW_VERBOSE_RING_ID
, wl_cfgvendor_dbg_ring_send_evt
);
7244 dhd_os_dbg_register_callback(FW_EVENT_RING_ID
, wl_cfgvendor_dbg_ring_send_evt
);
7245 dhd_os_dbg_register_callback(DHD_EVENT_RING_ID
, wl_cfgvendor_dbg_ring_send_evt
);
7246 dhd_os_dbg_register_callback(NAN_EVENT_RING_ID
, wl_cfgvendor_dbg_ring_send_evt
);
7247 dhd_os_dbg_register_urgent_notifier(dhd
, wl_cfgvendor_dbg_send_urgent_evt
);
7248 #endif /* DEBUGABILITY */
7253 int wl_cfgvendor_detach(struct wiphy
*wiphy
)
7255 WL_INFORM_MEM(("Vendor: Unregister BRCM cfg80211 vendor interface \n"));
7257 wiphy
->vendor_commands
= NULL
;
7258 wiphy
->vendor_events
= NULL
;
7259 wiphy
->n_vendor_commands
= 0;
7260 wiphy
->n_vendor_events
= 0;
7264 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
7266 #ifdef WL_CFGVENDOR_SEND_HANG_EVENT
7268 wl_cfgvendor_send_hang_event(struct net_device
*dev
, u16 reason
, char *string
, int hang_info_cnt
)
7270 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
7271 struct wiphy
*wiphy
;
7275 uint32 dumy_data
= 0;
7276 int reason_hang_info
= 0;
7279 int hang_reason_mismatch
= FALSE
;
7281 if (!cfg
|| !cfg
->wdev
) {
7282 WL_ERR(("cfg=%p wdev=%p\n", cfg
, (cfg
? cfg
->wdev
: NULL
)));
7286 wiphy
= cfg
->wdev
->wiphy
;
7289 WL_ERR(("wiphy is NULL\n"));
7293 hang_info
= MALLOCZ(cfg
->osh
, VENDOR_SEND_HANG_EXT_INFO_LEN
);
7294 if (hang_info
== NULL
) {
7295 WL_ERR(("alloc hang_info failed\n"));
7299 dhd
= (dhd_pub_t
*)(cfg
->pub
);
7302 /* check fakeapscan in progress then stop scan */
7303 if (cfg
->bcnrecv_info
.bcnrecv_state
== BEACON_RECV_STARTED
) {
7304 wl_android_bcnrecv_stop(dev
, WL_BCNRECV_HANG
);
7306 #endif /* WL_BCNRECV */
7307 sscanf(string
, "%d", &reason_hang_info
);
7309 len
= VENDOR_SEND_HANG_EXT_INFO_LEN
- bytes_written
;
7310 if (strlen(string
) == 0 || (reason_hang_info
!= reason
)) {
7311 WL_ERR(("hang reason mismatch: string len %d reason_hang_info %d\n",
7312 (int)strlen(string
), reason_hang_info
));
7313 hang_reason_mismatch
= TRUE
;
7315 get_debug_dump_time(dhd
->debug_dump_time_hang_str
);
7316 copy_debug_dump_time(dhd
->debug_dump_time_str
,
7317 dhd
->debug_dump_time_hang_str
);
7319 bytes_written
+= scnprintf(&hang_info
[bytes_written
], len
,
7320 "%d %d %s %08x %08x %08x %08x %08x %08x %08x",
7321 reason
, VENDOR_SEND_HANG_EXT_INFO_VER
,
7322 dhd
->debug_dump_time_hang_str
,
7323 0, 0, 0, 0, 0, 0, 0);
7325 clear_debug_dump_time(dhd
->debug_dump_time_hang_str
);
7328 bytes_written
+= scnprintf(&hang_info
[bytes_written
], len
, "%s", string
);
7331 WL_ERR(("hang reason: %d info cnt: %d\n", reason
, hang_info_cnt
));
7333 if (hang_reason_mismatch
== FALSE
) {
7334 cnt
= hang_info_cnt
;
7336 cnt
= HANG_FIELD_MISMATCH_CNT
;
7339 while (cnt
< HANG_FIELD_CNT_MAX
) {
7340 len
= VENDOR_SEND_HANG_EXT_INFO_LEN
- bytes_written
;
7341 bytes_written
+= scnprintf(&hang_info
[bytes_written
], len
,
7342 "%c%08x", HANG_RAW_DEL
, dumy_data
);
7346 WL_ERR(("hang info cnt: %d len: %d\n", cnt
, (int)strlen(hang_info
)));
7347 WL_ERR(("hang info data: %s\n", hang_info
));
7349 wl_cfgvendor_send_async_event(wiphy
,
7350 bcmcfg_to_prmry_ndev(cfg
), BRCM_VENDOR_EVENT_HANGED
,
7351 hang_info
, (int)strlen(hang_info
));
7353 memset(string
, 0, VENDOR_SEND_HANG_EXT_INFO_LEN
);
7356 MFREE(cfg
->osh
, hang_info
, VENDOR_SEND_HANG_EXT_INFO_LEN
);
7360 if (dhd
->debug_dump_time_hang_str
) {
7361 dhd_logdump_cookie_save(dhd
, dhd
->debug_dump_time_hang_str
, "HANG");
7363 #endif /* DHD_LOG_DUMP */
7366 clear_debug_dump_time(dhd
->debug_dump_time_str
);
7371 wl_copy_hang_info_if_falure(struct net_device
*dev
, u16 reason
, s32 ret
)
7373 struct bcm_cfg80211
*cfg
= NULL
;
7376 char ioctl_buf
[WLC_IOCTL_SMLEN
];
7378 int bytes_written
= 0;
7382 WL_ERR(("dev is null"));
7387 cfg
= wl_get_cfg(dev
);
7389 WL_ERR(("dev=%p cfg=%p\n", dev
, cfg
));
7393 dhd
= (dhd_pub_t
*)(cfg
->pub
);
7395 if (!dhd
|| !dhd
->hang_info
) {
7396 WL_ERR(("%s dhd=%p hang_info=%p\n", __FUNCTION__
,
7397 dhd
, (dhd
? dhd
->hang_info
: NULL
)));
7401 err
= wldev_iovar_getbuf_bsscfg(dev
, "memuse",
7402 NULL
, 0, ioctl_buf
, WLC_IOCTL_SMLEN
, 0, NULL
);
7403 if (unlikely(err
)) {
7404 WL_ERR(("error (%d)\n", err
));
7408 memcpy(&mu
, ioctl_buf
, sizeof(memuse_info_t
));
7410 if (mu
.len
>= sizeof(memuse_info_t
)) {
7411 WL_ERR(("Heap Total: %d(%dK)\n", mu
.arena_size
, KB(mu
.arena_size
)));
7412 WL_ERR(("Free: %d(%dK), LWM: %d(%dK)\n",
7413 mu
.arena_free
, KB(mu
.arena_free
),
7414 mu
.free_lwm
, KB(mu
.free_lwm
)));
7415 WL_ERR(("In use: %d(%dK), HWM: %d(%dK)\n",
7416 mu
.inuse_size
, KB(mu
.inuse_size
),
7417 mu
.inuse_hwm
, KB(mu
.inuse_hwm
)));
7418 WL_ERR(("Malloc failure count: %d\n", mu
.mf_count
));
7421 memset(dhd
->hang_info
, 0, VENDOR_SEND_HANG_EXT_INFO_LEN
);
7422 remain_len
= VENDOR_SEND_HANG_EXT_INFO_LEN
- bytes_written
;
7424 get_debug_dump_time(dhd
->debug_dump_time_hang_str
);
7425 copy_debug_dump_time(dhd
->debug_dump_time_str
, dhd
->debug_dump_time_hang_str
);
7427 bytes_written
+= scnprintf(&dhd
->hang_info
[bytes_written
], remain_len
,
7428 "%d %d %s %d %d %d %d %d %08x %08x",
7429 reason
, VENDOR_SEND_HANG_EXT_INFO_VER
,
7430 dhd
->debug_dump_time_hang_str
,
7431 ret
, mu
.arena_size
, mu
.arena_free
, mu
.inuse_size
, mu
.mf_count
, 0, 0);
7433 dhd
->hang_info_cnt
= HANG_FIELD_IF_FAILURE_CNT
;
7435 clear_debug_dump_time(dhd
->debug_dump_time_hang_str
);
7439 #endif /* WL_CFGVENDOR_SEND_HANG_EVENT */