Message ID | 20241009054429.3970438-2-guanyulin@google.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Support system sleep with offloaded usb transfers | expand |
On Wed, Oct 09, 2024 at 05:42:55AM +0000, Guan-Yu Lin wrote: > Separate dev_pm_ops for different power events such as suspend, thaw, > and hibernation. This is crucial when dwc3 driver needs to adapt its > behavior based on different power state changes. > > Signed-off-by: Guan-Yu Lin <guanyulin@google.com> > --- > drivers/usb/dwc3/core.c | 77 ++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 76 insertions(+), 1 deletion(-) > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > index b25d80f318a9..2fdafbcbe44c 100644 > --- a/drivers/usb/dwc3/core.c > +++ b/drivers/usb/dwc3/core.c > @@ -2582,6 +2582,76 @@ static int dwc3_resume(struct device *dev) > return 0; > } > > +static int dwc3_freeze(struct device *dev) > +{ > + struct dwc3 *dwc = dev_get_drvdata(dev); > + int ret; > + > + ret = dwc3_suspend_common(dwc, PMSG_FREEZE); > + if (ret) > + return ret; > + > + pinctrl_pm_select_sleep_state(dev); > + > + return 0; > +} > + > +static int dwc3_thaw(struct device *dev) > +{ > + struct dwc3 *dwc = dev_get_drvdata(dev); > + int ret; > + > + pinctrl_pm_select_default_state(dev); > + > + pm_runtime_disable(dev); > + pm_runtime_set_active(dev); > + > + ret = dwc3_resume_common(dwc, PMSG_THAW); > + if (ret) { > + pm_runtime_set_suspended(dev); > + return ret; > + } > + > + pm_runtime_enable(dev); > + > + return 0; > +} > + > +static int dwc3_poweroff(struct device *dev) > +{ > + struct dwc3 *dwc = dev_get_drvdata(dev); > + int ret; > + > + ret = dwc3_suspend_common(dwc, PMSG_HIBERNATE); Why is power off hibernate? This needs an ack from the dwc3 maintainer as I can't determine if it's correct at all... thanks, greg k-h
On Wed, Oct 9, 2024 at 8:45 PM Greg KH <gregkh@linuxfoundation.org> wrote: > > On Wed, Oct 09, 2024 at 05:42:55AM +0000, Guan-Yu Lin wrote: > > + > > +static int dwc3_poweroff(struct device *dev) > > +{ > > + struct dwc3 *dwc = dev_get_drvdata(dev); > > + int ret; > > + > > + ret = dwc3_suspend_common(dwc, PMSG_HIBERNATE); > > Why is power off hibernate? > > This needs an ack from the dwc3 maintainer as I can't determine if it's > correct at all... > > thanks, > > greg k-h Described in /include/linux/pm.h, PM_EVENT_HIBERNATE message denotes the following transition in the PM core code: "Hibernation image has been saved, call ->prepare() and ->poweroff() for all devices." Meantime, the interpretation of the the above description could be found in /drivers/base/power/main.c: static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state) { ... case PM_EVENT_HIBERNATE: return ops->poweroff; ... } An example in device drivers could be found in usb/drivers/usb/core/usb.c: static int usb_dev_suspend(struct device *dev) { return usb_suspend(dev, PMSG_SUSPEND); } Regards, Guan-Yu
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index b25d80f318a9..2fdafbcbe44c 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -2582,6 +2582,76 @@ static int dwc3_resume(struct device *dev) return 0; } +static int dwc3_freeze(struct device *dev) +{ + struct dwc3 *dwc = dev_get_drvdata(dev); + int ret; + + ret = dwc3_suspend_common(dwc, PMSG_FREEZE); + if (ret) + return ret; + + pinctrl_pm_select_sleep_state(dev); + + return 0; +} + +static int dwc3_thaw(struct device *dev) +{ + struct dwc3 *dwc = dev_get_drvdata(dev); + int ret; + + pinctrl_pm_select_default_state(dev); + + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + + ret = dwc3_resume_common(dwc, PMSG_THAW); + if (ret) { + pm_runtime_set_suspended(dev); + return ret; + } + + pm_runtime_enable(dev); + + return 0; +} + +static int dwc3_poweroff(struct device *dev) +{ + struct dwc3 *dwc = dev_get_drvdata(dev); + int ret; + + ret = dwc3_suspend_common(dwc, PMSG_HIBERNATE); + if (ret) + return ret; + + pinctrl_pm_select_sleep_state(dev); + + return 0; +} + +static int dwc3_restore(struct device *dev) +{ + struct dwc3 *dwc = dev_get_drvdata(dev); + int ret; + + pinctrl_pm_select_default_state(dev); + + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + + ret = dwc3_resume_common(dwc, PMSG_RESTORE); + if (ret) { + pm_runtime_set_suspended(dev); + return ret; + } + + pm_runtime_enable(dev); + + return 0; +} + static void dwc3_complete(struct device *dev) { struct dwc3 *dwc = dev_get_drvdata(dev); @@ -2599,7 +2669,12 @@ static void dwc3_complete(struct device *dev) #endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops dwc3_dev_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) + .suspend = pm_sleep_ptr(dwc3_suspend), + .resume = pm_sleep_ptr(dwc3_resume), + .freeze = pm_sleep_ptr(dwc3_freeze), + .thaw = pm_sleep_ptr(dwc3_thaw), + .poweroff = pm_sleep_ptr(dwc3_poweroff), + .restore = pm_sleep_ptr(dwc3_restore), .complete = dwc3_complete, SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume, dwc3_runtime_idle)
Separate dev_pm_ops for different power events such as suspend, thaw, and hibernation. This is crucial when dwc3 driver needs to adapt its behavior based on different power state changes. Signed-off-by: Guan-Yu Lin <guanyulin@google.com> --- drivers/usb/dwc3/core.c | 77 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-)