]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.fixes/iwlwifi-fix-rs_get_rate-oops.patch
Move xen patchset to new version's subdir.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.fixes / iwlwifi-fix-rs_get_rate-oops.patch
diff --git a/src/patches/suse-2.6.27.31/patches.fixes/iwlwifi-fix-rs_get_rate-oops.patch b/src/patches/suse-2.6.27.31/patches.fixes/iwlwifi-fix-rs_get_rate-oops.patch
new file mode 100644 (file)
index 0000000..34879cc
--- /dev/null
@@ -0,0 +1,119 @@
+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;
+       }