]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/usb/host/ehci-hcd.c
USB: Add OMAP EHCI glue layer
[linux-2.6-omap-h63xx.git] / drivers / usb / host / ehci-hcd.c
index 35cdba10411b3c09bf7a3e72b697cc0f0fef6931..455298722453545f84bf1e526b178d9371c5876b 100644 (file)
@@ -570,10 +570,21 @@ static int ehci_run (struct usb_hcd *hcd)
         * are explicitly handed to companion controller(s), so no TT is
         * involved with the root hub.  (Except where one is integrated,
         * and there's no companion controller unless maybe for USB OTG.)
+        *
+        * Turning on the CF flag will transfer ownership of all ports
+        * from the companions to the EHCI controller.  If any of the
+        * companions are in the middle of a port reset at the time, it
+        * could cause trouble.  Write-locking ehci_cf_port_reset_rwsem
+        * guarantees that no resets are in progress.  After we set CF,
+        * a short delay lets the hardware catch up; new resets shouldn't
+        * be started before the port switching actions could complete.
         */
+       down_write(&ehci_cf_port_reset_rwsem);
        hcd->state = HC_STATE_RUNNING;
        ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
        ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
+       msleep(5);
+       up_write(&ehci_cf_port_reset_rwsem);
 
        temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
        ehci_info (ehci,
@@ -719,7 +730,6 @@ dead:
  */
 static int ehci_urb_enqueue (
        struct usb_hcd  *hcd,
-       struct usb_host_endpoint *ep,
        struct urb      *urb,
        gfp_t           mem_flags
 ) {
@@ -734,12 +744,12 @@ static int ehci_urb_enqueue (
        default:
                if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
                        return -ENOMEM;
-               return submit_async (ehci, ep, urb, &qtd_list, mem_flags);
+               return submit_async(ehci, urb, &qtd_list, mem_flags);
 
        case PIPE_INTERRUPT:
                if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
                        return -ENOMEM;
-               return intr_submit (ehci, ep, urb, &qtd_list, mem_flags);
+               return intr_submit(ehci, urb, &qtd_list, mem_flags);
 
        case PIPE_ISOCHRONOUS:
                if (urb->dev->speed == USB_SPEED_HIGH)
@@ -777,13 +787,18 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
  * completions normally happen asynchronously
  */
 
-static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
        struct ehci_qh          *qh;
        unsigned long           flags;
+       int                     rc;
 
        spin_lock_irqsave (&ehci->lock, flags);
+       rc = usb_hcd_check_unlink_urb(hcd, urb, status);
+       if (rc)
+               goto done;
+
        switch (usb_pipetype (urb->pipe)) {
        // case PIPE_CONTROL:
        // case PIPE_BULK:
@@ -838,7 +853,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
        }
 done:
        spin_unlock_irqrestore (&ehci->lock, flags);
-       return 0;
+       return rc;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -939,6 +954,11 @@ MODULE_LICENSE ("GPL");
 #define        PLATFORM_DRIVER         ehci_hcd_au1xxx_driver
 #endif
 
+#ifdef CONFIG_ARCH_OMAP34XX
+#include "ehci-omap.c"
+#define        PLATFORM_DRIVER         ehci_hcd_omap_driver
+#endif
+
 #ifdef CONFIG_PPC_PS3
 #include "ehci-ps3.c"
 #define        PS3_SYSTEM_BUS_DRIVER   ps3_ehci_driver