aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvo van Doorn <IvDoorn@gmail.com>2008-06-06 16:53:14 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-14 12:17:56 -0400
commitb869767b6f5049f1d1ede2bb3e48832e0722ca5a (patch)
treea75e43aad931ffdaea889af7b2275f12a16f077a
parent6db3786aee36b32e5ed072ed67fad6d5341b0991 (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.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c10
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c28
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h19
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c1
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);
163void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, 163void 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}
189EXPORT_SYMBOL_GPL(rt2x00queue_write_tx_descriptor); 194EXPORT_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 */
88enum 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 */
473static 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;