2015-05-21 08:33:19

by Fu Wei

[permalink] [raw]
Subject: [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver

From: Fu Wei <[email protected]>

This patchset:

(1)Export "arch_timer_get_rate" in arm_arch_timer.c for the
other drivers, like SBSA watchdog driver

(2)Introduce Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
for FDT info of SBSA Generic Watchdog, and give two examples of
adding SBSA Generic Watchdog device node into the dts files:
foundation-v8.dts and amd-seattle-soc.dtsi.

(3)Introduce "pretimeout" into the watchdog framework, and update
Documentation/watchdog/watchdog-kernel-api.txt to introduce:
(1)the new elements in the watchdog_device and watchdog_ops struct;
(2)the new API "watchdog_init_timeouts".

(4)Introduce ARM SBSA watchdog driver:
a.Use linux kernel watchdog framework;
b.Work with FDT on ARM64;
c.Use "pretimeout" in watchdog framework;
d.In first timeout(WS0), do panic to save system context;
e.Support geting timeout and pretimeout from parameter and FDT
at the driver init stage.

(5)Parse SBSA Generic Watchdog Structure in GTDT table of ACPI,
and create a platform device with that information.
This platform device can be used by This Watchdog driver.

This patchset has been tested with watchdog daemon
(ACPI/FDT, module/build-in) on the following platforms:
(1)ARM Foundation v8 model
(2)AMD Seattle B0

Changelog:
v2: Improve watchdog-kernel-api.txt documentation for pretimeout support.
Export "arch_timer_get_rate" in arm_arch_timer.c.
Add watchdog_init_timeouts API for pretimeout support in framework.
Improve suspend and resume foundation in driver
Improve timeout/pretimeout values init code in driver.
Delete unnecessary items of the sbsa_gwdt struct and #define.
Delete all unnecessary debug info in driver.
Fix 64bit division bug.
Use the arch_timer interface to get watchdog clock rate.
Add MODULE_DEVICE_TABLE for platform device id.
Fix typoes.

v1: The first version upstream patchset to linux mailing list

Fu Wei (7):
clocksource: export "arch_timer_get_rate" for the other drivers
Documentation: add sbsa-gwdt.txt documentation
ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
Watchdog: introduce "pretimeout" into framework
Watchdog: introduce ARM SBSA watchdog driver
ACPI: import watchdog info of GTDT into platform device

.../devicetree/bindings/watchdog/sbsa-gwdt.txt | 36 ++
Documentation/watchdog/watchdog-kernel-api.txt | 62 ++-
arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi | 11 +
arch/arm64/boot/dts/arm/foundation-v8.dts | 10 +
arch/arm64/kernel/acpi.c | 136 ++++++
drivers/clocksource/arm_arch_timer.c | 1 +
drivers/watchdog/Kconfig | 12 +
drivers/watchdog/Makefile | 1 +
drivers/watchdog/sbsa_gwdt.c | 476 +++++++++++++++++++++
drivers/watchdog/watchdog_core.c | 103 +++--
drivers/watchdog/watchdog_dev.c | 48 +++
include/linux/watchdog.h | 30 +-
12 files changed, 891 insertions(+), 35 deletions(-)
create mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
create mode 100644 drivers/watchdog/sbsa_gwdt.c

--
1.9.1


2015-05-21 08:33:28

by Fu Wei

[permalink] [raw]
Subject: [PATCH v2 1/7] clocksource: export "arch_timer_get_rate" for the other drivers

From: Fu Wei <[email protected]>

Some devices get clock from system counter, like SBSA watchdog
driver. They may need to get system counter rate.

Signed-off-by: Fu Wei <[email protected]>
---
drivers/clocksource/arm_arch_timer.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 0aa135d..4327bf9 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -410,6 +410,7 @@ u32 arch_timer_get_rate(void)
{
return arch_timer_rate;
}
+EXPORT_SYMBOL_GPL(arch_timer_get_rate);

static u64 arch_counter_get_cntvct_mem(void)
{
--
1.9.1

2015-05-21 08:33:37

by Fu Wei

[permalink] [raw]
Subject: [PATCH v2 2/7] Documentation: add sbsa-gwdt.txt documentation

From: Fu Wei <[email protected]>

The sbsa-gwdt.txt documentation in devicetree/bindings/watchdog is for
introducing SBSA(Server Base System Architecture) Generic Watchdog
device node info into FDT.

Signed-off-by: Fu Wei <[email protected]>
---
.../devicetree/bindings/watchdog/sbsa-gwdt.txt | 36 ++++++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt b/Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
new file mode 100644
index 0000000..bd1768d
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
@@ -0,0 +1,36 @@
+* SBSA(Server Base System Architecture) Generic Watchdog
+
+The SBSA Generic Watchdog Timer is used for resetting the system after
+two stages of timeout.
+More details: ARM-DEN-0029 - Server Base System Architecture (SBSA)
+
+Required properties:
+- compatible : Should at least contain "arm,sbsa-gwdt".
+
+- reg : base physical address of the frames and length of memory mapped region.
+
+- reg-names : Should contain the resource reg names to show the order of
+ the values in "reg".
+ Must include the following entries : "refresh", "control".
+
+- interrupts : Should at least contain WS0 interrupt,
+ the WS1 Signal is optional.
+
+- interrupt-names : Should contain the resource interrupt names.
+ Must include the following entries : "ws0". "ws1" is optional.
+
+Optional properties
+- timeout-sec : Watchdog pre-timeout and timeout values (in seconds).
+ The first is timeout values, then pre-timeout.
+
+Example for FVP Foundation Model v8:
+
+watchdog@2a450000 {
+ compatible = "arm,sbsa-gwdt";
+ reg = <0x0 0x2a450000 0 0x10000>,
+ <0x0 0x2a440000 0 0x10000>;
+ reg-names = "refresh", "control";
+ interrupts = <0 27 4>;
+ interrupt-names = "ws0";
+ timeout-sec = <10 5>;
+};
--
1.9.1

2015-05-21 08:33:51

by Fu Wei

[permalink] [raw]
Subject: [PATCH v2 3/7] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts

From: Fu Wei <[email protected]>

This can be a example of adding SBSA Generic Watchdog device node
into some dts files for the Soc which contains SBSA Generic Watchdog.

Signed-off-by: Fu Wei <[email protected]>
---
arch/arm64/boot/dts/arm/foundation-v8.dts | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dts b/arch/arm64/boot/dts/arm/foundation-v8.dts
index 4eac8dc..e3fae16 100644
--- a/arch/arm64/boot/dts/arm/foundation-v8.dts
+++ b/arch/arm64/boot/dts/arm/foundation-v8.dts
@@ -237,4 +237,14 @@
};
};
};
+ watchdog0: watchdog@2a450000 {
+ compatible = "arm,sbsa-gwdt";
+ reg = <0x0 0x2a450000 0 0x10000>,
+ <0x0 0x2a440000 0 0x10000>;
+ reg-names = "refresh",
+ "control";
+ interrupts = <0 27 4>;
+ interrupt-names = "ws0";
+ timeout-sec = <10 5>;
+ };
};
--
1.9.1

2015-05-21 08:33:55

by Fu Wei

[permalink] [raw]
Subject: [PATCH v2 4/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi

From: Fu Wei <[email protected]>

This can be a example of adding SBSA Generic Watchdog device node
into some dts files for the Soc which contains SBSA Generic Watchdog.

Signed-off-by: Fu Wei <[email protected]>
---
arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi b/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi
index 2874d92..95994eb 100644
--- a/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi
+++ b/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi
@@ -84,6 +84,17 @@
clock-names = "uartclk", "apb_pclk";
};

+ watchdog0: watchdog@e0bb0000 {
+ compatible = "arm,sbsa-gwdt";
+ reg = <0x0 0xe0bb0000 0 0x10000>,
+ <0x0 0xe0bc0000 0 0x10000>;
+ reg-names = "refresh",
+ "control";
+ interrupts = <0 337 4>;
+ interrupt-names = "ws0";
+ timeout-sec = <10 5>;
+ };
+
spi0: ssp@e1020000 {
status = "disabled";
compatible = "arm,pl022", "arm,primecell";
--
1.9.1

2015-05-21 08:35:18

by Fu Wei

[permalink] [raw]
Subject: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

From: Fu Wei <[email protected]>

Also update Documentation/watchdog/watchdog-kernel-api.txt to
introduce:
(1)the new elements in the watchdog_device and watchdog_ops struct;
(2)the new API "watchdog_init_timeouts".

Reasons:
(1)kernel already has two watchdog drivers are using "pretimeout":
drivers/char/ipmi/ipmi_watchdog.c
drivers/watchdog/kempld_wdt.c(but the definition is different)
(2)some other dirvers are going to use this: ARM SBSA Generic Watchdog

Signed-off-by: Fu Wei <[email protected]>
---
Documentation/watchdog/watchdog-kernel-api.txt | 62 ++++++++++++---
drivers/watchdog/watchdog_core.c | 103 +++++++++++++++++++------
drivers/watchdog/watchdog_dev.c | 48 ++++++++++++
include/linux/watchdog.h | 30 ++++++-
4 files changed, 208 insertions(+), 35 deletions(-)

diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index a0438f3..43900df 100644
--- a/Documentation/watchdog/watchdog-kernel-api.txt
+++ b/Documentation/watchdog/watchdog-kernel-api.txt
@@ -49,6 +49,9 @@ struct watchdog_device {
unsigned int timeout;
unsigned int min_timeout;
unsigned int max_timeout;
+ unsigned int pretimeout;
+ unsigned int min_pretimeout;
+ unsigned int max_pretimeout;
void *driver_data;
struct mutex lock;
unsigned long status;
@@ -70,6 +73,9 @@ It contains following fields:
* timeout: the watchdog timer's timeout value (in seconds).
* min_timeout: the watchdog timer's minimum timeout value (in seconds).
* max_timeout: the watchdog timer's maximum timeout value (in seconds).
+* pretimeout: the watchdog timer's pretimeout value (in seconds).
+* min_pretimeout: the watchdog timer's minimum pretimeout value (in seconds).
+* max_pretimeout: the watchdog timer's maximum pretimeout value (in seconds).
* bootstatus: status of the device after booting (reported with watchdog
WDIOF_* status bits).
* driver_data: a pointer to the drivers private data of a watchdog device.
@@ -92,6 +98,7 @@ struct watchdog_ops {
int (*ping)(struct watchdog_device *);
unsigned int (*status)(struct watchdog_device *);
int (*set_timeout)(struct watchdog_device *, unsigned int);
+ int (*set_pretimeout)(struct watchdog_device *, unsigned int);
unsigned int (*get_timeleft)(struct watchdog_device *);
void (*ref)(struct watchdog_device *);
void (*unref)(struct watchdog_device *);
@@ -153,9 +160,19 @@ they are supported. These optional routines/operations are:
and -EIO for "could not write value to the watchdog". On success this
routine should set the timeout value of the watchdog_device to the
achieved timeout value (which may be different from the requested one
- because the watchdog does not necessarily has a 1 second resolution).
+ because the watchdog does not necessarily has a 1 second resolution;
+ If the driver supports pretimeout, then the timeout value must be greater
+ than that).
(Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the
watchdog's info structure).
+* set_pretimeout: this routine checks and changes the pretimeout of the
+ watchdog timer device. It returns 0 on success, -EINVAL for "parameter out of
+ range" and -EIO for "could not write value to the watchdog". On success this
+ routine should set the pretimeout value of the watchdog_device to the
+ achieved pretimeout value (which may be different from the requested one
+ because the watchdog does not necessarily has a 1 second resolution).
+ (Note: the WDIOF_PRETIMEOUT needs to be set in the options field of the
+ watchdog's info structure).
* get_timeleft: this routines returns the time that's left before a reset.
* ref: the operation that calls kref_get on the kref of a dynamically
allocated watchdog_device struct.
@@ -213,14 +230,41 @@ 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:
+To initialize the timeout and pretimeout fields, the following function can be
+used:

-extern int watchdog_init_timeout(struct watchdog_device *wdd,
- unsigned int timeout_parm, struct device *dev);
+extern int watchdog_init_timeouts(struct watchdog_device *wdd,
+ unsigned int pretimeout_parm,
+ unsigned int timeout_parm,
+ void (*update_limits)(struct watchdog_device *),
+ 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.
+The watchdog_init_timeouts function allows you to initialize the pretimeout and
+timeout fields using the module pretimeout and timeout parameter or by
+retrieving the elements in the timeout-sec property(the first element is for
+timeout, the second one is for pretimeout) from the device tree(if the module
+pretimeout and timeout parameter are invalid).
+Normally, the pretimeout value will affect the limitation of timeout, and it
+is also hardware related. So you can write a function in your driver to update
+the limitation of timeout, according to the pretimeout value. Then pass the
+function pointer by the update_limits parameter. If you driver doesn't
+need this adjustment, just pass NULL to the update_limits parameter.
+Most of watchdog timers have not pretimeout as the warning signal. They just
+reset the system, once the timeout watch period expires. In this case, we can
+pass 0 to the pretimeout_parm, and pass NULL to the update_limits. Or use the
+old API: watchdog_init_timeout(see below)
+Best practice is to set the default pretimeout and timeout value as pretimeout
+and timeout value in the watchdog_device and then use this function to set the
+user "preferred" pretimeout value.
This routine returns zero on success and a negative errno code for failure.
+
+For backward compatibility, we also support the timeout initialization API:
+
+static inline int watchdog_init_timeout(struct watchdog_device *wdd,
+ unsigned int timeout_parm,
+ struct device *dev);
+
+Because of the introduction of pretimeout and watchdog_init_timeouts, this
+function has become a small wrapper function of watchdog_init_timeouts.
+
+
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index cec9b55..460796e 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -43,60 +43,115 @@
static DEFINE_IDA(watchdog_ida);
static struct class *watchdog_class;

-static void watchdog_check_min_max_timeout(struct watchdog_device *wdd)
+static void watchdog_check_min_max_timeouts(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)
+ * Check that we have valid min and max pretimeout and timeout values,
+ * if not reset them both to 0 (=not used or unknown)
*/
+ if (wdd->min_pretimeout > wdd->max_pretimeout) {
+ pr_info("Invalid min and max pretimeout, resetting to 0!\n");
+ wdd->min_pretimeout = 0;
+ wdd->max_pretimeout = 0;
+ }
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;
}
+ /*
+ * Check that we have valid min and max timeout values,
+ * if not reset them both to pretimeout limits
+ */
+ if (wdd->min_pretimeout && wdd->min_timeout < wdd->min_pretimeout) {
+ pr_info("Invalid min timeout, resetting to min pretimeout!\n");
+ wdd->min_timeout = wdd->min_pretimeout;
+ }
+ if (wdd->max_pretimeout && wdd->max_timeout < wdd->max_pretimeout) {
+ pr_info("Invalid max timeout, resetting to max pretimeout!\n");
+ wdd->max_timeout = wdd->max_pretimeout;
+ }
}

/**
- * watchdog_init_timeout() - initialize the timeout field
+ * watchdog_init_timeouts() - initialize the pretimeout and timeout field
+ * @pretimeout_parm: pretimeout module parameter
* @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.
+ * Initialize the pretimeout and timeout field of the watchdog_device struct
+ * with either the pretimeout and timeout module parameter (if it is valid
+ * value) or the timeout-sec property (only if it is a valid value and the
+ * pretimeout_parm and 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)
+int watchdog_init_timeouts(struct watchdog_device *wdd,
+ unsigned int pretimeout_parm,
+ unsigned int timeout_parm,
+ void (*update_limits)(struct watchdog_device *),
+ struct device *dev)
{
- unsigned int t = 0;
+ unsigned int timeout = 0, pretimeout = 0;
+ const __be32 *ppretimeout;
int ret = 0;
+ struct property *timeout_sec;
+ int length;

- watchdog_check_min_max_timeout(wdd);
+ watchdog_check_min_max_timeouts(wdd);

- /* try to get the timeout module parameter first */
- if (!watchdog_timeout_invalid(wdd, timeout_parm) && timeout_parm) {
- wdd->timeout = timeout_parm;
- return ret;
+ /* try to get the timeout and pretimeout module parameter first */
+ if (pretimeout_parm) {
+ if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm)) {
+ wdd->pretimeout = pretimeout_parm;
+ if (update_limits)
+ update_limits(wdd);
+ } else {
+ pr_warn("Invalid pretimeout parameter!\n");
+ ret = -EINVAL;
+ }
}
- if (timeout_parm)
+
+ if (timeout_parm) {
+ if (!watchdog_timeout_invalid(wdd, timeout_parm)) {
+ wdd->timeout = timeout_parm;
+ return ret;
+ }
+ pr_warn("Invalid timeout parameter!\n");
ret = -EINVAL;
+ }

/* try to get the timeout_sec property */
if (dev == NULL || dev->of_node == NULL)
return ret;
- of_property_read_u32(dev->of_node, "timeout-sec", &t);
- if (!watchdog_timeout_invalid(wdd, t) && t)
- wdd->timeout = t;
- else
+
+ timeout_sec = of_find_property(dev->of_node, "timeout-sec", &length);
+ if (timeout_sec) {
+ ppretimeout = of_prop_next_u32(timeout_sec, NULL, &timeout);
+ if (length == 2) {
+ of_prop_next_u32(timeout_sec, ppretimeout, &pretimeout);
+ if (!watchdog_pretimeout_invalid(wdd, pretimeout) &&
+ pretimeout) {
+ wdd->pretimeout = pretimeout;
+ if (update_limits)
+ update_limits(wdd);
+ } else {
+ ret = -EINVAL;
+ }
+ }
+ if (!watchdog_timeout_invalid(wdd, timeout) && timeout)
+ wdd->timeout = timeout;
+ else
+ ret = -EINVAL;
+ } else {
ret = -EINVAL;
+ }

return ret;
}
-EXPORT_SYMBOL_GPL(watchdog_init_timeout);
+EXPORT_SYMBOL_GPL(watchdog_init_timeouts);

/**
* watchdog_register_device() - register a watchdog device
@@ -119,7 +174,7 @@ int watchdog_register_device(struct watchdog_device *wdd)
if (wdd->ops->start == NULL || wdd->ops->stop == NULL)
return -EINVAL;

- watchdog_check_min_max_timeout(wdd);
+ watchdog_check_min_max_timeouts(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 6aaefba..b519257 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -218,6 +218,38 @@ out_timeout:
}

/*
+ * watchdog_set_pretimeout: set the watchdog timer pretimeout
+ * @wddev: the watchdog device to set the timeout for
+ * @pretimeout: pretimeout to set in seconds
+ */
+
+static int watchdog_set_pretimeout(struct watchdog_device *wddev,
+ unsigned int pretimeout)
+{
+ int err;
+
+ if (!wddev->ops->set_pretimeout ||
+ !(wddev->info->options & WDIOF_PRETIMEOUT))
+ return -EOPNOTSUPP;
+
+ if (watchdog_pretimeout_invalid(wddev, pretimeout))
+ return -EINVAL;
+
+ mutex_lock(&wddev->lock);
+
+ if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
+ err = -ENODEV;
+ goto out_pretimeout;
+ }
+
+ err = wddev->ops->set_pretimeout(wddev, pretimeout);
+
+out_pretimeout:
+ mutex_unlock(&wddev->lock);
+ return err;
+}
+
+/*
* watchdog_get_timeleft: wrapper to get the time left before a reboot
* @wddev: the watchdog device to get the remaining time from
* @timeleft: the time that's left
@@ -388,6 +420,22 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
if (wdd->timeout == 0)
return -EOPNOTSUPP;
return put_user(wdd->timeout, p);
+ case WDIOC_SETPRETIMEOUT:
+ if (get_user(val, p))
+ return -EFAULT;
+ err = watchdog_set_pretimeout(wdd, val);
+ if (err < 0)
+ return err;
+ /* If the watchdog is active then we send a keepalive ping
+ * to make sure that the watchdog keep's running (and if
+ * possible that it takes the new timeout) */
+ watchdog_ping(wdd);
+ /* Fall */
+ case WDIOC_GETPRETIMEOUT:
+ /* timeout == 0 means that we don't use the pretimeout */
+ if (wdd->pretimeout == 0)
+ return -EOPNOTSUPP;
+ return put_user(wdd->pretimeout, p);
case WDIOC_GETTIMELEFT:
err = watchdog_get_timeleft(wdd, &val);
if (err)
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index a746bf5..df430a3 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -25,6 +25,7 @@ struct watchdog_device;
* @ping: The routine that sends a keepalive ping to the watchdog device.
* @status: The routine that shows the status of the watchdog device.
* @set_timeout:The routine for setting the watchdog devices timeout value.
+ * @set_pretimeout:The routine for setting the watchdog devices pretimeout value
* @get_timeleft:The routine that get's the time that's left before a reset.
* @ref: The ref operation for dyn. allocated watchdog_device structs
* @unref: The unref operation for dyn. allocated watchdog_device structs
@@ -44,6 +45,7 @@ struct watchdog_ops {
int (*ping)(struct watchdog_device *);
unsigned int (*status)(struct watchdog_device *);
int (*set_timeout)(struct watchdog_device *, unsigned int);
+ int (*set_pretimeout)(struct watchdog_device *, unsigned int);
unsigned int (*get_timeleft)(struct watchdog_device *);
void (*ref)(struct watchdog_device *);
void (*unref)(struct watchdog_device *);
@@ -62,6 +64,9 @@ struct watchdog_ops {
* @timeout: The watchdog devices timeout value.
* @min_timeout:The watchdog devices minimum timeout value.
* @max_timeout:The watchdog devices maximum timeout value.
+ * @pretimeout: The watchdog devices pretimeout value.
+ * @min_pretimeout:The watchdog devices minimum pretimeout value.
+ * @max_pretimeout:The watchdog devices maximum pretimeout value.
* @driver-data:Pointer to the drivers private data.
* @lock: Lock for watchdog core internal use only.
* @status: Field that contains the devices internal status bits.
@@ -86,6 +91,9 @@ struct watchdog_device {
unsigned int timeout;
unsigned int min_timeout;
unsigned int max_timeout;
+ unsigned int pretimeout;
+ unsigned int min_pretimeout;
+ unsigned int max_pretimeout;
void *driver_data;
struct mutex lock;
unsigned long status;
@@ -120,6 +128,14 @@ static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigne
(t < wdd->min_timeout || t > wdd->max_timeout));
}

+/* Use the following function to check if a pretimeout value is invalid */
+static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd,
+ unsigned int t)
+{
+ return ((wdd->max_pretimeout != 0) &&
+ (t < wdd->min_pretimeout || t > wdd->max_pretimeout));
+}
+
/* Use the following functions to manipulate watchdog driver specific data */
static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data)
{
@@ -132,11 +148,21 @@ 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_init_timeouts(struct watchdog_device *wdd,
+ unsigned int pretimeout_parm,
+ unsigned int timeout_parm,
+ void (*update_limits)(struct watchdog_device *),
+ struct device *dev);
extern int watchdog_register_device(struct watchdog_device *);
extern void watchdog_unregister_device(struct watchdog_device *);

+static inline int watchdog_init_timeout(struct watchdog_device *wdd,
+ unsigned int timeout_parm,
+ struct device *dev)
+{
+ return watchdog_init_timeouts(wdd, 0, timeout_parm, NULL, dev);
+}
+
#ifdef CONFIG_HARDLOCKUP_DETECTOR
void watchdog_nmi_disable_all(void);
void watchdog_nmi_enable_all(void);
--
1.9.1

2015-05-21 08:34:11

by Fu Wei

[permalink] [raw]
Subject: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

From: Fu Wei <[email protected]>

This driver bases on linux kernel watchdog framework, and
use "pretimeout" in the framework. It supports getting timeout and
pretimeout from parameter and FDT at the driver init stage.
In first timeout(WS0), the interrupt routine run panic to save
system context.

Signed-off-by: Fu Wei <[email protected]>
---
drivers/watchdog/Kconfig | 12 ++
drivers/watchdog/Makefile | 1 +
drivers/watchdog/sbsa_gwdt.c | 476 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 489 insertions(+)
create mode 100644 drivers/watchdog/sbsa_gwdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e5e7c55..25a0df1 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -152,6 +152,18 @@ config ARM_SP805_WATCHDOG
ARM Primecell SP805 Watchdog timer. This will reboot your system when
the timeout is reached.

+config ARM_SBSA_WATCHDOG
+ tristate "ARM SBSA Generic Watchdog"
+ depends on ARM || ARM64 || COMPILE_TEST
+ depends on ARM_ARCH_TIMER
+ select WATCHDOG_CORE
+ help
+ ARM SBSA Generic Watchdog timer. This has two Watchdog Signals
+ (WS0/WS1), will trigger a warning interrupt(do panic) at the first
+ timeout(WS0); will reboot your system when the second timeout(WS1)
+ is reached.
+ More details: DEN0029B - Server Base System Architecture (SBSA)
+
config AT91RM9200_WATCHDOG
tristate "AT91RM9200 watchdog"
depends on SOC_AT91RM9200 && MFD_SYSCON
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 5c19294..471f1b7c 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o

# ARM Architecture
obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o
+obj-$(CONFIG_ARM_SBSA_WATCHDOG) += sbsa_gwdt.o
obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o
obj-$(CONFIG_CADENCE_WATCHDOG) += cadence_wdt.o
diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
new file mode 100644
index 0000000..4ebe7c3
--- /dev/null
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -0,0 +1,476 @@
+/*
+ * SBSA(Server Base System Architecture) Generic Watchdog driver
+ *
+ * Copyright (c) 2015, Linaro Ltd.
+ * Author: Fu Wei <[email protected]>
+ * Suravee Suthikulpanit <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Note: This SBSA Generic watchdog driver is compatible with
+ * the pretimeout concept of Linux kernel.
+ * The timeout and pretimeout are set by the different REGs.
+ * The first watch period is set by writing WCV directly,
+ * that can support more than 10s timeout at the maximum
+ * system counter frequency.
+ * The second watch period is set by WOR(32bit) which will be loaded
+ * automatically by hardware, when WS0 is triggered.
+ * This gives a maximum watch period of around 10s at the maximum
+ * system counter frequency.
+ * The System Counter shall run at maximum of 400MHz.
+ * More details: DEN0029B - Server Base System Architecture (SBSA)
+ *
+ * Kernel/API: P---------| pretimeout
+ * |-------------------------------T timeout
+ * SBSA GWDT: P--WOR---WS1 pretimeout
+ * |-------WCV----------WS0~~~~~~~~T timeout
+ */
+
+#include <asm/arch_timer.h>
+
+#include <linux/acpi.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/watchdog.h>
+
+/* SBSA Generic Watchdog register definitions */
+/* refresh frame */
+#define SBSA_GWDT_WRR 0x000
+
+/* control frame */
+#define SBSA_GWDT_WCS 0x000
+#define SBSA_GWDT_WOR 0x008
+#define SBSA_GWDT_WCV_LO 0x010
+#define SBSA_GWDT_WCV_HI 0x014
+
+/* refresh/control frame */
+#define SBSA_GWDT_W_IIDR 0xfcc
+#define SBSA_GWDT_IDR 0xfd0
+
+/* Watchdog Control and Status Register */
+#define SBSA_GWDT_WCS_EN BIT(0)
+#define SBSA_GWDT_WCS_WS0 BIT(1)
+#define SBSA_GWDT_WCS_WS1 BIT(2)
+
+/**
+ * struct sbsa_gwdt - Internal representation of the SBSA GWDT
+ * @wdd: kernel watchdog_device structure
+ * @clk: store the System Counter clock frequency, in Hz.
+ * @refresh_base: Virtual address of the watchdog refresh frame
+ * @control_base: Virtual address of the watchdog control frame
+ */
+struct sbsa_gwdt {
+ struct watchdog_device wdd;
+ u32 clk;
+ void __iomem *refresh_base;
+ void __iomem *control_base;
+};
+
+#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
+
+#define DEFAULT_TIMEOUT 10 /* seconds, the 1st + 2nd watch periods*/
+#define DEFAULT_PRETIMEOUT 5 /* seconds, the 2nd watch period*/
+
+static unsigned int timeout;
+module_param(timeout, uint, 0);
+MODULE_PARM_DESC(timeout,
+ "Watchdog timeout in seconds. (>=0, default="
+ __MODULE_STRING(DEFAULT_TIMEOUT) ")");
+
+static unsigned int max_timeout = UINT_MAX;
+module_param(max_timeout, uint, 0);
+MODULE_PARM_DESC(max_timeout,
+ "Watchdog max timeout in seconds. (>=0, default="
+ __MODULE_STRING(UINT_MAX) ")");
+
+static unsigned int pretimeout;
+module_param(pretimeout, uint, 0);
+MODULE_PARM_DESC(pretimeout,
+ "Watchdog pretimeout in seconds. (>=0, default="
+ __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
+
+static unsigned int max_pretimeout = U32_MAX;
+module_param(max_pretimeout, uint, 0);
+MODULE_PARM_DESC(max_pretimeout,
+ "Watchdog max pretimeout in seconds. (>=0, default="
+ __MODULE_STRING(U32_MAX) ")");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, S_IRUGO);
+MODULE_PARM_DESC(nowayout,
+ "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+/*
+ * Architected system timer support.
+ */
+static void sbsa_gwdt_cf_write(unsigned int reg, u32 val,
+ struct watchdog_device *wdd)
+{
+ struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+ writel_relaxed(val, gwdt->control_base + reg);
+}
+
+static void sbsa_gwdt_rf_write(unsigned int reg, u32 val,
+ struct watchdog_device *wdd)
+{
+ struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+ writel_relaxed(val, gwdt->refresh_base + reg);
+}
+
+static u32 sbsa_gwdt_cf_read(unsigned int reg, struct watchdog_device *wdd)
+{
+ struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+ return readl_relaxed(gwdt->control_base + reg);
+}
+
+/*
+ * help founctions for accessing 64bit WCV register
+ */
+static u64 sbsa_gwdt_get_wcv(struct watchdog_device *wdd)
+{
+ u32 wcv_lo, wcv_hi;
+
+ do {
+ wcv_hi = sbsa_gwdt_cf_read(SBSA_GWDT_WCV_HI, wdd);
+ wcv_lo = sbsa_gwdt_cf_read(SBSA_GWDT_WCV_LO, wdd);
+ } while (wcv_hi != sbsa_gwdt_cf_read(SBSA_GWDT_WCV_HI, wdd));
+
+ return (((u64)wcv_hi << 32) | wcv_lo);
+}
+
+static void sbsa_gwdt_set_wcv(struct watchdog_device *wdd, u64 value)
+{
+ u32 wcv_lo, wcv_hi;
+
+ wcv_lo = value & U32_MAX;
+ wcv_hi = (value >> 32) & U32_MAX;
+
+ sbsa_gwdt_cf_write(SBSA_GWDT_WCV_HI, wcv_hi, wdd);
+ sbsa_gwdt_cf_write(SBSA_GWDT_WCV_LO, wcv_lo, wdd);
+}
+
+static void reload_timeout_to_wcv(struct watchdog_device *wdd)
+{
+ struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+ u64 wcv;
+
+ wcv = arch_counter_get_cntvct() +
+ (u64)(wdd->timeout - wdd->pretimeout) * gwdt->clk;
+
+ sbsa_gwdt_set_wcv(wdd, wcv);
+}
+
+/*
+ * Use the following function to set the limit of timeout
+ * after updating pretimeout
+ */
+static void sbsa_gwdt_update_limits(struct watchdog_device *wdd)
+{
+ struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+ u64 first_period_max = U64_MAX;
+
+ do_div(first_period_max, gwdt->clk);
+
+ wdd->min_timeout = wdd->pretimeout + 1;
+ wdd->max_timeout = min((uint)(wdd->pretimeout + first_period_max),
+ wdd->max_timeout);
+}
+
+static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
+ unsigned int timeout)
+{
+ wdd->timeout = timeout;
+
+ return 0;
+}
+
+static int sbsa_gwdt_set_pretimeout(struct watchdog_device *wdd,
+ unsigned int pretimeout)
+{
+ struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+ u32 wor;
+
+ wdd->pretimeout = pretimeout;
+ sbsa_gwdt_update_limits(wdd);
+
+ if (!pretimeout)
+ /* gives sbsa_gwdt_start a chance to setup timeout */
+ wor = gwdt->clk;
+ else
+ wor = pretimeout * gwdt->clk;
+
+ /* refresh the WOR, that will cause an explicit watchdog refresh */
+ sbsa_gwdt_cf_write(SBSA_GWDT_WOR, wor, wdd);
+
+ return 0;
+}
+
+static unsigned int sbsa_gwdt_get_timeleft(struct watchdog_device *wdd)
+{
+ struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+ u64 timeleft = sbsa_gwdt_get_wcv(wdd) - arch_counter_get_cntvct();
+
+ do_div(timeleft, gwdt->clk);
+
+ return timeleft;
+}
+
+static int sbsa_gwdt_start(struct watchdog_device *wdd)
+{
+ /* Force refresh */
+ sbsa_gwdt_rf_write(SBSA_GWDT_WRR, 0xc0ffee, wdd);
+ /* writing WCS will cause an explicit watchdog refresh */
+ sbsa_gwdt_cf_write(SBSA_GWDT_WCS, SBSA_GWDT_WCS_EN, wdd);
+
+ reload_timeout_to_wcv(wdd);
+
+ return 0;
+}
+
+static int sbsa_gwdt_stop(struct watchdog_device *wdd)
+{
+ /* Force refresh */
+ sbsa_gwdt_rf_write(SBSA_GWDT_WRR, 0xc0ffee, wdd);
+ /* writing WCS will cause an explicit watchdog refresh */
+ sbsa_gwdt_cf_write(SBSA_GWDT_WCS, 0, wdd);
+
+ return 0;
+}
+
+static int sbsa_gwdt_keepalive(struct watchdog_device *wdd)
+{
+ /*
+ * Writing WRR for an explicit watchdog refresh
+ * You can write anyting(like 0xc0ffee)
+ */
+ sbsa_gwdt_rf_write(SBSA_GWDT_WRR, 0xc0ffee, wdd);
+
+ reload_timeout_to_wcv(wdd);
+
+ return 0;
+}
+
+static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
+{
+ struct sbsa_gwdt *gwdt = (struct sbsa_gwdt *)dev_id;
+ struct watchdog_device *wdd = &gwdt->wdd;
+ u32 status;
+
+ status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
+
+ if (status & SBSA_GWDT_WCS_WS0)
+ panic("SBSA Watchdog pre-timeout");
+
+ return IRQ_HANDLED;
+}
+
+static struct watchdog_info sbsa_gwdt_info = {
+ .identity = "SBSA Generic Watchdog",
+ .options = WDIOF_SETTIMEOUT |
+ WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE |
+ WDIOF_PRETIMEOUT |
+ WDIOF_CARDRESET,
+};
+
+static struct watchdog_ops sbsa_gwdt_ops = {
+ .owner = THIS_MODULE,
+ .start = sbsa_gwdt_start,
+ .stop = sbsa_gwdt_stop,
+ .ping = sbsa_gwdt_keepalive,
+ .set_timeout = sbsa_gwdt_set_timeout,
+ .set_pretimeout = sbsa_gwdt_set_pretimeout,
+ .get_timeleft = sbsa_gwdt_get_timeleft,
+};
+
+static int sbsa_gwdt_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct sbsa_gwdt *gwdt;
+ struct watchdog_device *wdd;
+ struct resource *res;
+ void *rf_base, *cf_base;
+ int irq;
+ u32 clk, status;
+ int ret = 0;
+ u64 first_period_max = U64_MAX;
+
+ /*
+ * Try to determine the frequency from the arch_timer interface
+ */
+ clk = arch_timer_get_rate();
+ if (!clk) {
+ dev_err(dev, "System Counter frequency not available\n");
+ return -EINVAL;
+ }
+
+ gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
+ if (!gwdt)
+ return -ENOMEM;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "refresh");
+ rf_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(rf_base))
+ return PTR_ERR(rf_base);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control");
+ cf_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(rf_base))
+ return PTR_ERR(rf_base);
+
+ irq = platform_get_irq_byname(pdev, "ws0");
+ if (irq < 0) {
+ dev_err(dev, "unable to get ws0 interrupt.\n");
+ return irq;
+ }
+
+ gwdt->refresh_base = rf_base;
+ gwdt->control_base = cf_base;
+ gwdt->clk = clk;
+
+ platform_set_drvdata(pdev, gwdt);
+
+ wdd = &gwdt->wdd;
+ wdd->parent = dev;
+ wdd->info = &sbsa_gwdt_info;
+ wdd->ops = &sbsa_gwdt_ops;
+ watchdog_set_drvdata(wdd, gwdt);
+ watchdog_set_nowayout(wdd, nowayout);
+
+ status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
+ if (status & SBSA_GWDT_WCS_WS1) {
+ dev_warn(dev, "System reset by WDT(WCS: %x, WCV: %llx)\n",
+ status, sbsa_gwdt_get_wcv(wdd));
+ wdd->bootstatus |= WDIOF_CARDRESET;
+ }
+ /* Check if watchdog is already enabled */
+ if (status & SBSA_GWDT_WCS_EN) {
+ dev_warn(dev, "already enabled! WCS:0x%x\n", status);
+ sbsa_gwdt_keepalive(wdd);
+ }
+
+ wdd->min_pretimeout = 0;
+ wdd->max_pretimeout = min(U32_MAX / clk, max_pretimeout);
+ wdd->min_timeout = 1;
+ do_div(first_period_max, clk);
+ wdd->max_timeout = min((uint)(wdd->pretimeout + first_period_max),
+ max_timeout);
+
+ wdd->pretimeout = DEFAULT_PRETIMEOUT;
+ wdd->timeout = DEFAULT_TIMEOUT;
+ watchdog_init_timeouts(wdd, pretimeout, timeout,
+ sbsa_gwdt_update_limits, dev);
+ /* update pretimeout to WOR */
+ sbsa_gwdt_cf_write(SBSA_GWDT_WOR, wdd->pretimeout * clk, wdd);
+
+ ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, IRQF_TIMER,
+ pdev->name, gwdt);
+ if (ret) {
+ dev_err(dev, "unable to request IRQ %d\n", irq);
+ return ret;
+ }
+
+ ret = watchdog_register_device(wdd);
+ if (ret)
+ return ret;
+
+ dev_info(dev, "Initialized with %ds timeout, %ds pretimeout @ %uHz\n",
+ wdd->timeout, wdd->pretimeout, gwdt->clk);
+
+ return 0;
+}
+
+static void sbsa_gwdt_shutdown(struct platform_device *pdev)
+{
+ struct sbsa_gwdt *gwdt = platform_get_drvdata(pdev);
+
+ sbsa_gwdt_stop(&gwdt->wdd);
+}
+
+static int sbsa_gwdt_remove(struct platform_device *pdev)
+{
+ struct sbsa_gwdt *gwdt = platform_get_drvdata(pdev);
+ int ret = 0;
+
+ if (!nowayout)
+ ret = sbsa_gwdt_stop(&gwdt->wdd);
+
+ watchdog_unregister_device(&gwdt->wdd);
+
+ return ret;
+}
+
+/* Disable watchdog if it is active during suspend */
+static int __maybe_unused sbsa_gwdt_suspend(struct device *dev)
+{
+ struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
+
+ if (watchdog_active(&gwdt->wdd))
+ sbsa_gwdt_stop(&gwdt->wdd);
+
+ return 0;
+}
+
+/* Enable watchdog and configure it if necessary */
+static int __maybe_unused sbsa_gwdt_resume(struct device *dev)
+{
+ struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
+
+ if (watchdog_active(&gwdt->wdd))
+ sbsa_gwdt_start(&gwdt->wdd);
+
+ return 0;
+}
+
+static const struct dev_pm_ops sbsa_gwdt_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(sbsa_gwdt_suspend, sbsa_gwdt_resume)
+};
+
+static const struct of_device_id sbsa_gwdt_of_match[] = {
+ { .compatible = "arm,sbsa-gwdt", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, sbsa_gwdt_of_match);
+
+static const struct platform_device_id sbsa_gwdt_pdev_match[] = {
+ { .name = "sbsa-gwdt", },
+ {},
+};
+MODULE_DEVICE_TABLE(platform, sbsa_gwdt_pdev_match);
+
+static struct platform_driver sbsa_gwdt_driver = {
+ .driver = {
+ .name = "sbsa-gwdt",
+ .pm = &sbsa_gwdt_pm_ops,
+ .of_match_table = sbsa_gwdt_of_match,
+ },
+ .probe = sbsa_gwdt_probe,
+ .remove = sbsa_gwdt_remove,
+ .shutdown = sbsa_gwdt_shutdown,
+ .id_table = sbsa_gwdt_pdev_match,
+};
+
+module_platform_driver(sbsa_gwdt_driver);
+
+MODULE_DESCRIPTION("SBSA Generic Watchdog Driver");
+MODULE_VERSION("v1.0");
+MODULE_AUTHOR("Fu Wei <[email protected]>");
+MODULE_AUTHOR("Suravee Suthikulpanit <[email protected]>");
+MODULE_LICENSE("GPL v2");
--
1.9.1

2015-05-21 08:34:15

by Fu Wei

[permalink] [raw]
Subject: [PATCH v2 7/7] ACPI: import watchdog info of GTDT into platform device

From: Fu Wei <[email protected]>

Parse SBSA Generic Watchdog Structure in GTDT table of ACPI,
and create a platform device with that information.
This platform device can be used by the ARM SBSA Generic
Watchdog driver.

Signed-off-by: Fu Wei <[email protected]>
---
arch/arm64/kernel/acpi.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 136 insertions(+)

diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 8b83955..1ed11fd 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -23,6 +23,7 @@
#include <linux/irqdomain.h>
#include <linux/memblock.h>
#include <linux/of_fdt.h>
+#include <linux/platform_device.h>
#include <linux/smp.h>

#include <asm/cputype.h>
@@ -343,3 +344,138 @@ void __init acpi_gic_init(void)

early_acpi_os_unmap_memory((char *)table, tbl_size);
}
+
+static int __init acpi_gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
+ int index)
+{
+ struct platform_device *pdev;
+ struct resource *res;
+ u32 gsi, flags;
+ int irq, trigger, polarity;
+ resource_size_t rf_base_phy, cf_base_phy;
+ int err = -ENOMEM;
+
+ /*
+ * Get SBSA Generic Watchdog info
+ * from a Watchdog GT type structure in GTDT
+ */
+ rf_base_phy = (resource_size_t)wd->refresh_frame_address;
+ cf_base_phy = (resource_size_t)wd->control_frame_address;
+ gsi = wd->timer_interrupt;
+ flags = wd->timer_flags;
+
+ pr_info("GTDT: a Watchdog GT structure(0x%llx/0x%llx gsi:%u flags:0x%x)\n",
+ rf_base_phy, cf_base_phy, gsi, flags);
+
+ if (!(rf_base_phy && cf_base_phy && gsi)) {
+ pr_err("GTDT: failed geting the device info.\n");
+ return -EINVAL;
+ }
+
+ trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+ : ACPI_LEVEL_SENSITIVE;
+ polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+ : ACPI_ACTIVE_HIGH;
+ irq = acpi_register_gsi(NULL, gsi, trigger, polarity);
+ if (irq < 0) {
+ pr_err("GTDT: failed to register GSI of the Watchdog GT.\n");
+ return -EINVAL;
+ }
+
+ pdev = platform_device_alloc("sbsa-gwdt", index);
+ if (!pdev)
+ goto err_unregister_gsi;
+
+ res = kcalloc(3, sizeof(*res), GFP_KERNEL);
+ if (!res)
+ goto err_device_put;
+
+ res[0].start = rf_base_phy;
+ res[0].end = rf_base_phy + SZ_4K - 1;
+ res[0].name = "refresh";
+ res[0].flags = IORESOURCE_MEM;
+
+ res[1].start = cf_base_phy;
+ res[1].end = cf_base_phy + SZ_4K - 1;
+ res[1].name = "control";
+ res[1].flags = IORESOURCE_MEM;
+
+ res[2].start = irq;
+ res[2].end = res[2].start;
+ res[2].name = "ws0";
+ res[2].flags = IORESOURCE_IRQ;
+
+ err = platform_device_add_resources(pdev, res, 3);
+ if (err)
+ goto err_free_res;
+
+ err = platform_device_add(pdev);
+ if (err)
+ goto err_free_res;
+
+ return 0;
+
+err_free_res:
+ kfree(res);
+err_device_put:
+ platform_device_put(pdev);
+err_unregister_gsi:
+ acpi_unregister_gsi(gsi);
+
+ return err;
+}
+
+/* Initialize SBSA generic Watchdog platform device info from GTDT */
+static int __init acpi_gtdt_sbsa_gwdt_init(struct acpi_table_header *table)
+{
+ struct acpi_table_gtdt *gtdt;
+ struct acpi_gtdt_header *header;
+ void *gtdt_subtable;
+ int i, gwdt_index;
+ int ret = 0;
+
+ if (table->revision < 2) {
+ pr_info("GTDT: Revision:%d doesn't support Platform Timers.\n",
+ table->revision);
+ return 0;
+ }
+
+ gtdt = container_of(table, struct acpi_table_gtdt, header);
+ if (!gtdt->platform_timer_count) {
+ pr_info("GTDT: No Platform Timer structures.\n");
+ return 0;
+ }
+
+ gtdt_subtable = (void *)gtdt + gtdt->platform_timer_offset;
+
+ for (i = 0, gwdt_index = 0; i < gtdt->platform_timer_count; i++) {
+ if (gtdt_subtable > (void *)table + table->length) {
+ pr_err("GTDT: subtable pointer overflows, bad table\n");
+ return -EINVAL;
+ }
+ header = (struct acpi_gtdt_header *)gtdt_subtable;
+ if (header->type == ACPI_GTDT_TYPE_WATCHDOG) {
+ ret = acpi_gtdt_import_sbsa_gwdt(gtdt_subtable,
+ gwdt_index);
+ if (ret)
+ pr_err("GTDT: failed to import subtable %d\n",
+ i);
+ else
+ gwdt_index++;
+ }
+ gtdt_subtable += header->length;
+ }
+
+ return ret;
+}
+
+/* Initialize the SBSA Generic Watchdog presented in GTDT */
+static int __init acpi_gtdt_init(void)
+{
+ if (acpi_disabled)
+ return 0;
+
+ return acpi_table_parse(ACPI_SIG_GTDT, acpi_gtdt_sbsa_gwdt_init);
+}
+
+arch_initcall(acpi_gtdt_init);
--
1.9.1

