aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2008-01-06 17:40:27 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-01-10 16:18:25 -0500
commitc5d0dc5f0dd66770232d7d360c770d2344b76d52 (patch)
tree8a0347ce38d9132f2bd839425d5984a8540ca2cd /drivers/net/wireless
parentdd87145d2c3a7b1c8b338e1f6e174b3d2a17cd35 (diff)
rt2x00: Put 802.11 data on 4 byte boundary
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>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c20
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c17
2 files changed, 31 insertions, 6 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 2780df00623c..6d5d9aba0b73 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -124,7 +124,10 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
124 struct data_entry *entry; 124 struct data_entry *entry;
125 struct data_desc *rxd; 125 struct data_desc *rxd;
126 struct sk_buff *skb; 126 struct sk_buff *skb;
127 struct ieee80211_hdr *hdr;
127 struct rxdata_entry_desc desc; 128 struct rxdata_entry_desc desc;
129 int header_size;
130 int align;
128 u32 word; 131 u32 word;
129 132
130 while (1) { 133 while (1) {
@@ -138,17 +141,26 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
138 memset(&desc, 0x00, sizeof(desc)); 141 memset(&desc, 0x00, sizeof(desc));
139 rt2x00dev->ops->lib->fill_rxdone(entry, &desc); 142 rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
140 143
144 hdr = (struct ieee80211_hdr *)entry->data_addr;
145 header_size =
146 ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
147
148 /*
149 * The data behind the ieee80211 header must be
150 * aligned on a 4 byte boundary.
151 */
152 align = NET_IP_ALIGN + (2 * (header_size % 4 == 0));
153
141 /* 154 /*
142 * Allocate the sk_buffer, initialize it and copy 155 * Allocate the sk_buffer, initialize it and copy
143 * all data into it. 156 * all data into it.
144 */ 157 */
145 skb = dev_alloc_skb(desc.size + NET_IP_ALIGN); 158 skb = dev_alloc_skb(desc.size + align);
146 if (!skb) 159 if (!skb)
147 return; 160 return;
148 161
149 skb_reserve(skb, NET_IP_ALIGN); 162 skb_reserve(skb, align);
150 skb_put(skb, desc.size); 163 memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size);
151 memcpy(skb->data, entry->data_addr, desc.size);
152 164
153 /* 165 /*
154 * Send the frame to rt2x00lib for further processing. 166 * Send the frame to rt2x00lib for further processing.
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 1f5675dd329f..ab4797ed94c9 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) ||
@@ -253,9 +255,20 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
253 skb_put(skb, frame_size); 255 skb_put(skb, frame_size);
254 256
255 /* 257 /*
256 * Trim the skb_buffer to only contain the valid 258 * The data behind the ieee80211 header must be
257 * frame data (so ignore the device's descriptor). 259 * aligned on a 4 byte boundary.
260 * After that trim the entire buffer down to only
261 * contain the valid frame data excluding the device
262 * descriptor.
258 */ 263 */
264 hdr = (struct ieee80211_hdr *)entry->skb->data;
265 header_size =
266 ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
267
268 if (header_size % 4 == 0) {
269 skb_push(entry->skb, 2);
270 memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2);
271 }
259 skb_trim(entry->skb, desc.size); 272 skb_trim(entry->skb, desc.size);
260 273
261 /* 274 /*