On Wednesday 08 June 2005 5:02 pm, Todd Poynor wrote:
> Suspend/resume for the Intel XScale PXA27x OHCI host controller, from
> Nicolas Pitre and myself, based on the TI OMAP OHCI driver code.

Too bad all those pm_message_t changes broke that, then.  :(


It's no longer possible to have driver suspend() methods do
anything intelligent based on the target suspend level,
including basics like leaving clocks active during STR level
suspend but turning them off in deeper suspend states; or
kicking in the appropriate wakeup triggering mechanism.


I've been meaning to rip out all that now-broken code, but
haven't made time to figure out something sensible to do
instead.  I suspect the only workable answer for now is to
give up and assume that "suspend" means "power down" ... the
only way those pm_message_t changes really make sense seems
to be to assume you're running a laptop, and want to snapshot
to disk then power the whole thing off.  With no possibility
of supporting wakeup events other than a power switch, of
course.


> This platform power cycles the device on certain system suspend modes,
> all of which currently arrive as state 3, so the code to react to host
> controller power cycle is performed for a resume from any state.  I know
> that sort of thing is being hashed out on another list...

It is?  I'd almost given up on system PM transitions or pm_message_t
ever making sense, actually.  Maybe I should check out some of the
recent postings on the linux-pm list; maybe some will make sense for
systems where there's no persistent swapspace for "swsusp" to manage,
or where "suspend" is really a suspend state, with wakeup events.
(Ben had some good ideas...)


> If CONFIG_USB_SUSPEND=y then "already suspended/resumed" debug messages
> are generated, but that's true for OMAP as well, so I figured this is a
> work in progress.
> 
> If this should go to the ARM patch system instead please clue me in,
> thanks.

No, USB patches can come through the USB list; I'm reasonably sure
Russell wants to avoid worrying about anything except ARM-core patches
and a few pet driver subsystems.


Comments below.  I think the main point I'd make now is that the
pm_message_t parameter effectively became useless and so it'd
probably be best to ignore it until there's some new work to
un-break the PM framework ... just always turn off/reset the
controller during suspend.  Yes that reduces functionality,
but that seemed to be a goal of pm_message_t:  remove things
that don't fit the snapshot-laptop-and-power-off model.

- Dave




> Signed-off-by: Todd Poynor <[EMAIL PROTECTED]>
> 
> Index: linux-2.6.12-rc4/drivers/usb/host/ohci-pxa27x.c
> ===================================================================
> --- linux-2.6.12-rc4.orig/drivers/usb/host/ohci-pxa27x.c      2005-06-08 
> 22:42:48.000000000 +0000
> +++ linux-2.6.12-rc4/drivers/usb/host/ohci-pxa27x.c   2005-06-08 
> 22:51:14.000000000 +0000
> @@ -310,6 +310,7 @@
>       .hub_suspend =          ohci_hub_suspend,
>       .hub_resume =           ohci_hub_resume,
>  #endif
> +     .start_port_reset =     ohci_start_port_reset,
>  };
>  
>  /*-------------------------------------------------------------------------*/
> @@ -337,32 +338,83 @@
>       return 0;
>  }
>  
> +
> +#ifdef       CONFIG_PM
> +
>  static int ohci_hcd_pxa27x_drv_suspend(struct device *dev, pm_message_t 
> state, u32 level)

I prefer to call these "message" not "state", since they've
stopped being even vaguely meaningful as states.  Originally
the "state" made sense as a target ACPI state number, so that
for example S4 would powerdown and S3 wouldn't necessarily.

Specifially, PM_SUSPEND_DISK (4) and PM_SUSPEND_MEM (3) would
get passed.  I originally thought the pm_message_t stuff was
going to formalize that stuff rather than come up with some
new thing and removing the only truly useful parameter data.


