diff mbox

[3/5] watchdog: sp805: set WDOG_HW_RUNNING when appropriate

Message ID 1527014840-21236-4-git-send-email-ray.jui@broadcom.com (mailing list archive)
State New, archived
Headers show

Commit Message

Ray Jui May 22, 2018, 6:47 p.m. UTC
If the watchdog hardware is already enabled during the boot process,
when the Linux watchdog driver loads, it should reset the watchdog and
tell the watchdog framework. As a result, ping can be generated from
the watchdog framework, until the userspace watchdog daemon takes over
control

Signed-off-by: Ray Jui <ray.jui@broadcom.com>
Reviewed-by: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
Reviewed-by: Scott Branden <scott.branden@broadcom.com>
---
 drivers/watchdog/sp805_wdt.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

Comments

Guenter Roeck May 22, 2018, 8:54 p.m. UTC | #1
On Tue, May 22, 2018 at 11:47:18AM -0700, Ray Jui wrote:
> If the watchdog hardware is already enabled during the boot process,
> when the Linux watchdog driver loads, it should reset the watchdog and
> tell the watchdog framework. As a result, ping can be generated from
> the watchdog framework, until the userspace watchdog daemon takes over
> control
> 
> Signed-off-by: Ray Jui <ray.jui@broadcom.com>
> Reviewed-by: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
> Reviewed-by: Scott Branden <scott.branden@broadcom.com>
> ---
>  drivers/watchdog/sp805_wdt.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
> index 1484609..408ffbe 100644
> --- a/drivers/watchdog/sp805_wdt.c
> +++ b/drivers/watchdog/sp805_wdt.c
> @@ -42,6 +42,7 @@
>  	/* control register masks */
>  	#define	INT_ENABLE	(1 << 0)
>  	#define	RESET_ENABLE	(1 << 1)
> +	#define	ENABLE_MASK	(INT_ENABLE | RESET_ENABLE)
>  #define WDTINTCLR		0x00C
>  #define WDTRIS			0x010
>  #define WDTMIS			0x014
> @@ -74,6 +75,18 @@ module_param(nowayout, bool, 0);
>  MODULE_PARM_DESC(nowayout,
>  		"Set to 1 to keep watchdog running after device release");
>  
> +/* returns true if wdt is running; otherwise returns false */
> +static bool wdt_is_running(struct watchdog_device *wdd)
> +{
> +	struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
> +
> +	if ((readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK) ==
> +	    ENABLE_MASK)
> +		return true;
> +	else
> +		return false;

	return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));