2015-05-21 08:46:11

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH v2 3/7] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts

On Thursday 21 May 2015 16:32:32 [email protected] wrote:
> + watchdog0: watchdog@2a450000 {
> + compatible = "arm,sbsa-gwdt";
> + reg = <0x0 0x2a450000 0 0x10000>,
> + <0x0 0x2a440000 0 0x10000>;
> + reg-names = "refresh",
> + "control";
> + interrupts = <0 27 4>;
> + interrupt-names = "ws0";
> + timeout-sec = <10 5>;
> + };
> };
>

just one tiny comment: you can drop the 'watchdog0:' label here, there
is normally no reason to assign a label to a watchdog device, especially
if it's in a .dts file rather than a .dtsi.

The same is true for the example in the binding documentation.

Arnd

2015-05-21 08:47:21

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [Linaro-acpi] [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver

On Thursday 21 May 2015 16:32:29 [email protected] wrote:
>
> This patchset:
>
> (1)Export "arch_timer_get_rate" in arm_arch_timer.c for the
> other drivers, like SBSA watchdog driver
>
> (2)Introduce Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
> for FDT info of SBSA Generic Watchdog, and give two examples of
> adding SBSA Generic Watchdog device node into the dts files:
> foundation-v8.dts and amd-seattle-soc.dtsi.
>
> (3)Introduce "pretimeout" into the watchdog framework, and update
> Documentation/watchdog/watchdog-kernel-api.txt to introduce:
> (1)the new elements in the watchdog_device and watchdog_ops struct;
> (2)the new API "watchdog_init_timeouts".
>
> (4)Introduce ARM SBSA watchdog driver:
> a.Use linux kernel watchdog framework;
> b.Work with FDT on ARM64;
> c.Use "pretimeout" in watchdog framework;
> d.In first timeout(WS0), do panic to save system context;
> e.Support geting timeout and pretimeout from parameter and FDT
> at the driver init stage.

Looks all good to me, please add

Acked-by: Arnd Bergmann <[email protected]>

for patches 1-6.

> (5)Parse SBSA Generic Watchdog Structure in GTDT table of ACPI,
> and create a platform device with that information.
> This platform device can be used by This Watchdog driver.

This needs to be reviewed by someone who understands ACPI.

Arnd

2015-05-21 08:49:39

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 3/7] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts

Hi Arnd,

yes, you are right , will delete it :-)

On 21 May 2015 at 16:45, Arnd Bergmann <[email protected]> wrote:
> On Thursday 21 May 2015 16:32:32 [email protected] wrote:
>> + watchdog0: watchdog@2a450000 {
>> + compatible = "arm,sbsa-gwdt";
>> + reg = <0x0 0x2a450000 0 0x10000>,
>> + <0x0 0x2a440000 0 0x10000>;
>> + reg-names = "refresh",
>> + "control";
>> + interrupts = <0 27 4>;
>> + interrupt-names = "ws0";
>> + timeout-sec = <10 5>;
>> + };
>> };
>>
>
> just one tiny comment: you can drop the 'watchdog0:' label here, there
> is normally no reason to assign a label to a watchdog device, especially
> if it's in a .dts file rather than a .dtsi.
>
> The same is true for the example in the binding documentation.
>
> Arnd



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-21 09:01:06

by Fu Wei

[permalink] [raw]
Subject: Re: [Linaro-acpi] [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Arnd,

Great thanks for your review! :-)

On 21 May 2015 at 16:46, Arnd Bergmann <[email protected]> wrote:
> On Thursday 21 May 2015 16:32:29 [email protected] wrote:
>>
>> This patchset:
>>
>> (1)Export "arch_timer_get_rate" in arm_arch_timer.c for the
>> other drivers, like SBSA watchdog driver
>>
>> (2)Introduce Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
>> for FDT info of SBSA Generic Watchdog, and give two examples of
>> adding SBSA Generic Watchdog device node into the dts files:
>> foundation-v8.dts and amd-seattle-soc.dtsi.
>>
>> (3)Introduce "pretimeout" into the watchdog framework, and update
>> Documentation/watchdog/watchdog-kernel-api.txt to introduce:
>> (1)the new elements in the watchdog_device and watchdog_ops struct;
>> (2)the new API "watchdog_init_timeouts".
>>
>> (4)Introduce ARM SBSA watchdog driver:
>> a.Use linux kernel watchdog framework;
>> b.Work with FDT on ARM64;
>> c.Use "pretimeout" in watchdog framework;
>> d.In first timeout(WS0), do panic to save system context;
>> e.Support geting timeout and pretimeout from parameter and FDT
>> at the driver init stage.
>
> Looks all good to me, please add
>
> Acked-by: Arnd Bergmann <[email protected]>
>
> for patches 1-6.

Great! happy to do so :-)

>
>> (5)Parse SBSA Generic Watchdog Structure in GTDT table of ACPI,
>> and create a platform device with that information.
>> This platform device can be used by This Watchdog driver.
>
> This needs to be reviewed by someone who understands ACPI.

yes, maybe Hanjun and Al can help :-)

>
> Arnd



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-21 09:04:50

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

On 05/21/2015 01:32 AM, [email protected] wrote:
> From: Fu Wei <[email protected]>
>
> Also update Documentation/watchdog/watchdog-kernel-api.txt to
> introduce:
> (1)the new elements in the watchdog_device and watchdog_ops struct;
> (2)the new API "watchdog_init_timeouts".
>
> Reasons:
> (1)kernel already has two watchdog drivers are using "pretimeout":
> drivers/char/ipmi/ipmi_watchdog.c
> drivers/watchdog/kempld_wdt.c(but the definition is different)
> (2)some other dirvers are going to use this: ARM SBSA Generic Watchdog
>
> Signed-off-by: Fu Wei <[email protected]>
> ---

[ ... ]

> +extern int watchdog_init_timeouts(struct watchdog_device *wdd,
> + unsigned int pretimeout_parm,
> + unsigned int timeout_parm,
> + void (*update_limits)(struct watchdog_device *),
> + 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.
> +The watchdog_init_timeouts function allows you to initialize the pretimeout and
> +timeout fields using the module pretimeout and timeout parameter or by
> +retrieving the elements in the timeout-sec property(the first element is for
> +timeout, the second one is for pretimeout) from the device tree(if the module
> +pretimeout and timeout parameter are invalid).
> +Normally, the pretimeout value will affect the limitation of timeout, and it
> +is also hardware related. So you can write a function in your driver to update
> +the limitation of timeout, according to the pretimeout value. Then pass the
> +function pointer by the update_limits parameter. If you driver doesn't
> +need this adjustment, just pass NULL to the update_limits parameter.

You've lost me a bit with the update_limits function. watchdog_init_timeouts()
is called from the driver. Why should the function have to call back into the
driver to update the parameters which are passed from the driver ?
Seems to me the driver can do that calculation first, then call
watchdog_init_timeouts() with the result. Am I missing something ?

Thanks,
Guenter

2015-05-21 10:05:36

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

Hi Guenter,

Thanks for review. :-)
feedback inline below

On 21 May 2015 at 17:04, Guenter Roeck <[email protected]> wrote:
> On 05/21/2015 01:32 AM, [email protected] wrote:
>>
>> From: Fu Wei <[email protected]>
>>
>> Also update Documentation/watchdog/watchdog-kernel-api.txt to
>> introduce:
>> (1)the new elements in the watchdog_device and watchdog_ops struct;
>> (2)the new API "watchdog_init_timeouts".
>>
>> Reasons:
>> (1)kernel already has two watchdog drivers are using "pretimeout":
>> drivers/char/ipmi/ipmi_watchdog.c
>> drivers/watchdog/kempld_wdt.c(but the definition is different)
>> (2)some other dirvers are going to use this: ARM SBSA Generic Watchdog
>>
>> Signed-off-by: Fu Wei <[email protected]>
>> ---
>
>
> [ ... ]
>
>> +extern int watchdog_init_timeouts(struct watchdog_device *wdd,
>> + unsigned int pretimeout_parm,
>> + unsigned int timeout_parm,
>> + void (*update_limits)(struct
>> watchdog_device *),
>> + 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.
>> +The watchdog_init_timeouts function allows you to initialize the
>> pretimeout and
>> +timeout fields using the module pretimeout and timeout parameter or by
>> +retrieving the elements in the timeout-sec property(the first element is
>> for
>> +timeout, the second one is for pretimeout) from the device tree(if the
>> module
>> +pretimeout and timeout parameter are invalid).
>> +Normally, the pretimeout value will affect the limitation of timeout, and
>> it
>> +is also hardware related. So you can write a function in your driver to
>> update
>> +the limitation of timeout, according to the pretimeout value. Then pass
>> the
>> +function pointer by the update_limits parameter. If you driver doesn't
>> +need this adjustment, just pass NULL to the update_limits parameter.
>
>
> You've lost me a bit with the update_limits function.
> watchdog_init_timeouts()
> is called from the driver.

yes, that is the help function which will be called from watchdog
driver, like SBSA watchdog driver

> Why should the function have to call back into
> the
> driver to update the parameters which are passed from the driver ?

Let me explain this, please correct me if I misunderstand something.
According to the concept of "pretimeout" in kernel, the timeout
contains the pretimeout, like

* Kernel/API: P---------| pretimeout
* |-------------------------------T timeout

If you set up the value of pretimeout, that means pretimeout
<min_timeout < timeout < max_timeout < (pretimeout +
max_timeout_for_1th_stage)
For min_timeout > pretimeout. if some one setup a timeout like :
pretimeout > timeout > min_timeout, I think that could be a problem
For max_timeout < (pretimeout + max_timeout_for_1th_stage), if some
one setup a timeout like (pretimeout + max_timeout_for_1th_stage) <
timeout > max_timeout .

I have explained a little in doc, but the adjustment may have
something to do with hardware, like max_timeout_for_1th_stage(in SBSA
watchdog , limited by WCV)

maybe this problem wouldn't happen ,if you set up max_timeout to a
small number. so you can pass NULL to the pointer.
but I think maybe for other device , that may happen.

> Seems to me the driver can do that calculation first, then call
> watchdog_init_timeouts() with the result. Am I missing something ?

maybe I am overthinking it :-)
please correct me

>
> Thanks,
> Guenter
>



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-21 10:12:08

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

On 05/21/2015 01:32 AM, [email protected] wrote:
> From: Fu Wei <[email protected]>
>
> Also update Documentation/watchdog/watchdog-kernel-api.txt to
> introduce:
> (1)the new elements in the watchdog_device and watchdog_ops struct;
> (2)the new API "watchdog_init_timeouts".
>
> Reasons:
> (1)kernel already has two watchdog drivers are using "pretimeout":
> drivers/char/ipmi/ipmi_watchdog.c
> drivers/watchdog/kempld_wdt.c(but the definition is different)
> (2)some other dirvers are going to use this: ARM SBSA Generic Watchdog
>
drivers

> Signed-off-by: Fu Wei <[email protected]>
> ---
> Documentation/watchdog/watchdog-kernel-api.txt | 62 ++++++++++++---
> drivers/watchdog/watchdog_core.c | 103 +++++++++++++++++++------
> drivers/watchdog/watchdog_dev.c | 48 ++++++++++++
> include/linux/watchdog.h | 30 ++++++-
> 4 files changed, 208 insertions(+), 35 deletions(-)
>
> diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
> index a0438f3..43900df 100644
> --- a/Documentation/watchdog/watchdog-kernel-api.txt
> +++ b/Documentation/watchdog/watchdog-kernel-api.txt
> @@ -49,6 +49,9 @@ struct watchdog_device {
> unsigned int timeout;
> unsigned int min_timeout;
> unsigned int max_timeout;
> + unsigned int pretimeout;
> + unsigned int min_pretimeout;
> + unsigned int max_pretimeout;
> void *driver_data;
> struct mutex lock;
> unsigned long status;
> @@ -70,6 +73,9 @@ It contains following fields:
> * timeout: the watchdog timer's timeout value (in seconds).
> * min_timeout: the watchdog timer's minimum timeout value (in seconds).
> * max_timeout: the watchdog timer's maximum timeout value (in seconds).
> +* pretimeout: the watchdog timer's pretimeout value (in seconds).
> +* min_pretimeout: the watchdog timer's minimum pretimeout value (in seconds).
> +* max_pretimeout: the watchdog timer's maximum pretimeout value (in seconds).
> * bootstatus: status of the device after booting (reported with watchdog
> WDIOF_* status bits).
> * driver_data: a pointer to the drivers private data of a watchdog device.
> @@ -92,6 +98,7 @@ struct watchdog_ops {
> int (*ping)(struct watchdog_device *);
> unsigned int (*status)(struct watchdog_device *);
> int (*set_timeout)(struct watchdog_device *, unsigned int);
> + int (*set_pretimeout)(struct watchdog_device *, unsigned int);
> unsigned int (*get_timeleft)(struct watchdog_device *);
> void (*ref)(struct watchdog_device *);
> void (*unref)(struct watchdog_device *);
> @@ -153,9 +160,19 @@ they are supported. These optional routines/operations are:
> and -EIO for "could not write value to the watchdog". On success this
> routine should set the timeout value of the watchdog_device to the
> achieved timeout value (which may be different from the requested one
> - because the watchdog does not necessarily has a 1 second resolution).
> + because the watchdog does not necessarily has a 1 second resolution;
> + If the driver supports pretimeout, then the timeout value must be greater
> + than that).
> (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the
> watchdog's info structure).
> +* set_pretimeout: this routine checks and changes the pretimeout of the
> + watchdog timer device. It returns 0 on success, -EINVAL for "parameter out of
> + range" and -EIO for "could not write value to the watchdog". On success this
> + routine should set the pretimeout value of the watchdog_device to the
> + achieved pretimeout value (which may be different from the requested one
> + because the watchdog does not necessarily has a 1 second resolution).
> + (Note: the WDIOF_PRETIMEOUT needs to be set in the options field of the
> + watchdog's info structure).
> * get_timeleft: this routines returns the time that's left before a reset.
> * ref: the operation that calls kref_get on the kref of a dynamically
> allocated watchdog_device struct.
> @@ -213,14 +230,41 @@ 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:
> +To initialize the timeout and pretimeout fields, the following function can be
> +used:
>
> -extern int watchdog_init_timeout(struct watchdog_device *wdd,
> - unsigned int timeout_parm, struct device *dev);

I think this API should still be listed here. Drivers not supporting pretimeout
can and should still use it.

> +extern int watchdog_init_timeouts(struct watchdog_device *wdd,
> + unsigned int pretimeout_parm,
> + unsigned int timeout_parm,
> + void (*update_limits)(struct watchdog_device *),
> + 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.
> +The watchdog_init_timeouts function allows you to initialize the pretimeout and
> +timeout fields using the module pretimeout and timeout parameter or by
> +retrieving the elements in the timeout-sec property(the first element is for
> +timeout, the second one is for pretimeout) from the device tree(if the module
> +pretimeout and timeout parameter are invalid).
> +Normally, the pretimeout value will affect the limitation of timeout, and it
> +is also hardware related. So you can write a function in your driver to update
> +the limitation of timeout, according to the pretimeout value. Then pass the
> +function pointer by the update_limits parameter. If you driver doesn't
> +need this adjustment, just pass NULL to the update_limits parameter.

Is there a reason to believe that the update_limits function is necessary and
can not be handled by the set_pretimeout and set_timeout driver functions,
or possibly by the driver itself after calling watchdog_init_timeouts() ?

> +Most of watchdog timers have not pretimeout as the warning signal. They just
> +reset the system, once the timeout watch period expires. In this case, we can
> +pass 0 to the pretimeout_parm, and pass NULL to the update_limits. Or use the
> +old API: watchdog_init_timeout(see below)
> +Best practice is to set the default pretimeout and timeout value as pretimeout
> +and timeout value in the watchdog_device and then use this function to set the
> +user "preferred" pretimeout value.
> This routine returns zero on success and a negative errno code for failure.
> +
> +For backward compatibility, we also support the timeout initialization API:
> +

Why only for backward compatibility ? Why (try to) force new drivers which don't
support pretimeout to use the new API function ?

> +static inline int watchdog_init_timeout(struct watchdog_device *wdd,
> + unsigned int timeout_parm,
> + struct device *dev);
> +
> +Because of the introduction of pretimeout and watchdog_init_timeouts, this
> +function has become a small wrapper function of watchdog_init_timeouts.

The last sentence is irrelevant; how watchdog_init_timeout() is implemented
is an implementation detail, not part of the API.

> +
> +
Empty lines at end of file will cause whitespace errors on merge. Doesn't checkpatch
complain about this ?

> diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
> index cec9b55..460796e 100644
> --- a/drivers/watchdog/watchdog_core.c
> +++ b/drivers/watchdog/watchdog_core.c
> @@ -43,60 +43,115 @@
> static DEFINE_IDA(watchdog_ida);
> static struct class *watchdog_class;
>
> -static void watchdog_check_min_max_timeout(struct watchdog_device *wdd)
> +static void watchdog_check_min_max_timeouts(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)
> + * Check that we have valid min and max pretimeout and timeout values,
> + * if not reset them both to 0 (=not used or unknown)
> */
> + if (wdd->min_pretimeout > wdd->max_pretimeout) {
> + pr_info("Invalid min and max pretimeout, resetting to 0!\n");

Please drop the "!" at the end. While used in the old code, it is unnecessary
and often frowned upon nowadays.

> + wdd->min_pretimeout = 0;
> + wdd->max_pretimeout = 0;
> + }
> 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;
> }
> + /*
> + * Check that we have valid min and max timeout values,
> + * if not reset them both to pretimeout limits
> + */
> + if (wdd->min_pretimeout && wdd->min_timeout < wdd->min_pretimeout) {
> + pr_info("Invalid min timeout, resetting to min pretimeout!\n");
> + wdd->min_timeout = wdd->min_pretimeout;
> + }
> + if (wdd->max_pretimeout && wdd->max_timeout < wdd->max_pretimeout) {
> + pr_info("Invalid max timeout, resetting to max pretimeout!\n");
> + wdd->max_timeout = wdd->max_pretimeout;
> + }
> }
>
> /**
> - * watchdog_init_timeout() - initialize the timeout field
> + * watchdog_init_timeouts() - initialize the pretimeout and timeout field
> + * @pretimeout_parm: pretimeout module parameter
> * @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.
> + * Initialize the pretimeout and timeout field of the watchdog_device struct
> + * with either the pretimeout and timeout module parameter (if it is valid
> + * value) or the timeout-sec property (only if it is a valid value and the
> + * pretimeout_parm and 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.

valid, then we keep ... 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)
> +int watchdog_init_timeouts(struct watchdog_device *wdd,
> + unsigned int pretimeout_parm,
> + unsigned int timeout_parm,
> + void (*update_limits)(struct watchdog_device *),
> + struct device *dev)
> {
> - unsigned int t = 0;
> + unsigned int timeout = 0, pretimeout = 0;
> + const __be32 *ppretimeout;
> int ret = 0;
> + struct property *timeout_sec;
> + int length;
>
> - watchdog_check_min_max_timeout(wdd);
> + watchdog_check_min_max_timeouts(wdd);
>
> - /* try to get the timeout module parameter first */
> - if (!watchdog_timeout_invalid(wdd, timeout_parm) && timeout_parm) {
> - wdd->timeout = timeout_parm;
> - return ret;
> + /* try to get the timeout and pretimeout module parameter first */
> + if (pretimeout_parm) {
> + if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm)) {
> + wdd->pretimeout = pretimeout_parm;
> + if (update_limits)
> + update_limits(wdd);
> + } else {
> + pr_warn("Invalid pretimeout parameter!\n");

We didn't have all this noise earlier. Can we keep it that way ?

> + ret = -EINVAL;
> + }
> }
> - if (timeout_parm)
> +
> + if (timeout_parm) {
> + if (!watchdog_timeout_invalid(wdd, timeout_parm)) {
> + wdd->timeout = timeout_parm;
> + return ret;
> + }
> + pr_warn("Invalid timeout parameter!\n");
> ret = -EINVAL;
> + }
>
> /* try to get the timeout_sec property */
> if (dev == NULL || dev->of_node == NULL)
> return ret;
> - of_property_read_u32(dev->of_node, "timeout-sec", &t);
> - if (!watchdog_timeout_invalid(wdd, t) && t)
> - wdd->timeout = t;
> - else
> +
> + timeout_sec = of_find_property(dev->of_node, "timeout-sec", &length);
> + if (timeout_sec) {
> + ppretimeout = of_prop_next_u32(timeout_sec, NULL, &timeout);

Could you just use of_property_read_u32_array() and pass length as parameter ?

> + if (length == 2) {
> + of_prop_next_u32(timeout_sec, ppretimeout, &pretimeout);
> + if (!watchdog_pretimeout_invalid(wdd, pretimeout) &&
> + pretimeout) {
> + wdd->pretimeout = pretimeout;
> + if (update_limits)
> + update_limits(wdd);
> + } else {
> + ret = -EINVAL;
> + }
> + }
> + if (!watchdog_timeout_invalid(wdd, timeout) && timeout)
> + wdd->timeout = timeout;
> + else
> + ret = -EINVAL;
> + } else {
> ret = -EINVAL;
> + }
>
> return ret;
> }
> -EXPORT_SYMBOL_GPL(watchdog_init_timeout);
> +EXPORT_SYMBOL_GPL(watchdog_init_timeouts);
>
> /**
> * watchdog_register_device() - register a watchdog device
> @@ -119,7 +174,7 @@ int watchdog_register_device(struct watchdog_device *wdd)
> if (wdd->ops->start == NULL || wdd->ops->stop == NULL)
> return -EINVAL;
>
> - watchdog_check_min_max_timeout(wdd);
> + watchdog_check_min_max_timeouts(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 6aaefba..b519257 100644
> --- a/drivers/watchdog/watchdog_dev.c
> +++ b/drivers/watchdog/watchdog_dev.c
> @@ -218,6 +218,38 @@ out_timeout:
> }
>
> /*
> + * watchdog_set_pretimeout: set the watchdog timer pretimeout
> + * @wddev: the watchdog device to set the timeout for
> + * @pretimeout: pretimeout to set in seconds
> + */
> +
> +static int watchdog_set_pretimeout(struct watchdog_device *wddev,
> + unsigned int pretimeout)
> +{
> + int err;
> +
> + if (!wddev->ops->set_pretimeout ||
> + !(wddev->info->options & WDIOF_PRETIMEOUT))
> + return -EOPNOTSUPP;
> +
> + if (watchdog_pretimeout_invalid(wddev, pretimeout))
> + return -EINVAL;
> +
> + mutex_lock(&wddev->lock);
> +
> + if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
> + err = -ENODEV;
> + goto out_pretimeout;
> + }
> +
> + err = wddev->ops->set_pretimeout(wddev, pretimeout);
> +
> +out_pretimeout:
> + mutex_unlock(&wddev->lock);
> + return err;
> +}
> +
> +/*
> * watchdog_get_timeleft: wrapper to get the time left before a reboot
> * @wddev: the watchdog device to get the remaining time from
> * @timeleft: the time that's left
> @@ -388,6 +420,22 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
> if (wdd->timeout == 0)
> return -EOPNOTSUPP;
> return put_user(wdd->timeout, p);
> + case WDIOC_SETPRETIMEOUT:
> + if (get_user(val, p))
> + return -EFAULT;
> + err = watchdog_set_pretimeout(wdd, val);
> + if (err < 0)
> + return err;
> + /* If the watchdog is active then we send a keepalive ping
> + * to make sure that the watchdog keep's running (and if
> + * possible that it takes the new timeout) */

Please use the standard multi-line comment format.

> + watchdog_ping(wdd);
> + /* Fall */
> + case WDIOC_GETPRETIMEOUT:
> + /* timeout == 0 means that we don't use the pretimeout */

pretimeout == 0 means ...

"use" or "know" ?

> + if (wdd->pretimeout == 0)
> + return -EOPNOTSUPP;
> + return put_user(wdd->pretimeout, p);
> case WDIOC_GETTIMELEFT:
> err = watchdog_get_timeleft(wdd, &val);
> if (err)
> diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
> index a746bf5..df430a3 100644
> --- a/include/linux/watchdog.h
> +++ b/include/linux/watchdog.h
> @@ -25,6 +25,7 @@ struct watchdog_device;
> * @ping: The routine that sends a keepalive ping to the watchdog device.
> * @status: The routine that shows the status of the watchdog device.
> * @set_timeout:The routine for setting the watchdog devices timeout value.
> + * @set_pretimeout:The routine for setting the watchdog devices pretimeout value
> * @get_timeleft:The routine that get's the time that's left before a reset.
> * @ref: The ref operation for dyn. allocated watchdog_device structs
> * @unref: The unref operation for dyn. allocated watchdog_device structs
> @@ -44,6 +45,7 @@ struct watchdog_ops {
> int (*ping)(struct watchdog_device *);
> unsigned int (*status)(struct watchdog_device *);
> int (*set_timeout)(struct watchdog_device *, unsigned int);
> + int (*set_pretimeout)(struct watchdog_device *, unsigned int);
> unsigned int (*get_timeleft)(struct watchdog_device *);
> void (*ref)(struct watchdog_device *);
> void (*unref)(struct watchdog_device *);
> @@ -62,6 +64,9 @@ struct watchdog_ops {
> * @timeout: The watchdog devices timeout value.
> * @min_timeout:The watchdog devices minimum timeout value.
> * @max_timeout:The watchdog devices maximum timeout value.
> + * @pretimeout: The watchdog devices pretimeout value.
> + * @min_pretimeout:The watchdog devices minimum pretimeout value.
> + * @max_pretimeout:The watchdog devices maximum pretimeout value.
> * @driver-data:Pointer to the drivers private data.
> * @lock: Lock for watchdog core internal use only.
> * @status: Field that contains the devices internal status bits.
> @@ -86,6 +91,9 @@ struct watchdog_device {
> unsigned int timeout;
> unsigned int min_timeout;
> unsigned int max_timeout;
> + unsigned int pretimeout;
> + unsigned int min_pretimeout;
> + unsigned int max_pretimeout;
> void *driver_data;
> struct mutex lock;
> unsigned long status;
> @@ -120,6 +128,14 @@ static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigne
> (t < wdd->min_timeout || t > wdd->max_timeout));
> }
>
> +/* Use the following function to check if a pretimeout value is invalid */
> +static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd,
> + unsigned int t)
> +{
> + return ((wdd->max_pretimeout != 0) &&

Please drop the unnecessary ( ).

> + (t < wdd->min_pretimeout || t > wdd->max_pretimeout));
> +}
> +
> /* Use the following functions to manipulate watchdog driver specific data */
> static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data)
> {
> @@ -132,11 +148,21 @@ 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_init_timeouts(struct watchdog_device *wdd,
> + unsigned int pretimeout_parm,
> + unsigned int timeout_parm,
> + void (*update_limits)(struct watchdog_device *),
> + struct device *dev);
> extern int watchdog_register_device(struct watchdog_device *);
> extern void watchdog_unregister_device(struct watchdog_device *);
>
> +static inline int watchdog_init_timeout(struct watchdog_device *wdd,
> + unsigned int timeout_parm,
> + struct device *dev)
> +{
> + return watchdog_init_timeouts(wdd, 0, timeout_parm, NULL, dev);
> +}
> +
> #ifdef CONFIG_HARDLOCKUP_DETECTOR
> void watchdog_nmi_disable_all(void);
> void watchdog_nmi_enable_all(void);
>

2015-05-21 10:17:36

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

On 05/21/2015 03:05 AM, Fu Wei wrote:
> Hi Guenter,
>
> Thanks for review. :-)
> feedback inline below
>
> On 21 May 2015 at 17:04, Guenter Roeck <[email protected]> wrote:
>> On 05/21/2015 01:32 AM, [email protected] wrote:
>>>
>>> From: Fu Wei <[email protected]>
>>>
>>> Also update Documentation/watchdog/watchdog-kernel-api.txt to
>>> introduce:
>>> (1)the new elements in the watchdog_device and watchdog_ops struct;
>>> (2)the new API "watchdog_init_timeouts".
>>>
>>> Reasons:
>>> (1)kernel already has two watchdog drivers are using "pretimeout":
>>> drivers/char/ipmi/ipmi_watchdog.c
>>> drivers/watchdog/kempld_wdt.c(but the definition is different)
>>> (2)some other dirvers are going to use this: ARM SBSA Generic Watchdog
>>>
>>> Signed-off-by: Fu Wei <[email protected]>
>>> ---
>>
>>
>> [ ... ]
>>
>>> +extern int watchdog_init_timeouts(struct watchdog_device *wdd,
>>> + unsigned int pretimeout_parm,
>>> + unsigned int timeout_parm,
>>> + void (*update_limits)(struct
>>> watchdog_device *),
>>> + 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.
>>> +The watchdog_init_timeouts function allows you to initialize the
>>> pretimeout and
>>> +timeout fields using the module pretimeout and timeout parameter or by
>>> +retrieving the elements in the timeout-sec property(the first element is
>>> for
>>> +timeout, the second one is for pretimeout) from the device tree(if the
>>> module
>>> +pretimeout and timeout parameter are invalid).
>>> +Normally, the pretimeout value will affect the limitation of timeout, and
>>> it
>>> +is also hardware related. So you can write a function in your driver to
>>> update
>>> +the limitation of timeout, according to the pretimeout value. Then pass
>>> the
>>> +function pointer by the update_limits parameter. If you driver doesn't
>>> +need this adjustment, just pass NULL to the update_limits parameter.
>>
>>
>> You've lost me a bit with the update_limits function.
>> watchdog_init_timeouts()
>> is called from the driver.
>
> yes, that is the help function which will be called from watchdog
> driver, like SBSA watchdog driver
>
>> Why should the function have to call back into
>> the
>> driver to update the parameters which are passed from the driver ?
>
> Let me explain this, please correct me if I misunderstand something.
> According to the concept of "pretimeout" in kernel, the timeout
> contains the pretimeout, like
>
> * Kernel/API: P---------| pretimeout
> * |-------------------------------T timeout
>
> If you set up the value of pretimeout, that means pretimeout
> <min_timeout < timeout < max_timeout < (pretimeout +
> max_timeout_for_1th_stage)
> For min_timeout > pretimeout. if some one setup a timeout like :
> pretimeout > timeout > min_timeout, I think that could be a problem
> For max_timeout < (pretimeout + max_timeout_for_1th_stage), if some
> one setup a timeout like (pretimeout + max_timeout_for_1th_stage) <
> timeout > max_timeout .
>
> I have explained a little in doc, but the adjustment may have
> something to do with hardware, like max_timeout_for_1th_stage(in SBSA
> watchdog , limited by WCV)
>
> maybe this problem wouldn't happen ,if you set up max_timeout to a
> small number. so you can pass NULL to the pointer.
> but I think maybe for other device , that may happen.
>
>> Seems to me the driver can do that calculation first, then call
>> watchdog_init_timeouts() with the result. Am I missing something ?
>
> maybe I am overthinking it :-)
> please correct me
>

