__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);
}
/*