diff mbox

[v7,1/6] watchdog: core: dt: add support for the timeout-sec dt property

Message ID 1357639455-21935-2-git-send-email-fabio.porcedda@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Fabio Porcedda Jan. 8, 2013, 10:04 a.m. UTC
Signed-off-by: Fabio Porcedda <fabio.porcedda@gmail.com>
---
 Documentation/watchdog/watchdog-kernel-api.txt | 10 +++++++
 drivers/watchdog/watchdog_core.c               | 37 ++++++++++++++++++++++++++
 include/linux/watchdog.h                       |  3 +++
 3 files changed, 50 insertions(+)

Comments

Fabio Porcedda Feb. 13, 2013, 9:28 a.m. UTC | #1
On Wed, Feb 13, 2013 at 12:03 AM, Wim Van Sebroeck <wim@iguana.be> wrote:
> Hi Fabio,
>
> I must admit that the different iterations of this patch only made it better.
> I like the idea that you are proposing here (put the default timeout in the
> watchdog_device struct and use a helper function to set the timeout parameter
> value or the timeout-sec dt value). To be able to use other mechanism in the
> future also, I think it make more sense to pass the device instead of the
> device_node.

If i understand correctly you want to use "struct platform_device"
instead of "struct device_node",
in the function watchdog_init_timeout?

>> Signed-off-by: Fabio Porcedda <fabio.porcedda@gmail.com>
>> ---
>>  Documentation/watchdog/watchdog-kernel-api.txt | 10 +++++++
>>  drivers/watchdog/watchdog_core.c               | 37 ++++++++++++++++++++++++++
>>  include/linux/watchdog.h                       |  3 +++
>>  3 files changed, 50 insertions(+)
>>
> ...
>>
>> +static bool watchdog_is_valid_timeout(struct watchdog_device *wdd,
>> +                                   unsigned int t)
>> +
>> +{
>> +     if (wdd->min_timeout < wdd->max_timeout)
>> +             return (wdd->min_timeout <= t) && (t <= wdd->max_timeout);
>> +     else
>> +             return (t > 0);
>> +}
>
> We use a similar check allready in watchdog_dev.c in the set_timeout wrapper.
> And we should move this to the watchdog.h include file so that drivers can also
> use the logic if necessary.

Do you prefer that i move or just export that function in watchdog.h?
I think it's better to just export it because the function is
not small enough as inline function, but both solutions are fine to me.

>
>> +/**
>> + * watchdog_init_timeout() - initialize the timeout field
>> + * @parm: timeout module parameter, it takes precedence over the
>> + *        timeout-sec property.
>> + * @node: Retrieve the timeout-sec property only if the parm_timeout
>> + *        is out of bounds.
>> + */
>> +void watchdog_init_timeout(struct watchdog_device *wdd, unsigned int parm,
>> +                        struct device_node *node)
>
> make this int so that drivers can give appropriate warnings if necessary.

In which cases i must return a non zero result?
For a value out of range in parm or node?
Wich value -EINVAL?


> I also detailed your documentation a bit more and incorporated above changes
> in an adjusted patch. Can you have a look at it and if OK for you I will put
> it in linux-watchdog-next as your v10 :-).

That's good for sure :)

