Message ID | 20170330195818.17669-1-d-gerlach@ti.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
* Dave Gerlach <d-gerlach@ti.com> [170330 13:01]: > Starting from commit 5de85b9d57ab ("PM / runtime: Re-init runtime PM > states at probe error and driver unbind") pm_runtime core now changes > device runtime_status back to after RPM_SUSPENDED after a probe defer. > Certain OMAP devices make use of "ti,no-idle-on-init" flag which causes > omap_device_enable to be called during the BUS_NOTIFY_ADD_DEVICE event > during probe, along with pm_runtime_set_active. > > This call to pm_runtime_set_active typically will prevent a call to > pm_runtime_get in a driver probe function from re-enabling the > omap_device. However, in the case of a probe defer that happens before > the driver probe function is able to run, such as a missing pinctrl > states defer, pm_runtime_reinit will set the device as RPM_SUSPENDED and > then once driver probe is actually able to run, pm_runtime_get will see > the device as suspended and call through to the omap_device layer, > attempting to enable the already enabled omap_device and causing errors > like this: > > omap-gpmc 50000000.gpmc: omap_device: omap_device_enable() called from invalid state 1 > omap-gpmc 50000000.gpmc: use pm_runtime_put_sync_suspend() in driver? > > We can avoid this error by making sure the pm_runtime status of a device > matches the omap_device state before a probe attempt. By extending the > omap_device bus notifier to act on the BUS_NOTIFY_BIND_DRIVER event we > can check if a device is enabled in omap_device but with a pm_runtime > status of RPM_SUSPENDED and once again mark the device as RPM_ACTIVE to > avoid a second incorrect call to omap_device_enable. > > Tested-by: Franklin S Cooper Jr. <fcooper@ti.com> > Signed-off-by: Dave Gerlach <d-gerlach@ti.com> Applying into omap-for-v4.11/fixes thanks. Will let this one sit in Linux next for a while. Regards, Tony > --- > arch/arm/mach-omap2/omap_device.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > > diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c > index e920dd83e443..f989145480c8 100644 > --- a/arch/arm/mach-omap2/omap_device.c > +++ b/arch/arm/mach-omap2/omap_device.c > @@ -222,6 +222,14 @@ static int _omap_device_notifier_call(struct notifier_block *nb, > dev_err(dev, "failed to idle\n"); > } > break; > + case BUS_NOTIFY_BIND_DRIVER: > + od = to_omap_device(pdev); > + if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED) && > + pm_runtime_status_suspended(dev)) { > + od->_driver_status = BUS_NOTIFY_BIND_DRIVER; > + pm_runtime_set_active(dev); > + } > + break; > case BUS_NOTIFY_ADD_DEVICE: > if (pdev->dev.of_node) > omap_device_build_from_dt(pdev); > -- > 2.11.0 >
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index e920dd83e443..f989145480c8 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -222,6 +222,14 @@ static int _omap_device_notifier_call(struct notifier_block *nb, dev_err(dev, "failed to idle\n"); } break; + case BUS_NOTIFY_BIND_DRIVER: + od = to_omap_device(pdev); + if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED) && + pm_runtime_status_suspended(dev)) { + od->_driver_status = BUS_NOTIFY_BIND_DRIVER; + pm_runtime_set_active(dev); + } + break; case BUS_NOTIFY_ADD_DEVICE: if (pdev->dev.of_node) omap_device_build_from_dt(pdev);