diff options
author | Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de> | 2013-07-08 10:55:56 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-07-16 02:58:09 -0400 |
commit | 7ca15a0ae865067aac8d36e27e0acbe4a8f1e70a (patch) | |
tree | 0e1fb6ea9187626b3f9d2f806f26942e571d93c6 /net/mac80211 | |
parent | 0430c883470d0c9a23661ea9f02c56b1d91cf93c (diff) |
mac80211: allow scanning for 5/10 MHz channels in IBSS
Use a chandef instead of just the channel for scanning, and enable
5/10 Mhz scanning for IBSS mode. Also reporting is changed to the new
inform_bss functions.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/ibss.c | 16 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 5 | ||||
-rw-r--r-- | net/mac80211/main.c | 13 | ||||
-rw-r--r-- | net/mac80211/scan.c | 45 |
4 files changed, 56 insertions, 23 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 299603e4939f..8fa1c27bdfe3 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -51,6 +51,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
51 | u32 bss_change, rate_flags, rates = 0, rates_added = 0; | 51 | u32 bss_change, rate_flags, rates = 0, rates_added = 0; |
52 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | 52 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; |
53 | struct cfg80211_chan_def chandef; | 53 | struct cfg80211_chan_def chandef; |
54 | enum nl80211_bss_scan_width scan_width; | ||
54 | struct beacon_data *presp; | 55 | struct beacon_data *presp; |
55 | int frame_len; | 56 | int frame_len; |
56 | int shift; | 57 | int shift; |
@@ -271,8 +272,10 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
271 | mod_timer(&ifibss->timer, | 272 | mod_timer(&ifibss->timer, |
272 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); | 273 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); |
273 | 274 | ||
274 | bss = cfg80211_inform_bss_frame(local->hw.wiphy, chan, | 275 | scan_width = cfg80211_chandef_to_scan_width(&chandef); |
275 | mgmt, presp->head_len, 0, GFP_KERNEL); | 276 | bss = cfg80211_inform_bss_width_frame(local->hw.wiphy, chan, |
277 | scan_width, mgmt, | ||
278 | presp->head_len, 0, GFP_KERNEL); | ||
276 | cfg80211_put_bss(local->hw.wiphy, bss); | 279 | cfg80211_put_bss(local->hw.wiphy, bss); |
277 | netif_carrier_on(sdata->dev); | 280 | netif_carrier_on(sdata->dev); |
278 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); | 281 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); |
@@ -726,6 +729,7 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) | |||
726 | static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | 729 | static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) |
727 | { | 730 | { |
728 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 731 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
732 | enum nl80211_bss_scan_width scan_width; | ||
729 | 733 | ||
730 | sdata_assert_lock(sdata); | 734 | sdata_assert_lock(sdata); |
731 | 735 | ||
@@ -747,8 +751,9 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | |||
747 | sdata_info(sdata, | 751 | sdata_info(sdata, |
748 | "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); | 752 | "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); |
749 | 753 | ||
754 | scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef); | ||
750 | ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, | 755 | ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, |
751 | NULL); | 756 | NULL, scan_width); |
752 | } | 757 | } |
753 | 758 | ||
754 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | 759 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) |
@@ -798,6 +803,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
798 | struct cfg80211_bss *cbss; | 803 | struct cfg80211_bss *cbss; |
799 | struct ieee80211_channel *chan = NULL; | 804 | struct ieee80211_channel *chan = NULL; |
800 | const u8 *bssid = NULL; | 805 | const u8 *bssid = NULL; |
806 | enum nl80211_bss_scan_width scan_width; | ||
801 | int active_ibss; | 807 | int active_ibss; |
802 | u16 capability; | 808 | u16 capability; |
803 | 809 | ||
@@ -846,8 +852,10 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
846 | IEEE80211_SCAN_INTERVAL)) { | 852 | IEEE80211_SCAN_INTERVAL)) { |
847 | sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); | 853 | sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); |
848 | 854 | ||
855 | scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef); | ||
849 | ieee80211_request_ibss_scan(sdata, ifibss->ssid, | 856 | ieee80211_request_ibss_scan(sdata, ifibss->ssid, |
850 | ifibss->ssid_len, chan); | 857 | ifibss->ssid_len, chan, |
858 | scan_width); | ||
851 | } else { | 859 | } else { |
852 | int interval = IEEE80211_SCAN_INTERVAL; | 860 | int interval = IEEE80211_SCAN_INTERVAL; |
853 | 861 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6596da66bfaf..23a191b03bbf 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1057,7 +1057,7 @@ struct ieee80211_local { | |||
1057 | struct cfg80211_ssid scan_ssid; | 1057 | struct cfg80211_ssid scan_ssid; |
1058 | struct cfg80211_scan_request *int_scan_req; | 1058 | struct cfg80211_scan_request *int_scan_req; |
1059 | struct cfg80211_scan_request *scan_req, *hw_scan_req; | 1059 | struct cfg80211_scan_request *scan_req, *hw_scan_req; |
1060 | struct ieee80211_channel *scan_channel; | 1060 | struct cfg80211_chan_def scan_chandef; |
1061 | enum ieee80211_band hw_scan_band; | 1061 | enum ieee80211_band hw_scan_band; |
1062 | int scan_channel_idx; | 1062 | int scan_channel_idx; |
1063 | int scan_ies_len; | 1063 | int scan_ies_len; |
@@ -1337,7 +1337,8 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1337 | void ieee80211_scan_work(struct work_struct *work); | 1337 | void ieee80211_scan_work(struct work_struct *work); |
1338 | int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, | 1338 | int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, |
1339 | const u8 *ssid, u8 ssid_len, | 1339 | const u8 *ssid, u8 ssid_len, |
1340 | struct ieee80211_channel *chan); | 1340 | struct ieee80211_channel *chan, |
1341 | enum nl80211_bss_scan_width scan_width); | ||
1341 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 1342 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
1342 | struct cfg80211_scan_request *req); | 1343 | struct cfg80211_scan_request *req); |
1343 | void ieee80211_scan_cancel(struct ieee80211_local *local); | 1344 | void ieee80211_scan_cancel(struct ieee80211_local *local); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6da98c77496b..25eb35b01938 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -102,17 +102,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) | |||
102 | 102 | ||
103 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | 103 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
104 | 104 | ||
105 | if (local->scan_channel) { | 105 | if (local->scan_chandef.chan) { |
106 | chandef.chan = local->scan_channel; | 106 | chandef = local->scan_chandef; |
107 | /* If scanning on oper channel, use whatever channel-type | ||
108 | * is currently in use. | ||
109 | */ | ||
110 | if (chandef.chan == local->_oper_chandef.chan) { | ||
111 | chandef = local->_oper_chandef; | ||
112 | } else { | ||
113 | chandef.width = NL80211_CHAN_WIDTH_20_NOHT; | ||
114 | chandef.center_freq1 = chandef.chan->center_freq; | ||
115 | } | ||
116 | } else if (local->tmp_channel) { | 107 | } else if (local->tmp_channel) { |
117 | chandef.chan = local->tmp_channel; | 108 | chandef.chan = local->tmp_channel; |
118 | chandef.width = NL80211_CHAN_WIDTH_20_NOHT; | 109 | chandef.width = NL80211_CHAN_WIDTH_20_NOHT; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 819d0956eb3b..08afe74b98f4 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -66,6 +66,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
66 | struct cfg80211_bss *cbss; | 66 | struct cfg80211_bss *cbss; |
67 | struct ieee80211_bss *bss; | 67 | struct ieee80211_bss *bss; |
68 | int clen, srlen; | 68 | int clen, srlen; |
69 | enum nl80211_bss_scan_width scan_width; | ||
69 | s32 signal = 0; | 70 | s32 signal = 0; |
70 | 71 | ||
71 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 72 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
@@ -73,8 +74,15 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
73 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) | 74 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) |
74 | signal = (rx_status->signal * 100) / local->hw.max_signal; | 75 | signal = (rx_status->signal * 100) / local->hw.max_signal; |
75 | 76 | ||
76 | cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel, | 77 | scan_width = NL80211_BSS_CHAN_WIDTH_20; |
77 | mgmt, len, signal, GFP_ATOMIC); | 78 | if (rx_status->flag & RX_FLAG_5MHZ) |
79 | scan_width = NL80211_BSS_CHAN_WIDTH_5; | ||
80 | if (rx_status->flag & RX_FLAG_10MHZ) | ||
81 | scan_width = NL80211_BSS_CHAN_WIDTH_10; | ||
82 | |||
83 | cbss = cfg80211_inform_bss_width_frame(local->hw.wiphy, channel, | ||
84 | scan_width, mgmt, len, signal, | ||
85 | GFP_ATOMIC); | ||
78 | if (!cbss) | 86 | if (!cbss) |
79 | return NULL; | 87 | return NULL; |
80 | 88 | ||
@@ -300,7 +308,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | |||
300 | rcu_assign_pointer(local->scan_sdata, NULL); | 308 | rcu_assign_pointer(local->scan_sdata, NULL); |
301 | 309 | ||
302 | local->scanning = 0; | 310 | local->scanning = 0; |
303 | local->scan_channel = NULL; | 311 | local->scan_chandef.chan = NULL; |
304 | 312 | ||
305 | /* Set power back to normal operating levels. */ | 313 | /* Set power back to normal operating levels. */ |
306 | ieee80211_hw_config(local, 0); | 314 | ieee80211_hw_config(local, 0); |
@@ -635,11 +643,34 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | |||
635 | { | 643 | { |
636 | int skip; | 644 | int skip; |
637 | struct ieee80211_channel *chan; | 645 | struct ieee80211_channel *chan; |
646 | enum nl80211_bss_scan_width oper_scan_width; | ||
638 | 647 | ||
639 | skip = 0; | 648 | skip = 0; |
640 | chan = local->scan_req->channels[local->scan_channel_idx]; | 649 | chan = local->scan_req->channels[local->scan_channel_idx]; |
641 | 650 | ||
642 | local->scan_channel = chan; | 651 | local->scan_chandef.chan = chan; |
652 | local->scan_chandef.center_freq1 = chan->center_freq; | ||
653 | local->scan_chandef.center_freq2 = 0; | ||
654 | switch (local->scan_req->scan_width) { | ||
655 | case NL80211_BSS_CHAN_WIDTH_5: | ||
656 | local->scan_chandef.width = NL80211_CHAN_WIDTH_5; | ||
657 | break; | ||
658 | case NL80211_BSS_CHAN_WIDTH_10: | ||
659 | local->scan_chandef.width = NL80211_CHAN_WIDTH_10; | ||
660 | break; | ||
661 | case NL80211_BSS_CHAN_WIDTH_20: | ||
662 | /* If scanning on oper channel, use whatever channel-type | ||
663 | * is currently in use. | ||
664 | */ | ||
665 | oper_scan_width = cfg80211_chandef_to_scan_width( | ||
666 | &local->_oper_chandef); | ||
667 | if (chan == local->_oper_chandef.chan && | ||
668 | oper_scan_width == local->scan_req->scan_width) | ||
669 | local->scan_chandef = local->_oper_chandef; | ||
670 | else | ||
671 | local->scan_chandef.width = NL80211_CHAN_WIDTH_20_NOHT; | ||
672 | break; | ||
673 | } | ||
643 | 674 | ||
644 | if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL)) | 675 | if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL)) |
645 | skip = 1; | 676 | skip = 1; |
@@ -679,7 +710,7 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local, | |||
679 | unsigned long *next_delay) | 710 | unsigned long *next_delay) |
680 | { | 711 | { |
681 | /* switch back to the operating channel */ | 712 | /* switch back to the operating channel */ |
682 | local->scan_channel = NULL; | 713 | local->scan_chandef.chan = NULL; |
683 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 714 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
684 | 715 | ||
685 | /* disable PS */ | 716 | /* disable PS */ |
@@ -821,7 +852,8 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | |||
821 | 852 | ||
822 | int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, | 853 | int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, |
823 | const u8 *ssid, u8 ssid_len, | 854 | const u8 *ssid, u8 ssid_len, |
824 | struct ieee80211_channel *chan) | 855 | struct ieee80211_channel *chan, |
856 | enum nl80211_bss_scan_width scan_width) | ||
825 | { | 857 | { |
826 | struct ieee80211_local *local = sdata->local; | 858 | struct ieee80211_local *local = sdata->local; |
827 | int ret = -EBUSY; | 859 | int ret = -EBUSY; |
@@ -871,6 +903,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, | |||
871 | 903 | ||
872 | local->int_scan_req->ssids = &local->scan_ssid; | 904 | local->int_scan_req->ssids = &local->scan_ssid; |
873 | local->int_scan_req->n_ssids = 1; | 905 | local->int_scan_req->n_ssids = 1; |
906 | local->int_scan_req->scan_width = scan_width; | ||
874 | memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); | 907 | memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); |
875 | local->int_scan_req->ssids[0].ssid_len = ssid_len; | 908 | local->int_scan_req->ssids[0].ssid_len = ssid_len; |
876 | 909 | ||