diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 60 |
1 files changed, 27 insertions, 33 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 719f4aebcaf6..7452fa850a0f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -177,45 +177,38 @@ void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length) | |||
177 | 177 | ||
178 | void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) | 178 | void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) |
179 | { | 179 | { |
180 | unsigned int frame_length = skb->len; | 180 | unsigned int payload_length = skb->len - header_length; |
181 | unsigned int header_align = ALIGN_SIZE(skb, 0); | 181 | unsigned int header_align = ALIGN_SIZE(skb, 0); |
182 | unsigned int payload_align = ALIGN_SIZE(skb, header_length); | 182 | unsigned int payload_align = ALIGN_SIZE(skb, header_length); |
183 | unsigned int l2pad = L2PAD_SIZE(header_length); | 183 | unsigned int l2pad = L2PAD_SIZE(header_length); |
184 | 184 | ||
185 | if (header_align == payload_align) { | 185 | /* |
186 | /* | 186 | * Adjust the header alignment if the payload needs to be moved more |
187 | * Both header and payload must be moved the same | 187 | * than the header. |
188 | * amount of bytes to align them properly. This means | 188 | */ |
189 | * we don't use the L2 padding but just move the entire | 189 | if (payload_align > header_align) |
190 | * frame. | 190 | header_align += 4; |
191 | */ | 191 | |
192 | rt2x00queue_align_frame(skb); | 192 | /* There is nothing to do if no alignment is needed */ |
193 | } else if (!payload_align) { | 193 | if (!header_align) |
194 | /* | 194 | return; |
195 | * Simple L2 padding, only the header needs to be moved, | ||
196 | * the payload is already properly aligned. | ||
197 | */ | ||
198 | skb_push(skb, header_align); | ||
199 | memmove(skb->data, skb->data + header_align, header_length); | ||
200 | } else { | ||
201 | /* | ||
202 | * | ||
203 | * Complicated L2 padding, both header and payload need | ||
204 | * to be moved. By default we only move to the start | ||
205 | * of the buffer, so our header alignment needs to be | ||
206 | * increased if there is not enough room for the header | ||
207 | * to be moved. | ||
208 | */ | ||
209 | if (payload_align > header_align) | ||
210 | header_align += 4; | ||
211 | 195 | ||
212 | skb_push(skb, header_align); | 196 | /* Reserve the amount of space needed in front of the frame */ |
213 | memmove(skb->data, skb->data + header_align, header_length); | 197 | skb_push(skb, header_align); |
198 | |||
199 | /* | ||
200 | * Move the header. | ||
201 | */ | ||
202 | memmove(skb->data, skb->data + header_align, header_length); | ||
203 | |||
204 | /* Move the payload, if present and if required */ | ||
205 | if (payload_length && payload_align) | ||
214 | memmove(skb->data + header_length + l2pad, | 206 | memmove(skb->data + header_length + l2pad, |
215 | skb->data + header_length + l2pad + payload_align, | 207 | skb->data + header_length + l2pad + payload_align, |
216 | frame_length - header_length); | 208 | payload_length); |
217 | skb_trim(skb, frame_length + l2pad); | 209 | |
218 | } | 210 | /* Trim the skb to the correct size */ |
211 | skb_trim(skb, header_length + l2pad + payload_length); | ||
219 | } | 212 | } |
220 | 213 | ||
221 | void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) | 214 | void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) |
@@ -343,7 +336,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
343 | * Header and alignment information. | 336 | * Header and alignment information. |
344 | */ | 337 | */ |
345 | txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); | 338 | txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); |
346 | if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) | 339 | if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags) && |
340 | (entry->skb->len > txdesc->header_length)) | ||
347 | txdesc->l2pad = L2PAD_SIZE(txdesc->header_length); | 341 | txdesc->l2pad = L2PAD_SIZE(txdesc->header_length); |
348 | 342 | ||
349 | /* | 343 | /* |