scan.c (1d76250bd34af86c6498fc51e50cab3bfbbeceaa) scan.c (7947d3e075cde1a18e538f2dafbc850aa356ff79)
1/*
2 * Scanning implementation
3 *
4 * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
5 * Copyright 2004, Instant802 Networks, Inc.
6 * Copyright 2005, Devicescape Software, Inc.
7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
9 * Copyright 2013-2015 Intel Mobile Communications GmbH
1/*
2 * Scanning implementation
3 *
4 * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
5 * Copyright 2004, Instant802 Networks, Inc.
6 * Copyright 2005, Devicescape Software, Inc.
7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
9 * Copyright 2013-2015 Intel Mobile Communications GmbH
10 * Copyright 2016 Intel Deutschland GmbH
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include <linux/if_arp.h>
17#include <linux/etherdevice.h>

--- 47 unchanged lines hidden (view full) ---

65 bool beacon = ieee80211_is_beacon(mgmt->frame_control);
66 struct cfg80211_bss *cbss;
67 struct ieee80211_bss *bss;
68 int clen, srlen;
69 struct cfg80211_inform_bss bss_meta = {
70 .boottime_ns = rx_status->boottime_ns,
71 };
72 bool signal_valid;
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 */
16
17#include <linux/if_arp.h>
18#include <linux/etherdevice.h>

--- 47 unchanged lines hidden (view full) ---

66 bool beacon = ieee80211_is_beacon(mgmt->frame_control);
67 struct cfg80211_bss *cbss;
68 struct ieee80211_bss *bss;
69 int clen, srlen;
70 struct cfg80211_inform_bss bss_meta = {
71 .boottime_ns = rx_status->boottime_ns,
72 };
73 bool signal_valid;
74 struct ieee80211_sub_if_data *scan_sdata;
73
74 if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
75 bss_meta.signal = rx_status->signal * 100;
76 else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC))
77 bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal;
78
79 bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_20;
80 if (rx_status->flag & RX_FLAG_5MHZ)
81 bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_5;
82 if (rx_status->flag & RX_FLAG_10MHZ)
83 bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_10;
84
85 bss_meta.chan = channel;
75
76 if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
77 bss_meta.signal = rx_status->signal * 100;
78 else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC))
79 bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal;
80
81 bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_20;
82 if (rx_status->flag & RX_FLAG_5MHZ)
83 bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_5;
84 if (rx_status->flag & RX_FLAG_10MHZ)
85 bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_10;
86
87 bss_meta.chan = channel;
88
89 rcu_read_lock();
90 scan_sdata = rcu_dereference(local->scan_sdata);
91 if (scan_sdata && scan_sdata->vif.type == NL80211_IFTYPE_STATION &&
92 scan_sdata->vif.bss_conf.assoc &&
93 ieee80211_have_rx_timestamp(rx_status)) {
94 bss_meta.parent_tsf =
95 ieee80211_calculate_rx_timestamp(local, rx_status,
96 len + FCS_LEN, 24);
97 ether_addr_copy(bss_meta.parent_bssid,
98 scan_sdata->vif.bss_conf.bssid);
99 }
100 rcu_read_unlock();
101
86 cbss = cfg80211_inform_bss_frame_data(local->hw.wiphy, &bss_meta,
87 mgmt, len, GFP_ATOMIC);
88 if (!cbss)
89 return NULL;
90 /* In case the signal is invalid update the status */
91 signal_valid = abs(channel->center_freq - cbss->channel->center_freq)
92 <= local->hw.wiphy->max_adj_channel_rssi_comp;
93 if (!signal_valid)

--- 246 unchanged lines hidden (view full) ---

340
341 rc = drv_hw_scan(local,
342 rcu_dereference_protected(local->scan_sdata,
343 lockdep_is_held(&local->mtx)),
344 local->hw_scan_req);
345
346 if (rc == 0)
347 return;
102 cbss = cfg80211_inform_bss_frame_data(local->hw.wiphy, &bss_meta,
103 mgmt, len, GFP_ATOMIC);
104 if (!cbss)
105 return NULL;
106 /* In case the signal is invalid update the status */
107 signal_valid = abs(channel->center_freq - cbss->channel->center_freq)
108 <= local->hw.wiphy->max_adj_channel_rssi_comp;
109 if (!signal_valid)

--- 246 unchanged lines hidden (view full) ---

356
357 rc = drv_hw_scan(local,
358 rcu_dereference_protected(local->scan_sdata,
359 lockdep_is_held(&local->mtx)),
360 local->hw_scan_req);
361
362 if (rc == 0)
363 return;
364
365 /* HW scan failed and is going to be reported as done, so clear
366 * old scan info.
367 */
368 memset(&local->scan_info, 0, sizeof(local->scan_info));
348 }
349
350 kfree(local->hw_scan_req);
351 local->hw_scan_req = NULL;
352
353 scan_req = rcu_dereference_protected(local->scan_req,
354 lockdep_is_held(&local->mtx));
355
356 if (scan_req != local->int_scan_req) {
369 }
370
371 kfree(local->hw_scan_req);
372 local->hw_scan_req = NULL;
373
374 scan_req = rcu_dereference_protected(local->scan_req,
375 lockdep_is_held(&local->mtx));
376
377 if (scan_req != local->int_scan_req) {
357 struct cfg80211_scan_info info = {
358 .aborted = aborted,
359 };
360
361 cfg80211_scan_done(scan_req, &info);
378 local->scan_info.aborted = aborted;
379 cfg80211_scan_done(scan_req, &local->scan_info);
362 }
363 RCU_INIT_POINTER(local->scan_req, NULL);
364
365 scan_sdata = rcu_dereference_protected(local->scan_sdata,
366 lockdep_is_held(&local->mtx));
367 RCU_INIT_POINTER(local->scan_sdata, NULL);
368
369 local->scanning = 0;

