On Thursday, November 03, 2011, Alan Stern wrote: > Originally, the runtime PM core would send an idle notification > whenever a suspend attempt failed. The idle callback routine could > then schedule a delayed suspend for some time later. > > However this behavior was changed by commit > f71648d73c1650b8b4aceb3856bebbde6daa3b86 (PM / Runtime: Remove idle > notification after failing suspend). No notifications were sent, and > there was no clear mechanism to retry failed suspends. > > This caused problems for the usbhid driver, because it fails > autosuspend attempts as long as a key is being held down. Therefore > this patch (as1492) adds a mechanism for retrying failed > autosuspends. If the callback routine updates the last_busy field so > that the next autosuspend expiration time is in the future, the > autosuspend will automatically be rescheduled. > > Signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> > Tested-by: Henrik Rydberg <rydberg@xxxxxxxxxxx> > CC: <stable@xxxxxxxxxx> Applied to linux-pm/linux-next. Thanks, Rafael > --- > > Documentation/power/runtime_pm.txt | 10 ++++++++++ > drivers/base/power/runtime.c | 18 ++++++++++++++++-- > 2 files changed, 26 insertions(+), 2 deletions(-) > > Index: usb-3.1/Documentation/power/runtime_pm.txt > =================================================================== > --- usb-3.1.orig/Documentation/power/runtime_pm.txt > +++ usb-3.1/Documentation/power/runtime_pm.txt > @@ -789,6 +789,16 @@ will behave normally, not taking the aut > Similarly, if the power.use_autosuspend field isn't set then the autosuspend > helper functions will behave just like the non-autosuspend counterparts. > > +Under some circumstances a driver or subsystem may want to prevent a device > +from autosuspending immediately, even though the usage counter is zero and the > +autosuspend delay time has expired. If the ->runtime_suspend() callback > +returns -EAGAIN or -EBUSY, and if the next autosuspend delay expiration time is > +in the future (as it normally would be if the callback invoked > +pm_runtime_mark_last_busy()), the PM core will automatically reschedule the > +autosuspend. The ->runtime_suspend() callback can't do this rescheduling > +itself because no suspend requests of any kind are accepted while the device is > +suspending (i.e., while the callback is running). > + > The implementation is well suited for asynchronous use in interrupt contexts. > However such use inevitably involves races, because the PM core can't > synchronize ->runtime_suspend() callbacks with the arrival of I/O requests. > Index: usb-3.1/drivers/base/power/runtime.c > =================================================================== > --- usb-3.1.orig/drivers/base/power/runtime.c > +++ usb-3.1/drivers/base/power/runtime.c > @@ -296,6 +296,9 @@ static int rpm_callback(int (*cb)(struct > * the callback was running then carry it out, otherwise send an idle > * notification for its parent (if the suspend succeeded and both > * ignore_children of parent->power and irq_safe of dev->power are not set). > + * If ->runtime_suspend failed with -EAGAIN or -EBUSY, and if the RPM_AUTO > + * flag is set and the next autosuspend-delay expiration time is in the > + * future, schedule another autosuspend attempt. > * > * This function must be called under dev->power.lock with interrupts disabled. > */ > @@ -416,10 +419,21 @@ static int rpm_suspend(struct device *de > if (retval) { > __update_runtime_status(dev, RPM_ACTIVE); > dev->power.deferred_resume = false; > - if (retval == -EAGAIN || retval == -EBUSY) > + if (retval == -EAGAIN || retval == -EBUSY) { > dev->power.runtime_error = 0; > - else > + > + /* > + * If the callback routine failed an autosuspend, and > + * if the last_busy time has been updated so that there > + * is a new autosuspend expiration time, automatically > + * reschedule another autosuspend. > + */ > + if ((rpmflags & RPM_AUTO) && > + pm_runtime_autosuspend_expiration(dev) != 0) > + goto repeat; > + } else { > pm_runtime_cancel_pending(dev); > + } > wake_up_all(&dev->power.wait_queue); > goto out; > } > > > -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html