diff options
Diffstat (limited to 'net/mac80211/ieee80211.c')
-rw-r--r-- | net/mac80211/ieee80211.c | 64 |
1 files changed, 42 insertions, 22 deletions
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 616ce10d2a38..8c0f782d21e3 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c | |||
@@ -569,12 +569,12 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
569 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 569 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); |
570 | 570 | ||
571 | /* we have tried too many times, receiver does not want A-MPDU */ | 571 | /* we have tried too many times, receiver does not want A-MPDU */ |
572 | if (sta->ampdu_mlme.tid_tx[tid].addba_req_num > HT_AGG_MAX_RETRIES) { | 572 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { |
573 | ret = -EBUSY; | 573 | ret = -EBUSY; |
574 | goto start_ba_exit; | 574 | goto start_ba_exit; |
575 | } | 575 | } |
576 | 576 | ||
577 | state = &sta->ampdu_mlme.tid_tx[tid].state; | 577 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
578 | /* check if the TID is not in aggregation flow already */ | 578 | /* check if the TID is not in aggregation flow already */ |
579 | if (*state != HT_AGG_STATE_IDLE) { | 579 | if (*state != HT_AGG_STATE_IDLE) { |
580 | #ifdef CONFIG_MAC80211_HT_DEBUG | 580 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -585,6 +585,23 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
585 | goto start_ba_exit; | 585 | goto start_ba_exit; |
586 | } | 586 | } |
587 | 587 | ||
588 | /* prepare A-MPDU MLME for Tx aggregation */ | ||
589 | sta->ampdu_mlme.tid_tx[tid] = | ||
590 | kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); | ||
591 | if (!sta->ampdu_mlme.tid_tx[tid]) { | ||
592 | if (net_ratelimit()) | ||
593 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", | ||
594 | tid); | ||
595 | ret = -ENOMEM; | ||
596 | goto start_ba_exit; | ||
597 | } | ||
598 | /* Tx timer */ | ||
599 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = | ||
600 | sta_addba_resp_timer_expired; | ||
601 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data = | ||
602 | (unsigned long)&sta->timer_to_tid[tid]; | ||
603 | init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
604 | |||
588 | /* ensure that TX flow won't interrupt us | 605 | /* ensure that TX flow won't interrupt us |
589 | * until the end of the call to requeue function */ | 606 | * until the end of the call to requeue function */ |
590 | spin_lock_bh(&local->mdev->queue_lock); | 607 | spin_lock_bh(&local->mdev->queue_lock); |
@@ -596,11 +613,10 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
596 | * don't switch to aggregation */ | 613 | * don't switch to aggregation */ |
597 | if (ret) { | 614 | if (ret) { |
598 | #ifdef CONFIG_MAC80211_HT_DEBUG | 615 | #ifdef CONFIG_MAC80211_HT_DEBUG |
599 | printk(KERN_DEBUG "BA request denied - no queue available for" | 616 | printk(KERN_DEBUG "BA request denied - queue unavailable for" |
600 | " tid %d\n", tid); | 617 | " tid %d\n", tid); |
601 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 618 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
602 | spin_unlock_bh(&local->mdev->queue_lock); | 619 | goto start_ba_err; |
603 | goto start_ba_exit; | ||
604 | } | 620 | } |
605 | sdata = sta->sdata; | 621 | sdata = sta->sdata; |
606 | 622 | ||
@@ -618,38 +634,40 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
618 | * allocated queue */ | 634 | * allocated queue */ |
619 | ieee80211_ht_agg_queue_remove(local, sta, tid, 0); | 635 | ieee80211_ht_agg_queue_remove(local, sta, tid, 0); |
620 | #ifdef CONFIG_MAC80211_HT_DEBUG | 636 | #ifdef CONFIG_MAC80211_HT_DEBUG |
621 | printk(KERN_DEBUG "BA request denied - HW or queue unavailable" | 637 | printk(KERN_DEBUG "BA request denied - HW unavailable for" |
622 | " for tid %d\n", tid); | 638 | " tid %d\n", tid); |
623 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 639 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
624 | spin_unlock_bh(&local->mdev->queue_lock); | ||
625 | *state = HT_AGG_STATE_IDLE; | 640 | *state = HT_AGG_STATE_IDLE; |
626 | goto start_ba_exit; | 641 | goto start_ba_err; |
627 | } | 642 | } |
628 | 643 | ||
629 | /* Will put all the packets in the new SW queue */ | 644 | /* Will put all the packets in the new SW queue */ |
630 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); | 645 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); |
631 | spin_unlock_bh(&local->mdev->queue_lock); | 646 | spin_unlock_bh(&local->mdev->queue_lock); |
632 | 647 | ||
633 | /* We have most probably almost emptied the legacy queue */ | ||
634 | /* ieee80211_wake_queue(local_to_hw(local), ieee802_1d_to_ac[tid]); */ | ||
635 | |||
636 | /* send an addBA request */ | 648 | /* send an addBA request */ |
637 | sta->ampdu_mlme.dialog_token_allocator++; | 649 | sta->ampdu_mlme.dialog_token_allocator++; |
638 | sta->ampdu_mlme.tid_tx[tid].dialog_token = | 650 | sta->ampdu_mlme.tid_tx[tid]->dialog_token = |
639 | sta->ampdu_mlme.dialog_token_allocator; | 651 | sta->ampdu_mlme.dialog_token_allocator; |
640 | sta->ampdu_mlme.tid_tx[tid].ssn = start_seq_num; | 652 | sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; |
641 | 653 | ||
642 | ieee80211_send_addba_request(sta->sdata->dev, ra, tid, | 654 | ieee80211_send_addba_request(sta->sdata->dev, ra, tid, |
643 | sta->ampdu_mlme.tid_tx[tid].dialog_token, | 655 | sta->ampdu_mlme.tid_tx[tid]->dialog_token, |
644 | sta->ampdu_mlme.tid_tx[tid].ssn, | 656 | sta->ampdu_mlme.tid_tx[tid]->ssn, |
645 | 0x40, 5000); | 657 | 0x40, 5000); |
646 | 658 | ||
647 | /* activate the timer for the recipient's addBA response */ | 659 | /* activate the timer for the recipient's addBA response */ |
648 | sta->ampdu_mlme.tid_tx[tid].addba_resp_timer.expires = | 660 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = |
649 | jiffies + ADDBA_RESP_INTERVAL; | 661 | jiffies + ADDBA_RESP_INTERVAL; |
650 | add_timer(&sta->ampdu_mlme.tid_tx[tid].addba_resp_timer); | 662 | add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); |
651 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); | 663 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); |
664 | goto start_ba_exit; | ||
652 | 665 | ||
666 | start_ba_err: | ||
667 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
668 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
669 | spin_unlock_bh(&local->mdev->queue_lock); | ||
670 | ret = -EBUSY; | ||
653 | start_ba_exit: | 671 | start_ba_exit: |
654 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 672 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); |
655 | rcu_read_unlock(); | 673 | rcu_read_unlock(); |
@@ -683,7 +701,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | |||
683 | } | 701 | } |
684 | 702 | ||
685 | /* check if the TID is in aggregation */ | 703 | /* check if the TID is in aggregation */ |
686 | state = &sta->ampdu_mlme.tid_tx[tid].state; | 704 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
687 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 705 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); |
688 | 706 | ||
689 | if (*state != HT_AGG_STATE_OPERATIONAL) { | 707 | if (*state != HT_AGG_STATE_OPERATIONAL) { |
@@ -741,7 +759,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
741 | return; | 759 | return; |
742 | } | 760 | } |
743 | 761 | ||
744 | state = &sta->ampdu_mlme.tid_tx[tid].state; | 762 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
745 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 763 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); |
746 | 764 | ||
747 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | 765 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { |
@@ -790,7 +808,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | |||
790 | rcu_read_unlock(); | 808 | rcu_read_unlock(); |
791 | return; | 809 | return; |
792 | } | 810 | } |
793 | state = &sta->ampdu_mlme.tid_tx[tid].state; | 811 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
794 | 812 | ||
795 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 813 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); |
796 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { | 814 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { |
@@ -819,7 +837,9 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | |||
819 | * necessarily stopped */ | 837 | * necessarily stopped */ |
820 | netif_schedule(local->mdev); | 838 | netif_schedule(local->mdev); |
821 | *state = HT_AGG_STATE_IDLE; | 839 | *state = HT_AGG_STATE_IDLE; |
822 | sta->ampdu_mlme.tid_tx[tid].addba_req_num = 0; | 840 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
841 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
842 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
823 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 843 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); |
824 | 844 | ||
825 | rcu_read_unlock(); | 845 | rcu_read_unlock(); |