diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 60 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 26 |
3 files changed, 62 insertions, 47 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 661cf3d7212a..3be4c7ea8dd1 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1129,20 +1129,22 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, | |||
1129 | __le32 *rxd = | 1129 | __le32 *rxd = |
1130 | (__le32 *)(entry->skb->data + | 1130 | (__le32 *)(entry->skb->data + |
1131 | (priv_rx->urb->actual_length - entry->queue->desc_size)); | 1131 | (priv_rx->urb->actual_length - entry->queue->desc_size)); |
1132 | unsigned int offset = entry->queue->desc_size + 2; | ||
1133 | u32 word0; | 1132 | u32 word0; |
1134 | u32 word1; | 1133 | u32 word1; |
1135 | 1134 | ||
1136 | /* | 1135 | /* |
1137 | * Copy descriptor to the available headroom inside the skbuffer. | 1136 | * Copy descriptor to the skb->cb array, this has 2 benefits: |
1137 | * 1) Each descriptor word is 4 byte aligned. | ||
1138 | * 2) Descriptor is safe from moving of frame data in rt2x00usb. | ||
1138 | */ | 1139 | */ |
1139 | skb_push(entry->skb, offset); | 1140 | skbdesc->desc_len = |
1140 | memcpy(entry->skb->data, rxd, entry->queue->desc_size); | 1141 | min_t(u16, entry->queue->desc_size, sizeof(entry->skb->cb)); |
1141 | rxd = (__le32 *)entry->skb->data; | 1142 | memcpy(entry->skb->cb, rxd, skbdesc->desc_len); |
1143 | skbdesc->desc = entry->skb->cb; | ||
1144 | rxd = (__le32 *)skbdesc->desc; | ||
1142 | 1145 | ||
1143 | /* | 1146 | /* |
1144 | * The descriptor is now aligned to 4 bytes and thus it is | 1147 | * It is now safe to read the descriptor on all architectures. |
1145 | * now safe to read it on all architectures. | ||
1146 | */ | 1148 | */ |
1147 | rt2x00_desc_read(rxd, 0, &word0); | 1149 | rt2x00_desc_read(rxd, 0, &word0); |
1148 | rt2x00_desc_read(rxd, 1, &word1); | 1150 | rt2x00_desc_read(rxd, 1, &word1); |
@@ -1173,16 +1175,9 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, | |||
1173 | /* | 1175 | /* |
1174 | * Adjust the skb memory window to the frame boundaries. | 1176 | * Adjust the skb memory window to the frame boundaries. |
1175 | */ | 1177 | */ |
1176 | skb_pull(entry->skb, offset); | ||
1177 | skb_trim(entry->skb, rxdesc->size); | 1178 | skb_trim(entry->skb, rxdesc->size); |
1178 | |||
1179 | /* | ||
1180 | * Set descriptor and data pointer. | ||
1181 | */ | ||
1182 | skbdesc->data = entry->skb->data; | 1179 | skbdesc->data = entry->skb->data; |
1183 | skbdesc->data_len = rxdesc->size; | 1180 | skbdesc->data_len = rxdesc->size; |
1184 | skbdesc->desc = rxd; | ||
1185 | skbdesc->desc_len = entry->queue->desc_size; | ||
1186 | } | 1181 | } |
1187 | 1182 | ||
1188 | /* | 1183 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index caee65e82198..f72b3d07a42d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -246,22 +246,35 @@ static struct sk_buff* rt2x00usb_alloc_rxskb(struct data_queue *queue) | |||
246 | { | 246 | { |
247 | struct sk_buff *skb; | 247 | struct sk_buff *skb; |
248 | unsigned int frame_size; | 248 | unsigned int frame_size; |
249 | unsigned int reserved_size; | ||
249 | 250 | ||
250 | /* | 251 | /* |
251 | * As alignment we use 2 and not NET_IP_ALIGN because we need | 252 | * The frame size includes descriptor size, because the |
252 | * to be sure we have 2 bytes room in the head. (NET_IP_ALIGN | 253 | * hardware directly receive the frame into the skbuffer. |
253 | * can be 0 on some hardware). We use these 2 bytes for frame | ||
254 | * alignment later, we assume that the chance that | ||
255 | * header_size % 4 == 2 is bigger then header_size % 2 == 0 | ||
256 | * and thus optimize alignment by reserving the 2 bytes in | ||
257 | * advance. | ||
258 | */ | 254 | */ |
259 | frame_size = queue->data_size + queue->desc_size; | 255 | frame_size = queue->data_size + queue->desc_size; |
260 | skb = dev_alloc_skb(queue->desc_size + frame_size + 2); | 256 | |
257 | /* | ||
258 | * For the allocation we should keep a few things in mind: | ||
259 | * 1) 4byte alignment of 802.11 payload | ||
260 | * | ||
261 | * For (1) we need at most 4 bytes to guarentee the correct | ||
262 | * alignment. We are going to optimize the fact that the chance | ||
263 | * that the 802.11 header_size % 4 == 2 is much bigger then | ||
264 | * anything else. However since we need to move the frame up | ||
265 | * to 3 bytes to the front, which means we need to preallocate | ||
266 | * 6 bytes. | ||
267 | */ | ||
268 | reserved_size = 6; | ||
269 | |||
270 | /* | ||
271 | * Allocate skbuffer. | ||
272 | */ | ||
273 | skb = dev_alloc_skb(frame_size + reserved_size); | ||
261 | if (!skb) | 274 | if (!skb) |
262 | return NULL; | 275 | return NULL; |
263 | 276 | ||
264 | skb_reserve(skb, queue->desc_size + 2); | 277 | skb_reserve(skb, reserved_size); |
265 | skb_put(skb, frame_size); | 278 | skb_put(skb, frame_size); |
266 | 279 | ||
267 | return skb; | 280 | return skb; |
@@ -274,7 +287,8 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
274 | struct sk_buff *skb; | 287 | struct sk_buff *skb; |
275 | struct skb_frame_desc *skbdesc; | 288 | struct skb_frame_desc *skbdesc; |
276 | struct rxdone_entry_desc rxdesc; | 289 | struct rxdone_entry_desc rxdesc; |
277 | int header_size; | 290 | unsigned int header_size; |
291 | unsigned int align; | ||
278 | 292 | ||
279 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || | 293 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || |
280 | !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | 294 | !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
@@ -298,19 +312,29 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
298 | memset(&rxdesc, 0, sizeof(rxdesc)); | 312 | memset(&rxdesc, 0, sizeof(rxdesc)); |
299 | rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); | 313 | rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); |
300 | 314 | ||
315 | header_size = ieee80211_get_hdrlen_from_skb(entry->skb); | ||
316 | |||
301 | /* | 317 | /* |
302 | * The data behind the ieee80211 header must be | 318 | * The data behind the ieee80211 header must be |
303 | * aligned on a 4 byte boundary. | 319 | * aligned on a 4 byte boundary. We already reserved |
320 | * 2 bytes for header_size % 4 == 2 optimization. | ||
321 | * To determine the number of bytes which the data | ||
322 | * should be moved to the left, we must add these | ||
323 | * 2 bytes to the header_size. | ||
304 | */ | 324 | */ |
305 | header_size = ieee80211_get_hdrlen_from_skb(entry->skb); | 325 | align = (header_size + 2) % 4; |
306 | if (header_size % 4 == 0) { | 326 | |
307 | skb_push(entry->skb, 2); | 327 | if (align) { |
308 | memmove(entry->skb->data, entry->skb->data + 2, | 328 | skb_push(entry->skb, align); |
309 | entry->skb->len - 2); | 329 | /* Move entire frame in 1 command */ |
310 | skbdesc->data = entry->skb->data; | 330 | memmove(entry->skb->data, entry->skb->data + align, |
311 | skb_trim(entry->skb,entry->skb->len - 2); | 331 | rxdesc.size); |
312 | } | 332 | } |
313 | 333 | ||
334 | /* Update data pointers, trim buffer to correct size */ | ||
335 | skbdesc->data = entry->skb->data; | ||
336 | skb_trim(entry->skb, rxdesc.size); | ||
337 | |||
314 | /* | 338 | /* |
315 | * Allocate a new sk buffer to replace the current one. | 339 | * Allocate a new sk buffer to replace the current one. |
316 | * If allocation fails, we should drop the current frame | 340 | * If allocation fails, we should drop the current frame |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 2191d8b94a89..1bcf8c132cdc 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -1403,20 +1403,22 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, | |||
1403 | { | 1403 | { |
1404 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 1404 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
1405 | __le32 *rxd = (__le32 *)entry->skb->data; | 1405 | __le32 *rxd = (__le32 *)entry->skb->data; |
1406 | unsigned int offset = entry->queue->desc_size + 2; | ||
1407 | u32 word0; | 1406 | u32 word0; |
1408 | u32 word1; | 1407 | u32 word1; |
1409 | 1408 | ||
1410 | /* | 1409 | /* |
1411 | * Copy descriptor to the available headroom inside the skbuffer. | 1410 | * Copy descriptor to the skb->cb array, this has 2 benefits: |
1411 | * 1) Each descriptor word is 4 byte aligned. | ||
1412 | * 2) Descriptor is safe from moving of frame data in rt2x00usb. | ||
1412 | */ | 1413 | */ |
1413 | skb_push(entry->skb, offset); | 1414 | skbdesc->desc_len = |
1414 | memcpy(entry->skb->data, rxd, entry->queue->desc_size); | 1415 | min_t(u16, entry->queue->desc_size, sizeof(entry->skb->cb)); |
1415 | rxd = (__le32 *)entry->skb->data; | 1416 | memcpy(entry->skb->cb, rxd, skbdesc->desc_len); |
1417 | skbdesc->desc = entry->skb->cb; | ||
1418 | rxd = (__le32 *)skbdesc->desc; | ||
1416 | 1419 | ||
1417 | /* | 1420 | /* |
1418 | * The descriptor is now aligned to 4 bytes and thus it is | 1421 | * It is now safe to read the descriptor on all architectures. |
1419 | * now safe to read it on all architectures. | ||
1420 | */ | 1422 | */ |
1421 | rt2x00_desc_read(rxd, 0, &word0); | 1423 | rt2x00_desc_read(rxd, 0, &word0); |
1422 | rt2x00_desc_read(rxd, 1, &word1); | 1424 | rt2x00_desc_read(rxd, 1, &word1); |
@@ -1442,18 +1444,12 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, | |||
1442 | rxdesc->dev_flags |= RXDONE_MY_BSS; | 1444 | rxdesc->dev_flags |= RXDONE_MY_BSS; |
1443 | 1445 | ||
1444 | /* | 1446 | /* |
1445 | * Adjust the skb memory window to the frame boundaries. | 1447 | * Set skb pointers, and update frame information. |
1446 | */ | 1448 | */ |
1447 | skb_pull(entry->skb, offset + entry->queue->desc_size); | 1449 | skb_pull(entry->skb, entry->queue->desc_size); |
1448 | skb_trim(entry->skb, rxdesc->size); | 1450 | skb_trim(entry->skb, rxdesc->size); |
1449 | |||
1450 | /* | ||
1451 | * Set descriptor and data pointer. | ||
1452 | */ | ||
1453 | skbdesc->data = entry->skb->data; | 1451 | skbdesc->data = entry->skb->data; |
1454 | skbdesc->data_len = rxdesc->size; | 1452 | skbdesc->data_len = rxdesc->size; |
1455 | skbdesc->desc = rxd; | ||
1456 | skbdesc->desc_len = entry->queue->desc_size; | ||
1457 | } | 1453 | } |
1458 | 1454 | ||
1459 | /* | 1455 | /* |