diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-05-16 18:57:14 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-05-21 21:48:14 -0400 |
commit | e2530083609148a7835b54c431f6b8956407c1f6 (patch) | |
tree | 8ed43347541444c7a72d2c79f550f69a93cad591 | |
parent | eefce91a384a64c7bbf913eb08c4adfb911c3639 (diff) |
mac80211: use multi-queue master netdevice
This patch updates mac80211 and drivers to be multi-queue aware and
use that instead of the internal queue mapping. Also does a number
of cleanups in various pieces of the code that fall out and reduces
internal mac80211 state size.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath5k/base.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/b43/dma.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/b43/pio.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/b43legacy/dma.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54common.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/rtl8180_dev.c | 4 | ||||
-rw-r--r-- | include/net/mac80211.h | 20 | ||||
-rw-r--r-- | net/mac80211/Kconfig | 14 | ||||
-rw-r--r-- | net/mac80211/Makefile | 2 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 16 | ||||
-rw-r--r-- | net/mac80211/iface.c | 2 | ||||
-rw-r--r-- | net/mac80211/main.c | 29 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 2 | ||||
-rw-r--r-- | net/mac80211/tx.c | 97 | ||||
-rw-r--r-- | net/mac80211/util.c | 29 | ||||
-rw-r--r-- | net/mac80211/wme.c | 14 | ||||
-rw-r--r-- | net/mac80211/wme.h | 2 |
21 files changed, 158 insertions, 132 deletions
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 7d97934265db..18e9422d26dd 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -2657,7 +2657,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2657 | if (list_empty(&sc->txbuf)) { | 2657 | if (list_empty(&sc->txbuf)) { |
2658 | ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); | 2658 | ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); |
2659 | spin_unlock_irqrestore(&sc->txbuflock, flags); | 2659 | spin_unlock_irqrestore(&sc->txbuflock, flags); |
2660 | ieee80211_stop_queue(hw, info->queue); | 2660 | ieee80211_stop_queue(hw, skb_get_queue_mapping(skb)); |
2661 | return -1; | 2661 | return -1; |
2662 | } | 2662 | } |
2663 | bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list); | 2663 | bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list); |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index aced9866d815..b4eadd908bea 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
@@ -1297,7 +1297,8 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) | |||
1297 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 1297 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
1298 | } else { | 1298 | } else { |
1299 | /* Decide by priority where to put this frame. */ | 1299 | /* Decide by priority where to put this frame. */ |
1300 | ring = select_ring_by_priority(dev, info->queue); | 1300 | ring = select_ring_by_priority( |
1301 | dev, skb_get_queue_mapping(skb)); | ||
1301 | } | 1302 | } |
1302 | 1303 | ||
1303 | spin_lock_irqsave(&ring->lock, flags); | 1304 | spin_lock_irqsave(&ring->lock, flags); |
@@ -1315,7 +1316,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) | |||
1315 | /* Assign the queue number to the ring (if not already done before) | 1316 | /* Assign the queue number to the ring (if not already done before) |
1316 | * so TX status handling can use it. The queue to ring mapping is | 1317 | * so TX status handling can use it. The queue to ring mapping is |
1317 | * static, so we don't need to store it per frame. */ | 1318 | * static, so we don't need to store it per frame. */ |
1318 | ring->queue_prio = info->queue; | 1319 | ring->queue_prio = skb_get_queue_mapping(skb); |
1319 | 1320 | ||
1320 | err = dma_tx_fragment(ring, skb); | 1321 | err = dma_tx_fragment(ring, skb); |
1321 | if (unlikely(err == -ENOKEY)) { | 1322 | if (unlikely(err == -ENOKEY)) { |
@@ -1333,7 +1334,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) | |||
1333 | if ((free_slots(ring) < SLOTS_PER_PACKET) || | 1334 | if ((free_slots(ring) < SLOTS_PER_PACKET) || |
1334 | should_inject_overflow(ring)) { | 1335 | should_inject_overflow(ring)) { |
1335 | /* This TX ring is full. */ | 1336 | /* This TX ring is full. */ |
1336 | ieee80211_stop_queue(dev->wl->hw, info->queue); | 1337 | ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb)); |
1337 | ring->stopped = 1; | 1338 | ring->stopped = 1; |
1338 | if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { | 1339 | if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { |
1339 | b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index); | 1340 | b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index); |
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 284786a94e7d..8b1555d95f1c 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c | |||
@@ -509,7 +509,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) | |||
509 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 509 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
510 | } else { | 510 | } else { |
511 | /* Decide by priority where to put this frame. */ | 511 | /* Decide by priority where to put this frame. */ |
512 | q = select_queue_by_priority(dev, info->queue); | 512 | q = select_queue_by_priority(dev, skb_get_queue_mapping(skb)); |
513 | } | 513 | } |
514 | 514 | ||
515 | spin_lock_irqsave(&q->lock, flags); | 515 | spin_lock_irqsave(&q->lock, flags); |
@@ -532,7 +532,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) | |||
532 | if (total_len > (q->buffer_size - q->buffer_used)) { | 532 | if (total_len > (q->buffer_size - q->buffer_used)) { |
533 | /* Not enough memory on the queue. */ | 533 | /* Not enough memory on the queue. */ |
534 | err = -EBUSY; | 534 | err = -EBUSY; |
535 | ieee80211_stop_queue(dev->wl->hw, info->queue); | 535 | ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb)); |
536 | q->stopped = 1; | 536 | q->stopped = 1; |
537 | goto out_unlock; | 537 | goto out_unlock; |
538 | } | 538 | } |
@@ -540,7 +540,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) | |||
540 | /* Assign the queue number to the ring (if not already done before) | 540 | /* Assign the queue number to the ring (if not already done before) |
541 | * so TX status handling can use it. The mac80211-queue to b43-queue | 541 | * so TX status handling can use it. The mac80211-queue to b43-queue |
542 | * mapping is static, so we don't need to store it per frame. */ | 542 | * mapping is static, so we don't need to store it per frame. */ |
543 | q->queue_prio = info->queue; | 543 | q->queue_prio = skb_get_queue_mapping(skb); |
544 | 544 | ||
545 | err = pio_tx_frame(q, skb); | 545 | err = pio_tx_frame(q, skb); |
546 | if (unlikely(err == -ENOKEY)) { | 546 | if (unlikely(err == -ENOKEY)) { |
@@ -560,7 +560,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) | |||
560 | if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) || | 560 | if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) || |
561 | (q->free_packet_slots == 0)) { | 561 | (q->free_packet_slots == 0)) { |
562 | /* The queue is full. */ | 562 | /* The queue is full. */ |
563 | ieee80211_stop_queue(dev->wl->hw, info->queue); | 563 | ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb)); |
564 | q->stopped = 1; | 564 | q->stopped = 1; |
565 | } | 565 | } |
566 | 566 | ||
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index c1c501d963bc..33cc256c5baf 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c | |||
@@ -1325,11 +1325,10 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev, | |||
1325 | struct sk_buff *skb) | 1325 | struct sk_buff *skb) |
1326 | { | 1326 | { |
1327 | struct b43legacy_dmaring *ring; | 1327 | struct b43legacy_dmaring *ring; |
1328 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1329 | int err = 0; | 1328 | int err = 0; |
1330 | unsigned long flags; | 1329 | unsigned long flags; |
1331 | 1330 | ||
1332 | ring = priority_to_txring(dev, info->queue); | 1331 | ring = priority_to_txring(dev, skb_get_queue_mapping(skb)); |
1333 | spin_lock_irqsave(&ring->lock, flags); | 1332 | spin_lock_irqsave(&ring->lock, flags); |
1334 | B43legacy_WARN_ON(!ring->tx); | 1333 | B43legacy_WARN_ON(!ring->tx); |
1335 | if (unlikely(free_slots(ring) < SLOTS_PER_PACKET)) { | 1334 | if (unlikely(free_slots(ring) < SLOTS_PER_PACKET)) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index a61293ba3f6b..0ebab967d5e7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -696,7 +696,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
696 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 696 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
697 | struct iwl_tfd_frame *tfd; | 697 | struct iwl_tfd_frame *tfd; |
698 | u32 *control_flags; | 698 | u32 *control_flags; |
699 | int txq_id = info->queue; | 699 | int txq_id = skb_get_queue_mapping(skb); |
700 | struct iwl_tx_queue *txq = NULL; | 700 | struct iwl_tx_queue *txq = NULL; |
701 | struct iwl_queue *q = NULL; | 701 | struct iwl_queue *q = NULL; |
702 | dma_addr_t phys_addr; | 702 | dma_addr_t phys_addr; |
@@ -917,7 +917,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
917 | spin_unlock_irqrestore(&priv->lock, flags); | 917 | spin_unlock_irqrestore(&priv->lock, flags); |
918 | } | 918 | } |
919 | 919 | ||
920 | ieee80211_stop_queue(priv->hw, info->queue); | 920 | ieee80211_stop_queue(priv->hw, skb_get_queue_mapping(skb)); |
921 | } | 921 | } |
922 | 922 | ||
923 | return 0; | 923 | return 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index a740a1817d16..e0f52e264418 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -2552,7 +2552,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) | |||
2552 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2552 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2553 | struct iwl3945_tfd_frame *tfd; | 2553 | struct iwl3945_tfd_frame *tfd; |
2554 | u32 *control_flags; | 2554 | u32 *control_flags; |
2555 | int txq_id = info->queue; | 2555 | int txq_id = skb_get_queue_mapping(skb); |
2556 | struct iwl3945_tx_queue *txq = NULL; | 2556 | struct iwl3945_tx_queue *txq = NULL; |
2557 | struct iwl3945_queue *q = NULL; | 2557 | struct iwl3945_queue *q = NULL; |
2558 | dma_addr_t phys_addr; | 2558 | dma_addr_t phys_addr; |
@@ -2765,7 +2765,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) | |||
2765 | spin_unlock_irqrestore(&priv->lock, flags); | 2765 | spin_unlock_irqrestore(&priv->lock, flags); |
2766 | } | 2766 | } |
2767 | 2767 | ||
2768 | ieee80211_stop_queue(priv->hw, info->queue); | 2768 | ieee80211_stop_queue(priv->hw, skb_get_queue_mapping(skb)); |
2769 | } | 2769 | } |
2770 | 2770 | ||
2771 | return 0; | 2771 | return 0; |
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 850857932e29..91ac9208b77d 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -407,7 +407,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
407 | last_addr = range->end_addr; | 407 | last_addr = range->end_addr; |
408 | __skb_unlink(entry, &priv->tx_queue); | 408 | __skb_unlink(entry, &priv->tx_queue); |
409 | memset(&info->status, 0, sizeof(info->status)); | 409 | memset(&info->status, 0, sizeof(info->status)); |
410 | priv->tx_stats[info->queue].len--; | 410 | priv->tx_stats[skb_get_queue_mapping(skb)].len--; |
411 | entry_hdr = (struct p54_control_hdr *) entry->data; | 411 | entry_hdr = (struct p54_control_hdr *) entry->data; |
412 | entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; | 412 | entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; |
413 | if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) | 413 | if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) |
@@ -551,13 +551,13 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
551 | size_t padding, len; | 551 | size_t padding, len; |
552 | u8 rate; | 552 | u8 rate; |
553 | 553 | ||
554 | current_queue = &priv->tx_stats[info->queue]; | 554 | current_queue = &priv->tx_stats[skb_get_queue_mapping(skb)]; |
555 | if (unlikely(current_queue->len > current_queue->limit)) | 555 | if (unlikely(current_queue->len > current_queue->limit)) |
556 | return NETDEV_TX_BUSY; | 556 | return NETDEV_TX_BUSY; |
557 | current_queue->len++; | 557 | current_queue->len++; |
558 | current_queue->count++; | 558 | current_queue->count++; |
559 | if (current_queue->len == current_queue->limit) | 559 | if (current_queue->len == current_queue->limit) |
560 | ieee80211_stop_queue(dev, info->queue); | 560 | ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); |
561 | 561 | ||
562 | padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3; | 562 | padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3; |
563 | len = skb->len; | 563 | len = skb->len; |
@@ -589,7 +589,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
589 | memset(txhdr->rateset, rate, 8); | 589 | memset(txhdr->rateset, rate, 8); |
590 | txhdr->wep_key_present = 0; | 590 | txhdr->wep_key_present = 0; |
591 | txhdr->wep_key_len = 0; | 591 | txhdr->wep_key_len = 0; |
592 | txhdr->frame_type = cpu_to_le32(info->queue + 4); | 592 | txhdr->frame_type = cpu_to_le32(skb_get_queue_mapping(skb) + 4); |
593 | txhdr->magic4 = 0; | 593 | txhdr->magic4 = 0; |
594 | txhdr->antenna = (info->antenna_sel_tx == 0) ? | 594 | txhdr->antenna = (info->antenna_sel_tx == 0) ? |
595 | 2 : info->antenna_sel_tx - 1; | 595 | 2 : info->antenna_sel_tx - 1; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index b5379b027b18..c05e05b58887 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -102,7 +102,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
102 | struct rt2x00_dev *rt2x00dev = hw->priv; | 102 | struct rt2x00_dev *rt2x00dev = hw->priv; |
103 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 103 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
104 | struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; | 104 | struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; |
105 | enum data_queue_qid qid = mac80211_queue_to_qid(tx_info->queue); | 105 | enum data_queue_qid qid = skb_get_queue_mapping(skb); |
106 | struct data_queue *queue; | 106 | struct data_queue *queue; |
107 | u16 frame_control; | 107 | u16 frame_control; |
108 | 108 | ||
@@ -149,23 +149,23 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
149 | IEEE80211_TX_CTL_USE_CTS_PROTECT)) && | 149 | IEEE80211_TX_CTL_USE_CTS_PROTECT)) && |
150 | !rt2x00dev->ops->hw->set_rts_threshold) { | 150 | !rt2x00dev->ops->hw->set_rts_threshold) { |
151 | if (rt2x00queue_available(queue) <= 1) { | 151 | if (rt2x00queue_available(queue) <= 1) { |
152 | ieee80211_stop_queue(rt2x00dev->hw, tx_info->queue); | 152 | ieee80211_stop_queue(rt2x00dev->hw, qid); |
153 | return NETDEV_TX_BUSY; | 153 | return NETDEV_TX_BUSY; |
154 | } | 154 | } |
155 | 155 | ||
156 | if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb)) { | 156 | if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb)) { |
157 | ieee80211_stop_queue(rt2x00dev->hw, tx_info->queue); | 157 | ieee80211_stop_queue(rt2x00dev->hw, qid); |
158 | return NETDEV_TX_BUSY; | 158 | return NETDEV_TX_BUSY; |
159 | } | 159 | } |
160 | } | 160 | } |
161 | 161 | ||
162 | if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb)) { | 162 | if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb)) { |
163 | ieee80211_stop_queue(rt2x00dev->hw, tx_info->queue); | 163 | ieee80211_stop_queue(rt2x00dev->hw, qid); |
164 | return NETDEV_TX_BUSY; | 164 | return NETDEV_TX_BUSY; |
165 | } | 165 | } |
166 | 166 | ||
167 | if (rt2x00queue_full(queue)) | 167 | if (rt2x00queue_full(queue)) |
168 | ieee80211_stop_queue(rt2x00dev->hw, tx_info->queue); | 168 | ieee80211_stop_queue(rt2x00dev->hw, qid); |
169 | 169 | ||
170 | if (rt2x00dev->ops->lib->kick_tx_queue) | 170 | if (rt2x00dev->ops->lib->kick_tx_queue) |
171 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, qid); | 171 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, qid); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index f263fe422f87..4d00ced14cc7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -80,19 +80,6 @@ enum data_queue_qid { | |||
80 | }; | 80 | }; |
81 | 81 | ||
82 | /** | 82 | /** |
83 | * mac80211_queue_to_qid - Convert mac80211 queue to rt2x00 qid | ||
84 | * @queue: mac80211 queue. | ||
85 | */ | ||
86 | static inline enum data_queue_qid mac80211_queue_to_qid(unsigned int queue) | ||
87 | { | ||
88 | /* Regular TX queues are mapped directly */ | ||
89 | if (queue < 4) | ||
90 | return queue; | ||
91 | WARN_ON(1); | ||
92 | return QID_OTHER; | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc | 83 | * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc |
97 | * | 84 | * |
98 | * @FRAME_DESC_DRIVER_GENERATED: Frame was generated inside driver | 85 | * @FRAME_DESC_DRIVER_GENERATED: Frame was generated inside driver |
diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c index 4427bc9f78a9..b7172a12c057 100644 --- a/drivers/net/wireless/rtl8180_dev.c +++ b/drivers/net/wireless/rtl8180_dev.c | |||
@@ -246,7 +246,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
246 | u16 plcp_len = 0; | 246 | u16 plcp_len = 0; |
247 | __le16 rts_duration = 0; | 247 | __le16 rts_duration = 0; |
248 | 248 | ||
249 | prio = info->queue; | 249 | prio = skb_get_queue_mapping(skb); |
250 | ring = &priv->tx_ring[prio]; | 250 | ring = &priv->tx_ring[prio]; |
251 | 251 | ||
252 | mapping = pci_map_single(priv->pdev, skb->data, | 252 | mapping = pci_map_single(priv->pdev, skb->data, |
@@ -298,7 +298,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
298 | entry->flags = cpu_to_le32(tx_flags); | 298 | entry->flags = cpu_to_le32(tx_flags); |
299 | __skb_queue_tail(&ring->queue, skb); | 299 | __skb_queue_tail(&ring->queue, skb); |
300 | if (ring->entries - skb_queue_len(&ring->queue) < 2) | 300 | if (ring->entries - skb_queue_len(&ring->queue) < 2) |
301 | ieee80211_stop_queue(dev, info->queue); | 301 | ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); |
302 | spin_unlock_irqrestore(&priv->lock, flags); | 302 | spin_unlock_irqrestore(&priv->lock, flags); |
303 | 303 | ||
304 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); | 304 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 4df39eb9115f..c80e3be8f79e 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -293,7 +293,7 @@ struct ieee80211_tx_info { | |||
293 | s8 tx_rate_idx; | 293 | s8 tx_rate_idx; |
294 | u8 antenna_sel_tx; | 294 | u8 antenna_sel_tx; |
295 | 295 | ||
296 | u8 queue; /* use skb_queue_mapping soon */ | 296 | /* 1 byte hole */ |
297 | 297 | ||
298 | union { | 298 | union { |
299 | struct { | 299 | struct { |
@@ -802,6 +802,24 @@ static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr) | |||
802 | memcpy(hw->wiphy->perm_addr, addr, ETH_ALEN); | 802 | memcpy(hw->wiphy->perm_addr, addr, ETH_ALEN); |
803 | } | 803 | } |
804 | 804 | ||
805 | static inline int ieee80211_num_regular_queues(struct ieee80211_hw *hw) | ||
806 | { | ||
807 | #ifdef CONFIG_MAC80211_QOS | ||
808 | return hw->queues; | ||
809 | #else | ||
810 | return 1; | ||
811 | #endif | ||
812 | } | ||
813 | |||
814 | static inline int ieee80211_num_queues(struct ieee80211_hw *hw) | ||
815 | { | ||
816 | #ifdef CONFIG_MAC80211_QOS | ||
817 | return hw->queues + hw->ampdu_queues; | ||
818 | #else | ||
819 | return 1; | ||
820 | #endif | ||
821 | } | ||
822 | |||
805 | static inline struct ieee80211_rate * | 823 | static inline struct ieee80211_rate * |
806 | ieee80211_get_tx_rate(const struct ieee80211_hw *hw, | 824 | ieee80211_get_tx_rate(const struct ieee80211_hw *hw, |
807 | const struct ieee80211_tx_info *c) | 825 | const struct ieee80211_tx_info *c) |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index a24b459dd45a..590e00b2766c 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -7,11 +7,23 @@ config MAC80211 | |||
7 | select CRC32 | 7 | select CRC32 |
8 | select WIRELESS_EXT | 8 | select WIRELESS_EXT |
9 | select CFG80211 | 9 | select CFG80211 |
10 | select NET_SCH_FIFO | ||
11 | ---help--- | 10 | ---help--- |
12 | This option enables the hardware independent IEEE 802.11 | 11 | This option enables the hardware independent IEEE 802.11 |
13 | networking stack. | 12 | networking stack. |
14 | 13 | ||
14 | config MAC80211_QOS | ||
15 | def_bool y | ||
16 | depends on MAC80211 | ||
17 | depends on NET_SCHED | ||
18 | depends on NETDEVICES_MULTIQUEUE | ||
19 | |||
20 | comment "QoS/HT support disabled" | ||
21 | depends on MAC80211 && !MAC80211_QOS | ||
22 | comment "QoS/HT support needs CONFIG_NET_SCHED" | ||
23 | depends on MAC80211 && !NET_SCHED | ||
24 | comment "QoS/HT support needs CONFIG_NETDEVICES_MULTIQUEUE" | ||
25 | depends on MAC80211 && !NETDEVICES_MULTIQUEUE | ||
26 | |||
15 | menu "Rate control algorithm selection" | 27 | menu "Rate control algorithm selection" |
16 | depends on MAC80211 != n | 28 | depends on MAC80211 != n |
17 | 29 | ||
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 4e5847fd316c..1d2a4e010e5c 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -29,7 +29,7 @@ mac80211-y := \ | |||
29 | event.o | 29 | event.o |
30 | 30 | ||
31 | mac80211-$(CONFIG_MAC80211_LEDS) += led.o | 31 | mac80211-$(CONFIG_MAC80211_LEDS) += led.o |
32 | mac80211-$(CONFIG_NET_SCHED) += wme.o | 32 | mac80211-$(CONFIG_MAC80211_QOS) += wme.o |
33 | mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ | 33 | mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ |
34 | debugfs.o \ | 34 | debugfs.o \ |
35 | debugfs_sta.o \ | 35 | debugfs_sta.o \ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 86a861251e8c..7d614cdcefcb 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -594,7 +594,7 @@ struct ieee80211_local { | |||
594 | struct sta_info *sta_hash[STA_HASH_SIZE]; | 594 | struct sta_info *sta_hash[STA_HASH_SIZE]; |
595 | struct timer_list sta_cleanup; | 595 | struct timer_list sta_cleanup; |
596 | 596 | ||
597 | unsigned long state[IEEE80211_MAX_QUEUES + IEEE80211_MAX_AMPDU_QUEUES]; | 597 | unsigned long queues_pending[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; |
598 | struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES]; | 598 | struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES]; |
599 | struct tasklet_struct tx_pending_tasklet; | 599 | struct tasklet_struct tx_pending_tasklet; |
600 | 600 | ||
@@ -758,6 +758,15 @@ struct ieee80211_local { | |||
758 | #endif | 758 | #endif |
759 | }; | 759 | }; |
760 | 760 | ||
761 | static inline int ieee80211_is_multiqueue(struct ieee80211_local *local) | ||
762 | { | ||
763 | #ifdef CONFIG_MAC80211_QOS | ||
764 | return netif_is_multiqueue(local->mdev); | ||
765 | #else | ||
766 | return 0; | ||
767 | #endif | ||
768 | } | ||
769 | |||
761 | /* this struct represents 802.11n's RA/TID combination */ | 770 | /* this struct represents 802.11n's RA/TID combination */ |
762 | struct ieee80211_ra_tid { | 771 | struct ieee80211_ra_tid { |
763 | u8 ra[ETH_ALEN]; | 772 | u8 ra[ETH_ALEN]; |
@@ -827,11 +836,6 @@ static inline struct ieee80211_hw *local_to_hw( | |||
827 | return &local->hw; | 836 | return &local->hw; |
828 | } | 837 | } |
829 | 838 | ||
830 | enum ieee80211_link_state_t { | ||
831 | IEEE80211_LINK_STATE_XOFF = 0, | ||
832 | IEEE80211_LINK_STATE_PENDING, | ||
833 | }; | ||
834 | |||
835 | struct sta_attribute { | 839 | struct sta_attribute { |
836 | struct attribute attr; | 840 | struct attribute attr; |
837 | ssize_t (*show)(const struct sta_info *, char *buf); | 841 | ssize_t (*show)(const struct sta_info *, char *buf); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 3c64e42eb12e..984472702381 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -168,7 +168,7 @@ void ieee80211_if_set_type(struct net_device *dev, int type) | |||
168 | ifsta->flags |= IEEE80211_STA_CREATE_IBSS | | 168 | ifsta->flags |= IEEE80211_STA_CREATE_IBSS | |
169 | IEEE80211_STA_AUTO_BSSID_SEL | | 169 | IEEE80211_STA_AUTO_BSSID_SEL | |
170 | IEEE80211_STA_AUTO_CHANNEL_SEL; | 170 | IEEE80211_STA_AUTO_CHANNEL_SEL; |
171 | if (sdata->local->hw.queues >= 4) | 171 | if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) |
172 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; | 172 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; |
173 | 173 | ||
174 | msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev); | 174 | msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 8f1ff7ef1667..97d4a537ca2f 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -1634,12 +1634,32 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1634 | if (result < 0) | 1634 | if (result < 0) |
1635 | return result; | 1635 | return result; |
1636 | 1636 | ||
1637 | /* | ||
1638 | * We use the number of queues for feature tests (QoS, HT) internally | ||
1639 | * so restrict them appropriately. | ||
1640 | */ | ||
1641 | #ifdef CONFIG_MAC80211_QOS | ||
1642 | if (hw->queues > IEEE80211_MAX_QUEUES) | ||
1643 | hw->queues = IEEE80211_MAX_QUEUES; | ||
1644 | if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES) | ||
1645 | hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES; | ||
1646 | if (hw->queues < 4) | ||
1647 | hw->ampdu_queues = 0; | ||
1648 | #else | ||
1649 | hw->queues = 1; | ||
1650 | hw->ampdu_queues = 0; | ||
1651 | #endif | ||
1652 | |||
1637 | /* for now, mdev needs sub_if_data :/ */ | 1653 | /* for now, mdev needs sub_if_data :/ */ |
1638 | mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data), | 1654 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_sub_if_data), |
1639 | "wmaster%d", ether_setup); | 1655 | "wmaster%d", ether_setup, |
1656 | ieee80211_num_queues(hw)); | ||
1640 | if (!mdev) | 1657 | if (!mdev) |
1641 | goto fail_mdev_alloc; | 1658 | goto fail_mdev_alloc; |
1642 | 1659 | ||
1660 | if (ieee80211_num_queues(hw) > 1) | ||
1661 | mdev->features |= NETIF_F_MULTI_QUEUE; | ||
1662 | |||
1643 | sdata = IEEE80211_DEV_TO_SUB_IF(mdev); | 1663 | sdata = IEEE80211_DEV_TO_SUB_IF(mdev); |
1644 | mdev->ieee80211_ptr = &sdata->wdev; | 1664 | mdev->ieee80211_ptr = &sdata->wdev; |
1645 | sdata->wdev.wiphy = local->hw.wiphy; | 1665 | sdata->wdev.wiphy = local->hw.wiphy; |
@@ -1728,11 +1748,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1728 | goto fail_wep; | 1748 | goto fail_wep; |
1729 | } | 1749 | } |
1730 | 1750 | ||
1731 | if (hw->queues > IEEE80211_MAX_QUEUES) | ||
1732 | hw->queues = IEEE80211_MAX_QUEUES; | ||
1733 | if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES) | ||
1734 | hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES; | ||
1735 | |||
1736 | ieee80211_install_qdisc(local->mdev); | 1751 | ieee80211_install_qdisc(local->mdev); |
1737 | 1752 | ||
1738 | /* add one default STA interface */ | 1753 | /* add one default STA interface */ |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index ef3149324d54..c24770cb02c5 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -255,7 +255,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
255 | * sta_rx_agg_session_timer_expired for useage */ | 255 | * sta_rx_agg_session_timer_expired for useage */ |
256 | sta->timer_to_tid[i] = i; | 256 | sta->timer_to_tid[i] = i; |
257 | /* tid to tx queue: initialize according to HW (0 is valid) */ | 257 | /* tid to tx queue: initialize according to HW (0 is valid) */ |
258 | sta->tid_to_tx_q[i] = local->hw.queues + local->hw.ampdu_queues; | 258 | sta->tid_to_tx_q[i] = ieee80211_num_queues(&local->hw); |
259 | /* rx */ | 259 | /* rx */ |
260 | sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE; | 260 | sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE; |
261 | sta->ampdu_mlme.tid_rx[i] = NULL; | 261 | sta->ampdu_mlme.tid_rx[i] = NULL; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 6268bbca148e..9273651d3d7c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -213,18 +213,6 @@ static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
213 | return dur; | 213 | return dur; |
214 | } | 214 | } |
215 | 215 | ||
216 | static inline int __ieee80211_queue_stopped(const struct ieee80211_local *local, | ||
217 | int queue) | ||
218 | { | ||
219 | return test_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]); | ||
220 | } | ||
221 | |||
222 | static inline int __ieee80211_queue_pending(const struct ieee80211_local *local, | ||
223 | int queue) | ||
224 | { | ||
225 | return test_bit(IEEE80211_LINK_STATE_PENDING, &local->state[queue]); | ||
226 | } | ||
227 | |||
228 | static int inline is_ieee80211_device(struct net_device *dev, | 216 | static int inline is_ieee80211_device(struct net_device *dev, |
229 | struct net_device *master) | 217 | struct net_device *master) |
230 | { | 218 | { |
@@ -680,7 +668,8 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
680 | * etc. | 668 | * etc. |
681 | */ | 669 | */ |
682 | if (WARN_ON(tx->flags & IEEE80211_TX_CTL_AMPDU || | 670 | if (WARN_ON(tx->flags & IEEE80211_TX_CTL_AMPDU || |
683 | IEEE80211_SKB_CB(tx->skb)->queue >= tx->local->hw.queues)) | 671 | skb_get_queue_mapping(tx->skb) >= |
672 | ieee80211_num_regular_queues(&tx->local->hw))) | ||
684 | return TX_DROP; | 673 | return TX_DROP; |
685 | 674 | ||
686 | first = tx->skb; | 675 | first = tx->skb; |
@@ -1098,11 +1087,9 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | |||
1098 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1087 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1099 | int ret, i; | 1088 | int ret, i; |
1100 | 1089 | ||
1101 | if (!ieee80211_qdisc_installed(local->mdev) && | 1090 | if (netif_subqueue_stopped(local->mdev, skb)) |
1102 | __ieee80211_queue_stopped(local, 0)) { | ||
1103 | netif_stop_queue(local->mdev); | ||
1104 | return IEEE80211_TX_AGAIN; | 1091 | return IEEE80211_TX_AGAIN; |
1105 | } | 1092 | |
1106 | if (skb) { | 1093 | if (skb) { |
1107 | ieee80211_dump_frame(wiphy_name(local->hw.wiphy), | 1094 | ieee80211_dump_frame(wiphy_name(local->hw.wiphy), |
1108 | "TX to low-level driver", skb); | 1095 | "TX to low-level driver", skb); |
@@ -1121,7 +1108,8 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | |||
1121 | IEEE80211_TX_CTL_USE_CTS_PROTECT | | 1108 | IEEE80211_TX_CTL_USE_CTS_PROTECT | |
1122 | IEEE80211_TX_CTL_CLEAR_PS_FILT | | 1109 | IEEE80211_TX_CTL_CLEAR_PS_FILT | |
1123 | IEEE80211_TX_CTL_FIRST_FRAGMENT); | 1110 | IEEE80211_TX_CTL_FIRST_FRAGMENT); |
1124 | if (__ieee80211_queue_stopped(local, info->queue)) | 1111 | if (netif_subqueue_stopped(local->mdev, |
1112 | tx->extra_frag[i])) | ||
1125 | return IEEE80211_TX_FRAG_AGAIN; | 1113 | return IEEE80211_TX_FRAG_AGAIN; |
1126 | if (i == tx->num_extra_frag) { | 1114 | if (i == tx->num_extra_frag) { |
1127 | info->tx_rate_idx = tx->last_frag_rate_idx; | 1115 | info->tx_rate_idx = tx->last_frag_rate_idx; |
@@ -1160,9 +1148,11 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) | |||
1160 | ieee80211_tx_result res = TX_DROP, res_prepare; | 1148 | ieee80211_tx_result res = TX_DROP, res_prepare; |
1161 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1149 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1162 | int ret, i; | 1150 | int ret, i; |
1163 | int queue = info->queue; | 1151 | u16 queue; |
1164 | 1152 | ||
1165 | WARN_ON(__ieee80211_queue_pending(local, queue)); | 1153 | queue = skb_get_queue_mapping(skb); |
1154 | |||
1155 | WARN_ON(test_bit(queue, local->queues_pending)); | ||
1166 | 1156 | ||
1167 | if (unlikely(skb->len < 10)) { | 1157 | if (unlikely(skb->len < 10)) { |
1168 | dev_kfree_skb(skb); | 1158 | dev_kfree_skb(skb); |
@@ -1233,28 +1223,28 @@ retry: | |||
1233 | * queues, there's no reason for a driver to reject | 1223 | * queues, there's no reason for a driver to reject |
1234 | * a frame there, warn and drop it. | 1224 | * a frame there, warn and drop it. |
1235 | */ | 1225 | */ |
1236 | if (WARN_ON(queue >= local->hw.queues)) | 1226 | if (WARN_ON(queue >= ieee80211_num_regular_queues(&local->hw))) |
1237 | goto drop; | 1227 | goto drop; |
1238 | 1228 | ||
1239 | store = &local->pending_packet[queue]; | 1229 | store = &local->pending_packet[queue]; |
1240 | 1230 | ||
1241 | if (ret == IEEE80211_TX_FRAG_AGAIN) | 1231 | if (ret == IEEE80211_TX_FRAG_AGAIN) |
1242 | skb = NULL; | 1232 | skb = NULL; |
1243 | set_bit(IEEE80211_LINK_STATE_PENDING, | 1233 | set_bit(queue, local->queues_pending); |
1244 | &local->state[queue]); | ||
1245 | smp_mb(); | 1234 | smp_mb(); |
1246 | /* When the driver gets out of buffers during sending of | 1235 | /* |
1247 | * fragments and calls ieee80211_stop_queue, there is | 1236 | * When the driver gets out of buffers during sending of |
1248 | * a small window between IEEE80211_LINK_STATE_XOFF and | 1237 | * fragments and calls ieee80211_stop_queue, the netif |
1249 | * IEEE80211_LINK_STATE_PENDING flags are set. If a buffer | 1238 | * subqueue is stopped. There is, however, a small window |
1239 | * in which the PENDING bit is not yet set. If a buffer | ||
1250 | * gets available in that window (i.e. driver calls | 1240 | * gets available in that window (i.e. driver calls |
1251 | * ieee80211_wake_queue), we would end up with ieee80211_tx | 1241 | * ieee80211_wake_queue), we would end up with ieee80211_tx |
1252 | * called with IEEE80211_LINK_STATE_PENDING. Prevent this by | 1242 | * called with the PENDING bit still set. Prevent this by |
1253 | * continuing transmitting here when that situation is | 1243 | * continuing transmitting here when that situation is |
1254 | * possible to have happened. */ | 1244 | * possible to have happened. |
1255 | if (!__ieee80211_queue_stopped(local, queue)) { | 1245 | */ |
1256 | clear_bit(IEEE80211_LINK_STATE_PENDING, | 1246 | if (!__netif_subqueue_stopped(local->mdev, queue)) { |
1257 | &local->state[queue]); | 1247 | clear_bit(queue, local->queues_pending); |
1258 | goto retry; | 1248 | goto retry; |
1259 | } | 1249 | } |
1260 | store->skb = skb; | 1250 | store->skb = skb; |
@@ -1509,7 +1499,8 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1509 | } | 1499 | } |
1510 | 1500 | ||
1511 | /* receiver and we are QoS enabled, use a QoS type frame */ | 1501 | /* receiver and we are QoS enabled, use a QoS type frame */ |
1512 | if (sta_flags & WLAN_STA_WME && local->hw.queues >= 4) { | 1502 | if (sta_flags & WLAN_STA_WME && |
1503 | ieee80211_num_regular_queues(&local->hw) >= 4) { | ||
1513 | fc |= IEEE80211_STYPE_QOS_DATA; | 1504 | fc |= IEEE80211_STYPE_QOS_DATA; |
1514 | hdrlen += 2; | 1505 | hdrlen += 2; |
1515 | } | 1506 | } |
@@ -1661,41 +1652,51 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1661 | return ret; | 1652 | return ret; |
1662 | } | 1653 | } |
1663 | 1654 | ||
1664 | /* helper functions for pending packets for when queues are stopped */ | ||
1665 | 1655 | ||
1656 | /* | ||
1657 | * ieee80211_clear_tx_pending may not be called in a context where | ||
1658 | * it is possible that it packets could come in again. | ||
1659 | */ | ||
1666 | void ieee80211_clear_tx_pending(struct ieee80211_local *local) | 1660 | void ieee80211_clear_tx_pending(struct ieee80211_local *local) |
1667 | { | 1661 | { |
1668 | int i, j; | 1662 | int i, j; |
1669 | struct ieee80211_tx_stored_packet *store; | 1663 | struct ieee80211_tx_stored_packet *store; |
1670 | 1664 | ||
1671 | for (i = 0; i < local->hw.queues; i++) { | 1665 | for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { |
1672 | if (!__ieee80211_queue_pending(local, i)) | 1666 | if (!test_bit(i, local->queues_pending)) |
1673 | continue; | 1667 | continue; |
1674 | store = &local->pending_packet[i]; | 1668 | store = &local->pending_packet[i]; |
1675 | kfree_skb(store->skb); | 1669 | kfree_skb(store->skb); |
1676 | for (j = 0; j < store->num_extra_frag; j++) | 1670 | for (j = 0; j < store->num_extra_frag; j++) |
1677 | kfree_skb(store->extra_frag[j]); | 1671 | kfree_skb(store->extra_frag[j]); |
1678 | kfree(store->extra_frag); | 1672 | kfree(store->extra_frag); |
1679 | clear_bit(IEEE80211_LINK_STATE_PENDING, &local->state[i]); | 1673 | clear_bit(i, local->queues_pending); |
1680 | } | 1674 | } |
1681 | } | 1675 | } |
1682 | 1676 | ||
1677 | /* | ||
1678 | * Transmit all pending packets. Called from tasklet, locks master device | ||
1679 | * TX lock so that no new packets can come in. | ||
1680 | */ | ||
1683 | void ieee80211_tx_pending(unsigned long data) | 1681 | void ieee80211_tx_pending(unsigned long data) |
1684 | { | 1682 | { |
1685 | struct ieee80211_local *local = (struct ieee80211_local *)data; | 1683 | struct ieee80211_local *local = (struct ieee80211_local *)data; |
1686 | struct net_device *dev = local->mdev; | 1684 | struct net_device *dev = local->mdev; |
1687 | struct ieee80211_tx_stored_packet *store; | 1685 | struct ieee80211_tx_stored_packet *store; |
1688 | struct ieee80211_tx_data tx; | 1686 | struct ieee80211_tx_data tx; |
1689 | int i, ret, reschedule = 0; | 1687 | int i, ret; |
1690 | 1688 | ||
1691 | netif_tx_lock_bh(dev); | 1689 | netif_tx_lock_bh(dev); |
1692 | for (i = 0; i < local->hw.queues; i++) { | 1690 | for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { |
1693 | if (__ieee80211_queue_stopped(local, i)) | 1691 | /* Check that this queue is ok */ |
1692 | if (__netif_subqueue_stopped(local->mdev, i)) | ||
1694 | continue; | 1693 | continue; |
1695 | if (!__ieee80211_queue_pending(local, i)) { | 1694 | |
1696 | reschedule = 1; | 1695 | if (!test_bit(i, local->queues_pending)) { |
1696 | ieee80211_wake_queue(&local->hw, i); | ||
1697 | continue; | 1697 | continue; |
1698 | } | 1698 | } |
1699 | |||
1699 | store = &local->pending_packet[i]; | 1700 | store = &local->pending_packet[i]; |
1700 | tx.extra_frag = store->extra_frag; | 1701 | tx.extra_frag = store->extra_frag; |
1701 | tx.num_extra_frag = store->num_extra_frag; | 1702 | tx.num_extra_frag = store->num_extra_frag; |
@@ -1708,19 +1709,11 @@ void ieee80211_tx_pending(unsigned long data) | |||
1708 | if (ret == IEEE80211_TX_FRAG_AGAIN) | 1709 | if (ret == IEEE80211_TX_FRAG_AGAIN) |
1709 | store->skb = NULL; | 1710 | store->skb = NULL; |
1710 | } else { | 1711 | } else { |
1711 | clear_bit(IEEE80211_LINK_STATE_PENDING, | 1712 | clear_bit(i, local->queues_pending); |
1712 | &local->state[i]); | 1713 | ieee80211_wake_queue(&local->hw, i); |
1713 | reschedule = 1; | ||
1714 | } | 1714 | } |
1715 | } | 1715 | } |
1716 | netif_tx_unlock_bh(dev); | 1716 | netif_tx_unlock_bh(dev); |
1717 | if (reschedule) { | ||
1718 | if (!ieee80211_qdisc_installed(dev)) { | ||
1719 | if (!__ieee80211_queue_stopped(local, 0)) | ||
1720 | netif_wake_queue(dev); | ||
1721 | } else | ||
1722 | netif_schedule(dev); | ||
1723 | } | ||
1724 | } | 1717 | } |
1725 | 1718 | ||
1726 | /* functions for drivers to get certain frames */ | 1719 | /* functions for drivers to get certain frames */ |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d9109dee461f..4f7180b287da 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -331,17 +331,15 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) | |||
331 | { | 331 | { |
332 | struct ieee80211_local *local = hw_to_local(hw); | 332 | struct ieee80211_local *local = hw_to_local(hw); |
333 | 333 | ||
334 | if (test_and_clear_bit(IEEE80211_LINK_STATE_XOFF, | 334 | if (test_bit(queue, local->queues_pending)) { |
335 | &local->state[queue])) { | 335 | tasklet_schedule(&local->tx_pending_tasklet); |
336 | if (test_bit(IEEE80211_LINK_STATE_PENDING, | 336 | } else { |
337 | &local->state[queue])) | 337 | if (ieee80211_is_multiqueue(local)) { |
338 | tasklet_schedule(&local->tx_pending_tasklet); | 338 | netif_wake_subqueue(local->mdev, queue); |
339 | else | 339 | } else { |
340 | if (!ieee80211_qdisc_installed(local->mdev)) { | 340 | WARN_ON(queue != 0); |
341 | if (queue == 0) | 341 | netif_wake_queue(local->mdev); |
342 | netif_wake_queue(local->mdev); | 342 | } |
343 | } else | ||
344 | __netif_schedule(local->mdev); | ||
345 | } | 343 | } |
346 | } | 344 | } |
347 | EXPORT_SYMBOL(ieee80211_wake_queue); | 345 | EXPORT_SYMBOL(ieee80211_wake_queue); |
@@ -350,9 +348,12 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) | |||
350 | { | 348 | { |
351 | struct ieee80211_local *local = hw_to_local(hw); | 349 | struct ieee80211_local *local = hw_to_local(hw); |
352 | 350 | ||
353 | if (!ieee80211_qdisc_installed(local->mdev) && queue == 0) | 351 | if (ieee80211_is_multiqueue(local)) { |
352 | netif_stop_subqueue(local->mdev, queue); | ||
353 | } else { | ||
354 | WARN_ON(queue != 0); | ||
354 | netif_stop_queue(local->mdev); | 355 | netif_stop_queue(local->mdev); |
355 | set_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]); | 356 | } |
356 | } | 357 | } |
357 | EXPORT_SYMBOL(ieee80211_stop_queue); | 358 | EXPORT_SYMBOL(ieee80211_stop_queue); |
358 | 359 | ||
@@ -360,7 +361,7 @@ void ieee80211_stop_queues(struct ieee80211_hw *hw) | |||
360 | { | 361 | { |
361 | int i; | 362 | int i; |
362 | 363 | ||
363 | for (i = 0; i < hw->queues + hw->ampdu_queues; i++) | 364 | for (i = 0; i < ieee80211_num_queues(hw); i++) |
364 | ieee80211_stop_queue(hw, i); | 365 | ieee80211_stop_queue(hw, i); |
365 | } | 366 | } |
366 | EXPORT_SYMBOL(ieee80211_stop_queues); | 367 | EXPORT_SYMBOL(ieee80211_stop_queues); |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 477690f4dca7..14a9ff10a1e9 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -158,7 +158,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) | |||
158 | u8 tid; | 158 | u8 tid; |
159 | 159 | ||
160 | if (info->flags & IEEE80211_TX_CTL_REQUEUE) { | 160 | if (info->flags & IEEE80211_TX_CTL_REQUEUE) { |
161 | queue = info->queue; | 161 | queue = skb_get_queue_mapping(skb); |
162 | rcu_read_lock(); | 162 | rcu_read_lock(); |
163 | sta = sta_info_get(local, hdr->addr1); | 163 | sta = sta_info_get(local, hdr->addr1); |
164 | tid = skb->priority & QOS_CONTROL_TAG1D_MASK; | 164 | tid = skb->priority & QOS_CONTROL_TAG1D_MASK; |
@@ -219,7 +219,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) | |||
219 | err = NET_XMIT_DROP; | 219 | err = NET_XMIT_DROP; |
220 | } else { | 220 | } else { |
221 | tid = skb->priority & QOS_CONTROL_TAG1D_MASK; | 221 | tid = skb->priority & QOS_CONTROL_TAG1D_MASK; |
222 | info->queue = (unsigned int) queue; | 222 | skb_set_queue_mapping(skb, queue); |
223 | qdisc = q->queues[queue]; | 223 | qdisc = q->queues[queue]; |
224 | err = qdisc->enqueue(skb, qdisc); | 224 | err = qdisc->enqueue(skb, qdisc); |
225 | if (err == NET_XMIT_SUCCESS) { | 225 | if (err == NET_XMIT_SUCCESS) { |
@@ -240,12 +240,11 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) | |||
240 | static int wme_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd) | 240 | static int wme_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd) |
241 | { | 241 | { |
242 | struct ieee80211_sched_data *q = qdisc_priv(qd); | 242 | struct ieee80211_sched_data *q = qdisc_priv(qd); |
243 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
244 | struct Qdisc *qdisc; | 243 | struct Qdisc *qdisc; |
245 | int err; | 244 | int err; |
246 | 245 | ||
247 | /* we recorded which queue to use earlier! */ | 246 | /* we recorded which queue to use earlier! */ |
248 | qdisc = q->queues[info->queue]; | 247 | qdisc = q->queues[skb_get_queue_mapping(skb)]; |
249 | 248 | ||
250 | if ((err = qdisc->ops->requeue(skb, qdisc)) == 0) { | 249 | if ((err = qdisc->ops->requeue(skb, qdisc)) == 0) { |
251 | qd->q.qlen++; | 250 | qd->q.qlen++; |
@@ -269,11 +268,8 @@ static struct sk_buff *wme_qdiscop_dequeue(struct Qdisc* qd) | |||
269 | /* check all the h/w queues in numeric/priority order */ | 268 | /* check all the h/w queues in numeric/priority order */ |
270 | for (queue = 0; queue < QD_NUM(hw); queue++) { | 269 | for (queue = 0; queue < QD_NUM(hw); queue++) { |
271 | /* see if there is room in this hardware queue */ | 270 | /* see if there is room in this hardware queue */ |
272 | if ((test_bit(IEEE80211_LINK_STATE_XOFF, | 271 | if (__netif_subqueue_stopped(local->mdev, queue) || |
273 | &local->state[queue])) || | 272 | !test_bit(queue, q->qdisc_pool)) |
274 | (test_bit(IEEE80211_LINK_STATE_PENDING, | ||
275 | &local->state[queue])) || | ||
276 | (!test_bit(queue, q->qdisc_pool))) | ||
277 | continue; | 273 | continue; |
278 | 274 | ||
279 | /* there is space - try and get a frame */ | 275 | /* there is space - try and get a frame */ |
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index fcc6b05508cc..bbdb53344817 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h | |||
@@ -31,7 +31,7 @@ static inline int WLAN_FC_IS_QOS_DATA(u16 fc) | |||
31 | return (fc & 0x8C) == 0x88; | 31 | return (fc & 0x8C) == 0x88; |
32 | } | 32 | } |
33 | 33 | ||
34 | #ifdef CONFIG_NET_SCHED | 34 | #ifdef CONFIG_MAC80211_QOS |
35 | void ieee80211_install_qdisc(struct net_device *dev); | 35 | void ieee80211_install_qdisc(struct net_device *dev); |
36 | int ieee80211_qdisc_installed(struct net_device *dev); | 36 | int ieee80211_qdisc_installed(struct net_device *dev); |
37 | int ieee80211_ht_agg_queue_add(struct ieee80211_local *local, | 37 | int ieee80211_ht_agg_queue_add(struct ieee80211_local *local, |