diff options
author | Gertjan van Wingerde <gwingerde@gmail.com> | 2010-06-03 04:51:45 -0400 |
---|---|---|
committer | Ivo van Doorn <IvDoorn@gmail.com> | 2010-06-03 04:51:45 -0400 |
commit | 0b8004aa12d13ec750d102ba4082a95f0107c649 (patch) | |
tree | eac5224159d34ae525b552254816c3a1e056336c /drivers/net/wireless/rt2x00 | |
parent | baaffe67b5b33e4215409669226ef623cb65e15c (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/rt2x00')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2400pci.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500pci.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 14 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800pci.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800usb.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00lib.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00pci.c | 40 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00pci.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 24 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt61pci.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 14 |
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 | } |
283 | EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); | 283 | EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); |
284 | 284 | ||
285 | void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc) | 285 | void 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 | ||
114 | void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc); | 114 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc); |
115 | void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *txdesc); | 115 | void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *txdesc); |
116 | 116 | ||
117 | extern const struct rt2x00debug rt2800_rt2x00debug; | 117 | extern 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, | |||
616 | static void rt2800pci_write_tx_datadesc(struct queue_entry* entry, | 616 | static 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) | |||
1002 | void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); | 1002 | void 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 | */ | ||
1009 | void 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 | */ | ||
112 | void 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 | } |
92 | EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data); | 104 | EXPORT_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 | */ |
109 | void 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 | } | ||
135 | EXPORT_SYMBOL_GPL(rt2x00pci_txdone); | ||
136 | |||
97 | void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) | 137 | void 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 | */ | ||
116 | void 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 | } |
120 | EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb); | 107 | EXPORT_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 | } |
125 | EXPORT_SYMBOL_GPL(rt2x00queue_unmap_skb); | ||
143 | 126 | ||
144 | void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) | 127 | void 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); |