__le32 *rxd =
            (__le32 *)(entry->skb->data +
                       (priv_rx->urb->actual_length - entry->queue->desc_size));
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
-       int header_size = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
+       unsigned int offset = entry->queue->desc_size + 2;
        u32 word0;
        u32 word1;
 
+       /*
+        * Copy descriptor to the available headroom inside the skbuffer.
+        * Remove the original copy by trimming the skbuffer.
+        */
+       skb_push(entry->skb, offset);
+       memcpy(entry->skb->data, rxd, entry->queue->desc_size);
+       rxd = (__le32 *)entry->skb->data;
+       skb_pull(entry->skb, offset);
+       skb_trim(entry->skb, rxdesc->size);
+
+       /*
+        * The descriptor is now aligned to 4 bytes and thus it is
+        * now safe to read it on all architectures.
+        */
        rt2x00_desc_read(rxd, 0, &word0);
        rt2x00_desc_read(rxd, 1, &word1);
 
        rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
 
        /*
-        * The data behind the ieee80211 header must be
-        * aligned on a 4 byte boundary.
-        */
-       if (header_size % 4 == 0) {
-               skb_push(entry->skb, 2);
-               memmove(entry->skb->data, entry->skb->data + 2,
-                       entry->skb->len - 2);
-       }
-
-       /*
-        * Set descriptor pointer.
+        * Set descriptor and data pointer.
         */
        skbdesc->data = entry->skb->data;
        skbdesc->data_len = rxdesc->size;
-       skbdesc->desc = entry->skb->data + rxdesc->size;
+       skbdesc->desc = entry->skb->data - offset;
        skbdesc->desc_len = entry->queue->desc_size;
-
-       /*
-        * Remove descriptor from skb buffer and trim the whole thing
-        * down to only contain data.
-        */
-       skb_trim(entry->skb, rxdesc->size);
 }
 
 /*
 
         * 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;
        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))
        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
 
 {
        struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
        __le32 *rxd = (__le32 *)entry->skb->data;
-       struct ieee80211_hdr *hdr =
-           (struct ieee80211_hdr *)entry->skb->data + entry->queue->desc_size;
-       int header_size = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
+       unsigned int offset = entry->queue->desc_size + 2;
        u32 word0;
        u32 word1;
 
+       /*
+        * Copy descriptor to the available headroom inside the skbuffer.
+        * Remove the original copy by pulling the skbuffer.
+        */
+       skb_push(entry->skb, offset);
+       memcpy(entry->skb->data, rxd, entry->queue->desc_size);
+       rxd = (__le32 *)entry->skb->data;
+       skb_pull(entry->skb, offset + skbdesc->desc_len);
+       skb_trim(entry->skb, rxdesc->size);
+
+       /*
+        * The descriptor is now aligned to 4 bytes and thus it is
+        * now safe to read it on all architectures.
+        */
        rt2x00_desc_read(rxd, 0, &word0);
        rt2x00_desc_read(rxd, 1, &word1);
 
        rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
        rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
 
-       /*
-        * The data behind the ieee80211 header must be
-        * aligned on a 4 byte boundary.
-        */
-       if (header_size % 4 == 0) {
-               skb_push(entry->skb, 2);
-               memmove(entry->skb->data, entry->skb->data + 2,
-                       entry->skb->len - 2);
-       }
-
        /*
         * Set descriptor and data pointer.
         */
-       skbdesc->data = entry->skb->data + entry->queue->desc_size;
+       skbdesc->data = entry->skb->data;
        skbdesc->data_len = rxdesc->size;
-       skbdesc->desc = entry->skb->data;
+       skbdesc->desc = entry->skb->data - offset;
        skbdesc->desc_len = entry->queue->desc_size;
-
-       /*
-        * Remove descriptor from skb buffer and trim the whole thing
-        * down to only contain data.
-        */
-       skb_pull(entry->skb, skbdesc->desc_len);
-       skb_trim(entry->skb, rxdesc->size);
 }
 
 /*