diff options
author | Ivo van Doorn <IvDoorn@gmail.com> | 2008-06-06 16:53:14 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-06-14 12:17:56 -0400 |
commit | b869767b6f5049f1d1ede2bb3e48832e0722ca5a (patch) | |
tree | a75e43aad931ffdaea889af7b2275f12a16f077a | |
parent | 6db3786aee36b32e5ed072ed67fad6d5341b0991 (diff) |
rt2x00: Don't kick TX queue after each frame
TX queues shouldn't be kicked after each frame that is put into the
queue. This could cause problems during RTS and CTS-to-self as well
as with fragmentation. In all those cases you want all frames to be
send out in a single burst. Off course we shouldn't let the queue fill
up entirely, thus we introduce a 10% threshold which, when reached,
will force the frames to be send out regardless of the frame.
In addition we should prevent queues to become full in such a way
that the tx() handler can fail. Instead of stopping the queue when
it is full, we should stop it when it is below the threshold.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2400pci.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500pci.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00pci.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 28 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.h | 19 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt61pci.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 1 |
11 files changed, 39 insertions, 37 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 94226b47d1d9..b5b0ded83e0f 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -1507,7 +1507,6 @@ static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1507 | */ | 1507 | */ |
1508 | skbdesc = get_skb_frame_desc(skb); | 1508 | skbdesc = get_skb_frame_desc(skb); |
1509 | memset(skbdesc, 0, sizeof(*skbdesc)); | 1509 | memset(skbdesc, 0, sizeof(*skbdesc)); |
1510 | skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; | ||
1511 | skbdesc->data = skb->data; | 1510 | skbdesc->data = skb->data; |
1512 | skbdesc->data_len = skb->len; | 1511 | skbdesc->data_len = skb->len; |
1513 | skbdesc->desc = entry_priv->desc; | 1512 | skbdesc->desc = entry_priv->desc; |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index c8cf8c1d095f..74b54c948b8d 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -1823,7 +1823,6 @@ static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1823 | */ | 1823 | */ |
1824 | skbdesc = get_skb_frame_desc(skb); | 1824 | skbdesc = get_skb_frame_desc(skb); |
1825 | memset(skbdesc, 0, sizeof(*skbdesc)); | 1825 | memset(skbdesc, 0, sizeof(*skbdesc)); |
1826 | skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; | ||
1827 | skbdesc->data = skb->data; | 1826 | skbdesc->data = skb->data; |
1828 | skbdesc->data_len = skb->len; | 1827 | skbdesc->data_len = skb->len; |
1829 | skbdesc->desc = entry_priv->desc; | 1828 | skbdesc->desc = entry_priv->desc; |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 6abb4c5338f5..076221413db7 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1711,7 +1711,6 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1711 | */ | 1711 | */ |
1712 | skbdesc = get_skb_frame_desc(skb); | 1712 | skbdesc = get_skb_frame_desc(skb); |
1713 | memset(skbdesc, 0, sizeof(*skbdesc)); | 1713 | memset(skbdesc, 0, sizeof(*skbdesc)); |
1714 | skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; | ||
1715 | skbdesc->data = skb->data + intf->beacon->queue->desc_size; | 1714 | skbdesc->data = skb->data + intf->beacon->queue->desc_size; |
1716 | skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; | 1715 | skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; |
1717 | skbdesc->desc = skb->data; | 1716 | skbdesc->desc = skb->data; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index c7da3c25237e..938d375027be 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -826,7 +826,7 @@ struct rt2x00_dev { | |||
826 | * The Beacon array also contains the Atim queue | 826 | * The Beacon array also contains the Atim queue |
827 | * if that is supported by the device. | 827 | * if that is supported by the device. |
828 | */ | 828 | */ |
829 | int data_queues; | 829 | unsigned int data_queues; |
830 | struct data_queue *rx; | 830 | struct data_queue *rx; |
831 | struct data_queue *tx; | 831 | struct data_queue *tx; |
832 | struct data_queue *bcn; | 832 | struct data_queue *bcn; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index e7f544c404bc..59f273bf5b5e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -34,7 +34,6 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, | |||
34 | struct sk_buff *frag_skb) | 34 | struct sk_buff *frag_skb) |
35 | { | 35 | { |
36 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb); | 36 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb); |
37 | struct skb_frame_desc *skbdesc; | ||
38 | struct ieee80211_tx_info *rts_info; | 37 | struct ieee80211_tx_info *rts_info; |
39 | struct sk_buff *skb; | 38 | struct sk_buff *skb; |
40 | int size; | 39 | int size; |
@@ -82,13 +81,6 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, | |||
82 | frag_skb->data, size, tx_info, | 81 | frag_skb->data, size, tx_info, |
83 | (struct ieee80211_rts *)(skb->data)); | 82 | (struct ieee80211_rts *)(skb->data)); |
84 | 83 | ||
85 | /* | ||
86 | * Initialize skb descriptor | ||
87 | */ | ||
88 | skbdesc = get_skb_frame_desc(skb); | ||
89 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
90 | skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; | ||
91 | |||
92 | if (rt2x00queue_write_tx_frame(queue, skb)) { | 84 | if (rt2x00queue_write_tx_frame(queue, skb)) { |
93 | WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); | 85 | WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); |
94 | return NETDEV_TX_BUSY; | 86 | return NETDEV_TX_BUSY; |
@@ -163,7 +155,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
163 | return NETDEV_TX_BUSY; | 155 | return NETDEV_TX_BUSY; |
164 | } | 156 | } |
165 | 157 | ||
166 | if (rt2x00queue_full(queue)) | 158 | if (rt2x00queue_threshold(queue)) |
167 | ieee80211_stop_queue(rt2x00dev->hw, qid); | 159 | ieee80211_stop_queue(rt2x00dev->hw, qid); |
168 | 160 | ||
169 | return NETDEV_TX_OK; | 161 | return NETDEV_TX_OK; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index a6bac75de9f2..9745277c81ce 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -170,11 +170,11 @@ void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry, | |||
170 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); | 170 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); |
171 | 171 | ||
172 | /* | 172 | /* |
173 | * If the data queue was full before the txdone handler | 173 | * If the data queue was below the threshold before the txdone |
174 | * we must make sure the packet queue in the mac80211 stack | 174 | * handler we must make sure the packet queue in the mac80211 stack |
175 | * is reenabled when the txdone handler has finished. | 175 | * is reenabled when the txdone handler has finished. |
176 | */ | 176 | */ |
177 | if (!rt2x00queue_full(entry->queue)) | 177 | if (!rt2x00queue_threshold(entry->queue)) |
178 | ieee80211_wake_queue(rt2x00dev->hw, qid); | 178 | ieee80211_wake_queue(rt2x00dev->hw, qid); |
179 | 179 | ||
180 | } | 180 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index f875b7ab09fe..493066519ef3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -163,8 +163,8 @@ EXPORT_SYMBOL_GPL(rt2x00queue_create_tx_descriptor); | |||
163 | void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, | 163 | void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, |
164 | struct txentry_desc *txdesc) | 164 | struct txentry_desc *txdesc) |
165 | { | 165 | { |
166 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 166 | struct data_queue *queue = entry->queue; |
167 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 167 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; |
168 | 168 | ||
169 | rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry->skb, txdesc); | 169 | rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry->skb, txdesc); |
170 | 170 | ||
@@ -175,16 +175,21 @@ void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, | |||
175 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TX, entry->skb); | 175 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TX, entry->skb); |
176 | 176 | ||
177 | /* | 177 | /* |
178 | * We are done writing the frame to the queue entry, | 178 | * Check if we need to kick the queue, there are however a few rules |
179 | * also kick the queue in case the correct flags are set, | 179 | * 1) Don't kick beacon queue |
180 | * note that this will automatically filter beacons and | 180 | * 2) Don't kick unless this is the last in frame in a burst. |
181 | * RTS/CTS frames since those frames don't have this flag | 181 | * When the burst flag is set, this frame is always followed |
182 | * set. | 182 | * by another frame which in some way are related to eachother. |
183 | * This is true for fragments, RTS or CTS-to-self frames. | ||
184 | * 3) Rule 2 can be broken when the available entries | ||
185 | * in the queue are less then a certain threshold. | ||
183 | */ | 186 | */ |
184 | if (rt2x00dev->ops->lib->kick_tx_queue && | 187 | if (entry->queue->qid == QID_BEACON) |
185 | !(skbdesc->flags & FRAME_DESC_DRIVER_GENERATED)) | 188 | return; |
186 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, | 189 | |
187 | entry->queue->qid); | 190 | if (rt2x00queue_threshold(queue) || |
191 | !test_bit(ENTRY_TXD_BURST, &txdesc->flags)) | ||
192 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid); | ||
188 | } | 193 | } |
189 | EXPORT_SYMBOL_GPL(rt2x00queue_write_tx_descriptor); | 194 | EXPORT_SYMBOL_GPL(rt2x00queue_write_tx_descriptor); |
190 | 195 | ||
@@ -349,6 +354,7 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue, | |||
349 | rt2x00queue_reset(queue); | 354 | rt2x00queue_reset(queue); |
350 | 355 | ||
351 | queue->limit = qdesc->entry_num; | 356 | queue->limit = qdesc->entry_num; |
357 | queue->threshold = DIV_ROUND_UP(qdesc->entry_num, 10); | ||
352 | queue->data_size = qdesc->data_size; | 358 | queue->data_size = qdesc->data_size; |
353 | queue->desc_size = qdesc->desc_size; | 359 | queue->desc_size = qdesc->desc_size; |
354 | 360 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 303d5568470d..623fc27dc7bb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -82,12 +82,10 @@ enum data_queue_qid { | |||
82 | /** | 82 | /** |
83 | * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc | 83 | * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc |
84 | * | 84 | * |
85 | * @FRAME_DESC_DRIVER_GENERATED: Frame was generated inside driver | ||
86 | * and should not be reported back to mac80211 during txdone. | ||
87 | */ | 85 | */ |
88 | enum skb_frame_desc_flags { | 86 | //enum skb_frame_desc_flags { |
89 | FRAME_DESC_DRIVER_GENERATED = 1 << 0, | 87 | // TEMPORARILY EMPTY |
90 | }; | 88 | //}; |
91 | 89 | ||
92 | /** | 90 | /** |
93 | * struct skb_frame_desc: Descriptor information for the skb buffer | 91 | * struct skb_frame_desc: Descriptor information for the skb buffer |
@@ -325,6 +323,7 @@ enum queue_index { | |||
325 | * index corruption due to concurrency. | 323 | * index corruption due to concurrency. |
326 | * @count: Number of frames handled in the queue. | 324 | * @count: Number of frames handled in the queue. |
327 | * @limit: Maximum number of entries in the queue. | 325 | * @limit: Maximum number of entries in the queue. |
326 | * @threshold: Minimum number of free entries before queue is kicked by force. | ||
328 | * @length: Number of frames in queue. | 327 | * @length: Number of frames in queue. |
329 | * @index: Index pointers to entry positions in the queue, | 328 | * @index: Index pointers to entry positions in the queue, |
330 | * use &enum queue_index to get a specific index field. | 329 | * use &enum queue_index to get a specific index field. |
@@ -343,6 +342,7 @@ struct data_queue { | |||
343 | spinlock_t lock; | 342 | spinlock_t lock; |
344 | unsigned int count; | 343 | unsigned int count; |
345 | unsigned short limit; | 344 | unsigned short limit; |
345 | unsigned short threshold; | ||
346 | unsigned short length; | 346 | unsigned short length; |
347 | unsigned short index[Q_INDEX_MAX]; | 347 | unsigned short index[Q_INDEX_MAX]; |
348 | 348 | ||
@@ -467,6 +467,15 @@ static inline int rt2x00queue_available(struct data_queue *queue) | |||
467 | } | 467 | } |
468 | 468 | ||
469 | /** | 469 | /** |
470 | * rt2x00queue_threshold - Check if the queue is below threshold | ||
471 | * @queue: Queue to check. | ||
472 | */ | ||
473 | static inline int rt2x00queue_threshold(struct data_queue *queue) | ||
474 | { | ||
475 | return rt2x00queue_available(queue) < queue->threshold; | ||
476 | } | ||
477 | |||
478 | /** | ||
470 | * rt2x00_desc_read - Read a word from the hardware descriptor. | 479 | * rt2x00_desc_read - Read a word from the hardware descriptor. |
471 | * @desc: Base descriptor address | 480 | * @desc: Base descriptor address |
472 | * @word: Word index from where the descriptor should be read. | 481 | * @word: Word index from where the descriptor should be read. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index fdf505beb79c..8cf6e3f253e9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -165,11 +165,11 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) | |||
165 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); | 165 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); |
166 | 166 | ||
167 | /* | 167 | /* |
168 | * If the data queue was full before the txdone handler | 168 | * If the data queue was below the threshold before the txdone |
169 | * we must make sure the packet queue in the mac80211 stack | 169 | * handler we must make sure the packet queue in the mac80211 stack |
170 | * is reenabled when the txdone handler has finished. | 170 | * is reenabled when the txdone handler has finished. |
171 | */ | 171 | */ |
172 | if (!rt2x00queue_full(entry->queue)) | 172 | if (!rt2x00queue_threshold(entry->queue)) |
173 | ieee80211_wake_queue(rt2x00dev->hw, qid); | 173 | ieee80211_wake_queue(rt2x00dev->hw, qid); |
174 | } | 174 | } |
175 | 175 | ||
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index aa9ef66921b8..746f87c8e704 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -2375,7 +2375,6 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2375 | */ | 2375 | */ |
2376 | skbdesc = get_skb_frame_desc(skb); | 2376 | skbdesc = get_skb_frame_desc(skb); |
2377 | memset(skbdesc, 0, sizeof(*skbdesc)); | 2377 | memset(skbdesc, 0, sizeof(*skbdesc)); |
2378 | skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; | ||
2379 | skbdesc->data = skb->data; | 2378 | skbdesc->data = skb->data; |
2380 | skbdesc->data_len = skb->len; | 2379 | skbdesc->data_len = skb->len; |
2381 | skbdesc->desc = entry_priv->desc; | 2380 | skbdesc->desc = entry_priv->desc; |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 5e5f6034383a..ae50f6332dfa 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -1980,7 +1980,6 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1980 | */ | 1980 | */ |
1981 | skbdesc = get_skb_frame_desc(skb); | 1981 | skbdesc = get_skb_frame_desc(skb); |
1982 | memset(skbdesc, 0, sizeof(*skbdesc)); | 1982 | memset(skbdesc, 0, sizeof(*skbdesc)); |
1983 | skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; | ||
1984 | skbdesc->data = skb->data + intf->beacon->queue->desc_size; | 1983 | skbdesc->data = skb->data + intf->beacon->queue->desc_size; |
1985 | skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; | 1984 | skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; |
1986 | skbdesc->desc = skb->data; | 1985 | skbdesc->desc = skb->data; |