aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRA-Jay Hung <Jay_Hung@ralinktech.com>2010-11-13 13:11:46 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-17 16:18:55 -0500
commitb43d63bd69ae5464a52bf1796e84097607917b2f (patch)
tree250c4ae0481e888392dca3f24c188b6eed341a31
parentef8397cfb3a385bc57a32213d0e4a5b7903a9dc6 (diff)
rt2x00: Fix rt2800 USB TX Path DMA issue
rt2800usb chips need to add 1~3 bytes zero padding after each 802.11 header & payload, and at the end need to add 4 bytes zero padding whether doing TX bulk aggregation or not, TXINFO_W0_USB_DMA_TX_PKT_LEN in TXINFO must include 1-3 bytes padding after 802.11 header & payload but do not include 4 bytes end zero padding. In rt2800usb_get_tx_data_len do not consider multiple of the USB packet size case, sometimes this will cause USB DMA problem. Signed-off-by: RA-Jay Hung <jay_hung@ralinktech.com> 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/rt2800usb.c39
1 files changed, 26 insertions, 13 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 2933bf1d74bb..935b76d3ce4f 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -307,8 +307,14 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry,
307 * Initialize TXINFO descriptor 307 * Initialize TXINFO descriptor
308 */ 308 */
309 rt2x00_desc_read(txi, 0, &word); 309 rt2x00_desc_read(txi, 0, &word);
310
311 /*
312 * The size of TXINFO_W0_USB_DMA_TX_PKT_LEN is
313 * TXWI + 802.11 header + L2 pad + payload + pad,
314 * so need to decrease size of TXINFO and USB end pad.
315 */
310 rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, 316 rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
311 entry->skb->len - TXINFO_DESC_SIZE); 317 entry->skb->len - TXINFO_DESC_SIZE - 4);
312 rt2x00_set_field32(&word, TXINFO_W0_WIV, 318 rt2x00_set_field32(&word, TXINFO_W0_WIV,
313 !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); 319 !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
314 rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2); 320 rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2);
@@ -326,22 +332,29 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry,
326 skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE; 332 skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE;
327} 333}
328 334
329/* 335static void rt2800usb_write_tx_data(struct queue_entry *entry,
330 * TX data initialization 336 struct txentry_desc *txdesc)
331 */
332static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
333{ 337{
334 int length; 338 u8 padding_len;
335 339
336 /* 340 /*
337 * The length _must_ include 4 bytes padding, 341 * pad(1~3 bytes) is added after each 802.11 payload.
338 * it should always be multiple of 4, 342 * USB end pad(4 bytes) is added at each USB bulk out packet end.
339 * but it must _not_ be a multiple of the USB packet size. 343 * TX frame format is :
344 * | TXINFO | TXWI | 802.11 header | L2 pad | payload | pad | USB end pad |
345 * |<------------- tx_pkt_len ------------->|
340 */ 346 */
341 length = roundup(entry->skb->len + 4, 4); 347 rt2800_write_tx_data(entry, txdesc);
342 length += (4 * !(length % entry->queue->usb_maxpacket)); 348 padding_len = roundup(entry->skb->len + 4, 4) - entry->skb->len;
349 memset(skb_put(entry->skb, padding_len), 0, padding_len);
350}
343 351
344 return length; 352/*
353 * TX data initialization
354 */
355static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
356{
357 return entry->skb->len;
345} 358}
346 359
347/* 360/*
@@ -579,7 +592,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
579 .link_tuner = rt2800_link_tuner, 592 .link_tuner = rt2800_link_tuner,
580 .watchdog = rt2800usb_watchdog, 593 .watchdog = rt2800usb_watchdog,
581 .write_tx_desc = rt2800usb_write_tx_desc, 594 .write_tx_desc = rt2800usb_write_tx_desc,
582 .write_tx_data = rt2800_write_tx_data, 595 .write_tx_data = rt2800usb_write_tx_data,
583 .write_beacon = rt2800_write_beacon, 596 .write_beacon = rt2800_write_beacon,
584 .get_tx_data_len = rt2800usb_get_tx_data_len, 597 .get_tx_data_len = rt2800usb_get_tx_data_len,
585 .kick_tx_queue = rt2x00usb_kick_tx_queue, 598 .kick_tx_queue = rt2x00usb_kick_tx_queue,