Skip to content

Commit

Permalink
iwlwifi: fix rs_get_rate WARN_ON()
Browse files Browse the repository at this point in the history
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>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Abbas, Mohamed authored and John W. Linville committed Jan 23, 2009
1 parent b4068a8 commit c338ba3
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 5 deletions.
14 changes: 11 additions & 3 deletions drivers/net/wireless/iwlwifi/iwl-3945-rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -638,24 +638,32 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
s8 scale_action = 0;
unsigned long flags;
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 ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);

IWL_DEBUG_RATE("enter\n");

if (sta)
rate_mask = sta->supp_rates[sband->band];

/* Send management frames and broadcast/multicast data using lowest
* rate. */
fc = le16_to_cpu(hdr->frame_control);
if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
is_multicast_ether_addr(hdr->addr1) ||
!sta || !priv_sta) {
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;
}

rate_mask = sta->supp_rates[sband->band];
index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);

if (sband->band == IEEE80211_BAND_5GHZ)
Expand Down
14 changes: 12 additions & 2 deletions drivers/net/wireless/iwlwifi/iwl-agn-rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,8 @@ 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. */
rs_rate_scale_perform(priv, hdr, sta, lq_sta);
if (sta && sta->supp_rates[sband->band])
rs_rate_scale_perform(priv, hdr, sta, lq_sta);
out:
return;
}
Expand Down Expand Up @@ -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 iwl_lq_sta *lq_sta = priv_sta;
int rate_idx;
u64 mask_bit = 0;

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
* rate. */
if (!ieee80211_is_data(hdr->frame_control) ||
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;
}

Expand Down

0 comments on commit c338ba3

Please sign in to comment.