mac80211: brcmfmac: backport scheduled scan cleanup and chip support
[librecmc/librecmc.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 */