Nice! I see your follow-up, but a few comments anyway here on this version. > + /* Driver has no native support for iTXQ, handle the queues */ > + ieee80211_txq_schedule_start(&local->hw, txq->txq.ac); > + while ((queue = ieee80211_next_txq(&local->hw, txq->txq.ac)) != NULL) { > + control.sta = queue->sta; > + while ((skb = ieee80211_tx_dequeue(&local->hw, queue))) > + drv_tx(local, &control, skb); Yeah, I think I see how that might not work right - you don't necessarily want to pull out everything here. But it should be easy to break out here, I guess, and continue if the driver restarts the corresponding queue? > -/* Indicate which queue to use. */ > u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, > struct sk_buff *skb) > { > -[...] > + /* mac80211 only supports iTXQ nowadays. Only calculate the hash while > + * the skb is still hot in the CPU cache > + */ > + skb_get_hash(skb); > + return 0; Hmm. Is that really worth keeping? I'd probably rather remove the netdev_select_queue callbacks completely. Regardless, once this works I'm sure we can make a lot of cleanups elsewhere, e.g. a couple of "!txq" checks in tx.c (tx_prep_agg, amsdu_aggregate). Eventually with this implementation I think it'd be worth doing it for all the cases where ieee80211_get_txq() returns NULL or for where it's skipped in ieee80211_queue_skb(), i.e. * monitor mode, * management frames, * after-DTIM * PS response * STA not uploaded as well, and just going into the mac80211 iTXQ scheduling code you wrote in wake_tx_queue() for those cases. That way, we could get rid of all the special cases in ieee80211_queue_skb() and callers that depend on the return value. That would allow us to remove a LOT of code, all the stuff handling local->pending (tx_pending), tx_frags, etc. johannes