> +}
> +
>  /* This routine finds load value that will reset system in required timout */
>  static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout)
>  {
> @@ -239,6 +252,15 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
>  	watchdog_init_timeout(&wdt->wdd, 0, &adev->dev);
>  	wdt_setload(&wdt->wdd, wdt->wdd.timeout);
>  
> +	/*
> +	 * If HW is already running, enable/reset the wdt and set the running
> +	 * bit to tell the wdt subsystem
> +	 */
> +	if (wdt_is_running(&wdt->wdd)) {
> +		wdt_enable(&wdt->wdd);
> +		set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
> +	}
> +
>  	ret = watchdog_register_device(&wdt->wdd);
>  	if (ret) {
>  		dev_err(&adev->dev, "watchdog_register_device() failed: %d\n",
> -- 
> 2.1.4
>
Ray Jui May 22, 2018, 11:24 p.m. UTC | #2
Hi Guenter,

On 5/22/2018 1:54 PM, Guenter Roeck wrote:
> On Tue, May 22, 2018 at 11:47:18AM -0700, Ray Jui wrote:
>> If the watchdog hardware is already enabled during the boot process,
>> when the Linux watchdog driver loads, it should reset the watchdog and
>> tell the watchdog framework. As a result, ping can be generated from
>> the watchdog framework, until the userspace watchdog daemon takes over
>> control
>>
>> Signed-off-by: Ray Jui <ray.jui@broadcom.com>
>> Reviewed-by: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
>> Reviewed-by: Scott Branden <scott.branden@broadcom.com>
>> ---
>>   drivers/watchdog/sp805_wdt.c | 22 ++++++++++++++++++++++
>>   1 file changed, 22 insertions(+)
>>
>> diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
>> index 1484609..408ffbe 100644
>> --- a/drivers/watchdog/sp805_wdt.c
>> +++ b/drivers/watchdog/sp805_wdt.c
>> @@ -42,6 +42,7 @@
>>   	/* control register masks */
>>   	#define	INT_ENABLE	(1 << 0)
>>   	#define	RESET_ENABLE	(1 << 1)
>> +	#define	ENABLE_MASK	(INT_ENABLE | RESET_ENABLE)
>>   #define WDTINTCLR		0x00C
>>   #define WDTRIS			0x010
>>   #define WDTMIS			0x014
>> @@ -74,6 +75,18 @@ module_param(nowayout, bool, 0);
>>   MODULE_PARM_DESC(nowayout,
>>   		"Set to 1 to keep watchdog running after device release");
>>   
>> +/* returns true if wdt is running; otherwise returns false */
>> +static bool wdt_is_running(struct watchdog_device *wdd)
>> +{
>> +	struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
>> +
>> +	if ((readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK) ==
>> +	    ENABLE_MASK)
>> +		return true;
>> +	else
>> +		return false;
> 
> 	return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));
> 

Note ENABLE_MASK contains two bits (INT_ENABLE and RESET_ENABLE); 
therefore, a simple !!(expression) would not work? That is, the masked 
result needs to be compared against the mask again to ensure both bits 
are set, right?

Thanks,

Ray
Scott Branden May 23, 2018, 7:52 a.m. UTC | #3
On 18-05-22 04:24 PM, Ray Jui wrote:
> Hi Guenter,
>
> On 5/22/2018 1:54 PM, Guenter Roeck wrote:
>> On Tue, May 22, 2018 at 11:47:18AM -0700, Ray Jui wrote:
>>> If the watchdog hardware is already enabled during the boot process,
>>> when the Linux watchdog driver loads, it should reset the watchdog and
>>> tell the watchdog framework. As a result, ping can be generated from
>>> the watchdog framework, until the userspace watchdog daemon takes over
>>> control
>>>
>>> Signed-off-by: Ray Jui <ray.jui@broadcom.com>
>>> Reviewed-by: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
>>> Reviewed-by: Scott Branden <scott.branden@broadcom.com>
>>> ---
>>>   drivers/watchdog/sp805_wdt.c | 22 ++++++++++++++++++++++
>>>   1 file changed, 22 insertions(+)
>>>
>>> diff --git a/drivers/watchdog/sp805_wdt.c 
>>> b/drivers/watchdog/sp805_wdt.c
>>> index 1484609..408ffbe 100644
>>> --- a/drivers/watchdog/sp805_wdt.c
>>> +++ b/drivers/watchdog/sp805_wdt.c
>>> @@ -42,6 +42,7 @@
>>>       /* control register masks */
>>>       #define    INT_ENABLE    (1 << 0)
>>>       #define    RESET_ENABLE    (1 << 1)
>>> +    #define    ENABLE_MASK    (INT_ENABLE | RESET_ENABLE)
>>>   #define WDTINTCLR        0x00C
>>>   #define WDTRIS            0x010
>>>   #define WDTMIS            0x014
>>> @@ -74,6 +75,18 @@ module_param(nowayout, bool, 0);
>>>   MODULE_PARM_DESC(nowayout,
>>>           "Set to 1 to keep watchdog running after device release");
>>>   +/* returns true if wdt is running; otherwise returns false */
>>> +static bool wdt_is_running(struct watchdog_device *wdd)
>>> +{
>>> +    struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
>>> +
>>> +    if ((readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK) ==
>>> +        ENABLE_MASK)
>>> +        return true;
>>> +    else
>>> +        return false;
>>
>>     return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));
>>
>
> Note ENABLE_MASK contains two bits (INT_ENABLE and RESET_ENABLE); 
> therefore, a simple !!(expression) would not work? That is, the masked 
> result needs to be compared against the mask again to ensure both bits 
> are set, right?
Ray - your original code looks correct to me.  Easier to read and less 
prone to errors as shown in the attempted translation to a single statement.
>
> Thanks,
>
> Ray
Robin Murphy May 23, 2018, 11:48 a.m. UTC | #4
On 23/05/18 08:52, Scott Branden wrote:
> 
> 
> On 18-05-22 04:24 PM, Ray Jui wrote:
>> Hi Guenter,
>>
>> On 5/22/2018 1:54 PM, Guenter Roeck wrote:
>>> On Tue, May 22, 2018 at 11:47:18AM -0700, Ray Jui wrote:
>>>> If the watchdog hardware is already enabled during the boot process,
>>>> when the Linux watchdog driver loads, it should reset the watchdog and
>>>> tell the watchdog framework. As a result, ping can be generated from
>>>> the watchdog framework, until the userspace watchdog daemon takes over
>>>> control
>>>>
>>>> Signed-off-by: Ray Jui <ray.jui@broadcom.com>
>>>> Reviewed-by: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
>>>> Reviewed-by: Scott Branden <scott.branden@broadcom.com>
>>>> ---
>>>>   drivers/watchdog/sp805_wdt.c | 22 ++++++++++++++++++++++
>>>>   1 file changed, 22 insertions(+)
>>>>
>>>> diff --git a/drivers/watchdog/sp805_wdt.c 
>>>> b/drivers/watchdog/sp805_wdt.c
>>>> index 1484609..408ffbe 100644
>>>> --- a/drivers/watchdog/sp805_wdt.c
>>>> +++ b/drivers/watchdog/sp805_wdt.c
>>>> @@ -42,6 +42,7 @@
>>>>       /* control register masks */
>>>>       #define    INT_ENABLE    (1 << 0)
>>>>       #define    RESET_ENABLE    (1 << 1)
>>>> +    #define    ENABLE_MASK    (INT_ENABLE | RESET_ENABLE)
>>>>   #define WDTINTCLR        0x00C
>>>>   #define WDTRIS            0x010
>>>>   #define WDTMIS            0x014
>>>> @@ -74,6 +75,18 @@ module_param(nowayout, bool, 0);
>>>>   MODULE_PARM_DESC(nowayout,
>>>>           "Set to 1 to keep watchdog running after device release");
>>>>   +/* returns true if wdt is running; otherwise returns false */
>>>> +static bool wdt_is_running(struct watchdog_device *wdd)
>>>> +{
>>>> +    struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
>>>> +
>>>> +    if ((readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK) ==
>>>> +        ENABLE_MASK)
>>>> +        return true;
>>>> +    else
>>>> +        return false;
>>>
>>>     return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));
>>>
>>
>> Note ENABLE_MASK contains two bits (INT_ENABLE and RESET_ENABLE); 
>> therefore, a simple !!(expression) would not work? That is, the masked 
>> result needs to be compared against the mask again to ensure both bits 
>> are set, right?
> Ray - your original code looks correct to me.  Easier to read and less 
> prone to errors as shown in the attempted translation to a single 
> statement.

	if (<boolean condition>)
		return true;
	else
		return false;