I just sent a more complete review. In general I think this problem
(where the driver needs to update timeout limits based on the value of
pretimeout) is very driver specific, and should be kept in the driver.
I would prefer to keep it out of the API if possible.

Unless I am missing something, it should be possible to call the
update_limits function in the driver after calling init_timeouts.

Thanks,
Guenter

2015-05-21 10:34:56

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/21/2015 01:32 AM, [email protected] wrote:
> From: Fu Wei <[email protected]>
>
> This driver bases on linux kernel watchdog framework, and
> use "pretimeout" in the framework. It supports getting timeout and
> pretimeout from parameter and FDT at the driver init stage.
> In first timeout(WS0), the interrupt routine run panic to save
> system context.
>
> Signed-off-by: Fu Wei <[email protected]>
> ---
> drivers/watchdog/Kconfig | 12 ++
> drivers/watchdog/Makefile | 1 +
> drivers/watchdog/sbsa_gwdt.c | 476 +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 489 insertions(+)
> create mode 100644 drivers/watchdog/sbsa_gwdt.c
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index e5e7c55..25a0df1 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -152,6 +152,18 @@ config ARM_SP805_WATCHDOG
> ARM Primecell SP805 Watchdog timer. This will reboot your system when
> the timeout is reached.
>
> +config ARM_SBSA_WATCHDOG
> + tristate "ARM SBSA Generic Watchdog"
> + depends on ARM || ARM64 || COMPILE_TEST
> + depends on ARM_ARCH_TIMER
> + select WATCHDOG_CORE
> + help
> + ARM SBSA Generic Watchdog timer. This has two Watchdog Signals
> + (WS0/WS1), will trigger a warning interrupt(do panic) at the first
> + timeout(WS0); will reboot your system when the second timeout(WS1)
> + is reached.

I think it would be better to keep the WS0/WS1 out of the help text.
It is an implementation detail, and no user will be able to make sense of it.

> + More details: DEN0029B - Server Base System Architecture (SBSA)
> +
> config AT91RM9200_WATCHDOG
> tristate "AT91RM9200 watchdog"
> depends on SOC_AT91RM9200 && MFD_SYSCON
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index 5c19294..471f1b7c 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -30,6 +30,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
>
> # ARM Architecture
> obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o
> +obj-$(CONFIG_ARM_SBSA_WATCHDOG) += sbsa_gwdt.o
> obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
> obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o
> obj-$(CONFIG_CADENCE_WATCHDOG) += cadence_wdt.o
> diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
> new file mode 100644
> index 0000000..4ebe7c3
> --- /dev/null
> +++ b/drivers/watchdog/sbsa_gwdt.c
> @@ -0,0 +1,476 @@
> +/*
> + * SBSA(Server Base System Architecture) Generic Watchdog driver
> + *
> + * Copyright (c) 2015, Linaro Ltd.
> + * Author: Fu Wei <[email protected]>
> + * Suravee Suthikulpanit <[email protected]>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License 2 as published
> + * by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Note: This SBSA Generic watchdog driver is compatible with
> + * the pretimeout concept of Linux kernel.
> + * The timeout and pretimeout are set by the different REGs.
> + * The first watch period is set by writing WCV directly,
> + * that can support more than 10s timeout at the maximum
> + * system counter frequency.
> + * The second watch period is set by WOR(32bit) which will be loaded
> + * automatically by hardware, when WS0 is triggered.
> + * This gives a maximum watch period of around 10s at the maximum
> + * system counter frequency.
> + * The System Counter shall run at maximum of 400MHz.
> + * More details: DEN0029B - Server Base System Architecture (SBSA)
> + *
> + * Kernel/API: P---------| pretimeout
> + * |-------------------------------T timeout
> + * SBSA GWDT: P--WOR---WS1 pretimeout
> + * |-------WCV----------WS0~~~~~~~~T timeout
> + */
> +
> +#include <asm/arch_timer.h>
> +
> +#include <linux/acpi.h>
> +#include <linux/io.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/moduleparam.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/uaccess.h>
> +#include <linux/watchdog.h>
> +
> +/* SBSA Generic Watchdog register definitions */
> +/* refresh frame */
> +#define SBSA_GWDT_WRR 0x000
> +
> +/* control frame */
> +#define SBSA_GWDT_WCS 0x000
> +#define SBSA_GWDT_WOR 0x008
> +#define SBSA_GWDT_WCV_LO 0x010
> +#define SBSA_GWDT_WCV_HI 0x014
> +
> +/* refresh/control frame */
> +#define SBSA_GWDT_W_IIDR 0xfcc
> +#define SBSA_GWDT_IDR 0xfd0
> +
> +/* Watchdog Control and Status Register */
> +#define SBSA_GWDT_WCS_EN BIT(0)
> +#define SBSA_GWDT_WCS_WS0 BIT(1)
> +#define SBSA_GWDT_WCS_WS1 BIT(2)
> +
> +/**
> + * struct sbsa_gwdt - Internal representation of the SBSA GWDT
> + * @wdd: kernel watchdog_device structure
> + * @clk: store the System Counter clock frequency, in Hz.
> + * @refresh_base: Virtual address of the watchdog refresh frame
> + * @control_base: Virtual address of the watchdog control frame
> + */
> +struct sbsa_gwdt {
> + struct watchdog_device wdd;
> + u32 clk;
> + void __iomem *refresh_base;
> + void __iomem *control_base;
> +};
> +
> +#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
> +
> +#define DEFAULT_TIMEOUT 10 /* seconds, the 1st + 2nd watch periods*/
> +#define DEFAULT_PRETIMEOUT 5 /* seconds, the 2nd watch period*/
> +
> +static unsigned int timeout;
> +module_param(timeout, uint, 0);
> +MODULE_PARM_DESC(timeout,
> + "Watchdog timeout in seconds. (>=0, default="
> + __MODULE_STRING(DEFAULT_TIMEOUT) ")");
> +
> +static unsigned int max_timeout = UINT_MAX;
> +module_param(max_timeout, uint, 0);
> +MODULE_PARM_DESC(max_timeout,
> + "Watchdog max timeout in seconds. (>=0, default="
> + __MODULE_STRING(UINT_MAX) ")");
> +
> +static unsigned int pretimeout;
> +module_param(pretimeout, uint, 0);
> +MODULE_PARM_DESC(pretimeout,
> + "Watchdog pretimeout in seconds. (>=0, default="
> + __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
> +
> +static unsigned int max_pretimeout = U32_MAX;
> +module_param(max_pretimeout, uint, 0);
> +MODULE_PARM_DESC(max_pretimeout,
> + "Watchdog max pretimeout in seconds. (>=0, default="
> + __MODULE_STRING(U32_MAX) ")");
> +
> +static bool nowayout = WATCHDOG_NOWAYOUT;
> +module_param(nowayout, bool, S_IRUGO);
> +MODULE_PARM_DESC(nowayout,
> + "Watchdog cannot be stopped once started (default="
> + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
> +
> +/*
> + * Architected system timer support.

Architected ? Sounds a bit odd. Not sure if this comment serves a real purpose.

> + */
> +static void sbsa_gwdt_cf_write(unsigned int reg, u32 val,
> + struct watchdog_device *wdd)
> +{
> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +
> + writel_relaxed(val, gwdt->control_base + reg);
> +}
> +
> +static void sbsa_gwdt_rf_write(unsigned int reg, u32 val,
> + struct watchdog_device *wdd)
> +{
> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +
> + writel_relaxed(val, gwdt->refresh_base + reg);
> +}
> +
> +static u32 sbsa_gwdt_cf_read(unsigned int reg, struct watchdog_device *wdd)
> +{
> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +
> + return readl_relaxed(gwdt->control_base + reg);
> +}
> +
> +/*
> + * help founctions for accessing 64bit WCV register

functions

> + */
> +static u64 sbsa_gwdt_get_wcv(struct watchdog_device *wdd)
> +{
> + u32 wcv_lo, wcv_hi;
> +
> + do {
> + wcv_hi = sbsa_gwdt_cf_read(SBSA_GWDT_WCV_HI, wdd);
> + wcv_lo = sbsa_gwdt_cf_read(SBSA_GWDT_WCV_LO, wdd);
> + } while (wcv_hi != sbsa_gwdt_cf_read(SBSA_GWDT_WCV_HI, wdd));
> +
> + return (((u64)wcv_hi << 32) | wcv_lo);
> +}
> +
> +static void sbsa_gwdt_set_wcv(struct watchdog_device *wdd, u64 value)
> +{
> + u32 wcv_lo, wcv_hi;
> +
> + wcv_lo = value & U32_MAX;
> + wcv_hi = (value >> 32) & U32_MAX;
> +
> + sbsa_gwdt_cf_write(SBSA_GWDT_WCV_HI, wcv_hi, wdd);
> + sbsa_gwdt_cf_write(SBSA_GWDT_WCV_LO, wcv_lo, wdd);
> +}
> +
> +static void reload_timeout_to_wcv(struct watchdog_device *wdd)
> +{
> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> + u64 wcv;
> +
> + wcv = arch_counter_get_cntvct() +
> + (u64)(wdd->timeout - wdd->pretimeout) * gwdt->clk;
> +
> + sbsa_gwdt_set_wcv(wdd, wcv);
> +}
> +
> +/*
> + * Use the following function to set the limit of timeout

s/limit of timeout/timeout limits/

> + * after updating pretimeout
> + */
> +static void sbsa_gwdt_update_limits(struct watchdog_device *wdd)
> +{
> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> + u64 first_period_max = U64_MAX;
> +
> + do_div(first_period_max, gwdt->clk);
> +
> + wdd->min_timeout = wdd->pretimeout + 1;
> + wdd->max_timeout = min((uint)(wdd->pretimeout + first_period_max),
> + wdd->max_timeout);
> +}
> +
> +static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
> + unsigned int timeout)
> +{
> + wdd->timeout = timeout;
> +
> + return 0;
> +}
> +
> +static int sbsa_gwdt_set_pretimeout(struct watchdog_device *wdd,
> + unsigned int pretimeout)
> +{
> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> + u32 wor;
> +
> + wdd->pretimeout = pretimeout;
> + sbsa_gwdt_update_limits(wdd);
> +
> + if (!pretimeout)
> + /* gives sbsa_gwdt_start a chance to setup timeout */
> + wor = gwdt->clk;
> + else
> + wor = pretimeout * gwdt->clk;
> +
> + /* refresh the WOR, that will cause an explicit watchdog refresh */
> + sbsa_gwdt_cf_write(SBSA_GWDT_WOR, wor, wdd);
> +
> + return 0;
> +}
> +
> +static unsigned int sbsa_gwdt_get_timeleft(struct watchdog_device *wdd)
> +{
> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> + u64 timeleft = sbsa_gwdt_get_wcv(wdd) - arch_counter_get_cntvct();
> +

Still not happy about the use of arch_counter_get_cntvct
instead of using the clock subsystem. I am quite sure this could be done,
possibly through arch_sys_counter, though at this point I am getting wary
of bringing it up, so I guess I'll just let it go.

> + do_div(timeleft, gwdt->clk);
> +
> + return timeleft;
> +}
> +
> +static int sbsa_gwdt_start(struct watchdog_device *wdd)
> +{
> + /* Force refresh */
> + sbsa_gwdt_rf_write(SBSA_GWDT_WRR, 0xc0ffee, wdd);
> + /* writing WCS will cause an explicit watchdog refresh */
> + sbsa_gwdt_cf_write(SBSA_GWDT_WCS, SBSA_GWDT_WCS_EN, wdd);
> +
> + reload_timeout_to_wcv(wdd);
> +
> + return 0;
> +}
> +
> +static int sbsa_gwdt_stop(struct watchdog_device *wdd)
> +{
> + /* Force refresh */
> + sbsa_gwdt_rf_write(SBSA_GWDT_WRR, 0xc0ffee, wdd);
> + /* writing WCS will cause an explicit watchdog refresh */
> + sbsa_gwdt_cf_write(SBSA_GWDT_WCS, 0, wdd);
> +
> + return 0;
> +}
> +
> +static int sbsa_gwdt_keepalive(struct watchdog_device *wdd)
> +{
> + /*
> + * Writing WRR for an explicit watchdog refresh
> + * You can write anyting(like 0xc0ffee)
> + */
> + sbsa_gwdt_rf_write(SBSA_GWDT_WRR, 0xc0ffee, wdd);
> +
> + reload_timeout_to_wcv(wdd);
> +
> + return 0;
> +}
> +
> +static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
> +{
> + struct sbsa_gwdt *gwdt = (struct sbsa_gwdt *)dev_id;
> + struct watchdog_device *wdd = &gwdt->wdd;
> + u32 status;
> +
> + status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
> +
> + if (status & SBSA_GWDT_WCS_WS0)
> + panic("SBSA Watchdog pre-timeout");
> +
> + return IRQ_HANDLED;
> +}
> +
> +static struct watchdog_info sbsa_gwdt_info = {
> + .identity = "SBSA Generic Watchdog",
> + .options = WDIOF_SETTIMEOUT |
> + WDIOF_KEEPALIVEPING |
> + WDIOF_MAGICCLOSE |
> + WDIOF_PRETIMEOUT |
> + WDIOF_CARDRESET,
> +};
> +
> +static struct watchdog_ops sbsa_gwdt_ops = {
> + .owner = THIS_MODULE,
> + .start = sbsa_gwdt_start,
> + .stop = sbsa_gwdt_stop,
> + .ping = sbsa_gwdt_keepalive,
> + .set_timeout = sbsa_gwdt_set_timeout,
> + .set_pretimeout = sbsa_gwdt_set_pretimeout,
> + .get_timeleft = sbsa_gwdt_get_timeleft,
> +};
> +
> +static int sbsa_gwdt_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct sbsa_gwdt *gwdt;
> + struct watchdog_device *wdd;
> + struct resource *res;
> + void *rf_base, *cf_base;
> + int irq;
> + u32 clk, status;
> + int ret = 0;
> + u64 first_period_max = U64_MAX;
> +
> + /*
> + * Try to determine the frequency from the arch_timer interface
> + */
> + clk = arch_timer_get_rate();

arch_timer_get_rate() does not seem to be exported. Did you try to build
the driver as module ?

> + if (!clk) {
> + dev_err(dev, "System Counter frequency not available\n");
> + return -EINVAL;
> + }
> +
> + gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
> + if (!gwdt)
> + return -ENOMEM;
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "refresh");
> + rf_base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(rf_base))
> + return PTR_ERR(rf_base);
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control");
> + cf_base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(rf_base))
> + return PTR_ERR(rf_base);
> +
> + irq = platform_get_irq_byname(pdev, "ws0");
> + if (irq < 0) {
> + dev_err(dev, "unable to get ws0 interrupt.\n");
> + return irq;
> + }
> +
> + gwdt->refresh_base = rf_base;
> + gwdt->control_base = cf_base;
> + gwdt->clk = clk;
> +
> + platform_set_drvdata(pdev, gwdt);
> +
> + wdd = &gwdt->wdd;
> + wdd->parent = dev;
> + wdd->info = &sbsa_gwdt_info;
> + wdd->ops = &sbsa_gwdt_ops;
> + watchdog_set_drvdata(wdd, gwdt);
> + watchdog_set_nowayout(wdd, nowayout);
> +
> + status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
> + if (status & SBSA_GWDT_WCS_WS1) {
> + dev_warn(dev, "System reset by WDT(WCS: %x, WCV: %llx)\n",
> + status, sbsa_gwdt_get_wcv(wdd));
> + wdd->bootstatus |= WDIOF_CARDRESET;
> + }
> + /* Check if watchdog is already enabled */
> + if (status & SBSA_GWDT_WCS_EN) {
> + dev_warn(dev, "already enabled! WCS:0x%x\n", status);
> + sbsa_gwdt_keepalive(wdd);
> + }
> +
> + wdd->min_pretimeout = 0;
> + wdd->max_pretimeout = min(U32_MAX / clk, max_pretimeout);
> + wdd->min_timeout = 1;
> + do_div(first_period_max, clk);
> + wdd->max_timeout = min((uint)(wdd->pretimeout + first_period_max),
> + max_timeout);
> +
> + wdd->pretimeout = DEFAULT_PRETIMEOUT;
> + wdd->timeout = DEFAULT_TIMEOUT;
> + watchdog_init_timeouts(wdd, pretimeout, timeout,
> + sbsa_gwdt_update_limits, dev);
> + /* update pretimeout to WOR */
> + sbsa_gwdt_cf_write(SBSA_GWDT_WOR, wdd->pretimeout * clk, wdd);
> +
> + ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, IRQF_TIMER,
> + pdev->name, gwdt);
> + if (ret) {
> + dev_err(dev, "unable to request IRQ %d\n", irq);
> + return ret;
> + }
> +
> + ret = watchdog_register_device(wdd);
> + if (ret)
> + return ret;
> +
> + dev_info(dev, "Initialized with %ds timeout, %ds pretimeout @ %uHz\n",
> + wdd->timeout, wdd->pretimeout, gwdt->clk);
> +
> + return 0;
> +}
> +
> +static void sbsa_gwdt_shutdown(struct platform_device *pdev)
> +{
> + struct sbsa_gwdt *gwdt = platform_get_drvdata(pdev);
> +
> + sbsa_gwdt_stop(&gwdt->wdd);
> +}
> +
> +static int sbsa_gwdt_remove(struct platform_device *pdev)
> +{
> + struct sbsa_gwdt *gwdt = platform_get_drvdata(pdev);
> + int ret = 0;
> +
> + if (!nowayout)
> + ret = sbsa_gwdt_stop(&gwdt->wdd);
> +
> + watchdog_unregister_device(&gwdt->wdd);
> +
> + return ret;
> +}
> +
> +/* Disable watchdog if it is active during suspend */
> +static int __maybe_unused sbsa_gwdt_suspend(struct device *dev)
> +{
> + struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
> +
> + if (watchdog_active(&gwdt->wdd))
> + sbsa_gwdt_stop(&gwdt->wdd);
> +
> + return 0;
> +}
> +
> +/* Enable watchdog and configure it if necessary */
> +static int __maybe_unused sbsa_gwdt_resume(struct device *dev)
> +{
> + struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
> +
> + if (watchdog_active(&gwdt->wdd))
> + sbsa_gwdt_start(&gwdt->wdd);
> +
> + return 0;
> +}
> +
> +static const struct dev_pm_ops sbsa_gwdt_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(sbsa_gwdt_suspend, sbsa_gwdt_resume)
> +};
> +
> +static const struct of_device_id sbsa_gwdt_of_match[] = {
> + { .compatible = "arm,sbsa-gwdt", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, sbsa_gwdt_of_match);
> +
> +static const struct platform_device_id sbsa_gwdt_pdev_match[] = {
> + { .name = "sbsa-gwdt", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(platform, sbsa_gwdt_pdev_match);
> +
> +static struct platform_driver sbsa_gwdt_driver = {
> + .driver = {
> + .name = "sbsa-gwdt",
> + .pm = &sbsa_gwdt_pm_ops,
> + .of_match_table = sbsa_gwdt_of_match,
> + },
> + .probe = sbsa_gwdt_probe,
> + .remove = sbsa_gwdt_remove,
> + .shutdown = sbsa_gwdt_shutdown,
> + .id_table = sbsa_gwdt_pdev_match,
> +};
> +
> +module_platform_driver(sbsa_gwdt_driver);
> +
> +MODULE_DESCRIPTION("SBSA Generic Watchdog Driver");
> +MODULE_VERSION("v1.0");
> +MODULE_AUTHOR("Fu Wei <[email protected]>");
> +MODULE_AUTHOR("Suravee Suthikulpanit <[email protected]>");
> +MODULE_LICENSE("GPL v2");
>

2015-05-21 10:51:01

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

Hi Guenter,

Great thanks, I have got your review feedback, I will fix the problems :-)
For update_limits, I also don't want to have that in the watchdog
driver, and you can't find it in my last version.
And this version, I integrate the watchdog_init_timeout and
watchdog_init_pretimeout. so I can not add a driver specific
"update_limits" between them.
I think maybe we can not make this "update_limits" after calling
init_timeouts, because we need to test and verify the timeout setting
right after init_pretimeout by max_timeout and min_timeout. that is
why I call update_limits right after init_pretimeout and before
init_timeout.

any suggestion ? Great thanks ! :-)

On 21 May 2015 at 18:17, Guenter Roeck <[email protected]> wrote:
> On 05/21/2015 03:05 AM, Fu Wei wrote:
>>
>> Hi Guenter,
>>
>> Thanks for review. :-)
>> feedback inline below
>>
>> On 21 May 2015 at 17:04, Guenter Roeck <[email protected]> wrote:
>>>
>>> On 05/21/2015 01:32 AM, [email protected] wrote:
>>>>
>>>>
>>>> From: Fu Wei <[email protected]>
>>>>
>>>> Also update Documentation/watchdog/watchdog-kernel-api.txt to
>>>> introduce:
>>>> (1)the new elements in the watchdog_device and watchdog_ops struct;
>>>> (2)the new API "watchdog_init_timeouts".
>>>>
>>>> Reasons:
>>>> (1)kernel already has two watchdog drivers are using "pretimeout":
>>>> drivers/char/ipmi/ipmi_watchdog.c
>>>> drivers/watchdog/kempld_wdt.c(but the definition is different)
>>>> (2)some other dirvers are going to use this: ARM SBSA Generic Watchdog
>>>>
>>>> Signed-off-by: Fu Wei <[email protected]>
>>>> ---
>>>
>>>
>>>
>>> [ ... ]
>>>
>>>> +extern int watchdog_init_timeouts(struct watchdog_device *wdd,
>>>> + unsigned int pretimeout_parm,
>>>> + unsigned int timeout_parm,
>>>> + void (*update_limits)(struct
>>>> watchdog_device *),
>>>> + 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.
>>>> +The watchdog_init_timeouts function allows you to initialize the
>>>> pretimeout and
>>>> +timeout fields using the module pretimeout and timeout parameter or by
>>>> +retrieving the elements in the timeout-sec property(the first element
>>>> is
>>>> for
>>>> +timeout, the second one is for pretimeout) from the device tree(if the
>>>> module
>>>> +pretimeout and timeout parameter are invalid).
>>>> +Normally, the pretimeout value will affect the limitation of timeout,
>>>> and
>>>> it
>>>> +is also hardware related. So you can write a function in your driver to
>>>> update
>>>> +the limitation of timeout, according to the pretimeout value. Then pass
>>>> the
>>>> +function pointer by the update_limits parameter. If you driver doesn't
>>>> +need this adjustment, just pass NULL to the update_limits parameter.
>>>
>>>
>>>
>>> You've lost me a bit with the update_limits function.
>>> watchdog_init_timeouts()
>>> is called from the driver.
>>
>>
>> yes, that is the help function which will be called from watchdog
>> driver, like SBSA watchdog driver
>>
>>> Why should the function have to call back into
>>> the
>>> driver to update the parameters which are passed from the driver ?
>>
>>
>> Let me explain this, please correct me if I misunderstand something.
>> According to the concept of "pretimeout" in kernel, the timeout
>> contains the pretimeout, like
>>
>> * Kernel/API: P---------| pretimeout
>> * |-------------------------------T timeout
>>
>> If you set up the value of pretimeout, that means pretimeout
>> <min_timeout < timeout < max_timeout < (pretimeout +
>> max_timeout_for_1th_stage)
>> For min_timeout > pretimeout. if some one setup a timeout like :
>> pretimeout > timeout > min_timeout, I think that could be a problem
>> For max_timeout < (pretimeout + max_timeout_for_1th_stage), if some
>> one setup a timeout like (pretimeout + max_timeout_for_1th_stage) <
>> timeout > max_timeout .
>>
>> I have explained a little in doc, but the adjustment may have
>> something to do with hardware, like max_timeout_for_1th_stage(in SBSA
>> watchdog , limited by WCV)
>>
>> maybe this problem wouldn't happen ,if you set up max_timeout to a
>> small number. so you can pass NULL to the pointer.
>> but I think maybe for other device , that may happen.
>>
>>> Seems to me the driver can do that calculation first, then call
>>> watchdog_init_timeouts() with the result. Am I missing something ?
>>
>>
>> maybe I am overthinking it :-)
>> please correct me
>>
>
> I just sent a more complete review. In general I think this problem
> (where the driver needs to update timeout limits based on the value of
> pretimeout) is very driver specific, and should be kept in the driver.
> I would prefer to keep it out of the API if possible.
>
> Unless I am missing something, it should be possible to call the
> update_limits function in the driver after calling init_timeouts.
>
> Thanks,
> Guenter
>



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-21 11:08:38

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Guenter,

Thanks for review :-)

On 21 May 2015 at 18:34, Guenter Roeck <[email protected]> wrote:
> On 05/21/2015 01:32 AM, [email protected] wrote:
>>
>> From: Fu Wei <[email protected]>
>>
>> This driver bases on linux kernel watchdog framework, and
>> use "pretimeout" in the framework. It supports getting timeout and
>> pretimeout from parameter and FDT at the driver init stage.
>> In first timeout(WS0), the interrupt routine run panic to save
>> system context.
>>
>> Signed-off-by: Fu Wei <[email protected]>
>> ---
>> drivers/watchdog/Kconfig | 12 ++
>> drivers/watchdog/Makefile | 1 +
>> drivers/watchdog/sbsa_gwdt.c | 476
>> +++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 489 insertions(+)
>> create mode 100644 drivers/watchdog/sbsa_gwdt.c
>>
>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>> index e5e7c55..25a0df1 100644
>> --- a/drivers/watchdog/Kconfig
>> +++ b/drivers/watchdog/Kconfig
>> @@ -152,6 +152,18 @@ config ARM_SP805_WATCHDOG
>> ARM Primecell SP805 Watchdog timer. This will reboot your system
>> when
>> the timeout is reached.
>>
>> +config ARM_SBSA_WATCHDOG
>> + tristate "ARM SBSA Generic Watchdog"
>> + depends on ARM || ARM64 || COMPILE_TEST
>> + depends on ARM_ARCH_TIMER
>> + select WATCHDOG_CORE
>> + help
>> + ARM SBSA Generic Watchdog timer. This has two Watchdog Signals
>> + (WS0/WS1), will trigger a warning interrupt(do panic) at the
>> first
>> + timeout(WS0); will reboot your system when the second
>> timeout(WS1)
>> + is reached.
>
>
> I think it would be better to keep the WS0/WS1 out of the help text.
> It is an implementation detail, and no user will be able to make sense of
> it.

I don't mind to delete it , but those are in SBSA spec, is that an
implementation detail ?

Sorry , just try to re-confirm it :-)

