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 150a51b27eSJohannes Berg #include <linux/wireless.h> 160a51b27eSJohannes Berg #include <linux/if_arp.h> 17078e1e60SJohannes Berg #include <linux/rtnetlink.h> 180a51b27eSJohannes Berg #include <net/mac80211.h> 190a51b27eSJohannes Berg 200a51b27eSJohannes Berg #include "ieee80211_i.h" 2124487981SJohannes Berg #include "driver-ops.h" 225484e237SJohannes Berg #include "mesh.h" 230a51b27eSJohannes Berg 240a51b27eSJohannes Berg #define IEEE80211_PROBE_DELAY (HZ / 33) 250a51b27eSJohannes Berg #define IEEE80211_CHANNEL_TIME (HZ / 33) 2696f7e739SHelmut Schaa #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 8) 270a51b27eSJohannes Berg 28c2b13452SJohannes Berg struct ieee80211_bss * 295484e237SJohannes Berg ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, 305484e237SJohannes Berg u8 *ssid, u8 ssid_len) 315484e237SJohannes Berg { 320c1ad2caSJohannes Berg struct cfg80211_bss *cbss; 330c1ad2caSJohannes Berg 340c1ad2caSJohannes Berg cbss = cfg80211_get_bss(local->hw.wiphy, 350c1ad2caSJohannes Berg ieee80211_get_channel(local->hw.wiphy, freq), 360c1ad2caSJohannes Berg bssid, ssid, ssid_len, 0, 0); 370c1ad2caSJohannes Berg if (!cbss) 380c1ad2caSJohannes Berg return NULL; 390c1ad2caSJohannes Berg return (void *)cbss->priv; 405484e237SJohannes Berg } 415484e237SJohannes Berg 4200d3f14cSJohannes Berg static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss) 435484e237SJohannes Berg { 440c1ad2caSJohannes Berg struct ieee80211_bss *bss = (void *)cbss->priv; 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 { 530c1ad2caSJohannes Berg if (!bss) 540c1ad2caSJohannes Berg return; 550c1ad2caSJohannes Berg cfg80211_put_bss(container_of((void *)bss, struct cfg80211_bss, priv)); 565484e237SJohannes Berg } 575484e237SJohannes Berg 58c2b13452SJohannes Berg struct ieee80211_bss * 595484e237SJohannes Berg ieee80211_bss_info_update(struct ieee80211_local *local, 605484e237SJohannes Berg struct ieee80211_rx_status *rx_status, 615484e237SJohannes Berg struct ieee80211_mgmt *mgmt, 625484e237SJohannes Berg size_t len, 635484e237SJohannes Berg struct ieee802_11_elems *elems, 642a519311SJohannes Berg struct ieee80211_channel *channel, 652a519311SJohannes Berg bool beacon) 665484e237SJohannes Berg { 670c1ad2caSJohannes Berg struct cfg80211_bss *cbss; 68c2b13452SJohannes Berg struct ieee80211_bss *bss; 6900d3f14cSJohannes Berg int clen; 702a519311SJohannes Berg s32 signal = 0; 712a519311SJohannes Berg 7277965c97SJohannes Berg if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) 732a519311SJohannes Berg signal = rx_status->signal * 100; 7477965c97SJohannes Berg else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) 752a519311SJohannes Berg signal = (rx_status->signal * 100) / local->hw.max_signal; 762a519311SJohannes Berg 770c1ad2caSJohannes Berg cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel, 7877965c97SJohannes Berg mgmt, len, signal, GFP_ATOMIC); 795484e237SJohannes Berg 800c1ad2caSJohannes Berg if (!cbss) 815484e237SJohannes Berg return NULL; 8200d3f14cSJohannes Berg 830c1ad2caSJohannes Berg cbss->free_priv = ieee80211_rx_bss_free; 840c1ad2caSJohannes Berg bss = (void *)cbss->priv; 855484e237SJohannes Berg 865484e237SJohannes Berg /* save the ERP value so that it is available at association time */ 875484e237SJohannes Berg if (elems->erp_info && elems->erp_info_len >= 1) { 885484e237SJohannes Berg bss->erp_value = elems->erp_info[0]; 895484e237SJohannes Berg bss->has_erp_value = 1; 905484e237SJohannes Berg } 915484e237SJohannes Berg 925484e237SJohannes Berg if (elems->tim) { 935484e237SJohannes Berg struct ieee80211_tim_ie *tim_ie = 945484e237SJohannes Berg (struct ieee80211_tim_ie *)elems->tim; 955484e237SJohannes Berg bss->dtim_period = tim_ie->dtim_period; 965484e237SJohannes Berg } 975484e237SJohannes Berg 986a211bf1SJohannes Berg /* set default value for buggy AP/no TIM element */ 996a211bf1SJohannes Berg if (bss->dtim_period == 0) 1005484e237SJohannes Berg bss->dtim_period = 1; 1015484e237SJohannes Berg 1025484e237SJohannes Berg bss->supp_rates_len = 0; 1035484e237SJohannes Berg if (elems->supp_rates) { 1045484e237SJohannes Berg clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; 1055484e237SJohannes Berg if (clen > elems->supp_rates_len) 1065484e237SJohannes Berg clen = elems->supp_rates_len; 1075484e237SJohannes Berg memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates, 1085484e237SJohannes Berg clen); 1095484e237SJohannes Berg bss->supp_rates_len += clen; 1105484e237SJohannes Berg } 1115484e237SJohannes Berg if (elems->ext_supp_rates) { 1125484e237SJohannes Berg clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; 1135484e237SJohannes Berg if (clen > elems->ext_supp_rates_len) 1145484e237SJohannes Berg clen = elems->ext_supp_rates_len; 1155484e237SJohannes Berg memcpy(&bss->supp_rates[bss->supp_rates_len], 1165484e237SJohannes Berg elems->ext_supp_rates, clen); 1175484e237SJohannes Berg bss->supp_rates_len += clen; 1185484e237SJohannes Berg } 1195484e237SJohannes Berg 1205484e237SJohannes Berg bss->wmm_used = elems->wmm_param || elems->wmm_info; 1215484e237SJohannes Berg 1225484e237SJohannes Berg if (!beacon) 1235484e237SJohannes Berg bss->last_probe_resp = jiffies; 1245484e237SJohannes Berg 1255484e237SJohannes Berg return bss; 1265484e237SJohannes Berg } 1270a51b27eSJohannes Berg 12898c8fccfSJohannes Berg ieee80211_rx_result 129f1d58c25SJohannes Berg ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) 13098c8fccfSJohannes Berg { 131f1d58c25SJohannes Berg struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); 13298c8fccfSJohannes Berg struct ieee80211_mgmt *mgmt; 133c2b13452SJohannes Berg struct ieee80211_bss *bss; 13498c8fccfSJohannes Berg u8 *elements; 13598c8fccfSJohannes Berg struct ieee80211_channel *channel; 13698c8fccfSJohannes Berg size_t baselen; 13798c8fccfSJohannes Berg int freq; 13898c8fccfSJohannes Berg __le16 fc; 13998c8fccfSJohannes Berg bool presp, beacon = false; 14098c8fccfSJohannes Berg struct ieee802_11_elems elems; 14198c8fccfSJohannes Berg 14298c8fccfSJohannes Berg if (skb->len < 2) 14398c8fccfSJohannes Berg return RX_DROP_UNUSABLE; 14498c8fccfSJohannes Berg 14598c8fccfSJohannes Berg mgmt = (struct ieee80211_mgmt *) skb->data; 14698c8fccfSJohannes Berg fc = mgmt->frame_control; 14798c8fccfSJohannes Berg 14898c8fccfSJohannes Berg if (ieee80211_is_ctl(fc)) 14998c8fccfSJohannes Berg return RX_CONTINUE; 15098c8fccfSJohannes Berg 15198c8fccfSJohannes Berg if (skb->len < 24) 15298c8fccfSJohannes Berg return RX_DROP_MONITOR; 15398c8fccfSJohannes Berg 15498c8fccfSJohannes Berg presp = ieee80211_is_probe_resp(fc); 15598c8fccfSJohannes Berg if (presp) { 15698c8fccfSJohannes Berg /* ignore ProbeResp to foreign address */ 15747846c9bSJohannes Berg if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN)) 15898c8fccfSJohannes Berg return RX_DROP_MONITOR; 15998c8fccfSJohannes Berg 16098c8fccfSJohannes Berg presp = true; 16198c8fccfSJohannes Berg elements = mgmt->u.probe_resp.variable; 16298c8fccfSJohannes Berg baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); 16398c8fccfSJohannes Berg } else { 16498c8fccfSJohannes Berg beacon = ieee80211_is_beacon(fc); 16598c8fccfSJohannes Berg baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable); 16698c8fccfSJohannes Berg elements = mgmt->u.beacon.variable; 16798c8fccfSJohannes Berg } 16898c8fccfSJohannes Berg 16998c8fccfSJohannes Berg if (!presp && !beacon) 17098c8fccfSJohannes Berg return RX_CONTINUE; 17198c8fccfSJohannes Berg 17298c8fccfSJohannes Berg if (baselen > skb->len) 17398c8fccfSJohannes Berg return RX_DROP_MONITOR; 17498c8fccfSJohannes Berg 17598c8fccfSJohannes Berg ieee802_11_parse_elems(elements, skb->len - baselen, &elems); 17698c8fccfSJohannes Berg 17798c8fccfSJohannes Berg if (elems.ds_params && elems.ds_params_len == 1) 17898c8fccfSJohannes Berg freq = ieee80211_channel_to_frequency(elems.ds_params[0]); 17998c8fccfSJohannes Berg else 18098c8fccfSJohannes Berg freq = rx_status->freq; 18198c8fccfSJohannes Berg 18298c8fccfSJohannes Berg channel = ieee80211_get_channel(sdata->local->hw.wiphy, freq); 18398c8fccfSJohannes Berg 18498c8fccfSJohannes Berg if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) 18598c8fccfSJohannes Berg return RX_DROP_MONITOR; 18698c8fccfSJohannes Berg 18798c8fccfSJohannes Berg bss = ieee80211_bss_info_update(sdata->local, rx_status, 18898c8fccfSJohannes Berg mgmt, skb->len, &elems, 1892a519311SJohannes Berg channel, beacon); 190d048e503SJouni Malinen if (bss) 19198c8fccfSJohannes Berg ieee80211_rx_bss_put(sdata->local, bss); 19298c8fccfSJohannes Berg 19398c8fccfSJohannes Berg dev_kfree_skb(skb); 19498c8fccfSJohannes Berg return RX_QUEUED; 19598c8fccfSJohannes Berg } 19698c8fccfSJohannes Berg 1974d36ec58SJohannes Berg /* return false if no more work */ 1984d36ec58SJohannes Berg static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) 1994d36ec58SJohannes Berg { 2004d36ec58SJohannes Berg struct cfg80211_scan_request *req = local->scan_req; 2014d36ec58SJohannes Berg enum ieee80211_band band; 2024d36ec58SJohannes Berg int i, ielen, n_chans; 2034d36ec58SJohannes Berg 2044d36ec58SJohannes Berg do { 2054d36ec58SJohannes Berg if (local->hw_scan_band == IEEE80211_NUM_BANDS) 2064d36ec58SJohannes Berg return false; 2074d36ec58SJohannes Berg 2084d36ec58SJohannes Berg band = local->hw_scan_band; 2094d36ec58SJohannes Berg n_chans = 0; 2104d36ec58SJohannes Berg for (i = 0; i < req->n_channels; i++) { 2114d36ec58SJohannes Berg if (req->channels[i]->band == band) { 2124d36ec58SJohannes Berg local->hw_scan_req->channels[n_chans] = 2134d36ec58SJohannes Berg req->channels[i]; 2144d36ec58SJohannes Berg n_chans++; 2154d36ec58SJohannes Berg } 2164d36ec58SJohannes Berg } 2174d36ec58SJohannes Berg 2184d36ec58SJohannes Berg local->hw_scan_band++; 2194d36ec58SJohannes Berg } while (!n_chans); 2204d36ec58SJohannes Berg 2214d36ec58SJohannes Berg local->hw_scan_req->n_channels = n_chans; 2224d36ec58SJohannes Berg 2234d36ec58SJohannes Berg ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, 2244d36ec58SJohannes Berg req->ie, req->ie_len, band); 2254d36ec58SJohannes Berg local->hw_scan_req->ie_len = ielen; 2264d36ec58SJohannes Berg 2274d36ec58SJohannes Berg return true; 2284d36ec58SJohannes Berg } 2294d36ec58SJohannes Berg 230f3b85252SJohannes Berg void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) 231f3b85252SJohannes Berg { 232f3b85252SJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 233f3b85252SJohannes Berg bool was_hw_scan; 234f3b85252SJohannes Berg 235f3b85252SJohannes Berg mutex_lock(&local->scan_mtx); 236f3b85252SJohannes Berg 2376d3560d4SJohannes Berg /* 2386d3560d4SJohannes Berg * It's ok to abort a not-yet-running scan (that 2396d3560d4SJohannes Berg * we have one at all will be verified by checking 2406d3560d4SJohannes Berg * local->scan_req next), but not to complete it 2416d3560d4SJohannes Berg * successfully. 2426d3560d4SJohannes Berg */ 2436d3560d4SJohannes Berg if (WARN_ON(!local->scanning && !aborted)) 2446d3560d4SJohannes Berg aborted = true; 245f3b85252SJohannes Berg 246f3b85252SJohannes Berg if (WARN_ON(!local->scan_req)) { 247f3b85252SJohannes Berg mutex_unlock(&local->scan_mtx); 248f3b85252SJohannes Berg return; 249f3b85252SJohannes Berg } 250f3b85252SJohannes Berg 2514d36ec58SJohannes Berg was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning); 2524d36ec58SJohannes Berg if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { 2534d36ec58SJohannes Berg ieee80211_queue_delayed_work(&local->hw, 2544d36ec58SJohannes Berg &local->scan_work, 0); 2554d36ec58SJohannes Berg mutex_unlock(&local->scan_mtx); 2564d36ec58SJohannes Berg return; 2574d36ec58SJohannes Berg } 2584d36ec58SJohannes Berg 2594d36ec58SJohannes Berg kfree(local->hw_scan_req); 2604d36ec58SJohannes Berg local->hw_scan_req = NULL; 261f3b85252SJohannes Berg 2625ba63533SJohannes Berg if (local->scan_req != local->int_scan_req) 2632a519311SJohannes Berg cfg80211_scan_done(local->scan_req, aborted); 2642a519311SJohannes Berg local->scan_req = NULL; 26515db0b7fSJohannes Berg local->scan_sdata = NULL; 2662a519311SJohannes Berg 267fbe9c429SHelmut Schaa local->scanning = 0; 26858905ca5SJohannes Berg local->scan_channel = NULL; 269f3b85252SJohannes Berg 270f3b85252SJohannes Berg /* we only have to protect scan_req and hw/sw scan */ 271f3b85252SJohannes Berg mutex_unlock(&local->scan_mtx); 272f3b85252SJohannes Berg 273e8975581SJohannes Berg ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 2745cff20e6SJohannes Berg if (was_hw_scan) 2755cff20e6SJohannes Berg goto done; 2760a51b27eSJohannes Berg 2773ac64beeSJohannes Berg ieee80211_configure_filter(local); 2780a51b27eSJohannes Berg 27924487981SJohannes Berg drv_sw_scan_complete(local); 28080e775bfSMichael Buesch 281*b203ffc3SJouni Malinen ieee80211_offchannel_return(local, true); 2820a51b27eSJohannes Berg 2830a51b27eSJohannes Berg done: 2845cff20e6SJohannes Berg ieee80211_recalc_idle(local); 2850a51b27eSJohannes Berg ieee80211_mlme_notify_scan_completed(local); 28646900298SJohannes Berg ieee80211_ibss_notify_scan_completed(local); 287472dbc45SJohannes Berg ieee80211_mesh_notify_scan_completed(local); 2880a51b27eSJohannes Berg } 2890a51b27eSJohannes Berg EXPORT_SYMBOL(ieee80211_scan_completed); 2900a51b27eSJohannes Berg 291f3b85252SJohannes Berg static int ieee80211_start_sw_scan(struct ieee80211_local *local) 292f3b85252SJohannes Berg { 293f3b85252SJohannes Berg /* 294f3b85252SJohannes Berg * Hardware/driver doesn't support hw_scan, so use software 295f3b85252SJohannes Berg * scanning instead. First send a nullfunc frame with power save 296f3b85252SJohannes Berg * bit on so that AP will buffer the frames for us while we are not 297f3b85252SJohannes Berg * listening, then send probe requests to each channel and wait for 298f3b85252SJohannes Berg * the responses. After all channels are scanned, tune back to the 299f3b85252SJohannes Berg * original channel and send a nullfunc frame with power save bit 300f3b85252SJohannes Berg * off to trigger the AP to send us all the buffered frames. 301f3b85252SJohannes Berg * 302f3b85252SJohannes Berg * Note that while local->sw_scanning is true everything else but 303f3b85252SJohannes Berg * nullfunc frames and probe requests will be dropped in 304f3b85252SJohannes Berg * ieee80211_tx_h_check_assoc(). 305f3b85252SJohannes Berg */ 30624487981SJohannes Berg drv_sw_scan_start(local); 307f3b85252SJohannes Berg 308*b203ffc3SJouni Malinen ieee80211_offchannel_stop_beaconing(local); 309f3b85252SJohannes Berg 310977923b0SHelmut Schaa local->next_scan_state = SCAN_DECISION; 311f3b85252SJohannes Berg local->scan_channel_idx = 0; 312f3b85252SJohannes Berg 313a80f7c0bSJohannes Berg drv_flush(local, false); 314a80f7c0bSJohannes Berg 3153ac64beeSJohannes Berg ieee80211_configure_filter(local); 316f3b85252SJohannes Berg 31742935ecaSLuis R. Rodriguez ieee80211_queue_delayed_work(&local->hw, 31842935ecaSLuis R. Rodriguez &local->scan_work, 319f3b85252SJohannes Berg IEEE80211_CHANNEL_TIME); 320f3b85252SJohannes Berg 321f3b85252SJohannes Berg return 0; 322f3b85252SJohannes Berg } 323f3b85252SJohannes Berg 324f3b85252SJohannes Berg 325f3b85252SJohannes Berg static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, 326f3b85252SJohannes Berg struct cfg80211_scan_request *req) 327f3b85252SJohannes Berg { 328f3b85252SJohannes Berg struct ieee80211_local *local = sdata->local; 329f3b85252SJohannes Berg int rc; 330f3b85252SJohannes Berg 331f3b85252SJohannes Berg if (local->scan_req) 332f3b85252SJohannes Berg return -EBUSY; 333f3b85252SJohannes Berg 334f3b85252SJohannes Berg if (local->ops->hw_scan) { 335f3b85252SJohannes Berg u8 *ies; 336f3b85252SJohannes Berg 3374d36ec58SJohannes Berg local->hw_scan_req = kmalloc( 3384d36ec58SJohannes Berg sizeof(*local->hw_scan_req) + 3394d36ec58SJohannes Berg req->n_channels * sizeof(req->channels[0]) + 3404d36ec58SJohannes Berg 2 + IEEE80211_MAX_SSID_LEN + local->scan_ies_len + 3414d36ec58SJohannes Berg req->ie_len, GFP_KERNEL); 3424d36ec58SJohannes Berg if (!local->hw_scan_req) 343f3b85252SJohannes Berg return -ENOMEM; 344f3b85252SJohannes Berg 3454d36ec58SJohannes Berg local->hw_scan_req->ssids = req->ssids; 3464d36ec58SJohannes Berg local->hw_scan_req->n_ssids = req->n_ssids; 3474d36ec58SJohannes Berg ies = (u8 *)local->hw_scan_req + 3484d36ec58SJohannes Berg sizeof(*local->hw_scan_req) + 3494d36ec58SJohannes Berg req->n_channels * sizeof(req->channels[0]); 3504d36ec58SJohannes Berg local->hw_scan_req->ie = ies; 3514d36ec58SJohannes Berg 3524d36ec58SJohannes Berg local->hw_scan_band = 0; 353f3b85252SJohannes Berg } 354f3b85252SJohannes Berg 355f3b85252SJohannes Berg local->scan_req = req; 356f3b85252SJohannes Berg local->scan_sdata = sdata; 357f3b85252SJohannes Berg 358af6b6374SJohannes Berg if (!list_empty(&local->work_list)) { 359af6b6374SJohannes Berg /* wait for the work to finish/time out */ 360f3b85252SJohannes Berg return 0; 361f3b85252SJohannes Berg } 362f3b85252SJohannes Berg 363f3b85252SJohannes Berg if (local->ops->hw_scan) 364fbe9c429SHelmut Schaa __set_bit(SCAN_HW_SCANNING, &local->scanning); 365f3b85252SJohannes Berg else 366fbe9c429SHelmut Schaa __set_bit(SCAN_SW_SCANNING, &local->scanning); 367f3b85252SJohannes Berg /* 368f3b85252SJohannes Berg * Kicking off the scan need not be protected, 369f3b85252SJohannes Berg * only the scan variable stuff, since now 370f3b85252SJohannes Berg * local->scan_req is assigned and other callers 371f3b85252SJohannes Berg * will abort their scan attempts. 372f3b85252SJohannes Berg * 373f3b85252SJohannes Berg * This avoids getting a scan_mtx -> iflist_mtx 374f3b85252SJohannes Berg * dependency, so that the scan completed calls 375f3b85252SJohannes Berg * have more locking freedom. 376f3b85252SJohannes Berg */ 3775cff20e6SJohannes Berg 3785cff20e6SJohannes Berg ieee80211_recalc_idle(local); 379f3b85252SJohannes Berg mutex_unlock(&local->scan_mtx); 380f3b85252SJohannes Berg 3814d36ec58SJohannes Berg if (local->ops->hw_scan) { 3824d36ec58SJohannes Berg WARN_ON(!ieee80211_prep_hw_scan(local)); 3834d36ec58SJohannes Berg rc = drv_hw_scan(local, local->hw_scan_req); 3844d36ec58SJohannes Berg } else 385f3b85252SJohannes Berg rc = ieee80211_start_sw_scan(local); 386f3b85252SJohannes Berg 387f3b85252SJohannes Berg mutex_lock(&local->scan_mtx); 388f3b85252SJohannes Berg 389f3b85252SJohannes Berg if (rc) { 3904d36ec58SJohannes Berg kfree(local->hw_scan_req); 3914d36ec58SJohannes Berg local->hw_scan_req = NULL; 392fbe9c429SHelmut Schaa local->scanning = 0; 393f3b85252SJohannes Berg 3945cff20e6SJohannes Berg ieee80211_recalc_idle(local); 3955cff20e6SJohannes Berg 396f3b85252SJohannes Berg local->scan_req = NULL; 397f3b85252SJohannes Berg local->scan_sdata = NULL; 398f3b85252SJohannes Berg } 399f3b85252SJohannes Berg 400f3b85252SJohannes Berg return rc; 401f3b85252SJohannes Berg } 402f3b85252SJohannes Berg 4032fb3f028SHelmut Schaa static int ieee80211_scan_state_decision(struct ieee80211_local *local, 4042fb3f028SHelmut Schaa unsigned long *next_delay) 4052fb3f028SHelmut Schaa { 406142b9f50SHelmut Schaa bool associated = false; 407142b9f50SHelmut Schaa struct ieee80211_sub_if_data *sdata; 408142b9f50SHelmut Schaa 409142b9f50SHelmut Schaa /* if no more bands/channels left, complete scan and advance to the idle state */ 4102fb3f028SHelmut Schaa if (local->scan_channel_idx >= local->scan_req->n_channels) { 4112fb3f028SHelmut Schaa ieee80211_scan_completed(&local->hw, false); 4122fb3f028SHelmut Schaa return 1; 4132fb3f028SHelmut Schaa } 4142fb3f028SHelmut Schaa 415142b9f50SHelmut Schaa /* check if at least one STA interface is associated */ 416142b9f50SHelmut Schaa mutex_lock(&local->iflist_mtx); 417142b9f50SHelmut Schaa list_for_each_entry(sdata, &local->interfaces, list) { 4189607e6b6SJohannes Berg if (!ieee80211_sdata_running(sdata)) 419142b9f50SHelmut Schaa continue; 420142b9f50SHelmut Schaa 421142b9f50SHelmut Schaa if (sdata->vif.type == NL80211_IFTYPE_STATION) { 422142b9f50SHelmut Schaa if (sdata->u.mgd.associated) { 423142b9f50SHelmut Schaa associated = true; 424142b9f50SHelmut Schaa break; 425142b9f50SHelmut Schaa } 426142b9f50SHelmut Schaa } 427142b9f50SHelmut Schaa } 428142b9f50SHelmut Schaa mutex_unlock(&local->iflist_mtx); 429142b9f50SHelmut Schaa 430142b9f50SHelmut Schaa if (local->scan_channel) { 431142b9f50SHelmut Schaa /* 432142b9f50SHelmut Schaa * we're currently scanning a different channel, let's 433142b9f50SHelmut Schaa * switch back to the operating channel now if at least 434142b9f50SHelmut Schaa * one interface is associated. Otherwise just scan the 435142b9f50SHelmut Schaa * next channel 436142b9f50SHelmut Schaa */ 437142b9f50SHelmut Schaa if (associated) 438977923b0SHelmut Schaa local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; 439142b9f50SHelmut Schaa else 440977923b0SHelmut Schaa local->next_scan_state = SCAN_SET_CHANNEL; 441142b9f50SHelmut Schaa } else { 442142b9f50SHelmut Schaa /* 443142b9f50SHelmut Schaa * we're on the operating channel currently, let's 444142b9f50SHelmut Schaa * leave that channel now to scan another one 445142b9f50SHelmut Schaa */ 446977923b0SHelmut Schaa local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; 447142b9f50SHelmut Schaa } 448142b9f50SHelmut Schaa 449142b9f50SHelmut Schaa *next_delay = 0; 4502fb3f028SHelmut Schaa return 0; 4512fb3f028SHelmut Schaa } 4522fb3f028SHelmut Schaa 453142b9f50SHelmut Schaa static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, 454142b9f50SHelmut Schaa unsigned long *next_delay) 455142b9f50SHelmut Schaa { 456*b203ffc3SJouni Malinen ieee80211_offchannel_stop_station(local); 457142b9f50SHelmut Schaa 458142b9f50SHelmut Schaa __set_bit(SCAN_OFF_CHANNEL, &local->scanning); 459142b9f50SHelmut Schaa 460a80f7c0bSJohannes Berg /* 461a80f7c0bSJohannes Berg * What if the nullfunc frames didn't arrive? 462a80f7c0bSJohannes Berg */ 463a80f7c0bSJohannes Berg drv_flush(local, false); 464a80f7c0bSJohannes Berg if (local->ops->flush) 465a80f7c0bSJohannes Berg *next_delay = 0; 466a80f7c0bSJohannes Berg else 467142b9f50SHelmut Schaa *next_delay = HZ / 10; 468a80f7c0bSJohannes Berg 469a80f7c0bSJohannes Berg /* advance to the next channel to be scanned */ 470977923b0SHelmut Schaa local->next_scan_state = SCAN_SET_CHANNEL; 471142b9f50SHelmut Schaa } 472142b9f50SHelmut Schaa 473142b9f50SHelmut Schaa static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local, 474142b9f50SHelmut Schaa unsigned long *next_delay) 475142b9f50SHelmut Schaa { 476142b9f50SHelmut Schaa /* switch back to the operating channel */ 477142b9f50SHelmut Schaa local->scan_channel = NULL; 478142b9f50SHelmut Schaa ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 479142b9f50SHelmut Schaa 480142b9f50SHelmut Schaa /* 481*b203ffc3SJouni Malinen * Only re-enable station mode interface now; beaconing will be 482*b203ffc3SJouni Malinen * re-enabled once the full scan has been completed. 483142b9f50SHelmut Schaa */ 484*b203ffc3SJouni Malinen ieee80211_offchannel_return(local, false); 485142b9f50SHelmut Schaa 486142b9f50SHelmut Schaa __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); 487142b9f50SHelmut Schaa 488142b9f50SHelmut Schaa *next_delay = HZ / 5; 489977923b0SHelmut Schaa local->next_scan_state = SCAN_DECISION; 490142b9f50SHelmut Schaa } 491142b9f50SHelmut Schaa 4922fb3f028SHelmut Schaa static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, 4937d3be3ccSHelmut Schaa unsigned long *next_delay) 4947d3be3ccSHelmut Schaa { 4957d3be3ccSHelmut Schaa int skip; 4967d3be3ccSHelmut Schaa struct ieee80211_channel *chan; 4977d3be3ccSHelmut Schaa 4987d3be3ccSHelmut Schaa skip = 0; 4997d3be3ccSHelmut Schaa chan = local->scan_req->channels[local->scan_channel_idx]; 5007d3be3ccSHelmut Schaa 5017d3be3ccSHelmut Schaa local->scan_channel = chan; 502584991dcSJohannes Berg if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL)) 5037d3be3ccSHelmut Schaa skip = 1; 5047d3be3ccSHelmut Schaa 5057d3be3ccSHelmut Schaa /* advance state machine to next channel/band */ 5067d3be3ccSHelmut Schaa local->scan_channel_idx++; 5077d3be3ccSHelmut Schaa 5080ee9c13cSHelmut Schaa if (skip) { 5090ee9c13cSHelmut Schaa /* if we skip this channel return to the decision state */ 5100ee9c13cSHelmut Schaa local->next_scan_state = SCAN_DECISION; 5112fb3f028SHelmut Schaa return; 5120ee9c13cSHelmut Schaa } 5137d3be3ccSHelmut Schaa 5147d3be3ccSHelmut Schaa /* 5157d3be3ccSHelmut Schaa * Probe delay is used to update the NAV, cf. 11.1.3.2.2 5167d3be3ccSHelmut Schaa * (which unfortunately doesn't say _why_ step a) is done, 5177d3be3ccSHelmut Schaa * but it waits for the probe delay or until a frame is 5187d3be3ccSHelmut Schaa * received - and the received frame would update the NAV). 5197d3be3ccSHelmut Schaa * For now, we do not support waiting until a frame is 5207d3be3ccSHelmut Schaa * received. 5217d3be3ccSHelmut Schaa * 5227d3be3ccSHelmut Schaa * In any case, it is not necessary for a passive scan. 5237d3be3ccSHelmut Schaa */ 5247d3be3ccSHelmut Schaa if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN || 5257d3be3ccSHelmut Schaa !local->scan_req->n_ssids) { 5267d3be3ccSHelmut Schaa *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; 527977923b0SHelmut Schaa local->next_scan_state = SCAN_DECISION; 5282fb3f028SHelmut Schaa return; 5297d3be3ccSHelmut Schaa } 5307d3be3ccSHelmut Schaa 5312fb3f028SHelmut Schaa /* active scan, send probes */ 5327d3be3ccSHelmut Schaa *next_delay = IEEE80211_PROBE_DELAY; 533977923b0SHelmut Schaa local->next_scan_state = SCAN_SEND_PROBE; 5347d3be3ccSHelmut Schaa } 5357d3be3ccSHelmut Schaa 5367d3be3ccSHelmut Schaa static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, 5377d3be3ccSHelmut Schaa unsigned long *next_delay) 5387d3be3ccSHelmut Schaa { 5397d3be3ccSHelmut Schaa int i; 5407d3be3ccSHelmut Schaa struct ieee80211_sub_if_data *sdata = local->scan_sdata; 5417d3be3ccSHelmut Schaa 5427d3be3ccSHelmut Schaa for (i = 0; i < local->scan_req->n_ssids; i++) 5437d3be3ccSHelmut Schaa ieee80211_send_probe_req( 5447d3be3ccSHelmut Schaa sdata, NULL, 5457d3be3ccSHelmut Schaa local->scan_req->ssids[i].ssid, 5467d3be3ccSHelmut Schaa local->scan_req->ssids[i].ssid_len, 5477d3be3ccSHelmut Schaa local->scan_req->ie, local->scan_req->ie_len); 5487d3be3ccSHelmut Schaa 5497d3be3ccSHelmut Schaa /* 5507d3be3ccSHelmut Schaa * After sending probe requests, wait for probe responses 5517d3be3ccSHelmut Schaa * on the channel. 5527d3be3ccSHelmut Schaa */ 5537d3be3ccSHelmut Schaa *next_delay = IEEE80211_CHANNEL_TIME; 554977923b0SHelmut Schaa local->next_scan_state = SCAN_DECISION; 5557d3be3ccSHelmut Schaa } 5567d3be3ccSHelmut Schaa 557c2b13452SJohannes Berg void ieee80211_scan_work(struct work_struct *work) 5580a51b27eSJohannes Berg { 5590a51b27eSJohannes Berg struct ieee80211_local *local = 5600a51b27eSJohannes Berg container_of(work, struct ieee80211_local, scan_work.work); 5610a51b27eSJohannes Berg struct ieee80211_sub_if_data *sdata = local->scan_sdata; 5620a51b27eSJohannes Berg unsigned long next_delay = 0; 5630a51b27eSJohannes Berg 564f3b85252SJohannes Berg mutex_lock(&local->scan_mtx); 565f3b85252SJohannes Berg if (!sdata || !local->scan_req) { 566f3b85252SJohannes Berg mutex_unlock(&local->scan_mtx); 567f3b85252SJohannes Berg return; 568f3b85252SJohannes Berg } 569f3b85252SJohannes Berg 5704d36ec58SJohannes Berg if (local->hw_scan_req) { 5714d36ec58SJohannes Berg int rc = drv_hw_scan(local, local->hw_scan_req); 5724d36ec58SJohannes Berg mutex_unlock(&local->scan_mtx); 5734d36ec58SJohannes Berg if (rc) 5744d36ec58SJohannes Berg ieee80211_scan_completed(&local->hw, true); 5754d36ec58SJohannes Berg return; 5764d36ec58SJohannes Berg } 5774d36ec58SJohannes Berg 578fbe9c429SHelmut Schaa if (local->scan_req && !local->scanning) { 579f3b85252SJohannes Berg struct cfg80211_scan_request *req = local->scan_req; 580f3b85252SJohannes Berg int rc; 581f3b85252SJohannes Berg 582f3b85252SJohannes Berg local->scan_req = NULL; 58315db0b7fSJohannes Berg local->scan_sdata = NULL; 584f3b85252SJohannes Berg 585f3b85252SJohannes Berg rc = __ieee80211_start_scan(sdata, req); 586f3b85252SJohannes Berg mutex_unlock(&local->scan_mtx); 587f3b85252SJohannes Berg 588f3b85252SJohannes Berg if (rc) 589f3b85252SJohannes Berg ieee80211_scan_completed(&local->hw, true); 590f3b85252SJohannes Berg return; 591f3b85252SJohannes Berg } 592f3b85252SJohannes Berg 593f3b85252SJohannes Berg mutex_unlock(&local->scan_mtx); 594f3b85252SJohannes Berg 5955bc75728SJohannes Berg /* 5965bc75728SJohannes Berg * Avoid re-scheduling when the sdata is going away. 5975bc75728SJohannes Berg */ 5989607e6b6SJohannes Berg if (!ieee80211_sdata_running(sdata)) { 599f3b85252SJohannes Berg ieee80211_scan_completed(&local->hw, true); 6000a51b27eSJohannes Berg return; 601f3b85252SJohannes Berg } 6020a51b27eSJohannes Berg 603f502d09bSHelmut Schaa /* 604f502d09bSHelmut Schaa * as long as no delay is required advance immediately 605f502d09bSHelmut Schaa * without scheduling a new work 606f502d09bSHelmut Schaa */ 607f502d09bSHelmut Schaa do { 608977923b0SHelmut Schaa switch (local->next_scan_state) { 6092fb3f028SHelmut Schaa case SCAN_DECISION: 6102fb3f028SHelmut Schaa if (ieee80211_scan_state_decision(local, &next_delay)) 6110a51b27eSJohannes Berg return; 6120a51b27eSJohannes Berg break; 6132fb3f028SHelmut Schaa case SCAN_SET_CHANNEL: 6142fb3f028SHelmut Schaa ieee80211_scan_state_set_channel(local, &next_delay); 6152fb3f028SHelmut Schaa break; 6160a51b27eSJohannes Berg case SCAN_SEND_PROBE: 6177d3be3ccSHelmut Schaa ieee80211_scan_state_send_probe(local, &next_delay); 6180a51b27eSJohannes Berg break; 619142b9f50SHelmut Schaa case SCAN_LEAVE_OPER_CHANNEL: 620142b9f50SHelmut Schaa ieee80211_scan_state_leave_oper_channel(local, &next_delay); 621142b9f50SHelmut Schaa break; 622142b9f50SHelmut Schaa case SCAN_ENTER_OPER_CHANNEL: 623142b9f50SHelmut Schaa ieee80211_scan_state_enter_oper_channel(local, &next_delay); 624142b9f50SHelmut Schaa break; 6250a51b27eSJohannes Berg } 626f502d09bSHelmut Schaa } while (next_delay == 0); 6270a51b27eSJohannes Berg 62842935ecaSLuis R. Rodriguez ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay); 6290a51b27eSJohannes Berg } 6300a51b27eSJohannes Berg 631c2b13452SJohannes Berg int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, 6322a519311SJohannes Berg struct cfg80211_scan_request *req) 6330a51b27eSJohannes Berg { 634f3b85252SJohannes Berg int res; 6350a51b27eSJohannes Berg 636f3b85252SJohannes Berg mutex_lock(&sdata->local->scan_mtx); 637f3b85252SJohannes Berg res = __ieee80211_start_scan(sdata, req); 638f3b85252SJohannes Berg mutex_unlock(&sdata->local->scan_mtx); 6392a519311SJohannes Berg 640f3b85252SJohannes Berg return res; 6410a51b27eSJohannes Berg } 6420a51b27eSJohannes Berg 643f3b85252SJohannes Berg int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, 644f3b85252SJohannes Berg const u8 *ssid, u8 ssid_len) 645f3b85252SJohannes Berg { 646f3b85252SJohannes Berg struct ieee80211_local *local = sdata->local; 647f3b85252SJohannes Berg int ret = -EBUSY; 6489116dd01SJohannes Berg 649f3b85252SJohannes Berg mutex_lock(&local->scan_mtx); 650f3b85252SJohannes Berg 651f3b85252SJohannes Berg /* busy scanning */ 652f3b85252SJohannes Berg if (local->scan_req) 653f3b85252SJohannes Berg goto unlock; 654f3b85252SJohannes Berg 6555ba63533SJohannes Berg memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); 6565ba63533SJohannes Berg local->int_scan_req->ssids[0].ssid_len = ssid_len; 657f3b85252SJohannes Berg 6585ba63533SJohannes Berg ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req); 659f3b85252SJohannes Berg unlock: 660f3b85252SJohannes Berg mutex_unlock(&local->scan_mtx); 661f3b85252SJohannes Berg return ret; 6620a51b27eSJohannes Berg } 6635bb644a0SJohannes Berg 6645bb644a0SJohannes Berg void ieee80211_scan_cancel(struct ieee80211_local *local) 6655bb644a0SJohannes Berg { 66615db0b7fSJohannes Berg bool abortscan; 6675bb644a0SJohannes Berg 6685bb644a0SJohannes Berg cancel_delayed_work_sync(&local->scan_work); 6695bb644a0SJohannes Berg 6705bb644a0SJohannes Berg /* 6715bb644a0SJohannes Berg * Only call this function when a scan can't be 6725bb644a0SJohannes Berg * queued -- mostly at suspend under RTNL. 6735bb644a0SJohannes Berg */ 6745bb644a0SJohannes Berg mutex_lock(&local->scan_mtx); 67515db0b7fSJohannes Berg abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) || 67615db0b7fSJohannes Berg (!local->scanning && local->scan_req); 6775bb644a0SJohannes Berg mutex_unlock(&local->scan_mtx); 6785bb644a0SJohannes Berg 67915db0b7fSJohannes Berg if (abortscan) 6805bb644a0SJohannes Berg ieee80211_scan_completed(&local->hw, true); 6815bb644a0SJohannes Berg } 682