still looks really dumb, though, and IMO is actually harder to read than 
just "return <boolean condition>;" because it forces you to stop and 
double-check that the logic is, in fact, only doing the obvious thing.

Robin.



p.s. No thanks for making me remember the mind-boggling horror of 
briefly maintaining part of this legacy codebase... :P

$ grep -r '? true : false' --include=*.cpp . | wc -l
951
Ray Jui May 23, 2018, 4:29 p.m. UTC | #5
Hi Robin,

On 5/23/2018 4:48 AM, Robin Murphy wrote:
> On 23/05/18 08:52, Scott Branden wrote:
>>
>>
>> On 18-05-22 04:24 PM, Ray Jui wrote:
>>> Hi Guenter,
>>>
>>> On 5/22/2018 1:54 PM, Guenter Roeck wrote:
>>>> On Tue, May 22, 2018 at 11:47:18AM -0700, Ray Jui wrote:
>>>>> If the watchdog hardware is already enabled during the boot process,
>>>>> when the Linux watchdog driver loads, it should reset the watchdog and
>>>>> tell the watchdog framework. As a result, ping can be generated from
>>>>> the watchdog framework, until the userspace watchdog daemon takes over
>>>>> control
>>>>>
>>>>> Signed-off-by: Ray Jui <ray.jui@broadcom.com>
>>>>> Reviewed-by: Vladimir Olovyannikov 
>>>>> <vladimir.olovyannikov@broadcom.com>
>>>>> Reviewed-by: Scott Branden <scott.branden@broadcom.com>
>>>>> ---
>>>>>   drivers/watchdog/sp805_wdt.c | 22 ++++++++++++++++++++++
>>>>>   1 file changed, 22 insertions(+)
>>>>>
>>>>> diff --git a/drivers/watchdog/sp805_wdt.c 
>>>>> b/drivers/watchdog/sp805_wdt.c
>>>>> index 1484609..408ffbe 100644
>>>>> --- a/drivers/watchdog/sp805_wdt.c
>>>>> +++ b/drivers/watchdog/sp805_wdt.c
>>>>> @@ -42,6 +42,7 @@
>>>>>       /* control register masks */
>>>>>       #define    INT_ENABLE    (1 << 0)
>>>>>       #define    RESET_ENABLE    (1 << 1)
>>>>> +    #define    ENABLE_MASK    (INT_ENABLE | RESET_ENABLE)
>>>>>   #define WDTINTCLR        0x00C
>>>>>   #define WDTRIS            0x010
>>>>>   #define WDTMIS            0x014
>>>>> @@ -74,6 +75,18 @@ module_param(nowayout, bool, 0);
>>>>>   MODULE_PARM_DESC(nowayout,
>>>>>           "Set to 1 to keep watchdog running after device release");
>>>>>   +/* returns true if wdt is running; otherwise returns false */
>>>>> +static bool wdt_is_running(struct watchdog_device *wdd)
>>>>> +{
>>>>> +    struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
>>>>> +
>>>>> +    if ((readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK) ==
>>>>> +        ENABLE_MASK)
>>>>> +        return true;
>>>>> +    else
>>>>> +        return false;
>>>>
>>>>     return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));
>>>>
>>>
>>> Note ENABLE_MASK contains two bits (INT_ENABLE and RESET_ENABLE); 
>>> therefore, a simple !!(expression) would not work? That is, the 
>>> masked result needs to be compared against the mask again to ensure 
>>> both bits are set, right?
>> Ray - your original code looks correct to me.  Easier to read and less 
>> prone to errors as shown in the attempted translation to a single 
>> statement.
> 
>      if (<boolean condition>)
>          return true;
>      else
>          return false;
> 
> still looks really dumb, though, and IMO is actually harder to read than 
> just "return <boolean condition>;" because it forces you to stop and 
> double-check that the logic is, in fact, only doing the obvious thing.

If you can propose a way to modify my original code above to make it 
more readable, I'm fine to make the change.

As I mentioned, I don't think the following change proposed by Guenter 
will work due to the reason I pointed out:

return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));

