diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-03-23 12:28:36 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-27 20:13:21 -0400 |
commit | f0e72851f7ad108fed20426b46a18ab5fcd5729f (patch) | |
tree | 5e8d1795fa06127f9c9ae9755140eb0d871ae2f9 /net | |
parent | 2de8e0d999b8790861cd3749bec2236ccc1c8110 (diff) |
mac80211: fix A-MPDU queue assignment
Internally, mac80211 requires the skb's queue mapping to be set
to the AC queue, not the virtual A-MPDU queue. This is not done
correctly currently, this patch moves the code down to directly
before the driver is invoked and adds a comment that it will be
moved into the driver later.
Since this requires __ieee80211_tx() to have the sta pointer,
make sure to provide it in ieee80211_tx_pending().
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Reviewed-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/tx.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 51bf49cc75bc..0d97cad84b1b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1024,13 +1024,8 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1024 | 1024 | ||
1025 | spin_lock_irqsave(&tx->sta->lock, flags); | 1025 | spin_lock_irqsave(&tx->sta->lock, flags); |
1026 | state = &tx->sta->ampdu_mlme.tid_state_tx[tid]; | 1026 | state = &tx->sta->ampdu_mlme.tid_state_tx[tid]; |
1027 | if (*state == HT_AGG_STATE_OPERATIONAL) { | 1027 | if (*state == HT_AGG_STATE_OPERATIONAL) |
1028 | info->flags |= IEEE80211_TX_CTL_AMPDU; | 1028 | info->flags |= IEEE80211_TX_CTL_AMPDU; |
1029 | if (local->hw.ampdu_queues) | ||
1030 | skb_set_queue_mapping( | ||
1031 | skb, tx->local->hw.queues + | ||
1032 | tx->sta->tid_to_tx_q[tid]); | ||
1033 | } | ||
1034 | spin_unlock_irqrestore(&tx->sta->lock, flags); | 1029 | spin_unlock_irqrestore(&tx->sta->lock, flags); |
1035 | } | 1030 | } |
1036 | 1031 | ||
@@ -1103,10 +1098,29 @@ static int __ieee80211_tx(struct ieee80211_local *local, | |||
1103 | skb_get_queue_mapping(skb))) | 1098 | skb_get_queue_mapping(skb))) |
1104 | return IEEE80211_TX_PENDING; | 1099 | return IEEE80211_TX_PENDING; |
1105 | 1100 | ||
1106 | if (fragm) { | 1101 | info = IEEE80211_SKB_CB(skb); |
1107 | info = IEEE80211_SKB_CB(skb); | 1102 | |
1103 | if (fragm) | ||
1108 | info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | | 1104 | info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | |
1109 | IEEE80211_TX_CTL_FIRST_FRAGMENT); | 1105 | IEEE80211_TX_CTL_FIRST_FRAGMENT); |
1106 | |||
1107 | /* | ||
1108 | * Internally, we need to have the queue mapping point to | ||
1109 | * the real AC queue, not the virtual A-MPDU queue. This | ||
1110 | * now finally sets the queue to what the driver wants. | ||
1111 | * We will later move this down into the only driver that | ||
1112 | * needs it, iwlwifi. | ||
1113 | */ | ||
1114 | if (tx->sta && local->hw.ampdu_queues && | ||
1115 | info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
1116 | unsigned long flags; | ||
1117 | u8 *qc = ieee80211_get_qos_ctl((void *) skb->data); | ||
1118 | int tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | ||
1119 | |||
1120 | spin_lock_irqsave(&tx->sta->lock, flags); | ||
1121 | skb_set_queue_mapping(skb, local->hw.queues + | ||
1122 | tx->sta->tid_to_tx_q[tid]); | ||
1123 | spin_unlock_irqrestore(&tx->sta->lock, flags); | ||
1110 | } | 1124 | } |
1111 | 1125 | ||
1112 | next = skb->next; | 1126 | next = skb->next; |
@@ -1817,9 +1831,11 @@ void ieee80211_tx_pending(unsigned long data) | |||
1817 | struct ieee80211_local *local = (struct ieee80211_local *)data; | 1831 | struct ieee80211_local *local = (struct ieee80211_local *)data; |
1818 | struct net_device *dev = local->mdev; | 1832 | struct net_device *dev = local->mdev; |
1819 | struct ieee80211_tx_stored_packet *store; | 1833 | struct ieee80211_tx_stored_packet *store; |
1834 | struct ieee80211_hdr *hdr; | ||
1820 | struct ieee80211_tx_data tx; | 1835 | struct ieee80211_tx_data tx; |
1821 | int i, ret; | 1836 | int i, ret; |
1822 | 1837 | ||
1838 | rcu_read_lock(); | ||
1823 | netif_tx_lock_bh(dev); | 1839 | netif_tx_lock_bh(dev); |
1824 | for (i = 0; i < local->hw.queues; i++) { | 1840 | for (i = 0; i < local->hw.queues; i++) { |
1825 | /* Check that this queue is ok */ | 1841 | /* Check that this queue is ok */ |
@@ -1839,6 +1855,8 @@ void ieee80211_tx_pending(unsigned long data) | |||
1839 | store = &local->pending_packet[i]; | 1855 | store = &local->pending_packet[i]; |
1840 | tx.flags = 0; | 1856 | tx.flags = 0; |
1841 | tx.skb = store->skb; | 1857 | tx.skb = store->skb; |
1858 | hdr = (struct ieee80211_hdr *)tx.skb->data; | ||
1859 | tx.sta = sta_info_get(local, hdr->addr1); | ||
1842 | ret = __ieee80211_tx(local, &tx); | 1860 | ret = __ieee80211_tx(local, &tx); |
1843 | store->skb = tx.skb; | 1861 | store->skb = tx.skb; |
1844 | if (!ret) { | 1862 | if (!ret) { |
@@ -1847,6 +1865,7 @@ void ieee80211_tx_pending(unsigned long data) | |||
1847 | } | 1865 | } |
1848 | } | 1866 | } |
1849 | netif_tx_unlock_bh(dev); | 1867 | netif_tx_unlock_bh(dev); |
1868 | rcu_read_unlock(); | ||
1850 | } | 1869 | } |
1851 | 1870 | ||
1852 | /* functions for drivers to get certain frames */ | 1871 | /* functions for drivers to get certain frames */ |