]> err.no Git - linux-2.6/blobdiff - drivers/net/wireless/rt2x00/rt2x00usb.c
rt2x00: Split rt2x00lib_write_tx_desc()
[linux-2.6] / drivers / net / wireless / rt2x00 / rt2x00usb.c
index 5a331674dcb2384c036f77b08aa79f93b819946a..df6621025f4b2dd6d4d81605836120bab729b37c 100644 (file)
@@ -147,8 +147,17 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
 
        /*
         * Obtain the status about this packet.
+        * Note that when the status is 0 it does not mean the
+        * frame was send out correctly. It only means the frame
+        * was succesfully pushed to the hardware, we have no
+        * way to determine the transmission status right now.
+        * (Only indirectly by looking at the failed TX counters
+        * in the register).
         */
-       txdesc.status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY;
+       if (!urb->status)
+               __set_bit(TXDONE_UNKNOWN, &txdesc.flags);
+       else
+               __set_bit(TXDONE_FAILURE, &txdesc.flags);
        txdesc.retry = 0;
        txdesc.control = &priv_tx->control;
 
@@ -177,6 +186,7 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
        struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
        struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data;
        struct skb_frame_desc *skbdesc;
+       struct txentry_desc txdesc;
        u32 length;
 
        if (rt2x00queue_full(queue))
@@ -186,10 +196,18 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
                ERROR(rt2x00dev,
                      "Arrived at non-free entry in the non-full queue %d.\n"
                      "Please file bug report to %s.\n",
-                     control->queue, DRV_PROJECT);
+                     entry->queue->qid, DRV_PROJECT);
                return -EINVAL;
        }
 
+       /*
+        * Copy all TX descriptor information into txdesc,
+        * after that we are free to use the skb->cb array
+        * for our information.
+        */
+       entry->skb = skb;
+       rt2x00queue_create_tx_descriptor(entry, &txdesc, control);
+
        /*
         * Add the descriptor in front of the skb.
         */
@@ -207,7 +225,7 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
        skbdesc->entry = entry;
 
        memcpy(&priv_tx->control, control, sizeof(priv_tx->control));
-       rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
+       rt2x00queue_write_tx_descriptor(entry, &txdesc);
 
        /*
         * USB devices cannot blindly pass the skb->len as the
@@ -237,22 +255,35 @@ static struct sk_buff* rt2x00usb_alloc_rxskb(struct data_queue *queue)
 {
        struct sk_buff *skb;
        unsigned int frame_size;
+       unsigned int reserved_size;
 
        /*
-        * As alignment we use 2 and not NET_IP_ALIGN because we need
-        * to be sure we have 2 bytes room in the head. (NET_IP_ALIGN
-        * can be 0 on some hardware). We use these 2 bytes for frame
-        * alignment later, we assume that the chance that
-        * header_size % 4 == 2 is bigger then header_size % 2 == 0
-        * and thus optimize alignment by reserving the 2 bytes in
-        * advance.
+        * The frame size includes descriptor size, because the
+        * hardware directly receive the frame into the skbuffer.
         */
        frame_size = queue->data_size + queue->desc_size;
-       skb = dev_alloc_skb(queue->desc_size + frame_size + 2);
+
+       /*
+        * For the allocation we should keep a few things in mind:
+        * 1) 4byte alignment of 802.11 payload
+        *
+        * For (1) we need at most 4 bytes to guarentee the correct
+        * alignment. We are going to optimize the fact that the chance
+        * that the 802.11 header_size % 4 == 2 is much bigger then
+        * anything else. However since we need to move the frame up
+        * to 3 bytes to the front, which means we need to preallocate
+        * 6 bytes.
+        */
+       reserved_size = 6;
+
+       /*
+        * Allocate skbuffer.
+        */
+       skb = dev_alloc_skb(frame_size + reserved_size);
        if (!skb)
                return NULL;
 
-       skb_reserve(skb, queue->desc_size + 2);
+       skb_reserve(skb, reserved_size);
        skb_put(skb, frame_size);
 
        return skb;
@@ -265,7 +296,8 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
        struct sk_buff *skb;
        struct skb_frame_desc *skbdesc;
        struct rxdone_entry_desc rxdesc;
-       int header_size;
+       unsigned int header_size;
+       unsigned int align;
 
        if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
            !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
@@ -289,19 +321,29 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
        memset(&rxdesc, 0, sizeof(rxdesc));
        rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
 
+       header_size = ieee80211_get_hdrlen_from_skb(entry->skb);
+
        /*
         * The data behind the ieee80211 header must be
-        * aligned on a 4 byte boundary.
+        * aligned on a 4 byte boundary. We already reserved
+        * 2 bytes for header_size % 4 == 2 optimization.
+        * To determine the number of bytes which the data
+        * should be moved to the left, we must add these
+        * 2 bytes to the header_size.
         */
-       header_size = ieee80211_get_hdrlen_from_skb(entry->skb);
-       if (header_size % 4 == 0) {
-               skb_push(entry->skb, 2);
-               memmove(entry->skb->data, entry->skb->data + 2,
-                       entry->skb->len - 2);
-               skbdesc->data = entry->skb->data;
-               skb_trim(entry->skb,entry->skb->len - 2);
+       align = (header_size + 2) % 4;
+
+       if (align) {
+               skb_push(entry->skb, align);
+               /* Move entire frame in 1 command */
+               memmove(entry->skb->data, entry->skb->data + align,
+                       rxdesc.size);
        }
 
+       /* Update data pointers, trim buffer to correct size */
+       skbdesc->data = entry->skb->data;
+       skb_trim(entry->skb, rxdesc.size);
+
        /*
         * Allocate a new sk buffer to replace the current one.
         * If allocation fails, we should drop the current frame
@@ -344,7 +386,7 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
        struct data_queue *queue;
        unsigned int i;
 
-       rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0x0000, 0x0000,
+       rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 00,
                                    REGISTER_TIMEOUT);
 
        /*