--- /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;
+ }
+