Commit f0e72851f7ad108fed20426b46a18ab5fcd5729f
Committed by
John W. Linville
1 parent
2de8e0d999
Exists in
master
and in
39 other branches
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>
Showing 1 changed file with 27 additions and 8 deletions Side-by-side Diff
net/mac80211/tx.c
... | ... | @@ -1024,13 +1024,8 @@ |
1024 | 1024 | |
1025 | 1025 | spin_lock_irqsave(&tx->sta->lock, flags); |
1026 | 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 | 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 | 1029 | spin_unlock_irqrestore(&tx->sta->lock, flags); |
1035 | 1030 | } |
1036 | 1031 | |
1037 | 1032 | |
... | ... | @@ -1103,10 +1098,29 @@ |
1103 | 1098 | skb_get_queue_mapping(skb))) |
1104 | 1099 | return IEEE80211_TX_PENDING; |
1105 | 1100 | |
1106 | - if (fragm) { | |
1107 | - info = IEEE80211_SKB_CB(skb); | |
1101 | + info = IEEE80211_SKB_CB(skb); | |
1102 | + | |
1103 | + if (fragm) | |
1108 | 1104 | info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | |
1109 | 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 | 1126 | next = skb->next; |
1113 | 1127 | |
... | ... | @@ -1817,9 +1831,11 @@ |
1817 | 1831 | struct ieee80211_local *local = (struct ieee80211_local *)data; |
1818 | 1832 | struct net_device *dev = local->mdev; |
1819 | 1833 | struct ieee80211_tx_stored_packet *store; |
1834 | + struct ieee80211_hdr *hdr; | |
1820 | 1835 | struct ieee80211_tx_data tx; |
1821 | 1836 | int i, ret; |
1822 | 1837 | |
1838 | + rcu_read_lock(); | |
1823 | 1839 | netif_tx_lock_bh(dev); |
1824 | 1840 | for (i = 0; i < local->hw.queues; i++) { |
1825 | 1841 | /* Check that this queue is ok */ |
... | ... | @@ -1839,6 +1855,8 @@ |
1839 | 1855 | store = &local->pending_packet[i]; |
1840 | 1856 | tx.flags = 0; |
1841 | 1857 | tx.skb = store->skb; |
1858 | + hdr = (struct ieee80211_hdr *)tx.skb->data; | |
1859 | + tx.sta = sta_info_get(local, hdr->addr1); | |
1842 | 1860 | ret = __ieee80211_tx(local, &tx); |
1843 | 1861 | store->skb = tx.skb; |
1844 | 1862 | if (!ret) { |
... | ... | @@ -1847,6 +1865,7 @@ |
1847 | 1865 | } |
1848 | 1866 | } |
1849 | 1867 | netif_tx_unlock_bh(dev); |
1868 | + rcu_read_unlock(); | |
1850 | 1869 | } |
1851 | 1870 | |
1852 | 1871 | /* functions for drivers to get certain frames */ |