diff options
author | Ivo van Doorn <IvDoorn@gmail.com> | 2008-06-06 16:47:39 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-06-14 12:17:56 -0400 |
commit | f019d51410a9b61278eeff811a1ca11d2a905241 (patch) | |
tree | 3f038d3e8b7301c33df31344307c7a3180227e51 | |
parent | 565a019ac635d4f5140a8c4da21387c3b2b28fb9 (diff) |
rt2x00: Implement rt2x00usb_kick_tx_queue()
rt2x00usb_kick_tx_queue() will loop over all entries
within the INDEX_DONE->INDEX range and kick each entry
which is pending to be kicked. This makes the kick_tx_queue
approach work the same as with the PCI drivers which
will allow for more code generalisation into rt2x00lib.
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/rt2500usb.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 48 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 4 |
5 files changed, 67 insertions, 3 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 0d51b748c5b7..6abb4c5338f5 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1116,8 +1116,10 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | |||
1116 | { | 1116 | { |
1117 | u16 reg; | 1117 | u16 reg; |
1118 | 1118 | ||
1119 | if (queue != QID_BEACON) | 1119 | if (queue != QID_BEACON) { |
1120 | rt2x00usb_kick_tx_queue(rt2x00dev, queue); | ||
1120 | return; | 1121 | return; |
1122 | } | ||
1121 | 1123 | ||
1122 | rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); | 1124 | rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); |
1123 | if (!rt2x00_get_field16(reg, TXRX_CSR19_BEACON_GEN)) { | 1125 | if (!rt2x00_get_field16(reg, TXRX_CSR19_BEACON_GEN)) { |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 4d00ced14cc7..303d5568470d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -260,11 +260,14 @@ struct txentry_desc { | |||
260 | * @ENTRY_OWNER_DEVICE_CRYPTO: This entry is owned by the device for data | 260 | * @ENTRY_OWNER_DEVICE_CRYPTO: This entry is owned by the device for data |
261 | * encryption or decryption. The entry should only be touched after | 261 | * encryption or decryption. The entry should only be touched after |
262 | * the device has signaled it is done with it. | 262 | * the device has signaled it is done with it. |
263 | * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting | ||
264 | * for the signal to start sending. | ||
263 | */ | 265 | */ |
264 | enum queue_entry_flags { | 266 | enum queue_entry_flags { |
265 | ENTRY_BCN_ASSIGNED, | 267 | ENTRY_BCN_ASSIGNED, |
266 | ENTRY_OWNER_DEVICE_DATA, | 268 | ENTRY_OWNER_DEVICE_DATA, |
267 | ENTRY_OWNER_DEVICE_CRYPTO, | 269 | ENTRY_OWNER_DEVICE_CRYPTO, |
270 | ENTRY_DATA_PENDING, | ||
268 | }; | 271 | }; |
269 | 272 | ||
270 | /** | 273 | /** |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 66f15e6c7d25..cdac9280fe42 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -232,9 +232,10 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, | |||
232 | * Initialize URB and send the frame to the device. | 232 | * Initialize URB and send the frame to the device. |
233 | */ | 233 | */ |
234 | __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 234 | __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
235 | __set_bit(ENTRY_DATA_PENDING, &entry->flags); | ||
236 | |||
235 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, usb_sndbulkpipe(usb_dev, 1), | 237 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, usb_sndbulkpipe(usb_dev, 1), |
236 | skb->data, length, rt2x00usb_interrupt_txdone, entry); | 238 | skb->data, length, rt2x00usb_interrupt_txdone, entry); |
237 | usb_submit_urb(entry_priv->urb, GFP_ATOMIC); | ||
238 | 239 | ||
239 | rt2x00queue_index_inc(queue, Q_INDEX); | 240 | rt2x00queue_index_inc(queue, Q_INDEX); |
240 | 241 | ||
@@ -242,6 +243,51 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, | |||
242 | } | 243 | } |
243 | EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data); | 244 | EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data); |
244 | 245 | ||
246 | static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) | ||
247 | { | ||
248 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | ||
249 | |||
250 | if (__test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) | ||
251 | usb_submit_urb(entry_priv->urb, GFP_ATOMIC); | ||
252 | } | ||
253 | |||
254 | void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | ||
255 | const enum data_queue_qid qid) | ||
256 | { | ||
257 | struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, qid); | ||
258 | unsigned long irqflags; | ||
259 | unsigned int index; | ||
260 | unsigned int index_done; | ||
261 | unsigned int i; | ||
262 | |||
263 | /* | ||
264 | * Only protect the range we are going to loop over, | ||
265 | * if during our loop a extra entry is set to pending | ||
266 | * it should not be kicked during this run, since it | ||
267 | * is part of another TX operation. | ||
268 | */ | ||
269 | spin_lock_irqsave(&queue->lock, irqflags); | ||
270 | index = queue->index[Q_INDEX]; | ||
271 | index_done = queue->index[Q_INDEX_DONE]; | ||
272 | spin_unlock_irqrestore(&queue->lock, irqflags); | ||
273 | |||
274 | /* | ||
275 | * Start from the TX done pointer, this guarentees that we will | ||
276 | * send out all frames in the correct order. | ||
277 | */ | ||
278 | if (index_done < index) { | ||
279 | for (i = index_done; i < index; i++) | ||
280 | rt2x00usb_kick_tx_entry(&queue->entries[i]); | ||
281 | } else { | ||
282 | for (i = index_done; i < queue->limit; i++) | ||
283 | rt2x00usb_kick_tx_entry(&queue->entries[i]); | ||
284 | |||
285 | for (i = 0; i < index; i++) | ||
286 | rt2x00usb_kick_tx_entry(&queue->entries[i]); | ||
287 | } | ||
288 | } | ||
289 | EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue); | ||
290 | |||
245 | /* | 291 | /* |
246 | * RX data handlers. | 292 | * RX data handlers. |
247 | */ | 293 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 26f53f868af6..460d32c444d1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h | |||
@@ -245,6 +245,17 @@ struct queue_entry_priv_usb_bcn { | |||
245 | struct urb *guardian_urb; | 245 | struct urb *guardian_urb; |
246 | }; | 246 | }; |
247 | 247 | ||
248 | /** | ||
249 | * rt2x00usb_kick_tx_queue - Kick data queue | ||
250 | * @rt2x00dev: Pointer to &struct rt2x00_dev | ||
251 | * @qid: Data queue to kick | ||
252 | * | ||
253 | * This will walk through all entries of the queue and push all pending | ||
254 | * frames to the hardware as a single burst. | ||
255 | */ | ||
256 | void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | ||
257 | const enum data_queue_qid qid); | ||
258 | |||
248 | /* | 259 | /* |
249 | * Device initialization handlers. | 260 | * Device initialization handlers. |
250 | */ | 261 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index db1fc136cda4..5e5f6034383a 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -1350,8 +1350,10 @@ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | |||
1350 | { | 1350 | { |
1351 | u32 reg; | 1351 | u32 reg; |
1352 | 1352 | ||
1353 | if (queue != QID_BEACON) | 1353 | if (queue != QID_BEACON) { |
1354 | rt2x00usb_kick_tx_queue(rt2x00dev, queue); | ||
1354 | return; | 1355 | return; |
1356 | } | ||
1355 | 1357 | ||
1356 | /* | 1358 | /* |
1357 | * For Wi-Fi faily generated beacons between participating stations. | 1359 | * For Wi-Fi faily generated beacons between participating stations. |