+++ /dev/null
-From: Abbas, Mohamed <mohamed.abbas@intel.com>
-Subject: iwlwifi: fix rs_get_rate WARN_ON()
-Patch-mainline: not yet
-References: bnc#456002
-
-In ieee80211_sta structure there is u64 supp_rates[IEEE80211_NUM_BANDS]
-this is filled with all support rate from assoc_resp. If we associate
-with G-band AP only supp_rates of G-band will be set the other band
-supp_rates will be set to 0. If the user type this command
-this will cause mac80211 to set to new channel, mac80211
-does not disassociate in setting new channel, so the active
-band is now A-band. then in handling the new essid mac80211 will
-kick in the assoc steps which involve sending disassociation frame.
-in this mac80211 will WARN_ON sta->supp_rates[A_BAND] == 0.
-
-This fixes:
-http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1822
-http://www.kerneloops.org/searchweek.php?search=rs_get_rate
-
-Signed-off-by: mohamed abbas <mohamed.abbas@intel.com>
-Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
-Acked-by: Helmut Schaa <hschaa@suse.de>
-Acked-by: Jiri Benc <jbenc@suse.cz>
-
----
- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 11 ++++++++---
- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 14 ++++++++++++--
- 2 files changed, 20 insertions(+), 5 deletions(-)
-
---- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
-+++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
-@@ -652,7 +652,8 @@ static void rs_get_rate(void *priv_rate,
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct sta_info *sta;
-- u16 fc, rate_mask;
-+ u16 fc;
-+ u16 rate_mask = 0;
- struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
- DECLARE_MAC_BUF(mac);
-
-@@ -661,6 +662,8 @@ static void rs_get_rate(void *priv_rate,
- rcu_read_lock();
-
- sta = sta_info_get(local, hdr->addr1);
-+ if (sta)
-+ rate_mask = sta->supp_rates[sband->band];
-
- /* Send management frames and broadcast/multicast data using lowest
- * rate. */
-@@ -669,12 +672,14 @@ static void rs_get_rate(void *priv_rate,
- is_multicast_ether_addr(hdr->addr1) ||
- !sta || !sta->rate_ctrl_priv) {
- IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
-- sel->rate_idx = rate_lowest_index(local, sband, sta);
-+ if (!rate_mask)
-+ sel->rate_idx = rate_lowest_index(local, sband, NULL);
-+ else
-+ sel->rate_idx = rate_lowest_index(local, sband, sta);
- rcu_read_unlock();
- return;
- }
-
-- rate_mask = sta->supp_rates[sband->band];
- index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
-
- if (sband->band == IEEE80211_BAND_5GHZ)
---- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
-+++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
-@@ -795,9 +795,12 @@ static void rs_tx_status(void *priv_rate
- u8 active_index = 0;
- __le16 fc = hdr->frame_control;
- s32 tpt = 0;
-+ struct ieee80211_supported_band *sband;
-
- IWL_DEBUG_RATE_LIMIT("get frame ack response, update rate scale window\n");
-
-+ sband = local->hw.wiphy->bands[info->band];
-+
- if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1))
- return;
-
-@@ -965,7 +968,8 @@ static void rs_tx_status(void *priv_rate
- }
-
- /* See if there's a better rate or modulation mode to try. */
-- rs_rate_scale_perform(priv, dev, hdr, sta);
-+ if(sta && sta->supp_rates[sband->band])
-+ rs_rate_scale_perform(priv, dev, hdr, sta);
- out:
- rcu_read_unlock();
- return;
-@@ -2090,19 +2094,25 @@ static void rs_get_rate(void *priv_rate,
- __le16 fc;
- struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
- struct iwl_lq_sta *lq_sta;
-+ u64 mask_bit = 0;
-
- IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
-
- rcu_read_lock();
-
- sta = sta_info_get(local, hdr->addr1);
-+ if (sta)
-+ mask_bit = sta->supp_rates[sband->band];
-
- /* Send management frames and broadcast/multicast data using lowest
- * rate. */
- fc = hdr->frame_control;
- if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
- !sta || !sta->rate_ctrl_priv) {
-- sel->rate_idx = rate_lowest_index(local, sband, sta);
-+ if (!mask_bit)
-+ sel->rate_idx = rate_lowest_index(local, sband, NULL);
-+ else
-+ sel->rate_idx = rate_lowest_index(local, sband, sta);
- goto out;
- }
-