> Kind regards,
> Wim.
> ---
> diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
> index 086638f..a0438f3 100644
> --- a/Documentation/watchdog/watchdog-kernel-api.txt
> +++ b/Documentation/watchdog/watchdog-kernel-api.txt
> @@ -1,6 +1,6 @@
>  The Linux WatchDog Timer Driver Core kernel API.
>  ===============================================
> -Last reviewed: 22-May-2012
> +Last reviewed: 12-Feb-2013
>
>  Wim Van Sebroeck <wim@iguana.be>
>
> @@ -212,3 +212,15 @@ driver specific data to and a pointer to the data itself.
>  The watchdog_get_drvdata function allows you to retrieve driver specific data.
>  The argument of this function is the watchdog device where you want to retrieve
>  data from. The function returns the pointer to the driver specific data.
> +
> +To initialize the timeout field, the following function can be used:
> +
> +extern int watchdog_init_timeout(struct watchdog_device *wdd,
> +                                  unsigned int timeout_parm, struct device *dev);
> +
> +The watchdog_init_timeout function allows you to initialize the timeout field
> +using the module timeout parameter or by retrieving the timeout-sec property from
> +the device tree (if the module timeout parameter is invalid). Best practice is
> +to set the default timeout value as timeout value in the watchdog_device and
> +then use this function to set the user "preferred" timeout value.
> +This routine returns zero on success and a negative errno code for failure.
> diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
> index 3796434..a74a3ef 100644
> --- a/drivers/watchdog/watchdog_core.c
> +++ b/drivers/watchdog/watchdog_core.c
> @@ -36,12 +36,62 @@
>  #include <linux/init.h>                /* For __init/__exit/... */
>  #include <linux/idr.h>         /* For ida_* macros */
>  #include <linux/err.h>         /* For IS_ERR macros */
> +#include <linux/of.h>          /* For of_get_timeout_sec */
>
>  #include "watchdog_core.h"     /* For watchdog_dev_register/... */
>
>  static DEFINE_IDA(watchdog_ida);
>  static struct class *watchdog_class;
>
> +void watchdog_check_min_max_timeout(struct watchdog_device *wdd)
> +{
> +       /*
> +        * Check that we have valid min and max timeout values, if
> +        * not reset them both to 0 (=not used or unknown)
> +        */
> +       if (wdd->min_timeout > wdd->max_timeout) {
> +               pr_info("Invalid min and max timeout values, resetting to 0!\n");
> +               wdd->min_timeout = 0;
> +               wdd->max_timeout = 0;
> +       }
> +}
> +
> +/**
> + * watchdog_init_timeout() - initialize the timeout field
> + * @timeout_parm: timeout module parameter
> + * @dev: Device that stores the timeout-sec property
> + *
> + * Initialize the timeout field of the watchdog_device struct with either the
> + * timeout module parameter (if it is valid value) or the timeout-sec property
> + * (only if it is a valid value and the timeout_parm is out of bounds).
> + * If none of them are valid then we keep the old value (which should normally
> + * be the default timeout value.
> + *
> + * A zero is returned on success and -EINVAL for failure.
> + */
> +int watchdog_init_timeout(struct watchdog_device *wdd,
> +                               unsigned int timeout_parm, struct device *dev)
> +{
> +       unsigned int t = 0;
> +
> +       watchdog_check_min_max_timeout(wdd);
> +
> +       /* try to get the tiemout module parameter first */
> +       if (!watchdog_timeout_invalid(wdd, timeout_parm)) {
> +               wdd->timeout = timeout_parm;
> +               return 0;
> +       }
> +
> +       /* try to get the timeout_sec property */
> +       if (dev == NULL || dev->of_node == NULL)
> +               return -EINVAL;
> +       of_property_read_u32(dev->of_node, "timeout-sec", &t);
> +       if (!watchdog_timeout_invalid(wdd, t))
> +               wdd->timeout = t;
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(watchdog_init_timeout);
> +
>  /**
>   * watchdog_register_device() - register a watchdog device
>   * @wdd: watchdog device
> @@ -63,15 +113,7 @@ int watchdog_register_device(struct watchdog_device *wdd)
>         if (wdd->ops->start == NULL || wdd->ops->stop == NULL)
>                 return -EINVAL;
>
> -       /*
> -        * Check that we have valid min and max timeout values, if
> -        * not reset them both to 0 (=not used or unknown)
> -        */
> -       if (wdd->min_timeout > wdd->max_timeout) {
> -               pr_info("Invalid min and max timeout values, resetting to 0!\n");
> -               wdd->min_timeout = 0;
> -               wdd->max_timeout = 0;
> -       }
> +       watchdog_check_min_max_timeout(wdd);
>
>         /*
>          * Note: now that all watchdog_device data has been verified, we
> diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
> index ef8edec..08b48bb 100644
> --- a/drivers/watchdog/watchdog_dev.c
> +++ b/drivers/watchdog/watchdog_dev.c
> @@ -200,8 +200,7 @@ static int watchdog_set_timeout(struct watchdog_device *wddev,
>             !(wddev->info->options & WDIOF_SETTIMEOUT))
>                 return -EOPNOTSUPP;
>
> -       if ((wddev->max_timeout != 0) &&
> -           (timeout < wddev->min_timeout || timeout > wddev->max_timeout))
> +       if (watchdog_timeout_invalid(wddev, timeout))
>                 return -EINVAL;
>
>         mutex_lock(&wddev->lock);
> diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
> index 3a9df2f..2a3038e 100644
> --- a/include/linux/watchdog.h
> +++ b/include/linux/watchdog.h
> @@ -118,6 +118,13 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
>                 set_bit(WDOG_NO_WAY_OUT, &wdd->status);
>  }
>
> +/* Use the following function to check if a timeout value is invalid */
> +static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
> +{
> +       return ((wdd->max_timeout != 0) &&
> +               (t < wdd->min_timeout || t > wdd->max_timeout));
> +}
> +
>  /* Use the following functions to manipulate watchdog driver specific data */
>  static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data)
>  {
> @@ -130,6 +137,8 @@ static inline void *watchdog_get_drvdata(struct watchdog_device *wdd)
>  }
>
>  /* drivers/watchdog/watchdog_core.c */
> +extern int watchdog_init_timeout(struct watchdog_device *wdd,
> +                                 unsigned int timeout_parm, struct device *dev);
>  extern int watchdog_register_device(struct watchdog_device *);
>  extern void watchdog_unregister_device(struct watchdog_device *);
>



