Commit c338ba3c authored by Abbas, Mohamed's avatar Abbas, Mohamed Committed by John W. Linville

iwlwifi: fix rs_get_rate WARN_ON()

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_rateSigned-off-by: default avatarmohamed abbas <mohamed.abbas@intel.com>
Signed-off-by: default avatarReinette Chatre <reinette.chatre@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent b4068a80
...@@ -638,12 +638,16 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, ...@@ -638,12 +638,16 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
s8 scale_action = 0; s8 scale_action = 0;
unsigned long flags; unsigned long flags;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
u16 fc, rate_mask; u16 fc;
u16 rate_mask = 0;
struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
IWL_DEBUG_RATE("enter\n"); IWL_DEBUG_RATE("enter\n");
if (sta)
rate_mask = sta->supp_rates[sband->band];
/* Send management frames and broadcast/multicast data using lowest /* Send management frames and broadcast/multicast data using lowest
* rate. */ * rate. */
fc = le16_to_cpu(hdr->frame_control); fc = le16_to_cpu(hdr->frame_control);
...@@ -651,11 +655,15 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, ...@@ -651,11 +655,15 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
is_multicast_ether_addr(hdr->addr1) || is_multicast_ether_addr(hdr->addr1) ||
!sta || !priv_sta) { !sta || !priv_sta) {
IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
info->control.rates[0].idx = rate_lowest_index(sband, sta); if (!rate_mask)
info->control.rates[0].idx =
rate_lowest_index(sband, NULL);
else
info->control.rates[0].idx =
rate_lowest_index(sband, sta);
return; return;
} }
rate_mask = sta->supp_rates[sband->band];
index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
if (sband->band == IEEE80211_BAND_5GHZ) if (sband->band == IEEE80211_BAND_5GHZ)
......
...@@ -944,6 +944,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, ...@@ -944,6 +944,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
} }
/* See if there's a better rate or modulation mode to try. */ /* See if there's a better rate or modulation mode to try. */
if (sta && sta->supp_rates[sband->band])
rs_rate_scale_perform(priv, hdr, sta, lq_sta); rs_rate_scale_perform(priv, hdr, sta, lq_sta);
out: out:
return; return;
...@@ -2101,14 +2102,23 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, ...@@ -2101,14 +2102,23 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_lq_sta *lq_sta = priv_sta; struct iwl_lq_sta *lq_sta = priv_sta;
int rate_idx; int rate_idx;
u64 mask_bit = 0;
IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
if (sta)
mask_bit = sta->supp_rates[sband->band];
/* Send management frames and broadcast/multicast data using lowest /* Send management frames and broadcast/multicast data using lowest
* rate. */ * rate. */
if (!ieee80211_is_data(hdr->frame_control) || if (!ieee80211_is_data(hdr->frame_control) ||
is_multicast_ether_addr(hdr->addr1) || !sta || !lq_sta) { is_multicast_ether_addr(hdr->addr1) || !sta || !lq_sta) {
info->control.rates[0].idx = rate_lowest_index(sband, sta); if (!mask_bit)
info->control.rates[0].idx =
rate_lowest_index(sband, NULL);
else
info->control.rates[0].idx =
rate_lowest_index(sband, sta);
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment