]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/usb/host/sl811-hcd.c
Merge iSeries include file move
[karo-tx-linux.git] / drivers / usb / host / sl811-hcd.c
index 7a890a65f55dc53664b8dd130ee3b4a6b048ffa7..40169d9cf2b1855c6b5bdd060e16291423af8aad 100644 (file)
@@ -782,6 +782,9 @@ retry:
 /* usb 1.1 says max 90% of a frame is available for periodic transfers.
  * this driver doesn't promise that much since it's got to handle an
  * IRQ per packet; irq handling latencies also use up that time.
+ *
+ * NOTE:  the periodic schedule is a sparse tree, with the load for
+ * each branch minimized.  see fig 3.5 in the OHCI spec for example.
  */
 #define        MAX_PERIODIC_LOAD       500     /* out of 1000 usec */
 
@@ -815,7 +818,7 @@ static int sl811h_urb_enqueue(
        struct usb_hcd          *hcd,
        struct usb_host_endpoint *hep,
        struct urb              *urb,
-       unsigned                mem_flags
+       gfp_t                   mem_flags
 ) {
        struct sl811            *sl811 = hcd_to_sl811(hcd);
        struct usb_device       *udev = urb->dev;
@@ -835,7 +838,7 @@ static int sl811h_urb_enqueue(
 
        /* avoid all allocations within spinlocks */
        if (!hep->hcpriv)
-               ep = kcalloc(1, sizeof *ep, mem_flags);
+               ep = kzalloc(sizeof *ep, mem_flags);
 
        spin_lock_irqsave(&sl811->lock, flags);
 
@@ -843,6 +846,7 @@ static int sl811h_urb_enqueue(
        if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE))
                        || !HC_IS_RUNNING(hcd->state)) {
                retval = -ENODEV;
+               kfree(ep);
                goto fail;
        }
 
@@ -911,8 +915,16 @@ static int sl811h_urb_enqueue(
        case PIPE_ISOCHRONOUS:
        case PIPE_INTERRUPT:
                urb->interval = ep->period;
-               if (ep->branch < PERIODIC_SIZE)
+               if (ep->branch < PERIODIC_SIZE) {
+                       /* NOTE:  the phase is correct here, but the value
+                        * needs offsetting by the transfer queue depth.
+                        * All current drivers ignore start_frame, so this
+                        * is unlikely to ever matter...
+                        */
+                       urb->start_frame = (sl811->frame & (PERIODIC_SIZE - 1))
+                                               + ep->branch;
                        break;
+               }
 
                retval = balance(sl811, ep->period, ep->load);
                if (retval < 0)
@@ -1122,7 +1134,7 @@ sl811h_hub_descriptor (
        desc->wHubCharacteristics = (__force __u16)cpu_to_le16(temp);
 
        /* two bitmaps:  ports removable, and legacy PortPwrCtrlMask */
-       desc->bitmap[0] = 1 << 1;
+       desc->bitmap[0] = 0 << 1;
        desc->bitmap[1] = ~0;
 }
 
@@ -1351,7 +1363,7 @@ error:
 #ifdef CONFIG_PM
 
 static int
-sl811h_hub_suspend(struct usb_hcd *hcd)
+sl811h_bus_suspend(struct usb_hcd *hcd)
 {
        // SOFs off
        DBG("%s\n", __FUNCTION__);
@@ -1359,7 +1371,7 @@ sl811h_hub_suspend(struct usb_hcd *hcd)
 }
 
 static int
-sl811h_hub_resume(struct usb_hcd *hcd)
+sl811h_bus_resume(struct usb_hcd *hcd)
 {
        // SOFs on
        DBG("%s\n", __FUNCTION__);
@@ -1368,8 +1380,8 @@ sl811h_hub_resume(struct usb_hcd *hcd)
 
 #else
 
-#define        sl811h_hub_suspend      NULL
-#define        sl811h_hub_resume       NULL
+#define        sl811h_bus_suspend      NULL
+#define        sl811h_bus_resume       NULL
 
 #endif
 
@@ -1611,8 +1623,8 @@ static struct hc_driver sl811h_hc_driver = {
         */
        .hub_status_data =      sl811h_hub_status_data,
        .hub_control =          sl811h_hub_control,
-       .hub_suspend =          sl811h_hub_suspend,
-       .hub_resume =           sl811h_hub_resume,
+       .bus_suspend =          sl811h_bus_suspend,
+       .bus_resume =           sl811h_bus_resume,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -1772,18 +1784,15 @@ sl811h_probe(struct device *dev)
  */
 
 static int
-sl811h_suspend(struct device *dev, pm_message_t state, u32 phase)
+sl811h_suspend(struct device *dev, pm_message_t state)
 {
        struct usb_hcd  *hcd = dev_get_drvdata(dev);
        struct sl811    *sl811 = hcd_to_sl811(hcd);
        int             retval = 0;
 
-       if (phase != SUSPEND_POWER_DOWN)
-               return retval;
-
-       if (state <= PM_SUSPEND_MEM)
-               retval = sl811h_hub_suspend(hcd);
-       else
+       if (state.event == PM_EVENT_FREEZE)
+               retval = sl811h_bus_suspend(hcd);
+       else if (state.event == PM_EVENT_SUSPEND)
                port_power(sl811, 0);
        if (retval == 0)
                dev->power.power_state = state;
@@ -1791,18 +1800,15 @@ sl811h_suspend(struct device *dev, pm_message_t state, u32 phase)
 }
 
 static int
-sl811h_resume(struct device *dev, u32 phase)
+sl811h_resume(struct device *dev)
 {
        struct usb_hcd  *hcd = dev_get_drvdata(dev);
        struct sl811    *sl811 = hcd_to_sl811(hcd);
 
-       if (phase != RESUME_POWER_ON)
-               return 0;
-
        /* with no "check to see if VBUS is still powered" board hook,
         * let's assume it'd only be powered to enable remote wakeup.
         */
-       if (dev->power.power_state > PM_SUSPEND_MEM
+       if (dev->power.power_state.event == PM_EVENT_SUSPEND
                        || !hcd->can_wakeup) {
                sl811->port1 = 0;
                port_power(sl811, 1);
@@ -1810,7 +1816,7 @@ sl811h_resume(struct device *dev, u32 phase)
        }
 
        dev->power.power_state = PMSG_ON;
-       return sl811h_hub_resume(hcd);
+       return sl811h_bus_resume(hcd);
 }
 
 #else
@@ -1825,6 +1831,7 @@ sl811h_resume(struct device *dev, u32 phase)
 struct device_driver sl811h_driver = {
        .name =         (char *) hcd_name,
        .bus =          &platform_bus_type,
+       .owner =        THIS_MODULE,
 
        .probe =        sl811h_probe,
        .remove =       __devexit_p(sl811h_remove),