> 
> Robin.
> 
> 
> 
> p.s. No thanks for making me remember the mind-boggling horror of 
> briefly maintaining part of this legacy codebase... :P
> 
> $ grep -r '? true : false' --include=*.cpp . | wc -l
> 951
Robin Murphy May 23, 2018, 5:15 p.m. UTC | #6
On 23/05/18 17:29, Ray Jui wrote:
> Hi Robin,
> 
> On 5/23/2018 4:48 AM, Robin Murphy wrote:
>> On 23/05/18 08:52, Scott Branden wrote:
>>>
>>>
>>> On 18-05-22 04:24 PM, Ray Jui wrote:
>>>> Hi Guenter,
>>>>
>>>> On 5/22/2018 1:54 PM, Guenter Roeck wrote:
>>>>> On Tue, May 22, 2018 at 11:47:18AM -0700, Ray Jui wrote:
>>>>>> If the watchdog hardware is already enabled during the boot process,
>>>>>> when the Linux watchdog driver loads, it should reset the watchdog 
>>>>>> and
>>>>>> tell the watchdog framework. As a result, ping can be generated from
>>>>>> the watchdog framework, until the userspace watchdog daemon takes 
>>>>>> over
>>>>>> control
>>>>>>
>>>>>> Signed-off-by: Ray Jui <ray.jui@broadcom.com>
>>>>>> Reviewed-by: Vladimir Olovyannikov 
>>>>>> <vladimir.olovyannikov@broadcom.com>
>>>>>> Reviewed-by: Scott Branden <scott.branden@broadcom.com>
>>>>>> ---
>>>>>>   drivers/watchdog/sp805_wdt.c | 22 ++++++++++++++++++++++
>>>>>>   1 file changed, 22 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/watchdog/sp805_wdt.c 
>>>>>> b/drivers/watchdog/sp805_wdt.c
>>>>>> index 1484609..408ffbe 100644
>>>>>> --- a/drivers/watchdog/sp805_wdt.c
>>>>>> +++ b/drivers/watchdog/sp805_wdt.c
>>>>>> @@ -42,6 +42,7 @@
>>>>>>       /* control register masks */
>>>>>>       #define    INT_ENABLE    (1 << 0)
>>>>>>       #define    RESET_ENABLE    (1 << 1)
>>>>>> +    #define    ENABLE_MASK    (INT_ENABLE | RESET_ENABLE)
>>>>>>   #define WDTINTCLR        0x00C
>>>>>>   #define WDTRIS            0x010
>>>>>>   #define WDTMIS            0x014
>>>>>> @@ -74,6 +75,18 @@ module_param(nowayout, bool, 0);
>>>>>>   MODULE_PARM_DESC(nowayout,
>>>>>>           "Set to 1 to keep watchdog running after device release");
>>>>>>   +/* returns true if wdt is running; otherwise returns false */
>>>>>> +static bool wdt_is_running(struct watchdog_device *wdd)
>>>>>> +{
>>>>>> +    struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
>>>>>> +
>>>>>> +    if ((readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK) ==
>>>>>> +        ENABLE_MASK)
>>>>>> +        return true;
>>>>>> +    else
>>>>>> +        return false;
>>>>>
>>>>>     return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));
>>>>>
>>>>
>>>> Note ENABLE_MASK contains two bits (INT_ENABLE and RESET_ENABLE); 
>>>> therefore, a simple !!(expression) would not work? That is, the 
>>>> masked result needs to be compared against the mask again to ensure 
>>>> both bits are set, right?
>>> Ray - your original code looks correct to me.  Easier to read and 
>>> less prone to errors as shown in the attempted translation to a 
>>> single statement.
>>
>>      if (<boolean condition>)
>>          return true;
>>      else
>>          return false;
>>
>> still looks really dumb, though, and IMO is actually harder to read 
>> than just "return <boolean condition>;" because it forces you to stop 
>> and double-check that the logic is, in fact, only doing the obvious 
>> thing.
> 
> If you can propose a way to modify my original code above to make it 
> more readable, I'm fine to make the change.

Well,

	return readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK == ENABLE_MASK;

would probably be reasonable to anyone other than the 80-column zealots, 
but removing the silly boolean-to-boolean translation idiom really only 
emphasises the fact that it's fundamentally a big complex statement; for 
maximum clarity I'd be inclined to separate the two logical operations 
(read and comparison), e.g.:

	u32 wdtcontrol = readl_relaxed(wdt->base + WDTCONTROL);

	return wdtcontrol & ENABLE_MASK == ENABLE_MASK;

which is still -3 lines vs. the original.

> As I mentioned, I don't think the following change proposed by Guenter 
> will work due to the reason I pointed out:
> 
> return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));

FWIW, getting the desired result should only need one logical not 
swapping for a bitwise one there:

	return !(~readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK);

but that's well into "too clever for its own good" territory ;)

Robin.
Scott Branden May 23, 2018, 5:15 p.m. UTC | #7
Raym


