rt2x00: trivial: add missing \n on warnings
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / net / wireless / rt2x00 / rt2x00usb.c
index ff3a366..608200e 100644 (file)
@@ -1,5 +1,6 @@
 /*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+       Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -167,137 +168,139 @@ EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read);
 /*
  * TX data handlers.
  */
-static void rt2x00usb_interrupt_txdone(struct urb *urb)
+static void rt2x00usb_work_txdone_entry(struct queue_entry *entry)
 {
-       struct queue_entry *entry = (struct queue_entry *)urb->context;
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct txdone_entry_desc txdesc;
-
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
-           !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
-               return;
-
        /*
-        * Obtain the status about this packet.
-        * Note that when the status is 0 it does not mean the
+        * If the transfer to hardware succeeded, 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.flags = 0;
-       if (!urb->status)
-               __set_bit(TXDONE_UNKNOWN, &txdesc.flags);
+       if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+               rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
        else
-               __set_bit(TXDONE_FAILURE, &txdesc.flags);
-       txdesc.retry = 0;
-
-       rt2x00lib_txdone(entry, &txdesc);
+               rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
 }
 
-static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
+static void rt2x00usb_work_txdone(struct work_struct *work)
 {
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
-       struct queue_entry_priv_usb *entry_priv = entry->priv_data;
-       u32 length;
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, txdone_work);
+       struct data_queue *queue;
+       struct queue_entry *entry;
 
-       if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) {
-               /*
-                * USB devices cannot blindly pass the skb->len as the
-                * length of the data to usb_fill_bulk_urb. Pass the skb
-                * to the driver to determine what the length should be.
-                */
-               length = rt2x00dev->ops->lib->get_tx_data_len(entry);
+       tx_queue_for_each(rt2x00dev, queue) {
+               while (!rt2x00queue_empty(queue)) {
+                       entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
 
-               usb_fill_bulk_urb(entry_priv->urb, usb_dev,
-                                 usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
-                                 entry->skb->data, length,
-                                 rt2x00usb_interrupt_txdone, entry);
+                       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+                               break;
 
-               usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+                       rt2x00usb_work_txdone_entry(entry);
+               }
        }
 }
 
-void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
-                            const enum data_queue_qid qid)
+static void rt2x00usb_interrupt_txdone(struct urb *urb)
 {
-       struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, qid);
-       unsigned long irqflags;
-       unsigned int index;
-       unsigned int index_done;
-       unsigned int i;
+       struct queue_entry *entry = (struct queue_entry *)urb->context;
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+
+       if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+               return;
 
        /*
-        * Only protect the range we are going to loop over,
-        * if during our loop a extra entry is set to pending
-        * it should not be kicked during this run, since it
-        * is part of another TX operation.
+        * Report the frame as DMA done
         */
-       spin_lock_irqsave(&queue->lock, irqflags);
-       index = queue->index[Q_INDEX];
-       index_done = queue->index[Q_INDEX_DONE];
-       spin_unlock_irqrestore(&queue->lock, irqflags);
+       rt2x00lib_dmadone(entry);
 
        /*
-        * Start from the TX done pointer, this guarentees that we will
-        * send out all frames in the correct order.
+        * Check if the frame was correctly uploaded
         */
-       if (index_done < index) {
-               for (i = index_done; i < index; i++)
-                       rt2x00usb_kick_tx_entry(&queue->entries[i]);
-       } else {
-               for (i = index_done; i < queue->limit; i++)
-                       rt2x00usb_kick_tx_entry(&queue->entries[i]);
+       if (urb->status)
+               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
 
-               for (i = 0; i < index; i++)
-                       rt2x00usb_kick_tx_entry(&queue->entries[i]);
-       }
+       /*
+        * Schedule the delayed work for reading the TX status
+        * from the device.
+        */
+       ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work);
 }
-EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue);
 
-void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
-                            const enum data_queue_qid qid)
+static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
 {
-       struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, qid);
-       struct queue_entry_priv_usb *entry_priv;
-       struct queue_entry_priv_usb_bcn *bcn_priv;
-       unsigned int i;
-       bool kill_guard;
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
+       struct queue_entry_priv_usb *entry_priv = entry->priv_data;
+       u32 length;
+       int status;
+
+       if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags))
+               return;
 
        /*
-        * When killing the beacon queue, we must also kill
-        * the beacon guard byte.
+        * USB devices cannot blindly pass the skb->len as the
+        * length of the data to usb_fill_bulk_urb. Pass the skb
+        * to the driver to determine what the length should be.
         */
