1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2019 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15
16 #include <drv_types.h>
17
18 #ifdef CONFIG_IOCTL_CFG80211
19
20 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT)
21
22 /*
23 #include <linux/kernel.h>
24 #include <linux/if_arp.h>
25 #include <asm/uaccess.h>
26
27 #include <linux/kernel.h>
28 #include <linux/kthread.h>
29 #include <linux/netdevice.h>
30 #include <linux/sched.h>
31 #include <linux/etherdevice.h>
32 #include <linux/wireless.h>
33 #include <linux/ieee80211.h>
34 #include <linux/wait.h>
35 #include <net/cfg80211.h>
36 */
37
38 #include <net/rtnetlink.h>
39
40 #ifndef MIN
41 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
42 #endif
43
44 #ifdef DBG_MEM_ALLOC
45 extern bool match_mstat_sniff_rules(const enum mstat_f flags, const size_t size);
dbg_rtw_cfg80211_vendor_event_alloc(struct wiphy * wiphy,struct wireless_dev * wdev,int len,int event_id,gfp_t gfp,const enum mstat_f flags,const char * func,const int line)46 struct sk_buff *dbg_rtw_cfg80211_vendor_event_alloc(struct wiphy *wiphy, struct wireless_dev *wdev, int len, int event_id, gfp_t gfp
47 , const enum mstat_f flags, const char *func, const int line)
48 {
49 struct sk_buff *skb;
50 unsigned int truesize = 0;
51
52 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))
53 skb = cfg80211_vendor_event_alloc(wiphy, len, event_id, gfp);
54 #else
55 skb = cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp);
56 #endif
57
58 if (skb)
59 truesize = skb->truesize;
60
61 if (!skb || truesize < len || match_mstat_sniff_rules(flags, truesize))
62 RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d), skb:%p, truesize=%u\n", func, line, __FUNCTION__, len, skb, truesize);
63
64 rtw_mstat_update(
65 flags
66 , skb ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
67 , truesize
68 );
69
70 return skb;
71 }
72
dbg_rtw_cfg80211_vendor_event(struct sk_buff * skb,gfp_t gfp,const enum mstat_f flags,const char * func,const int line)73 void dbg_rtw_cfg80211_vendor_event(struct sk_buff *skb, gfp_t gfp
74 , const enum mstat_f flags, const char *func, const int line)
75 {
76 unsigned int truesize = skb->truesize;
77
78 if (match_mstat_sniff_rules(flags, truesize))
79 RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __FUNCTION__, truesize);
80
81 cfg80211_vendor_event(skb, gfp);
82
83 rtw_mstat_update(
84 flags
85 , MSTAT_FREE
86 , truesize
87 );
88 }
89
dbg_rtw_cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy * wiphy,int len,const enum mstat_f flags,const char * func,const int line)90 struct sk_buff *dbg_rtw_cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy *wiphy, int len
91 , const enum mstat_f flags, const char *func, const int line)
92 {
93 struct sk_buff *skb;
94 unsigned int truesize = 0;
95
96 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
97
98 if (skb)
99 truesize = skb->truesize;
100
101 if (!skb || truesize < len || match_mstat_sniff_rules(flags, truesize))
102 RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d), skb:%p, truesize=%u\n", func, line, __FUNCTION__, len, skb, truesize);
103
104 rtw_mstat_update(
105 flags
106 , skb ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
107 , truesize
108 );
109
110 return skb;
111 }
112
dbg_rtw_cfg80211_vendor_cmd_reply(struct sk_buff * skb,const enum mstat_f flags,const char * func,const int line)113 int dbg_rtw_cfg80211_vendor_cmd_reply(struct sk_buff *skb
114 , const enum mstat_f flags, const char *func, const int line)
115 {
116 unsigned int truesize = skb->truesize;
117 int ret;
118
119 if (match_mstat_sniff_rules(flags, truesize))
120 RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __FUNCTION__, truesize);
121
122 ret = cfg80211_vendor_cmd_reply(skb);
123
124 rtw_mstat_update(
125 flags
126 , MSTAT_FREE
127 , truesize
128 );
129
130 return ret;
131 }
132
133 #define rtw_cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp) \
134 dbg_rtw_cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)
135
136 #define rtw_cfg80211_vendor_event(skb, gfp) \
137 dbg_rtw_cfg80211_vendor_event(skb, gfp, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)
138
139 #define rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len) \
140 dbg_rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)
141
142 #define rtw_cfg80211_vendor_cmd_reply(skb) \
143 dbg_rtw_cfg80211_vendor_cmd_reply(skb, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)
144 #else
145
rtw_cfg80211_vendor_event_alloc(struct wiphy * wiphy,struct wireless_dev * wdev,int len,int event_id,gfp_t gfp)146 struct sk_buff *rtw_cfg80211_vendor_event_alloc(
147 struct wiphy *wiphy, struct wireless_dev *wdev, int len, int event_id, gfp_t gfp)
148 {
149 struct sk_buff *skb;
150
151 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))
152 skb = cfg80211_vendor_event_alloc(wiphy, len, event_id, gfp);
153 #else
154 skb = cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp);
155 #endif
156 return skb;
157 }
158
159 #define rtw_cfg80211_vendor_event(skb, gfp) \
160 cfg80211_vendor_event(skb, gfp)
161
162 #define rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len) \
163 cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len)
164
165 #define rtw_cfg80211_vendor_cmd_reply(skb) \
166 cfg80211_vendor_cmd_reply(skb)
167 #endif /* DBG_MEM_ALLOC */
168
169 /*
170 * This API is to be used for asynchronous vendor events. This
171 * shouldn't be used in response to a vendor command from its
172 * do_it handler context (instead rtw_cfgvendor_send_cmd_reply should
173 * be used).
174 */
rtw_cfgvendor_send_async_event(struct wiphy * wiphy,struct net_device * dev,int event_id,const void * data,int len)175 int rtw_cfgvendor_send_async_event(struct wiphy *wiphy,
176 struct net_device *dev, int event_id, const void *data, int len)
177 {
178 int kflags;
179 struct sk_buff *skb;
180
181 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
182
183 /* Alloc the SKB for vendor_event */
184 skb = rtw_cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(dev), len, event_id, kflags);
185 if (!skb) {
186 RTW_ERR(FUNC_NDEV_FMT" skb alloc failed", FUNC_NDEV_ARG(dev));
187 return -ENOMEM;
188 }
189
190 /* Push the data to the skb */
191 nla_put_nohdr(skb, len, data);
192
193 rtw_cfg80211_vendor_event(skb, kflags);
194
195 return 0;
196 }
197
rtw_cfgvendor_send_cmd_reply(struct wiphy * wiphy,struct net_device * dev,const void * data,int len)198 static int rtw_cfgvendor_send_cmd_reply(struct wiphy *wiphy,
199 struct net_device *dev, const void *data, int len)
200 {
201 struct sk_buff *skb;
202
203 /* Alloc the SKB for vendor_event */
204 skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
205 if (unlikely(!skb)) {
206 RTW_ERR(FUNC_NDEV_FMT" skb alloc failed", FUNC_NDEV_ARG(dev));
207 return -ENOMEM;
208 }
209
210 /* Push the data to the skb */
211 nla_put_nohdr(skb, len, data);
212
213 return rtw_cfg80211_vendor_cmd_reply(skb);
214 }
215
216 /* Feature enums */
217 #define WIFI_FEATURE_INFRA 0x0001 // Basic infrastructure mode
218 #define WIFI_FEATURE_INFRA_5G 0x0002 // Support for 5 GHz Band
219 #define WIFI_FEATURE_HOTSPOT 0x0004 // Support for GAS/ANQP
220 #define WIFI_FEATURE_P2P 0x0008 // Wifi-Direct
221 #define WIFI_FEATURE_SOFT_AP 0x0010 // Soft AP
222 #define WIFI_FEATURE_GSCAN 0x0020 // Google-Scan APIs
223 #define WIFI_FEATURE_NAN 0x0040 // Neighbor Awareness Networking
224 #define WIFI_FEATURE_D2D_RTT 0x0080 // Device-to-device RTT
225 #define WIFI_FEATURE_D2AP_RTT 0x0100 // Device-to-AP RTT
226 #define WIFI_FEATURE_BATCH_SCAN 0x0200 // Batched Scan (legacy)
227 #define WIFI_FEATURE_PNO 0x0400 // Preferred network offload
228 #define WIFI_FEATURE_ADDITIONAL_STA 0x0800 // Support for two STAs
229 #define WIFI_FEATURE_TDLS 0x1000 // Tunnel directed link setup
230 #define WIFI_FEATURE_TDLS_OFFCHANNEL 0x2000 // Support for TDLS off channel
231 #define WIFI_FEATURE_EPR 0x4000 // Enhanced power reporting
232 #define WIFI_FEATURE_AP_STA 0x8000 // Support for AP STA Concurrency
233 #define WIFI_FEATURE_LINK_LAYER_STATS 0x10000 // Link layer stats collection
234 #define WIFI_FEATURE_LOGGER 0x20000 // WiFi Logger
235 #define WIFI_FEATURE_HAL_EPNO 0x40000 // WiFi PNO enhanced
236 #define WIFI_FEATURE_RSSI_MONITOR 0x80000 // RSSI Monitor
237 #define WIFI_FEATURE_MKEEP_ALIVE 0x100000 // WiFi mkeep_alive
238 #define WIFI_FEATURE_CONFIG_NDO 0x200000 // ND offload configure
239 #define WIFI_FEATURE_TX_TRANSMIT_POWER 0x400000 // Capture Tx transmit power levels
240 #define WIFI_FEATURE_CONTROL_ROAMING 0x800000 // Enable/Disable firmware roaming
241 #define WIFI_FEATURE_IE_WHITELIST 0x1000000 // Support Probe IE white listing
242 #define WIFI_FEATURE_SCAN_RAND 0x2000000 // Support MAC & Probe Sequence Number randomization
243 // Add more features here
244
245 #define MAX_FEATURE_SET_CONCURRRENT_GROUPS 3
246
rtw_dev_get_feature_set(struct net_device * dev)247 int rtw_dev_get_feature_set(struct net_device *dev)
248 {
249 _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
250 int feature_set = 0;
251
252 feature_set |= WIFI_FEATURE_INFRA;
253
254 #if CONFIG_IEEE80211_BAND_5GHZ
255 if (is_supported_5g(adapter_to_regsty(adapter)->band_type))
256 feature_set |= WIFI_FEATURE_INFRA_5G;
257 #endif
258
259 feature_set |= WIFI_FEATURE_P2P;
260 feature_set |= WIFI_FEATURE_SOFT_AP;
261
262 feature_set |= WIFI_FEATURE_ADDITIONAL_STA;
263 #ifdef CONFIG_RTW_CFGVENDOR_LLSTATS
264 feature_set |= WIFI_FEATURE_LINK_LAYER_STATS;
265 #endif /* CONFIG_RTW_CFGVENDOR_LLSTATS */
266
267 #ifdef CONFIG_RTW_CFGVENDOR_RSSIMONITOR
268 feature_set |= WIFI_FEATURE_RSSI_MONITOR;
269 #endif
270
271 #ifdef CONFIG_RTW_CFGVENDOR_WIFI_LOGGER
272 feature_set |= WIFI_FEATURE_LOGGER;
273 #endif
274
275 #ifdef CONFIG_RTW_WIFI_HAL
276 feature_set |= WIFI_FEATURE_CONFIG_NDO;
277 feature_set |= WIFI_FEATURE_SCAN_RAND;
278 #endif
279
280 return feature_set;
281 }
282
rtw_dev_get_feature_set_matrix(struct net_device * dev,int * num)283 int *rtw_dev_get_feature_set_matrix(struct net_device *dev, int *num)
284 {
285 int feature_set_full, mem_needed;
286 int *ret;
287
288 *num = 0;
289 mem_needed = sizeof(int) * MAX_FEATURE_SET_CONCURRRENT_GROUPS;
290 ret = (int *)rtw_malloc(mem_needed);
291
292 if (!ret) {
293 RTW_ERR(FUNC_NDEV_FMT" failed to allocate %d bytes\n"
294 , FUNC_NDEV_ARG(dev), mem_needed);
295 return ret;
296 }
297
298 feature_set_full = rtw_dev_get_feature_set(dev);
299
300 ret[0] = (feature_set_full & WIFI_FEATURE_INFRA) |
301 (feature_set_full & WIFI_FEATURE_INFRA_5G) |
302 (feature_set_full & WIFI_FEATURE_NAN) |
303 (feature_set_full & WIFI_FEATURE_D2D_RTT) |
304 (feature_set_full & WIFI_FEATURE_D2AP_RTT) |
305 (feature_set_full & WIFI_FEATURE_PNO) |
306 (feature_set_full & WIFI_FEATURE_BATCH_SCAN) |
307 (feature_set_full & WIFI_FEATURE_GSCAN) |
308 (feature_set_full & WIFI_FEATURE_HOTSPOT) |
309 (feature_set_full & WIFI_FEATURE_ADDITIONAL_STA) |
310 (feature_set_full & WIFI_FEATURE_EPR);
311
312 ret[1] = (feature_set_full & WIFI_FEATURE_INFRA) |
313 (feature_set_full & WIFI_FEATURE_INFRA_5G) |
314 /* Not yet verified NAN with P2P */
315 /* (feature_set_full & WIFI_FEATURE_NAN) | */
316 (feature_set_full & WIFI_FEATURE_P2P) |
317 (feature_set_full & WIFI_FEATURE_D2AP_RTT) |
318 (feature_set_full & WIFI_FEATURE_D2D_RTT) |
319 (feature_set_full & WIFI_FEATURE_EPR);
320
321 ret[2] = (feature_set_full & WIFI_FEATURE_INFRA) |
322 (feature_set_full & WIFI_FEATURE_INFRA_5G) |
323 (feature_set_full & WIFI_FEATURE_NAN) |
324 (feature_set_full & WIFI_FEATURE_D2D_RTT) |
325 (feature_set_full & WIFI_FEATURE_D2AP_RTT) |
326 (feature_set_full & WIFI_FEATURE_TDLS) |
327 (feature_set_full & WIFI_FEATURE_TDLS_OFFCHANNEL) |
328 (feature_set_full & WIFI_FEATURE_EPR);
329 *num = MAX_FEATURE_SET_CONCURRRENT_GROUPS;
330
331 return ret;
332 }
333
rtw_cfgvendor_get_feature_set(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)334 static int rtw_cfgvendor_get_feature_set(struct wiphy *wiphy,
335 struct wireless_dev *wdev, const void *data, int len)
336 {
337 int err = 0;
338 int reply;
339
340 reply = rtw_dev_get_feature_set(wdev_to_ndev(wdev));
341
342 err = rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev), &reply, sizeof(int));
343
344 if (unlikely(err))
345 RTW_ERR(FUNC_NDEV_FMT" Vendor Command reply failed ret:%d\n"
346 , FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);
347
348 return err;
349 }
350
rtw_cfgvendor_get_feature_set_matrix(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)351 static int rtw_cfgvendor_get_feature_set_matrix(struct wiphy *wiphy,
352 struct wireless_dev *wdev, const void *data, int len)
353 {
354 int err = 0;
355 struct sk_buff *skb;
356 int *reply;
357 int num, mem_needed, i;
358
359 reply = rtw_dev_get_feature_set_matrix(wdev_to_ndev(wdev), &num);
360
361 if (!reply) {
362 RTW_ERR(FUNC_NDEV_FMT" Could not get feature list matrix\n"
363 , FUNC_NDEV_ARG(wdev_to_ndev(wdev)));
364 err = -EINVAL;
365 return err;
366 }
367
368 mem_needed = VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * num) +
369 ATTRIBUTE_U32_LEN;
370
371 /* Alloc the SKB for vendor_event */
372 skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
373 if (unlikely(!skb)) {
374 RTW_ERR(FUNC_NDEV_FMT" skb alloc failed", FUNC_NDEV_ARG(wdev_to_ndev(wdev)));
375 err = -ENOMEM;
376 goto exit;
377 }
378
379 nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, num);
380 for (i = 0; i < num; i++)
381 nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_FEATURE_SET, reply[i]);
382
383 err = rtw_cfg80211_vendor_cmd_reply(skb);
384
385 if (unlikely(err))
386 RTW_ERR(FUNC_NDEV_FMT" Vendor Command reply failed ret:%d\n"
387 , FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);
388 exit:
389 rtw_mfree((u8 *)reply, sizeof(int) * num);
390 return err;
391 }
392
393 #if defined(GSCAN_SUPPORT) && 0
rtw_cfgvendor_send_hotlist_event(struct wiphy * wiphy,struct net_device * dev,void * data,int len,rtw_vendor_event_t event)394 int rtw_cfgvendor_send_hotlist_event(struct wiphy *wiphy,
395 struct net_device *dev, void *data, int len, rtw_vendor_event_t event)
396 {
397 u16 kflags;
398 const void *ptr;
399 struct sk_buff *skb;
400 int malloc_len, total, iter_cnt_to_send, cnt;
401 gscan_results_cache_t *cache = (gscan_results_cache_t *)data;
402
403 total = len / sizeof(wifi_gscan_result_t);
404 while (total > 0) {
405 malloc_len = (total * sizeof(wifi_gscan_result_t)) + VENDOR_DATA_OVERHEAD;
406 if (malloc_len > NLMSG_DEFAULT_SIZE)
407 malloc_len = NLMSG_DEFAULT_SIZE;
408 iter_cnt_to_send =
409 (malloc_len - VENDOR_DATA_OVERHEAD) / sizeof(wifi_gscan_result_t);
410 total = total - iter_cnt_to_send;
411
412 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
413
414 /* Alloc the SKB for vendor_event */
415 skb = rtw_cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(dev), malloc_len, event, kflags);
416 if (!skb) {
417 WL_ERR(("skb alloc failed"));
418 return -ENOMEM;
419 }
420
421 while (cache && iter_cnt_to_send) {
422 ptr = (const void *) &cache->results[cache->tot_consumed];
423
424 if (iter_cnt_to_send < (cache->tot_count - cache->tot_consumed))
425 cnt = iter_cnt_to_send;
426 else
427 cnt = (cache->tot_count - cache->tot_consumed);
428
429 iter_cnt_to_send -= cnt;
430 cache->tot_consumed += cnt;
431 /* Push the data to the skb */
432 nla_append(skb, cnt * sizeof(wifi_gscan_result_t), ptr);
433 if (cache->tot_consumed == cache->tot_count)
434 cache = cache->next;
435
436 }
437
438 rtw_cfg80211_vendor_event(skb, kflags);
439 }
440
441 return 0;
442 }
443
444
rtw_cfgvendor_gscan_get_capabilities(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)445 static int rtw_cfgvendor_gscan_get_capabilities(struct wiphy *wiphy,
446 struct wireless_dev *wdev, const void *data, int len)
447 {
448 int err = 0;
449 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
450 dhd_pno_gscan_capabilities_t *reply = NULL;
451 uint32 reply_len = 0;
452
453
454 reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
455 DHD_PNO_GET_CAPABILITIES, NULL, &reply_len);
456 if (!reply) {
457 WL_ERR(("Could not get capabilities\n"));
458 err = -EINVAL;
459 return err;
460 }
461
462 err = rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
463 reply, reply_len);
464
465 if (unlikely(err))
466 WL_ERR(("Vendor Command reply failed ret:%d\n", err));
467
468 kfree(reply);
469 return err;
470 }
471
rtw_cfgvendor_gscan_get_channel_list(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)472 static int rtw_cfgvendor_gscan_get_channel_list(struct wiphy *wiphy,
473 struct wireless_dev *wdev, const void *data, int len)
474 {
475 int err = 0, type, band;
476 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
477 uint16 *reply = NULL;
478 uint32 reply_len = 0, num_channels, mem_needed;
479 struct sk_buff *skb;
480
481 type = nla_type(data);
482
483 if (type == GSCAN_ATTRIBUTE_BAND)
484 band = nla_get_u32(data);
485 else
486 return -1;
487
488 reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
489 DHD_PNO_GET_CHANNEL_LIST, &band, &reply_len);
490
491 if (!reply) {
492 WL_ERR(("Could not get channel list\n"));
493 err = -EINVAL;
494 return err;
495 }
496 num_channels = reply_len / sizeof(uint32);
497 mem_needed = reply_len + VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * 2);
498
499 /* Alloc the SKB for vendor_event */
500 skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
501 if (unlikely(!skb)) {
502 WL_ERR(("skb alloc failed"));
503 err = -ENOMEM;
504 goto exit;
505 }
506
507 nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channels);
508 nla_put(skb, GSCAN_ATTRIBUTE_CHANNEL_LIST, reply_len, reply);
509
510 err = rtw_cfg80211_vendor_cmd_reply(skb);
511
512 if (unlikely(err))
513 WL_ERR(("Vendor Command reply failed ret:%d\n", err));
514 exit:
515 kfree(reply);
516 return err;
517 }
518
rtw_cfgvendor_gscan_get_batch_results(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)519 static int rtw_cfgvendor_gscan_get_batch_results(struct wiphy *wiphy,
520 struct wireless_dev *wdev, const void *data, int len)
521 {
522 int err = 0;
523 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
524 gscan_results_cache_t *results, *iter;
525 uint32 reply_len, complete = 0, num_results_iter;
526 int32 mem_needed;
527 wifi_gscan_result_t *ptr;
528 uint16 num_scan_ids, num_results;
529 struct sk_buff *skb;
530 struct nlattr *scan_hdr;
531
532 dhd_dev_wait_batch_results_complete(bcmcfg_to_prmry_ndev(cfg));
533 dhd_dev_pno_lock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
534 results = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
535 DHD_PNO_GET_BATCH_RESULTS, NULL, &reply_len);
536
537 if (!results) {
538 WL_ERR(("No results to send %d\n", err));
539 err = rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
540 results, 0);
541
542 if (unlikely(err))
543 WL_ERR(("Vendor Command reply failed ret:%d\n", err));
544 dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
545 return err;
546 }
547 num_scan_ids = reply_len & 0xFFFF;
548 num_results = (reply_len & 0xFFFF0000) >> 16;
549 mem_needed = (num_results * sizeof(wifi_gscan_result_t)) +
550 (num_scan_ids * GSCAN_BATCH_RESULT_HDR_LEN) +
551 VENDOR_REPLY_OVERHEAD + SCAN_RESULTS_COMPLETE_FLAG_LEN;
552
553 if (mem_needed > (int32)NLMSG_DEFAULT_SIZE) {
554 mem_needed = (int32)NLMSG_DEFAULT_SIZE;
555 complete = 0;
556 } else
557 complete = 1;
558
559 WL_TRACE(("complete %d mem_needed %d max_mem %d\n", complete, mem_needed,
560 (int)NLMSG_DEFAULT_SIZE));
561 /* Alloc the SKB for vendor_event */
562 skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
563 if (unlikely(!skb)) {
564 WL_ERR(("skb alloc failed"));
565 dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
566 return -ENOMEM;
567 }
568 iter = results;
569
570 nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, complete);
571
572 mem_needed = mem_needed - (SCAN_RESULTS_COMPLETE_FLAG_LEN + VENDOR_REPLY_OVERHEAD);
573
574 while (iter && ((mem_needed - GSCAN_BATCH_RESULT_HDR_LEN) > 0)) {
575 scan_hdr = nla_nest_start(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS);
576 nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_ID, iter->scan_id);
577 nla_put_u8(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, iter->flag);
578 num_results_iter =
579 (mem_needed - GSCAN_BATCH_RESULT_HDR_LEN) / sizeof(wifi_gscan_result_t);
580
581 if ((iter->tot_count - iter->tot_consumed) < num_results_iter)
582 num_results_iter = iter->tot_count - iter->tot_consumed;
583
584 nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num_results_iter);
585 if (num_results_iter) {
586 ptr = &iter->results[iter->tot_consumed];
587 iter->tot_consumed += num_results_iter;
588 nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS,
589 num_results_iter * sizeof(wifi_gscan_result_t), ptr);
590 }
591 nla_nest_end(skb, scan_hdr);
592 mem_needed -= GSCAN_BATCH_RESULT_HDR_LEN +
593 (num_results_iter * sizeof(wifi_gscan_result_t));
594 iter = iter->next;
595 }
596
597 dhd_dev_gscan_batch_cache_cleanup(bcmcfg_to_prmry_ndev(cfg));
598 dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
599
600 return rtw_cfg80211_vendor_cmd_reply(skb);
601 }
602
rtw_cfgvendor_initiate_gscan(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)603 static int rtw_cfgvendor_initiate_gscan(struct wiphy *wiphy,
604 struct wireless_dev *wdev, const void *data, int len)
605 {
606 int err = 0;
607 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
608 int type, tmp = len;
609 int run = 0xFF;
610 int flush = 0;
611 const struct nlattr *iter;
612
613 nla_for_each_attr(iter, data, len, tmp) {
614 type = nla_type(iter);
615 if (type == GSCAN_ATTRIBUTE_ENABLE_FEATURE)
616 run = nla_get_u32(iter);
617 else if (type == GSCAN_ATTRIBUTE_FLUSH_FEATURE)
618 flush = nla_get_u32(iter);
619 }
620
621 if (run != 0xFF) {
622 err = dhd_dev_pno_run_gscan(bcmcfg_to_prmry_ndev(cfg), run, flush);
623
624 if (unlikely(err))
625 WL_ERR(("Could not run gscan:%d\n", err));
626 return err;
627 } else
628 return -1;
629
630
631 }
632
rtw_cfgvendor_enable_full_scan_result(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)633 static int rtw_cfgvendor_enable_full_scan_result(struct wiphy *wiphy,
634 struct wireless_dev *wdev, const void *data, int len)
635 {
636 int err = 0;
637 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
638 int type;
639 bool real_time = FALSE;
640
641 type = nla_type(data);
642
643 if (type == GSCAN_ATTRIBUTE_ENABLE_FULL_SCAN_RESULTS) {
644 real_time = nla_get_u32(data);
645
646 err = dhd_dev_pno_enable_full_scan_result(bcmcfg_to_prmry_ndev(cfg), real_time);
647
648 if (unlikely(err))
649 WL_ERR(("Could not run gscan:%d\n", err));
650
651 } else
652 err = -1;
653
654 return err;
655 }
656
rtw_cfgvendor_set_scan_cfg(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)657 static int rtw_cfgvendor_set_scan_cfg(struct wiphy *wiphy,
658 struct wireless_dev *wdev, const void *data, int len)
659 {
660 int err = 0;
661 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
662 gscan_scan_params_t *scan_param;
663 int j = 0;
664 int type, tmp, tmp1, tmp2, k = 0;
665 const struct nlattr *iter, *iter1, *iter2;
666 struct dhd_pno_gscan_channel_bucket *ch_bucket;
667
668 scan_param = kzalloc(sizeof(gscan_scan_params_t), GFP_KERNEL);
669 if (!scan_param) {
670 WL_ERR(("Could not set GSCAN scan cfg, mem alloc failure\n"));
671 err = -EINVAL;
672 return err;
673
674 }
675
676 scan_param->scan_fr = PNO_SCAN_MIN_FW_SEC;
677 nla_for_each_attr(iter, data, len, tmp) {
678 type = nla_type(iter);
679
680 if (j >= GSCAN_MAX_CH_BUCKETS)
681 break;
682
683 switch (type) {
684 case GSCAN_ATTRIBUTE_BASE_PERIOD:
685 scan_param->scan_fr = nla_get_u32(iter) / 1000;
686 break;
687 case GSCAN_ATTRIBUTE_NUM_BUCKETS:
688 scan_param->nchannel_buckets = nla_get_u32(iter);
689 break;
690 case GSCAN_ATTRIBUTE_CH_BUCKET_1:
691 case GSCAN_ATTRIBUTE_CH_BUCKET_2:
692 case GSCAN_ATTRIBUTE_CH_BUCKET_3:
693 case GSCAN_ATTRIBUTE_CH_BUCKET_4:
694 case GSCAN_ATTRIBUTE_CH_BUCKET_5:
695 case GSCAN_ATTRIBUTE_CH_BUCKET_6:
696 case GSCAN_ATTRIBUTE_CH_BUCKET_7:
697 nla_for_each_nested(iter1, iter, tmp1) {
698 type = nla_type(iter1);
699 ch_bucket =
700 scan_param->channel_bucket;
701
702 switch (type) {
703 case GSCAN_ATTRIBUTE_BUCKET_ID:
704 break;
705 case GSCAN_ATTRIBUTE_BUCKET_PERIOD:
706 ch_bucket[j].bucket_freq_multiple =
707 nla_get_u32(iter1) / 1000;
708 break;
709 case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS:
710 ch_bucket[j].num_channels =
711 nla_get_u32(iter1);
712 break;
713 case GSCAN_ATTRIBUTE_BUCKET_CHANNELS:
714 nla_for_each_nested(iter2, iter1, tmp2) {
715 if (k >= PFN_SWC_RSSI_WINDOW_MAX)
716 break;
717 ch_bucket[j].chan_list[k] =
718 nla_get_u32(iter2);
719 k++;
720 }
721 k = 0;
722 break;
723 case GSCAN_ATTRIBUTE_BUCKETS_BAND:
724 ch_bucket[j].band = (uint16)
725 nla_get_u32(iter1);
726 break;
727 case GSCAN_ATTRIBUTE_REPORT_EVENTS:
728 ch_bucket[j].report_flag = (uint8)
729 nla_get_u32(iter1);
730 break;
731 }
732 }
733 j++;
734 break;
735 }
736 }
737
738 if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
739 DHD_PNO_SCAN_CFG_ID, scan_param, 0) < 0) {
740 WL_ERR(("Could not set GSCAN scan cfg\n"));
741 err = -EINVAL;
742 }
743
744 kfree(scan_param);
745 return err;
746
747 }
748
rtw_cfgvendor_hotlist_cfg(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)749 static int rtw_cfgvendor_hotlist_cfg(struct wiphy *wiphy,
750 struct wireless_dev *wdev, const void *data, int len)
751 {
752 int err = 0;
753 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
754 gscan_hotlist_scan_params_t *hotlist_params;
755 int tmp, tmp1, tmp2, type, j = 0, dummy;
756 const struct nlattr *outer, *inner, *iter;
757 uint8 flush = 0;
758 struct bssid_t *pbssid;
759
760 hotlist_params = (gscan_hotlist_scan_params_t *)kzalloc(len, GFP_KERNEL);
761 if (!hotlist_params) {
762 WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes\n", len));
763 return -1;
764 }
765
766 hotlist_params->lost_ap_window = GSCAN_LOST_AP_WINDOW_DEFAULT;
767
768 nla_for_each_attr(iter, data, len, tmp2) {
769 type = nla_type(iter);
770 switch (type) {
771 case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS:
772 pbssid = hotlist_params->bssid;
773 nla_for_each_nested(outer, iter, tmp) {
774 nla_for_each_nested(inner, outer, tmp1) {
775 type = nla_type(inner);
776
777 switch (type) {
778 case GSCAN_ATTRIBUTE_BSSID:
779 _rtw_memcpy(&(pbssid[j].macaddr),
780 nla_data(inner), ETHER_ADDR_LEN);
781 break;
782 case GSCAN_ATTRIBUTE_RSSI_LOW:
783 pbssid[j].rssi_reporting_threshold =
784 (int8) nla_get_u8(inner);
785 break;
786 case GSCAN_ATTRIBUTE_RSSI_HIGH:
787 dummy = (int8) nla_get_u8(inner);
788 break;
789 }
790 }
791 j++;
792 }
793 hotlist_params->nbssid = j;
794 break;
795 case GSCAN_ATTRIBUTE_HOTLIST_FLUSH:
796 flush = nla_get_u8(iter);
797 break;
798 case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
799 hotlist_params->lost_ap_window = nla_get_u32(iter);
800 break;
801 }
802
803 }
804
805 if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
806 DHD_PNO_GEOFENCE_SCAN_CFG_ID, hotlist_params, flush) < 0) {
807 WL_ERR(("Could not set GSCAN HOTLIST cfg\n"));
808 err = -EINVAL;
809 goto exit;
810 }
811 exit:
812 kfree(hotlist_params);
813 return err;
814 }
rtw_cfgvendor_set_batch_scan_cfg(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)815 static int rtw_cfgvendor_set_batch_scan_cfg(struct wiphy *wiphy,
816 struct wireless_dev *wdev, const void *data, int len)
817 {
818 int err = 0, tmp, type;
819 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
820 gscan_batch_params_t batch_param;
821 const struct nlattr *iter;
822
823 batch_param.mscan = batch_param.bestn = 0;
824 batch_param.buffer_threshold = GSCAN_BATCH_NO_THR_SET;
825
826 nla_for_each_attr(iter, data, len, tmp) {
827 type = nla_type(iter);
828
829 switch (type) {
830 case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN:
831 batch_param.bestn = nla_get_u32(iter);
832 break;
833 case GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE:
834 batch_param.mscan = nla_get_u32(iter);
835 break;
836 case GSCAN_ATTRIBUTE_REPORT_THRESHOLD:
837 batch_param.buffer_threshold = nla_get_u32(iter);
838 break;
839 }
840 }
841
842 if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
843 DHD_PNO_BATCH_SCAN_CFG_ID, &batch_param, 0) < 0) {
844 WL_ERR(("Could not set batch cfg\n"));
845 err = -EINVAL;
846 return err;
847 }
848
849 return err;
850 }
851
rtw_cfgvendor_significant_change_cfg(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)852 static int rtw_cfgvendor_significant_change_cfg(struct wiphy *wiphy,
853 struct wireless_dev *wdev, const void *data, int len)
854 {
855 int err = 0;
856 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
857 gscan_swc_params_t *significant_params;
858 int tmp, tmp1, tmp2, type, j = 0;
859 const struct nlattr *outer, *inner, *iter;
860 uint8 flush = 0;
861 wl_pfn_significant_bssid_t *pbssid;
862
863 significant_params = (gscan_swc_params_t *) kzalloc(len, GFP_KERNEL);
864 if (!significant_params) {
865 WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes\n", len));
866 return -1;
867 }
868
869
870 nla_for_each_attr(iter, data, len, tmp2) {
871 type = nla_type(iter);
872
873 switch (type) {
874 case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH:
875 flush = nla_get_u8(iter);
876 break;
877 case GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE:
878 significant_params->rssi_window = nla_get_u16(iter);
879 break;
880 case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
881 significant_params->lost_ap_window = nla_get_u16(iter);
882 break;
883 case GSCAN_ATTRIBUTE_MIN_BREACHING:
884 significant_params->swc_threshold = nla_get_u16(iter);
885 break;
886 case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS:
887 pbssid = significant_params->bssid_elem_list;
888 nla_for_each_nested(outer, iter, tmp) {
889 nla_for_each_nested(inner, outer, tmp1) {
890 switch (nla_type(inner)) {
891 case GSCAN_ATTRIBUTE_BSSID:
892 _rtw_memcpy(&(pbssid[j].macaddr),
893 nla_data(inner),
894 ETHER_ADDR_LEN);
895 break;
896 case GSCAN_ATTRIBUTE_RSSI_HIGH:
897 pbssid[j].rssi_high_threshold =
898 (int8) nla_get_u8(inner);
899 break;
900 case GSCAN_ATTRIBUTE_RSSI_LOW:
901 pbssid[j].rssi_low_threshold =
902 (int8) nla_get_u8(inner);
903 break;
904 }
905 }
906 j++;
907 }
908 break;
909 }
910 }
911 significant_params->nbssid = j;
912
913 if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
914 DHD_PNO_SIGNIFICANT_SCAN_CFG_ID, significant_params, flush) < 0) {
915 WL_ERR(("Could not set GSCAN significant cfg\n"));
916 err = -EINVAL;
917 goto exit;
918 }
919 exit:
920 kfree(significant_params);
921 return err;
922 }
923 #endif /* GSCAN_SUPPORT */
924
925 #if defined(RTT_SUPPORT) && 0
rtw_cfgvendor_rtt_evt(void * ctx,void * rtt_data)926 void rtw_cfgvendor_rtt_evt(void *ctx, void *rtt_data)
927 {
928 struct wireless_dev *wdev = (struct wireless_dev *)ctx;
929 struct wiphy *wiphy;
930 struct sk_buff *skb;
931 uint32 tot_len = NLMSG_DEFAULT_SIZE, entry_len = 0;
932 gfp_t kflags;
933 rtt_report_t *rtt_report = NULL;
934 rtt_result_t *rtt_result = NULL;
935 struct list_head *rtt_list;
936 wiphy = wdev->wiphy;
937
938 WL_DBG(("In\n"));
939 /* Push the data to the skb */
940 if (!rtt_data) {
941 WL_ERR(("rtt_data is NULL\n"));
942 goto exit;
943 }
944 rtt_list = (struct list_head *)rtt_data;
945 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
946 /* Alloc the SKB for vendor_event */
947 skb = rtw_cfg80211_vendor_event_alloc(wiphy, wdev, tot_len, GOOGLE_RTT_COMPLETE_EVENT, kflags);
948 if (!skb) {
949 WL_ERR(("skb alloc failed"));
950 goto exit;
951 }
952 /* fill in the rtt results on each entry */
953 list_for_each_entry(rtt_result, rtt_list, list) {
954 entry_len = 0;
955 if (rtt_result->TOF_type == TOF_TYPE_ONE_WAY) {
956 entry_len = sizeof(rtt_report_t);
957 rtt_report = kzalloc(entry_len, kflags);
958 if (!rtt_report) {
959 WL_ERR(("rtt_report alloc failed"));
960 goto exit;
961 }
962 rtt_report->addr = rtt_result->peer_mac;
963 rtt_report->num_measurement = 1; /* ONE SHOT */
964 rtt_report->status = rtt_result->err_code;
965 rtt_report->type = (rtt_result->TOF_type == TOF_TYPE_ONE_WAY) ? RTT_ONE_WAY : RTT_TWO_WAY;
966 rtt_report->peer = rtt_result->target_info->peer;
967 rtt_report->channel = rtt_result->target_info->channel;
968 rtt_report->rssi = rtt_result->avg_rssi;
969 /* tx_rate */
970 rtt_report->tx_rate = rtt_result->tx_rate;
971 /* RTT */
972 rtt_report->rtt = rtt_result->meanrtt;
973 rtt_report->rtt_sd = rtt_result->sdrtt;
974 /* convert to centi meter */
975 if (rtt_result->distance != 0xffffffff)
976 rtt_report->distance = (rtt_result->distance >> 2) * 25;
977 else /* invalid distance */
978 rtt_report->distance = -1;
979
980 rtt_report->ts = rtt_result->ts;
981 nla_append(skb, entry_len, rtt_report);
982 kfree(rtt_report);
983 }
984 }
985 rtw_cfg80211_vendor_event(skb, kflags);
986 exit:
987 return;
988 }
989
rtw_cfgvendor_rtt_set_config(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)990 static int rtw_cfgvendor_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev,
991 const void *data, int len)
992 {
993 int err = 0, rem, rem1, rem2, type;
994 rtt_config_params_t rtt_param;
995 rtt_target_info_t *rtt_target = NULL;
996 const struct nlattr *iter, *iter1, *iter2;
997 int8 eabuf[ETHER_ADDR_STR_LEN];
998 int8 chanbuf[CHANSPEC_STR_LEN];
999 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1000
1001 WL_DBG(("In\n"));
1002 err = dhd_dev_rtt_register_noti_callback(wdev->netdev, wdev, wl_cfgvendor_rtt_evt);
1003 if (err < 0) {
1004 WL_ERR(("failed to register rtt_noti_callback\n"));
1005 goto exit;
1006 }
1007 memset(&rtt_param, 0, sizeof(rtt_param));
1008 nla_for_each_attr(iter, data, len, rem) {
1009 type = nla_type(iter);
1010 switch (type) {
1011 case RTT_ATTRIBUTE_TARGET_CNT:
1012 rtt_param.rtt_target_cnt = nla_get_u8(iter);
1013 if (rtt_param.rtt_target_cnt > RTT_MAX_TARGET_CNT) {
1014 WL_ERR(("exceed max target count : %d\n",
1015 rtt_param.rtt_target_cnt));
1016 err = BCME_RANGE;
1017 }
1018 break;
1019 case RTT_ATTRIBUTE_TARGET_INFO:
1020 rtt_target = rtt_param.target_info;
1021 nla_for_each_nested(iter1, iter, rem1) {
1022 nla_for_each_nested(iter2, iter1, rem2) {
1023 type = nla_type(iter2);
1024 switch (type) {
1025 case RTT_ATTRIBUTE_TARGET_MAC:
1026 _rtw_memcpy(&rtt_target->addr, nla_data(iter2), ETHER_ADDR_LEN);
1027 break;
1028 case RTT_ATTRIBUTE_TARGET_TYPE:
1029 rtt_target->type = nla_get_u8(iter2);
1030 break;
1031 case RTT_ATTRIBUTE_TARGET_PEER:
1032 rtt_target->peer = nla_get_u8(iter2);
1033 break;
1034 case RTT_ATTRIBUTE_TARGET_CHAN:
1035 _rtw_memcpy(&rtt_target->channel, nla_data(iter2),
1036 sizeof(rtt_target->channel));
1037 break;
1038 case RTT_ATTRIBUTE_TARGET_MODE:
1039 rtt_target->continuous = nla_get_u8(iter2);
1040 break;
1041 case RTT_ATTRIBUTE_TARGET_INTERVAL:
1042 rtt_target->interval = nla_get_u32(iter2);
1043 break;
1044 case RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT:
1045 rtt_target->measure_cnt = nla_get_u32(iter2);
1046 break;
1047 case RTT_ATTRIBUTE_TARGET_NUM_PKT:
1048 rtt_target->ftm_cnt = nla_get_u32(iter2);
1049 break;
1050 case RTT_ATTRIBUTE_TARGET_NUM_RETRY:
1051 rtt_target->retry_cnt = nla_get_u32(iter2);
1052 }
1053 }
1054 /* convert to chanspec value */
1055 rtt_target->chanspec = dhd_rtt_convert_to_chspec(rtt_target->channel);
1056 if (rtt_target->chanspec == 0) {
1057 WL_ERR(("Channel is not valid\n"));
1058 goto exit;
1059 }
1060 WL_INFORM(("Target addr %s, Channel : %s for RTT\n",
1061 bcm_ether_ntoa((const struct ether_addr *)&rtt_target->addr, eabuf),
1062 wf_chspec_ntoa(rtt_target->chanspec, chanbuf)));
1063 rtt_target++;
1064 }
1065 break;
1066 }
1067 }
1068 WL_DBG(("leave :target_cnt : %d\n", rtt_param.rtt_target_cnt));
1069 if (dhd_dev_rtt_set_cfg(bcmcfg_to_prmry_ndev(cfg), &rtt_param) < 0) {
1070 WL_ERR(("Could not set RTT configuration\n"));
1071 err = -EINVAL;
1072 }
1073 exit:
1074 return err;
1075 }
1076
rtw_cfgvendor_rtt_cancel_config(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1077 static int rtw_cfgvendor_rtt_cancel_config(struct wiphy *wiphy, struct wireless_dev *wdev,
1078 const void *data, int len)
1079 {
1080 int err = 0, rem, type, target_cnt = 0;
1081 const struct nlattr *iter;
1082 struct ether_addr *mac_list = NULL, *mac_addr = NULL;
1083 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1084
1085 nla_for_each_attr(iter, data, len, rem) {
1086 type = nla_type(iter);
1087 switch (type) {
1088 case RTT_ATTRIBUTE_TARGET_CNT:
1089 target_cnt = nla_get_u8(iter);
1090 mac_list = (struct ether_addr *)kzalloc(target_cnt * ETHER_ADDR_LEN , GFP_KERNEL);
1091 if (mac_list == NULL) {
1092 WL_ERR(("failed to allocate mem for mac list\n"));
1093 goto exit;
1094 }
1095 mac_addr = &mac_list[0];
1096 break;
1097 case RTT_ATTRIBUTE_TARGET_MAC:
1098 if (mac_addr)
1099 _rtw_memcpy(mac_addr++, nla_data(iter), ETHER_ADDR_LEN);
1100 else {
1101 WL_ERR(("mac_list is NULL\n"));
1102 goto exit;
1103 }
1104 break;
1105 }
1106 if (dhd_dev_rtt_cancel_cfg(bcmcfg_to_prmry_ndev(cfg), mac_list, target_cnt) < 0) {
1107 WL_ERR(("Could not cancel RTT configuration\n"));
1108 err = -EINVAL;
1109 goto exit;
1110 }
1111 }
1112 exit:
1113 if (mac_list)
1114 kfree(mac_list);
1115 return err;
1116 }
rtw_cfgvendor_rtt_get_capability(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1117 static int rtw_cfgvendor_rtt_get_capability(struct wiphy *wiphy, struct wireless_dev *wdev,
1118 const void *data, int len)
1119 {
1120 int err = 0;
1121 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1122 rtt_capabilities_t capability;
1123
1124 err = dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg), &capability);
1125 if (unlikely(err)) {
1126 WL_ERR(("Vendor Command reply failed ret:%d\n", err));
1127 goto exit;
1128 }
1129 err = rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
1130 &capability, sizeof(capability));
1131
1132 if (unlikely(err))
1133 WL_ERR(("Vendor Command reply failed ret:%d\n", err));
1134 exit:
1135 return err;
1136 }
1137
1138 #endif /* RTT_SUPPORT */
1139
1140 #ifdef CONFIG_RTW_CFGVENDOR_LLSTATS
1141 enum {
1142 LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START,
1143 LSTATS_SUBCMD_SET_INFO,
1144 LSTATS_SUBCMD_CLEAR_INFO,
1145 };
LinkLayerStats(_adapter * padapter)1146 static void LinkLayerStats(_adapter *padapter)
1147 {
1148 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
1149 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1150 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
1151 u32 ps_time, trx_total_time;
1152 u64 tx_bytes, rx_bytes, trx_total_bytes = 0;
1153 u64 tmp = 0;
1154
1155 RTW_DBG("%s adapter type : %u\n", __func__, padapter->adapter_type);
1156
1157 tx_bytes = 0;
1158 rx_bytes = 0;
1159 ps_time = 0;
1160 trx_total_time = 0;
1161
1162 if ( padapter->netif_up == _TRUE ) {
1163
1164 pwrpriv->on_time = rtw_get_passing_time_ms(pwrpriv->radio_on_start_time);
1165
1166 if (rtw_mi_check_fwstate(padapter, WIFI_ASOC_STATE)) {
1167 if ( pwrpriv->bpower_saving == _TRUE ) {
1168 pwrpriv->pwr_saving_time += rtw_get_passing_time_ms(pwrpriv->pwr_saving_start_time);
1169 pwrpriv->pwr_saving_start_time = rtw_get_current_time();
1170 }
1171 } else {
1172 #ifdef CONFIG_IPS
1173 if ( pwrpriv->bpower_saving == _TRUE ) {
1174 pwrpriv->pwr_saving_time += rtw_get_passing_time_ms(pwrpriv->pwr_saving_start_time);
1175 pwrpriv->pwr_saving_start_time = rtw_get_current_time();
1176 }
1177 #else
1178 pwrpriv->pwr_saving_time = pwrpriv->on_time;
1179 #endif
1180 }
1181
1182 ps_time = pwrpriv->pwr_saving_time;
1183
1184 /* Deviation caused by caculation start time */
1185 if ( ps_time > pwrpriv->on_time )
1186 ps_time = pwrpriv->on_time;
1187
1188 tx_bytes = pdvobjpriv->traffic_stat.last_tx_bytes;
1189 rx_bytes = pdvobjpriv->traffic_stat.last_rx_bytes;
1190 trx_total_bytes = tx_bytes + rx_bytes;
1191
1192 trx_total_time = pwrpriv->on_time - ps_time;
1193
1194 if ( trx_total_bytes == 0) {
1195 pwrpriv->tx_time = 0;
1196 pwrpriv->rx_time = 0;
1197 } else {
1198
1199 /* tx_time = (trx_total_time * tx_total_bytes) / trx_total_bytes; */
1200 /* rx_time = (trx_total_time * rx_total_bytes) / trx_total_bytes; */
1201
1202 tmp = (tx_bytes * trx_total_time);
1203 tmp = rtw_division64(tmp, trx_total_bytes);
1204 pwrpriv->tx_time = tmp;
1205
1206 tmp = (rx_bytes * trx_total_time);
1207 tmp = rtw_division64(tmp, trx_total_bytes);
1208 pwrpriv->rx_time = tmp;
1209
1210 }
1211
1212 }
1213 else {
1214 pwrpriv->on_time = 0;
1215 pwrpriv->tx_time = 0;
1216 pwrpriv->rx_time = 0;
1217 }
1218
1219 #ifdef CONFIG_RTW_WIFI_HAL_DEBUG
1220 RTW_INFO("- tx_bytes : %llu rx_bytes : %llu total bytes : %llu\n", tx_bytes, rx_bytes, trx_total_bytes);
1221 RTW_INFO("- netif_up = %s, on_time : %u ms\n", padapter->netif_up ? "1":"0", pwrpriv->on_time);
1222 RTW_INFO("- pwr_saving_time : %u (%u) ms\n", pwrpriv->pwr_saving_time, ps_time);
1223 RTW_INFO("- trx_total_time : %u ms\n", trx_total_time);
1224 RTW_INFO("- tx_time : %u ms\n", pwrpriv->tx_time);
1225 RTW_INFO("- rx_time : %u ms\n", pwrpriv->rx_time);
1226 #endif /* CONFIG_RTW_WIFI_HAL_DEBUG */
1227
1228 }
1229
1230 #define DUMMY_TIME_STATICS 99
rtw_cfgvendor_lstats_get_info(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1231 static int rtw_cfgvendor_lstats_get_info(struct wiphy *wiphy,
1232 struct wireless_dev *wdev, const void *data, int len)
1233 {
1234 int err = 0;
1235 _adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));
1236 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1237 wifi_radio_stat_internal *radio;
1238 wifi_iface_stat *iface;
1239 char *output;
1240
1241 output = rtw_malloc(sizeof(wifi_radio_stat_internal) + sizeof(wifi_iface_stat));
1242 if (output == NULL) {
1243 RTW_DBG("Allocate lstats info buffer fail!\n");
1244 }
1245
1246 radio = (wifi_radio_stat_internal *)output;
1247
1248 radio->num_channels = 0;
1249 radio->radio = 1;
1250
1251 /* to get on_time, tx_time, rx_time */
1252 LinkLayerStats(padapter);
1253
1254 radio->on_time = pwrpriv->on_time;
1255 radio->tx_time = pwrpriv->tx_time;
1256 radio->rx_time = pwrpriv->rx_time;
1257 radio->on_time_scan = 0;
1258 radio->on_time_nbd = 0;
1259 radio->on_time_gscan = 0;
1260 radio->on_time_pno_scan = 0;
1261 radio->on_time_hs20 = 0;
1262 #ifdef CONFIG_RTW_WIFI_HAL_DEBUG
1263 RTW_INFO("==== %s ====\n", __func__);
1264 RTW_INFO("radio->radio : %d\n", (radio->radio));
1265 RTW_INFO("pwrpriv->on_time : %u ms\n", (pwrpriv->on_time));
1266 RTW_INFO("pwrpriv->tx_time : %u ms\n", (pwrpriv->tx_time));
1267 RTW_INFO("pwrpriv->rx_time : %u ms\n", (pwrpriv->rx_time));
1268 RTW_INFO("radio->on_time : %u ms\n", (radio->on_time));
1269 RTW_INFO("radio->tx_time : %u ms\n", (radio->tx_time));
1270 RTW_INFO("radio->rx_time : %u ms\n", (radio->rx_time));
1271 #endif /* CONFIG_RTW_WIFI_HAL_DEBUG */
1272
1273 RTW_DBG(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char*)data);
1274 err = rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev),
1275 output, sizeof(wifi_iface_stat) + sizeof(wifi_radio_stat_internal));
1276 if (unlikely(err))
1277 RTW_ERR(FUNC_NDEV_FMT"Vendor Command reply failed ret:%d \n"
1278 , FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);
1279 rtw_mfree(output, sizeof(wifi_iface_stat) + sizeof(wifi_radio_stat_internal));
1280 return err;
1281 }
rtw_cfgvendor_lstats_set_info(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1282 static int rtw_cfgvendor_lstats_set_info(struct wiphy *wiphy,
1283 struct wireless_dev *wdev, const void *data, int len)
1284 {
1285 int err = 0;
1286 RTW_INFO("%s\n", __func__);
1287 return err;
1288 }
rtw_cfgvendor_lstats_clear_info(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1289 static int rtw_cfgvendor_lstats_clear_info(struct wiphy *wiphy,
1290 struct wireless_dev *wdev, const void *data, int len)
1291 {
1292 int err = 0;
1293 RTW_INFO("%s\n", __func__);
1294 return err;
1295 }
1296 #endif /* CONFIG_RTW_CFGVENDOR_LLSTATS */
1297 #ifdef CONFIG_RTW_CFGVENDOR_RSSIMONITOR
rtw_cfgvendor_set_rssi_monitor(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1298 static int rtw_cfgvendor_set_rssi_monitor(struct wiphy *wiphy,
1299 struct wireless_dev *wdev, const void *data, int len)
1300 {
1301 _adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));
1302 struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
1303 int err = 0, rem, type;
1304 const struct nlattr *iter;
1305
1306 RTW_DBG(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char*)data);
1307
1308 nla_for_each_attr(iter, data, len, rem) {
1309 type = nla_type(iter);
1310
1311 switch (type) {
1312 case RSSI_MONITOR_ATTRIBUTE_MAX_RSSI:
1313 pwdev_priv->rssi_monitor_max = (s8)nla_get_u32(iter);;
1314 break;
1315 case RSSI_MONITOR_ATTRIBUTE_MIN_RSSI:
1316 pwdev_priv->rssi_monitor_min = (s8)nla_get_u32(iter);
1317 break;
1318 case RSSI_MONITOR_ATTRIBUTE_START:
1319 pwdev_priv->rssi_monitor_enable = (u8)nla_get_u32(iter);
1320 break;
1321 }
1322 }
1323
1324 return err;
1325 }
1326
rtw_cfgvendor_rssi_monitor_evt(_adapter * padapter)1327 void rtw_cfgvendor_rssi_monitor_evt(_adapter *padapter) {
1328 struct wireless_dev *wdev = padapter->rtw_wdev;
1329 struct wiphy *wiphy= wdev->wiphy;
1330 struct recv_info *precvinfo = &padapter->recvinfo;
1331 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1332 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
1333 struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
1334 struct sk_buff *skb;
1335 u32 tot_len = NLMSG_DEFAULT_SIZE;
1336 gfp_t kflags;
1337 rssi_monitor_evt data ;
1338 s8 rssi = precvinfo->rssi;
1339
1340 if (pwdev_priv->rssi_monitor_enable == 0 || check_fwstate(pmlmepriv, WIFI_ASOC_STATE) != _TRUE)
1341 return;
1342
1343 if (rssi < pwdev_priv->rssi_monitor_max || rssi > pwdev_priv->rssi_monitor_min)
1344 return;
1345
1346 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
1347
1348 /* Alloc the SKB for vendor_event */
1349 skb = rtw_cfg80211_vendor_event_alloc(wiphy, wdev, tot_len, GOOGLE_RSSI_MONITOR_EVENT, kflags);
1350 if (!skb) {
1351 goto exit;
1352 }
1353
1354 _rtw_memset(&data, 0, sizeof(data));
1355
1356 data.version = RSSI_MONITOR_EVT_VERSION;
1357 data.cur_rssi = rssi;
1358 _rtw_memcpy(data.BSSID, pcur_network->network.MacAddress, sizeof(mac_addr));
1359
1360 nla_append(skb, sizeof(data), &data);
1361
1362 rtw_cfg80211_vendor_event(skb, kflags);
1363 exit:
1364 return;
1365 }
1366 #endif /* CONFIG_RTW_CFGVENDOR_RSSIMONITR */
1367
1368 #ifdef CONFIG_RTW_CFGVENDOR_WIFI_LOGGER
rtw_cfgvendor_logger_start_logging(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1369 static int rtw_cfgvendor_logger_start_logging(struct wiphy *wiphy,
1370 struct wireless_dev *wdev, const void *data, int len)
1371 {
1372 int ret = 0, rem, type;
1373 char ring_name[32] = {0};
1374 int log_level = 0, flags = 0, time_intval = 0, threshold = 0;
1375 const struct nlattr *iter;
1376
1377 nla_for_each_attr(iter, data, len, rem) {
1378 type = nla_type(iter);
1379 switch (type) {
1380 case LOGGER_ATTRIBUTE_RING_NAME:
1381 strncpy(ring_name, nla_data(iter),
1382 MIN(sizeof(ring_name) -1, nla_len(iter)));
1383 break;
1384 case LOGGER_ATTRIBUTE_LOG_LEVEL:
1385 log_level = nla_get_u32(iter);
1386 break;
1387 case LOGGER_ATTRIBUTE_RING_FLAGS:
1388 flags = nla_get_u32(iter);
1389 break;
1390 case LOGGER_ATTRIBUTE_LOG_TIME_INTVAL:
1391 time_intval = nla_get_u32(iter);
1392 break;
1393 case LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE:
1394 threshold = nla_get_u32(iter);
1395 break;
1396 default:
1397 RTW_ERR("Unknown type: %d\n", type);
1398 ret = WIFI_ERROR_INVALID_ARGS;
1399 goto exit;
1400 }
1401 }
1402
1403 exit:
1404 return ret;
1405 }
rtw_cfgvendor_logger_get_feature(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1406 static int rtw_cfgvendor_logger_get_feature(struct wiphy *wiphy,
1407 struct wireless_dev *wdev, const void *data, int len)
1408 {
1409 int err = 0;
1410 u32 supported_features = 0;
1411
1412 err = rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev), &supported_features, sizeof(supported_features));
1413
1414 if (unlikely(err))
1415 RTW_ERR(FUNC_NDEV_FMT" Vendor Command reply failed ret:%d\n"
1416 , FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);
1417
1418 return err;
1419 }
rtw_cfgvendor_logger_get_version(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1420 static int rtw_cfgvendor_logger_get_version(struct wiphy *wiphy,
1421 struct wireless_dev *wdev, const void *data, int len)
1422 {
1423 _adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));
1424 int ret = 0, rem, type;
1425 int buf_len = 1024;
1426 char *buf_ptr;
1427 const struct nlattr *iter;
1428 gfp_t kflags;
1429
1430 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
1431 buf_ptr = kzalloc(buf_len, kflags);
1432 if (!buf_ptr) {
1433 RTW_ERR("failed to allocate the buffer for version n");
1434 ret = -ENOMEM;
1435 goto exit;
1436 }
1437 nla_for_each_attr(iter, data, len, rem) {
1438 type = nla_type(iter);
1439 switch (type) {
1440 case LOGGER_ATTRIBUTE_GET_DRIVER:
1441 _rtw_memcpy(buf_ptr, DRIVERVERSION, strlen(DRIVERVERSION)+1);
1442 break;
1443 case LOGGER_ATTRIBUTE_GET_FW:
1444 rtw_phl_get_fw_ver(GET_PHL_INFO(adapter_to_dvobj(padapter)), buf_ptr, buf_len);
1445 break;
1446 default:
1447 RTW_ERR("Unknown type: %d\n", type);
1448 ret = -EINVAL;
1449 goto exit;
1450 }
1451 }
1452 if (ret < 0) {
1453 RTW_ERR("failed to get the version %d\n", ret);
1454 goto exit;
1455 }
1456
1457
1458 ret = rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev), buf_ptr, strlen(buf_ptr));
1459 exit:
1460 kfree(buf_ptr);
1461 return ret;
1462 }
1463
rtw_cfgvendor_logger_get_ring_status(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1464 static int rtw_cfgvendor_logger_get_ring_status(struct wiphy *wiphy,
1465 struct wireless_dev *wdev, const void *data, int len)
1466 {
1467 int ret = 0;
1468 int ring_id;
1469 char ring_buf_name[] = "RTW_RING_BUFFER";
1470
1471 struct sk_buff *skb;
1472 wifi_ring_buffer_status ring_status;
1473
1474
1475 _rtw_memcpy(ring_status.name, ring_buf_name, strlen(ring_buf_name)+1);
1476 ring_status.ring_id = 1;
1477 /* Alloc the SKB for vendor_event */
1478 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1479 sizeof(wifi_ring_buffer_status));
1480 if (!skb) {
1481 RTW_ERR("skb allocation is failed\n");
1482 ret = FAIL;
1483 goto exit;
1484 }
1485
1486 nla_put_u32(skb, LOGGER_ATTRIBUTE_RING_NUM, 1);
1487 nla_put(skb, LOGGER_ATTRIBUTE_RING_STATUS, sizeof(wifi_ring_buffer_status),
1488 &ring_status);
1489 ret = cfg80211_vendor_cmd_reply(skb);
1490
1491 if (ret) {
1492 RTW_ERR("Vendor Command reply failed ret:%d \n", ret);
1493 }
1494 exit:
1495 return ret;
1496 }
1497
rtw_cfgvendor_logger_get_ring_data(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1498 static int rtw_cfgvendor_logger_get_ring_data(struct wiphy *wiphy,
1499 struct wireless_dev *wdev, const void *data, int len)
1500 {
1501 int ret = 0, rem, type;
1502 char ring_name[32] = {0};
1503 const struct nlattr *iter;
1504
1505 nla_for_each_attr(iter, data, len, rem) {
1506 type = nla_type(iter);
1507 switch (type) {
1508 case LOGGER_ATTRIBUTE_RING_NAME:
1509 strncpy(ring_name, nla_data(iter),
1510 MIN(sizeof(ring_name) -1, nla_len(iter)));
1511 RTW_INFO(" %s LOGGER_ATTRIBUTE_RING_NAME : %s\n", __func__, ring_name);
1512 break;
1513 default:
1514 RTW_ERR("Unknown type: %d\n", type);
1515 return ret;
1516 }
1517 }
1518
1519
1520 return ret;
1521 }
1522
rtw_cfgvendor_logger_get_firmware_memory_dump(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1523 static int rtw_cfgvendor_logger_get_firmware_memory_dump(struct wiphy *wiphy,
1524 struct wireless_dev *wdev, const void *data, int len)
1525 {
1526 int ret = WIFI_ERROR_NOT_SUPPORTED;
1527
1528 return ret;
1529 }
1530
rtw_cfgvendor_logger_start_pkt_fate_monitoring(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1531 static int rtw_cfgvendor_logger_start_pkt_fate_monitoring(struct wiphy *wiphy,
1532 struct wireless_dev *wdev, const void *data, int len)
1533 {
1534 int ret = WIFI_SUCCESS;
1535
1536 return ret;
1537 }
1538
rtw_cfgvendor_logger_get_tx_pkt_fates(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1539 static int rtw_cfgvendor_logger_get_tx_pkt_fates(struct wiphy *wiphy,
1540 struct wireless_dev *wdev, const void *data, int len)
1541 {
1542 int ret = WIFI_SUCCESS;
1543
1544 return ret;
1545 }
1546
rtw_cfgvendor_logger_get_rx_pkt_fates(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1547 static int rtw_cfgvendor_logger_get_rx_pkt_fates(struct wiphy *wiphy,
1548 struct wireless_dev *wdev, const void *data, int len)
1549 {
1550 int ret = WIFI_SUCCESS;
1551
1552 return ret;
1553 }
1554
1555 #endif /* CONFIG_RTW_CFGVENDOR_WIFI_LOGGER */
1556 #ifdef CONFIG_RTW_WIFI_HAL
1557 #ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
1558
1559 #ifndef ETHER_ISMULTI
1560 #define ETHER_ISMULTI(ea) (((const u8 *)(ea))[0] & 1)
1561 #endif
1562
1563
1564 static u8 null_addr[ETH_ALEN] = {0};
rtw_hal_random_gen_mac_addr(u8 * mac_addr)1565 static void rtw_hal_random_gen_mac_addr(u8 *mac_addr)
1566 {
1567 do {
1568 get_random_bytes(&mac_addr[3], ETH_ALEN-3);
1569 if (_rtw_memcmp(mac_addr, null_addr, ETH_ALEN) != _TRUE)
1570 break;
1571 } while(1);
1572 }
1573
rtw_hal_pno_random_gen_mac_addr(_adapter * adapter)1574 void rtw_hal_pno_random_gen_mac_addr(_adapter *adapter)
1575 {
1576 u8 mac_addr[ETH_ALEN];
1577 struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
1578
1579 _rtw_memcpy(mac_addr, pwdev_priv->pno_mac_addr, ETH_ALEN);
1580 if (mac_addr[0] == 0xFF) return;
1581 rtw_hal_random_gen_mac_addr(mac_addr);
1582 _rtw_memcpy(pwdev_priv->pno_mac_addr, mac_addr, ETH_ALEN);
1583 #ifdef CONFIG_RTW_DEBUG
1584 print_hex_dump(KERN_DEBUG, "pno_mac_addr: ",
1585 DUMP_PREFIX_OFFSET, 16, 1, pwdev_priv->pno_mac_addr,
1586 ETH_ALEN, 1);
1587 #endif
1588 }
1589
rtw_hal_set_hw_mac_addr(_adapter * adapter,u8 * mac_addr)1590 void rtw_hal_set_hw_mac_addr(_adapter *adapter, u8 *mac_addr)
1591 {
1592 rtw_ps_deny(adapter, PS_DENY_IOCTL);
1593 LeaveAllPowerSaveModeDirect(adapter);
1594
1595 rtw_hal_set_hwreg(adapter, HW_VAR_MAC_ADDR, mac_addr);
1596
1597 #ifdef CONFIG_RTW_DEBUG
1598 rtw_hal_dump_macaddr(RTW_DBGDUMP, adapter);
1599 #endif
1600 rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL);
1601 }
1602
rtw_cfgvendor_set_rand_mac_oui(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1603 static int rtw_cfgvendor_set_rand_mac_oui(struct wiphy *wiphy,
1604 struct wireless_dev *wdev, const void *data, int len)
1605 {
1606 int err = 0;
1607 _adapter *adapter;
1608 void *devaddr;
1609 struct net_device *netdev;
1610 int type, mac_len;
1611 u8 pno_random_mac_oui[3];
1612 u8 mac_addr[ETH_ALEN] = {0};
1613 struct pwrctrl_priv *pwrctl;
1614 struct rtw_wdev_priv *pwdev_priv;
1615
1616 type = nla_type(data);
1617 mac_len = nla_len(data);
1618 if (mac_len != 3) {
1619 RTW_ERR("%s oui len error %d != 3\n", __func__, mac_len);
1620 return -1;
1621 }
1622
1623 if (type == ANDR_WIFI_ATTRIBUTE_RANDOM_MAC_OUI) {
1624 _rtw_memcpy(pno_random_mac_oui, nla_data(data), 3);
1625 print_hex_dump(KERN_DEBUG, "pno_random_mac_oui: ",
1626 DUMP_PREFIX_OFFSET, 16, 1, pno_random_mac_oui,
1627 3, 1);
1628
1629 if (ETHER_ISMULTI(pno_random_mac_oui)) {
1630 pr_err("%s: oui is multicast address\n", __func__);
1631 return -1;
1632 }
1633
1634 adapter = wiphy_to_adapter(wiphy);
1635 if (adapter == NULL) {
1636 pr_err("%s: wiphy_to_adapter == NULL\n", __func__);
1637 return -1;
1638 }
1639
1640 pwdev_priv = adapter_wdev_data(adapter);
1641
1642 _rtw_memcpy(mac_addr, pno_random_mac_oui, 3);
1643 rtw_hal_random_gen_mac_addr(mac_addr);
1644 _rtw_memcpy(pwdev_priv->pno_mac_addr, mac_addr, ETH_ALEN);
1645 #ifdef CONFIG_RTW_DEBUG
1646 print_hex_dump(KERN_DEBUG, "pno_mac_addr: ",
1647 DUMP_PREFIX_OFFSET, 16, 1, pwdev_priv->pno_mac_addr,
1648 ETH_ALEN, 1);
1649 #endif
1650 } else {
1651 RTW_ERR("%s oui type error %x != 0x2\n", __func__, type);
1652 err = -1;
1653 }
1654
1655
1656 return err;
1657 }
1658
1659 #endif
1660
1661 #ifdef CONFIG_RTW_CFGVENDOR_WIFI_OFFLOAD
rtw_cfgvendor_start_mkeep_alive(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1662 static int rtw_cfgvendor_start_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev,
1663 const void *data, int len)
1664 {
1665 int ret = WIFI_SUCCESS;
1666
1667 RTW_INFO("%s : TODO\n", __func__);
1668
1669 return ret;
1670 }
1671
rtw_cfgvendor_stop_mkeep_alive(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1672 static int rtw_cfgvendor_stop_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev,
1673 const void *data, int len)
1674 {
1675 int ret = WIFI_SUCCESS;
1676
1677 RTW_INFO("%s : TODO\n", __func__);
1678
1679 return ret;
1680 }
1681 #endif
1682
rtw_cfgvendor_set_nodfs_flag(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1683 static int rtw_cfgvendor_set_nodfs_flag(struct wiphy *wiphy,
1684 struct wireless_dev *wdev, const void *data, int len)
1685 {
1686 int err = 0;
1687 int type;
1688 u32 nodfs = 0;
1689 _adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));
1690
1691 RTW_DBG(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char*)data);
1692
1693 type = nla_type(data);
1694 if (type == ANDR_WIFI_ATTRIBUTE_NODFS_SET) {
1695 nodfs = nla_get_u32(data);
1696 adapter_to_dvobj(padapter)->nodfs = nodfs;
1697 } else {
1698 err = -EINVAL;
1699 }
1700
1701 RTW_INFO("%s nodfs=%d, err=%d\n", __func__, nodfs, err);
1702
1703 return err;
1704 }
1705
rtw_cfgvendor_set_country(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1706 static int rtw_cfgvendor_set_country(struct wiphy *wiphy,
1707 struct wireless_dev *wdev, const void *data, int len)
1708 {
1709 #define CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */
1710 int err = 0, rem, type;
1711 char country_code[CNTRY_BUF_SZ] = {0};
1712 const struct nlattr *iter;
1713 _adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));
1714
1715 RTW_DBG(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char*)data);
1716
1717 nla_for_each_attr(iter, data, len, rem) {
1718 type = nla_type(iter);
1719 switch (type) {
1720 case ANDR_WIFI_ATTRIBUTE_COUNTRY:
1721 _rtw_memcpy(country_code, nla_data(iter),
1722 MIN(nla_len(iter), CNTRY_BUF_SZ));
1723 break;
1724 default:
1725 RTW_ERR("Unknown type: %d\n", type);
1726 return -EINVAL;
1727 }
1728 }
1729
1730 RTW_INFO("%s country_code:\"%c%c\" \n", __func__, country_code[0], country_code[1]);
1731
1732 rtw_set_country(padapter, country_code, RTW_REGD_SET_BY_USER);
1733
1734 return err;
1735 }
1736
rtw_cfgvendor_set_nd_offload(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int len)1737 static int rtw_cfgvendor_set_nd_offload(struct wiphy *wiphy,
1738 struct wireless_dev *wdev, const void *data, int len)
1739 {
1740 int err = 0;
1741 int type;
1742 u8 nd_en = 0;
1743 _adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));
1744
1745 RTW_DBG(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char*)data);
1746
1747 type = nla_type(data);
1748 if (type == ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE) {
1749 nd_en = nla_get_u8(data);
1750 /* ND has been enabled when wow is enabled */
1751 } else {
1752 err = -EINVAL;
1753 }
1754
1755 RTW_INFO("%s nd_en=%d, err=%d\n", __func__, nd_en, err);
1756
1757 return err;
1758 }
1759 #endif /* CONFIG_RTW_WIFI_HAL */
1760
1761 static const struct wiphy_vendor_command rtw_vendor_cmds[] = {
1762 #if defined(GSCAN_SUPPORT) && 0
1763 {
1764 {
1765 .vendor_id = OUI_GOOGLE,
1766 .subcmd = GSCAN_SUBCMD_GET_CAPABILITIES
1767 },
1768 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1769 .doit = rtw_cfgvendor_gscan_get_capabilities,
1770 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1771 .policy= VENDOR_CMD_RAW_DATA,
1772 #endif
1773 },
1774 {
1775 {
1776 .vendor_id = OUI_GOOGLE,
1777 .subcmd = GSCAN_SUBCMD_SET_CONFIG
1778 },
1779 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1780 .doit = rtw_cfgvendor_set_scan_cfg,
1781 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1782 .policy= VENDOR_CMD_RAW_DATA,
1783 #endif
1784 },
1785 {
1786 {
1787 .vendor_id = OUI_GOOGLE,
1788 .subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG
1789 },
1790 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1791 .doit = rtw_cfgvendor_set_batch_scan_cfg,
1792 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1793 .policy= VENDOR_CMD_RAW_DATA,
1794 #endif
1795 },
1796 {
1797 {
1798 .vendor_id = OUI_GOOGLE,
1799 .subcmd = GSCAN_SUBCMD_ENABLE_GSCAN
1800 },
1801 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1802 .doit = rtw_cfgvendor_initiate_gscan,
1803 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1804 .policy= VENDOR_CMD_RAW_DATA,
1805 #endif
1806 },
1807 {
1808 {
1809 .vendor_id = OUI_GOOGLE,
1810 .subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
1811 },
1812 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1813 .doit = rtw_cfgvendor_enable_full_scan_result,
1814 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1815 .policy= VENDOR_CMD_RAW_DATA,
1816 #endif
1817 },
1818 {
1819 {
1820 .vendor_id = OUI_GOOGLE,
1821 .subcmd = GSCAN_SUBCMD_SET_HOTLIST
1822 },
1823 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1824 .doit = rtw_cfgvendor_hotlist_cfg,
1825 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1826 .policy= VENDOR_CMD_RAW_DATA,
1827 #endif
1828 },
1829 {
1830 {
1831 .vendor_id = OUI_GOOGLE,
1832 .subcmd = GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG
1833 },
1834 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1835 .doit = rtw_cfgvendor_significant_change_cfg,
1836 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1837 .policy= VENDOR_CMD_RAW_DATA,
1838 #endif
1839 },
1840 {
1841 {
1842 .vendor_id = OUI_GOOGLE,
1843 .subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS
1844 },
1845 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1846 .doit = rtw_cfgvendor_gscan_get_batch_results,
1847 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1848 .policy= VENDOR_CMD_RAW_DATA,
1849 #endif
1850 },
1851 {
1852 {
1853 .vendor_id = OUI_GOOGLE,
1854 .subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST
1855 },
1856 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1857 .doit = rtw_cfgvendor_gscan_get_channel_list,
1858 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1859 .policy= VENDOR_CMD_RAW_DATA,
1860 #endif
1861 },
1862 #endif /* GSCAN_SUPPORT */
1863 #if defined(RTT_SUPPORT) && 0
1864 {
1865 {
1866 .vendor_id = OUI_GOOGLE,
1867 .subcmd = RTT_SUBCMD_SET_CONFIG
1868 },
1869 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1870 .doit = rtw_cfgvendor_rtt_set_config,
1871 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1872 .policy= VENDOR_CMD_RAW_DATA,
1873 #endif
1874 },
1875 {
1876 {
1877 .vendor_id = OUI_GOOGLE,
1878 .subcmd = RTT_SUBCMD_CANCEL_CONFIG
1879 },
1880 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1881 .doit = rtw_cfgvendor_rtt_cancel_config,
1882 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1883 .policy= VENDOR_CMD_RAW_DATA,
1884 #endif
1885 },
1886 {
1887 {
1888 .vendor_id = OUI_GOOGLE,
1889 .subcmd = RTT_SUBCMD_GETCAPABILITY
1890 },
1891 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1892 .doit = rtw_cfgvendor_rtt_get_capability,
1893 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1894 .policy= VENDOR_CMD_RAW_DATA,
1895 #endif
1896 },
1897 #endif /* RTT_SUPPORT */
1898 #ifdef CONFIG_RTW_CFGVENDOR_LLSTATS
1899 {
1900 {
1901 .vendor_id = OUI_GOOGLE,
1902 .subcmd = LSTATS_SUBCMD_GET_INFO
1903 },
1904 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1905 .doit = rtw_cfgvendor_lstats_get_info,
1906 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1907 .policy= VENDOR_CMD_RAW_DATA,
1908 #endif
1909 },
1910 {
1911 {
1912 .vendor_id = OUI_GOOGLE,
1913 .subcmd = LSTATS_SUBCMD_SET_INFO
1914 },
1915 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1916 .doit = rtw_cfgvendor_lstats_set_info,
1917 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1918 .policy= VENDOR_CMD_RAW_DATA,
1919 #endif
1920 },
1921 {
1922 {
1923 .vendor_id = OUI_GOOGLE,
1924 .subcmd = LSTATS_SUBCMD_CLEAR_INFO
1925 },
1926 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1927 .doit = rtw_cfgvendor_lstats_clear_info,
1928 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1929 .policy= VENDOR_CMD_RAW_DATA,
1930 #endif
1931 },
1932 #endif /* CONFIG_RTW_CFGVENDOR_LLSTATS */
1933 #ifdef CONFIG_RTW_CFGVENDOR_RSSIMONITOR
1934 {
1935 {
1936 .vendor_id = OUI_GOOGLE,
1937 .subcmd = WIFI_SUBCMD_SET_RSSI_MONITOR
1938 },
1939 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1940 .doit = rtw_cfgvendor_set_rssi_monitor,
1941 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1942 .policy= VENDOR_CMD_RAW_DATA,
1943 #endif
1944 },
1945 #endif /* CONFIG_RTW_CFGVENDOR_RSSIMONITOR */
1946 #ifdef CONFIG_RTW_CFGVENDOR_WIFI_LOGGER
1947 {
1948 {
1949 .vendor_id = OUI_GOOGLE,
1950 .subcmd = LOGGER_START_LOGGING
1951 },
1952 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1953 .doit = rtw_cfgvendor_logger_start_logging,
1954 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1955 .policy= VENDOR_CMD_RAW_DATA,
1956 #endif
1957 },
1958 {
1959 {
1960 .vendor_id = OUI_GOOGLE,
1961 .subcmd = LOGGER_GET_FEATURE
1962 },
1963 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1964 .doit = rtw_cfgvendor_logger_get_feature,
1965 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1966 .policy= VENDOR_CMD_RAW_DATA,
1967 #endif
1968 },
1969 {
1970 {
1971 .vendor_id = OUI_GOOGLE,
1972 .subcmd = LOGGER_GET_VER
1973 },
1974 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1975 .doit = rtw_cfgvendor_logger_get_version,
1976 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1977 .policy= VENDOR_CMD_RAW_DATA,
1978 #endif
1979 },
1980 {
1981 {
1982 .vendor_id = OUI_GOOGLE,
1983 .subcmd = LOGGER_GET_RING_STATUS
1984 },
1985 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1986 .doit = rtw_cfgvendor_logger_get_ring_status,
1987 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1988 .policy= VENDOR_CMD_RAW_DATA,
1989 #endif
1990 },
1991 {
1992 {
1993 .vendor_id = OUI_GOOGLE,
1994 .subcmd = LOGGER_GET_RING_DATA
1995 },
1996 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1997 .doit = rtw_cfgvendor_logger_get_ring_data,
1998 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1999 .policy= VENDOR_CMD_RAW_DATA,
2000 #endif
2001 },
2002 {
2003 {
2004 .vendor_id = OUI_GOOGLE,
2005 .subcmd = LOGGER_TRIGGER_MEM_DUMP
2006 },
2007 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2008 .doit = rtw_cfgvendor_logger_get_firmware_memory_dump,
2009 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2010 .policy = VENDOR_CMD_RAW_DATA,
2011 #endif
2012 },
2013 {
2014 {
2015 .vendor_id = OUI_GOOGLE,
2016 .subcmd = LOGGER_START_PKT_FATE_MONITORING
2017 },
2018 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2019 .doit = rtw_cfgvendor_logger_start_pkt_fate_monitoring,
2020 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2021 .policy = VENDOR_CMD_RAW_DATA,
2022 #endif
2023 },
2024 {
2025 {
2026 .vendor_id = OUI_GOOGLE,
2027 .subcmd = LOGGER_GET_TX_PKT_FATES
2028 },
2029 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2030 .doit = rtw_cfgvendor_logger_get_tx_pkt_fates,
2031 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2032 .policy = VENDOR_CMD_RAW_DATA,
2033 #endif
2034 },
2035 {
2036 {
2037 .vendor_id = OUI_GOOGLE,
2038 .subcmd = LOGGER_GET_RX_PKT_FATES
2039 },
2040 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2041 .doit = rtw_cfgvendor_logger_get_rx_pkt_fates,
2042 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2043 .policy = VENDOR_CMD_RAW_DATA,
2044 #endif
2045 },
2046 #endif /* CONFIG_RTW_CFGVENDOR_WIFI_LOGGER */
2047 #ifdef CONFIG_RTW_WIFI_HAL
2048 #ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
2049 {
2050 {
2051 .vendor_id = OUI_GOOGLE,
2052 .subcmd = WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI
2053 },
2054 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2055 .doit = rtw_cfgvendor_set_rand_mac_oui,
2056 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2057 .policy = VENDOR_CMD_RAW_DATA,
2058 #endif
2059 },
2060 #endif
2061 #ifdef CONFIG_RTW_CFGVENDOR_WIFI_OFFLOAD
2062 {
2063 {
2064 .vendor_id = OUI_GOOGLE,
2065 .subcmd = WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE
2066 },
2067 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2068 .doit = rtw_cfgvendor_start_mkeep_alive,
2069 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2070 .policy = VENDOR_CMD_RAW_DATA,
2071 #endif
2072 },
2073 {
2074 {
2075 .vendor_id = OUI_GOOGLE,
2076 .subcmd = WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE
2077 },
2078 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2079 .doit = rtw_cfgvendor_stop_mkeep_alive,
2080 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2081 .policy = VENDOR_CMD_RAW_DATA,
2082 #endif
2083 },
2084 #endif
2085 {
2086 {
2087 .vendor_id = OUI_GOOGLE,
2088 .subcmd = WIFI_SUBCMD_NODFS_SET
2089 },
2090 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2091 .doit = rtw_cfgvendor_set_nodfs_flag,
2092 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2093 .policy = VENDOR_CMD_RAW_DATA,
2094 #endif
2095 },
2096 {
2097 {
2098 .vendor_id = OUI_GOOGLE,
2099 .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE
2100 },
2101 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2102 .doit = rtw_cfgvendor_set_country,
2103 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2104 .policy = VENDOR_CMD_RAW_DATA,
2105 #endif
2106 },
2107 {
2108 {
2109 .vendor_id = OUI_GOOGLE,
2110 .subcmd = WIFI_SUBCMD_CONFIG_ND_OFFLOAD
2111 },
2112 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2113 .doit = rtw_cfgvendor_set_nd_offload,
2114 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2115 .policy = VENDOR_CMD_RAW_DATA,
2116 #endif
2117 },
2118 #endif /* CONFIG_RTW_WIFI_HAL */
2119 {
2120 {
2121 .vendor_id = OUI_GOOGLE,
2122 .subcmd = WIFI_SUBCMD_GET_FEATURE_SET
2123 },
2124 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2125 .doit = rtw_cfgvendor_get_feature_set,
2126 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2127 .policy = VENDOR_CMD_RAW_DATA,
2128 #endif
2129 },
2130 {
2131 {
2132 .vendor_id = OUI_GOOGLE,
2133 .subcmd = WIFI_SUBCMD_GET_FEATURE_SET_MATRIX
2134 },
2135 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2136 .doit = rtw_cfgvendor_get_feature_set_matrix,
2137 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2138 .policy = VENDOR_CMD_RAW_DATA,
2139 #endif
2140 }
2141 };
2142
2143 static const struct nl80211_vendor_cmd_info rtw_vendor_events[] = {
2144 #if defined(GSCAN_SUPPORT) && 0
2145 { OUI_GOOGLE, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS },
2146 { OUI_GOOGLE, GSCAN_EVENT_HOTLIST_RESULTS_FOUND },
2147 { OUI_GOOGLE, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE },
2148 { OUI_GOOGLE, GSCAN_EVENT_FULL_SCAN_RESULTS },
2149 #endif /* GSCAN_SUPPORT */
2150 #if defined(RTT_SUPPORT) && 0
2151 { OUI_GOOGLE, RTT_EVENT_COMPLETE },
2152 #endif /* RTT_SUPPORT */
2153
2154 #ifdef CONFIG_RTW_CFGVENDOR_RSSIMONITOR
2155 { OUI_GOOGLE, GOOGLE_RSSI_MONITOR_EVENT },
2156 #endif /* RTW_CFGVENDOR_RSSIMONITR */
2157
2158 #if defined(GSCAN_SUPPORT) && 0
2159 { OUI_GOOGLE, GSCAN_EVENT_COMPLETE_SCAN },
2160 { OUI_GOOGLE, GSCAN_EVENT_HOTLIST_RESULTS_LOST }
2161 #endif /* GSCAN_SUPPORT */
2162 };
2163
rtw_cfgvendor_attach(struct wiphy * wiphy)2164 int rtw_cfgvendor_attach(struct wiphy *wiphy)
2165 {
2166
2167 RTW_INFO("Register RTW cfg80211 vendor cmd(0x%x) interface\n", NL80211_CMD_VENDOR);
2168
2169 wiphy->vendor_commands = rtw_vendor_cmds;
2170 wiphy->n_vendor_commands = ARRAY_SIZE(rtw_vendor_cmds);
2171 wiphy->vendor_events = rtw_vendor_events;
2172 wiphy->n_vendor_events = ARRAY_SIZE(rtw_vendor_events);
2173
2174 return 0;
2175 }
2176
rtw_cfgvendor_detach(struct wiphy * wiphy)2177 int rtw_cfgvendor_detach(struct wiphy *wiphy)
2178 {
2179 RTW_INFO("Vendor: Unregister RTW cfg80211 vendor interface\n");
2180
2181 wiphy->vendor_commands = NULL;
2182 wiphy->vendor_events = NULL;
2183 wiphy->n_vendor_commands = 0;
2184 wiphy->n_vendor_events = 0;
2185
2186 return 0;
2187 }
2188 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT) */
2189
2190 #endif /* CONFIG_IOCTL_CFG80211 */
2191