diff options
author | Ivo van Doorn <ivdoorn@gmail.com> | 2008-05-10 07:43:38 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-05-21 21:47:32 -0400 |
commit | 70a96109439cba0af0780ee1dc25ec7ed15f0bae (patch) | |
tree | 1e6feb2b77486a90012f117201c13b35ab2020d7 /drivers/net/wireless/rt2x00/rt73usb.c | |
parent | 61448f88078e813bbaaa58eb775d650c85e7d407 (diff) |
rt2x00: Preserve descriptor information after memmove()
Due to usage of memmove() in rt2x00usb the descriptor can become
corrupted because it is being overwritten by the data part.
Overall having the descriptor in front of the frame is a bad idea,
we can however use the skb->cb array for this task, since that
contains more then enough room to hold the entire descriptor and
preserve the information long enough.
After this we can also cleanup the alignment code a bit to make it
work a bit more flexible to allow for all kinds of odd header lengths.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt73usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 26 |
1 files changed, 11 insertions, 15 deletions
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 2191d8b94a89..1bcf8c132cdc 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -1403,20 +1403,22 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, | |||
1403 | { | 1403 | { |
1404 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 1404 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
1405 | __le32 *rxd = (__le32 *)entry->skb->data; | 1405 | __le32 *rxd = (__le32 *)entry->skb->data; |
1406 | unsigned int offset = entry->queue->desc_size + 2; | ||
1407 | u32 word0; | 1406 | u32 word0; |
1408 | u32 word1; | 1407 | u32 word1; |
1409 | 1408 | ||
1410 | /* | 1409 | /* |
1411 | * Copy descriptor to the available headroom inside the skbuffer. | 1410 | * Copy descriptor to the skb->cb array, this has 2 benefits: |
1411 | * 1) Each descriptor word is 4 byte aligned. | ||
1412 | * 2) Descriptor is safe from moving of frame data in rt2x00usb. | ||
1412 | */ | 1413 | */ |
1413 | skb_push(entry->skb, offset); | 1414 | skbdesc->desc_len = |
1414 | memcpy(entry->skb->data, rxd, entry->queue->desc_size); | 1415 | min_t(u16, entry->queue->desc_size, sizeof(entry->skb->cb)); |
1415 | rxd = (__le32 *)entry->skb->data; | 1416 | memcpy(entry->skb->cb, rxd, skbdesc->desc_len); |
1417 | skbdesc->desc = entry->skb->cb; | ||
1418 | rxd = (__le32 *)skbdesc->desc; | ||
1416 | 1419 | ||
1417 | /* | 1420 | /* |
1418 | * The descriptor is now aligned to 4 bytes and thus it is | 1421 | * It is now safe to read the descriptor on all architectures. |
1419 | * now safe to read it on all architectures. | ||
1420 | */ | 1422 | */ |
1421 | rt2x00_desc_read(rxd, 0, &word0); | 1423 | rt2x00_desc_read(rxd, 0, &word0); |
1422 | rt2x00_desc_read(rxd, 1, &word1); | 1424 | rt2x00_desc_read(rxd, 1, &word1); |
@@ -1442,18 +1444,12 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, | |||
1442 | rxdesc->dev_flags |= RXDONE_MY_BSS; | 1444 | rxdesc->dev_flags |= RXDONE_MY_BSS; |
1443 | 1445 | ||
1444 | /* | 1446 | /* |
1445 | * Adjust the skb memory window to the frame boundaries. | 1447 | * Set skb pointers, and update frame information. |
1446 | */ | 1448 | */ |
1447 | skb_pull(entry->skb, offset + entry->queue->desc_size); | 1449 | skb_pull(entry->skb, entry->queue->desc_size); |
1448 | skb_trim(entry->skb, rxdesc->size); | 1450 | skb_trim(entry->skb, rxdesc->size); |
1449 | |||
1450 | /* | ||
1451 | * Set descriptor and data pointer. | ||
1452 | */ | ||
1453 | skbdesc->data = entry->skb->data; | 1451 | skbdesc->data = entry->skb->data; |
1454 | skbdesc->data_len = rxdesc->size; | 1452 | skbdesc->data_len = rxdesc->size; |
1455 | skbdesc->desc = rxd; | ||
1456 | skbdesc->desc_len = entry->queue->desc_size; | ||
1457 | } | 1453 | } |
1458 | 1454 | ||
1459 | /* | 1455 | /* |