Skip to content

Commit

Permalink
mac80211: fix A-MPDU queue assignment
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Johannes Berg authored and John W. Linville committed Mar 28, 2009
1 parent 2de8e0d commit f0e7285
Showing 1 changed file with 27 additions and 8 deletions.
35 changes: 27 additions & 8 deletions net/mac80211/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1024,13 +1024,8 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,

spin_lock_irqsave(&tx->sta->lock, flags);
state = &tx->sta->ampdu_mlme.tid_state_tx[tid];
if (*state == HT_AGG_STATE_OPERATIONAL) {
if (*state == HT_AGG_STATE_OPERATIONAL)
info->flags |= IEEE80211_TX_CTL_AMPDU;
if (local->hw.ampdu_queues)
skb_set_queue_mapping(
skb, tx->local->hw.queues +
tx->sta->tid_to_tx_q[tid]);
}
spin_unlock_irqrestore(&tx->sta->lock, flags);
}

Expand Down Expand Up @@ -1103,10 +1098,29 @@ static int __ieee80211_tx(struct ieee80211_local *local,
skb_get_queue_mapping(skb)))
return IEEE80211_TX_PENDING;

if (fragm) {
info = IEEE80211_SKB_CB(skb);
info = IEEE80211_SKB_CB(skb);

if (fragm)
info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT |
IEEE80211_TX_CTL_FIRST_FRAGMENT);

/*
* Internally, we need to have the queue mapping point to
* the real AC queue, not the virtual A-MPDU queue. This
* now finally sets the queue to what the driver wants.
* We will later move this down into the only driver that
* needs it, iwlwifi.
*/
if (tx->sta && local->hw.ampdu_queues &&
info->flags & IEEE80211_TX_CTL_AMPDU) {
unsigned long flags;
u8 *qc = ieee80211_get_qos_ctl((void *) skb->data);
int tid = *qc & IEEE80211_QOS_CTL_TID_MASK;

spin_lock_irqsave(&tx->sta->lock, flags);
skb_set_queue_mapping(skb, local->hw.queues +
tx->sta->tid_to_tx_q[tid]);
spin_unlock_irqrestore(&tx->sta->lock, flags);
}

next = skb->next;
Expand Down Expand Up @@ -1817,9 +1831,11 @@ void ieee80211_tx_pending(unsigned long data)
struct ieee80211_local *local = (struct ieee80211_local *)data;
struct net_device *dev = local->mdev;
struct ieee80211_tx_stored_packet *store;
struct ieee80211_hdr *hdr;
struct ieee80211_tx_data tx;
int i, ret;

rcu_read_lock();
netif_tx_lock_bh(dev);
for (i = 0; i < local->hw.queues; i++) {
/* Check that this queue is ok */
Expand All @@ -1839,6 +1855,8 @@ void ieee80211_tx_pending(unsigned long data)
store = &local->pending_packet[i];
tx.flags = 0;
tx.skb = store->skb;
hdr = (struct ieee80211_hdr *)tx.skb->data;
tx.sta = sta_info_get(local, hdr->addr1);
ret = __ieee80211_tx(local, &tx);
store->skb = tx.skb;
if (!ret) {
Expand All @@ -1847,6 +1865,7 @@ void ieee80211_tx_pending(unsigned long data)
}
}
netif_tx_unlock_bh(dev);
rcu_read_unlock();
}

/* functions for drivers to get certain frames */
Expand Down

0 comments on commit f0e7285

Please sign in to comment.