aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00usb.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 1f5675dd329f..568d73847dca 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -221,7 +221,9 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
221 struct data_ring *ring = entry->ring; 221 struct data_ring *ring = entry->ring;
222 struct rt2x00_dev *rt2x00dev = ring->rt2x00dev; 222 struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
223 struct sk_buff *skb; 223 struct sk_buff *skb;
224 struct ieee80211_hdr *hdr;
224 struct rxdata_entry_desc desc; 225 struct rxdata_entry_desc desc;
226 int header_size;
225 int frame_size; 227 int frame_size;
226 228
227 if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || 229 if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
@@ -243,19 +245,37 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
243 * Allocate a new sk buffer to replace the current one. 245 * Allocate a new sk buffer to replace the current one.
244 * If allocation fails, we should drop the current frame 246 * If allocation fails, we should drop the current frame
245 * so we can recycle the existing sk buffer for the new frame. 247 * so we can recycle the existing sk buffer for the new frame.
248 * As alignment we use 2 and not NET_IP_ALIGN because we need
249 * to be sure we have 2 bytes room in the head. (NET_IP_ALIGN
250 * can be 0 on some hardware). We use these 2 bytes for frame
251 * alignment later, we assume that the chance that
252 * header_size % 4 == 2 is bigger then header_size % 2 == 0
253 * and thus optimize alignment by reserving the 2 bytes in
254 * advance.
246 */ 255 */
247 frame_size = entry->ring->data_size + entry->ring->desc_size; 256 frame_size = entry->ring->data_size + entry->ring->desc_size;
248 skb = dev_alloc_skb(frame_size + NET_IP_ALIGN); 257 skb = dev_alloc_skb(frame_size + 2);
249 if (!skb) 258 if (!skb)
250 goto skip_entry; 259 goto skip_entry;
251 260
252 skb_reserve(skb, NET_IP_ALIGN); 261 skb_reserve(skb, 2);
253 skb_put(skb, frame_size); 262 skb_put(skb, frame_size);
254 263
255 /* 264 /*
256 * Trim the skb_buffer to only contain the valid 265 * The data behind the ieee80211 header must be
257 * frame data (so ignore the device's descriptor). 266 * aligned on a 4 byte boundary.
267 * After that trim the entire buffer down to only
268 * contain the valid frame data excluding the device
269 * descriptor.
258 */ 270 */
271 hdr = (struct ieee80211_hdr *)entry->skb->data;
272 header_size =
273 ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
274
275 if (header_size % 4 == 0) {
276 skb_push(entry->skb, 2);
277 memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2);
278 }
259 skb_trim(entry->skb, desc.size); 279 skb_trim(entry->skb, desc.size);
260 280
261 /* 281 /*