diff options
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r-- | net/mac80211/main.c | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d999bf3b84e1..e323d4e6647b 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -100,7 +100,7 @@ static void ieee80211_reconfig_filter(struct work_struct *work) | |||
100 | */ | 100 | */ |
101 | bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local) | 101 | bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local) |
102 | { | 102 | { |
103 | struct ieee80211_channel *chan, *scan_chan; | 103 | struct ieee80211_channel *chan; |
104 | enum nl80211_channel_type channel_type; | 104 | enum nl80211_channel_type channel_type; |
105 | 105 | ||
106 | /* This logic needs to match logic in ieee80211_hw_config */ | 106 | /* This logic needs to match logic in ieee80211_hw_config */ |
@@ -114,7 +114,7 @@ bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local) | |||
114 | else | 114 | else |
115 | channel_type = NL80211_CHAN_NO_HT; | 115 | channel_type = NL80211_CHAN_NO_HT; |
116 | } else if (local->tmp_channel) { | 116 | } else if (local->tmp_channel) { |
117 | chan = scan_chan = local->tmp_channel; | 117 | chan = local->tmp_channel; |
118 | channel_type = local->tmp_channel_type; | 118 | channel_type = local->tmp_channel_type; |
119 | } else { | 119 | } else { |
120 | chan = local->oper_channel; | 120 | chan = local->oper_channel; |
@@ -126,8 +126,8 @@ bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local) | |||
126 | return false; | 126 | return false; |
127 | 127 | ||
128 | /* Check current hardware-config against oper_channel. */ | 128 | /* Check current hardware-config against oper_channel. */ |
129 | if ((local->oper_channel != local->hw.conf.channel) || | 129 | if (local->oper_channel != local->hw.conf.channel || |
130 | (local->_oper_channel_type != local->hw.conf.channel_type)) | 130 | local->_oper_channel_type != local->hw.conf.channel_type) |
131 | return false; | 131 | return false; |
132 | 132 | ||
133 | return true; | 133 | return true; |
@@ -135,7 +135,7 @@ bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local) | |||
135 | 135 | ||
136 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | 136 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) |
137 | { | 137 | { |
138 | struct ieee80211_channel *chan, *scan_chan; | 138 | struct ieee80211_channel *chan; |
139 | int ret = 0; | 139 | int ret = 0; |
140 | int power; | 140 | int power; |
141 | enum nl80211_channel_type channel_type; | 141 | enum nl80211_channel_type channel_type; |
@@ -143,14 +143,12 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
143 | 143 | ||
144 | might_sleep(); | 144 | might_sleep(); |
145 | 145 | ||
146 | scan_chan = local->scan_channel; | ||
147 | |||
148 | /* If this off-channel logic ever changes, ieee80211_on_oper_channel | 146 | /* If this off-channel logic ever changes, ieee80211_on_oper_channel |
149 | * may need to change as well. | 147 | * may need to change as well. |
150 | */ | 148 | */ |
151 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | 149 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
152 | if (scan_chan) { | 150 | if (local->scan_channel) { |
153 | chan = scan_chan; | 151 | chan = local->scan_channel; |
154 | /* If scanning on oper channel, use whatever channel-type | 152 | /* If scanning on oper channel, use whatever channel-type |
155 | * is currently in use. | 153 | * is currently in use. |
156 | */ | 154 | */ |
@@ -159,7 +157,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
159 | else | 157 | else |
160 | channel_type = NL80211_CHAN_NO_HT; | 158 | channel_type = NL80211_CHAN_NO_HT; |
161 | } else if (local->tmp_channel) { | 159 | } else if (local->tmp_channel) { |
162 | chan = scan_chan = local->tmp_channel; | 160 | chan = local->tmp_channel; |
163 | channel_type = local->tmp_channel_type; | 161 | channel_type = local->tmp_channel_type; |
164 | } else { | 162 | } else { |
165 | chan = local->oper_channel; | 163 | chan = local->oper_channel; |
@@ -595,7 +593,10 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
595 | 593 | ||
596 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | | 594 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | |
597 | WIPHY_FLAG_4ADDR_AP | | 595 | WIPHY_FLAG_4ADDR_AP | |
598 | WIPHY_FLAG_4ADDR_STATION; | 596 | WIPHY_FLAG_4ADDR_STATION | |
597 | WIPHY_FLAG_REPORTS_OBSS; | ||
598 | |||
599 | wiphy->features = NL80211_FEATURE_SK_TX_STATUS; | ||
599 | 600 | ||
600 | if (!ops->set_key) | 601 | if (!ops->set_key) |
601 | wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 602 | wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
@@ -670,6 +671,11 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
670 | INIT_WORK(&local->sched_scan_stopped_work, | 671 | INIT_WORK(&local->sched_scan_stopped_work, |
671 | ieee80211_sched_scan_stopped_work); | 672 | ieee80211_sched_scan_stopped_work); |
672 | 673 | ||
674 | spin_lock_init(&local->ack_status_lock); | ||
675 | idr_init(&local->ack_status_frames); | ||
676 | /* preallocate at least one entry */ | ||
677 | idr_pre_get(&local->ack_status_frames, GFP_KERNEL); | ||
678 | |||
673 | sta_info_init(local); | 679 | sta_info_init(local); |
674 | 680 | ||
675 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { | 681 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { |
@@ -1045,6 +1051,13 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1045 | } | 1051 | } |
1046 | EXPORT_SYMBOL(ieee80211_unregister_hw); | 1052 | EXPORT_SYMBOL(ieee80211_unregister_hw); |
1047 | 1053 | ||
1054 | static int ieee80211_free_ack_frame(int id, void *p, void *data) | ||
1055 | { | ||
1056 | WARN_ONCE(1, "Have pending ack frames!\n"); | ||
1057 | kfree_skb(p); | ||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1048 | void ieee80211_free_hw(struct ieee80211_hw *hw) | 1061 | void ieee80211_free_hw(struct ieee80211_hw *hw) |
1049 | { | 1062 | { |
1050 | struct ieee80211_local *local = hw_to_local(hw); | 1063 | struct ieee80211_local *local = hw_to_local(hw); |
@@ -1055,6 +1068,10 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) | |||
1055 | if (local->wiphy_ciphers_allocated) | 1068 | if (local->wiphy_ciphers_allocated) |
1056 | kfree(local->hw.wiphy->cipher_suites); | 1069 | kfree(local->hw.wiphy->cipher_suites); |
1057 | 1070 | ||
1071 | idr_for_each(&local->ack_status_frames, | ||
1072 | ieee80211_free_ack_frame, NULL); | ||
1073 | idr_destroy(&local->ack_status_frames); | ||
1074 | |||
1058 | wiphy_free(local->hw.wiphy); | 1075 | wiphy_free(local->hw.wiphy); |
1059 | } | 1076 | } |
1060 | EXPORT_SYMBOL(ieee80211_free_hw); | 1077 | EXPORT_SYMBOL(ieee80211_free_hw); |