--- 21 unchanged lines hidden (view full) ---

391 if (ieee80211_sdata_running(sdata))
392 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
393 }
394
395 if (was_scanning)
396 ieee80211_start_next_roc(local);
397}
398
380 }
381 RCU_INIT_POINTER(local->scan_req, NULL);
382
383 scan_sdata = rcu_dereference_protected(local->scan_sdata,
384 lockdep_is_held(&local->mtx));
385 RCU_INIT_POINTER(local->scan_sdata, NULL);
386
387 local->scanning = 0;

--- 21 unchanged lines hidden (view full) ---

409 if (ieee80211_sdata_running(sdata))
410 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
411 }
412
413 if (was_scanning)
414 ieee80211_start_next_roc(local);
415}
416
399void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
417void ieee80211_scan_completed(struct ieee80211_hw *hw,
418 struct cfg80211_scan_info *info)
400{
401 struct ieee80211_local *local = hw_to_local(hw);
402
419{
420 struct ieee80211_local *local = hw_to_local(hw);
421
403 trace_api_scan_completed(local, aborted);
422 trace_api_scan_completed(local, info);
404
405 set_bit(SCAN_COMPLETED, &local->scanning);
423
424 set_bit(SCAN_COMPLETED, &local->scanning);
406 if (aborted)
425 if (info->aborted)
407 set_bit(SCAN_ABORTED, &local->scanning);
426 set_bit(SCAN_ABORTED, &local->scanning);
427
428 memcpy(&local->scan_info, info, sizeof(*info));
429
408 ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
409}
410EXPORT_SYMBOL(ieee80211_scan_completed);
411
412static int ieee80211_start_sw_scan(struct ieee80211_local *local,
413 struct ieee80211_sub_if_data *sdata)
414{
415 /* Software scan is not supported in multi-channel cases */

--- 150 unchanged lines hidden (view full) ---

566 local->hw_scan_req->req.ssids = req->ssids;
567 local->hw_scan_req->req.n_ssids = req->n_ssids;
568 ies = (u8 *)local->hw_scan_req +
569 sizeof(*local->hw_scan_req) +
570 req->n_channels * sizeof(req->channels[0]);
571 local->hw_scan_req->req.ie = ies;
572 local->hw_scan_req->req.flags = req->flags;
573 eth_broadcast_addr(local->hw_scan_req->req.bssid);
430 ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
431}
432EXPORT_SYMBOL(ieee80211_scan_completed);
433
434static int ieee80211_start_sw_scan(struct ieee80211_local *local,
435 struct ieee80211_sub_if_data *sdata)
436{
437 /* Software scan is not supported in multi-channel cases */

--- 150 unchanged lines hidden (view full) ---

588 local->hw_scan_req->req.ssids = req->ssids;
589 local->hw_scan_req->req.n_ssids = req->n_ssids;
590 ies = (u8 *)local->hw_scan_req +
591 sizeof(*local->hw_scan_req) +
592 req->n_channels * sizeof(req->channels[0]);
593 local->hw_scan_req->req.ie = ies;
594 local->hw_scan_req->req.flags = req->flags;
595 eth_broadcast_addr(local->hw_scan_req->req.bssid);
596 local->hw_scan_req->req.duration = req->duration;
597 local->hw_scan_req->req.duration_mandatory =
598 req->duration_mandatory;
574
575 local->hw_scan_band = 0;
576
577 /*
578 * After allocating local->hw_scan_req, we must
579 * go through until ieee80211_prep_hw_scan(), so
580 * anything that might be changed here and leave
581 * this function early must not go after this

--- 491 unchanged lines hidden (view full) ---

1073
1074 /*
1075 * If the work is currently running, it must be blocked on
1076 * the mutex, but we'll set scan_sdata = NULL and it'll
1077 * simply exit once it acquires the mutex.
1078 */
1079 cancel_delayed_work(&local->scan_work);
1080 /* and clean up */
599
600 local->hw_scan_band = 0;
601
602 /*
603 * After allocating local->hw_scan_req, we must
604 * go through until ieee80211_prep_hw_scan(), so
605 * anything that might be changed here and leave
606 * this function early must not go after this

--- 491 unchanged lines hidden (view full) ---

1098
1099 /*
1100 * If the work is currently running, it must be blocked on
1101 * the mutex, but we'll set scan_sdata = NULL and it'll
1102 * simply exit once it acquires the mutex.
1103 */
1104 cancel_delayed_work(&local->scan_work);
1105 /* and clean up */
1106 memset(&local->scan_info, 0, sizeof(local->scan_info));
1081 __ieee80211_scan_completed(&local->hw, true);
1082out:
1083 mutex_unlock(&local->mtx);
1084}
1085
1086int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
1087 struct cfg80211_sched_scan_request *req)
1088{

--- 157 unchanged lines hidden ---
1107 __ieee80211_scan_completed(&local->hw, true);
1108out:
1109 mutex_unlock(&local->mtx);
1110}
1111
1112int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
1113 struct cfg80211_sched_scan_request *req)
1114{

--- 157 unchanged lines hidden ---