diff mbox series

[RFC] watchdog: renesas_wdt: support handover from bootloader

Message ID 20190415105201.2078-1-wsa+renesas@sang-engineering.com (mailing list archive)
State Changes Requested
Headers show
Series [RFC] watchdog: renesas_wdt: support handover from bootloader | expand

Commit Message

Wolfram Sang April 15, 2019, 10:52 a.m. UTC
Support an already running watchdog by checking its enable bit and set
up the status accordingly before registering the device.

Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---

This patch was tested using a Renesas Salvator XS board (R-Car M3N). It works.
However, there is a small window where the watchdog clock is disabled, namely
after the MSSR clock driver initializes it until RuntimePM of the watchdog
driver takes over. If the system hangs in this window, bad luck. So, I'd think
it makes sense to have this clock either always-on or to keep the state which
came from the firmware. Geert, what do you think?

 drivers/watchdog/renesas_wdt.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

Comments

Guenter Roeck April 17, 2019, 6:05 p.m. UTC | #1
On Mon, Apr 15, 2019 at 12:52:01PM +0200, Wolfram Sang wrote:
> Support an already running watchdog by checking its enable bit and set
> up the status accordingly before registering the device.
> 
> Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
> ---
> 
> This patch was tested using a Renesas Salvator XS board (R-Car M3N). It works.
> However, there is a small window where the watchdog clock is disabled, namely
> after the MSSR clock driver initializes it until RuntimePM of the watchdog
> driver takes over. If the system hangs in this window, bad luck. So, I'd think
> it makes sense to have this clock either always-on or to keep the state which
> came from the firmware. Geert, what do you think?
> 
>  drivers/watchdog/renesas_wdt.c | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/watchdog/renesas_wdt.c b/drivers/watchdog/renesas_wdt.c
> index 565dbc1ec638..37d757288b22 100644
> --- a/drivers/watchdog/renesas_wdt.c
> +++ b/drivers/watchdog/renesas_wdt.c
> @@ -179,6 +179,7 @@ static int rwdt_probe(struct platform_device *pdev)
>  	struct clk *clk;
>  	unsigned long clks_per_sec;
>  	int ret, i;
> +	u8 csra;
>  
>  	if (rwdt_blacklisted(&pdev->dev))
>  		return -ENODEV;
> @@ -198,8 +199,8 @@ static int rwdt_probe(struct platform_device *pdev)
>  	pm_runtime_enable(&pdev->dev);
>  	pm_runtime_get_sync(&pdev->dev);
>  	priv->clk_rate = clk_get_rate(clk);
> -	priv->wdev.bootstatus = (readb_relaxed(priv->base + RWTCSRA) &
> -				RWTCSRA_WOVF) ? WDIOF_CARDRESET : 0;
> +	csra = readb_relaxed(priv->base + RWTCSRA);
> +	priv->wdev.bootstatus = csra & RWTCSRA_WOVF ? WDIOF_CARDRESET : 0;
>  	pm_runtime_put(&pdev->dev);
>  
>  	if (!priv->clk_rate) {
> @@ -237,6 +238,16 @@ static int rwdt_probe(struct platform_device *pdev)
>  	/* This overrides the default timeout only if DT configuration was found */
>  	watchdog_init_timeout(&priv->wdev, 0, &pdev->dev);
>  
> +	if (csra & RWTCSRA_TME) {
> +		/* Ensure properly initialized dividers */
> +		rwdt_start(&priv->wdev);
> +		set_bit(WDOG_HW_RUNNING, &priv->wdev.status);
> +		//FIXME: We are missing pm_runtime_put in some code paths to
> +		// to balance PM calls. We first need to decide if we maybe
> +		// should have the RWDT clock always-on or if using RPM for
> +		// clock management is OK.

Maybe I am missing something, but ..

Is handover even possible if the clock is controlled by clock management ?
Seems to me the clock would then be turned off through pm, which effectively
turns off the watchdog. So it will be off between clock/pm initialization
and the above code, meaning wdt handover from the boot loader is for all
practical purposes useless if the kernel gets stuck in between.

Thanks,
Guenter

> +	}
> +
>  	ret = watchdog_register_device(&priv->wdev);
>  	if (ret < 0)
>  		goto out_pm_disable;
> -- 
> 2.11.0
>
Wolfram Sang April 17, 2019, 7:01 p.m. UTC | #2
Hi Guenter,

> > driver takes over. If the system hangs in this window, bad luck. So, I'd think
> > it makes sense to have this clock either always-on or to keep the state which
> > came from the firmware.

I wrote this paragraph...

> Is handover even possible if the clock is controlled by clock management ?
> Seems to me the clock would then be turned off through pm, which effectively
> turns off the watchdog. So it will be off between clock/pm initialization
> and the above code, meaning wdt handover from the boot loader is for all
> practical purposes useless if the kernel gets stuck in between.

... because I fully agree with you :)
Geert Uytterhoeven May 9, 2019, 7:38 a.m. UTC | #3
Hi Wolfram,

On Mon, Apr 15, 2019 at 12:52 PM Wolfram Sang
<wsa+renesas@sang-engineering.com> wrote:
> Support an already running watchdog by checking its enable bit and set
> up the status accordingly before registering the device.
>
> Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
> ---
>
> This patch was tested using a Renesas Salvator XS board (R-Car M3N). It works.
> However, there is a small window where the watchdog clock is disabled, namely
> after the MSSR clock driver initializes it until RuntimePM of the watchdog
> driver takes over. If the system hangs in this window, bad luck. So, I'd think
> it makes sense to have this clock either always-on or to keep the state which
> came from the firmware. Geert, what do you think?

