aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00usb.c
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2008-03-09 17:38:18 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-03-13 16:02:33 -0400
commitf855c10b6e7b0c448c35b88266f788dd3738375e (patch)
tree0144787573334e3b87b957347d01453196dc870b /drivers/net/wireless/rt2x00/rt2x00usb.c
parent40e024de932cca8b54fbcd0e5faf8f364cc84ec0 (diff)
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>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00usb.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 063b167da31e..512ff3914813 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -247,11 +247,11 @@ static struct sk_buff* rt2x00usb_alloc_rxskb(struct data_queue *queue)
247 * advance. 247 * advance.
248 */ 248 */
249 frame_size = queue->data_size + queue->desc_size; 249 frame_size = queue->data_size + queue->desc_size;
250 skb = dev_alloc_skb(frame_size + 2); 250 skb = dev_alloc_skb(queue->desc_size + frame_size + 2);
251 if (!skb) 251 if (!skb)
252 return NULL; 252 return NULL;
253 253
254 skb_reserve(skb, 2); 254 skb_reserve(skb, queue->desc_size + 2);
255 skb_put(skb, frame_size); 255 skb_put(skb, frame_size);
256 256
257 return skb; 257 return skb;
@@ -264,6 +264,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
264 struct sk_buff *skb; 264 struct sk_buff *skb;
265 struct skb_frame_desc *skbdesc; 265 struct skb_frame_desc *skbdesc;
266 struct rxdone_entry_desc rxdesc; 266 struct rxdone_entry_desc rxdesc;
267 int header_size;
267 268
268 if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || 269 if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
269 !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) 270 !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
@@ -288,6 +289,18 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
288 rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); 289 rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
289 290
290 /* 291 /*
292 * The data behind the ieee80211 header must be
293 * aligned on a 4 byte boundary.
294 */
295 header_size = ieee80211_get_hdrlen_from_skb(entry->skb);
296 if (header_size % 4 == 0) {
297 skb_push(entry->skb, 2);
298 memmove(entry->skb->data, entry->skb->data + 2,
299 entry->skb->len - 2);
300 skbdesc->data = entry->skb->data;
301 }
302
303 /*
291 * Allocate a new sk buffer to replace the current one. 304 * Allocate a new sk buffer to replace the current one.
292 * If allocation fails, we should drop the current frame 305 * If allocation fails, we should drop the current frame
293 * so we can recycle the existing sk buffer for the new frame. 306 * so we can recycle the existing sk buffer for the new frame.