On 18-05-23 09:29 AM, Ray Jui wrote:
> Hi Robin,
>
> On 5/23/2018 4:48 AM, Robin Murphy wrote:
>> On 23/05/18 08:52, Scott Branden wrote:
>>>
>>>
>>> On 18-05-22 04:24 PM, Ray Jui wrote:
>>>> Hi Guenter,
>>>>
>>>> On 5/22/2018 1:54 PM, Guenter Roeck wrote:
>>>>> On Tue, May 22, 2018 at 11:47:18AM -0700, Ray Jui wrote:
>>>>>> If the watchdog hardware is already enabled during the boot process,
>>>>>> when the Linux watchdog driver loads, it should reset the 
>>>>>> watchdog and
>>>>>> tell the watchdog framework. As a result, ping can be generated from
>>>>>> the watchdog framework, until the userspace watchdog daemon takes 
>>>>>> over
>>>>>> control
>>>>>>
>>>>>> Signed-off-by: Ray Jui <ray.jui@broadcom.com>
>>>>>> Reviewed-by: Vladimir Olovyannikov 
>>>>>> <vladimir.olovyannikov@broadcom.com>
>>>>>> Reviewed-by: Scott Branden <scott.branden@broadcom.com>
>>>>>> ---
>>>>>>   drivers/watchdog/sp805_wdt.c | 22 ++++++++++++++++++++++
>>>>>>   1 file changed, 22 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/watchdog/sp805_wdt.c 
>>>>>> b/drivers/watchdog/sp805_wdt.c
>>>>>> index 1484609..408ffbe 100644
>>>>>> --- a/drivers/watchdog/sp805_wdt.c
>>>>>> +++ b/drivers/watchdog/sp805_wdt.c
>>>>>> @@ -42,6 +42,7 @@
>>>>>>       /* control register masks */
>>>>>>       #define    INT_ENABLE    (1 << 0)
>>>>>>       #define    RESET_ENABLE    (1 << 1)
>>>>>> +    #define    ENABLE_MASK    (INT_ENABLE | RESET_ENABLE)
>>>>>>   #define WDTINTCLR        0x00C
>>>>>>   #define WDTRIS            0x010
>>>>>>   #define WDTMIS            0x014
>>>>>> @@ -74,6 +75,18 @@ module_param(nowayout, bool, 0);
>>>>>>   MODULE_PARM_DESC(nowayout,
>>>>>>           "Set to 1 to keep watchdog running after device release");
>>>>>>   +/* returns true if wdt is running; otherwise returns false */
>>>>>> +static bool wdt_is_running(struct watchdog_device *wdd)
>>>>>> +{
>>>>>> +    struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
>>>>>> +
>>>>>> +    if ((readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK) ==
>>>>>> +        ENABLE_MASK)
>>>>>> +        return true;
>>>>>> +    else
>>>>>> +        return false;
>>>>>
>>>>>     return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));
>>>>>
>>>>
>>>> Note ENABLE_MASK contains two bits (INT_ENABLE and RESET_ENABLE); 
>>>> therefore, a simple !!(expression) would not work? That is, the 
>>>> masked result needs to be compared against the mask again to ensure 
>>>> both bits are set, right?
>>> Ray - your original code looks correct to me.  Easier to read and 
>>> less prone to errors as shown in the attempted translation to a 
>>> single statement.
>>
>>      if (<boolean condition>)
>>          return true;
>>      else
>>          return false;
>>
>> still looks really dumb, though, and IMO is actually harder to read 
>> than just "return <boolean condition>;" because it forces you to stop 
>> and double-check that the logic is, in fact, only doing the obvious 
>> thing.
>
> If you can propose a way to modify my original code above to make it 
> more readable, I'm fine to make the change.
>
> As I mentioned, I don't think the following change proposed by Guenter 
> will work due to the reason I pointed out:
>
> return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));
What they are looking for is:
return ((readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK) == 
ENABLE_MASK);

