rt2x00: Use IEEE80211_TX_CTL_MORE_FRAMES flag
[pandora-kernel.git] / drivers / net / wireless / rt2x00 / rt2x00queue.c
index a5664bd..65435c9 100644 (file)
@@ -148,6 +148,35 @@ void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
        dev_kfree_skb_any(skb);
 }
 
+void rt2x00queue_payload_align(struct sk_buff *skb,
+                              bool l2pad, unsigned int header_length)
+{
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+       unsigned int frame_length = skb->len;
+       unsigned int align = ALIGN_SIZE(skb, header_length);
+
+       if (!align)
+               return;
+
+       if (l2pad) {
+               if (skbdesc->flags & SKBDESC_L2_PADDED) {
+                       /* Remove L2 padding */
+                       memmove(skb->data + align, skb->data, header_length);
+                       skb_pull(skb, align);
+                       skbdesc->flags &= ~SKBDESC_L2_PADDED;
+               } else {
+                       /* Add L2 padding */
+                       skb_push(skb, align);
+                       memmove(skb->data, skb->data + align, header_length);
+                       skbdesc->flags |= SKBDESC_L2_PADDED;
+               }
+       } else {
+               /* Generic payload alignment to 4-byte boundary */
+               skb_push(skb, align);
+               memmove(skb->data, skb->data + align, frame_length);
+       }
+}
+
 static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
                                                 struct txentry_desc *txdesc)
 {
@@ -258,6 +287,12 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
        txdesc->cw_max = entry->queue->cw_max;
        txdesc->aifs = entry->queue->aifs;
 
+       /*
+        * Header and alignment information.
+        */
+       txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
+       txdesc->l2pad = ALIGN_SIZE(entry->skb, txdesc->header_length);
+
        /*
         * Check whether this frame is to be acked.
         */
@@ -289,7 +324,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
        /*
         * Check if more fragments are pending
         */
-       if (ieee80211_has_morefrags(hdr->frame_control)) {
+       if (ieee80211_has_morefrags(hdr->frame_control) ||
+           (tx_info->flags & IEEE80211_TX_CTL_MORE_FRAMES)) {
                __set_bit(ENTRY_TXD_BURST, &txdesc->flags);
                __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags);
        }
@@ -326,6 +362,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
         * Apply TX descriptor handling by components
         */
        rt2x00crypto_create_tx_descriptor(entry, txdesc);
+       rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate);
        rt2x00queue_create_tx_descriptor_seq(entry, txdesc);
        rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
 }
@@ -368,7 +405,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
        struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
        struct txentry_desc txdesc;
        struct skb_frame_desc *skbdesc;
-       unsigned int iv_len = 0;
        u8 rate_idx, rate_flags;
 
        if (unlikely(rt2x00queue_full(queue)))
@@ -390,9 +426,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
        entry->skb = skb;
        rt2x00queue_create_tx_descriptor(entry, &txdesc);
 
-       if (IEEE80211_SKB_CB(skb)->control.hw_key != NULL)
-               iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
-
        /*
         * All information is retrieved from the skb->cb array,
         * now we should claim ownership of the driver part of that
@@ -415,11 +448,15 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
        if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
            !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
                if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags))
-                       rt2x00crypto_tx_copy_iv(skb, iv_len);
+                       rt2x00crypto_tx_copy_iv(skb, &txdesc);
                else
-                       rt2x00crypto_tx_remove_iv(skb, iv_len);
+                       rt2x00crypto_tx_remove_iv(skb, &txdesc);
        }
 
+       if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags))
+               rt2x00queue_payload_align(entry->skb, true,
+                                         txdesc.header_length);
+
        /*
         * It could be possible that the queue was corrupted and this
         * call failed. Since we always return NETDEV_TX_OK to mac80211,