USB: ohci: move ohci_pci_{suspend,resume} to ohci-hcd.c
[deliverable/linux.git] / drivers / usb / host / ohci-hcd.c
index 4a1d64d92338e7653035b054decf6e714909a41f..1382689b31db88011a39cd262104172f694ee00e 100644 (file)
@@ -231,13 +231,41 @@ static int ohci_urb_enqueue (
                        frame &= ~(ed->interval - 1);
                        frame |= ed->branch;
                        urb->start_frame = frame;
+               }
+       } else if (ed->type == PIPE_ISOCHRONOUS) {
+               u16     next = ohci_frame_no(ohci) + 2;
+               u16     frame = ed->last_iso + ed->interval;
+
+               /* Behind the scheduling threshold? */
+               if (unlikely(tick_before(frame, next))) {
+
+                       /* USB_ISO_ASAP: Round up to the first available slot */
+                       if (urb->transfer_flags & URB_ISO_ASAP)
+                               frame += (next - frame + ed->interval - 1) &
+                                               -ed->interval;
+
+                       /*
+                        * Not ASAP: Use the next slot in the stream.  If
+                        * the entire URB falls before the threshold, fail.
+                        */
+                       else if (tick_before(frame + ed->interval *
+                                       (urb->number_of_packets - 1), next)) {
+                               retval = -EXDEV;
+                               usb_hcd_unlink_urb_from_ep(hcd, urb);
+                               goto fail;
+                       }
 
-                       /* yes, only URB_ISO_ASAP is supported, and
-                        * urb->start_frame is never used as input.
+                       /*
+                        * Some OHCI hardware doesn't handle late TDs
+                        * correctly.  After retiring them it proceeds to
+                        * the next ED instead of the next TD.  Therefore
+                        * we have to omit the late TDs entirely.
                         */
+                       urb_priv->td_cnt = DIV_ROUND_UP(next - frame,
+                                       ed->interval);
                }
-       } else if (ed->type == PIPE_ISOCHRONOUS)
-               urb->start_frame = ed->last_iso + ed->interval;
+               urb->start_frame = frame;
+       }
 
        /* fill the TDs and link them to the ed; and
         * enable that part of the schedule, if needed
@@ -983,6 +1011,49 @@ static int ohci_restart (struct ohci_hcd *ohci)
 
 #endif
 
+#ifdef CONFIG_PM
+
+static int __maybe_unused ohci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+       unsigned long   flags;
+       int             rc = 0;
+
+       /* Root hub was already suspended. Disable irq emission and
+        * mark HW unaccessible, bail out if RH has been resumed. Use
+        * the spinlock to properly synchronize with possible pending
+        * RH suspend or resume activity.
+        */
+       spin_lock_irqsave (&ohci->lock, flags);
+       if (ohci->rh_state != OHCI_RH_SUSPENDED) {
+               rc = -EINVAL;
+               goto bail;
+       }
+       ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+       (void)ohci_readl(ohci, &ohci->regs->intrdisable);
+
+       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ bail:
+       spin_unlock_irqrestore (&ohci->lock, flags);
+
+       return rc;
+}
+
+
+static int __maybe_unused ohci_resume(struct usb_hcd *hcd, bool hibernated)
+{
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+       /* Make sure resume from hibernation re-enumerates everything */
+       if (hibernated)
+               ohci_usb_reset(hcd_to_ohci(hcd));
+
+       ohci_finish_controller_resume(hcd);
+       return 0;
+}
+
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 MODULE_AUTHOR (DRIVER_AUTHOR);
@@ -1039,11 +1110,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ohci_hcd_pnx8550_driver
 #endif
 
-#ifdef CONFIG_USB_OHCI_HCD_PPC_SOC
-#include "ohci-ppc-soc.c"
-#define PLATFORM_DRIVER                ohci_hcd_ppc_soc_driver
-#endif
-
 #ifdef CONFIG_ARCH_AT91
 #include "ohci-at91.c"
 #define PLATFORM_DRIVER                ohci_hcd_at91_driver
This page took 0.029129 seconds and 5 git commands to generate.