or maybe:
return !!((readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK) == 
ENABLE_MASK);
>
>>
>> Robin.
>>
>>
>>
>> p.s. No thanks for making me remember the mind-boggling horror of 
>> briefly maintaining part of this legacy codebase... :P
>>
>> $ grep -r '? true : false' --include=*.cpp . | wc -l
>> 951
Guenter Roeck May 23, 2018, 6:06 p.m. UTC | #8
On Wed, May 23, 2018 at 12:48:10PM +0100, Robin Murphy wrote:
> On 23/05/18 08:52, Scott Branden wrote:
> >
> >
> >On 18-05-22 04:24 PM, Ray Jui wrote:
> >>Hi Guenter,
> >>
> >>On 5/22/2018 1:54 PM, Guenter Roeck wrote:
> >>>On Tue, May 22, 2018 at 11:47:18AM -0700, Ray Jui wrote:
> >>>>If the watchdog hardware is already enabled during the boot process,
> >>>>when the Linux watchdog driver loads, it should reset the watchdog and
> >>>>tell the watchdog framework. As a result, ping can be generated from
> >>>>the watchdog framework, until the userspace watchdog daemon takes over
> >>>>control
> >>>>
> >>>>Signed-off-by: Ray Jui <ray.jui@broadcom.com>
> >>>>Reviewed-by: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
> >>>>Reviewed-by: Scott Branden <scott.branden@broadcom.com>
> >>>>---
> >>>>  drivers/watchdog/sp805_wdt.c | 22 ++++++++++++++++++++++
> >>>>  1 file changed, 22 insertions(+)
> >>>>
> >>>>diff --git a/drivers/watchdog/sp805_wdt.c
> >>>>b/drivers/watchdog/sp805_wdt.c
> >>>>index 1484609..408ffbe 100644
> >>>>--- a/drivers/watchdog/sp805_wdt.c
> >>>>+++ b/drivers/watchdog/sp805_wdt.c
> >>>>@@ -42,6 +42,7 @@
> >>>>      /* control register masks */
> >>>>      #define    INT_ENABLE    (1 << 0)
> >>>>      #define    RESET_ENABLE    (1 << 1)
> >>>>+    #define    ENABLE_MASK    (INT_ENABLE | RESET_ENABLE)
> >>>>  #define WDTINTCLR        0x00C
> >>>>  #define WDTRIS            0x010
> >>>>  #define WDTMIS            0x014
> >>>>@@ -74,6 +75,18 @@ module_param(nowayout, bool, 0);
> >>>>  MODULE_PARM_DESC(nowayout,
> >>>>          "Set to 1 to keep watchdog running after device release");
> >>>>  +/* returns true if wdt is running; otherwise returns false */
> >>>>+static bool wdt_is_running(struct watchdog_device *wdd)
> >>>>+{
> >>>>+    struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
> >>>>+
> >>>>+    if ((readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK) ==
> >>>>+        ENABLE_MASK)
> >>>>+        return true;
> >>>>+    else
> >>>>+        return false;
> >>>
> >>>    return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));
> >>>
> >>
> >>Note ENABLE_MASK contains two bits (INT_ENABLE and RESET_ENABLE);
> >>therefore, a simple !!(expression) would not work? That is, the masked
> >>result needs to be compared against the mask again to ensure both bits
> >>are set, right?
> >Ray - your original code looks correct to me.  Easier to read and less
> >prone to errors as shown in the attempted translation to a single
> >statement.
> 
> 	if (<boolean condition>)
> 		return true;
> 	else
> 		return false;
> 
> still looks really dumb, though, and IMO is actually harder to read than
> just "return <boolean condition>;" because it forces you to stop and
> double-check that the logic is, in fact, only doing the obvious thing.
> 

Yes, and I won't accept it, sorry.

Guenter

> Robin.
> 
> 
> 
> p.s. No thanks for making me remember the mind-boggling horror of briefly
> maintaining part of this legacy codebase... :P
> 
> $ grep -r '? true : false' --include=*.cpp . | wc -l
> 951
Guenter Roeck May 23, 2018, 6:09 p.m. UTC | #9
On Wed, May 23, 2018 at 06:15:14PM +0100, Robin Murphy wrote:
> On 23/05/18 17:29, Ray Jui wrote:
> >Hi Robin,
> >
> >On 5/23/2018 4:48 AM, Robin Murphy wrote:
> >>On 23/05/18 08:52, Scott Branden wrote:
> >>>
> >>>
> >>>On 18-05-22 04:24 PM, Ray Jui wrote:
> >>>>Hi Guenter,
> >>>>
> >>>>On 5/22/2018 1:54 PM, Guenter Roeck wrote:
> >>>>>On Tue, May 22, 2018 at 11:47:18AM -0700, Ray Jui wrote:
> >>>>>>If the watchdog hardware is already enabled during the boot process,
> >>>>>>when the Linux watchdog driver loads, it should reset the
> >>>>>>watchdog and
> >>>>>>tell the watchdog framework. As a result, ping can be generated from
> >>>>>>the watchdog framework, until the userspace watchdog daemon
> >>>>>>takes over
> >>>>>>control
> >>>>>>
> >>>>>>Signed-off-by: Ray Jui <ray.jui@broadcom.com>
> >>>>>>Reviewed-by: Vladimir Olovyannikov
> >>>>>><vladimir.olovyannikov@broadcom.com>
> >>>>>>Reviewed-by: Scott Branden <scott.branden@broadcom.com>
> >>>>>>---
> >>>>>>  drivers/watchdog/sp805_wdt.c | 22 ++++++++++++++++++++++
> >>>>>>  1 file changed, 22 insertions(+)
> >>>>>>
> >>>>>>diff --git a/drivers/watchdog/sp805_wdt.c
> >>>>>>b/drivers/watchdog/sp805_wdt.c
> >>>>>>index 1484609..408ffbe 100644
> >>>>>>--- a/drivers/watchdog/sp805_wdt.c
> >>>>>>+++ b/drivers/watchdog/sp805_wdt.c
> >>>>>>@@ -42,6 +42,7 @@
> >>>>>>      /* control register masks */
> >>>>>>      #define    INT_ENABLE    (1 << 0)
> >>>>>>      #define    RESET_ENABLE    (1 << 1)
> >>>>>>+    #define    ENABLE_MASK    (INT_ENABLE | RESET_ENABLE)
> >>>>>>  #define WDTINTCLR        0x00C
> >>>>>>  #define WDTRIS            0x010
> >>>>>>  #define WDTMIS            0x014
> >>>>>>@@ -74,6 +75,18 @@ module_param(nowayout, bool, 0);
> >>>>>>  MODULE_PARM_DESC(nowayout,
> >>>>>>          "Set to 1 to keep watchdog running after device release");
> >>>>>>  +/* returns true if wdt is running; otherwise returns false */
> >>>>>>+static bool wdt_is_running(struct watchdog_device *wdd)
> >>>>>>+{
> >>>>>>+    struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
> >>>>>>+
> >>>>>>+    if ((readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK) ==
> >>>>>>+        ENABLE_MASK)
> >>>>>>+        return true;
> >>>>>>+    else
> >>>>>>+        return false;
> >>>>>
> >>>>>    return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));
> >>>>>
> >>>>
> >>>>Note ENABLE_MASK contains two bits (INT_ENABLE and RESET_ENABLE);
> >>>>therefore, a simple !!(expression) would not work? That is, the
> >>>>masked result needs to be compared against the mask again to ensure
> >>>>both bits are set, right?
> >>>Ray - your original code looks correct to me.  Easier to read and less
> >>>prone to errors as shown in the attempted translation to a single
> >>>statement.
> >>
> >>     if (<boolean condition>)
> >>         return true;
> >>     else
> >>         return false;
> >>
> >>still looks really dumb, though, and IMO is actually harder to read than
> >>just "return <boolean condition>;" because it forces you to stop and
> >>double-check that the logic is, in fact, only doing the obvious thing.
> >
> >If you can propose a way to modify my original code above to make it more
> >readable, I'm fine to make the change.
> 
> Well,
> 
> 	return readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK == ENABLE_MASK;
> 
> would probably be reasonable to anyone other than the 80-column zealots, but
> removing the silly boolean-to-boolean translation idiom really only
> emphasises the fact that it's fundamentally a big complex statement; for
> maximum clarity I'd be inclined to separate the two logical operations (read
> and comparison), e.g.:
> 
> 	u32 wdtcontrol = readl_relaxed(wdt->base + WDTCONTROL);
> 
> 	return wdtcontrol & ENABLE_MASK == ENABLE_MASK;