>
>
>> + More details: DEN0029B - Server Base System Architecture (SBSA)
>> +
>> config AT91RM9200_WATCHDOG
>> tristate "AT91RM9200 watchdog"
>> depends on SOC_AT91RM9200 && MFD_SYSCON
>> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
>> index 5c19294..471f1b7c 100644
>> --- a/drivers/watchdog/Makefile
>> +++ b/drivers/watchdog/Makefile
>> @@ -30,6 +30,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
>>
>> # ARM Architecture
>> obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o
>> +obj-$(CONFIG_ARM_SBSA_WATCHDOG) += sbsa_gwdt.o
>> obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
>> obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o
>> obj-$(CONFIG_CADENCE_WATCHDOG) += cadence_wdt.o
>> diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
>> new file mode 100644
>> index 0000000..4ebe7c3
>> --- /dev/null
>> +++ b/drivers/watchdog/sbsa_gwdt.c
>> @@ -0,0 +1,476 @@
>> +/*
>> + * SBSA(Server Base System Architecture) Generic Watchdog driver
>> + *
>> + * Copyright (c) 2015, Linaro Ltd.
>> + * Author: Fu Wei <[email protected]>
>> + * Suravee Suthikulpanit <[email protected]>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License 2 as published
>> + * by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * Note: This SBSA Generic watchdog driver is compatible with
>> + * the pretimeout concept of Linux kernel.
>> + * The timeout and pretimeout are set by the different REGs.
>> + * The first watch period is set by writing WCV directly,
>> + * that can support more than 10s timeout at the maximum
>> + * system counter frequency.
>> + * The second watch period is set by WOR(32bit) which will be
>> loaded
>> + * automatically by hardware, when WS0 is triggered.
>> + * This gives a maximum watch period of around 10s at the maximum
>> + * system counter frequency.
>> + * The System Counter shall run at maximum of 400MHz.
>> + * More details: DEN0029B - Server Base System Architecture (SBSA)
>> + *
>> + * Kernel/API: P---------| pretimeout
>> + * |-------------------------------T timeout
>> + * SBSA GWDT: P--WOR---WS1 pretimeout
>> + * |-------WCV----------WS0~~~~~~~~T timeout
>> + */
>> +
>> +#include <asm/arch_timer.h>
>> +
>> +#include <linux/acpi.h>
>> +#include <linux/io.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/module.h>
>> +#include <linux/moduleparam.h>
>> +#include <linux/of.h>
>> +#include <linux/of_device.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/uaccess.h>
>> +#include <linux/watchdog.h>
>> +
>> +/* SBSA Generic Watchdog register definitions */
>> +/* refresh frame */
>> +#define SBSA_GWDT_WRR 0x000
>> +
>> +/* control frame */
>> +#define SBSA_GWDT_WCS 0x000
>> +#define SBSA_GWDT_WOR 0x008
>> +#define SBSA_GWDT_WCV_LO 0x010
>> +#define SBSA_GWDT_WCV_HI 0x014
>> +
>> +/* refresh/control frame */
>> +#define SBSA_GWDT_W_IIDR 0xfcc
>> +#define SBSA_GWDT_IDR 0xfd0
>> +
>> +/* Watchdog Control and Status Register */
>> +#define SBSA_GWDT_WCS_EN BIT(0)
>> +#define SBSA_GWDT_WCS_WS0 BIT(1)
>> +#define SBSA_GWDT_WCS_WS1 BIT(2)
>> +
>> +/**
>> + * struct sbsa_gwdt - Internal representation of the SBSA GWDT
>> + * @wdd: kernel watchdog_device structure
>> + * @clk: store the System Counter clock frequency, in Hz.
>> + * @refresh_base: Virtual address of the watchdog refresh frame
>> + * @control_base: Virtual address of the watchdog control frame
>> + */
>> +struct sbsa_gwdt {
>> + struct watchdog_device wdd;
>> + u32 clk;
>> + void __iomem *refresh_base;
>> + void __iomem *control_base;
>> +};
>> +
>> +#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
>> +
>> +#define DEFAULT_TIMEOUT 10 /* seconds, the 1st + 2nd watch
>> periods*/
>> +#define DEFAULT_PRETIMEOUT 5 /* seconds, the 2nd watch period*/
>> +
>> +static unsigned int timeout;
>> +module_param(timeout, uint, 0);
>> +MODULE_PARM_DESC(timeout,
>> + "Watchdog timeout in seconds. (>=0, default="
>> + __MODULE_STRING(DEFAULT_TIMEOUT) ")");
>> +
>> +static unsigned int max_timeout = UINT_MAX;
>> +module_param(max_timeout, uint, 0);
>> +MODULE_PARM_DESC(max_timeout,
>> + "Watchdog max timeout in seconds. (>=0, default="
>> + __MODULE_STRING(UINT_MAX) ")");
>> +
>> +static unsigned int pretimeout;
>> +module_param(pretimeout, uint, 0);
>> +MODULE_PARM_DESC(pretimeout,
>> + "Watchdog pretimeout in seconds. (>=0, default="
>> + __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
>> +
>> +static unsigned int max_pretimeout = U32_MAX;
>> +module_param(max_pretimeout, uint, 0);
>> +MODULE_PARM_DESC(max_pretimeout,
>> + "Watchdog max pretimeout in seconds. (>=0, default="
>> + __MODULE_STRING(U32_MAX) ")");
>> +
>> +static bool nowayout = WATCHDOG_NOWAYOUT;
>> +module_param(nowayout, bool, S_IRUGO);
>> +MODULE_PARM_DESC(nowayout,
>> + "Watchdog cannot be stopped once started (default="
>> + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
>> +
>> +/*
>> + * Architected system timer support.
>
>
> Architected ? Sounds a bit odd. Not sure if this comment serves a real
> purpose.

Ah, sorry , this is comment is a legacy , will update it . :-)

>
>
>> + */
>> +static void sbsa_gwdt_cf_write(unsigned int reg, u32 val,
>> + struct watchdog_device *wdd)
>> +{
>> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> +
>> + writel_relaxed(val, gwdt->control_base + reg);
>> +}
>> +
>> +static void sbsa_gwdt_rf_write(unsigned int reg, u32 val,
>> + struct watchdog_device *wdd)
>> +{
>> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> +
>> + writel_relaxed(val, gwdt->refresh_base + reg);
>> +}
>> +
>> +static u32 sbsa_gwdt_cf_read(unsigned int reg, struct watchdog_device
>> *wdd)
>> +{
>> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> +
>> + return readl_relaxed(gwdt->control_base + reg);
>> +}
>> +
>> +/*
>> + * help founctions for accessing 64bit WCV register
>
>
> functions

Ah , typo , sorry

>
>
>> + */
>> +static u64 sbsa_gwdt_get_wcv(struct watchdog_device *wdd)
>> +{
>> + u32 wcv_lo, wcv_hi;
>> +
>> + do {
>> + wcv_hi = sbsa_gwdt_cf_read(SBSA_GWDT_WCV_HI, wdd);
>> + wcv_lo = sbsa_gwdt_cf_read(SBSA_GWDT_WCV_LO, wdd);
>> + } while (wcv_hi != sbsa_gwdt_cf_read(SBSA_GWDT_WCV_HI, wdd));
>> +
>> + return (((u64)wcv_hi << 32) | wcv_lo);
>> +}
>> +
>> +static void sbsa_gwdt_set_wcv(struct watchdog_device *wdd, u64 value)
>> +{
>> + u32 wcv_lo, wcv_hi;
>> +
>> + wcv_lo = value & U32_MAX;
>> + wcv_hi = (value >> 32) & U32_MAX;
>> +
>> + sbsa_gwdt_cf_write(SBSA_GWDT_WCV_HI, wcv_hi, wdd);
>> + sbsa_gwdt_cf_write(SBSA_GWDT_WCV_LO, wcv_lo, wdd);
>> +}
>> +
>> +static void reload_timeout_to_wcv(struct watchdog_device *wdd)
>> +{
>> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> + u64 wcv;
>> +
>> + wcv = arch_counter_get_cntvct() +
>> + (u64)(wdd->timeout - wdd->pretimeout) * gwdt->clk;
>> +
>> + sbsa_gwdt_set_wcv(wdd, wcv);
>> +}
>> +
>> +/*
>> + * Use the following function to set the limit of timeout
>
>
> s/limit of timeout/timeout limits/

Thanks , will fix it

>
>
>> + * after updating pretimeout
>> + */
>> +static void sbsa_gwdt_update_limits(struct watchdog_device *wdd)
>> +{
>> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> + u64 first_period_max = U64_MAX;
>> +
>> + do_div(first_period_max, gwdt->clk);
>> +
>> + wdd->min_timeout = wdd->pretimeout + 1;
>> + wdd->max_timeout = min((uint)(wdd->pretimeout + first_period_max),
>> + wdd->max_timeout);
>> +}
>> +
>> +static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
>> + unsigned int timeout)
>> +{
>> + wdd->timeout = timeout;
>> +
>> + return 0;
>> +}
>> +
>> +static int sbsa_gwdt_set_pretimeout(struct watchdog_device *wdd,
>> + unsigned int pretimeout)
>> +{
>> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> + u32 wor;
>> +
>> + wdd->pretimeout = pretimeout;
>> + sbsa_gwdt_update_limits(wdd);
>> +
>> + if (!pretimeout)
>> + /* gives sbsa_gwdt_start a chance to setup timeout */
>> + wor = gwdt->clk;
>> + else
>> + wor = pretimeout * gwdt->clk;
>> +
>> + /* refresh the WOR, that will cause an explicit watchdog refresh
>> */
>> + sbsa_gwdt_cf_write(SBSA_GWDT_WOR, wor, wdd);
>> +
>> + return 0;
>> +}
>> +
>> +static unsigned int sbsa_gwdt_get_timeleft(struct watchdog_device *wdd)
>> +{
>> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> + u64 timeleft = sbsa_gwdt_get_wcv(wdd) - arch_counter_get_cntvct();
>> +
>
>
> Still not happy about the use of arch_counter_get_cntvct
> instead of using the clock subsystem. I am quite sure this could be done,
> possibly through arch_sys_counter, though at this point I am getting wary
> of bringing it up, so I guess I'll just let it go.

yes, It is the code I should check again, will sent more feedback
once I get better idea


>
>
>> + do_div(timeleft, gwdt->clk);
>> +
>> + return timeleft;
>> +}
>> +
>> +static int sbsa_gwdt_start(struct watchdog_device *wdd)
>> +{
>> + /* Force refresh */
>> + sbsa_gwdt_rf_write(SBSA_GWDT_WRR, 0xc0ffee, wdd);
>> + /* writing WCS will cause an explicit watchdog refresh */
>> + sbsa_gwdt_cf_write(SBSA_GWDT_WCS, SBSA_GWDT_WCS_EN, wdd);
>> +
>> + reload_timeout_to_wcv(wdd);
>> +
>> + return 0;
>> +}
>> +
>> +static int sbsa_gwdt_stop(struct watchdog_device *wdd)
>> +{
>> + /* Force refresh */
>> + sbsa_gwdt_rf_write(SBSA_GWDT_WRR, 0xc0ffee, wdd);
>> + /* writing WCS will cause an explicit watchdog refresh */
>> + sbsa_gwdt_cf_write(SBSA_GWDT_WCS, 0, wdd);
>> +
>> + return 0;
>> +}
>> +
>> +static int sbsa_gwdt_keepalive(struct watchdog_device *wdd)
>> +{
>> + /*
>> + * Writing WRR for an explicit watchdog refresh
>> + * You can write anyting(like 0xc0ffee)
>> + */
>> + sbsa_gwdt_rf_write(SBSA_GWDT_WRR, 0xc0ffee, wdd);
>> +
>> + reload_timeout_to_wcv(wdd);
>> +
>> + return 0;
>> +}
>> +
>> +static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
>> +{
>> + struct sbsa_gwdt *gwdt = (struct sbsa_gwdt *)dev_id;
>> + struct watchdog_device *wdd = &gwdt->wdd;
>> + u32 status;
>> +
>> + status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
>> +
>> + if (status & SBSA_GWDT_WCS_WS0)
>> + panic("SBSA Watchdog pre-timeout");
>> +
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static struct watchdog_info sbsa_gwdt_info = {
>> + .identity = "SBSA Generic Watchdog",
>> + .options = WDIOF_SETTIMEOUT |
>> + WDIOF_KEEPALIVEPING |
>> + WDIOF_MAGICCLOSE |
>> + WDIOF_PRETIMEOUT |
>> + WDIOF_CARDRESET,
>> +};
>> +
>> +static struct watchdog_ops sbsa_gwdt_ops = {
>> + .owner = THIS_MODULE,
>> + .start = sbsa_gwdt_start,
>> + .stop = sbsa_gwdt_stop,
>> + .ping = sbsa_gwdt_keepalive,
>> + .set_timeout = sbsa_gwdt_set_timeout,
>> + .set_pretimeout = sbsa_gwdt_set_pretimeout,
>> + .get_timeleft = sbsa_gwdt_get_timeleft,
>> +};
>> +
>> +static int sbsa_gwdt_probe(struct platform_device *pdev)
>> +{
>> + struct device *dev = &pdev->dev;
>> + struct sbsa_gwdt *gwdt;
>> + struct watchdog_device *wdd;
>> + struct resource *res;
>> + void *rf_base, *cf_base;
>> + int irq;
>> + u32 clk, status;
>> + int ret = 0;
>> + u64 first_period_max = U64_MAX;
>> +
>> + /*
>> + * Try to determine the frequency from the arch_timer interface
>> + */
>> + clk = arch_timer_get_rate();
>
>
> arch_timer_get_rate() does not seem to be exported. Did you try to build
> the driver as module ?

yes, I have built it as a ko module, that is why I made a patch to
export this interface in the first patch of this patchset

but I will confirm it again :-)

>
>
>> + if (!clk) {
>> + dev_err(dev, "System Counter frequency not available\n");
>> + return -EINVAL;
>> + }
>> +
>> + gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
>> + if (!gwdt)
>> + return -ENOMEM;
>> +
>> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>> "refresh");
>> + rf_base = devm_ioremap_resource(dev, res);
>> + if (IS_ERR(rf_base))
>> + return PTR_ERR(rf_base);
>> +
>> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>> "control");
>> + cf_base = devm_ioremap_resource(dev, res);
>> + if (IS_ERR(rf_base))
>> + return PTR_ERR(rf_base);
>> +
>> + irq = platform_get_irq_byname(pdev, "ws0");
>> + if (irq < 0) {
>> + dev_err(dev, "unable to get ws0 interrupt.\n");
>> + return irq;
>> + }
>> +
>> + gwdt->refresh_base = rf_base;
>> + gwdt->control_base = cf_base;
>> + gwdt->clk = clk;
>> +
>> + platform_set_drvdata(pdev, gwdt);
>> +
>> + wdd = &gwdt->wdd;
>> + wdd->parent = dev;
>> + wdd->info = &sbsa_gwdt_info;
>> + wdd->ops = &sbsa_gwdt_ops;
>> + watchdog_set_drvdata(wdd, gwdt);
>> + watchdog_set_nowayout(wdd, nowayout);
>> +
>> + status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
>> + if (status & SBSA_GWDT_WCS_WS1) {
>> + dev_warn(dev, "System reset by WDT(WCS: %x, WCV: %llx)\n",
>> + status, sbsa_gwdt_get_wcv(wdd));
>> + wdd->bootstatus |= WDIOF_CARDRESET;
>> + }
>> + /* Check if watchdog is already enabled */
>> + if (status & SBSA_GWDT_WCS_EN) {
>> + dev_warn(dev, "already enabled! WCS:0x%x\n", status);
>> + sbsa_gwdt_keepalive(wdd);
>> + }
>> +
>> + wdd->min_pretimeout = 0;
>> + wdd->max_pretimeout = min(U32_MAX / clk, max_pretimeout);
>> + wdd->min_timeout = 1;
>> + do_div(first_period_max, clk);
>> + wdd->max_timeout = min((uint)(wdd->pretimeout + first_period_max),
>> + max_timeout);
>> +
>> + wdd->pretimeout = DEFAULT_PRETIMEOUT;
>> + wdd->timeout = DEFAULT_TIMEOUT;
>> + watchdog_init_timeouts(wdd, pretimeout, timeout,
>> + sbsa_gwdt_update_limits, dev);
>> + /* update pretimeout to WOR */
>> + sbsa_gwdt_cf_write(SBSA_GWDT_WOR, wdd->pretimeout * clk, wdd);
>> +
>> + ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, IRQF_TIMER,
>> + pdev->name, gwdt);
>> + if (ret) {
>> + dev_err(dev, "unable to request IRQ %d\n", irq);
>> + return ret;
>> + }
>> +
>> + ret = watchdog_register_device(wdd);
>> + if (ret)
>> + return ret;
>> +
>> + dev_info(dev, "Initialized with %ds timeout, %ds pretimeout @
>> %uHz\n",
>> + wdd->timeout, wdd->pretimeout, gwdt->clk);
>> +
>> + return 0;
>> +}
>> +
>> +static void sbsa_gwdt_shutdown(struct platform_device *pdev)
>> +{
>> + struct sbsa_gwdt *gwdt = platform_get_drvdata(pdev);
>> +
>> + sbsa_gwdt_stop(&gwdt->wdd);
>> +}
>> +
>> +static int sbsa_gwdt_remove(struct platform_device *pdev)
>> +{
>> + struct sbsa_gwdt *gwdt = platform_get_drvdata(pdev);
>> + int ret = 0;
>> +
>> + if (!nowayout)
>> + ret = sbsa_gwdt_stop(&gwdt->wdd);
>> +
>> + watchdog_unregister_device(&gwdt->wdd);
>> +
>> + return ret;
>> +}
>> +
>> +/* Disable watchdog if it is active during suspend */
>> +static int __maybe_unused sbsa_gwdt_suspend(struct device *dev)
>> +{
>> + struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
>> +
>> + if (watchdog_active(&gwdt->wdd))
>> + sbsa_gwdt_stop(&gwdt->wdd);
>> +
>> + return 0;
>> +}
>> +
>> +/* Enable watchdog and configure it if necessary */
>> +static int __maybe_unused sbsa_gwdt_resume(struct device *dev)
>> +{
>> + struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
>> +
>> + if (watchdog_active(&gwdt->wdd))
>> + sbsa_gwdt_start(&gwdt->wdd);
>> +
>> + return 0;
>> +}
>> +
>> +static const struct dev_pm_ops sbsa_gwdt_pm_ops = {
>> + SET_SYSTEM_SLEEP_PM_OPS(sbsa_gwdt_suspend, sbsa_gwdt_resume)
>> +};
>> +
>> +static const struct of_device_id sbsa_gwdt_of_match[] = {
>> + { .compatible = "arm,sbsa-gwdt", },
>> + {},
>> +};
>> +MODULE_DEVICE_TABLE(of, sbsa_gwdt_of_match);
>> +
>> +static const struct platform_device_id sbsa_gwdt_pdev_match[] = {
>> + { .name = "sbsa-gwdt", },
>> + {},
>> +};
>> +MODULE_DEVICE_TABLE(platform, sbsa_gwdt_pdev_match);
>> +
>> +static struct platform_driver sbsa_gwdt_driver = {
>> + .driver = {
>> + .name = "sbsa-gwdt",
>> + .pm = &sbsa_gwdt_pm_ops,
>> + .of_match_table = sbsa_gwdt_of_match,
>> + },
>> + .probe = sbsa_gwdt_probe,
>> + .remove = sbsa_gwdt_remove,
>> + .shutdown = sbsa_gwdt_shutdown,
>> + .id_table = sbsa_gwdt_pdev_match,
>> +};
>> +
>> +module_platform_driver(sbsa_gwdt_driver);
>> +
>> +MODULE_DESCRIPTION("SBSA Generic Watchdog Driver");
>> +MODULE_VERSION("v1.0");
>> +MODULE_AUTHOR("Fu Wei <[email protected]>");
>> +MODULE_AUTHOR("Suravee Suthikulpanit <[email protected]>");
>> +MODULE_LICENSE("GPL v2");
>>
>



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-21 13:09:09

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Guenter Roeck wrote:
>>
>> +static unsigned int sbsa_gwdt_get_timeleft(struct watchdog_device *wdd)
>> +{
>> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> + u64 timeleft = sbsa_gwdt_get_wcv(wdd) - arch_counter_get_cntvct();
>> +
>
> Still not happy about the use of arch_counter_get_cntvct
> instead of using the clock subsystem. I am quite sure this could be done,
> possibly through arch_sys_counter, though at this point I am getting wary
> of bringing it up, so I guess I'll just let it go.

You made the same comment with my driver, and I keep asking for
clarification. The clk_get_sys() API does not work on my system,
because there are not clocks defined. That must be an ACPI limitation
that I can't fix.

The alternative to arch_counter_get_cntvct() is
arch_timer_read_counter(), which is not exported. So we have two choices,

1) Continue to use arch_counter_get_cntvct(), which works on all ARM64
platforms that this driver supports anyway

2) Export arch_timer_read_counter()

I prefer option #1.

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-21 13:28:15

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

On 05/21/2015 03:50 AM, Fu Wei wrote:
> Hi Guenter,
>
> Great thanks, I have got your review feedback, I will fix the problems :-)
> For update_limits, I also don't want to have that in the watchdog
> driver, and you can't find it in my last version.
> And this version, I integrate the watchdog_init_timeout and
> watchdog_init_pretimeout. so I can not add a driver specific
> "update_limits" between them.
> I think maybe we can not make this "update_limits" after calling
> init_timeouts, because we need to test and verify the timeout setting
> right after init_pretimeout by max_timeout and min_timeout. that is

Don't you have to do that in set_pretimeout as well, and even adjust
timeout if necessary ?

> why I call update_limits right after init_pretimeout and before
> init_timeout.
>
> any suggestion ? Great thanks ! :-)
>

Any sequence of
set_timeout()
set_pretimeout()
can result in an invalid timeout, since the practical timeout limits
changed. Therefore, you'll have to validate (and possibly update)
the timeout after or during each call to set_pretimeout().
Changing min_timeout and max_timeout won't help there, that
validation still has to happen.

Given this, some other driver developer may choose to not change the
timeout limits at all, validate (and if necessary silently adjust)
the timeout value in the set_timeout function, and call the set_timeout
function from set_pretimeout to ensure that the timeout is still
valid after the call to set_pretimeout. At least I would most likely
implement it that way.

This means your choice of continuously updating the timeout limits
is really a driver developer choice, not something that is needed
in the driver core. It might even be problematic, since driver
developers might forget to re-validate the current timeout after
changing the pretimeout in a similar situation.

Having said that, and looking through the SBSA driver code, it seems
to me that it does not re-validate the current timeout after setting
a new pretimeout. Unless I am missing something,
set_timeout(10);
set_pretimeout(20);
might therefore result in an invalid / unexpected timeout value.
Setting
set_timeout(10);
set_pretimeout(10);
might have even more interesting results. Can you try what happens
with your driver if you set those values ?

Thanks,
Guenter

2015-05-21 15:18:56

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On Thu, May 21, 2015 at 07:08:34PM +0800, Fu Wei wrote:
> Hi Guenter,
>
> Thanks for review :-)
>
> On 21 May 2015 at 18:34, Guenter Roeck <[email protected]> wrote:
> > On 05/21/2015 01:32 AM, [email protected] wrote:
> >>
> >> From: Fu Wei <[email protected]>
> >>
> >> This driver bases on linux kernel watchdog framework, and
> >> use "pretimeout" in the framework. It supports getting timeout and
> >> pretimeout from parameter and FDT at the driver init stage.
> >> In first timeout(WS0), the interrupt routine run panic to save
> >> system context.
> >>
> >> Signed-off-by: Fu Wei <[email protected]>
> >> ---
> >> drivers/watchdog/Kconfig | 12 ++
> >> drivers/watchdog/Makefile | 1 +
> >> drivers/watchdog/sbsa_gwdt.c | 476
> >> +++++++++++++++++++++++++++++++++++++++++++
> >> 3 files changed, 489 insertions(+)
> >> create mode 100644 drivers/watchdog/sbsa_gwdt.c
> >>
> >> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> >> index e5e7c55..25a0df1 100644
> >> --- a/drivers/watchdog/Kconfig
> >> +++ b/drivers/watchdog/Kconfig
> >> @@ -152,6 +152,18 @@ config ARM_SP805_WATCHDOG
> >> ARM Primecell SP805 Watchdog timer. This will reboot your system
> >> when
> >> the timeout is reached.
> >>
> >> +config ARM_SBSA_WATCHDOG
> >> + tristate "ARM SBSA Generic Watchdog"
> >> + depends on ARM || ARM64 || COMPILE_TEST
> >> + depends on ARM_ARCH_TIMER
> >> + select WATCHDOG_CORE
> >> + help
> >> + ARM SBSA Generic Watchdog timer. This has two Watchdog Signals
> >> + (WS0/WS1), will trigger a warning interrupt(do panic) at the
> >> first
> >> + timeout(WS0); will reboot your system when the second
> >> timeout(WS1)
> >> + is reached.
> >
> >
> > I think it would be better to keep the WS0/WS1 out of the help text.
> > It is an implementation detail, and no user will be able to make sense of
> > it.
>
> I don't mind to delete it , but those are in SBSA spec, is that an
> implementation detail ?
>
I think so.

Ask yourself - assuming you are not involved in the development of this driver,
and you read this help text. Is the help text going to help you to know about
WS0 and WS1 ? Why not just something like the following, if you want to be
verbose ?

ARM SBSA Generic Watchdog. This watchdog has two Watchdog timeouts.
The first timeout will trigger a panic; the second timeout will trigger
a system reset.

Anyway, not worth arguing about.

> >> +
> >> + /*
> >> + * Try to determine the frequency from the arch_timer interface
> >> + */
> >> + clk = arch_timer_get_rate();
> >
> >
> > arch_timer_get_rate() does not seem to be exported. Did you try to build
> > the driver as module ?
>
> yes, I have built it as a ko module, that is why I made a patch to
> export this interface in the first patch of this patchset
>
> but I will confirm it again :-)
>
Guess I'll give it a try myself. I don't really understand how this
can work unless arch_timer_get_rate() is exported in your tree.

Guenter

2015-05-21 15:28:46

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On Thu, May 21, 2015 at 08:09:02AM -0500, Timur Tabi wrote:
> Guenter Roeck wrote:
> >>
> >>+static unsigned int sbsa_gwdt_get_timeleft(struct watchdog_device *wdd)
> >>+{
> >>+ struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> >>+ u64 timeleft = sbsa_gwdt_get_wcv(wdd) - arch_counter_get_cntvct();
> >>+
> >
> >Still not happy about the use of arch_counter_get_cntvct
> >instead of using the clock subsystem. I am quite sure this could be done,
> >possibly through arch_sys_counter, though at this point I am getting wary
> >of bringing it up, so I guess I'll just let it go.
>
> You made the same comment with my driver, and I keep asking for
> clarification. The clk_get_sys() API does not work on my system, because
> there are not clocks defined. That must be an ACPI limitation that I can't
> fix.
>
Would it be possible to define such clocks ?

> The alternative to arch_counter_get_cntvct() is arch_timer_read_counter(),
> which is not exported. So we have two choices,
>
> 1) Continue to use arch_counter_get_cntvct(), which works on all ARM64
> platforms that this driver supports anyway
>
> 2) Export arch_timer_read_counter()
>
> I prefer option #1.
>
Do we have any feedback from the arm maintainers ?

My problem is that I don't want to be the first one to permit using
those functions outside architecture and clock code. If we do this,
we should get an Ack from an arm maintainer specifically for the use
of arch_counter_get_cntvct() and arch_timer_get_rate().

Thanks,
Guenter

2015-05-21 15:32:32

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

On Thu, May 21, 2015 at 04:32:34PM +0800, [email protected] wrote:
> From: Fu Wei <[email protected]>
>
> Also update Documentation/watchdog/watchdog-kernel-api.txt to
> introduce:
> (1)the new elements in the watchdog_device and watchdog_ops struct;
> (2)the new API "watchdog_init_timeouts".
>
> Reasons:
> (1)kernel already has two watchdog drivers are using "pretimeout":
> drivers/char/ipmi/ipmi_watchdog.c
> drivers/watchdog/kempld_wdt.c(but the definition is different)
> (2)some other dirvers are going to use this: ARM SBSA Generic Watchdog
>
> Signed-off-by: Fu Wei <[email protected]>
> ---

[ ... ]

>
> +/* Use the following function to check if a pretimeout value is invalid */
> +static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd,
> + unsigned int t)
> +{
> + return ((wdd->max_pretimeout != 0) &&
> + (t < wdd->min_pretimeout || t > wdd->max_pretimeout));
> +}

Should this function also enforce "t < wdd->timeout", and
should watchdog_timeout_invalid() enforce "t > wdd->pretimeout" ?

Thanks,
Guenter

2015-05-21 15:42:21

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/21/2015 03:32 AM, [email protected] wrote:

> +static void reload_timeout_to_wcv(struct watchdog_device *wdd)
> +{
> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> + u64 wcv;
> +
> + wcv = arch_counter_get_cntvct() +
> + (u64)(wdd->timeout - wdd->pretimeout) * gwdt->clk;
> +
> + sbsa_gwdt_set_wcv(wdd, wcv);
> +}

...

> +static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
> + unsigned int timeout)
> +{
> + wdd->timeout = timeout;
> +
> + return 0;
> +}

...

> +static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
> +{
> + struct sbsa_gwdt *gwdt = (struct sbsa_gwdt *)dev_id;
> + struct watchdog_device *wdd = &gwdt->wdd;
> + u32 status;
> +
> + status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
> +
> + if (status & SBSA_GWDT_WCS_WS0)
> + panic("SBSA Watchdog pre-timeout");
> +
> + return IRQ_HANDLED;
> +}

There's one thing I don't understand about your driver. The 'timeout'
value from the kernel is supposed to to be the number of seconds until
the system reboots. You are programming the WCV with that value, which
means that the WS0 interrupt will fire when the timeout expires the
first time. However, you don't reboot the system during this interrupt.
The "panic" will cause the system to halt, but not reboot. Instead,
it will just sit there. You're waiting for the WS1 timeout for the
system to reboot, but this is not a clean reboot, and it occurs at
2*timeout seconds.

That's why I like my driver better. It doesn't have any of this
pretimeout stuff, and when the timeout expires during the WS0 interrupt,
it calls emergency_restart() which reboots the system properly. The WS1
hard reset is used as a "backup" reset in case emergency_restart() fails.

--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

2015-05-21 15:46:57

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Guenter,

Great thanks :-)

On 21 May 2015 at 23:18, Guenter Roeck <[email protected]> wrote:
> On Thu, May 21, 2015 at 07:08:34PM +0800, Fu Wei wrote:
>> Hi Guenter,
>>
>> Thanks for review :-)
>>
>> On 21 May 2015 at 18:34, Guenter Roeck <[email protected]> wrote:
>> > On 05/21/2015 01:32 AM, [email protected] wrote:
>> >>
>> >> From: Fu Wei <[email protected]>
>> >>
>> >> This driver bases on linux kernel watchdog framework, and
>> >> use "pretimeout" in the framework. It supports getting timeout and
>> >> pretimeout from parameter and FDT at the driver init stage.
>> >> In first timeout(WS0), the interrupt routine run panic to save
>> >> system context.
>> >>
>> >> Signed-off-by: Fu Wei <[email protected]>
>> >> ---
>> >> drivers/watchdog/Kconfig | 12 ++
>> >> drivers/watchdog/Makefile | 1 +
>> >> drivers/watchdog/sbsa_gwdt.c | 476
>> >> +++++++++++++++++++++++++++++++++++++++++++
>> >> 3 files changed, 489 insertions(+)
>> >> create mode 100644 drivers/watchdog/sbsa_gwdt.c
>> >>
>> >> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>> >> index e5e7c55..25a0df1 100644
>> >> --- a/drivers/watchdog/Kconfig
>> >> +++ b/drivers/watchdog/Kconfig
>> >> @@ -152,6 +152,18 @@ config ARM_SP805_WATCHDOG
>> >> ARM Primecell SP805 Watchdog timer. This will reboot your system
>> >> when
>> >> the timeout is reached.
>> >>
>> >> +config ARM_SBSA_WATCHDOG
>> >> + tristate "ARM SBSA Generic Watchdog"
>> >> + depends on ARM || ARM64 || COMPILE_TEST
>> >> + depends on ARM_ARCH_TIMER
>> >> + select WATCHDOG_CORE
>> >> + help
>> >> + ARM SBSA Generic Watchdog timer. This has two Watchdog Signals
>> >> + (WS0/WS1), will trigger a warning interrupt(do panic) at the
>> >> first
>> >> + timeout(WS0); will reboot your system when the second
>> >> timeout(WS1)
>> >> + is reached.
>> >
>> >
>> > I think it would be better to keep the WS0/WS1 out of the help text.
>> > It is an implementation detail, and no user will be able to make sense of
>> > it.
>>
>> I don't mind to delete it , but those are in SBSA spec, is that an
>> implementation detail ?
>>
> I think so.
>
> Ask yourself - assuming you are not involved in the development of this driver,
> and you read this help text. Is the help text going to help you to know about
> WS0 and WS1 ? Why not just something like the following, if you want to be
> verbose ?
>
> ARM SBSA Generic Watchdog. This watchdog has two Watchdog timeouts.
> The first timeout will trigger a panic; the second timeout will trigger
> a system reset.

Great thanks, that is better, yes, If I never read SBSA spec, I don't
know WS is watchdog signal :-)

>
> Anyway, not worth arguing about.

yes, agree , Thanks for the example "help" :-)

>
>> >> +
>> >> + /*
>> >> + * Try to determine the frequency from the arch_timer interface
>> >> + */
>> >> + clk = arch_timer_get_rate();
>> >
>> >
>> > arch_timer_get_rate() does not seem to be exported. Did you try to build
>> > the driver as module ?
>>
>> yes, I have built it as a ko module, that is why I made a patch to
>> export this interface in the first patch of this patchset
>>
>> but I will confirm it again :-)
>>
> Guess I'll give it a try myself. I don't really understand how this
> can work unless arch_timer_get_rate() is exported in your tree.

yes, I have exported it , I think it make sense to export it.
Because other driver maybe need to get system counter info

Do you agree ? :-)

>
> Guenter



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-21 16:00:01

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On Thu, May 21, 2015 at 11:46:53PM +0800, Fu Wei wrote:
> Hi Guenter,
>
[ ... ]

> >> >> +
> >> >> + /*
> >> >> + * Try to determine the frequency from the arch_timer interface
> >> >> + */
> >> >> + clk = arch_timer_get_rate();
> >> >
> >> >
> >> > arch_timer_get_rate() does not seem to be exported. Did you try to build
> >> > the driver as module ?
> >>
> >> yes, I have built it as a ko module, that is why I made a patch to
> >> export this interface in the first patch of this patchset
> >>
> >> but I will confirm it again :-)
> >>
> > Guess I'll give it a try myself. I don't really understand how this
> > can work unless arch_timer_get_rate() is exported in your tree.
>
> yes, I have exported it , I think it make sense to export it.
> Because other driver maybe need to get system counter info
>
> Do you agree ? :-)
>
I don't think it is for me to agree or not. The arm maintainers
will need to be involved. You can not just export such a function
without maintainer Ack.

Having said that, my personal preference would be for the counter
and rate to be exported through the clock subsystem (ie with
clk_get_rate). But that would still not provide the current counter
value, so maybe that isn't even possible.

Thanks,
Guenter

2015-05-21 16:12:27

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Guenter,



On 21 May 2015 at 23:59, Guenter Roeck <[email protected]> wrote:
> On Thu, May 21, 2015 at 11:46:53PM +0800, Fu Wei wrote:
>> Hi Guenter,
>>
> [ ... ]
>
>> >> >> +
>> >> >> + /*
>> >> >> + * Try to determine the frequency from the arch_timer interface
>> >> >> + */
>> >> >> + clk = arch_timer_get_rate();
>> >> >
>> >> >
>> >> > arch_timer_get_rate() does not seem to be exported. Did you try to build
>> >> > the driver as module ?
>> >>
>> >> yes, I have built it as a ko module, that is why I made a patch to
>> >> export this interface in the first patch of this patchset
>> >>
>> >> but I will confirm it again :-)
>> >>
>> > Guess I'll give it a try myself. I don't really understand how this
>> > can work unless arch_timer_get_rate() is exported in your tree.
>>
>> yes, I have exported it , I think it make sense to export it.
>> Because other driver maybe need to get system counter info
>>
>> Do you agree ? :-)
>>
> I don't think it is for me to agree or not. The arm maintainers
> will need to be involved. You can not just export such a function
> without maintainer Ack.

yes, I have added Mark Rutland in the CC list when I sent this
patchset . He added the "arch_timer_get_rate();" in the arch timer
driver.
See if he can provide some suggestion. :-)

maybe I should add some more arm arch timer maintainers to get more
help on this :-)

>
> Having said that, my personal preference would be for the counter
> and rate to be exported through the clock subsystem (ie with
> clk_get_rate). But that would still not provide the current counter
> value, so maybe that isn't even possible.

I will try to make a patch for this, If the arm maintainers don't like
exporting "arch_timer_get_rate();"

But your thought is good, the clk_get_rate is the best way to do for now

>
> Thanks,
> Guenter



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-21 16:33:09

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/21/2015 11:12 AM, Fu Wei wrote:
>> >
>> >Having said that, my personal preference would be for the counter
>> >and rate to be exported through the clock subsystem (ie with
>> >clk_get_rate). But that would still not provide the current counter
>> >value, so maybe that isn't even possible.
> I will try to make a patch for this, If the arm maintainers don't like
> exporting "arch_timer_get_rate();"
>
> But your thought is good, the clk_get_rate is the best way to do for now

The rate isn't the problem. It's the current timestamp counter. The
only way to get that is with either arch_counter_get_cntvct() or
arch_timer_read_counter(). I'm not sure which of the two functions is
better. However, arch_timer_read_counter() is really just a function
pointer that points to arch_counter_get_cntvct().

Also, clk_get_rate() only works if you have a real clk object. I've
said this before many times, but on my ACPI platform, there are no clk
objects. Clocks are handled by UEFI.

--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

2015-05-21 20:33:26

by Suthikulpanit, Suravee

[permalink] [raw]
Subject: Re: [PATCH v2 4/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi

On 5/21/15 03:32, [email protected] wrote:
> From: Fu Wei <[email protected]>
>
> This can be a example of adding SBSA Generic Watchdog device node
> into some dts files for the Soc which contains SBSA Generic Watchdog.
>
> Signed-off-by: Fu Wei <[email protected]>
> ---
> arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi b/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi
> index 2874d92..95994eb 100644
> --- a/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi
> +++ b/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi
> @@ -84,6 +84,17 @@
> clock-names = "uartclk", "apb_pclk";
> };
>
> + watchdog0: watchdog@e0bb0000 {
> + compatible = "arm,sbsa-gwdt";
> + reg = <0x0 0xe0bb0000 0 0x10000>,
> + <0x0 0xe0bc0000 0 0x10000>;
> + reg-names = "refresh",
> + "control";
> + interrupts = <0 337 4>;
> + interrupt-names = "ws0";
> + timeout-sec = <10 5>;
> + };
> +
> spi0: ssp@e1020000 {
> status = "disabled";
> compatible = "arm,pl022", "arm,primecell";
>

Tested-by: Suravee Suthikulpanit <[email protected]>
Acked-by: Suravee Suthikulpanit <[email protected]>

2015-05-21 20:36:47

by Suthikulpanit, Suravee

[permalink] [raw]
Subject: Re: [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver

For patch 1,4,5,6,and 7, I have tested this on AMD Seattle platform.

Tested-by: Suravee Suthikulpanit <[email protected]>

Thanks,

Suravee

On 5/21/15 03:32, [email protected] wrote:
> From: Fu Wei <[email protected]>
>
> This patchset:
>
> (1)Export "arch_timer_get_rate" in arm_arch_timer.c for the
> other drivers, like SBSA watchdog driver
>
> (2)Introduce Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
> for FDT info of SBSA Generic Watchdog, and give two examples of
> adding SBSA Generic Watchdog device node into the dts files:
> foundation-v8.dts and amd-seattle-soc.dtsi.
>
> (3)Introduce "pretimeout" into the watchdog framework, and update
> Documentation/watchdog/watchdog-kernel-api.txt to introduce:
> (1)the new elements in the watchdog_device and watchdog_ops struct;
> (2)the new API "watchdog_init_timeouts".
>
> (4)Introduce ARM SBSA watchdog driver:
> a.Use linux kernel watchdog framework;
> b.Work with FDT on ARM64;
> c.Use "pretimeout" in watchdog framework;
> d.In first timeout(WS0), do panic to save system context;
> e.Support geting timeout and pretimeout from parameter and FDT
> at the driver init stage.
>
> (5)Parse SBSA Generic Watchdog Structure in GTDT table of ACPI,
> and create a platform device with that information.
> This platform device can be used by This Watchdog driver.
>
> This patchset has been tested with watchdog daemon
> (ACPI/FDT, module/build-in) on the following platforms:
> (1)ARM Foundation v8 model
> (2)AMD Seattle B0
>
> Changelog:
> v2: Improve watchdog-kernel-api.txt documentation for pretimeout support.
> Export "arch_timer_get_rate" in arm_arch_timer.c.
> Add watchdog_init_timeouts API for pretimeout support in framework.
> Improve suspend and resume foundation in driver
> Improve timeout/pretimeout values init code in driver.
> Delete unnecessary items of the sbsa_gwdt struct and #define.
> Delete all unnecessary debug info in driver.
> Fix 64bit division bug.
> Use the arch_timer interface to get watchdog clock rate.
> Add MODULE_DEVICE_TABLE for platform device id.
> Fix typoes.
>
> v1: The first version upstream patchset to linux mailing list
>
> Fu Wei (7):
> clocksource: export "arch_timer_get_rate" for the other drivers
> Documentation: add sbsa-gwdt.txt documentation
> ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
> ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
> Watchdog: introduce "pretimeout" into framework
> Watchdog: introduce ARM SBSA watchdog driver
> ACPI: import watchdog info of GTDT into platform device
>
> .../devicetree/bindings/watchdog/sbsa-gwdt.txt | 36 ++
> Documentation/watchdog/watchdog-kernel-api.txt | 62 ++-
> arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi | 11 +
> arch/arm64/boot/dts/arm/foundation-v8.dts | 10 +
> arch/arm64/kernel/acpi.c | 136 ++++++
> drivers/clocksource/arm_arch_timer.c | 1 +
> drivers/watchdog/Kconfig | 12 +
> drivers/watchdog/Makefile | 1 +
> drivers/watchdog/sbsa_gwdt.c | 476 +++++++++++++++++++++
> drivers/watchdog/watchdog_core.c | 103 +++--
> drivers/watchdog/watchdog_dev.c | 48 +++
> include/linux/watchdog.h | 30 +-
> 12 files changed, 891 insertions(+), 35 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
> create mode 100644 drivers/watchdog/sbsa_gwdt.c
>

2015-05-22 05:05:47

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Timur.

On 22 May 2015 at 00:33, Timur Tabi <[email protected]> wrote:
> On 05/21/2015 11:12 AM, Fu Wei wrote:
>>>
>>> >
>>> >Having said that, my personal preference would be for the counter
>>> >and rate to be exported through the clock subsystem (ie with
>>> >clk_get_rate). But that would still not provide the current counter
>>> >value, so maybe that isn't even possible.
>>
>> I will try to make a patch for this, If the arm maintainers don't like
>> exporting "arch_timer_get_rate();"
>>
>> But your thought is good, the clk_get_rate is the best way to do for now
>
>
> The rate isn't the problem. It's the current timestamp counter. The only
> way to get that is with either arch_counter_get_cntvct() or
> arch_timer_read_counter(). I'm not sure which of the two functions is
> better. However, arch_timer_read_counter() is really just a function
> pointer that points to arch_counter_get_cntvct().
>
> Also, clk_get_rate() only works if you have a real clk object. I've said
> this before many times, but on my ACPI platform, there are no clk objects.
> Clocks are handled by UEFI.

Thanks for your info,
I think : right now , do what we can do, export the interface of arch_timer,
If the arm maintainers don't like this way, we can find another way
later or find a option as plan B.

>
> --
> Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the
> Code Aurora Forum, a Linux Foundation Collaborative Project.



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-22 05:08:51

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Suravee,

Great thanks for your test, will add your "Tested-by:" in these
patches, if I don't modify them in the next version

On 22 May 2015 at 04:36, Suravee Suthikulpanit
<[email protected]> wrote:
> For patch 1,4,5,6,and 7, I have tested this on AMD Seattle platform.
>
> Tested-by: Suravee Suthikulpanit <[email protected]>
>
> Thanks,
>
> Suravee
>
>
> On 5/21/15 03:32, [email protected] wrote:
>>
>> From: Fu Wei <[email protected]>
>>
>> This patchset:
>>
>> (1)Export "arch_timer_get_rate" in arm_arch_timer.c for the
>> other drivers, like SBSA watchdog driver
>>
>> (2)Introduce Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
>> for FDT info of SBSA Generic Watchdog, and give two examples of
>> adding SBSA Generic Watchdog device node into the dts files:
>> foundation-v8.dts and amd-seattle-soc.dtsi.
>>
>> (3)Introduce "pretimeout" into the watchdog framework, and update
>> Documentation/watchdog/watchdog-kernel-api.txt to introduce:
>> (1)the new elements in the watchdog_device and watchdog_ops
>> struct;
>> (2)the new API "watchdog_init_timeouts".
>>
>> (4)Introduce ARM SBSA watchdog driver:
>> a.Use linux kernel watchdog framework;
>> b.Work with FDT on ARM64;
>> c.Use "pretimeout" in watchdog framework;
>> d.In first timeout(WS0), do panic to save system context;
>> e.Support geting timeout and pretimeout from parameter and FDT
>> at the driver init stage.
>>
>> (5)Parse SBSA Generic Watchdog Structure in GTDT table of ACPI,
>> and create a platform device with that information.
>> This platform device can be used by This Watchdog driver.
>>
>> This patchset has been tested with watchdog daemon
>> (ACPI/FDT, module/build-in) on the following platforms:
>> (1)ARM Foundation v8 model
>> (2)AMD Seattle B0
>>
>> Changelog:
>> v2: Improve watchdog-kernel-api.txt documentation for pretimeout support.
>> Export "arch_timer_get_rate" in arm_arch_timer.c.
>> Add watchdog_init_timeouts API for pretimeout support in framework.
>> Improve suspend and resume foundation in driver
>> Improve timeout/pretimeout values init code in driver.
>> Delete unnecessary items of the sbsa_gwdt struct and #define.
>> Delete all unnecessary debug info in driver.
>> Fix 64bit division bug.
>> Use the arch_timer interface to get watchdog clock rate.
>> Add MODULE_DEVICE_TABLE for platform device id.
>> Fix typoes.
>>
>> v1: The first version upstream patchset to linux mailing list
>>
>> Fu Wei (7):
>> clocksource: export "arch_timer_get_rate" for the other drivers
>> Documentation: add sbsa-gwdt.txt documentation
>> ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
>> ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
>> Watchdog: introduce "pretimeout" into framework
>> Watchdog: introduce ARM SBSA watchdog driver
>> ACPI: import watchdog info of GTDT into platform device
>>
>> .../devicetree/bindings/watchdog/sbsa-gwdt.txt | 36 ++
>> Documentation/watchdog/watchdog-kernel-api.txt | 62 ++-
>> arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi | 11 +
>> arch/arm64/boot/dts/arm/foundation-v8.dts | 10 +
>> arch/arm64/kernel/acpi.c | 136 ++++++
>> drivers/clocksource/arm_arch_timer.c | 1 +
>> drivers/watchdog/Kconfig | 12 +
>> drivers/watchdog/Makefile | 1 +
>> drivers/watchdog/sbsa_gwdt.c | 476
>> +++++++++++++++++++++
>> drivers/watchdog/watchdog_core.c | 103 +++--
>> drivers/watchdog/watchdog_dev.c | 48 +++
>> include/linux/watchdog.h | 30 +-
>> 12 files changed, 891 insertions(+), 35 deletions(-)
>> create mode 100644
>> Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
>> create mode 100644 drivers/watchdog/sbsa_gwdt.c
>>
>



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-22 05:17:55

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

Hi Guenter,


On 21 May 2015 at 23:32, Guenter Roeck <[email protected]> wrote:
> On Thu, May 21, 2015 at 04:32:34PM +0800, [email protected] wrote:
>> From: Fu Wei <[email protected]>
>>
>> Also update Documentation/watchdog/watchdog-kernel-api.txt to
>> introduce:
>> (1)the new elements in the watchdog_device and watchdog_ops struct;
>> (2)the new API "watchdog_init_timeouts".
>>
>> Reasons:
>> (1)kernel already has two watchdog drivers are using "pretimeout":
>> drivers/char/ipmi/ipmi_watchdog.c
>> drivers/watchdog/kempld_wdt.c(but the definition is different)
>> (2)some other dirvers are going to use this: ARM SBSA Generic Watchdog
>>
>> Signed-off-by: Fu Wei <[email protected]>
>> ---
>
> [ ... ]
>
>>
>> +/* Use the following function to check if a pretimeout value is invalid */
>> +static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd,
>> + unsigned int t)
>> +{
>> + return ((wdd->max_pretimeout != 0) &&
>> + (t < wdd->min_pretimeout || t > wdd->max_pretimeout));
>> +}
>
> Should this function also enforce "t < wdd->timeout", and
> should watchdog_timeout_invalid() enforce "t > wdd->pretimeout" ?

yes, you are right , thanks for the correction !! :-)

