diff options
author | Juuso Oikarinen <juuso.oikarinen@nokia.com> | 2010-04-22 03:27:48 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-04-26 14:11:40 -0400 |
commit | 0c86980817853e4166f66c7cd18bc5fe1adeb5f7 (patch) | |
tree | 945d0486a2bb79e37ee7bde7ea9de510362f5c0d /net/mac80211 | |
parent | 5af55428858a45d94893fd6124d60988e89c0d59 (diff) |
mac80211: Fix sta->last_tx_rate setting with no-op rate control devices
The sta->last_tx_rate is traditionally updated just before transmitting a
frame based on information from the rate control algorithm. However, for
hardware drivers with IEEE80211_HW_HAS_RATE_CONTROL this is not performed,
as the rate control algorithm is not executed, and because the used rate is
not known before the frame has actually been transmitted.
This causes atleast a fixed 1Mb/s to be reported to user space. A few other
instances of code also rely on this information.
Fix this by setting the sta->last_tx_rate in tx_status handling. There, look
for last rates entry set by the driver, and use that as value for
sta->last_tx_rate.
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/status.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 11805a3a626f..94613af009f3 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -171,6 +171,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
171 | struct net_device *prev_dev = NULL; | 171 | struct net_device *prev_dev = NULL; |
172 | struct sta_info *sta, *tmp; | 172 | struct sta_info *sta, *tmp; |
173 | int retry_count = -1, i; | 173 | int retry_count = -1, i; |
174 | int rates_idx = -1; | ||
174 | bool send_to_cooked; | 175 | bool send_to_cooked; |
175 | 176 | ||
176 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 177 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
@@ -178,6 +179,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
178 | if (i >= hw->max_rates) { | 179 | if (i >= hw->max_rates) { |
179 | info->status.rates[i].idx = -1; | 180 | info->status.rates[i].idx = -1; |
180 | info->status.rates[i].count = 0; | 181 | info->status.rates[i].count = 0; |
182 | } else if (info->status.rates[i].idx >= 0) { | ||
183 | rates_idx = i; | ||
181 | } | 184 | } |
182 | 185 | ||
183 | retry_count += info->status.rates[i].count; | 186 | retry_count += info->status.rates[i].count; |
@@ -206,6 +209,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
206 | return; | 209 | return; |
207 | } | 210 | } |
208 | 211 | ||
212 | if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) && | ||
213 | (rates_idx != -1)) | ||
214 | sta->last_tx_rate = info->status.rates[rates_idx]; | ||
215 | |||
209 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | 216 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && |
210 | (ieee80211_is_data_qos(fc))) { | 217 | (ieee80211_is_data_qos(fc))) { |
211 | u16 tid, ssn; | 218 | u16 tid, ssn; |