== has higher precendence than bitwise &, so this will need ( ),
but otherwise I agree.

> 
> which is still -3 lines vs. the original.
> 
> >As I mentioned, I don't think the following change proposed by Guenter
> >will work due to the reason I pointed out:
> >
> >return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));
> 
> FWIW, getting the desired result should only need one logical not swapping
> for a bitwise one there:
> 
> 	return !(~readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK);
> 
> but that's well into "too clever for its own good" territory ;)

Yes, that would be confusing.

> 
> Robin.
Ray Jui May 23, 2018, 7:35 p.m. UTC | #10
Hi Guenter/Robin,

On 5/23/2018 11:09 AM, Guenter Roeck wrote:
> On Wed, May 23, 2018 at 06:15:14PM +0100, Robin Murphy wrote:
>> On 23/05/18 17:29, Ray Jui wrote:
>>> Hi Robin,
>>>
>>> On 5/23/2018 4:48 AM, Robin Murphy wrote:
>>>> On 23/05/18 08:52, Scott Branden wrote:
>>>>>
>>>>>
>>>>> On 18-05-22 04:24 PM, Ray Jui wrote:
>>>>>> Hi Guenter,
>>>>>>
>>>>>> On 5/22/2018 1:54 PM, Guenter Roeck wrote:
>>>>>>> On Tue, May 22, 2018 at 11:47:18AM -0700, Ray Jui wrote:
>>>>>>>> If the watchdog hardware is already enabled during the boot process,
>>>>>>>> when the Linux watchdog driver loads, it should reset the
>>>>>>>> watchdog and
>>>>>>>> tell the watchdog framework. As a result, ping can be generated from
>>>>>>>> the watchdog framework, until the userspace watchdog daemon
>>>>>>>> takes over
>>>>>>>> control
>>>>>>>>
>>>>>>>> Signed-off-by: Ray Jui <ray.jui@broadcom.com>
>>>>>>>> Reviewed-by: Vladimir Olovyannikov
>>>>>>>> <vladimir.olovyannikov@broadcom.com>
>>>>>>>> Reviewed-by: Scott Branden <scott.branden@broadcom.com>
>>>>>>>> ---
>>>>>>>>    drivers/watchdog/sp805_wdt.c | 22 ++++++++++++++++++++++
>>>>>>>>    1 file changed, 22 insertions(+)
>>>>>>>>
>>>>>>>> diff --git a/drivers/watchdog/sp805_wdt.c
>>>>>>>> b/drivers/watchdog/sp805_wdt.c
>>>>>>>> index 1484609..408ffbe 100644
>>>>>>>> --- a/drivers/watchdog/sp805_wdt.c
>>>>>>>> +++ b/drivers/watchdog/sp805_wdt.c
>>>>>>>> @@ -42,6 +42,7 @@
>>>>>>>>        /* control register masks */
>>>>>>>>        #define    INT_ENABLE    (1 << 0)
>>>>>>>>        #define    RESET_ENABLE    (1 << 1)
>>>>>>>> +    #define    ENABLE_MASK    (INT_ENABLE | RESET_ENABLE)
>>>>>>>>    #define WDTINTCLR        0x00C
>>>>>>>>    #define WDTRIS            0x010
>>>>>>>>    #define WDTMIS            0x014
>>>>>>>> @@ -74,6 +75,18 @@ module_param(nowayout, bool, 0);
>>>>>>>>    MODULE_PARM_DESC(nowayout,
>>>>>>>>            "Set to 1 to keep watchdog running after device release");
>>>>>>>>    +/* returns true if wdt is running; otherwise returns false */
>>>>>>>> +static bool wdt_is_running(struct watchdog_device *wdd)
>>>>>>>> +{
>>>>>>>> +    struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
>>>>>>>> +
>>>>>>>> +    if ((readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK) ==
>>>>>>>> +        ENABLE_MASK)
>>>>>>>> +        return true;
>>>>>>>> +    else
>>>>>>>> +        return false;
>>>>>>>
>>>>>>>      return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));
>>>>>>>
>>>>>>
>>>>>> Note ENABLE_MASK contains two bits (INT_ENABLE and RESET_ENABLE);
>>>>>> therefore, a simple !!(expression) would not work? That is, the
>>>>>> masked result needs to be compared against the mask again to ensure
>>>>>> both bits are set, right?
>>>>> Ray - your original code looks correct to me.  Easier to read and less
>>>>> prone to errors as shown in the attempted translation to a single
>>>>> statement.
>>>>
>>>>       if (<boolean condition>)
>>>>           return true;
>>>>       else
>>>>           return false;
>>>>
>>>> still looks really dumb, though, and IMO is actually harder to read than
>>>> just "return <boolean condition>;" because it forces you to stop and
>>>> double-check that the logic is, in fact, only doing the obvious thing.
>>>
>>> If you can propose a way to modify my original code above to make it more
>>> readable, I'm fine to make the change.
>>
>> Well,
>>
>> 	return readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK == ENABLE_MASK;
>>
>> would probably be reasonable to anyone other than the 80-column zealots, but
>> removing the silly boolean-to-boolean translation idiom really only
>> emphasises the fact that it's fundamentally a big complex statement; for
>> maximum clarity I'd be inclined to separate the two logical operations (read
>> and comparison), e.g.:
>>
>> 	u32 wdtcontrol = readl_relaxed(wdt->base + WDTCONTROL);
>>
>> 	return wdtcontrol & ENABLE_MASK == ENABLE_MASK;
> 
> == has higher precendence than bitwise &, so this will need ( ),
> but otherwise I agree.
> 

