xref: /linux/net/mac80211/scan.c (revision 58905ca5b11a0ff3860f55b789cbbf052f7158a7)
10a51b27eSJohannes Berg /*
25484e237SJohannes Berg  * Scanning implementation
35484e237SJohannes Berg  *
40a51b27eSJohannes Berg  * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
50a51b27eSJohannes Berg  * Copyright 2004, Instant802 Networks, Inc.
60a51b27eSJohannes Berg  * Copyright 2005, Devicescape Software, Inc.
70a51b27eSJohannes Berg  * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
80a51b27eSJohannes Berg  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
90a51b27eSJohannes Berg  *
100a51b27eSJohannes Berg  * This program is free software; you can redistribute it and/or modify
110a51b27eSJohannes Berg  * it under the terms of the GNU General Public License version 2 as
120a51b27eSJohannes Berg  * published by the Free Software Foundation.
130a51b27eSJohannes Berg  */
140a51b27eSJohannes Berg 
1500d3f14cSJohannes Berg /* TODO: figure out how to avoid that the "current BSS" expires */
165484e237SJohannes Berg 
170a51b27eSJohannes Berg #include <linux/wireless.h>
180a51b27eSJohannes Berg #include <linux/if_arp.h>
19078e1e60SJohannes Berg #include <linux/rtnetlink.h>
200a51b27eSJohannes Berg #include <net/mac80211.h>
210a51b27eSJohannes Berg #include <net/iw_handler.h>
220a51b27eSJohannes Berg 
230a51b27eSJohannes Berg #include "ieee80211_i.h"
2424487981SJohannes Berg #include "driver-ops.h"
255484e237SJohannes Berg #include "mesh.h"
260a51b27eSJohannes Berg 
270a51b27eSJohannes Berg #define IEEE80211_PROBE_DELAY (HZ / 33)
280a51b27eSJohannes Berg #define IEEE80211_CHANNEL_TIME (HZ / 33)
290a51b27eSJohannes Berg #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)
300a51b27eSJohannes Berg 
31c2b13452SJohannes Berg struct ieee80211_bss *
325484e237SJohannes Berg ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
335484e237SJohannes Berg 		     u8 *ssid, u8 ssid_len)
345484e237SJohannes Berg {
3500d3f14cSJohannes Berg 	return (void *)cfg80211_get_bss(local->hw.wiphy,
3600d3f14cSJohannes Berg 					ieee80211_get_channel(local->hw.wiphy,
3700d3f14cSJohannes Berg 							      freq),
3800d3f14cSJohannes Berg 					bssid, ssid, ssid_len,
3900d3f14cSJohannes Berg 					0, 0);
405484e237SJohannes Berg }
415484e237SJohannes Berg 
4200d3f14cSJohannes Berg static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss)
435484e237SJohannes Berg {
4400d3f14cSJohannes Berg 	struct ieee80211_bss *bss = (void *)cbss;
455484e237SJohannes Berg 
465484e237SJohannes Berg 	kfree(bss_mesh_id(bss));
475484e237SJohannes Berg 	kfree(bss_mesh_cfg(bss));
485484e237SJohannes Berg }
495484e237SJohannes Berg 
505484e237SJohannes Berg void ieee80211_rx_bss_put(struct ieee80211_local *local,
51c2b13452SJohannes Berg 			  struct ieee80211_bss *bss)
525484e237SJohannes Berg {
5300d3f14cSJohannes Berg 	cfg80211_put_bss((struct cfg80211_bss *)bss);
545484e237SJohannes Berg }
555484e237SJohannes Berg 
56c2b13452SJohannes Berg struct ieee80211_bss *
575484e237SJohannes Berg ieee80211_bss_info_update(struct ieee80211_local *local,
585484e237SJohannes Berg 			  struct ieee80211_rx_status *rx_status,
595484e237SJohannes Berg 			  struct ieee80211_mgmt *mgmt,
605484e237SJohannes Berg 			  size_t len,
615484e237SJohannes Berg 			  struct ieee802_11_elems *elems,
622a519311SJohannes Berg 			  struct ieee80211_channel *channel,
632a519311SJohannes Berg 			  bool beacon)
645484e237SJohannes Berg {
65c2b13452SJohannes Berg 	struct ieee80211_bss *bss;
6600d3f14cSJohannes Berg 	int clen;
672a519311SJohannes Berg 	s32 signal = 0;
682a519311SJohannes Berg 
6977965c97SJohannes Berg 	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
702a519311SJohannes Berg 		signal = rx_status->signal * 100;
7177965c97SJohannes Berg 	else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
722a519311SJohannes Berg 		signal = (rx_status->signal * 100) / local->hw.max_signal;
732a519311SJohannes Berg 
7400d3f14cSJohannes Berg 	bss = (void *)cfg80211_inform_bss_frame(local->hw.wiphy, channel,
7577965c97SJohannes Berg 						mgmt, len, signal, GFP_ATOMIC);
765484e237SJohannes Berg 
775484e237SJohannes Berg 	if (!bss)
785484e237SJohannes Berg 		return NULL;
7900d3f14cSJohannes Berg 
8000d3f14cSJohannes Berg 	bss->cbss.free_priv = ieee80211_rx_bss_free;
815484e237SJohannes Berg 
825484e237SJohannes Berg 	/* save the ERP value so that it is available at association time */
835484e237SJohannes Berg 	if (elems->erp_info && elems->erp_info_len >= 1) {
845484e237SJohannes Berg 		bss->erp_value = elems->erp_info[0];
855484e237SJohannes Berg 		bss->has_erp_value = 1;
865484e237SJohannes Berg 	}
875484e237SJohannes Berg 
885484e237SJohannes Berg 	if (elems->tim) {
895484e237SJohannes Berg 		struct ieee80211_tim_ie *tim_ie =
905484e237SJohannes Berg 			(struct ieee80211_tim_ie *)elems->tim;
915484e237SJohannes Berg 		bss->dtim_period = tim_ie->dtim_period;
925484e237SJohannes Berg 	}
935484e237SJohannes Berg 
945484e237SJohannes Berg 	/* set default value for buggy APs */
955484e237SJohannes Berg 	if (!elems->tim || bss->dtim_period == 0)
965484e237SJohannes Berg 		bss->dtim_period = 1;
975484e237SJohannes Berg 
985484e237SJohannes Berg 	bss->supp_rates_len = 0;
995484e237SJohannes Berg 	if (elems->supp_rates) {
1005484e237SJohannes Berg 		clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
1015484e237SJohannes Berg 		if (clen > elems->supp_rates_len)
1025484e237SJohannes Berg 			clen = elems->supp_rates_len;
1035484e237SJohannes Berg 		memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates,
1045484e237SJohannes Berg 		       clen);
1055484e237SJohannes Berg 		bss->supp_rates_len += clen;
1065484e237SJohannes Berg 	}
1075484e237SJohannes Berg 	if (elems->ext_supp_rates) {
1085484e237SJohannes Berg 		clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
1095484e237SJohannes Berg 		if (clen > elems->ext_supp_rates_len)
1105484e237SJohannes Berg 			clen = elems->ext_supp_rates_len;
1115484e237SJohannes Berg 		memcpy(&bss->supp_rates[bss->supp_rates_len],
1125484e237SJohannes Berg 		       elems->ext_supp_rates, clen);
1135484e237SJohannes Berg 		bss->supp_rates_len += clen;
1145484e237SJohannes Berg 	}
1155484e237SJohannes Berg 
1165484e237SJohannes Berg 	bss->wmm_used = elems->wmm_param || elems->wmm_info;
1175484e237SJohannes Berg 
1185484e237SJohannes Berg 	if (!beacon)
1195484e237SJohannes Berg 		bss->last_probe_resp = jiffies;
1205484e237SJohannes Berg 
1215484e237SJohannes Berg 	return bss;
1225484e237SJohannes Berg }
1230a51b27eSJohannes Berg 
1247a947080SVasanthakumar Thiagarajan void ieee80211_rx_bss_remove(struct ieee80211_sub_if_data *sdata, u8 *bssid,
1257a947080SVasanthakumar Thiagarajan 			     int freq, u8 *ssid, u8 ssid_len)
1267a947080SVasanthakumar Thiagarajan {
1277a947080SVasanthakumar Thiagarajan 	struct ieee80211_bss *bss;
1287a947080SVasanthakumar Thiagarajan 	struct ieee80211_local *local = sdata->local;
1297a947080SVasanthakumar Thiagarajan 
1307a947080SVasanthakumar Thiagarajan 	bss = ieee80211_rx_bss_get(local, bssid, freq, ssid, ssid_len);
1317a947080SVasanthakumar Thiagarajan 	if (bss) {
13200d3f14cSJohannes Berg 		cfg80211_unlink_bss(local->hw.wiphy, (void *)bss);
1337a947080SVasanthakumar Thiagarajan 		ieee80211_rx_bss_put(local, bss);
1347a947080SVasanthakumar Thiagarajan 	}
1357a947080SVasanthakumar Thiagarajan }
1367a947080SVasanthakumar Thiagarajan 
13798c8fccfSJohannes Berg ieee80211_rx_result
138c2b13452SJohannes Berg ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
13998c8fccfSJohannes Berg 		  struct ieee80211_rx_status *rx_status)
14098c8fccfSJohannes Berg {
14198c8fccfSJohannes Berg 	struct ieee80211_mgmt *mgmt;
142c2b13452SJohannes Berg 	struct ieee80211_bss *bss;
14398c8fccfSJohannes Berg 	u8 *elements;
14498c8fccfSJohannes Berg 	struct ieee80211_channel *channel;
14598c8fccfSJohannes Berg 	size_t baselen;
14698c8fccfSJohannes Berg 	int freq;
14798c8fccfSJohannes Berg 	__le16 fc;
14898c8fccfSJohannes Berg 	bool presp, beacon = false;
14998c8fccfSJohannes Berg 	struct ieee802_11_elems elems;
15098c8fccfSJohannes Berg 
15198c8fccfSJohannes Berg 	if (skb->len < 2)
15298c8fccfSJohannes Berg 		return RX_DROP_UNUSABLE;
15398c8fccfSJohannes Berg 
15498c8fccfSJohannes Berg 	mgmt = (struct ieee80211_mgmt *) skb->data;
15598c8fccfSJohannes Berg 	fc = mgmt->frame_control;
15698c8fccfSJohannes Berg 
15798c8fccfSJohannes Berg 	if (ieee80211_is_ctl(fc))
15898c8fccfSJohannes Berg 		return RX_CONTINUE;
15998c8fccfSJohannes Berg 
16098c8fccfSJohannes Berg 	if (skb->len < 24)
16198c8fccfSJohannes Berg 		return RX_DROP_MONITOR;
16298c8fccfSJohannes Berg 
16398c8fccfSJohannes Berg 	presp = ieee80211_is_probe_resp(fc);
16498c8fccfSJohannes Berg 	if (presp) {
16598c8fccfSJohannes Berg 		/* ignore ProbeResp to foreign address */
16698c8fccfSJohannes Berg 		if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
16798c8fccfSJohannes Berg 			return RX_DROP_MONITOR;
16898c8fccfSJohannes Berg 
16998c8fccfSJohannes Berg 		presp = true;
17098c8fccfSJohannes Berg 		elements = mgmt->u.probe_resp.variable;
17198c8fccfSJohannes Berg 		baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
17298c8fccfSJohannes Berg 	} else {
17398c8fccfSJohannes Berg 		beacon = ieee80211_is_beacon(fc);
17498c8fccfSJohannes Berg 		baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
17598c8fccfSJohannes Berg 		elements = mgmt->u.beacon.variable;
17698c8fccfSJohannes Berg 	}
17798c8fccfSJohannes Berg 
17898c8fccfSJohannes Berg 	if (!presp && !beacon)
17998c8fccfSJohannes Berg 		return RX_CONTINUE;
18098c8fccfSJohannes Berg 
18198c8fccfSJohannes Berg 	if (baselen > skb->len)
18298c8fccfSJohannes Berg 		return RX_DROP_MONITOR;
18398c8fccfSJohannes Berg 
18498c8fccfSJohannes Berg 	ieee802_11_parse_elems(elements, skb->len - baselen, &elems);
18598c8fccfSJohannes Berg 
18698c8fccfSJohannes Berg 	if (elems.ds_params && elems.ds_params_len == 1)
18798c8fccfSJohannes Berg 		freq = ieee80211_channel_to_frequency(elems.ds_params[0]);
18898c8fccfSJohannes Berg 	else
18998c8fccfSJohannes Berg 		freq = rx_status->freq;
19098c8fccfSJohannes Berg 
19198c8fccfSJohannes Berg 	channel = ieee80211_get_channel(sdata->local->hw.wiphy, freq);
19298c8fccfSJohannes Berg 
19398c8fccfSJohannes Berg 	if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
19498c8fccfSJohannes Berg 		return RX_DROP_MONITOR;
19598c8fccfSJohannes Berg 
19698c8fccfSJohannes Berg 	bss = ieee80211_bss_info_update(sdata->local, rx_status,
19798c8fccfSJohannes Berg 					mgmt, skb->len, &elems,
1982a519311SJohannes Berg 					channel, beacon);
199d048e503SJouni Malinen 	if (bss)
20098c8fccfSJohannes Berg 		ieee80211_rx_bss_put(sdata->local, bss);
20198c8fccfSJohannes Berg 
20298c8fccfSJohannes Berg 	dev_kfree_skb(skb);
20398c8fccfSJohannes Berg 	return RX_QUEUED;
20498c8fccfSJohannes Berg }
20598c8fccfSJohannes Berg 
2069050bdd8SKalle Valo /*
2079050bdd8SKalle Valo  * inform AP that we will go to sleep so that it will buffer the frames
2089050bdd8SKalle Valo  * while we scan
2099050bdd8SKalle Valo  */
2109050bdd8SKalle Valo static void ieee80211_scan_ps_enable(struct ieee80211_sub_if_data *sdata)
2119050bdd8SKalle Valo {
2129050bdd8SKalle Valo 	struct ieee80211_local *local = sdata->local;
2139050bdd8SKalle Valo 	bool ps = false;
2149050bdd8SKalle Valo 
2159050bdd8SKalle Valo 	/* FIXME: what to do when local->pspolling is true? */
2169050bdd8SKalle Valo 
2179050bdd8SKalle Valo 	del_timer_sync(&local->dynamic_ps_timer);
2189050bdd8SKalle Valo 	cancel_work_sync(&local->dynamic_ps_enable_work);
2199050bdd8SKalle Valo 
2209050bdd8SKalle Valo 	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
2219050bdd8SKalle Valo 		ps = true;
2229050bdd8SKalle Valo 		local->hw.conf.flags &= ~IEEE80211_CONF_PS;
2239050bdd8SKalle Valo 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
2249050bdd8SKalle Valo 	}
2259050bdd8SKalle Valo 
2269050bdd8SKalle Valo 	if (!ps || !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
2279050bdd8SKalle Valo 		/*
2289050bdd8SKalle Valo 		 * If power save was enabled, no need to send a nullfunc
2299050bdd8SKalle Valo 		 * frame because AP knows that we are sleeping. But if the
2309050bdd8SKalle Valo 		 * hardware is creating the nullfunc frame for power save
2319050bdd8SKalle Valo 		 * status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not
2329050bdd8SKalle Valo 		 * enabled) and power save was enabled, the firmware just
2339050bdd8SKalle Valo 		 * sent a null frame with power save disabled. So we need
2349050bdd8SKalle Valo 		 * to send a new nullfunc frame to inform the AP that we
2359050bdd8SKalle Valo 		 * are again sleeping.
2369050bdd8SKalle Valo 		 */
2379050bdd8SKalle Valo 		ieee80211_send_nullfunc(local, sdata, 1);
2389050bdd8SKalle Valo }
2399050bdd8SKalle Valo 
2409050bdd8SKalle Valo /* inform AP that we are awake again, unless power save is enabled */
2419050bdd8SKalle Valo static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata)
2429050bdd8SKalle Valo {
2439050bdd8SKalle Valo 	struct ieee80211_local *local = sdata->local;
2449050bdd8SKalle Valo 
245965bedadSJohannes Berg 	if (!local->ps_sdata)
2469050bdd8SKalle Valo 		ieee80211_send_nullfunc(local, sdata, 0);
2479050bdd8SKalle Valo 	else {
2489050bdd8SKalle Valo 		/*
2499050bdd8SKalle Valo 		 * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware
2509050bdd8SKalle Valo 		 * will send a nullfunc frame with the powersave bit set
2519050bdd8SKalle Valo 		 * even though the AP already knows that we are sleeping.
2529050bdd8SKalle Valo 		 * This could be avoided by sending a null frame with power
2539050bdd8SKalle Valo 		 * save bit disabled before enabling the power save, but
2549050bdd8SKalle Valo 		 * this doesn't gain anything.
2559050bdd8SKalle Valo 		 *
2569050bdd8SKalle Valo 		 * When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need
2579050bdd8SKalle Valo 		 * to send a nullfunc frame because AP already knows that
2589050bdd8SKalle Valo 		 * we are sleeping, let's just enable power save mode in
2599050bdd8SKalle Valo 		 * hardware.
2609050bdd8SKalle Valo 		 */
2619050bdd8SKalle Valo 		local->hw.conf.flags |= IEEE80211_CONF_PS;
2629050bdd8SKalle Valo 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
2639050bdd8SKalle Valo 	}
2649050bdd8SKalle Valo }
2659050bdd8SKalle Valo 
266f3b85252SJohannes Berg static void ieee80211_restore_scan_ies(struct ieee80211_local *local)
2670a51b27eSJohannes Berg {
268de95a54bSJohannes Berg 	kfree(local->scan_req->ie);
269de95a54bSJohannes Berg 	local->scan_req->ie = local->orig_ies;
270de95a54bSJohannes Berg 	local->scan_req->ie_len = local->orig_ies_len;
271de95a54bSJohannes Berg }
272de95a54bSJohannes Berg 
273f3b85252SJohannes Berg void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
274f3b85252SJohannes Berg {
275f3b85252SJohannes Berg 	struct ieee80211_local *local = hw_to_local(hw);
276f3b85252SJohannes Berg 	struct ieee80211_sub_if_data *sdata;
277f3b85252SJohannes Berg 	bool was_hw_scan;
278f3b85252SJohannes Berg 
279f3b85252SJohannes Berg 	mutex_lock(&local->scan_mtx);
280f3b85252SJohannes Berg 
281f3b85252SJohannes Berg 	if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) {
282f3b85252SJohannes Berg 		mutex_unlock(&local->scan_mtx);
283f3b85252SJohannes Berg 		return;
284f3b85252SJohannes Berg 	}
285f3b85252SJohannes Berg 
286f3b85252SJohannes Berg 	if (WARN_ON(!local->scan_req)) {
287f3b85252SJohannes Berg 		mutex_unlock(&local->scan_mtx);
288f3b85252SJohannes Berg 		return;
289f3b85252SJohannes Berg 	}
290f3b85252SJohannes Berg 
291f3b85252SJohannes Berg 	if (local->hw_scanning)
292f3b85252SJohannes Berg 		ieee80211_restore_scan_ies(local);
293f3b85252SJohannes Berg 
2942a519311SJohannes Berg 	if (local->scan_req != &local->int_scan_req)
2952a519311SJohannes Berg 		cfg80211_scan_done(local->scan_req, aborted);
2962a519311SJohannes Berg 	local->scan_req = NULL;
2972a519311SJohannes Berg 
298f3b85252SJohannes Berg 	was_hw_scan = local->hw_scanning;
299c2b13452SJohannes Berg 	local->hw_scanning = false;
300f3b85252SJohannes Berg 	local->sw_scanning = false;
301*58905ca5SJohannes Berg 	local->scan_channel = NULL;
302f3b85252SJohannes Berg 
303f3b85252SJohannes Berg 	/* we only have to protect scan_req and hw/sw scan */
304f3b85252SJohannes Berg 	mutex_unlock(&local->scan_mtx);
305f3b85252SJohannes Berg 
306e8975581SJohannes Berg 	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
3075cff20e6SJohannes Berg 	if (was_hw_scan)
3085cff20e6SJohannes Berg 		goto done;
3090a51b27eSJohannes Berg 
3100a51b27eSJohannes Berg 	netif_tx_lock_bh(local->mdev);
3110a51b27eSJohannes Berg 	netif_addr_lock(local->mdev);
3120a51b27eSJohannes Berg 	local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC;
31324487981SJohannes Berg 	drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC,
3140a51b27eSJohannes Berg 			     &local->filter_flags,
3150a51b27eSJohannes Berg 			     local->mdev->mc_count,
3160a51b27eSJohannes Berg 			     local->mdev->mc_list);
3170a51b27eSJohannes Berg 
3180a51b27eSJohannes Berg 	netif_addr_unlock(local->mdev);
3190a51b27eSJohannes Berg 	netif_tx_unlock_bh(local->mdev);
3200a51b27eSJohannes Berg 
32124487981SJohannes Berg 	drv_sw_scan_complete(local);
32280e775bfSMichael Buesch 
323078e1e60SJohannes Berg 	mutex_lock(&local->iflist_mtx);
324078e1e60SJohannes Berg 	list_for_each_entry(sdata, &local->interfaces, list) {
325fb9ddbf0SJohannes Berg 		if (!netif_running(sdata->dev))
326fb9ddbf0SJohannes Berg 			continue;
327fb9ddbf0SJohannes Berg 
3280a51b27eSJohannes Berg 		/* Tell AP we're back */
32905c914feSJohannes Berg 		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
33046900298SJohannes Berg 			if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) {
3319050bdd8SKalle Valo 				ieee80211_scan_ps_disable(sdata);
3320a51b27eSJohannes Berg 				netif_tx_wake_all_queues(sdata->dev);
3330a51b27eSJohannes Berg 			}
3340a51b27eSJohannes Berg 		} else
3350a51b27eSJohannes Berg 			netif_tx_wake_all_queues(sdata->dev);
336078e1e60SJohannes Berg 
33714b80724SJohannes Berg 		/* re-enable beaconing */
33814b80724SJohannes Berg 		if (sdata->vif.type == NL80211_IFTYPE_AP ||
33914b80724SJohannes Berg 		    sdata->vif.type == NL80211_IFTYPE_ADHOC ||
34014b80724SJohannes Berg 		    sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
3412d0ddec5SJohannes Berg 			ieee80211_bss_info_change_notify(
3422d0ddec5SJohannes Berg 				sdata, BSS_CHANGED_BEACON_ENABLED);
3430a51b27eSJohannes Berg 	}
344078e1e60SJohannes Berg 	mutex_unlock(&local->iflist_mtx);
3450a51b27eSJohannes Berg 
3460a51b27eSJohannes Berg  done:
3475cff20e6SJohannes Berg 	ieee80211_recalc_idle(local);
3480a51b27eSJohannes Berg 	ieee80211_mlme_notify_scan_completed(local);
34946900298SJohannes Berg 	ieee80211_ibss_notify_scan_completed(local);
350472dbc45SJohannes Berg 	ieee80211_mesh_notify_scan_completed(local);
3510a51b27eSJohannes Berg }
3520a51b27eSJohannes Berg EXPORT_SYMBOL(ieee80211_scan_completed);
3530a51b27eSJohannes Berg 
354f3b85252SJohannes Berg static int ieee80211_start_sw_scan(struct ieee80211_local *local)
355f3b85252SJohannes Berg {
356f3b85252SJohannes Berg 	struct ieee80211_sub_if_data *sdata;
357f3b85252SJohannes Berg 
358f3b85252SJohannes Berg 	/*
359f3b85252SJohannes Berg 	 * Hardware/driver doesn't support hw_scan, so use software
360f3b85252SJohannes Berg 	 * scanning instead. First send a nullfunc frame with power save
361f3b85252SJohannes Berg 	 * bit on so that AP will buffer the frames for us while we are not
362f3b85252SJohannes Berg 	 * listening, then send probe requests to each channel and wait for
363f3b85252SJohannes Berg 	 * the responses. After all channels are scanned, tune back to the
364f3b85252SJohannes Berg 	 * original channel and send a nullfunc frame with power save bit
365f3b85252SJohannes Berg 	 * off to trigger the AP to send us all the buffered frames.
366f3b85252SJohannes Berg 	 *
367f3b85252SJohannes Berg 	 * Note that while local->sw_scanning is true everything else but
368f3b85252SJohannes Berg 	 * nullfunc frames and probe requests will be dropped in
369f3b85252SJohannes Berg 	 * ieee80211_tx_h_check_assoc().
370f3b85252SJohannes Berg 	 */
37124487981SJohannes Berg 	drv_sw_scan_start(local);
372f3b85252SJohannes Berg 
373f3b85252SJohannes Berg 	mutex_lock(&local->iflist_mtx);
374f3b85252SJohannes Berg 	list_for_each_entry(sdata, &local->interfaces, list) {
375f3b85252SJohannes Berg 		if (!netif_running(sdata->dev))
376f3b85252SJohannes Berg 			continue;
377f3b85252SJohannes Berg 
378f3b85252SJohannes Berg 		/* disable beaconing */
379f3b85252SJohannes Berg 		if (sdata->vif.type == NL80211_IFTYPE_AP ||
380f3b85252SJohannes Berg 		    sdata->vif.type == NL80211_IFTYPE_ADHOC ||
381f3b85252SJohannes Berg 		    sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
3822d0ddec5SJohannes Berg 			ieee80211_bss_info_change_notify(
3832d0ddec5SJohannes Berg 				sdata, BSS_CHANGED_BEACON_ENABLED);
384f3b85252SJohannes Berg 
385f3b85252SJohannes Berg 		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
386f3b85252SJohannes Berg 			if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) {
387f3b85252SJohannes Berg 				netif_tx_stop_all_queues(sdata->dev);
388f3b85252SJohannes Berg 				ieee80211_scan_ps_enable(sdata);
389f3b85252SJohannes Berg 			}
390f3b85252SJohannes Berg 		} else
391f3b85252SJohannes Berg 			netif_tx_stop_all_queues(sdata->dev);
392f3b85252SJohannes Berg 	}
393f3b85252SJohannes Berg 	mutex_unlock(&local->iflist_mtx);
394f3b85252SJohannes Berg 
395f3b85252SJohannes Berg 	local->scan_state = SCAN_SET_CHANNEL;
396f3b85252SJohannes Berg 	local->scan_channel_idx = 0;
397f3b85252SJohannes Berg 
398f3b85252SJohannes Berg 	netif_addr_lock_bh(local->mdev);
399f3b85252SJohannes Berg 	local->filter_flags |= FIF_BCN_PRBRESP_PROMISC;
40024487981SJohannes Berg 	drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC,
401f3b85252SJohannes Berg 			     &local->filter_flags,
402f3b85252SJohannes Berg 			     local->mdev->mc_count,
403f3b85252SJohannes Berg 			     local->mdev->mc_list);
404f3b85252SJohannes Berg 	netif_addr_unlock_bh(local->mdev);
405f3b85252SJohannes Berg 
406f3b85252SJohannes Berg 	/* TODO: start scan as soon as all nullfunc frames are ACKed */
407f3b85252SJohannes Berg 	queue_delayed_work(local->hw.workqueue, &local->scan_work,
408f3b85252SJohannes Berg 			   IEEE80211_CHANNEL_TIME);
409f3b85252SJohannes Berg 
410f3b85252SJohannes Berg 	return 0;
411f3b85252SJohannes Berg }
412f3b85252SJohannes Berg 
413f3b85252SJohannes Berg 
414f3b85252SJohannes Berg static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
415f3b85252SJohannes Berg 				  struct cfg80211_scan_request *req)
416f3b85252SJohannes Berg {
417f3b85252SJohannes Berg 	struct ieee80211_local *local = sdata->local;
418f3b85252SJohannes Berg 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
419f3b85252SJohannes Berg 	int rc;
420f3b85252SJohannes Berg 
421f3b85252SJohannes Berg 	if (local->scan_req)
422f3b85252SJohannes Berg 		return -EBUSY;
423f3b85252SJohannes Berg 
424f3b85252SJohannes Berg 	if (local->ops->hw_scan) {
425f3b85252SJohannes Berg 		u8 *ies;
426f3b85252SJohannes Berg 		int ielen;
427f3b85252SJohannes Berg 
428f3b85252SJohannes Berg 		ies = kmalloc(2 + IEEE80211_MAX_SSID_LEN +
429f3b85252SJohannes Berg 			      local->scan_ies_len + req->ie_len, GFP_KERNEL);
430f3b85252SJohannes Berg 		if (!ies)
431f3b85252SJohannes Berg 			return -ENOMEM;
432f3b85252SJohannes Berg 
433f3b85252SJohannes Berg 		ielen = ieee80211_build_preq_ies(local, ies,
434f3b85252SJohannes Berg 						 req->ie, req->ie_len);
435f3b85252SJohannes Berg 		local->orig_ies = req->ie;
436f3b85252SJohannes Berg 		local->orig_ies_len = req->ie_len;
437f3b85252SJohannes Berg 		req->ie = ies;
438f3b85252SJohannes Berg 		req->ie_len = ielen;
439f3b85252SJohannes Berg 	}
440f3b85252SJohannes Berg 
441f3b85252SJohannes Berg 	local->scan_req = req;
442f3b85252SJohannes Berg 	local->scan_sdata = sdata;
443f3b85252SJohannes Berg 
444f3b85252SJohannes Berg 	if (req != &local->int_scan_req &&
445f3b85252SJohannes Berg 	    sdata->vif.type == NL80211_IFTYPE_STATION &&
446f3b85252SJohannes Berg 	    (ifmgd->state == IEEE80211_STA_MLME_DIRECT_PROBE ||
447f3b85252SJohannes Berg 	     ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE ||
448f3b85252SJohannes Berg 	     ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE)) {
449f3b85252SJohannes Berg 		/* actually wait for the assoc to finish/time out */
450f3b85252SJohannes Berg 		set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request);
451f3b85252SJohannes Berg 		return 0;
452f3b85252SJohannes Berg 	}
453f3b85252SJohannes Berg 
454f3b85252SJohannes Berg 	if (local->ops->hw_scan)
455f3b85252SJohannes Berg 		local->hw_scanning = true;
456f3b85252SJohannes Berg 	else
457f3b85252SJohannes Berg 		local->sw_scanning = true;
458f3b85252SJohannes Berg 	/*
459f3b85252SJohannes Berg 	 * Kicking off the scan need not be protected,
460f3b85252SJohannes Berg 	 * only the scan variable stuff, since now
461f3b85252SJohannes Berg 	 * local->scan_req is assigned and other callers
462f3b85252SJohannes Berg 	 * will abort their scan attempts.
463f3b85252SJohannes Berg 	 *
464f3b85252SJohannes Berg 	 * This avoids getting a scan_mtx -> iflist_mtx
465f3b85252SJohannes Berg 	 * dependency, so that the scan completed calls
466f3b85252SJohannes Berg 	 * have more locking freedom.
467f3b85252SJohannes Berg 	 */
4685cff20e6SJohannes Berg 
4695cff20e6SJohannes Berg 	ieee80211_recalc_idle(local);
470f3b85252SJohannes Berg 	mutex_unlock(&local->scan_mtx);
471f3b85252SJohannes Berg 
472f3b85252SJohannes Berg 	if (local->ops->hw_scan)
47324487981SJohannes Berg 		rc = drv_hw_scan(local, local->scan_req);
474f3b85252SJohannes Berg 	else
475f3b85252SJohannes Berg 		rc = ieee80211_start_sw_scan(local);
476f3b85252SJohannes Berg 
477f3b85252SJohannes Berg 	mutex_lock(&local->scan_mtx);
478f3b85252SJohannes Berg 
479f3b85252SJohannes Berg 	if (rc) {
480f3b85252SJohannes Berg 		if (local->ops->hw_scan) {
481f3b85252SJohannes Berg 			local->hw_scanning = false;
482f3b85252SJohannes Berg 			ieee80211_restore_scan_ies(local);
483f3b85252SJohannes Berg 		} else
484f3b85252SJohannes Berg 			local->sw_scanning = false;
485f3b85252SJohannes Berg 
4865cff20e6SJohannes Berg 		ieee80211_recalc_idle(local);
4875cff20e6SJohannes Berg 
488f3b85252SJohannes Berg 		local->scan_req = NULL;
489f3b85252SJohannes Berg 		local->scan_sdata = NULL;
490f3b85252SJohannes Berg 	}
491f3b85252SJohannes Berg 
492f3b85252SJohannes Berg 	return rc;
493f3b85252SJohannes Berg }
494f3b85252SJohannes Berg 
495c2b13452SJohannes Berg void ieee80211_scan_work(struct work_struct *work)
4960a51b27eSJohannes Berg {
4970a51b27eSJohannes Berg 	struct ieee80211_local *local =
4980a51b27eSJohannes Berg 		container_of(work, struct ieee80211_local, scan_work.work);
4990a51b27eSJohannes Berg 	struct ieee80211_sub_if_data *sdata = local->scan_sdata;
5000a51b27eSJohannes Berg 	struct ieee80211_channel *chan;
5012a519311SJohannes Berg 	int skip, i;
5020a51b27eSJohannes Berg 	unsigned long next_delay = 0;
5030a51b27eSJohannes Berg 
504f3b85252SJohannes Berg 	mutex_lock(&local->scan_mtx);
505f3b85252SJohannes Berg 	if (!sdata || !local->scan_req) {
506f3b85252SJohannes Berg 		mutex_unlock(&local->scan_mtx);
507f3b85252SJohannes Berg 		return;
508f3b85252SJohannes Berg 	}
509f3b85252SJohannes Berg 
510f3b85252SJohannes Berg 	if (local->scan_req && !(local->sw_scanning || local->hw_scanning)) {
511f3b85252SJohannes Berg 		struct cfg80211_scan_request *req = local->scan_req;
512f3b85252SJohannes Berg 		int rc;
513f3b85252SJohannes Berg 
514f3b85252SJohannes Berg 		local->scan_req = NULL;
515f3b85252SJohannes Berg 
516f3b85252SJohannes Berg 		rc = __ieee80211_start_scan(sdata, req);
517f3b85252SJohannes Berg 		mutex_unlock(&local->scan_mtx);
518f3b85252SJohannes Berg 
519f3b85252SJohannes Berg 		if (rc)
520f3b85252SJohannes Berg 			ieee80211_scan_completed(&local->hw, true);
521f3b85252SJohannes Berg 		return;
522f3b85252SJohannes Berg 	}
523f3b85252SJohannes Berg 
524f3b85252SJohannes Berg 	mutex_unlock(&local->scan_mtx);
525f3b85252SJohannes Berg 
5265bc75728SJohannes Berg 	/*
5275bc75728SJohannes Berg 	 * Avoid re-scheduling when the sdata is going away.
5285bc75728SJohannes Berg 	 */
529f3b85252SJohannes Berg 	if (!netif_running(sdata->dev)) {
530f3b85252SJohannes Berg 		ieee80211_scan_completed(&local->hw, true);
5310a51b27eSJohannes Berg 		return;
532f3b85252SJohannes Berg 	}
5330a51b27eSJohannes Berg 
5340a51b27eSJohannes Berg 	switch (local->scan_state) {
5350a51b27eSJohannes Berg 	case SCAN_SET_CHANNEL:
5360a51b27eSJohannes Berg 		/* if no more bands/channels left, complete scan */
5372a519311SJohannes Berg 		if (local->scan_channel_idx >= local->scan_req->n_channels) {
538f3b85252SJohannes Berg 			ieee80211_scan_completed(&local->hw, false);
5390a51b27eSJohannes Berg 			return;
5400a51b27eSJohannes Berg 		}
5410a51b27eSJohannes Berg 		skip = 0;
5422a519311SJohannes Berg 		chan = local->scan_req->channels[local->scan_channel_idx];
5430a51b27eSJohannes Berg 
5440a51b27eSJohannes Berg 		if (chan->flags & IEEE80211_CHAN_DISABLED ||
54505c914feSJohannes Berg 		    (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
5460a51b27eSJohannes Berg 		     chan->flags & IEEE80211_CHAN_NO_IBSS))
5470a51b27eSJohannes Berg 			skip = 1;
5480a51b27eSJohannes Berg 
5490a51b27eSJohannes Berg 		if (!skip) {
5500a51b27eSJohannes Berg 			local->scan_channel = chan;
551e8975581SJohannes Berg 			if (ieee80211_hw_config(local,
552e8975581SJohannes Berg 						IEEE80211_CONF_CHANGE_CHANNEL))
5530a51b27eSJohannes Berg 				skip = 1;
5540a51b27eSJohannes Berg 		}
5550a51b27eSJohannes Berg 
5560a51b27eSJohannes Berg 		/* advance state machine to next channel/band */
5570a51b27eSJohannes Berg 		local->scan_channel_idx++;
5580a51b27eSJohannes Berg 
5590a51b27eSJohannes Berg 		if (skip)
5600a51b27eSJohannes Berg 			break;
5610a51b27eSJohannes Berg 
5620a51b27eSJohannes Berg 		next_delay = IEEE80211_PROBE_DELAY +
5630a51b27eSJohannes Berg 			     usecs_to_jiffies(local->hw.channel_change_time);
5640a51b27eSJohannes Berg 		local->scan_state = SCAN_SEND_PROBE;
5650a51b27eSJohannes Berg 		break;
5660a51b27eSJohannes Berg 	case SCAN_SEND_PROBE:
5670a51b27eSJohannes Berg 		next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
5680a51b27eSJohannes Berg 		local->scan_state = SCAN_SET_CHANNEL;
5690a51b27eSJohannes Berg 
5702a519311SJohannes Berg 		if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
5712a519311SJohannes Berg 		    !local->scan_req->n_ssids)
5720a51b27eSJohannes Berg 			break;
5732a519311SJohannes Berg 		for (i = 0; i < local->scan_req->n_ssids; i++)
5742a519311SJohannes Berg 			ieee80211_send_probe_req(
5752a519311SJohannes Berg 				sdata, NULL,
5762a519311SJohannes Berg 				local->scan_req->ssids[i].ssid,
57770692ad2SJouni Malinen 				local->scan_req->ssids[i].ssid_len,
57870692ad2SJouni Malinen 				local->scan_req->ie, local->scan_req->ie_len);
5790a51b27eSJohannes Berg 		next_delay = IEEE80211_CHANNEL_TIME;
5800a51b27eSJohannes Berg 		break;
5810a51b27eSJohannes Berg 	}
5820a51b27eSJohannes Berg 
5830a51b27eSJohannes Berg 	queue_delayed_work(local->hw.workqueue, &local->scan_work,
5840a51b27eSJohannes Berg 			   next_delay);
5850a51b27eSJohannes Berg }
5860a51b27eSJohannes Berg 
587c2b13452SJohannes Berg int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
5882a519311SJohannes Berg 			   struct cfg80211_scan_request *req)
5890a51b27eSJohannes Berg {
590f3b85252SJohannes Berg 	int res;
5910a51b27eSJohannes Berg 
592f3b85252SJohannes Berg 	mutex_lock(&sdata->local->scan_mtx);
593f3b85252SJohannes Berg 	res = __ieee80211_start_scan(sdata, req);
594f3b85252SJohannes Berg 	mutex_unlock(&sdata->local->scan_mtx);
5952a519311SJohannes Berg 
596f3b85252SJohannes Berg 	return res;
5970a51b27eSJohannes Berg }
5980a51b27eSJohannes Berg 
599f3b85252SJohannes Berg int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
600f3b85252SJohannes Berg 				    const u8 *ssid, u8 ssid_len)
601f3b85252SJohannes Berg {
602f3b85252SJohannes Berg 	struct ieee80211_local *local = sdata->local;
603f3b85252SJohannes Berg 	int ret = -EBUSY;
6049116dd01SJohannes Berg 
605f3b85252SJohannes Berg 	mutex_lock(&local->scan_mtx);
606f3b85252SJohannes Berg 
607f3b85252SJohannes Berg 	/* busy scanning */
608f3b85252SJohannes Berg 	if (local->scan_req)
609f3b85252SJohannes Berg 		goto unlock;
610f3b85252SJohannes Berg 
611f3b85252SJohannes Berg 	memcpy(local->int_scan_req.ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
612f3b85252SJohannes Berg 	local->int_scan_req.ssids[0].ssid_len = ssid_len;
613f3b85252SJohannes Berg 
614f3b85252SJohannes Berg 	ret = __ieee80211_start_scan(sdata, &sdata->local->int_scan_req);
615f3b85252SJohannes Berg  unlock:
616f3b85252SJohannes Berg 	mutex_unlock(&local->scan_mtx);
617f3b85252SJohannes Berg 	return ret;
6180a51b27eSJohannes Berg }
619