PM / Runtime: Remove idle notification after failing suspend

If runtime suspend of a device fails returning -EAGAIN or -EBUSY,
which means that it's safe to try to suspend it again, the PM core
runs the runtime idle helper function for it. Unfortunately this may
lead to problems, for example for PCI devices whose drivers don't
implement the ->runtime_idle() callback, because in that case the
PCI bus type's ->runtime_idle() always calls pm_runtime_suspend()
for the given device. Then, if there's an automatic idle
notification after the driver's ->runtime_suspend() returning -EAGAIN
or -EBUSY, it will make the suspend happen again possibly causing a
busy loop to appear. To avoid that, remove the idle notification
after failing runtime suspend of a device altogether and let the
callers of pm_runtime_suspend() repeat the operation if need be.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Alan Stern <stern@rowland.harvard.edu>

+2 -9
+2 -9
drivers/base/power/runtime.c
··· 281 { 282 int (*callback)(struct device *); 283 struct device *parent = NULL; 284 - bool notify = false; 285 int retval; 286 287 dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags); ··· 382 if (retval) { 383 __update_runtime_status(dev, RPM_ACTIVE); 384 dev->power.deferred_resume = 0; 385 - if (retval == -EAGAIN || retval == -EBUSY) { 386 - if (dev->power.timer_expires == 0) 387 - notify = true; 388 dev->power.runtime_error = 0; 389 - } else { 390 pm_runtime_cancel_pending(dev); 391 - } 392 } else { 393 no_callback: 394 __update_runtime_status(dev, RPM_SUSPENDED); ··· 403 retval = -EAGAIN; 404 goto out; 405 } 406 - 407 - if (notify) 408 - rpm_idle(dev, 0); 409 410 if (parent && !parent->power.ignore_children) { 411 spin_unlock_irq(&dev->power.lock);
··· 281 { 282 int (*callback)(struct device *); 283 struct device *parent = NULL; 284 int retval; 285 286 dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags); ··· 383 if (retval) { 384 __update_runtime_status(dev, RPM_ACTIVE); 385 dev->power.deferred_resume = 0; 386 + if (retval == -EAGAIN || retval == -EBUSY) 387 dev->power.runtime_error = 0; 388 + else 389 pm_runtime_cancel_pending(dev); 390 } else { 391 no_callback: 392 __update_runtime_status(dev, RPM_SUSPENDED); ··· 407 retval = -EAGAIN; 408 goto out; 409 } 410 411 if (parent && !parent->power.ignore_children) { 412 spin_unlock_irq(&dev->power.lock);