struct data_entry *entry;
struct data_desc *rxd;
struct sk_buff *skb;
+ struct ieee80211_hdr *hdr;
struct rxdata_entry_desc desc;
+ int header_size;
+ int align;
u32 word;
while (1) {
memset(&desc, 0x00, sizeof(desc));
rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
+ hdr = (struct ieee80211_hdr *)entry->data_addr;
+ header_size =
+ ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
+
+ /*
+ * The data behind the ieee80211 header must be
+ * aligned on a 4 byte boundary.
+ */
+ align = NET_IP_ALIGN + (2 * (header_size % 4 == 0));
+
/*
* Allocate the sk_buffer, initialize it and copy
* all data into it.
*/
- skb = dev_alloc_skb(desc.size + NET_IP_ALIGN);
+ skb = dev_alloc_skb(desc.size + align);
if (!skb)
return;
- skb_reserve(skb, NET_IP_ALIGN);
- skb_put(skb, desc.size);
- memcpy(skb->data, entry->data_addr, desc.size);
+ skb_reserve(skb, align);
+ memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size);
/*
* Send the frame to rt2x00lib for further processing.
struct data_ring *ring = entry->ring;
struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
struct sk_buff *skb;
+ struct ieee80211_hdr *hdr;
struct rxdata_entry_desc desc;
+ int header_size;
int frame_size;
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
skb_put(skb, frame_size);
/*
- * Trim the skb_buffer to only contain the valid
- * frame data (so ignore the device's descriptor).
+ * The data behind the ieee80211 header must be
+ * aligned on a 4 byte boundary.
+ * After that trim the entire buffer down to only
+ * contain the valid frame data excluding the device
+ * descriptor.
*/
+ hdr = (struct ieee80211_hdr *)entry->skb->data;
+ header_size =
+ ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
+
+ if (header_size % 4 == 0) {
+ skb_push(entry->skb, 2);
+ memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2);
+ }
skb_trim(entry->skb, desc.size);
/*