]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/wireless/rt2x00/rt2x00usb.c
Merge branch 'drivers-platform' into release
[linux-2.6-omap-h63xx.git] / drivers / net / wireless / rt2x00 / rt2x00usb.c
index b73a7e0aeed4c54221435bbb3050326450dc093a..83df312ac56fe02b3b833022c8f432d674e0215e 100644 (file)
@@ -79,7 +79,7 @@ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
 {
        int status;
 
-       BUG_ON(!mutex_is_locked(&rt2x00dev->usb_cache_mutex));
+       BUG_ON(!mutex_is_locked(&rt2x00dev->csr_mutex));
 
        /*
         * Check for Cache availability.
@@ -110,13 +110,13 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
 {
        int status;
 
-       mutex_lock(&rt2x00dev->usb_cache_mutex);
+       mutex_lock(&rt2x00dev->csr_mutex);
 
        status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request,
                                                requesttype, offset, buffer,
                                                buffer_length, timeout);
 
-       mutex_unlock(&rt2x00dev->usb_cache_mutex);
+       mutex_unlock(&rt2x00dev->csr_mutex);
 
        return status;
 }
@@ -132,7 +132,7 @@ int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev,
        unsigned char *tb;
        u16 off, len, bsize;
 
-       mutex_lock(&rt2x00dev->usb_cache_mutex);
+       mutex_lock(&rt2x00dev->csr_mutex);
 
        tb  = (char *)buffer;
        off = offset;
@@ -148,12 +148,34 @@ int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev,
                off += bsize;
        }
 
-       mutex_unlock(&rt2x00dev->usb_cache_mutex);
+       mutex_unlock(&rt2x00dev->csr_mutex);
 
        return status;
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_large_buff);
 
+int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
+                          const unsigned int offset,
+                          struct rt2x00_field32 field,
+                          u32 *reg)
+{
+       unsigned int i;
+
+       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+               rt2x00usb_register_read_lock(rt2x00dev, offset, reg);
+               if (!rt2x00_get_field32(*reg, field))
+                       return 1;
+               udelay(REGISTER_BUSY_DELAY);
+       }
+
+       ERROR(rt2x00dev, "Indirect register access failed: "
+             "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
+       *reg = ~0;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read);
+
 /*
  * TX data handlers.
  */
@@ -212,10 +234,10 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry)
         * 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(rt2x00dev, entry->skb);
+       length = rt2x00dev->ops->lib->get_tx_data_len(entry);
 
        usb_fill_bulk_urb(entry_priv->urb, usb_dev,
-                         usb_sndbulkpipe(usb_dev, 1),
+                         usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
                          entry->skb->data, length,
                          rt2x00usb_interrupt_txdone, entry);
 
@@ -351,28 +373,96 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
 /*
  * Device initialization handlers.
  */
-void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
-                           struct queue_entry *entry)
+void rt2x00usb_clear_entry(struct queue_entry *entry)
 {
-       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
+       struct usb_device *usb_dev =
+           to_usb_device_intf(entry->queue->rt2x00dev->dev);
        struct queue_entry_priv_usb *entry_priv = entry->priv_data;
+       int pipe;
 
-       usb_fill_bulk_urb(entry_priv->urb, usb_dev,
-                         usb_rcvbulkpipe(usb_dev, 1),
-                         entry->skb->data, entry->skb->len,
-                         rt2x00usb_interrupt_rxdone, entry);
+       if (entry->queue->qid == QID_RX) {
+               pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint);
+               usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe,
+                               entry->skb->data, entry->skb->len,
+                               rt2x00usb_interrupt_rxdone, entry);
 
-       set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-       usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+               set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
+               usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+       } else {
+               entry->flags = 0;
+       }
 }
-EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry);
+EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);
 
-void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
-                           struct queue_entry *entry)
+static void rt2x00usb_assign_endpoint(struct data_queue *queue,
+                                     struct usb_endpoint_descriptor *ep_desc)
 {
-       entry->flags = 0;
+       struct usb_device *usb_dev = to_usb_device_intf(queue->rt2x00dev->dev);
+       int pipe;
+
+       queue->usb_endpoint = usb_endpoint_num(ep_desc);
+
+       if (queue->qid == QID_RX) {
+               pipe = usb_rcvbulkpipe(usb_dev, queue->usb_endpoint);
+               queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 0);
+       } else {
+               pipe = usb_sndbulkpipe(usb_dev, queue->usb_endpoint);
+               queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 1);
+       }
+
+       if (!queue->usb_maxpacket)
+               queue->usb_maxpacket = 1;
+}
+
+static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev)
+{
+       struct usb_interface *intf = to_usb_interface(rt2x00dev->dev);
+       struct usb_host_interface *intf_desc = intf->cur_altsetting;
+       struct usb_endpoint_descriptor *ep_desc;
+       struct data_queue *queue = rt2x00dev->tx;
+       struct usb_endpoint_descriptor *tx_ep_desc = NULL;
+       unsigned int i;
+
+       /*
+        * Walk through all available endpoints to search for "bulk in"
+        * and "bulk out" endpoints. When we find such endpoints collect
+        * the information we need from the descriptor and assign it
+        * to the queue.
+        */
+       for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
+               ep_desc = &intf_desc->endpoint[i].desc;
+
+               if (usb_endpoint_is_bulk_in(ep_desc)) {
+                       rt2x00usb_assign_endpoint(rt2x00dev->rx, ep_desc);
+               } else if (usb_endpoint_is_bulk_out(ep_desc)) {
+                       rt2x00usb_assign_endpoint(queue, ep_desc);
+
+                       if (queue != queue_end(rt2x00dev))
+                               queue = queue_next(queue);
+                       tx_ep_desc = ep_desc;
+               }
+       }
+
+       /*
+        * At least 1 endpoint for RX and 1 endpoint for TX must be available.
+        */
+       if (!rt2x00dev->rx->usb_endpoint || !rt2x00dev->tx->usb_endpoint) {
+               ERROR(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n");
+               return -EPIPE;
+       }
+
+       /*
+        * It might be possible not all queues have a dedicated endpoint.
+        * Loop through all TX queues and copy the endpoint information
+        * which we have gathered from already assigned endpoints.
+        */
+       txall_queue_for_each(rt2x00dev, queue) {
+               if (!queue->usb_endpoint)
+                       rt2x00usb_assign_endpoint(queue, tx_ep_desc);
+       }
+
+       return 0;
 }
-EXPORT_SYMBOL_GPL(rt2x00usb_init_txentry);
 
 static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
                               struct data_queue *queue)
@@ -444,6 +534,13 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
        struct data_queue *queue;
        int status;
 
+       /*
+        * Find endpoints for each queue
+        */
+       status = rt2x00usb_find_endpoints(rt2x00dev);
+       if (status)
+               goto exit;
+
        /*
         * Allocate DMA
         */
@@ -534,12 +631,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
        rt2x00dev->dev = &usb_intf->dev;
        rt2x00dev->ops = ops;
        rt2x00dev->hw = hw;
-       mutex_init(&rt2x00dev->usb_cache_mutex);
-
-       rt2x00dev->usb_maxpacket =
-           usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1);
-       if (!rt2x00dev->usb_maxpacket)
-               rt2x00dev->usb_maxpacket = 1;
 
        retval = rt2x00usb_alloc_reg(rt2x00dev);
        if (retval)