rt2x00: Align RX descriptor to 4 bytes

Some architectures give problems when reading
RX frame descriptor words when the descriptor
is not aligned on a 4 byte boundrary.

Due to optimalizations for the ieee80211 payload
4 byte alignment, it is no longer guarenteed
that the descriptor is placed on the 4 byte
boundrary (In fact, for rt73usb it is absolutely
never aligned to 4 bytes, for rt2500usb it depends
on the length of the payload).

This will copy the descriptor to a 4 byte aligned
location before it is read for the first time.
This will also move the payload data alignment
in rt2x00usb (instead of inside the driver) where
it has always belonged.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Ivo van Doorn
2008-03-09 22:38:18 +01:00
committed by John W. Linville
parent 40e024de93
commit f855c10b6e
3 changed files with 49 additions and 44 deletions

View File

@ -247,11 +247,11 @@ static struct sk_buff* rt2x00usb_alloc_rxskb(struct data_queue *queue)
* advance.
*/
frame_size = queue->data_size + queue->desc_size;
skb = dev_alloc_skb(frame_size + 2);
skb = dev_alloc_skb(queue->desc_size + frame_size + 2);
if (!skb)
return NULL;
skb_reserve(skb, 2);
skb_reserve(skb, queue->desc_size + 2);
skb_put(skb, frame_size);
return skb;
@ -264,6 +264,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
struct sk_buff *skb;
struct skb_frame_desc *skbdesc;
struct rxdone_entry_desc rxdesc;
int header_size;
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
@ -287,6 +288,18 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
memset(&rxdesc, 0, sizeof(rxdesc));
rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
/*
* The data behind the ieee80211 header must be
* aligned on a 4 byte boundary.
*/
header_size = ieee80211_get_hdrlen_from_skb(entry->skb);
if (header_size % 4 == 0) {
skb_push(entry->skb, 2);
memmove(entry->skb->data, entry->skb->data + 2,
entry->skb->len - 2);
skbdesc->data = entry->skb->data;
}
/*
* Allocate a new sk buffer to replace the current one.
* If allocation fails, we should drop the current frame