diff mbox series

[PATCHv2] watchdog: qcom: Add suspend/resume support

Message ID 20190117151942.6092-1-saiprakash.ranjan@codeaurora.org (mailing list archive)
State Mainlined, archived
Commit 671cdde36e26feb509e5cc25c0ca273907eaf914
Headers show
Series [PATCHv2] watchdog: qcom: Add suspend/resume support | expand

Commit Message

Sai Prakash Ranjan Jan. 17, 2019, 3:19 p.m. UTC
This adds the support for qcom watchdog suspend and resume
when entering and exiting deep sleep states. Otherwise
having watchdog active after suspend would result in unwanted
crashes/resets if resume happens after a long time.

Signed-off-by: Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>

---

v2:
 * Use __maybe_unused instead of #ifdef as suggested by
   Brian and Guenter
---
 drivers/watchdog/qcom-wdt.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

Comments

Sai Prakash Ranjan Jan. 17, 2019, 3:26 p.m. UTC | #1
On 1/17/2019 8:49 PM, Sai Prakash Ranjan wrote:
> This adds the support for qcom watchdog suspend and resume
> when entering and exiting deep sleep states. Otherwise
> having watchdog active after suspend would result in unwanted
> crashes/resets if resume happens after a long time.
> 
> Signed-off-by: Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
> 
> ---
> 
> v2:
>   * Use __maybe_unused instead of #ifdef as suggested by
>     Brian and Guenter
> ---
>   drivers/watchdog/qcom-wdt.c | 23 +++++++++++++++++++++++
>   1 file changed, 23 insertions(+)
> 
> 