>  {
> -//   struct platform_device *pdev = to_platform_device(dev);
> -//   struct usb_hcd *hcd = dev_get_drvdata(dev);
> -     printk("%s: not implemented yet\n", __FUNCTION__);
> +     struct platform_device *pdev = to_platform_device(dev);
> +     struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
> +     int status = -EINVAL;
>  
> -     return 0;
> +     if (level != SUSPEND_POWER_DOWN)
> +             return 0;
> +     if (state <= dev->power.power_state)
> +             return 0;

Doesn't "sparse" choke on stuff like this lately?  Regardless,
the "power state" is no longer directly comprehensible in terms
of the suspend parameter, which is a "message".  It's probably
not even worth looking at that parameter; there's only one
value it can legally have in a suspend() method.


> +     dev_dbg(dev, "suspend to %d\n", state);
> +     down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
> +     status = ohci_hub_suspend(ohci_to_hcd(ohci));
> +     if (status == 0) {
> +             if (state >= 4) {
> +                     pxa27x_stop_hc(pdev);
> +                     ohci_to_hcd(ohci)->self.root_hub->state =
> +                                     USB_STATE_SUSPENDED;
> +                     state = 4;

And this is the class of functionality that's been broken by
those pm_message_t changes.  PM_SUSPEND_DISK == 4, which worked
with this; and PM_SUSPEND_MEM == 3 with the other state.

But today, "pm_message_t" is just a fancy and useless boolean.

I've not had time to come up with a better idea than just
going back to the way things were before pm_message_t changes
started to roll in, but meanwhile I think the only solution
allowed by current pm_message_t stuff is to reset and power
down the HC in suspend() methods.  That means no wakeup event
support here, no matter what kind of state the system is in.

(Though at least for OMAP 1710 ES2.0 it's clear how to do
OHCI wakeup events even from deep sleep.  I don't know what
the PXA 27x does in such cases.)


> +             }
> +             ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
> +             dev->power.power_state = state;
> +     }
> +     up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
> +     return status;
>  }
>  
>  static int ohci_hcd_pxa27x_drv_resume(struct device *dev, u32 level)
>  {
> -//   struct platform_device *pdev = to_platform_device(dev);
> -//   struct usb_hcd *hcd = dev_get_drvdata(dev);
> -     printk("%s: not implemented yet\n", __FUNCTION__);
> +     struct platform_device *pdev = to_platform_device(dev);
> +     struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
> +     int             status = 0;
>  
> -     return 0;
> +     if (level != RESUME_POWER_ON)
> +             return 0;
> +
> +     switch (dev->power.power_state) {
> +     case 0:
> +             break;
> +     case 4:

Again, state 4 (PM_SUSPEND_DISK) isn't worth testing for any
longer, given the pm_message_t changes that broke things.


> +             if (time_before(jiffies, ohci->next_statechange))
> +                     msleep(5);
> +             ohci->next_statechange = jiffies;
> +             /* FALLTHROUGH */
> +     default:
> +             dev_dbg(dev, "resume from %d\n", dev->power.power_state);
> +             pxa27x_start_hc(pdev);
> +#ifdef       CONFIG_USB_SUSPEND
> +             /* get extra cleanup even if remote wakeup isn't in use */
> +             status = usb_resume_device(ohci_to_hcd(ohci)->self.root_hub);

This stuff's messy, but last I looked it was still needed.


> +#else
> +             down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
> +             status = ohci_hub_resume(ohci_to_hcd(ohci));
> +             up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
> +#endif
> +             if (status == 0)
> +                     dev->power.power_state = 0;
> +             break;
> +     }
> +     return status;
>  }
>  
> +#endif
>  
>  static struct device_driver ohci_hcd_pxa27x_driver = {
>       .name           = "pxa27x-ohci",
>       .bus            = &platform_bus_type,
>       .probe          = ohci_hcd_pxa27x_drv_probe,
>       .remove         = ohci_hcd_pxa27x_drv_remove,
> +#ifdef       CONFIG_PM
>       .suspend        = ohci_hcd_pxa27x_drv_suspend, 
> -     .resume         = ohci_hcd_pxa27x_drv_resume, 
> +     .resume         = ohci_hcd_pxa27x_drv_resume,
> +#endif 
>  };
>  
>  static int __init ohci_hcd_pxa27x_init (void)
> 
> 
> 



-------------------------------------------------------
This SF.Net email is sponsored by: NEC IT Guy Games.  How far can you shotput
a projector? How fast can you ride your desk chair down the office luge track?
If you want to score the big prize, get to know the little guy.  
Play to win an NEC 61" plasma display: http://www.necitguy.com/?r=20
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to