00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <linux/if_arp.h>
00016 #include <linux/etherdevice.h>
00017 #include <linux/rtnetlink.h>
00018 #include <linux/pm_qos.h>
00019 #include <net/sch_generic.h>
00020 #include <linux/slab.h>
00021 #include <linux/export.h>
00022 #include <net/mac80211.h>
00023
00024 #include "ieee80211_i.h"
00025 #include "driver-ops.h"
00026 #include "mesh.h"
00027
00028 #define IEEE80211_PROBE_DELAY (HZ / 33)
00029 #define IEEE80211_CHANNEL_TIME (HZ / 33)
00030 #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 8)
00031
00032 static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss)
00033 {
00034 struct ieee80211_bss *bss = (void *)cbss->priv;
00035
00036 kfree(bss_mesh_id(bss));
00037 kfree(bss_mesh_cfg(bss));
00038 }
00039
00040 void ieee80211_rx_bss_put(struct ieee80211_local *local,
00041 struct ieee80211_bss *bss)
00042 {
00043 if (!bss)
00044 return;
00045 cfg80211_put_bss(container_of((void *)bss, struct cfg80211_bss, priv));
00046 }
00047
00048 static bool is_uapsd_supported(struct ieee802_11_elems *elems)
00049 {
00050 u8 qos_info;
00051
00052 if (elems->wmm_info && elems->wmm_info_len == 7
00053 && elems->wmm_info[5] == 1)
00054 qos_info = elems->wmm_info[6];
00055 else if (elems->wmm_param && elems->wmm_param_len == 24
00056 && elems->wmm_param[5] == 1)
00057 qos_info = elems->wmm_param[6];
00058 else
00059
00060 return false;
00061
00062 return qos_info & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD;
00063 }
00064
00065 struct ieee80211_bss *
00066 ieee80211_bss_info_update(struct ieee80211_local *local,
00067 struct ieee80211_rx_status *rx_status,
00068 struct ieee80211_mgmt *mgmt,
00069 size_t len,
00070 struct ieee802_11_elems *elems,
00071 struct ieee80211_channel *channel,
00072 bool beacon)
00073 {
00074 struct cfg80211_bss *cbss;
00075 struct ieee80211_bss *bss;
00076 int clen, srlen;
00077 s32 signal = 0;
00078
00079 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
00080 signal = rx_status->signal * 100;
00081 else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
00082 signal = (rx_status->signal * 100) / local->hw.max_signal;
00083
00084 cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel,
00085 mgmt, len, signal, GFP_ATOMIC);
00086
00087 if (!cbss)
00088 return NULL;
00089
00090 cbss->free_priv = ieee80211_rx_bss_free;
00091 bss = (void *)cbss->priv;
00092
00093 if (elems->parse_error) {
00094 if (beacon)
00095 bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON;
00096 else
00097 bss->corrupt_data |= IEEE80211_BSS_CORRUPT_PROBE_RESP;
00098 } else {
00099 if (beacon)
00100 bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_BEACON;
00101 else
00102 bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_PROBE_RESP;
00103 }
00104
00105
00106 if (elems->erp_info && elems->erp_info_len >= 1 &&
00107 (!elems->parse_error ||
00108 !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) {
00109 bss->erp_value = elems->erp_info[0];
00110 bss->has_erp_value = true;
00111 if (!elems->parse_error)
00112 bss->valid_data |= IEEE80211_BSS_VALID_ERP;
00113 }
00114
00115 if (elems->tim && (!elems->parse_error ||
00116 !(bss->valid_data & IEEE80211_BSS_VALID_DTIM))) {
00117 struct ieee80211_tim_ie *tim_ie =
00118 (struct ieee80211_tim_ie *)elems->tim;
00119 bss->dtim_period = tim_ie->dtim_period;
00120 if (!elems->parse_error)
00121 bss->valid_data |= IEEE80211_BSS_VALID_DTIM;
00122 }
00123
00124
00125 if (beacon && !bss->dtim_period)
00126 bss->dtim_period = 1;
00127
00128
00129 if (!elems->parse_error ||
00130 !(bss->valid_data & IEEE80211_BSS_VALID_RATES)) {
00131 srlen = 0;
00132 if (elems->supp_rates) {
00133 clen = IEEE80211_MAX_SUPP_RATES;
00134 if (clen > elems->supp_rates_len)
00135 clen = elems->supp_rates_len;
00136 memcpy(bss->supp_rates, elems->supp_rates, clen);
00137 srlen += clen;
00138 }
00139 if (elems->ext_supp_rates) {
00140 clen = IEEE80211_MAX_SUPP_RATES - srlen;
00141 if (clen > elems->ext_supp_rates_len)
00142 clen = elems->ext_supp_rates_len;
00143 memcpy(bss->supp_rates + srlen, elems->ext_supp_rates,
00144 clen);
00145 srlen += clen;
00146 }
00147 if (srlen) {
00148 bss->supp_rates_len = srlen;
00149 if (!elems->parse_error)
00150 bss->valid_data |= IEEE80211_BSS_VALID_RATES;
00151 }
00152 }
00153
00154 if (!elems->parse_error ||
00155 !(bss->valid_data & IEEE80211_BSS_VALID_WMM)) {
00156 bss->wmm_used = elems->wmm_param || elems->wmm_info;
00157 bss->uapsd_supported = is_uapsd_supported(elems);
00158 if (!elems->parse_error)
00159 bss->valid_data |= IEEE80211_BSS_VALID_WMM;
00160 }
00161
00162 if (!beacon)
00163 bss->last_probe_resp = jiffies;
00164
00165 return bss;
00166 }
00167
00168 ieee80211_rx_result
00169 ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
00170 {
00171 struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
00172 struct ieee80211_mgmt *mgmt;
00173 struct ieee80211_bss *bss;
00174 u8 *elements;
00175 struct ieee80211_channel *channel;
00176 size_t baselen;
00177 int freq;
00178 __le16 fc;
00179 bool presp, beacon = false;
00180 struct ieee802_11_elems elems;
00181
00182 if (skb->len < 2)
00183 return RX_DROP_UNUSABLE;
00184
00185 mgmt = (struct ieee80211_mgmt *) skb->data;
00186 fc = mgmt->frame_control;
00187
00188 if (ieee80211_is_ctl(fc))
00189 return RX_CONTINUE;
00190
00191 if (skb->len < 24)
00192 return RX_CONTINUE;
00193
00194 presp = ieee80211_is_probe_resp(fc);
00195 if (presp) {
00196
00197 if (!ether_addr_equal(mgmt->da, sdata->vif.addr))
00198 return RX_DROP_MONITOR;
00199
00200 presp = true;
00201 elements = mgmt->u.probe_resp.variable;
00202 baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
00203 } else {
00204 beacon = ieee80211_is_beacon(fc);
00205 baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
00206 elements = mgmt->u.beacon.variable;
00207 }
00208
00209 if (!presp && !beacon)
00210 return RX_CONTINUE;
00211
00212 if (baselen > skb->len)
00213 return RX_DROP_MONITOR;
00214
00215 ieee802_11_parse_elems(elements, skb->len - baselen, &elems);
00216
00217 if (elems.ds_params && elems.ds_params_len == 1)
00218 freq = ieee80211_channel_to_frequency(elems.ds_params[0],
00219 rx_status->band);
00220 else
00221 freq = rx_status->freq;
00222
00223 channel = ieee80211_get_channel(sdata->local->hw.wiphy, freq);
00224
00225 if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
00226 return RX_DROP_MONITOR;
00227
00228 bss = ieee80211_bss_info_update(sdata->local, rx_status,
00229 mgmt, skb->len, &elems,
00230 channel, beacon);
00231 if (bss)
00232 ieee80211_rx_bss_put(sdata->local, bss);
00233
00234 if (channel == sdata->local->oper_channel)
00235 return RX_CONTINUE;
00236
00237 dev_kfree_skb(skb);
00238 return RX_QUEUED;
00239 }
00240
00241
00242 static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
00243 {
00244 struct cfg80211_scan_request *req = local->scan_req;
00245 enum ieee80211_band band;
00246 int i, ielen, n_chans;
00247
00248 do {
00249 if (local->hw_scan_band == IEEE80211_NUM_BANDS)
00250 return false;
00251
00252 band = local->hw_scan_band;
00253 n_chans = 0;
00254 for (i = 0; i < req->n_channels; i++) {
00255 if (req->channels[i]->band == band) {
00256 local->hw_scan_req->channels[n_chans] =
00257 req->channels[i];
00258 n_chans++;
00259 }
00260 }
00261
00262 local->hw_scan_band++;
00263 } while (!n_chans);
00264
00265 local->hw_scan_req->n_channels = n_chans;
00266
00267 ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie,
00268 req->ie, req->ie_len, band,
00269 req->rates[band], 0);
00270 local->hw_scan_req->ie_len = ielen;
00271 local->hw_scan_req->no_cck = req->no_cck;
00272
00273 return true;
00274 }
00275
00276 static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
00277 bool was_hw_scan)
00278 {
00279 struct ieee80211_local *local = hw_to_local(hw);
00280
00281 lockdep_assert_held(&local->mtx);
00282
00283
00284
00285
00286
00287
00288
00289 if (WARN_ON(!local->scanning && !aborted))
00290 aborted = true;
00291
00292 if (WARN_ON(!local->scan_req))
00293 return;
00294
00295 if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
00296 int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req);
00297 if (rc == 0)
00298 return;
00299 }
00300
00301 kfree(local->hw_scan_req);
00302 local->hw_scan_req = NULL;
00303
00304 if (local->scan_req != local->int_scan_req)
00305 cfg80211_scan_done(local->scan_req, aborted);
00306 local->scan_req = NULL;
00307 local->scan_sdata = NULL;
00308
00309 local->scanning = 0;
00310 local->scan_channel = NULL;
00311
00312
00313 ieee80211_hw_config(local, 0);
00314
00315 if (!was_hw_scan) {
00316 ieee80211_configure_filter(local);
00317 drv_sw_scan_complete(local);
00318 ieee80211_offchannel_return(local, true);
00319 }
00320
00321 ieee80211_recalc_idle(local);
00322
00323 ieee80211_mlme_notify_scan_completed(local);
00324 ieee80211_ibss_notify_scan_completed(local);
00325 ieee80211_mesh_notify_scan_completed(local);
00326 ieee80211_queue_work(&local->hw, &local->work_work);
00327 }
00328
00329 void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
00330 {
00331 struct ieee80211_local *local = hw_to_local(hw);
00332
00333 trace_api_scan_completed(local, aborted);
00334
00335 set_bit(SCAN_COMPLETED, &local->scanning);
00336 if (aborted)
00337 set_bit(SCAN_ABORTED, &local->scanning);
00338 ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
00339 }
00340 EXPORT_SYMBOL(ieee80211_scan_completed);
00341
00342 static int ieee80211_start_sw_scan(struct ieee80211_local *local)
00343 {
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 drv_sw_scan_start(local);
00358
00359 local->leave_oper_channel_time = jiffies;
00360 local->next_scan_state = SCAN_DECISION;
00361 local->scan_channel_idx = 0;
00362
00363 ieee80211_offchannel_stop_vifs(local, true);
00364
00365 ieee80211_configure_filter(local);
00366
00367
00368 ieee80211_hw_config(local, 0);
00369
00370 ieee80211_queue_delayed_work(&local->hw,
00371 &local->scan_work, 0);
00372
00373 return 0;
00374 }
00375
00376 static bool ieee80211_can_scan(struct ieee80211_local *local,
00377 struct ieee80211_sub_if_data *sdata)
00378 {
00379 if (!list_empty(&local->work_list))
00380 return false;
00381
00382 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
00383 sdata->u.mgd.flags & (IEEE80211_STA_BEACON_POLL |
00384 IEEE80211_STA_CONNECTION_POLL))
00385 return false;
00386
00387 return true;
00388 }
00389
00390 void ieee80211_run_deferred_scan(struct ieee80211_local *local)
00391 {
00392 lockdep_assert_held(&local->mtx);
00393
00394 if (!local->scan_req || local->scanning)
00395 return;
00396
00397 if (!ieee80211_can_scan(local, local->scan_sdata))
00398 return;
00399
00400 ieee80211_queue_delayed_work(&local->hw, &local->scan_work,
00401 round_jiffies_relative(0));
00402 }
00403
00404 static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
00405 unsigned long *next_delay)
00406 {
00407 int i;
00408 struct ieee80211_sub_if_data *sdata = local->scan_sdata;
00409 enum ieee80211_band band = local->hw.conf.channel->band;
00410
00411 for (i = 0; i < local->scan_req->n_ssids; i++)
00412 ieee80211_send_probe_req(
00413 sdata, NULL,
00414 local->scan_req->ssids[i].ssid,
00415 local->scan_req->ssids[i].ssid_len,
00416 local->scan_req->ie, local->scan_req->ie_len,
00417 local->scan_req->rates[band], false,
00418 local->scan_req->no_cck);
00419
00420
00421
00422
00423
00424 *next_delay = IEEE80211_CHANNEL_TIME;
00425 local->next_scan_state = SCAN_DECISION;
00426 }
00427
00428 static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
00429 struct cfg80211_scan_request *req)
00430 {
00431 struct ieee80211_local *local = sdata->local;
00432 int rc;
00433
00434 lockdep_assert_held(&local->mtx);
00435
00436 if (local->scan_req)
00437 return -EBUSY;
00438
00439 if (!ieee80211_can_scan(local, sdata)) {
00440
00441 local->scan_req = req;
00442 local->scan_sdata = sdata;
00443 return 0;
00444 }
00445
00446 if (local->ops->hw_scan) {
00447 u8 *ies;
00448
00449 local->hw_scan_req = kmalloc(
00450 sizeof(*local->hw_scan_req) +
00451 req->n_channels * sizeof(req->channels[0]) +
00452 2 + IEEE80211_MAX_SSID_LEN + local->scan_ies_len +
00453 req->ie_len, GFP_KERNEL);
00454 if (!local->hw_scan_req)
00455 return -ENOMEM;
00456
00457 local->hw_scan_req->ssids = req->ssids;
00458 local->hw_scan_req->n_ssids = req->n_ssids;
00459 ies = (u8 *)local->hw_scan_req +
00460 sizeof(*local->hw_scan_req) +
00461 req->n_channels * sizeof(req->channels[0]);
00462 local->hw_scan_req->ie = ies;
00463
00464 local->hw_scan_band = 0;
00465
00466
00467
00468
00469
00470
00471
00472
00473 }
00474
00475 local->scan_req = req;
00476 local->scan_sdata = sdata;
00477
00478 if (local->ops->hw_scan) {
00479 __set_bit(SCAN_HW_SCANNING, &local->scanning);
00480 } else if ((req->n_channels == 1) &&
00481 (req->channels[0]->center_freq ==
00482 local->hw.conf.channel->center_freq)) {
00483
00484
00485
00486
00487 unsigned long next_delay;
00488
00489 __set_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning);
00490
00491 ieee80211_recalc_idle(local);
00492
00493
00494
00495 drv_sw_scan_start(local);
00496
00497 ieee80211_configure_filter(local);
00498
00499
00500 ieee80211_hw_config(local, 0);
00501
00502 if ((req->channels[0]->flags &
00503 IEEE80211_CHAN_PASSIVE_SCAN) ||
00504 !local->scan_req->n_ssids) {
00505 next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
00506 } else {
00507 ieee80211_scan_state_send_probe(local, &next_delay);
00508 next_delay = IEEE80211_CHANNEL_TIME;
00509 }
00510
00511
00512 ieee80211_queue_delayed_work(&local->hw, &local->scan_work,
00513 next_delay);
00514 return 0;
00515 } else {
00516
00517 __set_bit(SCAN_SW_SCANNING, &local->scanning);
00518 }
00519
00520 ieee80211_recalc_idle(local);
00521
00522 if (local->ops->hw_scan) {
00523 WARN_ON(!ieee80211_prep_hw_scan(local));
00524 rc = drv_hw_scan(local, sdata, local->hw_scan_req);
00525 } else
00526 rc = ieee80211_start_sw_scan(local);
00527
00528 if (rc) {
00529 kfree(local->hw_scan_req);
00530 local->hw_scan_req = NULL;
00531 local->scanning = 0;
00532
00533 ieee80211_recalc_idle(local);
00534
00535 local->scan_req = NULL;
00536 local->scan_sdata = NULL;
00537 }
00538
00539 return rc;
00540 }
00541
00542 static unsigned long
00543 ieee80211_scan_get_channel_time(struct ieee80211_channel *chan)
00544 {
00545
00546
00547
00548
00549 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
00550 return IEEE80211_PASSIVE_CHANNEL_TIME;
00551 return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME;
00552 }
00553
00554 static void ieee80211_scan_state_decision(struct ieee80211_local *local,
00555 unsigned long *next_delay)
00556 {
00557 bool associated = false;
00558 bool tx_empty = true;
00559 bool bad_latency;
00560 bool listen_int_exceeded;
00561 unsigned long min_beacon_int = 0;
00562 struct ieee80211_sub_if_data *sdata;
00563 struct ieee80211_channel *next_chan;
00564
00565
00566
00567
00568
00569
00570 mutex_lock(&local->iflist_mtx);
00571 list_for_each_entry(sdata, &local->interfaces, list) {
00572 if (!ieee80211_sdata_running(sdata))
00573 continue;
00574
00575 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
00576 if (sdata->u.mgd.associated) {
00577 associated = true;
00578
00579 if (sdata->vif.bss_conf.beacon_int <
00580 min_beacon_int || min_beacon_int == 0)
00581 min_beacon_int =
00582 sdata->vif.bss_conf.beacon_int;
00583
00584 if (!qdisc_all_tx_empty(sdata->dev)) {
00585 tx_empty = false;
00586 break;
00587 }
00588 }
00589 }
00590 }
00591 mutex_unlock(&local->iflist_mtx);
00592
00593 next_chan = local->scan_req->channels[local->scan_channel_idx];
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 bad_latency = time_after(jiffies +
00612 ieee80211_scan_get_channel_time(next_chan),
00613 local->leave_oper_channel_time +
00614 usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY)));
00615
00616 listen_int_exceeded = time_after(jiffies +
00617 ieee80211_scan_get_channel_time(next_chan),
00618 local->leave_oper_channel_time +
00619 usecs_to_jiffies(min_beacon_int * 1024) *
00620 local->hw.conf.listen_interval);
00621
00622 if (associated && (!tx_empty || bad_latency || listen_int_exceeded))
00623 local->next_scan_state = SCAN_SUSPEND;
00624 else
00625 local->next_scan_state = SCAN_SET_CHANNEL;
00626
00627 *next_delay = 0;
00628 }
00629
00630 static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
00631 unsigned long *next_delay)
00632 {
00633 int skip;
00634 struct ieee80211_channel *chan;
00635
00636 skip = 0;
00637 chan = local->scan_req->channels[local->scan_channel_idx];
00638
00639 local->scan_channel = chan;
00640
00641 if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
00642 skip = 1;
00643
00644
00645 local->scan_channel_idx++;
00646
00647 if (skip) {
00648
00649 local->next_scan_state = SCAN_DECISION;
00650 return;
00651 }
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
00664 !local->scan_req->n_ssids) {
00665 *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
00666 local->next_scan_state = SCAN_DECISION;
00667 return;
00668 }
00669
00670
00671 *next_delay = IEEE80211_PROBE_DELAY;
00672 local->next_scan_state = SCAN_SEND_PROBE;
00673 }
00674
00675 static void ieee80211_scan_state_suspend(struct ieee80211_local *local,
00676 unsigned long *next_delay)
00677 {
00678
00679 local->scan_channel = NULL;
00680 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
00681
00682
00683
00684
00685
00686
00687 ieee80211_offchannel_return(local, false);
00688
00689 *next_delay = HZ / 5;
00690
00691 local->next_scan_state = SCAN_RESUME;
00692 }
00693
00694 static void ieee80211_scan_state_resume(struct ieee80211_local *local,
00695 unsigned long *next_delay)
00696 {
00697
00698 ieee80211_offchannel_stop_vifs(local, false);
00699
00700 if (local->ops->flush) {
00701 drv_flush(local, false);
00702 *next_delay = 0;
00703 } else
00704 *next_delay = HZ / 10;
00705
00706
00707 local->leave_oper_channel_time = jiffies;
00708
00709
00710 local->next_scan_state = SCAN_SET_CHANNEL;
00711 }
00712
00713 void ieee80211_scan_work(struct work_struct *work)
00714 {
00715 struct ieee80211_local *local =
00716 container_of(work, struct ieee80211_local, scan_work.work);
00717 struct ieee80211_sub_if_data *sdata;
00718 unsigned long next_delay = 0;
00719 bool aborted, hw_scan;
00720
00721 mutex_lock(&local->mtx);
00722
00723 sdata = local->scan_sdata;
00724
00725
00726 if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) {
00727 aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);
00728 goto out_complete;
00729 }
00730
00731 if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) {
00732 aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);
00733 goto out_complete;
00734 }
00735
00736 if (!sdata || !local->scan_req)
00737 goto out;
00738
00739 if (local->scan_req && !local->scanning) {
00740 struct cfg80211_scan_request *req = local->scan_req;
00741 int rc;
00742
00743 local->scan_req = NULL;
00744 local->scan_sdata = NULL;
00745
00746 rc = __ieee80211_start_scan(sdata, req);
00747 if (rc) {
00748
00749 local->scan_req = req;
00750 aborted = true;
00751 goto out_complete;
00752 } else
00753 goto out;
00754 }
00755
00756
00757
00758
00759 if (!ieee80211_sdata_running(sdata)) {
00760 aborted = true;
00761 goto out_complete;
00762 }
00763
00764
00765
00766
00767
00768 do {
00769 if (!ieee80211_sdata_running(sdata)) {
00770 aborted = true;
00771 goto out_complete;
00772 }
00773
00774 switch (local->next_scan_state) {
00775 case SCAN_DECISION:
00776
00777 if (local->scan_channel_idx >= local->scan_req->n_channels) {
00778 aborted = false;
00779 goto out_complete;
00780 }
00781 ieee80211_scan_state_decision(local, &next_delay);
00782 break;
00783 case SCAN_SET_CHANNEL:
00784 ieee80211_scan_state_set_channel(local, &next_delay);
00785 break;
00786 case SCAN_SEND_PROBE:
00787 ieee80211_scan_state_send_probe(local, &next_delay);
00788 break;
00789 case SCAN_SUSPEND:
00790 ieee80211_scan_state_suspend(local, &next_delay);
00791 break;
00792 case SCAN_RESUME:
00793 ieee80211_scan_state_resume(local, &next_delay);
00794 break;
00795 }
00796 } while (next_delay == 0);
00797
00798 ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay);
00799 goto out;
00800
00801 out_complete:
00802 hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
00803 __ieee80211_scan_completed(&local->hw, aborted, hw_scan);
00804 out:
00805 mutex_unlock(&local->mtx);
00806 }
00807
00808 int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
00809 struct cfg80211_scan_request *req)
00810 {
00811 int res;
00812
00813 mutex_lock(&sdata->local->mtx);
00814 res = __ieee80211_start_scan(sdata, req);
00815 mutex_unlock(&sdata->local->mtx);
00816
00817 return res;
00818 }
00819
00820 int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
00821 const u8 *ssid, u8 ssid_len,
00822 struct ieee80211_channel *chan)
00823 {
00824 struct ieee80211_local *local = sdata->local;
00825 int ret = -EBUSY;
00826 enum ieee80211_band band;
00827
00828 mutex_lock(&local->mtx);
00829
00830
00831 if (local->scan_req)
00832 goto unlock;
00833
00834
00835 if (!chan) {
00836 int i, nchan = 0;
00837
00838 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
00839 if (!local->hw.wiphy->bands[band])
00840 continue;
00841 for (i = 0;
00842 i < local->hw.wiphy->bands[band]->n_channels;
00843 i++) {
00844 local->int_scan_req->channels[nchan] =
00845 &local->hw.wiphy->bands[band]->channels[i];
00846 nchan++;
00847 }
00848 }
00849
00850 local->int_scan_req->n_channels = nchan;
00851 } else {
00852 local->int_scan_req->channels[0] = chan;
00853 local->int_scan_req->n_channels = 1;
00854 }
00855
00856 local->int_scan_req->ssids = &local->scan_ssid;
00857 local->int_scan_req->n_ssids = 1;
00858 memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
00859 local->int_scan_req->ssids[0].ssid_len = ssid_len;
00860
00861 ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req);
00862 unlock:
00863 mutex_unlock(&local->mtx);
00864 return ret;
00865 }
00866
00867
00868
00869
00870 void ieee80211_scan_cancel(struct ieee80211_local *local)
00871 {
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890 mutex_lock(&local->mtx);
00891 if (!local->scan_req)
00892 goto out;
00893
00894 if (test_bit(SCAN_HW_SCANNING, &local->scanning)) {
00895 if (local->ops->cancel_hw_scan)
00896 drv_cancel_hw_scan(local, local->scan_sdata);
00897 goto out;
00898 }
00899
00900
00901
00902
00903
00904
00905 cancel_delayed_work(&local->scan_work);
00906
00907 __ieee80211_scan_completed(&local->hw, true, false);
00908 out:
00909 mutex_unlock(&local->mtx);
00910 }
00911
00912 int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
00913 struct cfg80211_sched_scan_request *req)
00914 {
00915 struct ieee80211_local *local = sdata->local;
00916 int ret, i;
00917
00918 mutex_lock(&sdata->local->mtx);
00919
00920 if (local->sched_scanning) {
00921 ret = -EBUSY;
00922 goto out;
00923 }
00924
00925 if (!local->ops->sched_scan_start) {
00926 ret = -ENOTSUPP;
00927 goto out;
00928 }
00929
00930 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
00931 local->sched_scan_ies.ie[i] = kzalloc(2 +
00932 IEEE80211_MAX_SSID_LEN +
00933 local->scan_ies_len +
00934 req->ie_len,
00935 GFP_KERNEL);
00936 if (!local->sched_scan_ies.ie[i]) {
00937 ret = -ENOMEM;
00938 goto out_free;
00939 }
00940
00941 local->sched_scan_ies.len[i] =
00942 ieee80211_build_preq_ies(local,
00943 local->sched_scan_ies.ie[i],
00944 req->ie, req->ie_len, i,
00945 (u32) -1, 0);
00946 }
00947
00948 ret = drv_sched_scan_start(local, sdata, req,
00949 &local->sched_scan_ies);
00950 if (ret == 0) {
00951 local->sched_scanning = true;
00952 goto out;
00953 }
00954
00955 out_free:
00956 while (i > 0)
00957 kfree(local->sched_scan_ies.ie[--i]);
00958 out:
00959 mutex_unlock(&sdata->local->mtx);
00960 return ret;
00961 }
00962
00963 int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
00964 {
00965 struct ieee80211_local *local = sdata->local;
00966 int ret = 0, i;
00967
00968 mutex_lock(&sdata->local->mtx);
00969
00970 if (!local->ops->sched_scan_stop) {
00971 ret = -ENOTSUPP;
00972 goto out;
00973 }
00974
00975 if (local->sched_scanning) {
00976 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
00977 kfree(local->sched_scan_ies.ie[i]);
00978
00979 drv_sched_scan_stop(local, sdata);
00980 local->sched_scanning = false;
00981 }
00982 out:
00983 mutex_unlock(&sdata->local->mtx);
00984
00985 return ret;
00986 }
00987
00988 void ieee80211_sched_scan_results(struct ieee80211_hw *hw)
00989 {
00990 struct ieee80211_local *local = hw_to_local(hw);
00991
00992 trace_api_sched_scan_results(local);
00993
00994 cfg80211_sched_scan_results(hw->wiphy);
00995 }
00996 EXPORT_SYMBOL(ieee80211_sched_scan_results);
00997
00998 void ieee80211_sched_scan_stopped_work(struct work_struct *work)
00999 {
01000 struct ieee80211_local *local =
01001 container_of(work, struct ieee80211_local,
01002 sched_scan_stopped_work);
01003 int i;
01004
01005 mutex_lock(&local->mtx);
01006
01007 if (!local->sched_scanning) {
01008 mutex_unlock(&local->mtx);
01009 return;
01010 }
01011
01012 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
01013 kfree(local->sched_scan_ies.ie[i]);
01014
01015 local->sched_scanning = false;
01016
01017 mutex_unlock(&local->mtx);
01018
01019 cfg80211_sched_scan_stopped(local->hw.wiphy);
01020 }
01021
01022 void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw)
01023 {
01024 struct ieee80211_local *local = hw_to_local(hw);
01025
01026 trace_api_sched_scan_stopped(local);
01027
01028 ieee80211_queue_work(&local->hw, &local->sched_scan_stopped_work);
01029 }
01030 EXPORT_SYMBOL(ieee80211_sched_scan_stopped);