aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c60
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
178void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) 178void 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
221void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) 214void 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 /*