aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/chan.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-07-26 11:24:39 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-10-17 05:02:09 -0400
commit55de908ab292c03f1eb280f51170ddb9c6b57e31 (patch)
treebc75bb5cea581cadf6fe8b4f121cce02d07c276a /net/mac80211/chan.c
parentfe57d9f5c0a2c1ef97ba8cdc42cfda5743f287b8 (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/chan.c')
-rw-r--r--net/mac80211/chan.c152
1 files changed, 27 insertions, 125 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 1a8dee42e546..41e1aa69f7aa 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -7,106 +7,6 @@
7#include "ieee80211_i.h" 7#include "ieee80211_i.h"
8#include "driver-ops.h" 8#include "driver-ops.h"
9 9
10static enum ieee80211_chan_mode
11__ieee80211_get_channel_mode(struct ieee80211_local *local,
12 struct ieee80211_sub_if_data *ignore)
13{
14 struct ieee80211_sub_if_data *sdata;
15
16 lockdep_assert_held(&local->iflist_mtx);
17
18 list_for_each_entry(sdata, &local->interfaces, list) {
19 if (sdata == ignore)
20 continue;
21
22 if (!ieee80211_sdata_running(sdata))
23 continue;
24
25 switch (sdata->vif.type) {
26 case NL80211_IFTYPE_MONITOR:
27 continue;
28 case NL80211_IFTYPE_STATION:
29 if (!sdata->u.mgd.associated)
30 continue;
31 break;
32 case NL80211_IFTYPE_ADHOC:
33 if (!sdata->u.ibss.ssid_len)
34 continue;
35 if (!sdata->u.ibss.fixed_channel)
36 return CHAN_MODE_HOPPING;
37 break;
38 case NL80211_IFTYPE_AP_VLAN:
39 /* will also have _AP interface */
40 continue;
41 case NL80211_IFTYPE_AP:
42 if (!sdata->u.ap.beacon)
43 continue;
44 break;
45 case NL80211_IFTYPE_MESH_POINT:
46 if (!sdata->wdev.mesh_id_len)
47 continue;
48 break;
49 default:
50 break;
51 }
52
53 return CHAN_MODE_FIXED;
54 }
55
56 return CHAN_MODE_UNDEFINED;
57}
58
59enum ieee80211_chan_mode
60ieee80211_get_channel_mode(struct ieee80211_local *local,
61 struct ieee80211_sub_if_data *ignore)
62{
63 enum ieee80211_chan_mode mode;
64
65 mutex_lock(&local->iflist_mtx);
66 mode = __ieee80211_get_channel_mode(local, ignore);
67 mutex_unlock(&local->iflist_mtx);
68
69 return mode;
70}
71
72static enum nl80211_channel_type
73ieee80211_get_superchan(struct ieee80211_local *local,
74 struct ieee80211_sub_if_data *sdata)
75{
76 enum nl80211_channel_type superchan = NL80211_CHAN_NO_HT;
77 struct ieee80211_sub_if_data *tmp;
78
79 mutex_lock(&local->iflist_mtx);
80 list_for_each_entry(tmp, &local->interfaces, list) {
81 if (tmp == sdata)
82 continue;
83
84 if (!ieee80211_sdata_running(tmp))
85 continue;
86
87 switch (tmp->vif.bss_conf.channel_type) {
88 case NL80211_CHAN_NO_HT:
89 case NL80211_CHAN_HT20:
90 if (superchan > tmp->vif.bss_conf.channel_type)
91 break;
92
93 superchan = tmp->vif.bss_conf.channel_type;
94 break;
95 case NL80211_CHAN_HT40PLUS:
96 WARN_ON(superchan == NL80211_CHAN_HT40MINUS);
97 superchan = NL80211_CHAN_HT40PLUS;
98 break;
99 case NL80211_CHAN_HT40MINUS:
100 WARN_ON(superchan == NL80211_CHAN_HT40PLUS);
101 superchan = NL80211_CHAN_HT40MINUS;
102 break;
103 }
104 }
105 mutex_unlock(&local->iflist_mtx);
106
107 return superchan;
108}
109
110static bool 10static bool
111ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1, 11ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1,
112 enum nl80211_channel_type chantype2, 12 enum nl80211_channel_type chantype2,
@@ -149,26 +49,6 @@ ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1,
149 return true; 49 return true;
150} 50}
151 51
152bool ieee80211_set_channel_type(struct ieee80211_local *local,
153 struct ieee80211_sub_if_data *sdata,
154 enum nl80211_channel_type chantype)
155{
156 enum nl80211_channel_type superchan;
157 enum nl80211_channel_type compatchan;
158
159 superchan = ieee80211_get_superchan(local, sdata);
160 if (!ieee80211_channel_types_are_compatible(superchan, chantype,
161 &compatchan))
162 return false;
163
164 local->_oper_channel_type = compatchan;
165
166 if (sdata)
167 sdata->vif.bss_conf.channel_type = chantype;
168
169 return true;
170}
171
172static void ieee80211_change_chantype(struct ieee80211_local *local, 52static void ieee80211_change_chantype(struct ieee80211_local *local,
173 struct ieee80211_chanctx *ctx, 53 struct ieee80211_chanctx *ctx,
174 enum nl80211_channel_type chantype) 54 enum nl80211_channel_type chantype)
@@ -178,6 +58,11 @@ static void ieee80211_change_chantype(struct ieee80211_local *local,
178 58
179 ctx->conf.channel_type = chantype; 59 ctx->conf.channel_type = chantype;
180 drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE); 60 drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE);
61
62 if (!local->use_chanctx) {
63 local->_oper_channel_type = chantype;
64 ieee80211_hw_config(local, 0);
65 }
181} 66}
182 67
183static struct ieee80211_chanctx * 68static struct ieee80211_chanctx *
@@ -235,10 +120,16 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
235 ctx->conf.channel_type = channel_type; 120 ctx->conf.channel_type = channel_type;
236 ctx->mode = mode; 121 ctx->mode = mode;
237 122
238 err = drv_add_chanctx(local, ctx); 123 if (!local->use_chanctx) {
239 if (err) { 124 local->_oper_channel_type = channel_type;
240 kfree(ctx); 125 local->_oper_channel = channel;
241 return ERR_PTR(err); 126 ieee80211_hw_config(local, 0);
127 } else {
128 err = drv_add_chanctx(local, ctx);
129 if (err) {
130 kfree(ctx);
131 return ERR_PTR(err);
132 }
242 } 133 }
243 134
244 list_add(&ctx->list, &local->chanctx_list); 135 list_add(&ctx->list, &local->chanctx_list);
@@ -253,7 +144,12 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
253 144
254 WARN_ON_ONCE(ctx->refcount != 0); 145 WARN_ON_ONCE(ctx->refcount != 0);
255 146
256 drv_remove_chanctx(local, ctx); 147 if (!local->use_chanctx) {
148 local->_oper_channel_type = NL80211_CHAN_NO_HT;
149 ieee80211_hw_config(local, 0);
150 } else {
151 drv_remove_chanctx(local, ctx);
152 }
257 153
258 list_del(&ctx->list); 154 list_del(&ctx->list);
259 kfree_rcu(ctx, rcu_head); 155 kfree_rcu(ctx, rcu_head);
@@ -359,6 +255,8 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
359 struct ieee80211_chanctx *ctx; 255 struct ieee80211_chanctx *ctx;
360 int ret; 256 int ret;
361 257
258 WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
259
362 mutex_lock(&local->chanctx_mtx); 260 mutex_lock(&local->chanctx_mtx);
363 __ieee80211_vif_release_channel(sdata); 261 __ieee80211_vif_release_channel(sdata);
364 262
@@ -370,6 +268,8 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
370 goto out; 268 goto out;
371 } 269 }
372 270
271 sdata->vif.bss_conf.channel_type = channel_type;
272
373 ret = ieee80211_assign_vif_chanctx(sdata, ctx); 273 ret = ieee80211_assign_vif_chanctx(sdata, ctx);
374 if (ret) { 274 if (ret) {
375 /* if assign fails refcount stays the same */ 275 /* if assign fails refcount stays the same */
@@ -385,6 +285,8 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
385 285
386void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) 286void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
387{ 287{
288 WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
289
388 mutex_lock(&sdata->local->chanctx_mtx); 290 mutex_lock(&sdata->local->chanctx_mtx);
389 __ieee80211_vif_release_channel(sdata); 291 __ieee80211_vif_release_channel(sdata);
390 mutex_unlock(&sdata->local->chanctx_mtx); 292 mutex_unlock(&sdata->local->chanctx_mtx);