>
> Thanks,
> Guenter



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-22 06:30:38

by Timo Kokkonen

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

On 21.05.2015 11:32, [email protected] wrote:
> From: Fu Wei <[email protected]>
>
> Also update Documentation/watchdog/watchdog-kernel-api.txt to
> introduce:
> (1)the new elements in the watchdog_device and watchdog_ops struct;
> (2)the new API "watchdog_init_timeouts".
>
> Reasons:
> (1)kernel already has two watchdog drivers are using "pretimeout":
> drivers/char/ipmi/ipmi_watchdog.c
> drivers/watchdog/kempld_wdt.c(but the definition is different)
> (2)some other dirvers are going to use this: ARM SBSA Generic Watchdog
>

Hi,

As I was proposing some other API changes with my early-timeout-sec
work, I can see my work is going to collide with your API change
proposal a bit. So maybe I should ask your opinion as well..

Could this pretimeout feature be something that other drivers could
benefit too? I can see that it does not do anything else except call
panic() before letting the watchdog expire. This is something that could
be emulated easily by the watchdog core for drivers that don't know
anything about pretimeouts at all.

The way I was planning the API change there would need to be a small
change with each watchdog driver in order to let the watchdog core take
over generic behaviour on behalf of the driver. My goal was to make the
change so that each driver that gets converted to the new API extensions
gets a support for early-timeout-sec for free, without needing to enable
support for it any way. If the API was designed properly, also
pretimeouts could be handled easily and maybe even so that other drivers
could have that feature even though their hardware does not explicitly
give any support for it.

Any thoughts?

Thanks,
-Timo

2015-05-22 08:23:20

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

Hi Timo,


On 22 May 2015 at 14:30, Timo Kokkonen <[email protected]> wrote:
> On 21.05.2015 11:32, [email protected] wrote:
>>
>> From: Fu Wei <[email protected]>
>>
>> Also update Documentation/watchdog/watchdog-kernel-api.txt to
>> introduce:
>> (1)the new elements in the watchdog_device and watchdog_ops struct;
>> (2)the new API "watchdog_init_timeouts".
>>
>> Reasons:
>> (1)kernel already has two watchdog drivers are using "pretimeout":
>> drivers/char/ipmi/ipmi_watchdog.c
>> drivers/watchdog/kempld_wdt.c(but the definition is different)
>> (2)some other dirvers are going to use this: ARM SBSA Generic Watchdog
>>
>
> Hi,
>
> As I was proposing some other API changes with my early-timeout-sec work, I
> can see my work is going to collide with your API change proposal a bit. So
> maybe I should ask your opinion as well..

Thank you for reminding me of that, I saw "early-timeout-sec", but
because I don't get it in kernel API or watchdog_core.c, so I did not
pay attention to it.
Sorry.

>
> Could this pretimeout feature be something that other drivers could benefit
> too?

yes , as you may know, I am making a patch for pretimeout support in
watchdog framework

> I can see that it does not do anything else except call panic() before
> letting the watchdog expire. This is something that could be emulated easily
> by the watchdog core for drivers that don't know anything about pretimeouts
> at all.

For SBSA watchdog, there are two stage timeout, and according to kernel doc:
----------------------
Pretimeouts:

Some watchdog timers can be set to have a trigger go off before the
actual time they will reset the system. This can be done with an NMI,
interrupt, or other mechanism. This allows Linux to record useful
information (like panic information and kernel coredumps) before it
resets.
----------------------

I think panic() is the right way to do now. but people may also need
to config :
PANIC_TIMEOUT [!=0]
KEXEC
KDUMP
for debug reason

>
> The way I was planning the API change there would need to be a small change
> with each watchdog driver in order to let the watchdog core take over
> generic behaviour on behalf of the driver. My goal was to make the change so
> that each driver that gets converted to the new API extensions gets a
> support for early-timeout-sec for free, without needing to enable support
> for it any way. If the API was designed properly, also pretimeouts could be
> handled easily and maybe even so that other drivers could have that feature
> even though their hardware does not explicitly give any support for it.

could you please point out your patch , then I can learn your idea :-)
For now , I am working on a common "Pretimeouts" following the concept
in kernel doc.

>
> Any thoughts?

my thoughts is in my pretimeout patch , would you provide some suggestion ?

Great thanks !

>
> Thanks,
> -Timo



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-22 09:36:29

by Timo Kokkonen

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

On 22.05.2015 11:23, Fu Wei wrote:
> Hi Timo,
>
>
> On 22 May 2015 at 14:30, Timo Kokkonen <[email protected]> wrote:
>> On 21.05.2015 11:32, [email protected] wrote:
>>>
>>> From: Fu Wei <[email protected]>
>>>
>>> Also update Documentation/watchdog/watchdog-kernel-api.txt to
>>> introduce:
>>> (1)the new elements in the watchdog_device and watchdog_ops struct;
>>> (2)the new API "watchdog_init_timeouts".
>>>
>>> Reasons:
>>> (1)kernel already has two watchdog drivers are using "pretimeout":
>>> drivers/char/ipmi/ipmi_watchdog.c
>>> drivers/watchdog/kempld_wdt.c(but the definition is different)
>>> (2)some other dirvers are going to use this: ARM SBSA Generic Watchdog
>>>
>>
>> Hi,
>>
>> As I was proposing some other API changes with my early-timeout-sec work, I
>> can see my work is going to collide with your API change proposal a bit. So
>> maybe I should ask your opinion as well..
>
> Thank you for reminding me of that, I saw "early-timeout-sec", but
> because I don't get it in kernel API or watchdog_core.c, so I did not
> pay attention to it.
> Sorry.
>
>>
>> Could this pretimeout feature be something that other drivers could benefit
>> too?
>
> yes , as you may know, I am making a patch for pretimeout support in
> watchdog framework
>
>> I can see that it does not do anything else except call panic() before
>> letting the watchdog expire. This is something that could be emulated easily
>> by the watchdog core for drivers that don't know anything about pretimeouts
>> at all.
>
> For SBSA watchdog, there are two stage timeout, and according to kernel doc:
> ----------------------
> Pretimeouts:
>
> Some watchdog timers can be set to have a trigger go off before the
> actual time they will reset the system. This can be done with an NMI,
> interrupt, or other mechanism. This allows Linux to record useful
> information (like panic information and kernel coredumps) before it
> resets.
> ----------------------
>
> I think panic() is the right way to do now. but people may also need
> to config :
> PANIC_TIMEOUT [!=0]
> KEXEC
> KDUMP
> for debug reason
>

Yes, so basically if we hit pretimeout, we probably have already
crashed. The only difference is that we now have some seconds time to
dump out useful data and then either reboot or let the actual watchdog
reset take care of resetting the device. panic() sounds like a good
thing to do. Maybe you could also dump registers on other CPUs too or
try to get out some other useful information about the kernel in case it
has crashed or something. But I'm just guessing.

>>
>> The way I was planning the API change there would need to be a small change
>> with each watchdog driver in order to let the watchdog core take over
>> generic behaviour on behalf of the driver. My goal was to make the change so
>> that each driver that gets converted to the new API extensions gets a
>> support for early-timeout-sec for free, without needing to enable support
>> for it any way. If the API was designed properly, also pretimeouts could be
>> handled easily and maybe even so that other drivers could have that feature
>> even though their hardware does not explicitly give any support for it.
>
> could you please point out your patch , then I can learn your idea :-)
> For now , I am working on a common "Pretimeouts" following the concept
> in kernel doc.
>
>>
>> Any thoughts?
>
> my thoughts is in my pretimeout patch , would you provide some suggestion ?
>

Here is an archive link to my patch set:

http://www.spinics.net/lists/linux-watchdog/msg06473.html

Your patch set is adding a new call to the core for adjusting the
pretimoeut, which is probably a good thing in case the driver needs
special handling for it anyway. But if the core had capability to
emulate pretimeout for drivers that can't support it in hardware, it
would be good if there was a way for the core to support it even though
the driver had zero code for it. The core also has
watchdog_init_timeout() right now but even that is not called from that
many drivers. I would like to fix that too so that drivers would not
need to bother so much about it but let core take care of it more. This
is why I proposed the watchdog_init_params() call that could dig all the
generic parameters from device tree on behalf of the driver. This is
where I though timeout and early-timeout-sec parameters would be parsed
from device tree, but it could also parse pretimeout parameter as well.
Apparently Guenter did not like my approach so we might need some other
way to do it.

I don't get to say how this should be done, I'm just throwing ideas
here. But I think the watchdog core would be a lot better place for
implementing the generic features than drivers. That way a lot of
drivers could enable support the new features for free.

Thanks,
-Timo

2015-05-22 10:46:35

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

Hi Timo,

On 22 May 2015 at 16:59, Timo Kokkonen <[email protected]> wrote:
> On 22.05.2015 11:23, Fu Wei wrote:
>>
>> Hi Timo,
>>
>>
>> On 22 May 2015 at 14:30, Timo Kokkonen <[email protected]> wrote:
>>>
>>> On 21.05.2015 11:32, [email protected] wrote:
>>>>
>>>>
>>>> From: Fu Wei <[email protected]>
>>>>
>>>> Also update Documentation/watchdog/watchdog-kernel-api.txt to
>>>> introduce:
>>>> (1)the new elements in the watchdog_device and watchdog_ops struct;
>>>> (2)the new API "watchdog_init_timeouts".
>>>>
>>>> Reasons:
>>>> (1)kernel already has two watchdog drivers are using "pretimeout":
>>>> drivers/char/ipmi/ipmi_watchdog.c
>>>> drivers/watchdog/kempld_wdt.c(but the definition is different)
>>>> (2)some other dirvers are going to use this: ARM SBSA Generic Watchdog
>>>>
>>>
>>> Hi,
>>>
>>> As I was proposing some other API changes with my early-timeout-sec work,
>>> I
>>> can see my work is going to collide with your API change proposal a bit.
>>> So
>>> maybe I should ask your opinion as well..
>>
>>
>> Thank you for reminding me of that, I saw "early-timeout-sec", but
>> because I don't get it in kernel API or watchdog_core.c, so I did not
>> pay attention to it.
>> Sorry.
>>
>>>
>>> Could this pretimeout feature be something that other drivers could
>>> benefit
>>> too?
>>
>>
>> yes , as you may know, I am making a patch for pretimeout support in
>> watchdog framework
>>
>>> I can see that it does not do anything else except call panic() before
>>> letting the watchdog expire. This is something that could be emulated
>>> easily
>>> by the watchdog core for drivers that don't know anything about
>>> pretimeouts
>>> at all.
>>
>>
>> For SBSA watchdog, there are two stage timeout, and according to kernel
>> doc:
>> ----------------------
>> Pretimeouts:
>>
>> Some watchdog timers can be set to have a trigger go off before the
>> actual time they will reset the system. This can be done with an NMI,
>> interrupt, or other mechanism. This allows Linux to record useful
>> information (like panic information and kernel coredumps) before it
>> resets.
>> ----------------------
>>
>> I think panic() is the right way to do now. but people may also need
>> to config :
>> PANIC_TIMEOUT [!=0]
>> KEXEC
>> KDUMP
>> for debug reason
>>
>
> Yes, so basically if we hit pretimeout, we probably have already crashed.

yes, for now , I only use panic(), but at the beginning, I offer
user some options:

https://lists.linaro.org/pipermail/linaro-acpi/2015-April/004350.html

> The only difference is that we now have some seconds time to dump out useful
> data and then either reboot or let the actual watchdog reset take care of
> resetting the device. panic() sounds like a good thing to do. Maybe you
> could also dump registers on other CPUs too or try to get out some other
> useful information about the kernel in case it has crashed or something. But
> I'm just guessing.

yes, that is my thought.
because there is the kdump support in panic(), so that can give use a
chance to figure out why the watchdog wasn't fed.

>
>>>
>>> The way I was planning the API change there would need to be a small
>>> change
>>> with each watchdog driver in order to let the watchdog core take over
>>> generic behaviour on behalf of the driver. My goal was to make the change
>>> so
>>> that each driver that gets converted to the new API extensions gets a
>>> support for early-timeout-sec for free, without needing to enable support
>>> for it any way. If the API was designed properly, also pretimeouts could
>>> be
>>> handled easily and maybe even so that other drivers could have that
>>> feature
>>> even though their hardware does not explicitly give any support for it.
>>
>>
>> could you please point out your patch , then I can learn your idea :-)
>> For now , I am working on a common "Pretimeouts" following the concept
>> in kernel doc.
>>
>>>
>>> Any thoughts?
>>
>>
>> my thoughts is in my pretimeout patch , would you provide some suggestion
>> ?
>>
>
> Here is an archive link to my patch set:
>
> http://www.spinics.net/lists/linux-watchdog/msg06473.html

Ah , cool, I can see some common in your patch. Thanks :-)
See if I can learn something from your patches

>
> Your patch set is adding a new call to the core for adjusting the
> pretimoeut, which is probably a good thing in case the driver needs special
> handling for it anyway. But if the core had capability to emulate pretimeout
> for drivers that can't support it in hardware, it would be good if there was
> a way for the core to support it even though the driver had zero code for
> it. The core also has watchdog_init_timeout() right now but even that is not
> called from that many drivers. I would like to fix that too so that drivers
> would not need to bother so much about it but let core take care of it more.
> This is why I proposed the watchdog_init_params() call that could dig all
> the generic parameters from device tree on behalf of the driver. This is
> where I though timeout and early-timeout-sec parameters would be parsed from
> device tree, but it could also parse pretimeout parameter as well.
> Apparently Guenter did not like my approach so we might need some other way
> to do it.

I am using pretimeout, because SBSA watchdog hardware support two
stages timeout,
I am reusing the existing kernel concept, but your early_timeout_sec
is a new concept.
If you check my previous patchset , you will see : at the beginning,
pretimeout support is not a generic features in my patchset.
Then Arnd suggest that I can try to make pretimeout into watchdog
framework, and Guenter said :"Makes sense."
So I am still trying to improve pretimeout support :-)
If I can make pretimeout merged, may be you can try pretimeout to
implement early_timeout_sec function?
It is up to the maintainers, I will try my best.

Thanks :-)

>
> I don't get to say how this should be done, I'm just throwing ideas here.
> But I think the watchdog core would be a lot better place for implementing
> the generic features than drivers. That way a lot of drivers could enable
> support the new features for free.
>
> Thanks,
> -Timo



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-22 12:14:20

by Timo Kokkonen

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

On 22.05.2015 13:46, Fu Wei wrote:
> Hi Timo,
>
> On 22 May 2015 at 16:59, Timo Kokkonen <[email protected]> wrote:
>> On 22.05.2015 11:23, Fu Wei wrote:
>>>
>>> Hi Timo,
>>>
>>>
>>> On 22 May 2015 at 14:30, Timo Kokkonen <[email protected]> wrote:
>>>>
>>>> On 21.05.2015 11:32, [email protected] wrote:
>>>>>
>>>>>
>>>>> From: Fu Wei <[email protected]>
>>>>>
>>>>> Also update Documentation/watchdog/watchdog-kernel-api.txt to
>>>>> introduce:
>>>>> (1)the new elements in the watchdog_device and watchdog_ops struct;
>>>>> (2)the new API "watchdog_init_timeouts".
>>>>>
>>>>> Reasons:
>>>>> (1)kernel already has two watchdog drivers are using "pretimeout":
>>>>> drivers/char/ipmi/ipmi_watchdog.c
>>>>> drivers/watchdog/kempld_wdt.c(but the definition is different)
>>>>> (2)some other dirvers are going to use this: ARM SBSA Generic Watchdog
>>>>>
>>>>
>>>> Hi,
>>>>
>>>> As I was proposing some other API changes with my early-timeout-sec work,
>>>> I
>>>> can see my work is going to collide with your API change proposal a bit.
>>>> So
>>>> maybe I should ask your opinion as well..
>>>
>>>
>>> Thank you for reminding me of that, I saw "early-timeout-sec", but
>>> because I don't get it in kernel API or watchdog_core.c, so I did not
>>> pay attention to it.
>>> Sorry.
>>>
>>>>
>>>> Could this pretimeout feature be something that other drivers could
>>>> benefit
>>>> too?
>>>
>>>
>>> yes , as you may know, I am making a patch for pretimeout support in
>>> watchdog framework
>>>
>>>> I can see that it does not do anything else except call panic() before
>>>> letting the watchdog expire. This is something that could be emulated
>>>> easily
>>>> by the watchdog core for drivers that don't know anything about
>>>> pretimeouts
>>>> at all.
>>>
>>>
>>> For SBSA watchdog, there are two stage timeout, and according to kernel
>>> doc:
>>> ----------------------
>>> Pretimeouts:
>>>
>>> Some watchdog timers can be set to have a trigger go off before the
>>> actual time they will reset the system. This can be done with an NMI,
>>> interrupt, or other mechanism. This allows Linux to record useful
>>> information (like panic information and kernel coredumps) before it
>>> resets.
>>> ----------------------
>>>
>>> I think panic() is the right way to do now. but people may also need
>>> to config :
>>> PANIC_TIMEOUT [!=0]
>>> KEXEC
>>> KDUMP
>>> for debug reason
>>>
>>
>> Yes, so basically if we hit pretimeout, we probably have already crashed.
>
> yes, for now , I only use panic(), but at the beginning, I offer
> user some options:
>
> https://lists.linaro.org/pipermail/linaro-acpi/2015-April/004350.html
>
>> The only difference is that we now have some seconds time to dump out useful
>> data and then either reboot or let the actual watchdog reset take care of
>> resetting the device. panic() sounds like a good thing to do. Maybe you
>> could also dump registers on other CPUs too or try to get out some other
>> useful information about the kernel in case it has crashed or something. But
>> I'm just guessing.
>
> yes, that is my thought.
> because there is the kdump support in panic(), so that can give use a
> chance to figure out why the watchdog wasn't fed.
>

Yes indeed, sounds good!

>>
>>>>
>>>> The way I was planning the API change there would need to be a small
>>>> change
>>>> with each watchdog driver in order to let the watchdog core take over
>>>> generic behaviour on behalf of the driver. My goal was to make the change
>>>> so
>>>> that each driver that gets converted to the new API extensions gets a
>>>> support for early-timeout-sec for free, without needing to enable support
>>>> for it any way. If the API was designed properly, also pretimeouts could
>>>> be
>>>> handled easily and maybe even so that other drivers could have that
>>>> feature
>>>> even though their hardware does not explicitly give any support for it.
>>>
>>>
>>> could you please point out your patch , then I can learn your idea :-)
>>> For now , I am working on a common "Pretimeouts" following the concept
>>> in kernel doc.
>>>
>>>>
>>>> Any thoughts?
>>>
>>>
>>> my thoughts is in my pretimeout patch , would you provide some suggestion
>>> ?
>>>
>>
>> Here is an archive link to my patch set:
>>
>> http://www.spinics.net/lists/linux-watchdog/msg06473.html
>
> Ah , cool, I can see some common in your patch. Thanks :-)
> See if I can learn something from your patches
>
>>
>> Your patch set is adding a new call to the core for adjusting the
>> pretimoeut, which is probably a good thing in case the driver needs special
>> handling for it anyway. But if the core had capability to emulate pretimeout
>> for drivers that can't support it in hardware, it would be good if there was
>> a way for the core to support it even though the driver had zero code for
>> it. The core also has watchdog_init_timeout() right now but even that is not
>> called from that many drivers. I would like to fix that too so that drivers
>> would not need to bother so much about it but let core take care of it more.
>> This is why I proposed the watchdog_init_params() call that could dig all
>> the generic parameters from device tree on behalf of the driver. This is
>> where I though timeout and early-timeout-sec parameters would be parsed from
>> device tree, but it could also parse pretimeout parameter as well.
>> Apparently Guenter did not like my approach so we might need some other way
>> to do it.
>
> I am using pretimeout, because SBSA watchdog hardware support two
> stages timeout,
> I am reusing the existing kernel concept, but your early_timeout_sec
> is a new concept.

Yes, the early-timeout-sec concept itself is new in mainline but there
are a lot of production devices out there that start up with watchdog
running and the watchdog must not be stopped ever. Those devices
typically hack the watchdog policy somehow into the drivers so that they
don't just freeze even if kernel or early userspace happens to crash for
some reason. So I thought it would be about time to get support for this
in mainline. I don't want to hack this feature any more into drivers :)

> If you check my previous patchset , you will see : at the beginning,
> pretimeout support is not a generic features in my patchset.
> Then Arnd suggest that I can try to make pretimeout into watchdog
> framework, and Guenter said :"Makes sense."

Yeah, the same story as mine. Early-timeout-sec was first atmel driver
specific but I was told to think something more generic. At first I
objected as I felt I would need to implement a lot of stuff into the
core before I could make it generic. Then I was given chance to spend
some time with this and I actually wrote a generic implementation in the
core in a way that allows all drivers to use it with minimal
modifications. It also lets core deal with unstoppable watchdogs and
watchdogs with very short maximum timeout so that driver don't need
special handling for it.

> So I am still trying to improve pretimeout support :-)
> If I can make pretimeout merged, may be you can try pretimeout to
> implement early_timeout_sec function?
> It is up to the maintainers, I will try my best.

Yes, which brings us to the actual implementation details. Right now we
only have watchdog_init_timeout() that some drivers are using. Your
proposal is going into direction where we would also have
init_watchdog_pretimeout() or init_watchdog_timeouts() call. Drivers
providing pretimeout support would call these functions to set up
pretimeout values.

My patch set is taking the timeout concept into completely different
direction where we have hardware timeout properties and then we have
userspace timeout requests. Watchdog core is in the middle and checks
whether userspace timeout requested by user is something small enough
that the hardware can actually support. If not, a worker pings the
watchdog core on behalf of userspace so that user daemon can have longer
timeout. The same works with unstoppable watchdogs and the new
early-timeout-sec property. Right now drivers with restricted hardware
are just implementing this on their own.

Also the parameter parsing is different on my patch set. I was trying to
make it so that all generic parameters were parsed by the core and
driver would not need to bother about then, unless user had specified
eg. module parameter that it fills in the watchdog_device structure and
the core would not then override it. This way new parameters could be
introduced in a way that the driver does not explicitly need to
implement support for it if core knows how to handle it. There was
someone making windowed watchdogs, maybe we could implement support for
that in core and let the watchdog core emulate windowed watchdog support
for all drivers even if the actual hardware implementation was not there.

This is the direction we could go eventually. Of course not all features
are in interest for everyone and it may not make sense to try implement
everything in the core. But we have a lot of drivers that implement all
sorts of timers in them and my patch set could eliminate a lot of code
from them. We also have couple of drivers that have pretimeout support
and there seems to be a desire make that generic as well. Obviously I
think it makes sense to combine this effort in order to avoid conflicts.

So I am too hoping more guidelines on what is the acceptable direction
where to aim at. For example we could make this parameter handling more
generic and future proof if we allow an API change that require small
change to all drivers. I don't know exactly where the line is drawn.

Thanks,
-Timo

2015-05-22 13:24:11

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

On 05/22/2015 03:46 AM, Fu Wei wrote:
> Hi Timo,
>
[ ... ]

> So I am still trying to improve pretimeout support :-)

Is there anything still missing from it ?

> If I can make pretimeout merged, may be you can try pretimeout to
> implement early_timeout_sec function?

Not sure how one would or even could do that.

Do you mean "implement early_pretimeout_sec", by any chance ?

> It is up to the maintainers, I will try my best.
>

Please don't make the pretimeout concept more complicated than necessary.

The smaller the patch, the more likely it is to get accepted.
The more you change, the more difficult it is for the maintainer to,
for example, back-port later bug fixes into earlier kernel releases
when needed. This is why it is, for example, better to keep the
existing watchdog_init_timeout() function instead of just replacing
it with watchdog_init_timeouts().

Try to put yourself into the maintainer's perspective: If you were
the maintainer, would you rather accept a patch or patch set which
maintains the existing API and doesn't require any changes to existing
drivers, or would you accept one that changes, say, some function
or variable names and will require manual back-ports later on if
there is a bug fix ? Would you rather accept a patch that adds 50 lines
of code, or one that changes another 100+ lines and rearranges everything
along the line ?

Thanks,
Guenter

2015-05-22 13:37:45

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

On 05/22/2015 05:14 AM, Timo Kokkonen wrote:
[ ... ]

> This is the direction we could go eventually. Of course not all features are in interest for everyone and it may not make sense to try implement everything in the core. But we have a lot of drivers that implement all sorts of timers in them and my patch set could eliminate a lot of code from them. We also have couple of drivers that have pretimeout support and there seems to be a desire make that generic as well. Obviously I think it makes sense to combine this effort in order to avoid conflicts.
>
I would suggest to avoid trying to combine efforts. If anything, I would suggest
to _separate_ patch sets.

> So I am too hoping more guidelines on what is the acceptable direction where to aim at. For example we could make this parameter handling more generic and future proof if we allow an API change that require small change to all drivers. I don't know exactly where the line is drawn.
>
As I just mentioned separately, the more changes you make, the less likely
it will be to get your changes accepted. A patch set requiring changes to
all drivers would have to provide substantial benefits to get accepted.
Talking about parameters (and assuming you mean module parameters), I don't
even see how you could make that work without changing the userspace ABI,
which would be a no-go.

Personally I think it would be easier if you tried to accomplish less
than more. Concentrate on early-timeout (only), get it merged. Provide
a clear separation between is_active (as in "watchdog running") from
is_open (userspace has the driver open) and get it merged. Add the
ability to "ping" a running watchdog while the driver is closed
into the watchdog core and get it merged. Add the ability to soft-ping
a watchdog while the driver is open into the core and get it merged.
Those are all logically separate functions, and could be introduced
separately.

Just my personal opinion, of course.

Thanks,
Guenter

2015-05-22 14:02:58

by Hanjun Guo

[permalink] [raw]
Subject: Re: [PATCH v2 1/7] clocksource: export "arch_timer_get_rate" for the other drivers

On 2015å¹´05月21æ—¥ 16:32, [email protected] wrote:
> From: Fu Wei <[email protected]>
>
> Some devices get clock from system counter, like SBSA watchdog
> driver. They may need to get system counter rate.

and please add a comment that SBSA watchdog is a kernel module,
then it would explicit that why EXPORT_SYMBOL_GPL is needed.

>
> Signed-off-by: Fu Wei <[email protected]>

Other than that,

Acked-by: Hanjun Guo <[email protected]>

> ---
> drivers/clocksource/arm_arch_timer.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
> index 0aa135d..4327bf9 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -410,6 +410,7 @@ u32 arch_timer_get_rate(void)
> {
> return arch_timer_rate;
> }
> +EXPORT_SYMBOL_GPL(arch_timer_get_rate);
>
> static u64 arch_counter_get_cntvct_mem(void)
> {
>

2015-05-22 14:09:18

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 1/7] clocksource: export "arch_timer_get_rate" for the other drivers

[email protected] wrote:
> Some devices get clock from system counter, like SBSA watchdog
> driver. They may need to get system counter rate.

We don't need this patch. The watchdog driver can use
arch_timer_get_cntfrq() instead of arch_timer_get_rate(). There's
nothing wrong with arch_timer_get_cntfrq() since the SBSA driver is
intended only for ARM64 server systems, and arch_timer_get_cntfrq() is
always defined for such systems.

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-22 14:38:37

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

Hi Guenter.

Sorry for my poor English .
let me explain this :

On 22 May 2015 at 21:23, Guenter Roeck <[email protected]> wrote:
> On 05/22/2015 03:46 AM, Fu Wei wrote:
>>
>> Hi Timo,
>>
> [ ... ]
>
>> So I am still trying to improve pretimeout support :-)
>
>
> Is there anything still missing from it ?
>
>> If I can make pretimeout merged, may be you can try pretimeout to
>> implement early_timeout_sec function?
>
>
> Not sure how one would or even could do that.
>
> Do you mean "implement early_pretimeout_sec", by any chance ?

I mean: using pretimeout to implement the function you want, instead
of early_pretimeout_sec

Hope I say the right word this time :-)

>
>> It is up to the maintainers, I will try my best.
>>
>
> Please don't make the pretimeout concept more complicated than necessary.
>
> The smaller the patch, the more likely it is to get accepted.
> The more you change, the more difficult it is for the maintainer to,
> for example, back-port later bug fixes into earlier kernel releases
> when needed. This is why it is, for example, better to keep the
> existing watchdog_init_timeout() function instead of just replacing
> it with watchdog_init_timeouts().
>
> Try to put yourself into the maintainer's perspective: If you were
> the maintainer, would you rather accept a patch or patch set which
> maintains the existing API and doesn't require any changes to existing
> drivers, or would you accept one that changes, say, some function
> or variable names and will require manual back-ports later on if
> there is a bug fix ? Would you rather accept a patch that adds 50 lines
> of code, or one that changes another 100+ lines and rearranges everything
> along the line ?
>
> Thanks,
> Guenter
>



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-22 14:50:51

by Hanjun Guo

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 2015å¹´05月21æ—¥ 16:32, [email protected] wrote:
> From: Fu Wei <[email protected]>
>
> This driver bases on linux kernel watchdog framework, and
> use "pretimeout" in the framework. It supports getting timeout and
> pretimeout from parameter and FDT at the driver init stage.
> In first timeout(WS0), the interrupt routine run panic to save
> system context.
>
> Signed-off-by: Fu Wei <[email protected]>
> ---
> drivers/watchdog/Kconfig | 12 ++
> drivers/watchdog/Makefile | 1 +
> drivers/watchdog/sbsa_gwdt.c | 476 +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 489 insertions(+)
> create mode 100644 drivers/watchdog/sbsa_gwdt.c
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index e5e7c55..25a0df1 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -152,6 +152,18 @@ config ARM_SP805_WATCHDOG
> ARM Primecell SP805 Watchdog timer. This will reboot your system when
> the timeout is reached.
>
> +config ARM_SBSA_WATCHDOG
> + tristate "ARM SBSA Generic Watchdog"
> + depends on ARM || ARM64 || COMPILE_TEST

SBSA is for ARMv8-A based (64-bit) servers, no need to depends on ARM,
and why we depends on COMPILE_TEST?

> + depends on ARM_ARCH_TIMER
> + select WATCHDOG_CORE
> + help
> + ARM SBSA Generic Watchdog timer. This has two Watchdog Signals
> + (WS0/WS1), will trigger a warning interrupt(do panic) at the first
> + timeout(WS0); will reboot your system when the second timeout(WS1)
> + is reached.
> + More details: DEN0029B - Server Base System Architecture (SBSA)
> +
> config AT91RM9200_WATCHDOG
> tristate "AT91RM9200 watchdog"
> depends on SOC_AT91RM9200 && MFD_SYSCON
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index 5c19294..471f1b7c 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -30,6 +30,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
>
> # ARM Architecture
> obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o
> +obj-$(CONFIG_ARM_SBSA_WATCHDOG) += sbsa_gwdt.o
> obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
> obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o
> obj-$(CONFIG_CADENCE_WATCHDOG) += cadence_wdt.o
> diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
> new file mode 100644
> index 0000000..4ebe7c3
> --- /dev/null
> +++ b/drivers/watchdog/sbsa_gwdt.c
> @@ -0,0 +1,476 @@
> +/*
> + * SBSA(Server Base System Architecture) Generic Watchdog driver
> + *
> + * Copyright (c) 2015, Linaro Ltd.
> + * Author: Fu Wei <[email protected]>
> + * Suravee Suthikulpanit <[email protected]>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License 2 as published
> + * by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Note: This SBSA Generic watchdog driver is compatible with
> + * the pretimeout concept of Linux kernel.
> + * The timeout and pretimeout are set by the different REGs.
> + * The first watch period is set by writing WCV directly,
> + * that can support more than 10s timeout at the maximum
> + * system counter frequency.
> + * The second watch period is set by WOR(32bit) which will be loaded
> + * automatically by hardware, when WS0 is triggered.
> + * This gives a maximum watch period of around 10s at the maximum
> + * system counter frequency.
> + * The System Counter shall run at maximum of 400MHz.
> + * More details: DEN0029B - Server Base System Architecture (SBSA)
> + *
> + * Kernel/API: P---------| pretimeout
> + * |-------------------------------T timeout
> + * SBSA GWDT: P--WOR---WS1 pretimeout
> + * |-------WCV----------WS0~~~~~~~~T timeout
> + */
> +
> +#include <asm/arch_timer.h>

please put it under #include <linux/*.h>, this is
the convention of order head files.

> +
> +#include <linux/acpi.h>

Will we add any acpi realted code in this patch? if not,
please remove this head file.

