forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_cfgvendor.c
....@@ -1,15 +1,16 @@
1
-/* SPDX-License-Identifier: GPL-2.0 */
21 /*
32 * Linux cfg80211 Vendor Extension Code
43 *
5
- * Copyright (C) 1999-2019, Broadcom Corporation
6
- *
4
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
5
+ *
6
+ * Copyright (C) 1999-2017, Broadcom Corporation
7
+ *
78 * Unless you and Broadcom execute a separate written software license
89 * agreement governing use of this software, this software is licensed to you
910 * under the terms of the GNU General Public License version 2 (the "GPL"),
1011 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
1112 * following added to such license:
12
- *
13
+ *
1314 * As a special exception, the copyright holders of this software give you
1415 * permission to link this software with independent modules, and to copy and
1516 * distribute the resulting executable under terms of your choice, provided that
....@@ -17,7 +18,7 @@
1718 * the license of that module. An independent module is a module which is not
1819 * derived from this software. The special exception does not apply to any
1920 * modifications of the software.
20
- *
21
+ *
2122 * Notwithstanding the above, under no circumstances may you combine this
2223 * software in any way with any other Broadcom software provided under a license
2324 * other than the GPL, without Broadcom's express prior written consent.
....@@ -25,7 +26,7 @@
2526 *
2627 * <<Broadcom-WL-IPTag/Open:>>
2728 *
28
- * $Id: wl_cfgvendor.c 455257 2014-02-20 08:10:24Z $
29
+ * $Id: wl_cfgvendor.c 815871 2019-04-22 06:21:38Z $
2930 */
3031
3132 /*
....@@ -42,10 +43,11 @@
4243 #include <bcmutils.h>
4344 #include <bcmwifi_channels.h>
4445 #include <bcmendian.h>
45
-#include <proto/ethernet.h>
46
-#include <proto/802.11.h>
46
+#include <ethernet.h>
47
+#include <802.11.h>
4748 #include <linux/if_arp.h>
48
-#include <linux/uaccess.h>
49
+#include <asm/uaccess.h>
50
+
4951 #include <dngl_stats.h>
5052 #include <dhd.h>
5153 #include <dhd_debug.h>
....@@ -53,13 +55,17 @@
5355 #include <wlioctl.h>
5456 #include <wlioctl_utils.h>
5557 #include <dhd_cfg80211.h>
58
+#ifdef DHD_PKT_LOGGING
59
+#include <dhd_pktlog.h>
60
+#endif /* DHD_PKT_LOGGING */
5661 #ifdef PNO_SUPPORT
5762 #include <dhd_pno.h>
5863 #endif /* PNO_SUPPORT */
5964 #ifdef RTT_SUPPORT
6065 #include <dhd_rtt.h>
6166 #endif /* RTT_SUPPORT */
62
-#include <proto/ethernet.h>
67
+
68
+#include <ethernet.h>
6369 #include <linux/kernel.h>
6470 #include <linux/kthread.h>
6571 #include <linux/netdevice.h>
....@@ -75,54 +81,136 @@
7581 #include <wldev_common.h>
7682 #include <wl_cfg80211.h>
7783 #include <wl_cfgp2p.h>
84
+#ifdef WL_NAN
85
+#include <wl_cfgnan.h>
86
+#endif /* WL_NAN */
87
+#ifdef OEM_ANDROID
7888 #include <wl_android.h>
89
+#endif /* OEM_ANDROID */
7990 #include <wl_cfgvendor.h>
80
-
8191 #ifdef PROP_TXSTATUS
8292 #include <dhd_wlfc.h>
83
-#endif
93
+#endif // endif
8494 #include <brcm_nl80211.h>
8595
86
-#if defined(WL_VENDOR_EXT_SUPPORT)
96
+char*
97
+wl_get_kernel_timestamp(void)
98
+{
99
+ static char buf[32];
100
+ u64 ts_nsec;
101
+ unsigned long rem_nsec;
102
+
103
+ ts_nsec = local_clock();
104
+ rem_nsec = DIV_AND_MOD_U64_BY_U32(ts_nsec, NSEC_PER_SEC);
105
+ snprintf(buf, sizeof(buf), "%5lu.%06lu",
106
+ (unsigned long)ts_nsec, rem_nsec / NSEC_PER_USEC);
107
+
108
+ return buf;
109
+}
110
+
111
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
112
+#if defined(WL_SUPP_EVENT)
113
+int
114
+wl_cfgvendor_send_supp_eventstring(const char *func_name, const char *fmt, ...)
115
+{
116
+ char buf[SUPP_LOG_LEN] = {0};
117
+ struct bcm_cfg80211 *cfg;
118
+ struct wiphy *wiphy;
119
+ va_list args;
120
+ int len;
121
+ int prefix_len;
122
+ int rem_len;
123
+
124
+ cfg = wl_cfg80211_get_bcmcfg();
125
+ if (!cfg || !cfg->wdev) {
126
+ WL_DBG(("supp evt invalid arg\n"));
127
+ return BCME_OK;
128
+ }
129
+
130
+ wiphy = cfg->wdev->wiphy;
131
+ prefix_len = snprintf(buf, SUPP_LOG_LEN, "[DHD]<%s> %s: ",
132
+ wl_get_kernel_timestamp(), __func__);
133
+ /* Remaining buffer len */
134
+ rem_len = SUPP_LOG_LEN - (prefix_len + 1);
135
+ /* Print the arg list on to the remaining part of the buffer */
136
+ va_start(args, fmt);
137
+ len = vsnprintf((buf + prefix_len), rem_len, fmt, args);
138
+ va_end(args);
139
+ if (len < 0) {
140
+ return -EINVAL;
141
+ }
142
+
143
+ if (len > rem_len) {
144
+ /* If return length is greater than buffer len,
145
+ * then its truncated buffer case.
146
+ */
147
+ len = rem_len;
148
+ }
149
+
150
+ /* Ensure the buffer is null terminated */
151
+ len += prefix_len;
152
+ buf[len] = '\0';
153
+ len++;
154
+
155
+ return wl_cfgvendor_send_async_event(wiphy,
156
+ bcmcfg_to_prmry_ndev(cfg), BRCM_VENDOR_EVENT_PRIV_STR, buf, len);
157
+}
158
+
159
+int
160
+wl_cfgvendor_notify_supp_event_str(const char *evt_name, const char *fmt, ...)
161
+{
162
+ char buf[SUPP_LOG_LEN] = {0};
163
+ struct bcm_cfg80211 *cfg;
164
+ struct wiphy *wiphy;
165
+ va_list args;
166
+ int len;
167
+ int prefix_len;
168
+ int rem_len;
169
+
170
+ cfg = wl_cfg80211_get_bcmcfg();
171
+ if (!cfg || !cfg->wdev) {
172
+ WL_DBG(("supp evt invalid arg\n"));
173
+ return BCME_OK;
174
+ }
175
+ wiphy = cfg->wdev->wiphy;
176
+ prefix_len = snprintf(buf, SUPP_LOG_LEN, "%s ", evt_name);
177
+ /* Remaining buffer len */
178
+ rem_len = SUPP_LOG_LEN - (prefix_len + 1);
179
+ /* Print the arg list on to the remaining part of the buffer */
180
+ va_start(args, fmt);
181
+ len = vsnprintf((buf + prefix_len), rem_len, fmt, args);
182
+ va_end(args);
183
+ if (len < 0) {
184
+ return -EINVAL;
185
+ }
186
+
187
+ if (len > rem_len) {
188
+ /* If return length is greater than buffer len,
189
+ * then its truncated buffer case.
190
+ */
191
+ len = rem_len;
192
+ }
193
+
194
+ /* Ensure the buffer is null terminated */
195
+ len += prefix_len;
196
+ buf[len] = '\0';
197
+ len++;
198
+
199
+ return wl_cfgvendor_send_async_event(wiphy,
200
+ bcmcfg_to_prmry_ndev(cfg), BRCM_VENDOR_EVENT_PRIV_STR, buf, len);
201
+}
202
+#endif /* WL_SUPP_EVENT */
203
+
87204 /*
88205 * This API is to be used for asynchronous vendor events. This
89206 * shouldn't be used in response to a vendor command from its
90207 * do_it handler context (instead wl_cfgvendor_send_cmd_reply should
91208 * be used).
92209 */
93
-static int
94
-wl_cfgvendor_set_country(struct wiphy *wiphy,
95
- struct wireless_dev *wdev, const void *data, int len)
96
-{
97
- int err = BCME_ERROR, rem, type;
98
- char country_code[WLC_CNTRY_BUF_SZ] = {0};
99
- const struct nlattr *iter;
100
-
101
- nla_for_each_attr(iter, data, len, rem) {
102
- type = nla_type(iter);
103
- switch (type) {
104
- case ANDR_WIFI_ATTRIBUTE_COUNTRY:
105
- memcpy(country_code, nla_data(iter),
106
- MIN(nla_len(iter), WLC_CNTRY_BUF_SZ));
107
- break;
108
- default:
109
- WL_ERR(("Unknown type: %d\n", type));
110
- return err;
111
- }
112
- }
113
-
114
- err = wldev_set_country(wdev->netdev, country_code, true, true, -1);
115
- if (err < 0) {
116
- WL_ERR(("Set country failed ret:%d\n", err));
117
- }
118
-
119
- return err;
120
-}
121
-
122210 int wl_cfgvendor_send_async_event(struct wiphy *wiphy,
123211 struct net_device *dev, int event_id, const void *data, int len)
124212 {
125
- u16 kflags;
213
+ gfp_t kflags;
126214 struct sk_buff *skb;
127215
128216 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
....@@ -130,7 +218,7 @@
130218 /* Alloc the SKB for vendor_event */
131219 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
132220 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
133
- skb = cfg80211_vendor_event_alloc(wiphy, NULL, len, event_id, kflags);
221
+ skb = cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(dev), len, event_id, kflags);
134222 #else
135223 skb = cfg80211_vendor_event_alloc(wiphy, len, event_id, kflags);
136224 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
....@@ -150,21 +238,25 @@
150238
151239 static int
152240 wl_cfgvendor_send_cmd_reply(struct wiphy *wiphy,
153
- struct net_device *dev, const void *data, int len)
241
+ const void *data, int len)
154242 {
155243 struct sk_buff *skb;
244
+ int err;
156245
157246 /* Alloc the SKB for vendor_event */
158247 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
159248 if (unlikely(!skb)) {
160249 WL_ERR(("skb alloc failed"));
161
- return -ENOMEM;
250
+ err = -ENOMEM;
251
+ goto exit;
162252 }
163253
164254 /* Push the data to the skb */
165255 nla_put_nohdr(skb, len, data);
166
-
167
- return cfg80211_vendor_cmd_reply(skb);
256
+ err = cfg80211_vendor_cmd_reply(skb);
257
+exit:
258
+ WL_DBG(("wl_cfgvendor_send_cmd_reply status %d", err));
259
+ return err;
168260 }
169261
170262 static int
....@@ -177,8 +269,7 @@
177269
178270 reply = dhd_dev_get_feature_set(bcmcfg_to_prmry_ndev(cfg));
179271
180
- err = wl_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
181
- &reply, sizeof(int));
272
+ err = wl_cfgvendor_send_cmd_reply(wiphy, &reply, sizeof(int));
182273 if (unlikely(err))
183274 WL_ERR(("Vendor Command reply failed ret:%d \n", err));
184275
....@@ -192,18 +283,11 @@
192283 int err = 0;
193284 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
194285 struct sk_buff *skb;
195
- int *reply;
196
- int num, mem_needed, i;
286
+ int reply;
287
+ int mem_needed, i;
197288
198
- reply = dhd_dev_get_feature_set_matrix(bcmcfg_to_prmry_ndev(cfg), &num);
199
-
200
- if (!reply) {
201
- WL_ERR(("Could not get feature list matrix\n"));
202
- err = -EINVAL;
203
- return err;
204
- }
205
- mem_needed = VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * num) +
206
- ATTRIBUTE_U32_LEN;
289
+ mem_needed = VENDOR_REPLY_OVERHEAD +
290
+ (ATTRIBUTE_U32_LEN * MAX_FEATURE_SET_CONCURRRENT_GROUPS) + ATTRIBUTE_U32_LEN;
207291
208292 /* Alloc the SKB for vendor_event */
209293 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
....@@ -213,74 +297,172 @@
213297 goto exit;
214298 }
215299
216
- nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, num);
217
- for (i = 0; i < num; i++) {
218
- nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_FEATURE_SET, reply[i]);
300
+ err = nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
301
+ MAX_FEATURE_SET_CONCURRRENT_GROUPS);
302
+ if (unlikely(err)) {
303
+ kfree_skb(skb);
304
+ goto exit;
305
+ }
306
+ for (i = 0; i < MAX_FEATURE_SET_CONCURRRENT_GROUPS; i++) {
307
+ reply = dhd_dev_get_feature_set_matrix(bcmcfg_to_prmry_ndev(cfg), i);
308
+ if (reply != WIFI_FEATURE_INVALID) {
309
+ err = nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_FEATURE_SET,
310
+ reply);
311
+ if (unlikely(err)) {
312
+ kfree_skb(skb);
313
+ goto exit;
314
+ }
315
+ }
219316 }
220317
221318 err = cfg80211_vendor_cmd_reply(skb);
222319
223
- if (unlikely(err))
320
+ if (unlikely(err)) {
224321 WL_ERR(("Vendor Command reply failed ret:%d \n", err));
225
-
322
+ }
226323 exit:
227
- kfree(reply);
228324 return err;
229325 }
230326
231327 static int
232
-wl_cfgvendor_set_rand_mac_oui(struct wiphy *wiphy,
328
+wl_cfgvendor_set_pno_rand_mac_oui(struct wiphy *wiphy,
233329 struct wireless_dev *wdev, const void *data, int len)
234330 {
235
- int err = 0;
331
+ int err = -EINVAL;
236332 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
237333 int type;
238
- uint8 random_mac_oui[DOT11_OUI_LEN];
334
+
335
+ if (!data) {
336
+ WL_ERR(("data is not available\n"));
337
+ goto exit;
338
+ }
339
+
340
+ if (len <= 0) {
341
+ WL_ERR(("invalid len %d\n", len));
342
+ goto exit;
343
+ }
239344
240345 type = nla_type(data);
241346
242
- if (type == ANDR_WIFI_ATTRIBUTE_RANDOM_MAC_OUI) {
243
- memcpy(random_mac_oui, nla_data(data), DOT11_OUI_LEN);
244
-
245
- err = dhd_dev_cfg_rand_mac_oui(bcmcfg_to_prmry_ndev(cfg), random_mac_oui);
347
+ if (type == ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI) {
348
+ if (nla_len(data) != DOT11_OUI_LEN) {
349
+ WL_ERR(("nla_len not matched.\n"));
350
+ goto exit;
351
+ }
352
+ err = dhd_dev_cfg_rand_mac_oui(bcmcfg_to_prmry_ndev(cfg), nla_data(data));
246353
247354 if (unlikely(err))
248355 WL_ERR(("Bad OUI, could not set:%d \n", err));
249
-
250
- } else {
251
- err = -1;
252356 }
253
-
357
+exit:
254358 return err;
255359 }
256
-
257360 #ifdef CUSTOM_FORCE_NODFS_FLAG
258361 static int
259362 wl_cfgvendor_set_nodfs_flag(struct wiphy *wiphy,
260363 struct wireless_dev *wdev, const void *data, int len)
261364 {
262
- int err = 0;
365
+ int err = -EINVAL;
263366 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
264367 int type;
265368 u32 nodfs;
369
+
370
+ if (!data) {
371
+ WL_ERR(("data is not available\n"));
372
+ return -EINVAL;
373
+ }
374
+
375
+ if (len <= 0) {
376
+ WL_ERR(("invalid len %d\n", len));
377
+ return -EINVAL;
378
+ }
266379
267380 type = nla_type(data);
268381 if (type == ANDR_WIFI_ATTRIBUTE_NODFS_SET) {
269382 nodfs = nla_get_u32(data);
270383 err = dhd_dev_set_nodfs(bcmcfg_to_prmry_ndev(cfg), nodfs);
271
- } else {
272
- err = -1;
273384 }
385
+
274386 return err;
275387 }
276388 #endif /* CUSTOM_FORCE_NODFS_FLAG */
389
+
390
+static int
391
+wl_cfgvendor_set_country(struct wiphy *wiphy,
392
+ struct wireless_dev *wdev, const void *data, int len)
393
+{
394
+ int err = BCME_ERROR, rem, type;
395
+ char country_code[WLC_CNTRY_BUF_SZ] = {0};
396
+ const struct nlattr *iter;
397
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
398
+ struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
399
+
400
+ nla_for_each_attr(iter, data, len, rem) {
401
+ type = nla_type(iter);
402
+ switch (type) {
403
+ case ANDR_WIFI_ATTRIBUTE_COUNTRY:
404
+ err = memcpy_s(country_code, WLC_CNTRY_BUF_SZ,
405
+ nla_data(iter), nla_len(iter));
406
+ if (err) {
407
+ WL_ERR(("Failed to copy country code: %d\n", err));
408
+ return err;
409
+ }
410
+ break;
411
+ default:
412
+ WL_ERR(("Unknown type: %d\n", type));
413
+ return err;
414
+ }
415
+ }
416
+ /* country code is unique for dongle..hence using primary interface. */
417
+ err = wl_cfg80211_set_country_code(primary_ndev, country_code, true, true, -1);
418
+ if (err < 0) {
419
+ WL_ERR(("Set country failed ret:%d\n", err));
420
+ }
421
+
422
+ return err;
423
+}
424
+
425
+#ifdef GSCAN_SUPPORT
426
+static int
427
+wl_cfgvendor_gscan_get_capabilities(struct wiphy *wiphy,
428
+ struct wireless_dev *wdev, const void *data, int len)
429
+{
430
+ int err = 0;
431
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
432
+ dhd_pno_gscan_capabilities_t *reply = NULL;
433
+ uint32 reply_len = 0;
434
+
435
+ reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
436
+ DHD_PNO_GET_CAPABILITIES, NULL, &reply_len);
437
+ if (!reply) {
438
+ WL_ERR(("Could not get capabilities\n"));
439
+ err = -EINVAL;
440
+ return err;
441
+ }
442
+
443
+ err = wl_cfgvendor_send_cmd_reply(wiphy, reply, reply_len);
444
+ if (unlikely(err)) {
445
+ WL_ERR(("Vendor Command reply failed ret:%d \n", err));
446
+ }
447
+
448
+ MFREE(cfg->osh, reply, reply_len);
449
+ return err;
450
+}
451
+#else
452
+static int
453
+wl_cfgvendor_gscan_get_capabilities(struct wiphy *wiphy,
454
+ struct wireless_dev *wdev, const void *data, int len)
455
+{
456
+ return WIFI_ERROR_NOT_SUPPORTED;
457
+}
458
+#endif /* GSCAN_SUPPORT */
277459
278460 #ifdef GSCAN_SUPPORT
279461 int
280462 wl_cfgvendor_send_hotlist_event(struct wiphy *wiphy,
281463 struct net_device *dev, void *data, int len, wl_vendor_event_t event)
282464 {
283
- u16 kflags;
465
+ gfp_t kflags;
284466 const void *ptr;
285467 struct sk_buff *skb;
286468 int malloc_len, total, iter_cnt_to_send, cnt;
....@@ -301,7 +483,8 @@
301483 /* Alloc the SKB for vendor_event */
302484 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
303485 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
304
- skb = cfg80211_vendor_event_alloc(wiphy, NULL, malloc_len, event, kflags);
486
+ skb = cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(dev),
487
+ malloc_len, event, kflags);
305488 #else
306489 skb = cfg80211_vendor_event_alloc(wiphy, malloc_len, event, kflags);
307490 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
....@@ -337,92 +520,13 @@
337520 }
338521
339522 static int
340
-wl_cfgvendor_gscan_get_capabilities(struct wiphy *wiphy,
341
- struct wireless_dev *wdev, const void *data, int len)
342
-{
343
- int err = 0;
344
- struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
345
- dhd_pno_gscan_capabilities_t *reply = NULL;
346
- uint32 reply_len = 0;
347
-
348
-
349
- reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
350
- DHD_PNO_GET_CAPABILITIES, NULL, &reply_len);
351
- if (!reply) {
352
- WL_ERR(("Could not get capabilities\n"));
353
- err = -EINVAL;
354
- return err;
355
- }
356
-
357
- err = wl_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
358
- reply, reply_len);
359
-
360
- if (unlikely(err)) {
361
- WL_ERR(("Vendor Command reply failed ret:%d \n", err));
362
- }
363
-
364
- kfree(reply);
365
- return err;
366
-}
367
-
368
-static int
369
-wl_cfgvendor_gscan_get_channel_list(struct wiphy *wiphy,
370
- struct wireless_dev *wdev, const void *data, int len)
371
-{
372
- int err = 0, type, band;
373
- struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
374
- uint16 *reply = NULL;
375
- uint32 reply_len = 0, num_channels, mem_needed;
376
- struct sk_buff *skb;
377
-
378
- type = nla_type(data);
379
-
380
- if (type == GSCAN_ATTRIBUTE_BAND) {
381
- band = nla_get_u32(data);
382
- } else {
383
- return -EINVAL;
384
- }
385
-
386
- reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
387
- DHD_PNO_GET_CHANNEL_LIST, &band, &reply_len);
388
-
389
- if (!reply) {
390
- WL_ERR(("Could not get channel list\n"));
391
- err = -EINVAL;
392
- return err;
393
- }
394
- num_channels = reply_len/ sizeof(uint32);
395
- mem_needed = reply_len + VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * 2);
396
-
397
- /* Alloc the SKB for vendor_event */
398
- skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
399
- if (unlikely(!skb)) {
400
- WL_ERR(("skb alloc failed"));
401
- err = -ENOMEM;
402
- goto exit;
403
- }
404
-
405
- nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channels);
406
- nla_put(skb, GSCAN_ATTRIBUTE_CHANNEL_LIST, reply_len, reply);
407
-
408
- err = cfg80211_vendor_cmd_reply(skb);
409
-
410
- if (unlikely(err)) {
411
- WL_ERR(("Vendor Command reply failed ret:%d \n", err));
412
- }
413
-exit:
414
- kfree(reply);
415
- return err;
416
-}
417
-
418
-static int
419523 wl_cfgvendor_gscan_get_batch_results(struct wiphy *wiphy,
420524 struct wireless_dev *wdev, const void *data, int len)
421525 {
422526 int err = 0;
423527 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
424528 gscan_results_cache_t *results, *iter;
425
- uint32 reply_len, complete = 1;
529
+ uint32 reply_len, is_done = 1;
426530 int32 mem_needed, num_results_iter;
427531 wifi_gscan_result_t *ptr;
428532 uint16 num_scan_ids, num_results;
....@@ -443,8 +547,7 @@
443547
444548 if (!results) {
445549 WL_ERR(("No results to send %d\n", err));
446
- err = wl_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
447
- results, 0);
550
+ err = wl_cfgvendor_send_cmd_reply(wiphy, results, 0);
448551
449552 if (unlikely(err))
450553 WL_ERR(("Vendor Command reply failed ret:%d \n", err));
....@@ -461,7 +564,7 @@
461564 mem_needed = (int32)NLMSG_DEFAULT_SIZE;
462565 }
463566
464
- WL_TRACE(("complete %d mem_needed %d max_mem %d\n", complete, mem_needed,
567
+ WL_TRACE(("is_done %d mem_needed %d max_mem %d\n", is_done, mem_needed,
465568 (int)NLMSG_DEFAULT_SIZE));
466569 /* Alloc the SKB for vendor_event */
467570 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
....@@ -472,12 +575,19 @@
472575 }
473576 iter = results;
474577 complete_flag = nla_reserve(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE,
475
- sizeof(complete));
578
+ sizeof(is_done));
579
+
580
+ if (unlikely(!complete_flag)) {
581
+ WL_ERR(("complete_flag could not be reserved"));
582
+ kfree_skb(skb);
583
+ dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
584
+ return -ENOMEM;
585
+ }
476586 mem_needed = mem_needed - (SCAN_RESULTS_COMPLETE_FLAG_LEN + VENDOR_REPLY_OVERHEAD);
477587
478588 while (iter) {
479589 num_results_iter = (mem_needed - (int32)GSCAN_BATCH_RESULT_HDR_LEN);
480
- num_results_iter /= ((int32)sizeof(wifi_gscan_result_t));
590
+ num_results_iter /= (int32)sizeof(wifi_gscan_result_t);
481591 if (num_results_iter <= 0 ||
482592 ((iter->tot_count - iter->tot_consumed) > num_results_iter)) {
483593 break;
....@@ -485,30 +595,52 @@
485595 scan_hdr = nla_nest_start(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS);
486596 /* no more room? we are done then (for now) */
487597 if (scan_hdr == NULL) {
488
- complete = 0;
598
+ is_done = 0;
489599 break;
490600 }
491
- nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_ID, iter->scan_id);
492
- nla_put_u8(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, iter->flag);
601
+ err = nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_ID, iter->scan_id);
602
+ if (unlikely(err)) {
603
+ goto fail;
604
+ }
605
+ err = nla_put_u8(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, iter->flag);
606
+ if (unlikely(err)) {
607
+ goto fail;
608
+ }
609
+ err = nla_put_u32(skb, GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK, iter->scan_ch_bucket);
610
+ if (unlikely(err)) {
611
+ goto fail;
612
+ }
493613 num_results_iter = iter->tot_count - iter->tot_consumed;
494614
495
- nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num_results_iter);
615
+ err = nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num_results_iter);
616
+ if (unlikely(err)) {
617
+ goto fail;
618
+ }
496619 if (num_results_iter) {
497620 ptr = &iter->results[iter->tot_consumed];
498
- iter->tot_consumed += num_results_iter;
499
- nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS,
621
+ err = nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS,
500622 num_results_iter * sizeof(wifi_gscan_result_t), ptr);
623
+ if (unlikely(err)) {
624
+ goto fail;
625
+ }
626
+ iter->tot_consumed += num_results_iter;
501627 }
502628 nla_nest_end(skb, scan_hdr);
503629 mem_needed -= GSCAN_BATCH_RESULT_HDR_LEN +
504
- (num_results_iter * sizeof(wifi_gscan_result_t));
630
+ (num_results_iter * sizeof(wifi_gscan_result_t));
505631 iter = iter->next;
506632 }
507
- /* Returns TRUE if all result consumed */
508
- complete = dhd_dev_gscan_batch_cache_cleanup(bcmcfg_to_prmry_ndev(cfg));
509
- memcpy(nla_data(complete_flag), &complete, sizeof(complete));
633
+ /* Cleans up consumed results and returns TRUE if all results are consumed */
634
+ is_done = dhd_dev_gscan_batch_cache_cleanup(bcmcfg_to_prmry_ndev(cfg));
635
+ memcpy(nla_data(complete_flag), &is_done, sizeof(is_done));
510636 dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
511637 return cfg80211_vendor_cmd_reply(skb);
638
+fail:
639
+ /* Free up consumed results which will now not be sent */
640
+ (void)dhd_dev_gscan_batch_cache_cleanup(bcmcfg_to_prmry_ndev(cfg));
641
+ kfree_skb(skb);
642
+ dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
643
+ return err;
512644 }
513645
514646 static int
....@@ -541,7 +673,6 @@
541673 return -EINVAL;
542674 }
543675
544
-
545676 }
546677
547678 static int
....@@ -552,6 +683,16 @@
552683 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
553684 int type;
554685 bool real_time = FALSE;
686
+
687
+ if (!data) {
688
+ WL_ERR(("data is not available\n"));
689
+ return -EINVAL;
690
+ }
691
+
692
+ if (len <= 0) {
693
+ WL_ERR(("invalid len %d\n", len));
694
+ return -EINVAL;
695
+ }
555696
556697 type = nla_type(data);
557698
....@@ -572,18 +713,109 @@
572713 }
573714
574715 static int
575
-wl_cfgvendor_set_scan_cfg(struct wiphy *wiphy,
576
- struct wireless_dev *wdev, const void *data, int len)
716
+wl_cfgvendor_set_scan_cfg_bucket(const struct nlattr *prev,
717
+ gscan_scan_params_t *scan_param, int num)
718
+{
719
+ struct dhd_pno_gscan_channel_bucket *ch_bucket;
720
+ int k = 0;
721
+ int type, err = 0, rem;
722
+ const struct nlattr *cur, *next;
723
+
724
+ nla_for_each_nested(cur, prev, rem) {
725
+ type = nla_type(cur);
726
+ ch_bucket = scan_param->channel_bucket;
727
+ switch (type) {
728
+ case GSCAN_ATTRIBUTE_BUCKET_ID:
729
+ break;
730
+ case GSCAN_ATTRIBUTE_BUCKET_PERIOD:
731
+ if (nla_len(cur) != sizeof(uint32)) {
732
+ err = -EINVAL;
733
+ goto exit;
734
+ }
735
+
736
+ ch_bucket[num].bucket_freq_multiple =
737
+ nla_get_u32(cur) / MSEC_PER_SEC;
738
+ break;
739
+ case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS:
740
+ if (nla_len(cur) != sizeof(uint32)) {
741
+ err = -EINVAL;
742
+ goto exit;
743
+ }
744
+ ch_bucket[num].num_channels = nla_get_u32(cur);
745
+ if (ch_bucket[num].num_channels >
746
+ GSCAN_MAX_CHANNELS_IN_BUCKET) {
747
+ WL_ERR(("channel range:%d,bucket:%d\n",
748
+ ch_bucket[num].num_channels,
749
+ num));
750
+ err = -EINVAL;
751
+ goto exit;
752
+ }
753
+ break;
754
+ case GSCAN_ATTRIBUTE_BUCKET_CHANNELS:
755
+ nla_for_each_nested(next, cur, rem) {
756
+ if (k >= GSCAN_MAX_CHANNELS_IN_BUCKET)
757
+ break;
758
+ if (nla_len(next) != sizeof(uint32)) {
759
+ err = -EINVAL;
760
+ goto exit;
761
+ }
762
+ ch_bucket[num].chan_list[k] = nla_get_u32(next);
763
+ k++;
764
+ }
765
+ break;
766
+ case GSCAN_ATTRIBUTE_BUCKETS_BAND:
767
+ if (nla_len(cur) != sizeof(uint32)) {
768
+ err = -EINVAL;
769
+ goto exit;
770
+ }
771
+ ch_bucket[num].band = (uint16)nla_get_u32(cur);
772
+ break;
773
+ case GSCAN_ATTRIBUTE_REPORT_EVENTS:
774
+ if (nla_len(cur) != sizeof(uint32)) {
775
+ err = -EINVAL;
776
+ goto exit;
777
+ }
778
+ ch_bucket[num].report_flag = (uint8)nla_get_u32(cur);
779
+ break;
780
+ case GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT:
781
+ if (nla_len(cur) != sizeof(uint32)) {
782
+ err = -EINVAL;
783
+ goto exit;
784
+ }
785
+ ch_bucket[num].repeat = (uint16)nla_get_u32(cur);
786
+ break;
787
+ case GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD:
788
+ if (nla_len(cur) != sizeof(uint32)) {
789
+ err = -EINVAL;
790
+ goto exit;
791
+ }
792
+ ch_bucket[num].bucket_max_multiple =
793
+ nla_get_u32(cur) / MSEC_PER_SEC;
794
+ break;
795
+ default:
796
+ WL_ERR(("unknown attr type:%d\n", type));
797
+ err = -EINVAL;
798
+ goto exit;
799
+ }
800
+ }
801
+
802
+exit:
803
+ return err;
804
+}
805
+
806
+static int
807
+wl_cfgvendor_set_scan_cfg(struct wiphy *wiphy, struct wireless_dev *wdev,
808
+ const void *data, int len)
577809 {
578810 int err = 0;
579811 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
580812 gscan_scan_params_t *scan_param;
581813 int j = 0;
582
- int type, tmp, tmp1, tmp2, k = 0;
583
- const struct nlattr *iter, *iter1, *iter2;
584
- struct dhd_pno_gscan_channel_bucket *ch_bucket;
814
+ int type, tmp;
815
+ const struct nlattr *iter;
585816
586
- scan_param = kzalloc(sizeof(gscan_scan_params_t), GFP_KERNEL);
817
+ scan_param = (gscan_scan_params_t *)MALLOCZ(cfg->osh,
818
+ sizeof(gscan_scan_params_t));
587819 if (!scan_param) {
588820 WL_ERR(("Could not set GSCAN scan cfg, mem alloc failure\n"));
589821 err = -EINVAL;
....@@ -601,10 +833,25 @@
601833
602834 switch (type) {
603835 case GSCAN_ATTRIBUTE_BASE_PERIOD:
604
- scan_param->scan_fr = nla_get_u32(iter)/1000;
836
+ if (nla_len(iter) != sizeof(uint32)) {
837
+ err = -EINVAL;
838
+ goto exit;
839
+ }
840
+ scan_param->scan_fr = nla_get_u32(iter) / MSEC_PER_SEC;
605841 break;
606842 case GSCAN_ATTRIBUTE_NUM_BUCKETS:
843
+ if (nla_len(iter) != sizeof(uint32)) {
844
+ err = -EINVAL;
845
+ goto exit;
846
+ }
607847 scan_param->nchannel_buckets = nla_get_u32(iter);
848
+ if (scan_param->nchannel_buckets >=
849
+ GSCAN_MAX_CH_BUCKETS) {
850
+ WL_ERR(("ncha_buck out of range %d\n",
851
+ scan_param->nchannel_buckets));
852
+ err = -EINVAL;
853
+ goto exit;
854
+ }
608855 break;
609856 case GSCAN_ATTRIBUTE_CH_BUCKET_1:
610857 case GSCAN_ATTRIBUTE_CH_BUCKET_2:
....@@ -613,69 +860,30 @@
613860 case GSCAN_ATTRIBUTE_CH_BUCKET_5:
614861 case GSCAN_ATTRIBUTE_CH_BUCKET_6:
615862 case GSCAN_ATTRIBUTE_CH_BUCKET_7:
616
- nla_for_each_nested(iter1, iter, tmp1) {
617
- type = nla_type(iter1);
618
- ch_bucket =
619
- scan_param->channel_bucket;
620
-
621
- switch (type) {
622
- case GSCAN_ATTRIBUTE_BUCKET_ID:
623
- break;
624
- case GSCAN_ATTRIBUTE_BUCKET_PERIOD:
625
- ch_bucket[j].bucket_freq_multiple =
626
- nla_get_u32(iter1)/1000;
627
- break;
628
- case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS:
629
- ch_bucket[j].num_channels =
630
- nla_get_u32(iter1);
631
- break;
632
- case GSCAN_ATTRIBUTE_BUCKET_CHANNELS:
633
- nla_for_each_nested(iter2, iter1, tmp2) {
634
- if (k >=
635
- GSCAN_MAX_CHANNELS_IN_BUCKET)
636
- break;
637
- ch_bucket[j].chan_list[k] =
638
- nla_get_u32(iter2);
639
- k++;
640
- }
641
- k = 0;
642
- break;
643
- case GSCAN_ATTRIBUTE_BUCKETS_BAND:
644
- ch_bucket[j].band = (uint16)
645
- nla_get_u32(iter1);
646
- break;
647
- case GSCAN_ATTRIBUTE_REPORT_EVENTS:
648
- ch_bucket[j].report_flag = (uint8)
649
- nla_get_u32(iter1);
650
- break;
651
- case GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT:
652
- ch_bucket[j].repeat = (uint16)
653
- nla_get_u32(iter1);
654
- break;
655
- case GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD:
656
- ch_bucket[j].bucket_max_multiple =
657
- nla_get_u32(iter1)/1000;
658
- default:
659
- WL_ERR(("bucket attribute type error %d\n",
660
- type));
661
- break;
662
- }
863
+ err = wl_cfgvendor_set_scan_cfg_bucket(iter, scan_param, j);
864
+ if (err < 0) {
865
+ WL_ERR(("set_scan_cfg_buck error:%d\n", err));
866
+ goto exit;
663867 }
664868 j++;
665869 break;
666870 default:
667871 WL_ERR(("Unknown type %d\n", type));
668
- break;
872
+ err = -EINVAL;
873
+ goto exit;
669874 }
670875 }
671876
672
- if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
673
- DHD_PNO_SCAN_CFG_ID, scan_param, 0) < 0) {
877
+ err = dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
878
+ DHD_PNO_SCAN_CFG_ID, scan_param, FALSE);
879
+
880
+ if (err < 0) {
674881 WL_ERR(("Could not set GSCAN scan cfg\n"));
675882 err = -EINVAL;
676883 }
677884
678
- kfree(scan_param);
885
+exit:
886
+ MFREE(cfg->osh, scan_param, sizeof(gscan_scan_params_t));
679887 return err;
680888
681889 }
....@@ -688,70 +896,143 @@
688896 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
689897 gscan_hotlist_scan_params_t *hotlist_params;
690898 int tmp, tmp1, tmp2, type, j = 0, dummy;
691
- const struct nlattr *outer, *inner, *iter;
692
- uint8 flush = 0;
899
+ const struct nlattr *outer, *inner = NULL, *iter;
900
+ bool flush = FALSE;
693901 struct bssid_t *pbssid;
694902
695
- hotlist_params = (gscan_hotlist_scan_params_t *)kzalloc(len, GFP_KERNEL);
903
+ BCM_REFERENCE(dummy);
904
+
905
+ if (len < sizeof(*hotlist_params) || len >= WLC_IOCTL_MAXLEN) {
906
+ WL_ERR(("buffer length :%d wrong - bail out.\n", len));
907
+ return -EINVAL;
908
+ }
909
+
910
+ hotlist_params = (gscan_hotlist_scan_params_t *)MALLOCZ(cfg->osh,
911
+ sizeof(*hotlist_params)
912
+ + (sizeof(struct bssid_t) * (PFN_SWC_MAX_NUM_APS - 1)));
913
+
696914 if (!hotlist_params) {
697
- WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes \n", len));
915
+ WL_ERR(("Cannot Malloc memory.\n"));
698916 return -ENOMEM;
699917 }
700918
701919 hotlist_params->lost_ap_window = GSCAN_LOST_AP_WINDOW_DEFAULT;
920
+
702921 nla_for_each_attr(iter, data, len, tmp2) {
703922 type = nla_type(iter);
704923 switch (type) {
705
- case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS:
706
- pbssid = hotlist_params->bssid;
707
- nla_for_each_nested(outer, iter, tmp) {
708
- nla_for_each_nested(inner, outer, tmp1) {
709
- type = nla_type(inner);
710
-
711
- switch (type) {
712
- case GSCAN_ATTRIBUTE_BSSID:
713
- memcpy(&(pbssid[j].macaddr),
714
- nla_data(inner), ETHER_ADDR_LEN);
715
- break;
716
- case GSCAN_ATTRIBUTE_RSSI_LOW:
717
- pbssid[j].rssi_reporting_threshold =
718
- (int8) nla_get_u8(inner);
719
- break;
720
- case GSCAN_ATTRIBUTE_RSSI_HIGH:
721
- dummy = (int8) nla_get_u8(inner);
722
- break;
723
- default:
724
- WL_ERR(("ATTR unknown %d\n",
725
- type));
726
- break;
727
- }
728
- }
729
- j++;
730
- }
731
- hotlist_params->nbssid = j;
732
- break;
733
- case GSCAN_ATTRIBUTE_HOTLIST_FLUSH:
734
- flush = nla_get_u8(iter);
735
- break;
736
- case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
737
- hotlist_params->lost_ap_window = nla_get_u32(iter);
738
- break;
739
- default:
740
- WL_ERR(("Unknown type %d\n", type));
741
- break;
924
+ case GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT:
925
+ if (nla_len(iter) != sizeof(uint32)) {
926
+ WL_DBG(("type:%d length:%d not matching.\n",
927
+ type, nla_len(iter)));
928
+ err = -EINVAL;
929
+ goto exit;
742930 }
931
+ hotlist_params->nbssid = (uint16)nla_get_u32(iter);
932
+ if ((hotlist_params->nbssid == 0) ||
933
+ (hotlist_params->nbssid > PFN_SWC_MAX_NUM_APS)) {
934
+ WL_ERR(("nbssid:%d exceed limit.\n",
935
+ hotlist_params->nbssid));
936
+ err = -EINVAL;
937
+ goto exit;
938
+ }
939
+ break;
940
+ case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS:
941
+ if (hotlist_params->nbssid == 0) {
942
+ WL_ERR(("nbssid not retrieved.\n"));
943
+ err = -EINVAL;
944
+ goto exit;
945
+ }
946
+ pbssid = hotlist_params->bssid;
947
+ nla_for_each_nested(outer, iter, tmp) {
948
+ if (j >= hotlist_params->nbssid)
949
+ break;
950
+ nla_for_each_nested(inner, outer, tmp1) {
951
+ type = nla_type(inner);
952
+
953
+ switch (type) {
954
+ case GSCAN_ATTRIBUTE_BSSID:
955
+ if (nla_len(inner) != sizeof(pbssid[j].macaddr)) {
956
+ WL_ERR(("type:%d length:%d not matching.\n",
957
+ type, nla_len(inner)));
958
+ err = -EINVAL;
959
+ goto exit;
960
+ }
961
+ memcpy(
962
+ &(pbssid[j].macaddr),
963
+ nla_data(inner),
964
+ sizeof(pbssid[j].macaddr));
965
+ break;
966
+ case GSCAN_ATTRIBUTE_RSSI_LOW:
967
+ if (nla_len(inner) != sizeof(uint8)) {
968
+ WL_ERR(("type:%d length:%d not matching.\n",
969
+ type, nla_len(inner)));
970
+ err = -EINVAL;
971
+ goto exit;
972
+ }
973
+ pbssid[j].rssi_reporting_threshold =
974
+ (int8)nla_get_u8(inner);
975
+ break;
976
+ case GSCAN_ATTRIBUTE_RSSI_HIGH:
977
+ if (nla_len(inner) != sizeof(uint8)) {
978
+ WL_ERR(("type:%d length:%d not matching.\n",
979
+ type, nla_len(inner)));
980
+ err = -EINVAL;
981
+ goto exit;
982
+ }
983
+ dummy = (int8)nla_get_u8(inner);
984
+ WL_DBG(("dummy %d\n", dummy));
985
+ break;
986
+ default:
987
+ WL_ERR(("ATTR unknown %d\n", type));
988
+ err = -EINVAL;
989
+ goto exit;
990
+ }
991
+ }
992
+ j++;
993
+ }
994
+ if (j != hotlist_params->nbssid) {
995
+ WL_ERR(("bssid_cnt:%d != nbssid:%d.\n", j,
996
+ hotlist_params->nbssid));
997
+ err = -EINVAL;
998
+ goto exit;
999
+ }
1000
+ break;
1001
+ case GSCAN_ATTRIBUTE_HOTLIST_FLUSH:
1002
+ if (nla_len(iter) != sizeof(uint8)) {
1003
+ WL_ERR(("type:%d length:%d not matching.\n",
1004
+ type, nla_len(iter)));
1005
+ err = -EINVAL;
1006
+ goto exit;
1007
+ }
1008
+ flush = nla_get_u8(iter);
1009
+ break;
1010
+ case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
1011
+ if (nla_len(iter) != sizeof(uint32)) {
1012
+ WL_ERR(("type:%d length:%d not matching.\n",
1013
+ type, nla_len(iter)));
1014
+ err = -EINVAL;
1015
+ goto exit;
1016
+ }
1017
+ hotlist_params->lost_ap_window = (uint16)nla_get_u32(iter);
1018
+ break;
1019
+ default:
1020
+ WL_ERR(("Unknown type %d\n", type));
1021
+ err = -EINVAL;
1022
+ goto exit;
1023
+ }
7431024
7441025 }
7451026
7461027 if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
747
- DHD_PNO_GEOFENCE_SCAN_CFG_ID,
748
- hotlist_params, flush) < 0) {
749
- WL_ERR(("Could not set GSCAN HOTLIST cfg\n"));
1028
+ DHD_PNO_GEOFENCE_SCAN_CFG_ID, hotlist_params, flush) < 0) {
1029
+ WL_ERR(("Could not set GSCAN HOTLIST cfg error: %d\n", err));
7501030 err = -EINVAL;
7511031 goto exit;
7521032 }
7531033 exit:
754
- kfree(hotlist_params);
1034
+ MFREE(cfg->osh, hotlist_params, sizeof(*hotlist_params)
1035
+ + (sizeof(struct bssid_t) * (PFN_SWC_MAX_NUM_APS - 1)));
7551036 return err;
7561037 }
7571038
....@@ -760,21 +1041,22 @@
7601041 {
7611042 int err = 0;
7621043 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
763
- dhd_epno_params_t *epno_params;
764
- int tmp, tmp1, tmp2, type, num = 0;
1044
+ dhd_pno_ssid_t *ssid_elem = NULL;
1045
+ int tmp, tmp1, tmp2, type = 0, num = 0;
7651046 const struct nlattr *outer, *inner, *iter;
766
- uint8 flush = 0, i = 0;
767
- uint16 num_visible_ssid = 0;
1047
+ uint8 flush = FALSE, i = 0;
1048
+ wl_ssid_ext_params_t params;
7681049
7691050 nla_for_each_attr(iter, data, len, tmp2) {
7701051 type = nla_type(iter);
7711052 switch (type) {
7721053 case GSCAN_ATTRIBUTE_EPNO_SSID_LIST:
7731054 nla_for_each_nested(outer, iter, tmp) {
774
- epno_params = (dhd_epno_params_t *)
775
- dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
776
- DHD_PNO_GET_EPNO_SSID_ELEM, NULL, &num);
777
- if (!epno_params) {
1055
+ ssid_elem = (dhd_pno_ssid_t *)
1056
+ dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
1057
+ DHD_PNO_GET_NEW_EPNO_SSID_ELEM,
1058
+ NULL, &num);
1059
+ if (!ssid_elem) {
7781060 WL_ERR(("Failed to get SSID LIST buffer\n"));
7791061 err = -ENOMEM;
7801062 goto exit;
....@@ -785,54 +1067,90 @@
7851067
7861068 switch (type) {
7871069 case GSCAN_ATTRIBUTE_EPNO_SSID:
788
- memcpy(epno_params->ssid,
1070
+ memcpy(ssid_elem->SSID,
7891071 nla_data(inner),
7901072 DOT11_MAX_SSID_LEN);
7911073 break;
7921074 case GSCAN_ATTRIBUTE_EPNO_SSID_LEN:
793
- len = nla_get_u8(inner);
794
- if (len < DOT11_MAX_SSID_LEN) {
795
- epno_params->ssid_len = len;
796
- } else {
1075
+ ssid_elem->SSID_len =
1076
+ nla_get_u32(inner);
1077
+ if (ssid_elem->SSID_len >
1078
+ DOT11_MAX_SSID_LEN) {
7971079 WL_ERR(("SSID too"
798
- "long %d\n", len));
1080
+ "long %d\n",
1081
+ ssid_elem->SSID_len));
7991082 err = -EINVAL;
1083
+ MFREE(cfg->osh, ssid_elem,
1084
+ num);
8001085 goto exit;
8011086 }
8021087 break;
803
- case GSCAN_ATTRIBUTE_EPNO_RSSI:
804
- epno_params->rssi_thresh =
805
- (int8) nla_get_u32(inner);
806
- break;
8071088 case GSCAN_ATTRIBUTE_EPNO_FLAGS:
808
- epno_params->flags =
809
- nla_get_u8(inner);
810
- if (!(epno_params->flags &
811
- DHD_PNO_USE_SSID))
812
- num_visible_ssid++;
1089
+ ssid_elem->flags =
1090
+ nla_get_u32(inner);
1091
+ ssid_elem->hidden =
1092
+ ((ssid_elem->flags &
1093
+ DHD_EPNO_HIDDEN_SSID) != 0);
8131094 break;
8141095 case GSCAN_ATTRIBUTE_EPNO_AUTH:
815
- epno_params->auth =
816
- nla_get_u8(inner);
1096
+ ssid_elem->wpa_auth =
1097
+ nla_get_u32(inner);
8171098 break;
8181099 }
8191100 }
1101
+ if (!ssid_elem->SSID_len) {
1102
+ WL_ERR(("Broadcast SSID is illegal for ePNO\n"));
1103
+ err = -EINVAL;
1104
+ MFREE(cfg->osh, ssid_elem, num);
1105
+ goto exit;
1106
+ }
1107
+ dhd_pno_translate_epno_fw_flags(&ssid_elem->flags);
1108
+ dhd_pno_set_epno_auth_flag(&ssid_elem->wpa_auth);
1109
+ MFREE(cfg->osh, ssid_elem, num);
8201110 }
8211111 break;
8221112 case GSCAN_ATTRIBUTE_EPNO_SSID_NUM:
8231113 num = nla_get_u8(iter);
8241114 break;
8251115 case GSCAN_ATTRIBUTE_EPNO_FLUSH:
826
- flush = nla_get_u8(iter);
1116
+ flush = (bool)nla_get_u32(iter);
1117
+ /* Flush attribute is expected before any ssid attribute */
1118
+ if (i && flush) {
1119
+ WL_ERR(("Bad attributes\n"));
1120
+ err = -EINVAL;
1121
+ goto exit;
1122
+ }
1123
+ /* Need to flush driver and FW cfg */
8271124 dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
828
- DHD_PNO_EPNO_CFG_ID, NULL, flush);
1125
+ DHD_PNO_EPNO_CFG_ID, NULL, flush);
1126
+ dhd_dev_flush_fw_epno(bcmcfg_to_prmry_ndev(cfg));
1127
+ break;
1128
+ case GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR:
1129
+ params.min5G_rssi = nla_get_s8(iter);
1130
+ break;
1131
+ case GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR:
1132
+ params.min2G_rssi = nla_get_s8(iter);
1133
+ break;
1134
+ case GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX:
1135
+ params.init_score_max = nla_get_s16(iter);
1136
+ break;
1137
+ case GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS:
1138
+ params.cur_bssid_bonus = nla_get_s16(iter);
1139
+ break;
1140
+ case GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS:
1141
+ params.same_ssid_bonus = nla_get_s16(iter);
1142
+ break;
1143
+ case GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS:
1144
+ params.secure_bonus = nla_get_s16(iter);
1145
+ break;
1146
+ case GSCAN_ATTRIBUTE_EPNO_5G_BONUS:
1147
+ params.band_5g_bonus = nla_get_s16(iter);
8291148 break;
8301149 default:
8311150 WL_ERR(("%s: No such attribute %d\n", __FUNCTION__, type));
8321151 err = -EINVAL;
8331152 goto exit;
8341153 }
835
-
8361154 }
8371155 if (i != num) {
8381156 WL_ERR(("%s: num_ssid %d does not match ssids sent %d\n", __FUNCTION__,
....@@ -841,9 +1159,16 @@
8411159 }
8421160 exit:
8431161 /* Flush all configs if error condition */
844
- flush = (err < 0) ? TRUE: FALSE;
845
- dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
846
- DHD_PNO_EPNO_CFG_ID, &num_visible_ssid, flush);
1162
+ if (err < 0) {
1163
+ dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
1164
+ DHD_PNO_EPNO_CFG_ID, NULL, TRUE);
1165
+ dhd_dev_flush_fw_epno(bcmcfg_to_prmry_ndev(cfg));
1166
+ } else if (type != GSCAN_ATTRIBUTE_EPNO_FLUSH) {
1167
+ /* If the last attribute was FLUSH, nothing else to do */
1168
+ dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
1169
+ DHD_PNO_EPNO_PARAMS_ID, &params, FALSE);
1170
+ err = dhd_dev_set_epno(bcmcfg_to_prmry_ndev(cfg));
1171
+ }
8471172 return err;
8481173 }
8491174
....@@ -879,8 +1204,7 @@
8791204 }
8801205
8811206 if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
882
- DHD_PNO_BATCH_SCAN_CFG_ID,
883
- &batch_param, 0) < 0) {
1207
+ DHD_PNO_BATCH_SCAN_CFG_ID, &batch_param, FALSE) < 0) {
8841208 WL_ERR(("Could not set batch cfg\n"));
8851209 err = -EINVAL;
8861210 return err;
....@@ -889,173 +1213,466 @@
8891213 return err;
8901214 }
8911215
1216
+#endif /* GSCAN_SUPPORT */
1217
+#if defined(GSCAN_SUPPORT) || defined(DHD_GET_VALID_CHANNELS)
8921218 static int
893
-wl_cfgvendor_significant_change_cfg(struct wiphy *wiphy,
1219
+wl_cfgvendor_gscan_get_channel_list(struct wiphy *wiphy,
8941220 struct wireless_dev *wdev, const void *data, int len)
8951221 {
896
- int err = 0;
1222
+ int err = 0, type, band;
8971223 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
898
- gscan_swc_params_t *significant_params;
899
- int tmp, tmp1, tmp2, type, j = 0;
900
- const struct nlattr *outer, *inner, *iter;
901
- uint8 flush = 0;
902
- wl_pfn_significant_bssid_t *bssid;
903
- uint16 num_bssid = 0;
904
- uint16 max_buf_size = sizeof(gscan_swc_params_t) +
905
- sizeof(wl_pfn_significant_bssid_t) * (PFN_SWC_MAX_NUM_APS - 1);
1224
+ uint16 *reply = NULL;
1225
+ uint32 reply_len = 0, num_channels, mem_needed;
1226
+ struct sk_buff *skb;
1227
+ dhd_pub_t *dhdp;
1228
+ struct net_device *ndev = wdev->netdev;
9061229
907
- significant_params = kzalloc(max_buf_size, GFP_KERNEL);
908
- if (!significant_params) {
909
- WL_ERR(("Cannot Malloc mem size:%d\n", max_buf_size));
910
- return BCME_NOMEM;
911
-
1230
+ if (!ndev) {
1231
+ WL_ERR(("ndev null\n"));
1232
+ return -EINVAL;
9121233 }
9131234
914
- nla_for_each_attr(iter, data, len, tmp2) {
1235
+ dhdp = wl_cfg80211_get_dhdp(ndev);
1236
+ if (!dhdp) {
1237
+ WL_ERR(("dhdp null\n"));
1238
+ return -EINVAL;
1239
+ }
1240
+
1241
+ if (!data) {
1242
+ WL_ERR(("data is not available\n"));
1243
+ return -EINVAL;
1244
+ }
1245
+
1246
+ if (len <= 0) {
1247
+ WL_ERR(("invalid len %d\n", len));
1248
+ return -EINVAL;
1249
+ }
1250
+
1251
+ type = nla_type(data);
1252
+ if (type == GSCAN_ATTRIBUTE_BAND) {
1253
+ band = nla_get_u32(data);
1254
+ } else {
1255
+ return -EINVAL;
1256
+ }
1257
+
1258
+ reply = dhd_pno_get_gscan(dhdp,
1259
+ DHD_PNO_GET_CHANNEL_LIST, &band, &reply_len);
1260
+ if (!reply) {
1261
+ WL_ERR(("Could not get channel list\n"));
1262
+ err = -EINVAL;
1263
+ return err;
1264
+ }
1265
+ num_channels = reply_len/ sizeof(uint32);
1266
+ mem_needed = reply_len + VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * 2);
1267
+
1268
+ /* Alloc the SKB for vendor_event */
1269
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
1270
+ if (unlikely(!skb)) {
1271
+ WL_ERR(("skb alloc failed"));
1272
+ err = -ENOMEM;
1273
+ goto exit;
1274
+ }
1275
+
1276
+ nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channels);
1277
+ nla_put(skb, GSCAN_ATTRIBUTE_CHANNEL_LIST, reply_len, reply);
1278
+
1279
+ err = cfg80211_vendor_cmd_reply(skb);
1280
+
1281
+ if (unlikely(err)) {
1282
+ WL_ERR(("Vendor Command reply failed ret:%d \n", err));
1283
+ }
1284
+exit:
1285
+ MFREE(cfg->osh, reply, reply_len);
1286
+ return err;
1287
+}
1288
+#endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */
1289
+
1290
+#ifdef RSSI_MONITOR_SUPPORT
1291
+static int wl_cfgvendor_set_rssi_monitor(struct wiphy *wiphy,
1292
+ struct wireless_dev *wdev, const void *data, int len)
1293
+{
1294
+ int err = 0, tmp, type, start = 0;
1295
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1296
+ int8 max_rssi = 0, min_rssi = 0;
1297
+ const struct nlattr *iter;
1298
+
1299
+ nla_for_each_attr(iter, data, len, tmp) {
9151300 type = nla_type(iter);
9161301 switch (type) {
917
- case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH:
918
- if (nla_len(iter) != sizeof(uint8)) {
919
- WL_ERR(("type:%d length:%d not matching.\n",
920
- type, nla_len(iter)));
921
- err = -EINVAL;
922
- goto exit;
923
- }
924
- flush = nla_get_u8(iter);
925
- break;
926
- case GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE:
927
- if (nla_len(iter) != sizeof(uint16)) {
928
- WL_ERR(("type:%d length:%d not matching.\n",
929
- type, nla_len(iter)));
930
- err = -EINVAL;
931
- goto exit;
932
- }
933
- significant_params->rssi_window = nla_get_u16(iter);
1302
+ case RSSI_MONITOR_ATTRIBUTE_MAX_RSSI:
1303
+ max_rssi = (int8) nla_get_u32(iter);
9341304 break;
935
- case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
936
- if (nla_len(iter) != sizeof(uint16)) {
937
- WL_ERR(("type:%d length:%d not matching\n",
938
- type, nla_len(iter)));
939
- err = -EINVAL;
940
- goto exit;
941
- }
942
- significant_params->lost_ap_window = nla_get_u16(iter);
1305
+ case RSSI_MONITOR_ATTRIBUTE_MIN_RSSI:
1306
+ min_rssi = (int8) nla_get_u32(iter);
9431307 break;
944
- case GSCAN_ATTRIBUTE_MIN_BREACHING:
945
- if (nla_len(iter) != sizeof(uint16)) {
946
- WL_ERR(("type:%d length:%d not matching\n",
947
- type, nla_len(iter)));
948
- err = -EINVAL;
949
- goto exit;
950
- }
951
- significant_params->swc_threshold = nla_get_u16(iter);
952
- break;
953
- case GSCAN_ATTRIBUTE_NUM_BSSID:
954
- num_bssid = nla_get_u16(iter);
955
- if (num_bssid > PFN_SWC_MAX_NUM_APS) {
956
- WL_ERR(("ovar max SWC bssids:%d\n",
957
- num_bssid));
958
- err = BCME_BADARG;
959
- goto exit;
960
- }
961
- break;
962
- case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS:
963
-
964
- if (num_bssid == 0 || num_bssid > PFN_SWC_MAX_NUM_APS) {
965
- WL_ERR(("Invalid num_bssid : %d\n", num_bssid));
966
- err = BCME_BADARG;
967
- goto exit;
968
- }
969
- bssid = significant_params->bssid_elem_list;
970
- nla_for_each_nested(outer, iter, tmp) {
971
- if ((j >= num_bssid) || (j > (PFN_SWC_MAX_NUM_APS - 1))) {
972
- j++;
973
- break;
974
- }
975
- nla_for_each_nested(inner, outer, tmp1) {
976
- switch (nla_type(inner)) {
977
- case GSCAN_ATTRIBUTE_BSSID:
978
- if (nla_len(inner) !=
979
- sizeof(bssid[j].macaddr)) {
980
- WL_ERR((
981
- "type:%d length:%d not matching.\n",
982
- type, nla_len(inner)));
983
- err = -EINVAL;
984
- goto exit;
985
- }
986
- memcpy(&(bssid[j].macaddr),
987
- nla_data(inner),
988
- ETHER_ADDR_LEN);
989
- break;
990
- case GSCAN_ATTRIBUTE_RSSI_HIGH:
991
- if (nla_len(inner) != sizeof(uint8)) {
992
- WL_ERR((
993
- "type:%d length:%d not matching.\n",
994
- type, nla_len(inner)));
995
- err = -EINVAL;
996
- goto exit;
997
- }
998
- bssid[j].rssi_high_threshold
999
- = (int8) nla_get_u8(inner);
1000
- break;
1001
- case GSCAN_ATTRIBUTE_RSSI_LOW:
1002
- if (nla_len(inner) != sizeof(uint8)) {
1003
- WL_ERR((
1004
- "type:%d length:%d not matching.\n",
1005
- type, nla_len(inner)));
1006
- err = -EINVAL;
1007
- goto exit;
1008
- }
1009
- bssid[j].rssi_low_threshold
1010
- = (int8) nla_get_u8(inner);
1011
- break;
1012
- default:
1013
- WL_ERR(("ATTR unknown %d\n",
1014
- type));
1015
- break;
1016
- }
1017
- }
1018
- j++;
1019
- }
1020
- break;
1021
- default:
1022
- WL_ERR(("Unknown type %d\n", type));
1023
- break;
1308
+ case RSSI_MONITOR_ATTRIBUTE_START:
1309
+ start = nla_get_u32(iter);
10241310 }
10251311 }
1026
- if (j != num_bssid) {
1027
- WL_ERR(("swc bssids count:%d not matched to num_bssid:%d\n",
1028
- j, num_bssid));
1312
+
1313
+ if (dhd_dev_set_rssi_monitor_cfg(bcmcfg_to_prmry_ndev(cfg),
1314
+ start, max_rssi, min_rssi) < 0) {
1315
+ WL_ERR(("Could not set rssi monitor cfg\n"));
1316
+ err = -EINVAL;
1317
+ }
1318
+ return err;
1319
+}
1320
+#else
1321
+static int wl_cfgvendor_set_rssi_monitor(struct wiphy *wiphy,
1322
+ struct wireless_dev *wdev, const void *data, int len)
1323
+{
1324
+ return WIFI_ERROR_NOT_SUPPORTED;
1325
+}
1326
+#endif /* RSSI_MONITOR_SUPPORT */
1327
+
1328
+#ifdef DHD_WAKE_STATUS
1329
+#define MAX_WAKE_EVENT_CNT (MIN(32, WLC_E_LAST))
1330
+static int
1331
+wl_cfgvendor_get_wake_reason_stats(struct wiphy *wiphy,
1332
+ struct wireless_dev *wdev, const void *data, int len)
1333
+{
1334
+ struct net_device *ndev = wdev_to_ndev(wdev);
1335
+ wake_counts_t *pwake_count_info;
1336
+ int ret, mem_needed;
1337
+#if defined(DHD_DEBUG) && defined(DHD_WAKE_EVENT_STATUS)
1338
+ int flowid;
1339
+#endif /* DHD_DEBUG && DHD_WAKE_EVENT_STATUS */
1340
+ struct sk_buff *skb = NULL;
1341
+ dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(ndev);
1342
+
1343
+ WL_DBG(("Recv get wake status info cmd.\n"));
1344
+
1345
+ pwake_count_info = dhd_get_wakecount(dhdp);
1346
+ mem_needed = VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * 20) +
1347
+ (MAX_WAKE_EVENT_CNT * sizeof(uint));
1348
+
1349
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
1350
+ if (unlikely(!skb)) {
1351
+ WL_ERR(("%s: can't allocate %d bytes\n", __FUNCTION__, mem_needed));
1352
+ ret = -ENOMEM;
1353
+ goto exit;
1354
+ }
1355
+#ifdef DHD_WAKE_EVENT_STATUS
1356
+ WL_ERR(("pwake_count_info->rcwake %d\n", pwake_count_info->rcwake));
1357
+ ret = nla_put_u32(skb, WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT, pwake_count_info->rcwake);
1358
+ if (unlikely(ret)) {
1359
+ WL_ERR(("Failed to put Total count of CMD event, ret=%d\n", ret));
1360
+ goto exit;
1361
+ }
1362
+
1363
+ ret = nla_put_u32(skb, WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT_USED, MAX_WAKE_EVENT_CNT);
1364
+ if (unlikely(ret)) {
1365
+ WL_ERR(("Failed to put Max count of event used, ret=%d\n", ret));
1366
+ goto exit;
1367
+ }
1368
+
1369
+ ret = nla_put(skb, WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE, (MAX_WAKE_EVENT_CNT * sizeof(uint)),
1370
+ pwake_count_info->rc_event);
1371
+ if (unlikely(ret)) {
1372
+ WL_ERR(("Failed to put Event wake data, ret=%d\n", ret));
1373
+ goto exit;
1374
+ }
1375
+#ifdef DHD_DEBUG
1376
+ for (flowid = 0; flowid < WLC_E_LAST; flowid++) {
1377
+ if (pwake_count_info->rc_event[flowid] != 0) {
1378
+ WL_ERR((" %s = %u\n", bcmevent_get_name(flowid),
1379
+ pwake_count_info->rc_event[flowid]));
1380
+ }
1381
+ }
1382
+#endif /* DHD_DEBUG */
1383
+#endif /* DHD_WAKE_EVENT_STATUS */
1384
+#ifdef DHD_WAKE_RX_STATUS
1385
+ WL_ERR(("pwake_count_info->rxwake %d\n", pwake_count_info->rxwake));
1386
+ ret = nla_put_u32(skb, WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE, pwake_count_info->rxwake);
1387
+ if (unlikely(ret)) {
1388
+ WL_ERR(("Failed to put Total Wake due RX data, ret=%d\n", ret));
1389
+ goto exit;
1390
+ }
1391
+ ret = nla_put_u32(skb, WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT, pwake_count_info->rx_ucast);
1392
+ if (unlikely(ret)) {
1393
+ WL_ERR(("Failed to put Total wake due to RX unicast, ret=%d\n", ret));
1394
+ goto exit;
1395
+ }
1396
+ ret = nla_put_u32(skb, WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT, pwake_count_info->rx_mcast);
1397
+ if (unlikely(ret)) {
1398
+ WL_ERR(("Failed to put Total wake due RX multicast, ret=%d\n", ret));
1399
+ goto exit;
1400
+ }
1401
+ ret = nla_put_u32(skb, WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT, pwake_count_info->rx_bcast);
1402
+ if (unlikely(ret)) {
1403
+ WL_ERR(("Failed to put Total wake due to RX broadcast, ret=%d\n", ret));
1404
+ goto exit;
1405
+ }
1406
+ ret = nla_put_u32(skb, WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT, pwake_count_info->rx_arp);
1407
+ if (unlikely(ret)) {
1408
+ WL_ERR(("Failed to put Total wake due to ICMP pkt, ret=%d\n", ret));
1409
+ goto exit;
1410
+ }
1411
+ ret = nla_put_u32(skb, WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT, pwake_count_info->rx_icmpv6);
1412
+ if (unlikely(ret)) {
1413
+ WL_ERR(("Failed to put Total wake due ICMPV6 pkt, ret=%d\n", ret));
1414
+ goto exit;
1415
+ }
1416
+ ret = nla_put_u32(skb, WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA, pwake_count_info->rx_icmpv6_ra);
1417
+ if (unlikely(ret)) {
1418
+ WL_ERR(("Failed to put Total wake due to ICMPV6_RA, ret=%d\n", ret));
1419
+ goto exit;
1420
+ }
1421
+ ret = nla_put_u32(skb, WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA, pwake_count_info->rx_icmpv6_na);
1422
+ if (unlikely(ret)) {
1423
+ WL_ERR(("Failed to put Total wake due to ICMPV6_NA, ret=%d\n", ret));
1424
+ goto exit;
1425
+ }
1426
+ ret = nla_put_u32(skb, WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS, pwake_count_info->rx_icmpv6_ns);
1427
+ if (unlikely(ret)) {
1428
+ WL_ERR(("Failed to put Total wake due to ICMPV6_NS, ret=%d\n", ret));
1429
+ goto exit;
1430
+ }
1431
+ ret = nla_put_u32(skb, WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT,
1432
+ pwake_count_info->rx_multi_ipv4);
1433
+ if (unlikely(ret)) {
1434
+ WL_ERR(("Failed to put Total wake due to RX IPV4 MULTICAST, ret=%d\n", ret));
1435
+ goto exit;
1436
+ }
1437
+ ret = nla_put_u32(skb, WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT,
1438
+ pwake_count_info->rx_multi_ipv6);
1439
+ if (unlikely(ret)) {
1440
+ WL_ERR(("Failed to put Total wake due to RX IPV6 MULTICAST, ret=%d\n", ret));
1441
+ goto exit;
1442
+ }
1443
+ ret = nla_put_u32(skb, WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT,
1444
+ pwake_count_info->rx_multi_other);
1445
+ if (unlikely(ret)) {
1446
+ WL_ERR(("Failed to put Total wake due to Other RX Multicast, ret=%d\n", ret));
1447
+ goto exit;
1448
+ }
1449
+#endif /* DHD_WAKE_RX_STATUS */
1450
+ ret = cfg80211_vendor_cmd_reply(skb);
1451
+ if (unlikely(ret)) {
1452
+ WL_ERR(("Vendor cmd reply for -get wake status failed:%d \n", ret));
1453
+ }
1454
+ /* On cfg80211_vendor_cmd_reply() skb is consumed and freed in case of success or failure */
1455
+ return ret;
1456
+
1457
+exit:
1458
+ /* Free skb memory */
1459
+ if (skb) {
1460
+ kfree_skb(skb);
1461
+ }
1462
+ return ret;
1463
+}
1464
+#else
1465
+/*
1466
+static int
1467
+wl_cfgvendor_get_wake_reason_stats(struct wiphy *wiphy,
1468
+ struct wireless_dev *wdev, const void *data, int len)
1469
+{
1470
+ return WIFI_ERROR_NOT_SUPPORTED;
1471
+}
1472
+*/
1473
+#endif /* DHD_WAKE_STATUS */
1474
+
1475
+#ifdef DHDTCPACK_SUPPRESS
1476
+static int
1477
+wl_cfgvendor_set_tcpack_sup_mode(struct wiphy *wiphy,
1478
+ struct wireless_dev *wdev, const void *data, int len)
1479
+{
1480
+ int err = BCME_OK, type;
1481
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1482
+ struct net_device *ndev = wdev_to_wlc_ndev(wdev, cfg);
1483
+ uint8 enable = 0;
1484
+
1485
+ if (!data) {
1486
+ WL_ERR(("data is not available\n"));
10291487 err = BCME_BADARG;
10301488 goto exit;
10311489 }
1032
- significant_params->nbssid = j;
10331490
1034
- if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
1035
- DHD_PNO_SIGNIFICANT_SCAN_CFG_ID,
1036
- significant_params, flush) < 0) {
1037
- WL_ERR(("Could not set GSCAN significant cfg\n"));
1038
- err = BCME_ERROR;
1491
+ if (len <= 0) {
1492
+ WL_ERR(("Length of the nlattr is not valid len : %d\n", len));
1493
+ err = BCME_BADARG;
10391494 goto exit;
10401495 }
1496
+
1497
+ type = nla_type(data);
1498
+ if (type == ANDR_WIFI_ATTRIBUTE_TCPACK_SUP_VALUE) {
1499
+ enable = (uint8) nla_get_u32(data);
1500
+ err = dhd_dev_set_tcpack_sup_mode_cfg(ndev, enable);
1501
+ if (unlikely(err)) {
1502
+ WL_ERR(("Could not set TCP Ack Suppress mode cfg: %d\n", err));
1503
+ }
1504
+ } else {
1505
+ err = BCME_BADARG;
1506
+ }
1507
+
10411508 exit:
1042
- kfree(significant_params);
10431509 return err;
10441510 }
1045
-#endif /* GSCAN_SUPPORT */
1511
+#endif /* DHDTCPACK_SUPPRESS */
1512
+
1513
+static int
1514
+wl_cfgvendor_set_latency_mode(struct wiphy *wiphy,
1515
+ struct wireless_dev *wdev, const void *data, int len)
1516
+{
1517
+ int err = BCME_OK;
1518
+ int type;
1519
+ bool lmode;
1520
+
1521
+ struct net_device *ndev = wdev_to_ndev(wdev);
1522
+ WL_DBG(("wl_cfgvendor_set_latency_mode Enter \n"));
1523
+ if (!data) {
1524
+ WL_ERR(("data is not available\n"));
1525
+ return -EINVAL;
1526
+ }
1527
+
1528
+ if (len <= 0) {
1529
+ WL_ERR(("invalid len %d\n", len));
1530
+ return -EINVAL;
1531
+ }
1532
+
1533
+ type = nla_type(data);
1534
+ if (type == ANDR_WIFI_ATTRIBUTE_LATENCY_MODE) {
1535
+ lmode = (bool)nla_get_u32(data);
1536
+ err = wl_cfg80211_set_power_mgmt(wiphy, ndev, !lmode, 0);
1537
+ }
1538
+ return err;
1539
+}
1540
+
1541
+#if 0
1542
+static int
1543
+wl_cfgvendor_set_random_mac(struct wiphy *wiphy,
1544
+ struct wireless_dev *wdev, const void *data, int len)
1545
+{
1546
+ int err = BCME_OK;
1547
+
1548
+ WL_ERR(("ANDR_WIFI_ATTRIBUTE_RANDOM_MAC is not available\n"));
1549
+ err = BCME_UNSUPPORTED;
1550
+
1551
+ return err;
1552
+}
1553
+#endif /* CONFIG_SOC_S5E5515 */
1554
+
1555
+static int
1556
+wl_cfgvendor_set_tx_power_scenario(struct wiphy *wiphy,
1557
+ struct wireless_dev *wdev, const void *data, int len)
1558
+{
1559
+ int err = BCME_OK;
1560
+ int type;
1561
+ if (!data) {
1562
+ WL_ERR(("data is not available\n"));
1563
+ return -EINVAL;
1564
+ }
1565
+ if (len <= 0) {
1566
+ WL_ERR(("invalid len %d\n", len));
1567
+ return -EINVAL;
1568
+ }
1569
+ type = nla_type(data);
1570
+ if (type == ANDR_WIFI_ATTRIBUTE_TX_POWER_SCENARIO) {
1571
+ //Handling to be implemented
1572
+ //err = wl_cfg80211_set_tx_power(wiphy,wdev,type,0);
1573
+ err = BCME_OK;
1574
+ }
1575
+ return err;
1576
+}
1577
+
1578
+#if defined(WL_CFG80211) && defined(DHD_FILE_DUMP_EVENT)
1579
+static int
1580
+wl_cfgvendor_notify_dump_completion(struct wiphy *wiphy,
1581
+ struct wireless_dev *wdev, const void *data, int len)
1582
+{
1583
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1584
+ dhd_pub_t *dhd_pub = cfg->pub;
1585
+ unsigned long flags = 0;
1586
+
1587
+ WL_INFORM(("%s, [DUMP] received file dump notification from HAL\n", __FUNCTION__));
1588
+
1589
+ DHD_GENERAL_LOCK(dhd_pub, flags);
1590
+ /* call wmb() to synchronize with the previous memory operations */
1591
+ OSL_SMP_WMB();
1592
+ DHD_BUS_BUSY_CLEAR_IN_HALDUMP(dhd_pub);
1593
+ /* Call another wmb() to make sure wait_for_dump_completion value
1594
+ * gets updated before waking up waiting context.
1595
+ */
1596
+ OSL_SMP_WMB();
1597
+ dhd_os_busbusy_wake(dhd_pub);
1598
+ DHD_GENERAL_UNLOCK(dhd_pub, flags);
1599
+
1600
+ return BCME_OK;
1601
+}
1602
+#endif /* WL_CFG80211 && DHD_FILE_DUMP_EVENT */
1603
+
1604
+#if defined(WL_CFG80211)
1605
+static int
1606
+wl_cfgvendor_set_hal_started(struct wiphy *wiphy,
1607
+ struct wireless_dev *wdev, const void *data, int len)
1608
+{
1609
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1610
+ WL_INFORM(("%s,[DUMP] HAL STARTED\n", __FUNCTION__));
1611
+
1612
+ cfg->hal_started = true;
1613
+ return BCME_OK;
1614
+}
1615
+
1616
+static int
1617
+wl_cfgvendor_stop_hal(struct wiphy *wiphy,
1618
+ struct wireless_dev *wdev, const void *data, int len)
1619
+{
1620
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1621
+ WL_INFORM(("%s,[DUMP] HAL STOPPED\n", __FUNCTION__));
1622
+
1623
+ cfg->hal_started = false;
1624
+ return BCME_OK;
1625
+}
1626
+
1627
+static int
1628
+wl_cfgvendor_set_hal_pid(struct wiphy *wiphy,
1629
+ struct wireless_dev *wdev, const void *data, int len)
1630
+{
1631
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1632
+ int ret = BCME_OK;
1633
+ int type;
1634
+
1635
+ WL_INFORM(("%s,[DUMP] SET HAL_PID\n", __FUNCTION__));
1636
+ if (data) {
1637
+ type = nla_type(data);
1638
+ if (type == SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID) {
1639
+ cfg->hal_pid = nla_get_u32(data);
1640
+ }
1641
+ } else {
1642
+ ret = BCME_ERROR;
1643
+ }
1644
+
1645
+ return ret;
1646
+}
1647
+#endif /* WL_CFG80211 */
1648
+
1649
+static int
1650
+wl_cfgvendor_chavoid_set_config(struct wiphy *wiphy,
1651
+ struct wireless_dev *wdev, const void *data, int len)
1652
+{
1653
+ return WIFI_ERROR_NOT_SUPPORTED;
1654
+}
1655
+
1656
+static int
1657
+wl_cfgvendor_usable_channel(struct wiphy *wiphy,
1658
+ struct wireless_dev *wdev, const void *data, int len)
1659
+{
1660
+ return WIFI_ERROR_NOT_SUPPORTED;
1661
+}
10461662 #ifdef RTT_SUPPORT
10471663 void
10481664 wl_cfgvendor_rtt_evt(void *ctx, void *rtt_data)
10491665 {
10501666 struct wireless_dev *wdev = (struct wireless_dev *)ctx;
10511667 struct wiphy *wiphy;
1052
- struct sk_buff *skb;
1053
- uint32 complete = 0;
1668
+ struct sk_buff *skb = NULL;
1669
+ uint32 evt_complete = 0;
10541670 gfp_t kflags;
10551671 rtt_result_t *rtt_result;
10561672 rtt_results_header_t *rtt_header;
10571673 struct list_head *rtt_cache_list;
10581674 struct nlattr *rtt_nl_hdr;
1675
+ int ret = BCME_OK;
10591676 wiphy = wdev->wiphy;
10601677
10611678 WL_DBG(("In\n"));
....@@ -1079,11 +1696,16 @@
10791696 WL_ERR(("skb alloc failed"));
10801697 return;
10811698 }
1082
- complete = 1;
1083
- nla_put_u32(skb, RTT_ATTRIBUTE_RESULTS_COMPLETE, complete);
1699
+ evt_complete = 1;
1700
+ ret = nla_put_u32(skb, RTT_ATTRIBUTE_RESULTS_COMPLETE, evt_complete);
1701
+ if (ret < 0) {
1702
+ WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULTS_COMPLETE\n"));
1703
+ goto free_mem;
1704
+ }
10841705 cfg80211_vendor_event(skb, kflags);
10851706 return;
10861707 }
1708
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
10871709 list_for_each_entry(rtt_header, rtt_cache_list, list) {
10881710 /* Alloc the SKB for vendor_event */
10891711 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
....@@ -1100,22 +1722,56 @@
11001722 return;
11011723 }
11021724 if (list_is_last(&rtt_header->list, rtt_cache_list)) {
1103
- complete = 1;
1725
+ evt_complete = 1;
11041726 }
1105
- nla_put_u32(skb, RTT_ATTRIBUTE_RESULTS_COMPLETE, complete);
1727
+ ret = nla_put_u32(skb, RTT_ATTRIBUTE_RESULTS_COMPLETE, evt_complete);
1728
+ if (ret < 0) {
1729
+ WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULTS_COMPLETE\n"));
1730
+ goto free_mem;
1731
+ }
11061732 rtt_nl_hdr = nla_nest_start(skb, RTT_ATTRIBUTE_RESULTS_PER_TARGET);
11071733 if (!rtt_nl_hdr) {
11081734 WL_ERR(("rtt_nl_hdr is NULL\n"));
1735
+ dev_kfree_skb_any(skb);
11091736 break;
11101737 }
1111
- nla_put(skb, RTT_ATTRIBUTE_TARGET_MAC, ETHER_ADDR_LEN, &rtt_header->peer_mac);
1112
- nla_put_u32(skb, RTT_ATTRIBUTE_RESULT_CNT, rtt_header->result_cnt);
1738
+ ret = nla_put(skb, RTT_ATTRIBUTE_TARGET_MAC, ETHER_ADDR_LEN,
1739
+ &rtt_header->peer_mac);
1740
+ if (ret < 0) {
1741
+ WL_ERR(("Failed to put RTT_ATTRIBUTE_TARGET_MAC, ret:%d\n", ret));
1742
+ goto free_mem;
1743
+ }
1744
+ ret = nla_put_u32(skb, RTT_ATTRIBUTE_RESULT_CNT, rtt_header->result_cnt);
1745
+ if (ret < 0) {
1746
+ WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULT_CNT, ret:%d\n", ret));
1747
+ goto free_mem;
1748
+ }
11131749 list_for_each_entry(rtt_result, &rtt_header->result_list, list) {
1114
- nla_put(skb, RTT_ATTRIBUTE_RESULT,
1750
+ ret = nla_put(skb, RTT_ATTRIBUTE_RESULT,
11151751 rtt_result->report_len, &rtt_result->report);
1752
+ if (ret < 0) {
1753
+ WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULT, ret:%d\n", ret));
1754
+ goto free_mem;
1755
+ }
1756
+ ret = nla_put(skb, RTT_ATTRIBUTE_RESULT_DETAIL,
1757
+ rtt_result->detail_len, &rtt_result->rtt_detail);
1758
+ if (ret < 0) {
1759
+ WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULT_DETAIL, ret:%d\n",
1760
+ ret));
1761
+ goto free_mem;
1762
+ }
11161763 }
11171764 nla_nest_end(skb, rtt_nl_hdr);
11181765 cfg80211_vendor_event(skb, kflags);
1766
+ }
1767
+ GCC_DIAGNOSTIC_POP();
1768
+
1769
+ return;
1770
+
1771
+free_mem:
1772
+ /* Free skb memory */
1773
+ if (skb) {
1774
+ kfree_skb(skb);
11191775 }
11201776 }
11211777
....@@ -1123,16 +1779,16 @@
11231779 wl_cfgvendor_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev,
11241780 const void *data, int len) {
11251781 int err = 0, rem, rem1, rem2, type;
1126
- int target_cnt;
1782
+ int target_cnt = 0;
11271783 rtt_config_params_t rtt_param;
11281784 rtt_target_info_t* rtt_target = NULL;
11291785 const struct nlattr *iter, *iter1, *iter2;
11301786 int8 eabuf[ETHER_ADDR_STR_LEN];
11311787 int8 chanbuf[CHANSPEC_STR_LEN];
1132
- int32 feature_set = 0;
11331788 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
11341789 rtt_capabilities_t capability;
1135
- feature_set = dhd_dev_get_feature_set(bcmcfg_to_prmry_ndev(cfg));
1790
+
1791
+ bzero(&rtt_param, sizeof(rtt_param));
11361792
11371793 WL_DBG(("In\n"));
11381794 err = dhd_dev_rtt_register_noti_callback(wdev->netdev, wdev, wl_cfgvendor_rtt_evt);
....@@ -1145,20 +1801,32 @@
11451801 WL_ERR(("failed to get the capability\n"));
11461802 goto exit;
11471803 }
1148
- memset(&rtt_param, 0, sizeof(rtt_param));
1804
+
1805
+ if (len <= 0) {
1806
+ WL_ERR(("Length of the nlattr is not valid len : %d\n", len));
1807
+ err = BCME_ERROR;
1808
+ goto exit;
1809
+ }
11491810 nla_for_each_attr(iter, data, len, rem) {
11501811 type = nla_type(iter);
11511812 switch (type) {
11521813 case RTT_ATTRIBUTE_TARGET_CNT:
1814
+ if (target_cnt != 0) {
1815
+ WL_ERR(("attempt to overwrite target_cnt"));
1816
+ err = -EINVAL;
1817
+ goto exit;
1818
+ }
11531819 target_cnt = nla_get_u8(iter);
1154
- if (rtt_param.rtt_target_cnt > RTT_MAX_TARGET_CNT) {
1155
- WL_ERR(("exceed max target count : %d\n",
1820
+ if ((target_cnt <= 0) || (target_cnt > RTT_MAX_TARGET_CNT)) {
1821
+ WL_ERR(("target_cnt is not valid : %d\n",
11561822 target_cnt));
11571823 err = BCME_RANGE;
11581824 goto exit;
11591825 }
11601826 rtt_param.rtt_target_cnt = target_cnt;
1161
- rtt_param.target_info = kzalloc(TARGET_INFO_SIZE(target_cnt), GFP_KERNEL);
1827
+
1828
+ rtt_param.target_info = (rtt_target_info_t *)MALLOCZ(cfg->osh,
1829
+ TARGET_INFO_SIZE(target_cnt));
11621830 if (rtt_param.target_info == NULL) {
11631831 WL_ERR(("failed to allocate target info for (%d)\n", target_cnt));
11641832 err = BCME_NOMEM;
....@@ -1166,12 +1834,31 @@
11661834 }
11671835 break;
11681836 case RTT_ATTRIBUTE_TARGET_INFO:
1837
+ /* Added this variable for safe check to avoid crash
1838
+ * incase the caller did not respect the order
1839
+ */
1840
+ if (rtt_param.target_info == NULL) {
1841
+ WL_ERR(("rtt_target_info is NULL\n"));
1842
+ err = BCME_NOMEM;
1843
+ goto exit;
1844
+ }
11691845 rtt_target = rtt_param.target_info;
11701846 nla_for_each_nested(iter1, iter, rem1) {
1847
+ if ((uint8 *)rtt_target >= ((uint8 *)rtt_param.target_info +
1848
+ TARGET_INFO_SIZE(target_cnt))) {
1849
+ WL_ERR(("rtt_target increased over its max size"));
1850
+ err = -EINVAL;
1851
+ goto exit;
1852
+ }
11711853 nla_for_each_nested(iter2, iter1, rem2) {
11721854 type = nla_type(iter2);
11731855 switch (type) {
11741856 case RTT_ATTRIBUTE_TARGET_MAC:
1857
+ if (nla_len(iter2) != ETHER_ADDR_LEN) {
1858
+ WL_ERR(("mac_addr length not match\n"));
1859
+ err = -EINVAL;
1860
+ goto exit;
1861
+ }
11751862 memcpy(&rtt_target->addr, nla_data(iter2),
11761863 ETHER_ADDR_LEN);
11771864 break;
....@@ -1272,12 +1959,12 @@
12721959 err = -EINVAL;
12731960 goto exit;
12741961 }
1275
- WL_INFORM(("Target addr %s, Channel : %s for RTT \n",
1962
+ WL_INFORM_MEM(("Target addr %s, Channel : %s for RTT \n",
12761963 bcm_ether_ntoa((const struct ether_addr *)&rtt_target->addr,
12771964 eabuf),
12781965 wf_chspec_ntoa(rtt_target->chanspec, chanbuf)));
12791966 rtt_target++;
1280
- }
1967
+ }
12811968 break;
12821969 }
12831970 }
....@@ -1288,7 +1975,10 @@
12881975 }
12891976 exit:
12901977 /* free the target info list */
1291
- kfree(rtt_param.target_info);
1978
+ if (rtt_param.target_info) {
1979
+ MFREE(cfg->osh, rtt_param.target_info,
1980
+ TARGET_INFO_SIZE(target_cnt));
1981
+ }
12921982 return err;
12931983 }
12941984
....@@ -1296,59 +1986,81 @@
12961986 wl_cfgvendor_rtt_cancel_config(struct wiphy *wiphy, struct wireless_dev *wdev,
12971987 const void *data, int len)
12981988 {
1299
- int err = 0, rem, type, target_cnt = 1;
1300
- int target_cnt_chk = 0;
1989
+ int err = 0, rem, type, target_cnt = 0;
1990
+ int target_idx = 0;
13011991 const struct nlattr *iter;
1302
- struct ether_addr *mac_list = NULL, *mac_addr = NULL;
1992
+ struct ether_addr *mac_list = NULL;
13031993 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
13041994
1995
+ if (len <= 0) {
1996
+ WL_ERR(("Length of nlattr is not valid len : %d\n", len));
1997
+ err = -EINVAL;
1998
+ goto exit;
1999
+ }
13052000 nla_for_each_attr(iter, data, len, rem) {
13062001 type = nla_type(iter);
1307
-
13082002 switch (type) {
13092003 case RTT_ATTRIBUTE_TARGET_CNT:
13102004 if (mac_list != NULL) {
13112005 WL_ERR(("mac_list is not NULL\n"));
2006
+ err = -EINVAL;
13122007 goto exit;
13132008 }
13142009 target_cnt = nla_get_u8(iter);
1315
- if (target_cnt > 0) {
1316
- mac_list = (struct ether_addr *)kzalloc(target_cnt * ETHER_ADDR_LEN,
1317
- GFP_KERNEL);
2010
+ if ((target_cnt > 0) && (target_cnt < RTT_MAX_TARGET_CNT)) {
2011
+ mac_list = (struct ether_addr *)MALLOCZ(cfg->osh,
2012
+ target_cnt * ETHER_ADDR_LEN);
13182013 if (mac_list == NULL) {
13192014 WL_ERR(("failed to allocate mem for mac list\n"));
2015
+ err = -EINVAL;
13202016 goto exit;
13212017 }
1322
- mac_addr = &mac_list[0];
13232018 } else {
13242019 /* cancel the current whole RTT process */
13252020 goto cancel;
13262021 }
13272022 break;
13282023 case RTT_ATTRIBUTE_TARGET_MAC:
1329
- if (mac_addr) {
1330
- memcpy(mac_addr++, nla_data(iter), ETHER_ADDR_LEN);
1331
- target_cnt_chk++;
1332
- if (target_cnt_chk > target_cnt) {
1333
- WL_ERR(("over target count\n"));
1334
- goto exit;
1335
- }
1336
- break;
1337
- } else {
1338
- WL_ERR(("mac_list is NULL\n"));
2024
+ if (mac_list == NULL) {
2025
+ WL_ERR(("ATTRIBUTE_TARGET_CNT not found before "
2026
+ " ATTRIBUTE_TARGET_MAC\n"));
2027
+ err = -EINVAL;
13392028 goto exit;
13402029 }
13412030
2031
+ if (target_idx >= target_cnt) {
2032
+ WL_ERR(("More TARGET_MAC entries found, "
2033
+ "expected TARGET_CNT:%d\n", target_cnt));
2034
+ err = -EINVAL;
2035
+ goto exit;
2036
+ }
2037
+
2038
+ if (nla_len(iter) != ETHER_ADDR_LEN) {
2039
+ WL_ERR(("Invalid TARGET_MAC ATTR len :%d\n", nla_len(iter)));
2040
+ err = -EINVAL;
2041
+ goto exit;
2042
+ }
2043
+
2044
+ memcpy(&mac_list[target_idx], nla_data(iter), ETHER_ADDR_LEN);
2045
+ target_idx++;
2046
+
2047
+ break;
2048
+ default:
2049
+ WL_ERR(("Uknown type : %d\n", type));
2050
+ err = -EINVAL;
2051
+ goto exit;
13422052 }
13432053 }
13442054 cancel:
1345
- if (dhd_dev_rtt_cancel_cfg(bcmcfg_to_prmry_ndev(cfg), mac_list, target_cnt) < 0) {
2055
+ if (mac_list && dhd_dev_rtt_cancel_cfg(
2056
+ bcmcfg_to_prmry_ndev(cfg), mac_list, target_cnt) < 0) {
13462057 WL_ERR(("Could not cancel RTT configuration\n"));
13472058 err = -EINVAL;
13482059 }
2060
+
13492061 exit:
13502062 if (mac_list) {
1351
- kfree(mac_list);
2063
+ MFREE(cfg->osh, mac_list, target_cnt * ETHER_ADDR_LEN);
13522064 }
13532065 return err;
13542066 }
....@@ -1359,7 +2071,6 @@
13592071 {
13602072 int err = 0;
13612073 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1362
-
13632074 rtt_capabilities_t capability;
13642075
13652076 err = dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg), &capability);
....@@ -1367,15 +2078,112 @@
13672078 WL_ERR(("Vendor Command reply failed ret:%d \n", err));
13682079 goto exit;
13692080 }
1370
- err = wl_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
1371
- &capability, sizeof(capability));
2081
+ err = wl_cfgvendor_send_cmd_reply(wiphy, &capability, sizeof(capability));
2082
+
13722083 if (unlikely(err)) {
13732084 WL_ERR(("Vendor Command reply failed ret:%d \n", err));
13742085 }
13752086 exit:
13762087 return err;
13772088 }
2089
+static int
2090
+get_responder_info(struct bcm_cfg80211 *cfg,
2091
+ struct wifi_rtt_responder *responder_info)
2092
+{
2093
+ int err = 0;
2094
+ rtt_capabilities_t capability;
2095
+ err = dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg), &capability);
2096
+ if (unlikely(err)) {
2097
+ WL_ERR(("Could not get responder capability:%d \n", err));
2098
+ return err;
2099
+ }
2100
+ if (capability.preamble_support & RTT_PREAMBLE_VHT) {
2101
+ responder_info->preamble |= RTT_PREAMBLE_VHT;
2102
+ }
2103
+ if (capability.preamble_support & RTT_PREAMBLE_HT) {
2104
+ responder_info->preamble |= RTT_PREAMBLE_HT;
2105
+ }
2106
+ err = dhd_dev_rtt_avail_channel(bcmcfg_to_prmry_ndev(cfg), &(responder_info->channel));
2107
+ if (unlikely(err)) {
2108
+ WL_ERR(("Could not get available channel:%d \n", err));
2109
+ return err;
2110
+ }
2111
+ return err;
2112
+}
2113
+static int
2114
+wl_cfgvendor_rtt_get_responder_info(struct wiphy *wiphy, struct wireless_dev *wdev,
2115
+ const void *data, int len)
2116
+{
2117
+ int err = 0;
2118
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2119
+ wifi_rtt_responder_t responder_info;
13782120
2121
+ WL_DBG(("Recv -get_avail_ch command \n"));
2122
+
2123
+ bzero(&responder_info, sizeof(responder_info));
2124
+ err = get_responder_info(cfg, &responder_info);
2125
+ if (unlikely(err)) {
2126
+ WL_ERR(("Failed to get responder info:%d \n", err));
2127
+ return err;
2128
+ }
2129
+ err = wl_cfgvendor_send_cmd_reply(wiphy, &responder_info, sizeof(responder_info));
2130
+ if (unlikely(err)) {
2131
+ WL_ERR(("Vendor cmd reply for -get_avail_ch failed ret:%d \n", err));
2132
+ }
2133
+ return err;
2134
+}
2135
+
2136
+static int
2137
+wl_cfgvendor_rtt_set_responder(struct wiphy *wiphy, struct wireless_dev *wdev,
2138
+ const void *data, int len)
2139
+{
2140
+ int err = 0;
2141
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2142
+ struct net_device *ndev = wdev_to_wlc_ndev(wdev, cfg);
2143
+ wifi_rtt_responder_t responder_info;
2144
+
2145
+ WL_DBG(("Recv rtt -enable_resp cmd.\n"));
2146
+
2147
+ bzero(&responder_info, sizeof(responder_info));
2148
+
2149
+ /*
2150
+ *Passing channel as NULL until implementation
2151
+ *to get chan info from upper layers is donex
2152
+ */
2153
+ err = dhd_dev_rtt_enable_responder(ndev, NULL);
2154
+ if (unlikely(err)) {
2155
+ WL_ERR(("Could not enable responder ret:%d \n", err));
2156
+ goto done;
2157
+ }
2158
+ err = get_responder_info(cfg, &responder_info);
2159
+ if (unlikely(err)) {
2160
+ WL_ERR(("Failed to get responder info:%d \n", err));
2161
+ dhd_dev_rtt_cancel_responder(ndev);
2162
+ goto done;
2163
+ }
2164
+done:
2165
+ err = wl_cfgvendor_send_cmd_reply(wiphy, &responder_info, sizeof(responder_info));
2166
+ if (unlikely(err)) {
2167
+ WL_ERR(("Vendor cmd reply for -enable_resp failed ret:%d \n", err));
2168
+ }
2169
+ return err;
2170
+}
2171
+
2172
+static int
2173
+wl_cfgvendor_rtt_cancel_responder(struct wiphy *wiphy, struct wireless_dev *wdev,
2174
+ const void *data, int len)
2175
+{
2176
+ int err = 0;
2177
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2178
+
2179
+ WL_DBG(("Recv rtt -cancel_resp cmd \n"));
2180
+
2181
+ err = dhd_dev_rtt_cancel_responder(bcmcfg_to_prmry_ndev(cfg));
2182
+ if (unlikely(err)) {
2183
+ WL_ERR(("Vendor cmd -cancel_resp failed ret:%d \n", err));
2184
+ }
2185
+ return err;
2186
+}
13792187 #endif /* RTT_SUPPORT */
13802188
13812189 #ifdef GSCAN_SUPPORT
....@@ -1387,6 +2195,16 @@
13872195 int type;
13882196 uint32 lazy_roam_enable_flag;
13892197
2198
+ if (!data) {
2199
+ WL_ERR(("data is not available\n"));
2200
+ return -EINVAL;
2201
+ }
2202
+
2203
+ if (len <= 0) {
2204
+ WL_ERR(("invaild len %d\n", len));
2205
+ return -EINVAL;
2206
+ }
2207
+
13902208 type = nla_type(data);
13912209
13922210 if (type == GSCAN_ATTRIBUTE_LAZY_ROAM_ENABLE) {
....@@ -1394,11 +2212,10 @@
13942212
13952213 err = dhd_dev_lazy_roam_enable(bcmcfg_to_prmry_ndev(cfg),
13962214 lazy_roam_enable_flag);
1397
-
13982215 if (unlikely(err))
13992216 WL_ERR(("Could not enable lazy roam:%d \n", err));
1400
-
14012217 }
2218
+
14022219 return err;
14032220 }
14042221
....@@ -1410,11 +2227,10 @@
14102227 wlc_roam_exp_params_t roam_param;
14112228 const struct nlattr *iter;
14122229
1413
- memset(&roam_param, 0, sizeof(roam_param));
2230
+ bzero(&roam_param, sizeof(roam_param));
14142231
14152232 nla_for_each_attr(iter, data, len, tmp) {
14162233 type = nla_type(iter);
1417
-
14182234 switch (type) {
14192235 case GSCAN_ATTRIBUTE_A_BAND_BOOST_THRESHOLD:
14202236 roam_param.a_band_boost_threshold = nla_get_u32(iter);
....@@ -1449,15 +2265,16 @@
14492265
14502266 /* small helper function */
14512267 static wl_bssid_pref_cfg_t *
1452
-create_bssid_pref_cfg(uint32 num)
2268
+create_bssid_pref_cfg(struct bcm_cfg80211 *cfg, uint32 num, uint32 *buf_len)
14532269 {
1454
- uint32 mem_needed;
14552270 wl_bssid_pref_cfg_t *bssid_pref;
14562271
1457
- mem_needed = sizeof(wl_bssid_pref_cfg_t);
1458
- if (num)
1459
- mem_needed += (num - 1) * sizeof(wl_bssid_pref_list_t);
1460
- bssid_pref = (wl_bssid_pref_cfg_t *) kmalloc(mem_needed, GFP_KERNEL);
2272
+ *buf_len = sizeof(wl_bssid_pref_cfg_t);
2273
+ if (num) {
2274
+ *buf_len += (num - 1) * sizeof(wl_bssid_pref_list_t);
2275
+ }
2276
+ bssid_pref = (wl_bssid_pref_cfg_t *)MALLOC(cfg->osh, *buf_len);
2277
+
14612278 return bssid_pref;
14622279 }
14632280
....@@ -1471,55 +2288,101 @@
14712288 wl_bssid_pref_list_t *bssids;
14722289 int tmp, tmp1, tmp2, type;
14732290 const struct nlattr *outer, *inner, *iter;
1474
- uint32 flush = 0, i = 0, num = 0;
2291
+ uint32 flush = 0, num = 0, buf_len = 0;
2292
+ uint8 bssid_found = 0, rssi_found = 0;
14752293
14762294 /* Assumption: NUM attribute must come first */
14772295 nla_for_each_attr(iter, data, len, tmp2) {
14782296 type = nla_type(iter);
14792297 switch (type) {
14802298 case GSCAN_ATTRIBUTE_NUM_BSSID:
1481
- num = nla_get_u32(iter);
1482
- if (num > MAX_BSSID_PREF_LIST_NUM) {
1483
- WL_ERR(("Too many Preferred BSSIDs!\n"));
2299
+ if (num) {
2300
+ WL_ERR(("attempt overide bssid num.\n"));
14842301 err = -EINVAL;
2302
+ goto exit;
2303
+ }
2304
+ if (nla_len(iter) != sizeof(uint32)) {
2305
+ WL_ERR(("nla_len not match\n"));
2306
+ err = -EINVAL;
2307
+ goto exit;
2308
+ }
2309
+ num = nla_get_u32(iter);
2310
+ if (num == 0 || num > MAX_BSSID_PREF_LIST_NUM) {
2311
+ WL_ERR(("wrong BSSID num:%d\n", num));
2312
+ err = -EINVAL;
2313
+ goto exit;
2314
+ }
2315
+ if ((bssid_pref = create_bssid_pref_cfg(cfg, num, &buf_len))
2316
+ == NULL) {
2317
+ WL_ERR(("Can't malloc memory\n"));
2318
+ err = -ENOMEM;
14852319 goto exit;
14862320 }
14872321 break;
14882322 case GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH:
1489
- flush = nla_get_u32(iter);
1490
- break;
1491
- case GSCAN_ATTRIBUTE_BSSID_PREF_LIST:
1492
- if (!num)
1493
- return -EINVAL;
1494
- if ((bssid_pref = create_bssid_pref_cfg(num)) == NULL) {
1495
- WL_ERR(("%s: Can't malloc memory\n", __FUNCTION__));
1496
- err = -ENOMEM;
2323
+ if (nla_len(iter) != sizeof(uint32)) {
2324
+ WL_ERR(("nla_len not match\n"));
2325
+ err = -EINVAL;
14972326 goto exit;
14982327 }
1499
- bssid_pref->count = num;
2328
+ flush = nla_get_u32(iter);
2329
+ if (flush != 1) {
2330
+ WL_ERR(("wrong flush value\n"));
2331
+ err = -EINVAL;
2332
+ goto exit;
2333
+ }
2334
+ break;
2335
+ case GSCAN_ATTRIBUTE_BSSID_PREF_LIST:
2336
+ if (!num || !bssid_pref) {
2337
+ WL_ERR(("bssid list count not set\n"));
2338
+ err = -EINVAL;
2339
+ goto exit;
2340
+ }
2341
+ bssid_pref->count = 0;
15002342 bssids = bssid_pref->bssids;
15012343 nla_for_each_nested(outer, iter, tmp) {
1502
- if (i >= num) {
1503
- WL_ERR(("CFGs don't seem right!\n"));
2344
+ if (bssid_pref->count >= num) {
2345
+ WL_ERR(("too many bssid list\n"));
15042346 err = -EINVAL;
15052347 goto exit;
15062348 }
2349
+ bssid_found = 0;
2350
+ rssi_found = 0;
15072351 nla_for_each_nested(inner, outer, tmp1) {
15082352 type = nla_type(inner);
15092353 switch (type) {
1510
- case GSCAN_ATTRIBUTE_BSSID_PREF:
1511
- memcpy(&(bssids[i].bssid),
1512
- nla_data(inner), ETHER_ADDR_LEN);
1513
- /* not used for now */
1514
- bssids[i].flags = 0;
1515
- break;
1516
- case GSCAN_ATTRIBUTE_RSSI_MODIFIER:
1517
- bssids[i].rssi_factor =
1518
- (int8) nla_get_u32(inner);
1519
- break;
2354
+ case GSCAN_ATTRIBUTE_BSSID_PREF:
2355
+ if (nla_len(inner) != ETHER_ADDR_LEN) {
2356
+ WL_ERR(("nla_len not match.\n"));
2357
+ err = -EINVAL;
2358
+ goto exit;
2359
+ }
2360
+ memcpy(&(bssids[bssid_pref->count].bssid),
2361
+ nla_data(inner), ETHER_ADDR_LEN);
2362
+ /* not used for now */
2363
+ bssids[bssid_pref->count].flags = 0;
2364
+ bssid_found = 1;
2365
+ break;
2366
+ case GSCAN_ATTRIBUTE_RSSI_MODIFIER:
2367
+ if (nla_len(inner) != sizeof(uint32)) {
2368
+ WL_ERR(("nla_len not match.\n"));
2369
+ err = -EINVAL;
2370
+ goto exit;
2371
+ }
2372
+ bssids[bssid_pref->count].rssi_factor =
2373
+ (int8) nla_get_u32(inner);
2374
+ rssi_found = 1;
2375
+ break;
2376
+ default:
2377
+ WL_ERR(("wrong type:%d\n", type));
2378
+ err = -EINVAL;
2379
+ goto exit;
2380
+ }
2381
+ if (bssid_found && rssi_found) {
2382
+ break;
15202383 }
15212384 }
1522
- i++;
2385
+ bssid_pref->count++;
15232386 }
15242387 break;
15252388 default:
....@@ -1531,7 +2394,7 @@
15312394 if (!bssid_pref) {
15322395 /* What if only flush is desired? */
15332396 if (flush) {
1534
- if ((bssid_pref = create_bssid_pref_cfg(0)) == NULL) {
2397
+ if ((bssid_pref = create_bssid_pref_cfg(cfg, 0, &buf_len)) == NULL) {
15352398 WL_ERR(("%s: Can't malloc memory\n", __FUNCTION__));
15362399 err = -ENOMEM;
15372400 goto exit;
....@@ -1545,11 +2408,13 @@
15452408 err = dhd_dev_set_lazy_roam_bssid_pref(bcmcfg_to_prmry_ndev(cfg),
15462409 bssid_pref, flush);
15472410 exit:
1548
- kfree(bssid_pref);
2411
+ if (bssid_pref) {
2412
+ MFREE(cfg->osh, bssid_pref, buf_len);
2413
+ }
15492414 return err;
15502415 }
1551
-
1552
-
2416
+#endif /* GSCAN_SUPPORT */
2417
+#if defined(GSCAN_SUPPORT) || defined(ROAMEXP_SUPPORT)
15532418 static int
15542419 wl_cfgvendor_set_bssid_blacklist(struct wiphy *wiphy,
15552420 struct wireless_dev *wdev, const void *data, int len)
....@@ -1559,57 +2424,92 @@
15592424 int err = 0;
15602425 int type, tmp;
15612426 const struct nlattr *iter;
1562
- uint32 mem_needed = 0, flush = 0, i = 0, num = 0;
2427
+ uint32 mem_needed = 0, flush = 0, num = 0;
15632428
15642429 /* Assumption: NUM attribute must come first */
15652430 nla_for_each_attr(iter, data, len, tmp) {
15662431 type = nla_type(iter);
15672432 switch (type) {
15682433 case GSCAN_ATTRIBUTE_NUM_BSSID:
2434
+ if (num != 0) {
2435
+ WL_ERR(("attempt to change BSSID num\n"));
2436
+ err = -EINVAL;
2437
+ goto exit;
2438
+ }
2439
+ if (nla_len(iter) != sizeof(uint32)) {
2440
+ WL_ERR(("not matching nla_len.\n"));
2441
+ err = -EINVAL;
2442
+ goto exit;
2443
+ }
15692444 num = nla_get_u32(iter);
1570
- if (num > MAX_BSSID_BLACKLIST_NUM) {
1571
- WL_ERR(("Too many Blacklist BSSIDs!\n"));
2445
+ if (num == 0 || num > MAX_BSSID_BLACKLIST_NUM) {
2446
+ WL_ERR(("wrong BSSID count:%d\n", num));
2447
+ err = -EINVAL;
2448
+ goto exit;
2449
+ }
2450
+ if (!blacklist) {
2451
+ mem_needed = OFFSETOF(maclist_t, ea) +
2452
+ sizeof(struct ether_addr) * (num);
2453
+ blacklist = (maclist_t *)
2454
+ MALLOCZ(cfg->osh, mem_needed);
2455
+ if (!blacklist) {
2456
+ WL_ERR(("MALLOCZ failed.\n"));
2457
+ err = -ENOMEM;
2458
+ goto exit;
2459
+ }
2460
+ }
2461
+ break;
2462
+ case GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH:
2463
+ if (nla_len(iter) != sizeof(uint32)) {
2464
+ WL_ERR(("not matching nla_len.\n"));
2465
+ err = -EINVAL;
2466
+ goto exit;
2467
+ }
2468
+ flush = nla_get_u32(iter);
2469
+ if (flush != 1) {
2470
+ WL_ERR(("flush arg is worng:%d\n", flush));
15722471 err = -EINVAL;
15732472 goto exit;
15742473 }
15752474 break;
1576
- case GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH:
1577
- flush = nla_get_u32(iter);
1578
- break;
15792475 case GSCAN_ATTRIBUTE_BLACKLIST_BSSID:
1580
- if (num) {
1581
- if (!blacklist) {
1582
- mem_needed = sizeof(maclist_t) +
1583
- sizeof(struct ether_addr) * (num - 1);
1584
- blacklist = (maclist_t *)
1585
- kmalloc(mem_needed, GFP_KERNEL);
1586
- if (!blacklist) {
1587
- WL_ERR(("%s: Can't malloc %d bytes\n",
1588
- __FUNCTION__, mem_needed));
1589
- err = -ENOMEM;
1590
- goto exit;
1591
- }
1592
- blacklist->count = num;
1593
- }
1594
- if (i >= num) {
1595
- WL_ERR(("CFGs don't seem right!\n"));
1596
- err = -EINVAL;
1597
- goto exit;
1598
- }
1599
- memcpy(&(blacklist->ea[i]),
1600
- nla_data(iter), ETHER_ADDR_LEN);
1601
- i++;
2476
+ if (num == 0 || !blacklist) {
2477
+ WL_ERR(("number of BSSIDs not received.\n"));
2478
+ err = -EINVAL;
2479
+ goto exit;
16022480 }
2481
+ if (nla_len(iter) != ETHER_ADDR_LEN) {
2482
+ WL_ERR(("not matching nla_len.\n"));
2483
+ err = -EINVAL;
2484
+ goto exit;
2485
+ }
2486
+ if (blacklist->count >= num) {
2487
+ WL_ERR(("too many BSSIDs than expected:%d\n",
2488
+ blacklist->count));
2489
+ err = -EINVAL;
2490
+ goto exit;
2491
+ }
2492
+ memcpy(&(blacklist->ea[blacklist->count]), nla_data(iter),
2493
+ ETHER_ADDR_LEN);
2494
+ blacklist->count++;
16032495 break;
1604
- default:
1605
- WL_ERR(("%s: No such attribute %d\n", __FUNCTION__, type));
1606
- break;
1607
- }
2496
+ default:
2497
+ WL_ERR(("No such attribute:%d\n", type));
2498
+ break;
2499
+ }
16082500 }
2501
+
2502
+ if (blacklist && (blacklist->count != num)) {
2503
+ WL_ERR(("not matching bssid count:%d to expected:%d\n",
2504
+ blacklist->count, num));
2505
+ err = -EINVAL;
2506
+ goto exit;
2507
+ }
2508
+
16092509 err = dhd_dev_set_blacklist_bssid(bcmcfg_to_prmry_ndev(cfg),
16102510 blacklist, mem_needed, flush);
16112511 exit:
1612
- kfree(blacklist);
2512
+ MFREE(cfg->osh, blacklist, mem_needed);
16132513 return err;
16142514 }
16152515
....@@ -1621,208 +2521,199 @@
16212521 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
16222522 wl_ssid_whitelist_t *ssid_whitelist = NULL;
16232523 wlc_ssid_t *ssid_elem;
1624
- int tmp, tmp2, mem_needed = 0, type;
1625
- const struct nlattr *inner, *iter;
1626
- uint32 flush = 0, i = 0, num = 0;
2524
+ int tmp, tmp1, mem_needed = 0, type;
2525
+ const struct nlattr *iter, *iter1;
2526
+ uint32 flush = 0, num = 0;
2527
+ int ssid_found = 0;
16272528
16282529 /* Assumption: NUM attribute must come first */
1629
- nla_for_each_attr(iter, data, len, tmp2) {
1630
- type = nla_type(iter);
1631
- switch (type) {
1632
- case GSCAN_ATTRIBUTE_NUM_WL_SSID:
1633
- num = nla_get_u32(iter);
1634
- if (num > MAX_SSID_WHITELIST_NUM) {
1635
- WL_ERR(("Too many WL SSIDs!\n"));
1636
- err = -EINVAL;
1637
- goto exit;
1638
- }
1639
- mem_needed = sizeof(wl_ssid_whitelist_t);
1640
- if (num)
1641
- mem_needed += (num - 1) * sizeof(ssid_info_t);
1642
- ssid_whitelist = (wl_ssid_whitelist_t *)
1643
- kzalloc(mem_needed, GFP_KERNEL);
1644
- if (ssid_whitelist == NULL) {
1645
- WL_ERR(("%s: Can't malloc %d bytes\n",
1646
- __FUNCTION__, mem_needed));
1647
- err = -ENOMEM;
1648
- goto exit;
1649
- }
1650
- ssid_whitelist->ssid_count = num;
1651
- break;
1652
- case GSCAN_ATTRIBUTE_WL_SSID_FLUSH:
1653
- flush = nla_get_u32(iter);
1654
- break;
1655
- case GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM:
1656
- if (!num || !ssid_whitelist) {
1657
- WL_ERR(("num ssid is not set!\n"));
1658
- return -EINVAL;
1659
- }
1660
- if (i >= num) {
1661
- WL_ERR(("CFGs don't seem right!\n"));
1662
- err = -EINVAL;
1663
- goto exit;
1664
- }
1665
- ssid_elem = &ssid_whitelist->ssids[i];
1666
- nla_for_each_nested(inner, iter, tmp) {
1667
- type = nla_type(inner);
1668
- switch (type) {
1669
- case GSCAN_ATTRIBUTE_WHITELIST_SSID:
1670
- memcpy(ssid_elem->SSID,
1671
- nla_data(inner),
1672
- DOT11_MAX_SSID_LEN);
1673
- break;
1674
- case GSCAN_ATTRIBUTE_WL_SSID_LEN:
1675
- ssid_elem->SSID_len = (uint8)
1676
- nla_get_u32(inner);
1677
- break;
1678
- }
1679
- }
1680
- i++;
1681
- break;
1682
- default:
1683
- WL_ERR(("%s: No such attribute %d\n", __FUNCTION__, type));
1684
- break;
1685
- }
1686
- }
1687
-
1688
- err = dhd_dev_set_whitelist_ssid(bcmcfg_to_prmry_ndev(cfg),
1689
- ssid_whitelist, mem_needed, flush);
1690
-exit:
1691
- kfree(ssid_whitelist);
1692
- return err;
1693
-}
1694
-#endif /* GSCAN_SUPPORT */
1695
-
1696
-#if defined(KEEP_ALIVE)
1697
-static int wl_cfgvendor_start_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev,
1698
- const void *data, int len)
1699
-{
1700
- /* max size of IP packet for keep alive */
1701
- const int MKEEP_ALIVE_IP_PKT_MAX = 256;
1702
-
1703
- int ret = BCME_OK, rem, type;
1704
- u8 mkeep_alive_id = 0;
1705
- u8 *ip_pkt = NULL;
1706
- u16 ip_pkt_len = 0;
1707
- u8 src_mac[ETHER_ADDR_LEN];
1708
- u8 dst_mac[ETHER_ADDR_LEN];
1709
- u32 period_msec = 0;
1710
- const struct nlattr *iter;
1711
- struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1712
- dhd_pub_t *dhd_pub = cfg->pub;
1713
- gfp_t kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
1714
-
1715
- nla_for_each_attr(iter, data, len, rem) {
1716
- type = nla_type(iter);
1717
- switch (type) {
1718
- case MKEEP_ALIVE_ATTRIBUTE_ID:
1719
- mkeep_alive_id = nla_get_u8(iter);
1720
- break;
1721
- case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN:
1722
- ip_pkt_len = nla_get_u16(iter);
1723
- if (ip_pkt_len > MKEEP_ALIVE_IP_PKT_MAX) {
1724
- ret = BCME_BADARG;
1725
- goto exit;
1726
- }
1727
- break;
1728
- case MKEEP_ALIVE_ATTRIBUTE_IP_PKT:
1729
- ip_pkt = (u8 *)kzalloc(ip_pkt_len, kflags);
1730
- if (ip_pkt == NULL) {
1731
- ret = BCME_NOMEM;
1732
- WL_ERR(("Failed to allocate mem for ip packet\n"));
1733
- goto exit;
1734
- }
1735
- memcpy(ip_pkt, (u8*)nla_data(iter), ip_pkt_len);
1736
- break;
1737
- case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR:
1738
- memcpy(src_mac, nla_data(iter), ETHER_ADDR_LEN);
1739
- break;
1740
- case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR:
1741
- memcpy(dst_mac, nla_data(iter), ETHER_ADDR_LEN);
1742
- break;
1743
- case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC:
1744
- period_msec = nla_get_u32(iter);
1745
- break;
1746
- default:
1747
- WL_ERR(("Unknown type: %d\n", type));
1748
- ret = BCME_BADARG;
1749
- goto exit;
1750
- }
1751
- }
1752
-
1753
- ret = dhd_dev_start_mkeep_alive(dhd_pub, mkeep_alive_id, ip_pkt, ip_pkt_len, src_mac,
1754
- dst_mac, period_msec);
1755
- if (ret < 0) {
1756
- WL_ERR(("start_mkeep_alive is failed ret: %d\n", ret));
1757
- }
1758
-
1759
-exit:
1760
- if (ip_pkt) {
1761
- kfree(ip_pkt);
1762
- }
1763
-
1764
- return ret;
1765
-}
1766
-
1767
-static int wl_cfgvendor_stop_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev,
1768
- const void *data, int len)
1769
-{
1770
- int ret = BCME_OK, rem, type;
1771
- u8 mkeep_alive_id = 0;
1772
- const struct nlattr *iter;
1773
- struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1774
- dhd_pub_t *dhd_pub = cfg->pub;
1775
-
1776
- nla_for_each_attr(iter, data, len, rem) {
1777
- type = nla_type(iter);
1778
- switch (type) {
1779
- case MKEEP_ALIVE_ATTRIBUTE_ID:
1780
- mkeep_alive_id = nla_get_u8(iter);
1781
- break;
1782
- default:
1783
- WL_ERR(("Unknown type: %d\n", type));
1784
- ret = BCME_BADARG;
1785
- break;
1786
- }
1787
- }
1788
-
1789
- ret = dhd_dev_stop_mkeep_alive(dhd_pub, mkeep_alive_id);
1790
- if (ret < 0) {
1791
- WL_ERR(("stop_mkeep_alive is failed ret: %d\n", ret));
1792
- }
1793
-
1794
- return ret;
1795
-}
1796
-#endif /* defined(KEEP_ALIVE) */
1797
-
1798
-static int wl_cfgvendor_set_rssi_monitor(struct wiphy *wiphy,
1799
- struct wireless_dev *wdev, const void *data, int len)
1800
-{
1801
- int err = 0, tmp, type, start = 0;
1802
- struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1803
- int8 max_rssi = 0, min_rssi = 0;
1804
- const struct nlattr *iter;
18052530 nla_for_each_attr(iter, data, len, tmp) {
18062531 type = nla_type(iter);
18072532 switch (type) {
1808
- case RSSI_MONITOR_ATTRIBUTE_MAX_RSSI:
1809
- max_rssi = (int8) nla_get_u32(iter);
1810
- break;
1811
- case RSSI_MONITOR_ATTRIBUTE_MIN_RSSI:
1812
- min_rssi = (int8) nla_get_u32(iter);
1813
- break;
1814
- case RSSI_MONITOR_ATTRIBUTE_START:
1815
- start = nla_get_u32(iter);
2533
+ case GSCAN_ATTRIBUTE_NUM_WL_SSID:
2534
+ if (num != 0) {
2535
+ WL_ERR(("try to change SSID num\n"));
2536
+ err = -EINVAL;
2537
+ goto exit;
2538
+ }
2539
+ if (nla_len(iter) != sizeof(uint32)) {
2540
+ WL_ERR(("not matching nla_len.\n"));
2541
+ err = -EINVAL;
2542
+ goto exit;
2543
+ }
2544
+ num = nla_get_u32(iter);
2545
+ if (num == 0 || num > MAX_SSID_WHITELIST_NUM) {
2546
+ WL_ERR(("wrong SSID count:%d\n", num));
2547
+ err = -EINVAL;
2548
+ goto exit;
2549
+ }
2550
+ mem_needed = sizeof(wl_ssid_whitelist_t) +
2551
+ sizeof(wlc_ssid_t) * num;
2552
+ ssid_whitelist = (wl_ssid_whitelist_t *)
2553
+ MALLOCZ(cfg->osh, mem_needed);
2554
+ if (ssid_whitelist == NULL) {
2555
+ WL_ERR(("failed to alloc mem\n"));
2556
+ err = -ENOMEM;
2557
+ goto exit;
2558
+ }
2559
+ break;
2560
+ case GSCAN_ATTRIBUTE_WL_SSID_FLUSH:
2561
+ if (nla_len(iter) != sizeof(uint32)) {
2562
+ WL_ERR(("not matching nla_len.\n"));
2563
+ err = -EINVAL;
2564
+ goto exit;
2565
+ }
2566
+ flush = nla_get_u32(iter);
2567
+ if (flush != 1) {
2568
+ WL_ERR(("flush arg worng:%d\n", flush));
2569
+ err = -EINVAL;
2570
+ goto exit;
2571
+ }
2572
+ break;
2573
+ case GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM:
2574
+ if (!num || !ssid_whitelist) {
2575
+ WL_ERR(("num ssid is not set!\n"));
2576
+ err = -EINVAL;
2577
+ goto exit;
2578
+ }
2579
+ if (ssid_whitelist->ssid_count >= num) {
2580
+ WL_ERR(("too many SSIDs:%d\n",
2581
+ ssid_whitelist->ssid_count));
2582
+ err = -EINVAL;
2583
+ goto exit;
2584
+ }
2585
+
2586
+ ssid_elem = &ssid_whitelist->ssids[
2587
+ ssid_whitelist->ssid_count];
2588
+ ssid_found = 0;
2589
+ nla_for_each_nested(iter1, iter, tmp1) {
2590
+ type = nla_type(iter1);
2591
+ switch (type) {
2592
+ case GSCAN_ATTRIBUTE_WL_SSID_LEN:
2593
+ if (nla_len(iter1) != sizeof(uint32)) {
2594
+ WL_ERR(("not match nla_len\n"));
2595
+ err = -EINVAL;
2596
+ goto exit;
2597
+ }
2598
+ ssid_elem->SSID_len = nla_get_u32(iter1);
2599
+ if (ssid_elem->SSID_len >
2600
+ DOT11_MAX_SSID_LEN) {
2601
+ WL_ERR(("wrong SSID len:%d\n",
2602
+ ssid_elem->SSID_len));
2603
+ err = -EINVAL;
2604
+ goto exit;
2605
+ }
2606
+ break;
2607
+ case GSCAN_ATTRIBUTE_WHITELIST_SSID:
2608
+ if (ssid_elem->SSID_len == 0) {
2609
+ WL_ERR(("SSID_len not received\n"));
2610
+ err = -EINVAL;
2611
+ goto exit;
2612
+ }
2613
+ if (nla_len(iter1) != ssid_elem->SSID_len) {
2614
+ WL_ERR(("not match nla_len\n"));
2615
+ err = -EINVAL;
2616
+ goto exit;
2617
+ }
2618
+ memcpy(ssid_elem->SSID, nla_data(iter1),
2619
+ ssid_elem->SSID_len);
2620
+ ssid_found = 1;
2621
+ break;
2622
+ }
2623
+ if (ssid_found) {
2624
+ ssid_whitelist->ssid_count++;
2625
+ break;
2626
+ }
2627
+ }
2628
+ break;
2629
+ default:
2630
+ WL_ERR(("No such attribute: %d\n", type));
2631
+ break;
18162632 }
18172633 }
18182634
1819
- if (dhd_dev_set_rssi_monitor_cfg(bcmcfg_to_prmry_ndev(cfg),
1820
- start, max_rssi, min_rssi) < 0) {
1821
- WL_ERR(("Could not set rssi monitor cfg\n"));
2635
+ if (ssid_whitelist && (ssid_whitelist->ssid_count != num)) {
2636
+ WL_ERR(("not matching ssid count:%d to expected:%d\n",
2637
+ ssid_whitelist->ssid_count, num));
18222638 err = -EINVAL;
2639
+ goto exit;
18232640 }
2641
+ err = dhd_dev_set_whitelist_ssid(bcmcfg_to_prmry_ndev(cfg),
2642
+ ssid_whitelist, mem_needed, flush);
2643
+exit:
2644
+ MFREE(cfg->osh, ssid_whitelist, mem_needed);
18242645 return err;
18252646 }
2647
+#endif /* GSCAN_SUPPORT || ROAMEXP_SUPPORT */
2648
+
2649
+#ifdef ROAMEXP_SUPPORT
2650
+typedef enum {
2651
+ FW_ROAMING_ENABLE = 1,
2652
+ FW_ROAMING_DISABLE,
2653
+ FW_ROAMING_PAUSE,
2654
+ FW_ROAMING_RESUME
2655
+} fw_roaming_state_t;
2656
+
2657
+static int
2658
+wl_cfgvendor_set_fw_roaming_state(struct wiphy *wiphy,
2659
+ struct wireless_dev *wdev, const void *data, int len)
2660
+{
2661
+ fw_roaming_state_t requested_roaming_state;
2662
+ int type;
2663
+ int err = 0;
2664
+
2665
+ if (!data) {
2666
+ WL_ERR(("data is not available\n"));
2667
+ return -EINVAL;
2668
+ }
2669
+
2670
+ if (len <= 0) {
2671
+ WL_ERR(("invalid len %d\n", len));
2672
+ return -EINVAL;
2673
+ }
2674
+
2675
+ /* Get the requested fw roaming state */
2676
+ type = nla_type(data);
2677
+ if (type != GSCAN_ATTRIBUTE_ROAM_STATE_SET) {
2678
+ WL_ERR(("%s: Invalid attribute %d\n", __FUNCTION__, type));
2679
+ return -EINVAL;
2680
+ }
2681
+
2682
+ requested_roaming_state = nla_get_u32(data);
2683
+ WL_INFORM(("setting FW roaming state to %d\n", requested_roaming_state));
2684
+
2685
+ if ((requested_roaming_state == FW_ROAMING_ENABLE) ||
2686
+ (requested_roaming_state == FW_ROAMING_RESUME)) {
2687
+ err = wldev_iovar_setint(wdev_to_ndev(wdev), "roam_off", FALSE);
2688
+ } else if ((requested_roaming_state == FW_ROAMING_DISABLE) ||
2689
+ (requested_roaming_state == FW_ROAMING_PAUSE)) {
2690
+ err = wldev_iovar_setint(wdev_to_ndev(wdev), "roam_off", TRUE);
2691
+ } else {
2692
+ err = -EINVAL;
2693
+ }
2694
+
2695
+ return err;
2696
+}
2697
+
2698
+static int
2699
+wl_cfgvendor_fw_roam_get_capability(struct wiphy *wiphy,
2700
+ struct wireless_dev *wdev, const void *data, int len)
2701
+{
2702
+ int err = 0;
2703
+ wifi_roaming_capabilities_t roaming_capability;
2704
+
2705
+ /* Update max number of blacklist bssids supported */
2706
+ roaming_capability.max_blacklist_size = MAX_BSSID_BLACKLIST_NUM;
2707
+ roaming_capability.max_whitelist_size = MAX_SSID_WHITELIST_NUM;
2708
+ err = wl_cfgvendor_send_cmd_reply(wiphy, &roaming_capability,
2709
+ sizeof(roaming_capability));
2710
+ if (unlikely(err)) {
2711
+ WL_ERR(("Vendor cmd reply for fw roam capability failed ret:%d \n", err));
2712
+ }
2713
+
2714
+ return err;
2715
+}
2716
+#endif /* ROAMEXP_SUPPORT */
18262717
18272718 static int
18282719 wl_cfgvendor_priv_string_handler(struct wiphy *wiphy,
....@@ -1835,27 +2726,56 @@
18352726 void *buf = NULL, *cur;
18362727 int maxmsglen = PAGE_SIZE - 0x100;
18372728 struct sk_buff *reply;
2729
+#if defined(OEM_ANDROID)
2730
+ dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(wdev->netdev);
18382731
1839
- WL_ERR(("entry: cmd = %d\n", nlioc->cmd));
2732
+ /* send to dongle only if we are not waiting for reload already */
2733
+ if (dhdp && dhdp->hang_was_sent) {
2734
+ WL_INFORM(("Bus down. HANG was sent up earlier\n"));
2735
+ DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp, DHD_EVENT_TIMEOUT_MS);
2736
+ DHD_OS_WAKE_UNLOCK(dhdp);
2737
+ return OSL_ERROR(BCME_DONGLE_DOWN);
2738
+ }
2739
+#endif /* (OEM_ANDROID) */
18402740
2741
+ if (!data) {
2742
+ WL_ERR(("data is not available\n"));
2743
+ return BCME_BADARG;
2744
+ }
2745
+
2746
+ if (len <= 0) {
2747
+ WL_ERR(("invalid len %d\n", len));
2748
+ return BCME_BADARG;
2749
+ }
2750
+
2751
+ WL_DBG(("entry: cmd = %d\n", nlioc->cmd));
2752
+
2753
+ if (nlioc->offset != sizeof(struct bcm_nlmsg_hdr) ||
2754
+ len <= sizeof(struct bcm_nlmsg_hdr)) {
2755
+ WL_ERR(("invalid offset %d\n", nlioc->offset));
2756
+ return BCME_BADARG;
2757
+ }
18412758 len -= sizeof(struct bcm_nlmsg_hdr);
18422759 ret_len = nlioc->len;
18432760 if (ret_len > 0 || len > 0) {
1844
- if (len > DHD_IOCTL_MAXLEN) {
2761
+ if (len >= DHD_IOCTL_MAXLEN) {
18452762 WL_ERR(("oversize input buffer %d\n", len));
1846
- len = DHD_IOCTL_MAXLEN;
2763
+ len = DHD_IOCTL_MAXLEN - 1;
18472764 }
1848
- if (ret_len > DHD_IOCTL_MAXLEN) {
2765
+ if (ret_len >= DHD_IOCTL_MAXLEN) {
18492766 WL_ERR(("oversize return buffer %d\n", ret_len));
1850
- ret_len = DHD_IOCTL_MAXLEN;
2767
+ ret_len = DHD_IOCTL_MAXLEN - 1;
18512768 }
2769
+
18522770 payload = max(ret_len, len) + 1;
18532771 buf = vzalloc(payload);
18542772 if (!buf) {
18552773 return -ENOMEM;
18562774 }
1857
- memcpy(buf, (void *)nlioc + nlioc->offset, len);
1858
- *(char *)(buf + len) = '\0';
2775
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
2776
+ memcpy(buf, (void *)((char *)nlioc + nlioc->offset), len);
2777
+ GCC_DIAGNOSTIC_POP();
2778
+ *((char *)buf + len) = '\0';
18592779 }
18602780
18612781 ret = dhd_cfgvendor_priv_string_handler(cfg, wdev, nlioc, buf);
....@@ -1866,7 +2786,7 @@
18662786 }
18672787 cur = buf;
18682788 while (ret_len > 0) {
1869
- msglen = nlioc->len > maxmsglen ? maxmsglen : ret_len;
2789
+ msglen = ret_len > maxmsglen ? maxmsglen : ret_len;
18702790 ret_len -= msglen;
18712791 payload = msglen + sizeof(msglen);
18722792 reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
....@@ -1888,7 +2808,7 @@
18882808 WL_ERR(("testmode reply failed:%d\n", ret));
18892809 break;
18902810 }
1891
- cur += msglen;
2811
+ cur = (void *)((char *)cur + msglen);
18922812 }
18932813
18942814 return ret;
....@@ -1896,12 +2816,13 @@
18962816
18972817 struct net_device *
18982818 wl_cfgvendor_get_ndev(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev,
1899
- const void *data, unsigned long int *out_addr)
2819
+ const char *data, unsigned long int *out_addr)
19002820 {
19012821 char *pos, *pos1;
19022822 char ifname[IFNAMSIZ + 1] = {0};
19032823 struct net_info *iter, *next;
19042824 struct net_device *ndev = NULL;
2825
+ ulong ifname_len;
19052826 *out_addr = (unsigned long int) data; /* point to command str by default */
19062827
19072828 /* check whether ifname=<ifname> is provided in the command */
....@@ -1913,7 +2834,13 @@
19132834 WL_ERR(("command format error \n"));
19142835 return NULL;
19152836 }
1916
- memcpy(ifname, pos, (pos1 - pos));
2837
+
2838
+ ifname_len = pos1 - pos;
2839
+ if (memcpy_s(ifname, (sizeof(ifname) - 1), pos, ifname_len) != BCME_OK) {
2840
+ WL_ERR(("Failed to copy data. len: %ld\n", ifname_len));
2841
+ return NULL;
2842
+ }
2843
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
19172844 for_each_ndev(cfg, iter, next) {
19182845 if (iter->ndev) {
19192846 if (strncmp(iter->ndev->name, ifname,
....@@ -1926,8 +2853,8 @@
19262853 return iter->ndev;
19272854 }
19282855 }
1929
-
19302856 }
2857
+ GCC_DIAGNOSTIC_POP();
19312858 WL_ERR(("Couldn't find ifname:%s in the netinfo list \n",
19322859 ifname));
19332860 return NULL;
....@@ -1939,6 +2866,53 @@
19392866 return ndev;
19402867 }
19412868
2869
+#ifdef WL_SAE
2870
+static int
2871
+wl_cfgvendor_set_sae_password(struct wiphy *wiphy,
2872
+ struct wireless_dev *wdev, const void *data, int len)
2873
+{
2874
+ int err = BCME_OK;
2875
+ struct net_device *net = wdev->netdev;
2876
+ struct bcm_cfg80211 *cfg = wl_get_cfg(net);
2877
+ wsec_pmk_t pmk;
2878
+ s32 bssidx;
2879
+
2880
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, net->ieee80211_ptr)) < 0) {
2881
+ WL_ERR(("Find p2p index from wdev(%p) failed\n", net->ieee80211_ptr));
2882
+ return BCME_ERROR;
2883
+ }
2884
+
2885
+ if (len < WSEC_MIN_PSK_LEN || len >= WSEC_MAX_PSK_LEN) {
2886
+ WL_ERR(("Invalid passphrase length %d..should be >=8 and <=63\n",
2887
+ len));
2888
+ err = BCME_BADLEN;
2889
+ goto done;
2890
+ }
2891
+ /* Set AUTH to SAE */
2892
+ err = wldev_iovar_setint_bsscfg(net, "wpa_auth", WPA3_AUTH_SAE_PSK, bssidx);
2893
+ if (unlikely(err)) {
2894
+ WL_ERR(("could not set wpa_auth (0x%x)\n", err));
2895
+ goto done;
2896
+ }
2897
+ pmk.key_len = htod16(len);
2898
+ bcopy((const u8*)data, pmk.key, len);
2899
+ pmk.flags = htod16(WSEC_PASSPHRASE);
2900
+
2901
+ err = wldev_ioctl_set(net, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk));
2902
+ if (err) {
2903
+ WL_ERR(("\n failed to set pmk %d\n", err));
2904
+ goto done;
2905
+ } else {
2906
+ WL_MEM(("sae passphrase set successfully\n"));
2907
+ }
2908
+done:
2909
+ return err;
2910
+}
2911
+#endif /* WL_SAE */
2912
+
2913
+#ifdef BCM_PRIV_CMD_SUPPORT
2914
+/* strlen("ifname=") + IFNAMESIZE + strlen(" ") + '\0' */
2915
+#define ANDROID_PRIV_CMD_IF_PREFIX_LEN (7 + IFNAMSIZ + 2)
19422916 /* Max length for the reply buffer. For BRCM_ATTR_DRIVER_CMD, the reply
19432917 * would be a formatted string and reply buf would be the size of the
19442918 * string.
....@@ -1948,18 +2922,22 @@
19482922 wl_cfgvendor_priv_bcm_handler(struct wiphy *wiphy,
19492923 struct wireless_dev *wdev, const void *data, int len)
19502924 {
1951
- struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
19522925 const struct nlattr *iter;
19532926 int err = 0;
19542927 int data_len = 0, cmd_len = 0, tmp = 0, type = 0;
1955
- char *cmd = NULL;
1956
- int bytes_written;
1957
- char *reply_buf = NULL;
1958
- struct net_device *net = NULL;
19592928 struct net_device *ndev = wdev->netdev;
2929
+ char *cmd = NULL;
2930
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2931
+ int bytes_written;
2932
+ struct net_device *net = NULL;
19602933 unsigned long int cmd_out = 0;
1961
- u32 reply_len = WL_DRIVER_PRIV_CMD_LEN;
1962
-
2934
+#if defined(WL_ANDROID_PRIV_CMD_OVER_NL80211) && defined(OEM_ANDROID)
2935
+ u32 cmd_buf_len = WL_DRIVER_PRIV_CMD_LEN;
2936
+ char cmd_prefix[ANDROID_PRIV_CMD_IF_PREFIX_LEN + 1] = {0};
2937
+ char *cmd_buf = NULL;
2938
+ char *current_pos;
2939
+ u32 cmd_offset;
2940
+#endif /* WL_ANDROID_PRIV_CMD_OVER_NL80211 && OEM_ANDROID */
19632941
19642942 WL_DBG(("%s: Enter \n", __func__));
19652943
....@@ -1971,207 +2949,3805 @@
19712949 cmd = nla_data(iter);
19722950 cmd_len = nla_len(iter);
19732951
1974
- WL_DBG(("%s: type: %d len:%d\n", __func__, type, cmd_len));
2952
+ WL_DBG(("%s: type: %d cmd_len:%d cmd_ptr:%p \n", __func__, type, cmd_len, cmd));
2953
+ if (!cmd || !cmd_len) {
2954
+ WL_ERR(("Invalid cmd data \n"));
2955
+ err = -EINVAL;
2956
+ goto exit;
2957
+ }
2958
+
2959
+#if defined(WL_ANDROID_PRIV_CMD_OVER_NL80211) && defined(OEM_ANDROID)
19752960 if (type == BRCM_ATTR_DRIVER_CMD) {
1976
- if (cmd_len >= WL_DRIVER_PRIV_CMD_LEN) {
1977
- WL_ERR(("Unexpected command length. Ignore the command\n"));
2961
+ if ((cmd_len >= WL_DRIVER_PRIV_CMD_LEN) ||
2962
+ (cmd_len < ANDROID_PRIV_CMD_IF_PREFIX_LEN)) {
2963
+ WL_ERR(("Unexpected command length (%u)."
2964
+ "Ignore the command\n", cmd_len));
19782965 err = -EINVAL;
19792966 goto exit;
19802967 }
1981
- net = wl_cfgvendor_get_ndev(cfg, wdev, cmd, &cmd_out);
1982
- if (!cmd_out || !net) {
1983
- err = -ENODEV;
1984
- goto exit;
1985
- }
1986
- cmd = (char *)cmd_out;
1987
- reply_buf = kzalloc(reply_len, GFP_KERNEL);
1988
- if (!reply_buf) {
1989
- WL_ERR(("memory alloc failed for %u \n", cmd_len));
2968
+
2969
+ /* check whether there is any ifname prefix provided */
2970
+ if (memcpy_s(cmd_prefix, (sizeof(cmd_prefix) - 1),
2971
+ cmd, ANDROID_PRIV_CMD_IF_PREFIX_LEN) != BCME_OK) {
2972
+ WL_ERR(("memcpy failed for cmd buffer. len:%d\n", cmd_len));
19902973 err = -ENOMEM;
19912974 goto exit;
19922975 }
1993
- memcpy(reply_buf, cmd, cmd_len);
1994
- WL_DBG(("vendor_command: %s len: %u \n", cmd, cmd_len));
1995
- bytes_written = wl_handle_private_cmd(net, reply_buf, reply_len);
2976
+
2977
+ net = wl_cfgvendor_get_ndev(cfg, wdev, cmd_prefix, &cmd_out);
2978
+ if (!cmd_out || !net) {
2979
+ WL_ERR(("ndev not found\n"));
2980
+ err = -ENODEV;
2981
+ goto exit;
2982
+ }
2983
+
2984
+ /* find offset of the command */
2985
+ current_pos = (char *)cmd_out;
2986
+ cmd_offset = current_pos - cmd_prefix;
2987
+
2988
+ if (!current_pos || (cmd_offset) > ANDROID_PRIV_CMD_IF_PREFIX_LEN) {
2989
+ WL_ERR(("Invalid len cmd_offset: %u \n", cmd_offset));
2990
+ err = -EINVAL;
2991
+ goto exit;
2992
+ }
2993
+
2994
+ /* Private command data in expected to be in str format. To ensure that
2995
+ * the data is null terminated, copy to a local buffer before use
2996
+ */
2997
+ cmd_buf = (char *)MALLOCZ(cfg->osh, cmd_buf_len);
2998
+ if (!cmd_buf) {
2999
+ WL_ERR(("memory alloc failed for %u \n", cmd_buf_len));
3000
+ err = -ENOMEM;
3001
+ goto exit;
3002
+ }
3003
+
3004
+ /* Point to the start of command */
3005
+ if (memcpy_s(cmd_buf, (WL_DRIVER_PRIV_CMD_LEN - 1),
3006
+ (const void *)(cmd + cmd_offset),
3007
+ (cmd_len - cmd_offset - 1)) != BCME_OK) {
3008
+ WL_ERR(("memcpy failed for cmd buffer. len:%d\n", cmd_len));
3009
+ err = -ENOMEM;
3010
+ goto exit;
3011
+ }
3012
+ cmd_buf[WL_DRIVER_PRIV_CMD_LEN - 1] = '\0';
3013
+
3014
+ WL_DBG(("vendor_command: %s len: %u \n", cmd_buf, cmd_buf_len));
3015
+ bytes_written = wl_handle_private_cmd(net, cmd_buf, cmd_buf_len);
19963016 WL_DBG(("bytes_written: %d \n", bytes_written));
19973017 if (bytes_written == 0) {
1998
- sprintf(reply_buf, "%s", "OK");
1999
- data_len = strlen("OK");
3018
+ snprintf(cmd_buf, cmd_buf_len, "%s", "OK");
3019
+ data_len = sizeof("OK");
20003020 } else if (bytes_written > 0) {
2001
- data_len = bytes_written > reply_len ?
2002
- reply_len : bytes_written;
3021
+ if (bytes_written >= (cmd_buf_len - 1)) {
3022
+ /* Not expected */
3023
+ ASSERT(0);
3024
+ err = -EINVAL;
3025
+ goto exit;
3026
+ }
3027
+ data_len = bytes_written;
20033028 } else {
20043029 /* -ve return value. Propagate the error back */
20053030 err = bytes_written;
20063031 goto exit;
20073032 }
3033
+ if ((data_len > 0) && (data_len < (cmd_buf_len - 1)) && cmd_buf) {
3034
+ err = wl_cfgvendor_send_cmd_reply(wiphy, cmd_buf, data_len);
3035
+ if (unlikely(err)) {
3036
+ WL_ERR(("Vendor Command reply failed ret:%d \n", err));
3037
+ } else {
3038
+ WL_DBG(("Vendor Command reply sent successfully!\n"));
3039
+ }
3040
+ } else {
3041
+ /* No data to be sent back as reply */
3042
+ WL_ERR(("Vendor_cmd: No reply expected. data_len:%u cmd_buf %p \n",
3043
+ data_len, cmd_buf));
3044
+ }
20083045 break;
20093046 }
2010
- }
2011
-
2012
- if ((data_len > 0) && reply_buf) {
2013
- err = wl_cfgvendor_send_cmd_reply(wiphy, wdev->netdev,
2014
- reply_buf, data_len+1);
2015
- if (unlikely(err))
2016
- WL_ERR(("Vendor Command reply failed ret:%d \n", err));
2017
- else
2018
- WL_DBG(("Vendor Command reply sent successfully!\n"));
2019
- } else {
2020
- /* No data to be sent back as reply */
2021
- WL_ERR(("Vendor_cmd: No reply expected. data_len:%u reply_buf %p \n",
2022
- data_len, reply_buf));
3047
+#endif /* WL_ANDROID_PRIV_CMD_OVER_NL80211 && OEM_ANDROID */
20233048 }
20243049
20253050 exit:
2026
- if (reply_buf)
2027
- kfree(reply_buf);
3051
+#if defined(WL_ANDROID_PRIV_CMD_OVER_NL80211) && defined(OEM_ANDROID)
3052
+ if (cmd_buf) {
3053
+ MFREE(cfg->osh, cmd_buf, cmd_buf_len);
3054
+ }
3055
+#endif /* WL_ANDROID_PRIV_CMD_OVER_NL80211 && OEM_ANDROID */
20283056 net_os_wake_unlock(ndev);
20293057 return err;
20303058 }
3059
+#endif /* BCM_PRIV_CMD_SUPPORT */
3060
+
3061
+#ifdef WL_NAN
3062
+static const char *nan_attr_to_str(u16 cmd)
3063
+{
3064
+ switch (cmd) {
3065
+ C2S(NAN_ATTRIBUTE_HEADER)
3066
+ C2S(NAN_ATTRIBUTE_HANDLE)
3067
+ C2S(NAN_ATTRIBUTE_TRANSAC_ID)
3068
+ C2S(NAN_ATTRIBUTE_2G_SUPPORT)
3069
+ C2S(NAN_ATTRIBUTE_SDF_2G_SUPPORT)
3070
+ C2S(NAN_ATTRIBUTE_SDF_5G_SUPPORT)
3071
+ C2S(NAN_ATTRIBUTE_5G_SUPPORT)
3072
+ C2S(NAN_ATTRIBUTE_SYNC_DISC_2G_BEACON)
3073
+ C2S(NAN_ATTRIBUTE_SYNC_DISC_5G_BEACON)
3074
+ C2S(NAN_ATTRIBUTE_CLUSTER_LOW)
3075
+ C2S(NAN_ATTRIBUTE_CLUSTER_HIGH)
3076
+ C2S(NAN_ATTRIBUTE_SID_BEACON)
3077
+ C2S(NAN_ATTRIBUTE_RSSI_CLOSE)
3078
+ C2S(NAN_ATTRIBUTE_RSSI_MIDDLE)
3079
+ C2S(NAN_ATTRIBUTE_RSSI_PROXIMITY)
3080
+ C2S(NAN_ATTRIBUTE_RSSI_CLOSE_5G)
3081
+ C2S(NAN_ATTRIBUTE_RSSI_MIDDLE_5G)
3082
+ C2S(NAN_ATTRIBUTE_RSSI_PROXIMITY_5G)
3083
+ C2S(NAN_ATTRIBUTE_HOP_COUNT_LIMIT)
3084
+ C2S(NAN_ATTRIBUTE_RANDOM_TIME)
3085
+ C2S(NAN_ATTRIBUTE_MASTER_PREF)
3086
+ C2S(NAN_ATTRIBUTE_PERIODIC_SCAN_INTERVAL)
3087
+ C2S(NAN_ATTRIBUTE_PUBLISH_ID)
3088
+ C2S(NAN_ATTRIBUTE_TTL)
3089
+ C2S(NAN_ATTRIBUTE_PERIOD)
3090
+ C2S(NAN_ATTRIBUTE_REPLIED_EVENT_FLAG)
3091
+ C2S(NAN_ATTRIBUTE_PUBLISH_TYPE)
3092
+ C2S(NAN_ATTRIBUTE_TX_TYPE)
3093
+ C2S(NAN_ATTRIBUTE_PUBLISH_COUNT)
3094
+ C2S(NAN_ATTRIBUTE_SERVICE_NAME_LEN)
3095
+ C2S(NAN_ATTRIBUTE_SERVICE_NAME)
3096
+ C2S(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN)
3097
+ C2S(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO)
3098
+ C2S(NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN)
3099
+ C2S(NAN_ATTRIBUTE_RX_MATCH_FILTER)
3100
+ C2S(NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN)
3101
+ C2S(NAN_ATTRIBUTE_TX_MATCH_FILTER)
3102
+ C2S(NAN_ATTRIBUTE_SUBSCRIBE_ID)
3103
+ C2S(NAN_ATTRIBUTE_SUBSCRIBE_TYPE)
3104
+ C2S(NAN_ATTRIBUTE_SERVICERESPONSEFILTER)
3105
+ C2S(NAN_ATTRIBUTE_SERVICERESPONSEINCLUDE)
3106
+ C2S(NAN_ATTRIBUTE_USESERVICERESPONSEFILTER)
3107
+ C2S(NAN_ATTRIBUTE_SSIREQUIREDFORMATCHINDICATION)
3108
+ C2S(NAN_ATTRIBUTE_SUBSCRIBE_MATCH)
3109
+ C2S(NAN_ATTRIBUTE_SUBSCRIBE_COUNT)
3110
+ C2S(NAN_ATTRIBUTE_MAC_ADDR)
3111
+ C2S(NAN_ATTRIBUTE_MAC_ADDR_LIST)
3112
+ C2S(NAN_ATTRIBUTE_MAC_ADDR_LIST_NUM_ENTRIES)
3113
+ C2S(NAN_ATTRIBUTE_PUBLISH_MATCH)
3114
+ C2S(NAN_ATTRIBUTE_ENABLE_STATUS)
3115
+ C2S(NAN_ATTRIBUTE_JOIN_STATUS)
3116
+ C2S(NAN_ATTRIBUTE_ROLE)
3117
+ C2S(NAN_ATTRIBUTE_MASTER_RANK)
3118
+ C2S(NAN_ATTRIBUTE_ANCHOR_MASTER_RANK)
3119
+ C2S(NAN_ATTRIBUTE_CNT_PEND_TXFRM)
3120
+ C2S(NAN_ATTRIBUTE_CNT_BCN_TX)
3121
+ C2S(NAN_ATTRIBUTE_CNT_BCN_RX)
3122
+ C2S(NAN_ATTRIBUTE_CNT_SVC_DISC_TX)
3123
+ C2S(NAN_ATTRIBUTE_CNT_SVC_DISC_RX)
3124
+ C2S(NAN_ATTRIBUTE_AMBTT)
3125
+ C2S(NAN_ATTRIBUTE_CLUSTER_ID)
3126
+ C2S(NAN_ATTRIBUTE_INST_ID)
3127
+ C2S(NAN_ATTRIBUTE_OUI)
3128
+ C2S(NAN_ATTRIBUTE_STATUS)
3129
+ C2S(NAN_ATTRIBUTE_DE_EVENT_TYPE)
3130
+ C2S(NAN_ATTRIBUTE_MERGE)
3131
+ C2S(NAN_ATTRIBUTE_IFACE)
3132
+ C2S(NAN_ATTRIBUTE_CHANNEL)
3133
+ C2S(NAN_ATTRIBUTE_24G_CHANNEL)
3134
+ C2S(NAN_ATTRIBUTE_5G_CHANNEL)
3135
+ C2S(NAN_ATTRIBUTE_PEER_ID)
3136
+ C2S(NAN_ATTRIBUTE_NDP_ID)
3137
+ C2S(NAN_ATTRIBUTE_SECURITY)
3138
+ C2S(NAN_ATTRIBUTE_QOS)
3139
+ C2S(NAN_ATTRIBUTE_RSP_CODE)
3140
+ C2S(NAN_ATTRIBUTE_INST_COUNT)
3141
+ C2S(NAN_ATTRIBUTE_PEER_DISC_MAC_ADDR)
3142
+ C2S(NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR)
3143
+ C2S(NAN_ATTRIBUTE_IF_ADDR)
3144
+ C2S(NAN_ATTRIBUTE_WARMUP_TIME)
3145
+ C2S(NAN_ATTRIBUTE_RECV_IND_CFG)
3146
+ C2S(NAN_ATTRIBUTE_CONNMAP)
3147
+ C2S(NAN_ATTRIBUTE_DWELL_TIME)
3148
+ C2S(NAN_ATTRIBUTE_SCAN_PERIOD)
3149
+ C2S(NAN_ATTRIBUTE_RSSI_WINDOW_SIZE)
3150
+ C2S(NAN_ATTRIBUTE_CONF_CLUSTER_VAL)
3151
+ C2S(NAN_ATTRIBUTE_CIPHER_SUITE_TYPE)
3152
+ C2S(NAN_ATTRIBUTE_KEY_TYPE)
3153
+ C2S(NAN_ATTRIBUTE_KEY_LEN)
3154
+ C2S(NAN_ATTRIBUTE_SCID)
3155
+ C2S(NAN_ATTRIBUTE_SCID_LEN)
3156
+ C2S(NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP)
3157
+ C2S(NAN_ATTRIBUTE_SDE_CONTROL_SECURITY)
3158
+ C2S(NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE)
3159
+ C2S(NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT)
3160
+ C2S(NAN_ATTRIBUTE_NO_CONFIG_AVAIL)
3161
+ C2S(NAN_ATTRIBUTE_2G_AWAKE_DW)
3162
+ C2S(NAN_ATTRIBUTE_5G_AWAKE_DW)
3163
+ C2S(NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG)
3164
+ C2S(NAN_ATTRIBUTE_KEY_DATA)
3165
+ C2S(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN)
3166
+ C2S(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO)
3167
+ C2S(NAN_ATTRIBUTE_REASON)
3168
+ C2S(NAN_ATTRIBUTE_DISC_IND_CFG)
3169
+ C2S(NAN_ATTRIBUTE_DWELL_TIME_5G)
3170
+ C2S(NAN_ATTRIBUTE_SCAN_PERIOD_5G)
3171
+ C2S(NAN_ATTRIBUTE_SUB_SID_BEACON)
3172
+ default:
3173
+ return "NAN_ATTRIBUTE_UNKNOWN";
3174
+ }
3175
+}
3176
+
3177
+nan_hal_status_t nan_status_reasonstr_map[] = {
3178
+ {NAN_STATUS_SUCCESS, "NAN status success"},
3179
+ {NAN_STATUS_INTERNAL_FAILURE, "NAN Discovery engine failure"},
3180
+ {NAN_STATUS_PROTOCOL_FAILURE, "protocol failure"},
3181
+ {NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID, "invalid pub_sub ID"},
3182
+ {NAN_STATUS_NO_RESOURCE_AVAILABLE, "No space available"},
3183
+ {NAN_STATUS_INVALID_PARAM, "invalid param"},
3184
+ {NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID, "invalid req inst id"},
3185
+ {NAN_STATUS_INVALID_NDP_ID, "invalid ndp id"},
3186
+ {NAN_STATUS_NAN_NOT_ALLOWED, "Nan not allowed"},
3187
+ {NAN_STATUS_NO_OTA_ACK, "No OTA ack"},
3188
+ {NAN_STATUS_ALREADY_ENABLED, "NAN is Already enabled"},
3189
+ {NAN_STATUS_FOLLOWUP_QUEUE_FULL, "Follow-up queue full"},
3190
+ {NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED, "unsupported concurrency"},
3191
+};
3192
+
3193
+void
3194
+wl_cfgvendor_add_nan_reason_str(nan_status_type_t status, nan_hal_resp_t *nan_req_resp)
3195
+{
3196
+ int i = 0;
3197
+ int num = (int)(sizeof(nan_status_reasonstr_map)/sizeof(nan_status_reasonstr_map[0]));
3198
+ for (i = 0; i < num; i++) {
3199
+ if (nan_status_reasonstr_map[i].status == status) {
3200
+ strlcpy(nan_req_resp->nan_reason, nan_status_reasonstr_map[i].nan_reason,
3201
+ sizeof(nan_status_reasonstr_map[i].nan_reason));
3202
+ break;
3203
+ }
3204
+ }
3205
+}
3206
+
3207
+nan_status_type_t
3208
+wl_cfgvendor_brcm_to_nanhal_status(int32 vendor_status)
3209
+{
3210
+ nan_status_type_t hal_status;
3211
+ switch (vendor_status) {
3212
+ case BCME_OK:
3213
+ hal_status = NAN_STATUS_SUCCESS;
3214
+ break;
3215
+ case BCME_BUSY:
3216
+ case BCME_NOTREADY:
3217
+ hal_status = NAN_STATUS_NAN_NOT_ALLOWED;
3218
+ break;
3219
+ case BCME_BADLEN:
3220
+ case BCME_BADBAND:
3221
+ case BCME_UNSUPPORTED:
3222
+ case BCME_USAGE_ERROR:
3223
+ case BCME_BADARG:
3224
+ hal_status = NAN_STATUS_INVALID_PARAM;
3225
+ break;
3226
+ case BCME_NOMEM:
3227
+ case BCME_NORESOURCE:
3228
+ case WL_NAN_E_SVC_SUB_LIST_FULL:
3229
+ hal_status = NAN_STATUS_NO_RESOURCE_AVAILABLE;
3230
+ break;
3231
+ case WL_NAN_E_SD_TX_LIST_FULL:
3232
+ hal_status = NAN_STATUS_FOLLOWUP_QUEUE_FULL;
3233
+ break;
3234
+ case WL_NAN_E_BAD_INSTANCE:
3235
+ hal_status = NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
3236
+ break;
3237
+ default:
3238
+ WL_ERR(("%s Unknown vendor status, status = %d\n",
3239
+ __func__, vendor_status));
3240
+ /* Generic error */
3241
+ hal_status = NAN_STATUS_INTERNAL_FAILURE;
3242
+ }
3243
+ return hal_status;
3244
+}
3245
+
3246
+static int
3247
+wl_cfgvendor_nan_cmd_reply(struct wiphy *wiphy, int nan_cmd,
3248
+ nan_hal_resp_t *nan_req_resp, int ret, int nan_cmd_status)
3249
+{
3250
+ int err;
3251
+ int nan_reply;
3252
+ nan_req_resp->subcmd = nan_cmd;
3253
+ if (ret == BCME_OK) {
3254
+ nan_reply = nan_cmd_status;
3255
+ } else {
3256
+ nan_reply = ret;
3257
+ }
3258
+ nan_req_resp->status = wl_cfgvendor_brcm_to_nanhal_status(nan_reply);
3259
+ nan_req_resp->value = ret;
3260
+ err = wl_cfgvendor_send_cmd_reply(wiphy, nan_req_resp,
3261
+ sizeof(*nan_req_resp));
3262
+ /* giving more prio to ret than err */
3263
+ return (ret == 0) ? err : ret;
3264
+}
3265
+
3266
+static void
3267
+wl_cfgvendor_free_disc_cmd_data(struct bcm_cfg80211 *cfg,
3268
+ nan_discover_cmd_data_t *cmd_data)
3269
+{
3270
+ if (!cmd_data) {
3271
+ WL_ERR(("Cmd_data is null\n"));
3272
+ return;
3273
+ }
3274
+ if (cmd_data->svc_info.data) {
3275
+ MFREE(cfg->osh, cmd_data->svc_info.data, cmd_data->svc_info.dlen);
3276
+ }
3277
+ if (cmd_data->svc_hash.data) {
3278
+ MFREE(cfg->osh, cmd_data->svc_hash.data, cmd_data->svc_hash.dlen);
3279
+ }
3280
+ if (cmd_data->rx_match.data) {
3281
+ MFREE(cfg->osh, cmd_data->rx_match.data, cmd_data->rx_match.dlen);
3282
+ }
3283
+ if (cmd_data->tx_match.data) {
3284
+ MFREE(cfg->osh, cmd_data->tx_match.data, cmd_data->tx_match.dlen);
3285
+ }
3286
+ if (cmd_data->mac_list.list) {
3287
+ MFREE(cfg->osh, cmd_data->mac_list.list,
3288
+ cmd_data->mac_list.num_mac_addr * ETHER_ADDR_LEN);
3289
+ }
3290
+ if (cmd_data->key.data) {
3291
+ MFREE(cfg->osh, cmd_data->key.data, NAN_MAX_PMK_LEN);
3292
+ }
3293
+ if (cmd_data->sde_svc_info.data) {
3294
+ MFREE(cfg->osh, cmd_data->sde_svc_info.data, cmd_data->sde_svc_info.dlen);
3295
+ }
3296
+ MFREE(cfg->osh, cmd_data, sizeof(*cmd_data));
3297
+}
3298
+
3299
+static void
3300
+wl_cfgvendor_free_dp_cmd_data(struct bcm_cfg80211 *cfg,
3301
+ nan_datapath_cmd_data_t *cmd_data)
3302
+{
3303
+ if (!cmd_data) {
3304
+ WL_ERR(("Cmd_data is null\n"));
3305
+ return;
3306
+ }
3307
+ if (cmd_data->svc_hash.data) {
3308
+ MFREE(cfg->osh, cmd_data->svc_hash.data, cmd_data->svc_hash.dlen);
3309
+ }
3310
+ if (cmd_data->svc_info.data) {
3311
+ MFREE(cfg->osh, cmd_data->svc_info.data, cmd_data->svc_info.dlen);
3312
+ }
3313
+ if (cmd_data->key.data) {
3314
+ MFREE(cfg->osh, cmd_data->key.data, NAN_MAX_PMK_LEN);
3315
+ }
3316
+ MFREE(cfg->osh, cmd_data, sizeof(*cmd_data));
3317
+}
3318
+
3319
+#define WL_NAN_EVENT_MAX_BUF 256
3320
+#ifdef WL_NAN_DISC_CACHE
3321
+static int
3322
+wl_cfgvendor_nan_parse_dp_sec_info_args(struct wiphy *wiphy,
3323
+ const void *buf, int len, nan_datapath_sec_info_cmd_data_t *cmd_data)
3324
+{
3325
+ int ret = BCME_OK;
3326
+ int attr_type;
3327
+ int rem = len;
3328
+ const struct nlattr *iter;
3329
+
3330
+ NAN_DBG_ENTER();
3331
+
3332
+ nla_for_each_attr(iter, buf, len, rem) {
3333
+ attr_type = nla_type(iter);
3334
+ WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type), attr_type));
3335
+
3336
+ switch (attr_type) {
3337
+ case NAN_ATTRIBUTE_MAC_ADDR:
3338
+ ret = memcpy_s((char*)&cmd_data->mac_addr, ETHER_ADDR_LEN,
3339
+ (char*)nla_data(iter), nla_len(iter));
3340
+ if (ret != BCME_OK) {
3341
+ WL_ERR(("Failed to copy mac addr\n"));
3342
+ return ret;
3343
+ }
3344
+ break;
3345
+ case NAN_ATTRIBUTE_PUBLISH_ID:
3346
+ cmd_data->pub_id = nla_get_u16(iter);
3347
+ break;
3348
+ case NAN_ATTRIBUTE_NDP_ID:
3349
+ cmd_data->ndp_instance_id = nla_get_u32(iter);
3350
+ break;
3351
+ default:
3352
+ WL_ERR(("%s: Unknown type, %d\n", __FUNCTION__, attr_type));
3353
+ ret = BCME_BADARG;
3354
+ break;
3355
+ }
3356
+ }
3357
+ /* We need to call set_config_handler b/f calling start enable TBD */
3358
+ NAN_DBG_EXIT();
3359
+ return ret;
3360
+}
3361
+#endif /* WL_NAN_DISC_CACHE */
3362
+
3363
+int8 chanbuf[CHANSPEC_STR_LEN];
3364
+static int
3365
+wl_cfgvendor_nan_parse_datapath_args(struct wiphy *wiphy,
3366
+ const void *buf, int len, nan_datapath_cmd_data_t *cmd_data)
3367
+{
3368
+ int ret = BCME_OK;
3369
+ int attr_type;
3370
+ int rem = len;
3371
+ const struct nlattr *iter;
3372
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3373
+ int chan;
3374
+
3375
+ NAN_DBG_ENTER();
3376
+
3377
+ nla_for_each_attr(iter, buf, len, rem) {
3378
+ attr_type = nla_type(iter);
3379
+ WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type), attr_type));
3380
+
3381
+ switch (attr_type) {
3382
+ case NAN_ATTRIBUTE_NDP_ID:
3383
+ if (nla_len(iter) != sizeof(uint32)) {
3384
+ ret = -EINVAL;
3385
+ goto exit;
3386
+ }
3387
+ cmd_data->ndp_instance_id = nla_get_u32(iter);
3388
+ break;
3389
+ case NAN_ATTRIBUTE_IFACE:
3390
+ if (nla_len(iter) >= sizeof(cmd_data->ndp_iface)) {
3391
+ WL_ERR(("iface_name len wrong:%d\n", nla_len(iter)));
3392
+ ret = -EINVAL;
3393
+ goto exit;
3394
+ }
3395
+ strlcpy((char *)cmd_data->ndp_iface, (char *)nla_data(iter),
3396
+ nla_len(iter));
3397
+ break;
3398
+ case NAN_ATTRIBUTE_SECURITY:
3399
+ if (nla_len(iter) != sizeof(uint8)) {
3400
+ ret = -EINVAL;
3401
+ goto exit;
3402
+ }
3403
+ cmd_data->ndp_cfg.security_cfg = nla_get_u8(iter);
3404
+ break;
3405
+ case NAN_ATTRIBUTE_QOS:
3406
+ if (nla_len(iter) != sizeof(uint8)) {
3407
+ ret = -EINVAL;
3408
+ goto exit;
3409
+ }
3410
+ cmd_data->ndp_cfg.qos_cfg = nla_get_u8(iter);
3411
+ break;
3412
+ case NAN_ATTRIBUTE_RSP_CODE:
3413
+ if (nla_len(iter) != sizeof(uint8)) {
3414
+ ret = -EINVAL;
3415
+ goto exit;
3416
+ }
3417
+ cmd_data->rsp_code = nla_get_u8(iter);
3418
+ break;
3419
+ case NAN_ATTRIBUTE_INST_COUNT:
3420
+ if (nla_len(iter) != sizeof(uint8)) {
3421
+ ret = -EINVAL;
3422
+ goto exit;
3423
+ }
3424
+ cmd_data->num_ndp_instances = nla_get_u8(iter);
3425
+ break;
3426
+ case NAN_ATTRIBUTE_PEER_DISC_MAC_ADDR:
3427
+ if (nla_len(iter) != ETHER_ADDR_LEN) {
3428
+ ret = -EINVAL;
3429
+ goto exit;
3430
+ }
3431
+ ret = memcpy_s((char*)&cmd_data->peer_disc_mac_addr,
3432
+ ETHER_ADDR_LEN, (char*)nla_data(iter), nla_len(iter));
3433
+ if (ret != BCME_OK) {
3434
+ WL_ERR(("Failed to copy peer_disc_mac_addr\n"));
3435
+ goto exit;
3436
+ }
3437
+ break;
3438
+ case NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR:
3439
+ if (nla_len(iter) != ETHER_ADDR_LEN) {
3440
+ ret = -EINVAL;
3441
+ goto exit;
3442
+ }
3443
+ ret = memcpy_s((char*)&cmd_data->peer_ndi_mac_addr,
3444
+ ETHER_ADDR_LEN, (char*)nla_data(iter), nla_len(iter));
3445
+ if (ret != BCME_OK) {
3446
+ WL_ERR(("Failed to copy peer_ndi_mac_addr\n"));
3447
+ goto exit;
3448
+ }
3449
+ break;
3450
+ case NAN_ATTRIBUTE_MAC_ADDR:
3451
+ if (nla_len(iter) != ETHER_ADDR_LEN) {
3452
+ ret = -EINVAL;
3453
+ goto exit;
3454
+ }
3455
+ ret = memcpy_s((char*)&cmd_data->mac_addr, ETHER_ADDR_LEN,
3456
+ (char*)nla_data(iter), nla_len(iter));
3457
+ if (ret != BCME_OK) {
3458
+ WL_ERR(("Failed to copy mac_addr\n"));
3459
+ goto exit;
3460
+ }
3461
+ break;
3462
+ case NAN_ATTRIBUTE_IF_ADDR:
3463
+ if (nla_len(iter) != ETHER_ADDR_LEN) {
3464
+ ret = -EINVAL;
3465
+ goto exit;
3466
+ }
3467
+ ret = memcpy_s((char*)&cmd_data->if_addr, ETHER_ADDR_LEN,
3468
+ (char*)nla_data(iter), nla_len(iter));
3469
+ if (ret != BCME_OK) {
3470
+ WL_ERR(("Failed to copy if_addr\n"));
3471
+ goto exit;
3472
+ }
3473
+ break;
3474
+ case NAN_ATTRIBUTE_ENTRY_CONTROL:
3475
+ if (nla_len(iter) != sizeof(uint8)) {
3476
+ ret = -EINVAL;
3477
+ goto exit;
3478
+ }
3479
+ cmd_data->avail_params.duration = nla_get_u8(iter);
3480
+ break;
3481
+ case NAN_ATTRIBUTE_AVAIL_BIT_MAP:
3482
+ if (nla_len(iter) != sizeof(uint32)) {
3483
+ ret = -EINVAL;
3484
+ goto exit;
3485
+ }
3486
+ cmd_data->avail_params.bmap = nla_get_u32(iter);
3487
+ break;
3488
+ case NAN_ATTRIBUTE_CHANNEL: {
3489
+ if (nla_len(iter) != sizeof(uint32)) {
3490
+ ret = -EINVAL;
3491
+ goto exit;
3492
+ }
3493
+ /* take the default channel start_factor frequency */
3494
+ chan = wf_mhz2channel((uint)nla_get_u32(iter), 0);
3495
+ if (chan <= CH_MAX_2G_CHANNEL) {
3496
+ cmd_data->avail_params.chanspec[0] =
3497
+ wf_channel2chspec(chan, WL_CHANSPEC_BW_20);
3498
+ } else {
3499
+ cmd_data->avail_params.chanspec[0] =
3500
+ wf_channel2chspec(chan, WL_CHANSPEC_BW_80);
3501
+ }
3502
+ if (cmd_data->avail_params.chanspec[0] == 0) {
3503
+ WL_ERR(("Channel is not valid \n"));
3504
+ ret = -EINVAL;
3505
+ goto exit;
3506
+ }
3507
+ WL_TRACE(("valid chanspec, chanspec = 0x%04x \n",
3508
+ cmd_data->avail_params.chanspec[0]));
3509
+ break;
3510
+ }
3511
+ case NAN_ATTRIBUTE_NO_CONFIG_AVAIL:
3512
+ if (nla_len(iter) != sizeof(uint8)) {
3513
+ ret = -EINVAL;
3514
+ goto exit;
3515
+ }
3516
+ cmd_data->avail_params.no_config_avail = (bool)nla_get_u8(iter);
3517
+ break;
3518
+ case NAN_ATTRIBUTE_SERVICE_NAME_LEN: {
3519
+ if (nla_len(iter) != sizeof(uint16)) {
3520
+ ret = -EINVAL;
3521
+ goto exit;
3522
+ }
3523
+ if (cmd_data->svc_hash.dlen) {
3524
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
3525
+ ret = -EINVAL;
3526
+ goto exit;
3527
+ }
3528
+ cmd_data->svc_hash.dlen = nla_get_u16(iter);
3529
+ if (cmd_data->svc_hash.dlen != WL_NAN_SVC_HASH_LEN) {
3530
+ WL_ERR(("invalid svc_hash length = %u\n", cmd_data->svc_hash.dlen));
3531
+ ret = -EINVAL;
3532
+ goto exit;
3533
+ }
3534
+ break;
3535
+ }
3536
+ case NAN_ATTRIBUTE_SERVICE_NAME:
3537
+ if ((!cmd_data->svc_hash.dlen) ||
3538
+ (nla_len(iter) != cmd_data->svc_hash.dlen)) {
3539
+ WL_ERR(("invalid svc_hash length = %d,%d\n",
3540
+ cmd_data->svc_hash.dlen, nla_len(iter)));
3541
+ ret = -EINVAL;
3542
+ goto exit;
3543
+ }
3544
+ if (cmd_data->svc_hash.data) {
3545
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
3546
+ ret = -EINVAL;
3547
+ goto exit;
3548
+ }
3549
+ cmd_data->svc_hash.data =
3550
+ MALLOCZ(cfg->osh, cmd_data->svc_hash.dlen);
3551
+ if (!cmd_data->svc_hash.data) {
3552
+ WL_ERR(("failed to allocate svc_hash data, len=%d\n",
3553
+ cmd_data->svc_hash.dlen));
3554
+ ret = -ENOMEM;
3555
+ goto exit;
3556
+ }
3557
+ ret = memcpy_s(cmd_data->svc_hash.data, cmd_data->svc_hash.dlen,
3558
+ nla_data(iter), nla_len(iter));
3559
+ if (ret != BCME_OK) {
3560
+ WL_ERR(("Failed to copy svc hash data\n"));
3561
+ goto exit;
3562
+ }
3563
+ break;
3564
+ case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN:
3565
+ if (nla_len(iter) != sizeof(uint16)) {
3566
+ ret = -EINVAL;
3567
+ goto exit;
3568
+ }
3569
+ if (cmd_data->svc_info.dlen) {
3570
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
3571
+ ret = -EINVAL;
3572
+ goto exit;
3573
+ }
3574
+ cmd_data->svc_info.dlen = nla_get_u16(iter);
3575
+ if (cmd_data->svc_info.dlen > MAX_APP_INFO_LEN) {
3576
+ WL_ERR_RLMT(("Not allowed beyond :%d\n", MAX_APP_INFO_LEN));
3577
+ ret = -EINVAL;
3578
+ goto exit;
3579
+ }
3580
+ break;
3581
+ case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO:
3582
+ if ((!cmd_data->svc_info.dlen) ||
3583
+ (nla_len(iter) != cmd_data->svc_info.dlen)) {
3584
+ WL_ERR(("failed to allocate svc info by invalid len=%d,%d\n",
3585
+ cmd_data->svc_info.dlen, nla_len(iter)));
3586
+ ret = -EINVAL;
3587
+ goto exit;
3588
+ }
3589
+ if (cmd_data->svc_info.data) {
3590
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
3591
+ ret = -EINVAL;
3592
+ goto exit;
3593
+ }
3594
+ cmd_data->svc_info.data = MALLOCZ(cfg->osh, cmd_data->svc_info.dlen);
3595
+ if (cmd_data->svc_info.data == NULL) {
3596
+ WL_ERR(("failed to allocate svc info data, len=%d\n",
3597
+ cmd_data->svc_info.dlen));
3598
+ ret = -ENOMEM;
3599
+ goto exit;
3600
+ }
3601
+ ret = memcpy_s(cmd_data->svc_info.data, cmd_data->svc_info.dlen,
3602
+ nla_data(iter), nla_len(iter));
3603
+ if (ret != BCME_OK) {
3604
+ WL_ERR(("Failed to copy svc info\n"));
3605
+ goto exit;
3606
+ }
3607
+ break;
3608
+ case NAN_ATTRIBUTE_PUBLISH_ID:
3609
+ if (nla_len(iter) != sizeof(uint32)) {
3610
+ ret = -EINVAL;
3611
+ goto exit;
3612
+ }
3613
+ cmd_data->pub_id = nla_get_u32(iter);
3614
+ break;
3615
+ case NAN_ATTRIBUTE_CIPHER_SUITE_TYPE:
3616
+ if (nla_len(iter) != sizeof(uint8)) {
3617
+ ret = -EINVAL;
3618
+ goto exit;
3619
+ }
3620
+ cmd_data->csid = nla_get_u8(iter);
3621
+ WL_TRACE(("CSID = %u\n", cmd_data->csid));
3622
+ break;
3623
+ case NAN_ATTRIBUTE_KEY_TYPE:
3624
+ if (nla_len(iter) != sizeof(uint8)) {
3625
+ ret = -EINVAL;
3626
+ goto exit;
3627
+ }
3628
+ cmd_data->key_type = nla_get_u8(iter);
3629
+ WL_TRACE(("Key Type = %u\n", cmd_data->key_type));
3630
+ break;
3631
+ case NAN_ATTRIBUTE_KEY_LEN:
3632
+ if (nla_len(iter) != sizeof(uint32)) {
3633
+ ret = -EINVAL;
3634
+ goto exit;
3635
+ }
3636
+ if (cmd_data->key.dlen) {
3637
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
3638
+ ret = -EINVAL;
3639
+ goto exit;
3640
+ }
3641
+ cmd_data->key.dlen = nla_get_u32(iter);
3642
+ if ((!cmd_data->key.dlen) || (cmd_data->key.dlen > WL_NAN_NCS_SK_PMK_LEN)) {
3643
+ WL_ERR(("invalid key length = %u\n", cmd_data->key.dlen));
3644
+ ret = -EINVAL;
3645
+ goto exit;
3646
+ }
3647
+ WL_TRACE(("valid key length = %u\n", cmd_data->key.dlen));
3648
+ break;
3649
+ case NAN_ATTRIBUTE_KEY_DATA:
3650
+ if ((!cmd_data->key.dlen) ||
3651
+ (nla_len(iter) != cmd_data->key.dlen)) {
3652
+ WL_ERR(("failed to allocate key data by invalid len=%d,%d\n",
3653
+ cmd_data->key.dlen, nla_len(iter)));
3654
+ ret = -EINVAL;
3655
+ goto exit;
3656
+ }
3657
+ if (cmd_data->key.data) {
3658
+ WL_ERR(("trying to overwrite key data.\n"));
3659
+ ret = -EINVAL;
3660
+ goto exit;
3661
+ }
3662
+
3663
+ cmd_data->key.data = MALLOCZ(cfg->osh, NAN_MAX_PMK_LEN);
3664
+ if (cmd_data->key.data == NULL) {
3665
+ WL_ERR(("failed to allocate key data, len=%d\n",
3666
+ cmd_data->key.dlen));
3667
+ ret = -ENOMEM;
3668
+ goto exit;
3669
+ }
3670
+ ret = memcpy_s(cmd_data->key.data, NAN_MAX_PMK_LEN,
3671
+ nla_data(iter), nla_len(iter));
3672
+ if (ret != BCME_OK) {
3673
+ WL_ERR(("Failed to key data\n"));
3674
+ goto exit;
3675
+ }
3676
+ break;
3677
+
3678
+ default:
3679
+ WL_ERR(("Unknown type, %d\n", attr_type));
3680
+ ret = -EINVAL;
3681
+ goto exit;
3682
+ }
3683
+ }
3684
+exit:
3685
+ /* We need to call set_config_handler b/f calling start enable TBD */
3686
+ NAN_DBG_EXIT();
3687
+ return ret;
3688
+}
3689
+
3690
+static int
3691
+wl_cfgvendor_nan_parse_discover_args(struct wiphy *wiphy,
3692
+ const void *buf, int len, nan_discover_cmd_data_t *cmd_data)
3693
+{
3694
+ int ret = BCME_OK;
3695
+ int attr_type;
3696
+ int rem = len;
3697
+ const struct nlattr *iter;
3698
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3699
+ u8 val_u8;
3700
+ u32 bit_flag;
3701
+ u8 flag_match;
3702
+
3703
+ NAN_DBG_ENTER();
3704
+
3705
+ nla_for_each_attr(iter, buf, len, rem) {
3706
+ attr_type = nla_type(iter);
3707
+ WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type), attr_type));
3708
+
3709
+ switch (attr_type) {
3710
+ case NAN_ATTRIBUTE_TRANSAC_ID:
3711
+ if (nla_len(iter) != sizeof(uint16)) {
3712
+ ret = -EINVAL;
3713
+ goto exit;
3714
+ }
3715
+ cmd_data->token = nla_get_u16(iter);
3716
+ break;
3717
+ case NAN_ATTRIBUTE_PERIODIC_SCAN_INTERVAL:
3718
+ break;
3719
+
3720
+ /* Nan Publish/Subscribe request Attributes */
3721
+ case NAN_ATTRIBUTE_PUBLISH_ID:
3722
+ if (nla_len(iter) != sizeof(uint16)) {
3723
+ ret = -EINVAL;
3724
+ goto exit;
3725
+ }
3726
+ cmd_data->pub_id = nla_get_u16(iter);
3727
+ cmd_data->local_id = cmd_data->pub_id;
3728
+ break;
3729
+ case NAN_ATTRIBUTE_MAC_ADDR:
3730
+ if (nla_len(iter) != ETHER_ADDR_LEN) {
3731
+ ret = -EINVAL;
3732
+ goto exit;
3733
+ }
3734
+ ret = memcpy_s((char*)&cmd_data->mac_addr, ETHER_ADDR_LEN,
3735
+ (char*)nla_data(iter), nla_len(iter));
3736
+ if (ret != BCME_OK) {
3737
+ WL_ERR(("Failed to copy mac addr\n"));
3738
+ return ret;
3739
+ }
3740
+ break;
3741
+ case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN:
3742
+ if (nla_len(iter) != sizeof(uint16)) {
3743
+ ret = -EINVAL;
3744
+ goto exit;
3745
+ }
3746
+ if (cmd_data->svc_info.dlen) {
3747
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
3748
+ ret = -EINVAL;
3749
+ goto exit;
3750
+ }
3751
+ cmd_data->svc_info.dlen = nla_get_u16(iter);
3752
+ if (cmd_data->svc_info.dlen > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
3753
+ WL_ERR_RLMT(("Not allowed beyond :%d\n",
3754
+ NAN_MAX_SERVICE_SPECIFIC_INFO_LEN));
3755
+ ret = -EINVAL;
3756
+ goto exit;
3757
+ }
3758
+ break;
3759
+ case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO:
3760
+ if ((!cmd_data->svc_info.dlen) ||
3761
+ (nla_len(iter) != cmd_data->svc_info.dlen)) {
3762
+ WL_ERR(("failed to allocate svc info by invalid len=%d,%d\n",
3763
+ cmd_data->svc_info.dlen, nla_len(iter)));
3764
+ ret = -EINVAL;
3765
+ goto exit;
3766
+ }
3767
+ if (cmd_data->svc_info.data) {
3768
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
3769
+ ret = -EINVAL;
3770
+ goto exit;
3771
+ }
3772
+
3773
+ cmd_data->svc_info.data = MALLOCZ(cfg->osh, cmd_data->svc_info.dlen);
3774
+ if (cmd_data->svc_info.data == NULL) {
3775
+ WL_ERR(("failed to allocate svc info data, len=%d\n",
3776
+ cmd_data->svc_info.dlen));
3777
+ ret = -ENOMEM;
3778
+ goto exit;
3779
+ }
3780
+ ret = memcpy_s(cmd_data->svc_info.data, cmd_data->svc_info.dlen,
3781
+ nla_data(iter), nla_len(iter));
3782
+ if (ret != BCME_OK) {
3783
+ WL_ERR(("Failed to copy svc info\n"));
3784
+ return ret;
3785
+ }
3786
+ break;
3787
+ case NAN_ATTRIBUTE_SUBSCRIBE_ID:
3788
+ if (nla_len(iter) != sizeof(uint16)) {
3789
+ ret = -EINVAL;
3790
+ goto exit;
3791
+ }
3792
+ cmd_data->sub_id = nla_get_u16(iter);
3793
+ cmd_data->local_id = cmd_data->sub_id;
3794
+ break;
3795
+ case NAN_ATTRIBUTE_SUBSCRIBE_TYPE:
3796
+ if (nla_len(iter) != sizeof(uint8)) {
3797
+ ret = -EINVAL;
3798
+ goto exit;
3799
+ }
3800
+ cmd_data->flags |= nla_get_u8(iter) ? WL_NAN_SUB_ACTIVE : 0;
3801
+ break;
3802
+ case NAN_ATTRIBUTE_PUBLISH_COUNT:
3803
+ if (nla_len(iter) != sizeof(uint8)) {
3804
+ ret = -EINVAL;
3805
+ goto exit;
3806
+ }
3807
+ cmd_data->life_count = nla_get_u8(iter);
3808
+ break;
3809
+ case NAN_ATTRIBUTE_PUBLISH_TYPE: {
3810
+ if (nla_len(iter) != sizeof(uint8)) {
3811
+ ret = -EINVAL;
3812
+ goto exit;
3813
+ }
3814
+ val_u8 = nla_get_u8(iter);
3815
+ if (val_u8 == 0) {
3816
+ cmd_data->flags |= WL_NAN_PUB_UNSOLICIT;
3817
+ } else if (val_u8 == 1) {
3818
+ cmd_data->flags |= WL_NAN_PUB_SOLICIT;
3819
+ } else {
3820
+ cmd_data->flags |= WL_NAN_PUB_BOTH;
3821
+ }
3822
+ break;
3823
+ }
3824
+ case NAN_ATTRIBUTE_PERIOD: {
3825
+ if (nla_len(iter) != sizeof(uint16)) {
3826
+ ret = -EINVAL;
3827
+ goto exit;
3828
+ }
3829
+ if (nla_get_u16(iter) > NAN_MAX_AWAKE_DW_INTERVAL) {
3830
+ WL_ERR(("Invalid/Out of bound value = %u\n", nla_get_u16(iter)));
3831
+ ret = BCME_BADARG;
3832
+ break;
3833
+ }
3834
+ if (nla_get_u16(iter)) {
3835
+ cmd_data->period = 1 << (nla_get_u16(iter)-1);
3836
+ }
3837
+ break;
3838
+ }
3839
+ case NAN_ATTRIBUTE_REPLIED_EVENT_FLAG:
3840
+ break;
3841
+ case NAN_ATTRIBUTE_TTL:
3842
+ if (nla_len(iter) != sizeof(uint16)) {
3843
+ ret = -EINVAL;
3844
+ goto exit;
3845
+ }
3846
+ cmd_data->ttl = nla_get_u16(iter);
3847
+ break;
3848
+ case NAN_ATTRIBUTE_SERVICE_NAME_LEN: {
3849
+ if (nla_len(iter) != sizeof(uint16)) {
3850
+ ret = -EINVAL;
3851
+ goto exit;
3852
+ }
3853
+ if (cmd_data->svc_hash.dlen) {
3854
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
3855
+ ret = -EINVAL;
3856
+ goto exit;
3857
+ }
3858
+
3859
+ cmd_data->svc_hash.dlen = nla_get_u16(iter);
3860
+ if (cmd_data->svc_hash.dlen != WL_NAN_SVC_HASH_LEN) {
3861
+ WL_ERR(("invalid svc_hash length = %u\n", cmd_data->svc_hash.dlen));
3862
+ ret = -EINVAL;
3863
+ goto exit;
3864
+ }
3865
+ break;
3866
+ }
3867
+ case NAN_ATTRIBUTE_SERVICE_NAME:
3868
+ if ((!cmd_data->svc_hash.dlen) ||
3869
+ (nla_len(iter) != cmd_data->svc_hash.dlen)) {
3870
+ WL_ERR(("invalid svc_hash length = %d,%d\n",
3871
+ cmd_data->svc_hash.dlen, nla_len(iter)));
3872
+ ret = -EINVAL;
3873
+ goto exit;
3874
+ }
3875
+ if (cmd_data->svc_hash.data) {
3876
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
3877
+ ret = -EINVAL;
3878
+ goto exit;
3879
+ }
3880
+
3881
+ cmd_data->svc_hash.data =
3882
+ MALLOCZ(cfg->osh, cmd_data->svc_hash.dlen);
3883
+ if (!cmd_data->svc_hash.data) {
3884
+ WL_ERR(("failed to allocate svc_hash data, len=%d\n",
3885
+ cmd_data->svc_hash.dlen));
3886
+ ret = -ENOMEM;
3887
+ goto exit;
3888
+ }
3889
+ ret = memcpy_s(cmd_data->svc_hash.data, cmd_data->svc_hash.dlen,
3890
+ nla_data(iter), nla_len(iter));
3891
+ if (ret != BCME_OK) {
3892
+ WL_ERR(("Failed to copy svc hash data\n"));
3893
+ return ret;
3894
+ }
3895
+ break;
3896
+ case NAN_ATTRIBUTE_PEER_ID:
3897
+ if (nla_len(iter) != sizeof(uint32)) {
3898
+ ret = -EINVAL;
3899
+ goto exit;
3900
+ }
3901
+ cmd_data->remote_id = nla_get_u32(iter);
3902
+ break;
3903
+ case NAN_ATTRIBUTE_INST_ID:
3904
+ if (nla_len(iter) != sizeof(uint16)) {
3905
+ ret = -EINVAL;
3906
+ goto exit;
3907
+ }
3908
+ cmd_data->local_id = nla_get_u16(iter);
3909
+ break;
3910
+ case NAN_ATTRIBUTE_SUBSCRIBE_COUNT:
3911
+ if (nla_len(iter) != sizeof(uint8)) {
3912
+ ret = -EINVAL;
3913
+ goto exit;
3914
+ }
3915
+ cmd_data->life_count = nla_get_u8(iter);
3916
+ break;
3917
+ case NAN_ATTRIBUTE_SSIREQUIREDFORMATCHINDICATION: {
3918
+ if (nla_len(iter) != sizeof(uint8)) {
3919
+ ret = -EINVAL;
3920
+ goto exit;
3921
+ }
3922
+ bit_flag = (u32)nla_get_u8(iter);
3923
+ cmd_data->flags |=
3924
+ bit_flag ? WL_NAN_SUB_MATCH_IF_SVC_INFO : 0;
3925
+ break;
3926
+ }
3927
+ case NAN_ATTRIBUTE_SUBSCRIBE_MATCH:
3928
+ case NAN_ATTRIBUTE_PUBLISH_MATCH: {
3929
+ if (nla_len(iter) != sizeof(uint8)) {
3930
+ ret = -EINVAL;
3931
+ goto exit;
3932
+ }
3933
+ flag_match = nla_get_u8(iter);
3934
+
3935
+ switch (flag_match) {
3936
+ case NAN_MATCH_ALG_MATCH_CONTINUOUS:
3937
+ /* Default fw behaviour, no need to set explicitly */
3938
+ break;
3939
+ case NAN_MATCH_ALG_MATCH_ONCE:
3940
+ cmd_data->flags |= WL_NAN_MATCH_ONCE;
3941
+ break;
3942
+ case NAN_MATCH_ALG_MATCH_NEVER:
3943
+ cmd_data->flags |= WL_NAN_MATCH_NEVER;
3944
+ break;
3945
+ default:
3946
+ WL_ERR(("invalid nan match alg = %u\n", flag_match));
3947
+ ret = -EINVAL;
3948
+ goto exit;
3949
+ }
3950
+ break;
3951
+ }
3952
+ case NAN_ATTRIBUTE_SERVICERESPONSEFILTER:
3953
+ if (nla_len(iter) != sizeof(uint8)) {
3954
+ ret = -EINVAL;
3955
+ goto exit;
3956
+ }
3957
+ cmd_data->srf_type = nla_get_u8(iter);
3958
+ break;
3959
+ case NAN_ATTRIBUTE_SERVICERESPONSEINCLUDE:
3960
+ if (nla_len(iter) != sizeof(uint8)) {
3961
+ ret = -EINVAL;
3962
+ goto exit;
3963
+ }
3964
+ cmd_data->srf_include = nla_get_u8(iter);
3965
+ break;
3966
+ case NAN_ATTRIBUTE_USESERVICERESPONSEFILTER:
3967
+ if (nla_len(iter) != sizeof(uint8)) {
3968
+ ret = -EINVAL;
3969
+ goto exit;
3970
+ }
3971
+ cmd_data->use_srf = nla_get_u8(iter);
3972
+ break;
3973
+ case NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN:
3974
+ if (nla_len(iter) != sizeof(uint16)) {
3975
+ ret = -EINVAL;
3976
+ goto exit;
3977
+ }
3978
+ if (cmd_data->rx_match.dlen) {
3979
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
3980
+ ret = -EINVAL;
3981
+ goto exit;
3982
+ }
3983
+ cmd_data->rx_match.dlen = nla_get_u16(iter);
3984
+ if (cmd_data->rx_match.dlen > MAX_MATCH_FILTER_LEN) {
3985
+ ret = -EINVAL;
3986
+ WL_ERR_RLMT(("Not allowed beyond %d\n", MAX_MATCH_FILTER_LEN));
3987
+ goto exit;
3988
+ }
3989
+ break;
3990
+ case NAN_ATTRIBUTE_RX_MATCH_FILTER:
3991
+ if ((!cmd_data->rx_match.dlen) ||
3992
+ (nla_len(iter) != cmd_data->rx_match.dlen)) {
3993
+ WL_ERR(("RX match filter len wrong:%d,%d\n",
3994
+ cmd_data->rx_match.dlen, nla_len(iter)));
3995
+ ret = -EINVAL;
3996
+ goto exit;
3997
+ }
3998
+ if (cmd_data->rx_match.data) {
3999
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
4000
+ ret = -EINVAL;
4001
+ goto exit;
4002
+ }
4003
+ cmd_data->rx_match.data =
4004
+ MALLOCZ(cfg->osh, cmd_data->rx_match.dlen);
4005
+ if (cmd_data->rx_match.data == NULL) {
4006
+ WL_ERR(("failed to allocate LEN=[%u]\n",
4007
+ cmd_data->rx_match.dlen));
4008
+ ret = -ENOMEM;
4009
+ goto exit;
4010
+ }
4011
+ ret = memcpy_s(cmd_data->rx_match.data, cmd_data->rx_match.dlen,
4012
+ nla_data(iter), nla_len(iter));
4013
+ if (ret != BCME_OK) {
4014
+ WL_ERR(("Failed to copy rx match data\n"));
4015
+ return ret;
4016
+ }
4017
+ break;
4018
+ case NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN:
4019
+ if (nla_len(iter) != sizeof(uint16)) {
4020
+ ret = -EINVAL;
4021
+ goto exit;
4022
+ }
4023
+ if (cmd_data->tx_match.dlen) {
4024
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
4025
+ ret = -EINVAL;
4026
+ goto exit;
4027
+ }
4028
+ cmd_data->tx_match.dlen = nla_get_u16(iter);
4029
+ if (cmd_data->tx_match.dlen > MAX_MATCH_FILTER_LEN) {
4030
+ ret = -EINVAL;
4031
+ WL_ERR_RLMT(("Not allowed beyond %d\n", MAX_MATCH_FILTER_LEN));
4032
+ goto exit;
4033
+ }
4034
+ break;
4035
+ case NAN_ATTRIBUTE_TX_MATCH_FILTER:
4036
+ if ((!cmd_data->tx_match.dlen) ||
4037
+ (nla_len(iter) != cmd_data->tx_match.dlen)) {
4038
+ WL_ERR(("TX match filter len wrong:%d,%d\n",
4039
+ cmd_data->tx_match.dlen, nla_len(iter)));
4040
+ ret = -EINVAL;
4041
+ goto exit;
4042
+ }
4043
+ if (cmd_data->tx_match.data) {
4044
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
4045
+ ret = -EINVAL;
4046
+ goto exit;
4047
+ }
4048
+ cmd_data->tx_match.data =
4049
+ MALLOCZ(cfg->osh, cmd_data->tx_match.dlen);
4050
+ if (cmd_data->tx_match.data == NULL) {
4051
+ WL_ERR(("failed to allocate LEN=[%u]\n",
4052
+ cmd_data->tx_match.dlen));
4053
+ ret = -EINVAL;
4054
+ goto exit;
4055
+ }
4056
+ ret = memcpy_s(cmd_data->tx_match.data, cmd_data->tx_match.dlen,
4057
+ nla_data(iter), nla_len(iter));
4058
+ if (ret != BCME_OK) {
4059
+ WL_ERR(("Failed to copy tx match data\n"));
4060
+ return ret;
4061
+ }
4062
+ break;
4063
+ case NAN_ATTRIBUTE_MAC_ADDR_LIST_NUM_ENTRIES:
4064
+ if (nla_len(iter) != sizeof(uint16)) {
4065
+ ret = -EINVAL;
4066
+ goto exit;
4067
+ }
4068
+ if (cmd_data->mac_list.num_mac_addr) {
4069
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
4070
+ ret = -EINVAL;
4071
+ goto exit;
4072
+ }
4073
+ cmd_data->mac_list.num_mac_addr = nla_get_u16(iter);
4074
+ break;
4075
+ case NAN_ATTRIBUTE_MAC_ADDR_LIST:
4076
+ if ((!cmd_data->mac_list.num_mac_addr) ||
4077
+ (nla_len(iter) != (cmd_data->mac_list.num_mac_addr * ETHER_ADDR_LEN))) {
4078
+ WL_ERR(("wrong mac list len:%d,%d\n",
4079
+ cmd_data->mac_list.num_mac_addr, nla_len(iter)));
4080
+ ret = -EINVAL;
4081
+ goto exit;
4082
+ }
4083
+ if (cmd_data->mac_list.list) {
4084
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
4085
+ ret = -EINVAL;
4086
+ goto exit;
4087
+ }
4088
+ cmd_data->mac_list.list =
4089
+ MALLOCZ(cfg->osh, (cmd_data->mac_list.num_mac_addr
4090
+ * ETHER_ADDR_LEN));
4091
+ if (cmd_data->mac_list.list == NULL) {
4092
+ WL_ERR(("failed to allocate LEN=[%u]\n",
4093
+ (cmd_data->mac_list.num_mac_addr * ETHER_ADDR_LEN)));
4094
+ ret = -ENOMEM;
4095
+ goto exit;
4096
+ }
4097
+ ret = memcpy_s(cmd_data->mac_list.list,
4098
+ (cmd_data->mac_list.num_mac_addr * ETHER_ADDR_LEN),
4099
+ nla_data(iter), nla_len(iter));
4100
+ if (ret != BCME_OK) {
4101
+ WL_ERR(("Failed to copy list of mac addresses\n"));
4102
+ return ret;
4103
+ }
4104
+ break;
4105
+ case NAN_ATTRIBUTE_TX_TYPE:
4106
+ if (nla_len(iter) != sizeof(uint8)) {
4107
+ ret = -EINVAL;
4108
+ goto exit;
4109
+ }
4110
+ val_u8 = nla_get_u8(iter);
4111
+ if (val_u8 == 0) {
4112
+ cmd_data->flags |= WL_NAN_PUB_BCAST;
4113
+ WL_TRACE(("NAN_ATTRIBUTE_TX_TYPE: flags=NAN_PUB_BCAST\n"));
4114
+ }
4115
+ break;
4116
+ case NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP:
4117
+ if (nla_len(iter) != sizeof(uint8)) {
4118
+ ret = -EINVAL;
4119
+ goto exit;
4120
+ }
4121
+ if (nla_get_u8(iter) == 1) {
4122
+ cmd_data->sde_control_flag
4123
+ |= NAN_SDE_CF_DP_REQUIRED;
4124
+ break;
4125
+ }
4126
+ break;
4127
+ case NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT:
4128
+ if (nla_len(iter) != sizeof(uint8)) {
4129
+ ret = -EINVAL;
4130
+ goto exit;
4131
+ }
4132
+ cmd_data->sde_control_config = TRUE;
4133
+ if (nla_get_u8(iter) == 1) {
4134
+ cmd_data->sde_control_flag
4135
+ |= NAN_SDE_CF_RANGING_REQUIRED;
4136
+ break;
4137
+ }
4138
+ break;
4139
+ case NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE:
4140
+ if (nla_len(iter) != sizeof(uint8)) {
4141
+ ret = -EINVAL;
4142
+ goto exit;
4143
+ }
4144
+ if (nla_get_u8(iter) == 1) {
4145
+ cmd_data->sde_control_flag
4146
+ |= NAN_SDE_CF_MULTICAST_TYPE;
4147
+ break;
4148
+ }
4149
+ break;
4150
+ case NAN_ATTRIBUTE_SDE_CONTROL_SECURITY:
4151
+ if (nla_len(iter) != sizeof(uint8)) {
4152
+ ret = -EINVAL;
4153
+ goto exit;
4154
+ }
4155
+ if (nla_get_u8(iter) == 1) {
4156
+ cmd_data->sde_control_flag
4157
+ |= NAN_SDE_CF_SECURITY_REQUIRED;
4158
+ break;
4159
+ }
4160
+ break;
4161
+ case NAN_ATTRIBUTE_RECV_IND_CFG:
4162
+ if (nla_len(iter) != sizeof(uint8)) {
4163
+ ret = -EINVAL;
4164
+ goto exit;
4165
+ }
4166
+ cmd_data->recv_ind_flag = nla_get_u8(iter);
4167
+ break;
4168
+ case NAN_ATTRIBUTE_CIPHER_SUITE_TYPE:
4169
+ if (nla_len(iter) != sizeof(uint8)) {
4170
+ ret = -EINVAL;
4171
+ goto exit;
4172
+ }
4173
+ cmd_data->csid = nla_get_u8(iter);
4174
+ WL_TRACE(("CSID = %u\n", cmd_data->csid));
4175
+ break;
4176
+ case NAN_ATTRIBUTE_KEY_TYPE:
4177
+ if (nla_len(iter) != sizeof(uint8)) {
4178
+ ret = -EINVAL;
4179
+ goto exit;
4180
+ }
4181
+ cmd_data->key_type = nla_get_u8(iter);
4182
+ WL_TRACE(("Key Type = %u\n", cmd_data->key_type));
4183
+ break;
4184
+ case NAN_ATTRIBUTE_KEY_LEN:
4185
+ if (nla_len(iter) != sizeof(uint32)) {
4186
+ ret = -EINVAL;
4187
+ goto exit;
4188
+ }
4189
+ if (cmd_data->key.dlen) {
4190
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
4191
+ ret = -EINVAL;
4192
+ goto exit;
4193
+ }
4194
+ cmd_data->key.dlen = nla_get_u32(iter);
4195
+ if ((!cmd_data->key.dlen) || (cmd_data->key.dlen > WL_NAN_NCS_SK_PMK_LEN)) {
4196
+ WL_ERR(("invalid key length = %u\n",
4197
+ cmd_data->key.dlen));
4198
+ break;
4199
+ }
4200
+ WL_TRACE(("valid key length = %u\n", cmd_data->key.dlen));
4201
+ break;
4202
+ case NAN_ATTRIBUTE_KEY_DATA:
4203
+ if (!cmd_data->key.dlen ||
4204
+ (nla_len(iter) != cmd_data->key.dlen)) {
4205
+ WL_ERR(("failed to allocate key data by invalid len=%d,%d\n",
4206
+ cmd_data->key.dlen, nla_len(iter)));
4207
+ ret = -EINVAL;
4208
+ goto exit;
4209
+ }
4210
+ if (cmd_data->key.data) {
4211
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
4212
+ ret = -EINVAL;
4213
+ goto exit;
4214
+ }
4215
+
4216
+ cmd_data->key.data = MALLOCZ(cfg->osh, NAN_MAX_PMK_LEN);
4217
+ if (cmd_data->key.data == NULL) {
4218
+ WL_ERR(("failed to allocate key data, len=%d\n",
4219
+ cmd_data->key.dlen));
4220
+ ret = -ENOMEM;
4221
+ goto exit;
4222
+ }
4223
+ ret = memcpy_s(cmd_data->key.data, NAN_MAX_PMK_LEN,
4224
+ nla_data(iter), nla_len(iter));
4225
+ if (ret != BCME_OK) {
4226
+ WL_ERR(("Failed to key data\n"));
4227
+ return ret;
4228
+ }
4229
+ break;
4230
+ case NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG:
4231
+ if (nla_len(iter) != sizeof(uint8)) {
4232
+ ret = -EINVAL;
4233
+ goto exit;
4234
+ }
4235
+ if (nla_get_u8(iter) == 1) {
4236
+ cmd_data->flags |=
4237
+ WL_NAN_RANGE_LIMITED;
4238
+ break;
4239
+ }
4240
+ break;
4241
+ case NAN_ATTRIBUTE_DISC_IND_CFG:
4242
+ if (nla_len(iter) != sizeof(uint8)) {
4243
+ ret = -EINVAL;
4244
+ goto exit;
4245
+ }
4246
+ cmd_data->disc_ind_cfg = nla_get_u8(iter);
4247
+ break;
4248
+ case NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN:
4249
+ if (nla_len(iter) != sizeof(uint16)) {
4250
+ ret = -EINVAL;
4251
+ goto exit;
4252
+ }
4253
+ if (cmd_data->sde_svc_info.dlen) {
4254
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
4255
+ ret = -EINVAL;
4256
+ goto exit;
4257
+ }
4258
+ cmd_data->sde_svc_info.dlen = nla_get_u16(iter);
4259
+ if (cmd_data->sde_svc_info.dlen > MAX_SDEA_SVC_INFO_LEN) {
4260
+ ret = -EINVAL;
4261
+ WL_ERR_RLMT(("Not allowed beyond %d\n", MAX_SDEA_SVC_INFO_LEN));
4262
+ goto exit;
4263
+ }
4264
+ break;
4265
+ case NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO:
4266
+ if ((!cmd_data->sde_svc_info.dlen) ||
4267
+ (nla_len(iter) != cmd_data->sde_svc_info.dlen)) {
4268
+ WL_ERR(("wrong sdea info len:%d,%d\n",
4269
+ cmd_data->sde_svc_info.dlen, nla_len(iter)));
4270
+ ret = -EINVAL;
4271
+ goto exit;
4272
+ }
4273
+ if (cmd_data->sde_svc_info.data) {
4274
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
4275
+ ret = -EINVAL;
4276
+ goto exit;
4277
+ }
4278
+ cmd_data->sde_svc_info.data = MALLOCZ(cfg->osh,
4279
+ cmd_data->sde_svc_info.dlen);
4280
+ if (cmd_data->sde_svc_info.data == NULL) {
4281
+ WL_ERR(("failed to allocate svc info data, len=%d\n",
4282
+ cmd_data->sde_svc_info.dlen));
4283
+ ret = -ENOMEM;
4284
+ goto exit;
4285
+ }
4286
+ ret = memcpy_s(cmd_data->sde_svc_info.data,
4287
+ cmd_data->sde_svc_info.dlen,
4288
+ nla_data(iter), nla_len(iter));
4289
+ if (ret != BCME_OK) {
4290
+ WL_ERR(("Failed to sdea info data\n"));
4291
+ return ret;
4292
+ }
4293
+ break;
4294
+ case NAN_ATTRIBUTE_SECURITY:
4295
+ if (nla_len(iter) != sizeof(uint8)) {
4296
+ ret = -EINVAL;
4297
+ goto exit;
4298
+ }
4299
+ cmd_data->ndp_cfg.security_cfg = nla_get_u8(iter);
4300
+ break;
4301
+ case NAN_ATTRIBUTE_RANGING_INTERVAL:
4302
+ if (nla_len(iter) != sizeof(uint32)) {
4303
+ ret = -EINVAL;
4304
+ goto exit;
4305
+ }
4306
+ cmd_data->ranging_intvl_msec = nla_get_u32(iter);
4307
+ break;
4308
+ case NAN_ATTRIBUTE_RANGING_INGRESS_LIMIT:
4309
+ if (nla_len(iter) != sizeof(uint32)) {
4310
+ ret = -EINVAL;
4311
+ goto exit;
4312
+ }
4313
+ cmd_data->ingress_limit = nla_get_u32(iter);
4314
+ break;
4315
+ case NAN_ATTRIBUTE_RANGING_EGRESS_LIMIT:
4316
+ if (nla_len(iter) != sizeof(uint32)) {
4317
+ ret = -EINVAL;
4318
+ goto exit;
4319
+ }
4320
+ cmd_data->egress_limit = nla_get_u32(iter);
4321
+ break;
4322
+ case NAN_ATTRIBUTE_RANGING_INDICATION:
4323
+ if (nla_len(iter) != sizeof(uint32)) {
4324
+ ret = -EINVAL;
4325
+ goto exit;
4326
+ }
4327
+ cmd_data->ranging_indication = nla_get_u32(iter);
4328
+ break;
4329
+ /* Nan accept policy: Per service basis policy
4330
+ * Based on this policy(ALL/NONE), responder side
4331
+ * will send ACCEPT/REJECT
4332
+ */
4333
+ case NAN_ATTRIBUTE_SVC_RESPONDER_POLICY:
4334
+ if (nla_len(iter) != sizeof(uint8)) {
4335
+ ret = -EINVAL;
4336
+ goto exit;
4337
+ }
4338
+ cmd_data->service_responder_policy = nla_get_u8(iter);
4339
+ break;
4340
+ default:
4341
+ WL_ERR(("Unknown type, %d\n", attr_type));
4342
+ ret = -EINVAL;
4343
+ goto exit;
4344
+ }
4345
+ }
4346
+exit:
4347
+ /* We need to call set_config_handler b/f calling start enable TBD */
4348
+ NAN_DBG_EXIT();
4349
+ return ret;
4350
+}
4351
+
4352
+static int
4353
+wl_cfgvendor_nan_parse_args(struct wiphy *wiphy, const void *buf,
4354
+ int len, nan_config_cmd_data_t *cmd_data, uint32 *nan_attr_mask)
4355
+{
4356
+ int ret = BCME_OK;
4357
+ int attr_type = 0;
4358
+ int rem = len;
4359
+ const struct nlattr *iter;
4360
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4361
+ int chan;
4362
+ u8 sid_beacon = 0, sub_sid_beacon = 0;
4363
+
4364
+ NAN_DBG_ENTER();
4365
+
4366
+ nla_for_each_attr(iter, buf, len, rem) {
4367
+ attr_type = nla_type(iter);
4368
+ WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type), attr_type));
4369
+
4370
+ switch (attr_type) {
4371
+ /* NAN Enable request attributes */
4372
+ case NAN_ATTRIBUTE_2G_SUPPORT:{
4373
+ if (nla_len(iter) != sizeof(uint8)) {
4374
+ ret = -EINVAL;
4375
+ goto exit;
4376
+ }
4377
+ cmd_data->support_2g = nla_get_u8(iter);
4378
+ *nan_attr_mask |= NAN_ATTR_SUPPORT_2G_CONFIG;
4379
+ break;
4380
+ }
4381
+ case NAN_ATTRIBUTE_5G_SUPPORT:{
4382
+ if (nla_len(iter) != sizeof(uint8)) {
4383
+ ret = -EINVAL;
4384
+ goto exit;
4385
+ }
4386
+ cmd_data->support_5g = nla_get_u8(iter);
4387
+ *nan_attr_mask |= NAN_ATTR_SUPPORT_5G_CONFIG;
4388
+ break;
4389
+ }
4390
+ case NAN_ATTRIBUTE_CLUSTER_LOW: {
4391
+ if (nla_len(iter) != sizeof(uint16)) {
4392
+ ret = -EINVAL;
4393
+ goto exit;
4394
+ }
4395
+ cmd_data->clus_id.octet[5] = nla_get_u16(iter);
4396
+ break;
4397
+ }
4398
+ case NAN_ATTRIBUTE_CLUSTER_HIGH: {
4399
+ if (nla_len(iter) != sizeof(uint16)) {
4400
+ ret = -EINVAL;
4401
+ goto exit;
4402
+ }
4403
+ cmd_data->clus_id.octet[4] = nla_get_u16(iter);
4404
+ break;
4405
+ }
4406
+ case NAN_ATTRIBUTE_SID_BEACON: {
4407
+ if (nla_len(iter) != sizeof(uint8)) {
4408
+ ret = -EINVAL;
4409
+ goto exit;
4410
+ }
4411
+ sid_beacon = nla_get_u8(iter);
4412
+ cmd_data->sid_beacon.sid_enable = (sid_beacon & 0x01);
4413
+ if (cmd_data->sid_beacon.sid_enable) {
4414
+ cmd_data->sid_beacon.sid_count = (sid_beacon >> 1);
4415
+ *nan_attr_mask |= NAN_ATTR_SID_BEACON_CONFIG;
4416
+ }
4417
+ break;
4418
+ }
4419
+ case NAN_ATTRIBUTE_SUB_SID_BEACON: {
4420
+ if (nla_len(iter) != sizeof(uint8)) {
4421
+ ret = -EINVAL;
4422
+ goto exit;
4423
+ }
4424
+ sub_sid_beacon = nla_get_u8(iter);
4425
+ cmd_data->sid_beacon.sub_sid_enable = (sub_sid_beacon & 0x01);
4426
+ if (cmd_data->sid_beacon.sub_sid_enable) {
4427
+ cmd_data->sid_beacon.sub_sid_count = (sub_sid_beacon >> 1);
4428
+ *nan_attr_mask |= NAN_ATTR_SUB_SID_BEACON_CONFIG;
4429
+ }
4430
+ break;
4431
+ }
4432
+ case NAN_ATTRIBUTE_SYNC_DISC_2G_BEACON:
4433
+ if (nla_len(iter) != sizeof(uint8)) {
4434
+ ret = -EINVAL;
4435
+ goto exit;
4436
+ }
4437
+ cmd_data->beacon_2g_val = nla_get_u8(iter);
4438
+ *nan_attr_mask |= NAN_ATTR_SYNC_DISC_2G_BEACON_CONFIG;
4439
+ break;
4440
+ case NAN_ATTRIBUTE_SYNC_DISC_5G_BEACON:
4441
+ if (nla_len(iter) != sizeof(uint8)) {
4442
+ ret = -EINVAL;
4443
+ goto exit;
4444
+ }
4445
+ cmd_data->beacon_5g_val = nla_get_u8(iter);
4446
+ *nan_attr_mask |= NAN_ATTR_SYNC_DISC_5G_BEACON_CONFIG;
4447
+ break;
4448
+ case NAN_ATTRIBUTE_SDF_2G_SUPPORT:
4449
+ if (nla_len(iter) != sizeof(uint8)) {
4450
+ ret = -EINVAL;
4451
+ goto exit;
4452
+ }
4453
+ cmd_data->sdf_2g_val = nla_get_u8(iter);
4454
+ *nan_attr_mask |= NAN_ATTR_SDF_2G_SUPPORT_CONFIG;
4455
+ break;
4456
+ case NAN_ATTRIBUTE_SDF_5G_SUPPORT:
4457
+ if (nla_len(iter) != sizeof(uint8)) {
4458
+ ret = -EINVAL;
4459
+ goto exit;
4460
+ }
4461
+ cmd_data->sdf_5g_val = nla_get_u8(iter);
4462
+ *nan_attr_mask |= NAN_ATTR_SDF_5G_SUPPORT_CONFIG;
4463
+ break;
4464
+ case NAN_ATTRIBUTE_HOP_COUNT_LIMIT:
4465
+ if (nla_len(iter) != sizeof(uint8)) {
4466
+ ret = -EINVAL;
4467
+ goto exit;
4468
+ }
4469
+ cmd_data->hop_count_limit = nla_get_u8(iter);
4470
+ *nan_attr_mask |= NAN_ATTR_HOP_COUNT_LIMIT_CONFIG;
4471
+ break;
4472
+ case NAN_ATTRIBUTE_RANDOM_TIME:
4473
+ if (nla_len(iter) != sizeof(uint8)) {
4474
+ ret = -EINVAL;
4475
+ goto exit;
4476
+ }
4477
+ cmd_data->metrics.random_factor = nla_get_u8(iter);
4478
+ *nan_attr_mask |= NAN_ATTR_RAND_FACTOR_CONFIG;
4479
+ break;
4480
+ case NAN_ATTRIBUTE_MASTER_PREF:
4481
+ if (nla_len(iter) != sizeof(uint8)) {
4482
+ ret = -EINVAL;
4483
+ goto exit;
4484
+ }
4485
+ cmd_data->metrics.master_pref = nla_get_u8(iter);
4486
+ break;
4487
+ case NAN_ATTRIBUTE_OUI:
4488
+ if (nla_len(iter) != sizeof(uint32)) {
4489
+ ret = -EINVAL;
4490
+ goto exit;
4491
+ }
4492
+ cmd_data->nan_oui = nla_get_u32(iter);
4493
+ *nan_attr_mask |= NAN_ATTR_OUI_CONFIG;
4494
+ WL_TRACE(("nan_oui=%d\n", cmd_data->nan_oui));
4495
+ break;
4496
+ case NAN_ATTRIBUTE_WARMUP_TIME:
4497
+ if (nla_len(iter) != sizeof(uint16)) {
4498
+ ret = -EINVAL;
4499
+ goto exit;
4500
+ }
4501
+ cmd_data->warmup_time = nla_get_u16(iter);
4502
+ break;
4503
+ case NAN_ATTRIBUTE_AMBTT:
4504
+ case NAN_ATTRIBUTE_MASTER_RANK:
4505
+ WL_DBG(("Unhandled attribute, %d\n", attr_type));
4506
+ break;
4507
+ case NAN_ATTRIBUTE_CHANNEL: {
4508
+ if (nla_len(iter) != sizeof(uint32)) {
4509
+ ret = -EINVAL;
4510
+ goto exit;
4511
+ }
4512
+ /* take the default channel start_factor frequency */
4513
+ chan = wf_mhz2channel((uint)nla_get_u32(iter), 0);
4514
+ if (chan <= CH_MAX_2G_CHANNEL) {
4515
+ cmd_data->chanspec[0] = wf_channel2chspec(chan, WL_CHANSPEC_BW_20);
4516
+ } else {
4517
+ cmd_data->chanspec[0] = wf_channel2chspec(chan, WL_CHANSPEC_BW_80);
4518
+ }
4519
+ if (cmd_data->chanspec[0] == 0) {
4520
+ WL_ERR(("Channel is not valid \n"));
4521
+ ret = -EINVAL;
4522
+ goto exit;
4523
+ }
4524
+ WL_TRACE(("valid chanspec, chanspec = 0x%04x \n",
4525
+ cmd_data->chanspec[0]));
4526
+ break;
4527
+ }
4528
+ case NAN_ATTRIBUTE_24G_CHANNEL: {
4529
+ if (nla_len(iter) != sizeof(uint32)) {
4530
+ ret = -EINVAL;
4531
+ goto exit;
4532
+ }
4533
+ /* take the default channel start_factor frequency */
4534
+ chan = wf_mhz2channel((uint)nla_get_u32(iter), 0);
4535
+ /* 20MHz as BW */
4536
+ cmd_data->chanspec[1] = wf_channel2chspec(chan, WL_CHANSPEC_BW_20);
4537
+ if (cmd_data->chanspec[1] == 0) {
4538
+ WL_ERR((" 2.4GHz Channel is not valid \n"));
4539
+ ret = -EINVAL;
4540
+ break;
4541
+ }
4542
+ *nan_attr_mask |= NAN_ATTR_2G_CHAN_CONFIG;
4543
+ WL_TRACE(("valid 2.4GHz chanspec, chanspec = 0x%04x \n",
4544
+ cmd_data->chanspec[1]));
4545
+ break;
4546
+ }
4547
+ case NAN_ATTRIBUTE_5G_CHANNEL: {
4548
+ if (nla_len(iter) != sizeof(uint32)) {
4549
+ ret = -EINVAL;
4550
+ goto exit;
4551
+ }
4552
+ /* take the default channel start_factor frequency */
4553
+ chan = wf_mhz2channel((uint)nla_get_u32(iter), 0);
4554
+ /* 20MHz as BW */
4555
+ cmd_data->chanspec[2] = wf_channel2chspec(chan, WL_CHANSPEC_BW_20);
4556
+ if (cmd_data->chanspec[2] == 0) {
4557
+ WL_ERR((" 5GHz Channel is not valid \n"));
4558
+ ret = -EINVAL;
4559
+ break;
4560
+ }
4561
+ *nan_attr_mask |= NAN_ATTR_5G_CHAN_CONFIG;
4562
+ WL_TRACE(("valid 5GHz chanspec, chanspec = 0x%04x \n",
4563
+ cmd_data->chanspec[2]));
4564
+ break;
4565
+ }
4566
+ case NAN_ATTRIBUTE_CONF_CLUSTER_VAL:
4567
+ if (nla_len(iter) != sizeof(uint8)) {
4568
+ ret = -EINVAL;
4569
+ goto exit;
4570
+ }
4571
+ cmd_data->config_cluster_val = nla_get_u8(iter);
4572
+ *nan_attr_mask |= NAN_ATTR_CLUSTER_VAL_CONFIG;
4573
+ break;
4574
+ case NAN_ATTRIBUTE_DWELL_TIME:
4575
+ if (nla_len(iter) != sizeof(uint8)) {
4576
+ ret = -EINVAL;
4577
+ goto exit;
4578
+ }
4579
+ cmd_data->dwell_time[0] = nla_get_u8(iter);
4580
+ *nan_attr_mask |= NAN_ATTR_2G_DWELL_TIME_CONFIG;
4581
+ break;
4582
+ case NAN_ATTRIBUTE_SCAN_PERIOD:
4583
+ if (nla_len(iter) != sizeof(uint16)) {
4584
+ ret = -EINVAL;
4585
+ goto exit;
4586
+ }
4587
+ cmd_data->scan_period[0] = nla_get_u16(iter);
4588
+ *nan_attr_mask |= NAN_ATTR_2G_SCAN_PERIOD_CONFIG;
4589
+ break;
4590
+ case NAN_ATTRIBUTE_DWELL_TIME_5G:
4591
+ if (nla_len(iter) != sizeof(uint8)) {
4592
+ ret = -EINVAL;
4593
+ goto exit;
4594
+ }
4595
+ cmd_data->dwell_time[1] = nla_get_u8(iter);
4596
+ *nan_attr_mask |= NAN_ATTR_5G_DWELL_TIME_CONFIG;
4597
+ break;
4598
+ case NAN_ATTRIBUTE_SCAN_PERIOD_5G:
4599
+ if (nla_len(iter) != sizeof(uint16)) {
4600
+ ret = -EINVAL;
4601
+ goto exit;
4602
+ }
4603
+ cmd_data->scan_period[1] = nla_get_u16(iter);
4604
+ *nan_attr_mask |= NAN_ATTR_5G_SCAN_PERIOD_CONFIG;
4605
+ break;
4606
+ case NAN_ATTRIBUTE_AVAIL_BIT_MAP:
4607
+ if (nla_len(iter) != sizeof(uint32)) {
4608
+ ret = -EINVAL;
4609
+ goto exit;
4610
+ }
4611
+ cmd_data->bmap = nla_get_u32(iter);
4612
+ break;
4613
+ case NAN_ATTRIBUTE_ENTRY_CONTROL:
4614
+ if (nla_len(iter) != sizeof(uint8)) {
4615
+ ret = -EINVAL;
4616
+ goto exit;
4617
+ }
4618
+ cmd_data->avail_params.duration = nla_get_u8(iter);
4619
+ break;
4620
+ case NAN_ATTRIBUTE_RSSI_CLOSE:
4621
+ if (nla_len(iter) != sizeof(uint8)) {
4622
+ ret = -EINVAL;
4623
+ goto exit;
4624
+ }
4625
+ cmd_data->rssi_attr.rssi_close_2dot4g_val = nla_get_s8(iter);
4626
+ *nan_attr_mask |= NAN_ATTR_RSSI_CLOSE_CONFIG;
4627
+ break;
4628
+ case NAN_ATTRIBUTE_RSSI_MIDDLE:
4629
+ if (nla_len(iter) != sizeof(uint8)) {
4630
+ ret = -EINVAL;
4631
+ goto exit;
4632
+ }
4633
+ cmd_data->rssi_attr.rssi_middle_2dot4g_val = nla_get_s8(iter);
4634
+ *nan_attr_mask |= NAN_ATTR_RSSI_MIDDLE_2G_CONFIG;
4635
+ break;
4636
+ case NAN_ATTRIBUTE_RSSI_PROXIMITY:
4637
+ if (nla_len(iter) != sizeof(uint8)) {
4638
+ ret = -EINVAL;
4639
+ goto exit;
4640
+ }
4641
+ cmd_data->rssi_attr.rssi_proximity_2dot4g_val = nla_get_s8(iter);
4642
+ *nan_attr_mask |= NAN_ATTR_RSSI_PROXIMITY_2G_CONFIG;
4643
+ break;
4644
+ case NAN_ATTRIBUTE_RSSI_CLOSE_5G:
4645
+ if (nla_len(iter) != sizeof(uint8)) {
4646
+ ret = -EINVAL;
4647
+ goto exit;
4648
+ }
4649
+ cmd_data->rssi_attr.rssi_close_5g_val = nla_get_s8(iter);
4650
+ *nan_attr_mask |= NAN_ATTR_RSSI_CLOSE_5G_CONFIG;
4651
+ break;
4652
+ case NAN_ATTRIBUTE_RSSI_MIDDLE_5G:
4653
+ if (nla_len(iter) != sizeof(uint8)) {
4654
+ ret = -EINVAL;
4655
+ goto exit;
4656
+ }
4657
+ cmd_data->rssi_attr.rssi_middle_5g_val = nla_get_s8(iter);
4658
+ *nan_attr_mask |= NAN_ATTR_RSSI_MIDDLE_5G_CONFIG;
4659
+ break;
4660
+ case NAN_ATTRIBUTE_RSSI_PROXIMITY_5G:
4661
+ if (nla_len(iter) != sizeof(uint8)) {
4662
+ ret = -EINVAL;
4663
+ goto exit;
4664
+ }
4665
+ cmd_data->rssi_attr.rssi_proximity_5g_val = nla_get_s8(iter);
4666
+ *nan_attr_mask |= NAN_ATTR_RSSI_PROXIMITY_5G_CONFIG;
4667
+ break;
4668
+ case NAN_ATTRIBUTE_RSSI_WINDOW_SIZE:
4669
+ if (nla_len(iter) != sizeof(uint8)) {
4670
+ ret = -EINVAL;
4671
+ goto exit;
4672
+ }
4673
+ cmd_data->rssi_attr.rssi_window_size = nla_get_u8(iter);
4674
+ *nan_attr_mask |= NAN_ATTR_RSSI_WINDOW_SIZE_CONFIG;
4675
+ break;
4676
+ case NAN_ATTRIBUTE_CIPHER_SUITE_TYPE:
4677
+ if (nla_len(iter) != sizeof(uint8)) {
4678
+ ret = -EINVAL;
4679
+ goto exit;
4680
+ }
4681
+ cmd_data->csid = nla_get_u8(iter);
4682
+ WL_TRACE(("CSID = %u\n", cmd_data->csid));
4683
+ break;
4684
+ case NAN_ATTRIBUTE_SCID_LEN:
4685
+ if (nla_len(iter) != sizeof(uint32)) {
4686
+ ret = -EINVAL;
4687
+ goto exit;
4688
+ }
4689
+ if (cmd_data->scid.dlen) {
4690
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
4691
+ ret = -EINVAL;
4692
+ goto exit;
4693
+ }
4694
+ cmd_data->scid.dlen = nla_get_u32(iter);
4695
+ if (cmd_data->scid.dlen > MAX_SCID_LEN) {
4696
+ ret = -EINVAL;
4697
+ WL_ERR_RLMT(("Not allowed beyond %d\n", MAX_SCID_LEN));
4698
+ goto exit;
4699
+ }
4700
+ WL_TRACE(("valid scid length = %u\n", cmd_data->scid.dlen));
4701
+ break;
4702
+ case NAN_ATTRIBUTE_SCID:
4703
+ if (!cmd_data->scid.dlen || (nla_len(iter) != cmd_data->scid.dlen)) {
4704
+ WL_ERR(("wrong scid len:%d,%d\n", cmd_data->scid.dlen,
4705
+ nla_len(iter)));
4706
+ ret = -EINVAL;
4707
+ goto exit;
4708
+ }
4709
+ if (cmd_data->scid.data) {
4710
+ WL_ERR(("trying to overwrite:%d\n", attr_type));
4711
+ ret = -EINVAL;
4712
+ goto exit;
4713
+ }
4714
+
4715
+ cmd_data->scid.data = MALLOCZ(cfg->osh, cmd_data->scid.dlen);
4716
+ if (cmd_data->scid.data == NULL) {
4717
+ WL_ERR(("failed to allocate scid, len=%d\n",
4718
+ cmd_data->scid.dlen));
4719
+ ret = -ENOMEM;
4720
+ goto exit;
4721
+ }
4722
+ ret = memcpy_s(cmd_data->scid.data, cmd_data->scid.dlen,
4723
+ nla_data(iter), nla_len(iter));
4724
+ if (ret != BCME_OK) {
4725
+ WL_ERR(("Failed to scid data\n"));
4726
+ return ret;
4727
+ }
4728
+ break;
4729
+ case NAN_ATTRIBUTE_2G_AWAKE_DW:
4730
+ if (nla_len(iter) != sizeof(uint32)) {
4731
+ ret = -EINVAL;
4732
+ goto exit;
4733
+ }
4734
+ if (nla_get_u32(iter) > NAN_MAX_AWAKE_DW_INTERVAL) {
4735
+ WL_ERR(("%s: Invalid/Out of bound value = %u\n",
4736
+ __FUNCTION__, nla_get_u32(iter)));
4737
+ ret = -EINVAL;
4738
+ goto exit;
4739
+ }
4740
+ if (nla_get_u32(iter)) {
4741
+ cmd_data->awake_dws.dw_interval_2g =
4742
+ 1 << (nla_get_u32(iter)-1);
4743
+ }
4744
+ *nan_attr_mask |= NAN_ATTR_2G_DW_CONFIG;
4745
+ break;
4746
+ case NAN_ATTRIBUTE_5G_AWAKE_DW:
4747
+ if (nla_len(iter) != sizeof(uint32)) {
4748
+ ret = -EINVAL;
4749
+ goto exit;
4750
+ }
4751
+ if (nla_get_u32(iter) > NAN_MAX_AWAKE_DW_INTERVAL) {
4752
+ WL_ERR(("%s: Invalid/Out of bound value = %u\n",
4753
+ __FUNCTION__, nla_get_u32(iter)));
4754
+ ret = BCME_BADARG;
4755
+ break;
4756
+ }
4757
+ if (nla_get_u32(iter)) {
4758
+ cmd_data->awake_dws.dw_interval_5g =
4759
+ 1 << (nla_get_u32(iter)-1);
4760
+ }
4761
+ *nan_attr_mask |= NAN_ATTR_5G_DW_CONFIG;
4762
+ break;
4763
+ case NAN_ATTRIBUTE_DISC_IND_CFG:
4764
+ if (nla_len(iter) != sizeof(uint8)) {
4765
+ ret = -EINVAL;
4766
+ goto exit;
4767
+ }
4768
+ cmd_data->disc_ind_cfg = nla_get_u8(iter);
4769
+ break;
4770
+ case NAN_ATTRIBUTE_MAC_ADDR:
4771
+ if (nla_len(iter) != ETHER_ADDR_LEN) {
4772
+ ret = -EINVAL;
4773
+ goto exit;
4774
+ }
4775
+ ret = memcpy_s((char*)&cmd_data->mac_addr, ETHER_ADDR_LEN,
4776
+ (char*)nla_data(iter), nla_len(iter));
4777
+ if (ret != BCME_OK) {
4778
+ WL_ERR(("Failed to copy mac addr\n"));
4779
+ return ret;
4780
+ }
4781
+ break;
4782
+ case NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL:
4783
+ if (nla_len(iter) != sizeof(uint32)) {
4784
+ ret = -EINVAL;
4785
+ goto exit;
4786
+ }
4787
+ cmd_data->nmi_rand_intvl = nla_get_u8(iter);
4788
+ if (cmd_data->nmi_rand_intvl > 0) {
4789
+ cfg->nancfg.mac_rand = true;
4790
+ } else {
4791
+ cfg->nancfg.mac_rand = false;
4792
+ }
4793
+ break;
4794
+ default:
4795
+ WL_ERR(("%s: Unknown type, %d\n", __FUNCTION__, attr_type));
4796
+ ret = -EINVAL;
4797
+ goto exit;
4798
+ }
4799
+ }
4800
+
4801
+exit:
4802
+ /* We need to call set_config_handler b/f calling start enable TBD */
4803
+ NAN_DBG_EXIT();
4804
+ if (ret) {
4805
+ WL_ERR(("%s: Failed to parse attribute %d ret %d",
4806
+ __FUNCTION__, attr_type, ret));
4807
+ }
4808
+ return ret;
4809
+
4810
+}
4811
+
4812
+static int
4813
+wl_cfgvendor_nan_dp_estb_event_data_filler(struct sk_buff *msg,
4814
+ nan_event_data_t *event_data) {
4815
+ int ret = BCME_OK;
4816
+ ret = nla_put_u32(msg, NAN_ATTRIBUTE_NDP_ID, event_data->ndp_id);
4817
+ if (unlikely(ret)) {
4818
+ WL_ERR(("Failed to put NDP ID, ret=%d\n", ret));
4819
+ goto fail;
4820
+ }
4821
+ /*
4822
+ * NDI mac address of the peer
4823
+ * (required to derive target ipv6 address)
4824
+ */
4825
+ ret = nla_put(msg, NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR, ETH_ALEN,
4826
+ event_data->responder_ndi.octet);
4827
+ if (unlikely(ret)) {
4828
+ WL_ERR(("Failed to put resp ndi, ret=%d\n", ret));
4829
+ goto fail;
4830
+ }
4831
+ ret = nla_put_u8(msg, NAN_ATTRIBUTE_RSP_CODE, event_data->status);
4832
+ if (unlikely(ret)) {
4833
+ WL_ERR(("Failed to put response code, ret=%d\n", ret));
4834
+ goto fail;
4835
+ }
4836
+ if (event_data->svc_info.dlen && event_data->svc_info.data) {
4837
+ ret = nla_put_u16(msg, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN,
4838
+ event_data->svc_info.dlen);
4839
+ if (unlikely(ret)) {
4840
+ WL_ERR(("Failed to put svc info len, ret=%d\n", ret));
4841
+ goto fail;
4842
+ }
4843
+ ret = nla_put(msg, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO,
4844
+ event_data->svc_info.dlen, event_data->svc_info.data);
4845
+ if (unlikely(ret)) {
4846
+ WL_ERR(("Failed to put svc info, ret=%d\n", ret));
4847
+ goto fail;
4848
+ }
4849
+ }
4850
+
4851
+fail:
4852
+ return ret;
4853
+}
4854
+static int
4855
+wl_cfgvendor_nan_dp_ind_event_data_filler(struct sk_buff *msg,
4856
+ nan_event_data_t *event_data) {
4857
+ int ret = BCME_OK;
4858
+
4859
+ ret = nla_put_u16(msg, NAN_ATTRIBUTE_PUBLISH_ID,
4860
+ event_data->pub_id);
4861
+ if (unlikely(ret)) {
4862
+ WL_ERR(("Failed to put pub ID, ret=%d\n", ret));
4863
+ goto fail;
4864
+ }
4865
+ ret = nla_put_u32(msg, NAN_ATTRIBUTE_NDP_ID, event_data->ndp_id);
4866
+ if (unlikely(ret)) {
4867
+ WL_ERR(("Failed to put NDP ID, ret=%d\n", ret));
4868
+ goto fail;
4869
+ }
4870
+ /* Discovery MAC addr of the peer/initiator */
4871
+ ret = nla_put(msg, NAN_ATTRIBUTE_MAC_ADDR, ETH_ALEN,
4872
+ event_data->remote_nmi.octet);
4873
+ if (unlikely(ret)) {
4874
+ WL_ERR(("Failed to put remote NMI, ret=%d\n", ret));
4875
+ goto fail;
4876
+ }
4877
+ ret = nla_put_u8(msg, NAN_ATTRIBUTE_SECURITY, event_data->security);
4878
+ if (unlikely(ret)) {
4879
+ WL_ERR(("Failed to put security, ret=%d\n", ret));
4880
+ goto fail;
4881
+ }
4882
+ if (event_data->svc_info.dlen && event_data->svc_info.data) {
4883
+ ret = nla_put_u16(msg, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN,
4884
+ event_data->svc_info.dlen);
4885
+ if (unlikely(ret)) {
4886
+ WL_ERR(("Failed to put svc info len, ret=%d\n", ret));
4887
+ goto fail;
4888
+ }
4889
+ ret = nla_put(msg, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO,
4890
+ event_data->svc_info.dlen, event_data->svc_info.data);
4891
+ if (unlikely(ret)) {
4892
+ WL_ERR(("Failed to put svc info, ret=%d\n", ret));
4893
+ goto fail;
4894
+ }
4895
+ }
4896
+
4897
+fail:
4898
+ return ret;
4899
+}
4900
+
4901
+static int
4902
+wl_cfgvendor_nan_tx_followup_ind_event_data_filler(struct sk_buff *msg,
4903
+ nan_event_data_t *event_data) {
4904
+ int ret = BCME_OK;
4905
+ ret = nla_put_u16(msg, NAN_ATTRIBUTE_TRANSAC_ID, event_data->token);
4906
+ if (unlikely(ret)) {
4907
+ WL_ERR(("Failed to put transaction id, ret=%d\n", ret));
4908
+ goto fail;
4909
+ }
4910
+ ret = nla_put_u8(msg, NAN_ATTRIBUTE_HANDLE, event_data->local_inst_id);
4911
+ if (unlikely(ret)) {
4912
+ WL_ERR(("Failed to put handle, ret=%d\n", ret));
4913
+ goto fail;
4914
+ }
4915
+ ret = nla_put_u16(msg, NAN_ATTRIBUTE_STATUS, event_data->status);
4916
+ if (unlikely(ret)) {
4917
+ WL_ERR(("Failed to put nan status, ret=%d\n", ret));
4918
+ goto fail;
4919
+ }
4920
+ if (event_data->status == NAN_STATUS_SUCCESS) {
4921
+ ret = nla_put(msg, NAN_ATTRIBUTE_REASON,
4922
+ strlen("NAN_STATUS_SUCCESS"), event_data->nan_reason);
4923
+ if (unlikely(ret)) {
4924
+ WL_ERR(("Failed to put nan reason, ret=%d\n", ret));
4925
+ goto fail;
4926
+ }
4927
+ } else {
4928
+ ret = nla_put(msg, NAN_ATTRIBUTE_REASON,
4929
+ strlen("NAN_STATUS_NO_OTA_ACK"), event_data->nan_reason);
4930
+ if (unlikely(ret)) {
4931
+ WL_ERR(("Failed to put nan reason, ret=%d\n", ret));
4932
+ goto fail;
4933
+ }
4934
+ }
4935
+fail:
4936
+ return ret;
4937
+}
4938
+
4939
+static int
4940
+wl_cfgvendor_nan_svc_terminate_event_filler(struct sk_buff *msg,
4941
+ struct bcm_cfg80211 *cfg, int event_id, nan_event_data_t *event_data) {
4942
+ int ret = BCME_OK;
4943
+ ret = nla_put_u8(msg, NAN_ATTRIBUTE_HANDLE, event_data->local_inst_id);
4944
+ if (unlikely(ret)) {
4945
+ WL_ERR(("Failed to put handle, ret=%d\n", ret));
4946
+ goto fail;
4947
+ }
4948
+
4949
+ if (event_id == GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED) {
4950
+ ret = nla_put_u16(msg, NAN_ATTRIBUTE_SUBSCRIBE_ID,
4951
+ event_data->local_inst_id);
4952
+ if (unlikely(ret)) {
4953
+ WL_ERR(("Failed to put local inst id, ret=%d\n", ret));
4954
+ goto fail;
4955
+ }
4956
+ } else {
4957
+ ret = nla_put_u16(msg, NAN_ATTRIBUTE_PUBLISH_ID,
4958
+ event_data->local_inst_id);
4959
+ if (unlikely(ret)) {
4960
+ WL_ERR(("Failed to put local inst id, ret=%d\n", ret));
4961
+ goto fail;
4962
+ }
4963
+ }
4964
+ ret = nla_put_u16(msg, NAN_ATTRIBUTE_STATUS, event_data->status);
4965
+ if (unlikely(ret)) {
4966
+ WL_ERR(("Failed to put status, ret=%d\n", ret));
4967
+ goto fail;
4968
+ }
4969
+ if (event_data->status == NAN_STATUS_SUCCESS) {
4970
+ ret = nla_put(msg, NAN_ATTRIBUTE_REASON,
4971
+ strlen("NAN_STATUS_SUCCESS"), event_data->nan_reason);
4972
+ if (unlikely(ret)) {
4973
+ WL_ERR(("Failed to put nan reason, ret=%d\n", ret));
4974
+ goto fail;
4975
+ }
4976
+ } else {
4977
+ ret = nla_put(msg, NAN_ATTRIBUTE_REASON,
4978
+ strlen("NAN_STATUS_INTERNAL_FAILURE"), event_data->nan_reason);
4979
+ if (unlikely(ret)) {
4980
+ WL_ERR(("Failed to put nan reason, ret=%d\n", ret));
4981
+ goto fail;
4982
+ }
4983
+ }
4984
+
4985
+ ret = wl_cfgnan_remove_inst_id(cfg, event_data->local_inst_id);
4986
+ if (ret) {
4987
+ WL_ERR(("failed to free svc instance-id[%d], ret=%d, event_id = %d\n",
4988
+ event_data->local_inst_id, ret, event_id));
4989
+ goto fail;
4990
+ }
4991
+fail:
4992
+ return ret;
4993
+}
4994
+
4995
+static int
4996
+wl_cfgvendor_nan_opt_params_filler(struct sk_buff *msg,
4997
+ nan_event_data_t *event_data) {
4998
+ int ret = BCME_OK;
4999
+ /* service specific info data */
5000
+ if (event_data->svc_info.dlen && event_data->svc_info.data) {
5001
+ ret = nla_put_u16(msg, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN,
5002
+ event_data->svc_info.dlen);
5003
+ if (unlikely(ret)) {
5004
+ WL_ERR(("Failed to put svc info len, ret=%d\n", ret));
5005
+ goto fail;
5006
+ }
5007
+ ret = nla_put(msg, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO,
5008
+ event_data->svc_info.dlen, event_data->svc_info.data);
5009
+ if (unlikely(ret)) {
5010
+ WL_ERR(("Failed to put svc info, ret=%d\n", ret));
5011
+ goto fail;
5012
+ }
5013
+ WL_TRACE(("svc info len = %d\n", event_data->svc_info.dlen));
5014
+ }
5015
+
5016
+ /* sdea service specific info data */
5017
+ if (event_data->sde_svc_info.dlen && event_data->sde_svc_info.data) {
5018
+ ret = nla_put_u16(msg, NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN,
5019
+ event_data->sde_svc_info.dlen);
5020
+ if (unlikely(ret)) {
5021
+ WL_ERR(("Failed to put sdea svc info len, ret=%d\n", ret));
5022
+ goto fail;
5023
+ }
5024
+ ret = nla_put(msg, NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO,
5025
+ event_data->sde_svc_info.dlen,
5026
+ event_data->sde_svc_info.data);
5027
+ if (unlikely(ret)) {
5028
+ WL_ERR(("Failed to put sdea svc info, ret=%d\n", ret));
5029
+ goto fail;
5030
+ }
5031
+ WL_TRACE(("sdea svc info len = %d\n", event_data->sde_svc_info.dlen));
5032
+ }
5033
+ /* service control discovery range limit */
5034
+ /* TODO: */
5035
+
5036
+ /* service control binding bitmap */
5037
+ /* TODO: */
5038
+fail:
5039
+ return ret;
5040
+}
5041
+
5042
+static int
5043
+wl_cfgvendor_nan_tx_followup_event_filler(struct sk_buff *msg,
5044
+ nan_event_data_t *event_data) {
5045
+ int ret = BCME_OK;
5046
+ /* In followup pkt, instance id and requestor instance id are configured
5047
+ * from the transmitter perspective. As the event is processed with the
5048
+ * role of receiver, the local handle should use requestor instance
5049
+ * id (peer_inst_id)
5050
+ */
5051
+ WL_TRACE(("handle=%d\n", event_data->requestor_id));
5052
+ WL_TRACE(("inst id (local id)=%d\n", event_data->local_inst_id));
5053
+ WL_TRACE(("peer id (remote id)=%d\n", event_data->requestor_id));
5054
+ WL_TRACE(("peer mac addr=" MACDBG "\n",
5055
+ MAC2STRDBG(event_data->remote_nmi.octet)));
5056
+ WL_TRACE(("peer rssi: %d\n", event_data->fup_rssi));
5057
+ WL_TRACE(("attribute no: %d\n", event_data->attr_num));
5058
+ WL_TRACE(("attribute len: %d\n", event_data->attr_list_len));
5059
+
5060
+ ret = nla_put_u8(msg, NAN_ATTRIBUTE_HANDLE, event_data->requestor_id);
5061
+ if (unlikely(ret)) {
5062
+ WL_ERR(("Failed to put handle, ret=%d\n", ret));
5063
+ goto fail;
5064
+ }
5065
+ ret = nla_put_u32(msg, NAN_ATTRIBUTE_INST_ID, event_data->local_inst_id);
5066
+ if (unlikely(ret)) {
5067
+ WL_ERR(("Failed to put local inst id, ret=%d\n", ret));
5068
+ goto fail;
5069
+ }
5070
+ ret = nla_put_u16(msg, NAN_ATTRIBUTE_PEER_ID, event_data->requestor_id);
5071
+ if (unlikely(ret)) {
5072
+ WL_ERR(("Failed to put requestor inst id, ret=%d\n", ret));
5073
+ goto fail;
5074
+ }
5075
+ ret = nla_put(msg, NAN_ATTRIBUTE_MAC_ADDR, ETHER_ADDR_LEN,
5076
+ event_data->remote_nmi.octet);
5077
+ if (unlikely(ret)) {
5078
+ WL_ERR(("Failed to put remote nmi, ret=%d\n", ret));
5079
+ goto fail;
5080
+ }
5081
+ ret = nla_put_s8(msg, NAN_ATTRIBUTE_RSSI_PROXIMITY,
5082
+ event_data->fup_rssi);
5083
+ if (unlikely(ret)) {
5084
+ WL_ERR(("Failed to put fup rssi, ret=%d\n", ret));
5085
+ goto fail;
5086
+ }
5087
+fail:
5088
+ return ret;
5089
+}
5090
+
5091
+static int
5092
+wl_cfgvendor_nan_sub_match_event_filler(struct sk_buff *msg,
5093
+ nan_event_data_t *event_data) {
5094
+ int ret = BCME_OK;
5095
+ WL_TRACE(("handle (sub_id)=%d\n", event_data->sub_id));
5096
+ WL_TRACE(("pub id=%d\n", event_data->pub_id));
5097
+ WL_TRACE(("sub id=%d\n", event_data->sub_id));
5098
+ WL_TRACE(("pub mac addr=" MACDBG "\n",
5099
+ MAC2STRDBG(event_data->remote_nmi.octet)));
5100
+ WL_TRACE(("attr no: %d\n", event_data->attr_num));
5101
+ WL_TRACE(("attr len: %d\n", event_data->attr_list_len));
5102
+
5103
+ ret = nla_put_u8(msg, NAN_ATTRIBUTE_HANDLE, event_data->sub_id);
5104
+ if (unlikely(ret)) {
5105
+ WL_ERR(("Failed to put handle, ret=%d\n", ret));
5106
+ goto fail;
5107
+ }
5108
+ ret = nla_put_u16(msg, NAN_ATTRIBUTE_PUBLISH_ID, event_data->pub_id);
5109
+ if (unlikely(ret)) {
5110
+ WL_ERR(("Failed to put pub id, ret=%d\n", ret));
5111
+ goto fail;
5112
+ }
5113
+ ret = nla_put_u16(msg, NAN_ATTRIBUTE_SUBSCRIBE_ID, event_data->sub_id);
5114
+ if (unlikely(ret)) {
5115
+ WL_ERR(("Failed to put Sub Id, ret=%d\n", ret));
5116
+ goto fail;
5117
+ }
5118
+ ret = nla_put(msg, NAN_ATTRIBUTE_MAC_ADDR, ETHER_ADDR_LEN,
5119
+ event_data->remote_nmi.octet);
5120
+ if (unlikely(ret)) {
5121
+ WL_ERR(("Failed to put remote NMI, ret=%d\n", ret));
5122
+ goto fail;
5123
+ }
5124
+ if (event_data->publish_rssi) {
5125
+ event_data->publish_rssi = -event_data->publish_rssi;
5126
+ ret = nla_put_u8(msg, NAN_ATTRIBUTE_RSSI_PROXIMITY,
5127
+ event_data->publish_rssi);
5128
+ if (unlikely(ret)) {
5129
+ WL_ERR(("Failed to put publish rssi, ret=%d\n", ret));
5130
+ goto fail;
5131
+ }
5132
+ }
5133
+ if (event_data->ranging_result_present) {
5134
+ ret = nla_put_u32(msg, NAN_ATTRIBUTE_RANGING_INDICATION,
5135
+ event_data->ranging_ind);
5136
+ if (unlikely(ret)) {
5137
+ WL_ERR(("Failed to put ranging ind, ret=%d\n", ret));
5138
+ goto fail;
5139
+ }
5140
+ ret = nla_put_u32(msg, NAN_ATTRIBUTE_RANGING_RESULT,
5141
+ event_data->range_measurement_cm);
5142
+ if (unlikely(ret)) {
5143
+ WL_ERR(("Failed to put range measurement cm, ret=%d\n",
5144
+ ret));
5145
+ goto fail;
5146
+ }
5147
+ }
5148
+ /*
5149
+ * handling optional service control, service response filter
5150
+ */
5151
+ if (event_data->tx_match_filter.dlen && event_data->tx_match_filter.data) {
5152
+ ret = nla_put_u16(msg, NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN,
5153
+ event_data->tx_match_filter.dlen);
5154
+ if (unlikely(ret)) {
5155
+ WL_ERR(("Failed to put tx match filter len, ret=%d\n",
5156
+ ret));
5157
+ goto fail;
5158
+ }
5159
+ ret = nla_put(msg, NAN_ATTRIBUTE_TX_MATCH_FILTER,
5160
+ event_data->tx_match_filter.dlen,
5161
+ event_data->tx_match_filter.data);
5162
+ if (unlikely(ret)) {
5163
+ WL_ERR(("Failed to put tx match filter data, ret=%d\n",
5164
+ ret));
5165
+ goto fail;
5166
+ }
5167
+ WL_TRACE(("tx matching filter (%d):\n",
5168
+ event_data->tx_match_filter.dlen));
5169
+ }
5170
+
5171
+fail:
5172
+ return ret;
5173
+}
5174
+
5175
+static int
5176
+wl_cfgvendor_nan_de_event_filler(struct sk_buff *msg, nan_event_data_t *event_data)
5177
+{
5178
+ int ret = BCME_OK;
5179
+ ret = nla_put_u8(msg, NAN_ATTRIBUTE_ENABLE_STATUS, event_data->enabled);
5180
+ if (unlikely(ret)) {
5181
+ WL_ERR(("Failed to put event_data->enabled, ret=%d\n", ret));
5182
+ goto fail;
5183
+ }
5184
+ ret = nla_put_u8(msg, NAN_ATTRIBUTE_DE_EVENT_TYPE,
5185
+ event_data->nan_de_evt_type);
5186
+ if (unlikely(ret)) {
5187
+ WL_ERR(("Failed to put nan_de_evt_type, ret=%d\n", ret));
5188
+ goto fail;
5189
+ }
5190
+ ret = nla_put(msg, NAN_ATTRIBUTE_CLUSTER_ID, ETH_ALEN,
5191
+ event_data->clus_id.octet);
5192
+ if (unlikely(ret)) {
5193
+ WL_ERR(("Failed to put clust id, ret=%d\n", ret));
5194
+ goto fail;
5195
+ }
5196
+ /* OOB tests requires local nmi */
5197
+ ret = nla_put(msg, NAN_ATTRIBUTE_MAC_ADDR, ETH_ALEN,
5198
+ event_data->local_nmi.octet);
5199
+ if (unlikely(ret)) {
5200
+ WL_ERR(("Failed to put NMI, ret=%d\n", ret));
5201
+ goto fail;
5202
+ }
5203
+fail:
5204
+ return ret;
5205
+}
5206
+
5207
+#ifdef RTT_SUPPORT
5208
+s32
5209
+wl_cfgvendor_send_as_rtt_legacy_event(struct wiphy *wiphy, struct net_device *dev,
5210
+ wl_nan_ev_rng_rpt_ind_t *range_res, uint32 status)
5211
+{
5212
+ s32 ret = BCME_OK;
5213
+ gfp_t kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
5214
+ rtt_report_t *report = NULL;
5215
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5216
+ struct sk_buff *msg = NULL;
5217
+ struct nlattr *rtt_nl_hdr;
5218
+
5219
+ NAN_DBG_ENTER();
5220
+
5221
+ report = MALLOCZ(cfg->osh, sizeof(*report));
5222
+ if (!report) {
5223
+ WL_ERR(("%s: memory allocation failed\n", __func__));
5224
+ ret = BCME_NOMEM;
5225
+ goto exit;
5226
+ }
5227
+ if (range_res) {
5228
+ report->distance = range_res->dist_mm/10;
5229
+ ret = memcpy_s(&report->addr, ETHER_ADDR_LEN,
5230
+ &range_res->peer_m_addr, ETHER_ADDR_LEN);
5231
+ if (ret != BCME_OK) {
5232
+ WL_ERR(("Failed to copy peer_m_addr\n"));
5233
+ goto exit;
5234
+ }
5235
+ }
5236
+ report->status = (rtt_reason_t)status;
5237
+ report->type = RTT_TWO_WAY;
5238
+
5239
+#if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
5240
+ LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
5241
+ msg = cfg80211_vendor_event_alloc(wiphy, NULL, 100,
5242
+ GOOGLE_RTT_COMPLETE_EVENT, kflags);
5243
+#else
5244
+ msg = cfg80211_vendor_event_alloc(wiphy, 100, GOOGLE_RTT_COMPLETE_EVENT, kflags);
5245
+#endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
5246
+ /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
5247
+ if (!msg) {
5248
+ WL_ERR(("%s: fail to allocate skb for vendor event\n", __FUNCTION__));
5249
+ ret = BCME_NOMEM;
5250
+ goto exit;
5251
+ }
5252
+
5253
+ ret = nla_put_u32(msg, RTT_ATTRIBUTE_RESULTS_COMPLETE, 1);
5254
+ if (ret < 0) {
5255
+ WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULTS_COMPLETE\n"));
5256
+ goto exit;
5257
+ }
5258
+ rtt_nl_hdr = nla_nest_start(msg, RTT_ATTRIBUTE_RESULTS_PER_TARGET);
5259
+ if (!rtt_nl_hdr) {
5260
+ WL_ERR(("rtt_nl_hdr is NULL\n"));
5261
+ ret = BCME_NOMEM;
5262
+ goto exit;
5263
+ }
5264
+ ret = nla_put(msg, RTT_ATTRIBUTE_TARGET_MAC, ETHER_ADDR_LEN, &report->addr);
5265
+ if (ret < 0) {
5266
+ WL_ERR(("Failed to put RTT_ATTRIBUTE_TARGET_MAC\n"));
5267
+ goto exit;
5268
+ }
5269
+ ret = nla_put_u32(msg, RTT_ATTRIBUTE_RESULT_CNT, 1);
5270
+ if (ret < 0) {
5271
+ WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULT_CNT\n"));
5272
+ goto exit;
5273
+ }
5274
+ ret = nla_put(msg, RTT_ATTRIBUTE_RESULT,
5275
+ sizeof(*report), report);
5276
+ if (ret < 0) {
5277
+ WL_ERR(("Failed to put RTT_ATTRIBUTE_RESULTS\n"));
5278
+ goto exit;
5279
+ }
5280
+ nla_nest_end(msg, rtt_nl_hdr);
5281
+ cfg80211_vendor_event(msg, kflags);
5282
+ if (report) {
5283
+ MFREE(cfg->osh, report, sizeof(*report));
5284
+ }
5285
+
5286
+ return ret;
5287
+exit:
5288
+ if (msg)
5289
+ dev_kfree_skb_any(msg);
5290
+ WL_ERR(("Failed to send event GOOGLE_RTT_COMPLETE_EVENT,"
5291
+ " -- Free skb, ret = %d\n", ret));
5292
+ if (report)
5293
+ MFREE(cfg->osh, report, sizeof(*report));
5294
+ NAN_DBG_EXIT();
5295
+ return ret;
5296
+}
5297
+#endif /* RTT_SUPPORT */
5298
+
5299
+int
5300
+wl_cfgvendor_send_nan_event(struct wiphy *wiphy, struct net_device *dev,
5301
+ int event_id, nan_event_data_t *event_data)
5302
+{
5303
+ int ret = BCME_OK;
5304
+ int buf_len = NAN_EVENT_BUFFER_SIZE_LARGE;
5305
+ gfp_t kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
5306
+
5307
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5308
+ struct sk_buff *msg;
5309
+
5310
+ NAN_DBG_ENTER();
5311
+
5312
+ /* Allocate the skb for vendor event */
5313
+#if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
5314
+ LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
5315
+ msg = cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(dev), buf_len, event_id, kflags);
5316
+#else
5317
+ msg = cfg80211_vendor_event_alloc(wiphy, buf_len, event_id, kflags);
5318
+#endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
5319
+ /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
5320
+
5321
+ if (!msg) {
5322
+ WL_ERR(("%s: fail to allocate skb for vendor event\n", __FUNCTION__));
5323
+ return -ENOMEM;
5324
+ }
5325
+
5326
+ switch (event_id) {
5327
+ case GOOGLE_NAN_EVENT_DE_EVENT: {
5328
+ WL_INFORM_MEM(("[NAN] GOOGLE_NAN_DE_EVENT cluster id=" MACDBG "nmi= " MACDBG "\n",
5329
+ MAC2STRDBG(event_data->clus_id.octet),
5330
+ MAC2STRDBG(event_data->local_nmi.octet)));
5331
+ ret = wl_cfgvendor_nan_de_event_filler(msg, event_data);
5332
+ if (unlikely(ret)) {
5333
+ WL_ERR(("Failed to fill de event data, ret=%d\n", ret));
5334
+ goto fail;
5335
+ }
5336
+ break;
5337
+ }
5338
+ case GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH:
5339
+ case GOOGLE_NAN_EVENT_FOLLOWUP: {
5340
+ if (event_id == GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH) {
5341
+ WL_DBG(("GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH\n"));
5342
+ ret = wl_cfgvendor_nan_sub_match_event_filler(msg, event_data);
5343
+ if (unlikely(ret)) {
5344
+ WL_ERR(("Failed to fill sub match event data, ret=%d\n", ret));
5345
+ goto fail;
5346
+ }
5347
+ } else if (event_id == GOOGLE_NAN_EVENT_FOLLOWUP) {
5348
+ WL_DBG(("GOOGLE_NAN_EVENT_FOLLOWUP\n"));
5349
+ ret = wl_cfgvendor_nan_tx_followup_event_filler(msg, event_data);
5350
+ if (unlikely(ret)) {
5351
+ WL_ERR(("Failed to fill sub match event data, ret=%d\n", ret));
5352
+ goto fail;
5353
+ }
5354
+ }
5355
+ ret = wl_cfgvendor_nan_opt_params_filler(msg, event_data);
5356
+ if (unlikely(ret)) {
5357
+ WL_ERR(("Failed to fill sub match event data, ret=%d\n", ret));
5358
+ goto fail;
5359
+ }
5360
+ break;
5361
+ }
5362
+
5363
+ case GOOGLE_NAN_EVENT_DISABLED: {
5364
+ WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DISABLED\n"));
5365
+ ret = nla_put_u8(msg, NAN_ATTRIBUTE_HANDLE, 0);
5366
+ if (unlikely(ret)) {
5367
+ WL_ERR(("Failed to put handle, ret=%d\n", ret));
5368
+ goto fail;
5369
+ }
5370
+ ret = nla_put_u16(msg, NAN_ATTRIBUTE_STATUS, event_data->status);
5371
+ if (unlikely(ret)) {
5372
+ WL_ERR(("Failed to put status, ret=%d\n", ret));
5373
+ goto fail;
5374
+ }
5375
+ ret = nla_put(msg, NAN_ATTRIBUTE_REASON,
5376
+ strlen("NAN_STATUS_SUCCESS"), event_data->nan_reason);
5377
+ if (unlikely(ret)) {
5378
+ WL_ERR(("Failed to put reason code, ret=%d\n", ret));
5379
+ goto fail;
5380
+ }
5381
+ break;
5382
+ }
5383
+
5384
+ case GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED:
5385
+ case GOOGLE_NAN_EVENT_PUBLISH_TERMINATED: {
5386
+ WL_DBG(("GOOGLE_NAN_SVC_TERMINATED, %d\n", event_id));
5387
+ ret = wl_cfgvendor_nan_svc_terminate_event_filler(msg, cfg, event_id, event_data);
5388
+ if (unlikely(ret)) {
5389
+ WL_ERR(("Failed to fill svc terminate event data, ret=%d\n", ret));
5390
+ goto fail;
5391
+ }
5392
+ break;
5393
+ }
5394
+
5395
+ case GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND: {
5396
+ WL_DBG(("GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND %d\n",
5397
+ GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND));
5398
+ ret = wl_cfgvendor_nan_tx_followup_ind_event_data_filler(msg, event_data);
5399
+ if (unlikely(ret)) {
5400
+ WL_ERR(("Failed to fill tx follow up ind event data, ret=%d\n", ret));
5401
+ goto fail;
5402
+ }
5403
+
5404
+ break;
5405
+ }
5406
+
5407
+ case GOOGLE_NAN_EVENT_DATA_REQUEST: {
5408
+ WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DATA_REQUEST\n"));
5409
+ ret = wl_cfgvendor_nan_dp_ind_event_data_filler(msg, event_data);
5410
+ if (unlikely(ret)) {
5411
+ WL_ERR(("Failed to fill dp ind event data, ret=%d\n", ret));
5412
+ goto fail;
5413
+ }
5414
+ break;
5415
+ }
5416
+
5417
+ case GOOGLE_NAN_EVENT_DATA_CONFIRMATION: {
5418
+ WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DATA_CONFIRMATION\n"));
5419
+
5420
+ ret = wl_cfgvendor_nan_dp_estb_event_data_filler(msg, event_data);
5421
+ if (unlikely(ret)) {
5422
+ WL_ERR(("Failed to fill dp estb event data, ret=%d\n", ret));
5423
+ goto fail;
5424
+ }
5425
+ break;
5426
+ }
5427
+
5428
+ case GOOGLE_NAN_EVENT_DATA_END: {
5429
+ WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DATA_END\n"));
5430
+ ret = nla_put_u8(msg, NAN_ATTRIBUTE_INST_COUNT, 1);
5431
+ if (unlikely(ret)) {
5432
+ WL_ERR(("Failed to put inst count, ret=%d\n", ret));
5433
+ goto fail;
5434
+ }
5435
+ ret = nla_put_u32(msg, NAN_ATTRIBUTE_NDP_ID, event_data->ndp_id);
5436
+ if (unlikely(ret)) {
5437
+ WL_ERR(("Failed to put ndp id, ret=%d\n", ret));
5438
+ goto fail;
5439
+ }
5440
+ break;
5441
+ }
5442
+
5443
+ default:
5444
+ goto fail;
5445
+ }
5446
+
5447
+ cfg80211_vendor_event(msg, kflags);
5448
+ NAN_DBG_EXIT();
5449
+ return ret;
5450
+
5451
+fail:
5452
+ dev_kfree_skb_any(msg);
5453
+ WL_ERR(("Event not implemented or unknown -- Free skb, event_id = %d, ret = %d\n",
5454
+ event_id, ret));
5455
+ NAN_DBG_EXIT();
5456
+ return ret;
5457
+}
5458
+
5459
+static int
5460
+wl_cfgvendor_nan_req_subscribe(struct wiphy *wiphy,
5461
+ struct wireless_dev *wdev, const void * data, int len)
5462
+{
5463
+ int ret = 0;
5464
+ nan_discover_cmd_data_t *cmd_data = NULL;
5465
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5466
+ nan_hal_resp_t nan_req_resp;
5467
+
5468
+ NAN_DBG_ENTER();
5469
+ /* Blocking Subscribe if NAN is not enable */
5470
+ if (!cfg->nan_enable) {
5471
+ WL_ERR(("nan is not enabled, subscribe blocked\n"));
5472
+ ret = BCME_ERROR;
5473
+ goto exit;
5474
+ }
5475
+ cmd_data = (nan_discover_cmd_data_t *)MALLOCZ(cfg->osh, sizeof(*cmd_data));
5476
+ if (!cmd_data) {
5477
+ WL_ERR(("%s: memory allocation failed\n", __func__));
5478
+ ret = BCME_NOMEM;
5479
+ goto exit;
5480
+ }
5481
+
5482
+ bzero(&nan_req_resp, sizeof(nan_req_resp));
5483
+ ret = wl_cfgvendor_nan_parse_discover_args(wiphy, data, len, cmd_data);
5484
+ if (ret) {
5485
+ WL_ERR(("failed to parse nan disc vendor args, ret = %d\n", ret));
5486
+ goto exit;
5487
+ }
5488
+
5489
+ if (cmd_data->sub_id == 0) {
5490
+ ret = wl_cfgnan_generate_inst_id(cfg, &cmd_data->sub_id);
5491
+ if (ret) {
5492
+ WL_ERR(("failed to generate instance-id for subscribe\n"));
5493
+ goto exit;
5494
+ }
5495
+ } else {
5496
+ cmd_data->svc_update = true;
5497
+ }
5498
+
5499
+ ret = wl_cfgnan_subscribe_handler(wdev->netdev, cfg, cmd_data);
5500
+ if (unlikely(ret) || unlikely(cmd_data->status)) {
5501
+ WL_ERR(("failed to subscribe error[%d], status = [%d]\n",
5502
+ ret, cmd_data->status));
5503
+ wl_cfgnan_remove_inst_id(cfg, cmd_data->sub_id);
5504
+ goto exit;
5505
+ }
5506
+
5507
+ WL_DBG(("subscriber instance id=%d\n", cmd_data->sub_id));
5508
+
5509
+ if (cmd_data->status == WL_NAN_E_OK) {
5510
+ nan_req_resp.instance_id = cmd_data->sub_id;
5511
+ } else {
5512
+ nan_req_resp.instance_id = 0;
5513
+ }
5514
+exit:
5515
+ ret = wl_cfgvendor_nan_cmd_reply(wiphy, NAN_WIFI_SUBCMD_REQUEST_SUBSCRIBE,
5516
+ &nan_req_resp, ret, cmd_data ? cmd_data->status : BCME_OK);
5517
+ wl_cfgvendor_free_disc_cmd_data(cfg, cmd_data);
5518
+ NAN_DBG_EXIT();
5519
+ return ret;
5520
+}
5521
+
5522
+static int
5523
+wl_cfgvendor_nan_req_publish(struct wiphy *wiphy,
5524
+ struct wireless_dev *wdev, const void * data, int len)
5525
+{
5526
+ int ret = 0;
5527
+ nan_discover_cmd_data_t *cmd_data = NULL;
5528
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5529
+ nan_hal_resp_t nan_req_resp;
5530
+ NAN_DBG_ENTER();
5531
+
5532
+ /* Blocking Publish if NAN is not enable */
5533
+ if (!cfg->nan_enable) {
5534
+ WL_ERR(("nan is not enabled publish blocked\n"));
5535
+ ret = BCME_ERROR;
5536
+ goto exit;
5537
+ }
5538
+ cmd_data = (nan_discover_cmd_data_t *)MALLOCZ(cfg->osh, sizeof(*cmd_data));
5539
+ if (!cmd_data) {
5540
+ WL_ERR(("%s: memory allocation failed\n", __func__));
5541
+ ret = BCME_NOMEM;
5542
+ goto exit;
5543
+ }
5544
+
5545
+ bzero(&nan_req_resp, sizeof(nan_req_resp));
5546
+ ret = wl_cfgvendor_nan_parse_discover_args(wiphy, data, len, cmd_data);
5547
+ if (ret) {
5548
+ WL_ERR(("failed to parse nan disc vendor args, ret = %d\n", ret));
5549
+ goto exit;
5550
+ }
5551
+
5552
+ if (cmd_data->pub_id == 0) {
5553
+ ret = wl_cfgnan_generate_inst_id(cfg, &cmd_data->pub_id);
5554
+ if (ret) {
5555
+ WL_ERR(("failed to generate instance-id for publisher\n"));
5556
+ goto exit;
5557
+ }
5558
+ } else {
5559
+ cmd_data->svc_update = true;
5560
+ }
5561
+
5562
+ ret = wl_cfgnan_publish_handler(wdev->netdev, cfg, cmd_data);
5563
+ if (unlikely(ret) || unlikely(cmd_data->status)) {
5564
+ WL_ERR(("failed to publish error[%d], status[%d]\n",
5565
+ ret, cmd_data->status));
5566
+ wl_cfgnan_remove_inst_id(cfg, cmd_data->pub_id);
5567
+ goto exit;
5568
+ }
5569
+
5570
+ WL_DBG(("publisher instance id=%d\n", cmd_data->pub_id));
5571
+
5572
+ if (cmd_data->status == WL_NAN_E_OK) {
5573
+ nan_req_resp.instance_id = cmd_data->pub_id;
5574
+ } else {
5575
+ nan_req_resp.instance_id = 0;
5576
+ }
5577
+exit:
5578
+ ret = wl_cfgvendor_nan_cmd_reply(wiphy, NAN_WIFI_SUBCMD_REQUEST_PUBLISH,
5579
+ &nan_req_resp, ret, cmd_data ? cmd_data->status : BCME_OK);
5580
+ wl_cfgvendor_free_disc_cmd_data(cfg, cmd_data);
5581
+ NAN_DBG_EXIT();
5582
+ return ret;
5583
+}
5584
+
5585
+static int
5586
+wl_cfgvendor_nan_start_handler(struct wiphy *wiphy,
5587
+ struct wireless_dev *wdev, const void *data, int len)
5588
+{
5589
+ int ret = 0;
5590
+ nan_config_cmd_data_t *cmd_data;
5591
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5592
+ nan_hal_resp_t nan_req_resp;
5593
+ uint32 nan_attr_mask = 0;
5594
+
5595
+ cmd_data = (nan_config_cmd_data_t *)MALLOCZ(cfg->osh, sizeof(*cmd_data));
5596
+ if (!cmd_data) {
5597
+ WL_ERR(("%s: memory allocation failed\n", __func__));
5598
+ ret = BCME_NOMEM;
5599
+ goto exit;
5600
+ }
5601
+ NAN_DBG_ENTER();
5602
+
5603
+ if (cfg->nan_enable) {
5604
+ WL_ERR(("nan is already enabled\n"));
5605
+ ret = BCME_OK;
5606
+ goto exit;
5607
+ }
5608
+ bzero(&nan_req_resp, sizeof(nan_req_resp));
5609
+
5610
+ cmd_data->sid_beacon.sid_enable = NAN_SID_ENABLE_FLAG_INVALID; /* Setting to some default */
5611
+ cmd_data->sid_beacon.sid_count = NAN_SID_BEACON_COUNT_INVALID; /* Setting to some default */
5612
+
5613
+ ret = wl_cfgvendor_nan_parse_args(wiphy, data, len, cmd_data, &nan_attr_mask);
5614
+ if (ret) {
5615
+ WL_ERR(("failed to parse nan vendor args, ret %d\n", ret));
5616
+ goto exit;
5617
+ }
5618
+
5619
+ ret = wl_cfgnan_start_handler(wdev->netdev, cfg, cmd_data, nan_attr_mask);
5620
+ if (ret) {
5621
+ WL_ERR(("failed to start nan error[%d]\n", ret));
5622
+ goto exit;
5623
+ }
5624
+ /* Initializing Instance Id List */
5625
+ bzero(cfg->nan_inst_ctrl, NAN_ID_CTRL_SIZE * sizeof(nan_svc_inst_t));
5626
+exit:
5627
+ ret = wl_cfgvendor_nan_cmd_reply(wiphy, NAN_WIFI_SUBCMD_ENABLE,
5628
+ &nan_req_resp, ret, cmd_data ? cmd_data->status : BCME_OK);
5629
+ if (cmd_data) {
5630
+ if (cmd_data->scid.data) {
5631
+ MFREE(cfg->osh, cmd_data->scid.data, cmd_data->scid.dlen);
5632
+ cmd_data->scid.dlen = 0;
5633
+ }
5634
+ MFREE(cfg->osh, cmd_data, sizeof(*cmd_data));
5635
+ }
5636
+ NAN_DBG_EXIT();
5637
+ return ret;
5638
+}
5639
+
5640
+static int
5641
+wl_cfgvendor_nan_stop_handler(struct wiphy *wiphy,
5642
+ struct wireless_dev *wdev, const void * data, int len)
5643
+{
5644
+ int ret = 0;
5645
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5646
+ nan_hal_resp_t nan_req_resp;
5647
+ NAN_DBG_ENTER();
5648
+
5649
+ if (!cfg->nan_init_state) {
5650
+ WL_ERR(("nan is not initialized/nmi doesnt exists\n"));
5651
+ ret = BCME_OK;
5652
+ goto exit;
5653
+ }
5654
+
5655
+ mutex_lock(&cfg->if_sync);
5656
+ if (cfg->nan_enable) {
5657
+ ret = wl_cfgnan_disable(cfg, NAN_USER_INITIATED);
5658
+ if (ret) {
5659
+ WL_ERR(("failed to disable nan, error[%d]\n", ret));
5660
+ }
5661
+ }
5662
+ mutex_unlock(&cfg->if_sync);
5663
+ bzero(&nan_req_resp, sizeof(nan_req_resp));
5664
+exit:
5665
+ ret = wl_cfgvendor_nan_cmd_reply(wiphy, NAN_WIFI_SUBCMD_DISABLE,
5666
+ &nan_req_resp, ret, BCME_OK);
5667
+ NAN_DBG_EXIT();
5668
+ return ret;
5669
+}
5670
+
5671
+static int
5672
+wl_cfgvendor_nan_config_handler(struct wiphy *wiphy,
5673
+ struct wireless_dev *wdev, const void *data, int len)
5674
+{
5675
+ int ret = 0;
5676
+ nan_config_cmd_data_t *cmd_data;
5677
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5678
+ nan_hal_resp_t nan_req_resp;
5679
+ uint32 nan_attr_mask = 0;
5680
+
5681
+ cmd_data = MALLOCZ(cfg->osh, sizeof(*cmd_data));
5682
+ if (!cmd_data) {
5683
+ WL_ERR(("%s: memory allocation failed\n", __func__));
5684
+ ret = BCME_NOMEM;
5685
+ goto exit;
5686
+ }
5687
+ NAN_DBG_ENTER();
5688
+
5689
+ bzero(&nan_req_resp, sizeof(nan_req_resp));
5690
+
5691
+ cmd_data->avail_params.duration = NAN_BAND_INVALID; /* Setting to some default */
5692
+ cmd_data->sid_beacon.sid_enable = NAN_SID_ENABLE_FLAG_INVALID; /* Setting to some default */
5693
+ cmd_data->sid_beacon.sid_count = NAN_SID_BEACON_COUNT_INVALID; /* Setting to some default */
5694
+
5695
+ ret = wl_cfgvendor_nan_parse_args(wiphy, data, len, cmd_data, &nan_attr_mask);
5696
+ if (ret) {
5697
+ WL_ERR(("failed to parse nan vendor args, ret = %d\n", ret));
5698
+ goto exit;
5699
+ }
5700
+
5701
+ ret = wl_cfgnan_config_handler(wdev->netdev, cfg, cmd_data, nan_attr_mask);
5702
+ if (ret) {
5703
+ WL_ERR(("failed in config request, nan error[%d]\n", ret));
5704
+ goto exit;
5705
+ }
5706
+exit:
5707
+ ret = wl_cfgvendor_nan_cmd_reply(wiphy, NAN_WIFI_SUBCMD_CONFIG,
5708
+ &nan_req_resp, ret, cmd_data ? cmd_data->status : BCME_OK);
5709
+ if (cmd_data) {
5710
+ if (cmd_data->scid.data) {
5711
+ MFREE(cfg->osh, cmd_data->scid.data, cmd_data->scid.dlen);
5712
+ cmd_data->scid.dlen = 0;
5713
+ }
5714
+ MFREE(cfg->osh, cmd_data, sizeof(*cmd_data));
5715
+ }
5716
+ NAN_DBG_EXIT();
5717
+ return ret;
5718
+}
5719
+
5720
+static int
5721
+wl_cfgvendor_nan_cancel_publish(struct wiphy *wiphy,
5722
+ struct wireless_dev *wdev, const void * data, int len)
5723
+{
5724
+ int ret = 0;
5725
+ nan_discover_cmd_data_t *cmd_data = NULL;
5726
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5727
+ nan_hal_resp_t nan_req_resp;
5728
+
5729
+ /* Blocking Cancel_Publish if NAN is not enable */
5730
+ if (!cfg->nan_enable) {
5731
+ WL_ERR(("nan is not enabled, cancel publish blocked\n"));
5732
+ ret = BCME_ERROR;
5733
+ goto exit;
5734
+ }
5735
+ cmd_data = (nan_discover_cmd_data_t *)MALLOCZ(cfg->osh, sizeof(*cmd_data));
5736
+ if (!cmd_data) {
5737
+ WL_ERR(("%s: memory allocation failed\n", __func__));
5738
+ ret = BCME_NOMEM;
5739
+ goto exit;
5740
+ }
5741
+ NAN_DBG_ENTER();
5742
+
5743
+ bzero(&nan_req_resp, sizeof(nan_req_resp));
5744
+
5745
+ ret = wl_cfgvendor_nan_parse_discover_args(wiphy, data, len, cmd_data);
5746
+ if (ret) {
5747
+ WL_ERR(("failed to parse nan disc vendor args, ret= %d\n", ret));
5748
+ goto exit;
5749
+ }
5750
+ nan_req_resp.instance_id = cmd_data->pub_id;
5751
+ WL_INFORM_MEM(("[NAN] cancel publish instance_id=%d\n", cmd_data->pub_id));
5752
+
5753
+ ret = wl_cfgnan_cancel_pub_handler(wdev->netdev, cfg, cmd_data);
5754
+ if (ret) {
5755
+ WL_ERR(("failed to cancel publish nan instance-id[%d] error[%d]\n",
5756
+ cmd_data->pub_id, ret));
5757
+ goto exit;
5758
+ }
5759
+exit:
5760
+ ret = wl_cfgvendor_nan_cmd_reply(wiphy, NAN_WIFI_SUBCMD_CANCEL_PUBLISH,
5761
+ &nan_req_resp, ret, cmd_data ? cmd_data->status : BCME_OK);
5762
+ wl_cfgvendor_free_disc_cmd_data(cfg, cmd_data);
5763
+ NAN_DBG_EXIT();
5764
+ return ret;
5765
+}
5766
+
5767
+static int
5768
+wl_cfgvendor_nan_cancel_subscribe(struct wiphy *wiphy,
5769
+ struct wireless_dev *wdev, const void * data, int len)
5770
+{
5771
+ int ret = 0;
5772
+ nan_discover_cmd_data_t *cmd_data = NULL;
5773
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5774
+ nan_hal_resp_t nan_req_resp;
5775
+
5776
+ /* Blocking Cancel_Subscribe if NAN is not enableb */
5777
+ if (!cfg->nan_enable) {
5778
+ WL_ERR(("nan is not enabled, cancel subscribe blocked\n"));
5779
+ ret = BCME_ERROR;
5780
+ goto exit;
5781
+ }
5782
+ cmd_data = MALLOCZ(cfg->osh, sizeof(*cmd_data));
5783
+ if (!cmd_data) {
5784
+ WL_ERR(("%s: memory allocation failed\n", __func__));
5785
+ ret = BCME_NOMEM;
5786
+ goto exit;
5787
+ }
5788
+ NAN_DBG_ENTER();
5789
+
5790
+ bzero(&nan_req_resp, sizeof(nan_req_resp));
5791
+
5792
+ ret = wl_cfgvendor_nan_parse_discover_args(wiphy, data, len, cmd_data);
5793
+ if (ret) {
5794
+ WL_ERR(("failed to parse nan disc vendor args, ret= %d\n", ret));
5795
+ goto exit;
5796
+ }
5797
+ nan_req_resp.instance_id = cmd_data->sub_id;
5798
+ WL_INFORM_MEM(("[NAN] cancel subscribe instance_id=%d\n", cmd_data->sub_id));
5799
+
5800
+ ret = wl_cfgnan_cancel_sub_handler(wdev->netdev, cfg, cmd_data);
5801
+ if (ret) {
5802
+ WL_ERR(("failed to cancel subscribe nan instance-id[%d] error[%d]\n",
5803
+ cmd_data->sub_id, ret));
5804
+ goto exit;
5805
+ }
5806
+exit:
5807
+ ret = wl_cfgvendor_nan_cmd_reply(wiphy, NAN_WIFI_SUBCMD_CANCEL_SUBSCRIBE,
5808
+ &nan_req_resp, ret, cmd_data ? cmd_data->status : BCME_OK);
5809
+ wl_cfgvendor_free_disc_cmd_data(cfg, cmd_data);
5810
+ NAN_DBG_EXIT();
5811
+ return ret;
5812
+}
5813
+
5814
+static int
5815
+wl_cfgvendor_nan_transmit(struct wiphy *wiphy,
5816
+ struct wireless_dev *wdev, const void * data, int len)
5817
+{
5818
+ int ret = 0;
5819
+ nan_discover_cmd_data_t *cmd_data = NULL;
5820
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5821
+ nan_hal_resp_t nan_req_resp;
5822
+
5823
+ /* Blocking Transmit if NAN is not enable */
5824
+ if (!cfg->nan_enable) {
5825
+ WL_ERR(("nan is not enabled, transmit blocked\n"));
5826
+ ret = BCME_ERROR;
5827
+ goto exit;
5828
+ }
5829
+ cmd_data = (nan_discover_cmd_data_t *)MALLOCZ(cfg->osh, sizeof(*cmd_data));
5830
+ if (!cmd_data) {
5831
+ WL_ERR(("%s: memory allocation failed\n", __func__));
5832
+ ret = BCME_NOMEM;
5833
+ goto exit;
5834
+ }
5835
+ NAN_DBG_ENTER();
5836
+
5837
+ bzero(&nan_req_resp, sizeof(nan_req_resp));
5838
+
5839
+ ret = wl_cfgvendor_nan_parse_discover_args(wiphy, data, len, cmd_data);
5840
+ if (ret) {
5841
+ WL_ERR(("failed to parse nan disc vendor args, ret= %d\n", ret));
5842
+ goto exit;
5843
+ }
5844
+ nan_req_resp.instance_id = cmd_data->local_id;
5845
+ ret = wl_cfgnan_transmit_handler(wdev->netdev, cfg, cmd_data);
5846
+ if (ret) {
5847
+ WL_ERR(("failed to transmit-followup nan error[%d]\n", ret));
5848
+ goto exit;
5849
+ }
5850
+exit:
5851
+ ret = wl_cfgvendor_nan_cmd_reply(wiphy, NAN_WIFI_SUBCMD_TRANSMIT,
5852
+ &nan_req_resp, ret, cmd_data ? cmd_data->status : BCME_OK);
5853
+ wl_cfgvendor_free_disc_cmd_data(cfg, cmd_data);
5854
+ NAN_DBG_EXIT();
5855
+ return ret;
5856
+}
5857
+
5858
+static int
5859
+wl_cfgvendor_nan_get_capablities(struct wiphy *wiphy,
5860
+ struct wireless_dev *wdev, const void * data, int len)
5861
+{
5862
+ int ret = 0;
5863
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5864
+ nan_hal_resp_t nan_req_resp;
5865
+
5866
+ NAN_DBG_ENTER();
5867
+
5868
+ bzero(&nan_req_resp, sizeof(nan_req_resp));
5869
+ ret = wl_cfgnan_get_capablities_handler(wdev->netdev, cfg, &nan_req_resp.capabilities);
5870
+ if (ret) {
5871
+ WL_ERR(("Could not get capabilities\n"));
5872
+ ret = -EINVAL;
5873
+ goto exit;
5874
+ }
5875
+exit:
5876
+ ret = wl_cfgvendor_nan_cmd_reply(wiphy, NAN_WIFI_SUBCMD_GET_CAPABILITIES,
5877
+ &nan_req_resp, ret, BCME_OK);
5878
+ wl_cfgvendor_send_cmd_reply(wiphy, &nan_req_resp, sizeof(nan_req_resp));
5879
+
5880
+ NAN_DBG_EXIT();
5881
+ return ret;
5882
+}
5883
+
5884
+static int
5885
+wl_cfgvendor_nan_data_path_iface_create(struct wiphy *wiphy,
5886
+ struct wireless_dev *wdev, const void * data, int len)
5887
+{
5888
+ int ret = 0;
5889
+ nan_datapath_cmd_data_t *cmd_data = NULL;
5890
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5891
+ nan_hal_resp_t nan_req_resp;
5892
+ dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(wdev->netdev);
5893
+
5894
+ if (!cfg->nan_init_state) {
5895
+ WL_ERR(("%s: NAN is not inited or Device doesn't support NAN \n", __func__));
5896
+ ret = -ENODEV;
5897
+ goto exit;
5898
+ }
5899
+
5900
+ cmd_data = (nan_datapath_cmd_data_t *)MALLOCZ(cfg->osh, sizeof(*cmd_data));
5901
+ if (!cmd_data) {
5902
+ WL_ERR(("%s: memory allocation failed\n", __func__));
5903
+ ret = BCME_NOMEM;
5904
+ goto exit;
5905
+ }
5906
+ NAN_DBG_ENTER();
5907
+
5908
+ bzero(&nan_req_resp, sizeof(nan_req_resp));
5909
+
5910
+ ret = wl_cfgvendor_nan_parse_datapath_args(wiphy, data, len, cmd_data);
5911
+ if (ret) {
5912
+ WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret));
5913
+ goto exit;
5914
+ }
5915
+
5916
+ if (cfg->nan_enable) { /* new framework Impl, iface create called after nan enab */
5917
+ ret = wl_cfgnan_data_path_iface_create_delete_handler(wdev->netdev,
5918
+ cfg, cmd_data->ndp_iface,
5919
+ NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE, dhdp->up);
5920
+ if (ret != BCME_OK) {
5921
+ WL_ERR(("failed to create iface, ret = %d\n", ret));
5922
+ goto exit;
5923
+ }
5924
+ }
5925
+exit:
5926
+ ret = wl_cfgvendor_nan_cmd_reply(wiphy, NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE,
5927
+ &nan_req_resp, ret, cmd_data ? cmd_data->status : BCME_OK);
5928
+ wl_cfgvendor_free_dp_cmd_data(cfg, cmd_data);
5929
+ NAN_DBG_EXIT();
5930
+ return ret;
5931
+}
5932
+
5933
+static int
5934
+wl_cfgvendor_nan_data_path_iface_delete(struct wiphy *wiphy,
5935
+ struct wireless_dev *wdev, const void * data, int len)
5936
+{
5937
+ int ret = 0;
5938
+ nan_datapath_cmd_data_t *cmd_data = NULL;
5939
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5940
+ nan_hal_resp_t nan_req_resp;
5941
+ dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(wdev->netdev);
5942
+
5943
+ if (cfg->nan_init_state == false) {
5944
+ WL_ERR(("%s: NAN is not inited or Device doesn't support NAN \n", __func__));
5945
+ /* Deinit has taken care of cleaing the virtual iface */
5946
+ ret = BCME_OK;
5947
+ goto exit;
5948
+ }
5949
+
5950
+ NAN_DBG_ENTER();
5951
+ cmd_data = (nan_datapath_cmd_data_t *)MALLOCZ(cfg->osh, sizeof(*cmd_data));
5952
+ if (!cmd_data) {
5953
+ WL_ERR(("%s: memory allocation failed\n", __func__));
5954
+ ret = BCME_NOMEM;
5955
+ goto exit;
5956
+ }
5957
+ bzero(&nan_req_resp, sizeof(nan_req_resp));
5958
+ ret = wl_cfgvendor_nan_parse_datapath_args(wiphy, data, len, cmd_data);
5959
+ if (ret) {
5960
+ WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret));
5961
+ goto exit;
5962
+ }
5963
+
5964
+ ret = wl_cfgnan_data_path_iface_create_delete_handler(wdev->netdev, cfg,
5965
+ (char*)cmd_data->ndp_iface,
5966
+ NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE, dhdp->up);
5967
+ if (ret) {
5968
+ WL_ERR(("failed to delete ndp iface [%d]\n", ret));
5969
+ goto exit;
5970
+ }
5971
+exit:
5972
+ ret = wl_cfgvendor_nan_cmd_reply(wiphy, NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE,
5973
+ &nan_req_resp, ret, cmd_data ? cmd_data->status : BCME_OK);
5974
+ wl_cfgvendor_free_dp_cmd_data(cfg, cmd_data);
5975
+ NAN_DBG_EXIT();
5976
+ return ret;
5977
+}
5978
+
5979
+static int
5980
+wl_cfgvendor_nan_data_path_request(struct wiphy *wiphy,
5981
+ struct wireless_dev *wdev, const void * data, int len)
5982
+{
5983
+ int ret = 0;
5984
+ nan_datapath_cmd_data_t *cmd_data = NULL;
5985
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5986
+ nan_hal_resp_t nan_req_resp;
5987
+ uint8 ndp_instance_id = 0;
5988
+
5989
+ if (!cfg->nan_enable) {
5990
+ WL_ERR(("nan is not enabled, nan data path request blocked\n"));
5991
+ ret = BCME_ERROR;
5992
+ goto exit;
5993
+ }
5994
+
5995
+ NAN_DBG_ENTER();
5996
+ cmd_data = (nan_datapath_cmd_data_t *)MALLOCZ(cfg->osh, sizeof(*cmd_data));
5997
+ if (!cmd_data) {
5998
+ WL_ERR(("%s: memory allocation failed\n", __func__));
5999
+ ret = BCME_NOMEM;
6000
+ goto exit;
6001
+ }
6002
+
6003
+ bzero(&nan_req_resp, sizeof(nan_req_resp));
6004
+ ret = wl_cfgvendor_nan_parse_datapath_args(wiphy, data, len, cmd_data);
6005
+ if (ret) {
6006
+ WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret));
6007
+ goto exit;
6008
+ }
6009
+
6010
+ ret = wl_cfgnan_data_path_request_handler(wdev->netdev, cfg,
6011
+ cmd_data, &ndp_instance_id);
6012
+ if (ret) {
6013
+ WL_ERR(("failed to request nan data path [%d]\n", ret));
6014
+ goto exit;
6015
+ }
6016
+
6017
+ if (cmd_data->status == BCME_OK) {
6018
+ nan_req_resp.ndp_instance_id = cmd_data->ndp_instance_id;
6019
+ } else {
6020
+ nan_req_resp.ndp_instance_id = 0;
6021
+ }
6022
+exit:
6023
+ ret = wl_cfgvendor_nan_cmd_reply(wiphy, NAN_WIFI_SUBCMD_DATA_PATH_REQUEST,
6024
+ &nan_req_resp, ret, cmd_data ? cmd_data->status : BCME_OK);
6025
+ wl_cfgvendor_free_dp_cmd_data(cfg, cmd_data);
6026
+ NAN_DBG_EXIT();
6027
+ return ret;
6028
+}
6029
+
6030
+static int
6031
+wl_cfgvendor_nan_data_path_response(struct wiphy *wiphy,
6032
+ struct wireless_dev *wdev, const void * data, int len)
6033
+{
6034
+ int ret = 0;
6035
+ nan_datapath_cmd_data_t *cmd_data = NULL;
6036
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6037
+ nan_hal_resp_t nan_req_resp;
6038
+
6039
+ if (!cfg->nan_enable) {
6040
+ WL_ERR(("nan is not enabled, nan data path response blocked\n"));
6041
+ ret = BCME_ERROR;
6042
+ goto exit;
6043
+ }
6044
+ NAN_DBG_ENTER();
6045
+ cmd_data = (nan_datapath_cmd_data_t *)MALLOCZ(cfg->osh, sizeof(*cmd_data));
6046
+ if (!cmd_data) {
6047
+ WL_ERR(("%s: memory allocation failed\n", __func__));
6048
+ ret = BCME_NOMEM;
6049
+ goto exit;
6050
+ }
6051
+
6052
+ bzero(&nan_req_resp, sizeof(nan_req_resp));
6053
+ ret = wl_cfgvendor_nan_parse_datapath_args(wiphy, data, len, cmd_data);
6054
+ if (ret) {
6055
+ WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret));
6056
+ goto exit;
6057
+ }
6058
+ ret = wl_cfgnan_data_path_response_handler(wdev->netdev, cfg, cmd_data);
6059
+ if (ret) {
6060
+ WL_ERR(("failed to response nan data path [%d]\n", ret));
6061
+ goto exit;
6062
+ }
6063
+exit:
6064
+ ret = wl_cfgvendor_nan_cmd_reply(wiphy, NAN_WIFI_SUBCMD_DATA_PATH_RESPONSE,
6065
+ &nan_req_resp, ret, cmd_data ? cmd_data->status : BCME_OK);
6066
+ wl_cfgvendor_free_dp_cmd_data(cfg, cmd_data);
6067
+ NAN_DBG_EXIT();
6068
+ return ret;
6069
+}
6070
+
6071
+static int
6072
+wl_cfgvendor_nan_data_path_end(struct wiphy *wiphy,
6073
+ struct wireless_dev *wdev, const void * data, int len)
6074
+{
6075
+ int ret = 0;
6076
+ nan_datapath_cmd_data_t *cmd_data = NULL;
6077
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6078
+ nan_hal_resp_t nan_req_resp;
6079
+
6080
+ NAN_DBG_ENTER();
6081
+ if (!cfg->nan_enable) {
6082
+ WL_ERR(("nan is not enabled, nan data path end blocked\n"));
6083
+ ret = BCME_OK;
6084
+ goto exit;
6085
+ }
6086
+ cmd_data = (nan_datapath_cmd_data_t *)MALLOCZ(cfg->osh, sizeof(*cmd_data));
6087
+ if (!cmd_data) {
6088
+ WL_ERR(("%s: memory allocation failed\n", __func__));
6089
+ ret = BCME_NOMEM;
6090
+ goto exit;
6091
+ }
6092
+
6093
+ bzero(&nan_req_resp, sizeof(nan_req_resp));
6094
+ ret = wl_cfgvendor_nan_parse_datapath_args(wiphy, data, len, cmd_data);
6095
+ if (ret) {
6096
+ WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret));
6097
+ goto exit;
6098
+ }
6099
+ ret = wl_cfgnan_data_path_end_handler(wdev->netdev, cfg, cmd_data);
6100
+ if (ret) {
6101
+ WL_ERR(("failed to end nan data path [%d]\n", ret));
6102
+ goto exit;
6103
+ }
6104
+exit:
6105
+ ret = wl_cfgvendor_nan_cmd_reply(wiphy, NAN_WIFI_SUBCMD_DATA_PATH_END,
6106
+ &nan_req_resp, ret, cmd_data ? cmd_data->status : BCME_OK);
6107
+ wl_cfgvendor_free_dp_cmd_data(cfg, cmd_data);
6108
+ NAN_DBG_EXIT();
6109
+ return ret;
6110
+}
6111
+
6112
+#ifdef WL_NAN_DISC_CACHE
6113
+static int
6114
+wl_cfgvendor_nan_data_path_sec_info(struct wiphy *wiphy,
6115
+ struct wireless_dev *wdev, const void *data, int len)
6116
+{
6117
+ int ret = 0;
6118
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6119
+ nan_hal_resp_t nan_req_resp;
6120
+ nan_datapath_sec_info_cmd_data_t *cmd_data = NULL;
6121
+ dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(wdev->netdev);
6122
+
6123
+ NAN_DBG_ENTER();
6124
+ if (!cfg->nan_enable) {
6125
+ WL_ERR(("nan is not enabled\n"));
6126
+ ret = BCME_UNSUPPORTED;
6127
+ goto exit;
6128
+ }
6129
+ cmd_data = MALLOCZ(dhdp->osh, sizeof(*cmd_data));
6130
+ if (!cmd_data) {
6131
+ WL_ERR(("%s: memory allocation failed\n", __func__));
6132
+ ret = BCME_NOMEM;
6133
+ goto exit;
6134
+ }
6135
+
6136
+ ret = wl_cfgvendor_nan_parse_dp_sec_info_args(wiphy, data, len, cmd_data);
6137
+ if (ret) {
6138
+ WL_ERR(("failed to parse sec info args\n"));
6139
+ goto exit;
6140
+ }
6141
+
6142
+ bzero(&nan_req_resp, sizeof(nan_req_resp));
6143
+ ret = wl_cfgnan_sec_info_handler(cfg, cmd_data, &nan_req_resp);
6144
+ if (ret) {
6145
+ WL_ERR(("failed to retrieve svc hash/pub nmi error[%d]\n", ret));
6146
+ goto exit;
6147
+ }
6148
+exit:
6149
+ ret = wl_cfgvendor_nan_cmd_reply(wiphy, NAN_WIFI_SUBCMD_DATA_PATH_SEC_INFO,
6150
+ &nan_req_resp, ret, BCME_OK);
6151
+ if (cmd_data) {
6152
+ MFREE(dhdp->osh, cmd_data, sizeof(*cmd_data));
6153
+ }
6154
+ NAN_DBG_EXIT();
6155
+ return ret;
6156
+}
6157
+#endif /* WL_NAN_DISC_CACHE */
6158
+
6159
+static int
6160
+wl_cfgvendor_nan_version_info(struct wiphy *wiphy,
6161
+ struct wireless_dev *wdev, const void *data, int len)
6162
+{
6163
+ int ret = BCME_OK;
6164
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6165
+ uint32 version = NAN_HAL_VERSION_1;
6166
+
6167
+ BCM_REFERENCE(cfg);
6168
+ WL_DBG(("Enter %s version %d\n", __FUNCTION__, version));
6169
+ ret = wl_cfgvendor_send_cmd_reply(wiphy, &version, sizeof(version));
6170
+ return ret;
6171
+}
6172
+
6173
+#endif /* WL_NAN */
20316174
20326175 #ifdef LINKSTAT_SUPPORT
6176
+
20336177 #define NUM_RATE 32
20346178 #define NUM_PEER 1
20356179 #define NUM_CHAN 11
20366180 #define HEADER_SIZE sizeof(ver_len)
6181
+
6182
+static int wl_cfgvendor_lstats_get_bcn_mbss(char *buf, uint32 *rxbeaconmbss)
6183
+{
6184
+ wl_cnt_info_t *cbuf = (wl_cnt_info_t *)buf;
6185
+ const void *cnt;
6186
+
6187
+ if ((cnt = (const void *)bcm_get_data_from_xtlv_buf(cbuf->data, cbuf->datalen,
6188
+ WL_CNT_XTLV_CNTV_LE10_UCODE, NULL, BCM_XTLV_OPTION_ALIGN32)) != NULL) {
6189
+ *rxbeaconmbss = ((const wl_cnt_v_le10_mcst_t *)cnt)->rxbeaconmbss;
6190
+ } else if ((cnt = (const void *)bcm_get_data_from_xtlv_buf(cbuf->data, cbuf->datalen,
6191
+ WL_CNT_XTLV_LT40_UCODE_V1, NULL, BCM_XTLV_OPTION_ALIGN32)) != NULL) {
6192
+ *rxbeaconmbss = ((const wl_cnt_lt40mcst_v1_t *)cnt)->rxbeaconmbss;
6193
+ } else if ((cnt = (const void *)bcm_get_data_from_xtlv_buf(cbuf->data, cbuf->datalen,
6194
+ WL_CNT_XTLV_GE40_UCODE_V1, NULL, BCM_XTLV_OPTION_ALIGN32)) != NULL) {
6195
+ *rxbeaconmbss = ((const wl_cnt_ge40mcst_v1_t *)cnt)->rxbeaconmbss;
6196
+ } else if ((cnt = (const void *)bcm_get_data_from_xtlv_buf(cbuf->data, cbuf->datalen,
6197
+ WL_CNT_XTLV_GE80_UCODE_V1, NULL, BCM_XTLV_OPTION_ALIGN32)) != NULL) {
6198
+ *rxbeaconmbss = ((const wl_cnt_ge80mcst_v1_t *)cnt)->rxbeaconmbss;
6199
+ } else {
6200
+ *rxbeaconmbss = 0;
6201
+ return BCME_NOTFOUND;
6202
+ }
6203
+
6204
+ return BCME_OK;
6205
+}
6206
+
20376207 static int wl_cfgvendor_lstats_get_info(struct wiphy *wiphy,
20386208 struct wireless_dev *wdev, const void *data, int len)
20396209 {
20406210 static char iovar_buf[WLC_IOCTL_MAXLEN];
20416211 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
20426212 int err = 0, i;
2043
- wifi_iface_stat *iface;
20446213 wifi_radio_stat *radio;
6214
+ wifi_radio_stat_h radio_h;
20456215 wl_wme_cnt_t *wl_wme_cnt;
2046
- wl_cnt_v_le10_mcst_t *macstat_cnt;
2047
- wl_cnt_wlc_t *wlc_cnt;
6216
+ const wl_cnt_wlc_t *wlc_cnt;
20486217 scb_val_t scbval;
2049
- char *output;
6218
+ char *output = NULL;
6219
+ char *outdata = NULL;
6220
+ wifi_rate_stat_v1 *p_wifi_rate_stat_v1 = NULL;
6221
+ wifi_rate_stat *p_wifi_rate_stat = NULL;
6222
+ uint total_len = 0;
6223
+ uint32 rxbeaconmbss;
6224
+ wifi_iface_stat iface;
6225
+ wlc_rev_info_t revinfo;
20506226
2051
- WL_INFORM(("%s: Enter \n", __func__));
6227
+ WL_INFORM_MEM(("%s: Enter \n", __func__));
20526228 RETURN_EIO_IF_NOT_UP(cfg);
20536229
2054
- bzero(cfg->ioctl_buf, WLC_IOCTL_MAXLEN);
2055
- bzero(iovar_buf, WLC_IOCTL_MAXLEN);
6230
+ /* Get the device rev info */
6231
+ bzero(&revinfo, sizeof(revinfo));
6232
+ err = wldev_ioctl_get(bcmcfg_to_prmry_ndev(cfg), WLC_GET_REVINFO, &revinfo,
6233
+ sizeof(revinfo));
6234
+ if (err != BCME_OK) {
6235
+ goto exit;
6236
+ }
20566237
2057
- output = cfg->ioctl_buf;
6238
+ outdata = (void *)MALLOCZ(cfg->osh, WLC_IOCTL_MAXLEN);
6239
+ if (outdata == NULL) {
6240
+ WL_ERR(("%s: alloc failed\n", __func__));
6241
+ return -ENOMEM;
6242
+ }
6243
+
6244
+ bzero(&scbval, sizeof(scb_val_t));
6245
+ bzero(outdata, WLC_IOCTL_MAXLEN);
6246
+ output = outdata;
20586247
20596248 err = wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg), "radiostat", NULL, 0,
20606249 iovar_buf, WLC_IOCTL_MAXLEN, NULL);
20616250 if (err != BCME_OK && err != BCME_UNSUPPORTED) {
20626251 WL_ERR(("error (%d) - size = %zu\n", err, sizeof(wifi_radio_stat)));
2063
- return err;
6252
+ goto exit;
20646253 }
20656254 radio = (wifi_radio_stat *)iovar_buf;
2066
- radio->num_channels = NUM_CHAN;
2067
- memcpy(output, iovar_buf+HEADER_SIZE, sizeof(wifi_radio_stat)-HEADER_SIZE);
20686255
2069
- output += (sizeof(wifi_radio_stat) - HEADER_SIZE);
2070
- output += (NUM_CHAN*sizeof(wifi_channel_stat));
6256
+ bzero(&radio_h, sizeof(wifi_radio_stat_h));
6257
+ radio_h.on_time = radio->on_time;
6258
+ radio_h.tx_time = radio->tx_time;
6259
+ radio_h.rx_time = radio->rx_time;
6260
+ radio_h.on_time_scan = radio->on_time_scan;
6261
+ radio_h.on_time_nbd = radio->on_time_nbd;
6262
+ radio_h.on_time_gscan = radio->on_time_gscan;
6263
+ radio_h.on_time_roam_scan = radio->on_time_roam_scan;
6264
+ radio_h.on_time_pno_scan = radio->on_time_pno_scan;
6265
+ radio_h.on_time_hs20 = radio->on_time_hs20;
6266
+ radio_h.num_channels = NUM_CHAN;
6267
+
6268
+ memcpy(output, &radio_h, sizeof(wifi_radio_stat_h));
6269
+
6270
+ output += sizeof(wifi_radio_stat_h);
6271
+ output += (NUM_CHAN * sizeof(wifi_channel_stat));
20716272
20726273 err = wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg), "wme_counters", NULL, 0,
20736274 iovar_buf, WLC_IOCTL_MAXLEN, NULL);
20746275 if (unlikely(err)) {
20756276 WL_ERR(("error (%d)\n", err));
2076
- return err;
6277
+ goto exit;
20776278 }
20786279 wl_wme_cnt = (wl_wme_cnt_t *)iovar_buf;
2079
- iface = (wifi_iface_stat *)output;
20806280
2081
- iface->ac[WIFI_AC_VO].ac = WIFI_AC_VO;
2082
- iface->ac[WIFI_AC_VO].tx_mpdu = wl_wme_cnt->tx[AC_VO].packets;
2083
- iface->ac[WIFI_AC_VO].rx_mpdu = wl_wme_cnt->rx[AC_VO].packets;
2084
- iface->ac[WIFI_AC_VO].mpdu_lost = wl_wme_cnt->tx_failed[WIFI_AC_VO].packets;
6281
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_VO].ac, WIFI_AC_VO);
6282
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_VO].tx_mpdu, wl_wme_cnt->tx[AC_VO].packets);
6283
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_VO].rx_mpdu, wl_wme_cnt->rx[AC_VO].packets);
6284
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_VO].mpdu_lost,
6285
+ wl_wme_cnt->tx_failed[WIFI_AC_VO].packets);
20856286
2086
- iface->ac[WIFI_AC_VI].ac = WIFI_AC_VI;
2087
- iface->ac[WIFI_AC_VI].tx_mpdu = wl_wme_cnt->tx[AC_VI].packets;
2088
- iface->ac[WIFI_AC_VI].rx_mpdu = wl_wme_cnt->rx[AC_VI].packets;
2089
- iface->ac[WIFI_AC_VI].mpdu_lost = wl_wme_cnt->tx_failed[WIFI_AC_VI].packets;
6287
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_VI].ac, WIFI_AC_VI);
6288
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_VI].tx_mpdu, wl_wme_cnt->tx[AC_VI].packets);
6289
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_VI].rx_mpdu, wl_wme_cnt->rx[AC_VI].packets);
6290
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_VI].mpdu_lost,
6291
+ wl_wme_cnt->tx_failed[WIFI_AC_VI].packets);
20906292
2091
- iface->ac[WIFI_AC_BE].ac = WIFI_AC_BE;
2092
- iface->ac[WIFI_AC_BE].tx_mpdu = wl_wme_cnt->tx[AC_BE].packets;
2093
- iface->ac[WIFI_AC_BE].rx_mpdu = wl_wme_cnt->rx[AC_BE].packets;
2094
- iface->ac[WIFI_AC_BE].mpdu_lost = wl_wme_cnt->tx_failed[WIFI_AC_BE].packets;
6293
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_BE].ac, WIFI_AC_BE);
6294
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_BE].tx_mpdu, wl_wme_cnt->tx[AC_BE].packets);
6295
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_BE].rx_mpdu, wl_wme_cnt->rx[AC_BE].packets);
6296
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_BE].mpdu_lost,
6297
+ wl_wme_cnt->tx_failed[WIFI_AC_BE].packets);
20956298
2096
- iface->ac[WIFI_AC_BK].ac = WIFI_AC_BK;
2097
- iface->ac[WIFI_AC_BK].tx_mpdu = wl_wme_cnt->tx[AC_BK].packets;
2098
- iface->ac[WIFI_AC_BK].rx_mpdu = wl_wme_cnt->rx[AC_BK].packets;
2099
- iface->ac[WIFI_AC_BK].mpdu_lost = wl_wme_cnt->tx_failed[WIFI_AC_BK].packets;
2100
- bzero(iovar_buf, WLC_IOCTL_MAXLEN);
6299
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_BK].ac, WIFI_AC_BK);
6300
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_BK].tx_mpdu, wl_wme_cnt->tx[AC_BK].packets);
6301
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_BK].rx_mpdu, wl_wme_cnt->rx[AC_BK].packets);
6302
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_BK].mpdu_lost,
6303
+ wl_wme_cnt->tx_failed[WIFI_AC_BK].packets);
21016304
21026305 err = wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg), "counters", NULL, 0,
21036306 iovar_buf, WLC_IOCTL_MAXLEN, NULL);
21046307 if (unlikely(err)) {
21056308 WL_ERR(("error (%d) - size = %zu\n", err, sizeof(wl_cnt_wlc_t)));
2106
- return err;
6309
+ goto exit;
21076310 }
21086311
6312
+ CHK_CNTBUF_DATALEN(iovar_buf, WLC_IOCTL_MAXLEN);
21096313 /* Translate traditional (ver <= 10) counters struct to new xtlv type struct */
2110
- err = wl_cntbuf_to_xtlv_format(NULL, iovar_buf, WL_CNTBUF_MAX_SIZE, 0);
6314
+ err = wl_cntbuf_to_xtlv_format(NULL, iovar_buf, WLC_IOCTL_MAXLEN, revinfo.corerev);
21116315 if (err != BCME_OK) {
21126316 WL_ERR(("%s wl_cntbuf_to_xtlv_format ERR %d\n",
2113
- __FUNCTION__, err));
2114
- return err;
6317
+ __FUNCTION__, err));
6318
+ goto exit;
21156319 }
21166320
21176321 if (!(wlc_cnt = GET_WLCCNT_FROM_CNTBUF(iovar_buf))) {
21186322 WL_ERR(("%s wlc_cnt NULL!\n", __FUNCTION__));
2119
- return BCME_ERROR;
6323
+ err = BCME_ERROR;
6324
+ goto exit;
21206325 }
21216326
2122
- iface->ac[WIFI_AC_BE].retries = wlc_cnt->txretry;
6327
+ COMPAT_ASSIGN_VALUE(iface, ac[WIFI_AC_BE].retries, wlc_cnt->txretry);
21236328
2124
- if ((macstat_cnt = bcm_get_data_from_xtlv_buf(((wl_cnt_info_t *)iovar_buf)->data,
2125
- ((wl_cnt_info_t *)iovar_buf)->datalen, WL_CNT_XTLV_CNTV_LE10_UCODE, NULL,
2126
- BCM_XTLV_OPTION_ALIGN32)) == NULL) {
2127
- macstat_cnt = bcm_get_data_from_xtlv_buf(((wl_cnt_info_t *)iovar_buf)->data,
2128
- ((wl_cnt_info_t *)iovar_buf)->datalen,
2129
- WL_CNT_XTLV_LT40_UCODE_V1, NULL,
2130
- BCM_XTLV_OPTION_ALIGN32);
6329
+ err = wl_cfgvendor_lstats_get_bcn_mbss(iovar_buf, &rxbeaconmbss);
6330
+ if (unlikely(err)) {
6331
+ WL_ERR(("get_bcn_mbss error (%d)\n", err));
6332
+ goto exit;
21316333 }
2132
-
2133
- if (macstat_cnt == NULL) {
2134
- printf("wlmTxGetAckedPackets: macstat_cnt NULL!\n");
2135
- return FALSE;
2136
- }
2137
-
2138
- iface->beacon_rx = macstat_cnt->rxbeaconmbss;
21396334
21406335 err = wldev_get_rssi(bcmcfg_to_prmry_ndev(cfg), &scbval);
21416336 if (unlikely(err)) {
21426337 WL_ERR(("get_rssi error (%d)\n", err));
2143
- return err;
6338
+ goto exit;
21446339 }
2145
- iface->rssi_mgmt = scbval.val;
21466340
2147
- iface->num_peers = NUM_PEER;
2148
- iface->peer_info->num_rate = NUM_RATE;
6341
+ COMPAT_ASSIGN_VALUE(iface, beacon_rx, rxbeaconmbss);
6342
+ COMPAT_ASSIGN_VALUE(iface, rssi_mgmt, scbval.val);
6343
+ COMPAT_ASSIGN_VALUE(iface, num_peers, NUM_PEER);
6344
+ COMPAT_ASSIGN_VALUE(iface, peer_info->num_rate, NUM_RATE);
21496345
2150
- bzero(iovar_buf, WLC_IOCTL_MAXLEN);
2151
- output = (char *)iface + sizeof(wifi_iface_stat) + NUM_PEER*sizeof(wifi_peer_info);
6346
+ {
6347
+ memcpy(output, &iface, sizeof(iface));
6348
+ output += (sizeof(iface) - sizeof(wifi_rate_stat));
6349
+ }
21526350
21536351 err = wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg), "ratestat", NULL, 0,
21546352 iovar_buf, WLC_IOCTL_MAXLEN, NULL);
21556353 if (err != BCME_OK && err != BCME_UNSUPPORTED) {
21566354 WL_ERR(("error (%d) - size = %zu\n", err, NUM_RATE*sizeof(wifi_rate_stat)));
2157
- return err;
6355
+ goto exit;
21586356 }
2159
- for (i = 0; i < NUM_RATE; i++)
2160
- memcpy(output, iovar_buf+HEADER_SIZE+i*sizeof(wifi_rate_stat),
2161
- sizeof(wifi_rate_stat)-HEADER_SIZE);
6357
+ for (i = 0; i < NUM_RATE; i++) {
6358
+ p_wifi_rate_stat =
6359
+ (wifi_rate_stat *)(iovar_buf + i*sizeof(wifi_rate_stat));
6360
+ p_wifi_rate_stat_v1 = (wifi_rate_stat_v1 *)output;
6361
+ p_wifi_rate_stat_v1->rate.preamble = p_wifi_rate_stat->rate.preamble;
6362
+ p_wifi_rate_stat_v1->rate.nss = p_wifi_rate_stat->rate.nss;
6363
+ p_wifi_rate_stat_v1->rate.bw = p_wifi_rate_stat->rate.bw;
6364
+ p_wifi_rate_stat_v1->rate.rateMcsIdx = p_wifi_rate_stat->rate.rateMcsIdx;
6365
+ p_wifi_rate_stat_v1->rate.reserved = p_wifi_rate_stat->rate.reserved;
6366
+ p_wifi_rate_stat_v1->rate.bitrate = p_wifi_rate_stat->rate.bitrate;
6367
+ p_wifi_rate_stat_v1->tx_mpdu = p_wifi_rate_stat->tx_mpdu;
6368
+ p_wifi_rate_stat_v1->rx_mpdu = p_wifi_rate_stat->rx_mpdu;
6369
+ p_wifi_rate_stat_v1->mpdu_lost = p_wifi_rate_stat->mpdu_lost;
6370
+ p_wifi_rate_stat_v1->retries = p_wifi_rate_stat->retries;
6371
+ p_wifi_rate_stat_v1->retries_short = p_wifi_rate_stat->retries_short;
6372
+ p_wifi_rate_stat_v1->retries_long = p_wifi_rate_stat->retries_long;
6373
+ output = (char *) &(p_wifi_rate_stat_v1->retries_long);
6374
+ output += sizeof(p_wifi_rate_stat_v1->retries_long);
6375
+ }
21626376
2163
- err = wl_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
2164
- cfg->ioctl_buf,
2165
- sizeof(wifi_radio_stat)-HEADER_SIZE +
2166
- NUM_CHAN*sizeof(wifi_channel_stat) +
2167
- sizeof(wifi_iface_stat)+NUM_PEER*sizeof(wifi_peer_info) +
2168
- NUM_RATE*(sizeof(wifi_rate_stat)-HEADER_SIZE));
6377
+ total_len = sizeof(wifi_radio_stat_h) +
6378
+ NUM_CHAN * sizeof(wifi_channel_stat);
6379
+
6380
+ {
6381
+ total_len += sizeof(wifi_iface_stat);
6382
+ }
6383
+
6384
+ total_len = total_len - sizeof(wifi_peer_info) +
6385
+ NUM_PEER * (sizeof(wifi_peer_info) - sizeof(wifi_rate_stat_v1) +
6386
+ NUM_RATE * sizeof(wifi_rate_stat_v1));
6387
+
6388
+ if (total_len > WLC_IOCTL_MAXLEN) {
6389
+ WL_ERR(("Error! total_len:%d is unexpected value\n", total_len));
6390
+ err = BCME_BADLEN;
6391
+ goto exit;
6392
+ }
6393
+ err = wl_cfgvendor_send_cmd_reply(wiphy, outdata, total_len);
6394
+
21696395 if (unlikely(err))
21706396 WL_ERR(("Vendor Command reply failed ret:%d \n", err));
21716397
6398
+exit:
6399
+ if (outdata) {
6400
+ MFREE(cfg->osh, outdata, WLC_IOCTL_MAXLEN);
6401
+ }
21726402 return err;
21736403 }
6404
+#else
6405
+static int wl_cfgvendor_lstats_get_info(struct wiphy *wiphy,
6406
+ struct wireless_dev *wdev, const void *data, int len)
6407
+{
6408
+ return WIFI_ERROR_NOT_SUPPORTED;
6409
+}
21746410 #endif /* LINKSTAT_SUPPORT */
6411
+
6412
+#ifdef DHD_LOG_DUMP
6413
+static int
6414
+wl_cfgvendor_get_buf_data(const struct nlattr *iter, struct buf_data **buf)
6415
+{
6416
+ int ret = BCME_OK;
6417
+
6418
+ if (nla_len(iter) != sizeof(struct buf_data)) {
6419
+ WL_ERR(("Invalid len : %d\n", nla_len(iter)));
6420
+ ret = BCME_BADLEN;
6421
+ }
6422
+ (*buf) = (struct buf_data *)nla_data(iter);
6423
+ if (!(*buf) || (((*buf)->len) <= 0) || !((*buf)->data_buf[0])) {
6424
+ WL_ERR(("Invalid buffer\n"));
6425
+ ret = BCME_ERROR;
6426
+ }
6427
+ return ret;
6428
+}
6429
+
6430
+static int
6431
+wl_cfgvendor_dbg_file_dump(struct wiphy *wiphy,
6432
+ struct wireless_dev *wdev, const void *data, int len)
6433
+{
6434
+ int ret = BCME_OK, rem, type = 0;
6435
+ const struct nlattr *iter;
6436
+ char *mem_buf = NULL;
6437
+ struct sk_buff *skb = NULL;
6438
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6439
+ struct buf_data *buf;
6440
+ int pos = 0;
6441
+
6442
+ /* Alloc the SKB for vendor_event */
6443
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, CFG80211_VENDOR_CMD_REPLY_SKB_SZ);
6444
+ if (!skb) {
6445
+ WL_ERR(("skb allocation is failed\n"));
6446
+ ret = BCME_NOMEM;
6447
+ goto exit;
6448
+ }
6449
+ WL_ERR(("%s\n", __FUNCTION__));
6450
+ nla_for_each_attr(iter, data, len, rem) {
6451
+ type = nla_type(iter);
6452
+ ret = wl_cfgvendor_get_buf_data(iter, &buf);
6453
+ if (ret)
6454
+ goto exit;
6455
+ switch (type) {
6456
+ case DUMP_BUF_ATTR_MEMDUMP:
6457
+ ret = dhd_os_get_socram_dump(bcmcfg_to_prmry_ndev(cfg), &mem_buf,
6458
+ (uint32 *)(&(buf->len)));
6459
+ if (ret) {
6460
+ WL_ERR(("failed to get_socram_dump : %d\n", ret));
6461
+ goto exit;
6462
+ }
6463
+ ret = dhd_export_debug_data(mem_buf, NULL, buf->data_buf[0],
6464
+ (int)buf->len, &pos);
6465
+ break;
6466
+
6467
+ case DUMP_BUF_ATTR_TIMESTAMP :
6468
+ ret = dhd_print_time_str(buf->data_buf[0], NULL,
6469
+ (uint32)buf->len, &pos);
6470
+ break;
6471
+#ifdef EWP_ECNTRS_LOGGING
6472
+ case DUMP_BUF_ATTR_ECNTRS :
6473
+ ret = dhd_print_ecntrs_data(bcmcfg_to_prmry_ndev(cfg), NULL,
6474
+ buf->data_buf[0], NULL, (uint32)buf->len, &pos);
6475
+ break;
6476
+#endif /* EWP_ECNTRS_LOGGING */
6477
+#ifdef DHD_STATUS_LOGGING
6478
+ case DUMP_BUF_ATTR_STATUS_LOG :
6479
+ ret = dhd_print_status_log_data(bcmcfg_to_prmry_ndev(cfg), NULL,
6480
+ buf->data_buf[0], NULL, (uint32)buf->len, &pos);
6481
+ break;
6482
+#endif /* DHD_STATUS_LOGGING */
6483
+#ifdef EWP_RTT_LOGGING
6484
+ case DUMP_BUF_ATTR_RTT_LOG :
6485
+ ret = dhd_print_rtt_data(bcmcfg_to_prmry_ndev(cfg), NULL,
6486
+ buf->data_buf[0], NULL, (uint32)buf->len, &pos);
6487
+ break;
6488
+#endif /* EWP_RTT_LOGGING */
6489
+ case DUMP_BUF_ATTR_DHD_DUMP :
6490
+ ret = dhd_print_dump_data(bcmcfg_to_prmry_ndev(cfg), NULL,
6491
+ buf->data_buf[0], NULL, (uint32)buf->len, &pos);
6492
+ break;
6493
+#if defined(BCMPCIE)
6494
+ case DUMP_BUF_ATTR_EXT_TRAP :
6495
+ ret = dhd_print_ext_trap_data(bcmcfg_to_prmry_ndev(cfg), NULL,
6496
+ buf->data_buf[0], NULL, (uint32)buf->len, &pos);
6497
+ break;
6498
+#endif /* BCMPCIE */
6499
+#if defined(DHD_FW_COREDUMP) && defined(DNGL_EVENT_SUPPORT)
6500
+ case DUMP_BUF_ATTR_HEALTH_CHK :
6501
+ ret = dhd_print_health_chk_data(bcmcfg_to_prmry_ndev(cfg), NULL,
6502
+ buf->data_buf[0], NULL, (uint32)buf->len, &pos);
6503
+ break;
6504
+#endif // endif
6505
+ case DUMP_BUF_ATTR_COOKIE :
6506
+ ret = dhd_print_cookie_data(bcmcfg_to_prmry_ndev(cfg), NULL,
6507
+ buf->data_buf[0], NULL, (uint32)buf->len, &pos);
6508
+ break;
6509
+#ifdef DHD_DUMP_PCIE_RINGS
6510
+ case DUMP_BUF_ATTR_FLOWRING_DUMP :
6511
+ ret = dhd_print_flowring_data(bcmcfg_to_prmry_ndev(cfg), NULL,
6512
+ buf->data_buf[0], NULL, (uint32)buf->len, &pos);
6513
+ break;
6514
+#endif // endif
6515
+ case DUMP_BUF_ATTR_GENERAL_LOG :
6516
+ ret = dhd_get_dld_log_dump(bcmcfg_to_prmry_ndev(cfg), NULL,
6517
+ buf->data_buf[0], NULL, (uint32)buf->len,
6518
+ DLD_BUF_TYPE_GENERAL, &pos);
6519
+ break;
6520
+
6521
+ case DUMP_BUF_ATTR_PRESERVE_LOG :
6522
+ ret = dhd_get_dld_log_dump(bcmcfg_to_prmry_ndev(cfg), NULL,
6523
+ buf->data_buf[0], NULL, (uint32)buf->len,
6524
+ DLD_BUF_TYPE_PRESERVE, &pos);
6525
+ break;
6526
+
6527
+ case DUMP_BUF_ATTR_SPECIAL_LOG :
6528
+ ret = dhd_get_dld_log_dump(bcmcfg_to_prmry_ndev(cfg), NULL,
6529
+ buf->data_buf[0], NULL, (uint32)buf->len,
6530
+ DLD_BUF_TYPE_SPECIAL, &pos);
6531
+ break;
6532
+#ifdef DHD_SSSR_DUMP
6533
+ case DUMP_BUF_ATTR_SSSR_C0_D11_BEFORE :
6534
+ ret = dhd_sssr_dump_d11_buf_before(bcmcfg_to_prmry_ndev(cfg),
6535
+ buf->data_buf[0], (uint32)buf->len, 0);
6536
+ break;
6537
+
6538
+ case DUMP_BUF_ATTR_SSSR_C0_D11_AFTER :
6539
+ ret = dhd_sssr_dump_d11_buf_after(bcmcfg_to_prmry_ndev(cfg),
6540
+ buf->data_buf[0], (uint32)buf->len, 0);
6541
+ break;
6542
+
6543
+ case DUMP_BUF_ATTR_SSSR_C1_D11_BEFORE :
6544
+ ret = dhd_sssr_dump_d11_buf_before(bcmcfg_to_prmry_ndev(cfg),
6545
+ buf->data_buf[0], (uint32)buf->len, 1);
6546
+ break;
6547
+
6548
+ case DUMP_BUF_ATTR_SSSR_C1_D11_AFTER :
6549
+ ret = dhd_sssr_dump_d11_buf_after(bcmcfg_to_prmry_ndev(cfg),
6550
+ buf->data_buf[0], (uint32)buf->len, 1);
6551
+ break;
6552
+
6553
+ case DUMP_BUF_ATTR_SSSR_DIG_BEFORE :
6554
+ ret = dhd_sssr_dump_dig_buf_before(bcmcfg_to_prmry_ndev(cfg),
6555
+ buf->data_buf[0], (uint32)buf->len);
6556
+ break;
6557
+
6558
+ case DUMP_BUF_ATTR_SSSR_DIG_AFTER :
6559
+ ret = dhd_sssr_dump_dig_buf_after(bcmcfg_to_prmry_ndev(cfg),
6560
+ buf->data_buf[0], (uint32)buf->len);
6561
+ break;
6562
+#endif /* DHD_SSSR_DUMP */
6563
+#ifdef DHD_PKT_LOGGING
6564
+ case DUMP_BUF_ATTR_PKTLOG:
6565
+ ret = dhd_os_get_pktlog_dump(bcmcfg_to_prmry_ndev(cfg),
6566
+ buf->data_buf[0], (uint32)buf->len);
6567
+ break;
6568
+#endif /* DHD_PKT_LOGGING */
6569
+#ifdef DNGL_AXI_ERROR_LOGGING
6570
+ case DUMP_BUF_ATTR_AXI_ERROR:
6571
+ ret = dhd_os_get_axi_error_dump(bcmcfg_to_prmry_ndev(cfg),
6572
+ buf->data_buf[0], (uint32)buf->len);
6573
+ break;
6574
+#endif /* DNGL_AXI_ERROR_LOGGING */
6575
+ default:
6576
+ WL_ERR(("Unknown type: %d\n", type));
6577
+ ret = BCME_ERROR;
6578
+ goto exit;
6579
+ }
6580
+ }
6581
+
6582
+ if (ret)
6583
+ goto exit;
6584
+
6585
+ ret = nla_put_u32(skb, type, (uint32)(ret));
6586
+ if (ret < 0) {
6587
+ WL_ERR(("Failed to put type, ret:%d\n", ret));
6588
+ goto exit;
6589
+ }
6590
+ ret = cfg80211_vendor_cmd_reply(skb);
6591
+ if (ret) {
6592
+ WL_ERR(("Vendor Command reply failed ret:%d \n", ret));
6593
+ }
6594
+ return ret;
6595
+exit:
6596
+ if (skb) {
6597
+ /* Free skb memory */
6598
+ kfree_skb(skb);
6599
+ }
6600
+ return ret;
6601
+}
6602
+#endif /* DHD_LOG_DUMP */
6603
+
6604
+#ifdef DEBUGABILITY
6605
+static int
6606
+wl_cfgvendor_dbg_trigger_mem_dump(struct wiphy *wiphy,
6607
+ struct wireless_dev *wdev, const void *data, int len)
6608
+{
6609
+ int ret = BCME_OK;
6610
+ uint32 alloc_len;
6611
+ struct sk_buff *skb = NULL;
6612
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6613
+ dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
6614
+
6615
+ WL_ERR(("wl_cfgvendor_dbg_trigger_mem_dump %d\n", __LINE__));
6616
+
6617
+ dhdp->memdump_type = DUMP_TYPE_CFG_VENDOR_TRIGGERED;
6618
+ ret = dhd_os_socram_dump(bcmcfg_to_prmry_ndev(cfg), &alloc_len);
6619
+ if (ret) {
6620
+ WL_ERR(("failed to call dhd_os_socram_dump : %d\n", ret));
6621
+ goto exit;
6622
+ }
6623
+ /* Alloc the SKB for vendor_event */
6624
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, CFG80211_VENDOR_CMD_REPLY_SKB_SZ);
6625
+ if (!skb) {
6626
+ WL_ERR(("skb allocation is failed\n"));
6627
+ ret = BCME_NOMEM;
6628
+ goto exit;
6629
+ }
6630
+ ret = nla_put_u32(skb, DEBUG_ATTRIBUTE_FW_DUMP_LEN, alloc_len);
6631
+
6632
+ if (unlikely(ret)) {
6633
+ WL_ERR(("Failed to put fw dump length, ret=%d\n", ret));
6634
+ goto exit;
6635
+ }
6636
+
6637
+ ret = cfg80211_vendor_cmd_reply(skb);
6638
+
6639
+ if (ret) {
6640
+ WL_ERR(("Vendor Command reply failed ret:%d \n", ret));
6641
+ goto exit;
6642
+ }
6643
+ return ret;
6644
+exit:
6645
+ /* Free skb memory */
6646
+ if (skb) {
6647
+ kfree_skb(skb);
6648
+ }
6649
+ return ret;
6650
+}
6651
+
6652
+static int
6653
+wl_cfgvendor_dbg_get_mem_dump(struct wiphy *wiphy,
6654
+ struct wireless_dev *wdev, const void *data, int len)
6655
+{
6656
+ int ret = BCME_OK, rem, type;
6657
+ int buf_len = 0;
6658
+ uintptr_t user_buf = (uintptr_t)NULL;
6659
+ const struct nlattr *iter;
6660
+ char *mem_buf = NULL;
6661
+ struct sk_buff *skb = NULL;
6662
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6663
+
6664
+ nla_for_each_attr(iter, data, len, rem) {
6665
+ type = nla_type(iter);
6666
+ switch (type) {
6667
+ case DEBUG_ATTRIBUTE_FW_DUMP_LEN:
6668
+ /* Check if the iter is valid and
6669
+ * buffer length is not already initialized.
6670
+ */
6671
+ if ((nla_len(iter) == sizeof(uint32)) &&
6672
+ !buf_len) {
6673
+ buf_len = nla_get_u32(iter);
6674
+ if (buf_len <= 0) {
6675
+ ret = BCME_ERROR;
6676
+ goto exit;
6677
+ }
6678
+ } else {
6679
+ ret = BCME_ERROR;
6680
+ goto exit;
6681
+ }
6682
+ break;
6683
+ case DEBUG_ATTRIBUTE_FW_DUMP_DATA:
6684
+ if (nla_len(iter) != sizeof(uint64)) {
6685
+ WL_ERR(("Invalid len\n"));
6686
+ ret = BCME_ERROR;
6687
+ goto exit;
6688
+ }
6689
+ user_buf = (uintptr_t)nla_get_u64(iter);
6690
+ if (!user_buf) {
6691
+ ret = BCME_ERROR;
6692
+ goto exit;
6693
+ }
6694
+ break;
6695
+ default:
6696
+ WL_ERR(("Unknown type: %d\n", type));
6697
+ ret = BCME_ERROR;
6698
+ goto exit;
6699
+ }
6700
+ }
6701
+ if (buf_len > 0 && user_buf) {
6702
+ mem_buf = vmalloc(buf_len);
6703
+ if (!mem_buf) {
6704
+ WL_ERR(("failed to allocate mem_buf with size : %d\n", buf_len));
6705
+ ret = BCME_NOMEM;
6706
+ goto exit;
6707
+ }
6708
+ ret = dhd_os_get_socram_dump(bcmcfg_to_prmry_ndev(cfg), &mem_buf, &buf_len);
6709
+ if (ret) {
6710
+ WL_ERR(("failed to get_socram_dump : %d\n", ret));
6711
+ goto free_mem;
6712
+ }
6713
+ {
6714
+ ret = copy_to_user((void*)user_buf, mem_buf, buf_len);
6715
+ if (ret) {
6716
+ WL_ERR(("failed to copy memdump into user buffer : %d\n", ret));
6717
+ goto free_mem;
6718
+ }
6719
+ }
6720
+ /* Alloc the SKB for vendor_event */
6721
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, CFG80211_VENDOR_CMD_REPLY_SKB_SZ);
6722
+ if (!skb) {
6723
+ WL_ERR(("skb allocation is failed\n"));
6724
+ ret = BCME_NOMEM;
6725
+ goto free_mem;
6726
+ }
6727
+ /* Indicate the memdump is succesfully copied */
6728
+ ret = nla_put(skb, DEBUG_ATTRIBUTE_FW_DUMP_DATA, sizeof(ret), &ret);
6729
+ if (ret < 0) {
6730
+ WL_ERR(("Failed to put DEBUG_ATTRIBUTE_FW_DUMP_DATA, ret:%d\n", ret));
6731
+ goto free_mem;
6732
+ }
6733
+
6734
+ ret = cfg80211_vendor_cmd_reply(skb);
6735
+
6736
+ if (ret) {
6737
+ WL_ERR(("Vendor Command reply failed ret:%d \n", ret));
6738
+ }
6739
+ skb = NULL;
6740
+ }
6741
+
6742
+free_mem:
6743
+ vfree(mem_buf);
6744
+ /* Free skb memory */
6745
+ if (skb) {
6746
+ kfree_skb(skb);
6747
+ }
6748
+exit:
6749
+ return ret;
6750
+}
21756751
21766752 static int wl_cfgvendor_dbg_start_logging(struct wiphy *wiphy,
21776753 struct wireless_dev *wdev, const void *data, int len)
....@@ -2216,106 +6792,6 @@
22166792 return ret;
22176793 }
22186794
2219
-#ifdef DHD_FW_COREDUMP
2220
-static int wl_cfgvendor_dbg_trigger_mem_dump(struct wiphy *wiphy,
2221
- struct wireless_dev *wdev, const void *data, int len)
2222
-{
2223
- int ret = BCME_OK;
2224
- uint32 alloc_len;
2225
- struct sk_buff *skb;
2226
- struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2227
-
2228
- ret = dhd_os_socram_dump(bcmcfg_to_prmry_ndev(cfg), &alloc_len);
2229
- if (ret) {
2230
- WL_ERR(("failed to call dhd_os_socram_dump : %d\n", ret));
2231
- goto exit;
2232
- }
2233
- /* Alloc the SKB for vendor_event */
2234
- skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 100);
2235
- if (!skb) {
2236
- WL_ERR(("skb allocation is failed\n"));
2237
- ret = BCME_NOMEM;
2238
- goto exit;
2239
- }
2240
- nla_put_u32(skb, DEBUG_ATTRIBUTE_FW_DUMP_LEN, alloc_len);
2241
-
2242
- ret = cfg80211_vendor_cmd_reply(skb);
2243
-
2244
- if (ret) {
2245
- WL_ERR(("Vendor Command reply failed ret:%d \n", ret));
2246
- }
2247
-
2248
-exit:
2249
- return ret;
2250
-}
2251
-
2252
-static int wl_cfgvendor_dbg_get_mem_dump(struct wiphy *wiphy,
2253
- struct wireless_dev *wdev, const void *data, int len)
2254
-{
2255
- int ret = BCME_OK, rem, type;
2256
- int buf_len = 0;
2257
- void __user *user_buf = NULL;
2258
- const struct nlattr *iter;
2259
- char *mem_buf;
2260
- struct sk_buff *skb;
2261
- struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2262
-
2263
- nla_for_each_attr(iter, data, len, rem) {
2264
- type = nla_type(iter);
2265
- switch (type) {
2266
- case DEBUG_ATTRIBUTE_FW_DUMP_LEN:
2267
- buf_len = nla_get_u32(iter);
2268
- break;
2269
- case DEBUG_ATTRIBUTE_FW_DUMP_DATA:
2270
- user_buf = (void __user *) (unsigned long) nla_get_u64(iter);
2271
- break;
2272
- default:
2273
- WL_ERR(("Unknown type: %d\n", type));
2274
- ret = BCME_ERROR;
2275
- goto exit;
2276
- }
2277
- }
2278
- if (buf_len > 0 && user_buf) {
2279
- mem_buf = vmalloc(buf_len);
2280
- if (!mem_buf) {
2281
- WL_ERR(("failed to allocate mem_buf with size : %d\n", buf_len));
2282
- ret = BCME_NOMEM;
2283
- goto exit;
2284
- }
2285
- ret = dhd_os_get_socram_dump(bcmcfg_to_prmry_ndev(cfg), &mem_buf, &buf_len);
2286
- if (ret) {
2287
- WL_ERR(("failed to get_socram_dump : %d\n", ret));
2288
- goto free_mem;
2289
- }
2290
- ret = copy_to_user(user_buf, mem_buf, buf_len);
2291
- if (ret) {
2292
- WL_ERR(("failed to copy memdump into user buffer : %d\n", ret));
2293
- goto free_mem;
2294
- }
2295
- /* Alloc the SKB for vendor_event */
2296
- skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 100);
2297
- if (!skb) {
2298
- WL_ERR(("skb allocation is failed\n"));
2299
- ret = BCME_NOMEM;
2300
- goto free_mem;
2301
- }
2302
- /* Indicate the memdump is succesfully copied */
2303
- nla_put(skb, DEBUG_ATTRIBUTE_FW_DUMP_DATA, sizeof(ret), &ret);
2304
-
2305
- ret = cfg80211_vendor_cmd_reply(skb);
2306
-
2307
- if (ret) {
2308
- WL_ERR(("Vendor Command reply failed ret:%d \n", ret));
2309
- }
2310
- }
2311
-
2312
-free_mem:
2313
- vfree(mem_buf);
2314
-exit:
2315
- return ret;
2316
-}
2317
-#endif /* DHD_FW_COREDUMP */
2318
-
23196795 static int wl_cfgvendor_dbg_reset_logging(struct wiphy *wiphy,
23206796 struct wireless_dev *wdev, const void *data, int len)
23216797 {
....@@ -2331,52 +6807,6 @@
23316807 return ret;
23326808 }
23336809
2334
-#ifdef DHD_FW_COREDUMP
2335
-static int wl_cfgvendor_dbg_get_version(struct wiphy *wiphy,
2336
- struct wireless_dev *wdev, const void *data, int len)
2337
-{
2338
- int ret = BCME_OK, rem, type;
2339
- int buf_len = 1024;
2340
- bool dhd_ver = FALSE;
2341
- char *buf_ptr;
2342
- const struct nlattr *iter;
2343
- gfp_t kflags;
2344
- struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2345
- kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
2346
- buf_ptr = kzalloc(buf_len, kflags);
2347
- if (!buf_ptr) {
2348
- WL_ERR(("failed to allocate the buffer for version n"));
2349
- ret = BCME_NOMEM;
2350
- goto exit;
2351
- }
2352
- nla_for_each_attr(iter, data, len, rem) {
2353
- type = nla_type(iter);
2354
- switch (type) {
2355
- case DEBUG_ATTRIBUTE_GET_DRIVER:
2356
- dhd_ver = TRUE;
2357
- break;
2358
- case DEBUG_ATTRIBUTE_GET_FW:
2359
- dhd_ver = FALSE;
2360
- break;
2361
- default:
2362
- WL_ERR(("Unknown type: %d\n", type));
2363
- ret = BCME_ERROR;
2364
- goto exit;
2365
- }
2366
- }
2367
- ret = dhd_os_get_version(bcmcfg_to_prmry_ndev(cfg), dhd_ver, &buf_ptr, buf_len);
2368
- if (ret < 0) {
2369
- WL_ERR(("failed to get the version %d\n", ret));
2370
- goto exit;
2371
- }
2372
- ret = wl_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
2373
- buf_ptr, strlen(buf_ptr));
2374
-exit:
2375
- kfree(buf_ptr);
2376
- return ret;
2377
-}
2378
-#endif /* DHD_FW_COREDUMP */
2379
-
23806810 static int wl_cfgvendor_dbg_get_ring_status(struct wiphy *wiphy,
23816811 struct wireless_dev *wdev, const void *data, int len)
23826812 {
....@@ -2388,7 +6818,7 @@
23886818 dhd_dbg_ring_status_t ring_status;
23896819 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
23906820 dhd_pub_t *dhd_pub = cfg->pub;
2391
- memset(dbg_ring_status, 0, DBG_RING_STATUS_SIZE * DEBUG_RING_ID_MAX);
6821
+ bzero(dbg_ring_status, DBG_RING_STATUS_SIZE * DEBUG_RING_ID_MAX);
23926822 ring_cnt = 0;
23936823 for (ring_id = DEBUG_RING_ID_INVALID + 1; ring_id < DEBUG_RING_ID_MAX; ring_id++) {
23946824 ret = dhd_os_get_ring_status(dhd_pub, ring_id, &ring_status);
....@@ -2400,16 +6830,19 @@
24006830 }
24016831 /* Alloc the SKB for vendor_event */
24026832 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2403
- (DBG_RING_STATUS_SIZE * ring_cnt) + 100);
6833
+ nla_total_size(DBG_RING_STATUS_SIZE) * ring_cnt + nla_total_size(sizeof(ring_cnt)));
24046834 if (!skb) {
24056835 WL_ERR(("skb allocation is failed\n"));
24066836 ret = BCME_NOMEM;
24076837 goto exit;
24086838 }
24096839
2410
- nla_put_u32(skb, DEBUG_ATTRIBUTE_RING_NUM, ring_cnt);
6840
+ /* Ignore return of nla_put_u32 and nla_put since the skb allocated
6841
+ * above has a requested size for all payload
6842
+ */
6843
+ (void)nla_put_u32(skb, DEBUG_ATTRIBUTE_RING_NUM, ring_cnt);
24116844 for (i = 0; i < ring_cnt; i++) {
2412
- nla_put(skb, DEBUG_ATTRIBUTE_RING_STATUS, DBG_RING_STATUS_SIZE,
6845
+ (void)nla_put(skb, DEBUG_ATTRIBUTE_RING_STATUS, DBG_RING_STATUS_SIZE,
24136846 &dbg_ring_status[i]);
24146847 }
24156848 ret = cfg80211_vendor_cmd_reply(skb);
....@@ -2434,8 +6867,7 @@
24346867 type = nla_type(iter);
24356868 switch (type) {
24366869 case DEBUG_ATTRIBUTE_RING_NAME:
2437
- strncpy(ring_name, nla_data(iter),
2438
- MIN(sizeof(ring_name) -1, nla_len(iter)));
6870
+ strlcpy(ring_name, nla_data(iter), sizeof(ring_name));
24396871 break;
24406872 default:
24416873 WL_ERR(("Unknown type: %d\n", type));
....@@ -2450,12 +6882,51 @@
24506882
24516883 return ret;
24526884 }
6885
+#else
6886
+static int
6887
+wl_cfgvendor_dbg_trigger_mem_dump(struct wiphy *wiphy,
6888
+ struct wireless_dev *wdev, const void *data, int len)
6889
+{
6890
+ return WIFI_ERROR_NOT_SUPPORTED;
6891
+}
6892
+
6893
+static int
6894
+wl_cfgvendor_dbg_get_mem_dump(struct wiphy *wiphy,
6895
+ struct wireless_dev *wdev, const void *data, int len)
6896
+{
6897
+ return WIFI_ERROR_NOT_SUPPORTED;
6898
+}
6899
+
6900
+static int wl_cfgvendor_dbg_start_logging(struct wiphy *wiphy,
6901
+ struct wireless_dev *wdev, const void *data, int len)
6902
+{
6903
+ return WIFI_ERROR_NOT_SUPPORTED;
6904
+}
6905
+
6906
+static int wl_cfgvendor_dbg_reset_logging(struct wiphy *wiphy,
6907
+ struct wireless_dev *wdev, const void *data, int len)
6908
+{
6909
+ return WIFI_ERROR_NOT_SUPPORTED;
6910
+}
6911
+
6912
+static int wl_cfgvendor_dbg_get_ring_status(struct wiphy *wiphy,
6913
+ struct wireless_dev *wdev, const void *data, int len)
6914
+{
6915
+ return WIFI_ERROR_NOT_SUPPORTED;
6916
+}
6917
+
6918
+static int wl_cfgvendor_dbg_get_ring_data(struct wiphy *wiphy,
6919
+ struct wireless_dev *wdev, const void *data, int len)
6920
+{
6921
+ return WIFI_ERROR_NOT_SUPPORTED;
6922
+}
6923
+#endif /* DEBUGABILITY */
24536924
24546925 static int wl_cfgvendor_dbg_get_feature(struct wiphy *wiphy,
24556926 struct wireless_dev *wdev, const void *data, int len)
24566927 {
24576928 int ret = BCME_OK;
2458
- u32 supported_features;
6929
+ u32 supported_features = 0;
24596930 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
24606931 dhd_pub_t *dhd_pub = cfg->pub;
24616932
....@@ -2464,12 +6935,13 @@
24646935 WL_ERR(("dbg_get_feature failed ret:%d\n", ret));
24656936 goto exit;
24666937 }
2467
- ret = wl_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
2468
- &supported_features, sizeof(supported_features));
6938
+ ret = wl_cfgvendor_send_cmd_reply(wiphy, &supported_features,
6939
+ sizeof(supported_features));
24696940 exit:
24706941 return ret;
24716942 }
24726943
6944
+#ifdef DEBUGABILITY
24736945 static void wl_cfgvendor_dbg_ring_send_evt(void *ctx,
24746946 const int ring_id, const void *data, const uint32 len,
24756947 const dhd_dbg_ring_status_t ring_status)
....@@ -2502,85 +6974,1724 @@
25026974 nla_put(skb, DEBUG_ATTRIBUTE_RING_DATA, len, data);
25036975 cfg80211_vendor_event(skb, kflags);
25046976 }
6977
+#endif /* DEBUGABILITY */
25056978
2506
-static void wl_cfgvendor_dbg_send_urgent_evt(void *ctx, const void *data,
6979
+#ifdef DHD_LOG_DUMP
6980
+static int wl_cfgvendor_nla_put_sssr_dump_data(struct sk_buff *skb,
6981
+ struct net_device *ndev)
6982
+{
6983
+ int ret = BCME_OK;
6984
+#ifdef DHD_SSSR_DUMP
6985
+ uint32 arr_len[DUMP_SSSR_ATTR_COUNT];
6986
+ int i = 0, j = 0;
6987
+#endif /* DHD_SSSR_DUMP */
6988
+ char memdump_path[MEMDUMP_PATH_LEN];
6989
+
6990
+ dhd_get_memdump_filename(ndev, memdump_path, MEMDUMP_PATH_LEN,
6991
+ "sssr_dump_core_0_before_SR");
6992
+ ret = nla_put_string(skb, DUMP_FILENAME_ATTR_SSSR_CORE_0_BEFORE_DUMP, memdump_path);
6993
+ if (unlikely(ret)) {
6994
+ WL_ERR(("Failed to nla put sssr core 0 before dump path, ret=%d\n", ret));
6995
+ goto exit;
6996
+ }
6997
+
6998
+ dhd_get_memdump_filename(ndev, memdump_path, MEMDUMP_PATH_LEN,
6999
+ "sssr_dump_core_0_after_SR");
7000
+ ret = nla_put_string(skb, DUMP_FILENAME_ATTR_SSSR_CORE_0_AFTER_DUMP, memdump_path);
7001
+ if (unlikely(ret)) {
7002
+ WL_ERR(("Failed to nla put sssr core 1 after dump path, ret=%d\n", ret));
7003
+ goto exit;
7004
+ }
7005
+
7006
+ dhd_get_memdump_filename(ndev, memdump_path, MEMDUMP_PATH_LEN,
7007
+ "sssr_dump_core_1_before_SR");
7008
+ ret = nla_put_string(skb, DUMP_FILENAME_ATTR_SSSR_CORE_1_BEFORE_DUMP, memdump_path);
7009
+ if (unlikely(ret)) {
7010
+ WL_ERR(("Failed to nla put sssr core 1 before dump path, ret=%d\n", ret));
7011
+ goto exit;
7012
+ }
7013
+
7014
+ dhd_get_memdump_filename(ndev, memdump_path, MEMDUMP_PATH_LEN,
7015
+ "sssr_dump_core_1_after_SR");
7016
+ ret = nla_put_string(skb, DUMP_FILENAME_ATTR_SSSR_CORE_1_AFTER_DUMP, memdump_path);
7017
+ if (unlikely(ret)) {
7018
+ WL_ERR(("Failed to nla put sssr core 1 after dump path, ret=%d\n", ret));
7019
+ goto exit;
7020
+ }
7021
+
7022
+ dhd_get_memdump_filename(ndev, memdump_path, MEMDUMP_PATH_LEN,
7023
+ "sssr_dump_dig_before_SR");
7024
+ ret = nla_put_string(skb, DUMP_FILENAME_ATTR_SSSR_DIG_BEFORE_DUMP, memdump_path);
7025
+ if (unlikely(ret)) {
7026
+ WL_ERR(("Failed to nla put sssr dig before dump path, ret=%d\n", ret));
7027
+ goto exit;
7028
+ }
7029
+
7030
+ dhd_get_memdump_filename(ndev, memdump_path, MEMDUMP_PATH_LEN,
7031
+ "sssr_dump_dig_after_SR");
7032
+ ret = nla_put_string(skb, DUMP_FILENAME_ATTR_SSSR_DIG_AFTER_DUMP, memdump_path);
7033
+ if (unlikely(ret)) {
7034
+ WL_ERR(("Failed to nla put sssr dig after dump path, ret=%d\n", ret));
7035
+ goto exit;
7036
+ }
7037
+
7038
+#ifdef DHD_SSSR_DUMP
7039
+ memset(arr_len, 0, sizeof(arr_len));
7040
+ dhd_nla_put_sssr_dump_len(ndev, arr_len);
7041
+
7042
+ for (i = 0, j = DUMP_SSSR_ATTR_START; i < DUMP_SSSR_ATTR_COUNT; i++, j++) {
7043
+ if (arr_len[i]) {
7044
+ ret = nla_put_u32(skb, j, arr_len[i]);
7045
+ if (unlikely(ret)) {
7046
+ WL_ERR(("Failed to nla put sssr dump len, ret=%d\n", ret));
7047
+ goto exit;
7048
+ }
7049
+ }
7050
+ }
7051
+#endif /* DHD_SSSR_DUMP */
7052
+
7053
+exit:
7054
+ return ret;
7055
+}
7056
+
7057
+static int wl_cfgvendor_nla_put_debug_dump_data(struct sk_buff *skb,
7058
+ struct net_device *ndev)
7059
+{
7060
+ int ret = BCME_OK;
7061
+ uint32 len = 0;
7062
+ char dump_path[128];
7063
+
7064
+ ret = dhd_get_debug_dump_file_name(ndev, NULL, dump_path, sizeof(dump_path));
7065
+ if (ret < 0) {
7066
+ WL_ERR(("%s: Failed to get debug dump filename\n", __FUNCTION__));
7067
+ goto exit;
7068
+ }
7069
+ ret = nla_put_string(skb, DUMP_FILENAME_ATTR_DEBUG_DUMP, dump_path);
7070
+ if (unlikely(ret)) {
7071
+ WL_ERR(("Failed to nla put debug dump path, ret=%d\n", ret));
7072
+ goto exit;
7073
+ }
7074
+ WL_ERR(("debug_dump path = %s%s\n", dump_path, FILE_NAME_HAL_TAG));
7075
+ wl_print_verinfo(wl_get_cfg(ndev));
7076
+
7077
+ len = dhd_get_time_str_len();
7078
+ if (len) {
7079
+ ret = nla_put_u32(skb, DUMP_LEN_ATTR_TIMESTAMP, len);
7080
+ if (unlikely(ret)) {
7081
+ WL_ERR(("Failed to nla put time stamp length, ret=%d\n", ret));
7082
+ goto exit;
7083
+ }
7084
+ }
7085
+
7086
+ len = dhd_get_dld_len(DLD_BUF_TYPE_GENERAL);
7087
+ if (len) {
7088
+ ret = nla_put_u32(skb, DUMP_LEN_ATTR_GENERAL_LOG, len);
7089
+ if (unlikely(ret)) {
7090
+ WL_ERR(("Failed to nla put general log length, ret=%d\n", ret));
7091
+ goto exit;
7092
+ }
7093
+ }
7094
+#ifdef EWP_ECNTRS_LOGGING
7095
+ len = dhd_get_ecntrs_len(ndev, NULL);
7096
+ if (len) {
7097
+ ret = nla_put_u32(skb, DUMP_LEN_ATTR_ECNTRS, len);
7098
+ if (unlikely(ret)) {
7099
+ WL_ERR(("Failed to nla put ecntrs length, ret=%d\n", ret));
7100
+ goto exit;
7101
+ }
7102
+ }
7103
+#endif /* EWP_ECNTRS_LOGGING */
7104
+ len = dhd_get_dld_len(DLD_BUF_TYPE_SPECIAL);
7105
+ if (len) {
7106
+ ret = nla_put_u32(skb, DUMP_LEN_ATTR_SPECIAL_LOG, len);
7107
+ if (unlikely(ret)) {
7108
+ WL_ERR(("Failed to nla put special log length, ret=%d\n", ret));
7109
+ goto exit;
7110
+ }
7111
+ }
7112
+ len = dhd_get_dhd_dump_len(ndev, NULL);
7113
+ if (len) {
7114
+ ret = nla_put_u32(skb, DUMP_LEN_ATTR_DHD_DUMP, len);
7115
+ if (unlikely(ret)) {
7116
+ WL_ERR(("Failed to nla put dhd dump length, ret=%d\n", ret));
7117
+ goto exit;
7118
+ }
7119
+ }
7120
+
7121
+#if defined(BCMPCIE)
7122
+ len = dhd_get_ext_trap_len(ndev, NULL);
7123
+ if (len) {
7124
+ ret = nla_put_u32(skb, DUMP_LEN_ATTR_EXT_TRAP, len);
7125
+ if (unlikely(ret)) {
7126
+ WL_ERR(("Failed to nla put ext trap length, ret=%d\n", ret));
7127
+ goto exit;
7128
+ }
7129
+ }
7130
+#endif /* BCMPCIE */
7131
+
7132
+#if defined(DHD_FW_COREDUMP) && defined(DNGL_EVENT_SUPPORT)
7133
+ len = dhd_get_health_chk_len(ndev, NULL);
7134
+ if (len) {
7135
+ ret = nla_put_u32(skb, DUMP_LEN_ATTR_HEALTH_CHK, len);
7136
+ if (unlikely(ret)) {
7137
+ WL_ERR(("Failed to nla put health check length, ret=%d\n", ret));
7138
+ goto exit;
7139
+ }
7140
+ }
7141
+#endif // endif
7142
+
7143
+ len = dhd_get_dld_len(DLD_BUF_TYPE_PRESERVE);
7144
+ if (len) {
7145
+ ret = nla_put_u32(skb, DUMP_LEN_ATTR_PRESERVE_LOG, len);
7146
+ if (unlikely(ret)) {
7147
+ WL_ERR(("Failed to nla put preserve log length, ret=%d\n", ret));
7148
+ goto exit;
7149
+ }
7150
+ }
7151
+
7152
+ len = dhd_get_cookie_log_len(ndev, NULL);
7153
+ if (len) {
7154
+ ret = nla_put_u32(skb, DUMP_LEN_ATTR_COOKIE, len);
7155
+ if (unlikely(ret)) {
7156
+ WL_ERR(("Failed to nla put cookie length, ret=%d\n", ret));
7157
+ goto exit;
7158
+ }
7159
+ }
7160
+#ifdef DHD_DUMP_PCIE_RINGS
7161
+ len = dhd_get_flowring_len(ndev, NULL);
7162
+ if (len) {
7163
+ ret = nla_put_u32(skb, DUMP_LEN_ATTR_FLOWRING_DUMP, len);
7164
+ if (unlikely(ret)) {
7165
+ WL_ERR(("Failed to nla put flowring dump length, ret=%d\n", ret));
7166
+ goto exit;
7167
+ }
7168
+ }
7169
+#endif // endif
7170
+#ifdef DHD_STATUS_LOGGING
7171
+ len = dhd_get_status_log_len(ndev, NULL);
7172
+ if (len) {
7173
+ ret = nla_put_u32(skb, DUMP_LEN_ATTR_STATUS_LOG, len);
7174
+ if (unlikely(ret)) {
7175
+ WL_ERR(("Failed to nla put status log length, ret=%d\n", ret));
7176
+ goto exit;
7177
+ }
7178
+ }
7179
+#endif /* DHD_STATUS_LOGGING */
7180
+#ifdef EWP_RTT_LOGGING
7181
+ len = dhd_get_rtt_len(ndev, NULL);
7182
+ if (len) {
7183
+ ret = nla_put_u32(skb, DUMP_LEN_ATTR_RTT_LOG, len);
7184
+ if (unlikely(ret)) {
7185
+ WL_ERR(("Failed to nla put rtt log length, ret=%d\n", ret));
7186
+ goto exit;
7187
+ }
7188
+ }
7189
+#endif /* EWP_RTT_LOGGING */
7190
+exit:
7191
+ return ret;
7192
+}
7193
+#ifdef DNGL_AXI_ERROR_LOGGING
7194
+static void wl_cfgvendor_nla_put_axi_error_data(struct sk_buff *skb,
7195
+ struct net_device *ndev)
7196
+{
7197
+ int ret = 0;
7198
+ char axierrordump_path[MEMDUMP_PATH_LEN];
7199
+ int dumpsize = dhd_os_get_axi_error_dump_size(ndev);
7200
+ if (dumpsize <= 0) {
7201
+ WL_ERR(("Failed to calcuate axi error dump len\n"));
7202
+ return;
7203
+ }
7204
+ dhd_os_get_axi_error_filename(ndev, axierrordump_path, MEMDUMP_PATH_LEN);
7205
+ ret = nla_put_string(skb, DUMP_FILENAME_ATTR_AXI_ERROR_DUMP, axierrordump_path);
7206
+ if (ret) {
7207
+ WL_ERR(("Failed to put filename\n"));
7208
+ return;
7209
+ }
7210
+ ret = nla_put_u32(skb, DUMP_LEN_ATTR_AXI_ERROR, dumpsize);
7211
+ if (ret) {
7212
+ WL_ERR(("Failed to put filesize\n"));
7213
+ return;
7214
+ }
7215
+}
7216
+#endif /* DNGL_AXI_ERROR_LOGGING */
7217
+#ifdef DHD_PKT_LOGGING
7218
+static void wl_cfgvendor_nla_put_pktlogdump_data(struct sk_buff *skb,
7219
+ struct net_device *ndev)
7220
+{
7221
+ int ret = 0;
7222
+ char pktlogdump_path[MEMDUMP_PATH_LEN];
7223
+ uint32 pktlog_dumpsize = dhd_os_get_pktlog_dump_size(ndev);
7224
+ if (pktlog_dumpsize == 0) {
7225
+ WL_ERR(("Failed to calcuate pktlog len\n"));
7226
+ return;
7227
+ }
7228
+ dhd_os_get_pktlogdump_filename(ndev, pktlogdump_path, MEMDUMP_PATH_LEN);
7229
+ ret = nla_put_string(skb, DUMP_FILENAME_ATTR_PKTLOG_DUMP, pktlogdump_path);
7230
+ if (ret) {
7231
+ WL_ERR(("Failed to put filename\n"));
7232
+ return;
7233
+ }
7234
+ ret = nla_put_u32(skb, DUMP_LEN_ATTR_PKTLOG, pktlog_dumpsize);
7235
+ if (ret) {
7236
+ WL_ERR(("Failed to put filesize\n"));
7237
+ return;
7238
+ }
7239
+}
7240
+#endif /* DHD_PKT_LOGGING */
7241
+
7242
+static int wl_cfgvendor_nla_put_memdump_data(struct sk_buff *skb,
7243
+ struct net_device *ndev, const uint32 fw_len)
7244
+{
7245
+ char memdump_path[MEMDUMP_PATH_LEN];
7246
+ int ret = BCME_OK;
7247
+
7248
+ dhd_get_memdump_filename(ndev, memdump_path, MEMDUMP_PATH_LEN, "mem_dump");
7249
+ ret = nla_put_string(skb, DUMP_FILENAME_ATTR_MEM_DUMP, memdump_path);
7250
+ if (unlikely(ret)) {
7251
+ WL_ERR(("Failed to nla put mem dump path, ret=%d\n", ret));
7252
+ goto exit;
7253
+ }
7254
+ ret = nla_put_u32(skb, DUMP_LEN_ATTR_MEMDUMP, fw_len);
7255
+ if (unlikely(ret)) {
7256
+ WL_ERR(("Failed to nla put mem dump length, ret=%d\n", ret));
7257
+ goto exit;
7258
+ }
7259
+
7260
+exit:
7261
+ return ret;
7262
+}
7263
+
7264
+static void wl_cfgvendor_dbg_send_file_dump_evt(void *ctx, const void *data,
25077265 const uint32 len, const uint32 fw_len)
25087266 {
25097267 struct net_device *ndev = ctx;
25107268 struct wiphy *wiphy;
25117269 gfp_t kflags;
2512
- struct sk_buff *skb;
7270
+ struct sk_buff *skb = NULL;
7271
+ struct bcm_cfg80211 *cfg;
7272
+ dhd_pub_t *dhd_pub;
7273
+ int ret = BCME_OK;
7274
+
25137275 if (!ndev) {
25147276 WL_ERR(("ndev is NULL\n"));
25157277 return;
25167278 }
7279
+
25177280 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
25187281 wiphy = ndev->ieee80211_ptr->wiphy;
25197282 /* Alloc the SKB for vendor_event */
25207283 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
25217284 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
2522
- skb = cfg80211_vendor_event_alloc(wiphy, NULL, len + 100,
2523
- GOOGLE_FW_DUMP_EVENT, kflags);
7285
+ skb = cfg80211_vendor_event_alloc(wiphy, NULL, len + CFG80211_VENDOR_EVT_SKB_SZ,
7286
+ GOOGLE_FILE_DUMP_EVENT, kflags);
25247287 #else
2525
- skb = cfg80211_vendor_event_alloc(wiphy, len + 100,
2526
- GOOGLE_FW_DUMP_EVENT, kflags);
7288
+ skb = cfg80211_vendor_event_alloc(wiphy, len + CFG80211_VENDOR_EVT_SKB_SZ,
7289
+ GOOGLE_FILE_DUMP_EVENT, kflags);
25277290 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
25287291 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
25297292 if (!skb) {
25307293 WL_ERR(("skb alloc failed"));
25317294 return;
25327295 }
2533
- nla_put_u32(skb, DEBUG_ATTRIBUTE_FW_DUMP_LEN, fw_len);
2534
- nla_put(skb, DEBUG_ATTRIBUTE_RING_DATA, len, data);
7296
+
7297
+ cfg = wiphy_priv(wiphy);
7298
+ dhd_pub = cfg->pub;
7299
+#ifdef DNGL_AXI_ERROR_LOGGING
7300
+ if (dhd_pub->smmu_fault_occurred) {
7301
+ wl_cfgvendor_nla_put_axi_error_data(skb, ndev);
7302
+ }
7303
+#endif /* DNGL_AXI_ERROR_LOGGING */
7304
+ if (dhd_pub->memdump_enabled || (dhd_pub->memdump_type == DUMP_TYPE_BY_SYSDUMP)) {
7305
+ if (((ret = wl_cfgvendor_nla_put_memdump_data(skb, ndev, fw_len)) < 0) ||
7306
+ ((ret = wl_cfgvendor_nla_put_debug_dump_data(skb, ndev)) < 0) ||
7307
+ ((ret = wl_cfgvendor_nla_put_sssr_dump_data(skb, ndev)) < 0)) {
7308
+ WL_ERR(("nla put failed\n"));
7309
+ goto done;
7310
+ }
7311
+#ifdef DHD_PKT_LOGGING
7312
+ wl_cfgvendor_nla_put_pktlogdump_data(skb, ndev);
7313
+#endif /* DHD_PKT_LOGGING */
7314
+ }
7315
+ /* TODO : Similar to above function add for debug_dump, sssr_dump, and pktlog also. */
25357316 cfg80211_vendor_event(skb, kflags);
7317
+ return;
7318
+done:
7319
+ if (skb) {
7320
+ dev_kfree_skb_any(skb);
7321
+ }
7322
+}
7323
+#endif /* DHD_LOG_DUMP */
7324
+
7325
+static int wl_cfgvendor_priv_frameburst(struct wiphy *wiphy,
7326
+ struct wireless_dev *wdev, const void *data, int len)
7327
+{
7328
+ int ret = BCME_OK;
7329
+ int val = *(int *)data;
7330
+ int get_frmbrst = 0;
7331
+ int err = 0;
7332
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7333
+
7334
+ if (val == 0xa) {
7335
+ ret = wldev_ioctl_get(bcmcfg_to_prmry_ndev(cfg),
7336
+ WLC_GET_FAKEFRAG, &get_frmbrst, sizeof(int));
7337
+ if (ret) {
7338
+ WL_ERR(("Failed : %d\n", ret));
7339
+ }
7340
+ WL_DBG(("Get Frameburst : %d\n", get_frmbrst));
7341
+ err = wl_cfgvendor_send_cmd_reply(wiphy, &get_frmbrst, sizeof(int));
7342
+ if (unlikely(err))
7343
+ WL_ERR(("Vendor Command reply failed ret:%d \n", err));
7344
+ }
7345
+ else {
7346
+ WL_DBG(("Set frameburst %d\n", val));
7347
+ ret = wldev_ioctl_set(bcmcfg_to_prmry_ndev(cfg),
7348
+ WLC_SET_FAKEFRAG, &val, sizeof(val));
7349
+ if (ret < 0) {
7350
+ WL_ERR(("Failed set frameburst, ret=%d\n", ret));
7351
+ } else {
7352
+ WL_ERR(("frameburst is %s\n", val ? "enabled" : "disabled"));
7353
+ }
7354
+ }
7355
+ return ret;
25367356 }
25377357
7358
+static int wl_cfgvendor_priv_mpc(struct wiphy *wiphy,
7359
+ struct wireless_dev *wdev, const void *data, int len)
7360
+{
7361
+ int ret = BCME_OK;
7362
+ int val = *(int *)data;
7363
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7364
+ int get_mpc = 0;
7365
+ int err = 0;
7366
+
7367
+ if (val == 0xa) {
7368
+ ret = wldev_iovar_getint(bcmcfg_to_prmry_ndev(cfg), "mpc", &get_mpc);
7369
+ if (ret) {
7370
+ WL_ERR(("Failed : %d\n", ret));
7371
+ }
7372
+ WL_DBG(("Get MPC : %d\n", get_mpc));
7373
+ err = wl_cfgvendor_send_cmd_reply(wiphy, &get_mpc, sizeof(int));
7374
+ if (unlikely(err))
7375
+ WL_ERR(("Vendor Command reply failed ret:%d \n", err));
7376
+ }
7377
+ else {
7378
+ WL_DBG(("Set mpc val %d\n", val));
7379
+ ret = wldev_iovar_setint(bcmcfg_to_prmry_ndev(cfg), "mpc", val);
7380
+ if (ret < 0) {
7381
+ WL_ERR(("Failed set mpc, ret=%d\n", ret));
7382
+ } else {
7383
+ WL_INFORM_MEM(("mpc is %s\n", val ? "enabled" : "disabled"));
7384
+ }
7385
+ }
7386
+ return ret;
7387
+}
7388
+
7389
+static int wl_cfgvendor_priv_band(struct wiphy *wiphy,
7390
+ struct wireless_dev *wdev, const void *data, int len)
7391
+{
7392
+ int ret = BCME_OK;
7393
+ uint val = *(uint *)data;
7394
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7395
+ int get_band = 0;
7396
+ int err = 0;
7397
+
7398
+ if (val == 0xa) {
7399
+ ret = wldev_ioctl_get(bcmcfg_to_prmry_ndev(cfg),
7400
+ WLC_GET_BAND, &get_band, sizeof(int));
7401
+ if (ret) {
7402
+ WL_ERR(("Failed : %d\n", ret));
7403
+ }
7404
+ WL_DBG(("Get band : %d\n", get_band));
7405
+ err = wl_cfgvendor_send_cmd_reply(wiphy, &get_band, sizeof(int));
7406
+ if (unlikely(err))
7407
+ WL_ERR(("Vendor Command reply failed ret:%d \n", err));
7408
+ }
7409
+ else {
7410
+ WL_DBG(("Set band val %d\n", val));
7411
+ if ((val == WLC_BAND_AUTO) || (val == WLC_BAND_5G) || (val == WLC_BAND_2G)) {
7412
+ ret = wldev_ioctl_set(bcmcfg_to_prmry_ndev(cfg),
7413
+ WLC_SET_BAND, &val, sizeof(val));
7414
+ if (!ret)
7415
+ dhd_bus_band_set(bcmcfg_to_prmry_ndev(cfg), val);
7416
+ }
7417
+
7418
+ }
7419
+ return ret;
7420
+}
7421
+
7422
+static int wl_cfgvendor_dbg_get_version(struct wiphy *wiphy,
7423
+ struct wireless_dev *wdev, const void *data, int len)
7424
+{
7425
+ int ret = BCME_OK, rem, type;
7426
+ int buf_len = 1024;
7427
+ bool dhd_ver = FALSE;
7428
+ char *buf_ptr;
7429
+ const struct nlattr *iter;
7430
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7431
+
7432
+ buf_ptr = (char *)MALLOCZ(cfg->osh, buf_len);
7433
+ if (!buf_ptr) {
7434
+ WL_ERR(("failed to allocate the buffer for version n"));
7435
+ ret = BCME_NOMEM;
7436
+ goto exit;
7437
+ }
7438
+ nla_for_each_attr(iter, data, len, rem) {
7439
+ type = nla_type(iter);
7440
+ switch (type) {
7441
+ case DEBUG_ATTRIBUTE_GET_DRIVER:
7442
+ dhd_ver = TRUE;
7443
+ break;
7444
+ case DEBUG_ATTRIBUTE_GET_FW:
7445
+ dhd_ver = FALSE;
7446
+ break;
7447
+ default:
7448
+ WL_ERR(("Unknown type: %d\n", type));
7449
+ ret = BCME_ERROR;
7450
+ goto exit;
7451
+ }
7452
+ }
7453
+ ret = dhd_os_get_version(bcmcfg_to_prmry_ndev(cfg), dhd_ver, &buf_ptr, buf_len);
7454
+ if (ret < 0) {
7455
+ WL_ERR(("failed to get the version %d\n", ret));
7456
+ goto exit;
7457
+ }
7458
+ ret = wl_cfgvendor_send_cmd_reply(wiphy, buf_ptr, strlen(buf_ptr));
7459
+exit:
7460
+ MFREE(cfg->osh, buf_ptr, buf_len);
7461
+ return ret;
7462
+}
7463
+
7464
+#ifdef DBG_PKT_MON
7465
+static int wl_cfgvendor_dbg_start_pkt_fate_monitoring(struct wiphy *wiphy,
7466
+ struct wireless_dev *wdev, const void *data, int len)
7467
+{
7468
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7469
+ dhd_pub_t *dhd_pub = cfg->pub;
7470
+ int ret;
7471
+
7472
+ ret = dhd_os_dbg_attach_pkt_monitor(dhd_pub);
7473
+ if (unlikely(ret)) {
7474
+ WL_ERR(("failed to start pkt fate monitoring, ret=%d", ret));
7475
+ }
7476
+
7477
+ return ret;
7478
+}
7479
+
7480
+typedef int (*dbg_mon_get_pkts_t) (dhd_pub_t *dhdp, void __user *user_buf,
7481
+ uint16 req_count, uint16 *resp_count);
7482
+
7483
+static int __wl_cfgvendor_dbg_get_pkt_fates(struct wiphy *wiphy,
7484
+ const void *data, int len, dbg_mon_get_pkts_t dbg_mon_get_pkts)
7485
+{
7486
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7487
+ dhd_pub_t *dhd_pub = cfg->pub;
7488
+ struct sk_buff *skb = NULL;
7489
+ const struct nlattr *iter;
7490
+ void __user *user_buf = NULL;
7491
+ uint16 req_count = 0, resp_count = 0;
7492
+ int ret, tmp, type, mem_needed;
7493
+
7494
+ nla_for_each_attr(iter, data, len, tmp) {
7495
+ type = nla_type(iter);
7496
+ switch (type) {
7497
+ case DEBUG_ATTRIBUTE_PKT_FATE_NUM:
7498
+ req_count = nla_get_u32(iter);
7499
+ break;
7500
+ case DEBUG_ATTRIBUTE_PKT_FATE_DATA:
7501
+ user_buf = (void __user *)(unsigned long) nla_get_u64(iter);
7502
+ break;
7503
+ default:
7504
+ WL_ERR(("%s: no such attribute %d\n", __FUNCTION__, type));
7505
+ ret = -EINVAL;
7506
+ goto exit;
7507
+ }
7508
+ }
7509
+
7510
+ if (!req_count || !user_buf) {
7511
+ WL_ERR(("%s: invalid request, user_buf=%p, req_count=%u\n",
7512
+ __FUNCTION__, user_buf, req_count));
7513
+ ret = -EINVAL;
7514
+ goto exit;
7515
+ }
7516
+
7517
+ ret = dbg_mon_get_pkts(dhd_pub, user_buf, req_count, &resp_count);
7518
+ if (unlikely(ret)) {
7519
+ WL_ERR(("failed to get packets, ret:%d \n", ret));
7520
+ goto exit;
7521
+ }
7522
+
7523
+ mem_needed = VENDOR_REPLY_OVERHEAD + ATTRIBUTE_U32_LEN;
7524
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
7525
+ if (unlikely(!skb)) {
7526
+ WL_ERR(("skb alloc failed"));
7527
+ ret = -ENOMEM;
7528
+ goto exit;
7529
+ }
7530
+
7531
+ ret = nla_put_u32(skb, DEBUG_ATTRIBUTE_PKT_FATE_NUM, resp_count);
7532
+ if (ret < 0) {
7533
+ WL_ERR(("Failed to put DEBUG_ATTRIBUTE_PKT_FATE_NUM, ret:%d\n", ret));
7534
+ goto exit;
7535
+ }
7536
+
7537
+ ret = cfg80211_vendor_cmd_reply(skb);
7538
+ if (unlikely(ret)) {
7539
+ WL_ERR(("vendor Command reply failed ret:%d \n", ret));
7540
+ }
7541
+ return ret;
7542
+
7543
+exit:
7544
+ /* Free skb memory */
7545
+ if (skb) {
7546
+ kfree_skb(skb);
7547
+ }
7548
+ return ret;
7549
+}
7550
+
7551
+static int wl_cfgvendor_dbg_get_tx_pkt_fates(struct wiphy *wiphy,
7552
+ struct wireless_dev *wdev, const void *data, int len)
7553
+{
7554
+ int ret;
7555
+
7556
+ ret = __wl_cfgvendor_dbg_get_pkt_fates(wiphy, data, len,
7557
+ dhd_os_dbg_monitor_get_tx_pkts);
7558
+ if (unlikely(ret)) {
7559
+ WL_ERR(("failed to get tx packets, ret:%d \n", ret));
7560
+ }
7561
+
7562
+ return ret;
7563
+}
7564
+
7565
+static int wl_cfgvendor_dbg_get_rx_pkt_fates(struct wiphy *wiphy,
7566
+ struct wireless_dev *wdev, const void *data, int len)
7567
+{
7568
+ int ret;
7569
+
7570
+ ret = __wl_cfgvendor_dbg_get_pkt_fates(wiphy, data, len,
7571
+ dhd_os_dbg_monitor_get_rx_pkts);
7572
+ if (unlikely(ret)) {
7573
+ WL_ERR(("failed to get rx packets, ret:%d \n", ret));
7574
+ }
7575
+
7576
+ return ret;
7577
+}
7578
+#else
7579
+
7580
+static int wl_cfgvendor_dbg_start_pkt_fate_monitoring(struct wiphy *wiphy,
7581
+ struct wireless_dev *wdev, const void *data, int len)
7582
+{
7583
+ return WIFI_ERROR_NOT_SUPPORTED;
7584
+}
7585
+
7586
+static int wl_cfgvendor_dbg_get_tx_pkt_fates(struct wiphy *wiphy,
7587
+ struct wireless_dev *wdev, const void *data, int len)
7588
+{
7589
+ return WIFI_ERROR_NOT_SUPPORTED;
7590
+}
7591
+
7592
+static int wl_cfgvendor_dbg_get_rx_pkt_fates(struct wiphy *wiphy,
7593
+ struct wireless_dev *wdev, const void *data, int len)
7594
+{
7595
+ return WIFI_ERROR_NOT_SUPPORTED;
7596
+}
7597
+#endif /* DBG_PKT_MON */
7598
+
7599
+#ifdef KEEP_ALIVE
7600
+static int wl_cfgvendor_start_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev,
7601
+ const void *data, int len)
7602
+{
7603
+ /* max size of IP packet for keep alive */
7604
+ const int MKEEP_ALIVE_IP_PKT_MAX = 256;
7605
+
7606
+ int ret = BCME_OK, rem, type;
7607
+ uint8 mkeep_alive_id = 0;
7608
+ uint8 *ip_pkt = NULL;
7609
+ uint16 ip_pkt_len = 0;
7610
+ uint8 src_mac[ETHER_ADDR_LEN];
7611
+ uint8 dst_mac[ETHER_ADDR_LEN];
7612
+ uint32 period_msec = 0;
7613
+ const struct nlattr *iter;
7614
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7615
+ dhd_pub_t *dhd_pub = cfg->pub;
7616
+
7617
+ nla_for_each_attr(iter, data, len, rem) {
7618
+ type = nla_type(iter);
7619
+ switch (type) {
7620
+ case MKEEP_ALIVE_ATTRIBUTE_ID:
7621
+ mkeep_alive_id = nla_get_u8(iter);
7622
+ break;
7623
+ case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN:
7624
+ ip_pkt_len = nla_get_u16(iter);
7625
+ if (ip_pkt_len > MKEEP_ALIVE_IP_PKT_MAX) {
7626
+ ret = BCME_BADARG;
7627
+ goto exit;
7628
+ }
7629
+ break;
7630
+ case MKEEP_ALIVE_ATTRIBUTE_IP_PKT:
7631
+ if (ip_pkt) {
7632
+ ret = BCME_BADARG;
7633
+ WL_ERR(("ip_pkt already allocated\n"));
7634
+ goto exit;
7635
+ }
7636
+ if (!ip_pkt_len) {
7637
+ ret = BCME_BADARG;
7638
+ WL_ERR(("ip packet length is 0\n"));
7639
+ goto exit;
7640
+ }
7641
+ ip_pkt = (u8 *)MALLOCZ(cfg->osh, ip_pkt_len);
7642
+ if (ip_pkt == NULL) {
7643
+ ret = BCME_NOMEM;
7644
+ WL_ERR(("Failed to allocate mem for ip packet\n"));
7645
+ goto exit;
7646
+ }
7647
+ memcpy(ip_pkt, (u8*)nla_data(iter), ip_pkt_len);
7648
+ break;
7649
+ case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR:
7650
+ memcpy(src_mac, nla_data(iter), ETHER_ADDR_LEN);
7651
+ break;
7652
+ case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR:
7653
+ memcpy(dst_mac, nla_data(iter), ETHER_ADDR_LEN);
7654
+ break;
7655
+ case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC:
7656
+ period_msec = nla_get_u32(iter);
7657
+ break;
7658
+ default:
7659
+ WL_ERR(("Unknown type: %d\n", type));
7660
+ ret = BCME_BADARG;
7661
+ goto exit;
7662
+ }
7663
+ }
7664
+
7665
+ if (ip_pkt == NULL) {
7666
+ ret = BCME_BADARG;
7667
+ WL_ERR(("ip packet is NULL\n"));
7668
+ goto exit;
7669
+ }
7670
+
7671
+ ret = dhd_dev_start_mkeep_alive(dhd_pub, mkeep_alive_id, ip_pkt, ip_pkt_len, src_mac,
7672
+ dst_mac, period_msec);
7673
+ if (ret < 0) {
7674
+ WL_ERR(("start_mkeep_alive is failed ret: %d\n", ret));
7675
+ }
7676
+
7677
+exit:
7678
+ if (ip_pkt) {
7679
+ MFREE(cfg->osh, ip_pkt, ip_pkt_len);
7680
+ }
7681
+
7682
+ return ret;
7683
+}
7684
+
7685
+static int wl_cfgvendor_stop_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev,
7686
+ const void *data, int len)
7687
+{
7688
+ int ret = BCME_OK, rem, type;
7689
+ uint8 mkeep_alive_id = 0;
7690
+ const struct nlattr *iter;
7691
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7692
+ dhd_pub_t *dhd_pub = cfg->pub;
7693
+
7694
+ nla_for_each_attr(iter, data, len, rem) {
7695
+ type = nla_type(iter);
7696
+ switch (type) {
7697
+ case MKEEP_ALIVE_ATTRIBUTE_ID:
7698
+ mkeep_alive_id = nla_get_u8(iter);
7699
+ break;
7700
+ default:
7701
+ WL_ERR(("Unknown type: %d\n", type));
7702
+ ret = BCME_BADARG;
7703
+ break;
7704
+ }
7705
+ }
7706
+
7707
+ ret = dhd_dev_stop_mkeep_alive(dhd_pub, mkeep_alive_id);
7708
+ if (ret < 0) {
7709
+ WL_ERR(("stop_mkeep_alive is failed ret: %d\n", ret));
7710
+ }
7711
+
7712
+ return ret;
7713
+}
7714
+#endif /* KEEP_ALIVE */
7715
+
7716
+#if defined(PKT_FILTER_SUPPORT) && defined(APF)
7717
+static int
7718
+wl_cfgvendor_apf_get_capabilities(struct wiphy *wiphy,
7719
+ struct wireless_dev *wdev, const void *data, int len)
7720
+{
7721
+ struct net_device *ndev = wdev_to_ndev(wdev);
7722
+ struct sk_buff *skb = NULL;
7723
+ int ret, ver, max_len, mem_needed;
7724
+
7725
+ /* APF version */
7726
+ ver = 0;
7727
+ ret = dhd_dev_apf_get_version(ndev, &ver);
7728
+ if (unlikely(ret)) {
7729
+ WL_ERR(("APF get version failed, ret=%d\n", ret));
7730
+ return ret;
7731
+ }
7732
+
7733
+ /* APF memory size limit */
7734
+ max_len = 0;
7735
+ ret = dhd_dev_apf_get_max_len(ndev, &max_len);
7736
+ if (unlikely(ret)) {
7737
+ WL_ERR(("APF get maximum length failed, ret=%d\n", ret));
7738
+ return ret;
7739
+ }
7740
+
7741
+ mem_needed = VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * 2);
7742
+
7743
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
7744
+ if (unlikely(!skb)) {
7745
+ WL_ERR(("%s: can't allocate %d bytes\n", __FUNCTION__, mem_needed));
7746
+ return -ENOMEM;
7747
+ }
7748
+
7749
+ ret = nla_put_u32(skb, APF_ATTRIBUTE_VERSION, ver);
7750
+ if (ret < 0) {
7751
+ WL_ERR(("Failed to put APF_ATTRIBUTE_VERSION, ret:%d\n", ret));
7752
+ goto exit;
7753
+ }
7754
+ ret = nla_put_u32(skb, APF_ATTRIBUTE_MAX_LEN, max_len);
7755
+ if (ret < 0) {
7756
+ WL_ERR(("Failed to put APF_ATTRIBUTE_MAX_LEN, ret:%d\n", ret));
7757
+ goto exit;
7758
+ }
7759
+
7760
+ ret = cfg80211_vendor_cmd_reply(skb);
7761
+ if (unlikely(ret)) {
7762
+ WL_ERR(("vendor command reply failed, ret=%d\n", ret));
7763
+ }
7764
+ return ret;
7765
+exit:
7766
+ /* Free skb memory */
7767
+ kfree_skb(skb);
7768
+ return ret;
7769
+}
7770
+
7771
+static int
7772
+wl_cfgvendor_apf_set_filter(struct wiphy *wiphy,
7773
+ struct wireless_dev *wdev, const void *data, int len)
7774
+{
7775
+ struct net_device *ndev = wdev_to_ndev(wdev);
7776
+ const struct nlattr *iter;
7777
+ u8 *program = NULL;
7778
+ u32 program_len = 0;
7779
+ int ret, tmp, type;
7780
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7781
+
7782
+ if (len <= 0) {
7783
+ WL_ERR(("Invalid len: %d\n", len));
7784
+ ret = -EINVAL;
7785
+ goto exit;
7786
+ }
7787
+ nla_for_each_attr(iter, data, len, tmp) {
7788
+ type = nla_type(iter);
7789
+ switch (type) {
7790
+ case APF_ATTRIBUTE_PROGRAM_LEN:
7791
+ /* check if the iter value is valid and program_len
7792
+ * is not already initialized.
7793
+ */
7794
+ if (nla_len(iter) == sizeof(uint32) && !program_len) {
7795
+ program_len = nla_get_u32(iter);
7796
+ } else {
7797
+ ret = -EINVAL;
7798
+ goto exit;
7799
+ }
7800
+
7801
+ if (program_len > WL_APF_PROGRAM_MAX_SIZE) {
7802
+ WL_ERR(("program len is more than expected len\n"));
7803
+ ret = -EINVAL;
7804
+ goto exit;
7805
+ }
7806
+
7807
+ if (unlikely(!program_len)) {
7808
+ WL_ERR(("zero program length\n"));
7809
+ ret = -EINVAL;
7810
+ goto exit;
7811
+ }
7812
+ break;
7813
+ case APF_ATTRIBUTE_PROGRAM:
7814
+ if (unlikely(program)) {
7815
+ WL_ERR(("program already allocated\n"));
7816
+ ret = -EINVAL;
7817
+ goto exit;
7818
+ }
7819
+ if (unlikely(!program_len)) {
7820
+ WL_ERR(("program len is not set\n"));
7821
+ ret = -EINVAL;
7822
+ goto exit;
7823
+ }
7824
+ if (nla_len(iter) != program_len) {
7825
+ WL_ERR(("program_len is not same\n"));
7826
+ ret = -EINVAL;
7827
+ goto exit;
7828
+ }
7829
+ program = MALLOCZ(cfg->osh, program_len);
7830
+ if (unlikely(!program)) {
7831
+ WL_ERR(("%s: can't allocate %d bytes\n",
7832
+ __FUNCTION__, program_len));
7833
+ ret = -ENOMEM;
7834
+ goto exit;
7835
+ }
7836
+ memcpy(program, (u8*)nla_data(iter), program_len);
7837
+ break;
7838
+ default:
7839
+ WL_ERR(("%s: no such attribute %d\n", __FUNCTION__, type));
7840
+ ret = -EINVAL;
7841
+ goto exit;
7842
+ }
7843
+ }
7844
+
7845
+ ret = dhd_dev_apf_add_filter(ndev, program, program_len);
7846
+
7847
+exit:
7848
+ if (program) {
7849
+ MFREE(cfg->osh, program, program_len);
7850
+ }
7851
+ return ret;
7852
+}
7853
+#endif /* PKT_FILTER_SUPPORT && APF */
7854
+
7855
+#ifdef NDO_CONFIG_SUPPORT
7856
+static int wl_cfgvendor_configure_nd_offload(struct wiphy *wiphy,
7857
+ struct wireless_dev *wdev, const void *data, int len)
7858
+{
7859
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7860
+ const struct nlattr *iter;
7861
+ int ret = BCME_OK, rem, type;
7862
+ u8 enable = 0;
7863
+ dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
7864
+
7865
+ if (dhdp && !FW_SUPPORTED(dhdp, ndoe)) {
7866
+ ret = WIFI_ERROR_NOT_SUPPORTED;
7867
+ goto exit;
7868
+ }
7869
+
7870
+ nla_for_each_attr(iter, data, len, rem) {
7871
+ type = nla_type(iter);
7872
+ switch (type) {
7873
+ case ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE:
7874
+ enable = nla_get_u8(iter);
7875
+ break;
7876
+ default:
7877
+ WL_ERR(("Unknown type: %d\n", type));
7878
+ ret = BCME_BADARG;
7879
+ goto exit;
7880
+ }
7881
+ }
7882
+
7883
+ ret = dhd_dev_ndo_cfg(bcmcfg_to_prmry_ndev(cfg), enable);
7884
+ if (ret < 0) {
7885
+ WL_ERR(("dhd_dev_ndo_cfg() failed: %d\n", ret));
7886
+ }
7887
+
7888
+exit:
7889
+ return ret;
7890
+}
7891
+#else
7892
+static int wl_cfgvendor_configure_nd_offload(struct wiphy *wiphy,
7893
+ struct wireless_dev *wdev, const void *data, int len)
7894
+{
7895
+ return WIFI_ERROR_NOT_SUPPORTED;
7896
+}
7897
+#endif /* NDO_CONFIG_SUPPORT */
7898
+
7899
+/* for kernel >= 4.13 NL80211 wl_cfg80211_set_pmk have to be used. */
7900
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0))
7901
+static int wl_cfgvendor_set_pmk(struct wiphy *wiphy,
7902
+ struct wireless_dev *wdev, const void *data, int len)
7903
+{
7904
+ int ret = 0;
7905
+ wsec_pmk_t pmk;
7906
+ const struct nlattr *iter;
7907
+ int rem, type;
7908
+ struct net_device *ndev = wdev_to_ndev(wdev);
7909
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7910
+ struct wl_security *sec;
7911
+
7912
+ nla_for_each_attr(iter, data, len, rem) {
7913
+ type = nla_type(iter);
7914
+ switch (type) {
7915
+ case BRCM_ATTR_DRIVER_KEY_PMK:
7916
+ if (nla_len(iter) > sizeof(pmk.key)) {
7917
+ ret = -EINVAL;
7918
+ goto exit;
7919
+ }
7920
+ pmk.flags = 0;
7921
+ pmk.key_len = htod16(nla_len(iter));
7922
+ bcopy((uint8 *)nla_data(iter), pmk.key, len);
7923
+ break;
7924
+ default:
7925
+ WL_ERR(("Unknown type: %d\n", type));
7926
+ ret = BCME_BADARG;
7927
+ goto exit;
7928
+ }
7929
+ }
7930
+
7931
+ sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
7932
+ if ((sec->wpa_auth == WLAN_AKM_SUITE_8021X) ||
7933
+ (sec->wpa_auth == WL_AKM_SUITE_SHA256_1X)) {
7934
+ ret = wldev_iovar_setbuf(ndev, "okc_info_pmk", pmk.key, pmk.key_len, cfg->ioctl_buf,
7935
+ WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
7936
+ if (ret) {
7937
+ /* could fail in case that 'okc' is not supported */
7938
+ WL_INFORM_MEM(("okc_info_pmk failed, err=%d (ignore)\n", ret));
7939
+ }
7940
+ }
7941
+
7942
+ ret = wldev_ioctl_set(ndev, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk));
7943
+ WL_INFORM_MEM(("IOVAR set_pmk ret:%d", ret));
7944
+exit:
7945
+ return ret;
7946
+}
7947
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) */
7948
+
7949
+static int wl_cfgvendor_get_driver_feature(struct wiphy *wiphy,
7950
+ struct wireless_dev *wdev, const void *data, int len)
7951
+{
7952
+ int ret = BCME_OK;
7953
+ u8 supported[(BRCM_WLAN_VENDOR_FEATURES_MAX / 8) + 1] = {0};
7954
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7955
+ dhd_pub_t *dhd_pub = cfg->pub;
7956
+ struct sk_buff *skb;
7957
+ int32 mem_needed;
7958
+
7959
+ mem_needed = VENDOR_REPLY_OVERHEAD + NLA_HDRLEN + sizeof(supported);
7960
+
7961
+ BCM_REFERENCE(dhd_pub);
7962
+
7963
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0))
7964
+ if (FW_SUPPORTED(dhd_pub, idsup)) {
7965
+ ret = wl_features_set(supported, sizeof(supported),
7966
+ BRCM_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
7967
+ }
7968
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) */
7969
+
7970
+ /* Alloc the SKB for vendor_event */
7971
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
7972
+ if (unlikely(!skb)) {
7973
+ WL_ERR(("skb alloc failed"));
7974
+ ret = BCME_NOMEM;
7975
+ goto exit;
7976
+ }
7977
+
7978
+ ret = nla_put(skb, BRCM_ATTR_DRIVER_FEATURE_FLAGS, sizeof(supported), supported);
7979
+ if (ret) {
7980
+ kfree_skb(skb);
7981
+ goto exit;
7982
+ }
7983
+ ret = cfg80211_vendor_cmd_reply(skb);
7984
+exit:
7985
+ return ret;
7986
+}
7987
+
7988
+static int
7989
+wl_cfgvendor_set_multista_primary_connection(struct wiphy *wiphy,
7990
+ struct wireless_dev *wdev, const void *data, int len)
7991
+{
7992
+ return WIFI_ERROR_NOT_SUPPORTED;
7993
+}
7994
+
7995
+static int
7996
+wl_cfgvendor_set_multista_use_case(struct wiphy *wiphy,
7997
+ struct wireless_dev *wdev, const void *data, int len)
7998
+{
7999
+ return WIFI_ERROR_NOT_SUPPORTED;
8000
+}
8001
+
8002
+#ifdef WL_SUPPORT_ACS_OFFLOAD
8003
+
8004
+#define ACS_OFFLOAD_DELAY 50
8005
+#define ACS_OFFLOAD_BUF_SIZE 1024
8006
+#define ACS_MAX_RETRY 10
8007
+#define ACS_OFFLOAD_DEFAULT_CH_2G 6
8008
+#define ACS_OFFLOAD_DEFAULT_CH_5G 149
8009
+
8010
+typedef struct acs_offload_report {
8011
+ u32 primary_freq;
8012
+ u32 second_freq;
8013
+ u16 ch_width;
8014
+ u8 vht_seg0_center;
8015
+ u8 vht_seg1_center;
8016
+ enum hostapd_hw_mode hw_mode;
8017
+}acs_offload_report_t;
8018
+
8019
+static int
8020
+wl_cfgvendor_acs_offload_report(acs_offload_work_t *acs_offload,
8021
+ acs_offload_report_t *report) {
8022
+ chanspec_t chspec = 0;
8023
+
8024
+ u32 ctl_freq, ctl_ch, bw, sb, band;
8025
+
8026
+ if (!acs_offload || !report) {
8027
+ WL_ERR(("ACS: failed %p, %p\n",acs_offload, report));
8028
+ return BCME_BADARG;
8029
+ }
8030
+
8031
+ /* if chanspec is invalid, changing to default */
8032
+ if (!wf_chspec_valid(acs_offload->selected)) {
8033
+ int channel = 0;
8034
+ int bw = WL_CHANSPEC_BW_20;
8035
+ if (acs_offload->parameter.band == WLC_BAND_2G) {
8036
+ channel = ACS_OFFLOAD_DEFAULT_CH_2G;
8037
+ bw = WL_CHANSPEC_BW_20;
8038
+ }
8039
+ else {
8040
+ channel = ACS_OFFLOAD_DEFAULT_CH_5G;
8041
+ if (acs_offload->parameter.ch_width == 80)
8042
+ bw = WL_CHANSPEC_BW_80;
8043
+ else if (acs_offload->parameter.ch_width == 40)
8044
+ bw = WL_CHANSPEC_BW_40;
8045
+ }
8046
+ chspec = wf_channel2chspec(channel, bw);
8047
+
8048
+ WL_ERR(("ACS: %x is wrong chanspec, changing to default %x\n",
8049
+ acs_offload->selected, chspec));
8050
+ }
8051
+ else
8052
+ chspec = acs_offload->selected;
8053
+
8054
+ bzero(report, sizeof(acs_offload_report_t));
8055
+
8056
+ band = CHSPEC_BAND(chspec);
8057
+ if (band == WL_CHANSPEC_BAND_2G)
8058
+ report->hw_mode = HOSTAPD_MODE_IEEE80211G;
8059
+ else
8060
+ report->hw_mode = HOSTAPD_MODE_IEEE80211A;
8061
+
8062
+ ctl_ch = wf_chspec_ctlchan(chspec);
8063
+ ctl_freq = ieee80211_channel_to_frequency( ctl_ch,
8064
+ (band==WL_CHANSPEC_BAND_2G)?IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ);
8065
+ bw = CHSPEC_BW(chspec);
8066
+ sb = CHSPEC_CTL_SB(chspec);
8067
+
8068
+ WL_ERR(("ACS: ctl_freq=%d, center_ch=%d, band=0x%X, bw=0x%X, sb=0x%X\n",
8069
+ ctl_freq, ctl_ch, band, bw, sb));
8070
+
8071
+ report->ch_width = bw;
8072
+ switch(bw) {
8073
+ case WL_CHANSPEC_BW_80:
8074
+ if (acs_offload->parameter.vht_enabled && acs_offload->parameter.ch_width == 80) {
8075
+ report->ch_width = 80;
8076
+ ctl_ch = wf_chspec_primary80_channel(chspec);
8077
+ if (ctl_ch == INVCHANNEL){
8078
+ report->ch_width = 0;
8079
+ break;
8080
+ }
8081
+ report->vht_seg0_center = ctl_ch;
8082
+ report->vht_seg1_center = 0;
8083
+ switch(sb) {
8084
+ case WL_CHANSPEC_CTL_SB_LL:
8085
+ case WL_CHANSPEC_CTL_SB_LU:
8086
+ report->primary_freq = ctl_freq;
8087
+ report->second_freq = ctl_freq + 20;
8088
+ break;
8089
+ case WL_CHANSPEC_CTL_SB_UL:
8090
+ case WL_CHANSPEC_CTL_SB_UU:
8091
+ report->primary_freq = ctl_freq;
8092
+ report->second_freq = ctl_freq - 20;
8093
+ default:
8094
+ report->ch_width = 0;
8095
+ break;
8096
+ }
8097
+ break;
8098
+ }
8099
+ case WL_CHANSPEC_BW_40:
8100
+ if (acs_offload->parameter.ht40_enabled) {
8101
+ report->ch_width = 40;
8102
+ switch(sb) {
8103
+ case WL_CHANSPEC_CTL_SB_U:
8104
+ report->primary_freq = ctl_freq;
8105
+ report->second_freq = ctl_freq - 20;
8106
+ break;
8107
+ case WL_CHANSPEC_CTL_SB_L:
8108
+ report->primary_freq = ctl_freq;
8109
+ report->second_freq = ctl_freq + 20;
8110
+ break;
8111
+ default :
8112
+ report->ch_width = 0;
8113
+ break;
8114
+ }
8115
+ }
8116
+ break;
8117
+ default :
8118
+ report->ch_width = 20;
8119
+ report->primary_freq = ctl_freq;
8120
+ report->second_freq = 0;
8121
+ }
8122
+
8123
+ if (!report->ch_width) {
8124
+ ctl_ch = wf_chspec_ctlchan(chspec);
8125
+ report->primary_freq = ctl_freq;
8126
+ report->second_freq = 0;
8127
+ report->ch_width = 20;
8128
+ }
8129
+ WL_ERR(("ACS: report pri = %d, sec = %d, width = %d, vht_seg0 = %d, vht_seg1 = %d\n",
8130
+ report->primary_freq, report->second_freq, report->ch_width,
8131
+ report->vht_seg0_center, report->vht_seg1_center));
8132
+
8133
+ return BCME_OK;
8134
+}
8135
+
8136
+static void
8137
+wl_cfgvendor_acs_offload_deinit(acs_offload_work_t *acs_offload) {
8138
+ if (acs_offload) {
8139
+ drv_acs_offload_params_t *params = &acs_offload->parameter;
8140
+ if (params->channels) {
8141
+ kfree(params->channels);
8142
+ }
8143
+ acs_offload->selected = 0;
8144
+ cancel_delayed_work_sync(&acs_offload->work);
8145
+ kfree(acs_offload);
8146
+ }
8147
+}
8148
+
8149
+static void wl_cfgvendor_acs_offload_work_handler(struct work_struct *work) {
8150
+ acs_offload_work_t *acs_offload = (acs_offload_work_t *)work;
8151
+ struct net_device *ndev = acs_offload->ndev;
8152
+ struct wireless_dev *wdev = NULL;
8153
+ struct wiphy *wiphy = NULL;
8154
+ gfp_t kflags;
8155
+ struct sk_buff *msg = NULL;
8156
+ int ret = BCME_OK;
8157
+ int len = 0;
8158
+ acs_offload_report_t report={0x00, };
8159
+
8160
+ do {
8161
+ if (!acs_offload) {
8162
+ ret = BCME_BADARG;
8163
+ break;
8164
+ }
8165
+
8166
+ wdev = acs_offload->wdev;
8167
+ if (!wdev) {
8168
+ ret = BCME_BADARG;
8169
+ break;
8170
+ }
8171
+
8172
+ ndev = wdev_to_ndev(wdev);
8173
+
8174
+ if (!ndev || !ndev->ieee80211_ptr || !ndev->ieee80211_ptr->wiphy) {
8175
+ ret = BCME_BADARG;
8176
+ break;
8177
+ }
8178
+
8179
+ wiphy = ndev->ieee80211_ptr->wiphy;
8180
+
8181
+ if (wl_cfgvendor_acs_offload_report(acs_offload, &report) != BCME_OK)
8182
+ break;
8183
+
8184
+ len = sizeof(acs_offload_report_t);
8185
+ kflags = in_atomic()? GFP_ATOMIC:GFP_KERNEL;
8186
+
8187
+ msg = CFG80211_VENDOR_EVENT_ALLOC(wiphy, wdev, len, BRCM_VENDOR_EVENT_ACS, kflags);
8188
+ if (!msg) {
8189
+ ret = BCME_NOMEM;
8190
+ WL_ERR(("ACS: Failed :: not enough memory\n"));
8191
+ break;
8192
+ }
8193
+
8194
+ ret = nla_put_u32(msg, BRCM_VENDOR_ATTR_ACS_PRIMARY_FREQ, report.primary_freq);
8195
+ if (ret < 0) {
8196
+ WL_ERR(("ACS: Failed to put BRCM_VENDOR_ATTR_ACS_PRIMARY_FREQ : %d\n", ret));
8197
+ break;
8198
+ }
8199
+ ret = nla_put_u32(msg, BRCM_VENDOR_ATTR_ACS_SECONDARY_FREQ, report.second_freq);
8200
+ if (ret < 0) {
8201
+ WL_ERR(("ACS: Failed to put BRCM_VENDOR_ATTR_ACS_SECONDARY_FREQ : %d\n", ret));
8202
+ break;
8203
+ }
8204
+ ret = nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL, report.vht_seg0_center);
8205
+ if (ret < 0) {
8206
+ WL_ERR(("ACS: Failed to put BRCM_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL : %d\n", ret));
8207
+ break;
8208
+ }
8209
+ ret = nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL, report.vht_seg1_center);
8210
+ if (ret < 0) {
8211
+ WL_ERR(("ACS: Failed to put BRCM_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL : %d\n", ret));
8212
+ break;
8213
+ }
8214
+ ret = nla_put_u16(msg, BRCM_VENDOR_ATTR_ACS_CHWIDTH, report.ch_width);
8215
+ if (ret < 0) {
8216
+ WL_ERR(("ACS: Failed to put BRCM_VENDOR_ATTR_ACS_CHWIDTH : %d\n", ret));
8217
+ break;
8218
+ }
8219
+ ret = nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HW_MODE, report.hw_mode);
8220
+ if (ret < 0) {
8221
+ WL_ERR(("ACS: Failed to put BRCM_VENDOR_ATTR_ACS_HW_MODE : %d\n", ret));
8222
+ break;
8223
+ }
8224
+
8225
+ cfg80211_vendor_event(msg, kflags);
8226
+ }while(0);
8227
+
8228
+ if (ret < 0) {
8229
+ WL_ERR(("ACS: failed : %d\n", ret));
8230
+ if (msg){
8231
+ dev_kfree_skb_any(msg);
8232
+ }
8233
+ }
8234
+}
8235
+
8236
+static int
8237
+wl_cfgvendor_acs_offload_init(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev) {
8238
+ gfp_t kflags;
8239
+ acs_offload_work_t *acs = NULL;
8240
+
8241
+ kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
8242
+ if (!cfg->acs_offload) {
8243
+ cfg->acs_offload = kzalloc(sizeof(acs_offload_work_t), kflags);
8244
+ if (!cfg->acs_offload) {
8245
+ WL_ERR(("ACS: Failed to allocate acs_offload\n"));
8246
+ return BCME_NOMEM;
8247
+ }
8248
+ }
8249
+ else
8250
+ cancel_delayed_work_sync(&cfg->acs_offload->work);
8251
+
8252
+ acs = cfg->acs_offload;
8253
+ acs->selected = 0;
8254
+ acs->wdev = wdev;
8255
+ INIT_DELAYED_WORK(&acs->work, wl_cfgvendor_acs_offload_work_handler);
8256
+ return BCME_OK;
8257
+}
8258
+
8259
+static int
8260
+wl_cfgvendor_acs_offload(struct wiphy *wiphy,
8261
+ struct wireless_dev *wdev, const void *data, int len)
8262
+{
8263
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8264
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
8265
+ drv_acs_offload_params_t *params = NULL;
8266
+ const struct nlattr *iter;
8267
+ wl_uint32_list_t *list;
8268
+
8269
+ void *buf = NULL;
8270
+ int rem, type, i;
8271
+ int ret=BCME_OK;
8272
+ int chosen = 0, retry=0, buflen=0;
8273
+ int selected = 0, bw = 0;
8274
+ int spect = 0;
8275
+
8276
+ if (wl_cfgvendor_acs_offload_init(cfg, wdev) != BCME_OK)
8277
+ goto failed;
8278
+
8279
+ params = &cfg->acs_offload->parameter;
8280
+
8281
+ /* the structure reassembly */
8282
+ nla_for_each_attr(iter, data, len, rem) {
8283
+ type = nla_type(iter);
8284
+ switch(type) {
8285
+ case BRCM_VENDOR_ATTR_ACS_HW_MODE:
8286
+ params->hw_mode = nla_get_u8(iter);
8287
+ switch (params->hw_mode) {
8288
+ case HOSTAPD_MODE_IEEE80211B:
8289
+ case HOSTAPD_MODE_IEEE80211G:
8290
+ params->band = WLC_BAND_2G;
8291
+ break;
8292
+ case HOSTAPD_MODE_IEEE80211A:
8293
+ params->band = WLC_BAND_5G;
8294
+ break;
8295
+ case HOSTAPD_MODE_IEEE80211ANY:
8296
+ params->band = WLC_BAND_AUTO;
8297
+ break;
8298
+ default :
8299
+ params->band = WLC_BAND_INVALID;
8300
+ break;
8301
+ };
8302
+ break;
8303
+ case BRCM_VENDOR_ATTR_ACS_HT_ENABLED:
8304
+ params->ht_enabled = nla_get_u8(iter);
8305
+ break;
8306
+ case BRCM_VENDOR_ATTR_ACS_HT40_ENABLED:
8307
+ params->ht40_enabled = nla_get_u8(iter);
8308
+ break;
8309
+ case BRCM_VENDOR_ATTR_ACS_VHT_ENABLED:
8310
+ params->vht_enabled = nla_get_u8(iter);
8311
+ break;
8312
+ case BRCM_VENDOR_ATTR_ACS_CHWIDTH:
8313
+ params->ch_width = nla_get_u16(iter);
8314
+ break;
8315
+ case BRCM_VENDOR_ATTR_ACS_FREQ_LIST:
8316
+ if (nla_len(iter)) {
8317
+ params->channels = kzalloc(nla_len(iter), GFP_KERNEL);
8318
+ bcopy((uint8 *)nla_data(iter), params->channels,
8319
+ nla_len(iter));
8320
+ params->chan_cnt = nla_len(iter) / sizeof(int);
8321
+ }
8322
+ break;
8323
+ }
8324
+ }
8325
+
8326
+ WL_INFORM_MEM(("ACS: hw_mode=%d, band=%d ht_enabled:%d,%d vht_enabled:%d ch_width:%d ch_cnt:%d\n",
8327
+ params->hw_mode, params->band, params->ht_enabled , params->ht40_enabled,
8328
+ params->vht_enabled, params->ch_width, params->chan_cnt));
8329
+
8330
+ /* if band of station and band for acs are same, use same chanspec to make SCC */
8331
+ if ( wl_cfg80211_get_sta_channel(cfg) ) {
8332
+ int chsp;
8333
+ chanspec_t chspec;
8334
+
8335
+ ret = wldev_iovar_getint(ndev, "chanspec", &chsp);
8336
+
8337
+ if (ret != BCME_OK) {
8338
+ WL_ERR(("Failed to get chanspec : %d\n", ret));
8339
+ goto failed;
8340
+ }
8341
+ chspec = wl_chspec_driver_to_host(chsp);
8342
+
8343
+ if( (CHSPEC_IS2G(chspec) && params->band == WLC_BAND_2G) ||
8344
+ (CHSPEC_IS5G(chspec) && params->band == WLC_BAND_5G)) {
8345
+ cfg->acs_offload->selected = chspec;
8346
+ goto done;
8347
+ }
8348
+ }
8349
+
8350
+ /* Convert frequency to channel */
8351
+
8352
+ for (i=0;i<params->chan_cnt;++i){
8353
+ params->channels[i] = ieee80211_frequency_to_channel(params->channels[i]);
8354
+ }
8355
+
8356
+ buf = (u8 *)kzalloc(ACS_OFFLOAD_BUF_SIZE, GFP_KERNEL);
8357
+ list = (wl_uint32_list_t *)buf;
8358
+
8359
+ for(i = 0;i<params->chan_cnt;++i) {
8360
+ list->element[i] = wl_ch_host_to_driver(params->channels[i]);
8361
+ }
8362
+
8363
+ ret = wldev_ioctl_get(ndev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect));
8364
+ if (ret) {
8365
+ WL_ERR(("ACS: error getting the spect, ret = %d\n",ret));
8366
+ goto failed;
8367
+ }
8368
+
8369
+ if (spect > 0) {
8370
+ ret = wl_cfg80211_set_spect(ndev, 0);
8371
+ if (ret) {
8372
+ WL_ERR(("ACS: error setting the spect, ret = %d\n",ret));
8373
+ goto failed;
8374
+ }
8375
+ }
8376
+
8377
+ buflen = sizeof(uint32) * (list->count + 1);
8378
+ ret = wldev_ioctl_set(ndev, WLC_START_CHANNEL_SEL, (void *)buf, buflen);
8379
+ if (ret < 0) {
8380
+ WL_ERR(("ACS: can't start ACS, err = %d\n", ret));
8381
+ selected = 0;
8382
+ }
8383
+
8384
+ if (params->band == WLC_BAND_AUTO)
8385
+ OSL_SLEEP(1000);
8386
+ else
8387
+ OSL_SLEEP(500);
8388
+
8389
+ retry = ACS_MAX_RETRY;
8390
+ while (retry--) {
8391
+ ret = wldev_ioctl_get(ndev, WLC_GET_CHANNEL_SEL, &chosen,
8392
+ sizeof(chosen));
8393
+ if (ret < 0) {
8394
+ chosen = 0;
8395
+ } else {
8396
+ chosen = dtoh32(chosen);
8397
+ }
8398
+
8399
+ if (chosen) {
8400
+ selected = CHSPEC_CHANNEL((chanspec_t)chosen);
8401
+ WL_ERR(("ACS: Got the acs chan : %d\n",selected));
8402
+ break;
8403
+ }
8404
+ OSL_SLEEP(250);
8405
+ };
8406
+
8407
+ if (spect > 0) {
8408
+ ret = wl_cfg80211_set_spect(ndev, spect);
8409
+ if (ret) {
8410
+ WL_ERR(("ACS: error restoring the spect, ret = %d\n",ret));
8411
+ goto failed;
8412
+ }
8413
+ }
8414
+ goto done;
8415
+failed:
8416
+ if (params->chan_cnt) {
8417
+ kfree(params->channels);
8418
+ params->channels = NULL;
8419
+ params->chan_cnt = 0;
8420
+ }
8421
+
8422
+ if (params->band == WLC_BAND_2G)
8423
+ selected = ACS_OFFLOAD_DEFAULT_CH_2G;
8424
+ else {
8425
+ selected = ACS_OFFLOAD_DEFAULT_CH_5G;
8426
+
8427
+done:
8428
+ if (buf)
8429
+ kfree(buf);
8430
+ if (!cfg->acs_offload->selected) {
8431
+ bw = ACS_OFFLOAD_DEFAULT_CH_2G;
8432
+ if (params->ch_width == 80)
8433
+ bw = WL_CHANSPEC_BW_80;
8434
+ else if (params->ch_width == 40)
8435
+ bw = WL_CHANSPEC_BW_40;
8436
+ }
8437
+ cfg->acs_offload->selected = wf_channel2chspec(selected, bw);
8438
+ }
8439
+
8440
+ cfg->acs_offload->ndev = ndev;
8441
+
8442
+ schedule_delayed_work(&cfg->acs_offload->work,
8443
+ msecs_to_jiffies((const unsigned int)ACS_OFFLOAD_DELAY));
8444
+
8445
+ return ret;
8446
+}
8447
+#endif // endif
8448
+
8449
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
8450
+#define WL_VENDOR_POLICY_RAW_DATA .policy = VENDOR_CMD_RAW_DATA
8451
+
8452
+const struct nla_policy brcm_drv_attr_policy[BRCM_ATTR_DRIVER_MAX] = {
8453
+ [BRCM_ATTR_DRIVER_CMD] = {.type = NLA_NUL_STRING},
8454
+ [BRCM_ATTR_DRIVER_KEY_PMK] = {.type = NLA_BINARY},
8455
+};
8456
+
8457
+const struct nla_policy andr_wifi_attr_policy[ANDR_WIFI_ATTRIBUTE_MAX] = {
8458
+ [ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET] = {.type = NLA_U32},
8459
+ [ANDR_WIFI_ATTRIBUTE_FEATURE_SET] = {.type = NLA_U32},
8460
+ [ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI] = {.type = NLA_NUL_STRING, .len = 3},
8461
+ [ANDR_WIFI_ATTRIBUTE_NODFS_SET] = {.type = NLA_U32},
8462
+ [ANDR_WIFI_ATTRIBUTE_COUNTRY] = {.type = NLA_NUL_STRING, .len = 3},
8463
+ [ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE] = {.type = NLA_U8},
8464
+ [ANDR_WIFI_ATTRIBUTE_TCPACK_SUP_VALUE] = {.type = NLA_U32},
8465
+ [ANDR_WIFI_ATTRIBUTE_LATENCY_MODE] = {.type = NLA_U32},
8466
+ [ANDR_WIFI_ATTRIBUTE_RANDOM_MAC] = {.type = NLA_U32},
8467
+ [ANDR_WIFI_ATTRIBUTE_TX_POWER_SCENARIO] = {.type = NLA_S8},
8468
+ [ANDR_WIFI_ATTRIBUTE_THERMAL_MITIGATION] = {.type = NLA_S8},
8469
+ [ANDR_WIFI_ATTRIBUTE_THERMAL_COMPLETION_WINDOW] = {.type = NLA_U32},
8470
+ [ANDR_WIFI_ATTRIBUTE_VOIP_MODE] = {.type = NLA_U32},
8471
+ [ANDR_WIFI_ATTRIBUTE_DTIM_MULTIPLIER] = {.type = NLA_U32},
8472
+};
8473
+#ifdef DHD_WAKE_STATUS
8474
+const struct nla_policy wake_stat_attr_policy[WAKE_STAT_ATTRIBUTE_MAX] = {
8475
+ [WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT] = {.type = NLA_U32},
8476
+ [WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE] = {.type = NLA_BINARY},
8477
+ [WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT] = {.type = NLA_U32},
8478
+ [WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT_USED] = {.type = NLA_U32},
8479
+ [WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW] = {.type = NLA_U32},
8480
+ [WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE] = {.type = NLA_U32},
8481
+ [WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT] = {.type = NLA_U32},
8482
+ [WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT_USED] = {.type = NLA_U32},
8483
+ [WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE] = {.type = NLA_U32},
8484
+ [WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT] = {.type = NLA_U32},
8485
+ [WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT] = {.type = NLA_U32},
8486
+ [WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT] = {.type = NLA_U32},
8487
+ [WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT] = {.type = NLA_U32},
8488
+ [WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT] = {.type = NLA_U32},
8489
+ [WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA] = {.type = NLA_U32},
8490
+ [WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA] = {.type = NLA_U32},
8491
+ [WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS] = {.type = NLA_U32},
8492
+ [WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT] = {.type = NLA_U32},
8493
+ [WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT] = {.type = NLA_U32},
8494
+ [WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT] = {.type = NLA_U32},
8495
+ [WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO] = {.type = NLA_NESTED},
8496
+};
8497
+#endif /* DHD_WAKE_STATUS */
8498
+
8499
+const struct nla_policy gscan_attr_policy[GSCAN_ATTRIBUTE_MAX] = {
8500
+ [GSCAN_ATTRIBUTE_BAND] = {.type = NLA_U32},
8501
+ [GSCAN_ATTRIBUTE_NUM_CHANNELS] = {.type = NLA_U32},
8502
+ [GSCAN_ATTRIBUTE_CHANNEL_LIST] = {.type = NLA_BINARY},
8503
+ [GSCAN_ATTRIBUTE_WHITELIST_SSID] = {.type = NLA_BINARY},
8504
+ [GSCAN_ATTRIBUTE_NUM_WL_SSID] = {.type = NLA_U32},
8505
+ [GSCAN_ATTRIBUTE_WL_SSID_LEN] = {.type = NLA_U32},
8506
+ [GSCAN_ATTRIBUTE_WL_SSID_FLUSH] = {.type = NLA_U32},
8507
+ [GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM] = {.type = NLA_NESTED},
8508
+ [GSCAN_ATTRIBUTE_NUM_BSSID] = {.type = NLA_U32},
8509
+ [GSCAN_ATTRIBUTE_BSSID_PREF_LIST] = {.type = NLA_NESTED},
8510
+ [GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH] = {.type = NLA_U32},
8511
+ [GSCAN_ATTRIBUTE_BSSID_PREF] = {.type = NLA_BINARY, .len = ETH_ALEN},
8512
+ [GSCAN_ATTRIBUTE_RSSI_MODIFIER] = {.type = NLA_U32},
8513
+ [GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH] = {.type = NLA_U32},
8514
+ [GSCAN_ATTRIBUTE_BLACKLIST_BSSID] = {.type = NLA_BINARY, .len = ETH_ALEN},
8515
+ [GSCAN_ATTRIBUTE_ROAM_STATE_SET] = {.type = NLA_U32},
8516
+};
8517
+
8518
+const struct nla_policy debug_attr_policy[DEBUG_ATTRIBUTE_MAX] = {
8519
+ [DEBUG_ATTRIBUTE_GET_DRIVER] = {.type = NLA_BINARY},
8520
+ [DEBUG_ATTRIBUTE_GET_FW] = {.type = NLA_BINARY},
8521
+ [DEBUG_ATTRIBUTE_RING_ID] = {.type = NLA_U32},
8522
+ [DEBUG_ATTRIBUTE_RING_NAME] = {.type = NLA_NUL_STRING},
8523
+ [DEBUG_ATTRIBUTE_RING_FLAGS] = {.type = NLA_U32},
8524
+ [DEBUG_ATTRIBUTE_LOG_LEVEL] = {.type = NLA_U32},
8525
+ [DEBUG_ATTRIBUTE_LOG_TIME_INTVAL] = {.type = NLA_U32},
8526
+ [DEBUG_ATTRIBUTE_LOG_MIN_DATA_SIZE] = {.type = NLA_U32},
8527
+ [DEBUG_ATTRIBUTE_FW_DUMP_LEN] = {.type = NLA_U32},
8528
+ [DEBUG_ATTRIBUTE_FW_DUMP_DATA] = {.type = NLA_U64},
8529
+ [DEBUG_ATTRIBUTE_FW_ERR_CODE] = {.type = NLA_U32},
8530
+ [DEBUG_ATTRIBUTE_RING_DATA] = {.type = NLA_BINARY},
8531
+ [DEBUG_ATTRIBUTE_RING_STATUS] = {.type = NLA_BINARY},
8532
+ [DEBUG_ATTRIBUTE_RING_NUM] = {.type = NLA_U32},
8533
+ [DEBUG_ATTRIBUTE_DRIVER_DUMP_LEN] = {.type = NLA_U32},
8534
+ [DEBUG_ATTRIBUTE_DRIVER_DUMP_DATA] = {.type = NLA_BINARY},
8535
+ [DEBUG_ATTRIBUTE_PKT_FATE_NUM] = {.type = NLA_U32},
8536
+ [DEBUG_ATTRIBUTE_PKT_FATE_DATA] = {.type = NLA_U64},
8537
+ [DEBUG_ATTRIBUTE_HANG_REASON] = {.type = NLA_BINARY},
8538
+};
8539
+
8540
+const struct nla_policy hal_start_attr_policy[SET_HAL_START_ATTRIBUTE_MAX] = {
8541
+ [SET_HAL_START_ATTRIBUTE_DEINIT] = {.type = NLA_UNSPEC},
8542
+ [SET_HAL_START_ATTRIBUTE_PRE_INIT] = {.type = NLA_NUL_STRING},
8543
+ [SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID] = {.type = NLA_U32},
8544
+};
8545
+
8546
+const struct nla_policy rssi_monitor_attr_policy[RSSI_MONITOR_ATTRIBUTE_MAX] = {
8547
+ [RSSI_MONITOR_ATTRIBUTE_MAX_RSSI] = { .type = NLA_U32 },
8548
+ [RSSI_MONITOR_ATTRIBUTE_MIN_RSSI] = { .type = NLA_U32 },
8549
+ [RSSI_MONITOR_ATTRIBUTE_START] = { .type = NLA_U32 }
8550
+};
8551
+
8552
+const struct nla_policy mkeep_alive_attr_policy[MKEEP_ALIVE_ATTRIBUTE_MAX] = {
8553
+ [MKEEP_ALIVE_ATTRIBUTE_ID] = {.type = NLA_U8},
8554
+ [MKEEP_ALIVE_ATTRIBUTE_IP_PKT] = {.type = NLA_BINARY},
8555
+ [MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN] = {.type = NLA_U16},
8556
+ [MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR] = {.type = NLA_BINARY},
8557
+ [MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR] = {.type = NLA_BINARY},
8558
+ [MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC] = {.type = NLA_U32},
8559
+ [MKEEP_ALIVE_ATTRIBUTE_ETHER_TYPE] = {.type = NLA_U16 }
8560
+};
8561
+
8562
+const struct nla_policy chavoid_attr_policy[CHAVOID_ATTRIBUTE_MAX] = {
8563
+ [CHAVOID_ATTRIBUTE_CNT] = {.type = NLA_U32},
8564
+ [CHAVOID_ATTRIBUTE_MANDATORY] = {.type = NLA_U32},
8565
+ [CHAVOID_ATTRIBUTE_CONFIG] = {.type = NLA_NESTED},
8566
+ [CHAVOID_ATTRIBUTE_BAND] = {.type = NLA_U32},
8567
+ [CHAVOID_ATTRIBUTE_CHANNEL] = {.type = NLA_U32},
8568
+ [CHAVOID_ATTRIBUTE_PWRCAP] = {.type = NLA_U32},
8569
+};
8570
+
8571
+const struct nla_policy usablech_attr_policy[USABLECHAN_ATTRIBUTE_MAX] = {
8572
+ [USABLECHAN_ATTRIBUTE_BAND] = {.type = NLA_U32},
8573
+ [USABLECHAN_ATTRIBUTE_IFACE] = {.type = NLA_U32},
8574
+ [USABLECHAN_ATTRIBUTE_FILTER] = {.type = NLA_U32},
8575
+ [USABLECHAN_ATTRIBUTE_MAX_SIZE] = {.type = NLA_U32},
8576
+ [USABLECHAN_ATTRIBUTE_SIZE] = {.type = NLA_U32},
8577
+ [USABLECHAN_ATTRIBUTE_CHANNELS] = {.type = NLA_BINARY},
8578
+};
8579
+
8580
+const struct nla_policy multista_attr_policy[MULTISTA_ATTRIBUTE_MAX] = {
8581
+ [MULTISTA_ATTRIBUTE_PRIM_CONN_IFACE] = { .type = NLA_NUL_STRING },
8582
+ [MULTISTA_ATTRIBUTE_USE_CASE] = { .type = NLA_U32 },
8583
+};
8584
+
8585
+#ifdef WL_SUPPORT_ACS_OFFLOAD
8586
+const struct nla_policy acs_offload_attr_policy[BRCM_VENDOR_ATTR_ACS_LAST] = {
8587
+ [BRCM_VENDOR_ATTR_ACS_CHANNEL_INVALID] = { .type = NLA_U8 },
8588
+ [BRCM_VENDOR_ATTR_ACS_PRIMARY_FREQ] = { .type = NLA_U32 },
8589
+ [BRCM_VENDOR_ATTR_ACS_SECONDARY_FREQ] = { .type = NLA_U32 },
8590
+ [BRCM_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL] = { .type = NLA_U8 },
8591
+ [BRCM_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL] = { .type = NLA_U8 },
8592
+ [BRCM_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
8593
+ [BRCM_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_U8 },
8594
+ [BRCM_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_U8 },
8595
+ [BRCM_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_U8 },
8596
+ [BRCM_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
8597
+ [BRCM_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_BINARY },
8598
+ [BRCM_VENDOR_ATTR_ACS_FREQ_LIST] = { .type = NLA_BINARY },
8599
+};
8600
+#endif // endif
8601
+
8602
+#else
8603
+#define WL_VENDOR_POLICY_RAW_DATA
8604
+#endif /* LINUX_VER >= 5.3 */
25388605
25398606 static const struct wiphy_vendor_command wl_vendor_cmds [] = {
8607
+ {
8608
+ {
8609
+ .vendor_id = OUI_BRCM,
8610
+ .subcmd = BRCM_VENDOR_SCMD_FRAMEBURST
8611
+ },
8612
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8613
+ .doit = wl_cfgvendor_priv_frameburst,
8614
+ WL_VENDOR_POLICY_RAW_DATA
8615
+ },
8616
+ {
8617
+ {
8618
+ .vendor_id = OUI_BRCM,
8619
+ .subcmd = BRCM_VENDOR_SCMD_MPC
8620
+ },
8621
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8622
+ .doit = wl_cfgvendor_priv_mpc,
8623
+ WL_VENDOR_POLICY_RAW_DATA
8624
+ },
8625
+ {
8626
+ {
8627
+ .vendor_id = OUI_BRCM,
8628
+ .subcmd = BRCM_VENDOR_SCMD_BAND
8629
+ },
8630
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8631
+ .doit = wl_cfgvendor_priv_band,
8632
+ WL_VENDOR_POLICY_RAW_DATA
8633
+ },
25408634 {
25418635 {
25428636 .vendor_id = OUI_BRCM,
25438637 .subcmd = BRCM_VENDOR_SCMD_PRIV_STR
25448638 },
25458639 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2546
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2547
- .policy = VENDOR_CMD_RAW_DATA,
2548
-#endif
2549
- .doit = wl_cfgvendor_priv_string_handler
8640
+ .doit = wl_cfgvendor_priv_string_handler,
8641
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
8642
+ .policy = brcm_drv_attr_policy,
8643
+ .maxattr = BRCM_ATTR_DRIVER_MAX
8644
+#endif // endif
25508645 },
8646
+#ifdef BCM_PRIV_CMD_SUPPORT
25518647 {
25528648 {
25538649 .vendor_id = OUI_BRCM,
25548650 .subcmd = BRCM_VENDOR_SCMD_BCM_STR
25558651 },
25568652 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2557
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2558
- .policy = VENDOR_CMD_RAW_DATA,
2559
-#endif
2560
- .doit = wl_cfgvendor_priv_bcm_handler
8653
+ .doit = wl_cfgvendor_priv_bcm_handler,
8654
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
8655
+ .policy = brcm_drv_attr_policy,
8656
+ .maxattr = BRCM_ATTR_DRIVER_MAX
8657
+#endif // endif
25618658 },
2562
-#ifdef GSCAN_SUPPORT
8659
+#endif /* BCM_PRIV_CMD_SUPPORT */
8660
+#ifdef WL_SAE
8661
+ {
8662
+ {
8663
+ .vendor_id = OUI_BRCM,
8664
+ .subcmd = BRCM_VENDOR_SCMD_BCM_PSK
8665
+ },
8666
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8667
+ .doit = wl_cfgvendor_set_sae_password,
8668
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
8669
+ .policy = brcm_drv_attr_policy,
8670
+ .maxattr = BRCM_ATTR_DRIVER_MAX
8671
+#endif // endif
8672
+ },
8673
+#endif /* WL_SAE */
25638674 {
25648675 {
25658676 .vendor_id = OUI_GOOGLE,
25668677 .subcmd = GSCAN_SUBCMD_GET_CAPABILITIES
25678678 },
25688679 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2569
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2570
- .policy = VENDOR_CMD_RAW_DATA,
2571
-#endif
2572
- .doit = wl_cfgvendor_gscan_get_capabilities
8680
+ .doit = wl_cfgvendor_gscan_get_capabilities,
8681
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
8682
+ .policy = gscan_attr_policy,
8683
+ .maxattr = BRCM_ATTR_DRIVER_MAX
8684
+#endif // endif
25738685 },
8686
+#ifdef GSCAN_SUPPORT
25748687 {
25758688 {
25768689 .vendor_id = OUI_GOOGLE,
25778690 .subcmd = GSCAN_SUBCMD_SET_CONFIG
25788691 },
25798692 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2580
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2581
- .policy = VENDOR_CMD_RAW_DATA,
2582
-#endif
2583
- .doit = wl_cfgvendor_set_scan_cfg
8693
+ .doit = wl_cfgvendor_set_scan_cfg,
8694
+ WL_VENDOR_POLICY_RAW_DATA
25848695 },
25858696 {
25868697 {
....@@ -2588,10 +8699,8 @@
25888699 .subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG
25898700 },
25908701 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2591
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2592
- .policy = VENDOR_CMD_RAW_DATA,
2593
-#endif
2594
- .doit = wl_cfgvendor_set_batch_scan_cfg
8702
+ .doit = wl_cfgvendor_set_batch_scan_cfg,
8703
+ WL_VENDOR_POLICY_RAW_DATA
25958704 },
25968705 {
25978706 {
....@@ -2599,10 +8708,8 @@
25998708 .subcmd = GSCAN_SUBCMD_ENABLE_GSCAN
26008709 },
26018710 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2602
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2603
- .policy = VENDOR_CMD_RAW_DATA,
2604
-#endif
2605
- .doit = wl_cfgvendor_initiate_gscan
8711
+ .doit = wl_cfgvendor_initiate_gscan,
8712
+ WL_VENDOR_POLICY_RAW_DATA
26068713 },
26078714 {
26088715 {
....@@ -2610,10 +8717,8 @@
26108717 .subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
26118718 },
26128719 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2613
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2614
- .policy = VENDOR_CMD_RAW_DATA,
2615
-#endif
2616
- .doit = wl_cfgvendor_enable_full_scan_result
8720
+ .doit = wl_cfgvendor_enable_full_scan_result,
8721
+ WL_VENDOR_POLICY_RAW_DATA
26178722 },
26188723 {
26198724 {
....@@ -2621,21 +8726,8 @@
26218726 .subcmd = GSCAN_SUBCMD_SET_HOTLIST
26228727 },
26238728 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2624
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2625
- .policy = VENDOR_CMD_RAW_DATA,
2626
-#endif
2627
- .doit = wl_cfgvendor_hotlist_cfg
2628
- },
2629
- {
2630
- {
2631
- .vendor_id = OUI_GOOGLE,
2632
- .subcmd = GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG
2633
- },
2634
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2635
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2636
- .policy = VENDOR_CMD_RAW_DATA,
2637
-#endif
2638
- .doit = wl_cfgvendor_significant_change_cfg
8729
+ .doit = wl_cfgvendor_hotlist_cfg,
8730
+ WL_VENDOR_POLICY_RAW_DATA
26398731 },
26408732 {
26418733 {
....@@ -2643,23 +8735,24 @@
26438735 .subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS
26448736 },
26458737 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2646
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2647
- .policy = VENDOR_CMD_RAW_DATA,
2648
-#endif
2649
- .doit = wl_cfgvendor_gscan_get_batch_results
8738
+ .doit = wl_cfgvendor_gscan_get_batch_results,
8739
+ WL_VENDOR_POLICY_RAW_DATA
26508740 },
8741
+#endif /* GSCAN_SUPPORT */
8742
+#if defined(GSCAN_SUPPORT) || defined(DHD_GET_VALID_CHANNELS)
26518743 {
26528744 {
26538745 .vendor_id = OUI_GOOGLE,
26548746 .subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST
26558747 },
26568748 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2657
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2658
- .policy = VENDOR_CMD_RAW_DATA,
2659
-#endif
2660
- .doit = wl_cfgvendor_gscan_get_channel_list
8749
+ .doit = wl_cfgvendor_gscan_get_channel_list,
8750
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
8751
+ .policy=gscan_attr_policy,
8752
+ .maxattr=GSCAN_ATTRIBUTE_MAX
8753
+#endif // endif
26618754 },
2662
-#endif /* GSCAN_SUPPORT */
8755
+#endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */
26638756 #ifdef RTT_SUPPORT
26648757 {
26658758 {
....@@ -2667,10 +8760,8 @@
26678760 .subcmd = RTT_SUBCMD_SET_CONFIG
26688761 },
26698762 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2670
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2671
- .policy = VENDOR_CMD_RAW_DATA,
2672
-#endif
2673
- .doit = wl_cfgvendor_rtt_set_config
8763
+ .doit = wl_cfgvendor_rtt_set_config,
8764
+ WL_VENDOR_POLICY_RAW_DATA
26748765 },
26758766 {
26768767 {
....@@ -2678,10 +8769,8 @@
26788769 .subcmd = RTT_SUBCMD_CANCEL_CONFIG
26798770 },
26808771 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2681
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2682
- .policy = VENDOR_CMD_RAW_DATA,
2683
-#endif
2684
- .doit = wl_cfgvendor_rtt_cancel_config
8772
+ .doit = wl_cfgvendor_rtt_cancel_config,
8773
+ WL_VENDOR_POLICY_RAW_DATA
26858774 },
26868775 {
26878776 {
....@@ -2689,46 +8778,48 @@
26898778 .subcmd = RTT_SUBCMD_GETCAPABILITY
26908779 },
26918780 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2692
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2693
- .policy = VENDOR_CMD_RAW_DATA,
2694
-#endif
2695
- .doit = wl_cfgvendor_rtt_get_capability
8781
+ .doit = wl_cfgvendor_rtt_get_capability,
8782
+ WL_VENDOR_POLICY_RAW_DATA
8783
+ },
8784
+ {
8785
+ {
8786
+ .vendor_id = OUI_GOOGLE,
8787
+ .subcmd = RTT_SUBCMD_GETAVAILCHANNEL
8788
+ },
8789
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8790
+ .doit = wl_cfgvendor_rtt_get_responder_info,
8791
+ WL_VENDOR_POLICY_RAW_DATA
8792
+ },
8793
+ {
8794
+ {
8795
+ .vendor_id = OUI_GOOGLE,
8796
+ .subcmd = RTT_SUBCMD_SET_RESPONDER
8797
+ },
8798
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8799
+ .doit = wl_cfgvendor_rtt_set_responder,
8800
+ WL_VENDOR_POLICY_RAW_DATA
8801
+ },
8802
+ {
8803
+ {
8804
+ .vendor_id = OUI_GOOGLE,
8805
+ .subcmd = RTT_SUBCMD_CANCEL_RESPONDER
8806
+ },
8807
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8808
+ .doit = wl_cfgvendor_rtt_cancel_responder,
8809
+ WL_VENDOR_POLICY_RAW_DATA
26968810 },
26978811 #endif /* RTT_SUPPORT */
2698
-#ifdef KEEP_ALIVE
2699
- {
2700
- {
2701
- .vendor_id = OUI_GOOGLE,
2702
- .subcmd = WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE
2703
- },
2704
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2705
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2706
- .policy = VENDOR_CMD_RAW_DATA,
2707
-#endif
2708
- .doit = wl_cfgvendor_start_mkeep_alive
2709
- },
2710
- {
2711
- {
2712
- .vendor_id = OUI_GOOGLE,
2713
- .subcmd = WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE
2714
- },
2715
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2716
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2717
- .policy = VENDOR_CMD_RAW_DATA,
2718
-#endif
2719
- .doit = wl_cfgvendor_stop_mkeep_alive
2720
- },
2721
-#endif /* KEEP_ALIVE */
27228812 {
27238813 {
27248814 .vendor_id = OUI_GOOGLE,
27258815 .subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET
27268816 },
27278817 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2728
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2729
- .policy = VENDOR_CMD_RAW_DATA,
2730
-#endif
2731
- .doit = wl_cfgvendor_get_feature_set
8818
+ .doit = wl_cfgvendor_get_feature_set,
8819
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
8820
+ .policy = andr_wifi_attr_policy,
8821
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
8822
+#endif // endif
27328823 },
27338824 {
27348825 {
....@@ -2736,21 +8827,23 @@
27368827 .subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX
27378828 },
27388829 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2739
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2740
- .policy = VENDOR_CMD_RAW_DATA,
2741
-#endif
2742
- .doit = wl_cfgvendor_get_feature_set_matrix
8830
+ .doit = wl_cfgvendor_get_feature_set_matrix,
8831
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
8832
+ .policy = andr_wifi_attr_policy,
8833
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
8834
+#endif // endif
27438835 },
27448836 {
27458837 {
27468838 .vendor_id = OUI_GOOGLE,
2747
- .subcmd = ANDR_WIFI_RANDOM_MAC_OUI
8839
+ .subcmd = ANDR_WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI
27488840 },
27498841 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2750
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2751
- .policy = VENDOR_CMD_RAW_DATA,
2752
-#endif
2753
- .doit = wl_cfgvendor_set_rand_mac_oui
8842
+ .doit = wl_cfgvendor_set_pno_rand_mac_oui,
8843
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
8844
+ .policy = andr_wifi_attr_policy,
8845
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
8846
+#endif // endif
27548847 },
27558848 #ifdef CUSTOM_FORCE_NODFS_FLAG
27568849 {
....@@ -2759,26 +8852,34 @@
27598852 .subcmd = ANDR_WIFI_NODFS_CHANNELS
27608853 },
27618854 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2762
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2763
- .policy = VENDOR_CMD_RAW_DATA,
2764
-#endif
2765
- .doit = wl_cfgvendor_set_nodfs_flag
2766
-
8855
+ .doit = wl_cfgvendor_set_nodfs_flag,
8856
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
8857
+ .policy = andr_wifi_attr_policy,
8858
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
8859
+#endif // endif
27678860 },
27688861 #endif /* CUSTOM_FORCE_NODFS_FLAG */
2769
-#ifdef LINKSTAT_SUPPORT
8862
+ {
8863
+ {
8864
+ .vendor_id = OUI_GOOGLE,
8865
+ .subcmd = ANDR_WIFI_SET_COUNTRY
8866
+ },
8867
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8868
+ .doit = wl_cfgvendor_set_country,
8869
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
8870
+ .policy = andr_wifi_attr_policy,
8871
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
8872
+#endif // endif
8873
+ },
27708874 {
27718875 {
27728876 .vendor_id = OUI_GOOGLE,
27738877 .subcmd = LSTATS_SUBCMD_GET_INFO
27748878 },
27758879 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2776
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2777
- .policy = VENDOR_CMD_RAW_DATA,
2778
-#endif
2779
- .doit = wl_cfgvendor_lstats_get_info
8880
+ .doit = wl_cfgvendor_lstats_get_info,
8881
+ WL_VENDOR_POLICY_RAW_DATA
27808882 },
2781
-#endif /* LINKSTAT_SUPPORT */
27828883 #ifdef GSCAN_SUPPORT
27838884 {
27848885 {
....@@ -2786,23 +8887,8 @@
27868887 .subcmd = GSCAN_SUBCMD_SET_EPNO_SSID
27878888 },
27888889 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2789
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2790
- .policy = VENDOR_CMD_RAW_DATA,
2791
-#endif
2792
- .doit = wl_cfgvendor_epno_cfg
2793
-
2794
- },
2795
- {
2796
- {
2797
- .vendor_id = OUI_GOOGLE,
2798
- .subcmd = WIFI_SUBCMD_SET_SSID_WHITELIST
2799
- },
2800
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2801
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2802
- .policy = VENDOR_CMD_RAW_DATA,
2803
-#endif
2804
- .doit = wl_cfgvendor_set_ssid_whitelist
2805
-
8890
+ .doit = wl_cfgvendor_epno_cfg,
8891
+ WL_VENDOR_POLICY_RAW_DATA
28068892 },
28078893 {
28088894 {
....@@ -2810,11 +8896,8 @@
28108896 .subcmd = WIFI_SUBCMD_SET_LAZY_ROAM_PARAMS
28118897 },
28128898 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2813
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2814
- .policy = VENDOR_CMD_RAW_DATA,
2815
-#endif
2816
- .doit = wl_cfgvendor_set_lazy_roam_cfg
2817
-
8899
+ .doit = wl_cfgvendor_set_lazy_roam_cfg,
8900
+ WL_VENDOR_POLICY_RAW_DATA
28188901 },
28198902 {
28208903 {
....@@ -2822,10 +8905,8 @@
28228905 .subcmd = WIFI_SUBCMD_ENABLE_LAZY_ROAM
28238906 },
28248907 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2825
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2826
- .policy = VENDOR_CMD_RAW_DATA,
2827
-#endif
2828
- .doit = wl_cfgvendor_enable_lazy_roam
8908
+ .doit = wl_cfgvendor_enable_lazy_roam,
8909
+ WL_VENDOR_POLICY_RAW_DATA
28298910
28308911 },
28318912 {
....@@ -2834,10 +8915,23 @@
28348915 .subcmd = WIFI_SUBCMD_SET_BSSID_PREF
28358916 },
28368917 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2837
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2838
- .policy = VENDOR_CMD_RAW_DATA,
2839
-#endif
2840
- .doit = wl_cfgvendor_set_bssid_pref
8918
+ .doit = wl_cfgvendor_set_bssid_pref,
8919
+ WL_VENDOR_POLICY_RAW_DATA
8920
+
8921
+ },
8922
+#endif /* GSCAN_SUPPORT */
8923
+#if defined(GSCAN_SUPPORT) || defined(ROAMEXP_SUPPORT)
8924
+ {
8925
+ {
8926
+ .vendor_id = OUI_GOOGLE,
8927
+ .subcmd = WIFI_SUBCMD_SET_SSID_WHITELIST
8928
+ },
8929
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8930
+ .doit = wl_cfgvendor_set_ssid_whitelist,
8931
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
8932
+ .policy = gscan_attr_policy,
8933
+ .maxattr = GSCAN_ATTRIBUTE_MAX
8934
+#endif // endif
28418935
28428936 },
28438937 {
....@@ -2846,45 +8940,67 @@
28468940 .subcmd = WIFI_SUBCMD_SET_BSSID_BLACKLIST
28478941 },
28488942 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2849
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2850
- .policy = VENDOR_CMD_RAW_DATA,
2851
-#endif
2852
- .doit = wl_cfgvendor_set_bssid_blacklist
8943
+ .doit = wl_cfgvendor_set_bssid_blacklist,
8944
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
8945
+ .policy = gscan_attr_policy,
8946
+ .maxattr = GSCAN_ATTRIBUTE_MAX
8947
+#endif // endif
28538948 },
2854
-#endif /* GSCAN_SUPPORT */
8949
+#endif /* GSCAN_SUPPORT || ROAMEXP_SUPPORT */
8950
+#ifdef ROAMEXP_SUPPORT
28558951 {
28568952 {
28578953 .vendor_id = OUI_GOOGLE,
2858
- .subcmd = WIFI_SUBCMD_SET_RSSI_MONITOR
8954
+ .subcmd = WIFI_SUBCMD_FW_ROAM_POLICY
28598955 },
28608956 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2861
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2862
- .policy = VENDOR_CMD_RAW_DATA,
2863
-#endif
2864
- .doit = wl_cfgvendor_set_rssi_monitor
8957
+ .doit = wl_cfgvendor_set_fw_roaming_state,
8958
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
8959
+ .policy = gscan_attr_policy,
8960
+ .maxattr = GSCAN_ATTRIBUTE_MAX
8961
+#endif // endif
28658962 },
28668963 {
28678964 {
28688965 .vendor_id = OUI_GOOGLE,
2869
- .subcmd = DEBUG_START_LOGGING
8966
+ .subcmd = WIFI_SUBCMD_ROAM_CAPABILITY
28708967 },
28718968 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2872
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2873
- .policy = VENDOR_CMD_RAW_DATA,
2874
-#endif
2875
- .doit = wl_cfgvendor_dbg_start_logging
8969
+ .doit = wl_cfgvendor_fw_roam_get_capability,
8970
+ WL_VENDOR_POLICY_RAW_DATA
28768971 },
2877
-#ifdef DHD_FW_COREDUMP
8972
+#endif /* ROAMEXP_SUPPORT */
8973
+ {
8974
+ {
8975
+ .vendor_id = OUI_GOOGLE,
8976
+ .subcmd = DEBUG_GET_VER
8977
+ },
8978
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8979
+ .doit = wl_cfgvendor_dbg_get_version,
8980
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
8981
+ .policy = debug_attr_policy,
8982
+ .maxattr = DEBUG_ATTRIBUTE_MAX
8983
+#endif // endif
8984
+ },
8985
+#ifdef DHD_LOG_DUMP
8986
+ {
8987
+ {
8988
+ .vendor_id = OUI_GOOGLE,
8989
+ .subcmd = DEBUG_GET_FILE_DUMP_BUF
8990
+ },
8991
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8992
+ .doit = wl_cfgvendor_dbg_file_dump,
8993
+ WL_VENDOR_POLICY_RAW_DATA
8994
+ },
8995
+#endif /* DHD_LOG_DUMP */
28788996 {
28798997 {
28808998 .vendor_id = OUI_GOOGLE,
28818999 .subcmd = DEBUG_TRIGGER_MEM_DUMP
28829000 },
28839001 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2884
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2885
- .policy = VENDOR_CMD_RAW_DATA,
2886
-#endif
2887
- .doit = wl_cfgvendor_dbg_trigger_mem_dump
9002
+ .doit = wl_cfgvendor_dbg_trigger_mem_dump,
9003
+ WL_VENDOR_POLICY_RAW_DATA
28889004 },
28899005 {
28909006 {
....@@ -2892,46 +9008,42 @@
28929008 .subcmd = DEBUG_GET_MEM_DUMP
28939009 },
28949010 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2895
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2896
- .policy = VENDOR_CMD_RAW_DATA,
2897
-#endif
2898
- .doit = wl_cfgvendor_dbg_get_mem_dump
9011
+ .doit = wl_cfgvendor_dbg_get_mem_dump,
9012
+ WL_VENDOR_POLICY_RAW_DATA
28999013 },
2900
-#endif /* DHD_FW_COREDUMP */
9014
+ {
9015
+ {
9016
+ .vendor_id = OUI_GOOGLE,
9017
+ .subcmd = DEBUG_START_LOGGING
9018
+ },
9019
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9020
+ .doit = wl_cfgvendor_dbg_start_logging,
9021
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9022
+ .policy = debug_attr_policy,
9023
+ .maxattr = DEBUG_ATTRIBUTE_MAX
9024
+#endif // endif
9025
+
9026
+ },
29019027 {
29029028 {
29039029 .vendor_id = OUI_GOOGLE,
29049030 .subcmd = DEBUG_RESET_LOGGING
29059031 },
29069032 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2907
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2908
- .policy = VENDOR_CMD_RAW_DATA,
2909
-#endif
2910
- .doit = wl_cfgvendor_dbg_reset_logging
9033
+ .doit = wl_cfgvendor_dbg_reset_logging,
9034
+ WL_VENDOR_POLICY_RAW_DATA
29119035 },
2912
-#ifdef DHD_FW_COREDUMP
2913
- {
2914
- {
2915
- .vendor_id = OUI_GOOGLE,
2916
- .subcmd = DEBUG_GET_VER
2917
- },
2918
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2919
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2920
- .policy = VENDOR_CMD_RAW_DATA,
2921
-#endif
2922
- .doit = wl_cfgvendor_dbg_get_version
2923
- },
2924
-#endif /* DHD_FW_COREDUMP */
29259036 {
29269037 {
29279038 .vendor_id = OUI_GOOGLE,
29289039 .subcmd = DEBUG_GET_RING_STATUS
29299040 },
29309041 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2931
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2932
- .policy = VENDOR_CMD_RAW_DATA,
2933
-#endif
2934
- .doit = wl_cfgvendor_dbg_get_ring_status
9042
+ .doit = wl_cfgvendor_dbg_get_ring_status,
9043
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9044
+ .policy = debug_attr_policy,
9045
+ .maxattr = DEBUG_ATTRIBUTE_MAX
9046
+#endif // endif
29359047 },
29369048 {
29379049 {
....@@ -2939,10 +9051,11 @@
29399051 .subcmd = DEBUG_GET_RING_DATA
29409052 },
29419053 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2942
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2943
- .policy = VENDOR_CMD_RAW_DATA,
2944
-#endif
2945
- .doit = wl_cfgvendor_dbg_get_ring_data
9054
+ .doit = wl_cfgvendor_dbg_get_ring_data,
9055
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9056
+ .policy = debug_attr_policy,
9057
+ .maxattr = DEBUG_ATTRIBUTE_MAX
9058
+#endif // endif
29469059 },
29479060 {
29489061 {
....@@ -2950,64 +9063,490 @@
29509063 .subcmd = DEBUG_GET_FEATURE
29519064 },
29529065 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2953
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
2954
- .policy = VENDOR_CMD_RAW_DATA,
2955
-#endif
2956
- .doit = wl_cfgvendor_dbg_get_feature
9066
+ .doit = wl_cfgvendor_dbg_get_feature,
9067
+ WL_VENDOR_POLICY_RAW_DATA
29579068 },
29589069 {
29599070 {
29609071 .vendor_id = OUI_GOOGLE,
2961
- .subcmd = ANDR_WIFI_SET_COUNTRY
9072
+ .subcmd = DEBUG_START_PKT_FATE_MONITORING
29629073 },
29639074 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2964
- .doit = wl_cfgvendor_set_country
9075
+ .doit = wl_cfgvendor_dbg_start_pkt_fate_monitoring,
9076
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9077
+ .policy = debug_attr_policy,
9078
+ .maxattr = DEBUG_ATTRIBUTE_MAX
9079
+#endif // endif
29659080 },
9081
+ {
9082
+ {
9083
+ .vendor_id = OUI_GOOGLE,
9084
+ .subcmd = DEBUG_GET_TX_PKT_FATES
9085
+ },
9086
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9087
+ .doit = wl_cfgvendor_dbg_get_tx_pkt_fates,
9088
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9089
+ .policy = debug_attr_policy,
9090
+ .maxattr = DEBUG_ATTRIBUTE_MAX
9091
+#endif // endif
9092
+ },
9093
+ {
9094
+ {
9095
+ .vendor_id = OUI_GOOGLE,
9096
+ .subcmd = DEBUG_GET_RX_PKT_FATES
9097
+ },
9098
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9099
+ .doit = wl_cfgvendor_dbg_get_rx_pkt_fates,
9100
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9101
+ .policy = debug_attr_policy,
9102
+ .maxattr = DEBUG_ATTRIBUTE_MAX
9103
+#endif // endif
9104
+ },
9105
+#ifdef KEEP_ALIVE
9106
+ {
9107
+ {
9108
+ .vendor_id = OUI_GOOGLE,
9109
+ .subcmd = WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE
9110
+ },
9111
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9112
+ .doit = wl_cfgvendor_start_mkeep_alive,
9113
+ WL_VENDOR_POLICY_RAW_DATA
9114
+ },
9115
+ {
9116
+ {
9117
+ .vendor_id = OUI_GOOGLE,
9118
+ .subcmd = WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE
9119
+ },
9120
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9121
+ .doit = wl_cfgvendor_stop_mkeep_alive,
9122
+ WL_VENDOR_POLICY_RAW_DATA
9123
+ },
9124
+#endif /* KEEP_ALIVE */
9125
+#ifdef WL_NAN
9126
+ {
9127
+ {
9128
+ .vendor_id = OUI_GOOGLE,
9129
+ .subcmd = NAN_WIFI_SUBCMD_ENABLE
9130
+ },
9131
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9132
+ .doit = wl_cfgvendor_nan_start_handler,
9133
+ WL_VENDOR_POLICY_RAW_DATA
9134
+ },
9135
+ {
9136
+ {
9137
+ .vendor_id = OUI_GOOGLE,
9138
+ .subcmd = NAN_WIFI_SUBCMD_DISABLE
9139
+ },
9140
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9141
+ .doit = wl_cfgvendor_nan_stop_handler,
9142
+ WL_VENDOR_POLICY_RAW_DATA
9143
+ },
9144
+ {
9145
+ {
9146
+ .vendor_id = OUI_GOOGLE,
9147
+ .subcmd = NAN_WIFI_SUBCMD_CONFIG
9148
+ },
9149
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9150
+ .doit = wl_cfgvendor_nan_config_handler,
9151
+ WL_VENDOR_POLICY_RAW_DATA
9152
+ },
9153
+ {
9154
+ {
9155
+ .vendor_id = OUI_GOOGLE,
9156
+ .subcmd = NAN_WIFI_SUBCMD_REQUEST_PUBLISH
9157
+ },
9158
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9159
+ .doit = wl_cfgvendor_nan_req_publish,
9160
+ WL_VENDOR_POLICY_RAW_DATA
9161
+ },
9162
+ {
9163
+ {
9164
+ .vendor_id = OUI_GOOGLE,
9165
+ .subcmd = NAN_WIFI_SUBCMD_REQUEST_SUBSCRIBE
9166
+ },
9167
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9168
+ .doit = wl_cfgvendor_nan_req_subscribe,
9169
+ WL_VENDOR_POLICY_RAW_DATA
9170
+ },
9171
+ {
9172
+ {
9173
+ .vendor_id = OUI_GOOGLE,
9174
+ .subcmd = NAN_WIFI_SUBCMD_CANCEL_PUBLISH
9175
+ },
9176
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9177
+ .doit = wl_cfgvendor_nan_cancel_publish,
9178
+ WL_VENDOR_POLICY_RAW_DATA
9179
+ },
9180
+ {
9181
+ {
9182
+ .vendor_id = OUI_GOOGLE,
9183
+ .subcmd = NAN_WIFI_SUBCMD_CANCEL_SUBSCRIBE
9184
+ },
9185
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9186
+ .doit = wl_cfgvendor_nan_cancel_subscribe,
9187
+ WL_VENDOR_POLICY_RAW_DATA
9188
+ },
9189
+ {
9190
+ {
9191
+ .vendor_id = OUI_GOOGLE,
9192
+ .subcmd = NAN_WIFI_SUBCMD_TRANSMIT
9193
+ },
9194
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9195
+ .doit = wl_cfgvendor_nan_transmit,
9196
+ WL_VENDOR_POLICY_RAW_DATA
9197
+ },
9198
+ {
9199
+ {
9200
+ .vendor_id = OUI_GOOGLE,
9201
+ .subcmd = NAN_WIFI_SUBCMD_GET_CAPABILITIES
9202
+ },
9203
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9204
+ .doit = wl_cfgvendor_nan_get_capablities,
9205
+ WL_VENDOR_POLICY_RAW_DATA
9206
+ },
9207
+
9208
+ {
9209
+ {
9210
+ .vendor_id = OUI_GOOGLE,
9211
+ .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE
9212
+ },
9213
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9214
+ .doit = wl_cfgvendor_nan_data_path_iface_create,
9215
+ WL_VENDOR_POLICY_RAW_DATA
9216
+ },
9217
+ {
9218
+ {
9219
+ .vendor_id = OUI_GOOGLE,
9220
+ .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE
9221
+ },
9222
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9223
+ .doit = wl_cfgvendor_nan_data_path_iface_delete,
9224
+ WL_VENDOR_POLICY_RAW_DATA
9225
+ },
9226
+ {
9227
+ {
9228
+ .vendor_id = OUI_GOOGLE,
9229
+ .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_REQUEST
9230
+ },
9231
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9232
+ .doit = wl_cfgvendor_nan_data_path_request,
9233
+ WL_VENDOR_POLICY_RAW_DATA
9234
+ },
9235
+ {
9236
+ {
9237
+ .vendor_id = OUI_GOOGLE,
9238
+ .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_RESPONSE
9239
+ },
9240
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9241
+ .doit = wl_cfgvendor_nan_data_path_response,
9242
+ WL_VENDOR_POLICY_RAW_DATA
9243
+ },
9244
+ {
9245
+ {
9246
+ .vendor_id = OUI_GOOGLE,
9247
+ .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_END
9248
+ },
9249
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9250
+ .doit = wl_cfgvendor_nan_data_path_end,
9251
+ WL_VENDOR_POLICY_RAW_DATA
9252
+ },
9253
+#ifdef WL_NAN_DISC_CACHE
9254
+ {
9255
+ {
9256
+ .vendor_id = OUI_GOOGLE,
9257
+ .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_SEC_INFO
9258
+ },
9259
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9260
+ .doit = wl_cfgvendor_nan_data_path_sec_info,
9261
+ WL_VENDOR_POLICY_RAW_DATA
9262
+ },
9263
+#endif /* WL_NAN_DISC_CACHE */
9264
+ {
9265
+ {
9266
+ .vendor_id = OUI_GOOGLE,
9267
+ .subcmd = NAN_WIFI_SUBCMD_VERSION_INFO
9268
+ },
9269
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9270
+ .doit = wl_cfgvendor_nan_version_info,
9271
+ WL_VENDOR_POLICY_RAW_DATA
9272
+ },
9273
+#endif /* WL_NAN */
9274
+#if defined(PKT_FILTER_SUPPORT) && defined(APF)
9275
+ {
9276
+ {
9277
+ .vendor_id = OUI_GOOGLE,
9278
+ .subcmd = APF_SUBCMD_GET_CAPABILITIES
9279
+ },
9280
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9281
+ .doit = wl_cfgvendor_apf_get_capabilities,
9282
+ WL_VENDOR_POLICY_RAW_DATA
9283
+ },
9284
+
9285
+ {
9286
+ {
9287
+ .vendor_id = OUI_GOOGLE,
9288
+ .subcmd = APF_SUBCMD_SET_FILTER
9289
+ },
9290
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9291
+ .doit = wl_cfgvendor_apf_set_filter,
9292
+ WL_VENDOR_POLICY_RAW_DATA
9293
+ },
9294
+#endif /* PKT_FILTER_SUPPORT && APF */
9295
+ {
9296
+ {
9297
+ .vendor_id = OUI_GOOGLE,
9298
+ .subcmd = WIFI_SUBCMD_CONFIG_ND_OFFLOAD
9299
+ },
9300
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9301
+ .doit = wl_cfgvendor_configure_nd_offload,
9302
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9303
+ .policy = andr_wifi_attr_policy,
9304
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
9305
+#endif // endif
9306
+ },
9307
+ {
9308
+ {
9309
+ .vendor_id = OUI_GOOGLE,
9310
+ .subcmd = WIFI_SUBCMD_SET_RSSI_MONITOR
9311
+ },
9312
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9313
+ .doit = wl_cfgvendor_set_rssi_monitor,
9314
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9315
+ .policy = rssi_monitor_attr_policy,
9316
+ .maxattr = RSSI_MONITOR_ATTRIBUTE_MAX
9317
+#endif // endif
9318
+ },
9319
+#ifdef DHD_WAKE_STATUS
9320
+ {
9321
+ {
9322
+ .vendor_id = OUI_GOOGLE,
9323
+ .subcmd = DEBUG_GET_WAKE_REASON_STATS
9324
+ },
9325
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9326
+ .doit = wl_cfgvendor_get_wake_reason_stats,
9327
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9328
+ .policy = wake_stat_attr_policy,
9329
+ .maxattr = WAKE_STAT_ATTRIBUTE_MAX
9330
+#endif // endif
9331
+ },
9332
+#endif /* DHD_WAKE_STATUS */
9333
+#ifdef DHDTCPACK_SUPPRESS
9334
+ {
9335
+ {
9336
+ .vendor_id = OUI_GOOGLE,
9337
+ .subcmd = WIFI_SUBCMD_CONFIG_TCPACK_SUP
9338
+ },
9339
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9340
+ .doit = wl_cfgvendor_set_tcpack_sup_mode,
9341
+ WL_VENDOR_POLICY_RAW_DATA
9342
+ },
9343
+#endif /* DHDTCPACK_SUPPRESS */
9344
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0))
9345
+ {
9346
+ {
9347
+ .vendor_id = OUI_BRCM,
9348
+ .subcmd = BRCM_VENDOR_SCMD_SET_PMK
9349
+ },
9350
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9351
+ .doit = wl_cfgvendor_set_pmk,
9352
+ WL_VENDOR_POLICY_RAW_DATA
9353
+ },
9354
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) */
9355
+ {
9356
+ {
9357
+ .vendor_id = OUI_BRCM,
9358
+ .subcmd = BRCM_VENDOR_SCMD_GET_FEATURES
9359
+ },
9360
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9361
+ .doit = wl_cfgvendor_get_driver_feature,
9362
+ WL_VENDOR_POLICY_RAW_DATA
9363
+ },
9364
+#if defined(WL_CFG80211) && defined(DHD_FILE_DUMP_EVENT)
9365
+ {
9366
+ {
9367
+ .vendor_id = OUI_GOOGLE,
9368
+ .subcmd = DEBUG_FILE_DUMP_DONE_IND
9369
+ },
9370
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9371
+ .doit = wl_cfgvendor_notify_dump_completion,
9372
+ WL_VENDOR_POLICY_RAW_DATA
9373
+ },
9374
+#endif /* WL_CFG80211 && DHD_FILE_DUMP_EVENT */
9375
+#if defined(WL_CFG80211)
9376
+ {
9377
+ {
9378
+ .vendor_id = OUI_GOOGLE,
9379
+ .subcmd = DEBUG_SET_HAL_START
9380
+ },
9381
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9382
+ .doit = wl_cfgvendor_set_hal_started,
9383
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9384
+ .policy = hal_start_attr_policy,
9385
+ .maxattr = SET_HAL_START_ATTRIBUTE_MAX
9386
+#endif // endif
9387
+ },
9388
+ {
9389
+ {
9390
+ .vendor_id = OUI_GOOGLE,
9391
+ .subcmd = DEBUG_SET_HAL_STOP
9392
+ },
9393
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9394
+ .doit = wl_cfgvendor_stop_hal,
9395
+ WL_VENDOR_POLICY_RAW_DATA
9396
+ },
9397
+ {
9398
+ {
9399
+ .vendor_id = OUI_GOOGLE,
9400
+ .subcmd = DEBUG_SET_HAL_PID
9401
+ },
9402
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9403
+ .doit = wl_cfgvendor_set_hal_pid,
9404
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9405
+ .policy = hal_start_attr_policy,
9406
+ .maxattr = SET_HAL_START_ATTRIBUTE_MAX
9407
+#endif // endif
9408
+ },
9409
+#endif /* WL_CFG80211 */
9410
+ {
9411
+ {
9412
+ .vendor_id = OUI_GOOGLE,
9413
+ .subcmd = WIFI_SUBCMD_SET_LATENCY_MODE
9414
+ },
9415
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9416
+ .doit = wl_cfgvendor_set_latency_mode,
9417
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9418
+ .policy = andr_wifi_attr_policy,
9419
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
9420
+#endif // endif
9421
+ },
9422
+ {
9423
+ {
9424
+ .vendor_id = OUI_GOOGLE,
9425
+ .subcmd = WIFI_SUBCMD_TX_POWER_SCENARIO
9426
+ },
9427
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9428
+ .doit = wl_cfgvendor_set_tx_power_scenario,
9429
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9430
+ .policy = andr_wifi_attr_policy,
9431
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
9432
+#endif // endif
9433
+ },
9434
+ {
9435
+ {
9436
+ .vendor_id = OUI_GOOGLE,
9437
+ .subcmd = CHAVOID_SUBCMD_SET_CONFIG
9438
+ },
9439
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9440
+ .doit = wl_cfgvendor_chavoid_set_config,
9441
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9442
+ .policy = chavoid_attr_policy,
9443
+ .maxattr = CHAVOID_ATTRIBUTE_MAX
9444
+#endif // endif
9445
+ },
9446
+ {
9447
+ {
9448
+ .vendor_id = OUI_GOOGLE,
9449
+ .subcmd = WIFI_SUBCMD_USABLE_CHANNEL
9450
+ },
9451
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9452
+ .doit = wl_cfgvendor_usable_channel,
9453
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9454
+ .policy = usablech_attr_policy,
9455
+ .maxattr = USABLECHAN_ATTRIBUTE_MAX
9456
+#endif // endif
9457
+ },
9458
+ {
9459
+ {
9460
+ .vendor_id = OUI_GOOGLE,
9461
+ .subcmd = WIFI_SUBCMD_SET_MULTISTA_PRIMARY_CONNECTION
9462
+ },
9463
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9464
+ .doit = wl_cfgvendor_set_multista_primary_connection,
9465
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9466
+ .policy = multista_attr_policy,
9467
+ .maxattr = MULTISTA_ATTRIBUTE_MAX
9468
+#endif // endif
9469
+ },
9470
+ {
9471
+ {
9472
+ .vendor_id = OUI_GOOGLE,
9473
+ .subcmd = WIFI_SUBCMD_SET_MULTISTA_USE_CASE
9474
+ },
9475
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9476
+ .doit = wl_cfgvendor_set_multista_use_case,
9477
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9478
+ .policy = multista_attr_policy,
9479
+ .maxattr = MULTISTA_ATTRIBUTE_MAX
9480
+#endif // endif
9481
+ },
9482
+#ifdef WL_SUPPORT_ACS_OFFLOAD
9483
+ {
9484
+ {
9485
+ .vendor_id = OUI_BRCM,
9486
+ .subcmd = BRCM_VENDOR_SCMD_ACS
9487
+ },
9488
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9489
+ .doit = wl_cfgvendor_acs_offload,
9490
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
9491
+ .policy = acs_offload_attr_policy,
9492
+ .maxattr = BRCM_VENDOR_ATTR_ACS_LAST
9493
+#endif /* LINUX_VERSION >= 5.3 */
9494
+ },
9495
+#endif // endif
9496
+
29669497 };
29679498
29689499 static const struct nl80211_vendor_cmd_info wl_vendor_events [] = {
29699500 { OUI_BRCM, BRCM_VENDOR_EVENT_UNSPEC },
29709501 { OUI_BRCM, BRCM_VENDOR_EVENT_PRIV_STR },
2971
-#ifdef GSCAN_SUPPORT
29729502 { OUI_GOOGLE, GOOGLE_GSCAN_SIGNIFICANT_EVENT },
29739503 { OUI_GOOGLE, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT },
29749504 { OUI_GOOGLE, GOOGLE_GSCAN_BATCH_SCAN_EVENT },
29759505 { OUI_GOOGLE, GOOGLE_SCAN_FULL_RESULTS_EVENT },
2976
-#endif /* GSCAN_SUPPORT */
2977
-#ifdef RTT_SUPPORT
29789506 { OUI_GOOGLE, GOOGLE_RTT_COMPLETE_EVENT },
2979
-#endif /* RTT_SUPPORT */
2980
-#ifdef GSCAN_SUPPORT
29819507 { OUI_GOOGLE, GOOGLE_SCAN_COMPLETE_EVENT },
29829508 { OUI_GOOGLE, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT },
29839509 { OUI_GOOGLE, GOOGLE_SCAN_EPNO_EVENT },
2984
-#endif /* GSCAN_SUPPORT */
29859510 { OUI_GOOGLE, GOOGLE_DEBUG_RING_EVENT },
29869511 { OUI_GOOGLE, GOOGLE_FW_DUMP_EVENT },
2987
-#ifdef GSCAN_SUPPORT
29889512 { OUI_GOOGLE, GOOGLE_PNO_HOTSPOT_FOUND_EVENT },
2989
-#endif /* GSCAN_SUPPORT */
29909513 { OUI_GOOGLE, GOOGLE_RSSI_MONITOR_EVENT },
2991
-#ifdef KEEP_ALIVE
29929514 { OUI_GOOGLE, GOOGLE_MKEEP_ALIVE_EVENT },
2993
-#endif
2994
- { OUI_GOOGLE, NAN_EVENT_ENABLED },
2995
- { OUI_GOOGLE, NAN_EVENT_DISABLED },
2996
- { OUI_GOOGLE, NAN_EVENT_PUBLISH_REPLIED },
2997
- { OUI_GOOGLE, NAN_EVENT_PUBLISH_TERMINATED },
2998
- { OUI_GOOGLE, NAN_EVENT_SUBSCRIBE_MATCH },
2999
- { OUI_GOOGLE, NAN_EVENT_SUBSCRIBE_UNMATCH },
3000
- { OUI_GOOGLE, NAN_EVENT_SUBSCRIBE_TERMINATED },
3001
- { OUI_GOOGLE, NAN_EVENT_DE_EVENT },
3002
- { OUI_GOOGLE, NAN_EVENT_FOLLOWUP },
3003
- { OUI_GOOGLE, NAN_EVENT_TCA },
3004
- { OUI_GOOGLE, NAN_EVENT_UNKNOWN }
9515
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_ENABLED},
9516
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_DISABLED},
9517
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH},
9518
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_REPLIED},
9519
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_PUBLISH_TERMINATED},
9520
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED},
9521
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_DE_EVENT},
9522
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_FOLLOWUP},
9523
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND},
9524
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_DATA_REQUEST},
9525
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_DATA_CONFIRMATION},
9526
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_DATA_END},
9527
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_BEACON},
9528
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_SDF},
9529
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_TCA},
9530
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_SUBSCRIBE_UNMATCH},
9531
+ { OUI_GOOGLE, GOOGLE_NAN_EVENT_UNKNOWN},
9532
+ { OUI_GOOGLE, GOOGLE_ROAM_EVENT_START},
9533
+ { OUI_BRCM, BRCM_VENDOR_EVENT_HANGED},
9534
+ { OUI_BRCM, BRCM_VENDOR_EVENT_SAE_KEY},
9535
+ { OUI_BRCM, BRCM_VENDOR_EVENT_BEACON_RECV},
9536
+ { OUI_BRCM, BRCM_VENDOR_EVENT_PORT_AUTHORIZED},
9537
+ { OUI_GOOGLE, GOOGLE_FILE_DUMP_EVENT },
9538
+ { OUI_BRCM, BRCM_VENDOR_EVENT_CU},
9539
+ { OUI_BRCM, BRCM_VENDOR_EVENT_WIPS},
9540
+ { OUI_BRCM, NAN_ASYNC_RESPONSE_DISABLED},
9541
+ { OUI_BRCM, BRCM_VENDOR_EVENT_RCC_INFO},
9542
+ { OUI_BRCM, BRCM_VENDOR_EVENT_ACS},
9543
+ { OUI_BRCM, BRCM_VENDOR_EVENT_OVERTEMP},
30059544 };
30069545
30079546 int wl_cfgvendor_attach(struct wiphy *wiphy, dhd_pub_t *dhd)
30089547 {
30099548
3010
- WL_INFORM(("Vendor: Register BRCM cfg80211 vendor cmd(0x%x) interface \n",
9549
+ WL_INFORM_MEM(("Vendor: Register BRCM cfg80211 vendor cmd(0x%x) interface \n",
30119550 NL80211_CMD_VENDOR));
30129551
30139552 wiphy->vendor_commands = wl_vendor_cmds;
....@@ -3015,24 +9554,163 @@
30159554 wiphy->vendor_events = wl_vendor_events;
30169555 wiphy->n_vendor_events = ARRAY_SIZE(wl_vendor_events);
30179556
9557
+#ifdef DEBUGABILITY
30189558 dhd_os_dbg_register_callback(FW_VERBOSE_RING_ID, wl_cfgvendor_dbg_ring_send_evt);
3019
- dhd_os_dbg_register_callback(FW_EVENT_RING_ID, wl_cfgvendor_dbg_ring_send_evt);
30209559 dhd_os_dbg_register_callback(DHD_EVENT_RING_ID, wl_cfgvendor_dbg_ring_send_evt);
3021
- dhd_os_dbg_register_callback(NAN_EVENT_RING_ID, wl_cfgvendor_dbg_ring_send_evt);
3022
- dhd_os_dbg_register_urgent_notifier(dhd, wl_cfgvendor_dbg_send_urgent_evt);
9560
+#endif /* DEBUGABILITY */
9561
+#ifdef DHD_LOG_DUMP
9562
+ dhd_os_dbg_register_urgent_notifier(dhd, wl_cfgvendor_dbg_send_file_dump_evt);
9563
+#endif /* DHD_LOG_DUMP */
30239564
30249565 return 0;
30259566 }
30269567
30279568 int wl_cfgvendor_detach(struct wiphy *wiphy)
30289569 {
3029
- WL_INFORM(("Vendor: Unregister BRCM cfg80211 vendor interface \n"));
9570
+#ifdef WL_SUPPORT_ACS_OFFLOAD
9571
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
9572
+#endif // endif
9573
+ WL_INFORM_MEM(("Vendor: Unregister BRCM cfg80211 vendor interface \n"));
30309574
30319575 wiphy->vendor_commands = NULL;
30329576 wiphy->vendor_events = NULL;
30339577 wiphy->n_vendor_commands = 0;
30349578 wiphy->n_vendor_events = 0;
30359579
9580
+#ifdef WL_SUPPORT_ACS_OFFLOAD
9581
+ wl_cfgvendor_acs_offload_deinit(cfg->acs_offload);
9582
+#endif // endif
9583
+
30369584 return 0;
30379585 }
3038
-#endif /* defined(WL_VENDOR_EXT_SUPPORT) */
9586
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
9587
+
9588
+#ifdef WL_CFGVENDOR_SEND_HANG_EVENT
9589
+#define WL_VENDOR_STR_MAX_LEN 128
9590
+void
9591
+wl_cfgvendor_send_hang_event(struct net_device *dev, u16 reason)
9592
+{
9593
+ struct bcm_cfg80211 *cfg;
9594
+ struct wiphy *wiphy;
9595
+ struct sk_buff *skb;
9596
+ dhd_pub_t *dhdp;
9597
+ gfp_t kflags;
9598
+ int len = 0;
9599
+ char reason_str[WL_VENDOR_STR_MAX_LEN] = {0x00, };
9600
+
9601
+ cfg = wl_cfg80211_get_bcmcfg();
9602
+ if (!cfg || !cfg->wdev) {
9603
+ WL_ERR(("cfg=%p wdev=%p\n", cfg, (cfg ? cfg->wdev : NULL)));
9604
+ return;
9605
+ }
9606
+
9607
+ wiphy = cfg->wdev->wiphy;
9608
+ if (!wiphy) {
9609
+ WL_ERR(("wiphy is NULL\n"));
9610
+ return;
9611
+ }
9612
+
9613
+ dhdp = (dhd_pub_t *)(cfg->pub);
9614
+ if (!dhdp) {
9615
+ WL_ERR(("dhdp is NULL\n"));
9616
+ return;
9617
+ }
9618
+
9619
+ kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
9620
+
9621
+#ifdef DHD_FW_COREDUMP
9622
+ len = snprintf(reason_str, WL_VENDOR_STR_MAX_LEN,
9623
+ "memdump_type = 0x%x, ", dhdp->memdump_type);
9624
+#endif // endif
9625
+ len = snprintf(reason_str + len, WL_VENDOR_STR_MAX_LEN,
9626
+ "HANG reason = 0x%x", reason);
9627
+
9628
+ /* Alloc the SKB for vendor_event */
9629
+#if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
9630
+ LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
9631
+ skb = cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(dev), WL_VENDOR_STR_MAX_LEN,
9632
+ BRCM_VENDOR_EVENT_HANGED, kflags);
9633
+#else
9634
+ skb = cfg80211_vendor_event_alloc(wiphy, len, BRCM_VENDOR_EVENT_HANGED, kflags);
9635
+#endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
9636
+ /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
9637
+
9638
+ if (!skb) {
9639
+ WL_ERR(("skb allocation is failed\n"));
9640
+ return;
9641
+ }
9642
+ WL_INFORM_MEM(("%s\n", reason_str));
9643
+ nla_put(skb, DEBUG_ATTRIBUTE_HANG_REASON, strlen(reason_str), reason_str);
9644
+ cfg80211_vendor_event(skb, kflags);
9645
+}
9646
+
9647
+void
9648
+wl_copy_hang_info_if_falure(struct net_device *dev, u16 reason, s32 ret)
9649
+{
9650
+ struct bcm_cfg80211 *cfg = NULL;
9651
+ dhd_pub_t *dhd;
9652
+ s32 err = 0;
9653
+ char ioctl_buf[WLC_IOCTL_SMLEN];
9654
+ memuse_info_t mu;
9655
+ int bytes_written = 0;
9656
+ int remain_len = 0;
9657
+
9658
+ if (!dev) {
9659
+ WL_ERR(("dev is null"));
9660
+ return;
9661
+
9662
+ }
9663
+
9664
+ cfg = wl_get_cfg(dev);
9665
+ if (!cfg) {
9666
+ WL_ERR(("dev=%p cfg=%p\n", dev, cfg));
9667
+ return;
9668
+ }
9669
+
9670
+ dhd = (dhd_pub_t *)(cfg->pub);
9671
+
9672
+ if (!dhd || !dhd->hang_info) {
9673
+ WL_ERR(("%s dhd=%p hang_info=%p\n", __FUNCTION__,
9674
+ dhd, (dhd ? dhd->hang_info : NULL)));
9675
+ return;
9676
+ }
9677
+
9678
+ err = wldev_iovar_getbuf_bsscfg(dev, "memuse",
9679
+ NULL, 0, ioctl_buf, WLC_IOCTL_SMLEN, 0, NULL);
9680
+ if (unlikely(err)) {
9681
+ WL_ERR(("error (%d)\n", err));
9682
+ return;
9683
+ }
9684
+
9685
+ memcpy(&mu, ioctl_buf, sizeof(memuse_info_t));
9686
+
9687
+ if (mu.len >= sizeof(memuse_info_t)) {
9688
+ WL_ERR(("Heap Total: %d(%dK)\n", mu.arena_size, KB(mu.arena_size)));
9689
+ WL_ERR(("Free: %d(%dK), LWM: %d(%dK)\n",
9690
+ mu.arena_free, KB(mu.arena_free),
9691
+ mu.free_lwm, KB(mu.free_lwm)));
9692
+ WL_ERR(("In use: %d(%dK), HWM: %d(%dK)\n",
9693
+ mu.inuse_size, KB(mu.inuse_size),
9694
+ mu.inuse_hwm, KB(mu.inuse_hwm)));
9695
+ WL_ERR(("Malloc failure count: %d\n", mu.mf_count));
9696
+ }
9697
+
9698
+ memset(dhd->hang_info, 0, VENDOR_SEND_HANG_EXT_INFO_LEN);
9699
+ remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - bytes_written;
9700
+
9701
+ get_debug_dump_time(dhd->debug_dump_time_hang_str);
9702
+ copy_debug_dump_time(dhd->debug_dump_time_str, dhd->debug_dump_time_hang_str);
9703
+
9704
+ bytes_written += scnprintf(&dhd->hang_info[bytes_written], remain_len,
9705
+ "%d %d %s %d %d %d %d %d %08x %08x",
9706
+ reason, VENDOR_SEND_HANG_EXT_INFO_VER,
9707
+ dhd->debug_dump_time_hang_str,
9708
+ ret, mu.arena_size, mu.arena_free, mu.inuse_size, mu.mf_count, 0, 0);
9709
+
9710
+ dhd->hang_info_cnt = HANG_FIELD_IF_FAILURE_CNT;
9711
+
9712
+ clear_debug_dump_time(dhd->debug_dump_time_hang_str);
9713
+
9714
+ return;
9715
+}
9716
+#endif /* WL_CFGVENDOR_SEND_HANG_EVENT */