--
Fabio Porcedda
Fabio Porcedda Feb. 13, 2013, 10:32 a.m. UTC | #2
On Wed, Feb 13, 2013 at 10:44 AM, Wim Van Sebroeck <wim@iguana.be> wrote:
> Hi Fabio,
>
>> > I must admit that the different iterations of this patch only made it better.
>> > I like the idea that you are proposing here (put the default timeout in the
>> > watchdog_device struct and use a helper function to set the timeout parameter
>> > value or the timeout-sec dt value). To be able to use other mechanism in the
>> > future also, I think it make more sense to pass the device instead of the
>> > device_node.
>>
>> If i understand correctly you want to use "struct platform_device"
>> instead of "struct device_node",
>> in the function watchdog_init_timeout?
>
> No struct device instead of struct device_node.
>
>> > I also detailed your documentation a bit more and incorporated above changes
>> > in an adjusted patch. Can you have a look at it and if OK for you I will put
>> > it in linux-watchdog-next as your v10 :-).
>>
>> That's good for sure :)
>
> Will add it to the linux-watchdog-next tree today.
>

In a few minutes I will send the v8 patch set.

Best regards
--
Fabio Porcedda

> Kind regards,
> Wim.
>
diff mbox

Patch

diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index 086638f..44098c2 100644
--- a/Documentation/watchdog/watchdog-kernel-api.txt
+++ b/Documentation/watchdog/watchdog-kernel-api.txt
@@ -212,3 +212,13 @@  driver specific data to and a pointer to the data itself.
 The watchdog_get_drvdata function allows you to retrieve driver specific data.
 The argument of this function is the watchdog device where you want to retrieve
 data from. The function returns the pointer to the driver specific data.
+
+To initialize the timeout field use the following function:
+
+extern void watchdog_init_timeout(struct watchdog_device *wdd,
+                                  unsigned int parm_timeout,
+                                  struct device_node *node);
+
+The watchdog_init_timeout function allows you to initialize the timeout field
+using the module timeout parameter or retrieving the timeout-sec property from
+the device tree.
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index 3796434..758a285 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -36,12 +36,49 @@ 
 #include <linux/init.h>		/* For __init/__exit/... */
 #include <linux/idr.h>		/* For ida_* macros */
 #include <linux/err.h>		/* For IS_ERR macros */
+#include <linux/of.h>		/* For of_get_timeout_sec */
 
 #include "watchdog_core.h"	/* For watchdog_dev_register/... */
 
 static DEFINE_IDA(watchdog_ida);
 static struct class *watchdog_class;
 
+static bool watchdog_is_valid_timeout(struct watchdog_device *wdd,
+				      unsigned int t)
+
+{
+	if (wdd->min_timeout < wdd->max_timeout)
+		return (wdd->min_timeout <= t) && (t <= wdd->max_timeout);
+	else
+		return (t > 0);
+}
+
+/**
+ * watchdog_init_timeout() - initialize the timeout field
+ * @parm: timeout module parameter, it takes precedence over the
+ *        timeout-sec property.
+ * @node: Retrieve the timeout-sec property only if the parm_timeout
+ *        is out of bounds.
+ */
+void watchdog_init_timeout(struct watchdog_device *wdd, unsigned int parm,
+			   struct device_node *node)
+{
+	unsigned int t = 0;
+
+	if (watchdog_is_valid_timeout(wdd, parm)) {
+		wdd->timeout = parm;
+		return;
+	}
+
+	/* try to get the timeout_sec property */
+	if (!node)
+		return;
+	of_property_read_u32(node, "timeout-sec", &t);
+	if (watchdog_is_valid_timeout(wdd, t))
+		wdd->timeout = t;
+}
+EXPORT_SYMBOL_GPL(watchdog_init_timeout);
+
 /**
  * watchdog_register_device() - register a watchdog device
  * @wdd: watchdog device
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index 3a9df2f..e40cc2b 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -130,6 +130,9 @@  static inline void *watchdog_get_drvdata(struct watchdog_device *wdd)
 }
 
 /* drivers/watchdog/watchdog_core.c */
+extern void watchdog_init_timeout(struct watchdog_device *wdd,
+				  unsigned int parm_timeout,
+				  struct device_node *node);
 extern int watchdog_register_device(struct watchdog_device *);
 extern void watchdog_unregister_device(struct watchdog_device *);