The MSSR clock driver does not disable the clock. The clock's core
clk_disable_unused() does, which is a late initcall.
So if the handover code calls rwdt_start() before that (i.e. no deferred
probing happens), the clock would never be disabled.

Note that pm_runtime_put() in rwdt_probe() queues a power down request,
but as it is not the _sync variant, it is delayed by some time, so
probably it would never happen if rwdt_start() is called by the handover
code in probe.

Now, if we would mark the clock always-on (CLK_IS_CRITICAL),
we can never disable it, even if the wdt is not used or the driver is
not compiled-in.

I don't think there's a way to mark a clock as "keep the state which
came from the firmware", CLK_IS_CRITICAL enables the clock in
__clk_core_init().

Gr{oetje,eeting}s,

                        Geert
Wolfram Sang May 24, 2019, 1:52 p.m. UTC | #4
On Mon, Apr 15, 2019 at 12:52:01PM +0200, Wolfram Sang wrote:
> Support an already running watchdog by checking its enable bit and set
> up the status accordingly before registering the device.
> 
> Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>

After second thought, I am getting confused a little. If the WDT is
already running then

a) before this patch: after successful probe, RPM will disable the
clock until userspace opens the watchdog device

b) after this patch: during probe, our default timeout will be
programmed and because of WDOG_HW_RUNNING, the core will generate pings
until userspace opens the watchdog device.

So, b) will protect from a crashing kernel (no pings anymore) but not
from something like missing rootfs, or?

The usecase I had in mind ("give the kernel <x> seconds to boot into
working userspace") seems to be achieved by loading the WDT driver as a
module then, I guess?
Guenter Roeck June 7, 2019, 8:41 p.m. UTC | #5
On Fri, May 24, 2019 at 03:52:37PM +0200, Wolfram Sang wrote:
> On Mon, Apr 15, 2019 at 12:52:01PM +0200, Wolfram Sang wrote:
> > Support an already running watchdog by checking its enable bit and set
> > up the status accordingly before registering the device.
> > 
> > Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
> 
> After second thought, I am getting confused a little. If the WDT is
> already running then
> 
> a) before this patch: after successful probe, RPM will disable the
> clock until userspace opens the watchdog device
> 
> b) after this patch: during probe, our default timeout will be
> programmed and because of WDOG_HW_RUNNING, the core will generate pings
> until userspace opens the watchdog device.
> 
> So, b) will protect from a crashing kernel (no pings anymore) but not
> from something like missing rootfs, or?
> 
> The usecase I had in mind ("give the kernel <x> seconds to boot into
> working userspace") seems to be achieved by loading the WDT driver as a
> module then, I guess?
> 

Would
https://lore.kernel.org/linux-watchdog/20190605140628.618-1-rasmus.villemoes@prevas.dk/

solve your use case ?

Guenter
Wolfram Sang June 7, 2019, 8:55 p.m. UTC | #6
> > The usecase I had in mind ("give the kernel <x> seconds to boot into
> > working userspace") seems to be achieved by loading the WDT driver as a
> > module then, I guess?
> > 
> 
> Would
> https://lore.kernel.org/linux-watchdog/20190605140628.618-1-rasmus.villemoes@prevas.dk/
> 
> solve your use case ?

Yes, it would. Thanks for the pointer! I missed the
"handle_boot_enabled" parameter, too, for some reason. I think this
could also be enough for some scenarios.

As a result, it seems it makes sense to respin my patch, and test it
with "handle_boot_enabled" and the patch series you were pointing out.

I'll try to get this done within the next two weeks.

Thanks again!
diff mbox series

Patch

diff --git a/drivers/watchdog/renesas_wdt.c b/drivers/watchdog/renesas_wdt.c
index 565dbc1ec638..37d757288b22 100644
--- a/drivers/watchdog/renesas_wdt.c
+++ b/drivers/watchdog/renesas_wdt.c
@@ -179,6 +179,7 @@  static int rwdt_probe(struct platform_device *pdev)
 	struct clk *clk;
 	unsigned long clks_per_sec;
 	int ret, i;
+	u8 csra;
 
 	if (rwdt_blacklisted(&pdev->dev))
 		return -ENODEV;
@@ -198,8 +199,8 @@  static int rwdt_probe(struct platform_device *pdev)
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_get_sync(&pdev->dev);
 	priv->clk_rate = clk_get_rate(clk);
-	priv->wdev.bootstatus = (readb_relaxed(priv->base + RWTCSRA) &
-				RWTCSRA_WOVF) ? WDIOF_CARDRESET : 0;
+	csra = readb_relaxed(priv->base + RWTCSRA);
+	priv->wdev.bootstatus = csra & RWTCSRA_WOVF ? WDIOF_CARDRESET : 0;
 	pm_runtime_put(&pdev->dev);
 
 	if (!priv->clk_rate) {
@@ -237,6 +238,16 @@  static int rwdt_probe(struct platform_device *pdev)
 	/* This overrides the default timeout only if DT configuration was found */
 	watchdog_init_timeout(&priv->wdev, 0, &pdev->dev);
 
+	if (csra & RWTCSRA_TME) {
+		/* Ensure properly initialized dividers */
+		rwdt_start(&priv->wdev);
+		set_bit(WDOG_HW_RUNNING, &priv->wdev.status);
+		//FIXME: We are missing pm_runtime_put in some code paths to
+		// to balance PM calls. We first need to decide if we maybe
+		// should have the RWDT clock always-on or if using RPM for
+		// clock management is OK.
+	}
+
 	ret = watchdog_register_device(&priv->wdev);
 	if (ret < 0)
 		goto out_pm_disable;