aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Spinadel <david.spinadel@intel.com>2014-02-06 09:15:23 -0500
committerJohannes Berg <johannes.berg@intel.com>2014-06-25 03:10:43 -0400
commit633e27132625a0692440c4db58b901fb3cb67c55 (patch)
tree6500b45b80c944e2addfda3f9c4515a2112056c9
parentc56ef6725068c0ce499e517409c0da226ef51b08 (diff)
mac80211: split sched scan IEs
Split sched scan IEs to band specific and not band specific blocks. Common IEs blocks may be sent to the FW once per command, instead of per band. This allows optimization of size of the command, which may be required by some drivers (eg. iwlmvm with newer firmware version). As this changes the mac80211 API, update all drivers to use the new version correctly, even if they don't (yet) make use of the split data. Signed-off-by: David Spinadel <david.spinadel@intel.com> Reviewed-by: Alexander Bondar <alexander.bondar@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/scan.c27
-rw-r--r--drivers/net/wireless/ti/wl12xx/scan.c20
-rw-r--r--drivers/net/wireless/ti/wl12xx/scan.h2
-rw-r--r--drivers/net/wireless/ti/wl18xx/scan.c16
-rw-r--r--drivers/net/wireless/ti/wl18xx/scan.h2
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c11
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.h3
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/scan.h2
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h2
-rw-r--r--include/net/mac80211.h23
-rw-r--r--net/mac80211/driver-ops.h2
-rw-r--r--net/mac80211/scan.c47
15 files changed, 88 insertions, 75 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 4dc2e05f49ce..7dd363dd3ad3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -1828,7 +1828,7 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
1828static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, 1828static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
1829 struct ieee80211_vif *vif, 1829 struct ieee80211_vif *vif,
1830 struct cfg80211_sched_scan_request *req, 1830 struct cfg80211_sched_scan_request *req,
1831 struct ieee80211_sched_scan_ies *ies) 1831 struct ieee80211_scan_ies *ies)
1832{ 1832{
1833 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1833 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1834 int ret; 1834 int ret;
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index fcc6c29482d0..97630f9a7cb9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -854,7 +854,7 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
854int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, 854int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
855 struct ieee80211_vif *vif, 855 struct ieee80211_vif *vif,
856 struct cfg80211_sched_scan_request *req, 856 struct cfg80211_sched_scan_request *req,
857 struct ieee80211_sched_scan_ies *ies); 857 struct ieee80211_scan_ies *ies);
858int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, 858int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
859 struct cfg80211_sched_scan_request *req); 859 struct cfg80211_sched_scan_request *req);
860int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, 860int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index 4b6c7d4bd199..3206fa097255 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -204,7 +204,8 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd,
204 */ 204 */
205static u16 iwl_mvm_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, 205static u16 iwl_mvm_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta,
206 int n_ssids, const u8 *ssid, int ssid_len, 206 int n_ssids, const u8 *ssid, int ssid_len,
207 const u8 *ie, int ie_len, 207 const u8 *band_ie, int band_ie_len,
208 const u8 *common_ie, int common_ie_len,
208 int left) 209 int left)
209{ 210{
210 int len = 0; 211 int len = 0;
@@ -244,12 +245,19 @@ static u16 iwl_mvm_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta,
244 245
245 len += ssid_len + 2; 246 len += ssid_len + 2;
246 247
247 if (WARN_ON(left < ie_len)) 248 if (WARN_ON(left < band_ie_len + common_ie_len))
248 return len; 249 return len;
249 250
250 if (ie && ie_len) { 251 if (band_ie && band_ie_len) {
251 memcpy(pos, ie, ie_len); 252 memcpy(pos, band_ie, band_ie_len);
252 len += ie_len; 253 pos += band_ie_len;
254 len += band_ie_len;
255 }
256
257 if (common_ie && common_ie_len) {
258 memcpy(pos, common_ie, common_ie_len);
259 pos += common_ie_len;
260 len += common_ie_len;
253 } 261 }
254 262
255 return (u16)len; 263 return (u16)len;
@@ -382,7 +390,7 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
382 (struct ieee80211_mgmt *)cmd->data, 390 (struct ieee80211_mgmt *)cmd->data,
383 vif->addr, 391 vif->addr,
384 req->n_ssids, ssid, ssid_len, 392 req->n_ssids, ssid, ssid_len,
385 req->ie, req->ie_len, 393 req->ie, req->ie_len, NULL, 0,
386 mvm->fw->ucode_capa.max_probe_length)); 394 mvm->fw->ucode_capa.max_probe_length));
387 395
388 iwl_mvm_scan_fill_channels(cmd, req, basic_ssid, &params); 396 iwl_mvm_scan_fill_channels(cmd, req, basic_ssid, &params);
@@ -561,7 +569,7 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
561 569
562static void iwl_scan_offload_build_tx_cmd(struct iwl_mvm *mvm, 570static void iwl_scan_offload_build_tx_cmd(struct iwl_mvm *mvm,
563 struct ieee80211_vif *vif, 571 struct ieee80211_vif *vif,
564 struct ieee80211_sched_scan_ies *ies, 572 struct ieee80211_scan_ies *ies,
565 enum ieee80211_band band, 573 enum ieee80211_band band,
566 struct iwl_tx_cmd *cmd, 574 struct iwl_tx_cmd *cmd,
567 u8 *data) 575 u8 *data)
@@ -577,7 +585,8 @@ static void iwl_scan_offload_build_tx_cmd(struct iwl_mvm *mvm,
577 cmd_len = iwl_mvm_fill_probe_req((struct ieee80211_mgmt *)data, 585 cmd_len = iwl_mvm_fill_probe_req((struct ieee80211_mgmt *)data,
578 vif->addr, 586 vif->addr,
579 1, NULL, 0, 587 1, NULL, 0,
580 ies->ie[band], ies->len[band], 588 ies->ies[band], ies->len[band],
589 ies->common_ies, ies->common_ie_len,
581 SCAN_OFFLOAD_PROBE_REQ_SIZE); 590 SCAN_OFFLOAD_PROBE_REQ_SIZE);
582 cmd->len = cpu_to_le16(cmd_len); 591 cmd->len = cpu_to_le16(cmd_len);
583} 592}
@@ -735,7 +744,7 @@ static void iwl_build_channel_cfg(struct iwl_mvm *mvm,
735int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, 744int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
736 struct ieee80211_vif *vif, 745 struct ieee80211_vif *vif,
737 struct cfg80211_sched_scan_request *req, 746 struct cfg80211_sched_scan_request *req,
738 struct ieee80211_sched_scan_ies *ies) 747 struct ieee80211_scan_ies *ies)
739{ 748{
740 int band_2ghz = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels; 749 int band_2ghz = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels;
741 int band_5ghz = mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; 750 int band_5ghz = mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels;
diff --git a/drivers/net/wireless/ti/wl12xx/scan.c b/drivers/net/wireless/ti/wl12xx/scan.c
index 7541bd1a4a4b..0c0d5cd98514 100644
--- a/drivers/net/wireless/ti/wl12xx/scan.c
+++ b/drivers/net/wireless/ti/wl12xx/scan.c
@@ -156,7 +156,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
156 cmd->params.role_id, band, 156 cmd->params.role_id, band,
157 wl->scan.ssid, wl->scan.ssid_len, 157 wl->scan.ssid, wl->scan.ssid_len,
158 wl->scan.req->ie, 158 wl->scan.req->ie,
159 wl->scan.req->ie_len, false); 159 wl->scan.req->ie_len, NULL, 0, false);
160 if (ret < 0) { 160 if (ret < 0) {
161 wl1271_error("PROBE request template failed"); 161 wl1271_error("PROBE request template failed");
162 goto out; 162 goto out;
@@ -317,7 +317,7 @@ static void wl12xx_adjust_channels(struct wl1271_cmd_sched_scan_config *cmd,
317int wl1271_scan_sched_scan_config(struct wl1271 *wl, 317int wl1271_scan_sched_scan_config(struct wl1271 *wl,
318 struct wl12xx_vif *wlvif, 318 struct wl12xx_vif *wlvif,
319 struct cfg80211_sched_scan_request *req, 319 struct cfg80211_sched_scan_request *req,
320 struct ieee80211_sched_scan_ies *ies) 320 struct ieee80211_scan_ies *ies)
321{ 321{
322 struct wl1271_cmd_sched_scan_config *cfg = NULL; 322 struct wl1271_cmd_sched_scan_config *cfg = NULL;
323 struct wlcore_scan_channels *cfg_channels = NULL; 323 struct wlcore_scan_channels *cfg_channels = NULL;
@@ -378,8 +378,11 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
378 wlvif->role_id, band, 378 wlvif->role_id, band,
379 req->ssids[0].ssid, 379 req->ssids[0].ssid,
380 req->ssids[0].ssid_len, 380 req->ssids[0].ssid_len,
381 ies->ie[band], 381 ies->ies[band],
382 ies->len[band], true); 382 ies->len[band],
383 ies->common_ies,
384 ies->common_ie_len,
385 true);
383 if (ret < 0) { 386 if (ret < 0) {
384 wl1271_error("2.4GHz PROBE request template failed"); 387 wl1271_error("2.4GHz PROBE request template failed");
385 goto out; 388 goto out;
@@ -392,8 +395,11 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
392 wlvif->role_id, band, 395 wlvif->role_id, band,
393 req->ssids[0].ssid, 396 req->ssids[0].ssid,
394 req->ssids[0].ssid_len, 397 req->ssids[0].ssid_len,
395 ies->ie[band], 398 ies->ies[band],
396 ies->len[band], true); 399 ies->len[band],
400 ies->common_ies,
401 ies->common_ie_len,
402 true);
397 if (ret < 0) { 403 if (ret < 0) {
398 wl1271_error("5GHz PROBE request template failed"); 404 wl1271_error("5GHz PROBE request template failed");
399 goto out; 405 goto out;
@@ -449,7 +455,7 @@ out_free:
449 455
450int wl12xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, 456int wl12xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
451 struct cfg80211_sched_scan_request *req, 457 struct cfg80211_sched_scan_request *req,
452 struct ieee80211_sched_scan_ies *ies) 458 struct ieee80211_scan_ies *ies)
453{ 459{
454 int ret; 460 int ret;
455 461
diff --git a/drivers/net/wireless/ti/wl12xx/scan.h b/drivers/net/wireless/ti/wl12xx/scan.h
index 264af7ac2785..427f9af85a00 100644
--- a/drivers/net/wireless/ti/wl12xx/scan.h
+++ b/drivers/net/wireless/ti/wl12xx/scan.h
@@ -135,6 +135,6 @@ int wl12xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif);
135void wl12xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif); 135void wl12xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif);
136int wl12xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, 136int wl12xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
137 struct cfg80211_sched_scan_request *req, 137 struct cfg80211_sched_scan_request *req,
138 struct ieee80211_sched_scan_ies *ies); 138 struct ieee80211_scan_ies *ies);
139void wl12xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif); 139void wl12xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif);
140#endif 140#endif
diff --git a/drivers/net/wireless/ti/wl18xx/scan.c b/drivers/net/wireless/ti/wl18xx/scan.c
index 2b642f8c9266..98666f235a12 100644
--- a/drivers/net/wireless/ti/wl18xx/scan.c
+++ b/drivers/net/wireless/ti/wl18xx/scan.c
@@ -113,6 +113,8 @@ static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
113 req->ssids ? req->ssids[0].ssid_len : 0, 113 req->ssids ? req->ssids[0].ssid_len : 0,
114 req->ie, 114 req->ie,
115 req->ie_len, 115 req->ie_len,
116 NULL,
117 0,
116 false); 118 false);
117 if (ret < 0) { 119 if (ret < 0) {
118 wl1271_error("2.4GHz PROBE request template failed"); 120 wl1271_error("2.4GHz PROBE request template failed");
@@ -128,6 +130,8 @@ static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
128 req->ssids ? req->ssids[0].ssid_len : 0, 130 req->ssids ? req->ssids[0].ssid_len : 0,
129 req->ie, 131 req->ie,
130 req->ie_len, 132 req->ie_len,
133 NULL,
134 0,
131 false); 135 false);
132 if (ret < 0) { 136 if (ret < 0) {
133 wl1271_error("5GHz PROBE request template failed"); 137 wl1271_error("5GHz PROBE request template failed");
@@ -161,7 +165,7 @@ static
161int wl18xx_scan_sched_scan_config(struct wl1271 *wl, 165int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
162 struct wl12xx_vif *wlvif, 166 struct wl12xx_vif *wlvif,
163 struct cfg80211_sched_scan_request *req, 167 struct cfg80211_sched_scan_request *req,
164 struct ieee80211_sched_scan_ies *ies) 168 struct ieee80211_scan_ies *ies)
165{ 169{
166 struct wl18xx_cmd_scan_params *cmd; 170 struct wl18xx_cmd_scan_params *cmd;
167 struct wlcore_scan_channels *cmd_channels = NULL; 171 struct wlcore_scan_channels *cmd_channels = NULL;
@@ -237,8 +241,10 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
237 cmd->role_id, band, 241 cmd->role_id, band,
238 req->ssids ? req->ssids[0].ssid : NULL, 242 req->ssids ? req->ssids[0].ssid : NULL,
239 req->ssids ? req->ssids[0].ssid_len : 0, 243 req->ssids ? req->ssids[0].ssid_len : 0,
240 ies->ie[band], 244 ies->ies[band],
241 ies->len[band], 245 ies->len[band],
246 ies->common_ies,
247 ies->common_ie_len,
242 true); 248 true);
243 if (ret < 0) { 249 if (ret < 0) {
244 wl1271_error("2.4GHz PROBE request template failed"); 250 wl1271_error("2.4GHz PROBE request template failed");
@@ -252,8 +258,10 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
252 cmd->role_id, band, 258 cmd->role_id, band,
253 req->ssids ? req->ssids[0].ssid : NULL, 259 req->ssids ? req->ssids[0].ssid : NULL,
254 req->ssids ? req->ssids[0].ssid_len : 0, 260 req->ssids ? req->ssids[0].ssid_len : 0,
255 ies->ie[band], 261 ies->ies[band],
256 ies->len[band], 262 ies->len[band],
263 ies->common_ies,
264 ies->common_ie_len,
257 true); 265 true);
258 if (ret < 0) { 266 if (ret < 0) {
259 wl1271_error("5GHz PROBE request template failed"); 267 wl1271_error("5GHz PROBE request template failed");
@@ -277,7 +285,7 @@ out:
277 285
278int wl18xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, 286int wl18xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
279 struct cfg80211_sched_scan_request *req, 287 struct cfg80211_sched_scan_request *req,
280 struct ieee80211_sched_scan_ies *ies) 288 struct ieee80211_scan_ies *ies)
281{ 289{
282 return wl18xx_scan_sched_scan_config(wl, wlvif, req, ies); 290 return wl18xx_scan_sched_scan_config(wl, wlvif, req, ies);
283} 291}
diff --git a/drivers/net/wireless/ti/wl18xx/scan.h b/drivers/net/wireless/ti/wl18xx/scan.h
index eadee42689d1..2e636aa5dba9 100644
--- a/drivers/net/wireless/ti/wl18xx/scan.h
+++ b/drivers/net/wireless/ti/wl18xx/scan.h
@@ -122,6 +122,6 @@ int wl18xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif);
122void wl18xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif); 122void wl18xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif);
123int wl18xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, 123int wl18xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
124 struct cfg80211_sched_scan_request *req, 124 struct cfg80211_sched_scan_request *req,
125 struct ieee80211_sched_scan_ies *ies); 125 struct ieee80211_scan_ies *ies);
126void wl18xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif); 126void wl18xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif);
127#endif 127#endif
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 40dc30f4faaa..e269c0a57017 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -1124,7 +1124,8 @@ out:
1124int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, 1124int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
1125 u8 role_id, u8 band, 1125 u8 role_id, u8 band,
1126 const u8 *ssid, size_t ssid_len, 1126 const u8 *ssid, size_t ssid_len,
1127 const u8 *ie, size_t ie_len, bool sched_scan) 1127 const u8 *ie0, size_t ie0_len, const u8 *ie1,
1128 size_t ie1_len, bool sched_scan)
1128{ 1129{
1129 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); 1130 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
1130 struct sk_buff *skb; 1131 struct sk_buff *skb;
@@ -1136,13 +1137,15 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
1136 wl1271_debug(DEBUG_SCAN, "build probe request band %d", band); 1137 wl1271_debug(DEBUG_SCAN, "build probe request band %d", band);
1137 1138
1138 skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, 1139 skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len,
1139 ie_len); 1140 ie0_len + ie1_len);
1140 if (!skb) { 1141 if (!skb) {
1141 ret = -ENOMEM; 1142 ret = -ENOMEM;
1142 goto out; 1143 goto out;
1143 } 1144 }
1144 if (ie_len) 1145 if (ie0_len)
1145 memcpy(skb_put(skb, ie_len), ie, ie_len); 1146 memcpy(skb_put(skb, ie0_len), ie0, ie0_len);
1147 if (ie1_len)
1148 memcpy(skb_put(skb, ie1_len), ie1, ie1_len);
1146 1149
1147 if (sched_scan && 1150 if (sched_scan &&
1148 (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL)) { 1151 (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL)) {
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h
index b084830a61cf..6788d7356ca5 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.h
+++ b/drivers/net/wireless/ti/wlcore/cmd.h
@@ -64,7 +64,8 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif,
64int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, 64int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
65 u8 role_id, u8 band, 65 u8 role_id, u8 band,
66 const u8 *ssid, size_t ssid_len, 66 const u8 *ssid, size_t ssid_len,
67 const u8 *ie, size_t ie_len, bool sched_scan); 67 const u8 *ie, size_t ie_len, const u8 *common_ie,
68 size_t common_ie_len, bool sched_scan);
68struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, 69struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
69 struct wl12xx_vif *wlvif, 70 struct wl12xx_vif *wlvif,
70 struct sk_buff *skb); 71 struct sk_buff *skb);
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index e5ffb8b91dd4..48f83868f9cb 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -3637,7 +3637,7 @@ out:
3637static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, 3637static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw,
3638 struct ieee80211_vif *vif, 3638 struct ieee80211_vif *vif,
3639 struct cfg80211_sched_scan_request *req, 3639 struct cfg80211_sched_scan_request *req,
3640 struct ieee80211_sched_scan_ies *ies) 3640 struct ieee80211_scan_ies *ies)
3641{ 3641{
3642 struct wl1271 *wl = hw->priv; 3642 struct wl1271 *wl = hw->priv;
3643 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); 3643 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
diff --git a/drivers/net/wireless/ti/wlcore/scan.h b/drivers/net/wireless/ti/wlcore/scan.h
index a6ab24b5c0f9..4dadd0c62cde 100644
--- a/drivers/net/wireless/ti/wlcore/scan.h
+++ b/drivers/net/wireless/ti/wlcore/scan.h
@@ -37,7 +37,7 @@ void wl1271_scan_complete_work(struct work_struct *work);
37int wl1271_scan_sched_scan_config(struct wl1271 *wl, 37int wl1271_scan_sched_scan_config(struct wl1271 *wl,
38 struct wl12xx_vif *wlvif, 38 struct wl12xx_vif *wlvif,
39 struct cfg80211_sched_scan_request *req, 39 struct cfg80211_sched_scan_request *req,
40 struct ieee80211_sched_scan_ies *ies); 40 struct ieee80211_scan_ies *ies);
41int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif); 41int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif);
42void wlcore_scan_sched_scan_results(struct wl1271 *wl); 42void wlcore_scan_sched_scan_results(struct wl1271 *wl);
43 43
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 95a54504f0cc..71320509b56d 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -95,7 +95,7 @@ struct wlcore_ops {
95 int (*scan_stop)(struct wl1271 *wl, struct wl12xx_vif *wlvif); 95 int (*scan_stop)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
96 int (*sched_scan_start)(struct wl1271 *wl, struct wl12xx_vif *wlvif, 96 int (*sched_scan_start)(struct wl1271 *wl, struct wl12xx_vif *wlvif,
97 struct cfg80211_sched_scan_request *req, 97 struct cfg80211_sched_scan_request *req,
98 struct ieee80211_sched_scan_ies *ies); 98 struct ieee80211_scan_ies *ies);
99 void (*sched_scan_stop)(struct wl1271 *wl, struct wl12xx_vif *wlvif); 99 void (*sched_scan_stop)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
100 int (*get_spare_blocks)(struct wl1271 *wl, bool is_gem); 100 int (*get_spare_blocks)(struct wl1271 *wl, bool is_gem);
101 int (*set_key)(struct wl1271 *wl, enum set_key_cmd cmd, 101 int (*set_key)(struct wl1271 *wl, enum set_key_cmd cmd,
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 9536ee3e22a9..545d2fa179c4 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -754,26 +754,11 @@ struct ieee80211_tx_info {
754}; 754};
755 755
756/** 756/**
757 * struct ieee80211_sched_scan_ies - scheduled scan IEs
758 *
759 * This structure is used to pass the appropriate IEs to be used in scheduled
760 * scans for all bands. It contains both the IEs passed from the userspace
761 * and the ones generated by mac80211.
762 *
763 * @ie: array with the IEs for each supported band
764 * @len: array with the total length of the IEs for each band
765 */
766struct ieee80211_sched_scan_ies {
767 u8 *ie[IEEE80211_NUM_BANDS];
768 size_t len[IEEE80211_NUM_BANDS];
769};
770
771/**
772 * struct ieee80211_scan_ies - descriptors for different blocks of IEs 757 * struct ieee80211_scan_ies - descriptors for different blocks of IEs
773 * 758 *
774 * This structure is used to point to different blocks of IEs in HW scan. 759 * This structure is used to point to different blocks of IEs in HW scan
775 * These blocks contain the IEs passed by userspace and the ones generated 760 * and scheduled scan. These blocks contain the IEs passed by userspace
776 * by mac80211. 761 * and the ones generated by mac80211.
777 * 762 *
778 * @ies: pointers to band specific IEs. 763 * @ies: pointers to band specific IEs.
779 * @len: lengths of band_specific IEs. 764 * @len: lengths of band_specific IEs.
@@ -2917,7 +2902,7 @@ struct ieee80211_ops {
2917 int (*sched_scan_start)(struct ieee80211_hw *hw, 2902 int (*sched_scan_start)(struct ieee80211_hw *hw,
2918 struct ieee80211_vif *vif, 2903 struct ieee80211_vif *vif,
2919 struct cfg80211_sched_scan_request *req, 2904 struct cfg80211_sched_scan_request *req,
2920 struct ieee80211_sched_scan_ies *ies); 2905 struct ieee80211_scan_ies *ies);
2921 int (*sched_scan_stop)(struct ieee80211_hw *hw, 2906 int (*sched_scan_stop)(struct ieee80211_hw *hw,
2922 struct ieee80211_vif *vif); 2907 struct ieee80211_vif *vif);
2923 void (*sw_scan_start)(struct ieee80211_hw *hw); 2908 void (*sw_scan_start)(struct ieee80211_hw *hw);
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index faa0d90f6e80..11423958116a 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -346,7 +346,7 @@ static inline int
346drv_sched_scan_start(struct ieee80211_local *local, 346drv_sched_scan_start(struct ieee80211_local *local,
347 struct ieee80211_sub_if_data *sdata, 347 struct ieee80211_sub_if_data *sdata,
348 struct cfg80211_sched_scan_request *req, 348 struct cfg80211_sched_scan_request *req,
349 struct ieee80211_sched_scan_ies *ies) 349 struct ieee80211_scan_ies *ies)
350{ 350{
351 int ret; 351 int ret;
352 352
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 116959e070d0..a0a938145dcc 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -1003,10 +1003,13 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
1003 struct cfg80211_sched_scan_request *req) 1003 struct cfg80211_sched_scan_request *req)
1004{ 1004{
1005 struct ieee80211_local *local = sdata->local; 1005 struct ieee80211_local *local = sdata->local;
1006 struct ieee80211_sched_scan_ies sched_scan_ies = {}; 1006 struct ieee80211_scan_ies sched_scan_ies = {};
1007 struct cfg80211_chan_def chandef; 1007 struct cfg80211_chan_def chandef;
1008 int ret, i, iebufsz; 1008 int ret, i, iebufsz, num_bands = 0;
1009 struct ieee80211_scan_ies dummy_ie_desc; 1009 u32 rate_masks[IEEE80211_NUM_BANDS] = {};
1010 u8 bands_used = 0;
1011 u8 *ie;
1012 size_t len;
1010 1013
1011 iebufsz = local->scan_ies_len + req->ie_len; 1014 iebufsz = local->scan_ies_len + req->ie_len;
1012 1015
@@ -1016,37 +1019,35 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
1016 return -ENOTSUPP; 1019 return -ENOTSUPP;
1017 1020
1018 for (i = 0; i < IEEE80211_NUM_BANDS; i++) { 1021 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
1019 u32 rate_masks[IEEE80211_NUM_BANDS] = {}; 1022 if (local->hw.wiphy->bands[i]) {
1020 1023 bands_used |= BIT(i);
1021 if (!local->hw.wiphy->bands[i]) 1024 rate_masks[i] = (u32) -1;
1022 continue; 1025 num_bands++;
1023
1024 sched_scan_ies.ie[i] = kzalloc(iebufsz, GFP_KERNEL);
1025 if (!sched_scan_ies.ie[i]) {
1026 ret = -ENOMEM;
1027 goto out_free;
1028 } 1026 }
1027 }
1029 1028
1030 ieee80211_prepare_scan_chandef(&chandef, req->scan_width); 1029 ie = kzalloc(num_bands * iebufsz, GFP_KERNEL);
1031 rate_masks[i] = (u32) -1; 1030 if (!ie) {
1032 1031 ret = -ENOMEM;
1033 sched_scan_ies.len[i] = 1032 goto out;
1034 ieee80211_build_preq_ies(local, sched_scan_ies.ie[i],
1035 iebufsz, &dummy_ie_desc,
1036 req->ie, req->ie_len, BIT(i),
1037 rate_masks, &chandef);
1038 } 1033 }
1039 1034
1035 ieee80211_prepare_scan_chandef(&chandef, req->scan_width);
1036
1037 len = ieee80211_build_preq_ies(local, ie, num_bands * iebufsz,
1038 &sched_scan_ies, req->ie,
1039 req->ie_len, bands_used,
1040 rate_masks, &chandef);
1041
1040 ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); 1042 ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies);
1041 if (ret == 0) { 1043 if (ret == 0) {
1042 rcu_assign_pointer(local->sched_scan_sdata, sdata); 1044 rcu_assign_pointer(local->sched_scan_sdata, sdata);
1043 local->sched_scan_req = req; 1045 local->sched_scan_req = req;
1044 } 1046 }
1045 1047
1046out_free: 1048 kfree(ie);
1047 while (i > 0)
1048 kfree(sched_scan_ies.ie[--i]);
1049 1049
1050out:
1050 if (ret) { 1051 if (ret) {
1051 /* Clean in case of failure after HW restart or upon resume. */ 1052 /* Clean in case of failure after HW restart or upon resume. */
1052 RCU_INIT_POINTER(local->sched_scan_sdata, NULL); 1053 RCU_INIT_POINTER(local->sched_scan_sdata, NULL);