-       kill_guard =
-           (qid == QID_BEACON) &&
-           (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags));
+       length = rt2x00dev->ops->lib->get_tx_data_len(entry);
+
+       usb_fill_bulk_urb(entry_priv->urb, usb_dev,
+                         usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
+                         entry->skb->data, length,
+                         rt2x00usb_interrupt_txdone, entry);
+
+       status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+       if (status) {
+               if (status == -ENODEV)
+                       clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
+               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+               rt2x00lib_dmadone(entry);
+       }
+}
+
+void rt2x00usb_kick_tx_queue(struct data_queue *queue)
+{
+       rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+                                  rt2x00usb_kick_tx_entry);
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue);
+
+static void rt2x00usb_kill_tx_entry(struct queue_entry *entry)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct queue_entry_priv_usb *entry_priv = entry->priv_data;
+       struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
+
+       if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+               return;
+
+       usb_kill_urb(entry_priv->urb);
 
        /*
-        * Cancel all entries.
+        * Kill guardian urb (if required by driver).
         */
-       for (i = 0; i < queue->limit; i++) {
-               entry_priv = queue->entries[i].priv_data;
-               usb_kill_urb(entry_priv->urb);
+       if ((entry->queue->qid == QID_BEACON) &&
+           (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)))
+               usb_kill_urb(bcn_priv->guardian_urb);
+}
 
-               /*
-                * Kill guardian urb (if required by driver).
-                */
-               if (kill_guard) {
-                       bcn_priv = queue->entries[i].priv_data;
-                       usb_kill_urb(bcn_priv->guardian_urb);
-               }
-       }
+void rt2x00usb_kill_tx_queue(struct data_queue *queue)
+{
+       rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+                                  rt2x00usb_kill_tx_entry);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue);
 
-static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue)
+static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
 {
-       struct queue_entry_priv_usb *entry_priv;
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
        unsigned short threshold = queue->threshold;
 
-       WARNING(queue->rt2x00dev, "TX queue %d timed out, invoke reset", queue->qid);
+       WARNING(queue->rt2x00dev, "TX queue %d DMA timed out,"
+               " invoke forced forced reset\n", queue->qid);
 
        /*
         * Temporarily disable the TX queue, this will force mac80211
@@ -307,28 +310,34 @@ static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue)
         * queue from being enabled during the txdone handler.
         */
        queue->threshold = queue->limit;
-       ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid);
+       ieee80211_stop_queue(rt2x00dev->hw, queue->qid);
 
        /*
-        * Reset all currently uploaded TX frames.
+        * Kill all entries in the queue, afterwards we need to
+        * wait a bit for all URBs to be cancelled.
         */
-       while (!rt2x00queue_empty(queue)) {
-               entry_priv = rt2x00queue_get_entry(queue, Q_INDEX_DONE)->priv_data;
-               usb_kill_urb(entry_priv->urb);
+       rt2x00usb_kill_tx_queue(queue);
 
-               /*
-                * We need a short delay here to wait for
-                * the URB to be canceled and invoked the tx_done handler.
-                */
-               udelay(200);
-       }
+       /*
+        * In case that a driver has overriden the txdone_work
+        * function, we invoke the TX done through there.
+        */
+       rt2x00dev->txdone_work.func(&rt2x00dev->txdone_work);
 
        /*
         * The queue has been reset, and mac80211 is allowed to use the
         * queue again.
         */
        queue->threshold = threshold;
-       ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid);
+       ieee80211_wake_queue(rt2x00dev->hw, queue->qid);
+}
+
+static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
+{
+       WARNING(queue->rt2x00dev, "TX queue %d status timed out,"
+               " invoke forced tx handler\n", queue->qid);
+
+       ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work);
 }
 
 void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
@@ -336,8 +345,12 @@ void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
        struct data_queue *queue;
 
        tx_queue_for_each(rt2x00dev, queue) {
-               if (rt2x00queue_timeout(queue))
-                       rt2x00usb_watchdog_reset_tx(queue);
+               if (!rt2x00queue_empty(queue)) {
+                       if (rt2x00queue_dma_timeout(queue))
+                               rt2x00usb_watchdog_tx_dma(queue);
+                       if (rt2x00queue_status_timeout(queue))
+                               rt2x00usb_watchdog_tx_status(queue);
+               }
        }
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_watchdog);
@@ -345,38 +358,60 @@ EXPORT_SYMBOL_GPL(rt2x00usb_watchdog);
 /*
  * RX data handlers.
  */
