diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-07-26 11:24:39 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-10-17 05:02:09 -0400 |
commit | 55de908ab292c03f1eb280f51170ddb9c6b57e31 (patch) | |
tree | bc75bb5cea581cadf6fe8b4f121cce02d07c276a /net/mac80211/main.c | |
parent | fe57d9f5c0a2c1ef97ba8cdc42cfda5743f287b8 (diff) |
mac80211: use channel contexts
Instead of operating on a single channel only,
use the new channel context infrastructure in
all mac80211 code.
This enables drivers that want to use the new
channel context infrastructure to use multiple
channels, while nothing should change for all
the other drivers that don't support it.
Right now this disables both TX power settings
and spatial multiplexing powersave. Both need
to be re-enabled on a channel context basis.
Additionally, when channel contexts are used
drop the connection when channel switch is
received rather than trying to handle it. This
will have to be improved later.
[With fixes from Eliad and Emmanuel incorporated]
Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r-- | net/mac80211/main.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0dd1ea241c54..9cb6280aa2f2 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -93,23 +93,21 @@ static void ieee80211_reconfig_filter(struct work_struct *work) | |||
93 | ieee80211_configure_filter(local); | 93 | ieee80211_configure_filter(local); |
94 | } | 94 | } |
95 | 95 | ||
96 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | 96 | static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) |
97 | { | 97 | { |
98 | struct ieee80211_channel *chan; | 98 | struct ieee80211_channel *chan; |
99 | int ret = 0; | 99 | u32 changed = 0; |
100 | int power; | 100 | int power; |
101 | enum nl80211_channel_type channel_type; | 101 | enum nl80211_channel_type channel_type; |
102 | u32 offchannel_flag; | 102 | u32 offchannel_flag; |
103 | 103 | ||
104 | might_sleep(); | ||
105 | |||
106 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | 104 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
107 | if (local->scan_channel) { | 105 | if (local->scan_channel) { |
108 | chan = local->scan_channel; | 106 | chan = local->scan_channel; |
109 | /* If scanning on oper channel, use whatever channel-type | 107 | /* If scanning on oper channel, use whatever channel-type |
110 | * is currently in use. | 108 | * is currently in use. |
111 | */ | 109 | */ |
112 | if (chan == local->oper_channel) | 110 | if (chan == local->_oper_channel) |
113 | channel_type = local->_oper_channel_type; | 111 | channel_type = local->_oper_channel_type; |
114 | else | 112 | else |
115 | channel_type = NL80211_CHAN_NO_HT; | 113 | channel_type = NL80211_CHAN_NO_HT; |
@@ -117,11 +115,11 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
117 | chan = local->tmp_channel; | 115 | chan = local->tmp_channel; |
118 | channel_type = local->tmp_channel_type; | 116 | channel_type = local->tmp_channel_type; |
119 | } else { | 117 | } else { |
120 | chan = local->oper_channel; | 118 | chan = local->_oper_channel; |
121 | channel_type = local->_oper_channel_type; | 119 | channel_type = local->_oper_channel_type; |
122 | } | 120 | } |
123 | 121 | ||
124 | if (chan != local->oper_channel || | 122 | if (chan != local->_oper_channel || |
125 | channel_type != local->_oper_channel_type) | 123 | channel_type != local->_oper_channel_type) |
126 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | 124 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; |
127 | else | 125 | else |
@@ -164,6 +162,21 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
164 | local->hw.conf.power_level = power; | 162 | local->hw.conf.power_level = power; |
165 | } | 163 | } |
166 | 164 | ||
165 | return changed; | ||
166 | } | ||
167 | |||
168 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | ||
169 | { | ||
170 | int ret = 0; | ||
171 | |||
172 | might_sleep(); | ||
173 | |||
174 | if (!local->use_chanctx) | ||
175 | changed |= ieee80211_hw_conf_chan(local); | ||
176 | else | ||
177 | changed &= ~(IEEE80211_CONF_CHANGE_CHANNEL | | ||
178 | IEEE80211_CONF_CHANGE_POWER); | ||
179 | |||
167 | if (changed && local->open_count) { | 180 | if (changed && local->open_count) { |
168 | ret = drv_config(local, changed); | 181 | ret = drv_config(local, changed); |
169 | /* | 182 | /* |
@@ -775,12 +788,16 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
775 | sband = local->hw.wiphy->bands[band]; | 788 | sband = local->hw.wiphy->bands[band]; |
776 | if (!sband) | 789 | if (!sband) |
777 | continue; | 790 | continue; |
778 | if (!local->oper_channel) { | 791 | if (!local->use_chanctx && !local->_oper_channel) { |
779 | /* init channel we're on */ | 792 | /* init channel we're on */ |
780 | local->hw.conf.channel = | 793 | local->hw.conf.channel = |
781 | local->oper_channel = &sband->channels[0]; | 794 | local->_oper_channel = &sband->channels[0]; |
782 | local->hw.conf.channel_type = NL80211_CHAN_NO_HT; | 795 | local->hw.conf.channel_type = NL80211_CHAN_NO_HT; |
783 | } | 796 | } |
797 | if (!local->monitor_channel) { | ||
798 | local->monitor_channel = &sband->channels[0]; | ||
799 | local->monitor_channel_type = NL80211_CHAN_NO_HT; | ||
800 | } | ||
784 | channels += sband->n_channels; | 801 | channels += sband->n_channels; |
785 | 802 | ||
786 | if (max_bitrates < sband->n_bitrates) | 803 | if (max_bitrates < sband->n_bitrates) |
@@ -810,19 +827,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
810 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); | 827 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); |
811 | hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR); | 828 | hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR); |
812 | 829 | ||
813 | /* | 830 | /* mac80211 doesn't support more than one IBSS interface right now */ |
814 | * mac80211 doesn't support more than 1 channel, and also not more | ||
815 | * than one IBSS interface | ||
816 | */ | ||
817 | for (i = 0; i < hw->wiphy->n_iface_combinations; i++) { | 831 | for (i = 0; i < hw->wiphy->n_iface_combinations; i++) { |
818 | const struct ieee80211_iface_combination *c; | 832 | const struct ieee80211_iface_combination *c; |
819 | int j; | 833 | int j; |
820 | 834 | ||
821 | c = &hw->wiphy->iface_combinations[i]; | 835 | c = &hw->wiphy->iface_combinations[i]; |
822 | 836 | ||
823 | if (c->num_different_channels > 1) | ||
824 | return -EINVAL; | ||
825 | |||
826 | for (j = 0; j < c->n_limits; j++) | 837 | for (j = 0; j < c->n_limits; j++) |
827 | if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) && | 838 | if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) && |
828 | c->limits[j].max > 1) | 839 | c->limits[j].max > 1) |