aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ibss.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/ibss.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/ibss.c')
-rw-r--r--net/mac80211/ibss.c70
1 files changed, 34 insertions, 36 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 5f3620f0bc0a..34d9235117d9 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -26,7 +26,6 @@
26#include "rate.h" 26#include "rate.h"
27 27
28#define IEEE80211_SCAN_INTERVAL (2 * HZ) 28#define IEEE80211_SCAN_INTERVAL (2 * HZ)
29#define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ)
30#define IEEE80211_IBSS_JOIN_TIMEOUT (7 * HZ) 29#define IEEE80211_IBSS_JOIN_TIMEOUT (7 * HZ)
31 30
32#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) 31#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
@@ -76,21 +75,22 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
76 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS); 75 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS);
77 } 76 }
78 77
79 memcpy(ifibss->bssid, bssid, ETH_ALEN);
80
81 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; 78 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
82 79
83 local->oper_channel = chan;
84 channel_type = ifibss->channel_type; 80 channel_type = ifibss->channel_type;
85 if (!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) 81 if (!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type))
86 channel_type = NL80211_CHAN_HT20; 82 channel_type = NL80211_CHAN_HT20;
87 if (!ieee80211_set_channel_type(local, sdata, channel_type)) { 83
88 /* can only fail due to HT40+/- mismatch */ 84 ieee80211_vif_release_channel(sdata);
89 channel_type = NL80211_CHAN_HT20; 85 if (ieee80211_vif_use_channel(sdata, chan, channel_type,
90 WARN_ON(!ieee80211_set_channel_type(local, sdata, 86 ifibss->fixed_channel ?
91 NL80211_CHAN_HT20)); 87 IEEE80211_CHANCTX_SHARED :
88 IEEE80211_CHANCTX_EXCLUSIVE)) {
89 sdata_info(sdata, "Failed to join IBSS, no channel context\n");
90 return;
92 } 91 }
93 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 92
93 memcpy(ifibss->bssid, bssid, ETH_ALEN);
94 94
95 sband = local->hw.wiphy->bands[chan->band]; 95 sband = local->hw.wiphy->bands[chan->band];
96 96
@@ -294,7 +294,8 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
294 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 294 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
295 struct ieee80211_local *local = sdata->local; 295 struct ieee80211_local *local = sdata->local;
296 struct sta_info *sta; 296 struct sta_info *sta;
297 int band = local->oper_channel->band; 297 struct ieee80211_chanctx_conf *chanctx_conf;
298 int band;
298 299
299 /* 300 /*
300 * XXX: Consider removing the least recently used entry and 301 * XXX: Consider removing the least recently used entry and
@@ -317,6 +318,13 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
317 return NULL; 318 return NULL;
318 } 319 }
319 320
321 rcu_read_lock();
322 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
323 if (WARN_ON_ONCE(!chanctx_conf))
324 return NULL;
325 band = chanctx_conf->channel->band;
326 rcu_read_unlock();
327
320 sta = sta_info_alloc(sdata, addr, GFP_KERNEL); 328 sta = sta_info_alloc(sdata, addr, GFP_KERNEL);
321 if (!sta) { 329 if (!sta) {
322 rcu_read_lock(); 330 rcu_read_lock();
@@ -517,7 +525,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
517 goto put_bss; 525 goto put_bss;
518 526
519 /* different channel */ 527 /* different channel */
520 if (cbss->channel != local->oper_channel) 528 if (sdata->u.ibss.fixed_channel &&
529 sdata->u.ibss.channel != cbss->channel)
521 goto put_bss; 530 goto put_bss;
522 531
523 /* different SSID */ 532 /* different SSID */
@@ -592,7 +601,8 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
592 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 601 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
593 struct ieee80211_local *local = sdata->local; 602 struct ieee80211_local *local = sdata->local;
594 struct sta_info *sta; 603 struct sta_info *sta;
595 int band = local->oper_channel->band; 604 struct ieee80211_chanctx_conf *chanctx_conf;
605 int band;
596 606
597 /* 607 /*
598 * XXX: Consider removing the least recently used entry and 608 * XXX: Consider removing the least recently used entry and
@@ -610,6 +620,15 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
610 if (!ether_addr_equal(bssid, sdata->u.ibss.bssid)) 620 if (!ether_addr_equal(bssid, sdata->u.ibss.bssid))
611 return; 621 return;
612 622
623 rcu_read_lock();
624 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
625 if (WARN_ON_ONCE(!chanctx_conf)) {
626 rcu_read_unlock();
627 return;
628 }
629 band = chanctx_conf->channel->band;
630 rcu_read_unlock();
631
613 sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); 632 sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
614 if (!sta) 633 if (!sta)
615 return; 634 return;
@@ -784,18 +803,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
784 int interval = IEEE80211_SCAN_INTERVAL; 803 int interval = IEEE80211_SCAN_INTERVAL;
785 804
786 if (time_after(jiffies, ifibss->ibss_join_req + 805 if (time_after(jiffies, ifibss->ibss_join_req +
787 IEEE80211_IBSS_JOIN_TIMEOUT)) { 806 IEEE80211_IBSS_JOIN_TIMEOUT))
788 if (!(local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS)) { 807 ieee80211_sta_create_ibss(sdata);
789 ieee80211_sta_create_ibss(sdata);
790 return;
791 }
792 sdata_info(sdata, "IBSS not allowed on %d MHz\n",
793 local->oper_channel->center_freq);
794
795 /* No IBSS found - decrease scan interval and continue
796 * scanning. */
797 interval = IEEE80211_SCAN_INTERVAL_SLOW;
798 }
799 808
800 mod_timer(&ifibss->timer, 809 mod_timer(&ifibss->timer,
801 round_jiffies(jiffies + interval)); 810 round_jiffies(jiffies + interval));
@@ -1086,17 +1095,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
1086 sdata->u.ibss.channel_type = params->channel_type; 1095 sdata->u.ibss.channel_type = params->channel_type;
1087 sdata->u.ibss.fixed_channel = params->channel_fixed; 1096 sdata->u.ibss.fixed_channel = params->channel_fixed;
1088 1097
1089 /* fix ourselves to that channel now already */
1090 if (params->channel_fixed) {
1091 sdata->local->oper_channel = params->channel;
1092 if (!ieee80211_set_channel_type(sdata->local, sdata,
1093 params->channel_type)) {
1094 mutex_unlock(&sdata->u.ibss.mtx);
1095 kfree_skb(skb);
1096 return -EINVAL;
1097 }
1098 }
1099
1100 if (params->ie) { 1098 if (params->ie) {
1101 sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len, 1099 sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len,
1102 GFP_KERNEL); 1100 GFP_KERNEL);