Skip to content

Commit

Permalink
mac80211: Fix rate reporting regression
Browse files Browse the repository at this point in the history
Mattias Nissler's "clean up rate selection" patch incorrectly changes
the behavior of txrate setting in sta_info. This patch backs out parts
of the rate selection consolidation in order to fix this issue for now.

Signed-off-by: Michael Wu <flamingice@sourmilk.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Michael Wu authored and David S. Miller committed Jan 28, 2008
1 parent 9ab4617 commit 2bc454b
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 25 deletions.
10 changes: 8 additions & 2 deletions drivers/net/wireless/iwlwifi/iwl-3945-rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -657,14 +657,20 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct sta_info *sta;
u16 rate_mask;
u16 fc, rate_mask;
struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
DECLARE_MAC_BUF(mac);

IWL_DEBUG_RATE("enter\n");

sta = sta_info_get(local, hdr->addr1);
if (!sta || !sta->rate_ctrl_priv) {

/* 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 || !sta->rate_ctrl_priv) {
IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
if (sta)
Expand Down
7 changes: 6 additions & 1 deletion drivers/net/wireless/iwlwifi/iwl-4965-rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2017,14 +2017,19 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
struct ieee80211_conf *conf = &local->hw.conf;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct sta_info *sta;
u16 fc;
struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
struct iwl4965_rate_scale_priv *lq;

IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");

sta = sta_info_get(local, hdr->addr1);

if (!sta || !sta->rate_ctrl_priv) {
/* Send management frames and broadcast/multicast data using lowest
* rate. */
fc = le16_to_cpu(hdr->frame_control);
if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
!sta || !sta->rate_ctrl_priv) {
sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
if (sta)
sta_info_put(sta);
Expand Down
18 changes: 1 addition & 17 deletions net/mac80211/ieee80211_rate.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,29 +168,13 @@ void rate_control_get_rate(struct net_device *dev,
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct rate_control_ref *ref = local->rate_ctrl;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct sta_info *sta = sta_info_get(local, hdr->addr1);
int i;
u16 fc;

memset(sel, 0, sizeof(struct rate_selection));

/* 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))
sel->rate = rate_lowest(local, mode, sta);

/* If a forced rate is in effect, select it. */
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
sel->rate = &mode->rates[sdata->bss->force_unicast_rateidx];

/* If we haven't found the rate yet, ask the rate control algo. */
if (!sel->rate)
ref->ops->get_rate(ref->priv, dev, mode, skb, sel);
ref->ops->get_rate(ref->priv, dev, mode, skb, sel);

/* Select a non-ERP backup rate. */
if (!sel->nonerp) {
Expand Down
20 changes: 17 additions & 3 deletions net/mac80211/rc80211_pid_algo.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,22 +310,36 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
int rateidx;
u16 fc;

sta = sta_info_get(local, hdr->addr1);

if (!sta) {
sel->rate = rate_lowest(local, mode, NULL);
sta_info_put(sta);
/* 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) {
sel->rate = rate_lowest(local, mode, sta);
if (sta)
sta_info_put(sta);
return;
}

/* If a forced rate is in effect, select it. */
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
sta->txrate = sdata->bss->force_unicast_rateidx;

rateidx = sta->txrate;

if (rateidx >= mode->num_rates)
rateidx = mode->num_rates - 1;

sta->last_txrate = rateidx;

sta_info_put(sta);

sel->rate = &mode->rates[rateidx];
Expand Down
19 changes: 17 additions & 2 deletions net/mac80211/rc80211_simple.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,21 +207,36 @@ rate_control_simple_get_rate(void *priv, struct net_device *dev,
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
int rateidx;
u16 fc;

sta = sta_info_get(local, hdr->addr1);

if (!sta) {
sel->rate = rate_lowest(local, mode, NULL);
/* 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) {
sel->rate = rate_lowest(local, mode, sta);
if (sta)
sta_info_put(sta);
return;
}

/* If a forced rate is in effect, select it. */
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
sta->txrate = sdata->bss->force_unicast_rateidx;

rateidx = sta->txrate;

if (rateidx >= mode->num_rates)
rateidx = mode->num_rates - 1;

sta->last_txrate = rateidx;

sta_info_put(sta);

sel->rate = &mode->rates[rateidx];
Expand Down

0 comments on commit 2bc454b

Please sign in to comment.