Adding Brian.
Guenter Roeck Jan. 17, 2019, 6:16 p.m. UTC | #2
On Thu, Jan 17, 2019 at 08:49:42PM +0530, Sai Prakash Ranjan wrote:
> This adds the support for qcom watchdog suspend and resume
> when entering and exiting deep sleep states. Otherwise
> having watchdog active after suspend would result in unwanted
> crashes/resets if resume happens after a long time.
> 
> Signed-off-by: Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> 
> ---
> 
> v2:
>  * Use __maybe_unused instead of #ifdef as suggested by
>    Brian and Guenter
> ---
>  drivers/watchdog/qcom-wdt.c | 23 +++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
> 
> diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c
> index 780971318810..5dfd604477a4 100644
> --- a/drivers/watchdog/qcom-wdt.c
> +++ b/drivers/watchdog/qcom-wdt.c
> @@ -245,6 +245,28 @@ static int qcom_wdt_remove(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +static int __maybe_unused qcom_wdt_suspend(struct device *dev)
> +{
> +	struct qcom_wdt *wdt = dev_get_drvdata(dev);
> +
> +	if (watchdog_active(&wdt->wdd))
> +		qcom_wdt_stop(&wdt->wdd);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused qcom_wdt_resume(struct device *dev)
> +{
> +	struct qcom_wdt *wdt = dev_get_drvdata(dev);
> +
> +	if (watchdog_active(&wdt->wdd))
> +		qcom_wdt_start(&wdt->wdd);
> +
> +	return 0;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(qcom_wdt_pm_ops, qcom_wdt_suspend, qcom_wdt_resume);
> +
>  static const struct of_device_id qcom_wdt_of_table[] = {
>  	{ .compatible = "qcom,kpss-timer", .data = reg_offset_data_apcs_tmr },
>  	{ .compatible = "qcom,scss-timer", .data = reg_offset_data_apcs_tmr },
> @@ -259,6 +281,7 @@ static struct platform_driver qcom_watchdog_driver = {
>  	.driver	= {
>  		.name		= KBUILD_MODNAME,
>  		.of_match_table	= qcom_wdt_of_table,
> +		.pm		= &qcom_wdt_pm_ops,
>  	},
>  };
>  module_platform_driver(qcom_watchdog_driver);
> -- 
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
>
Stephen Boyd Jan. 17, 2019, 6:37 p.m. UTC | #3
Quoting Sai Prakash Ranjan (2019-01-17 07:19:42)
> diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c
> index 780971318810..5dfd604477a4 100644
> --- a/drivers/watchdog/qcom-wdt.c
> +++ b/drivers/watchdog/qcom-wdt.c
> @@ -245,6 +245,28 @@ static int qcom_wdt_remove(struct platform_device *pdev)
>         return 0;
>  }
>  
> +static int __maybe_unused qcom_wdt_suspend(struct device *dev)
> +{
> +       struct qcom_wdt *wdt = dev_get_drvdata(dev);
> +
> +       if (watchdog_active(&wdt->wdd))
> +               qcom_wdt_stop(&wdt->wdd);
> +
> +       return 0;
> +}
> +
> +static int __maybe_unused qcom_wdt_resume(struct device *dev)
> +{
> +       struct qcom_wdt *wdt = dev_get_drvdata(dev);
> +
> +       if (watchdog_active(&wdt->wdd))
> +               qcom_wdt_start(&wdt->wdd);
> +
> +       return 0;
> +}

This looks fairly generic. For example, the Mediatek driver also stops
and starts (but also pings after starting). Grepping for 'active' in
drivers/watchdog/ finds more examples. Could there be some functions in
watchdog core that do the common things like watchdog_stop() and
watchdog_start() and watchdog_start_and_ping()? Or maybe a bit can be
set during registration so that the 'struct class watchdog_class' can
get PM ops to stop and start on suspend/resume of the watchdog character
device?

Nothing is wrong with the patch, I'm just bemoaning the amount of code
duplication here.
Guenter Roeck Jan. 17, 2019, 7:09 p.m. UTC | #4
On Thu, Jan 17, 2019 at 10:37 AM Stephen Boyd <swboyd@chromium.org> wrote:
>
> Quoting Sai Prakash Ranjan (2019-01-17 07:19:42)
> > diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c
> > index 780971318810..5dfd604477a4 100644
> > --- a/drivers/watchdog/qcom-wdt.c
> > +++ b/drivers/watchdog/qcom-wdt.c
> > @@ -245,6 +245,28 @@ static int qcom_wdt_remove(struct platform_device *pdev)
> >         return 0;
> >  }
> >
> > +static int __maybe_unused qcom_wdt_suspend(struct device *dev)
> > +{
> > +       struct qcom_wdt *wdt = dev_get_drvdata(dev);
> > +
> > +       if (watchdog_active(&wdt->wdd))
> > +               qcom_wdt_stop(&wdt->wdd);
> > +
> > +       return 0;
> > +}
> > +
> > +static int __maybe_unused qcom_wdt_resume(struct device *dev)
> > +{
> > +       struct qcom_wdt *wdt = dev_get_drvdata(dev);
> > +
> > +       if (watchdog_active(&wdt->wdd))
> > +               qcom_wdt_start(&wdt->wdd);
> > +
> > +       return 0;
> > +}
>
> This looks fairly generic. For example, the Mediatek driver also stops
> and starts (but also pings after starting). Grepping for 'active' in
> drivers/watchdog/ finds more examples. Could there be some functions in
> watchdog core that do the common things like watchdog_stop() and
> watchdog_start() and watchdog_start_and_ping()? Or maybe a bit can be
> set during registration so that the 'struct class watchdog_class' can
> get PM ops to stop and start on suspend/resume of the watchdog character
> device?
>
> Nothing is wrong with the patch, I'm just bemoaning the amount of code
> duplication here.
>

Patch(es) to add the functionality to the watchdog core are welcome;
it should be possible to move the functionality into the core (maybe
to be enabled with a new watchdog API call). Doing it using the class
device sounds like an excellent idea. This should be straightforward
to implement, though the question of "should we ping on resume or not"
might be an endless source for bike shedding fun.

Guenter
Jerry Hoemann Jan. 17, 2019, 9:14 p.m. UTC | #5
On Thu, Jan 17, 2019 at 11:09:31AM -0800, Guenter Roeck wrote:
> On Thu, Jan 17, 2019 at 10:37 AM Stephen Boyd <swboyd@chromium.org> wrote:
> >
> > Quoting Sai Prakash Ranjan (2019-01-17 07:19:42)
> > > diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c
> > > index 780971318810..5dfd604477a4 100644
> > > --- a/drivers/watchdog/qcom-wdt.c
> > > +++ b/drivers/watchdog/qcom-wdt.c
> > > @@ -245,6 +245,28 @@ static int qcom_wdt_remove(struct platform_device *pdev)
> > >         return 0;
> > >  }
> > >
> > > +static int __maybe_unused qcom_wdt_suspend(struct device *dev)
> > > +{
> > > +       struct qcom_wdt *wdt = dev_get_drvdata(dev);
> > > +
> > > +       if (watchdog_active(&wdt->wdd))
> > > +               qcom_wdt_stop(&wdt->wdd);
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static int __maybe_unused qcom_wdt_resume(struct device *dev)
> > > +{
> > > +       struct qcom_wdt *wdt = dev_get_drvdata(dev);
> > > +
> > > +       if (watchdog_active(&wdt->wdd))
> > > +               qcom_wdt_start(&wdt->wdd);
> > > +
> > > +       return 0;
> > > +}
> >
> > This looks fairly generic. For example, the Mediatek driver also stops
> > and starts (but also pings after starting). Grepping for 'active' in
> > drivers/watchdog/ finds more examples. Could there be some functions in
> > watchdog core that do the common things like watchdog_stop() and
> > watchdog_start() and watchdog_start_and_ping()? Or maybe a bit can be
> > set during registration so that the 'struct class watchdog_class' can
> > get PM ops to stop and start on suspend/resume of the watchdog character
> > device?
> >
> > Nothing is wrong with the patch, I'm just bemoaning the amount of code
> > duplication here.
> >
> 
> Patch(es) to add the functionality to the watchdog core are welcome;
> it should be possible to move the functionality into the core (maybe
> to be enabled with a new watchdog API call). Doing it using the class
> device sounds like an excellent idea. This should be straightforward
> to implement, though the question of "should we ping on resume or not"
> might be an endless source for bike shedding fun.
> 
> Guenter

It could be controlled by a currently unused bit in the
watchdog_info.options.  Then people can agree to disagree.
Guenter Roeck Jan. 17, 2019, 9:16 p.m. UTC | #6
On Thu, Jan 17, 2019 at 1:14 PM Jerry Hoemann <jerry.hoemann@hpe.com> wrote:
>
> On Thu, Jan 17, 2019 at 11:09:31AM -0800, Guenter Roeck wrote:
> > On Thu, Jan 17, 2019 at 10:37 AM Stephen Boyd <swboyd@chromium.org> wrote:
> > >
> > > Quoting Sai Prakash Ranjan (2019-01-17 07:19:42)
> > > > diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c
> > > > index 780971318810..5dfd604477a4 100644
> > > > --- a/drivers/watchdog/qcom-wdt.c
> > > > +++ b/drivers/watchdog/qcom-wdt.c
> > > > @@ -245,6 +245,28 @@ static int qcom_wdt_remove(struct platform_device *pdev)
> > > >         return 0;
> > > >  }
> > > >
> > > > +static int __maybe_unused qcom_wdt_suspend(struct device *dev)
> > > > +{
> > > > +       struct qcom_wdt *wdt = dev_get_drvdata(dev);
> > > > +
> > > > +       if (watchdog_active(&wdt->wdd))
> > > > +               qcom_wdt_stop(&wdt->wdd);
> > > > +
> > > > +       return 0;
> > > > +}
> > > > +
> > > > +static int __maybe_unused qcom_wdt_resume(struct device *dev)
> > > > +{
> > > > +       struct qcom_wdt *wdt = dev_get_drvdata(dev);
> > > > +
> > > > +       if (watchdog_active(&wdt->wdd))
> > > > +               qcom_wdt_start(&wdt->wdd);
> > > > +
> > > > +       return 0;
> > > > +}
> > >
> > > This looks fairly generic. For example, the Mediatek driver also stops
> > > and starts (but also pings after starting). Grepping for 'active' in
> > > drivers/watchdog/ finds more examples. Could there be some functions in
> > > watchdog core that do the common things like watchdog_stop() and
> > > watchdog_start() and watchdog_start_and_ping()? Or maybe a bit can be
> > > set during registration so that the 'struct class watchdog_class' can
> > > get PM ops to stop and start on suspend/resume of the watchdog character
> > > device?
> > >
> > > Nothing is wrong with the patch, I'm just bemoaning the amount of code
> > > duplication here.
> > >
> >
> > Patch(es) to add the functionality to the watchdog core are welcome;
> > it should be possible to move the functionality into the core (maybe
> > to be enabled with a new watchdog API call). Doing it using the class
> > device sounds like an excellent idea. This should be straightforward
> > to implement, though the question of "should we ping on resume or not"
> > might be an endless source for bike shedding fun.
> >
> > Guenter
>
> It could be controlled by a currently unused bit in the
> watchdog_info.options.  Then people can agree to disagree.
>
I thought about that, but that would result in inconsistent behavior
across drivers. Of course we could be all fancy and make it runtime
configurable via ioctl.

Guenter
Sai Prakash Ranjan Jan. 18, 2019, 2:58 a.m. UTC | #7
On 1/17/2019 11:46 PM, Guenter Roeck wrote:
> On Thu, Jan 17, 2019 at 08:49:42PM +0530, Sai Prakash Ranjan wrote:
>> This adds the support for qcom watchdog suspend and resume
>> when entering and exiting deep sleep states. Otherwise
>> having watchdog active after suspend would result in unwanted
>> crashes/resets if resume happens after a long time.
>>
>> Signed-off-by: Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
> 
> Reviewed-by: Guenter Roeck <linux@roeck-us.net>
> 

Thanks Guenter. Should I send a v3 with your reviewed-by?

- Sai
Guenter Roeck Jan. 18, 2019, 3:53 a.m. UTC | #8
On 1/17/19 6:58 PM, Sai Prakash Ranjan wrote:
> On 1/17/2019 11:46 PM, Guenter Roeck wrote:
>> On Thu, Jan 17, 2019 at 08:49:42PM +0530, Sai Prakash Ranjan wrote:
>>> This adds the support for qcom watchdog suspend and resume
>>> when entering and exiting deep sleep states. Otherwise
>>> having watchdog active after suspend would result in unwanted
>>> crashes/resets if resume happens after a long time.
>>>
>>> Signed-off-by: Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
>>
>> Reviewed-by: Guenter Roeck <linux@roeck-us.net>
>>
> 
> Thanks Guenter. Should I send a v3 with your reviewed-by?
> 

I add it to my watchdog-next branch and Wim will pick it up from there.
No need to resend.

Guenter
Sai Prakash Ranjan Jan. 18, 2019, 4:25 a.m. UTC | #9
On 1/18/2019 9:23 AM, Guenter Roeck wrote:
> On 1/17/19 6:58 PM, Sai Prakash Ranjan wrote:
>> On 1/17/2019 11:46 PM, Guenter Roeck wrote:
>>> On Thu, Jan 17, 2019 at 08:49:42PM +0530, Sai Prakash Ranjan wrote:
>>>> This adds the support for qcom watchdog suspend and resume
>>>> when entering and exiting deep sleep states. Otherwise
>>>> having watchdog active after suspend would result in unwanted
>>>> crashes/resets if resume happens after a long time.
>>>>
>>>> Signed-off-by: Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
>>>
>>> Reviewed-by: Guenter Roeck <linux@roeck-us.net>
>>>
>>
>> Thanks Guenter. Should I send a v3 with your reviewed-by?
>>
> 
> I add it to my watchdog-next branch and Wim will pick it up from there.
> No need to resend.
> 

Ok thanks.

- Sai
diff mbox series

Patch

diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c
index 780971318810..5dfd604477a4 100644
--- a/drivers/watchdog/qcom-wdt.c
+++ b/drivers/watchdog/qcom-wdt.c
@@ -245,6 +245,28 @@  static int qcom_wdt_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static int __maybe_unused qcom_wdt_suspend(struct device *dev)
+{
+	struct qcom_wdt *wdt = dev_get_drvdata(dev);
+
+	if (watchdog_active(&wdt->wdd))
+		qcom_wdt_stop(&wdt->wdd);
+
+	return 0;
+}
+
+static int __maybe_unused qcom_wdt_resume(struct device *dev)
+{
+	struct qcom_wdt *wdt = dev_get_drvdata(dev);
+
+	if (watchdog_active(&wdt->wdd))
+		qcom_wdt_start(&wdt->wdd);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(qcom_wdt_pm_ops, qcom_wdt_suspend, qcom_wdt_resume);
+
 static const struct of_device_id qcom_wdt_of_table[] = {
 	{ .compatible = "qcom,kpss-timer", .data = reg_offset_data_apcs_tmr },
 	{ .compatible = "qcom,scss-timer", .data = reg_offset_data_apcs_tmr },
@@ -259,6 +281,7 @@  static struct platform_driver qcom_watchdog_driver = {
 	.driver	= {
 		.name		= KBUILD_MODNAME,
 		.of_match_table	= qcom_wdt_of_table,
+		.pm		= &qcom_wdt_pm_ops,
 	},
 };
 module_platform_driver(qcom_watchdog_driver);