From: Felix Fietkau Date: Fri, 3 May 2013 09:14:03 +0000 (+0000) Subject: mac80211: merge a client mode channel switch handling fix X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=1b52dacef04bcb837cd28916316188a65f47c51e;p=openwrt%2Fstaging%2Frobimarko.git mac80211: merge a client mode channel switch handling fix Signed-off-by: Felix Fietkau SVN-Revision: 36531 --- diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch index 379e8f47ee..5d946ca102 100644 --- a/package/mac80211/patches/300-pending_work.patch +++ b/package/mac80211/patches/300-pending_work.patch @@ -1478,7 +1478,7 @@ if (!local->ops->channel_switch) { /* call "hw_config" only if doing sw channel switch */ -@@ -1054,56 +1013,193 @@ static void ieee80211_chswitch_timer(uns +@@ -1054,56 +1013,208 @@ static void ieee80211_chswitch_timer(uns ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work); } @@ -1487,7 +1487,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, - const struct ieee80211_channel_sw_ie *sw_elem, - struct ieee80211_bss *bss, u64 timestamp) -+ u64 timestamp, struct ieee802_11_elems *elems) ++ u64 timestamp, struct ieee802_11_elems *elems, ++ bool beacon) { - struct cfg80211_bss *cbss = - container_of((void *)bss, struct cfg80211_bss, priv); @@ -1509,36 +1510,38 @@ + struct cfg80211_chan_def new_vht_chandef = {}; + const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; + const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; ++ const struct ieee80211_ht_operation *ht_oper; + int secondary_channel_offset = -1; ASSERT_MGD_MTX(ifmgd); - if (!ifmgd->associated) + if (!cbss) ++ return; ++ ++ if (local->scanning) return; - if (sdata->local->scanning) -+ if (local->scanning) ++ /* disregard subsequent announcements if we are already processing */ ++ if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED) return; - /* Disregard subsequent beacons if we are already running a timer - processing a CSA */ -- -+ /* disregard subsequent announcements if we are already processing */ - if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED) - return; - -- new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); -- if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) { + sec_chan_offs = elems->sec_chan_offs; + wide_bw_chansw_ie = elems->wide_bw_chansw_ie; ++ ht_oper = elems->ht_operation; + + if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT | + IEEE80211_STA_DISABLE_40MHZ)) { + sec_chan_offs = NULL; + wide_bw_chansw_ie = NULL; ++ /* only used for bandwidth here */ ++ ht_oper = NULL; + } -+ + +- if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED) + if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) + wide_bw_chansw_ie = NULL; + @@ -1562,11 +1565,13 @@ + mode = elems->ch_switch_ie->mode; + } else { + /* nothing here we understand */ -+ return; + return; + } + + bss = (void *)cbss->priv; -+ + +- new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); +- if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) { + new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band); + new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); + if (!new_chan || new_chan->flags & IEEE80211_CHAN_DISABLED) { @@ -1579,10 +1584,20 @@ + return; + } + -+ if (sec_chan_offs) { ++ if (!beacon && sec_chan_offs) { + secondary_channel_offset = sec_chan_offs->sec_chan_offs; ++ } else if (beacon && ht_oper) { ++ secondary_channel_offset = ++ ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; + } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { -+ /* if HT is enabled and the IE not present, it's still HT */ ++ /* ++ * If it's not a beacon, HT is enabled and the IE not present, ++ * it's 20 MHz, 802.11-2012 8.5.2.6: ++ * This element [the Secondary Channel Offset Element] is ++ * present when switching to a 40 MHz channel. It may be ++ * present when switching to a 20 MHz channel (in which ++ * case the secondary channel offset is set to SCN). ++ */ + secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; + } + @@ -1692,7 +1707,7 @@ return; } chanctx = container_of(rcu_access_pointer(sdata->vif.chanctx_conf), -@@ -1111,40 +1207,39 @@ ieee80211_sta_process_chanswitch(struct +@@ -1111,40 +1222,39 @@ ieee80211_sta_process_chanswitch(struct if (chanctx->refcount > 1) { sdata_info(sdata, "channel switch with multiple interfaces on the same channel, disconnecting\n"); @@ -1747,7 +1762,7 @@ } static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, -@@ -2120,7 +2215,6 @@ void ieee80211_beacon_loss(struct ieee80 +@@ -2120,7 +2230,6 @@ void ieee80211_beacon_loss(struct ieee80 trace_api_beacon_loss(sdata); @@ -1755,7 +1770,7 @@ sdata->u.mgd.connection_loss = false; ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); } -@@ -2170,7 +2264,7 @@ static void ieee80211_auth_challenge(str +@@ -2170,7 +2279,7 @@ static void ieee80211_auth_challenge(str u32 tx_flags = 0; pos = mgmt->u.auth.variable; @@ -1764,7 +1779,7 @@ if (!elems.challenge) return; auth_data->expected_transaction = 4; -@@ -2435,7 +2529,7 @@ static bool ieee80211_assoc_success(stru +@@ -2435,7 +2544,7 @@ static bool ieee80211_assoc_success(stru } pos = mgmt->u.assoc_resp.variable; @@ -1773,7 +1788,7 @@ if (!elems.supp_rates) { sdata_info(sdata, "no SuppRates element in AssocResp\n"); -@@ -2604,7 +2698,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee +@@ -2604,7 +2713,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); pos = mgmt->u.assoc_resp.variable; @@ -1782,7 +1797,7 @@ if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && elems.timeout_int && -@@ -2659,6 +2753,8 @@ static void ieee80211_rx_bss_info(struct +@@ -2659,6 +2768,8 @@ static void ieee80211_rx_bss_info(struct struct ieee80211_channel *channel; bool need_ps = false; @@ -1791,7 +1806,7 @@ if ((sdata->u.mgd.associated && ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) || (sdata->u.mgd.assoc_data && -@@ -2689,7 +2785,8 @@ static void ieee80211_rx_bss_info(struct +@@ -2689,7 +2800,8 @@ static void ieee80211_rx_bss_info(struct if (bss) ieee80211_rx_bss_put(local, bss); @@ -1801,7 +1816,7 @@ return; if (need_ps) { -@@ -2698,10 +2795,8 @@ static void ieee80211_rx_bss_info(struct +@@ -2698,10 +2810,9 @@ static void ieee80211_rx_bss_info(struct mutex_unlock(&local->iflist_mtx); } @@ -1809,12 +1824,13 @@ - memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, ETH_ALEN) == 0) - ieee80211_sta_process_chanswitch(sdata, elems->ch_switch_ie, - bss, rx_status->mactime); -+ ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, elems); ++ ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, ++ elems, true); + } -@@ -2726,7 +2821,7 @@ static void ieee80211_rx_mgmt_probe_resp +@@ -2726,7 +2837,7 @@ static void ieee80211_rx_mgmt_probe_resp return; ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, @@ -1823,7 +1839,7 @@ ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); -@@ -2809,7 +2904,7 @@ ieee80211_rx_mgmt_beacon(struct ieee8021 +@@ -2809,7 +2920,7 @@ ieee80211_rx_mgmt_beacon(struct ieee8021 if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon && ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) { ieee802_11_parse_elems(mgmt->u.beacon.variable, @@ -1832,7 +1848,7 @@ ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); ifmgd->assoc_data->have_beacon = true; -@@ -2919,7 +3014,7 @@ ieee80211_rx_mgmt_beacon(struct ieee8021 +@@ -2919,7 +3030,7 @@ ieee80211_rx_mgmt_beacon(struct ieee8021 ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, @@ -1841,7 +1857,7 @@ care_about_ies, ncrc); if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) { -@@ -3066,6 +3161,8 @@ void ieee80211_sta_rx_queued_mgmt(struct +@@ -3066,6 +3177,8 @@ void ieee80211_sta_rx_queued_mgmt(struct enum rx_mgmt_action rma = RX_MGMT_NONE; u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN]; u16 fc; @@ -1850,7 +1866,7 @@ rx_status = (struct ieee80211_rx_status *) skb->cb; mgmt = (struct ieee80211_mgmt *) skb->data; -@@ -3095,14 +3192,48 @@ void ieee80211_sta_rx_queued_mgmt(struct +@@ -3095,14 +3208,48 @@ void ieee80211_sta_rx_queued_mgmt(struct rma = ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, &bss); break; case IEEE80211_STYPE_ACTION: @@ -1877,7 +1893,7 @@ - rx_status->mactime); - break; + rx_status->mactime, -+ &elems); ++ &elems, false); + } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) { + ies_len = skb->len - + offsetof(struct ieee80211_mgmt, @@ -1899,7 +1915,7 @@ + + ieee80211_sta_process_chanswitch(sdata, + rx_status->mactime, -+ &elems); ++ &elems, false); } + break; }