+static void rt2x00usb_work_rxdone(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, rxdone_work);
+       struct queue_entry *entry;
+       struct skb_frame_desc *skbdesc;
+       u8 rxd[32];
+
+       while (!rt2x00queue_empty(rt2x00dev->rx)) {
+               entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE);
+
+               if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+                       break;
+
+               /*
+                * Fill in desc fields of the skb descriptor
+                */
+               skbdesc = get_skb_frame_desc(entry->skb);
+               skbdesc->desc = rxd;
+               skbdesc->desc_len = entry->queue->desc_size;
+
+               /*
+                * Send the frame to rt2x00lib for further processing.
+                */
+               rt2x00lib_rxdone(entry);
+       }
+}
+
 static void rt2x00usb_interrupt_rxdone(struct urb *urb)
 {
        struct queue_entry *entry = (struct queue_entry *)urb->context;
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       u8 rxd[32];
 
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
-           !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+       if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
                return;
 
        /*
-        * Check if the received data is simply too small
-        * to be actually valid, or if the urb is signaling
-        * a problem.
+        * Report the frame as DMA done
         */
-       if (urb->actual_length < entry->queue->desc_size || urb->status) {
-               set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-               usb_submit_urb(urb, GFP_ATOMIC);
-               return;
-       }
+       rt2x00lib_dmadone(entry);
 
        /*
-        * Fill in desc fields of the skb descriptor
+        * Check if the received data is simply too small
+        * to be actually valid, or if the urb is signaling
+        * a problem.
         */
-       skbdesc->desc = rxd;
-       skbdesc->desc_len = entry->queue->desc_size;
+       if (urb->actual_length < entry->queue->desc_size || urb->status)
+               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
 
        /*
-        * Send the frame to rt2x00lib for further processing.
+        * Schedule the delayed work for reading the RX status
+        * from the device.
         */
-       rt2x00lib_rxdone(rt2x00dev, entry);
+       ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work);
 }
 
 /*
@@ -391,7 +426,7 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
         * The USB version of kill_tx_queue also works
         * on the RX queue.
         */
-       rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_RX);
+       rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev->rx);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
 
@@ -404,6 +439,9 @@ void rt2x00usb_clear_entry(struct queue_entry *entry)
            to_usb_device_intf(entry->queue->rt2x00dev->dev);
        struct queue_entry_priv_usb *entry_priv = entry->priv_data;
        int pipe;
+       int status;
+
+       entry->flags = 0;
 
        if (entry->queue->qid == QID_RX) {
                pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint);
@@ -412,9 +450,15 @@ void rt2x00usb_clear_entry(struct queue_entry *entry)
                                rt2x00usb_interrupt_rxdone, entry);
 
                set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-               usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
-       } else {
-               entry->flags = 0;
+
+               status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+               if (status) {
+                       if (status == -ENODEV)
+                               clear_bit(DEVICE_STATE_PRESENT,
+                                         &entry->queue->rt2x00dev->flags);
+                       set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+                       rt2x00lib_dmadone(entry);
+               }
        }
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);
@@ -489,9 +533,9 @@ static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev)
        return 0;
 }
 
-static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
-                              struct data_queue *queue)
+static int rt2x00usb_alloc_entries(struct data_queue *queue)
 {
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
        struct queue_entry_priv_usb *entry_priv;
        struct queue_entry_priv_usb_bcn *bcn_priv;
        unsigned int i;
@@ -508,7 +552,7 @@ static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
         * no guardian byte was required for the beacon,
         * then we are done.
         */
-       if (rt2x00dev->bcn != queue ||
+       if (queue->qid != QID_BEACON ||
            !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))
                return 0;
 
@@ -522,9 +566,9 @@ static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
        return 0;
 }
 
-static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev,
-                              struct data_queue *queue)
+static void rt2x00usb_free_entries(struct data_queue *queue)
 {
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
        struct queue_entry_priv_usb *entry_priv;
        struct queue_entry_priv_usb_bcn *bcn_priv;
        unsigned int i;
@@ -543,7 +587,7 @@ static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev,
         * no guardian byte was required for the beacon,
         * then we are done.
         */
-       if (rt2x00dev->bcn != queue ||
+       if (queue->qid != QID_BEACON ||
            !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))
                return;
 
@@ -570,7 +614,7 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
         * Allocate DMA
         */
        queue_for_each(rt2x00dev, queue) {
-               status = rt2x00usb_alloc_urb(rt2x00dev, queue);
+               status = rt2x00usb_alloc_entries(queue);
                if (status)
                        goto exit;
        }
@@ -589,7 +633,7 @@ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev)
        struct data_queue *queue;
 
        queue_for_each(rt2x00dev, queue)
-               rt2x00usb_free_urb(rt2x00dev, queue);
+               rt2x00usb_free_entries(queue);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize);
 
@@ -659,6 +703,9 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
 
        rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB);
 
+       INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);
+       INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
+
        retval = rt2x00usb_alloc_reg(rt2x00dev);
        if (retval)
                goto exit_free_device;