]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.fixes/iwlwifi-fix-rs_get_rate-oops.patch
Updated xen patches taken from suse.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.fixes / iwlwifi-fix-rs_get_rate-oops.patch
1 From: Abbas, Mohamed <mohamed.abbas@intel.com>
2 Subject: iwlwifi: fix rs_get_rate WARN_ON()
3 Patch-mainline: not yet
4 References: bnc#456002
5
6 In ieee80211_sta structure there is u64 supp_rates[IEEE80211_NUM_BANDS]
7 this is filled with all support rate from assoc_resp. If we associate
8 with G-band AP only supp_rates of G-band will be set the other band
9 supp_rates will be set to 0. If the user type this command
10 this will cause mac80211 to set to new channel, mac80211
11 does not disassociate in setting new channel, so the active
12 band is now A-band. then in handling the new essid mac80211 will
13 kick in the assoc steps which involve sending disassociation frame.
14 in this mac80211 will WARN_ON sta->supp_rates[A_BAND] == 0.
15
16 This fixes:
17 http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1822
18 http://www.kerneloops.org/searchweek.php?search=rs_get_rate
19
20 Signed-off-by: mohamed abbas <mohamed.abbas@intel.com>
21 Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
22 Acked-by: Helmut Schaa <hschaa@suse.de>
23 Acked-by: Jiri Benc <jbenc@suse.cz>
24
25 ---
26 drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 11 ++++++++---
27 drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 14 ++++++++++++--
28 2 files changed, 20 insertions(+), 5 deletions(-)
29
30 --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
31 +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
32 @@ -652,7 +652,8 @@ static void rs_get_rate(void *priv_rate,
33 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
34 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
35 struct sta_info *sta;
36 - u16 fc, rate_mask;
37 + u16 fc;
38 + u16 rate_mask = 0;
39 struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
40 DECLARE_MAC_BUF(mac);
41
42 @@ -661,6 +662,8 @@ static void rs_get_rate(void *priv_rate,
43 rcu_read_lock();
44
45 sta = sta_info_get(local, hdr->addr1);
46 + if (sta)
47 + rate_mask = sta->supp_rates[sband->band];
48
49 /* Send management frames and broadcast/multicast data using lowest
50 * rate. */
51 @@ -669,12 +672,14 @@ static void rs_get_rate(void *priv_rate,
52 is_multicast_ether_addr(hdr->addr1) ||
53 !sta || !sta->rate_ctrl_priv) {
54 IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
55 - sel->rate_idx = rate_lowest_index(local, sband, sta);
56 + if (!rate_mask)
57 + sel->rate_idx = rate_lowest_index(local, sband, NULL);
58 + else
59 + sel->rate_idx = rate_lowest_index(local, sband, sta);
60 rcu_read_unlock();
61 return;
62 }
63
64 - rate_mask = sta->supp_rates[sband->band];
65 index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
66
67 if (sband->band == IEEE80211_BAND_5GHZ)
68 --- linux-2.6.27.orig/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
69 +++ linux-2.6.27/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
70 @@ -795,9 +795,12 @@ static void rs_tx_status(void *priv_rate
71 u8 active_index = 0;
72 __le16 fc = hdr->frame_control;
73 s32 tpt = 0;
74 + struct ieee80211_supported_band *sband;
75
76 IWL_DEBUG_RATE_LIMIT("get frame ack response, update rate scale window\n");
77
78 + sband = local->hw.wiphy->bands[info->band];
79 +
80 if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1))
81 return;
82
83 @@ -965,7 +968,8 @@ static void rs_tx_status(void *priv_rate
84 }
85
86 /* See if there's a better rate or modulation mode to try. */
87 - rs_rate_scale_perform(priv, dev, hdr, sta);
88 + if(sta && sta->supp_rates[sband->band])
89 + rs_rate_scale_perform(priv, dev, hdr, sta);
90 out:
91 rcu_read_unlock();
92 return;
93 @@ -2090,19 +2094,25 @@ static void rs_get_rate(void *priv_rate,
94 __le16 fc;
95 struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
96 struct iwl_lq_sta *lq_sta;
97 + u64 mask_bit = 0;
98
99 IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
100
101 rcu_read_lock();
102
103 sta = sta_info_get(local, hdr->addr1);
104 + if (sta)
105 + mask_bit = sta->supp_rates[sband->band];
106
107 /* Send management frames and broadcast/multicast data using lowest
108 * rate. */
109 fc = hdr->frame_control;
110 if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
111 !sta || !sta->rate_ctrl_priv) {
112 - sel->rate_idx = rate_lowest_index(local, sband, sta);
113 + if (!mask_bit)
114 + sel->rate_idx = rate_lowest_index(local, sband, NULL);
115 + else
116 + sel->rate_idx = rate_lowest_index(local, sband, sta);
117 goto out;
118 }
119