diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/scan.c | 42 |
2 files changed, 35 insertions, 8 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 54edfb6fc1d1..f56d342c31b8 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1250,6 +1250,7 @@ struct ieee80211_local { | |||
1250 | int scan_channel_idx; | 1250 | int scan_channel_idx; |
1251 | int scan_ies_len; | 1251 | int scan_ies_len; |
1252 | int hw_scan_ies_bufsize; | 1252 | int hw_scan_ies_bufsize; |
1253 | struct cfg80211_scan_info scan_info; | ||
1253 | 1254 | ||
1254 | struct work_struct sched_scan_stopped_work; | 1255 | struct work_struct sched_scan_stopped_work; |
1255 | struct ieee80211_sub_if_data __rcu *sched_scan_sdata; | 1256 | struct ieee80211_sub_if_data __rcu *sched_scan_sdata; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 4ec1c52a1549..8d4a9cd8a39a 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | 8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> |
9 | * Copyright 2013-2015 Intel Mobile Communications GmbH | 9 | * Copyright 2013-2015 Intel Mobile Communications GmbH |
10 | * Copyright 2016 Intel Deutschland GmbH | ||
10 | * | 11 | * |
11 | * This program is free software; you can redistribute it and/or modify | 12 | * 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 | * it under the terms of the GNU General Public License version 2 as |
@@ -70,6 +71,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
70 | .boottime_ns = rx_status->boottime_ns, | 71 | .boottime_ns = rx_status->boottime_ns, |
71 | }; | 72 | }; |
72 | bool signal_valid; | 73 | bool signal_valid; |
74 | struct ieee80211_sub_if_data *scan_sdata; | ||
73 | 75 | ||
74 | if (ieee80211_hw_check(&local->hw, SIGNAL_DBM)) | 76 | if (ieee80211_hw_check(&local->hw, SIGNAL_DBM)) |
75 | bss_meta.signal = rx_status->signal * 100; | 77 | bss_meta.signal = rx_status->signal * 100; |
@@ -83,6 +85,20 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
83 | bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_10; | 85 | bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_10; |
84 | 86 | ||
85 | bss_meta.chan = channel; | 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, | 102 | cbss = cfg80211_inform_bss_frame_data(local->hw.wiphy, &bss_meta, |
87 | mgmt, len, GFP_ATOMIC); | 103 | mgmt, len, GFP_ATOMIC); |
88 | if (!cbss) | 104 | if (!cbss) |
@@ -345,6 +361,11 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
345 | 361 | ||
346 | if (rc == 0) | 362 | if (rc == 0) |
347 | return; | 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 | } | 369 | } |
349 | 370 | ||
350 | kfree(local->hw_scan_req); | 371 | kfree(local->hw_scan_req); |
@@ -354,11 +375,8 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
354 | lockdep_is_held(&local->mtx)); | 375 | lockdep_is_held(&local->mtx)); |
355 | 376 | ||
356 | if (scan_req != local->int_scan_req) { | 377 | if (scan_req != local->int_scan_req) { |
357 | struct cfg80211_scan_info info = { | 378 | local->scan_info.aborted = aborted; |
358 | .aborted = aborted, | 379 | cfg80211_scan_done(scan_req, &local->scan_info); |
359 | }; | ||
360 | |||
361 | cfg80211_scan_done(scan_req, &info); | ||
362 | } | 380 | } |
363 | RCU_INIT_POINTER(local->scan_req, NULL); | 381 | RCU_INIT_POINTER(local->scan_req, NULL); |
364 | 382 | ||
@@ -396,15 +414,19 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
396 | ieee80211_start_next_roc(local); | 414 | ieee80211_start_next_roc(local); |
397 | } | 415 | } |
398 | 416 | ||
399 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | 417 | void ieee80211_scan_completed(struct ieee80211_hw *hw, |
418 | struct cfg80211_scan_info *info) | ||
400 | { | 419 | { |
401 | struct ieee80211_local *local = hw_to_local(hw); | 420 | struct ieee80211_local *local = hw_to_local(hw); |
402 | 421 | ||
403 | trace_api_scan_completed(local, aborted); | 422 | trace_api_scan_completed(local, info); |
404 | 423 | ||
405 | set_bit(SCAN_COMPLETED, &local->scanning); | 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); | 430 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0); |
409 | } | 431 | } |
410 | EXPORT_SYMBOL(ieee80211_scan_completed); | 432 | EXPORT_SYMBOL(ieee80211_scan_completed); |
@@ -571,6 +593,9 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
571 | local->hw_scan_req->req.ie = ies; | 593 | local->hw_scan_req->req.ie = ies; |
572 | local->hw_scan_req->req.flags = req->flags; | 594 | local->hw_scan_req->req.flags = req->flags; |
573 | eth_broadcast_addr(local->hw_scan_req->req.bssid); | 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 | 599 | ||
575 | local->hw_scan_band = 0; | 600 | local->hw_scan_band = 0; |
576 | 601 | ||
@@ -1078,6 +1103,7 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) | |||
1078 | */ | 1103 | */ |
1079 | cancel_delayed_work(&local->scan_work); | 1104 | cancel_delayed_work(&local->scan_work); |
1080 | /* and clean up */ | 1105 | /* and clean up */ |
1106 | memset(&local->scan_info, 0, sizeof(local->scan_info)); | ||
1081 | __ieee80211_scan_completed(&local->hw, true); | 1107 | __ieee80211_scan_completed(&local->hw, true); |
1082 | out: | 1108 | out: |
1083 | mutex_unlock(&local->mtx); | 1109 | mutex_unlock(&local->mtx); |