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