aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/status.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/status.c')
-rw-r--r--net/mac80211/status.c51
1 files changed, 45 insertions, 6 deletions
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 3153c19893b8..38a797217a91 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -157,6 +157,15 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
157 } 157 }
158} 158}
159 159
160/*
161 * Use a static threshold for now, best value to be determined
162 * by testing ...
163 * Should it depend on:
164 * - on # of retransmissions
165 * - current throughput (higher value for higher tpt)?
166 */
167#define STA_LOST_PKT_THRESHOLD 50
168
160void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) 169void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
161{ 170{
162 struct sk_buff *skb2; 171 struct sk_buff *skb2;
@@ -173,6 +182,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
173 int retry_count = -1, i; 182 int retry_count = -1, i;
174 int rates_idx = -1; 183 int rates_idx = -1;
175 bool send_to_cooked; 184 bool send_to_cooked;
185 bool acked;
176 186
177 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { 187 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
178 /* the HW cannot have attempted that rate */ 188 /* the HW cannot have attempted that rate */
@@ -198,8 +208,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
198 if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) 208 if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN))
199 continue; 209 continue;
200 210
201 if (!(info->flags & IEEE80211_TX_STAT_ACK) && 211 acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
202 test_sta_flags(sta, WLAN_STA_PS_STA)) { 212 if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) {
203 /* 213 /*
204 * The STA is in power save mode, so assume 214 * The STA is in power save mode, so assume
205 * that this TX packet failed because of that. 215 * that this TX packet failed because of that.
@@ -231,7 +241,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
231 rcu_read_unlock(); 241 rcu_read_unlock();
232 return; 242 return;
233 } else { 243 } else {
234 if (!(info->flags & IEEE80211_TX_STAT_ACK)) 244 if (!acked)
235 sta->tx_retry_failed++; 245 sta->tx_retry_failed++;
236 sta->tx_retry_count += retry_count; 246 sta->tx_retry_count += retry_count;
237 } 247 }
@@ -240,9 +250,25 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
240 if (ieee80211_vif_is_mesh(&sta->sdata->vif)) 250 if (ieee80211_vif_is_mesh(&sta->sdata->vif))
241 ieee80211s_update_metric(local, sta, skb); 251 ieee80211s_update_metric(local, sta, skb);
242 252
243 if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && 253 if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked)
244 (info->flags & IEEE80211_TX_STAT_ACK))
245 ieee80211_frame_acked(sta, skb); 254 ieee80211_frame_acked(sta, skb);
255
256 if ((sta->sdata->vif.type == NL80211_IFTYPE_STATION) &&
257 (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS))
258 ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data, acked);
259
260 if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
261 if (info->flags & IEEE80211_TX_STAT_ACK) {
262 if (sta->lost_packets)
263 sta->lost_packets = 0;
264 } else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) {
265 cfg80211_cqm_pktloss_notify(sta->sdata->dev,
266 sta->sta.addr,
267 sta->lost_packets,
268 GFP_ATOMIC);
269 sta->lost_packets = 0;
270 }
271 }
246 } 272 }
247 273
248 rcu_read_unlock(); 274 rcu_read_unlock();
@@ -295,10 +321,23 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
295 msecs_to_jiffies(10)); 321 msecs_to_jiffies(10));
296 } 322 }
297 323
298 if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) 324 if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
325 struct ieee80211_work *wk;
326
327 rcu_read_lock();
328 list_for_each_entry_rcu(wk, &local->work_list, list) {
329 if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX)
330 continue;
331 if (wk->offchan_tx.frame != skb)
332 continue;
333 wk->offchan_tx.frame = NULL;
334 break;
335 }
336 rcu_read_unlock();
299 cfg80211_mgmt_tx_status( 337 cfg80211_mgmt_tx_status(
300 skb->dev, (unsigned long) skb, skb->data, skb->len, 338 skb->dev, (unsigned long) skb, skb->data, skb->len,
301 !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); 339 !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC);
340 }
302 341
303 /* this was a transmitted frame, but now we want to reuse it */ 342 /* this was a transmitted frame, but now we want to reuse it */
304 skb_orphan(skb); 343 skb_orphan(skb);