diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2008-10-24 00:25:27 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-10-31 19:02:14 -0400 |
commit | 8b30b1fe368ab03049435884c11c5c50e4c4ef0b (patch) | |
tree | 02b27b36cf90267d59584b493ad652e3a4cc6a7e | |
parent | 4393dce9402c58744433c7a4f3931e17ddde4fb4 (diff) |
mac80211: Re-enable aggregation
Wireless HW without any dedicated queues for aggregation
do not need the ampdu_queues mechanism present right now
in mac80211. Since mac80211 is still incomplete wrt TX MQ
changes, do not allow aggregation sessions for drivers that
set ampdu_queues.
This is only an interim hack until Intel fixes the requeue issue.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: Luis Rodriguez <Luis.Rodriguez@Atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath9k/main.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 3 | ||||
-rw-r--r-- | include/linux/skbuff.h | 4 | ||||
-rw-r--r-- | include/net/mac80211.h | 8 | ||||
-rw-r--r-- | net/core/skbuff.c | 1 | ||||
-rw-r--r-- | net/mac80211/ht.c | 60 | ||||
-rw-r--r-- | net/mac80211/main.c | 7 | ||||
-rw-r--r-- | net/mac80211/rx.c | 7 | ||||
-rw-r--r-- | net/mac80211/tx.c | 19 | ||||
-rw-r--r-- | net/mac80211/wme.c | 24 |
10 files changed, 76 insertions, 63 deletions
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 795fed5cadfa..f6dc4c826044 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -953,10 +953,7 @@ static int ath_attach(u16 devid, | |||
953 | &sc->sbands[IEEE80211_BAND_5GHZ]; | 953 | &sc->sbands[IEEE80211_BAND_5GHZ]; |
954 | } | 954 | } |
955 | 955 | ||
956 | /* FIXME: Have to figure out proper hw init values later */ | ||
957 | |||
958 | hw->queues = 4; | 956 | hw->queues = 4; |
959 | hw->ampdu_queues = 1; | ||
960 | 957 | ||
961 | /* Register rate control */ | 958 | /* Register rate control */ |
962 | hw->rate_control_algorithm = "ath9k_rate_control"; | 959 | hw->rate_control_algorithm = "ath9k_rate_control"; |
@@ -1745,7 +1742,8 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1745 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | 1742 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
1746 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | 1743 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | |
1747 | IEEE80211_HW_SIGNAL_DBM | | 1744 | IEEE80211_HW_SIGNAL_DBM | |
1748 | IEEE80211_HW_NOISE_DBM; | 1745 | IEEE80211_HW_NOISE_DBM | |
1746 | IEEE80211_HW_AMPDU_AGGREGATION; | ||
1749 | 1747 | ||
1750 | hw->wiphy->interface_modes = | 1748 | hw->wiphy->interface_modes = |
1751 | BIT(NL80211_IFTYPE_AP) | | 1749 | BIT(NL80211_IFTYPE_AP) | |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 20c7ff382914..ba05f5ddc6d0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -871,7 +871,8 @@ int iwl_setup_mac(struct iwl_priv *priv) | |||
871 | 871 | ||
872 | /* Tell mac80211 our characteristics */ | 872 | /* Tell mac80211 our characteristics */ |
873 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | 873 | hw->flags = IEEE80211_HW_SIGNAL_DBM | |
874 | IEEE80211_HW_NOISE_DBM; | 874 | IEEE80211_HW_NOISE_DBM | |
875 | IEEE80211_HW_AMPDU_AGGREGATION; | ||
875 | hw->wiphy->interface_modes = | 876 | hw->wiphy->interface_modes = |
876 | BIT(NL80211_IFTYPE_AP) | | 877 | BIT(NL80211_IFTYPE_AP) | |
877 | BIT(NL80211_IFTYPE_STATION) | | 878 | BIT(NL80211_IFTYPE_STATION) | |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 487e34507b41..a01b6f84e3bc 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -250,6 +250,9 @@ typedef unsigned char *sk_buff_data_t; | |||
250 | * @tc_verd: traffic control verdict | 250 | * @tc_verd: traffic control verdict |
251 | * @ndisc_nodetype: router type (from link layer) | 251 | * @ndisc_nodetype: router type (from link layer) |
252 | * @do_not_encrypt: set to prevent encryption of this frame | 252 | * @do_not_encrypt: set to prevent encryption of this frame |
253 | * @requeue: set to indicate that the wireless core should attempt | ||
254 | * a software retry on this frame if we failed to | ||
255 | * receive an ACK for it | ||
253 | * @dma_cookie: a cookie to one of several possible DMA operations | 256 | * @dma_cookie: a cookie to one of several possible DMA operations |
254 | * done by skb DMA functions | 257 | * done by skb DMA functions |
255 | * @secmark: security marking | 258 | * @secmark: security marking |
@@ -326,6 +329,7 @@ struct sk_buff { | |||
326 | #endif | 329 | #endif |
327 | #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) | 330 | #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) |
328 | __u8 do_not_encrypt:1; | 331 | __u8 do_not_encrypt:1; |
332 | __u8 requeue:1; | ||
329 | #endif | 333 | #endif |
330 | /* 0/13/14 bit hole */ | 334 | /* 0/13/14 bit hole */ |
331 | 335 | ||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 16c895969e6e..bba96a203885 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -242,7 +242,6 @@ struct ieee80211_bss_conf { | |||
242 | * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be | 242 | * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be |
243 | * set by rate control algorithms to indicate probe rate, will | 243 | * set by rate control algorithms to indicate probe rate, will |
244 | * be cleared for fragmented frames (except on the last fragment) | 244 | * be cleared for fragmented frames (except on the last fragment) |
245 | * @IEEE80211_TX_CTL_REQUEUE: REMOVE THIS | ||
246 | */ | 245 | */ |
247 | enum mac80211_tx_control_flags { | 246 | enum mac80211_tx_control_flags { |
248 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), | 247 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), |
@@ -258,9 +257,6 @@ enum mac80211_tx_control_flags { | |||
258 | IEEE80211_TX_STAT_AMPDU = BIT(10), | 257 | IEEE80211_TX_STAT_AMPDU = BIT(10), |
259 | IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), | 258 | IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), |
260 | IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), | 259 | IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), |
261 | |||
262 | /* XXX: remove this */ | ||
263 | IEEE80211_TX_CTL_REQUEUE = BIT(13), | ||
264 | }; | 260 | }; |
265 | 261 | ||
266 | enum mac80211_rate_control_flags { | 262 | enum mac80211_rate_control_flags { |
@@ -847,6 +843,9 @@ enum ieee80211_tkip_key_type { | |||
847 | * @IEEE80211_HW_SPECTRUM_MGMT: | 843 | * @IEEE80211_HW_SPECTRUM_MGMT: |
848 | * Hardware supports spectrum management defined in 802.11h | 844 | * Hardware supports spectrum management defined in 802.11h |
849 | * Measurement, Channel Switch, Quieting, TPC | 845 | * Measurement, Channel Switch, Quieting, TPC |
846 | * | ||
847 | * @IEEE80211_HW_AMPDU_AGGREGATION: | ||
848 | * Hardware supports 11n A-MPDU aggregation. | ||
850 | */ | 849 | */ |
851 | enum ieee80211_hw_flags { | 850 | enum ieee80211_hw_flags { |
852 | IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, | 851 | IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, |
@@ -858,6 +857,7 @@ enum ieee80211_hw_flags { | |||
858 | IEEE80211_HW_SIGNAL_DBM = 1<<7, | 857 | IEEE80211_HW_SIGNAL_DBM = 1<<7, |
859 | IEEE80211_HW_NOISE_DBM = 1<<8, | 858 | IEEE80211_HW_NOISE_DBM = 1<<8, |
860 | IEEE80211_HW_SPECTRUM_MGMT = 1<<9, | 859 | IEEE80211_HW_SPECTRUM_MGMT = 1<<9, |
860 | IEEE80211_HW_AMPDU_AGGREGATION = 1<<10, | ||
861 | }; | 861 | }; |
862 | 862 | ||
863 | /** | 863 | /** |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index cdfe473181af..c4c8a33f3418 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -544,6 +544,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) | |||
544 | C(truesize); | 544 | C(truesize); |
545 | #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) | 545 | #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) |
546 | C(do_not_encrypt); | 546 | C(do_not_encrypt); |
547 | C(requeue); | ||
547 | #endif | 548 | #endif |
548 | atomic_set(&n->users, 1); | 549 | atomic_set(&n->users, 1); |
549 | 550 | ||
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 42c3e590df98..08009d4b7d6e 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -458,7 +458,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
458 | u8 *state; | 458 | u8 *state; |
459 | int ret; | 459 | int ret; |
460 | 460 | ||
461 | if (tid >= STA_TID_NUM) | 461 | if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) |
462 | return -EINVAL; | 462 | return -EINVAL; |
463 | 463 | ||
464 | #ifdef CONFIG_MAC80211_HT_DEBUG | 464 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -515,17 +515,19 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
515 | (unsigned long)&sta->timer_to_tid[tid]; | 515 | (unsigned long)&sta->timer_to_tid[tid]; |
516 | init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | 516 | init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); |
517 | 517 | ||
518 | /* create a new queue for this aggregation */ | 518 | if (hw->ampdu_queues) { |
519 | ret = ieee80211_ht_agg_queue_add(local, sta, tid); | 519 | /* create a new queue for this aggregation */ |
520 | ret = ieee80211_ht_agg_queue_add(local, sta, tid); | ||
520 | 521 | ||
521 | /* case no queue is available to aggregation | 522 | /* case no queue is available to aggregation |
522 | * don't switch to aggregation */ | 523 | * don't switch to aggregation */ |
523 | if (ret) { | 524 | if (ret) { |
524 | #ifdef CONFIG_MAC80211_HT_DEBUG | 525 | #ifdef CONFIG_MAC80211_HT_DEBUG |
525 | printk(KERN_DEBUG "BA request denied - queue unavailable for" | 526 | printk(KERN_DEBUG "BA request denied - " |
526 | " tid %d\n", tid); | 527 | "queue unavailable for tid %d\n", tid); |
527 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 528 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
528 | goto err_unlock_queue; | 529 | goto err_unlock_queue; |
530 | } | ||
529 | } | 531 | } |
530 | sdata = sta->sdata; | 532 | sdata = sta->sdata; |
531 | 533 | ||
@@ -544,7 +546,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
544 | /* No need to requeue the packets in the agg queue, since we | 546 | /* No need to requeue the packets in the agg queue, since we |
545 | * held the tx lock: no packet could be enqueued to the newly | 547 | * held the tx lock: no packet could be enqueued to the newly |
546 | * allocated queue */ | 548 | * allocated queue */ |
547 | ieee80211_ht_agg_queue_remove(local, sta, tid, 0); | 549 | if (hw->ampdu_queues) |
550 | ieee80211_ht_agg_queue_remove(local, sta, tid, 0); | ||
548 | #ifdef CONFIG_MAC80211_HT_DEBUG | 551 | #ifdef CONFIG_MAC80211_HT_DEBUG |
549 | printk(KERN_DEBUG "BA request denied - HW unavailable for" | 552 | printk(KERN_DEBUG "BA request denied - HW unavailable for" |
550 | " tid %d\n", tid); | 553 | " tid %d\n", tid); |
@@ -554,7 +557,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
554 | } | 557 | } |
555 | 558 | ||
556 | /* Will put all the packets in the new SW queue */ | 559 | /* Will put all the packets in the new SW queue */ |
557 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); | 560 | if (hw->ampdu_queues) |
561 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); | ||
558 | spin_unlock_bh(&sta->lock); | 562 | spin_unlock_bh(&sta->lock); |
559 | 563 | ||
560 | /* send an addBA request */ | 564 | /* send an addBA request */ |
@@ -622,7 +626,8 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | |||
622 | ra, tid); | 626 | ra, tid); |
623 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 627 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
624 | 628 | ||
625 | ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]); | 629 | if (hw->ampdu_queues) |
630 | ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]); | ||
626 | 631 | ||
627 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | | 632 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | |
628 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | 633 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); |
@@ -635,7 +640,8 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | |||
635 | if (ret) { | 640 | if (ret) { |
636 | WARN_ON(ret != -EBUSY); | 641 | WARN_ON(ret != -EBUSY); |
637 | *state = HT_AGG_STATE_OPERATIONAL; | 642 | *state = HT_AGG_STATE_OPERATIONAL; |
638 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | 643 | if (hw->ampdu_queues) |
644 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
639 | goto stop_BA_exit; | 645 | goto stop_BA_exit; |
640 | } | 646 | } |
641 | 647 | ||
@@ -691,7 +697,8 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
691 | #ifdef CONFIG_MAC80211_HT_DEBUG | 697 | #ifdef CONFIG_MAC80211_HT_DEBUG |
692 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); | 698 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); |
693 | #endif | 699 | #endif |
694 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | 700 | if (hw->ampdu_queues) |
701 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
695 | } | 702 | } |
696 | spin_unlock_bh(&sta->lock); | 703 | spin_unlock_bh(&sta->lock); |
697 | rcu_read_unlock(); | 704 | rcu_read_unlock(); |
@@ -745,16 +752,18 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | |||
745 | ieee80211_send_delba(sta->sdata, ra, tid, | 752 | ieee80211_send_delba(sta->sdata, ra, tid, |
746 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); | 753 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); |
747 | 754 | ||
748 | agg_queue = sta->tid_to_tx_q[tid]; | 755 | if (hw->ampdu_queues) { |
749 | 756 | agg_queue = sta->tid_to_tx_q[tid]; | |
750 | ieee80211_ht_agg_queue_remove(local, sta, tid, 1); | 757 | ieee80211_ht_agg_queue_remove(local, sta, tid, 1); |
751 | 758 | ||
752 | /* We just requeued the all the frames that were in the | 759 | /* We just requeued the all the frames that were in the |
753 | * removed queue, and since we might miss a softirq we do | 760 | * removed queue, and since we might miss a softirq we do |
754 | * netif_schedule_queue. ieee80211_wake_queue is not used | 761 | * netif_schedule_queue. ieee80211_wake_queue is not used |
755 | * here as this queue is not necessarily stopped | 762 | * here as this queue is not necessarily stopped |
756 | */ | 763 | */ |
757 | netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue)); | 764 | netif_schedule_queue(netdev_get_tx_queue(local->mdev, |
765 | agg_queue)); | ||
766 | } | ||
758 | spin_lock_bh(&sta->lock); | 767 | spin_lock_bh(&sta->lock); |
759 | *state = HT_AGG_STATE_IDLE; | 768 | *state = HT_AGG_STATE_IDLE; |
760 | sta->ampdu_mlme.addba_req_num[tid] = 0; | 769 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
@@ -1011,7 +1020,8 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
1011 | *state |= HT_ADDBA_RECEIVED_MSK; | 1020 | *state |= HT_ADDBA_RECEIVED_MSK; |
1012 | sta->ampdu_mlme.addba_req_num[tid] = 0; | 1021 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
1013 | 1022 | ||
1014 | if (*state == HT_AGG_STATE_OPERATIONAL) | 1023 | if (*state == HT_AGG_STATE_OPERATIONAL && |
1024 | local->hw.ampdu_queues) | ||
1015 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | 1025 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); |
1016 | 1026 | ||
1017 | spin_unlock_bh(&sta->lock); | 1027 | spin_unlock_bh(&sta->lock); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 88c1975a97a5..fa0cc7a1e6b4 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -386,8 +386,6 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
386 | struct sta_info *sta, | 386 | struct sta_info *sta, |
387 | struct sk_buff *skb) | 387 | struct sk_buff *skb) |
388 | { | 388 | { |
389 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
390 | |||
391 | sta->tx_filtered_count++; | 389 | sta->tx_filtered_count++; |
392 | 390 | ||
393 | /* | 391 | /* |
@@ -434,10 +432,9 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
434 | return; | 432 | return; |
435 | } | 433 | } |
436 | 434 | ||
437 | if (!test_sta_flags(sta, WLAN_STA_PS) && | 435 | if (!test_sta_flags(sta, WLAN_STA_PS) && !skb->requeue) { |
438 | !(info->flags & IEEE80211_TX_CTL_REQUEUE)) { | ||
439 | /* Software retry the packet once */ | 436 | /* Software retry the packet once */ |
440 | info->flags |= IEEE80211_TX_CTL_REQUEUE; | 437 | skb->requeue = 1; |
441 | ieee80211_remove_tx_extra(local, sta->key, skb); | 438 | ieee80211_remove_tx_extra(local, sta->key, skb); |
442 | dev_queue_xmit(skb); | 439 | dev_queue_xmit(skb); |
443 | return; | 440 | return; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c4c95f1db605..648a1d0e6c82 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -669,7 +669,6 @@ static int ap_sta_ps_end(struct sta_info *sta) | |||
669 | struct ieee80211_local *local = sdata->local; | 669 | struct ieee80211_local *local = sdata->local; |
670 | struct sk_buff *skb; | 670 | struct sk_buff *skb; |
671 | int sent = 0; | 671 | int sent = 0; |
672 | struct ieee80211_tx_info *info; | ||
673 | 672 | ||
674 | atomic_dec(&sdata->bss->num_sta_ps); | 673 | atomic_dec(&sdata->bss->num_sta_ps); |
675 | 674 | ||
@@ -685,13 +684,11 @@ static int ap_sta_ps_end(struct sta_info *sta) | |||
685 | 684 | ||
686 | /* Send all buffered frames to the station */ | 685 | /* Send all buffered frames to the station */ |
687 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { | 686 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { |
688 | info = IEEE80211_SKB_CB(skb); | ||
689 | sent++; | 687 | sent++; |
690 | info->flags |= IEEE80211_TX_CTL_REQUEUE; | 688 | skb->requeue = 1; |
691 | dev_queue_xmit(skb); | 689 | dev_queue_xmit(skb); |
692 | } | 690 | } |
693 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { | 691 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { |
694 | info = IEEE80211_SKB_CB(skb); | ||
695 | local->total_ps_buffered--; | 692 | local->total_ps_buffered--; |
696 | sent++; | 693 | sent++; |
697 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 694 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
@@ -699,7 +696,7 @@ static int ap_sta_ps_end(struct sta_info *sta) | |||
699 | "since STA not sleeping anymore\n", sdata->dev->name, | 696 | "since STA not sleeping anymore\n", sdata->dev->name, |
700 | sta->sta.addr, sta->sta.aid); | 697 | sta->sta.addr, sta->sta.aid); |
701 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 698 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
702 | info->flags |= IEEE80211_TX_CTL_REQUEUE; | 699 | skb->requeue = 1; |
703 | dev_queue_xmit(skb); | 700 | dev_queue_xmit(skb); |
704 | } | 701 | } |
705 | 702 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 541e3e64493d..d6392af9cd20 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -661,6 +661,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
661 | static ieee80211_tx_result debug_noinline | 661 | static ieee80211_tx_result debug_noinline |
662 | ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | 662 | ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) |
663 | { | 663 | { |
664 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | ||
664 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 665 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
665 | size_t hdrlen, per_fragm, num_fragm, payload_len, left; | 666 | size_t hdrlen, per_fragm, num_fragm, payload_len, left; |
666 | struct sk_buff **frags, *first, *frag; | 667 | struct sk_buff **frags, *first, *frag; |
@@ -677,9 +678,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
677 | * This scenario is handled in __ieee80211_tx_prepare but extra | 678 | * This scenario is handled in __ieee80211_tx_prepare but extra |
678 | * caution taken here as fragmented ampdu may cause Tx stop. | 679 | * caution taken here as fragmented ampdu may cause Tx stop. |
679 | */ | 680 | */ |
680 | if (WARN_ON(tx->flags & IEEE80211_TX_CTL_AMPDU || | 681 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) |
681 | skb_get_queue_mapping(tx->skb) >= | ||
682 | ieee80211_num_regular_queues(&tx->local->hw))) | ||
683 | return TX_DROP; | 682 | return TX_DROP; |
684 | 683 | ||
685 | first = tx->skb; | 684 | first = tx->skb; |
@@ -951,7 +950,8 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
951 | struct ieee80211_sub_if_data *sdata; | 950 | struct ieee80211_sub_if_data *sdata; |
952 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 951 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
953 | 952 | ||
954 | int hdrlen; | 953 | int hdrlen, tid; |
954 | u8 *qc, *state; | ||
955 | 955 | ||
956 | memset(tx, 0, sizeof(*tx)); | 956 | memset(tx, 0, sizeof(*tx)); |
957 | tx->skb = skb; | 957 | tx->skb = skb; |
@@ -982,6 +982,15 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
982 | 982 | ||
983 | tx->sta = sta_info_get(local, hdr->addr1); | 983 | tx->sta = sta_info_get(local, hdr->addr1); |
984 | 984 | ||
985 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control)) { | ||
986 | qc = ieee80211_get_qos_ctl(hdr); | ||
987 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | ||
988 | |||
989 | state = &tx->sta->ampdu_mlme.tid_state_tx[tid]; | ||
990 | if (*state == HT_AGG_STATE_OPERATIONAL) | ||
991 | info->flags |= IEEE80211_TX_CTL_AMPDU; | ||
992 | } | ||
993 | |||
985 | if (is_multicast_ether_addr(hdr->addr1)) { | 994 | if (is_multicast_ether_addr(hdr->addr1)) { |
986 | tx->flags &= ~IEEE80211_TX_UNICAST; | 995 | tx->flags &= ~IEEE80211_TX_UNICAST; |
987 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | 996 | info->flags |= IEEE80211_TX_CTL_NO_ACK; |
@@ -1172,7 +1181,7 @@ retry: | |||
1172 | * queues, there's no reason for a driver to reject | 1181 | * queues, there's no reason for a driver to reject |
1173 | * a frame there, warn and drop it. | 1182 | * a frame there, warn and drop it. |
1174 | */ | 1183 | */ |
1175 | if (WARN_ON(queue >= ieee80211_num_regular_queues(&local->hw))) | 1184 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) |
1176 | goto drop; | 1185 | goto drop; |
1177 | 1186 | ||
1178 | store = &local->pending_packet[queue]; | 1187 | store = &local->pending_packet[queue]; |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index d27ef7f2d4a7..ac71b38f7cb5 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -114,8 +114,8 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) | |||
114 | { | 114 | { |
115 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | 115 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); |
116 | struct ieee80211_local *local = mpriv->local; | 116 | struct ieee80211_local *local = mpriv->local; |
117 | struct ieee80211_hw *hw = &local->hw; | ||
117 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 118 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
118 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
119 | struct sta_info *sta; | 119 | struct sta_info *sta; |
120 | u16 queue; | 120 | u16 queue; |
121 | u8 tid; | 121 | u8 tid; |
@@ -124,21 +124,19 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) | |||
124 | if (unlikely(queue >= local->hw.queues)) | 124 | if (unlikely(queue >= local->hw.queues)) |
125 | queue = local->hw.queues - 1; | 125 | queue = local->hw.queues - 1; |
126 | 126 | ||
127 | if (info->flags & IEEE80211_TX_CTL_REQUEUE) { | 127 | if (skb->requeue) { |
128 | if (!hw->ampdu_queues) | ||
129 | return queue; | ||
130 | |||
128 | rcu_read_lock(); | 131 | rcu_read_lock(); |
129 | sta = sta_info_get(local, hdr->addr1); | 132 | sta = sta_info_get(local, hdr->addr1); |
130 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; | 133 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; |
131 | if (sta) { | 134 | if (sta) { |
132 | struct ieee80211_hw *hw = &local->hw; | ||
133 | int ampdu_queue = sta->tid_to_tx_q[tid]; | 135 | int ampdu_queue = sta->tid_to_tx_q[tid]; |
134 | 136 | ||
135 | if ((ampdu_queue < ieee80211_num_queues(hw)) && | 137 | if ((ampdu_queue < ieee80211_num_queues(hw)) && |
136 | test_bit(ampdu_queue, local->queue_pool)) { | 138 | test_bit(ampdu_queue, local->queue_pool)) |
137 | queue = ampdu_queue; | 139 | queue = ampdu_queue; |
138 | info->flags |= IEEE80211_TX_CTL_AMPDU; | ||
139 | } else { | ||
140 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
141 | } | ||
142 | } | 140 | } |
143 | rcu_read_unlock(); | 141 | rcu_read_unlock(); |
144 | 142 | ||
@@ -159,20 +157,18 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) | |||
159 | *p++ = ack_policy | tid; | 157 | *p++ = ack_policy | tid; |
160 | *p = 0; | 158 | *p = 0; |
161 | 159 | ||
160 | if (!hw->ampdu_queues) | ||
161 | return queue; | ||
162 | |||
162 | rcu_read_lock(); | 163 | rcu_read_lock(); |
163 | 164 | ||
164 | sta = sta_info_get(local, hdr->addr1); | 165 | sta = sta_info_get(local, hdr->addr1); |
165 | if (sta) { | 166 | if (sta) { |
166 | int ampdu_queue = sta->tid_to_tx_q[tid]; | 167 | int ampdu_queue = sta->tid_to_tx_q[tid]; |
167 | struct ieee80211_hw *hw = &local->hw; | ||
168 | 168 | ||
169 | if ((ampdu_queue < ieee80211_num_queues(hw)) && | 169 | if ((ampdu_queue < ieee80211_num_queues(hw)) && |
170 | test_bit(ampdu_queue, local->queue_pool)) { | 170 | test_bit(ampdu_queue, local->queue_pool)) |
171 | queue = ampdu_queue; | 171 | queue = ampdu_queue; |
172 | info->flags |= IEEE80211_TX_CTL_AMPDU; | ||
173 | } else { | ||
174 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
175 | } | ||
176 | } | 172 | } |
177 | 173 | ||
178 | rcu_read_unlock(); | 174 | rcu_read_unlock(); |