> +#include <linux/io.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/moduleparam.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/uaccess.h>
> +#include <linux/watchdog.h>
> +
> +/* SBSA Generic Watchdog register definitions */
> +/* refresh frame */
> +#define SBSA_GWDT_WRR 0x000
> +
> +/* control frame */
> +#define SBSA_GWDT_WCS 0x000
> +#define SBSA_GWDT_WOR 0x008
> +#define SBSA_GWDT_WCV_LO 0x010
> +#define SBSA_GWDT_WCV_HI 0x014
> +
> +/* refresh/control frame */
> +#define SBSA_GWDT_W_IIDR 0xfcc
> +#define SBSA_GWDT_IDR 0xfd0
> +
> +/* Watchdog Control and Status Register */
> +#define SBSA_GWDT_WCS_EN BIT(0)
> +#define SBSA_GWDT_WCS_WS0 BIT(1)
> +#define SBSA_GWDT_WCS_WS1 BIT(2)
> +
> +/**
> + * struct sbsa_gwdt - Internal representation of the SBSA GWDT
> + * @wdd: kernel watchdog_device structure
> + * @clk: store the System Counter clock frequency, in Hz.
> + * @refresh_base: Virtual address of the watchdog refresh frame
> + * @control_base: Virtual address of the watchdog control frame
> + */
> +struct sbsa_gwdt {
> + struct watchdog_device wdd;
> + u32 clk;
> + void __iomem *refresh_base;
> + void __iomem *control_base;
> +};
> +
> +#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
> +
> +#define DEFAULT_TIMEOUT 10 /* seconds, the 1st + 2nd watch periods*/
> +#define DEFAULT_PRETIMEOUT 5 /* seconds, the 2nd watch period*/
> +
> +static unsigned int timeout;
> +module_param(timeout, uint, 0);
> +MODULE_PARM_DESC(timeout,
> + "Watchdog timeout in seconds. (>=0, default="
> + __MODULE_STRING(DEFAULT_TIMEOUT) ")");
> +
> +static unsigned int max_timeout = UINT_MAX;
> +module_param(max_timeout, uint, 0);
> +MODULE_PARM_DESC(max_timeout,
> + "Watchdog max timeout in seconds. (>=0, default="
> + __MODULE_STRING(UINT_MAX) ")");
> +
> +static unsigned int pretimeout;
> +module_param(pretimeout, uint, 0);
> +MODULE_PARM_DESC(pretimeout,
> + "Watchdog pretimeout in seconds. (>=0, default="
> + __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
> +
> +static unsigned int max_pretimeout = U32_MAX;
> +module_param(max_pretimeout, uint, 0);
> +MODULE_PARM_DESC(max_pretimeout,
> + "Watchdog max pretimeout in seconds. (>=0, default="
> + __MODULE_STRING(U32_MAX) ")");
> +
> +static bool nowayout = WATCHDOG_NOWAYOUT;
> +module_param(nowayout, bool, S_IRUGO);
> +MODULE_PARM_DESC(nowayout,
> + "Watchdog cannot be stopped once started (default="
> + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
> +
> +/*
> + * Architected system timer support.
> + */
> +static void sbsa_gwdt_cf_write(unsigned int reg, u32 val,
> + struct watchdog_device *wdd)
> +{
> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +
> + writel_relaxed(val, gwdt->control_base + reg);
> +}
> +
> +static void sbsa_gwdt_rf_write(unsigned int reg, u32 val,
> + struct watchdog_device *wdd)
> +{
> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +
> + writel_relaxed(val, gwdt->refresh_base + reg);
> +}
> +
> +static u32 sbsa_gwdt_cf_read(unsigned int reg, struct watchdog_device *wdd)
> +{
> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +
> + return readl_relaxed(gwdt->control_base + reg);
> +}
> +
> +/*
> + * help founctions for accessing 64bit WCV register
> + */
> +static u64 sbsa_gwdt_get_wcv(struct watchdog_device *wdd)
> +{
> + u32 wcv_lo, wcv_hi;
> +
> + do {
> + wcv_hi = sbsa_gwdt_cf_read(SBSA_GWDT_WCV_HI, wdd);
> + wcv_lo = sbsa_gwdt_cf_read(SBSA_GWDT_WCV_LO, wdd);
> + } while (wcv_hi != sbsa_gwdt_cf_read(SBSA_GWDT_WCV_HI, wdd));
> +
> + return (((u64)wcv_hi << 32) | wcv_lo);
> +}
> +
> +static void sbsa_gwdt_set_wcv(struct watchdog_device *wdd, u64 value)
> +{
> + u32 wcv_lo, wcv_hi;
> +
> + wcv_lo = value & U32_MAX;
> + wcv_hi = (value >> 32) & U32_MAX;
> +
> + sbsa_gwdt_cf_write(SBSA_GWDT_WCV_HI, wcv_hi, wdd);
> + sbsa_gwdt_cf_write(SBSA_GWDT_WCV_LO, wcv_lo, wdd);
> +}
> +
> +static void reload_timeout_to_wcv(struct watchdog_device *wdd)
> +{
> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> + u64 wcv;
> +
> + wcv = arch_counter_get_cntvct() +
> + (u64)(wdd->timeout - wdd->pretimeout) * gwdt->clk;
> +
> + sbsa_gwdt_set_wcv(wdd, wcv);
> +}
> +
> +/*
> + * Use the following function to set the limit of timeout
> + * after updating pretimeout
> + */
> +static void sbsa_gwdt_update_limits(struct watchdog_device *wdd)
> +{
> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> + u64 first_period_max = U64_MAX;
> +
> + do_div(first_period_max, gwdt->clk);
> +
> + wdd->min_timeout = wdd->pretimeout + 1;
> + wdd->max_timeout = min((uint)(wdd->pretimeout + first_period_max),
> + wdd->max_timeout);
> +}
> +
> +static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
> + unsigned int timeout)
> +{
> + wdd->timeout = timeout;
> +
> + return 0;
> +}
> +
> +static int sbsa_gwdt_set_pretimeout(struct watchdog_device *wdd,
> + unsigned int pretimeout)
> +{
> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> + u32 wor;
> +
> + wdd->pretimeout = pretimeout;
> + sbsa_gwdt_update_limits(wdd);
> +
> + if (!pretimeout)
> + /* gives sbsa_gwdt_start a chance to setup timeout */
> + wor = gwdt->clk;
> + else
> + wor = pretimeout * gwdt->clk;
> +
> + /* refresh the WOR, that will cause an explicit watchdog refresh */
> + sbsa_gwdt_cf_write(SBSA_GWDT_WOR, wor, wdd);
> +
> + return 0;
> +}
> +
> +static unsigned int sbsa_gwdt_get_timeleft(struct watchdog_device *wdd)
> +{
> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> + u64 timeleft = sbsa_gwdt_get_wcv(wdd) - arch_counter_get_cntvct();
> +
> + do_div(timeleft, gwdt->clk);
> +
> + return timeleft;
> +}
> +
> +static int sbsa_gwdt_start(struct watchdog_device *wdd)
> +{
> + /* Force refresh */
> + sbsa_gwdt_rf_write(SBSA_GWDT_WRR, 0xc0ffee, wdd);
> + /* writing WCS will cause an explicit watchdog refresh */
> + sbsa_gwdt_cf_write(SBSA_GWDT_WCS, SBSA_GWDT_WCS_EN, wdd);
> +
> + reload_timeout_to_wcv(wdd);
> +
> + return 0;
> +}
> +
> +static int sbsa_gwdt_stop(struct watchdog_device *wdd)
> +{
> + /* Force refresh */
> + sbsa_gwdt_rf_write(SBSA_GWDT_WRR, 0xc0ffee, wdd);
> + /* writing WCS will cause an explicit watchdog refresh */
> + sbsa_gwdt_cf_write(SBSA_GWDT_WCS, 0, wdd);
> +
> + return 0;
> +}
> +
> +static int sbsa_gwdt_keepalive(struct watchdog_device *wdd)
> +{
> + /*
> + * Writing WRR for an explicit watchdog refresh
> + * You can write anyting(like 0xc0ffee)
> + */
> + sbsa_gwdt_rf_write(SBSA_GWDT_WRR, 0xc0ffee, wdd);
> +
> + reload_timeout_to_wcv(wdd);
> +
> + return 0;
> +}
> +
> +static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
> +{
> + struct sbsa_gwdt *gwdt = (struct sbsa_gwdt *)dev_id;
> + struct watchdog_device *wdd = &gwdt->wdd;
> + u32 status;
> +
> + status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
> +
> + if (status & SBSA_GWDT_WCS_WS0)
> + panic("SBSA Watchdog pre-timeout");
> +
> + return IRQ_HANDLED;
> +}
> +
> +static struct watchdog_info sbsa_gwdt_info = {
> + .identity = "SBSA Generic Watchdog",
> + .options = WDIOF_SETTIMEOUT |
> + WDIOF_KEEPALIVEPING |
> + WDIOF_MAGICCLOSE |
> + WDIOF_PRETIMEOUT |
> + WDIOF_CARDRESET,
> +};
> +
> +static struct watchdog_ops sbsa_gwdt_ops = {
> + .owner = THIS_MODULE,
> + .start = sbsa_gwdt_start,
> + .stop = sbsa_gwdt_stop,
> + .ping = sbsa_gwdt_keepalive,
> + .set_timeout = sbsa_gwdt_set_timeout,
> + .set_pretimeout = sbsa_gwdt_set_pretimeout,
> + .get_timeleft = sbsa_gwdt_get_timeleft,
> +};
> +
> +static int sbsa_gwdt_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct sbsa_gwdt *gwdt;
> + struct watchdog_device *wdd;
> + struct resource *res;
> + void *rf_base, *cf_base;
> + int irq;
> + u32 clk, status;
> + int ret = 0;
> + u64 first_period_max = U64_MAX;
> +
> + /*
> + * Try to determine the frequency from the arch_timer interface
> + */
> + clk = arch_timer_get_rate();
> + if (!clk) {
> + dev_err(dev, "System Counter frequency not available\n");
> + return -EINVAL;
> + }
> +
> + gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
> + if (!gwdt)
> + return -ENOMEM;
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "refresh");
> + rf_base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(rf_base))
> + return PTR_ERR(rf_base);
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control");
> + cf_base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(rf_base))
> + return PTR_ERR(rf_base);
> +
> + irq = platform_get_irq_byname(pdev, "ws0");
> + if (irq < 0) {
> + dev_err(dev, "unable to get ws0 interrupt.\n");
> + return irq;
> + }
> +
> + gwdt->refresh_base = rf_base;
> + gwdt->control_base = cf_base;
> + gwdt->clk = clk;
> +
> + platform_set_drvdata(pdev, gwdt);
> +
> + wdd = &gwdt->wdd;
> + wdd->parent = dev;
> + wdd->info = &sbsa_gwdt_info;
> + wdd->ops = &sbsa_gwdt_ops;
> + watchdog_set_drvdata(wdd, gwdt);
> + watchdog_set_nowayout(wdd, nowayout);
> +
> + status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
> + if (status & SBSA_GWDT_WCS_WS1) {
> + dev_warn(dev, "System reset by WDT(WCS: %x, WCV: %llx)\n",
> + status, sbsa_gwdt_get_wcv(wdd));
> + wdd->bootstatus |= WDIOF_CARDRESET;
> + }
> + /* Check if watchdog is already enabled */
> + if (status & SBSA_GWDT_WCS_EN) {
> + dev_warn(dev, "already enabled! WCS:0x%x\n", status);
> + sbsa_gwdt_keepalive(wdd);
> + }
> +
> + wdd->min_pretimeout = 0;
> + wdd->max_pretimeout = min(U32_MAX / clk, max_pretimeout);
> + wdd->min_timeout = 1;
> + do_div(first_period_max, clk);
> + wdd->max_timeout = min((uint)(wdd->pretimeout + first_period_max),
> + max_timeout);
> +
> + wdd->pretimeout = DEFAULT_PRETIMEOUT;
> + wdd->timeout = DEFAULT_TIMEOUT;
> + watchdog_init_timeouts(wdd, pretimeout, timeout,
> + sbsa_gwdt_update_limits, dev);
> + /* update pretimeout to WOR */
> + sbsa_gwdt_cf_write(SBSA_GWDT_WOR, wdd->pretimeout * clk, wdd);
> +
> + ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, IRQF_TIMER,
> + pdev->name, gwdt);
> + if (ret) {
> + dev_err(dev, "unable to request IRQ %d\n", irq);
> + return ret;
> + }
> +
> + ret = watchdog_register_device(wdd);
> + if (ret)
> + return ret;
> +
> + dev_info(dev, "Initialized with %ds timeout, %ds pretimeout @ %uHz\n",
> + wdd->timeout, wdd->pretimeout, gwdt->clk);
> +
> + return 0;
> +}
> +
> +static void sbsa_gwdt_shutdown(struct platform_device *pdev)
> +{
> + struct sbsa_gwdt *gwdt = platform_get_drvdata(pdev);
> +
> + sbsa_gwdt_stop(&gwdt->wdd);
> +}
> +
> +static int sbsa_gwdt_remove(struct platform_device *pdev)
> +{
> + struct sbsa_gwdt *gwdt = platform_get_drvdata(pdev);
> + int ret = 0;
> +
> + if (!nowayout)
> + ret = sbsa_gwdt_stop(&gwdt->wdd);
> +
> + watchdog_unregister_device(&gwdt->wdd);
> +
> + return ret;
> +}
> +
> +/* Disable watchdog if it is active during suspend */
> +static int __maybe_unused sbsa_gwdt_suspend(struct device *dev)
> +{
> + struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
> +
> + if (watchdog_active(&gwdt->wdd))
> + sbsa_gwdt_stop(&gwdt->wdd);
> +
> + return 0;
> +}
> +
> +/* Enable watchdog and configure it if necessary */
> +static int __maybe_unused sbsa_gwdt_resume(struct device *dev)
> +{
> + struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
> +
> + if (watchdog_active(&gwdt->wdd))
> + sbsa_gwdt_start(&gwdt->wdd);
> +
> + return 0;
> +}
> +
> +static const struct dev_pm_ops sbsa_gwdt_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(sbsa_gwdt_suspend, sbsa_gwdt_resume)
> +};
> +
> +static const struct of_device_id sbsa_gwdt_of_match[] = {
> + { .compatible = "arm,sbsa-gwdt", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, sbsa_gwdt_of_match);
> +
> +static const struct platform_device_id sbsa_gwdt_pdev_match[] = {
> + { .name = "sbsa-gwdt", },

So this is because we need to auto load the module if
those resources are parsed from ACPI table, because
there is no acpi_device_id for ACPI tables, right?

If so, please add related code in the ACPI patch, and
comment on it please :)

Thanks
Hanjun

2015-05-22 14:55:28

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On Friday 22 May 2015 22:50:30 Hanjun Guo wrote:
> > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> > index e5e7c55..25a0df1 100644
> > --- a/drivers/watchdog/Kconfig
> > +++ b/drivers/watchdog/Kconfig
> > @@ -152,6 +152,18 @@ config ARM_SP805_WATCHDOG
> > ARM Primecell SP805 Watchdog timer. This will reboot your system when
> > the timeout is reached.
> >
> > +config ARM_SBSA_WATCHDOG
> > + tristate "ARM SBSA Generic Watchdog"
> > + depends on ARM || ARM64 || COMPILE_TEST
>
> SBSA is for ARMv8-A based (64-bit) servers, no need to depends on ARM,
> and why we depends on COMPILE_TEST?
>

I think it's a reasonable assumption that someone will sooner or later
put that hardware into an ARM32 machine, or run a 32-bit kernel on
a chip that has it.

While SBSA requires this watchdog device, nothing prevents SoC
manufacturers from using the same design in something that is not
a server.

Arnd

2015-05-22 15:01:53

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On Fri, May 22, 2015 at 04:55:04PM +0200, Arnd Bergmann wrote:
> On Friday 22 May 2015 22:50:30 Hanjun Guo wrote:
> > > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> > > index e5e7c55..25a0df1 100644
> > > --- a/drivers/watchdog/Kconfig
> > > +++ b/drivers/watchdog/Kconfig
> > > @@ -152,6 +152,18 @@ config ARM_SP805_WATCHDOG
> > > ARM Primecell SP805 Watchdog timer. This will reboot your system when
> > > the timeout is reached.
> > >
> > > +config ARM_SBSA_WATCHDOG
> > > + tristate "ARM SBSA Generic Watchdog"
> > > + depends on ARM || ARM64 || COMPILE_TEST
> >
> > SBSA is for ARMv8-A based (64-bit) servers, no need to depends on ARM,
> > and why we depends on COMPILE_TEST?
> >
>
> I think it's a reasonable assumption that someone will sooner or later
> put that hardware into an ARM32 machine, or run a 32-bit kernel on
> a chip that has it.
>
> While SBSA requires this watchdog device, nothing prevents SoC
> manufacturers from using the same design in something that is not
> a server.
>
Tricky, though. Since teh driver uses arm specific clock functions,
I don't think this can compile on a non-arm machine.

Guenter

2015-05-22 15:06:00

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

On Fri, May 22, 2015 at 10:38:32PM +0800, Fu Wei wrote:
> Hi Guenter.
>
> Sorry for my poor English .
> let me explain this :
>
> On 22 May 2015 at 21:23, Guenter Roeck <[email protected]> wrote:
> > On 05/22/2015 03:46 AM, Fu Wei wrote:
> >>
> >> Hi Timo,
> >>
> > [ ... ]
> >
> >> So I am still trying to improve pretimeout support :-)
> >
> >
> > Is there anything still missing from it ?
> >
> >> If I can make pretimeout merged, may be you can try pretimeout to
> >> implement early_timeout_sec function?
> >
> >
> > Not sure how one would or even could do that.
> >
> > Do you mean "implement early_pretimeout_sec", by any chance ?
>
> I mean: using pretimeout to implement the function you want, instead
> of early_pretimeout_sec
>
How would this work if the watchdog hardware doesn't support pretimeout ?

Pretimeout and early timeout are two logically different functions, with
different goals, so I don't entirely (if at all) understand why it would
make sense to tie them together.

Can you elaborate why you think this would be a good idea ?

Thanks,
Guenter

2015-05-22 15:16:23

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 1/7] clocksource: export "arch_timer_get_rate" for the other drivers

On Fri, May 22, 2015 at 09:09:10AM -0500, Timur Tabi wrote:
> [email protected] wrote:
> >Some devices get clock from system counter, like SBSA watchdog
> >driver. They may need to get system counter rate.
>
> We don't need this patch. The watchdog driver can use
> arch_timer_get_cntfrq() instead of arch_timer_get_rate(). There's nothing
> wrong with arch_timer_get_cntfrq() since the SBSA driver is intended only
> for ARM64 server systems, and arch_timer_get_cntfrq() is always defined for
> such systems.
>
I agree, since the SBSA driver also uses arch_counter_get_cntvct()
which is declared in the same include file as arch_timer_get_cntfrq().
The additional dependency does not provide any value, unless architecture
implementation dependencies can be removed entirely, which does not seem
to be the case.

Doo bad that SBSA is not hardware independent enough to provide all
the information needed to implement such a driver :-(.

Guenter

2015-05-22 15:18:36

by Hanjun Guo

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 2015年05月22日 23:01, Guenter Roeck wrote:
> On Fri, May 22, 2015 at 04:55:04PM +0200, Arnd Bergmann wrote:
>> On Friday 22 May 2015 22:50:30 Hanjun Guo wrote:
>>>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>>>> index e5e7c55..25a0df1 100644
>>>> --- a/drivers/watchdog/Kconfig
>>>> +++ b/drivers/watchdog/Kconfig
>>>> @@ -152,6 +152,18 @@ config ARM_SP805_WATCHDOG
>>>> ARM Primecell SP805 Watchdog timer. This will reboot your system when
>>>> the timeout is reached.
>>>>
>>>> +config ARM_SBSA_WATCHDOG
>>>> + tristate "ARM SBSA Generic Watchdog"
>>>> + depends on ARM || ARM64 || COMPILE_TEST
>>>
>>> SBSA is for ARMv8-A based (64-bit) servers, no need to depends on ARM,
>>> and why we depends on COMPILE_TEST?
>>>
>>
>> I think it's a reasonable assumption that someone will sooner or later
>> put that hardware into an ARM32 machine, or run a 32-bit kernel on
>> a chip that has it.
>>
>> While SBSA requires this watchdog device, nothing prevents SoC
>> manufacturers from using the same design in something that is not
>> a server.

From this point of view, I agree that SBSA watchdog design may used
in other ARM SoCs in the future, but how about add it back when this
kind of hardware showing up?

>>
> Tricky, though. Since teh driver uses arm specific clock functions,
> I don't think this can compile on a non-arm machine.

Since it depends on ARM64/ARM, we can temporary release from that now :)

Thanks
Hanjun

2015-05-22 15:24:13

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [Linaro-acpi] [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On Friday 22 May 2015 23:18:21 Hanjun Guo wrote:
> On 2015年05月22日 23:01, Guenter Roeck wrote:
> > On Fri, May 22, 2015 at 04:55:04PM +0200, Arnd Bergmann wrote:
> >> On Friday 22 May 2015 22:50:30 Hanjun Guo wrote:
> >>>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> >>>> index e5e7c55..25a0df1 100644
> >>>> --- a/drivers/watchdog/Kconfig
> >>>> +++ b/drivers/watchdog/Kconfig
> >>>> @@ -152,6 +152,18 @@ config ARM_SP805_WATCHDOG
> >>>> ARM Primecell SP805 Watchdog timer. This will reboot your system when
> >>>> the timeout is reached.
> >>>>
> >>>> +config ARM_SBSA_WATCHDOG
> >>>> + tristate "ARM SBSA Generic Watchdog"
> >>>> + depends on ARM || ARM64 || COMPILE_TEST
> >>>
> >>> SBSA is for ARMv8-A based (64-bit) servers, no need to depends on ARM,
> >>> and why we depends on COMPILE_TEST?
> >>>
> >>
> >> I think it's a reasonable assumption that someone will sooner or later
> >> put that hardware into an ARM32 machine, or run a 32-bit kernel on
> >> a chip that has it.
> >>
> >> While SBSA requires this watchdog device, nothing prevents SoC
> >> manufacturers from using the same design in something that is not
> >> a server.
>
> From this point of view, I agree that SBSA watchdog design may used
> in other ARM SoCs in the future, but how about add it back when this
> kind of hardware showing up?

If it builds on ARM32, I'd rather leave the option in, it doesn't hurt.

> > Tricky, though. Since teh driver uses arm specific clock functions,
> > I don't think this can compile on a non-arm machine.
>
> Since it depends on ARM64/ARM, we can temporary release from that now

We have to drop the '|| COMPILE_TEST' though as a result, or fix the
driver to look up the clock in DT and call 'clk_get_rate'.

That will break the ACPI case, but ACPI could use platform_data to
pass the clock rate into the driver, to make it independent of
low-level APIs.

Arnd

2015-05-22 15:38:14

by Hanjun Guo

[permalink] [raw]
Subject: Re: [PATCH v2 7/7] ACPI: import watchdog info of GTDT into platform device

+CC Catalin and Will

On 2015å¹´05月21æ—¥ 16:32, [email protected] wrote:
> From: Fu Wei <[email protected]>
>
> Parse SBSA Generic Watchdog Structure in GTDT table of ACPI,
> and create a platform device with that information.
> This platform device can be used by the ARM SBSA Generic
> Watchdog driver.
>
> Signed-off-by: Fu Wei <[email protected]>
> ---
> arch/arm64/kernel/acpi.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 136 insertions(+)
>
> diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
> index 8b83955..1ed11fd 100644
> --- a/arch/arm64/kernel/acpi.c
> +++ b/arch/arm64/kernel/acpi.c
> @@ -23,6 +23,7 @@
> #include <linux/irqdomain.h>
> #include <linux/memblock.h>
> #include <linux/of_fdt.h>
> +#include <linux/platform_device.h>
> #include <linux/smp.h>
>
> #include <asm/cputype.h>
> @@ -343,3 +344,138 @@ void __init acpi_gic_init(void)
>
> early_acpi_os_unmap_memory((char *)table, tbl_size);
> }
> +
> +static int __init acpi_gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
> + int index)
> +{
> + struct platform_device *pdev;
> + struct resource *res;
> + u32 gsi, flags;
> + int irq, trigger, polarity;
> + resource_size_t rf_base_phy, cf_base_phy;
> + int err = -ENOMEM;
> +
> + /*
> + * Get SBSA Generic Watchdog info
> + * from a Watchdog GT type structure in GTDT
> + */
> + rf_base_phy = (resource_size_t)wd->refresh_frame_address;
> + cf_base_phy = (resource_size_t)wd->control_frame_address;
> + gsi = wd->timer_interrupt;
> + flags = wd->timer_flags;
> +
> + pr_info("GTDT: a Watchdog GT structure(0x%llx/0x%llx gsi:%u flags:0x%x)\n",
> + rf_base_phy, cf_base_phy, gsi, flags);

Can we use pr_debug here? I don't think those information
worthy a pr_info.

> +
> + if (!(rf_base_phy && cf_base_phy && gsi)) {
> + pr_err("GTDT: failed geting the device info.\n");
> + return -EINVAL;
> + }
> +
> + trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
> + : ACPI_LEVEL_SENSITIVE;
> + polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
> + : ACPI_ACTIVE_HIGH;

I see places to duplicate this, I will look into this to see we can form
a function to handle it.

> + irq = acpi_register_gsi(NULL, gsi, trigger, polarity);
> + if (irq < 0) {
> + pr_err("GTDT: failed to register GSI of the Watchdog GT.\n");
> + return -EINVAL;
> + }
> +
> + pdev = platform_device_alloc("sbsa-gwdt", index);

Please put a comment before this function to explain
why we need a "sbsa-gwdt" name here.

> + if (!pdev)
> + goto err_unregister_gsi;
> +
> + res = kcalloc(3, sizeof(*res), GFP_KERNEL);
> + if (!res)
> + goto err_device_put;
> +
> + res[0].start = rf_base_phy;
> + res[0].end = rf_base_phy + SZ_4K - 1;
> + res[0].name = "refresh";
> + res[0].flags = IORESOURCE_MEM;
> +
> + res[1].start = cf_base_phy;
> + res[1].end = cf_base_phy + SZ_4K - 1;

So why SZ_4K? is it defined in SBSA spec? if so, please
comment on it too.

> + res[1].name = "control";
> + res[1].flags = IORESOURCE_MEM;
> +
> + res[2].start = irq;
> + res[2].end = res[2].start;
> + res[2].name = "ws0";
> + res[2].flags = IORESOURCE_IRQ;
> +
> + err = platform_device_add_resources(pdev, res, 3);
> + if (err)
> + goto err_free_res;
> +
> + err = platform_device_add(pdev);
> + if (err)
> + goto err_free_res;
> +
> + return 0;
> +
> +err_free_res:
> + kfree(res);
> +err_device_put:
> + platform_device_put(pdev);
> +err_unregister_gsi:
> + acpi_unregister_gsi(gsi);
> +
> + return err;
> +}
> +
> +/* Initialize SBSA generic Watchdog platform device info from GTDT */
> +static int __init acpi_gtdt_sbsa_gwdt_init(struct acpi_table_header *table)
> +{
> + struct acpi_table_gtdt *gtdt;
> + struct acpi_gtdt_header *header;
> + void *gtdt_subtable;
> + int i, gwdt_index;
> + int ret = 0;
> +
> + if (table->revision < 2) {
> + pr_info("GTDT: Revision:%d doesn't support Platform Timers.\n",
> + table->revision);

pr_warn() would be good.

Thanks
Hanjun

2015-05-22 16:18:12

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/22/2015 09:55 AM, Arnd Bergmann wrote:

> While SBSA requires this watchdog device, nothing prevents SoC
> manufacturers from using the same design in something that is not
> a server.

The first "S" in SBSA stands for "Server". I don't think it makes sense
to put an SBSA watchdog device in a non-server SOC.

Frankly, I don't understand why people want to make this driver work on
hardware that doesn't exist. The SBSA is intended for 64-bit ARM
Servers that use ACPI. Yes, there are a couple of ARM64 servers that
use device tree, but those are legacy platforms.

--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

2015-05-22 16:19:13

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/22/2015 10:01 AM, Guenter Roeck wrote:
>> >
> Tricky, though. Since teh driver uses arm specific clock functions,
> I don't think this can compile on a non-arm machine.

Any it doesn't need to. This driver is for 64-bit ARM Server SOCs.
There will never be any other kind of SOC that has an SBSA watchdog
device in it.

--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

2015-05-22 16:19:58

by Timur Tabi

[permalink] [raw]
Subject: Re: [Linaro-acpi] [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/22/2015 10:24 AM, Arnd Bergmann wrote:
> That will break the ACPI case, but ACPI could use platform_data to
> pass the clock rate into the driver, to make it independent of
> low-level APIs.

The clock rate isn't the only problem. You still need to current clock
timestamp, and that's ARM-specific.

--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

2015-05-22 16:22:23

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 1/7] clocksource: export "arch_timer_get_rate" for the other drivers

On 05/22/2015 10:16 AM, Guenter Roeck wrote:
> Doo bad that SBSA is not hardware independent enough to provide all
> the information needed to implement such a driver:-(.

The SBSA is designed and intended only for ARM Servers. It has no value
on non-ARM SOCs and and non-server SOCs. The SBSA is just a way for
64-bit ARM Server SOC vendors to re-use some drivers.

--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

2015-05-22 20:14:08

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [Linaro-acpi] [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On Friday 22 May 2015 11:19:52 Timur Tabi wrote:
> On 05/22/2015 10:24 AM, Arnd Bergmann wrote:
> > That will break the ACPI case, but ACPI could use platform_data to
> > pass the clock rate into the driver, to make it independent of
> > low-level APIs.
>
> The clock rate isn't the only problem. You still need to current clock
> timestamp, and that's ARM-specific.

Ah, I didn't realize that. I also just noticed that the two arch_timer
functions we call here are inline functions that just access control
registers.

If we want to enable COMPILE_TEST then, it would have to be something
like

#ifdef CONFIG_ARM || CONFIG_ARM64
#include <asm/arch_timer.h>
#else
... /* stub functions */
#endif

That might still be helpful to get coverage from things like the public
coverity builds that always build x86 allmodconfig, but it's also a bit
ugly.

Arnd

2015-05-22 20:17:55

by Timur Tabi

[permalink] [raw]
Subject: Re: [Linaro-acpi] [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/22/2015 03:13 PM, Arnd Bergmann wrote:
>
> That might still be helpful to get coverage from things like the public
> coverity builds that always build x86 allmodconfig, but it's also a bit
> ugly.

Adding #ifdefs to allow COMPILE_TEST to work seems ironic to me.

--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

2015-05-23 07:25:54

by Fu Wei

[permalink] [raw]
Subject: Re: [Linaro-acpi] [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Arnd

Thanks :-)

On 22 May 2015 at 23:24, Arnd Bergmann <[email protected]> wrote:
> On Friday 22 May 2015 23:18:21 Hanjun Guo wrote:
>> On 2015年05月22日 23:01, Guenter Roeck wrote:
>> > On Fri, May 22, 2015 at 04:55:04PM +0200, Arnd Bergmann wrote:
>> >> On Friday 22 May 2015 22:50:30 Hanjun Guo wrote:
>> >>>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>> >>>> index e5e7c55..25a0df1 100644
>> >>>> --- a/drivers/watchdog/Kconfig
>> >>>> +++ b/drivers/watchdog/Kconfig
>> >>>> @@ -152,6 +152,18 @@ config ARM_SP805_WATCHDOG
>> >>>> ARM Primecell SP805 Watchdog timer. This will reboot your system when
>> >>>> the timeout is reached.
>> >>>>
>> >>>> +config ARM_SBSA_WATCHDOG
>> >>>> + tristate "ARM SBSA Generic Watchdog"
>> >>>> + depends on ARM || ARM64 || COMPILE_TEST
>> >>>
>> >>> SBSA is for ARMv8-A based (64-bit) servers, no need to depends on ARM,
>> >>> and why we depends on COMPILE_TEST?
>> >>>
>> >>
>> >> I think it's a reasonable assumption that someone will sooner or later
>> >> put that hardware into an ARM32 machine, or run a 32-bit kernel on
>> >> a chip that has it.
>> >>
>> >> While SBSA requires this watchdog device, nothing prevents SoC
>> >> manufacturers from using the same design in something that is not
>> >> a server.
>>
>> From this point of view, I agree that SBSA watchdog design may used
>> in other ARM SoCs in the future, but how about add it back when this
>> kind of hardware showing up?
>
> If it builds on ARM32, I'd rather leave the option in, it doesn't hurt.

yes, I am agree with you.
Reason:
(1)Although the SBSA spec is all about ARMv8, but in "5 APPENDIX A:
GENERIC WATCHDOG", nothing says SBSA watchdog is only for ARM64.
(2)SBSA watchdog should work with arch_timer which has be used on
ARMv7 and ARMv8.
(3)there are ARM32 servers in the market(although there is not SBSA
watchdog in them)
(4) all the regs of SBSA watchdog are 32Bit, this IP core can be use
in ARM32(I don't know the implementation detail of this IP core, but
from the spec , I don't see "It can't be used on ARM32")
(5)we don't need to change any code, any line.(yes, it doesn't hurt)

So maybe we can keep this

The only problem we face is : there is not a ARM32 hardware or a
simulator of ARM32 has SBSA watchdog on it. and we don't know if ARM
will put this IP core in any Soc in the future :-(
Maybe because this IP core is new.

>
>> > Tricky, though. Since teh driver uses arm specific clock functions,
>> > I don't think this can compile on a non-arm machine.
>>
>> Since it depends on ARM64/ARM, we can temporary release from that now
>
> We have to drop the '|| COMPILE_TEST' though as a result, or fix the
> driver to look up the clock in DT and call 'clk_get_rate'.
>
> That will break the ACPI case, but ACPI could use platform_data to
> pass the clock rate into the driver, to make it independent of
> low-level APIs.

for this problem , we not only need to get "rate" but also need to get
timestamp.
So for now , we need to use some ARM specific code in arm_arch_timer.c,
unless those interface is integrated into clk framework(or we have
make a patch for if)

any suggestion or thought?

Great thanks for your review :-)


>
> Arnd
> _______________________________________________
> Linaro-acpi mailing list
> [email protected]
> https://lists.linaro.org/mailman/listinfo/linaro-acpi



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-23 14:47:56

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Guenter,


On 22 May 2015 at 23:01, Guenter Roeck <[email protected]> wrote:
> On Fri, May 22, 2015 at 04:55:04PM +0200, Arnd Bergmann wrote:
>> On Friday 22 May 2015 22:50:30 Hanjun Guo wrote:
>> > > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>> > > index e5e7c55..25a0df1 100644
>> > > --- a/drivers/watchdog/Kconfig
>> > > +++ b/drivers/watchdog/Kconfig
>> > > @@ -152,6 +152,18 @@ config ARM_SP805_WATCHDOG
>> > > ARM Primecell SP805 Watchdog timer. This will reboot your system when
>> > > the timeout is reached.
>> > >
>> > > +config ARM_SBSA_WATCHDOG
>> > > + tristate "ARM SBSA Generic Watchdog"
>> > > + depends on ARM || ARM64 || COMPILE_TEST
>> >
>> > SBSA is for ARMv8-A based (64-bit) servers, no need to depends on ARM,
>> > and why we depends on COMPILE_TEST?
>> >
>>
>> I think it's a reasonable assumption that someone will sooner or later
>> put that hardware into an ARM32 machine, or run a 32-bit kernel on
>> a chip that has it.
>>
>> While SBSA requires this watchdog device, nothing prevents SoC
>> manufacturers from using the same design in something that is not
>> a server.
>>
> Tricky, though. Since teh driver uses arm specific clock functions,
> I don't think this can compile on a non-arm machine.

yes, According to SBSA spec, the clock source of SBSAwatchdog is
system counter which is a part of arm arch timer.
So I think SBSA watchdog always goes with ARM.

ARM arch timer has been used on ARM32 and ARM64, so SBSA also can be
used on ARM32.
Just there is not a ARM32 hardware has that IP core right now.

>
> Guenter



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-23 15:08:12

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Arnd Bergmann wrote:
> I think it's a reasonable assumption that someone will sooner or later
> put that hardware into an ARM32 machine,

I'm going to have to disagree. If they haven't done it by now, I can't
imagine any ARM SOC vendor creating a 32-bit ARM SOC with an SBSA
watchdog in it. I can imagine a vendor trying to repurpose an existing
32-bit ARM SOC for the server market, but that SOC won't have an SBSA
watchdog in it.

> or run a 32-bit kernel on
> a chip that has it.

That might happen, but I would be very surprised, and I would need to be
convinced that it's useful.

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-23 16:28:08

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Timur,



On 21 May 2015 at 23:42, Timur Tabi <[email protected]> wrote:
> On 05/21/2015 03:32 AM, [email protected] wrote:
>
>> +static void reload_timeout_to_wcv(struct watchdog_device *wdd)
>> +{
>> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> + u64 wcv;
>> +
>> + wcv = arch_counter_get_cntvct() +
>> + (u64)(wdd->timeout - wdd->pretimeout) * gwdt->clk;
>> +
>> + sbsa_gwdt_set_wcv(wdd, wcv);
>> +}
>
>
> ...
>
>> +static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
>> + unsigned int timeout)
>> +{
>> + wdd->timeout = timeout;
>> +
>> + return 0;
>> +}
>
>
> ...
>
>> +static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
>> +{
>> + struct sbsa_gwdt *gwdt = (struct sbsa_gwdt *)dev_id;
>> + struct watchdog_device *wdd = &gwdt->wdd;
>> + u32 status;
>> +
>> + status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
>> +
>> + if (status & SBSA_GWDT_WCS_WS0)
>> + panic("SBSA Watchdog pre-timeout");
>> +
>> + return IRQ_HANDLED;
>> +}
>
>
> There's one thing I don't understand about your driver. The 'timeout' value
> from the kernel is supposed to to be the number of seconds until the system
> reboots. You are programming the WCV with that value, which means that the
> WS0 interrupt will fire when the timeout expires the first time. However,
> you don't reboot the system during this interrupt. The "panic" will cause
> the system to halt, but not reboot. Instead, it will just sit there.

the "panic" is not just halt the system, please check the code :
(1)It can trigger Kdump (not just print the panic message), if you
enable this in the config. that can help server administrator to
figure out why the system goes wrong.
(2)panic also can trigger a reboot, if you set up "panic timeout".

Obviously, it won't just sit there, it can help user figure out the problem.

At the beginning, I would like to make the first signal more useful,
but for simplifying the first version of driver , I decide to use
panic(). but if there is better "alerts" for a ARM server , I will go
on maintaining this driver to make WS0 more useful.

> You're waiting for the WS1 timeout for the system to reboot, but this is not
> a clean reboot, and it occurs at 2*timeout seconds.
>
> That's why I like my driver better. It doesn't have any of this pretimeout
> stuff, and when the timeout expires during the WS0 interrupt, it calls
> emergency_restart() which reboots the system properly. The WS1 hard reset
> is used as a "backup" reset in case emergency_restart() fails.

OK, If you think so, I hope you can read the SBSA spec more carefully
For the watchdog signal (WS0/WS1), SBSA say:
"The initial signal is typically wired to an interrupt and alerts the
system. The system can attempt to take corrective
action that includes refreshing the watchdog within the second watch
period. If the refresh is successful the
system returns to the previous normal operation. If it fails then the
second watch period expires and a second
signal is generated. The signal is fed to a higher agent as an
interrupt or reset for it to take executive action."

So WS0 is a warning, but not a reset. the WS1 maybe a reset, or a
interrupt to higher agent.

That is different from a normal watchdog use before. the two stage of
WS are not just for reset , at least the first one is definitely not a
reset. and the second one is not a backup.

If you make SBSA watchdog work like a normal watchdog,:
(1)why we need a new driver and new device? you can just use SP805 in
the system.
(2) why we need a two stages? ( if the second hardware reset signal
can work more reliably , why use emergency_restart() which is a
software reset, does it clean the system and do some useful backup or
sync? )
the only useful thing done by emergency_restart() is
kmsg_dump(KMSG_DUMP_EMERG);)
(3)why the first WS is connect to a interrupt, but not a reset
signal(I believe the direct reset signal is far more reliable than a
interrupt to trigger a software reset )

And because of WS0 is a warning, so I decide to use a existing
watchdog concept "pretimeout":
-----------------
Pretimeouts:

Some watchdog timers can be set to have a trigger go off before the
actual time they will reset the system. This can be done with an NMI,
interrupt, or other mechanism. This allows Linux to record useful
information (like panic information and kernel coredumps) before it
resets.
-----------------

>
> --
> Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the
> Code Aurora Forum, a Linux Foundation Collaborative Project.



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-23 16:51:00

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Timur,


On 24 May 2015 at 00:28, Fu Wei <[email protected]> wrote:
> Hi Timur,
>
>
>
> On 21 May 2015 at 23:42, Timur Tabi <[email protected]> wrote:
>> On 05/21/2015 03:32 AM, [email protected] wrote:
>>
>>> +static void reload_timeout_to_wcv(struct watchdog_device *wdd)
>>> +{
>>> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>>> + u64 wcv;
>>> +
>>> + wcv = arch_counter_get_cntvct() +
>>> + (u64)(wdd->timeout - wdd->pretimeout) * gwdt->clk;
>>> +
>>> + sbsa_gwdt_set_wcv(wdd, wcv);
>>> +}
>>
>>
>> ...
>>
>>> +static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
>>> + unsigned int timeout)
>>> +{
>>> + wdd->timeout = timeout;
>>> +
>>> + return 0;
>>> +}
>>
>>
>> ...
>>
>>> +static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
>>> +{
>>> + struct sbsa_gwdt *gwdt = (struct sbsa_gwdt *)dev_id;
>>> + struct watchdog_device *wdd = &gwdt->wdd;
>>> + u32 status;
>>> +
>>> + status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
>>> +
>>> + if (status & SBSA_GWDT_WCS_WS0)
>>> + panic("SBSA Watchdog pre-timeout");
>>> +
>>> + return IRQ_HANDLED;
>>> +}
>>
>>
>> There's one thing I don't understand about your driver. The 'timeout' value
>> from the kernel is supposed to to be the number of seconds until the system
>> reboots. You are programming the WCV with that value, which means that the
>> WS0 interrupt will fire when the timeout expires the first time. However,
>> you don't reboot the system during this interrupt. The "panic" will cause
>> the system to halt, but not reboot. Instead, it will just sit there.
>
> the "panic" is not just halt the system, please check the code :
> (1)It can trigger Kdump (not just print the panic message), if you
> enable this in the config. that can help server administrator to
> figure out why the system goes wrong.
> (2)panic also can trigger a reboot, if you set up "panic timeout".
>
> Obviously, it won't just sit there, it can help user figure out the problem.
>
> At the beginning, I would like to make the first signal more useful,
> but for simplifying the first version of driver , I decide to use
> panic(). but if there is better "alerts" for a ARM server , I will go
> on maintaining this driver to make WS0 more useful.
>
>> You're waiting for the WS1 timeout for the system to reboot, but this is not
>> a clean reboot, and it occurs at 2*timeout seconds.
>>
>> That's why I like my driver better. It doesn't have any of this pretimeout
>> stuff, and when the timeout expires during the WS0 interrupt, it calls
>> emergency_restart() which reboots the system properly. The WS1 hard reset
>> is used as a "backup" reset in case emergency_restart() fails.
>
> OK, If you think so, I hope you can read the SBSA spec more carefully
> For the watchdog signal (WS0/WS1), SBSA say:
> "The initial signal is typically wired to an interrupt and alerts the
> system. The system can attempt to take corrective
> action that includes refreshing the watchdog within the second watch
> period. If the refresh is successful the
> system returns to the previous normal operation.

>From here, you can see, even a panic is not good enough. we even can
refreshing the watchdog.

But for simplifying the driver, I think, at least, panic() can help
user to backup system context, it is very helpful for a server
administrator.
Because server should be very stable and important , if its software
goes wrong, we must figure out the problem, we can not let it happen
again.

but in WS0 interrupt routine , just simply restart , it is not a
server watchdog should do.

> If it fails then the
> second watch period expires and a second
> signal is generated. The signal is fed to a higher agent as an
> interrupt or reset for it to take executive action."
>
> So WS0 is a warning, but not a reset. the WS1 maybe a reset, or a
> interrupt to higher agent.
>
> That is different from a normal watchdog use before. the two stage of
> WS are not just for reset , at least the first one is definitely not a
> reset. and the second one is not a backup.
>
> If you make SBSA watchdog work like a normal watchdog,:
> (1)why we need a new driver and new device? you can just use SP805 in
> the system.
> (2) why we need a two stages? ( if the second hardware reset signal
> can work more reliably , why use emergency_restart() which is a
> software reset, does it clean the system and do some useful backup or
> sync? )
> the only useful thing done by emergency_restart() is
> kmsg_dump(KMSG_DUMP_EMERG);)
> (3)why the first WS is connect to a interrupt, but not a reset
> signal(I believe the direct reset signal is far more reliable than a
> interrupt to trigger a software reset )
>
> And because of WS0 is a warning, so I decide to use a existing
> watchdog concept "pretimeout":
> -----------------
> Pretimeouts:
>
> Some watchdog timers can be set to have a trigger go off before the
> actual time they will reset the system. This can be done with an NMI,
> interrupt, or other mechanism. This allows Linux to record useful
> information (like panic information and kernel coredumps) before it
> resets.
> -----------------
>
>>
>> --
>> Qualcomm Innovation Center, Inc.
>> The Qualcomm Innovation Center, Inc. is a member of the
>> Code Aurora Forum, a Linux Foundation Collaborative Project.
>
>
>
> --
> Best regards,
>
> Fu Wei
> Software Engineer
> Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
> Ph: +86 21 61221326(direct)
> Ph: +86 186 2020 4684 (mobile)
> Room 1512, Regus One Corporate Avenue,Level 15,
> One Corporate Avenue,222 Hubin Road,Huangpu District,
> Shanghai,China 200021



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-23 17:26:10

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Timur,



On 23 May 2015 at 23:08, Timur Tabi <[email protected]> wrote:
> Arnd Bergmann wrote:
>>
>> I think it's a reasonable assumption that someone will sooner or later
>> put that hardware into an ARM32 machine,
>
>
> I'm going to have to disagree. If they haven't done it by now, I can't
> imagine any ARM SOC vendor creating a 32-bit ARM SOC with an SBSA watchdog
> in it. I can imagine a vendor trying to repurpose an existing 32-bit ARM
> SOC for the server market, but that SOC won't have an SBSA watchdog in it.

I will agree with you on this, ONLY IF a people can represent ARM and
all chip vendors say publicly:
" We never ever use SBSA watchdog IP core on ARM32!" or " SBSA
watchdog IP core is imcompatible with ARM32"

Although the SBSA is all about ARMv8, but in "5 APPENDIX A: GENERIC
WATCHDOG", it doesn't say "this is only for ARMv8".
and its clock source "system counter" and arm_arch_timer have been in
ARM32 Soc for years,
and all the regs in SBSA watchdog is 32bit. I can't see why we can not
do that, unless I miss something.

I wonder why you are so sure "that SOC won't have an SBSA watchdog in
it." any documentation ?
Sorry, I am not a chip design engineer, I can't see why 32-bit ARM
won't have an SBSA watchdog in it.

>
>> or run a 32-bit kernel on
>>
>> a chip that has it.
>
>
> That might happen, but I would be very surprised, and I would need to be
> convinced that it's useful.
>
> --
> Sent by an employee of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the
> Code Aurora Forum, hosted by The Linux Foundation.



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-23 18:35:20

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/23/2015 10:26 AM, Fu Wei wrote:
> Hi Timur,
>
>
>
> On 23 May 2015 at 23:08, Timur Tabi <[email protected]> wrote:
>> Arnd Bergmann wrote:
>>>
>>> I think it's a reasonable assumption that someone will sooner or later
>>> put that hardware into an ARM32 machine,
>>
>>
>> I'm going to have to disagree. If they haven't done it by now, I can't
>> imagine any ARM SOC vendor creating a 32-bit ARM SOC with an SBSA watchdog
>> in it. I can imagine a vendor trying to repurpose an existing 32-bit ARM
>> SOC for the server market, but that SOC won't have an SBSA watchdog in it.
>
> I will agree with you on this, ONLY IF a people can represent ARM and
> all chip vendors say publicly:
> " We never ever use SBSA watchdog IP core on ARM32!" or " SBSA
> watchdog IP core is imcompatible with ARM32"
>
> Although the SBSA is all about ARMv8, but in "5 APPENDIX A: GENERIC
> WATCHDOG", it doesn't say "this is only for ARMv8".
> and its clock source "system counter" and arm_arch_timer have been in
> ARM32 Soc for years,
> and all the regs in SBSA watchdog is 32bit. I can't see why we can not
> do that, unless I miss something.
>
> I wonder why you are so sure "that SOC won't have an SBSA watchdog in
> it." any documentation ?
> Sorry, I am not a chip design engineer, I can't see why 32-bit ARM
> won't have an SBSA watchdog in it.
>

I think it is quite unfortunate that the specification is not public.
We have heard many statements about what is in the spec or not.
We have two possible implementations of the SBSA watchdog, but not
even the implementers of those two implementations seem to be able
to agree what the specification actually mandates/supports, or what
it doesn't mandate/support.

We have heard that the SBSA watchdog would require ACPI, and that it
doesn't. We have heard that it would require ARM64, and that it doesn't.
We have heard various assumptions about how WS0 and WS1 are supposed
to be wired. We have heard that all its registers are 32 bit (which
would suggest they have to be treated as such), but then we have a
64 bit register access in one of the drivers, and a more complex
implementation to read the same value as two 32-bit reads in the other.
We have heard that WS0 and WS1 are at least to some degree independent
of each other (and thus that it makes sense to set them separately),
and we have heard that WS1 is always equal to WS0 * 2. We have one
implementation limiting support to architecture revision 0, and the
other not imposing such a restriction.

Is the specification really that vague in such key areas ?
How do you expect anyone who doesn't have access to the specification
to be able to figure out what is actually correct and how to proceed ?

Thanks,
Guenter

2015-05-23 18:37:23

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Guenter Roeck wrote:
> I think it is quite unfortunate that the specification is not public.
> We have heard many statements about what is in the spec or not.

All you need to do is go to
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0029b/index.html,
get a free ARM account, and download the spec.

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-23 18:40:19

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Fu Wei wrote:
> I wonder why you are so sure "that SOC won't have an SBSA watchdog in
> it." any documentation ?
> Sorry, I am not a chip design engineer, I can't see why 32-bit ARM
> won't have an SBSA watchdog in it.

Because there's no market for it. I'm not talking about what's
theoretically possible. I'm only talking about what makes sense and
what will actually happen. And I'm quite certain that we will never see
an actual 32-bit ARM SOC with an SBSA watchdog device in it.

Therefore, it makes no sense to complicated the code so that we can
support an SOC that will never exist.

So can we PLEASE stop talking about 32-bit ARM support?

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-23 19:03:54

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Timur

On 24 May 2015 at 02:37, Timur Tabi <[email protected]> wrote:
> Guenter Roeck wrote:
>>
>> I think it is quite unfortunate that the specification is not public.
>> We have heard many statements about what is in the spec or not.
>
>
> All you need to do is go to
> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0029b/index.html,
> get a free ARM account, and download the spec.
>

Great thanks for providing this info!

>
> --
> Sent by an employee of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the
> Code Aurora Forum, hosted by The Linux Foundation.



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-23 19:14:29

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Timur

On 24 May 2015 at 02:40, Timur Tabi <[email protected]> wrote:
> Fu Wei wrote:
>>
>> I wonder why you are so sure "that SOC won't have an SBSA watchdog in
>> it." any documentation ?
>> Sorry, I am not a chip design engineer, I can't see why 32-bit ARM
>> won't have an SBSA watchdog in it.
>
>
> Because there's no market for it. I'm not talking about what's
> theoretically possible. I'm only talking about what makes sense and what
> will actually happen. And I'm quite certain that we will never see an
> actual 32-bit ARM SOC with an SBSA watchdog device in it.

Why are you quite certain? any info you can kindly share here?

>
> Therefore, it makes no sense to complicated the code so that we can support
> an SOC that will never exist.

yes, that is a good reason!

>
> So can we PLEASE stop talking about 32-bit ARM support?

why? we are just trying to figure out:
Do we need to add ARM in "depends on" for SBSA watchdog driver?

If some one suggests this, we need to figure out.

>
>
> --
> Sent by an employee of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the
> Code Aurora Forum, hosted by The Linux Foundation.



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-23 19:21:24

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Fu Wei wrote:

>> Because there's no market for it. I'm not talking about what's
>> theoretically possible. I'm only talking about what makes sense and what
>> will actually happen. And I'm quite certain that we will never see an
>> actual 32-bit ARM SOC with an SBSA watchdog device in it.
>
> Why are you quite certain? any info you can kindly share here?

I used to work for a company called Calxeda that tried to sell a 32-bit
ARM Server SOC. Calxeda went out of business because no one would buy
it, and that was two years ago.

>> So can we PLEASE stop talking about 32-bit ARM support?
>
> why? we are just trying to figure out:
> Do we need to add ARM in "depends on" for SBSA watchdog driver?
>
> If some one suggests this, we need to figure out.

We do not need to add "depends on ARM" in the Kconfig for the SBSA
watchdog driver.

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-23 19:40:35

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Fu Wei wrote:
> Hi Timur,
>
>
>
> On 21 May 2015 at 23:42, Timur Tabi <[email protected]> wrote:
>> On 05/21/2015 03:32 AM, [email protected] wrote:
>>
>>> +static void reload_timeout_to_wcv(struct watchdog_device *wdd)
>>> +{
>>> + struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>>> + u64 wcv;
>>> +
>>> + wcv = arch_counter_get_cntvct() +
>>> + (u64)(wdd->timeout - wdd->pretimeout) * gwdt->clk;
>>> +
>>> + sbsa_gwdt_set_wcv(wdd, wcv);
>>> +}
>>
>>
>> ...
>>
>>> +static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
>>> + unsigned int timeout)
>>> +{
>>> + wdd->timeout = timeout;
>>> +
>>> + return 0;
>>> +}
>>
>>
>> ...
>>
>>> +static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
>>> +{
>>> + struct sbsa_gwdt *gwdt = (struct sbsa_gwdt *)dev_id;
>>> + struct watchdog_device *wdd = &gwdt->wdd;
>>> + u32 status;
>>> +
>>> + status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
>>> +
>>> + if (status & SBSA_GWDT_WCS_WS0)
>>> + panic("SBSA Watchdog pre-timeout");
>>> +
>>> + return IRQ_HANDLED;
>>> +}
>>
>>
>> There's one thing I don't understand about your driver. The 'timeout' value
>> from the kernel is supposed to to be the number of seconds until the system
>> reboots. You are programming the WCV with that value, which means that the
>> WS0 interrupt will fire when the timeout expires the first time. However,
>> you don't reboot the system during this interrupt. The "panic" will cause
>> the system to halt, but not reboot. Instead, it will just sit there.
>
> the "panic" is not just halt the system, please check the code :
> (1)It can trigger Kdump (not just print the panic message), if you
> enable this in the config. that can help server administrator to
> figure out why the system goes wrong.
> (2)panic also can trigger a reboot, if you set up "panic timeout".
>
> Obviously, it won't just sit there, it can help user figure out the problem.
>
> At the beginning, I would like to make the first signal more useful,
> but for simplifying the first version of driver , I decide to use
> panic(). but if there is better "alerts" for a ARM server , I will go
> on maintaining this driver to make WS0 more useful.

