mac80211: brcmfmac: backport scheduled scan cleanup and chip support
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / 357-0004-brcmfmac-fix-handling-ssids-in-.sched_scan_start-cal.patch
1 From 3e2e86ab19c2a43953de30089c5411c580ddb5f7 Mon Sep 17 00:00:00 2001
2 From: Arend Van Spriel <arend.vanspriel@broadcom.com>
3 Date: Wed, 23 Nov 2016 10:25:23 +0000
4 Subject: [PATCH] brcmfmac: fix handling ssids in .sched_scan_start() callback
5
6 The ssids list in the scheduled scan request were not properly taken
7 into account when configuring in firmware. The hidden bit was set for
8 any ssid resulting in active scanning for all. Only set it for ssids
9 that are in the ssids list.
10
11 Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
12 Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
13 Reviewed-by: Franky Lin <franky.lin@broadcom.com>
14 Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
15 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
16 ---
17 .../broadcom/brcm80211/brcmfmac/cfg80211.c | 103 ++++++++++-----------
18 .../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 18 ++++
19 .../net/wireless/broadcom/brcm80211/brcmfmac/pno.h | 12 ++-
20 3 files changed, 76 insertions(+), 57 deletions(-)
21
22 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
23 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
24 @@ -3314,19 +3314,37 @@ out_err:
25 return err;
26 }
27
28 +static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid,
29 + struct cfg80211_sched_scan_request *req)
30 +{
31 + int i;
32 +
33 + if (!ssid || !req->ssids || !req->n_ssids)
34 + return false;
35 +
36 + for (i = 0; i < req->n_ssids; i++) {
37 + if (ssid->ssid_len == req->ssids[i].ssid_len) {
38 + if (!strncmp(ssid->ssid, req->ssids[i].ssid,
39 + ssid->ssid_len))
40 + return true;
41 + }
42 + }
43 + return false;
44 +}
45 +
46 static int
47 brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
48 struct net_device *ndev,
49 - struct cfg80211_sched_scan_request *request)
50 + struct cfg80211_sched_scan_request *req)
51 {
52 struct brcmf_if *ifp = netdev_priv(ndev);
53 struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
54 - struct brcmf_pno_net_param_le pfn;
55 + struct cfg80211_ssid *ssid;
56 int i;
57 int ret = 0;
58
59 brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n",
60 - request->n_match_sets, request->n_ssids);
61 + req->n_match_sets, req->n_ssids);
62 if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
63 brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
64 return -EAGAIN;
65 @@ -3337,71 +3355,46 @@ brcmf_cfg80211_sched_scan_start(struct w
66 return -EAGAIN;
67 }
68
69 - if (!request->n_ssids || !request->n_match_sets) {
70 - brcmf_dbg(SCAN, "Invalid sched scan req!! n_ssids:%d\n",
71 - request->n_ssids);
72 + if (req->n_match_sets <= 0) {
73 + brcmf_dbg(SCAN, "invalid number of matchsets specified: %d\n",
74 + req->n_match_sets);
75 return -EINVAL;
76 }
77
78 - if (request->n_ssids > 0) {
79 - for (i = 0; i < request->n_ssids; i++) {
80 - /* Active scan req for ssids */
81 - brcmf_dbg(SCAN, ">>> Active scan req for ssid (%s)\n",
82 - request->ssids[i].ssid);
83 -
84 - /* match_set ssids is a supert set of n_ssid list,
85 - * so we need not add these set separately.
86 - */
87 - }
88 + /* clean up everything */
89 + ret = brcmf_pno_clean(ifp);
90 + if (ret < 0) {
91 + brcmf_err("failed error=%d\n", ret);
92 + return ret;
93 }
94
95 - if (request->n_match_sets > 0) {
96 - /* clean up everything */
97 - ret = brcmf_pno_clean(ifp);
98 - if (ret < 0) {
99 - brcmf_err("failed error=%d\n", ret);
100 - return ret;
101 + /* configure pno */
102 + ret = brcmf_pno_config(ifp, req);
103 + if (ret < 0)
104 + return ret;
105 +
106 + /* configure each match set */
107 + for (i = 0; i < req->n_match_sets; i++) {
108 +
109 + ssid = &req->match_sets[i].ssid;
110 +
111 + if (!ssid->ssid_len) {
112 + brcmf_err("skip broadcast ssid\n");
113 + continue;
114 }
115
116 - /* configure pno */
117 - ret = brcmf_pno_config(ifp, request);
118 + ret = brcmf_pno_add_ssid(ifp, ssid,
119 + brcmf_is_ssid_active(ssid, req));
120 if (ret < 0)
121 - return ret;
122 -
123 - /* configure each match set */
124 - for (i = 0; i < request->n_match_sets; i++) {
125 - struct cfg80211_ssid *ssid;
126 - u32 ssid_len;
127 -
128 - ssid = &request->match_sets[i].ssid;
129 - ssid_len = ssid->ssid_len;
130 -
131 - if (!ssid_len) {
132 - brcmf_err("skip broadcast ssid\n");
133 - continue;
134 - }
135 - pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
136 - pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
137 - pfn.wsec = cpu_to_le32(0);
138 - pfn.infra = cpu_to_le32(1);
139 - pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
140 - pfn.ssid.SSID_len = cpu_to_le32(ssid_len);
141 - memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len);
142 - ret = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn,
143 - sizeof(pfn));
144 brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n",
145 ret == 0 ? "set" : "failed", ssid->ssid);
146 - }
147 - /* Enable the PNO */
148 - if (brcmf_fil_iovar_int_set(ifp, "pfn", 1) < 0) {
149 - brcmf_err("PNO enable failed!! ret=%d\n", ret);
150 - return -EINVAL;
151 - }
152 - } else {
153 - return -EINVAL;
154 }
155 + /* Enable the PNO */
156 + ret = brcmf_fil_iovar_int_set(ifp, "pfn", 1);
157 + if (ret < 0)
158 + brcmf_err("PNO enable failed!! ret=%d\n", ret);
159
160 - return 0;
161 + return ret;
162 }
163
164 static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
165 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
166 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
167 @@ -28,6 +28,8 @@
168 #define BRCMF_PNO_FREQ_EXPO_MAX 3
169 #define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6
170 #define BRCMF_PNO_SCAN_INCOMPLETE 0
171 +#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
172 +#define BRCMF_PNO_HIDDEN_BIT 2
173
174 int brcmf_pno_clean(struct brcmf_if *ifp)
175 {
176 @@ -98,3 +100,19 @@ int brcmf_pno_config(struct brcmf_if *if
177 return err;
178 }
179
180 +int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
181 + bool active)
182 +{
183 + struct brcmf_pno_net_param_le pfn;
184 +
185 + pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
186 + pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
187 + pfn.wsec = cpu_to_le32(0);
188 + pfn.infra = cpu_to_le32(1);
189 + if (active)
190 + pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
191 + pfn.ssid.SSID_len = cpu_to_le32(ssid->ssid_len);
192 + memcpy(pfn.ssid.SSID, ssid->ssid, ssid->ssid_len);
193 + return brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn));
194 +}
195 +
196 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
197 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
198 @@ -17,8 +17,6 @@
199 #define _BRCMF_PNO_H
200
201 #define BRCMF_PNO_SCAN_COMPLETE 1
202 -#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
203 -#define BRCMF_PNO_HIDDEN_BIT 2
204 #define BRCMF_PNO_MAX_PFN_COUNT 16
205
206 /**
207 @@ -37,4 +35,14 @@ int brcmf_pno_clean(struct brcmf_if *ifp
208 int brcmf_pno_config(struct brcmf_if *ifp,
209 struct cfg80211_sched_scan_request *request);
210
211 +/**
212 + * brcmf_pno_add_ssid - add ssid for pno in firmware.
213 + *
214 + * @ifp: interface object used.
215 + * @ssid: ssid information.
216 + * @active: indicate this ssid needs to be actively probed.
217 + */
218 +int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
219 + bool active);
220 +
221 #endif /* _BRCMF_PNO_H */