forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/dhd_pno.c
....@@ -1,16 +1,17 @@
1
-/* SPDX-License-Identifier: GPL-2.0 */
21 /*
32 * Broadcom Dongle Host Driver (DHD)
43 * Prefered Network Offload and Wi-Fi Location Service(WLS) code.
54 *
6
- * Copyright (C) 1999-2019, Broadcom Corporation
7
- *
5
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
6
+ *
7
+ * Copyright (C) 1999-2017, Broadcom Corporation
8
+ *
89 * Unless you and Broadcom execute a separate written software license
910 * agreement governing use of this software, this software is licensed to you
1011 * under the terms of the GNU General Public License version 2 (the "GPL"),
1112 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
1213 * following added to such license:
13
- *
14
+ *
1415 * As a special exception, the copyright holders of this software give you
1516 * permission to link this software with independent modules, and to copy and
1617 * distribute the resulting executable under terms of your choice, provided that
....@@ -18,7 +19,7 @@
1819 * the license of that module. An independent module is a module which is not
1920 * derived from this software. The special exception does not apply to any
2021 * modifications of the software.
21
- *
22
+ *
2223 * Notwithstanding the above, under no circumstances may you combine this
2324 * software in any way with any other Broadcom software provided under a license
2425 * other than the GPL, without Broadcom's express prior written consent.
....@@ -26,12 +27,12 @@
2627 *
2728 * <<Broadcom-WL-IPTag/Open:>>
2829 *
29
- * $Id: dhd_pno.c 423669 2013-09-18 13:01:55Z yangj$
30
+ * $Id: dhd_pno.c 812762 2019-04-02 09:36:26Z $
3031 */
3132
3233 #if defined(GSCAN_SUPPORT) && !defined(PNO_SUPPORT)
3334 #error "GSCAN needs PNO to be enabled!"
34
-#endif
35
+#endif // endif
3536
3637 #ifdef PNO_SUPPORT
3738 #include <typedefs.h>
....@@ -41,21 +42,27 @@
4142 #include <bcmutils.h>
4243
4344 #include <bcmendian.h>
45
+#ifdef OEM_ANDROID
4446 #include <linuxver.h>
4547 #include <linux/init.h>
4648 #include <linux/kernel.h>
4749 #include <linux/list.h>
4850 #include <linux/sort.h>
51
+#endif // endif
4952 #include <dngl_stats.h>
5053 #include <wlioctl.h>
5154
52
-#include <proto/bcmevent.h>
55
+#include <bcmevent.h>
5356 #include <dhd.h>
57
+#include <dhd_linux.h>
5458 #include <dhd_pno.h>
5559 #include <dhd_dbg.h>
5660 #ifdef GSCAN_SUPPORT
5761 #include <linux/gcd.h>
5862 #endif /* GSCAN_SUPPORT */
63
+#ifdef WL_CFG80211
64
+#include <wl_cfg80211.h>
65
+#endif /* WL_CFG80211 */
5966
6067 #ifdef __BIG_ENDIAN
6168 #include <bcmendian.h>
....@@ -74,20 +81,21 @@
7481 #define dtohchanspec(i) (i)
7582 #endif /* IL_BIGENDINA */
7683
77
-#define NULL_CHECK(p, s, err) \
78
- do { \
79
- if (!(p)) { \
80
- printf("NULL POINTER (%s) : %s\n", __FUNCTION__, (s)); \
81
- err = BCME_ERROR; \
82
- return err; \
83
- } \
84
- } while (0)
84
+#ifdef OEM_ANDROID
8585 #define PNO_GET_PNOSTATE(dhd) ((dhd_pno_status_info_t *)dhd->pno_state)
86
-#define PNO_BESTNET_LEN 2048
86
+
87
+#define PNO_BESTNET_LEN WLC_IOCTL_MEDLEN
88
+
8789 #define PNO_ON 1
8890 #define PNO_OFF 0
91
+#define CHANNEL_2G_MIN 1
8992 #define CHANNEL_2G_MAX 14
93
+#define CHANNEL_5G_MIN 34
9094 #define CHANNEL_5G_MAX 165
95
+#define IS_2G_CHANNEL(ch) ((ch >= CHANNEL_2G_MIN) && \
96
+ (ch <= CHANNEL_2G_MAX))
97
+#define IS_5G_CHANNEL(ch) ((ch >= CHANNEL_5G_MIN) && \
98
+ (ch <= CHANNEL_5G_MAX))
9199 #define MAX_NODE_CNT 5
92100 #define WLS_SUPPORTED(pno_state) (pno_state->wls_supported == TRUE)
93101 #define TIME_DIFF(timestamp1, timestamp2) (abs((uint32)(timestamp1/1000) \
....@@ -99,30 +107,46 @@
99107
100108 #define ENTRY_OVERHEAD strlen("bssid=\nssid=\nfreq=\nlevel=\nage=\ndist=\ndistSd=\n====")
101109 #define TIME_MIN_DIFF 5
102
-#define EVENT_DATABUF_MAXLEN (512 - sizeof(bcm_event_t))
103
-#define EVENT_MAX_NETCNT \
104
- ((EVENT_DATABUF_MAXLEN - sizeof(wl_pfn_scanresults_t)) \
105
- / sizeof(wl_pfn_net_info_t) + 1)
106
-#define WL_SCAN_IE_LEN_MAX 2048
107110
108
-static wlc_ssid_ext_t * dhd_pno_get_legacy_pno_ssid(dhd_pub_t *dhd,
109
- dhd_pno_status_info_t *pno_state);
111
+#define EVENT_DATABUF_MAXLEN (512 - sizeof(bcm_event_t))
112
+#define EVENT_MAX_NETCNT_V1 \
113
+ ((EVENT_DATABUF_MAXLEN - sizeof(wl_pfn_scanresults_v1_t)) \
114
+ / sizeof(wl_pfn_net_info_v1_t) + 1)
115
+#define EVENT_MAX_NETCNT_V2 \
116
+ ((EVENT_DATABUF_MAXLEN - sizeof(wl_pfn_scanresults_v2_t)) \
117
+ / sizeof(wl_pfn_net_info_v2_t) + 1)
118
+
110119 #ifdef GSCAN_SUPPORT
120
+static int _dhd_pno_flush_ssid(dhd_pub_t *dhd);
111121 static wl_pfn_gscan_ch_bucket_cfg_t *
112122 dhd_pno_gscan_create_channel_list(dhd_pub_t *dhd, dhd_pno_status_info_t *pno_state,
113
- uint16 *chan_list, uint32 *num_buckets, uint32 *num_buckets_to_fw);
123
+ uint16 *chan_list, uint32 *num_buckets, uint32 *num_buckets_to_fw);
114124 #endif /* GSCAN_SUPPORT */
115125
126
+static int dhd_pno_set_legacy_pno(dhd_pub_t *dhd, uint16 scan_fr, int pno_repeat,
127
+ int pno_freq_expo_max, uint16 *channel_list, int nchan);
128
+
116129 static inline bool
117
-is_dfs(uint16 channel)
130
+is_dfs(dhd_pub_t *dhd, uint16 channel)
118131 {
119
- if (channel >= 52 && channel <= 64) /* class 2 */
120
- return TRUE;
121
- else if (channel >= 100 && channel <= 140) /* class 4 */
122
- return TRUE;
123
- else
132
+ u32 ch;
133
+ s32 err;
134
+ u8 buf[32];
135
+
136
+ ch = wl_ch_host_to_driver(channel);
137
+ err = dhd_iovar(dhd, 0, "per_chan_info", (char *)&ch,
138
+ sizeof(u32), buf, sizeof(buf), FALSE);
139
+ if (unlikely(err)) {
140
+ DHD_ERROR(("get per chan info failed:%d\n", err));
124141 return FALSE;
142
+ }
143
+ /* Check the channel flags returned by fw */
144
+ if (*((u32 *)buf) & WL_CHAN_PASSIVE) {
145
+ return TRUE;
146
+ }
147
+ return FALSE;
125148 }
149
+
126150 int
127151 dhd_pno_clean(dhd_pub_t *dhd)
128152 {
....@@ -180,33 +204,100 @@
180204
181205 #ifdef GSCAN_SUPPORT
182206 static uint64
183
-convert_fw_rel_time_to_systime(uint32 fw_ts_ms)
207
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0))
208
+convert_fw_rel_time_to_systime(struct timespec64 *ts, uint32 fw_ts_ms)
209
+#else
210
+convert_fw_rel_time_to_systime(struct timespec *ts, uint32 fw_ts_ms)
211
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)) */
184212 {
185
- struct timespec ts;
186
-
187
- get_monotonic_boottime(&ts);
188
- return ((uint64)(TIMESPEC_TO_US(ts)) - (uint64)(fw_ts_ms * 1000));
213
+ return ((uint64)(TIMESPEC_TO_US(*ts)) - (uint64)(fw_ts_ms * 1000));
189214 }
190215
191216 static void
192217 dhd_pno_idx_to_ssid(struct dhd_pno_gscan_params *gscan_params,
193
- dhd_epno_results_t *res, uint32 idx)
218
+ dhd_epno_results_t *res, uint32 idx)
194219 {
195
- dhd_epno_params_t *iter, *next;
220
+ dhd_pno_ssid_t *iter, *next;
221
+ int i;
196222
197
- if (gscan_params->num_epno_ssid > 0) {
223
+ /* If idx doesn't make sense */
224
+ if (idx >= gscan_params->epno_cfg.num_epno_ssid) {
225
+ DHD_ERROR(("No match, idx %d num_ssid %d\n", idx,
226
+ gscan_params->epno_cfg.num_epno_ssid));
227
+ goto exit;
228
+ }
229
+
230
+ if (gscan_params->epno_cfg.num_epno_ssid > 0) {
231
+ i = 0;
232
+
233
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
198234 list_for_each_entry_safe(iter, next,
199
- &gscan_params->epno_ssid_list, list) {
200
- if (iter->index == idx) {
201
- memcpy(res->ssid, iter->ssid, iter->ssid_len);
202
- res->ssid_len = iter->ssid_len;
235
+ &gscan_params->epno_cfg.epno_ssid_list, list) {
236
+ GCC_DIAGNOSTIC_POP();
237
+ if (i++ == idx) {
238
+ memcpy(res->ssid, iter->SSID, iter->SSID_len);
239
+ res->ssid_len = iter->SSID_len;
203240 return;
204241 }
205242 }
206243 }
244
+exit:
207245 /* If we are here then there was no match */
208246 res->ssid[0] = '\0';
209247 res->ssid_len = 0;
248
+ return;
249
+}
250
+
251
+/* Translate HAL flag bitmask to BRCM FW flag bitmask */
252
+void
253
+dhd_pno_translate_epno_fw_flags(uint32 *flags)
254
+{
255
+ uint32 in_flags, fw_flags = 0;
256
+ in_flags = *flags;
257
+
258
+ if (in_flags & DHD_EPNO_A_BAND_TRIG) {
259
+ fw_flags |= WL_PFN_SSID_A_BAND_TRIG;
260
+ }
261
+
262
+ if (in_flags & DHD_EPNO_BG_BAND_TRIG) {
263
+ fw_flags |= WL_PFN_SSID_BG_BAND_TRIG;
264
+ }
265
+
266
+ if (!(in_flags & DHD_EPNO_STRICT_MATCH) &&
267
+ !(in_flags & DHD_EPNO_HIDDEN_SSID)) {
268
+ fw_flags |= WL_PFN_SSID_IMPRECISE_MATCH;
269
+ }
270
+
271
+ if (in_flags & DHD_EPNO_SAME_NETWORK) {
272
+ fw_flags |= WL_PFN_SSID_SAME_NETWORK;
273
+ }
274
+
275
+ /* Add any hard coded flags needed */
276
+ fw_flags |= WL_PFN_SUPPRESS_AGING_MASK;
277
+ *flags = fw_flags;
278
+
279
+ return;
280
+}
281
+
282
+/* Translate HAL auth bitmask to BRCM FW bitmask */
283
+void
284
+dhd_pno_set_epno_auth_flag(uint32 *wpa_auth)
285
+{
286
+ switch (*wpa_auth) {
287
+ case DHD_PNO_AUTH_CODE_OPEN:
288
+ *wpa_auth = WPA_AUTH_DISABLED;
289
+ break;
290
+ case DHD_PNO_AUTH_CODE_PSK:
291
+ *wpa_auth = (WPA_AUTH_PSK | WPA2_AUTH_PSK);
292
+ break;
293
+ case DHD_PNO_AUTH_CODE_EAPOL:
294
+ *wpa_auth = ~WPA_AUTH_NONE;
295
+ break;
296
+ default:
297
+ DHD_ERROR(("%s: Unknown auth %d", __FUNCTION__, *wpa_auth));
298
+ *wpa_auth = WPA_AUTH_PFN_ANY;
299
+ break;
300
+ }
210301 return;
211302 }
212303
....@@ -244,6 +335,21 @@
244335 goto exit;
245336 }
246337 exit:
338
+ return err;
339
+}
340
+
341
+static int
342
+_dhd_pno_flush_ssid(dhd_pub_t *dhd)
343
+{
344
+ int err;
345
+ wl_pfn_t pfn_elem;
346
+ memset(&pfn_elem, 0, sizeof(wl_pfn_t));
347
+ pfn_elem.flags = htod32(WL_PFN_FLUSH_ALL_SSIDS);
348
+
349
+ err = dhd_iovar(dhd, 0, "pfn_add", (char *)&pfn_elem, sizeof(wl_pfn_t), NULL, 0, TRUE);
350
+ if (err < 0) {
351
+ DHD_ERROR(("%s : failed to execute pfn_add\n", __FUNCTION__));
352
+ }
247353 return err;
248354 }
249355
....@@ -298,7 +404,7 @@
298404 }
299405 if (enable) {
300406 if ((_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) &&
301
- dhd_is_associated(dhd, NULL, NULL)) {
407
+ dhd_is_associated(dhd, 0, NULL)) {
302408 DHD_ERROR(("%s Legacy PNO mode cannot be enabled "
303409 "in assoc mode , ignore it\n", __FUNCTION__));
304410 err = BCME_BADOPTION;
....@@ -450,18 +556,17 @@
450556 pfn_param.flags |= htod16(ENABLE << ENABLE_ADAPTSCAN_BIT);
451557
452558 if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
453
- dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd);
454
- dhd_pno_params_t *_params;
559
+ dhd_pno_params_t *params;
455560
456
- _params = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]);
561
+ params = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]);
457562
458
- pfn_param.scan_freq = htod32(gcd(pno_params->params_gscan.scan_fr,
459
- _params->params_legacy.scan_fr));
563
+ pfn_param.scan_freq = gcd(pno_params->params_gscan.scan_fr,
564
+ params->params_legacy.scan_fr);
460565
461
- if ((_params->params_legacy.pno_repeat != 0) ||
462
- (_params->params_legacy.pno_freq_expo_max != 0)) {
463
- pfn_param.repeat = (uchar) (_params->params_legacy.pno_repeat);
464
- pfn_param.exp = (uchar) (_params->params_legacy.pno_freq_expo_max);
566
+ if ((params->params_legacy.pno_repeat != 0) ||
567
+ (params->params_legacy.pno_freq_expo_max != 0)) {
568
+ pfn_param.repeat = (uchar) (params->params_legacy.pno_repeat);
569
+ pfn_param.exp = (uchar) (params->params_legacy.pno_freq_expo_max);
465570 }
466571 }
467572
....@@ -494,12 +599,11 @@
494599 }
495600
496601 #ifdef GSCAN_SUPPORT
497
- if (mode == DHD_PNO_BATCH_MODE ||
498
- ((mode & DHD_PNO_GSCAN_MODE) && pno_params->params_gscan.mscan)) {
602
+ if (mode == DHD_PNO_BATCH_MODE ||
603
+ ((mode & DHD_PNO_GSCAN_MODE) && pno_params->params_gscan.mscan)) {
499604 #else
500
- if (mode == DHD_PNO_BATCH_MODE) {
605
+ if (mode == DHD_PNO_BATCH_MODE) {
501606 #endif /* GSCAN_SUPPORT */
502
-
503607 int _tmp = pfn_param.bestn;
504608 /* set bestn to calculate the max mscan which firmware supports */
505609 err = dhd_iovar(dhd, 0, "pfnmem", (char *)&_tmp, sizeof(_tmp), NULL, 0, TRUE);
....@@ -528,69 +632,64 @@
528632 return err;
529633 }
530634 static int
531
-_dhd_pno_add_ssid(dhd_pub_t *dhd, wlc_ssid_ext_t* ssids_list, int nssid)
635
+_dhd_pno_add_ssid(dhd_pub_t *dhd, struct list_head* ssid_list, int nssid)
532636 {
533637 int err = BCME_OK;
534
- int i = 0;
535
- wl_pfn_t pfn_element;
638
+ int i = 0, mem_needed;
639
+ wl_pfn_t *pfn_elem_buf;
640
+ struct dhd_pno_ssid *iter, *next;
641
+
536642 NULL_CHECK(dhd, "dhd is NULL", err);
537
- if (nssid) {
538
- NULL_CHECK(ssids_list, "ssid list is NULL", err);
643
+ if (!nssid) {
644
+ NULL_CHECK(ssid_list, "ssid list is NULL", err);
645
+ return BCME_ERROR;
539646 }
540
- memset(&pfn_element, 0, sizeof(pfn_element));
541
- {
542
- int j;
543
- for (j = 0; j < nssid; j++) {
544
- DHD_PNO(("%s size = %d hidden = %d flags = %x rssi_thresh %d\n",
545
- ssids_list[j].SSID, ssids_list[j].SSID_len, ssids_list[j].hidden,
546
- ssids_list[j].flags, ssids_list[i].rssi_thresh));
547
- }
647
+ mem_needed = (sizeof(wl_pfn_t) * nssid);
648
+ pfn_elem_buf = (wl_pfn_t *) MALLOCZ(dhd->osh, mem_needed);
649
+ if (!pfn_elem_buf) {
650
+ DHD_ERROR(("%s: Can't malloc %d bytes!\n", __FUNCTION__, mem_needed));
651
+ return BCME_NOMEM;
548652 }
549
- /* Check for broadcast ssid */
550
- for (i = 0; i < nssid; i++) {
551
- if (!ssids_list[i].SSID_len) {
552
- DHD_ERROR(("%d: Broadcast SSID is ilegal for PNO setting\n", i));
553
- err = BCME_ERROR;
554
- goto exit;
555
- }
556
- }
557
- /* set all pfn ssid */
558
- for (i = 0; i < nssid; i++) {
559
- pfn_element.infra = htod32(DOT11_BSSTYPE_INFRASTRUCTURE);
560
- pfn_element.auth = (DOT11_OPEN_SYSTEM);
561
- pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY);
562
- pfn_element.wsec = htod32(0);
563
- pfn_element.infra = htod32(1);
564
- if (ssids_list[i].hidden) {
565
- pfn_element.flags = htod32(ENABLE << WL_PFN_HIDDEN_BIT);
566
- } else {
567
- pfn_element.flags = 0;
568
- }
569
- pfn_element.flags |= htod32(ssids_list[i].flags);
653
+
654
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
655
+ list_for_each_entry_safe(iter, next, ssid_list, list) {
656
+ GCC_DIAGNOSTIC_POP();
657
+ pfn_elem_buf[i].infra = htod32(1);
658
+ pfn_elem_buf[i].auth = htod32(DOT11_OPEN_SYSTEM);
659
+ pfn_elem_buf[i].wpa_auth = htod32(iter->wpa_auth);
660
+ pfn_elem_buf[i].flags = htod32(iter->flags);
661
+ if (iter->hidden)
662
+ pfn_elem_buf[i].flags |= htod32(ENABLE << WL_PFN_HIDDEN_BIT);
570663 /* If a single RSSI threshold is defined, use that */
571664 #ifdef PNO_MIN_RSSI_TRIGGER
572
- pfn_element.flags |= ((PNO_MIN_RSSI_TRIGGER & 0xFF) << WL_PFN_RSSI_SHIFT);
665
+ pfn_elem_buf[i].flags |= ((PNO_MIN_RSSI_TRIGGER & 0xFF) << WL_PFN_RSSI_SHIFT);
573666 #else
574
- pfn_element.flags |= ((ssids_list[i].rssi_thresh & 0xFF) << WL_PFN_RSSI_SHIFT);
667
+ pfn_elem_buf[i].flags |= ((iter->rssi_thresh & 0xFF) << WL_PFN_RSSI_SHIFT);
575668 #endif /* PNO_MIN_RSSI_TRIGGER */
576
- memcpy((char *)pfn_element.ssid.SSID, ssids_list[i].SSID,
577
- ssids_list[i].SSID_len);
578
- pfn_element.ssid.SSID_len = ssids_list[i].SSID_len;
579
- err = dhd_iovar(dhd, 0, "pfn_add", (char *)&pfn_element, sizeof(pfn_element),
580
- NULL, 0, TRUE);
581
- if (err < 0) {
582
- DHD_ERROR(("%s : failed to execute pfn_add\n", __FUNCTION__));
583
- goto exit;
669
+ memcpy((char *)pfn_elem_buf[i].ssid.SSID, iter->SSID,
670
+ iter->SSID_len);
671
+ pfn_elem_buf[i].ssid.SSID_len = iter->SSID_len;
672
+ DHD_PNO(("%s size = %d hidden = %d flags = %x rssi_thresh %d\n",
673
+ iter->SSID, iter->SSID_len, iter->hidden,
674
+ iter->flags, iter->rssi_thresh));
675
+ if (++i >= nssid) {
676
+ /* shouldn't happen */
677
+ break;
584678 }
585679 }
586
-exit:
680
+
681
+ err = dhd_iovar(dhd, 0, "pfn_add", (char *)pfn_elem_buf, mem_needed, NULL, 0, TRUE);
682
+ if (err < 0) {
683
+ DHD_ERROR(("%s : failed to execute pfn_add\n", __FUNCTION__));
684
+ }
685
+ MFREE(dhd->osh, pfn_elem_buf, mem_needed);
587686 return err;
588687 }
589688 /* qsort compare function */
590689 static int
591690 _dhd_pno_cmpfunc(const void *a, const void *b)
592691 {
593
- return (*(uint16*)a - *(uint16*)b);
692
+ return (*(const uint16*)a - *(const uint16*)b);
594693 }
595694 static int
596695 _dhd_pno_chan_merge(uint16 *d_chan_list, int *nchan,
....@@ -639,40 +738,43 @@
639738 if (*nchan) {
640739 NULL_CHECK(d_chan_list, "d_chan_list is NULL", err);
641740 }
741
+ memset(&chan_buf, 0, sizeof(chan_buf));
642742 list = (wl_uint32_list_t *) (void *)chan_buf;
643743 list->count = htod32(WL_NUMCHANNELS);
644744 err = dhd_wl_ioctl_cmd(dhd, WLC_GET_VALID_CHANNELS, chan_buf, sizeof(chan_buf), FALSE, 0);
645745 if (err < 0) {
646746 DHD_ERROR(("failed to get channel list (err: %d)\n", err));
647
- goto exit;
747
+ return err;
648748 }
649749 for (i = 0, j = 0; i < dtoh32(list->count) && i < *nchan; i++) {
650
- if (band == WLC_BAND_2G) {
651
- if (dtoh32(list->element[i]) > CHANNEL_2G_MAX)
750
+ if (IS_2G_CHANNEL(dtoh32(list->element[i]))) {
751
+ if (!(band & WLC_BAND_2G)) {
752
+ /* Skip, if not 2g */
652753 continue;
653
- } else if (band == WLC_BAND_5G) {
654
- if (dtoh32(list->element[i]) <= CHANNEL_2G_MAX)
754
+ }
755
+ /* fall through to include the channel */
756
+ } else if (IS_5G_CHANNEL(dtoh32(list->element[i]))) {
757
+ bool dfs_channel = is_dfs(dhd, dtoh32(list->element[i]));
758
+ if ((skip_dfs && dfs_channel) ||
759
+ (!(band & WLC_BAND_5G) && !dfs_channel)) {
760
+ /* Skip the channel if:
761
+ * the DFS bit is NOT set & the channel is a dfs channel
762
+ * the band 5G is not set & the channel is a non DFS 5G channel
763
+ */
655764 continue;
656
- if (skip_dfs && is_dfs(dtoh32(list->element[i])))
657
- continue;
658
-
659
- } else if (band == WLC_BAND_AUTO) {
660
- if (skip_dfs || !is_dfs(dtoh32(list->element[i])))
661
- continue;
662
-
663
- } else { /* All channels */
664
- if (skip_dfs && is_dfs(dtoh32(list->element[i])))
665
- continue;
666
- }
667
- if (dtoh32(list->element[i]) <= CHANNEL_5G_MAX) {
668
- d_chan_list[j++] = (uint16) dtoh32(list->element[i]);
765
+ }
766
+ /* fall through to include the channel */
669767 } else {
670
- err = BCME_BADCHAN;
671
- goto exit;
768
+ /* Not in range. Bad channel */
769
+ DHD_ERROR(("Not in range. bad channel\n"));
770
+ *nchan = 0;
771
+ return BCME_BADCHAN;
672772 }
773
+
774
+ /* Include the channel */
775
+ d_chan_list[j++] = (uint16) dtoh32(list->element[i]);
673776 }
674777 *nchan = j;
675
-exit:
676778 return err;
677779 }
678780 static int
....@@ -689,7 +791,7 @@
689791 #ifdef PNO_DEBUG
690792 char *_base_bp;
691793 char msg[150];
692
-#endif
794
+#endif // endif
693795 dhd_pno_bestnet_entry_t *iter, *next;
694796 dhd_pno_scan_results_t *siter, *snext;
695797 dhd_pno_best_header_t *phead, *pprev;
....@@ -701,15 +803,17 @@
701803 DHD_PNO(("%s enter \n", __FUNCTION__));
702804 /* # of scans */
703805 if (!params_batch->get_batch.batch_started) {
704
- bp += nreadsize = sprintf(bp, "scancount=%d\n",
806
+ bp += nreadsize = snprintf(bp, nleftsize, "scancount=%d\n",
705807 params_batch->get_batch.expired_tot_scan_cnt);
706808 nleftsize -= nreadsize;
707809 params_batch->get_batch.batch_started = TRUE;
708810 }
709811 DHD_PNO(("%s scancount %d\n", __FUNCTION__, params_batch->get_batch.expired_tot_scan_cnt));
710812 /* preestimate scan count until which scan result this report is going to end */
813
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
711814 list_for_each_entry_safe(siter, snext,
712815 &params_batch->get_batch.expired_scan_results_list, list) {
816
+ GCC_DIAGNOSTIC_POP();
713817 phead = siter->bestnetheader;
714818 while (phead != NULL) {
715819 /* if left_size is less than bestheader total size , stop this */
....@@ -722,54 +826,57 @@
722826 DHD_PNO(("\n<loop : %d, apcount %d>\n", cnt - 1, phead->tot_cnt));
723827 /* attribute of the scan */
724828 if (phead->reason & PNO_STATUS_ABORT_MASK) {
725
- bp += nreadsize = sprintf(bp, "trunc\n");
829
+ bp += nreadsize = snprintf(bp, nleftsize, "trunc\n");
726830 nleftsize -= nreadsize;
727831 }
832
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
728833 list_for_each_entry_safe(iter, next,
729834 &phead->entry_list, list) {
835
+ GCC_DIAGNOSTIC_POP();
730836 t_delta = jiffies_to_msecs(jiffies - iter->recorded_time);
731837 #ifdef PNO_DEBUG
732838 _base_bp = bp;
733839 memset(msg, 0, sizeof(msg));
734
-#endif
840
+#endif // endif
735841 /* BSSID info */
736
- bp += nreadsize = sprintf(bp, "bssid=%s\n",
842
+ bp += nreadsize = snprintf(bp, nleftsize, "bssid=%s\n",
737843 bcm_ether_ntoa((const struct ether_addr *)&iter->BSSID, eabuf));
738844 nleftsize -= nreadsize;
739845 /* SSID */
740
- bp += nreadsize = sprintf(bp, "ssid=%s\n", iter->SSID);
846
+ bp += nreadsize = snprintf(bp, nleftsize, "ssid=%s\n", iter->SSID);
741847 nleftsize -= nreadsize;
742848 /* channel */
743
- bp += nreadsize = sprintf(bp, "freq=%d\n",
849
+ bp += nreadsize = snprintf(bp, nleftsize, "freq=%d\n",
744850 wf_channel2mhz(iter->channel,
745851 iter->channel <= CH_MAX_2G_CHANNEL?
746852 WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
747853 nleftsize -= nreadsize;
748854 /* RSSI */
749
- bp += nreadsize = sprintf(bp, "level=%d\n", iter->RSSI);
855
+ bp += nreadsize = snprintf(bp, nleftsize, "level=%d\n", iter->RSSI);
750856 nleftsize -= nreadsize;
751857 /* add the time consumed in Driver to the timestamp of firmware */
752858 iter->timestamp += t_delta;
753
- bp += nreadsize = sprintf(bp, "age=%d\n", iter->timestamp);
859
+ bp += nreadsize = snprintf(bp, nleftsize,
860
+ "age=%d\n", iter->timestamp);
754861 nleftsize -= nreadsize;
755862 /* RTT0 */
756
- bp += nreadsize = sprintf(bp, "dist=%d\n",
863
+ bp += nreadsize = snprintf(bp, nleftsize, "dist=%d\n",
757864 (iter->rtt0 == 0)? -1 : iter->rtt0);
758865 nleftsize -= nreadsize;
759866 /* RTT1 */
760
- bp += nreadsize = sprintf(bp, "distSd=%d\n",
867
+ bp += nreadsize = snprintf(bp, nleftsize, "distSd=%d\n",
761868 (iter->rtt0 == 0)? -1 : iter->rtt1);
762869 nleftsize -= nreadsize;
763
- bp += nreadsize = sprintf(bp, "%s", AP_END_MARKER);
870
+ bp += nreadsize = snprintf(bp, nleftsize, "%s", AP_END_MARKER);
764871 nleftsize -= nreadsize;
765872 list_del(&iter->list);
766873 MFREE(dhd->osh, iter, BESTNET_ENTRY_SIZE);
767874 #ifdef PNO_DEBUG
768875 memcpy(msg, _base_bp, bp - _base_bp);
769876 DHD_PNO(("Entry : \n%s", msg));
770
-#endif
877
+#endif // endif
771878 }
772
- bp += nreadsize = sprintf(bp, "%s", SCAN_END_MARKER);
879
+ bp += nreadsize = snprintf(bp, nleftsize, "%s", SCAN_END_MARKER);
773880 DHD_PNO(("%s", SCAN_END_MARKER));
774881 nleftsize -= nreadsize;
775882 pprev = phead;
....@@ -793,9 +900,11 @@
793900 }
794901 params_batch->get_batch.expired_tot_scan_cnt -= cnt;
795902 /* set FALSE only if the link list is empty after returning the data */
903
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
796904 if (list_empty(&params_batch->get_batch.expired_scan_results_list)) {
905
+ GCC_DIAGNOSTIC_POP();
797906 params_batch->get_batch.batch_started = FALSE;
798
- bp += sprintf(bp, "%s", RESULTS_END_MARKER);
907
+ bp += snprintf(bp, nleftsize, "%s", RESULTS_END_MARKER);
799908 DHD_PNO(("%s", RESULTS_END_MARKER));
800909 DHD_PNO(("%s : Getting the batching data is complete\n", __FUNCTION__));
801910 }
....@@ -815,6 +924,8 @@
815924 NULL_CHECK(head, "head is NULL", err);
816925 NULL_CHECK(head->next, "head->next is NULL", err);
817926 DHD_PNO(("%s enter\n", __FUNCTION__));
927
+
928
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
818929 list_for_each_entry_safe(siter, snext,
819930 head, list) {
820931 if (only_last) {
....@@ -843,6 +954,7 @@
843954 MFREE(dhd->osh, siter, SCAN_RESULTS_SIZE);
844955 }
845956 }
957
+ GCC_DIAGNOSTIC_POP();
846958 return removed_scan_cnt;
847959 }
848960
....@@ -892,12 +1004,15 @@
8921004 case DHD_PNO_LEGACY_MODE: {
8931005 struct dhd_pno_ssid *iter, *next;
8941006 if (params->params_legacy.nssid > 0) {
1007
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
8951008 list_for_each_entry_safe(iter, next,
8961009 &params->params_legacy.ssid_list, list) {
1010
+ GCC_DIAGNOSTIC_POP();
8971011 list_del(&iter->list);
898
- kfree(iter);
1012
+ MFREE(dhd->osh, iter, sizeof(struct dhd_pno_ssid));
8991013 }
9001014 }
1015
+
9011016 params->params_legacy.nssid = 0;
9021017 params->params_legacy.scan_fr = 0;
9031018 params->params_legacy.pno_freq_expo_max = 0;
....@@ -935,10 +1050,12 @@
9351050 case DHD_PNO_HOTLIST_MODE: {
9361051 struct dhd_pno_bssid *iter, *next;
9371052 if (params->params_hotlist.nbssid > 0) {
1053
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
9381054 list_for_each_entry_safe(iter, next,
9391055 &params->params_hotlist.bssid_list, list) {
1056
+ GCC_DIAGNOSTIC_POP();
9401057 list_del(&iter->list);
941
- kfree(iter);
1058
+ MFREE(dhd->osh, iter, sizeof(struct dhd_pno_ssid));
9421059 }
9431060 }
9441061 params->params_hotlist.scan_fr = 0;
....@@ -974,40 +1091,15 @@
9741091 return err;
9751092 }
9761093
977
-#ifdef GSCAN_SUPPORT
978
-static int
979
-_dhd_pno_add_significant_bssid(dhd_pub_t *dhd,
980
- wl_pfn_significant_bssid_t *p_pfn_significant_bssid, int nbssid)
981
-{
982
- int err = BCME_OK;
983
- NULL_CHECK(dhd, "dhd is NULL", err);
984
-
985
- if (!nbssid) {
986
- err = BCME_ERROR;
987
- goto exit;
988
- }
989
-
990
- NULL_CHECK(p_pfn_significant_bssid, "bssid list is NULL", err);
991
-
992
- err = dhd_iovar(dhd, 0, "pfn_add_swc_bssid", (char *)p_pfn_significant_bssid,
993
- sizeof(wl_pfn_significant_bssid_t) * nbssid, NULL, 0, TRUE);
994
- if (err < 0) {
995
- DHD_ERROR(("%s : failed to execute pfn_significant_bssid %d\n", __FUNCTION__, err));
996
- goto exit;
997
- }
998
-exit:
999
- return err;
1000
-}
1001
-#endif /* GSCAN_SUPPORT */
1002
-
10031094 int
10041095 dhd_pno_stop_for_ssid(dhd_pub_t *dhd)
10051096 {
10061097 int err = BCME_OK;
1007
- uint32 mode = 0;
1098
+ uint32 mode = 0, cnt = 0;
10081099 dhd_pno_status_info_t *_pno_state;
1009
- dhd_pno_params_t *_params;
1010
- wl_pfn_bssid_t *p_pfn_bssid = NULL;
1100
+ dhd_pno_params_t *_params = NULL;
1101
+ wl_pfn_bssid_t *p_pfn_bssid = NULL, *tmp_bssid;
1102
+
10111103 NULL_CHECK(dhd, "dev is NULL", err);
10121104 NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
10131105 _pno_state = PNO_GET_PNOSTATE(dhd);
....@@ -1016,7 +1108,11 @@
10161108 goto exit;
10171109 }
10181110 DHD_PNO(("%s enter\n", __FUNCTION__));
1111
+ /* If pno mode is PNO_LEGACY_MODE clear the pno values and unset the DHD_PNO_LEGACY_MODE */
1112
+ _params = &_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS];
1113
+ _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE);
10191114 _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
1115
+
10201116 #ifdef GSCAN_SUPPORT
10211117 if (_pno_state->pno_mode & DHD_PNO_GSCAN_MODE) {
10221118 struct dhd_pno_gscan_params *gscan_params;
....@@ -1053,7 +1149,14 @@
10531149 dhd_pno_get_for_batch(dhd, NULL, 0, PNO_STATUS_DISABLE);
10541150 /* save current pno_mode before calling dhd_pno_clean */
10551151 mode = _pno_state->pno_mode;
1056
- dhd_pno_clean(dhd);
1152
+ err = dhd_pno_clean(dhd);
1153
+ if (err < 0) {
1154
+ err = BCME_ERROR;
1155
+ DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
1156
+ __FUNCTION__, err));
1157
+ goto exit;
1158
+ }
1159
+
10571160 /* restore previous pno_mode */
10581161 _pno_state->pno_mode = mode;
10591162 if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
....@@ -1070,8 +1173,8 @@
10701173 /* restart HOTLIST SCAN */
10711174 struct dhd_pno_bssid *iter, *next;
10721175 _params = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]);
1073
- p_pfn_bssid = kzalloc(sizeof(wl_pfn_bssid_t) *
1074
- _params->params_hotlist.nbssid, GFP_KERNEL);
1176
+ p_pfn_bssid = MALLOCZ(dhd->osh, sizeof(wl_pfn_bssid_t) *
1177
+ _params->params_hotlist.nbssid);
10751178 if (p_pfn_bssid == NULL) {
10761179 DHD_ERROR(("%s : failed to allocate wl_pfn_bssid_t array"
10771180 " (count: %d)",
....@@ -1081,12 +1184,23 @@
10811184 goto exit;
10821185 }
10831186 /* convert dhd_pno_bssid to wl_pfn_bssid */
1187
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
1188
+ cnt = 0;
1189
+ tmp_bssid = p_pfn_bssid;
10841190 list_for_each_entry_safe(iter, next,
10851191 &_params->params_hotlist.bssid_list, list) {
1086
- memcpy(&p_pfn_bssid->macaddr,
1192
+ GCC_DIAGNOSTIC_POP();
1193
+ memcpy(&tmp_bssid->macaddr,
10871194 &iter->macaddr, ETHER_ADDR_LEN);
1088
- p_pfn_bssid->flags = iter->flags;
1089
- p_pfn_bssid++;
1195
+ tmp_bssid->flags = iter->flags;
1196
+ if (cnt < _params->params_hotlist.nbssid) {
1197
+ tmp_bssid++;
1198
+ cnt++;
1199
+ } else {
1200
+ DHD_ERROR(("%s: Allocated insufficient memory\n",
1201
+ __FUNCTION__));
1202
+ break;
1203
+ }
10901204 }
10911205 err = dhd_pno_set_for_hotlist(dhd, p_pfn_bssid, &_params->params_hotlist);
10921206 if (err < 0) {
....@@ -1105,7 +1219,10 @@
11051219 }
11061220 }
11071221 exit:
1108
- kfree(p_pfn_bssid);
1222
+ if (p_pfn_bssid) {
1223
+ MFREE(dhd->osh, p_pfn_bssid, sizeof(wl_pfn_bssid_t) *
1224
+ _params->params_hotlist.nbssid);
1225
+ }
11091226 return err;
11101227 }
11111228
....@@ -1118,140 +1235,11 @@
11181235 return (_dhd_pno_enable(dhd, enable));
11191236 }
11201237
1121
-static wlc_ssid_ext_t *
1122
-dhd_pno_get_legacy_pno_ssid(dhd_pub_t *dhd, dhd_pno_status_info_t *pno_state)
1123
-{
1124
- int err = BCME_OK;
1125
- int i;
1126
- struct dhd_pno_ssid *iter, *next;
1127
- dhd_pno_params_t *_params1 = &pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS];
1128
- wlc_ssid_ext_t *p_ssid_list;
1129
-
1130
- p_ssid_list = kzalloc(sizeof(wlc_ssid_ext_t) *
1131
- _params1->params_legacy.nssid, GFP_KERNEL);
1132
- if (p_ssid_list == NULL) {
1133
- DHD_ERROR(("%s : failed to allocate wlc_ssid_ext_t array (count: %d)",
1134
- __FUNCTION__, _params1->params_legacy.nssid));
1135
- err = BCME_ERROR;
1136
- pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
1137
- goto exit;
1138
- }
1139
- i = 0;
1140
- /* convert dhd_pno_ssid to wlc_ssid_ext_t */
1141
- list_for_each_entry_safe(iter, next, &_params1->params_legacy.ssid_list, list) {
1142
- p_ssid_list[i].SSID_len = iter->SSID_len;
1143
- p_ssid_list[i].hidden = iter->hidden;
1144
- p_ssid_list[i].rssi_thresh = iter->rssi_thresh;
1145
- memcpy(p_ssid_list[i].SSID, iter->SSID, p_ssid_list[i].SSID_len);
1146
- i++;
1147
- }
1148
-exit:
1149
- return p_ssid_list;
1150
-}
1151
-
1152
-#ifdef GSCAN_SUPPORT
1153
-static int dhd_epno_set_ssid(dhd_pub_t *dhd,
1154
- dhd_pno_status_info_t *pno_state)
1155
-{
1156
- int err = BCME_OK;
1157
- dhd_epno_params_t *iter, *next;
1158
- dhd_pno_params_t *_params1 = &pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
1159
- struct dhd_pno_gscan_params *gscan_params;
1160
- wlc_ssid_ext_t ssid_elem;
1161
- wl_pfn_ext_list_t *p_ssid_ext_elem = NULL;
1162
- uint32 mem_needed = 0, i = 0;
1163
- uint16 num_visible_epno_ssid;
1164
- uint8 flags;
1165
-
1166
- gscan_params = &_params1->params_gscan;
1167
- num_visible_epno_ssid = gscan_params->num_visible_epno_ssid;
1168
-
1169
- if (num_visible_epno_ssid) {
1170
- mem_needed = sizeof(wl_pfn_ext_list_t) + (sizeof(wl_pfn_ext_t) *
1171
- (num_visible_epno_ssid - 1));
1172
- p_ssid_ext_elem = kzalloc(mem_needed, GFP_KERNEL);
1173
- if (p_ssid_ext_elem == NULL) {
1174
- DHD_ERROR(("%s : failed to allocate memory %u\n",
1175
- __FUNCTION__, mem_needed));
1176
- err = BCME_NOMEM;
1177
- goto exit;
1178
- }
1179
- p_ssid_ext_elem->version = PFN_SSID_EXT_VERSION;
1180
- p_ssid_ext_elem->count = num_visible_epno_ssid;
1181
- }
1182
-
1183
- DHD_ERROR(("Total ssids %d, visible SSIDs %d\n", gscan_params->num_epno_ssid,
1184
- num_visible_epno_ssid));
1185
-
1186
- /* convert dhd_pno_ssid to wlc_ssid_ext_t */
1187
- list_for_each_entry_safe(iter, next, &gscan_params->epno_ssid_list, list) {
1188
- if (iter->flags & DHD_PNO_USE_SSID) {
1189
- memset(&ssid_elem, 0, sizeof(ssid_elem));
1190
- ssid_elem.SSID_len = iter->ssid_len;
1191
- ssid_elem.hidden = TRUE;
1192
- flags = (iter->flags & DHD_EPNO_A_BAND_TRIG) ?
1193
- WL_PFN_SSID_A_BAND_TRIG: 0;
1194
- flags |= (iter->flags & DHD_EPNO_BG_BAND_TRIG) ?
1195
- WL_PFN_SSID_BG_BAND_TRIG: 0;
1196
- ssid_elem.flags = flags;
1197
- ssid_elem.rssi_thresh = iter->rssi_thresh;
1198
- memcpy(ssid_elem.SSID, iter->ssid, iter->ssid_len);
1199
- if ((err = _dhd_pno_add_ssid(dhd, &ssid_elem, 1)) < 0) {
1200
- DHD_ERROR(("failed to add ssid list (err %d) in firmware\n", err));
1201
- goto exit;
1202
- }
1203
- } else if (i < num_visible_epno_ssid) {
1204
- p_ssid_ext_elem->pfn_ext[i].rssi_thresh = iter->rssi_thresh;
1205
- switch (iter->auth) {
1206
- case DHD_PNO_AUTH_CODE_OPEN:
1207
- p_ssid_ext_elem->pfn_ext[i].wpa_auth = WPA_AUTH_DISABLED;
1208
- break;
1209
- case DHD_PNO_AUTH_CODE_PSK:
1210
- p_ssid_ext_elem->pfn_ext[i].wpa_auth =
1211
- (WPA2_AUTH_PSK | WPA_AUTH_PSK);
1212
- break;
1213
- case DHD_PNO_AUTH_CODE_EAPOL:
1214
- p_ssid_ext_elem->pfn_ext[i].wpa_auth =
1215
- (uint16)WPA_AUTH_PFN_ANY;
1216
- break;
1217
- default:
1218
- p_ssid_ext_elem->pfn_ext[i].wpa_auth =
1219
- (uint16)WPA_AUTH_PFN_ANY;
1220
- break;
1221
- }
1222
- memcpy(p_ssid_ext_elem->pfn_ext[i].ssid, iter->ssid, iter->ssid_len);
1223
- p_ssid_ext_elem->pfn_ext[i].ssid_len = iter->ssid_len;
1224
- iter->index = gscan_params->ssid_ext_last_used_index++;
1225
- flags = (iter->flags & DHD_EPNO_A_BAND_TRIG) ?
1226
- WL_PFN_SSID_A_BAND_TRIG: 0;
1227
- flags |= (iter->flags & DHD_EPNO_BG_BAND_TRIG) ?
1228
- WL_PFN_SSID_BG_BAND_TRIG: 0;
1229
- p_ssid_ext_elem->pfn_ext[i].flags = flags;
1230
- DHD_ERROR(("SSID %s idx %d rssi thresh %d flags %x\n", iter->ssid,
1231
- iter->index, iter->rssi_thresh, flags));
1232
- i++;
1233
- }
1234
- }
1235
- if (num_visible_epno_ssid) {
1236
- err = dhd_iovar(dhd, 0, "pfn_add_ssid_ext", (char *)p_ssid_ext_elem,
1237
- mem_needed, NULL, 0, TRUE);
1238
-
1239
- if (err < 0) {
1240
- DHD_ERROR(("%s : failed to execute pfn_add_pno_ext_ssid %d\n", __FUNCTION__,
1241
- err));
1242
- }
1243
- }
1244
-exit:
1245
- kfree(p_ssid_ext_elem);
1246
- return err;
1247
-}
1248
-#endif /* GSCAN_SUPPORT */
1249
-
12501238 static int
1251
-dhd_pno_add_to_ssid_list(dhd_pno_params_t *params, wlc_ssid_ext_t *ssid_list,
1252
- int nssid)
1239
+dhd_pno_add_to_ssid_list(dhd_pub_t *dhd, struct list_head *ptr, wlc_ssid_ext_t *ssid_list,
1240
+ int nssid, int *num_ssid_added)
12531241 {
1254
- int ret = 0;
1242
+ int ret = BCME_OK;
12551243 int i;
12561244 struct dhd_pno_ssid *_pno_ssid;
12571245
....@@ -1262,7 +1250,14 @@
12621250 ret = BCME_ERROR;
12631251 goto exit;
12641252 }
1265
- _pno_ssid = kzalloc(sizeof(struct dhd_pno_ssid), GFP_KERNEL);
1253
+ /* Check for broadcast ssid */
1254
+ if (!ssid_list[i].SSID_len) {
1255
+ DHD_ERROR(("%d: Broadcast SSID is illegal for PNO setting\n", i));
1256
+ ret = BCME_ERROR;
1257
+ goto exit;
1258
+ }
1259
+ _pno_ssid = (struct dhd_pno_ssid *)MALLOCZ(dhd->osh,
1260
+ sizeof(struct dhd_pno_ssid));
12661261 if (_pno_ssid == NULL) {
12671262 DHD_ERROR(("%s : failed to allocate struct dhd_pno_ssid\n",
12681263 __FUNCTION__));
....@@ -1272,12 +1267,15 @@
12721267 _pno_ssid->SSID_len = ssid_list[i].SSID_len;
12731268 _pno_ssid->hidden = ssid_list[i].hidden;
12741269 _pno_ssid->rssi_thresh = ssid_list[i].rssi_thresh;
1270
+ _pno_ssid->flags = ssid_list[i].flags;
1271
+ _pno_ssid->wpa_auth = WPA_AUTH_PFN_ANY;
1272
+
12751273 memcpy(_pno_ssid->SSID, ssid_list[i].SSID, _pno_ssid->SSID_len);
1276
- list_add_tail(&_pno_ssid->list, &params->params_legacy.ssid_list);
1277
- params->params_legacy.nssid++;
1274
+ list_add_tail(&_pno_ssid->list, ptr);
12781275 }
12791276
12801277 exit:
1278
+ *num_ssid_added = i;
12811279 return ret;
12821280 }
12831281
....@@ -1285,25 +1283,63 @@
12851283 dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_ext_t* ssid_list, int nssid,
12861284 uint16 scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan)
12871285 {
1286
+ dhd_pno_status_info_t *_pno_state;
1287
+ dhd_pno_params_t *_params;
1288
+ struct dhd_pno_legacy_params *params_legacy;
1289
+ int err = BCME_OK;
1290
+
1291
+ if (!dhd || !dhd->pno_state) {
1292
+ DHD_ERROR(("%s: PNO Not enabled/Not ready\n", __FUNCTION__));
1293
+ return BCME_NOTREADY;
1294
+ }
1295
+
1296
+ if (!dhd_support_sta_mode(dhd)) {
1297
+ return BCME_BADOPTION;
1298
+ }
1299
+
1300
+ _pno_state = PNO_GET_PNOSTATE(dhd);
1301
+ _params = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]);
1302
+ params_legacy = &(_params->params_legacy);
1303
+ err = _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE);
1304
+
1305
+ if (err < 0) {
1306
+ DHD_ERROR(("%s : failed to reinitialize profile (err %d)\n",
1307
+ __FUNCTION__, err));
1308
+ return err;
1309
+ }
1310
+
1311
+ INIT_LIST_HEAD(&params_legacy->ssid_list);
1312
+
1313
+ if (dhd_pno_add_to_ssid_list(dhd, &params_legacy->ssid_list, ssid_list,
1314
+ nssid, &params_legacy->nssid) < 0) {
1315
+ _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE);
1316
+ return BCME_ERROR;
1317
+ }
1318
+
1319
+ DHD_PNO(("%s enter : nssid %d, scan_fr :%d, pno_repeat :%d,"
1320
+ "pno_freq_expo_max: %d, nchan :%d\n", __FUNCTION__,
1321
+ params_legacy->nssid, scan_fr, pno_repeat, pno_freq_expo_max, nchan));
1322
+
1323
+ return dhd_pno_set_legacy_pno(dhd, scan_fr, pno_repeat,
1324
+ pno_freq_expo_max, channel_list, nchan);
1325
+
1326
+}
1327
+
1328
+static int
1329
+dhd_pno_set_legacy_pno(dhd_pub_t *dhd, uint16 scan_fr, int pno_repeat,
1330
+ int pno_freq_expo_max, uint16 *channel_list, int nchan)
1331
+{
12881332 dhd_pno_params_t *_params;
12891333 dhd_pno_params_t *_params2;
12901334 dhd_pno_status_info_t *_pno_state;
12911335 uint16 _chan_list[WL_NUMCHANNELS];
12921336 int32 tot_nchan = 0;
12931337 int err = BCME_OK;
1294
- int i;
1338
+ int i, nssid;
12951339 int mode = 0;
1296
- NULL_CHECK(dhd, "dhd is NULL", err);
1297
- NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
1298
- _pno_state = PNO_GET_PNOSTATE(dhd);
1340
+ struct list_head *ssid_list;
12991341
1300
- if (!dhd_support_sta_mode(dhd)) {
1301
- err = BCME_BADOPTION;
1302
- goto exit_no_clear;
1303
- }
1304
- DHD_PNO(("%s enter : scan_fr :%d, pno_repeat :%d,"
1305
- "pno_freq_expo_max: %d, nchan :%d\n", __FUNCTION__,
1306
- scan_fr, pno_repeat, pno_freq_expo_max, nchan));
1342
+ _pno_state = PNO_GET_PNOSTATE(dhd);
13071343
13081344 _params = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]);
13091345 /* If GSCAN is also ON will handle this down below */
....@@ -1311,7 +1347,7 @@
13111347 if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE &&
13121348 !(_pno_state->pno_mode & DHD_PNO_GSCAN_MODE)) {
13131349 #else
1314
- if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
1350
+ if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
13151351 #endif /* GSCAN_SUPPORT */
13161352 DHD_ERROR(("%s : Legacy PNO mode was already started, "
13171353 "will disable previous one to start new one\n", __FUNCTION__));
....@@ -1319,16 +1355,10 @@
13191355 if (err < 0) {
13201356 DHD_ERROR(("%s : failed to stop legacy PNO (err %d)\n",
13211357 __FUNCTION__, err));
1322
- goto exit_no_clear;
1358
+ return err;
13231359 }
13241360 }
13251361 _pno_state->pno_mode |= DHD_PNO_LEGACY_MODE;
1326
- err = _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE);
1327
- if (err < 0) {
1328
- DHD_ERROR(("%s : failed to reinitialize profile (err %d)\n",
1329
- __FUNCTION__, err));
1330
- goto exit_no_clear;
1331
- }
13321362 memset(_chan_list, 0, sizeof(_chan_list));
13331363 tot_nchan = MIN(nchan, WL_NUMCHANNELS);
13341364 if (tot_nchan > 0 && channel_list) {
....@@ -1339,13 +1369,13 @@
13391369 else {
13401370 tot_nchan = WL_NUMCHANNELS;
13411371 err = _dhd_pno_get_channels(dhd, _chan_list, &tot_nchan,
1342
- (WLC_BAND_2G | WLC_BAND_5G), FALSE);
1372
+ (WLC_BAND_2G | WLC_BAND_5G), FALSE);
13431373 if (err < 0) {
13441374 tot_nchan = 0;
13451375 DHD_PNO(("Could not get channel list for PNO SSID\n"));
13461376 } else {
13471377 for (i = 0; i < tot_nchan; i++)
1348
- _params->params_legacy.chan_list[i] = _chan_list[i];
1378
+ _params->params_legacy.chan_list[i] = _chan_list[i];
13491379 }
13501380 }
13511381 #endif /* GSCAN_SUPPORT */
....@@ -1359,7 +1389,7 @@
13591389 err = _dhd_pno_enable(dhd, PNO_OFF);
13601390 if (err < 0) {
13611391 DHD_ERROR(("%s : failed to disable PNO\n", __FUNCTION__));
1362
- goto exit_no_clear;
1392
+ goto exit;
13631393 }
13641394 /* restore the previous mode */
13651395 _pno_state->pno_mode = mode;
....@@ -1375,7 +1405,7 @@
13751405 DHD_ERROR(("%s : failed to merge channel list"
13761406 " between legacy and batch\n",
13771407 __FUNCTION__));
1378
- goto exit_no_clear;
1408
+ goto exit;
13791409 }
13801410 } else {
13811411 DHD_PNO(("superset channel will use"
....@@ -1392,7 +1422,7 @@
13921422 DHD_ERROR(("%s : failed to merge channel list"
13931423 " between legacy and hotlist\n",
13941424 __FUNCTION__));
1395
- goto exit_no_clear;
1425
+ goto exit;
13961426 }
13971427 }
13981428 }
....@@ -1401,13 +1431,18 @@
14011431 _params->params_legacy.pno_repeat = pno_repeat;
14021432 _params->params_legacy.pno_freq_expo_max = pno_freq_expo_max;
14031433 _params->params_legacy.nchan = tot_nchan;
1404
- _params->params_legacy.nssid = 0;
1405
- INIT_LIST_HEAD(&_params->params_legacy.ssid_list);
1434
+ ssid_list = &_params->params_legacy.ssid_list;
1435
+ nssid = _params->params_legacy.nssid;
1436
+
14061437 #ifdef GSCAN_SUPPORT
14071438 /* dhd_pno_initiate_gscan_request will handle simultaneous Legacy PNO and GSCAN */
14081439 if (_pno_state->pno_mode & DHD_PNO_GSCAN_MODE) {
1409
- if (dhd_pno_add_to_ssid_list(_params, ssid_list, nssid) < 0) {
1410
- err = BCME_ERROR;
1440
+ struct dhd_pno_gscan_params *gscan_params;
1441
+ gscan_params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan;
1442
+ /* ePNO and Legacy PNO do not co-exist */
1443
+ if (gscan_params->epno_cfg.num_epno_ssid) {
1444
+ DHD_PNO(("ePNO and Legacy PNO do not co-exist\n"));
1445
+ err = BCME_EPERM;
14111446 goto exit;
14121447 }
14131448 DHD_PNO(("GSCAN mode is ON! Will restart GSCAN+Legacy PNO\n"));
....@@ -1421,10 +1456,6 @@
14211456 }
14221457 if ((err = _dhd_pno_add_ssid(dhd, ssid_list, nssid)) < 0) {
14231458 DHD_ERROR(("failed to add ssid list(err %d), %d in firmware\n", err, nssid));
1424
- goto exit;
1425
- }
1426
- if (dhd_pno_add_to_ssid_list(_params, ssid_list, nssid) < 0) {
1427
- err = BCME_ERROR;
14281459 goto exit;
14291460 }
14301461 if (tot_nchan > 0) {
....@@ -1442,7 +1473,6 @@
14421473 if (err < 0) {
14431474 _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE);
14441475 }
1445
-exit_no_clear:
14461476 /* clear mode in case of error */
14471477 if (err < 0) {
14481478 int ret = dhd_pno_clean(dhd);
....@@ -1466,7 +1496,6 @@
14661496 dhd_pno_params_t *_params;
14671497 dhd_pno_params_t *_params2;
14681498 dhd_pno_status_info_t *_pno_state;
1469
- wlc_ssid_ext_t *p_ssid_list = NULL;
14701499 NULL_CHECK(dhd, "dhd is NULL", err);
14711500 NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
14721501 NULL_CHECK(batch_params, "batch_params is NULL", err);
....@@ -1529,7 +1558,7 @@
15291558 }
15301559 DHD_PNO(("\n"));
15311560 }
1532
-#endif
1561
+#endif // endif
15331562 if (_params->params_batch.nchan) {
15341563 /* copy the channel list into local array */
15351564 memcpy(_chan_list, _params->params_batch.chan_list, sizeof(_chan_list));
....@@ -1562,14 +1591,8 @@
15621591 } else {
15631592 DHD_PNO(("superset channel will use all channels in firmware\n"));
15641593 }
1565
- p_ssid_list = dhd_pno_get_legacy_pno_ssid(dhd, _pno_state);
1566
- if (!p_ssid_list) {
1567
- err = BCME_NOMEM;
1568
- DHD_ERROR(("failed to get Legacy PNO SSID list\n"));
1569
- goto exit;
1570
- }
1571
- if ((err = _dhd_pno_add_ssid(dhd, p_ssid_list,
1572
- _params2->params_legacy.nssid)) < 0) {
1594
+ if ((err = _dhd_pno_add_ssid(dhd, &_params2->params_legacy.ssid_list,
1595
+ _params2->params_legacy.nssid)) < 0) {
15731596 DHD_ERROR(("failed to add ssid list (err %d) in firmware\n", err));
15741597 goto exit;
15751598 }
....@@ -1601,18 +1624,84 @@
16011624 /* return #max scan firmware can do */
16021625 err = mscan;
16031626 }
1604
- if (p_ssid_list)
1605
- kfree(p_ssid_list);
16061627 return err;
16071628 }
16081629
1609
-
16101630 #ifdef GSCAN_SUPPORT
1631
+
1632
+static int
1633
+dhd_set_epno_params(dhd_pub_t *dhd, wl_ssid_ext_params_t *params, bool set)
1634
+{
1635
+ wl_pfn_ssid_cfg_t cfg;
1636
+ int err;
1637
+ NULL_CHECK(dhd, "dhd is NULL\n", err);
1638
+ memset(&cfg, 0, sizeof(wl_pfn_ssid_cfg_t));
1639
+ cfg.version = WL_PFN_SSID_CFG_VERSION;
1640
+
1641
+ /* If asked to clear params (set == FALSE) just set the CLEAR bit */
1642
+ if (!set)
1643
+ cfg.flags |= WL_PFN_SSID_CFG_CLEAR;
1644
+ else if (params)
1645
+ memcpy(&cfg.params, params, sizeof(wl_ssid_ext_params_t));
1646
+ err = dhd_iovar(dhd, 0, "pfn_ssid_cfg", (char *)&cfg,
1647
+ sizeof(wl_pfn_ssid_cfg_t), NULL, 0, TRUE);
1648
+ if (err != BCME_OK) {
1649
+ DHD_ERROR(("%s : Failed to execute pfn_ssid_cfg %d\n", __FUNCTION__, err));
1650
+ }
1651
+ return err;
1652
+}
1653
+
1654
+int
1655
+dhd_pno_flush_fw_epno(dhd_pub_t *dhd)
1656
+{
1657
+ int err;
1658
+
1659
+ NULL_CHECK(dhd, "dhd is NULL\n", err);
1660
+
1661
+ err = dhd_set_epno_params(dhd, NULL, FALSE);
1662
+ if (err < 0) {
1663
+ DHD_ERROR(("failed to set ePNO params %d\n", err));
1664
+ return err;
1665
+ }
1666
+ err = _dhd_pno_flush_ssid(dhd);
1667
+ return err;
1668
+}
1669
+
1670
+int
1671
+dhd_pno_set_epno(dhd_pub_t *dhd)
1672
+{
1673
+ int err = BCME_OK;
1674
+ dhd_pno_params_t *params;
1675
+ dhd_pno_status_info_t *_pno_state;
1676
+
1677
+ struct dhd_pno_gscan_params *gscan_params;
1678
+
1679
+ NULL_CHECK(dhd, "dhd is NULL\n", err);
1680
+ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
1681
+ _pno_state = PNO_GET_PNOSTATE(dhd);
1682
+ params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
1683
+ gscan_params = &params->params_gscan;
1684
+
1685
+ if (gscan_params->epno_cfg.num_epno_ssid) {
1686
+ DHD_PNO(("num_epno_ssid %d\n", gscan_params->epno_cfg.num_epno_ssid));
1687
+ if ((err = _dhd_pno_add_ssid(dhd, &gscan_params->epno_cfg.epno_ssid_list,
1688
+ gscan_params->epno_cfg.num_epno_ssid)) < 0) {
1689
+ DHD_ERROR(("failed to add ssid list (err %d) to firmware\n", err));
1690
+ return err;
1691
+ }
1692
+ err = dhd_set_epno_params(dhd, &gscan_params->epno_cfg.params, TRUE);
1693
+ if (err < 0) {
1694
+ DHD_ERROR(("failed to set ePNO params %d\n", err));
1695
+ }
1696
+ }
1697
+ return err;
1698
+}
1699
+
16111700 static void
1612
-dhd_pno_reset_cfg_gscan(dhd_pno_params_t *_params,
1701
+dhd_pno_reset_cfg_gscan(dhd_pub_t *dhd, dhd_pno_params_t *_params,
16131702 dhd_pno_status_info_t *_pno_state, uint8 flags)
16141703 {
1615
- DHD_ERROR(("%s enter\n", __FUNCTION__));
1704
+ DHD_PNO(("%s enter\n", __FUNCTION__));
16161705
16171706 if (flags & GSCAN_FLUSH_SCAN_CFG) {
16181707 _params->params_gscan.bestn = 0;
....@@ -1629,41 +1718,32 @@
16291718 if (flags & GSCAN_FLUSH_HOTLIST_CFG) {
16301719 struct dhd_pno_bssid *iter, *next;
16311720 if (_params->params_gscan.nbssid_hotlist > 0) {
1721
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
16321722 list_for_each_entry_safe(iter, next,
16331723 &_params->params_gscan.hotlist_bssid_list, list) {
1724
+ GCC_DIAGNOSTIC_POP();
16341725 list_del(&iter->list);
1635
- kfree(iter);
1726
+ MFREE(dhd->osh, iter, sizeof(struct dhd_pno_bssid));
16361727 }
16371728 }
16381729 _params->params_gscan.nbssid_hotlist = 0;
16391730 DHD_PNO(("Flush Hotlist Config\n"));
16401731 }
1641
- if (flags & GSCAN_FLUSH_SIGNIFICANT_CFG) {
1642
- dhd_pno_significant_bssid_t *iter, *next;
1643
-
1644
- if (_params->params_gscan.nbssid_significant_change > 0) {
1645
- list_for_each_entry_safe(iter, next,
1646
- &_params->params_gscan.significant_bssid_list, list) {
1647
- list_del(&iter->list);
1648
- kfree(iter);
1649
- }
1650
- }
1651
- _params->params_gscan.nbssid_significant_change = 0;
1652
- DHD_PNO(("Flush Significant Change Config\n"));
1653
- }
16541732 if (flags & GSCAN_FLUSH_EPNO_CFG) {
1655
- dhd_epno_params_t *iter, *next;
1733
+ dhd_pno_ssid_t *iter, *next;
1734
+ dhd_epno_ssid_cfg_t *epno_cfg = &_params->params_gscan.epno_cfg;
16561735
1657
- if (_params->params_gscan.num_epno_ssid > 0) {
1736
+ if (epno_cfg->num_epno_ssid > 0) {
1737
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
16581738 list_for_each_entry_safe(iter, next,
1659
- &_params->params_gscan.epno_ssid_list, list) {
1739
+ &epno_cfg->epno_ssid_list, list) {
1740
+ GCC_DIAGNOSTIC_POP();
16601741 list_del(&iter->list);
1661
- kfree(iter);
1742
+ MFREE(dhd->osh, iter, sizeof(struct dhd_pno_bssid));
16621743 }
1744
+ epno_cfg->num_epno_ssid = 0;
16631745 }
1664
- _params->params_gscan.num_epno_ssid = 0;
1665
- _params->params_gscan.num_visible_epno_ssid = 0;
1666
- _params->params_gscan.ssid_ext_last_used_index = 0;
1746
+ memset(&epno_cfg->params, 0, sizeof(wl_ssid_ext_params_t));
16671747 DHD_PNO(("Flushed ePNO Config\n"));
16681748 }
16691749
....@@ -1739,162 +1819,9 @@
17391819 return err;
17401820 }
17411821
1742
-static void *
1743
-dhd_get_gscan_batch_results(dhd_pub_t *dhd, uint32 *len)
1744
-{
1745
- gscan_results_cache_t *iter, *results;
1746
- dhd_pno_status_info_t *_pno_state;
1747
- dhd_pno_params_t *_params;
1748
- uint16 num_scan_ids = 0, num_results = 0;
1749
-
1750
- _pno_state = PNO_GET_PNOSTATE(dhd);
1751
- _params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
1752
-
1753
- iter = results = _params->params_gscan.gscan_batch_cache;
1754
- while (iter) {
1755
- num_results += iter->tot_count - iter->tot_consumed;
1756
- num_scan_ids++;
1757
- iter = iter->next;
1758
- }
1759
-
1760
- *len = ((num_results << 16) | (num_scan_ids));
1761
- return results;
1762
-}
1763
-
1764
-void *
1765
-dhd_pno_get_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type,
1766
- void *info, uint32 *len)
1767
-{
1768
- void *ret = NULL;
1769
- dhd_pno_gscan_capabilities_t *ptr;
1770
- dhd_epno_params_t *epno_params;
1771
- dhd_pno_params_t *_params;
1772
- dhd_pno_status_info_t *_pno_state;
1773
-
1774
- if (!dhd || !dhd->pno_state) {
1775
- DHD_ERROR(("NULL POINTER : %s\n", __FUNCTION__));
1776
- return NULL;
1777
- }
1778
- _pno_state = PNO_GET_PNOSTATE(dhd);
1779
- _params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
1780
- if (!len) {
1781
- DHD_ERROR(("%s: len is NULL\n", __FUNCTION__));
1782
- return NULL;
1783
- }
1784
- switch (type) {
1785
- case DHD_PNO_GET_CAPABILITIES:
1786
- ptr = (dhd_pno_gscan_capabilities_t *)
1787
- kmalloc(sizeof(dhd_pno_gscan_capabilities_t), GFP_KERNEL);
1788
- if (!ptr)
1789
- break;
1790
- /* Hardcoding these values for now, need to get
1791
- * these values from FW, will change in a later check-in
1792
- */
1793
- ptr->max_scan_cache_size = GSCAN_MAX_AP_CACHE;
1794
- ptr->max_scan_buckets = GSCAN_MAX_CH_BUCKETS;
1795
- ptr->max_ap_cache_per_scan = GSCAN_MAX_AP_CACHE_PER_SCAN;
1796
- ptr->max_rssi_sample_size = PFN_SWC_RSSI_WINDOW_MAX;
1797
- ptr->max_scan_reporting_threshold = 100;
1798
- ptr->max_hotlist_aps = PFN_HOTLIST_MAX_NUM_APS;
1799
- ptr->max_significant_wifi_change_aps = PFN_SWC_MAX_NUM_APS;
1800
- ptr->max_epno_ssid_crc32 = MAX_EPNO_SSID_NUM;
1801
- ptr->max_epno_hidden_ssid = MAX_EPNO_HIDDEN_SSID;
1802
- ptr->max_white_list_ssid = MAX_WHITELIST_SSID;
1803
- ret = (void *)ptr;
1804
- *len = sizeof(dhd_pno_gscan_capabilities_t);
1805
- break;
1806
-
1807
- case DHD_PNO_GET_BATCH_RESULTS:
1808
- ret = dhd_get_gscan_batch_results(dhd, len);
1809
- break;
1810
- case DHD_PNO_GET_CHANNEL_LIST:
1811
- if (info) {
1812
- uint16 ch_list[WL_NUMCHANNELS];
1813
- uint32 *ptr, mem_needed, i;
1814
- int32 err, nchan = WL_NUMCHANNELS;
1815
- uint32 *gscan_band = (uint32 *) info;
1816
- uint8 band = 0;
1817
-
1818
- /* No band specified?, nothing to do */
1819
- if ((*gscan_band & GSCAN_BAND_MASK) == 0) {
1820
- DHD_PNO(("No band specified\n"));
1821
- *len = 0;
1822
- break;
1823
- }
1824
-
1825
- /* HAL and DHD use different bits for 2.4G and
1826
- * 5G in bitmap. Hence translating it here...
1827
- */
1828
- if (*gscan_band & GSCAN_BG_BAND_MASK) {
1829
- band |= WLC_BAND_2G;
1830
- }
1831
- if (*gscan_band & GSCAN_A_BAND_MASK) {
1832
- band |= WLC_BAND_5G;
1833
- }
1834
-
1835
- err = _dhd_pno_get_channels(dhd, ch_list, &nchan,
1836
- (band & GSCAN_ABG_BAND_MASK),
1837
- !(*gscan_band & GSCAN_DFS_MASK));
1838
-
1839
- if (err < 0) {
1840
- DHD_ERROR(("%s: failed to get valid channel list\n",
1841
- __FUNCTION__));
1842
- *len = 0;
1843
- } else {
1844
- mem_needed = sizeof(uint32) * nchan;
1845
- ptr = (uint32 *) kmalloc(mem_needed, GFP_KERNEL);
1846
- if (!ptr) {
1847
- DHD_ERROR(("%s: Unable to malloc %d bytes\n",
1848
- __FUNCTION__, mem_needed));
1849
- break;
1850
- }
1851
- for (i = 0; i < nchan; i++) {
1852
- ptr[i] = wf_channel2mhz(ch_list[i],
1853
- (ch_list[i] <= CH_MAX_2G_CHANNEL?
1854
- WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
1855
- }
1856
- ret = ptr;
1857
- *len = mem_needed;
1858
- }
1859
- } else {
1860
- *len = 0;
1861
- DHD_ERROR(("%s: info buffer is NULL\n", __FUNCTION__));
1862
- }
1863
- break;
1864
- case DHD_PNO_GET_EPNO_SSID_ELEM:
1865
- if (_params->params_gscan.num_epno_ssid >=
1866
- (MAX_EPNO_SSID_NUM + MAX_EPNO_HIDDEN_SSID)) {
1867
- DHD_ERROR(("Excessive number of ePNO SSIDs programmed %d\n",
1868
- _params->params_gscan.num_epno_ssid));
1869
- return NULL;
1870
- }
1871
-
1872
- if (!_params->params_gscan.num_epno_ssid)
1873
- INIT_LIST_HEAD(&_params->params_gscan.epno_ssid_list);
1874
-
1875
- epno_params = kzalloc(sizeof(dhd_epno_params_t), GFP_KERNEL);
1876
- if (!epno_params) {
1877
- DHD_ERROR(("EPNO ssid: cannot alloc %zd bytes",
1878
- sizeof(dhd_epno_params_t)));
1879
- return NULL;
1880
- }
1881
- _params->params_gscan.num_epno_ssid++;
1882
- epno_params->index = DHD_EPNO_DEFAULT_INDEX;
1883
- list_add_tail(&epno_params->list, &_params->params_gscan.epno_ssid_list);
1884
- ret = epno_params;
1885
- break;
1886
- default:
1887
- DHD_ERROR(("%s: Unrecognized cmd type - %d\n", __FUNCTION__, type));
1888
- break;
1889
- }
1890
-
1891
- return ret;
1892
-
1893
-}
1894
-
18951822 int
18961823 dhd_pno_set_cfg_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type,
1897
- void *buf, uint8 flush)
1824
+ void *buf, bool flush)
18981825 {
18991826 int err = BCME_OK;
19001827 dhd_pno_params_t *_params;
....@@ -1911,22 +1838,23 @@
19111838 mutex_lock(&_pno_state->pno_mutex);
19121839
19131840 switch (type) {
1914
- case DHD_PNO_BATCH_SCAN_CFG_ID:
1841
+ case DHD_PNO_BATCH_SCAN_CFG_ID:
19151842 {
19161843 gscan_batch_params_t *ptr = (gscan_batch_params_t *)buf;
19171844 _params->params_gscan.bestn = ptr->bestn;
19181845 _params->params_gscan.mscan = ptr->mscan;
19191846 _params->params_gscan.buffer_threshold = ptr->buffer_threshold;
1920
- break;
19211847 }
1848
+ break;
19221849 case DHD_PNO_GEOFENCE_SCAN_CFG_ID:
19231850 {
19241851 gscan_hotlist_scan_params_t *ptr = (gscan_hotlist_scan_params_t *)buf;
19251852 struct dhd_pno_bssid *_pno_bssid;
19261853 struct bssid_t *bssid_ptr;
19271854 int8 flags;
1855
+
19281856 if (flush) {
1929
- dhd_pno_reset_cfg_gscan(_params, _pno_state,
1857
+ dhd_pno_reset_cfg_gscan(dhd, _params, _pno_state,
19301858 GSCAN_FLUSH_HOTLIST_CFG);
19311859 }
19321860
....@@ -1936,18 +1864,19 @@
19361864 if (!_params->params_gscan.nbssid_hotlist) {
19371865 INIT_LIST_HEAD(&_params->params_gscan.hotlist_bssid_list);
19381866 }
1867
+
19391868 if ((_params->params_gscan.nbssid_hotlist +
1940
- ptr->nbssid) > PFN_SWC_MAX_NUM_APS) {
1869
+ ptr->nbssid) > PFN_SWC_MAX_NUM_APS) {
19411870 DHD_ERROR(("Excessive number of hotlist APs programmed %d\n",
1942
- (_params->params_gscan.nbssid_hotlist +
1943
- ptr->nbssid)));
1871
+ (_params->params_gscan.nbssid_hotlist +
1872
+ ptr->nbssid)));
19441873 err = BCME_RANGE;
19451874 goto exit;
19461875 }
19471876
19481877 for (i = 0, bssid_ptr = ptr->bssid; i < ptr->nbssid; i++, bssid_ptr++) {
1949
- _pno_bssid = kzalloc(sizeof(struct dhd_pno_bssid), GFP_KERNEL);
1950
-
1878
+ _pno_bssid = (struct dhd_pno_bssid *)MALLOCZ(dhd->osh,
1879
+ sizeof(struct dhd_pno_bssid));
19511880 if (!_pno_bssid) {
19521881 DHD_ERROR(("_pno_bssid is NULL, cannot kalloc %zd bytes",
19531882 sizeof(struct dhd_pno_bssid)));
....@@ -1964,65 +1893,11 @@
19641893
19651894 _params->params_gscan.nbssid_hotlist += ptr->nbssid;
19661895 _params->params_gscan.lost_ap_window = ptr->lost_ap_window;
1967
- break;
19681896 }
1969
- case DHD_PNO_SIGNIFICANT_SCAN_CFG_ID:
1897
+ break;
1898
+ case DHD_PNO_SCAN_CFG_ID:
19701899 {
1971
- gscan_swc_params_t *ptr = (gscan_swc_params_t *)buf;
1972
- dhd_pno_significant_bssid_t *_pno_significant_change_bssid;
1973
- wl_pfn_significant_bssid_t *significant_bssid_ptr;
1974
-
1975
- if (flush) {
1976
- dhd_pno_reset_cfg_gscan(_params, _pno_state,
1977
- GSCAN_FLUSH_SIGNIFICANT_CFG);
1978
- }
1979
-
1980
- if (!ptr->nbssid) {
1981
- break;
1982
- }
1983
- if (!_params->params_gscan.nbssid_significant_change) {
1984
- INIT_LIST_HEAD(&_params->params_gscan.significant_bssid_list);
1985
- }
1986
- if ((_params->params_gscan.nbssid_significant_change +
1987
- ptr->nbssid) > PFN_SWC_MAX_NUM_APS) {
1988
- DHD_ERROR(("Excessive number of SWC APs programmed %d\n",
1989
- (_params->params_gscan.nbssid_significant_change +
1990
- ptr->nbssid)));
1991
- err = BCME_RANGE;
1992
- goto exit;
1993
- }
1994
-
1995
- for (i = 0, significant_bssid_ptr = ptr->bssid_elem_list;
1996
- i < ptr->nbssid; i++, significant_bssid_ptr++) {
1997
- _pno_significant_change_bssid =
1998
- kzalloc(sizeof(dhd_pno_significant_bssid_t),
1999
- GFP_KERNEL);
2000
-
2001
- if (!_pno_significant_change_bssid) {
2002
- DHD_ERROR(("SWC bssidptr is NULL, cannot kalloc %zd bytes",
2003
- sizeof(dhd_pno_significant_bssid_t)));
2004
- err = BCME_NOMEM;
2005
- goto exit;
2006
- }
2007
- memcpy(&_pno_significant_change_bssid->BSSID,
2008
- &significant_bssid_ptr->macaddr, ETHER_ADDR_LEN);
2009
- _pno_significant_change_bssid->rssi_low_threshold =
2010
- significant_bssid_ptr->rssi_low_threshold;
2011
- _pno_significant_change_bssid->rssi_high_threshold =
2012
- significant_bssid_ptr->rssi_high_threshold;
2013
- list_add_tail(&_pno_significant_change_bssid->list,
2014
- &_params->params_gscan.significant_bssid_list);
2015
- }
2016
-
2017
- _params->params_gscan.swc_nbssid_threshold = ptr->swc_threshold;
2018
- _params->params_gscan.swc_rssi_window_size = ptr->rssi_window;
2019
- _params->params_gscan.lost_ap_window = ptr->lost_ap_window;
2020
- _params->params_gscan.nbssid_significant_change += ptr->nbssid;
2021
- break;
2022
- }
2023
- case DHD_PNO_SCAN_CFG_ID:
2024
- {
2025
- int i, k;
1900
+ int k;
20261901 uint16 band;
20271902 gscan_scan_params_t *ptr = (gscan_scan_params_t *)buf;
20281903 struct dhd_pno_gscan_channel_bucket *ch_bucket;
....@@ -2046,13 +1921,15 @@
20461921 /* HAL and DHD use different bits for 2.4G and
20471922 * 5G in bitmap. Hence translating it here...
20481923 */
2049
- if (band & GSCAN_BG_BAND_MASK)
1924
+ if (band & GSCAN_BG_BAND_MASK) {
20501925 ch_bucket[i].band |= WLC_BAND_2G;
2051
- if (band & GSCAN_A_BAND_MASK)
1926
+ }
1927
+ if (band & GSCAN_A_BAND_MASK) {
20521928 ch_bucket[i].band |= WLC_BAND_5G;
2053
- if (band & GSCAN_DFS_MASK)
1929
+ }
1930
+ if (band & GSCAN_DFS_MASK) {
20541931 ch_bucket[i].band |= GSCAN_DFS_MASK;
2055
-
1932
+ }
20561933 DHD_PNO(("band %d report_flag %d\n", ch_bucket[i].band,
20571934 ch_bucket[i].report_flag));
20581935 }
....@@ -2063,8 +1940,8 @@
20631940 ch_bucket[i].bucket_max_multiple =
20641941 ch_bucket[i].bucket_max_multiple/ptr->scan_fr;
20651942 DHD_PNO(("mult %d max_mult %d\n",
2066
- ch_bucket[i].bucket_freq_multiple,
2067
- ch_bucket[i].bucket_max_multiple));
1943
+ ch_bucket[i].bucket_freq_multiple,
1944
+ ch_bucket[i].bucket_max_multiple));
20681945 }
20691946 _params->params_gscan.scan_fr = ptr->scan_fr;
20701947
....@@ -2073,27 +1950,34 @@
20731950 } else {
20741951 err = BCME_BADARG;
20751952 }
2076
- break;
2077
- }
2078
- case DHD_PNO_EPNO_CFG_ID:
2079
- if (flush) {
2080
- dhd_pno_reset_cfg_gscan(_params, _pno_state,
2081
- GSCAN_FLUSH_EPNO_CFG);
2082
- } else {
2083
- _params->params_gscan.num_visible_epno_ssid += *((uint16 *)buf);
20841953 }
20851954 break;
2086
- default:
2087
- err = BCME_BADARG;
2088
- DHD_ERROR(("%s: Unrecognized cmd type - %d\n", __FUNCTION__, type));
2089
- break;
1955
+ case DHD_PNO_EPNO_CFG_ID:
1956
+ if (flush) {
1957
+ dhd_pno_reset_cfg_gscan(dhd, _params, _pno_state,
1958
+ GSCAN_FLUSH_EPNO_CFG);
1959
+ }
1960
+ break;
1961
+ case DHD_PNO_EPNO_PARAMS_ID:
1962
+ if (flush) {
1963
+ memset(&_params->params_gscan.epno_cfg.params, 0,
1964
+ sizeof(wl_ssid_ext_params_t));
1965
+ }
1966
+ if (buf) {
1967
+ memcpy(&_params->params_gscan.epno_cfg.params, buf,
1968
+ sizeof(wl_ssid_ext_params_t));
1969
+ }
1970
+ break;
1971
+ default:
1972
+ err = BCME_BADARG;
1973
+ DHD_ERROR(("%s: Unrecognized cmd type - %d\n", __FUNCTION__, type));
1974
+ break;
20901975 }
20911976 exit:
20921977 mutex_unlock(&_pno_state->pno_mutex);
20931978 return err;
20941979
20951980 }
2096
-
20971981
20981982 static bool
20991983 validate_gscan_params(struct dhd_pno_gscan_params *gscan_params)
....@@ -2125,20 +2009,17 @@
21252009 dhd_pno_set_for_gscan(dhd_pub_t *dhd, struct dhd_pno_gscan_params *gscan_params)
21262010 {
21272011 int err = BCME_OK;
2128
- int mode, i = 0, k;
2012
+ int mode, i = 0;
21292013 uint16 _chan_list[WL_NUMCHANNELS];
21302014 int tot_nchan = 0;
21312015 int num_buckets_to_fw, tot_num_buckets, gscan_param_size = 0;
21322016 dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd);
21332017 wl_pfn_gscan_ch_bucket_cfg_t *ch_bucket = NULL;
21342018 wl_pfn_gscan_cfg_t *pfn_gscan_cfg_t = NULL;
2135
- wl_pfn_significant_bssid_t *p_pfn_significant_bssid = NULL;
21362019 wl_pfn_bssid_t *p_pfn_bssid = NULL;
2137
- wlc_ssid_ext_t *pssid_list = NULL;
2138
- dhd_pno_params_t *params_legacy;
21392020 dhd_pno_params_t *_params;
2021
+ bool fw_flushed = FALSE;
21402022
2141
- params_legacy = &_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS];
21422023 _params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
21432024
21442025 NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
....@@ -2161,7 +2042,7 @@
21612042 err = BCME_BADARG;
21622043 goto exit;
21632044 }
2164
- /* Create channel list based on channel buckets */
2045
+
21652046 if (!(ch_bucket = dhd_pno_gscan_create_channel_list(dhd, _pno_state,
21662047 _chan_list, &tot_num_buckets, &num_buckets_to_fw))) {
21672048 goto exit;
....@@ -2181,23 +2062,21 @@
21812062 mutex_unlock(&_pno_state->pno_mutex);
21822063 goto exit;
21832064 }
2065
+ fw_flushed = TRUE;
21842066 /* restore the previous mode */
21852067 _pno_state->pno_mode = mode;
21862068 }
21872069 _pno_state->pno_mode |= DHD_PNO_GSCAN_MODE;
21882070 mutex_unlock(&_pno_state->pno_mutex);
21892071
2190
- if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
2191
- pssid_list = dhd_pno_get_legacy_pno_ssid(dhd, _pno_state);
2072
+ if ((_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) &&
2073
+ !gscan_params->epno_cfg.num_epno_ssid) {
2074
+ struct dhd_pno_legacy_params *params_legacy;
2075
+ params_legacy =
2076
+ &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy);
21922077
2193
- if (!pssid_list) {
2194
- err = BCME_NOMEM;
2195
- DHD_ERROR(("failed to get Legacy PNO SSID list\n"));
2196
- goto exit;
2197
- }
2198
-
2199
- if ((err = _dhd_pno_add_ssid(dhd, pssid_list,
2200
- params_legacy->params_legacy.nssid)) < 0) {
2078
+ if ((err = _dhd_pno_add_ssid(dhd, &params_legacy->ssid_list,
2079
+ params_legacy->nssid)) < 0) {
22012080 DHD_ERROR(("failed to add ssid list (err %d) in firmware\n", err));
22022081 goto exit;
22032082 }
....@@ -2210,7 +2089,7 @@
22102089
22112090 gscan_param_size = sizeof(wl_pfn_gscan_cfg_t) +
22122091 (num_buckets_to_fw - 1) * sizeof(wl_pfn_gscan_ch_bucket_cfg_t);
2213
- pfn_gscan_cfg_t = (wl_pfn_gscan_cfg_t *) MALLOC(dhd->osh, gscan_param_size);
2092
+ pfn_gscan_cfg_t = (wl_pfn_gscan_cfg_t *) MALLOCZ(dhd->osh, gscan_param_size);
22142093
22152094 if (!pfn_gscan_cfg_t) {
22162095 DHD_ERROR(("%s: failed to malloc memory of size %d\n",
....@@ -2220,40 +2099,28 @@
22202099 }
22212100
22222101 pfn_gscan_cfg_t->version = WL_GSCAN_CFG_VERSION;
2223
- if (gscan_params->mscan) {
2102
+ if (gscan_params->mscan)
22242103 pfn_gscan_cfg_t->buffer_threshold = gscan_params->buffer_threshold;
2225
- } else {
2104
+ else
22262105 pfn_gscan_cfg_t->buffer_threshold = GSCAN_BATCH_NO_THR_SET;
2227
- }
2228
- if (gscan_params->nbssid_significant_change) {
2229
- pfn_gscan_cfg_t->swc_nbssid_threshold = gscan_params->swc_nbssid_threshold;
2230
- pfn_gscan_cfg_t->swc_rssi_window_size = gscan_params->swc_rssi_window_size;
2231
- pfn_gscan_cfg_t->lost_ap_window = gscan_params->lost_ap_window;
2232
- } else {
2233
- pfn_gscan_cfg_t->swc_nbssid_threshold = 0;
2234
- pfn_gscan_cfg_t->swc_rssi_window_size = 0;
2235
- pfn_gscan_cfg_t->lost_ap_window = 0;
2236
- }
22372106
22382107 pfn_gscan_cfg_t->flags =
22392108 (gscan_params->send_all_results_flag & GSCAN_SEND_ALL_RESULTS_MASK);
2109
+ pfn_gscan_cfg_t->flags |= GSCAN_ALL_BUCKETS_IN_FIRST_SCAN_MASK;
22402110 pfn_gscan_cfg_t->count_of_channel_buckets = num_buckets_to_fw;
22412111 pfn_gscan_cfg_t->retry_threshold = GSCAN_RETRY_THRESHOLD;
22422112
2243
- for (i = 0, k = 0; i < tot_num_buckets; i++) {
2244
- if (ch_bucket[i].bucket_end_index != CHANNEL_BUCKET_EMPTY_INDEX) {
2245
- pfn_gscan_cfg_t->channel_bucket[k].bucket_end_index =
2246
- ch_bucket[i].bucket_end_index;
2247
- pfn_gscan_cfg_t->channel_bucket[k].bucket_freq_multiple =
2248
- ch_bucket[i].bucket_freq_multiple;
2249
- pfn_gscan_cfg_t->channel_bucket[k].max_freq_multiple =
2250
- ch_bucket[i].max_freq_multiple;
2251
- pfn_gscan_cfg_t->channel_bucket[k].repeat =
2252
- ch_bucket[i].repeat;
2253
- pfn_gscan_cfg_t->channel_bucket[k].flag =
2254
- ch_bucket[i].flag;
2255
- k++;
2256
- }
2113
+ for (i = 0; i < num_buckets_to_fw; i++) {
2114
+ pfn_gscan_cfg_t->channel_bucket[i].bucket_end_index =
2115
+ ch_bucket[i].bucket_end_index;
2116
+ pfn_gscan_cfg_t->channel_bucket[i].bucket_freq_multiple =
2117
+ ch_bucket[i].bucket_freq_multiple;
2118
+ pfn_gscan_cfg_t->channel_bucket[i].max_freq_multiple =
2119
+ ch_bucket[i].max_freq_multiple;
2120
+ pfn_gscan_cfg_t->channel_bucket[i].repeat =
2121
+ ch_bucket[i].repeat;
2122
+ pfn_gscan_cfg_t->channel_bucket[i].flag =
2123
+ ch_bucket[i].flag;
22572124 }
22582125
22592126 tot_nchan = pfn_gscan_cfg_t->channel_bucket[num_buckets_to_fw - 1].bucket_end_index + 1;
....@@ -2271,43 +2138,16 @@
22712138 __FUNCTION__, err));
22722139 goto exit;
22732140 }
2274
- if (gscan_params->nbssid_significant_change) {
2275
- dhd_pno_significant_bssid_t *iter, *next;
2276
-
2277
- p_pfn_significant_bssid = kzalloc(sizeof(wl_pfn_significant_bssid_t) *
2278
- gscan_params->nbssid_significant_change, GFP_KERNEL);
2279
- if (p_pfn_significant_bssid == NULL) {
2280
- DHD_ERROR(("%s : failed to allocate memory %zd\n",
2281
- __FUNCTION__,
2282
- sizeof(wl_pfn_significant_bssid_t) *
2283
- gscan_params->nbssid_significant_change));
2284
- err = BCME_NOMEM;
2285
- goto exit;
2286
- }
2287
- i = 0;
2288
- /* convert dhd_pno_significant_bssid_t to wl_pfn_significant_bssid_t */
2289
- list_for_each_entry_safe(iter, next, &gscan_params->significant_bssid_list, list) {
2290
- p_pfn_significant_bssid[i].rssi_low_threshold = iter->rssi_low_threshold;
2291
- p_pfn_significant_bssid[i].rssi_high_threshold = iter->rssi_high_threshold;
2292
- memcpy(&p_pfn_significant_bssid[i].macaddr, &iter->BSSID, ETHER_ADDR_LEN);
2293
- i++;
2294
- }
2295
- DHD_PNO(("nbssid_significant_change %d \n",
2296
- gscan_params->nbssid_significant_change));
2297
- err = _dhd_pno_add_significant_bssid(dhd, p_pfn_significant_bssid,
2298
- gscan_params->nbssid_significant_change);
2299
- if (err < 0) {
2300
- DHD_ERROR(("%s : failed to call _dhd_pno_add_significant_bssid(err :%d)\n",
2301
- __FUNCTION__, err));
2302
- goto exit;
2303
- }
2141
+ /* Reprogram ePNO cfg from dhd cache if FW has been flushed */
2142
+ if (fw_flushed) {
2143
+ dhd_pno_set_epno(dhd);
23042144 }
23052145
23062146 if (gscan_params->nbssid_hotlist) {
23072147 struct dhd_pno_bssid *iter, *next;
23082148 wl_pfn_bssid_t *ptr;
2309
- p_pfn_bssid = (wl_pfn_bssid_t *)kzalloc(sizeof(wl_pfn_bssid_t) *
2310
- gscan_params->nbssid_hotlist, GFP_KERNEL);
2149
+ p_pfn_bssid = (wl_pfn_bssid_t *)MALLOCZ(dhd->osh,
2150
+ sizeof(wl_pfn_bssid_t) * gscan_params->nbssid_hotlist);
23112151 if (p_pfn_bssid == NULL) {
23122152 DHD_ERROR(("%s : failed to allocate wl_pfn_bssid_t array"
23132153 " (count: %d)",
....@@ -2319,10 +2159,15 @@
23192159 ptr = p_pfn_bssid;
23202160 /* convert dhd_pno_bssid to wl_pfn_bssid */
23212161 DHD_PNO(("nhotlist %d\n", gscan_params->nbssid_hotlist));
2162
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
23222163 list_for_each_entry_safe(iter, next,
23232164 &gscan_params->hotlist_bssid_list, list) {
2165
+ char buffer_hotlist[64];
2166
+ GCC_DIAGNOSTIC_POP();
23242167 memcpy(&ptr->macaddr,
23252168 &iter->macaddr, ETHER_ADDR_LEN);
2169
+ BCM_REFERENCE(buffer_hotlist);
2170
+ DHD_PNO(("%s\n", bcm_ether_ntoa(&ptr->macaddr, buffer_hotlist)));
23262171 ptr->flags = iter->flags;
23272172 ptr++;
23282173 }
....@@ -2331,15 +2176,6 @@
23312176 if (err < 0) {
23322177 DHD_ERROR(("%s : failed to call _dhd_pno_add_bssid(err :%d)\n",
23332178 __FUNCTION__, err));
2334
- goto exit;
2335
- }
2336
- }
2337
-
2338
- if (gscan_params->num_epno_ssid > 0) {
2339
- DHD_ERROR(("num_epno_ssid %d\n", gscan_params->num_epno_ssid));
2340
- err = dhd_epno_set_ssid(dhd, _pno_state);
2341
- if (err < 0) {
2342
- DHD_ERROR(("failed to add ssid list (err %d) in firmware\n", err));
23432179 goto exit;
23442180 }
23452181 }
....@@ -2360,9 +2196,8 @@
23602196 _pno_state->pno_mode &= ~DHD_PNO_GSCAN_MODE;
23612197 }
23622198 }
2363
- kfree(pssid_list);
2364
- kfree(p_pfn_significant_bssid);
2365
- kfree(p_pfn_bssid);
2199
+ MFREE(dhd->osh, p_pfn_bssid,
2200
+ sizeof(wl_pfn_bssid_t) * gscan_params->nbssid_hotlist);
23662201 if (pfn_gscan_cfg_t) {
23672202 MFREE(dhd->osh, pfn_gscan_cfg_t, gscan_param_size);
23682203 }
....@@ -2385,12 +2220,16 @@
23852220 uint16 *ptr = chan_list, max;
23862221 wl_pfn_gscan_ch_bucket_cfg_t *ch_bucket;
23872222 dhd_pno_params_t *_params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
2388
- bool is_pno_legacy_running = _pno_state->pno_mode & DHD_PNO_LEGACY_MODE;
2223
+ bool is_pno_legacy_running;
23892224 dhd_pno_gscan_channel_bucket_t *gscan_buckets = _params->params_gscan.channel_bucket;
2225
+
2226
+ /* ePNO and Legacy PNO do not co-exist */
2227
+ is_pno_legacy_running = ((_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) &&
2228
+ !_params->params_gscan.epno_cfg.num_epno_ssid);
23902229
23912230 if (is_pno_legacy_running)
23922231 *num_buckets = _params->params_gscan.nchannel_buckets + 1;
2393
- else
2232
+ else
23942233 *num_buckets = _params->params_gscan.nchannel_buckets;
23952234
23962235 *num_buckets_to_fw = 0;
....@@ -2463,7 +2302,7 @@
24632302 /* If no space is left then only gscan buckets will be sent to FW */
24642303 if (nchan) {
24652304 common_freq = gcd(_params->params_gscan.scan_fr,
2466
- _params1->params_legacy.scan_fr);
2305
+ _params1->params_legacy.scan_fr);
24672306 max = gscan_buckets[0].bucket_freq_multiple;
24682307 /* GSCAN buckets */
24692308 for (i = 0; i < _params->params_gscan.nchannel_buckets; i++) {
....@@ -2474,11 +2313,11 @@
24742313 }
24752314 /* Legacy PNO bucket */
24762315 ch_bucket[legacy_bucket_idx].bucket_freq_multiple =
2477
- _params1->params_legacy.scan_fr;
2316
+ _params1->params_legacy.scan_fr;
24782317 ch_bucket[legacy_bucket_idx].bucket_freq_multiple /=
2479
- common_freq;
2318
+ common_freq;
24802319 _params->params_gscan.max_ch_bucket_freq = MAX(max,
2481
- ch_bucket[legacy_bucket_idx].bucket_freq_multiple);
2320
+ ch_bucket[legacy_bucket_idx].bucket_freq_multiple);
24822321 ch_bucket[legacy_bucket_idx].flag = CH_BUCKET_REPORT_REGULAR;
24832322 /* Now add channels to the legacy scan bucket */
24842323 for (i = 0; i < _params1->params_legacy.nchan && nchan; i++, nchan--) {
....@@ -2488,8 +2327,8 @@
24882327 ch_bucket[legacy_bucket_idx].bucket_end_index = num_channels - 1;
24892328 *num_buckets_to_fw = *num_buckets_to_fw + 1;
24902329 DHD_PNO(("end_idx %d freq_mult - %d\n",
2491
- ch_bucket[legacy_bucket_idx].bucket_end_index,
2492
- ch_bucket[legacy_bucket_idx].bucket_freq_multiple));
2330
+ ch_bucket[legacy_bucket_idx].bucket_end_index,
2331
+ ch_bucket[legacy_bucket_idx].bucket_freq_multiple));
24932332 }
24942333 }
24952334 return ch_bucket;
....@@ -2501,7 +2340,6 @@
25012340 int err = BCME_OK;
25022341 int mode;
25032342 dhd_pno_status_info_t *_pno_state;
2504
- wlc_ssid_ext_t *pssid_list = NULL;
25052343
25062344 _pno_state = PNO_GET_PNOSTATE(dhd);
25072345 DHD_PNO(("%s enter\n", __FUNCTION__));
....@@ -2538,7 +2376,6 @@
25382376 }
25392377 _pno_state->pno_mode = mode;
25402378 mutex_unlock(&_pno_state->pno_mutex);
2541
- _pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan.ssid_ext_last_used_index = 0;
25422379
25432380 /* Reprogram Legacy PNO if it was running */
25442381 if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
....@@ -2547,20 +2384,13 @@
25472384
25482385 params_legacy = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy);
25492386 _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
2550
- pssid_list = dhd_pno_get_legacy_pno_ssid(dhd, _pno_state);
2551
- if (!pssid_list) {
2552
- err = BCME_NOMEM;
2553
- DHD_ERROR(("failed to get Legacy PNO SSID list\n"));
2554
- goto exit;
2555
- }
25562387
25572388 DHD_PNO(("Restarting Legacy PNO SSID scan...\n"));
25582389 memcpy(chan_list, params_legacy->chan_list,
2559
- (params_legacy->nchan * sizeof(uint16)));
2560
- err = dhd_pno_set_for_ssid(dhd, pssid_list, params_legacy->nssid,
2561
- params_legacy->scan_fr, params_legacy->pno_repeat,
2562
- params_legacy->pno_freq_expo_max, chan_list,
2563
- params_legacy->nchan);
2390
+ (params_legacy->nchan * sizeof(uint16)));
2391
+ err = dhd_pno_set_legacy_pno(dhd, params_legacy->scan_fr,
2392
+ params_legacy->pno_repeat, params_legacy->pno_freq_expo_max,
2393
+ chan_list, params_legacy->nchan);
25642394 if (err < 0) {
25652395 DHD_ERROR(("%s : failed to restart legacy PNO scan(err: %d)\n",
25662396 __FUNCTION__, err));
....@@ -2570,7 +2400,6 @@
25702400 }
25712401
25722402 exit:
2573
- kfree(pssid_list);
25742403 return err;
25752404 }
25762405
....@@ -2596,7 +2425,7 @@
25962425 } else {
25972426 if (flush) {
25982427 mutex_lock(&_pno_state->pno_mutex);
2599
- dhd_pno_reset_cfg_gscan(params, _pno_state, GSCAN_FLUSH_ALL_CFG);
2428
+ dhd_pno_reset_cfg_gscan(dhd, params, _pno_state, GSCAN_FLUSH_ALL_CFG);
26002429 mutex_unlock(&_pno_state->pno_mutex);
26012430 }
26022431 /* Need to stop all gscan */
....@@ -2637,13 +2466,14 @@
26372466 if (_pno_state->pno_mode & DHD_PNO_GSCAN_MODE) {
26382467 if (old_flag != gscan_params->send_all_results_flag) {
26392468 wl_pfn_gscan_cfg_t gscan_cfg;
2469
+
26402470 gscan_cfg.version = WL_GSCAN_CFG_VERSION;
26412471 gscan_cfg.flags = (gscan_params->send_all_results_flag &
2642
- GSCAN_SEND_ALL_RESULTS_MASK);
2472
+ GSCAN_SEND_ALL_RESULTS_MASK);
26432473 gscan_cfg.flags |= GSCAN_CFG_FLAGS_ONLY_MASK;
26442474
26452475 if ((err = _dhd_pno_gscan_cfg(dhd, &gscan_cfg,
2646
- sizeof(wl_pfn_gscan_cfg_t))) < 0) {
2476
+ sizeof(wl_pfn_gscan_cfg_t))) < 0) {
26472477 DHD_ERROR(("%s : pno_gscan_cfg failed (err %d) in firmware\n",
26482478 __FUNCTION__, err));
26492479 goto exit_mutex_unlock;
....@@ -2661,7 +2491,7 @@
26612491 }
26622492
26632493 /* Cleanup any consumed results
2664
- * Return TRUE if all results consumed, else FALSE
2494
+ * Return TRUE if all results consumed else FALSE
26652495 */
26662496 int dhd_gscan_batch_cache_cleanup(dhd_pub_t *dhd)
26672497 {
....@@ -2679,7 +2509,9 @@
26792509 while (iter) {
26802510 if (iter->tot_consumed == iter->tot_count) {
26812511 tmp = iter->next;
2682
- kfree(iter);
2512
+ MFREE(dhd->osh, iter,
2513
+ ((iter->tot_count - 1) * sizeof(wifi_gscan_result_t))
2514
+ + sizeof(gscan_results_cache_t));
26832515 iter = tmp;
26842516 } else
26852517 break;
....@@ -2696,14 +2528,29 @@
26962528 uint32 timestamp = 0, ts = 0, i, j, timediff;
26972529 dhd_pno_params_t *params;
26982530 dhd_pno_status_info_t *_pno_state;
2699
- wl_pfn_lnet_info_t *plnetinfo;
2531
+ wl_pfn_lnet_info_v1_t *plnetinfo;
2532
+ wl_pfn_lnet_info_v2_t *plnetinfo_v2;
27002533 struct dhd_pno_gscan_params *gscan_params;
2701
- wl_pfn_lscanresults_t *plbestnet = NULL;
2534
+ wl_pfn_lscanresults_v1_t *plbestnet_v1 = NULL;
2535
+ wl_pfn_lscanresults_v2_t *plbestnet_v2 = NULL;
27022536 gscan_results_cache_t *iter, *tail;
27032537 wifi_gscan_result_t *result;
27042538 uint8 *nAPs_per_scan = NULL;
27052539 uint8 num_scans_in_cur_iter;
27062540 uint16 count;
2541
+ uint16 fwcount;
2542
+ uint16 fwstatus = PFN_INCOMPLETE;
2543
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0))
2544
+ struct timespec64 tm_spec;
2545
+#else
2546
+ struct timespec tm_spec;
2547
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)) */
2548
+
2549
+ /* Static asserts in _dhd_pno_get_for_batch() below guarantee the v1 and v2
2550
+ * net_info and subnet_info structures are compatible in size and SSID offset,
2551
+ * allowing v1 to be safely used in the code below except for lscanresults
2552
+ * fields themselves (status, count, offset to netinfo).
2553
+ */
27072554
27082555 NULL_CHECK(dhd, "dhd is NULL\n", err);
27092556 NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
....@@ -2731,7 +2578,14 @@
27312578 goto exit;
27322579 }
27332580
2734
- plbestnet = (wl_pfn_lscanresults_t *)MALLOC(dhd->osh, PNO_BESTNET_LEN);
2581
+ plbestnet_v1 = (wl_pfn_lscanresults_v1_t *)MALLOC(dhd->osh, PNO_BESTNET_LEN);
2582
+ if (!plbestnet_v1) {
2583
+ DHD_ERROR(("%s :Out of memory!! Cant malloc %d bytes\n", __FUNCTION__,
2584
+ (int)PNO_BESTNET_LEN));
2585
+ err = BCME_NOMEM;
2586
+ goto exit;
2587
+ }
2588
+ plbestnet_v2 = (wl_pfn_lscanresults_v2_t *)plbestnet_v1;
27352589
27362590 mutex_lock(&_pno_state->pno_mutex);
27372591
....@@ -2746,136 +2600,284 @@
27462600 timediff = timediff >> 1;
27472601
27482602 /* Ok, now lets start getting results from the FW */
2749
- plbestnet->status = PFN_INCOMPLETE;
27502603 tail = gscan_params->gscan_batch_cache;
2751
- while (plbestnet->status != PFN_COMPLETE) {
2752
- memset(plbestnet, 0, PNO_BESTNET_LEN);
2753
- err = dhd_iovar(dhd, 0, "pfnlbest", NULL, 0, (char *)plbestnet, PNO_BESTNET_LEN,
2754
- FALSE);
2604
+ do {
2605
+ err = dhd_iovar(dhd, 0, "pfnlbest", NULL, 0, (char *)plbestnet_v1, PNO_BESTNET_LEN,
2606
+ FALSE);
27552607 if (err < 0) {
27562608 DHD_ERROR(("%s : Cannot get all the batch results, err :%d\n",
27572609 __FUNCTION__, err));
27582610 goto exit_mutex_unlock;
27592611 }
2760
- DHD_PNO(("ver %d, status : %d, count %d\n", plbestnet->version,
2761
- plbestnet->status, plbestnet->count));
2762
- if (plbestnet->version != PFN_SCANRESULT_VERSION) {
2763
- err = BCME_VERSION;
2764
- DHD_ERROR(("bestnet version(%d) is mismatch with Driver version(%d)\n",
2765
- plbestnet->version, PFN_SCANRESULT_VERSION));
2766
- goto exit_mutex_unlock;
2767
- }
2768
- if (plbestnet->count == 0) {
2769
- DHD_PNO(("No more batch results\n"));
2770
- goto exit_mutex_unlock;
2771
- }
2772
- num_scans_in_cur_iter = 0;
2773
- timestamp = plbestnet->netinfo[0].timestamp;
2774
- /* find out how many scans' results did we get in this batch of FW results */
2775
- for (i = 0, count = 0; i < plbestnet->count; i++, count++) {
2776
- plnetinfo = &plbestnet->netinfo[i];
2777
- /* Unlikely to happen, but just in case the results from
2778
- * FW doesnt make sense..... Assume its part of one single scan
2779
- */
2780
- if (num_scans_in_cur_iter > gscan_params->mscan) {
2781
- num_scans_in_cur_iter = 0;
2782
- count = plbestnet->count;
2783
- break;
2784
- }
2785
- if (TIME_DIFF_MS(timestamp, plnetinfo->timestamp) > timediff) {
2786
- nAPs_per_scan[num_scans_in_cur_iter] = count;
2787
- count = 0;
2788
- num_scans_in_cur_iter++;
2789
- }
2790
- timestamp = plnetinfo->timestamp;
2791
- }
2792
- nAPs_per_scan[num_scans_in_cur_iter] = count;
2793
- num_scans_in_cur_iter++;
27942612
2795
- DHD_PNO(("num_scans_in_cur_iter %d\n", num_scans_in_cur_iter));
2796
- plnetinfo = &plbestnet->netinfo[0];
2613
+ get_monotonic_boottime(&tm_spec);
2614
+ if (plbestnet_v1->version == PFN_LBEST_SCAN_RESULT_VERSION_V1) {
2615
+ fwstatus = plbestnet_v1->status;
2616
+ fwcount = plbestnet_v1->count;
2617
+ plnetinfo = &plbestnet_v1->netinfo[0];
27972618
2798
- for (i = 0; i < num_scans_in_cur_iter; i++) {
2799
- iter = (gscan_results_cache_t *)
2800
- kmalloc(((nAPs_per_scan[i] - 1) * sizeof(wifi_gscan_result_t)) +
2801
- sizeof(gscan_results_cache_t), GFP_KERNEL);
2802
- if (!iter) {
2803
- DHD_ERROR(("%s :Out of memory!! Cant malloc %d bytes\n",
2804
- __FUNCTION__, gscan_params->mscan));
2805
- err = BCME_NOMEM;
2619
+ DHD_PNO(("ver %d, status : %d, count %d\n",
2620
+ plbestnet_v1->version, fwstatus, fwcount));
2621
+
2622
+ if (fwcount == 0) {
2623
+ DHD_PNO(("No more batch results\n"));
28062624 goto exit_mutex_unlock;
28072625 }
2808
- /* Need this check because the new set of results from FW
2809
- * maybe a continuation of previous sets' scan results
2626
+ if (fwcount > BESTN_MAX) {
2627
+ DHD_ERROR(("%s :fwcount %d is greater than BESTN_MAX %d \n",
2628
+ __FUNCTION__, fwcount, (int)BESTN_MAX));
2629
+ /* Process only BESTN_MAX number of results per batch */
2630
+ fwcount = BESTN_MAX;
2631
+ }
2632
+ num_scans_in_cur_iter = 0;
2633
+
2634
+ timestamp = plnetinfo->timestamp;
2635
+ /* find out how many scans' results did we get in
2636
+ * this batch of FW results
28102637 */
2811
- if (TIME_DIFF_MS(ts, plnetinfo->timestamp) > timediff) {
2812
- iter->scan_id = ++gscan_params->scan_id;
2813
- } else {
2814
- iter->scan_id = gscan_params->scan_id;
2815
- }
2816
- DHD_PNO(("scan_id %d tot_count %d\n", gscan_params->scan_id,
2817
- nAPs_per_scan[i]));
2818
- iter->tot_count = nAPs_per_scan[i];
2819
- iter->tot_consumed = 0;
2820
- iter->flag = 0;
2821
- if (plnetinfo->flags & PFN_PARTIAL_SCAN_MASK) {
2822
- DHD_PNO(("This scan is aborted\n"));
2823
- iter->flag = (ENABLE << PNO_STATUS_ABORT);
2824
- } else if (gscan_params->reason) {
2825
- iter->flag = (ENABLE << gscan_params->reason);
2826
- }
2827
-
2828
- if (!tail) {
2829
- gscan_params->gscan_batch_cache = iter;
2830
- } else {
2831
- tail->next = iter;
2832
- }
2833
- tail = iter;
2834
- iter->next = NULL;
2835
- for (j = 0; j < nAPs_per_scan[i]; j++, plnetinfo++) {
2836
- result = &iter->results[j];
2837
-
2838
- result->channel = wf_channel2mhz(plnetinfo->pfnsubnet.channel,
2839
- (plnetinfo->pfnsubnet.channel <= CH_MAX_2G_CHANNEL?
2840
- WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
2841
- result->rssi = (int32) plnetinfo->RSSI;
2842
- /* Info not available & not expected */
2843
- result->beacon_period = 0;
2844
- result->capability = 0;
2845
- result->ie_length = 0;
2846
- result->rtt = (uint64) plnetinfo->rtt0;
2847
- result->rtt_sd = (uint64) plnetinfo->rtt1;
2848
- result->ts = convert_fw_rel_time_to_systime(plnetinfo->timestamp);
2849
- ts = plnetinfo->timestamp;
2850
- if (plnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) {
2851
- DHD_ERROR(("%s: Invalid SSID length %d\n",
2852
- __FUNCTION__, plnetinfo->pfnsubnet.SSID_len));
2853
- plnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN;
2638
+ for (i = 0, count = 0; i < fwcount; i++, count++, plnetinfo++) {
2639
+ /* Unlikely to happen, but just in case the results from
2640
+ * FW doesnt make sense..... Assume its part of one single scan
2641
+ */
2642
+ if (num_scans_in_cur_iter >= gscan_params->mscan) {
2643
+ num_scans_in_cur_iter = 0;
2644
+ count = fwcount;
2645
+ break;
28542646 }
2855
- memcpy(result->ssid, plnetinfo->pfnsubnet.SSID,
2856
- plnetinfo->pfnsubnet.SSID_len);
2857
- result->ssid[plnetinfo->pfnsubnet.SSID_len] = '\0';
2858
- memcpy(&result->macaddr, &plnetinfo->pfnsubnet.BSSID,
2859
- ETHER_ADDR_LEN);
2860
-
2861
- DHD_PNO(("\tSSID : "));
2862
- DHD_PNO(("\n"));
2863
- DHD_PNO(("\tBSSID: %02x:%02x:%02x:%02x:%02x:%02x\n",
2864
- result->macaddr.octet[0],
2865
- result->macaddr.octet[1],
2866
- result->macaddr.octet[2],
2867
- result->macaddr.octet[3],
2868
- result->macaddr.octet[4],
2869
- result->macaddr.octet[5]));
2870
- DHD_PNO(("\tchannel: %d, RSSI: %d, timestamp: %d ms\n",
2871
- plnetinfo->pfnsubnet.channel,
2872
- plnetinfo->RSSI, plnetinfo->timestamp));
2873
- DHD_PNO(("\tRTT0 : %d, RTT1: %d\n",
2874
- plnetinfo->rtt0, plnetinfo->rtt1));
2875
-
2647
+ if (TIME_DIFF_MS(timestamp, plnetinfo->timestamp) > timediff) {
2648
+ nAPs_per_scan[num_scans_in_cur_iter] = count;
2649
+ count = 0;
2650
+ num_scans_in_cur_iter++;
2651
+ }
2652
+ timestamp = plnetinfo->timestamp;
28762653 }
2654
+ if (num_scans_in_cur_iter < gscan_params->mscan) {
2655
+ nAPs_per_scan[num_scans_in_cur_iter] = count;
2656
+ num_scans_in_cur_iter++;
2657
+ }
2658
+
2659
+ DHD_PNO(("num_scans_in_cur_iter %d\n", num_scans_in_cur_iter));
2660
+ /* reset plnetinfo to the first item for the next loop */
2661
+ plnetinfo -= i;
2662
+
2663
+ for (i = 0; i < num_scans_in_cur_iter; i++) {
2664
+ iter = (gscan_results_cache_t *)
2665
+ MALLOCZ(dhd->osh, ((nAPs_per_scan[i] - 1) *
2666
+ sizeof(wifi_gscan_result_t)) +
2667
+ sizeof(gscan_results_cache_t));
2668
+ if (!iter) {
2669
+ DHD_ERROR(("%s :Out of memory!! Cant malloc %d bytes\n",
2670
+ __FUNCTION__, gscan_params->mscan));
2671
+ err = BCME_NOMEM;
2672
+ goto exit_mutex_unlock;
2673
+ }
2674
+ /* Need this check because the new set of results from FW
2675
+ * maybe a continuation of previous sets' scan results
2676
+ */
2677
+ if (TIME_DIFF_MS(ts, plnetinfo->timestamp) > timediff) {
2678
+ iter->scan_id = ++gscan_params->scan_id;
2679
+ } else {
2680
+ iter->scan_id = gscan_params->scan_id;
2681
+ }
2682
+ DHD_PNO(("scan_id %d tot_count %d \n",
2683
+ gscan_params->scan_id, nAPs_per_scan[i]));
2684
+ iter->tot_count = nAPs_per_scan[i];
2685
+ iter->tot_consumed = 0;
2686
+ iter->flag = 0;
2687
+ if (plnetinfo->flags & PFN_PARTIAL_SCAN_MASK) {
2688
+ DHD_PNO(("This scan is aborted\n"));
2689
+ iter->flag = (ENABLE << PNO_STATUS_ABORT);
2690
+ } else if (gscan_params->reason) {
2691
+ iter->flag = (ENABLE << gscan_params->reason);
2692
+ }
2693
+
2694
+ if (!tail) {
2695
+ gscan_params->gscan_batch_cache = iter;
2696
+ } else {
2697
+ tail->next = iter;
2698
+ }
2699
+ tail = iter;
2700
+ iter->next = NULL;
2701
+ for (j = 0; j < nAPs_per_scan[i]; j++, plnetinfo++) {
2702
+ result = &iter->results[j];
2703
+
2704
+ result->channel =
2705
+ wf_channel2mhz(plnetinfo->pfnsubnet.channel,
2706
+ (plnetinfo->pfnsubnet.channel <= CH_MAX_2G_CHANNEL?
2707
+ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
2708
+ result->rssi = (int32) plnetinfo->RSSI;
2709
+ result->beacon_period = 0;
2710
+ result->capability = 0;
2711
+ result->rtt = (uint64) plnetinfo->rtt0;
2712
+ result->rtt_sd = (uint64) plnetinfo->rtt1;
2713
+ result->ts = convert_fw_rel_time_to_systime(&tm_spec,
2714
+ plnetinfo->timestamp);
2715
+ ts = plnetinfo->timestamp;
2716
+ if (plnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) {
2717
+ DHD_ERROR(("%s: Invalid SSID length %d\n",
2718
+ __FUNCTION__,
2719
+ plnetinfo->pfnsubnet.SSID_len));
2720
+ plnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN;
2721
+ }
2722
+ memcpy(result->ssid, plnetinfo->pfnsubnet.SSID,
2723
+ plnetinfo->pfnsubnet.SSID_len);
2724
+ result->ssid[plnetinfo->pfnsubnet.SSID_len] = '\0';
2725
+ memcpy(&result->macaddr, &plnetinfo->pfnsubnet.BSSID,
2726
+ ETHER_ADDR_LEN);
2727
+
2728
+ DHD_PNO(("\tSSID : "));
2729
+ DHD_PNO(("\n"));
2730
+ DHD_PNO(("\tBSSID: "MACDBG"\n",
2731
+ MAC2STRDBG(result->macaddr.octet)));
2732
+ DHD_PNO(("\tchannel: %d, RSSI: %d, timestamp: %d ms\n",
2733
+ plnetinfo->pfnsubnet.channel,
2734
+ plnetinfo->RSSI, plnetinfo->timestamp));
2735
+ DHD_PNO(("\tRTT0 : %d, RTT1: %d\n",
2736
+ plnetinfo->rtt0, plnetinfo->rtt1));
2737
+
2738
+ }
2739
+ }
2740
+
2741
+ } else if (plbestnet_v2->version == PFN_LBEST_SCAN_RESULT_VERSION_V2) {
2742
+ fwstatus = plbestnet_v2->status;
2743
+ fwcount = plbestnet_v2->count;
2744
+ plnetinfo_v2 = (wl_pfn_lnet_info_v2_t*)&plbestnet_v2->netinfo[0];
2745
+
2746
+ DHD_PNO(("ver %d, status : %d, count %d\n",
2747
+ plbestnet_v2->version, fwstatus, fwcount));
2748
+
2749
+ if (fwcount == 0) {
2750
+ DHD_PNO(("No more batch results\n"));
2751
+ goto exit_mutex_unlock;
2752
+ }
2753
+ if (fwcount > BESTN_MAX) {
2754
+ DHD_ERROR(("%s :fwcount %d is greater than BESTN_MAX %d \n",
2755
+ __FUNCTION__, fwcount, (int)BESTN_MAX));
2756
+ /* Process only BESTN_MAX number of results per batch */
2757
+ fwcount = BESTN_MAX;
2758
+ }
2759
+ num_scans_in_cur_iter = 0;
2760
+
2761
+ timestamp = plnetinfo_v2->timestamp;
2762
+ /* find out how many scans' results did we get
2763
+ * in this batch of FW results
2764
+ */
2765
+ for (i = 0, count = 0; i < fwcount; i++, count++, plnetinfo_v2++) {
2766
+ /* Unlikely to happen, but just in case the results from
2767
+ * FW doesnt make sense..... Assume its part of one single scan
2768
+ */
2769
+ if (num_scans_in_cur_iter >= gscan_params->mscan) {
2770
+ num_scans_in_cur_iter = 0;
2771
+ count = fwcount;
2772
+ break;
2773
+ }
2774
+ if (TIME_DIFF_MS(timestamp, plnetinfo_v2->timestamp) > timediff) {
2775
+ nAPs_per_scan[num_scans_in_cur_iter] = count;
2776
+ count = 0;
2777
+ num_scans_in_cur_iter++;
2778
+ }
2779
+ timestamp = plnetinfo_v2->timestamp;
2780
+ }
2781
+ if (num_scans_in_cur_iter < gscan_params->mscan) {
2782
+ nAPs_per_scan[num_scans_in_cur_iter] = count;
2783
+ num_scans_in_cur_iter++;
2784
+ }
2785
+
2786
+ DHD_PNO(("num_scans_in_cur_iter %d\n", num_scans_in_cur_iter));
2787
+ /* reset plnetinfo to the first item for the next loop */
2788
+ plnetinfo_v2 -= i;
2789
+
2790
+ for (i = 0; i < num_scans_in_cur_iter; i++) {
2791
+ iter = (gscan_results_cache_t *)
2792
+ MALLOCZ(dhd->osh, ((nAPs_per_scan[i] - 1) *
2793
+ sizeof(wifi_gscan_result_t)) +
2794
+ sizeof(gscan_results_cache_t));
2795
+ if (!iter) {
2796
+ DHD_ERROR(("%s :Out of memory!! Cant malloc %d bytes\n",
2797
+ __FUNCTION__, gscan_params->mscan));
2798
+ err = BCME_NOMEM;
2799
+ goto exit_mutex_unlock;
2800
+ }
2801
+ /* Need this check because the new set of results from FW
2802
+ * maybe a continuation of previous sets' scan results
2803
+ */
2804
+ if (TIME_DIFF_MS(ts, plnetinfo_v2->timestamp) > timediff) {
2805
+ iter->scan_id = ++gscan_params->scan_id;
2806
+ } else {
2807
+ iter->scan_id = gscan_params->scan_id;
2808
+ }
2809
+ DHD_PNO(("scan_id %d tot_count %d ch_bucket %x\n",
2810
+ gscan_params->scan_id, nAPs_per_scan[i],
2811
+ plbestnet_v2->scan_ch_buckets[i]));
2812
+ iter->tot_count = nAPs_per_scan[i];
2813
+ iter->scan_ch_bucket = plbestnet_v2->scan_ch_buckets[i];
2814
+ iter->tot_consumed = 0;
2815
+ iter->flag = 0;
2816
+ if (plnetinfo_v2->flags & PFN_PARTIAL_SCAN_MASK) {
2817
+ DHD_PNO(("This scan is aborted\n"));
2818
+ iter->flag = (ENABLE << PNO_STATUS_ABORT);
2819
+ } else if (gscan_params->reason) {
2820
+ iter->flag = (ENABLE << gscan_params->reason);
2821
+ }
2822
+
2823
+ if (!tail) {
2824
+ gscan_params->gscan_batch_cache = iter;
2825
+ } else {
2826
+ tail->next = iter;
2827
+ }
2828
+ tail = iter;
2829
+ iter->next = NULL;
2830
+ for (j = 0; j < nAPs_per_scan[i]; j++, plnetinfo_v2++) {
2831
+ result = &iter->results[j];
2832
+
2833
+ result->channel =
2834
+ wf_channel2mhz(plnetinfo_v2->pfnsubnet.channel,
2835
+ (plnetinfo_v2->pfnsubnet.channel <=
2836
+ CH_MAX_2G_CHANNEL?
2837
+ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
2838
+ result->rssi = (int32) plnetinfo_v2->RSSI;
2839
+ /* Info not available & not expected */
2840
+ result->beacon_period = 0;
2841
+ result->capability = 0;
2842
+ result->rtt = (uint64) plnetinfo_v2->rtt0;
2843
+ result->rtt_sd = (uint64) plnetinfo_v2->rtt1;
2844
+ result->ts = convert_fw_rel_time_to_systime(&tm_spec,
2845
+ plnetinfo_v2->timestamp);
2846
+ ts = plnetinfo_v2->timestamp;
2847
+ if (plnetinfo_v2->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) {
2848
+ DHD_ERROR(("%s: Invalid SSID length %d\n",
2849
+ __FUNCTION__,
2850
+ plnetinfo_v2->pfnsubnet.SSID_len));
2851
+ plnetinfo_v2->pfnsubnet.SSID_len =
2852
+ DOT11_MAX_SSID_LEN;
2853
+ }
2854
+ memcpy(result->ssid, plnetinfo_v2->pfnsubnet.u.SSID,
2855
+ plnetinfo_v2->pfnsubnet.SSID_len);
2856
+ result->ssid[plnetinfo_v2->pfnsubnet.SSID_len] = '\0';
2857
+ memcpy(&result->macaddr, &plnetinfo_v2->pfnsubnet.BSSID,
2858
+ ETHER_ADDR_LEN);
2859
+
2860
+ DHD_PNO(("\tSSID : "));
2861
+ DHD_PNO(("\n"));
2862
+ DHD_PNO(("\tBSSID: "MACDBG"\n",
2863
+ MAC2STRDBG(result->macaddr.octet)));
2864
+ DHD_PNO(("\tchannel: %d, RSSI: %d, timestamp: %d ms\n",
2865
+ plnetinfo_v2->pfnsubnet.channel,
2866
+ plnetinfo_v2->RSSI, plnetinfo_v2->timestamp));
2867
+ DHD_PNO(("\tRTT0 : %d, RTT1: %d\n",
2868
+ plnetinfo_v2->rtt0, plnetinfo_v2->rtt1));
2869
+
2870
+ }
2871
+ }
2872
+
2873
+ } else {
2874
+ err = BCME_VERSION;
2875
+ DHD_ERROR(("bestnet fw version %d not supported\n",
2876
+ plbestnet_v1->version));
2877
+ goto exit_mutex_unlock;
28772878 }
2878
- }
2879
+ } while (fwstatus == PFN_INCOMPLETE);
2880
+
28792881 exit_mutex_unlock:
28802882 mutex_unlock(&_pno_state->pno_mutex);
28812883 exit:
....@@ -2883,15 +2885,175 @@
28832885 smp_wmb();
28842886 wake_up_interruptible(&_pno_state->batch_get_wait);
28852887 if (nAPs_per_scan) {
2886
- MFREE(dhd->osh, nAPs_per_scan, gscan_params->mscan);
2888
+ MFREE(dhd->osh, nAPs_per_scan, gscan_params->mscan * sizeof(uint8));
28872889 }
2888
- if (plbestnet) {
2889
- MFREE(dhd->osh, plbestnet, PNO_BESTNET_LEN);
2890
+ if (plbestnet_v1) {
2891
+ MFREE(dhd->osh, plbestnet_v1, PNO_BESTNET_LEN);
28902892 }
28912893 DHD_PNO(("Batch retrieval done!\n"));
28922894 return err;
28932895 }
28942896 #endif /* GSCAN_SUPPORT */
2897
+
2898
+#if defined(GSCAN_SUPPORT) || defined(DHD_GET_VALID_CHANNELS)
2899
+static void *
2900
+dhd_get_gscan_batch_results(dhd_pub_t *dhd, uint32 *len)
2901
+{
2902
+ gscan_results_cache_t *iter, *results;
2903
+ dhd_pno_status_info_t *_pno_state;
2904
+ dhd_pno_params_t *_params;
2905
+ uint16 num_scan_ids = 0, num_results = 0;
2906
+
2907
+ _pno_state = PNO_GET_PNOSTATE(dhd);
2908
+ _params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
2909
+
2910
+ iter = results = _params->params_gscan.gscan_batch_cache;
2911
+ while (iter) {
2912
+ num_results += iter->tot_count - iter->tot_consumed;
2913
+ num_scan_ids++;
2914
+ iter = iter->next;
2915
+ }
2916
+
2917
+ *len = ((num_results << 16) | (num_scan_ids));
2918
+ return results;
2919
+}
2920
+
2921
+void *
2922
+dhd_pno_get_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type,
2923
+ void *info, uint32 *len)
2924
+{
2925
+ void *ret = NULL;
2926
+ dhd_pno_gscan_capabilities_t *ptr;
2927
+ dhd_pno_ssid_t *ssid_elem;
2928
+ dhd_pno_params_t *_params;
2929
+ dhd_epno_ssid_cfg_t *epno_cfg;
2930
+ dhd_pno_status_info_t *_pno_state;
2931
+
2932
+ if (!dhd || !dhd->pno_state) {
2933
+ DHD_ERROR(("NULL POINTER : %s\n", __FUNCTION__));
2934
+ return NULL;
2935
+ }
2936
+
2937
+ _pno_state = PNO_GET_PNOSTATE(dhd);
2938
+ _params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
2939
+
2940
+ if (!len) {
2941
+ DHD_ERROR(("%s: len is NULL\n", __FUNCTION__));
2942
+ return NULL;
2943
+ }
2944
+
2945
+ switch (type) {
2946
+ case DHD_PNO_GET_CAPABILITIES:
2947
+ ptr = (dhd_pno_gscan_capabilities_t *)
2948
+ MALLOCZ(dhd->osh, sizeof(dhd_pno_gscan_capabilities_t));
2949
+ if (!ptr)
2950
+ break;
2951
+ /* Hardcoding these values for now, need to get
2952
+ * these values from FW, will change in a later check-in
2953
+ */
2954
+ ptr->max_scan_cache_size = GSCAN_MAX_AP_CACHE;
2955
+ ptr->max_scan_buckets = GSCAN_MAX_CH_BUCKETS;
2956
+ ptr->max_ap_cache_per_scan = GSCAN_MAX_AP_CACHE_PER_SCAN;
2957
+ ptr->max_rssi_sample_size = PFN_SWC_RSSI_WINDOW_MAX;
2958
+ ptr->max_scan_reporting_threshold = 100;
2959
+ ptr->max_hotlist_bssids = PFN_HOTLIST_MAX_NUM_APS;
2960
+ ptr->max_hotlist_ssids = 0;
2961
+ ptr->max_significant_wifi_change_aps = 0;
2962
+ ptr->max_bssid_history_entries = 0;
2963
+ ptr->max_epno_ssid_crc32 = MAX_EPNO_SSID_NUM;
2964
+ ptr->max_epno_hidden_ssid = MAX_EPNO_HIDDEN_SSID;
2965
+ ptr->max_white_list_ssid = MAX_WHITELIST_SSID;
2966
+ ret = (void *)ptr;
2967
+ *len = sizeof(dhd_pno_gscan_capabilities_t);
2968
+ break;
2969
+
2970
+ case DHD_PNO_GET_BATCH_RESULTS:
2971
+ ret = dhd_get_gscan_batch_results(dhd, len);
2972
+ break;
2973
+ case DHD_PNO_GET_CHANNEL_LIST:
2974
+ if (info) {
2975
+ uint16 ch_list[WL_NUMCHANNELS];
2976
+ uint32 *p, mem_needed, i;
2977
+ int32 err, nchan = WL_NUMCHANNELS;
2978
+ uint32 *gscan_band = (uint32 *) info;
2979
+ uint8 band = 0;
2980
+
2981
+ /* No band specified?, nothing to do */
2982
+ if ((*gscan_band & GSCAN_BAND_MASK) == 0) {
2983
+ DHD_PNO(("No band specified\n"));
2984
+ *len = 0;
2985
+ break;
2986
+ }
2987
+
2988
+ /* HAL and DHD use different bits for 2.4G and
2989
+ * 5G in bitmap. Hence translating it here...
2990
+ */
2991
+ if (*gscan_band & GSCAN_BG_BAND_MASK) {
2992
+ band |= WLC_BAND_2G;
2993
+ }
2994
+ if (*gscan_band & GSCAN_A_BAND_MASK) {
2995
+ band |= WLC_BAND_5G;
2996
+ }
2997
+
2998
+ err = _dhd_pno_get_channels(dhd, ch_list, &nchan,
2999
+ (band & GSCAN_ABG_BAND_MASK),
3000
+ !(*gscan_band & GSCAN_DFS_MASK));
3001
+
3002
+ if (err < 0) {
3003
+ DHD_ERROR(("%s: failed to get valid channel list\n",
3004
+ __FUNCTION__));
3005
+ *len = 0;
3006
+ } else {
3007
+ mem_needed = sizeof(uint32) * nchan;
3008
+ p = (uint32 *)MALLOC(dhd->osh, mem_needed);
3009
+ if (!p) {
3010
+ DHD_ERROR(("%s: Unable to malloc %d bytes\n",
3011
+ __FUNCTION__, mem_needed));
3012
+ break;
3013
+ }
3014
+ for (i = 0; i < nchan; i++) {
3015
+ p[i] = wf_channel2mhz(ch_list[i],
3016
+ (ch_list[i] <= CH_MAX_2G_CHANNEL?
3017
+ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
3018
+ }
3019
+ ret = p;
3020
+ *len = mem_needed;
3021
+ }
3022
+ } else {
3023
+ *len = 0;
3024
+ DHD_ERROR(("%s: info buffer is NULL\n", __FUNCTION__));
3025
+ }
3026
+ break;
3027
+ case DHD_PNO_GET_NEW_EPNO_SSID_ELEM:
3028
+ epno_cfg = &_params->params_gscan.epno_cfg;
3029
+ if (epno_cfg->num_epno_ssid >=
3030
+ MAX_EPNO_SSID_NUM) {
3031
+ DHD_ERROR(("Excessive number of ePNO SSIDs programmed %d\n",
3032
+ epno_cfg->num_epno_ssid));
3033
+ return NULL;
3034
+ }
3035
+ if (!epno_cfg->num_epno_ssid) {
3036
+ INIT_LIST_HEAD(&epno_cfg->epno_ssid_list);
3037
+ }
3038
+ ssid_elem = MALLOCZ(dhd->osh, sizeof(dhd_pno_ssid_t));
3039
+ if (!ssid_elem) {
3040
+ DHD_ERROR(("EPNO ssid: cannot alloc %zd bytes",
3041
+ sizeof(dhd_pno_ssid_t)));
3042
+ return NULL;
3043
+ }
3044
+ epno_cfg->num_epno_ssid++;
3045
+ list_add_tail(&ssid_elem->list, &epno_cfg->epno_ssid_list);
3046
+ ret = ssid_elem;
3047
+ break;
3048
+ default:
3049
+ DHD_ERROR(("%s: Unrecognized cmd type - %d\n", __FUNCTION__, type));
3050
+ break;
3051
+ }
3052
+
3053
+ return ret;
3054
+
3055
+}
3056
+#endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */
28953057
28963058 static int
28973059 _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason)
....@@ -2901,20 +3063,38 @@
29013063 uint32 timestamp = 0;
29023064 dhd_pno_params_t *_params = NULL;
29033065 dhd_pno_status_info_t *_pno_state = NULL;
2904
- wl_pfn_lscanresults_t *plbestnet = NULL;
2905
- wl_pfn_lnet_info_t *plnetinfo;
3066
+ wl_pfn_lscanresults_v1_t *plbestnet_v1 = NULL;
3067
+ wl_pfn_lscanresults_v2_t *plbestnet_v2 = NULL;
3068
+ wl_pfn_lnet_info_v1_t *plnetinfo;
3069
+ wl_pfn_lnet_info_v2_t *plnetinfo_v2;
29063070 dhd_pno_bestnet_entry_t *pbestnet_entry;
29073071 dhd_pno_best_header_t *pbestnetheader = NULL;
29083072 dhd_pno_scan_results_t *pscan_results = NULL, *siter, *snext;
29093073 bool allocate_header = FALSE;
3074
+ uint16 fwstatus = PFN_INCOMPLETE;
3075
+ uint16 fwcount;
3076
+
29103077 NULL_CHECK(dhd, "dhd is NULL", err);
29113078 NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
3079
+
3080
+ /* The static asserts below guarantee the v1 and v2 net_info and subnet_info
3081
+ * structures are compatible in size and SSID offset, allowing v1 to be safely
3082
+ * used in the code below except for lscanresults fields themselves
3083
+ * (status, count, offset to netinfo).
3084
+ */
3085
+ STATIC_ASSERT(sizeof(wl_pfn_net_info_v1_t) == sizeof(wl_pfn_net_info_v2_t));
3086
+ STATIC_ASSERT(sizeof(wl_pfn_lnet_info_v1_t) == sizeof(wl_pfn_lnet_info_v2_t));
3087
+ STATIC_ASSERT(sizeof(wl_pfn_subnet_info_v1_t) == sizeof(wl_pfn_subnet_info_v2_t));
3088
+ STATIC_ASSERT(OFFSETOF(wl_pfn_subnet_info_v1_t, SSID) ==
3089
+ OFFSETOF(wl_pfn_subnet_info_v2_t, u.SSID));
3090
+
3091
+ DHD_PNO(("%s enter\n", __FUNCTION__));
3092
+ _pno_state = PNO_GET_PNOSTATE(dhd);
3093
+
29123094 if (!dhd_support_sta_mode(dhd)) {
29133095 err = BCME_BADOPTION;
29143096 goto exit_no_unlock;
29153097 }
2916
- DHD_PNO(("%s enter\n", __FUNCTION__));
2917
- _pno_state = PNO_GET_PNOSTATE(dhd);
29183098
29193099 if (!WLS_SUPPORTED(_pno_state)) {
29203100 DHD_ERROR(("%s : wifi location service is not supported\n", __FUNCTION__));
....@@ -2939,8 +3119,10 @@
29393119 /* this is a first try to get batching results */
29403120 if (!list_empty(&_params->params_batch.get_batch.scan_results_list)) {
29413121 /* move the scan_results_list to expired_scan_results_lists */
3122
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
29423123 list_for_each_entry_safe(siter, snext,
29433124 &_params->params_batch.get_batch.scan_results_list, list) {
3125
+ GCC_DIAGNOSTIC_POP();
29443126 list_move_tail(&siter->list,
29453127 &_params->params_batch.get_batch.expired_scan_results_list);
29463128 }
....@@ -2975,14 +3157,15 @@
29753157 list_add(&pscan_results->list, &_params->params_batch.get_batch.scan_results_list);
29763158
29773159 }
2978
- plbestnet = (wl_pfn_lscanresults_t *)MALLOC(dhd->osh, PNO_BESTNET_LEN);
2979
- NULL_CHECK(plbestnet, "failed to allocate buffer for bestnet", err);
3160
+
3161
+ plbestnet_v1 = (wl_pfn_lscanresults_v1_t *)MALLOC(dhd->osh, PNO_BESTNET_LEN);
3162
+ NULL_CHECK(plbestnet_v1, "failed to allocate buffer for bestnet", err);
3163
+ plbestnet_v2 = (wl_pfn_lscanresults_v2_t*)plbestnet_v1;
3164
+
29803165 DHD_PNO(("%s enter\n", __FUNCTION__));
2981
- memset(plbestnet, 0, PNO_BESTNET_LEN);
2982
- while (plbestnet->status != PFN_COMPLETE) {
2983
- memset(plbestnet, 0, PNO_BESTNET_LEN);
2984
- err = dhd_iovar(dhd, 0, "pfnlbest", NULL, 0, (char *)plbestnet, PNO_BESTNET_LEN,
2985
- FALSE);
3166
+ do {
3167
+ err = dhd_iovar(dhd, 0, "pfnlbest", NULL, 0, (char *)plbestnet_v1, PNO_BESTNET_LEN,
3168
+ FALSE);
29863169 if (err < 0) {
29873170 if (err == BCME_EPERM) {
29883171 DHD_ERROR(("we cannot get the batching data "
....@@ -2995,107 +3178,229 @@
29953178 goto exit;
29963179 }
29973180 }
2998
- DHD_PNO(("ver %d, status : %d, count %d\n", plbestnet->version,
2999
- plbestnet->status, plbestnet->count));
3000
- if (plbestnet->version != PFN_SCANRESULT_VERSION) {
3001
- err = BCME_VERSION;
3002
- DHD_ERROR(("bestnet version(%d) is mismatch with Driver version(%d)\n",
3003
- plbestnet->version, PFN_SCANRESULT_VERSION));
3004
- goto exit;
3005
- }
3006
- plnetinfo = plbestnet->netinfo;
3007
- for (i = 0; i < plbestnet->count; i++) {
3008
- pbestnet_entry = (dhd_pno_bestnet_entry_t *)
3009
- MALLOC(dhd->osh, BESTNET_ENTRY_SIZE);
3010
- if (pbestnet_entry == NULL) {
3011
- err = BCME_NOMEM;
3012
- DHD_ERROR(("failed to allocate dhd_pno_bestnet_entry\n"));
3181
+
3182
+ if (plbestnet_v1->version == PFN_LBEST_SCAN_RESULT_VERSION_V1) {
3183
+ fwstatus = plbestnet_v1->status;
3184
+ fwcount = plbestnet_v1->count;
3185
+ plnetinfo = &plbestnet_v1->netinfo[0];
3186
+ if (fwcount == 0) {
3187
+ DHD_PNO(("No more batch results\n"));
30133188 goto exit;
30143189 }
3015
- memset(pbestnet_entry, 0, BESTNET_ENTRY_SIZE);
3016
- pbestnet_entry->recorded_time = jiffies; /* record the current time */
3017
- /* create header for the first entry */
3018
- allocate_header = (i == 0)? TRUE : FALSE;
3019
- /* check whether the new generation is started or not */
3020
- if (timestamp && (TIME_DIFF(timestamp, plnetinfo->timestamp)
3021
- > TIME_MIN_DIFF))
3022
- allocate_header = TRUE;
3023
- timestamp = plnetinfo->timestamp;
3024
- if (allocate_header) {
3025
- pbestnetheader = (dhd_pno_best_header_t *)
3026
- MALLOC(dhd->osh, BEST_HEADER_SIZE);
3027
- if (pbestnetheader == NULL) {
3190
+ if (fwcount > BESTN_MAX) {
3191
+ DHD_ERROR(("%s :fwcount %d is greater than BESTN_MAX %d \n",
3192
+ __FUNCTION__, fwcount, (int)BESTN_MAX));
3193
+ /* Process only BESTN_MAX number of results per batch */
3194
+ fwcount = BESTN_MAX;
3195
+ }
3196
+ for (i = 0; i < fwcount; i++) {
3197
+ pbestnet_entry = (dhd_pno_bestnet_entry_t *)
3198
+ MALLOC(dhd->osh, BESTNET_ENTRY_SIZE);
3199
+ if (pbestnet_entry == NULL) {
30283200 err = BCME_NOMEM;
3029
- if (pbestnet_entry)
3030
- MFREE(dhd->osh, pbestnet_entry,
3031
- BESTNET_ENTRY_SIZE);
30323201 DHD_ERROR(("failed to allocate dhd_pno_bestnet_entry\n"));
30333202 goto exit;
30343203 }
3035
- /* increase total cnt of bestnet header */
3036
- pscan_results->cnt_header++;
3037
- /* need to record the reason to call dhd_pno_get_for_bach */
3038
- if (reason)
3039
- pbestnetheader->reason = (ENABLE << reason);
3040
- memset(pbestnetheader, 0, BEST_HEADER_SIZE);
3041
- /* initialize the head of linked list */
3042
- INIT_LIST_HEAD(&(pbestnetheader->entry_list));
3043
- /* link the pbestnet heaer into existed list */
3044
- if (pscan_results->bestnetheader == NULL)
3045
- /* In case of header */
3046
- pscan_results->bestnetheader = pbestnetheader;
3047
- else {
3048
- dhd_pno_best_header_t *head = pscan_results->bestnetheader;
3049
- pscan_results->bestnetheader = pbestnetheader;
3050
- pbestnetheader->next = head;
3204
+ memset(pbestnet_entry, 0, BESTNET_ENTRY_SIZE);
3205
+ /* record the current time */
3206
+ pbestnet_entry->recorded_time = jiffies;
3207
+ /* create header for the first entry */
3208
+ allocate_header = (i == 0)? TRUE : FALSE;
3209
+ /* check whether the new generation is started or not */
3210
+ if (timestamp && (TIME_DIFF(timestamp, plnetinfo->timestamp)
3211
+ > TIME_MIN_DIFF))
3212
+ allocate_header = TRUE;
3213
+ timestamp = plnetinfo->timestamp;
3214
+ if (allocate_header) {
3215
+ pbestnetheader = (dhd_pno_best_header_t *)
3216
+ MALLOC(dhd->osh, BEST_HEADER_SIZE);
3217
+ if (pbestnetheader == NULL) {
3218
+ err = BCME_NOMEM;
3219
+ if (pbestnet_entry)
3220
+ MFREE(dhd->osh, pbestnet_entry,
3221
+ BESTNET_ENTRY_SIZE);
3222
+ DHD_ERROR(("failed to allocate"
3223
+ " dhd_pno_bestnet_entry\n"));
3224
+ goto exit;
3225
+ }
3226
+ /* increase total cnt of bestnet header */
3227
+ pscan_results->cnt_header++;
3228
+ /* need to record the reason to call dhd_pno_get_for_bach */
3229
+ if (reason)
3230
+ pbestnetheader->reason = (ENABLE << reason);
3231
+ memset(pbestnetheader, 0, BEST_HEADER_SIZE);
3232
+ /* initialize the head of linked list */
3233
+ INIT_LIST_HEAD(&(pbestnetheader->entry_list));
3234
+ /* link the pbestnet heaer into existed list */
3235
+ if (pscan_results->bestnetheader == NULL)
3236
+ /* In case of header */
3237
+ pscan_results->bestnetheader = pbestnetheader;
3238
+ else {
3239
+ dhd_pno_best_header_t *head =
3240
+ pscan_results->bestnetheader;
3241
+ pscan_results->bestnetheader = pbestnetheader;
3242
+ pbestnetheader->next = head;
3243
+ }
30513244 }
3245
+ pbestnet_entry->channel = plnetinfo->pfnsubnet.channel;
3246
+ pbestnet_entry->RSSI = plnetinfo->RSSI;
3247
+ if (plnetinfo->flags & PFN_PARTIAL_SCAN_MASK) {
3248
+ /* if RSSI is positive value, we assume that
3249
+ * this scan is aborted by other scan
3250
+ */
3251
+ DHD_PNO(("This scan is aborted\n"));
3252
+ pbestnetheader->reason = (ENABLE << PNO_STATUS_ABORT);
3253
+ }
3254
+ pbestnet_entry->rtt0 = plnetinfo->rtt0;
3255
+ pbestnet_entry->rtt1 = plnetinfo->rtt1;
3256
+ pbestnet_entry->timestamp = plnetinfo->timestamp;
3257
+ if (plnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) {
3258
+ DHD_ERROR(("%s: Invalid SSID length"
3259
+ " %d: trimming it to max\n",
3260
+ __FUNCTION__, plnetinfo->pfnsubnet.SSID_len));
3261
+ plnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN;
3262
+ }
3263
+ pbestnet_entry->SSID_len = plnetinfo->pfnsubnet.SSID_len;
3264
+ memcpy(pbestnet_entry->SSID, plnetinfo->pfnsubnet.SSID,
3265
+ pbestnet_entry->SSID_len);
3266
+ memcpy(&pbestnet_entry->BSSID, &plnetinfo->pfnsubnet.BSSID,
3267
+ ETHER_ADDR_LEN);
3268
+ /* add the element into list */
3269
+ list_add_tail(&pbestnet_entry->list, &pbestnetheader->entry_list);
3270
+ /* increase best entry count */
3271
+ pbestnetheader->tot_cnt++;
3272
+ pbestnetheader->tot_size += BESTNET_ENTRY_SIZE;
3273
+ DHD_PNO(("Header %d\n", pscan_results->cnt_header - 1));
3274
+ DHD_PNO(("\tSSID : "));
3275
+ for (j = 0; j < plnetinfo->pfnsubnet.SSID_len; j++)
3276
+ DHD_PNO(("%c", plnetinfo->pfnsubnet.SSID[j]));
3277
+ DHD_PNO(("\n"));
3278
+ DHD_PNO(("\tBSSID: "MACDBG"\n",
3279
+ MAC2STRDBG(plnetinfo->pfnsubnet.BSSID.octet)));
3280
+ DHD_PNO(("\tchannel: %d, RSSI: %d, timestamp: %d ms\n",
3281
+ plnetinfo->pfnsubnet.channel,
3282
+ plnetinfo->RSSI, plnetinfo->timestamp));
3283
+ DHD_PNO(("\tRTT0 : %d, RTT1: %d\n", plnetinfo->rtt0,
3284
+ plnetinfo->rtt1));
3285
+ plnetinfo++;
30523286 }
3053
- /* fills the best network info */
3054
- pbestnet_entry->channel = plnetinfo->pfnsubnet.channel;
3055
- pbestnet_entry->RSSI = plnetinfo->RSSI;
3056
- if (plnetinfo->flags & PFN_PARTIAL_SCAN_MASK) {
3057
- /* if RSSI is positive value, we assume that
3058
- * this scan is aborted by other scan
3059
- */
3060
- DHD_PNO(("This scan is aborted\n"));
3061
- pbestnetheader->reason = (ENABLE << PNO_STATUS_ABORT);
3287
+ } else if (plbestnet_v2->version == PFN_LBEST_SCAN_RESULT_VERSION_V2) {
3288
+ fwstatus = plbestnet_v2->status;
3289
+ fwcount = plbestnet_v2->count;
3290
+ plnetinfo_v2 = (wl_pfn_lnet_info_v2_t*)&plbestnet_v2->netinfo[0];
3291
+ if (fwcount == 0) {
3292
+ DHD_PNO(("No more batch results\n"));
3293
+ goto exit;
30623294 }
3063
- pbestnet_entry->rtt0 = plnetinfo->rtt0;
3064
- pbestnet_entry->rtt1 = plnetinfo->rtt1;
3065
- pbestnet_entry->timestamp = plnetinfo->timestamp;
3066
- if (plnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) {
3067
- DHD_ERROR(("%s: Invalid SSID length %d: trimming it to max\n",
3068
- __FUNCTION__, plnetinfo->pfnsubnet.SSID_len));
3069
- plnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN;
3295
+ if (fwcount > BESTN_MAX) {
3296
+ DHD_ERROR(("%s :fwcount %d is greater than BESTN_MAX %d \n",
3297
+ __FUNCTION__, fwcount, (int)BESTN_MAX));
3298
+ /* Process only BESTN_MAX number of results per batch */
3299
+ fwcount = BESTN_MAX;
30703300 }
3071
- pbestnet_entry->SSID_len = plnetinfo->pfnsubnet.SSID_len;
3072
- memcpy(pbestnet_entry->SSID, plnetinfo->pfnsubnet.SSID,
3073
- pbestnet_entry->SSID_len);
3074
- memcpy(&pbestnet_entry->BSSID, &plnetinfo->pfnsubnet.BSSID, ETHER_ADDR_LEN);
3075
- /* add the element into list */
3076
- list_add_tail(&pbestnet_entry->list, &pbestnetheader->entry_list);
3077
- /* increase best entry count */
3078
- pbestnetheader->tot_cnt++;
3079
- pbestnetheader->tot_size += BESTNET_ENTRY_SIZE;
3080
- DHD_PNO(("Header %d\n", pscan_results->cnt_header - 1));
3081
- DHD_PNO(("\tSSID : "));
3082
- for (j = 0; j < plnetinfo->pfnsubnet.SSID_len; j++)
3083
- DHD_PNO(("%c", plnetinfo->pfnsubnet.SSID[j]));
3084
- DHD_PNO(("\n"));
3085
- DHD_PNO(("\tBSSID: %02x:%02x:%02x:%02x:%02x:%02x\n",
3086
- plnetinfo->pfnsubnet.BSSID.octet[0],
3087
- plnetinfo->pfnsubnet.BSSID.octet[1],
3088
- plnetinfo->pfnsubnet.BSSID.octet[2],
3089
- plnetinfo->pfnsubnet.BSSID.octet[3],
3090
- plnetinfo->pfnsubnet.BSSID.octet[4],
3091
- plnetinfo->pfnsubnet.BSSID.octet[5]));
3092
- DHD_PNO(("\tchannel: %d, RSSI: %d, timestamp: %d ms\n",
3093
- plnetinfo->pfnsubnet.channel,
3094
- plnetinfo->RSSI, plnetinfo->timestamp));
3095
- DHD_PNO(("\tRTT0 : %d, RTT1: %d\n", plnetinfo->rtt0, plnetinfo->rtt1));
3096
- plnetinfo++;
3301
+ DHD_PNO(("ver %d, status : %d, count %d\n",
3302
+ plbestnet_v2->version, fwstatus, fwcount));
3303
+
3304
+ for (i = 0; i < fwcount; i++) {
3305
+ pbestnet_entry = (dhd_pno_bestnet_entry_t *)
3306
+ MALLOC(dhd->osh, BESTNET_ENTRY_SIZE);
3307
+ if (pbestnet_entry == NULL) {
3308
+ err = BCME_NOMEM;
3309
+ DHD_ERROR(("failed to allocate dhd_pno_bestnet_entry\n"));
3310
+ goto exit;
3311
+ }
3312
+ memset(pbestnet_entry, 0, BESTNET_ENTRY_SIZE);
3313
+ /* record the current time */
3314
+ pbestnet_entry->recorded_time = jiffies;
3315
+ /* create header for the first entry */
3316
+ allocate_header = (i == 0)? TRUE : FALSE;
3317
+ /* check whether the new generation is started or not */
3318
+ if (timestamp && (TIME_DIFF(timestamp, plnetinfo_v2->timestamp)
3319
+ > TIME_MIN_DIFF))
3320
+ allocate_header = TRUE;
3321
+ timestamp = plnetinfo_v2->timestamp;
3322
+ if (allocate_header) {
3323
+ pbestnetheader = (dhd_pno_best_header_t *)
3324
+ MALLOC(dhd->osh, BEST_HEADER_SIZE);
3325
+ if (pbestnetheader == NULL) {
3326
+ err = BCME_NOMEM;
3327
+ if (pbestnet_entry)
3328
+ MFREE(dhd->osh, pbestnet_entry,
3329
+ BESTNET_ENTRY_SIZE);
3330
+ DHD_ERROR(("failed to allocate"
3331
+ " dhd_pno_bestnet_entry\n"));
3332
+ goto exit;
3333
+ }
3334
+ /* increase total cnt of bestnet header */
3335
+ pscan_results->cnt_header++;
3336
+ /* need to record the reason to call dhd_pno_get_for_bach */
3337
+ if (reason)
3338
+ pbestnetheader->reason = (ENABLE << reason);
3339
+ memset(pbestnetheader, 0, BEST_HEADER_SIZE);
3340
+ /* initialize the head of linked list */
3341
+ INIT_LIST_HEAD(&(pbestnetheader->entry_list));
3342
+ /* link the pbestnet heaer into existed list */
3343
+ if (pscan_results->bestnetheader == NULL)
3344
+ /* In case of header */
3345
+ pscan_results->bestnetheader = pbestnetheader;
3346
+ else {
3347
+ dhd_pno_best_header_t *head =
3348
+ pscan_results->bestnetheader;
3349
+ pscan_results->bestnetheader = pbestnetheader;
3350
+ pbestnetheader->next = head;
3351
+ }
3352
+ }
3353
+ /* fills the best network info */
3354
+ pbestnet_entry->channel = plnetinfo_v2->pfnsubnet.channel;
3355
+ pbestnet_entry->RSSI = plnetinfo_v2->RSSI;
3356
+ if (plnetinfo_v2->flags & PFN_PARTIAL_SCAN_MASK) {
3357
+ /* if RSSI is positive value, we assume that
3358
+ * this scan is aborted by other scan
3359
+ */
3360
+ DHD_PNO(("This scan is aborted\n"));
3361
+ pbestnetheader->reason = (ENABLE << PNO_STATUS_ABORT);
3362
+ }
3363
+ pbestnet_entry->rtt0 = plnetinfo_v2->rtt0;
3364
+ pbestnet_entry->rtt1 = plnetinfo_v2->rtt1;
3365
+ pbestnet_entry->timestamp = plnetinfo_v2->timestamp;
3366
+ if (plnetinfo_v2->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) {
3367
+ DHD_ERROR(("%s: Invalid SSID length"
3368
+ " %d: trimming it to max\n",
3369
+ __FUNCTION__, plnetinfo_v2->pfnsubnet.SSID_len));
3370
+ plnetinfo_v2->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN;
3371
+ }
3372
+ pbestnet_entry->SSID_len = plnetinfo_v2->pfnsubnet.SSID_len;
3373
+ memcpy(pbestnet_entry->SSID, plnetinfo_v2->pfnsubnet.u.SSID,
3374
+ pbestnet_entry->SSID_len);
3375
+ memcpy(&pbestnet_entry->BSSID, &plnetinfo_v2->pfnsubnet.BSSID,
3376
+ ETHER_ADDR_LEN);
3377
+ /* add the element into list */
3378
+ list_add_tail(&pbestnet_entry->list, &pbestnetheader->entry_list);
3379
+ /* increase best entry count */
3380
+ pbestnetheader->tot_cnt++;
3381
+ pbestnetheader->tot_size += BESTNET_ENTRY_SIZE;
3382
+ DHD_PNO(("Header %d\n", pscan_results->cnt_header - 1));
3383
+ DHD_PNO(("\tSSID : "));
3384
+ for (j = 0; j < plnetinfo_v2->pfnsubnet.SSID_len; j++)
3385
+ DHD_PNO(("%c", plnetinfo_v2->pfnsubnet.u.SSID[j]));
3386
+ DHD_PNO(("\n"));
3387
+ DHD_PNO(("\tBSSID: "MACDBG"\n",
3388
+ MAC2STRDBG(plnetinfo_v2->pfnsubnet.BSSID.octet)));
3389
+ DHD_PNO(("\tchannel: %d, RSSI: %d, timestamp: %d ms\n",
3390
+ plnetinfo_v2->pfnsubnet.channel,
3391
+ plnetinfo_v2->RSSI, plnetinfo_v2->timestamp));
3392
+ DHD_PNO(("\tRTT0 : %d, RTT1: %d\n", plnetinfo_v2->rtt0,
3393
+ plnetinfo_v2->rtt1));
3394
+ plnetinfo_v2++;
3395
+ }
3396
+ } else {
3397
+ err = BCME_VERSION;
3398
+ DHD_ERROR(("bestnet fw version %d not supported\n",
3399
+ plbestnet_v1->version));
3400
+ goto exit;
30973401 }
3098
- }
3402
+ } while (fwstatus != PFN_COMPLETE);
3403
+
30993404 if (pscan_results->cnt_header == 0) {
31003405 /* In case that we didn't get any data from the firmware
31013406 * Remove the current scan_result list from get_bach.scan_results_list.
....@@ -3104,16 +3409,19 @@
31043409 list_del(&pscan_results->list);
31053410 MFREE(dhd->osh, pscan_results, SCAN_RESULTS_SIZE);
31063411 _params->params_batch.get_batch.top_node_cnt--;
3412
+ } else {
3413
+ /* increase total scan count using current scan count */
3414
+ _params->params_batch.get_batch.tot_scan_cnt += pscan_results->cnt_header;
31073415 }
3108
- /* increase total scan count using current scan count */
3109
- _params->params_batch.get_batch.tot_scan_cnt += pscan_results->cnt_header;
31103416
31113417 if (buf && bufsize) {
31123418 /* This is a first try to get batching results */
31133419 if (!list_empty(&_params->params_batch.get_batch.scan_results_list)) {
31143420 /* move the scan_results_list to expired_scan_results_lists */
3421
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
31153422 list_for_each_entry_safe(siter, snext,
31163423 &_params->params_batch.get_batch.scan_results_list, list) {
3424
+ GCC_DIAGNOSTIC_POP();
31173425 list_move_tail(&siter->list,
31183426 &_params->params_batch.get_batch.expired_scan_results_list);
31193427 }
....@@ -3131,8 +3439,8 @@
31313439 }
31323440 }
31333441 exit:
3134
- if (plbestnet)
3135
- MFREE(dhd->osh, plbestnet, PNO_BESTNET_LEN);
3442
+ if (plbestnet_v1)
3443
+ MFREE(dhd->osh, plbestnet_v1, PNO_BESTNET_LEN);
31363444 if (_params) {
31373445 _params->params_batch.get_batch.buf = NULL;
31383446 _params->params_batch.get_batch.bufsize = 0;
....@@ -3140,7 +3448,11 @@
31403448 }
31413449 mutex_unlock(&_pno_state->pno_mutex);
31423450 exit_no_unlock:
3451
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
3452
+ if (swait_active(&_pno_state->get_batch_done.wait))
3453
+#else
31433454 if (waitqueue_active(&_pno_state->get_batch_done.wait))
3455
+#endif/* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) */
31443456 complete(&_pno_state->get_batch_done);
31453457 return err;
31463458 }
....@@ -3151,12 +3463,16 @@
31513463 dhd_pub_t *dhd;
31523464 struct dhd_pno_batch_params *params_batch;
31533465 DHD_PNO(("%s enter\n", __FUNCTION__));
3466
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
31543467 _pno_state = container_of(work, struct dhd_pno_status_info, work);
3468
+ GCC_DIAGNOSTIC_POP();
3469
+
31553470 dhd = _pno_state->dhd;
31563471 if (dhd == NULL) {
31573472 DHD_ERROR(("%s : dhd is NULL\n", __FUNCTION__));
31583473 return;
31593474 }
3475
+
31603476 #ifdef GSCAN_SUPPORT
31613477 _dhd_pno_get_gscan_batch_from_fw(dhd);
31623478 #endif /* GSCAN_SUPPORT */
....@@ -3202,13 +3518,13 @@
32023518 msecs_to_jiffies(GSCAN_BATCH_GET_MAX_WAIT));
32033519 }
32043520 } else
3205
-#endif
3521
+#endif // endif
32063522 {
32073523 if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) {
32083524 DHD_ERROR(("%s: Batching SCAN mode is not enabled\n", __FUNCTION__));
32093525 memset(pbuf, 0, bufsize);
3210
- pbuf += sprintf(pbuf, "scancount=%d\n", 0);
3211
- sprintf(pbuf, "%s", RESULTS_END_MARKER);
3526
+ pbuf += snprintf(pbuf, bufsize, "scancount=%d\n", 0);
3527
+ snprintf(pbuf, bufsize, "%s", RESULTS_END_MARKER);
32123528 err = strlen(buf);
32133529 goto exit;
32143530 }
....@@ -3222,7 +3538,7 @@
32223538
32233539 #ifdef GSCAN_SUPPORT
32243540 if (!(_pno_state->pno_mode & DHD_PNO_GSCAN_MODE))
3225
-#endif
3541
+#endif // endif
32263542 err = params_batch->get_batch.bytes_written;
32273543 exit:
32283544 return err;
....@@ -3237,7 +3553,6 @@
32373553 dhd_pno_status_info_t *_pno_state;
32383554 dhd_pno_params_t *_params;
32393555 wl_pfn_bssid_t *p_pfn_bssid = NULL;
3240
- wlc_ssid_ext_t *p_ssid_list = NULL;
32413556 NULL_CHECK(dhd, "dhd is NULL", err);
32423557 NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
32433558 _pno_state = PNO_GET_PNOSTATE(dhd);
....@@ -3258,7 +3573,7 @@
32583573 DHD_PNO(("Gscan is ongoing, nothing to stop here\n"));
32593574 return err;
32603575 }
3261
-#endif
3576
+#endif // endif
32623577
32633578 if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) {
32643579 DHD_ERROR(("%s : PNO BATCH MODE is not enabled\n", __FUNCTION__));
....@@ -3267,23 +3582,23 @@
32673582 _pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE;
32683583 if (_pno_state->pno_mode & (DHD_PNO_LEGACY_MODE | DHD_PNO_HOTLIST_MODE)) {
32693584 mode = _pno_state->pno_mode;
3270
- dhd_pno_clean(dhd);
3585
+ err = dhd_pno_clean(dhd);
3586
+ if (err < 0) {
3587
+ DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
3588
+ __FUNCTION__, err));
3589
+ goto exit;
3590
+ }
3591
+
32713592 _pno_state->pno_mode = mode;
32723593 /* restart Legacy PNO if the Legacy PNO is on */
32733594 if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
32743595 struct dhd_pno_legacy_params *_params_legacy;
32753596 _params_legacy =
32763597 &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy);
3277
- p_ssid_list = dhd_pno_get_legacy_pno_ssid(dhd, _pno_state);
3278
- if (!p_ssid_list) {
3279
- err = BCME_NOMEM;
3280
- DHD_ERROR(("failed to get Legacy PNO SSID list\n"));
3281
- goto exit;
3282
- }
3283
- err = dhd_pno_set_for_ssid(dhd, p_ssid_list, _params_legacy->nssid,
3284
- _params_legacy->scan_fr, _params_legacy->pno_repeat,
3285
- _params_legacy->pno_freq_expo_max, _params_legacy->chan_list,
3286
- _params_legacy->nchan);
3598
+ err = dhd_pno_set_legacy_pno(dhd, _params_legacy->scan_fr,
3599
+ _params_legacy->pno_repeat,
3600
+ _params_legacy->pno_freq_expo_max,
3601
+ _params_legacy->chan_list, _params_legacy->nchan);
32873602 if (err < 0) {
32883603 DHD_ERROR(("%s : failed to restart legacy PNO scan(err: %d)\n",
32893604 __FUNCTION__, err));
....@@ -3292,8 +3607,8 @@
32923607 } else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) {
32933608 struct dhd_pno_bssid *iter, *next;
32943609 _params = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]);
3295
- p_pfn_bssid = kzalloc(sizeof(wl_pfn_bssid_t) *
3296
- _params->params_hotlist.nbssid, GFP_KERNEL);
3610
+ p_pfn_bssid = (wl_pfn_bssid_t *)MALLOCZ(dhd->osh,
3611
+ sizeof(wl_pfn_bssid_t) * _params->params_hotlist.nbssid);
32973612 if (p_pfn_bssid == NULL) {
32983613 DHD_ERROR(("%s : failed to allocate wl_pfn_bssid_t array"
32993614 " (count: %d)",
....@@ -3304,8 +3619,10 @@
33043619 }
33053620 i = 0;
33063621 /* convert dhd_pno_bssid to wl_pfn_bssid */
3622
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
33073623 list_for_each_entry_safe(iter, next,
33083624 &_params->params_hotlist.bssid_list, list) {
3625
+ GCC_DIAGNOSTIC_POP();
33093626 memcpy(&p_pfn_bssid[i].macaddr, &iter->macaddr, ETHER_ADDR_LEN);
33103627 p_pfn_bssid[i].flags = iter->flags;
33113628 i++;
....@@ -3329,8 +3646,8 @@
33293646 exit:
33303647 _params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS];
33313648 _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_BATCH_MODE);
3332
- kfree(p_ssid_list);
3333
- kfree(p_pfn_bssid);
3649
+ MFREE(dhd->osh, p_pfn_bssid,
3650
+ sizeof(wl_pfn_bssid_t) * _params->params_hotlist.nbssid);
33343651 return err;
33353652 }
33363653
....@@ -3407,7 +3724,7 @@
34073724 }
34083725 DHD_PNO(("\n"));
34093726 }
3410
-#endif
3727
+#endif // endif
34113728 if (_params->params_hotlist.nchan) {
34123729 /* copy the channel list into local array */
34133730 memcpy(_chan_list, _params->params_hotlist.chan_list,
....@@ -3465,7 +3782,8 @@
34653782 }
34663783 }
34673784 for (i = 0; i < hotlist_params->nbssid; i++) {
3468
- _pno_bssid = kzalloc(sizeof(struct dhd_pno_bssid), GFP_KERNEL);
3785
+ _pno_bssid = (struct dhd_pno_bssid *)MALLOCZ(dhd->osh,
3786
+ sizeof(struct dhd_pno_bssid));
34693787 NULL_CHECK(_pno_bssid, "_pfn_bssid is NULL", err);
34703788 memcpy(&_pno_bssid->macaddr, &p_pfn_bssid[i].macaddr, ETHER_ADDR_LEN);
34713789 _pno_bssid->flags = p_pfn_bssid[i].flags;
....@@ -3490,7 +3808,6 @@
34903808 uint32 mode = 0;
34913809 dhd_pno_status_info_t *_pno_state;
34923810 dhd_pno_params_t *_params;
3493
- wlc_ssid_ext_t *p_ssid_list = NULL;
34943811 NULL_CHECK(dhd, "dhd is NULL", err);
34953812 NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
34963813 _pno_state = PNO_GET_PNOSTATE(dhd);
....@@ -3527,16 +3844,9 @@
35273844 struct dhd_pno_legacy_params *_params_legacy;
35283845 _params_legacy =
35293846 &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy);
3530
- p_ssid_list = dhd_pno_get_legacy_pno_ssid(dhd, _pno_state);
3531
- if (!p_ssid_list) {
3532
- err = BCME_NOMEM;
3533
- DHD_ERROR(("failed to get Legacy PNO SSID list\n"));
3534
- goto exit;
3535
- }
3536
- err = dhd_pno_set_for_ssid(dhd, p_ssid_list, _params_legacy->nssid,
3537
- _params_legacy->scan_fr, _params_legacy->pno_repeat,
3538
- _params_legacy->pno_freq_expo_max, _params_legacy->chan_list,
3539
- _params_legacy->nchan);
3847
+ err = dhd_pno_set_legacy_pno(dhd, _params_legacy->scan_fr,
3848
+ _params_legacy->pno_repeat, _params_legacy->pno_freq_expo_max,
3849
+ _params_legacy->chan_list, _params_legacy->nchan);
35403850 if (err < 0) {
35413851 DHD_ERROR(("%s : failed to restart legacy PNO scan(err: %d)\n",
35423852 __FUNCTION__, err));
....@@ -3563,7 +3873,6 @@
35633873 }
35643874 }
35653875 exit:
3566
- kfree(p_ssid_list);
35673876 return err;
35683877 }
35693878
....@@ -3599,82 +3908,6 @@
35993908 return err;
36003909 }
36013910
3602
-/* Handle Significant WiFi Change (SWC) event from FW
3603
- * Send event to HAL when all results arrive from FW
3604
- */
3605
-void *
3606
-dhd_handle_swc_evt(dhd_pub_t *dhd, const void *event_data, int *send_evt_bytes)
3607
-{
3608
- void *ptr = NULL;
3609
- dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd);
3610
- struct dhd_pno_gscan_params *gscan_params;
3611
- struct dhd_pno_swc_evt_param *params;
3612
- wl_pfn_swc_results_t *results = (wl_pfn_swc_results_t *)event_data;
3613
- wl_pfn_significant_net_t *change_array;
3614
- int i;
3615
-
3616
- gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan);
3617
- params = &(gscan_params->param_significant);
3618
-
3619
- if (!results->total_count) {
3620
- *send_evt_bytes = 0;
3621
- return ptr;
3622
- }
3623
-
3624
- if (!params->results_rxed_so_far) {
3625
- if (!params->change_array) {
3626
- params->change_array = (wl_pfn_significant_net_t *)
3627
- kmalloc(sizeof(wl_pfn_significant_net_t) * results->total_count,
3628
- GFP_KERNEL);
3629
-
3630
- if (!params->change_array) {
3631
- DHD_ERROR(("%s Cannot Malloc %zd bytes!!\n", __FUNCTION__,
3632
- sizeof(wl_pfn_significant_net_t) * results->total_count));
3633
- *send_evt_bytes = 0;
3634
- return ptr;
3635
- }
3636
- } else {
3637
- DHD_ERROR(("RX'ed WLC_E_PFN_SWC evt from FW, previous evt not complete!!"));
3638
- *send_evt_bytes = 0;
3639
- return ptr;
3640
- }
3641
-
3642
- }
3643
-
3644
- DHD_PNO(("%s: pkt_count %d total_count %d\n", __FUNCTION__,
3645
- results->pkt_count, results->total_count));
3646
-
3647
- for (i = 0; i < results->pkt_count; i++) {
3648
- DHD_PNO(("\t %02x:%02x:%02x:%02x:%02x:%02x\n",
3649
- results->list[i].BSSID.octet[0],
3650
- results->list[i].BSSID.octet[1],
3651
- results->list[i].BSSID.octet[2],
3652
- results->list[i].BSSID.octet[3],
3653
- results->list[i].BSSID.octet[4],
3654
- results->list[i].BSSID.octet[5]));
3655
- }
3656
-
3657
- change_array = &params->change_array[params->results_rxed_so_far];
3658
- memcpy(change_array, results->list, sizeof(wl_pfn_significant_net_t) * results->pkt_count);
3659
- params->results_rxed_so_far += results->pkt_count;
3660
-
3661
- if (params->results_rxed_so_far == results->total_count) {
3662
- params->results_rxed_so_far = 0;
3663
- *send_evt_bytes = sizeof(wl_pfn_significant_net_t) * results->total_count;
3664
- /* Pack up change buffer to send up and reset
3665
- * results_rxed_so_far, after its done.
3666
- */
3667
- ptr = (void *) params->change_array;
3668
- /* expecting the callee to free this mem chunk */
3669
- params->change_array = NULL;
3670
- }
3671
- else {
3672
- *send_evt_bytes = 0;
3673
- }
3674
-
3675
- return ptr;
3676
-}
3677
-
36783911 void
36793912 dhd_gscan_hotlist_cache_cleanup(dhd_pub_t *dhd, hotlist_type_t type)
36803913 {
....@@ -3697,7 +3930,9 @@
36973930
36983931 while (iter) {
36993932 tmp = iter->next;
3700
- kfree(iter);
3933
+ MFREE(dhd->osh, iter,
3934
+ ((iter->tot_count - 1) * sizeof(wifi_gscan_result_t))
3935
+ + sizeof(gscan_results_cache_t));
37013936 iter = tmp;
37023937 }
37033938
....@@ -3709,40 +3944,40 @@
37093944 {
37103945 wl_bss_info_t *bi = NULL;
37113946 wl_gscan_result_t *gscan_result;
3712
- wifi_gscan_result_t *result = NULL;
3947
+ wifi_gscan_full_result_t *result = NULL;
37133948 u32 bi_length = 0;
37143949 uint8 channel;
37153950 uint32 mem_needed;
3951
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0))
3952
+ struct timespec64 ts;
3953
+#else
37163954 struct timespec ts;
3955
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)) */
37173956 u32 bi_ie_length = 0;
37183957 u32 bi_ie_offset = 0;
37193958
37203959 *size = 0;
3721
-
3960
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
37223961 gscan_result = (wl_gscan_result_t *)data;
3723
-
3962
+ GCC_DIAGNOSTIC_POP();
37243963 if (!gscan_result) {
37253964 DHD_ERROR(("Invalid gscan result (NULL pointer)\n"));
37263965 goto exit;
37273966 }
3728
- if (!gscan_result->bss_info) {
3729
- DHD_ERROR(("Invalid gscan bss info (NULL pointer)\n"));
3730
- goto exit;
3731
- }
37323967
37333968 if ((len < sizeof(*gscan_result)) ||
3734
- (len < dtoh32(gscan_result->buflen)) ||
3735
- (dtoh32(gscan_result->buflen) >
3736
- (sizeof(*gscan_result) + WL_SCAN_IE_LEN_MAX))) {
3969
+ (len < dtoh32(gscan_result->buflen)) ||
3970
+ (dtoh32(gscan_result->buflen) >
3971
+ (sizeof(*gscan_result) + WL_SCAN_IE_LEN_MAX))) {
37373972 DHD_ERROR(("%s: invalid gscan buflen:%u\n", __FUNCTION__,
3738
- dtoh32(gscan_result->buflen)));
3973
+ dtoh32(gscan_result->buflen)));
37393974 goto exit;
37403975 }
37413976
37423977 bi = &gscan_result->bss_info[0].info;
37433978 bi_length = dtoh32(bi->length);
37443979 if (bi_length != (dtoh32(gscan_result->buflen) -
3745
- WL_GSCAN_RESULTS_FIXED_SIZE - WL_GSCAN_INFO_FIXED_FIELD_SIZE)) {
3980
+ WL_GSCAN_RESULTS_FIXED_SIZE - WL_GSCAN_INFO_FIXED_FIELD_SIZE)) {
37463981 DHD_ERROR(("Invalid bss_info length %d: ignoring\n", bi_length));
37473982 goto exit;
37483983 }
....@@ -3758,31 +3993,31 @@
37583993 goto exit;
37593994 }
37603995
3761
- mem_needed = OFFSETOF(wifi_gscan_result_t, ie_data) + bi_ie_length;
3762
- result = kmalloc(mem_needed, GFP_KERNEL);
3763
-
3996
+ mem_needed = OFFSETOF(wifi_gscan_full_result_t, ie_data) + bi->ie_length;
3997
+ result = (wifi_gscan_full_result_t *)MALLOC(dhd->osh, mem_needed);
37643998 if (!result) {
37653999 DHD_ERROR(("%s Cannot malloc scan result buffer %d bytes\n",
3766
- __FUNCTION__, mem_needed));
4000
+ __FUNCTION__, mem_needed));
37674001 goto exit;
37684002 }
37694003
3770
- memcpy(result->ssid, bi->SSID, bi->SSID_len);
3771
- result->ssid[bi->SSID_len] = '\0';
4004
+ result->scan_ch_bucket = gscan_result->scan_ch_bucket;
4005
+ memcpy(result->fixed.ssid, bi->SSID, bi->SSID_len);
4006
+ result->fixed.ssid[bi->SSID_len] = '\0';
37724007 channel = wf_chspec_ctlchan(bi->chanspec);
3773
- result->channel = wf_channel2mhz(channel,
4008
+ result->fixed.channel = wf_channel2mhz(channel,
37744009 (channel <= CH_MAX_2G_CHANNEL?
37754010 WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
3776
- result->rssi = (int32) bi->RSSI;
3777
- result->rtt = 0;
3778
- result->rtt_sd = 0;
4011
+ result->fixed.rssi = (int32) bi->RSSI;
4012
+ result->fixed.rtt = 0;
4013
+ result->fixed.rtt_sd = 0;
37794014 get_monotonic_boottime(&ts);
3780
- result->ts = (uint64) TIMESPEC_TO_US(ts);
3781
- result->beacon_period = dtoh16(bi->beacon_period);
3782
- result->capability = dtoh16(bi->capability);
4015
+ result->fixed.ts = (uint64) TIMESPEC_TO_US(ts);
4016
+ result->fixed.beacon_period = dtoh16(bi->beacon_period);
4017
+ result->fixed.capability = dtoh16(bi->capability);
37834018 result->ie_length = bi_ie_length;
3784
- memcpy(&result->macaddr, &bi->BSSID, ETHER_ADDR_LEN);
3785
- memcpy(result->ie_data, ((uint8 *)bi + bi_ie_offset), bi->ie_length);
4019
+ memcpy(&result->fixed.macaddr, &bi->BSSID, ETHER_ADDR_LEN);
4020
+ memcpy(result->ie_data, ((uint8 *)bi + bi_ie_offset), bi_ie_length);
37864021 *size = mem_needed;
37874022 exit:
37884023 return result;
....@@ -3803,87 +4038,96 @@
38034038 return NULL;
38044039 gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan);
38054040
3806
- if (event == WLC_E_PFN_SSID_EXT) {
3807
- wl_pfn_ssid_ext_result_t *evt_data;
3808
- evt_data = (wl_pfn_ssid_ext_result_t *) data;
4041
+ if (event == WLC_E_PFN_NET_FOUND || event == WLC_E_PFN_NET_LOST) {
4042
+ wl_pfn_scanresults_v1_t *pfn_result = (wl_pfn_scanresults_v1_t *)data;
4043
+ wl_pfn_scanresults_v2_t *pfn_result_v2 = (wl_pfn_scanresults_v2_t *)data;
4044
+ wl_pfn_net_info_v1_t *net;
4045
+ wl_pfn_net_info_v2_t *net_v2;
38094046
3810
- if (evt_data->version != PFN_SSID_EXT_VERSION) {
3811
- DHD_PNO(("ePNO event: Incorrect version %d %d\n", evt_data->version,
3812
- PFN_SSID_EXT_VERSION));
4047
+ if (pfn_result->version == PFN_SCANRESULT_VERSION_V1) {
4048
+ if ((pfn_result->count == 0) || (pfn_result->count > EVENT_MAX_NETCNT_V1)) {
4049
+ DHD_ERROR(("%s event %d: wrong pfn v1 results count %d\n",
4050
+ __FUNCTION__, event, pfn_result->count));
4051
+ return NULL;
4052
+ }
4053
+ count = pfn_result->count;
4054
+ mem_needed = sizeof(dhd_epno_results_t) * count;
4055
+ results = (dhd_epno_results_t *)MALLOC(dhd->osh, mem_needed);
4056
+ if (!results) {
4057
+ DHD_ERROR(("%s: Can't malloc %d bytes for results\n", __FUNCTION__,
4058
+ mem_needed));
4059
+ return NULL;
4060
+ }
4061
+ for (i = 0; i < count; i++) {
4062
+ net = &pfn_result->netinfo[i];
4063
+ results[i].rssi = net->RSSI;
4064
+ results[i].channel = wf_channel2mhz(net->pfnsubnet.channel,
4065
+ (net->pfnsubnet.channel <= CH_MAX_2G_CHANNEL ?
4066
+ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
4067
+ results[i].flags = (event == WLC_E_PFN_NET_FOUND) ?
4068
+ WL_PFN_SSID_EXT_FOUND: WL_PFN_SSID_EXT_LOST;
4069
+ results[i].ssid_len = min(net->pfnsubnet.SSID_len,
4070
+ (uint8)DOT11_MAX_SSID_LEN);
4071
+ bssid = &results[i].bssid;
4072
+ memcpy(bssid, &net->pfnsubnet.BSSID, ETHER_ADDR_LEN);
4073
+ if (!net->pfnsubnet.SSID_len) {
4074
+ DHD_ERROR(("%s: Gscan results indexing is not"
4075
+ " supported in version 1 \n", __FUNCTION__));
4076
+ MFREE(dhd->osh, results, mem_needed);
4077
+ return NULL;
4078
+ } else {
4079
+ memcpy(results[i].ssid, net->pfnsubnet.SSID,
4080
+ results[i].ssid_len);
4081
+ }
4082
+ memcpy(ssid, results[i].ssid, results[i].ssid_len);
4083
+ ssid[results[i].ssid_len] = '\0';
4084
+ DHD_PNO(("ssid - %s bssid "MACDBG" ch %d rssi %d flags %d\n",
4085
+ ssid, MAC2STRDBG(bssid->octet), results[i].channel,
4086
+ results[i].rssi, results[i].flags));
4087
+ }
4088
+ } else if (pfn_result_v2->version == PFN_SCANRESULT_VERSION_V2) {
4089
+ if ((pfn_result->count == 0) || (pfn_result->count > EVENT_MAX_NETCNT_V2)) {
4090
+ DHD_ERROR(("%s event %d: wrong pfn v2 results count %d\n",
4091
+ __FUNCTION__, event, pfn_result->count));
4092
+ return NULL;
4093
+ }
4094
+ count = pfn_result_v2->count;
4095
+ mem_needed = sizeof(dhd_epno_results_t) * count;
4096
+ results = (dhd_epno_results_t *)MALLOC(dhd->osh, mem_needed);
4097
+ if (!results) {
4098
+ DHD_ERROR(("%s: Can't malloc %d bytes for results\n", __FUNCTION__,
4099
+ mem_needed));
4100
+ return NULL;
4101
+ }
4102
+ for (i = 0; i < count; i++) {
4103
+ net_v2 = &pfn_result_v2->netinfo[i];
4104
+ results[i].rssi = net_v2->RSSI;
4105
+ results[i].channel = wf_channel2mhz(net_v2->pfnsubnet.channel,
4106
+ (net_v2->pfnsubnet.channel <= CH_MAX_2G_CHANNEL ?
4107
+ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
4108
+ results[i].flags = (event == WLC_E_PFN_NET_FOUND) ?
4109
+ WL_PFN_SSID_EXT_FOUND: WL_PFN_SSID_EXT_LOST;
4110
+ results[i].ssid_len = min(net_v2->pfnsubnet.SSID_len,
4111
+ (uint8)DOT11_MAX_SSID_LEN);
4112
+ bssid = &results[i].bssid;
4113
+ memcpy(bssid, &net_v2->pfnsubnet.BSSID, ETHER_ADDR_LEN);
4114
+ if (!net_v2->pfnsubnet.SSID_len) {
4115
+ dhd_pno_idx_to_ssid(gscan_params, &results[i],
4116
+ net_v2->pfnsubnet.u.index);
4117
+ } else {
4118
+ memcpy(results[i].ssid, net_v2->pfnsubnet.u.SSID,
4119
+ results[i].ssid_len);
4120
+ }
4121
+ memcpy(ssid, results[i].ssid, results[i].ssid_len);
4122
+ ssid[results[i].ssid_len] = '\0';
4123
+ DHD_PNO(("ssid - %s bssid "MACDBG" ch %d rssi %d flags %d\n",
4124
+ ssid, MAC2STRDBG(bssid->octet), results[i].channel,
4125
+ results[i].rssi, results[i].flags));
4126
+ }
4127
+ } else {
4128
+ DHD_ERROR(("%s event %d: Incorrect version %d , not supported\n",
4129
+ __FUNCTION__, event, pfn_result->version));
38134130 return NULL;
3814
- }
3815
- count = evt_data->count;
3816
- mem_needed = sizeof(dhd_epno_results_t) * count;
3817
- results = (dhd_epno_results_t *) kmalloc(mem_needed, GFP_KERNEL);
3818
- if (!results) {
3819
- DHD_ERROR(("%s: Can't malloc %d bytes for results\n", __FUNCTION__,
3820
- mem_needed));
3821
- return NULL;
3822
- }
3823
- DHD_ERROR(("Rx'ed WLC_E_PFN_SSID_EXT event: %d results\n", count));
3824
- for (i = 0; i < count; i++) {
3825
- results[i].rssi = evt_data->net[i].rssi;
3826
- results[i].channel = wf_channel2mhz(evt_data->net[i].channel,
3827
- (evt_data->net[i].channel <= CH_MAX_2G_CHANNEL ?
3828
- WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
3829
- results[i].flags = evt_data->net[i].flags;
3830
- dhd_pno_idx_to_ssid(gscan_params, &results[i],
3831
- evt_data->net[i].index);
3832
- memcpy(ssid, results[i].ssid, results[i].ssid_len);
3833
- bssid = &results[i].bssid;
3834
- memcpy(bssid, &evt_data->net[i].bssid, ETHER_ADDR_LEN);
3835
- ssid[results[i].ssid_len] = '\0';
3836
- DHD_PNO(("ssid - %s bssid %02x:%02x:%02x:%02x:%02x:%02x "
3837
- "idx %d ch %d rssi %d flags %d\n", ssid,
3838
- bssid->octet[0], bssid->octet[1],
3839
- bssid->octet[2], bssid->octet[3],
3840
- bssid->octet[4], bssid->octet[5],
3841
- evt_data->net[i].index, results[i].channel,
3842
- results[i].rssi, results[i].flags));
3843
- }
3844
- } else if (event == WLC_E_PFN_NET_FOUND || event == WLC_E_PFN_NET_LOST) {
3845
- wl_pfn_scanresults_t *pfn_result = (wl_pfn_scanresults_t *)data;
3846
- wl_pfn_net_info_t *net;
3847
-
3848
- if (pfn_result->version != PFN_SCANRESULT_VERSION) {
3849
- DHD_ERROR(("%s event %d: Incorrect version %d %d\n", __FUNCTION__, event,
3850
- pfn_result->version, PFN_SCANRESULT_VERSION));
3851
- return NULL;
3852
- }
3853
- if ((pfn_result->count == 0) || (pfn_result->count > EVENT_MAX_NETCNT)) {
3854
- DHD_ERROR(("%s event %d: wrong pfn results count %d\n",
3855
- __FUNCTION__, event, pfn_result->count));
3856
- return NULL;
3857
- }
3858
- count = pfn_result->count;
3859
- mem_needed = sizeof(dhd_epno_results_t) * count;
3860
- results = (dhd_epno_results_t *) kmalloc(mem_needed, GFP_KERNEL);
3861
- if (!results) {
3862
- DHD_ERROR(("%s: Can't malloc %d bytes for results\n", __FUNCTION__,
3863
- mem_needed));
3864
- return NULL;
3865
- }
3866
- for (i = 0; i < count; i++) {
3867
- net = &pfn_result->netinfo[i];
3868
- results[i].rssi = net->RSSI;
3869
- results[i].channel = wf_channel2mhz(net->pfnsubnet.channel,
3870
- (net->pfnsubnet.channel <= CH_MAX_2G_CHANNEL ?
3871
- WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
3872
- results[i].flags = (event == WLC_E_PFN_NET_FOUND) ?
3873
- WL_PFN_SSID_EXT_FOUND: WL_PFN_SSID_EXT_LOST;
3874
- results[i].ssid_len = min(net->pfnsubnet.SSID_len,
3875
- (uint8)DOT11_MAX_SSID_LEN);
3876
- bssid = &results[i].bssid;
3877
- memcpy(bssid, &net->pfnsubnet.BSSID, ETHER_ADDR_LEN);
3878
- memcpy(results[i].ssid, net->pfnsubnet.SSID, results[i].ssid_len);
3879
- memcpy(ssid, results[i].ssid, results[i].ssid_len);
3880
- ssid[results[i].ssid_len] = '\0';
3881
- DHD_PNO(("ssid - %s bssid %02x:%02x:%02x:%02x:%02x:%02x "
3882
- "ch %d rssi %d flags %d\n", ssid,
3883
- bssid->octet[0], bssid->octet[1],
3884
- bssid->octet[2], bssid->octet[3],
3885
- bssid->octet[4], bssid->octet[5],
3886
- results[i].channel, results[i].rssi, results[i].flags));
38874131 }
38884132 }
38894133 *size = mem_needed;
....@@ -3892,83 +4136,170 @@
38924136
38934137 void *
38944138 dhd_handle_hotlist_scan_evt(dhd_pub_t *dhd, const void *event_data,
3895
- int *send_evt_bytes, hotlist_type_t type)
4139
+ int *send_evt_bytes, hotlist_type_t type, u32 *buf_len)
38964140 {
38974141 void *ptr = NULL;
38984142 dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd);
38994143 struct dhd_pno_gscan_params *gscan_params;
3900
- wl_pfn_scanresults_t *results = (wl_pfn_scanresults_t *)event_data;
4144
+ wl_pfn_scanresults_v1_t *results_v1 = (wl_pfn_scanresults_v1_t *)event_data;
4145
+ wl_pfn_scanresults_v2_t *results_v2 = (wl_pfn_scanresults_v2_t *)event_data;
39014146 wifi_gscan_result_t *hotlist_found_array;
3902
- wl_pfn_net_info_t *plnetinfo;
4147
+ wl_pfn_net_info_v1_t *pnetinfo;
4148
+ wl_pfn_net_info_v2_t *pnetinfo_v2;
39034149 gscan_results_cache_t *gscan_hotlist_cache;
3904
- int malloc_size = 0, i, total = 0;
4150
+ u32 malloc_size = 0, i, total = 0;
4151
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0))
4152
+ struct timespec64 tm_spec;
4153
+#else
4154
+ struct timespec tm_spec;
4155
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)) */
4156
+ uint16 fwstatus;
4157
+ uint16 fwcount;
39054158
3906
- gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan);
4159
+ /* Static asserts in _dhd_pno_get_for_batch() above guarantee the v1 and v2
4160
+ * net_info and subnet_info structures are compatible in size and SSID offset,
4161
+ * allowing v1 to be safely used in the code below except for lscanresults
4162
+ * fields themselves (status, count, offset to netinfo).
4163
+ */
39074164
3908
- if ((results->count == 0) || (results->count > EVENT_MAX_NETCNT)) {
3909
- DHD_ERROR(("%s: wrong result count:%d\n", __FUNCTION__, results->count));
3910
- *send_evt_bytes = 0;
3911
- return ptr;
3912
- }
4165
+ *buf_len = 0;
4166
+ if (results_v1->version == PFN_SCANRESULTS_VERSION_V1) {
4167
+ fwstatus = results_v1->status;
4168
+ fwcount = results_v1->count;
4169
+ pnetinfo = &results_v1->netinfo[0];
39134170
3914
- malloc_size = sizeof(gscan_results_cache_t) +
3915
- ((results->count - 1) * sizeof(wifi_gscan_result_t));
3916
- gscan_hotlist_cache = (gscan_results_cache_t *) kmalloc(malloc_size, GFP_KERNEL);
4171
+ gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan);
39174172
3918
- if (!gscan_hotlist_cache) {
3919
- DHD_ERROR(("%s Cannot Malloc %d bytes!!\n", __FUNCTION__, malloc_size));
3920
- *send_evt_bytes = 0;
3921
- return ptr;
3922
- }
3923
-
3924
- if (type == HOTLIST_FOUND) {
3925
- gscan_hotlist_cache->next = gscan_params->gscan_hotlist_found;
3926
- gscan_params->gscan_hotlist_found = gscan_hotlist_cache;
3927
- DHD_PNO(("%s enter, FOUND results count %d\n", __FUNCTION__, results->count));
3928
- } else {
3929
- gscan_hotlist_cache->next = gscan_params->gscan_hotlist_lost;
3930
- gscan_params->gscan_hotlist_lost = gscan_hotlist_cache;
3931
- DHD_PNO(("%s enter, LOST results count %d\n", __FUNCTION__, results->count));
3932
- }
3933
-
3934
- gscan_hotlist_cache->tot_count = results->count;
3935
- gscan_hotlist_cache->tot_consumed = 0;
3936
- plnetinfo = results->netinfo;
3937
-
3938
- for (i = 0; i < results->count; i++, plnetinfo++) {
3939
- hotlist_found_array = &gscan_hotlist_cache->results[i];
3940
- hotlist_found_array->channel = wf_channel2mhz(plnetinfo->pfnsubnet.channel,
3941
- (plnetinfo->pfnsubnet.channel <= CH_MAX_2G_CHANNEL?
3942
- WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
3943
- hotlist_found_array->rssi = (int32) plnetinfo->RSSI;
3944
- /* Info not available & not expected */
3945
- hotlist_found_array->beacon_period = 0;
3946
- hotlist_found_array->capability = 0;
3947
- hotlist_found_array->ie_length = 0;
3948
-
3949
- hotlist_found_array->ts = convert_fw_rel_time_to_systime(plnetinfo->timestamp);
3950
- if (plnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) {
3951
- DHD_ERROR(("Invalid SSID length %d: trimming it to max\n",
3952
- plnetinfo->pfnsubnet.SSID_len));
3953
- plnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN;
4173
+ if (!fwcount || (fwcount > EVENT_MAX_NETCNT_V1)) {
4174
+ DHD_ERROR(("%s: wrong v1 fwcount:%d\n", __FUNCTION__, fwcount));
4175
+ *send_evt_bytes = 0;
4176
+ return ptr;
39544177 }
3955
- memcpy(hotlist_found_array->ssid, plnetinfo->pfnsubnet.SSID,
3956
- plnetinfo->pfnsubnet.SSID_len);
3957
- hotlist_found_array->ssid[plnetinfo->pfnsubnet.SSID_len] = '\0';
39584178
3959
- memcpy(&hotlist_found_array->macaddr, &plnetinfo->pfnsubnet.BSSID, ETHER_ADDR_LEN);
3960
- DHD_PNO(("\t%s %02x:%02x:%02x:%02x:%02x:%02x rssi %d\n", hotlist_found_array->ssid,
3961
- hotlist_found_array->macaddr.octet[0],
3962
- hotlist_found_array->macaddr.octet[1],
3963
- hotlist_found_array->macaddr.octet[2],
3964
- hotlist_found_array->macaddr.octet[3],
3965
- hotlist_found_array->macaddr.octet[4],
3966
- hotlist_found_array->macaddr.octet[5],
3967
- hotlist_found_array->rssi));
4179
+ get_monotonic_boottime(&tm_spec);
4180
+ malloc_size = sizeof(gscan_results_cache_t) +
4181
+ ((fwcount - 1) * sizeof(wifi_gscan_result_t));
4182
+ gscan_hotlist_cache = (gscan_results_cache_t *)MALLOC(dhd->osh, malloc_size);
4183
+ if (!gscan_hotlist_cache) {
4184
+ DHD_ERROR(("%s Cannot Malloc %d bytes!!\n", __FUNCTION__, malloc_size));
4185
+ *send_evt_bytes = 0;
4186
+ return ptr;
4187
+ }
4188
+
4189
+ *buf_len = malloc_size;
4190
+ if (type == HOTLIST_FOUND) {
4191
+ gscan_hotlist_cache->next = gscan_params->gscan_hotlist_found;
4192
+ gscan_params->gscan_hotlist_found = gscan_hotlist_cache;
4193
+ DHD_PNO(("%s enter, FOUND results count %d\n", __FUNCTION__, fwcount));
4194
+ } else {
4195
+ gscan_hotlist_cache->next = gscan_params->gscan_hotlist_lost;
4196
+ gscan_params->gscan_hotlist_lost = gscan_hotlist_cache;
4197
+ DHD_PNO(("%s enter, LOST results count %d\n", __FUNCTION__, fwcount));
4198
+ }
4199
+
4200
+ gscan_hotlist_cache->tot_count = fwcount;
4201
+ gscan_hotlist_cache->tot_consumed = 0;
4202
+
4203
+ for (i = 0; i < fwcount; i++, pnetinfo++) {
4204
+ hotlist_found_array = &gscan_hotlist_cache->results[i];
4205
+ memset(hotlist_found_array, 0, sizeof(wifi_gscan_result_t));
4206
+ hotlist_found_array->channel = wf_channel2mhz(pnetinfo->pfnsubnet.channel,
4207
+ (pnetinfo->pfnsubnet.channel <= CH_MAX_2G_CHANNEL?
4208
+ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
4209
+ hotlist_found_array->rssi = (int32) pnetinfo->RSSI;
4210
+
4211
+ hotlist_found_array->ts =
4212
+ convert_fw_rel_time_to_systime(&tm_spec,
4213
+ (pnetinfo->timestamp * 1000));
4214
+ if (pnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) {
4215
+ DHD_ERROR(("Invalid SSID length %d: trimming it to max\n",
4216
+ pnetinfo->pfnsubnet.SSID_len));
4217
+ pnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN;
4218
+ }
4219
+ memcpy(hotlist_found_array->ssid, pnetinfo->pfnsubnet.SSID,
4220
+ pnetinfo->pfnsubnet.SSID_len);
4221
+ hotlist_found_array->ssid[pnetinfo->pfnsubnet.SSID_len] = '\0';
4222
+
4223
+ memcpy(&hotlist_found_array->macaddr, &pnetinfo->pfnsubnet.BSSID,
4224
+ ETHER_ADDR_LEN);
4225
+ DHD_PNO(("\t%s "MACDBG" rssi %d\n",
4226
+ hotlist_found_array->ssid,
4227
+ MAC2STRDBG(hotlist_found_array->macaddr.octet),
4228
+ hotlist_found_array->rssi));
4229
+ }
4230
+ } else if (results_v2->version == PFN_SCANRESULTS_VERSION_V2) {
4231
+ fwstatus = results_v2->status;
4232
+ fwcount = results_v2->count;
4233
+ pnetinfo_v2 = (wl_pfn_net_info_v2_t*)&results_v2->netinfo[0];
4234
+
4235
+ gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan);
4236
+
4237
+ if (!fwcount || (fwcount > EVENT_MAX_NETCNT_V2)) {
4238
+ DHD_ERROR(("%s: wrong v2 fwcount:%d\n", __FUNCTION__, fwcount));
4239
+ *send_evt_bytes = 0;
4240
+ return ptr;
4241
+ }
4242
+
4243
+ get_monotonic_boottime(&tm_spec);
4244
+ malloc_size = sizeof(gscan_results_cache_t) +
4245
+ ((fwcount - 1) * sizeof(wifi_gscan_result_t));
4246
+ gscan_hotlist_cache =
4247
+ (gscan_results_cache_t *)MALLOC(dhd->osh, malloc_size);
4248
+ if (!gscan_hotlist_cache) {
4249
+ DHD_ERROR(("%s Cannot Malloc %d bytes!!\n", __FUNCTION__, malloc_size));
4250
+ *send_evt_bytes = 0;
4251
+ return ptr;
4252
+ }
4253
+ *buf_len = malloc_size;
4254
+ if (type == HOTLIST_FOUND) {
4255
+ gscan_hotlist_cache->next = gscan_params->gscan_hotlist_found;
4256
+ gscan_params->gscan_hotlist_found = gscan_hotlist_cache;
4257
+ DHD_PNO(("%s enter, FOUND results count %d\n", __FUNCTION__, fwcount));
4258
+ } else {
4259
+ gscan_hotlist_cache->next = gscan_params->gscan_hotlist_lost;
4260
+ gscan_params->gscan_hotlist_lost = gscan_hotlist_cache;
4261
+ DHD_PNO(("%s enter, LOST results count %d\n", __FUNCTION__, fwcount));
4262
+ }
4263
+
4264
+ gscan_hotlist_cache->tot_count = fwcount;
4265
+ gscan_hotlist_cache->tot_consumed = 0;
4266
+ gscan_hotlist_cache->scan_ch_bucket = results_v2->scan_ch_bucket;
4267
+
4268
+ for (i = 0; i < fwcount; i++, pnetinfo_v2++) {
4269
+ hotlist_found_array = &gscan_hotlist_cache->results[i];
4270
+ memset(hotlist_found_array, 0, sizeof(wifi_gscan_result_t));
4271
+ hotlist_found_array->channel =
4272
+ wf_channel2mhz(pnetinfo_v2->pfnsubnet.channel,
4273
+ (pnetinfo_v2->pfnsubnet.channel <= CH_MAX_2G_CHANNEL?
4274
+ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
4275
+ hotlist_found_array->rssi = (int32) pnetinfo_v2->RSSI;
4276
+
4277
+ hotlist_found_array->ts =
4278
+ convert_fw_rel_time_to_systime(&tm_spec,
4279
+ (pnetinfo_v2->timestamp * 1000));
4280
+ if (pnetinfo_v2->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) {
4281
+ DHD_ERROR(("Invalid SSID length %d: trimming it to max\n",
4282
+ pnetinfo_v2->pfnsubnet.SSID_len));
4283
+ pnetinfo_v2->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN;
4284
+ }
4285
+ memcpy(hotlist_found_array->ssid, pnetinfo_v2->pfnsubnet.u.SSID,
4286
+ pnetinfo_v2->pfnsubnet.SSID_len);
4287
+ hotlist_found_array->ssid[pnetinfo_v2->pfnsubnet.SSID_len] = '\0';
4288
+
4289
+ memcpy(&hotlist_found_array->macaddr, &pnetinfo_v2->pfnsubnet.BSSID,
4290
+ ETHER_ADDR_LEN);
4291
+ DHD_PNO(("\t%s "MACDBG" rssi %d\n",
4292
+ hotlist_found_array->ssid,
4293
+ MAC2STRDBG(hotlist_found_array->macaddr.octet),
4294
+ hotlist_found_array->rssi));
4295
+ }
4296
+ } else {
4297
+ DHD_ERROR(("%s: event version %d not supported\n",
4298
+ __FUNCTION__, results_v1->version));
4299
+ *send_evt_bytes = 0;
4300
+ return ptr;
39684301 }
3969
-
3970
-
3971
- if (results->status == PFN_COMPLETE) {
4302
+ if (fwstatus == PFN_COMPLETE) {
39724303 ptr = (void *) gscan_hotlist_cache;
39734304 while (gscan_hotlist_cache) {
39744305 total += gscan_hotlist_cache->tot_count;
....@@ -3980,11 +4311,12 @@
39804311 return ptr;
39814312 }
39824313 #endif /* GSCAN_SUPPORT */
4314
+
39834315 int
39844316 dhd_pno_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data)
39854317 {
39864318 int err = BCME_OK;
3987
- uint status, event_type, flags, datalen;
4319
+ uint event_type;
39884320 dhd_pno_status_info_t *_pno_state;
39894321 NULL_CHECK(dhd, "dhd is NULL", err);
39904322 NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
....@@ -3995,9 +4327,6 @@
39954327 goto exit;
39964328 }
39974329 event_type = ntoh32(event->event_type);
3998
- flags = ntoh16(event->flags);
3999
- status = ntoh32(event->status);
4000
- datalen = ntoh32(event->datalen);
40014330 DHD_PNO(("%s enter : event_type :%d\n", __FUNCTION__, event_type));
40024331 switch (event_type) {
40034332 case WLC_E_PFN_BSSID_NET_FOUND:
....@@ -4009,7 +4338,11 @@
40094338 {
40104339 struct dhd_pno_batch_params *params_batch;
40114340 params_batch = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS].params_batch;
4341
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
4342
+ if (!swait_active(&_pno_state->get_batch_done.wait))
4343
+#else
40124344 if (!waitqueue_active(&_pno_state->get_batch_done.wait)) {
4345
+#endif/* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) */
40134346 DHD_PNO(("%s : WLC_E_PFN_BEST_BATCHING\n", __FUNCTION__));
40144347 params_batch->get_batch.buf = NULL;
40154348 params_batch->get_batch.bufsize = 0;
....@@ -4053,13 +4386,13 @@
40534386 #ifdef GSCAN_SUPPORT
40544387 init_waitqueue_head(&_pno_state->batch_get_wait);
40554388 #endif /* GSCAN_SUPPORT */
4056
- buf = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL);
4389
+ buf = MALLOC(dhd->osh, WLC_IOCTL_SMLEN);
40574390 if (!buf) {
40584391 DHD_ERROR((":%s buf alloc err.\n", __FUNCTION__));
40594392 return BCME_NOMEM;
40604393 }
40614394 err = dhd_iovar(dhd, 0, "pfnlbest", NULL, 0, buf, WLC_IOCTL_SMLEN,
4062
- FALSE);
4395
+ FALSE);
40634396 if (err == BCME_UNSUPPORTED) {
40644397 _pno_state->wls_supported = FALSE;
40654398 DHD_INFO(("Current firmware doesn't support"
....@@ -4069,10 +4402,9 @@
40694402 __FUNCTION__));
40704403 }
40714404 exit:
4072
- kfree(buf);
4405
+ MFREE(dhd->osh, buf, WLC_IOCTL_SMLEN);
40734406 return err;
40744407 }
4075
-
40764408 int dhd_pno_deinit(dhd_pub_t *dhd)
40774409 {
40784410 int err = BCME_OK;
....@@ -4093,7 +4425,7 @@
40934425 if (_pno_state->pno_mode & DHD_PNO_GSCAN_MODE) {
40944426 _params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
40954427 mutex_lock(&_pno_state->pno_mutex);
4096
- dhd_pno_reset_cfg_gscan(_params, _pno_state, GSCAN_FLUSH_ALL_CFG);
4428
+ dhd_pno_reset_cfg_gscan(dhd, _params, _pno_state, GSCAN_FLUSH_ALL_CFG);
40974429 mutex_unlock(&_pno_state->pno_mutex);
40984430 }
40994431 #endif /* GSCAN_SUPPORT */
....@@ -4108,4 +4440,5 @@
41084440 dhd->pno_state = NULL;
41094441 return err;
41104442 }
4443
+#endif /* OEM_ANDROID */
41114444 #endif /* PNO_SUPPORT */