aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorGertjan van Wingerde <gwingerde@gmail.com>2010-06-03 04:51:45 -0400
committerIvo van Doorn <IvDoorn@gmail.com>2010-06-03 04:51:45 -0400
commit0b8004aa12d13ec750d102ba4082a95f0107c649 (patch)
treeeac5224159d34ae525b552254816c3a1e056336c /drivers/net/wireless
parentbaaffe67b5b33e4215409669226ef623cb65e15c (diff)
rt2x00: Properly reserve room for descriptors in skbs.
Instead of fiddling with the skb->data pointer and thereby risking out of bounds accesses, properly reserve the space needed in an skb for descriptors. Signed-off-by: Gertjan van Wingerde <gwingerde@gmail.com> Acked-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c14
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c23
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c22
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h7
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c5
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h7
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c40
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.h8
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c24
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c14
16 files changed, 109 insertions, 79 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 1e543ac2f86f..1eb882e15fb4 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1229,7 +1229,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
1229 } 1229 }
1230 txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); 1230 txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
1231 1231
1232 rt2x00lib_txdone(entry, &txdesc); 1232 rt2x00pci_txdone(entry, &txdesc);
1233 } 1233 }
1234} 1234}
1235 1235
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 1582cabd3a1e..a29cb212f89a 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1365,7 +1365,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
1365 } 1365 }
1366 txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); 1366 txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
1367 1367
1368 rt2x00lib_txdone(entry, &txdesc); 1368 rt2x00pci_txdone(entry, &txdesc);
1369 } 1369 }
1370} 1370}
1371 1371
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index d19f29a53523..9dab1dccdaff 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1034,7 +1034,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
1034 struct txentry_desc *txdesc) 1034 struct txentry_desc *txdesc)
1035{ 1035{
1036 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); 1036 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
1037 __le32 *txd = (__le32 *)(skb->data - TXD_DESC_SIZE); 1037 __le32 *txd = (__le32 *) skb->data;
1038 u32 word; 1038 u32 word;
1039 1039
1040 /* 1040 /*
@@ -1080,6 +1080,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
1080 /* 1080 /*
1081 * Register descriptor details in skb frame descriptor. 1081 * Register descriptor details in skb frame descriptor.
1082 */ 1082 */
1083 skbdesc->flags |= SKBDESC_DESC_IN_SKB;
1083 skbdesc->desc = txd; 1084 skbdesc->desc = txd;
1084 skbdesc->desc_len = TXD_DESC_SIZE; 1085 skbdesc->desc_len = TXD_DESC_SIZE;
1085} 1086}
@@ -1108,6 +1109,12 @@ static void rt2500usb_write_beacon(struct queue_entry *entry,
1108 rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); 1109 rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
1109 1110
1110 /* 1111 /*
1112 * Add space for the descriptor in front of the skb.
1113 */
1114 skb_push(entry->skb, TXD_DESC_SIZE);
1115 memset(entry->skb->data, 0, TXD_DESC_SIZE);
1116
1117 /*
1111 * Write the TX descriptor for the beacon. 1118 * Write the TX descriptor for the beacon.
1112 */ 1119 */
1113 rt2500usb_write_tx_desc(rt2x00dev, entry->skb, txdesc); 1120 rt2500usb_write_tx_desc(rt2x00dev, entry->skb, txdesc);
@@ -1118,11 +1125,6 @@ static void rt2500usb_write_beacon(struct queue_entry *entry,
1118 rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); 1125 rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
1119 1126
1120 /* 1127 /*
1121 * Take the descriptor in front of the skb into account.
1122 */
1123 skb_push(entry->skb, TXD_DESC_SIZE);
1124
1125 /*
1126 * USB devices cannot blindly pass the skb->len as the 1128 * USB devices cannot blindly pass the skb->len as the
1127 * length of the data to usb_fill_bulk_urb. Pass the skb 1129 * length of the data to usb_fill_bulk_urb. Pass the skb
1128 * to the driver to determine what the length should be. 1130 * to the driver to determine what the length should be.
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index db4250d1c8b3..3258301aa29c 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -282,9 +282,8 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
282} 282}
283EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); 283EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready);
284 284
285void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc) 285void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc)
286{ 286{
287 __le32 *txwi = (__le32 *)(skb->data - TXWI_DESC_SIZE);
288 u32 word; 287 u32 word;
289 288
290 /* 289 /*
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index 94de999e2290..0f0a13c61e68 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -111,7 +111,7 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
111 const u8 command, const u8 token, 111 const u8 command, const u8 token,
112 const u8 arg0, const u8 arg1); 112 const u8 arg0, const u8 arg1);
113 113
114void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc); 114void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc);
115void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *txdesc); 115void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *txdesc);
116 116
117extern const struct rt2x00debug rt2800_rt2x00debug; 117extern const struct rt2x00debug rt2800_rt2x00debug;
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 72e4f29a2fc7..db61a78e32b0 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -616,7 +616,7 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
616static void rt2800pci_write_tx_datadesc(struct queue_entry* entry, 616static void rt2800pci_write_tx_datadesc(struct queue_entry* entry,
617 struct txentry_desc *txdesc) 617 struct txentry_desc *txdesc)
618{ 618{
619 rt2800_write_txwi(entry->skb, txdesc); 619 rt2800_write_txwi((__le32 *) entry->skb->data, txdesc);
620} 620}
621 621
622 622
@@ -693,15 +693,22 @@ static void rt2800pci_write_beacon(struct queue_entry *entry,
693 rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); 693 rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
694 694
695 /* 695 /*
696 * Add space for the TXWI in front of the skb.
697 */
698 skb_push(entry->skb, TXWI_DESC_SIZE);
699 memset(entry->skb, 0, TXWI_DESC_SIZE);
700
701 /*
696 * Register descriptor details in skb frame descriptor. 702 * Register descriptor details in skb frame descriptor.
697 */ 703 */
698 skbdesc->desc = entry->skb->data - TXWI_DESC_SIZE; 704 skbdesc->flags |= SKBDESC_DESC_IN_SKB;
705 skbdesc->desc = entry->skb->data;
699 skbdesc->desc_len = TXWI_DESC_SIZE; 706 skbdesc->desc_len = TXWI_DESC_SIZE;
700 707
701 /* 708 /*
702 * Add the TXWI for the beacon to the skb. 709 * Add the TXWI for the beacon to the skb.
703 */ 710 */
704 rt2800_write_txwi(entry->skb, txdesc); 711 rt2800_write_txwi((__le32 *)entry->skb->data, txdesc);
705 712
706 /* 713 /*
707 * Dump beacon to userspace through debugfs. 714 * Dump beacon to userspace through debugfs.
@@ -709,11 +716,6 @@ static void rt2800pci_write_beacon(struct queue_entry *entry,
709 rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); 716 rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
710 717
711 /* 718 /*
712 * Adjust skb to take TXWI into account.
713 */
714 skb_push(entry->skb, TXWI_DESC_SIZE);
715
716 /*
717 * Write entire beacon with TXWI to register. 719 * Write entire beacon with TXWI to register.
718 */ 720 */
719 beacon_base = HW_BEACON_OFFSET(entry->entry_idx); 721 beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
@@ -888,8 +890,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
888 890
889 /* Check if we got a match by looking at WCID/ACK/PID 891 /* Check if we got a match by looking at WCID/ACK/PID
890 * fields */ 892 * fields */
891 txwi = (__le32 *)(entry->skb->data - 893 txwi = (__le32 *) entry->skb->data;
892 rt2x00dev->ops->extra_tx_headroom);
893 894
894 rt2x00_desc_read(txwi, 1, &word); 895 rt2x00_desc_read(txwi, 1, &word);
895 tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); 896 tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
@@ -934,7 +935,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
934 __set_bit(TXDONE_FALLBACK, &txdesc.flags); 935 __set_bit(TXDONE_FALLBACK, &txdesc.flags);
935 936
936 937
937 rt2x00lib_txdone(entry, &txdesc); 938 rt2x00pci_txdone(entry, &txdesc);
938 } 939 }
939} 940}
940 941
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index d0d8060040ba..ee407f138753 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -400,13 +400,14 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
400 struct txentry_desc *txdesc) 400 struct txentry_desc *txdesc)
401{ 401{
402 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); 402 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
403 __le32 *txi = (__le32 *)(skb->data - TXWI_DESC_SIZE - TXINFO_DESC_SIZE); 403 __le32 *txi = (__le32 *) skb->data;
404 __le32 *txwi = (__le32 *) (skb->data + TXINFO_DESC_SIZE);
404 u32 word; 405 u32 word;
405 406
406 /* 407 /*
407 * Initialize TXWI descriptor 408 * Initialize TXWI descriptor
408 */ 409 */
409 rt2800_write_txwi(skb, txdesc); 410 rt2800_write_txwi(txwi, txdesc);
410 411
411 /* 412 /*
412 * Initialize TXINFO descriptor 413 * Initialize TXINFO descriptor
@@ -426,6 +427,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
426 /* 427 /*
427 * Register descriptor details in skb frame descriptor. 428 * Register descriptor details in skb frame descriptor.
428 */ 429 */
430 skbdesc->flags |= SKBDESC_DESC_IN_SKB;
429 skbdesc->desc = txi; 431 skbdesc->desc = txi;
430 skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE; 432 skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE;
431} 433}
@@ -450,15 +452,22 @@ static void rt2800usb_write_beacon(struct queue_entry *entry,
450 rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); 452 rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
451 453
452 /* 454 /*
455 * Add space for the TXWI in front of the skb.
456 */
457 skb_push(entry->skb, TXWI_DESC_SIZE);
458 memset(entry->skb, 0, TXWI_DESC_SIZE);
459
460 /*
453 * Register descriptor details in skb frame descriptor. 461 * Register descriptor details in skb frame descriptor.
454 */ 462 */
455 skbdesc->desc = entry->skb->data - TXWI_DESC_SIZE; 463 skbdesc->flags |= SKBDESC_DESC_IN_SKB;
464 skbdesc->desc = entry->skb->data;
456 skbdesc->desc_len = TXWI_DESC_SIZE; 465 skbdesc->desc_len = TXWI_DESC_SIZE;
457 466
458 /* 467 /*
459 * Add the TXWI for the beacon to the skb. 468 * Add the TXWI for the beacon to the skb.
460 */ 469 */
461 rt2800_write_txwi(entry->skb, txdesc); 470 rt2800_write_txwi((__le32 *) entry->skb->data, txdesc);
462 471
463 /* 472 /*
464 * Dump beacon to userspace through debugfs. 473 * Dump beacon to userspace through debugfs.
@@ -466,11 +475,6 @@ static void rt2800usb_write_beacon(struct queue_entry *entry,
466 rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); 475 rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
467 476
468 /* 477 /*
469 * Adjust skb to take TXWI into account.
470 */
471 skb_push(entry->skb, TXWI_DESC_SIZE);
472
473 /*
474 * Write entire beacon with descriptor to register. 478 * Write entire beacon with descriptor to register.
475 */ 479 */
476 beacon_base = HW_BEACON_OFFSET(entry->entry_idx); 480 beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 811844be0053..889a372367f6 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -1002,6 +1002,13 @@ static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev)
1002void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); 1002void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
1003 1003
1004/** 1004/**
1005 * rt2x00queue_unmap_skb - Unmap a skb from DMA.
1006 * @rt2x00dev: Pointer to &struct rt2x00_dev.
1007 * @skb: The skb to unmap.
1008 */
1009void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
1010
1011/**
1005 * rt2x00queue_get_queue - Convert queue index to queue pointer 1012 * rt2x00queue_get_queue - Convert queue index to queue pointer
1006 * @rt2x00dev: Pointer to &struct rt2x00_dev. 1013 * @rt2x00dev: Pointer to &struct rt2x00_dev.
1007 * @queue: rt2x00 queue index (see &enum data_queue_qid). 1014 * @queue: rt2x00 queue index (see &enum data_queue_qid).
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 2ed32e02a06f..0b8efe8e6785 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -211,11 +211,6 @@ void rt2x00lib_txdone(struct queue_entry *entry,
211 bool success; 211 bool success;
212 212
213 /* 213 /*
214 * Unmap the skb.
215 */
216 rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
217
218 /*
219 * Remove L2 padding which was added during 214 * Remove L2 padding which was added during
220 */ 215 */
221 if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) 216 if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 0ca40e1fe699..822affc9b4ca 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -105,13 +105,6 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev,
105 struct queue_entry *entry); 105 struct queue_entry *entry);
106 106
107/** 107/**
108 * rt2x00queue_unmap_skb - Unmap a skb from DMA.
109 * @rt2x00dev: Pointer to &struct rt2x00_dev.
110 * @skb: The skb to unmap.
111 */
112void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
113
114/**
115 * rt2x00queue_free_skb - free a skb 108 * rt2x00queue_free_skb - free a skb
116 * @rt2x00dev: Pointer to &struct rt2x00_dev. 109 * @rt2x00dev: Pointer to &struct rt2x00_dev.
117 * @skb: The skb to free. 110 * @skb: The skb to free.
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 494b960e811c..d583ee070b47 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -82,11 +82,23 @@ int rt2x00pci_write_tx_data(struct queue_entry *entry,
82 } 82 }
83 83
84 /* 84 /*
85 * Add the requested extra tx headroom in front of the skb.
86 */
87 skb_push(entry->skb, rt2x00dev->ops->extra_tx_headroom);
88 memset(entry->skb->data, 0, rt2x00dev->ops->extra_tx_headroom);
89
90 /*
85 * Call the driver's write_tx_datadesc function, if it exists. 91 * Call the driver's write_tx_datadesc function, if it exists.
86 */ 92 */
87 if (rt2x00dev->ops->lib->write_tx_datadesc) 93 if (rt2x00dev->ops->lib->write_tx_datadesc)
88 rt2x00dev->ops->lib->write_tx_datadesc(entry, txdesc); 94 rt2x00dev->ops->lib->write_tx_datadesc(entry, txdesc);
89 95
96 /*
97 * Map the skb to DMA.
98 */
99 if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
100 rt2x00queue_map_txskb(rt2x00dev, entry->skb);
101
90 return 0; 102 return 0;
91} 103}
92EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data); 104EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data);
@@ -94,6 +106,34 @@ EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data);
94/* 106/*
95 * TX/RX data handlers. 107 * TX/RX data handlers.
96 */ 108 */
109void rt2x00pci_txdone(struct queue_entry *entry,
110 struct txdone_entry_desc *txdesc)
111{
112 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
113 struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
114
115 /*
116 * Unmap the skb.
117 */
118 rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
119
120 /*
121 * Remove the extra tx headroom from the skb.
122 */
123 skb_pull(entry->skb, rt2x00dev->ops->extra_tx_headroom);
124
125 /*
126 * Signal that the TX descriptor is no longer in the skb.
127 */
128 skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
129
130 /*
131 * Pass on to rt2x00lib.
132 */
133 rt2x00lib_txdone(entry, txdesc);
134}
135EXPORT_SYMBOL_GPL(rt2x00pci_txdone);
136
97void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) 137void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
98{ 138{
99 struct data_queue *queue = rt2x00dev->rx; 139 struct data_queue *queue = rt2x00dev->rx;
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
index 51bcef3839ce..00528b8a754d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -109,6 +109,14 @@ struct queue_entry_priv_pci {
109}; 109};
110 110
111/** 111/**
112 * rt2x00pci_txdone - Handle TX done events.
113 * @entry: The queue entry for which a TX done event was received.
114 * @txdesc: The TX done descriptor for the entry.
115 */
116void rt2x00pci_txdone(struct queue_entry *entry,
117 struct txdone_entry_desc *txdesc);
118
119/**
112 * rt2x00pci_rxdone - Handle RX done events 120 * rt2x00pci_rxdone - Handle RX done events
113 * @rt2x00dev: Device pointer, see &struct rt2x00_dev. 121 * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
114 */ 122 */
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index cf7bfe774e00..35858b178e8f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -100,21 +100,8 @@ void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
100{ 100{
101 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); 101 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
102 102
103 /*
104 * If device has requested headroom, we should make sure that
105 * is also mapped to the DMA so it can be used for transfering
106 * additional descriptor information to the hardware.
107 */
108 skb_push(skb, rt2x00dev->ops->extra_tx_headroom);
109
110 skbdesc->skb_dma = 103 skbdesc->skb_dma =
111 dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE); 104 dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE);
112
113 /*
114 * Restore data pointer to original location again.
115 */
116 skb_pull(skb, rt2x00dev->ops->extra_tx_headroom);
117
118 skbdesc->flags |= SKBDESC_DMA_MAPPED_TX; 105 skbdesc->flags |= SKBDESC_DMA_MAPPED_TX;
119} 106}
120EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb); 107EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb);
@@ -130,16 +117,12 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
130 } 117 }
131 118
132 if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) { 119 if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) {
133 /* 120 dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len,
134 * Add headroom to the skb length, it has been removed
135 * by the driver, but it was actually mapped to DMA.
136 */
137 dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma,
138 skb->len + rt2x00dev->ops->extra_tx_headroom,
139 DMA_TO_DEVICE); 121 DMA_TO_DEVICE);
140 skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX; 122 skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX;
141 } 123 }
142} 124}
125EXPORT_SYMBOL_GPL(rt2x00queue_unmap_skb);
143 126
144void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) 127void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
145{ 128{
@@ -534,9 +517,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
534 return -EIO; 517 return -EIO;
535 } 518 }
536 519
537 if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
538 rt2x00queue_map_txskb(queue->rt2x00dev, skb);
539
540 set_bit(ENTRY_DATA_PENDING, &entry->flags); 520 set_bit(ENTRY_DATA_PENDING, &entry->flags);
541 521
542 rt2x00queue_index_inc(queue, Q_INDEX); 522 rt2x00queue_index_inc(queue, Q_INDEX);
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 25cc376d388e..5e123519f8cb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -198,6 +198,11 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
198 return; 198 return;
199 199
200 /* 200 /*
201 * Remove the descriptor from the front of the skb.
202 */
203 skb_pull(entry->skb, entry->queue->desc_size);
204
205 /*
201 * Obtain the status about this packet. 206 * Obtain the status about this packet.
202 * Note that when the status is 0 it does not mean the 207 * Note that when the status is 0 it does not mean the
203 * frame was send out correctly. It only means the frame 208 * frame was send out correctly. It only means the frame
@@ -243,12 +248,6 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry,
243 rt2x00usb_interrupt_txdone, entry); 248 rt2x00usb_interrupt_txdone, entry);
244 249
245 /* 250 /*
246 * Make sure the skb->data pointer points to the frame, not the
247 * descriptor.
248 */
249 skb_pull(entry->skb, entry->queue->desc_size);
250
251 /*
252 * Call the driver's write_tx_datadesc function, if it exists. 251 * Call the driver's write_tx_datadesc function, if it exists.
253 */ 252 */
254 if (rt2x00dev->ops->lib->write_tx_datadesc) 253 if (rt2x00dev->ops->lib->write_tx_datadesc)
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index a7205c1711de..243df08ae910 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2110,7 +2110,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
2110 __set_bit(TXDONE_UNKNOWN, &txdesc.flags); 2110 __set_bit(TXDONE_UNKNOWN, &txdesc.flags);
2111 txdesc.retry = 0; 2111 txdesc.retry = 0;
2112 2112
2113 rt2x00lib_txdone(entry_done, &txdesc); 2113 rt2x00pci_txdone(entry_done, &txdesc);
2114 entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); 2114 entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
2115 } 2115 }
2116 2116
@@ -2130,7 +2130,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
2130 } 2130 }
2131 txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); 2131 txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
2132 2132
2133 rt2x00lib_txdone(entry, &txdesc); 2133 rt2x00pci_txdone(entry, &txdesc);
2134 } 2134 }
2135} 2135}
2136 2136
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index bd9a53e5fd9f..4ab38c3641cc 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1442,7 +1442,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
1442 struct txentry_desc *txdesc) 1442 struct txentry_desc *txdesc)
1443{ 1443{
1444 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); 1444 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
1445 __le32 *txd = (__le32 *)(skb->data - TXD_DESC_SIZE); 1445 __le32 *txd = (__le32 *) skb->data;
1446 u32 word; 1446 u32 word;
1447 1447
1448 /* 1448 /*
@@ -1505,6 +1505,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
1505 /* 1505 /*
1506 * Register descriptor details in skb frame descriptor. 1506 * Register descriptor details in skb frame descriptor.
1507 */ 1507 */
1508 skbdesc->flags |= SKBDESC_DESC_IN_SKB;
1508 skbdesc->desc = txd; 1509 skbdesc->desc = txd;
1509 skbdesc->desc_len = TXD_DESC_SIZE; 1510 skbdesc->desc_len = TXD_DESC_SIZE;
1510} 1511}
@@ -1528,6 +1529,12 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
1528 rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); 1529 rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
1529 1530
1530 /* 1531 /*
1532 * Add space for the descriptor in front of the skb.
1533 */
1534 skb_push(entry->skb, TXD_DESC_SIZE);
1535 memset(entry->skb->data, 0, TXD_DESC_SIZE);
1536
1537 /*
1531 * Write the TX descriptor for the beacon. 1538 * Write the TX descriptor for the beacon.
1532 */ 1539 */
1533 rt73usb_write_tx_desc(rt2x00dev, entry->skb, txdesc); 1540 rt73usb_write_tx_desc(rt2x00dev, entry->skb, txdesc);
@@ -1538,11 +1545,6 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
1538 rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); 1545 rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
1539 1546
1540 /* 1547 /*
1541 * Take the descriptor in front of the skb into account.
1542 */
1543 skb_push(entry->skb, TXD_DESC_SIZE);
1544
1545 /*
1546 * Write entire beacon with descriptor to register. 1548 * Write entire beacon with descriptor to register.
1547 */ 1549 */
1548 beacon_base = HW_BEACON_OFFSET(entry->entry_idx); 1550 beacon_base = HW_BEACON_OFFSET(entry->entry_idx);