I use emergency_restart(), because the watchdog-api.txt documentation
says this:

"If userspace fails (RAM error, kernel bug, whatever), the
notifications cease to occur, and the hardware watchdog will reset the
system (causing a reboot) after the timeout occurs."

Maybe I'm reading this too literally, but to me this means that when the
timeout expires, the system has to reset immediately.

However, maybe panic() is better, since it can do the same thing and more.

> So WS0 is a warning, but not a reset. the WS1 maybe a reset, or a
> interrupt to higher agent.

The watchdog documentation says that the system should reset when the
timeout occurs. Therefore, WCV needs to be programming for one-half the
timeout value, so that WS1 can occur when the watchdog expires. If the
application says, "set timeout to 10 second", then the system has to
reboot after 10 second (if the watchdog is pinged).

If the user does not specify a pre-timeout, and if he sets the watchdog
to 10 seconds, then WC1 will occur in 20 seconds. You will still call
panic() in 10 seconds (during WS0 interrupt), however, so I don't
understand how pre-timeout is supposed to work.

That's why I'm confused. I can't tell if you're programming WCV correctly.

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-23 19:47:00

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 7/7] ACPI: import watchdog info of GTDT into platform device

[email protected] wrote:
> From: Fu Wei<[email protected]>
>
> Parse SBSA Generic Watchdog Structure in GTDT table of ACPI,
> and create a platform device with that information.
> This platform device can be used by the ARM SBSA Generic
> Watchdog driver.
>
> Signed-off-by: Fu Wei<[email protected]>

Tested-by: Timur Tabi <[email protected]>

I have modified my watchdog driver to use this patch.

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-23 19:51:37

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/23/2015 11:37 AM, Timur Tabi wrote:
> Guenter Roeck wrote:
>> I think it is quite unfortunate that the specification is not public.
>> We have heard many statements about what is in the spec or not.
>
> All you need to do is go to http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0029b/index.html, get a free ARM account, and download the spec.
>
That helps - thanks a lot!

Folks, please correct me if my understanding of the specification
is wrong.

1) Pretimeout

The document suggests that
WS1 = WS0 * 2
is in fact correct. In essence, there is just one counter,
not two. This means that a separate pretimeout does not really
make sense, since in practice the timeout would always be
twice the pretimeout, and changing just one without affecting
the other is not really possible.

2) 64 bit WCV register

The specification is not clear on how to read this register.
It clearly states that it is comprised of two 32-bit registers,
but it does not specify if a single 64-bit read would be atomic,
or if it would be split into two separate 32-bit operations.
This leaves room for interpretation by the implementer, and
may result in bad values if the implementation changes the
counter from, say, 0x000010000 to 0x0000ffff while the value
is read.

My interpretation of this is that it would be safer to read two
32-bit values and ensure that the values are consistent
instead of relying on the assumption that a single 64-bit read
would be atomic.

3) ACPI vs. FDT

The specification does not say anything about ACPI or FDT support
except that it assumes that there are "System description data
structures such as ACPI or FDT". Given that, the driver should
support both.

4) ARM vs. ARM64

SBSA clearly states that any CPU supporting it shall be ARM v8
compliant (4.1.1, CPU architecture). Personally I think the
discussion around supporting the driver on ARM/ARM64 or ARM64
only is a bit pointless, especially since being able to build
it on ARM doesn't really hurt, even though there is currently
no HW supporting it.

Overall I must admit that I don't really understand why this is
such a contentious issue.

5) Revision support

While it is difficult to predict the future, it is common practice
in the industry to make future revisions of a standard (and chip)
as much backward compatible as possible, and to only add functionality.
As such, I don't see a reason to restrict support to revision 0
of the standard.

6) A note about driver messages

Implementation defined registers are just that, implementation
defined registers. I don't think it makes sense to display any
of those, not even for debugging purposes.

---

Again, please correct me if any of those statements is wrong.
When doing so, please reference the specification, to make sure
that we all know what we are talking about.

My hope is that we can use this as a starting point to converge
on a single driver.

Thanks,
Guenter

2015-05-23 20:02:08

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/23/2015 12:40 PM, Timur Tabi wrote:
[ ... ]
>
> I use emergency_restart(), because the watchdog-api.txt documentation says this:
>
> "If userspace fails (RAM error, kernel bug, whatever), the
> notifications cease to occur, and the hardware watchdog will reset the
> system (causing a reboot) after the timeout occurs."
>
> Maybe I'm reading this too literally, but to me this means that when the timeout expires, the system has to reset immediately.
>
> However, maybe panic() is better, since it can do the same thing and more.
>

I have a specific requirement at work to have watchdog expiration
(not this watchdog, this is different HW) result in a panic, specifically
to enable crashdump support and thus post-mortem analysis.

I had not thought about this use case myself, and I had always wondered
why watchdog driver implementers would choose to call panic() after an
interrupt or NMI. But we live and learn, so now I finally understand.

In the pretimeout/timeout world, the pretimeout would (typically)
result in a panic, and the timeout would result in a reset. So one
would set the timer register to 10s for 10s pretimeout and 20s timeout.

However, the pretimeout concept assumes that there are two timers
which can be set independently. As you had pointed out earlier,
and as the specification seems to confirm, that is not the case here.
As such, I don't really understand why and how the pretimeout / timeout
concept would add any value here and not just make things more
complicated than necessary. Maybe I am just missing something.

Thanks,
Guenter

2015-05-23 20:27:06

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Guenter Roeck wrote:
>
> However, the pretimeout concept assumes that there are two timers
> which can be set independently. As you had pointed out earlier,
> and as the specification seems to confirm, that is not the case here.
> As such, I don't really understand why and how the pretimeout / timeout
> concept would add any value here and not just make things more
> complicated than necessary. Maybe I am just missing something.

It might be possible to load a new value into the WOR register after the
WS0 interrupt occurs. That is, in the interrupt handler, we can do
something like this:

if (status & SBSA_GWDT_WCS_WS0)
// write new WOR value,
// then ping watchdog so that it's loaded

I'm not convinced that it's worth it, however. It would require
interrupts to still be working when WS0 times out, which somewhat
defeats the purpose of a watchdog.

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-23 20:44:38

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/23/2015 01:27 PM, Timur Tabi wrote:
> Guenter Roeck wrote:
>>
>> However, the pretimeout concept assumes that there are two timers
>> which can be set independently. As you had pointed out earlier,
>> and as the specification seems to confirm, that is not the case here.
>> As such, I don't really understand why and how the pretimeout / timeout
>> concept would add any value here and not just make things more
>> complicated than necessary. Maybe I am just missing something.
>
> It might be possible to load a new value into the WOR register after the WS0 interrupt occurs. That is, in the interrupt handler, we can do something like this:
>
> if (status & SBSA_GWDT_WCS_WS0)
> // write new WOR value,
> // then ping watchdog so that it's loaded
>
> I'm not convinced that it's worth it, however. It would require interrupts to still be working when WS0 times out, which somewhat defeats the purpose of a watchdog.
>

If I understand the specification correctly, reloading the register
would result in another WS0, not in WS1. That isn't really what we
would want to happen.

Reloading the register would normally be done in the crashdump kernel,
if it is loaded, to give it time to actually take the crashdump.
But that is post-restart, not pre-restart.

Thanks,
Guenter

2015-05-24 09:58:18

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Guenter,

Great thanks for your suggestion and review,
I have some questions below , would you please help me out?

On 24 May 2015 at 03:51, Guenter Roeck <[email protected]> wrote:
> On 05/23/2015 11:37 AM, Timur Tabi wrote:
>>
>> Guenter Roeck wrote:
>>>
>>> I think it is quite unfortunate that the specification is not public.
>>> We have heard many statements about what is in the spec or not.
>>
>>
>> All you need to do is go to
>> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0029b/index.html,
>> get a free ARM account, and download the spec.
>>
> That helps - thanks a lot!
>
> Folks, please correct me if my understanding of the specification
> is wrong.
>
> 1) Pretimeout
>
> The document suggests that
> WS1 = WS0 * 2

Are you saying: the first timeout == the second timeout

|-------------WS0
|-------------WS1

Sorry, could you let me know where is that suggestion??
I have checked the SBSA again, but I can not find it.
Maybe I really miss this part.

> is in fact correct. In essence, there is just one counter,
> not two. This means that a separate pretimeout does not really
> make sense, since in practice the timeout would always be
> twice the pretimeout,

Yes, you are right, if we only use "WOR", then the first timeout ==
the second timeout

> and changing just one without affecting
> the other is not really possible.

although there is only one counter, and it is 32 bits wide.
In SBSA, we can see this:
-------
Note: the watchdog offset register is 32 bits wide. This gives a
maximum watch period of around 10s at a system counter frequency of
400MHz.
If a larger watch period is required then the compare value can be
programmed directly into the compare value register.
-------
So for the first timeout, we can set the compare value register(WCV).
Then the two timeouts are different. and the first timeout has not
10s(@400MHz) limit.
just the the second timeout must use "WOR".

>
> 2) 64 bit WCV register
>
> The specification is not clear on how to read this register.
> It clearly states that it is comprised of two 32-bit registers,
> but it does not specify if a single 64-bit read would be atomic,
> or if it would be split into two separate 32-bit operations.
> This leaves room for interpretation by the implementer, and
> may result in bad values if the implementation changes the
> counter from, say, 0x000010000 to 0x0000ffff while the value
> is read.
>
> My interpretation of this is that it would be safer to read two
> 32-bit values and ensure that the values are consistent
> instead of relying on the assumption that a single 64-bit read
> would be atomic.

yes, thanks for pointing it out.

I found this problem in my first upstream patchset.
So in this patchset, there is not that problem now:

-------
do {
wcv_hi = sbsa_gwdt_cf_read(SBSA_GWDT_WCV_HI, wdd);
wcv_lo = sbsa_gwdt_cf_read(SBSA_GWDT_WCV_LO, wdd);
} while (wcv_hi != sbsa_gwdt_cf_read(SBSA_GWDT_WCV_HI, wdd));

-------

>
> 3) ACPI vs. FDT
>
> The specification does not say anything about ACPI or FDT support
> except that it assumes that there are "System description data
> structures such as ACPI or FDT". Given that, the driver should
> support both.

yes, this patchset has fully support ACPI and FDT, and has been
successfully tested on
(1)Foundation model
(2)AMD Seattle B0 Soc

>
> 4) ARM vs. ARM64
>
> SBSA clearly states that any CPU supporting it shall be ARM v8
> compliant (4.1.1, CPU architecture). Personally I think the
> discussion around supporting the driver on ARM/ARM64 or ARM64
> only is a bit pointless, especially since being able to build
> it on ARM doesn't really hurt, even though there is currently
> no HW supporting it.
>
> Overall I must admit that I don't really understand why this is
> such a contentious issue.

I think that is not a contentious issue.
Just some one has that suggestion, then we discussed it.
So I am going to delete ARM support.
If we have this hardware in the future, we can add it by then.

>
> 5) Revision support
>
> While it is difficult to predict the future, it is common practice
> in the industry to make future revisions of a standard (and chip)
> as much backward compatible as possible, and to only add functionality.
> As such, I don't see a reason to restrict support to revision 0
> of the standard.

Totally agree, there is not this problem in my patchset.

>
> 6) A note about driver messages
>
> Implementation defined registers are just that, implementation
> defined registers. I don't think it makes sense to display any
> of those, not even for debugging purposes.

in this patchset, I have totally deleted all the debug message, only keep:
(1)3 error messages
(2)2 warning messages
reason:
1. if system reset by watchdog, we need to inform user (WCS: store
watchdog status, WCV: store the timestamp of the last reboot, maybe
these can provide some basic info of reboot )
2. if watchdog has been enabled before register, there is something
wrong we need to inform user. (WCS: store watchdog status)
(3)1 info message
reason: if watchdog has been successfully registered, we log it.

Please let me know if there is any redundant massage, I will fix it.

>
> ---
>
> Again, please correct me if any of those statements is wrong.
> When doing so, please reference the specification, to make sure
> that we all know what we are talking about.

Great thanks for your help , those help me a lot.

So, for now , this only big problem in my patchset is "pretimeout",
but I have some doubt above, would you help me out ? :-) Thanks


>
> My hope is that we can use this as a starting point to converge
> on a single driver.
>
> Thanks,
> Guenter
>



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-24 10:15:11

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Guenter,

On 24 May 2015 at 04:01, Guenter Roeck <[email protected]> wrote:
> On 05/23/2015 12:40 PM, Timur Tabi wrote:
> [ ... ]
>>
>>
>> I use emergency_restart(), because the watchdog-api.txt documentation says
>> this:
>>
>> "If userspace fails (RAM error, kernel bug, whatever), the
>> notifications cease to occur, and the hardware watchdog will reset the
>> system (causing a reboot) after the timeout occurs."
>>
>> Maybe I'm reading this too literally, but to me this means that when the
>> timeout expires, the system has to reset immediately.
>>
>> However, maybe panic() is better, since it can do the same thing and more.
>>
>
> I have a specific requirement at work to have watchdog expiration
> (not this watchdog, this is different HW) result in a panic, specifically
> to enable crashdump support and thus post-mortem analysis.
>
> I had not thought about this use case myself, and I had always wondered
> why watchdog driver implementers would choose to call panic() after an
> interrupt or NMI. But we live and learn, so now I finally understand.
>
> In the pretimeout/timeout world, the pretimeout would (typically)
> result in a panic, and the timeout would result in a reset. So one
> would set the timer register to 10s for 10s pretimeout and 20s timeout.
>
> However, the pretimeout concept assumes that there are two timers
> which can be set independently. As you had pointed out earlier,
> and as the specification seems to confirm, that is not the case here.

Sorry, in Documentation/watchdog/watchdog-api.txt, I can not get the
info about " the pretimeout concept assumes that there are two timers
which can be set independently."
Could you kindly point out where is the assumption.

I thinks in kernel documentation, that meams "one watchdog has two
timeout stages", maybe I miss something. Could you help me out?

> As such, I don't really understand why and how the pretimeout / timeout
> concept would add any value here and not just make things more
> complicated than necessary. Maybe I am just missing something.

If pretimeout concept assumes that there are two timers, I
misunderstand the "pretimeout", then I will delete the pretimeout
immediately.

>
> Thanks,
> Guenter
>



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-24 10:50:56

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Guenter,

On 24 May 2015 at 04:44, Guenter Roeck <[email protected]> wrote:
> On 05/23/2015 01:27 PM, Timur Tabi wrote:
>>
>> Guenter Roeck wrote:
>>>
>>>
>>> However, the pretimeout concept assumes that there are two timers
>>> which can be set independently. As you had pointed out earlier,
>>> and as the specification seems to confirm, that is not the case here.
>>> As such, I don't really understand why and how the pretimeout / timeout
>>> concept would add any value here and not just make things more
>>> complicated than necessary. Maybe I am just missing something.
>>
>>
>> It might be possible to load a new value into the WOR register after the
>> WS0 interrupt occurs. That is, in the interrupt handler, we can do
>> something like this:
>>
>> if (status & SBSA_GWDT_WCS_WS0)
>> // write new WOR value,
>> // then ping watchdog so that it's loaded
>>
>> I'm not convinced that it's worth it, however. It would require
>> interrupts to still be working when WS0 times out, which somewhat defeats
>> the purpose of a watchdog.
>>
>
> If I understand the specification correctly, reloading the register
> would result in another WS0, not in WS1. That isn't really what we
> would want to happen.

Yes, you are 100% correct.
In SBSA:
---------------
An explicit watchdog refresh occurs when one of a number of different
events occur:
(1) The Watchdog Refresh Register is written.
(2) The Watchdog Offset Register is written.
(3) The Watchdog Control and Status register is written.
In the case of an explicit refresh the Watchdog Signals are cleared.
---------------
So, for the second timeout, we can only use WOR.(but maybe we can
write WCV in the WS0 routine to make the second timeout longer, if we
really need a long time for panic)
If we write WOR , that will clean WCS, then the system go back to
first timeout stage.

But for the first timeout, we can use WOR (that means the two timeout
stages will be the same, in another world, WS0==WS1*2 )
or we can write WCV directly.

And writing WCV will not trigger an explicit watchdog refresh, that is
what I am doing to set up pretimeout.

>
> Reloading the register would normally be done in the crashdump kernel,
> if it is loaded, to give it time to actually take the crashdump.
> But that is post-restart, not pre-restart.
>
> Thanks,
> Guenter
>



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-24 14:06:52

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/24/2015 02:58 AM, Fu Wei wrote:
> Hi Guenter,
>
> Great thanks for your suggestion and review,
> I have some questions below , would you please help me out?
>
> On 24 May 2015 at 03:51, Guenter Roeck <[email protected]> wrote:
>> On 05/23/2015 11:37 AM, Timur Tabi wrote:
>>>
>>> Guenter Roeck wrote:
>>>>
>>>> I think it is quite unfortunate that the specification is not public.
>>>> We have heard many statements about what is in the spec or not.
>>>
>>>
>>> All you need to do is go to
>>> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0029b/index.html,
>>> get a free ARM account, and download the spec.
>>>
>> That helps - thanks a lot!
>>
>> Folks, please correct me if my understanding of the specification
>> is wrong.
>>
>> 1) Pretimeout
>>
>> The document suggests that
>> WS1 = WS0 * 2
>
> Are you saying: the first timeout == the second timeout
>
> |-------------WS0
> |-------------WS1
>
> Sorry, could you let me know where is that suggestion??
> I have checked the SBSA again, but I can not find it.
> Maybe I really miss this part.
>

The document states:

"If both watchdog signals are deasserted and a timeout refresh occurs then WS0 is asserted.
If WS0 is asserted and a timeout refresh occurs then WS1 is asserted."

There is no mention that programming both WOR and WCV would or even
could result in different timeouts for the two watchdog signals.

>> is in fact correct. In essence, there is just one counter,
>> not two. This means that a separate pretimeout does not really
>> make sense, since in practice the timeout would always be
>> twice the pretimeout,
>
> Yes, you are right, if we only use "WOR", then the first timeout ==
> the second timeout
>
>> and changing just one without affecting
>> the other is not really possible.
>
> although there is only one counter, and it is 32 bits wide.
> In SBSA, we can see this:
> -------
> Note: the watchdog offset register is 32 bits wide. This gives a
> maximum watch period of around 10s at a system counter frequency of
> 400MHz.
> If a larger watch period is required then the compare value can be
> programmed directly into the compare value register.
> -------
> So for the first timeout, we can set the compare value register(WCV).
> Then the two timeouts are different. and the first timeout has not
> 10s(@400MHz) limit.
> just the the second timeout must use "WOR".
>

That is not how I read the specification. It only talks about
"timeout refresh". There is no indication that using both registers
would have the impact you describe.

Since there is no mention of different WS0 and WS1 timeout periods
in the specification, I am concerned that even _if_ a specific
implementation supports such different timeouts, it would be
implementation specific.

Maybe you and/or Timur can test this on the real systems you
have access to. It should be quite straightforward to test -
have the interrupt handler only print a message, program some
values into the watchdog, and see when WS0 and WS1 occur.

Thanks,
Guenter

2015-05-24 14:15:48

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/24/2015 03:15 AM, Fu Wei wrote:
> Hi Guenter,
>
> On 24 May 2015 at 04:01, Guenter Roeck <[email protected]> wrote:
>> On 05/23/2015 12:40 PM, Timur Tabi wrote:
>> [ ... ]
>>>
>>>
>>> I use emergency_restart(), because the watchdog-api.txt documentation says
>>> this:
>>>
>>> "If userspace fails (RAM error, kernel bug, whatever), the
>>> notifications cease to occur, and the hardware watchdog will reset the
>>> system (causing a reboot) after the timeout occurs."
>>>
>>> Maybe I'm reading this too literally, but to me this means that when the
>>> timeout expires, the system has to reset immediately.
>>>
>>> However, maybe panic() is better, since it can do the same thing and more.
>>>
>>
>> I have a specific requirement at work to have watchdog expiration
>> (not this watchdog, this is different HW) result in a panic, specifically
>> to enable crashdump support and thus post-mortem analysis.
>>
>> I had not thought about this use case myself, and I had always wondered
>> why watchdog driver implementers would choose to call panic() after an
>> interrupt or NMI. But we live and learn, so now I finally understand.
>>
>> In the pretimeout/timeout world, the pretimeout would (typically)
>> result in a panic, and the timeout would result in a reset. So one
>> would set the timer register to 10s for 10s pretimeout and 20s timeout.
>>
>> However, the pretimeout concept assumes that there are two timers
>> which can be set independently. As you had pointed out earlier,
>> and as the specification seems to confirm, that is not the case here.
>
> Sorry, in Documentation/watchdog/watchdog-api.txt, I can not get the
> info about " the pretimeout concept assumes that there are two timers
> which can be set independently."
> Could you kindly point out where is the assumption.
>
> I thinks in kernel documentation, that meams "one watchdog has two
> timeout stages", maybe I miss something. Could you help me out?
>
My apologies. Terminology problem; see below.

Note that the pretimeout, as documented, is a difference to the real
timeout, not an absolute time (which I had not realized before).

"Note that the pretimeout is the number of seconds before the time
when the timeout will go off. It is not the number of seconds until
the pretimeout. So, for instance, if you set the timeout to 60 seconds
and the pretimeout to 10 seconds, the pretimeout will go off in 50
seconds. Setting a pretimeout to zero disables it."

>> As such, I don't really understand why and how the pretimeout / timeout
>> concept would add any value here and not just make things more
>> complicated than necessary. Maybe I am just missing something.
>
> If pretimeout concept assumes that there are two timers, I
> misunderstand the "pretimeout", then I will delete the pretimeout
> immediately.
>
I think I used the wrong term. I should have said something like
"two distinct timeout values".

Guenter

2015-05-24 15:02:12

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Fu Wei wrote:
> If pretimeout concept assumes that there are two timers, I
> misunderstand the "pretimeout", then I will delete the pretimeout
> immediately.

In my opinion, calling panic() on a pre-timeout is not useful, because
that's really just a normal timeout. If there were a way to "warn" user
space that a timeout is about to occur, without a panic or reset, then
that might be useful. But as far as I can see, all you're doing is
redefining the word "timeout".

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-24 15:06:40

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Guenter Roeck wrote:
>
> Maybe you and/or Timur can test this on the real systems you
> have access to. It should be quite straightforward to test -
> have the interrupt handler only print a message, program some
> values into the watchdog, and see when WS0 and WS1 occur.

I'll try, but on my system, WS1 is currently not implemented fully. Let
me investigate and get back to you.

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-24 15:37:06

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Guenter,

