Merge branch 'for-next' into for-linus
[safe/jmp/linux-2.6] / drivers / net / wireless / rt2x00 / rt2x00queue.c
index 38ffca9..5b6b789 100644 (file)
@@ -177,55 +177,45 @@ void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length)
 
 void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)
 {
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-       unsigned int frame_length = skb->len;
+       unsigned int payload_length = skb->len - header_length;
        unsigned int header_align = ALIGN_SIZE(skb, 0);
        unsigned int payload_align = ALIGN_SIZE(skb, header_length);
-       unsigned int l2pad = 4 - (payload_align - header_align);
+       unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0;
 
-       if (header_align == payload_align) {
-               /*
-                * Both header and payload must be moved the same
-                * amount of bytes to align them properly. This means
-                * we don't use the L2 padding but just move the entire
-                * frame.
-                */
-               rt2x00queue_align_frame(skb);
-       } else if (!payload_align) {
-               /*
-                * Simple L2 padding, only the header needs to be moved,
-                * the payload is already properly aligned.
-                */
-               skb_push(skb, header_align);
-               memmove(skb->data, skb->data + header_align, frame_length);
-               skbdesc->flags |= SKBDESC_L2_PADDED;
-       } else {
-               /*
-                *
-                * Complicated L2 padding, both header and payload need
-                * to be moved. By default we only move to the start
-                * of the buffer, so our header alignment needs to be
-                * increased if there is not enough room for the header
-                * to be moved.
-                */
-               if (payload_align > header_align)
-                       header_align += 4;
+       /*
+        * Adjust the header alignment if the payload needs to be moved more
+        * than the header.
+        */
+       if (payload_align > header_align)
+               header_align += 4;
+
+       /* There is nothing to do if no alignment is needed */
+       if (!header_align)
+               return;
+
+       /* Reserve the amount of space needed in front of the frame */
+       skb_push(skb, header_align);
+
+       /*
+        * Move the header.
+        */
+       memmove(skb->data, skb->data + header_align, header_length);
 
-               skb_push(skb, header_align);
-               memmove(skb->data, skb->data + header_align, header_length);
+       /* Move the payload, if present and if required */
+       if (payload_length && payload_align)
                memmove(skb->data + header_length + l2pad,
                        skb->data + header_length + l2pad + payload_align,
-                       frame_length - header_length);
-               skbdesc->flags |= SKBDESC_L2_PADDED;
-       }
+                       payload_length);
+
+       /* Trim the skb to the correct size */
+       skb_trim(skb, header_length + l2pad + payload_length);
 }
 
 void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)
 {
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-       unsigned int l2pad = 4 - (header_length & 3);
+       unsigned int l2pad = L2PAD_SIZE(header_length);
 
-       if (!l2pad || (skbdesc->flags & SKBDESC_L2_PADDED))
+       if (!l2pad)
                return;
 
        memmove(skb->data + l2pad, skb->data, header_length);
@@ -346,7 +336,9 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
         * Header and alignment information.
         */
        txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
-       txdesc->l2pad = ALIGN_SIZE(entry->skb, txdesc->header_length);
+       if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags) &&
+           (entry->skb->len > txdesc->header_length))
+               txdesc->l2pad = L2PAD_SIZE(txdesc->header_length);
 
        /*
         * Check whether this frame is to be acked.
@@ -387,10 +379,13 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
 
        /*
         * Beacons and probe responses require the tsf timestamp
-        * to be inserted into the frame.
+        * to be inserted into the frame, except for a frame that has been injected
+        * through a monitor interface. This latter is needed for testing a
+        * monitor interface.
         */
-       if (ieee80211_is_beacon(hdr->frame_control) ||
-           ieee80211_is_probe_resp(hdr->frame_control))
+       if ((ieee80211_is_beacon(hdr->frame_control) ||
+           ieee80211_is_probe_resp(hdr->frame_control)) &&
+           (!(tx_info->flags & IEEE80211_TX_CTL_INJECTED)))
                __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags);
 
        /*