diff options
Diffstat (limited to 'net/mac80211/status.c')
-rw-r--r-- | net/mac80211/status.c | 145 |
1 files changed, 71 insertions, 74 deletions
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 21fa5c72ea14..2d931ad0e90a 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -325,6 +325,75 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band | |||
325 | 325 | ||
326 | } | 326 | } |
327 | 327 | ||
328 | static void ieee80211_report_used_skb(struct ieee80211_local *local, | ||
329 | struct sk_buff *skb, bool dropped) | ||
330 | { | ||
331 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
332 | struct ieee80211_hdr *hdr = (void *)skb->data; | ||
333 | bool acked = info->flags & IEEE80211_TX_STAT_ACK; | ||
334 | |||
335 | if (dropped) | ||
336 | acked = false; | ||
337 | |||
338 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { | ||
339 | struct ieee80211_sub_if_data *sdata = NULL; | ||
340 | struct ieee80211_sub_if_data *iter_sdata; | ||
341 | u64 cookie = (unsigned long)skb; | ||
342 | |||
343 | rcu_read_lock(); | ||
344 | |||
345 | if (skb->dev) { | ||
346 | list_for_each_entry_rcu(iter_sdata, &local->interfaces, | ||
347 | list) { | ||
348 | if (!iter_sdata->dev) | ||
349 | continue; | ||
350 | |||
351 | if (skb->dev == iter_sdata->dev) { | ||
352 | sdata = iter_sdata; | ||
353 | break; | ||
354 | } | ||
355 | } | ||
356 | } else { | ||
357 | sdata = rcu_dereference(local->p2p_sdata); | ||
358 | } | ||
359 | |||
360 | if (!sdata) | ||
361 | skb->dev = NULL; | ||
362 | else if (ieee80211_is_nullfunc(hdr->frame_control) || | ||
363 | ieee80211_is_qos_nullfunc(hdr->frame_control)) { | ||
364 | cfg80211_probe_status(sdata->dev, hdr->addr1, | ||
365 | cookie, acked, GFP_ATOMIC); | ||
366 | } else { | ||
367 | cfg80211_mgmt_tx_status(&sdata->wdev, cookie, skb->data, | ||
368 | skb->len, acked, GFP_ATOMIC); | ||
369 | } | ||
370 | |||
371 | rcu_read_unlock(); | ||
372 | } | ||
373 | |||
374 | if (unlikely(info->ack_frame_id)) { | ||
375 | struct sk_buff *ack_skb; | ||
376 | unsigned long flags; | ||
377 | |||
378 | spin_lock_irqsave(&local->ack_status_lock, flags); | ||
379 | ack_skb = idr_find(&local->ack_status_frames, | ||
380 | info->ack_frame_id); | ||
381 | if (ack_skb) | ||
382 | idr_remove(&local->ack_status_frames, | ||
383 | info->ack_frame_id); | ||
384 | spin_unlock_irqrestore(&local->ack_status_lock, flags); | ||
385 | |||
386 | if (ack_skb) { | ||
387 | if (!dropped) { | ||
388 | /* consumes ack_skb */ | ||
389 | skb_complete_wifi_ack(ack_skb, acked); | ||
390 | } else { | ||
391 | dev_kfree_skb_any(ack_skb); | ||
392 | } | ||
393 | } | ||
394 | } | ||
395 | } | ||
396 | |||
328 | /* | 397 | /* |
329 | * Use a static threshold for now, best value to be determined | 398 | * Use a static threshold for now, best value to be determined |
330 | * by testing ... | 399 | * by testing ... |
@@ -516,62 +585,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
516 | msecs_to_jiffies(10)); | 585 | msecs_to_jiffies(10)); |
517 | } | 586 | } |
518 | 587 | ||
519 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { | 588 | ieee80211_report_used_skb(local, skb, false); |
520 | u64 cookie = (unsigned long)skb; | ||
521 | bool found = false; | ||
522 | |||
523 | acked = info->flags & IEEE80211_TX_STAT_ACK; | ||
524 | |||
525 | rcu_read_lock(); | ||
526 | |||
527 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
528 | if (!sdata->dev) | ||
529 | continue; | ||
530 | |||
531 | if (skb->dev != sdata->dev) | ||
532 | continue; | ||
533 | |||
534 | found = true; | ||
535 | break; | ||
536 | } | ||
537 | |||
538 | if (!skb->dev) { | ||
539 | sdata = rcu_dereference(local->p2p_sdata); | ||
540 | if (sdata) | ||
541 | found = true; | ||
542 | } | ||
543 | |||
544 | if (!found) | ||
545 | skb->dev = NULL; | ||
546 | else if (ieee80211_is_nullfunc(hdr->frame_control) || | ||
547 | ieee80211_is_qos_nullfunc(hdr->frame_control)) { | ||
548 | cfg80211_probe_status(sdata->dev, hdr->addr1, | ||
549 | cookie, acked, GFP_ATOMIC); | ||
550 | } else { | ||
551 | cfg80211_mgmt_tx_status(&sdata->wdev, cookie, skb->data, | ||
552 | skb->len, acked, GFP_ATOMIC); | ||
553 | } | ||
554 | |||
555 | rcu_read_unlock(); | ||
556 | } | ||
557 | |||
558 | if (unlikely(info->ack_frame_id)) { | ||
559 | struct sk_buff *ack_skb; | ||
560 | unsigned long flags; | ||
561 | |||
562 | spin_lock_irqsave(&local->ack_status_lock, flags); | ||
563 | ack_skb = idr_find(&local->ack_status_frames, | ||
564 | info->ack_frame_id); | ||
565 | if (ack_skb) | ||
566 | idr_remove(&local->ack_status_frames, | ||
567 | info->ack_frame_id); | ||
568 | spin_unlock_irqrestore(&local->ack_status_lock, flags); | ||
569 | |||
570 | /* consumes ack_skb */ | ||
571 | if (ack_skb) | ||
572 | skb_complete_wifi_ack(ack_skb, | ||
573 | info->flags & IEEE80211_TX_STAT_ACK); | ||
574 | } | ||
575 | 589 | ||
576 | /* this was a transmitted frame, but now we want to reuse it */ | 590 | /* this was a transmitted frame, but now we want to reuse it */ |
577 | skb_orphan(skb); | 591 | skb_orphan(skb); |
@@ -647,25 +661,8 @@ EXPORT_SYMBOL(ieee80211_report_low_ack); | |||
647 | void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) | 661 | void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) |
648 | { | 662 | { |
649 | struct ieee80211_local *local = hw_to_local(hw); | 663 | struct ieee80211_local *local = hw_to_local(hw); |
650 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
651 | |||
652 | if (unlikely(info->ack_frame_id)) { | ||
653 | struct sk_buff *ack_skb; | ||
654 | unsigned long flags; | ||
655 | |||
656 | spin_lock_irqsave(&local->ack_status_lock, flags); | ||
657 | ack_skb = idr_find(&local->ack_status_frames, | ||
658 | info->ack_frame_id); | ||
659 | if (ack_skb) | ||
660 | idr_remove(&local->ack_status_frames, | ||
661 | info->ack_frame_id); | ||
662 | spin_unlock_irqrestore(&local->ack_status_lock, flags); | ||
663 | |||
664 | /* consumes ack_skb */ | ||
665 | if (ack_skb) | ||
666 | dev_kfree_skb_any(ack_skb); | ||
667 | } | ||
668 | 664 | ||
665 | ieee80211_report_used_skb(local, skb, true); | ||
669 | dev_kfree_skb_any(skb); | 666 | dev_kfree_skb_any(skb); |
670 | } | 667 | } |
671 | EXPORT_SYMBOL(ieee80211_free_txskb); | 668 | EXPORT_SYMBOL(ieee80211_free_txskb); |