Skip to content

Commit

Permalink
rt2x00: Put 802.11 data on 4 byte boundary
Browse files Browse the repository at this point in the history
Check the size of the ieee80211 header during rxdone
and make sure the data behind the ieee80211 header
is placed on a 4 byte boundary.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Ivo van Doorn authored and John W. Linville committed Jan 10, 2008
1 parent dd87145 commit c5d0dc5
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 6 deletions.
20 changes: 16 additions & 4 deletions drivers/net/wireless/rt2x00/rt2x00pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,10 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
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) {
Expand All @@ -138,17 +141,26 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
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.
Expand Down
17 changes: 15 additions & 2 deletions drivers/net/wireless/rt2x00/rt2x00usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,9 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
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) ||
Expand Down Expand Up @@ -253,9 +255,20 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
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);

/*
Expand Down

0 comments on commit c5d0dc5

Please sign in to comment.