Sure. Let me change the code to the following:

       u32 wdtcontrol = readl_relaxed(wdt->base + WDTCONTROL);

       return (wdtcontrol & ENABLE_MASK) == ENABLE_MASK;

Thanks.

Ray

>>
>> which is still -3 lines vs. the original.
>>
>>> As I mentioned, I don't think the following change proposed by Guenter
>>> will work due to the reason I pointed out:
>>>
>>> return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));
>>
>> FWIW, getting the desired result should only need one logical not swapping
>> for a bitwise one there:
>>
>> 	return !(~readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK);
>>
>> but that's well into "too clever for its own good" territory ;)
> 
> Yes, that would be confusing.
> 
>>
>> Robin.
diff mbox

Patch

diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
index 1484609..408ffbe 100644
--- a/drivers/watchdog/sp805_wdt.c
+++ b/drivers/watchdog/sp805_wdt.c
@@ -42,6 +42,7 @@ 
 	/* control register masks */
 	#define	INT_ENABLE	(1 << 0)
 	#define	RESET_ENABLE	(1 << 1)
+	#define	ENABLE_MASK	(INT_ENABLE | RESET_ENABLE)
 #define WDTINTCLR		0x00C
 #define WDTRIS			0x010
 #define WDTMIS			0x014
@@ -74,6 +75,18 @@  module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
 		"Set to 1 to keep watchdog running after device release");
 
+/* returns true if wdt is running; otherwise returns false */
+static bool wdt_is_running(struct watchdog_device *wdd)
+{
+	struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
+
+	if ((readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK) ==
+	    ENABLE_MASK)
+		return true;
+	else
+		return false;
+}
+
 /* This routine finds load value that will reset system in required timout */
 static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout)
 {
@@ -239,6 +252,15 @@  sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
 	watchdog_init_timeout(&wdt->wdd, 0, &adev->dev);
 	wdt_setload(&wdt->wdd, wdt->wdd.timeout);
 
+	/*
+	 * If HW is already running, enable/reset the wdt and set the running
+	 * bit to tell the wdt subsystem
+	 */
+	if (wdt_is_running(&wdt->wdd)) {
+		wdt_enable(&wdt->wdd);
+		set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
+	}
+
 	ret = watchdog_register_device(&wdt->wdd);
 	if (ret) {
 		dev_err(&adev->dev, "watchdog_register_device() failed: %d\n",