From d444fb7e9957205109852f2d9af95c02a3e68b5a Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Mon, 7 Feb 2011 13:44:36 -0800 Subject: [PATCH] --- yaml --- r: 237357 b: refs/heads/master c: da2fd1f0f7b78f21f6378f726d1f6de9d573b2d4 h: refs/heads/master i: 237355: 1f6a72e53c6d4a53433abbff24354c1d9dd988ab v: v3 --- [refs] | 2 +- trunk/net/mac80211/work.c | 53 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 3207c22b7ad9..a355e19eecdd 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 4f2e9d91f84ce39698517203974ffc2bcc32a21d +refs/heads/master: da2fd1f0f7b78f21f6378f726d1f6de9d573b2d4 diff --git a/trunk/net/mac80211/work.c b/trunk/net/mac80211/work.c index 6bf787a5b38a..64f2b2871282 100644 --- a/trunk/net/mac80211/work.c +++ b/trunk/net/mac80211/work.c @@ -874,6 +874,44 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, kfree_skb(skb); } +static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct, + enum nl80211_channel_type oper_ct) +{ + switch (wk_ct) { + case NL80211_CHAN_NO_HT: + return true; + case NL80211_CHAN_HT20: + if (oper_ct != NL80211_CHAN_NO_HT) + return true; + return false; + case NL80211_CHAN_HT40MINUS: + case NL80211_CHAN_HT40PLUS: + return (wk_ct == oper_ct); + } + WARN_ON(1); /* shouldn't get here */ + return false; +} + +static enum nl80211_channel_type +ieee80211_calc_ct(enum nl80211_channel_type wk_ct, + enum nl80211_channel_type oper_ct) +{ + switch (wk_ct) { + case NL80211_CHAN_NO_HT: + return oper_ct; + case NL80211_CHAN_HT20: + if (oper_ct != NL80211_CHAN_NO_HT) + return oper_ct; + return wk_ct; + case NL80211_CHAN_HT40MINUS: + case NL80211_CHAN_HT40PLUS: + return wk_ct; + } + WARN_ON(1); /* shouldn't get here */ + return wk_ct; +} + + static void ieee80211_work_timer(unsigned long data) { struct ieee80211_local *local = (void *) data; @@ -927,14 +965,22 @@ static void ieee80211_work_work(struct work_struct *work) bool on_oper_chan; bool tmp_chan_changed = false; bool on_oper_chan2; + enum nl80211_channel_type wk_ct; on_oper_chan = ieee80211_cfg_on_oper_channel(local); + + /* Work with existing channel type if possible. */ + wk_ct = wk->chan_type; + if (wk->chan == local->hw.conf.channel) + wk_ct = ieee80211_calc_ct(wk->chan_type, + local->hw.conf.channel_type); + if (local->tmp_channel) if ((local->tmp_channel != wk->chan) || - (local->tmp_channel_type != wk->chan_type)) + (local->tmp_channel_type != wk_ct)) tmp_chan_changed = true; local->tmp_channel = wk->chan; - local->tmp_channel_type = wk->chan_type; + local->tmp_channel_type = wk_ct; /* * Leave the station vifs in awake mode if they * happen to be on the same channel as @@ -1031,7 +1077,8 @@ static void ieee80211_work_work(struct work_struct *work) continue; if (wk->chan != local->tmp_channel) continue; - if (wk->chan_type != local->tmp_channel_type) + if (ieee80211_work_ct_coexists(wk->chan_type, + local->tmp_channel_type)) continue; remain_off_channel = true; }