Great thanks for your time,
you provide your feedback in your weekend, I am so appreciate that.

my feedback inline below

On 24 May 2015 at 22:06, Guenter Roeck <[email protected]> wrote:
> On 05/24/2015 02:58 AM, Fu Wei wrote:
>>
>> Hi Guenter,
>>
>> Great thanks for your suggestion and review,
>> I have some questions below , would you please help me out?
>>
>> On 24 May 2015 at 03:51, Guenter Roeck <[email protected]> wrote:
>>>
>>> On 05/23/2015 11:37 AM, Timur Tabi wrote:
>>>>
>>>>
>>>> Guenter Roeck wrote:
>>>>>
>>>>>
>>>>> I think it is quite unfortunate that the specification is not public.
>>>>> We have heard many statements about what is in the spec or not.
>>>>
>>>>
>>>>
>>>> All you need to do is go to
>>>>
>>>> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0029b/index.html,
>>>> get a free ARM account, and download the spec.
>>>>
>>> That helps - thanks a lot!
>>>
>>> Folks, please correct me if my understanding of the specification
>>> is wrong.
>>>
>>> 1) Pretimeout
>>>
>>> The document suggests that
>>> WS1 = WS0 * 2
>>
>>
>> Are you saying: the first timeout == the second timeout
>>
>> |-------------WS0
>> |-------------WS1
>>
>> Sorry, could you let me know where is that suggestion??
>> I have checked the SBSA again, but I can not find it.
>> Maybe I really miss this part.
>>
>
> The document states:
>
> "If both watchdog signals are deasserted and a timeout refresh occurs then
> WS0 is asserted.
> If WS0 is asserted and a timeout refresh occurs then WS1 is asserted."

yes, this just describe how the WS0/WS1 are deasserted or asserted.
but it doesn't suggest WS1 = WS0 * 2.
Of course, If we only config WOR in the driver, we get WS1 = WS0 * 2.

If we delete pretimeout concept from this driver
Then what is the timeout, |-------------WS0 or
|-------------WS0-------------WS1 ?

If we only config WOR , the timeout for two stage will be the same
I think the first stage should be called timeout, the user get a
panic in timeout(the first stage)
Then we can tell user, in this driver, if first timeout is triggered
but fail, we can wait for the same time for reboot.

but the second timeout is still like a pretimeout, why not just use it ?

IMO, the key point of SBSA watchdog is two signal, and the first one
is interrupt, the second one maybe a hardware reset OR a interrupt
if we drop "pretimeout", the watchdog just acts like a common watchdog
(just like SP805)

Now we assume that the second signal is a reset, but according to
SBSA, that maybe a interrupt. If that happens on a Soc(that will
happen), how to deal with that?
what is the timeout between WS0 and WS1?

If the two signals are all connect to interrupts, I think we still
need a pretimeout. why not use pretimeout right now. that will be more
easy to maintain the driver.

>
> There is no mention that programming both WOR and WCV would or even
> could result in different timeouts for the two watchdog signals.

yes, they don't mention it.
using WCV to config the first stage and WOR for the second stage is
my idea to solve the two stage timeouts.
Because by this way, we can make the first stage longer(has not that
10s(@400MHz) limit), and we can provide the full feature of SBSA
watchdog.
as I have mentioned above, If the two signals are all connect to
interrupts, we don't need to tell user : the two stage timeout must be
the same and 10s(@400MHz) limit,

>
>>> is in fact correct. In essence, there is just one counter,
>>> not two. This means that a separate pretimeout does not really
>>> make sense, since in practice the timeout would always be
>>> twice the pretimeout,
>>
>>
>> Yes, you are right, if we only use "WOR", then the first timeout ==
>> the second timeout
>>
>>> and changing just one without affecting
>>> the other is not really possible.
>>
>>
>> although there is only one counter, and it is 32 bits wide.
>> In SBSA, we can see this:
>> -------
>> Note: the watchdog offset register is 32 bits wide. This gives a
>> maximum watch period of around 10s at a system counter frequency of
>> 400MHz.
>> If a larger watch period is required then the compare value can be
>> programmed directly into the compare value register.
>> -------
>> So for the first timeout, we can set the compare value register(WCV).
>> Then the two timeouts are different. and the first timeout has not
>> 10s(@400MHz) limit.
>> just the the second timeout must use "WOR".
>>
>
> That is not how I read the specification. It only talks about
> "timeout refresh". There is no indication that using both registers
> would have the impact you describe.
>
> Since there is no mention of different WS0 and WS1 timeout periods
> in the specification, I am concerned that even _if_ a specific
> implementation supports such different timeouts, it would be
> implementation specific.

yes, you are right, they don't mention, but they can be different,
that is the way I use.
I just put limit on user , say: the two timeout must be the same. I
hope my driver can provide the full feature of hardware.
but they make driver a little more complicated than the one which
simply config WOR.
I have to say , another one make SBSA watchdog become a watchdog.

>
> Maybe you and/or Timur can test this on the real systems you
> have access to. It should be quite straightforward to test -
> have the interrupt handler only print a message, program some
> values into the watchdog, and see when WS0 and WS1 occur.

yes, the first version of my driver has printed the timeleft out, I
can have different timeouts and pretimeout

>
> Thanks,
> Guenter
>



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-24 15:50:52

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Guenter,

Thanks for your feedback

On 24 May 2015 at 22:15, Guenter Roeck <[email protected]> wrote:
> On 05/24/2015 03:15 AM, Fu Wei wrote:
>>
>> Hi Guenter,
>>
>> On 24 May 2015 at 04:01, Guenter Roeck <[email protected]> wrote:
>>>
>>> On 05/23/2015 12:40 PM, Timur Tabi wrote:
>>> [ ... ]
>>>>
>>>>
>>>>
>>>> I use emergency_restart(), because the watchdog-api.txt documentation
>>>> says
>>>> this:
>>>>
>>>> "If userspace fails (RAM error, kernel bug, whatever), the
>>>> notifications cease to occur, and the hardware watchdog will reset the
>>>> system (causing a reboot) after the timeout occurs."
>>>>
>>>> Maybe I'm reading this too literally, but to me this means that when the
>>>> timeout expires, the system has to reset immediately.
>>>>
>>>> However, maybe panic() is better, since it can do the same thing and
>>>> more.
>>>>
>>>
>>> I have a specific requirement at work to have watchdog expiration
>>> (not this watchdog, this is different HW) result in a panic, specifically
>>> to enable crashdump support and thus post-mortem analysis.
>>>
>>> I had not thought about this use case myself, and I had always wondered
>>> why watchdog driver implementers would choose to call panic() after an
>>> interrupt or NMI. But we live and learn, so now I finally understand.
>>>
>>> In the pretimeout/timeout world, the pretimeout would (typically)
>>> result in a panic, and the timeout would result in a reset. So one
>>> would set the timer register to 10s for 10s pretimeout and 20s timeout.
>>>
>>> However, the pretimeout concept assumes that there are two timers
>>> which can be set independently. As you had pointed out earlier,
>>> and as the specification seems to confirm, that is not the case here.
>>
>>
>> Sorry, in Documentation/watchdog/watchdog-api.txt, I can not get the
>> info about " the pretimeout concept assumes that there are two timers
>> which can be set independently."
>> Could you kindly point out where is the assumption.
>>
>> I thinks in kernel documentation, that meams "one watchdog has two
>> timeout stages", maybe I miss something. Could you help me out?
>>
> My apologies. Terminology problem; see below.
>
> Note that the pretimeout, as documented, is a difference to the real
> timeout, not an absolute time (which I had not realized before).
>
> "Note that the pretimeout is the number of seconds before the time
> when the timeout will go off. It is not the number of seconds until
> the pretimeout. So, for instance, if you set the timeout to 60 seconds
> and the pretimeout to 10 seconds, the pretimeout will go off in 50
> seconds. Setting a pretimeout to zero disables it."

yes , this patchset is designed for this pretimeout concept

>
>>> As such, I don't really understand why and how the pretimeout / timeout
>>> concept would add any value here and not just make things more
>>> complicated than necessary. Maybe I am just missing something.
>>
>>
>> If pretimeout concept assumes that there are two timers, I
>> misunderstand the "pretimeout", then I will delete the pretimeout
>> immediately.
>>
> I think I used the wrong term. I should have said something like
> "two distinct timeout values".

Actually, I have added my thought at the head of sbsa_gwdt.c as a comment :

*
* Note: This SBSA Generic watchdog driver is compatible with
* the pretimeout concept of Linux kernel.
* The timeout and pretimeout are set by the different REGs.
* The first watch period is set by writing WCV directly,
* that can support more than 10s timeout at the maximum
* system counter frequency.
* The second watch period is set by WOR(32bit) which will be loaded
* automatically by hardware, when WS0 is triggered.
* This gives a maximum watch period of around 10s at the maximum
* system counter frequency.
* The System Counter shall run at maximum of 400MHz.
* More details: DEN0029B - Server Base System Architecture (SBSA)
*
* Kernel/API: P---------| pretimeout
* |-------------------------------T timeout
* SBSA GWDT: P--WOR---WS1 pretimeout
* |-------WCV----------WS0~~~~~~~~T timeout
*/


>
> Guenter
>



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-24 16:04:38

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Timur,

I have said this before:

in the first timeout, just panic() maybe not enough, in [RFC]
version of my patchset, I offer some option as "preaction" to use, but
for simplifying the first version of driver, I have deleted them.
but at least, panic() is far more useful than a simple reset. at
least, it can provide the context of the crashed system to admin.

If you want to warn user space, that will make driver more
complicated, I don't think that is a good choose for a first version.
but we can find a way to improve this later

On 24 May 2015 at 23:02, Timur Tabi <[email protected]> wrote:
> Fu Wei wrote:
>>
>> If pretimeout concept assumes that there are two timers, I
>> misunderstand the "pretimeout", then I will delete the pretimeout
>> immediately.
>
>
> In my opinion, calling panic() on a pre-timeout is not useful, because
> that's really just a normal timeout. If there were a way to "warn" user
> space that a timeout is about to occur, without a panic or reset, then that
> might be useful. But as far as I can see, all you're doing is redefining
> the word "timeout".
>
>
> --
> Sent by an employee of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the
> Code Aurora Forum, hosted by The Linux Foundation.



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-24 16:13:37

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Fu Wei wrote:
> in the first timeout, just panic() maybe not enough, in [RFC]
> version of my patchset, I offer some option as "preaction" to use, but
> for simplifying the first version of driver, I have deleted them.
> but at least, panic() is far more useful than a simple reset. at
> least, it can provide the context of the crashed system to admin.

My point is that there is very little difference between

1) calling panic() on pre-timeout
2) calling panic() on timeout

In both cases, the system will panic. The watchdog API says that the
system should reset when a timeout occurs, so you cannot call panic()
before the timeout expires.

> If you want to warn user space, that will make driver more
> complicated, I don't think that is a good choose for a first version.
> but we can find a way to improve this later

In my opinion, this "first version" is not useful. I would like to see
a pre-timeout feature that does not panic or reset when a pre-timeout
occurs.

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-24 16:17:35

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

Hi Guenter,


On 22 May 2015 at 23:05, Guenter Roeck <[email protected]> wrote:
> On Fri, May 22, 2015 at 10:38:32PM +0800, Fu Wei wrote:
>> Hi Guenter.
>>
>> Sorry for my poor English .
>> let me explain this :
>>
>> On 22 May 2015 at 21:23, Guenter Roeck <[email protected]> wrote:
>> > On 05/22/2015 03:46 AM, Fu Wei wrote:
>> >>
>> >> Hi Timo,
>> >>
>> > [ ... ]
>> >
>> >> So I am still trying to improve pretimeout support :-)
>> >
>> >
>> > Is there anything still missing from it ?
>> >
>> >> If I can make pretimeout merged, may be you can try pretimeout to
>> >> implement early_timeout_sec function?
>> >
>> >
>> > Not sure how one would or even could do that.
>> >
>> > Do you mean "implement early_pretimeout_sec", by any chance ?
>>
>> I mean: using pretimeout to implement the function you want, instead
>> of early_pretimeout_sec
>>
> How would this work if the watchdog hardware doesn't support pretimeout ?
>
> Pretimeout and early timeout are two logically different functions, with
> different goals, so I don't entirely (if at all) understand why it would
> make sense to tie them together.
>
> Can you elaborate why you think this would be a good idea ?

sorry, my apology. forget about this, :-)
I think we should focus on SBSA watchdog patch here, but not a
early_timeout_sec.

>
> Thanks,
> Guenter
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-24 16:23:37

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/24/2015 08:50 AM, Fu Wei wrote:
[ ...]

> Actually, I have added my thought at the head of sbsa_gwdt.c as a comment :
>
> *
> * Note: This SBSA Generic watchdog driver is compatible with
> * the pretimeout concept of Linux kernel.
> * The timeout and pretimeout are set by the different REGs.
> * The first watch period is set by writing WCV directly,
> * that can support more than 10s timeout at the maximum
> * system counter frequency.
> * The second watch period is set by WOR(32bit) which will be loaded
> * automatically by hardware, when WS0 is triggered.
> * This gives a maximum watch period of around 10s at the maximum
> * system counter frequency.
> * The System Counter shall run at maximum of 400MHz.
> * More details: DEN0029B - Server Base System Architecture (SBSA)
> *
> * Kernel/API: P---------| pretimeout
> * |-------------------------------T timeout
> * SBSA GWDT: P--WOR---WS1 pretimeout
> * |-------WCV----------WS0~~~~~~~~T timeout
> */
>

Yes, but do we actually _know_ that it works that way, ie that WCV
drives WS0 and that WOR drives WS1 ? Unless I am missing something,
the specification doesn't say that, and it would have been a really
easy statement to make if that was the intent.

My concern here is that the above behavior is not spelled out in
the document, meaning it is up to interpretation by the hardware
engineer implementing it, to the point where it appears that not
even two software engineers can agree how it is supposed to work.
Which is a really bad starting point :-(.

Thanks,
Guenter

2015-05-24 16:29:43

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/24/2015 09:13 AM, Timur Tabi wrote:
> Fu Wei wrote:
>> in the first timeout, just panic() maybe not enough, in [RFC]
>> version of my patchset, I offer some option as "preaction" to use, but
>> for simplifying the first version of driver, I have deleted them.
>> but at least, panic() is far more useful than a simple reset. at
>> least, it can provide the context of the crashed system to admin.
>
> My point is that there is very little difference between
>
> 1) calling panic() on pre-timeout
> 2) calling panic() on timeout
>

The assumption would be that the second timeout doesn't cause a panic
but a system reset.

> In both cases, the system will panic. The watchdog API says that the system should reset when a timeout occurs, so you cannot call panic() before the timeout expires.
>
> > If you want to warn user space, that will make driver more
> > complicated, I don't think that is a good choose for a first version.
> > but we can find a way to improve this later
>
> In my opinion, this "first version" is not useful. I would like to see a pre-timeout feature that does not panic or reset when a pre-timeout occurs.
>

The current watchdog API suggests that the pretimeout "allows Linux
to record useful information (like panic information and kernel
coredumps) before it resets". The call to panic() would be the
means to make this happen.

Are you suggesting to change this definition ? What should it do
instead in your opinion ?

Thanks,
Guenter

2015-05-24 16:29:50

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Timur,

Sorry, how do you trigger a panic if WS1 ties to reset ?? don't know
what is your question

could you make it simple:

1) calling panic() on pre-timeout (WS0????)
2) calling panic() on timeout (WS1????)

in "first version" , I just print the timeleft for WS1 or panic when
WS0 occurs.

On 25 May 2015 at 00:13, Timur Tabi <[email protected]> wrote:
> Fu Wei wrote:
>>
>> in the first timeout, just panic() maybe not enough, in [RFC]
>> version of my patchset, I offer some option as "preaction" to use, but
>> for simplifying the first version of driver, I have deleted them.
>> but at least, panic() is far more useful than a simple reset. at
>> least, it can provide the context of the crashed system to admin.
>
>
> My point is that there is very little difference between
>
> 1) calling panic() on pre-timeout
> 2) calling panic() on timeout
>
> In both cases, the system will panic. The watchdog API says that the system
> should reset when a timeout occurs, so you cannot call panic() before the
> timeout expires.
>
>> If you want to warn user space, that will make driver more
>> complicated, I don't think that is a good choose for a first version.
>> but we can find a way to improve this later
>
> In my opinion, this "first version" is not useful. I would like to see a
> pre-timeout feature that does not panic or reset when a pre-timeout occurs.
>
>
> --
> Sent by an employee of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the
> Code Aurora Forum, hosted by The Linux Foundation.



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-24 16:33:14

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Guenter

On 25 May 2015 at 00:29, Guenter Roeck <[email protected]> wrote:
> On 05/24/2015 09:13 AM, Timur Tabi wrote:
>>
>> Fu Wei wrote:
>>>
>>> in the first timeout, just panic() maybe not enough, in [RFC]
>>> version of my patchset, I offer some option as "preaction" to use, but
>>> for simplifying the first version of driver, I have deleted them.
>>> but at least, panic() is far more useful than a simple reset. at
>>> least, it can provide the context of the crashed system to admin.
>>
>>
>> My point is that there is very little difference between
>>
>> 1) calling panic() on pre-timeout
>> 2) calling panic() on timeout
>>
>
> The assumption would be that the second timeout doesn't cause a panic
> but a system reset.
>
>> In both cases, the system will panic. The watchdog API says that the
>> system should reset when a timeout occurs, so you cannot call panic() before
>> the timeout expires.
>>
>> > If you want to warn user space, that will make driver more
>> > complicated, I don't think that is a good choose for a first version.
>> > but we can find a way to improve this later
>>
>> In my opinion, this "first version" is not useful. I would like to see a
>> pre-timeout feature that does not panic or reset when a pre-timeout occurs.
>>
>
> The current watchdog API suggests that the pretimeout "allows Linux
> to record useful information (like panic information and kernel
> coredumps) before it resets". The call to panic() would be the
> means to make this happen.

Yes, that is what I mean. Great thanks for your explanation. :-)

>
> Are you suggesting to change this definition ? What should it do
> instead in your opinion ?
>
> Thanks,
> Guenter
>



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-24 16:44:40

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Guenter Roeck wrote:

> The current watchdog API suggests that the pretimeout "allows Linux
> to record useful information (like panic information and kernel
> coredumps) before it resets". The call to panic() would be the
> means to make this happen.

Now that I think about it, that does make sense.

However, if a pre-timeout is not set, then the driver should never call
panic(). That means that the interrupt handler should only be
registered if sbsa_gwdt_set_pretimeout() is called.

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-24 16:47:19

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Guenter,

On 25 May 2015 at 00:23, Guenter Roeck <[email protected]> wrote:
> On 05/24/2015 08:50 AM, Fu Wei wrote:
> [ ...]
>
>> Actually, I have added my thought at the head of sbsa_gwdt.c as a comment
>> :
>>
>> *
>> * Note: This SBSA Generic watchdog driver is compatible with
>> * the pretimeout concept of Linux kernel.
>> * The timeout and pretimeout are set by the different REGs.
>> * The first watch period is set by writing WCV directly,
>> * that can support more than 10s timeout at the maximum
>> * system counter frequency.
>> * The second watch period is set by WOR(32bit) which will be
>> loaded
>> * automatically by hardware, when WS0 is triggered.
>> * This gives a maximum watch period of around 10s at the maximum
>> * system counter frequency.
>> * The System Counter shall run at maximum of 400MHz.
>> * More details: DEN0029B - Server Base System Architecture (SBSA)
>> *
>> * Kernel/API: P---------| pretimeout
>> * |-------------------------------T timeout
>> * SBSA GWDT: P--WOR---WS1 pretimeout
>> * |-------WCV----------WS0~~~~~~~~T timeout
>> */
>>
>
> Yes, but do we actually _know_ that it works that way, ie that WCV
> drives WS0 and that WOR drives WS1 ? Unless I am missing something,
> the specification doesn't say that, and it would have been a really
> easy statement to make if that was the intent.

yes, Suravee has tested it on Seattle B0 Soc, that works.
But hope Suravee can provide more info about test, I will ping him later.

According to SBSA, that WCV and WOR can both drive WS1 and WS0

the timeout and pretimeout in my patchset have been tested on Seattle
B0 and Foundation model.

>
> My concern here is that the above behavior is not spelled out in
> the document, meaning it is up to interpretation by the hardware
> engineer implementing it, to the point where it appears that not
> even two software engineers can agree how it is supposed to work.
> Which is a really bad starting point :-(.

Is that a real hardware teat can prove it works?

or actually, SBSA say that it should work:
-----------------
Note: the watchdog offset register is 32 bits wide. This gives a
maximum watch period of around 10s at a system
counter frequency of 400MHz. If a larger watch period is required then
the compare value can be programmed
directly into the compare value register.
-----------------
offset register == WOR
compare value register == WCV

>
> Thanks,
> Guenter
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-24 16:50:29

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/24/2015 09:44 AM, Timur Tabi wrote:
> Guenter Roeck wrote:
>
>> The current watchdog API suggests that the pretimeout "allows Linux
>> to record useful information (like panic information and kernel
>> coredumps) before it resets". The call to panic() would be the
>> means to make this happen.
>
> Now that I think about it, that does make sense.
>
> However, if a pre-timeout is not set, then the driver should never call panic(). That means that the interrupt handler should only be registered if sbsa_gwdt_set_pretimeout() is called.
>

This is a matter of opinion. Some watchdogs have two (or even more)
levels of timeouts without explicit pretimeout. The iTCO watchdog
in Intel systems is an example, but there are several others.

For such systems, there may be an initial interrupt followed
by a hard reset a little later. In such cases it does make sense
to wire up the interrupt and have it call panic(). If the system
gets stuck, the second timeout will reset it.

Guenter

2015-05-24 16:52:52

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Timur

On 25 May 2015 at 00:44, Timur Tabi <[email protected]> wrote:
> Guenter Roeck wrote:
>
>> The current watchdog API suggests that the pretimeout "allows Linux
>> to record useful information (like panic information and kernel
>> coredumps) before it resets". The call to panic() would be the
>> means to make this happen.
>
>
> Now that I think about it, that does make sense.
>
> However, if a pre-timeout is not set, then the driver should never call
> panic(). That means that the interrupt handler should only be registered if
> sbsa_gwdt_set_pretimeout() is called.

I don't know why you want to do this tricky way. you can always
register the interrupt handler,
if pre-timeout is 0, system will just trigger WS1 right after WS0


>
>
> --
> Sent by an employee of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the
> Code Aurora Forum, hosted by The Linux Foundation.



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-24 16:58:13

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/24/2015 09:47 AM, Fu Wei wrote:
> Hi Guenter,
>
> On 25 May 2015 at 00:23, Guenter Roeck <[email protected]> wrote:
>> On 05/24/2015 08:50 AM, Fu Wei wrote:
>> [ ...]
>>
>>> Actually, I have added my thought at the head of sbsa_gwdt.c as a comment
>>> :
>>>
>>> *
>>> * Note: This SBSA Generic watchdog driver is compatible with
>>> * the pretimeout concept of Linux kernel.
>>> * The timeout and pretimeout are set by the different REGs.
>>> * The first watch period is set by writing WCV directly,
>>> * that can support more than 10s timeout at the maximum
>>> * system counter frequency.
>>> * The second watch period is set by WOR(32bit) which will be
>>> loaded
>>> * automatically by hardware, when WS0 is triggered.
>>> * This gives a maximum watch period of around 10s at the maximum
>>> * system counter frequency.
>>> * The System Counter shall run at maximum of 400MHz.
>>> * More details: DEN0029B - Server Base System Architecture (SBSA)
>>> *
>>> * Kernel/API: P---------| pretimeout
>>> * |-------------------------------T timeout
>>> * SBSA GWDT: P--WOR---WS1 pretimeout
>>> * |-------WCV----------WS0~~~~~~~~T timeout
>>> */
>>>
>>
>> Yes, but do we actually _know_ that it works that way, ie that WCV
>> drives WS0 and that WOR drives WS1 ? Unless I am missing something,
>> the specification doesn't say that, and it would have been a really
>> easy statement to make if that was the intent.
>
> yes, Suravee has tested it on Seattle B0 Soc, that works.
> But hope Suravee can provide more info about test, I will ping him later.
>
> According to SBSA, that WCV and WOR can both drive WS1 and WS0
>
> the timeout and pretimeout in my patchset have been tested on Seattle
> B0 and Foundation model.
>
>>
>> My concern here is that the above behavior is not spelled out in
>> the document, meaning it is up to interpretation by the hardware
>> engineer implementing it, to the point where it appears that not
>> even two software engineers can agree how it is supposed to work.
>> Which is a really bad starting point :-(.
>
> Is that a real hardware teat can prove it works?
>
> or actually, SBSA say that it should work:
> -----------------
> Note: the watchdog offset register is 32 bits wide. This gives a
> maximum watch period of around 10s at a system
> counter frequency of 400MHz. If a larger watch period is required then
> the compare value can be programmed
> directly into the compare value register.
> -----------------
> offset register == WOR
> compare value register == WCV
>

Where does it say that WCV shall be associated with WS0 and that WOR
shall be associated with WS1 ? Guess I am missing that part.

Thanks,
Guenter

2015-05-24 17:04:38

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Guenter,



On 25 May 2015 at 00:58, Guenter Roeck <[email protected]> wrote:
> On 05/24/2015 09:47 AM, Fu Wei wrote:
>>
>> Hi Guenter,
>>
>> On 25 May 2015 at 00:23, Guenter Roeck <[email protected]> wrote:
>>>
>>> On 05/24/2015 08:50 AM, Fu Wei wrote:
>>> [ ...]
>>>
>>>> Actually, I have added my thought at the head of sbsa_gwdt.c as a
>>>> comment
>>>> :
>>>>
>>>> *
>>>> * Note: This SBSA Generic watchdog driver is compatible with
>>>> * the pretimeout concept of Linux kernel.
>>>> * The timeout and pretimeout are set by the different REGs.
>>>> * The first watch period is set by writing WCV directly,
>>>> * that can support more than 10s timeout at the maximum
>>>> * system counter frequency.
>>>> * The second watch period is set by WOR(32bit) which will be
>>>> loaded
>>>> * automatically by hardware, when WS0 is triggered.
>>>> * This gives a maximum watch period of around 10s at the
>>>> maximum
>>>> * system counter frequency.
>>>> * The System Counter shall run at maximum of 400MHz.
>>>> * More details: DEN0029B - Server Base System Architecture
>>>> (SBSA)
>>>> *
>>>> * Kernel/API: P---------| pretimeout
>>>> * |-------------------------------T timeout
>>>> * SBSA GWDT: P--WOR---WS1 pretimeout
>>>> * |-------WCV----------WS0~~~~~~~~T timeout
>>>> */
>>>>
>>>
>>> Yes, but do we actually _know_ that it works that way, ie that WCV
>>> drives WS0 and that WOR drives WS1 ? Unless I am missing something,
>>> the specification doesn't say that, and it would have been a really
>>> easy statement to make if that was the intent.
>>
>>
>> yes, Suravee has tested it on Seattle B0 Soc, that works.
>> But hope Suravee can provide more info about test, I will ping him later.
>>
>> According to SBSA, that WCV and WOR can both drive WS1 and WS0
>>
>> the timeout and pretimeout in my patchset have been tested on Seattle
>> B0 and Foundation model.
>>
>>>
>>> My concern here is that the above behavior is not spelled out in
>>> the document, meaning it is up to interpretation by the hardware
>>> engineer implementing it, to the point where it appears that not
>>> even two software engineers can agree how it is supposed to work.
>>> Which is a really bad starting point :-(.
>>
>>
>> Is that a real hardware teat can prove it works?
>>
>> or actually, SBSA say that it should work:
>> -----------------
>> Note: the watchdog offset register is 32 bits wide. This gives a
>> maximum watch period of around 10s at a system
>> counter frequency of 400MHz. If a larger watch period is required then
>> the compare value can be programmed
>> directly into the compare value register.
>> -----------------
>> offset register == WOR
>> compare value register == WCV
>>
>
> Where does it say that WCV shall be associated with WS0 and that WOR
> shall be associated with WS1 ? Guess I am missing that part.

no, it doesn't say WCV shall be associated with WS0, that is my driver doing.

but WCV can control both WS1/WS0. WOR is just a auto-reload value.

I think maybe you can read SBSA 2.3 Page 23, The pseudocode can
explain everything. :-)

Great thanks for your time

>
>
> Thanks,
> Guenter
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-24 17:19:14

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Fu Wei wrote:
> I don't know why you want to do this tricky way. you can always
> register the interrupt handler,
> if pre-timeout is 0, system will just trigger WS1 right after WS0

But that only works if the pre-timeout and timeout can be programmed to
separate values. And as Guenter says, the SBSA may not guarantee that.

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-24 17:23:34

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Timur,

On 25 May 2015 at 01:19, Timur Tabi <[email protected]> wrote:
> Fu Wei wrote:
>>
>> I don't know why you want to do this tricky way. you can always
>> register the interrupt handler,
>> if pre-timeout is 0, system will just trigger WS1 right after WS0
>
>
> But that only works if the pre-timeout and timeout can be programmed to
> separate values. And as Guenter says, the SBSA may not guarantee that.

In my driver patch, the first stage, I am using WCV, for the second
stage I am using WOR,
that have been tested on real hardware.

would you please read the pseudocode in Page 23 of SBSA 2.3

>
>
> --
> Sent by an employee of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the
> Code Aurora Forum, hosted by The Linux Foundation.



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-24 17:32:41

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

On 05/24/2015 10:19 AM, Timur Tabi wrote:
> Fu Wei wrote:
>> I don't know why you want to do this tricky way. you can always
>> register the interrupt handler,
>> if pre-timeout is 0, system will just trigger WS1 right after WS0
>
> But that only works if the pre-timeout and timeout can be programmed to separate values. And as Guenter says, the SBSA may not guarantee that.
>

The pseudo-code in the specification suggests that if WCV is configured,
WS0 = WCV
WS1 = WCV + WOR

Assuming that the implementation follows the pseudo-code in the specification,
we would have separately programmable values. Since the pretimeout (per ABI)
is the difference in seconds to the timeout, and not an absolute value,
we would have to program the registers as follows.

WCV = timeout - pretimeout;
WOR = pretimeout;

Does this make sense ?

Thanks,
Guenter

2015-05-24 17:47:21

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Guenter Roeck wrote:
>
> The pseudo-code in the specification suggests that if WCV is configured,
> WS0 = WCV
> WS1 = WCV + WOR
>
> Assuming that the implementation follows the pseudo-code in the
> specification,
> we would have separately programmable values. Since the pretimeout (per
> ABI)
> is the difference in seconds to the timeout, and not an absolute value,
> we would have to program the registers as follows.
>
> WCV = timeout - pretimeout;
> WOR = pretimeout;
>
> Does this make sense ?

Yes, thank you. I will test this on my hardware.

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-25 02:00:29

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi, Guenter,



On 25 May 2015 at 01:32, Guenter Roeck <[email protected]> wrote:
> On 05/24/2015 10:19 AM, Timur Tabi wrote:
>>
>> Fu Wei wrote:
>>>
>>> I don't know why you want to do this tricky way. you can always
>>> register the interrupt handler,
>>> if pre-timeout is 0, system will just trigger WS1 right after WS0
>>
>>
>> But that only works if the pre-timeout and timeout can be programmed to
>> separate values. And as Guenter says, the SBSA may not guarantee that.
>>
>
> The pseudo-code in the specification suggests that if WCV is configured,
> WS0 = WCV
> WS1 = WCV + WOR
>
> Assuming that the implementation follows the pseudo-code in the
> specification,
> we would have separately programmable values. Since the pretimeout (per ABI)
> is the difference in seconds to the timeout, and not an absolute value,
> we would have to program the registers as follows.
>
> WCV = timeout - pretimeout;
> WOR = pretimeout;

yes, this patchset is doing this way.

>
> Does this make sense ?
>
> Thanks,
> Guenter
>



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-25 02:03:09

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Guenter,


On 25 May 2015 at 01:47, Timur Tabi <[email protected]> wrote:
> Guenter Roeck wrote:
>>
>>
>> The pseudo-code in the specification suggests that if WCV is configured,
>> WS0 = WCV
>> WS1 = WCV + WOR
>>
>> Assuming that the implementation follows the pseudo-code in the
>> specification,
>> we would have separately programmable values. Since the pretimeout (per
>> ABI)
>> is the difference in seconds to the timeout, and not an absolute value,
>> we would have to program the registers as follows.
>>
>> WCV = timeout - pretimeout;
>> WOR = pretimeout;
>>
>> Does this make sense ?

And actually all the patchset I sent to upstream are all follow this
design, and have been test on Foundation model and Seattle B0

>
>
> Yes, thank you. I will test this on my hardware.
>
>
> --
> Sent by an employee of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the
> Code Aurora Forum, hosted by The Linux Foundation.



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-25 03:09:03

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework

Hi Guenter,

Great thanks for your suggestion,

I have put this kind of validation into watchdog_pretimeout_invalid
and watchdog_timeout_invalid.

So :

(1)
set_timeout(10); ------> if this setting is successful
set_pretimeout(20); -----> return fail (-EINVAL)


(2)
set_timeout(10); ------> if this setting is successful
set_pretimeout(10); -----> return fail (-EINVAL)

this kind of situation will not result in an invalid / unexpected timeout value.

you will see this change in my next patchset

On 21 May 2015 at 23:32, Guenter Roeck <[email protected]> wrote:
> On Thu, May 21, 2015 at 04:32:34PM +0800, [email protected] wrote:
>> From: Fu Wei <[email protected]>
>>
>> Also update Documentation/watchdog/watchdog-kernel-api.txt to
>> introduce:
>> (1)the new elements in the watchdog_device and watchdog_ops struct;
>> (2)the new API "watchdog_init_timeouts".
>>
>> Reasons:
>> (1)kernel already has two watchdog drivers are using "pretimeout":
>> drivers/char/ipmi/ipmi_watchdog.c
>> drivers/watchdog/kempld_wdt.c(but the definition is different)
>> (2)some other dirvers are going to use this: ARM SBSA Generic Watchdog
>>
>> Signed-off-by: Fu Wei <[email protected]>
>> ---
>
> [ ... ]
>
>>
>> +/* Use the following function to check if a pretimeout value is invalid */
>> +static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd,
>> + unsigned int t)
>> +{
>> + return ((wdd->max_pretimeout != 0) &&
>> + (t < wdd->min_pretimeout || t > wdd->max_pretimeout));
>> +}
>
> Should this function also enforce "t < wdd->timeout", and
> should watchdog_timeout_invalid() enforce "t > wdd->pretimeout" ?
>
> Thanks,
> Guenter



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-25 03:43:36

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Guenter,

On 21 May 2015 at 23:28, Guenter Roeck <[email protected]> wrote:
> On Thu, May 21, 2015 at 08:09:02AM -0500, Timur Tabi wrote:
>> Guenter Roeck wrote:
>> >>
>> >>+static unsigned int sbsa_gwdt_get_timeleft(struct watchdog_device *wdd)
>> >>+{
>> >>+ struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> >>+ u64 timeleft = sbsa_gwdt_get_wcv(wdd) - arch_counter_get_cntvct();
>> >>+
>> >
>> >Still not happy about the use of arch_counter_get_cntvct
>> >instead of using the clock subsystem. I am quite sure this could be done,
>> >possibly through arch_sys_counter, though at this point I am getting wary
>> >of bringing it up, so I guess I'll just let it go.
>>
>> You made the same comment with my driver, and I keep asking for
>> clarification. The clk_get_sys() API does not work on my system, because
>> there are not clocks defined. That must be an ACPI limitation that I can't
>> fix.
>>
> Would it be possible to define such clocks ?
>
>> The alternative to arch_counter_get_cntvct() is arch_timer_read_counter(),
>> which is not exported. So we have two choices,
>>
>> 1) Continue to use arch_counter_get_cntvct(), which works on all ARM64
>> platforms that this driver supports anyway
>>
>> 2) Export arch_timer_read_counter()
>>
>> I prefer option #1.
>>
> Do we have any feedback from the arm maintainers ?
>
> My problem is that I don't want to be the first one to permit using
> those functions outside architecture and clock code. If we do this,
> we should get an Ack from an arm maintainer specifically for the use
> of arch_counter_get_cntvct() and arch_timer_get_rate().

IMO, we may need to use arch_timer_read_counter.
Reason: Once the Linux kernel has KVM support and is in hyp mode. we
may need to use arch_counter_get_cntpct.
So arch_timer driver have helped us to make arch_timer_read_counter
point to the right function.
and arch_timer_read_counter is in the
include/clocksource/arm_arch_timer.h, just like arch_timer_get_rate
as a interface




>
> Thanks,
> Guenter
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021

2015-05-25 03:46:37

by Timur Tabi

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Fu Wei wrote:
> Once the Linux kernel has KVM support and is in hyp mode. we
> may need to use arch_counter_get_cntpct.

arch_counter_get_cntpct() does not appear to be valid for ARM64:

http://lxr.free-electrons.com/source/arch/arm64/include/asm/arch_timer.h#L108

--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

2015-05-25 04:11:23

by Fu Wei

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver

Hi Timur.


On 25 May 2015 at 11:46, Timur Tabi <[email protected]> wrote:
> Fu Wei wrote:
>>
>> Once the Linux kernel has KVM support and is in hyp mode. we
>> may need to use arch_counter_get_cntpct.
>
>
> arch_counter_get_cntpct() does not appear to be valid for ARM64:
>
> http://lxr.free-electrons.com/source/arch/arm64/include/asm/arch_timer.h#L108

Great thank for correction, that make sense.

>
>
> --
> Sent by an employee of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the
> Code Aurora Forum, hosted by The Linux Foundation.



--
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021