1 From: Abbas, Mohamed <mohamed.abbas@intel.com>
2 Subject: iwlwifi: fix rs_get_rate WARN_ON()
3 Patch-mainline: not yet
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.
17 http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1822
18 http://www.kerneloops.org/searchweek.php?search=rs_get_rate
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>
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(-)
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;
39 struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
42 @@ -661,6 +662,8 @@ static void rs_get_rate(void *priv_rate,
45 sta = sta_info_get(local, hdr->addr1);
47 + rate_mask = sta->supp_rates[sband->band];
49 /* Send management frames and broadcast/multicast data using lowest
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);
57 + sel->rate_idx = rate_lowest_index(local, sband, NULL);
59 + sel->rate_idx = rate_lowest_index(local, sband, sta);
64 - rate_mask = sta->supp_rates[sband->band];
65 index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
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
72 __le16 fc = hdr->frame_control;
74 + struct ieee80211_supported_band *sband;
76 IWL_DEBUG_RATE_LIMIT("get frame ack response, update rate scale window\n");
78 + sband = local->hw.wiphy->bands[info->band];
80 if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1))
83 @@ -965,7 +968,8 @@ static void rs_tx_status(void *priv_rate
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);
93 @@ -2090,19 +2094,25 @@ static void rs_get_rate(void *priv_rate,
95 struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
96 struct iwl_lq_sta *lq_sta;
99 IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
103 sta = sta_info_get(local, hdr->addr1);
105 + mask_bit = sta->supp_rates[sband->band];
107 /* Send management frames and broadcast/multicast data using lowest
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);
114 + sel->rate_idx = rate_lowest_index(local, sband, NULL);
116 + sel->rate_idx = rate_lowest_index(local, sband, sta);