All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] Watchdog: introdouce ARM SBSA watchdog driver
       [not found] <=fu.wei@linaro.org>
@ 2015-05-15 11:08 ` fu.wei
  2015-05-15 11:08   ` [PATCH 1/6] Documentation: add sbsa-gwdt.txt documentation fu.wei
                     ` (3 more replies)
  2015-05-15 11:24 ` [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework fu.wei
                   ` (13 subsequent siblings)
  14 siblings, 4 replies; 550+ messages in thread
From: fu.wei @ 2015-05-15 11:08 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patchset:

    (1)Introdouces 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

    (2)Introdouce "pretimeout" into the watchdog framework

    (3)Introdouces 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

    (4)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

Fu Wei (6):
  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: introdouce "pretimeout" into framework
  Watchdog: introdouce ARM SBSA watchdog driver
  ACPI: import watchdog info of GTDT into platform device

 .../devicetree/bindings/watchdog/sbsa-gwdt.txt     |  36 ++
 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/watchdog/Kconfig                           |  10 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/sbsa_gwdt.c                       | 553 +++++++++++++++++++++
 drivers/watchdog/watchdog_core.c                   |  66 +++
 drivers/watchdog/watchdog_dev.c                    |  48 ++
 include/linux/watchdog.h                           |  19 +
 10 files changed, 890 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

-- 
1.9.1


^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH 1/6] Documentation: add sbsa-gwdt.txt documentation
  2015-05-15 11:08 ` [PATCH 0/6] Watchdog: introdouce ARM SBSA watchdog driver fu.wei
@ 2015-05-15 11:08   ` fu.wei
  2015-05-15 14:06       ` Arnd Bergmann
  2015-05-15 11:08   ` [PATCH 2/6] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts fu.wei
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 550+ messages in thread
From: fu.wei @ 2015-05-15 11:08 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 <fu.wei@linaro.org>
---
 .../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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH 2/6] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
  2015-05-15 11:08 ` [PATCH 0/6] Watchdog: introdouce ARM SBSA watchdog driver fu.wei
  2015-05-15 11:08   ` [PATCH 1/6] Documentation: add sbsa-gwdt.txt documentation fu.wei
@ 2015-05-15 11:08   ` fu.wei
  2015-05-15 11:08     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  2015-05-15 14:07     ` Arnd Bergmann
  3 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-05-15 11:08 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 <fu.wei@linaro.org>
---
 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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH 3/6] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
@ 2015-05-15 11:08     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-05-15 11:08 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 <fu.wei@linaro.org>
---
 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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH 3/6] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
@ 2015-05-15 11:08     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-05-15 11:08 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 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

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
       [not found] <=fu.wei@linaro.org>
  2015-05-15 11:08 ` [PATCH 0/6] Watchdog: introdouce ARM SBSA watchdog driver fu.wei
@ 2015-05-15 11:24 ` fu.wei
  2015-05-15 11:24   ` [PATCH 5/6] Watchdog: introdouce ARM SBSA watchdog driver fu.wei
                     ` (3 more replies)
  2015-05-21  8:32   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                   ` (12 subsequent siblings)
  14 siblings, 4 replies; 550+ messages in thread
From: fu.wei @ 2015-05-15 11:24 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 <fu.wei@linaro.org>
---
 drivers/watchdog/watchdog_core.c | 66 ++++++++++++++++++++++++++++++++++++++++
 drivers/watchdog/watchdog_dev.c  | 48 +++++++++++++++++++++++++++++
 include/linux/watchdog.h         | 19 ++++++++++++
 3 files changed, 133 insertions(+)

diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index cec9b55..6ca9578 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -54,6 +54,14 @@ static void watchdog_check_min_max_timeout(struct watchdog_device *wdd)
 		wdd->min_timeout = 0;
 		wdd->max_timeout = 0;
 	}
+	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;
+	}
 }
 
 /**
@@ -98,6 +106,63 @@ int watchdog_init_timeout(struct watchdog_device *wdd,
 }
 EXPORT_SYMBOL_GPL(watchdog_init_timeout);
 
+static void watchdog_check_min_max_pretimeout(struct watchdog_device *wdd)
+{
+	/*
+	 * Check that we have valid min and max pretimeout 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;
+	}
+}
+
+/**
+ * watchdog_init_pretimeout() - initialize the pretimeout field
+ * @pretimeout_parm: pretimeout module parameter
+ * @dev: Device that stores the timeout-sec property
+ *
+ * Initialize the pretimeout field of the watchdog_device struct with either
+ * the pretimeout 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 pretimeout value.
+ *
+ * A zero is returned on success and -EINVAL for failure.
+ */
+int watchdog_init_pretimeout(struct watchdog_device *wdd,
+			     unsigned int pretimeout_parm, struct device *dev)
+{
+	int ret = 0;
+	u32 timeouts[2];
+
+	watchdog_check_min_max_pretimeout(wdd);
+
+	/* try to get the timeout module parameter first */
+	if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm) &&
+	    pretimeout_parm) {
+		wdd->pretimeout = pretimeout_parm;
+		return ret;
+	}
+	if (pretimeout_parm)
+		ret = -EINVAL;
+
+	/* try to get the timeout_sec property */
+	if (!dev || !dev->of_node)
+		return ret;
+	ret = of_property_read_u32_array(dev->of_node,
+					 "timeout-sec", timeouts, 2);
+	if (!watchdog_pretimeout_invalid(wdd, timeouts[1]) && timeouts[1])
+		wdd->pretimeout = timeouts[1];
+	else
+		ret = -EINVAL;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(watchdog_init_pretimeout);
+
 /**
  * watchdog_register_device() - register a watchdog device
  * @wdd: watchdog device
@@ -119,6 +184,7 @@ int watchdog_register_device(struct watchdog_device *wdd)
 	if (wdd->ops->start == NULL || wdd->ops->stop == NULL)
 		return -EINVAL;
 
+	watchdog_check_min_max_pretimeout(wdd);
 	watchdog_check_min_max_timeout(wdd);
 
 	/*
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..f0a3c5b 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)
 {
@@ -134,6 +150,9 @@ 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_pretimeout(struct watchdog_device *wdd,
+				    unsigned int pretimeout_parm,
+				    struct device *dev);
 extern int watchdog_register_device(struct watchdog_device *);
 extern void watchdog_unregister_device(struct watchdog_device *);
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH 5/6] Watchdog: introdouce ARM SBSA watchdog driver
  2015-05-15 11:24 ` [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework fu.wei
@ 2015-05-15 11:24   ` fu.wei
  2015-05-15 13:57     ` Arnd Bergmann
  2015-05-15 22:57       ` Guenter Roeck
  2015-05-15 11:24   ` [PATCH 6/6] ACPI: import watchdog info of GTDT into platform device fu.wei
                     ` (2 subsequent siblings)
  3 siblings, 2 replies; 550+ messages in thread
From: fu.wei @ 2015-05-15 11:24 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

    (1)Use linux kernel watchdog framework
    (2)Work with FDT on ARM64
    (3)Use "pretimeout" in watchdog framework
    (4)In first timeout(WS0), do panic to save system context
    (5)support geting timeout and pretimeout from
       parameter and FDT at the driver init stage.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 drivers/watchdog/Kconfig     |  10 +
 drivers/watchdog/Makefile    |   1 +
 drivers/watchdog/sbsa_gwdt.c | 553 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 564 insertions(+)
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e5e7c55..1e1bc8b 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -152,6 +152,16 @@ 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
+	select WATCHDOG_CORE
+	help
+	  ARM SBSA Generic Watchdog timer. This has two Watchdog Signal(WS0/WS1),
+	  will trigger a warnning interrupt(do panic) in 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..52838b1
--- /dev/null
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -0,0 +1,553 @@
+/*
+ * SBSA(Server Base System Architecture) Generic Watchdog driver
+ *
+ * Copyright (c) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei@linaro.org>
+ *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
+ *
+ * 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.
+ *       But 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.
+ *       And 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/spinlock.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)
+
+/* Watchdog Interface Identification Register */
+#define SBSA_GWDT_W_IIDR_PID(x)			((x >> 20) & 0xfff)
+#define SBSA_GWDT_W_IIDR_ARCH_VER(x)		((x >> 16) & 0xf)
+#define SBSA_GWDT_W_IIDR_REV(x)			((x >> 12) & 0xf)
+#define SBSA_GWDT_W_IIDR_IMPLEMENTER(x)		(x & 0xfff)
+#define SBSA_GWDT_W_IIDR_VID_BANK(x)		((x >> 8) & 0xf)
+#define SBSA_GWDT_W_IIDR_VID(x)			(x & 0x7f)
+
+/* Watchdog Identification Register */
+#define SBSA_GWDT_IDR_W_PIDR2			0xfe8
+#define SBSA_GWDT_IDR_W_PIDR2_ARCH_VER(x)	((x >> 4) & 0xf)
+
+/**
+ * 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:	VA of the watchdog refresh frame
+ * @control_base:	VA of the watchdog control frame
+ * @lock:		struct sbsa_gwdt spinlock
+ * @pm_status_store:	store the PM info of WDT
+ */
+struct sbsa_gwdt {
+	struct watchdog_device	wdd;
+	u32			clk;
+	void __iomem		*refresh_base;
+	void __iomem		*control_base;
+#ifdef CONFIG_PM_SLEEP
+	spinlock_t		lock;
+	u8			pm_status_store;
+#endif
+};
+
+#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
+
+#define DEFAULT_TIMEOUT_WS0	10 /* seconds, the 1st watch period*/
+#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_WS0 + DEFAULT_PRETIMEOUT) ")");
+
+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 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 unsigned int pretimeout;
+module_param(pretimeout, uint, 0);
+MODULE_PARM_DESC(pretimeout,
+		 "Watchdog pretimeout in seconds. (>=0, default="
+		 __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
+
+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
+ * mutex_lock must be called prior to calling this function.
+ */
+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);
+
+	pr_debug("sbsa_gwdt: set WCV to %llu, result: %llu\n",
+		 value, sbsa_gwdt_get_wcv(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_set_timeout_limits(struct sbsa_gwdt *gwdt)
+{
+	unsigned int first_period_max = (U64_MAX / gwdt->clk);
+	struct watchdog_device *wdd = &gwdt->wdd;
+
+	wdd->min_timeout = wdd->pretimeout + 1;
+	wdd->max_timeout = min(wdd->pretimeout + first_period_max, max_timeout);
+
+	pr_debug("sbsa_gwdt: timeout (%u-%u), pretimeout (%u-%u)\n",
+		 wdd->min_timeout, wdd->max_timeout,
+		 wdd->min_pretimeout, wdd->max_pretimeout);
+}
+
+static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
+				 unsigned int timeout)
+{
+	wdd->timeout = timeout;
+
+	return 0;
+	/* watchdog framework will trigger a ping, after this call */
+}
+
+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_set_timeout_limits(gwdt);
+
+	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);
+
+	pr_debug("sbsa_gwdt: set WOR to %x(%us), result: %x\n",
+		 wor, pretimeout, sbsa_gwdt_cf_read(SBSA_GWDT_WOR, wdd));
+
+	return 0;
+	/* watchdog framework will trigger a ping, after this call */
+}
+
+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();
+
+	return timeleft / gwdt->clk;
+}
+
+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);
+
+	pr_debug("sbsa_gwdt: WCS is %x(%s)\n",
+		 sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd), __func__);
+
+	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);
+
+	pr_debug("sbsa_gwdt: WCS is %x(%s)\n",
+		 sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd), __func__);
+
+	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);
+
+	pr_debug("sbsa_gwdt: ping, %us left.\n", sbsa_gwdt_get_timeleft(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);
+
+	pr_debug("sbsa_gwdt: interrupt routine, WCS@%x\n", status);
+
+	if (status & SBSA_GWDT_WCS_WS0) {
+		pr_debug("sbsa_gwdt WS0: trigger WS1 in %ds!\n",
+			 sbsa_gwdt_get_timeleft(wdd));
+		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, w_iidr;
+
+	int ret = 0;
+
+	/*
+	 * Try to determine the frequency from the cp15 interface
+	 */
+	clk = arch_timer_get_cntfrq();
+	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);
+
+	pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
+		 res->name, (unsigned long long)res->start,
+		(unsigned long long)(res->end - res->start + 1), 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);
+
+	pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
+		 res->name, (unsigned long long)res->start,
+		(unsigned long long)(res->end - res->start + 1), cf_base);
+
+	irq = platform_get_irq_byname(pdev, "ws0");
+	if (irq < 0) {
+		dev_err(dev, "unable to get ws0 interrupt.\n");
+		return irq;
+	}
+
+	pr_debug("sbsa_gwdt: ws0 irq %d.\n", irq);
+
+	gwdt->refresh_base = rf_base;
+	gwdt->control_base = cf_base;
+	gwdt->clk = clk;
+#ifdef CONFIG_PM_SLEEP
+	spin_lock_init(&gwdt->lock);
+#endif
+	platform_set_drvdata(pdev, gwdt);
+
+	pr_debug("sbsa_gwdt: hw clk: %uHz--> WOR(32bit) max timeout is %us.\n",
+		 gwdt->clk, U32_MAX / clk);
+
+	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 was reseted 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!\n");
+		sbsa_gwdt_keepalive(wdd);
+	}
+
+	pr_debug("sbsa_gwdt: WCS: %x(%s)\n", status, __func__);
+
+	wdd->min_pretimeout = 0;
+	wdd->max_pretimeout = min(U32_MAX / clk, max_timeout - 1);
+	sbsa_gwdt_set_timeout_limits(gwdt);
+
+	watchdog_init_pretimeout(wdd, pretimeout, dev);
+	if (!wdd->pretimeout) {
+		wdd->pretimeout = DEFAULT_PRETIMEOUT;
+		dev_info(dev, "can't get pretimeout param, set default %us.\n",
+			 wdd->pretimeout);
+	}
+	sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
+
+	watchdog_init_timeout(wdd, timeout, dev);
+	if (!wdd->timeout) {
+		wdd->timeout = wdd->pretimeout + DEFAULT_TIMEOUT_WS0;
+		dev_info(dev, "can't get timeout param, set default: %us.\n",
+			 wdd->timeout);
+	}
+	sbsa_gwdt_set_timeout(wdd, wdd->timeout);
+
+	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;
+
+	/* get device information from control frame and display */
+	w_iidr = sbsa_gwdt_cf_read(SBSA_GWDT_W_IIDR, &gwdt->wdd);
+	dev_info(dev, "PID:%u(JEP106 %u-%u), Arch v%u Rev %u.",
+		 SBSA_GWDT_W_IIDR_PID(w_iidr),
+		 SBSA_GWDT_W_IIDR_VID_BANK(w_iidr),
+		 SBSA_GWDT_W_IIDR_VID(w_iidr),
+		 SBSA_GWDT_W_IIDR_ARCH_VER(w_iidr),
+		 SBSA_GWDT_W_IIDR_REV(w_iidr));
+
+	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;
+}
+
+#ifdef CONFIG_PM_SLEEP
+/* Disable watchdog if it is active during suspend */
+static int sbsa_gwdt_suspend(struct device *dev)
+{
+	struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
+	struct watchdog_device *wdd = &gwdt->wdd;
+
+	spin_lock(&gwdt->lock);
+	gwdt->pm_status_store = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
+
+	if (gwdt->pm_status_store & SBSA_GWDT_WCS_EN)
+		sbsa_gwdt_stop(wdd);
+	spin_unlock(&gwdt->lock);
+
+	return 0;
+}
+
+/* Enable watchdog and configure it if necessary */
+static int sbsa_gwdt_resume(struct device *dev)
+{
+	struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
+	struct watchdog_device *wdd = &gwdt->wdd;
+
+	spin_lock(&gwdt->lock);
+	if (gwdt->pm_status_store & SBSA_GWDT_WCS_EN)
+		sbsa_gwdt_start(wdd);
+	else
+		sbsa_gwdt_stop(wdd);
+	spin_unlock(&gwdt->lock);
+
+	return 0;
+}
+#endif
+
+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 dev_pm_ops sbsa_gwdt_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(sbsa_gwdt_suspend, sbsa_gwdt_resume)
+};
+
+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,
+};
+
+module_platform_driver(sbsa_gwdt_driver);
+
+MODULE_DESCRIPTION("SBSA Generic Watchdog Driver");
+MODULE_AUTHOR("Fu Wei <fu.wei@linaro.org>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH 6/6] ACPI: import watchdog info of GTDT into platform device
  2015-05-15 11:24 ` [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework fu.wei
  2015-05-15 11:24   ` [PATCH 5/6] Watchdog: introdouce ARM SBSA watchdog driver fu.wei
@ 2015-05-15 11:24   ` fu.wei
  2015-05-15 13:33   ` [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework Guenter Roeck
  2015-05-15 14:04   ` Arnd Bergmann
  3 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-05-15 11:24 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 <fu.wei@linaro.org>
---
 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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
  2015-05-15 11:24 ` [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework fu.wei
  2015-05-15 11:24   ` [PATCH 5/6] Watchdog: introdouce ARM SBSA watchdog driver fu.wei
  2015-05-15 11:24   ` [PATCH 6/6] ACPI: import watchdog info of GTDT into platform device fu.wei
@ 2015-05-15 13:33   ` Guenter Roeck
  2015-05-15 13:49     ` Fu Wei
  2015-05-15 14:04   ` Arnd Bergmann
  3 siblings, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-05-15 13:33 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, vgandhi, wim, jcm, leo.duran, corbet

On 05/15/2015 04:24 AM, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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 <fu.wei@linaro.org>
> ---
>   drivers/watchdog/watchdog_core.c | 66 ++++++++++++++++++++++++++++++++++++++++
>   drivers/watchdog/watchdog_dev.c  | 48 +++++++++++++++++++++++++++++
>   include/linux/watchdog.h         | 19 ++++++++++++
>   3 files changed, 133 insertions(+)
>
> diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
> index cec9b55..6ca9578 100644
> --- a/drivers/watchdog/watchdog_core.c
> +++ b/drivers/watchdog/watchdog_core.c
> @@ -54,6 +54,14 @@ static void watchdog_check_min_max_timeout(struct watchdog_device *wdd)
>   		wdd->min_timeout = 0;
>   		wdd->max_timeout = 0;
>   	}
> +	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;
> +	}

I am a bit concerned about the context dependency introduced here. If someone calls
_init_pretimeout after calling init_timeout, this may result in still invalid timeout
values.

>   }
>
>   /**
> @@ -98,6 +106,63 @@ int watchdog_init_timeout(struct watchdog_device *wdd,
>   }
>   EXPORT_SYMBOL_GPL(watchdog_init_timeout);
>
> +static void watchdog_check_min_max_pretimeout(struct watchdog_device *wdd)
> +{
> +	/*
> +	 * Check that we have valid min and max pretimeout 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;
> +	}
> +}
> +
> +/**
> + * watchdog_init_pretimeout() - initialize the pretimeout field
> + * @pretimeout_parm: pretimeout module parameter
> + * @dev: Device that stores the timeout-sec property
> + *
> + * Initialize the pretimeout field of the watchdog_device struct with either
> + * the pretimeout 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 pretimeout value.
> + *
> + * A zero is returned on success and -EINVAL for failure.
> + */

The new API function also needs to be documented in
Documentation/watchdog/watchdog-kernel-api.txt.

> +int watchdog_init_pretimeout(struct watchdog_device *wdd,
> +			     unsigned int pretimeout_parm, struct device *dev)
> +{
> +	int ret = 0;
> +	u32 timeouts[2];
> +
> +	watchdog_check_min_max_pretimeout(wdd);
> +
> +	/* try to get the timeout module parameter first */
> +	if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm) &&
> +	    pretimeout_parm) {
> +		wdd->pretimeout = pretimeout_parm;
> +		return ret;
> +	}
> +	if (pretimeout_parm)
> +		ret = -EINVAL;
> +
> +	/* try to get the timeout_sec property */
> +	if (!dev || !dev->of_node)
> +		return ret;
> +	ret = of_property_read_u32_array(dev->of_node,
> +					 "timeout-sec", timeouts, 2);
> +	if (!watchdog_pretimeout_invalid(wdd, timeouts[1]) && timeouts[1])

Guess we are still waiting for feedback from the devicetree maintainers on this.

Both the above synchronization concern and this makes me wonder if we should introduce
watchdog_init_timeouts() instead, which would take pretimeout as additional parameter.
What do you think about that ?

> +		wdd->pretimeout = timeouts[1];
> +	else
> +		ret = -EINVAL;
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(watchdog_init_pretimeout);
> +
>   /**
>    * watchdog_register_device() - register a watchdog device
>    * @wdd: watchdog device
> @@ -119,6 +184,7 @@ int watchdog_register_device(struct watchdog_device *wdd)
>   	if (wdd->ops->start == NULL || wdd->ops->stop == NULL)
>   		return -EINVAL;
>
> +	watchdog_check_min_max_pretimeout(wdd);
>   	watchdog_check_min_max_timeout(wdd);
>
>   	/*
> 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

s/keep's/keeps/

> +		 * possible that it takes the new timeout) */

Please use the common multi-line comment style (that it isn't used above is not
an argument).

> +		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..f0a3c5b 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)
>   {
> @@ -134,6 +150,9 @@ 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_pretimeout(struct watchdog_device *wdd,
> +				    unsigned int pretimeout_parm,
> +				    struct device *dev);

Please drop the 'extern'. Guess it may be time to clean up the watchdog core code ;-).

Thanks,
Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
  2015-05-15 13:33   ` [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework Guenter Roeck
@ 2015-05-15 13:49     ` Fu Wei
  2015-05-15 13:55         ` Timur Tabi
  2015-05-15 18:01         ` Guenter Roeck
  0 siblings, 2 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-15 13:49 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet

Hi Guenter,

Great thanks for your review,
feedback inline below :-)

On 15 May 2015 at 21:33, Guenter Roeck <linux@roeck-us.net> wrote:
> On 05/15/2015 04:24 AM, fu.wei@linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> 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 <fu.wei@linaro.org>
>> ---
>>   drivers/watchdog/watchdog_core.c | 66
>> ++++++++++++++++++++++++++++++++++++++++
>>   drivers/watchdog/watchdog_dev.c  | 48 +++++++++++++++++++++++++++++
>>   include/linux/watchdog.h         | 19 ++++++++++++
>>   3 files changed, 133 insertions(+)
>>
>> diff --git a/drivers/watchdog/watchdog_core.c
>> b/drivers/watchdog/watchdog_core.c
>> index cec9b55..6ca9578 100644
>> --- a/drivers/watchdog/watchdog_core.c
>> +++ b/drivers/watchdog/watchdog_core.c
>> @@ -54,6 +54,14 @@ static void watchdog_check_min_max_timeout(struct
>> watchdog_device *wdd)
>>                 wdd->min_timeout = 0;
>>                 wdd->max_timeout = 0;
>>         }
>> +       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;
>> +       }
>
>
> I am a bit concerned about the context dependency introduced here. If
> someone calls
> _init_pretimeout after calling init_timeout, this may result in still
> invalid timeout
> values.

yes, that logic is not very clean, so my thought is :
maybe we can integrate watchdog_init_timeout and watchdog_init_pretimeout,
if maintainer agree to add pretimeout into framework.

>
>
>>   }
>>
>>   /**
>> @@ -98,6 +106,63 @@ int watchdog_init_timeout(struct watchdog_device *wdd,
>>   }
>>   EXPORT_SYMBOL_GPL(watchdog_init_timeout);
>>
>> +static void watchdog_check_min_max_pretimeout(struct watchdog_device
>> *wdd)
>> +{
>> +       /*
>> +        * Check that we have valid min and max pretimeout 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;
>> +       }
>> +}
>> +
>> +/**
>> + * watchdog_init_pretimeout() - initialize the pretimeout field
>> + * @pretimeout_parm: pretimeout module parameter
>> + * @dev: Device that stores the timeout-sec property
>> + *
>> + * Initialize the pretimeout field of the watchdog_device struct with
>> either
>> + * the pretimeout 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 pretimeout value.
>> + *
>> + * A zero is returned on success and -EINVAL for failure.
>> + */
>
>
> The new API function also needs to be documented in
> Documentation/watchdog/watchdog-kernel-api.txt.

good point, thanks will do

>
>> +int watchdog_init_pretimeout(struct watchdog_device *wdd,
>> +                            unsigned int pretimeout_parm, struct device
>> *dev)
>> +{
>> +       int ret = 0;
>> +       u32 timeouts[2];
>> +
>> +       watchdog_check_min_max_pretimeout(wdd);
>> +
>> +       /* try to get the timeout module parameter first */
>> +       if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm) &&
>> +           pretimeout_parm) {
>> +               wdd->pretimeout = pretimeout_parm;
>> +               return ret;
>> +       }
>> +       if (pretimeout_parm)
>> +               ret = -EINVAL;
>> +
>> +       /* try to get the timeout_sec property */
>> +       if (!dev || !dev->of_node)
>> +               return ret;
>> +       ret = of_property_read_u32_array(dev->of_node,
>> +                                        "timeout-sec", timeouts, 2);
>> +       if (!watchdog_pretimeout_invalid(wdd, timeouts[1]) && timeouts[1])
>
>
> Guess we are still waiting for feedback from the devicetree maintainers on
> this.

yes!

>
> Both the above synchronization concern and this makes me wonder if we should
> introduce
> watchdog_init_timeouts() instead, which would take pretimeout as additional
> parameter.
> What do you think about that ?

yes, that is what I am thinking about

>
>
>> +               wdd->pretimeout = timeouts[1];
>> +       else
>> +               ret = -EINVAL;
>> +
>> +       return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(watchdog_init_pretimeout);
>> +
>>   /**
>>    * watchdog_register_device() - register a watchdog device
>>    * @wdd: watchdog device
>> @@ -119,6 +184,7 @@ int watchdog_register_device(struct watchdog_device
>> *wdd)
>>         if (wdd->ops->start == NULL || wdd->ops->stop == NULL)
>>                 return -EINVAL;
>>
>> +       watchdog_check_min_max_pretimeout(wdd);
>>         watchdog_check_min_max_timeout(wdd);
>>
>>         /*
>> 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
>
>
> s/keep's/keeps/

Great thanks, typo

>
>> +                * possible that it takes the new timeout) */
>
>
> Please use the common multi-line comment style (that it isn't used above is
> not
> an argument).

yes, my bad, will fixed .

>
>
>> +               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..f0a3c5b 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)
>>   {
>> @@ -134,6 +150,9 @@ 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_pretimeout(struct watchdog_device *wdd,
>> +                                   unsigned int pretimeout_parm,
>> +                                   struct device *dev);
>
>
> Please drop the 'extern'. Guess it may be time to clean up the watchdog core
> code ;-).

yes, you are right, but in different patchset ??

>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
  2015-05-15 13:49     ` Fu Wei
@ 2015-05-15 13:55         ` Timur Tabi
  2015-05-15 18:01         ` Guenter Roeck
  1 sibling, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-15 13:55 UTC (permalink / raw)
  To: Fu Wei, Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet

Fu Wei wrote:
>> >The new API function also needs to be documented in
>> >Documentation/watchdog/watchdog-kernel-api.txt.
> good point, thanks will do

Yes, please, since my driver does not use or need any pre-timeout 
support, so I don't understand why this patch exists.  What is 
pre-timeout anyway?

-- 
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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
@ 2015-05-15 13:55         ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-15 13:55 UTC (permalink / raw)
  To: Fu Wei, Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet

Fu Wei wrote:
>> >The new API function also needs to be documented in
>> >Documentation/watchdog/watchdog-kernel-api.txt.
> good point, thanks will do

Yes, please, since my driver does not use or need any pre-timeout 
support, so I don't understand why this patch exists.  What is 
pre-timeout anyway?

-- 
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.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 5/6] Watchdog: introdouce ARM SBSA watchdog driver
  2015-05-15 11:24   ` [PATCH 5/6] Watchdog: introdouce ARM SBSA watchdog driver fu.wei
@ 2015-05-15 13:57     ` Arnd Bergmann
  2015-05-16 12:01         ` Fu Wei
  2015-05-15 22:57       ` Guenter Roeck
  1 sibling, 1 reply; 550+ messages in thread
From: Arnd Bergmann @ 2015-05-15 13:57 UTC (permalink / raw)
  To: fu.wei
  Cc: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, tekkamanninja, graeme.gregory, al.stone,
	hanjun.guo, timur, ashwin.chaugule, linux, vgandhi, wim, jcm,
	leo.duran, corbet

On Friday 15 May 2015 19:24:49 fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
>     (1)Use linux kernel watchdog framework
>     (2)Work with FDT on ARM64
>     (3)Use "pretimeout" in watchdog framework
>     (4)In first timeout(WS0), do panic to save system context
>     (5)support geting timeout and pretimeout from
>        parameter and FDT at the driver init stage.
> 
> Signed-off-by: Fu Wei <fu.wei@linaro.org>

The patch looks good overall. Please try to describe in the patch in 
full sentences in the changelog, as we normally do. 

A few tiny details that I'd do differently, but don't have to change
if the watchdog maintainer is fine with your version:

> +struct sbsa_gwdt {
> +	struct watchdog_device	wdd;
> +	u32			clk;
> +	void __iomem		*refresh_base;
> +	void __iomem		*control_base;
> +#ifdef CONFIG_PM_SLEEP
> +	spinlock_t		lock;
> +	u8			pm_status_store;
> +#endif
> +};

I would drop the #ifdef here, and favor readability over saving
a few bytes.

> +	/*
> +	 * Try to determine the frequency from the cp15 interface
> +	 */
> +	clk = arch_timer_get_cntfrq();
> +	if (!clk) {
> +		dev_err(dev, "System Counter frequency not available\n");
> +		return -EINVAL;
> +	}

Is it guaranteed that the same clock feeds the arch timer and the
watchdog? Maybe it would be better to use the clk API to read
the frequency, so we can avoid this dependency.

> +
> +	pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
> +		 res->name, (unsigned long long)res->start,
> +		(unsigned long long)(res->end - res->start + 1), 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);
> +
> +	pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
> +		 res->name, (unsigned long long)res->start,
> +		(unsigned long long)(res->end - res->start + 1), cf_base);

I would probably drop the various pr_debug() calls here. Once the driver
works fine, they are normally not that useful any more.

	Arnd

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
  2015-05-15 11:24 ` [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework fu.wei
                     ` (2 preceding siblings ...)
  2015-05-15 13:33   ` [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework Guenter Roeck
@ 2015-05-15 14:04   ` Arnd Bergmann
  2015-05-18 17:19       ` Fu Wei
  3 siblings, 1 reply; 550+ messages in thread
From: Arnd Bergmann @ 2015-05-15 14:04 UTC (permalink / raw)
  To: fu.wei
  Cc: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, tekkamanninja, graeme.gregory, al.stone,
	hanjun.guo, timur, ashwin.chaugule, linux, vgandhi, wim, jcm,
	leo.duran, corbet

On Friday 15 May 2015 19:24:48 fu.wei@linaro.org wrote:
> +static void watchdog_check_min_max_pretimeout(struct watchdog_device *wdd)
> +{
> +       /*
> +        * Check that we have valid min and max pretimeout 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;
> +       }
> +}

I would probably just fold this function into the existing
watchdog_check_min_max_timeout() and check both normal and pre-timeout
there.

> +/**
> + * watchdog_init_pretimeout() - initialize the pretimeout field
> + * @pretimeout_parm: pretimeout module parameter
> + * @dev: Device that stores the timeout-sec property
> + *
> + * Initialize the pretimeout field of the watchdog_device struct with either
> + * the pretimeout 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 pretimeout value.
> + *
> + * A zero is returned on success and -EINVAL for failure.
> + */
> +int watchdog_init_pretimeout(struct watchdog_device *wdd,
> +                            unsigned int pretimeout_parm, struct device *dev)
> +{
> +       int ret = 0;
> +       u32 timeouts[2];
> +
> +       watchdog_check_min_max_pretimeout(wdd);
> +
> +       /* try to get the timeout module parameter first */
> +       if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm) &&
> +           pretimeout_parm) {
> +               wdd->pretimeout = pretimeout_parm;
> +               return ret;
> +       }
> +       if (pretimeout_parm)
> +               ret = -EINVAL;
> +
> +       /* try to get the timeout_sec property */
> +       if (!dev || !dev->of_node)
> +               return ret;
> +       ret = of_property_read_u32_array(dev->of_node,
> +                                        "timeout-sec", timeouts, 2);
> +       if (!watchdog_pretimeout_invalid(wdd, timeouts[1]) && timeouts[1])
> +               wdd->pretimeout = timeouts[1];
> +       else
> +               ret = -EINVAL;
> +
> +       return ret;
> +}
> +EXPORT_SYMBOL_GPL(watchdog_init_pretimeout);

Same here: the function is very similar to the watchdog_init_timeout
function, and it reads the same property, so just do both here.

The easiest way for that is probably to use of_find_property()
and of_prop_next_u32() to read the two numbers.

	Arnd


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 1/6] Documentation: add sbsa-gwdt.txt documentation
@ 2015-05-15 14:06       ` Arnd Bergmann
  0 siblings, 0 replies; 550+ messages in thread
From: Arnd Bergmann @ 2015-05-15 14:06 UTC (permalink / raw)
  To: fu.wei
  Cc: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, tekkamanninja, graeme.gregory, al.stone,
	hanjun.guo, timur, ashwin.chaugule, linux, vgandhi, wim, jcm,
	leo.duran, corbet

On Friday 15 May 2015 19:08:05 fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> 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 <fu.wei@linaro.org>

Looks good, just one minor comment:

> +Optional properties
> +- timeout-sec : Watchdog pre-timeout and timeout values (in seconds).
> +	The first is timeout values, then pre-timeout.

Please update Documentation/watchdog/watchdog-kernel-api.txt as well, to
mention the second number in the timeout-sec property.

	Arnd


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 1/6] Documentation: add sbsa-gwdt.txt documentation
@ 2015-05-15 14:06       ` Arnd Bergmann
  0 siblings, 0 replies; 550+ messages in thread
From: Arnd Bergmann @ 2015-05-15 14:06 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A
  Cc: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs

On Friday 15 May 2015 19:08:05 fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> 
> 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Looks good, just one minor comment:

> +Optional properties
> +- timeout-sec : Watchdog pre-timeout and timeout values (in seconds).
> +	The first is timeout values, then pre-timeout.

Please update Documentation/watchdog/watchdog-kernel-api.txt as well, to
mention the second number in the timeout-sec property.

	Arnd

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH 0/6] Watchdog: introdouce ARM SBSA watchdog driver
@ 2015-05-15 14:07     ` Arnd Bergmann
  0 siblings, 0 replies; 550+ messages in thread
From: Arnd Bergmann @ 2015-05-15 14:07 UTC (permalink / raw)
  To: linaro-acpi
  Cc: fu.wei, Suravee.Suthikulpanit, linux-watchdog, devicetree,
	linux-kernel, linux-doc, corbet, jcm, timur, wim, tekkamanninja,
	vgandhi, linux

On Friday 15 May 2015 19:08:04 fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> This patchset:
> 
>     (1)Introdouces 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
> 
>     (2)Introdouce "pretimeout" into the watchdog framework
> 
>     (3)Introdouces 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
> 
>     (4)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
> 
> 

I've had a few very minor comments to the individual patches, otherwise
looks good. I have not reviewed the ACPI part of the series, as I have
no knowledge of that.

	Arnd

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH 0/6] Watchdog: introdouce ARM SBSA watchdog driver
@ 2015-05-15 14:07     ` Arnd Bergmann
  0 siblings, 0 replies; 550+ messages in thread
From: Arnd Bergmann @ 2015-05-15 14:07 UTC (permalink / raw)
  To: linaro-acpi-cunTk1MwBs8s++Sfvej+rw
  Cc: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, corbet-T1hC0tSOHrs,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, linux-0h96xk9xTtrk1uMJSBkQmQ

On Friday 15 May 2015 19:08:04 fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> 
> This patchset:
> 
>     (1)Introdouces 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
> 
>     (2)Introdouce "pretimeout" into the watchdog framework
> 
>     (3)Introdouces 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
> 
>     (4)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
> 
> 

I've had a few very minor comments to the individual patches, otherwise
looks good. I have not reviewed the ACPI part of the series, as I have
no knowledge of that.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 1/6] Documentation: add sbsa-gwdt.txt documentation
  2015-05-15 14:06       ` Arnd Bergmann
@ 2015-05-15 14:14         ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-15 14:14 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Guenter Roeck, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet

Hi Arnd,

Great thanks, np, will do so

On 15 May 2015 at 22:06, Arnd Bergmann <arnd@arndb.de> wrote:
> On Friday 15 May 2015 19:08:05 fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> 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 <fu.wei@linaro.org>
>
> Looks good, just one minor comment:
>
>> +Optional properties
>> +- timeout-sec : Watchdog pre-timeout and timeout values (in seconds).
>> +     The first is timeout values, then pre-timeout.
>
> Please update Documentation/watchdog/watchdog-kernel-api.txt as well, to
> mention the second number in the timeout-sec property.
>
>         Arnd
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 1/6] Documentation: add sbsa-gwdt.txt documentation
@ 2015-05-15 14:14         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-15 14:14 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Guenter Roeck,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet

Hi Arnd,

Great thanks, np, will do so

On 15 May 2015 at 22:06, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
> On Friday 15 May 2015 19:08:05 fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>
>> 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> Looks good, just one minor comment:
>
>> +Optional properties
>> +- timeout-sec : Watchdog pre-timeout and timeout values (in seconds).
>> +     The first is timeout values, then pre-timeout.
>
> Please update Documentation/watchdog/watchdog-kernel-api.txt as well, to
> mention the second number in the timeout-sec property.
>
>         Arnd
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
  2015-05-15 13:55         ` Timur Tabi
  (?)
@ 2015-05-15 17:59         ` Guenter Roeck
  -1 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-15 17:59 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Fu Wei, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet

On Fri, May 15, 2015 at 08:55:25AM -0500, Timur Tabi wrote:
> Fu Wei wrote:
> >>>The new API function also needs to be documented in
> >>>Documentation/watchdog/watchdog-kernel-api.txt.
> >good point, thanks will do
> 
> Yes, please, since my driver does not use or need any pre-timeout support,
> so I don't understand why this patch exists.  What is pre-timeout anyway?

Documentation/watchdog/watchdog-api.txt; look for "Pretimeouts:".

Guenter

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
  2015-05-15 13:49     ` Fu Wei
@ 2015-05-15 18:01         ` Guenter Roeck
  2015-05-15 18:01         ` Guenter Roeck
  1 sibling, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-15 18:01 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet

On Fri, May 15, 2015 at 09:49:07PM +0800, Fu Wei wrote:
> Hi Guenter,
> 
> Great thanks for your review,
> feedback inline below :-)
> 
> On 15 May 2015 at 21:33, Guenter Roeck <linux@roeck-us.net> wrote:

[ ... ]

> >> +       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;
> >> +       }
> >
> >
> > I am a bit concerned about the context dependency introduced here. If
> > someone calls
> > _init_pretimeout after calling init_timeout, this may result in still
> > invalid timeout
> > values.
> 
> yes, that logic is not very clean, so my thought is :
> maybe we can integrate watchdog_init_timeout and watchdog_init_pretimeout,
> if maintainer agree to add pretimeout into framework.
> 
I think we should just assume that Wim will accept it, and try to find
the best possible solution (or at least a good one).

Guenter

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
@ 2015-05-15 18:01         ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-15 18:01 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet

On Fri, May 15, 2015 at 09:49:07PM +0800, Fu Wei wrote:
> Hi Guenter,
> 
> Great thanks for your review,
> feedback inline below :-)
> 
> On 15 May 2015 at 21:33, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:

[ ... ]

> >> +       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;
> >> +       }
> >
> >
> > I am a bit concerned about the context dependency introduced here. If
> > someone calls
> > _init_pretimeout after calling init_timeout, this may result in still
> > invalid timeout
> > values.
> 
> yes, that logic is not very clean, so my thought is :
> maybe we can integrate watchdog_init_timeout and watchdog_init_pretimeout,
> if maintainer agree to add pretimeout into framework.
> 
I think we should just assume that Wim will accept it, and try to find
the best possible solution (or at least a good one).

Guenter
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 5/6] Watchdog: introdouce ARM SBSA watchdog driver
@ 2015-05-15 22:57       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-15 22:57 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, vgandhi, wim, jcm, leo.duran, corbet

On 05/15/2015 04:24 AM, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
>      (1)Use linux kernel watchdog framework
>      (2)Work with FDT on ARM64
>      (3)Use "pretimeout" in watchdog framework
>      (4)In first timeout(WS0), do panic to save system context
>      (5)support geting timeout and pretimeout from

getting

>         parameter and FDT at the driver init stage.

Subject: s/introdouce/introduce/

Please find a better description.

Also, please provide revisions numbers for your patch sets, and
list the changes from one revision to the next.

>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>   drivers/watchdog/Kconfig     |  10 +
>   drivers/watchdog/Makefile    |   1 +
>   drivers/watchdog/sbsa_gwdt.c | 553 +++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 564 insertions(+)
>   create mode 100644 drivers/watchdog/sbsa_gwdt.c
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index e5e7c55..1e1bc8b 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -152,6 +152,16 @@ 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
> +	select WATCHDOG_CORE
> +	help
> +	  ARM SBSA Generic Watchdog timer. This has two Watchdog Signal(WS0/WS1),

signals

> +	  will trigger a warnning interrupt(do panic) in the first timeout(WS0);

warning

> +	  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..52838b1
> --- /dev/null
> +++ b/drivers/watchdog/sbsa_gwdt.c
> @@ -0,0 +1,553 @@
> +/*
> + * SBSA(Server Base System Architecture) Generic Watchdog driver
> + *
> + * Copyright (c) 2015, Linaro Ltd.
> + * Author: Fu Wei <fu.wei@linaro.org>
> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> + *
> + * 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.
> + *       But timeout and pretimeout are set by the different REGs.

Why "But" ?

> + *       The first watch period is set by writing WCV directly,
> + *       that can support more than 10s timeout at the maximum
> + *       system counter frequency.
> + *       And the second watch period is set by WOR(32bit) which will be loaded

s/And the/The/

> + *       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/spinlock.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)
> +
> +/* Watchdog Interface Identification Register */
> +#define SBSA_GWDT_W_IIDR_PID(x)			((x >> 20) & 0xfff)
> +#define SBSA_GWDT_W_IIDR_ARCH_VER(x)		((x >> 16) & 0xf)
> +#define SBSA_GWDT_W_IIDR_REV(x)			((x >> 12) & 0xf)
> +#define SBSA_GWDT_W_IIDR_IMPLEMENTER(x)		(x & 0xfff)
> +#define SBSA_GWDT_W_IIDR_VID_BANK(x)		((x >> 8) & 0xf)
> +#define SBSA_GWDT_W_IIDR_VID(x)			(x & 0x7f)
> +
> +/* Watchdog Identification Register */
> +#define SBSA_GWDT_IDR_W_PIDR2			0xfe8
> +#define SBSA_GWDT_IDR_W_PIDR2_ARCH_VER(x)	((x >> 4) & 0xf)
> +

(x) for all the above macros, please.

> +/**
> + * 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:	VA of the watchdog refresh frame
> + * @control_base:	VA of the watchdog control frame

Please spell out "Virtual address".

> + * @lock:		struct sbsa_gwdt spinlock
> + * @pm_status_store:	store the PM info of WDT
> + */
> +struct sbsa_gwdt {
> +	struct watchdog_device	wdd;
> +	u32			clk;
> +	void __iomem		*refresh_base;
> +	void __iomem		*control_base;
> +#ifdef CONFIG_PM_SLEEP
> +	spinlock_t		lock;
> +	u8			pm_status_store;
> +#endif

Please avoid the #ifdef.

> +};
> +
> +#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
> +
> +#define DEFAULT_TIMEOUT_WS0	10 /* seconds, the 1st watch period*/
> +#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_WS0 + DEFAULT_PRETIMEOUT) ")");
> +
> +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 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 unsigned int pretimeout;
> +module_param(pretimeout, uint, 0);
> +MODULE_PARM_DESC(pretimeout,
> +		 "Watchdog pretimeout in seconds. (>=0, default="
> +		 __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
> +
> +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
> + * mutex_lock must be called prior to calling this function.
> + */
> +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);
> +
> +	pr_debug("sbsa_gwdt: set WCV to %llu, result: %llu\n",
> +		 value, sbsa_gwdt_get_wcv(wdd));

Is this pr_debug still necessary ?

> +}
> +
> +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_set_timeout_limits(struct sbsa_gwdt *gwdt)
> +{
> +	unsigned int first_period_max = (U64_MAX / gwdt->clk);
> +	struct watchdog_device *wdd = &gwdt->wdd;
> +
> +	wdd->min_timeout = wdd->pretimeout + 1;
> +	wdd->max_timeout = min(wdd->pretimeout + first_period_max, max_timeout);
> +
> +	pr_debug("sbsa_gwdt: timeout (%u-%u), pretimeout (%u-%u)\n",
> +		 wdd->min_timeout, wdd->max_timeout,
> +		 wdd->min_pretimeout, wdd->max_pretimeout);

Is this still necessary ?

> +}
> +
> +static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
> +				 unsigned int timeout)
> +{
> +	wdd->timeout = timeout;
> +
> +	return 0;
> +	/* watchdog framework will trigger a ping, after this call */

Unnecessary comment.

> +}
> +
> +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_set_timeout_limits(gwdt);
> +
> +	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);
> +
> +	pr_debug("sbsa_gwdt: set WOR to %x(%us), result: %x\n",
> +		 wor, pretimeout, sbsa_gwdt_cf_read(SBSA_GWDT_WOR, wdd));

Is this still necessary ?

> +
> +	return 0;
> +	/* watchdog framework will trigger a ping, after this call */

Unnecessary comment.

> +}
> +
> +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();
> +
> +	return timeleft / gwdt->clk;

Will this ever be built on a 32 bit target ? That may cause a link error
due to the 64 bit divide operation.

> +}
> +
> +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);
> +
> +	pr_debug("sbsa_gwdt: WCS is %x(%s)\n",
> +		 sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd), __func__);

Another one. If you think you need to keep those, can you at least use dev_dbg ?
I won't comment on the debug messages further, but I really think that even
for debug messages this is a bit noisy.

> +
> +	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);
> +
> +	pr_debug("sbsa_gwdt: WCS is %x(%s)\n",
> +		 sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd), __func__);
> +
> +	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);
> +
> +	pr_debug("sbsa_gwdt: ping, %us left.\n", sbsa_gwdt_get_timeleft(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);
> +
> +	pr_debug("sbsa_gwdt: interrupt routine, WCS@%x\n", status);
> +
> +	if (status & SBSA_GWDT_WCS_WS0) {
> +		pr_debug("sbsa_gwdt WS0: trigger WS1 in %ds!\n",
> +			 sbsa_gwdt_get_timeleft(wdd));
> +		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, w_iidr;
> +
> +	int ret = 0;

Please drop the empty lines above.

> +
> +	/*
> +	 * Try to determine the frequency from the cp15 interface
> +	 */
> +	clk = arch_timer_get_cntfrq();
> +	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);
> +
> +	pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
> +		 res->name, (unsigned long long)res->start,
> +		(unsigned long long)(res->end - res->start + 1), rf_base);

If you think you need to keep those messages, please at least use %pR.

> +
> +	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);
> +
> +	pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
> +		 res->name, (unsigned long long)res->start,
> +		(unsigned long long)(res->end - res->start + 1), cf_base);
> +
> +	irq = platform_get_irq_byname(pdev, "ws0");
> +	if (irq < 0) {
> +		dev_err(dev, "unable to get ws0 interrupt.\n");
> +		return irq;
> +	}
> +
> +	pr_debug("sbsa_gwdt: ws0 irq %d.\n", irq);
> +
> +	gwdt->refresh_base = rf_base;
> +	gwdt->control_base = cf_base;
> +	gwdt->clk = clk;
> +#ifdef CONFIG_PM_SLEEP
> +	spin_lock_init(&gwdt->lock);
> +#endif
> +	platform_set_drvdata(pdev, gwdt);
> +
> +	pr_debug("sbsa_gwdt: hw clk: %uHz--> WOR(32bit) max timeout is %us.\n",
> +		 gwdt->clk, U32_MAX / clk);
> +
> +	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 was reseted by WDT(WCS: %x, WCV: %llx)\n",

"was reseted" is kind of odd. Can you use just "reset" or maybe "restarted" ?

> +			 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!\n");
> +		sbsa_gwdt_keepalive(wdd);
> +	}
> +
> +	pr_debug("sbsa_gwdt: WCS: %x(%s)\n", status, __func__);
> +
> +	wdd->min_pretimeout = 0;
> +	wdd->max_pretimeout = min(U32_MAX / clk, max_timeout - 1);
> +	sbsa_gwdt_set_timeout_limits(gwdt);
> +
> +	watchdog_init_pretimeout(wdd, pretimeout, dev);
> +	if (!wdd->pretimeout) {
> +		wdd->pretimeout = DEFAULT_PRETIMEOUT;
> +		dev_info(dev, "can't get pretimeout param, set default %us.\n",
> +			 wdd->pretimeout);

Unnecessary message. The pretimeout is printed again below.

> +	}
> +	sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
> +
> +	watchdog_init_timeout(wdd, timeout, dev);
> +	if (!wdd->timeout) {
> +		wdd->timeout = wdd->pretimeout + DEFAULT_TIMEOUT_WS0;
> +		dev_info(dev, "can't get timeout param, set default: %us.\n",
> +			 wdd->timeout);

Same here.

> +	}
> +	sbsa_gwdt_set_timeout(wdd, wdd->timeout);
> +
> +	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;
> +
> +	/* get device information from control frame and display */
> +	w_iidr = sbsa_gwdt_cf_read(SBSA_GWDT_W_IIDR, &gwdt->wdd);
> +	dev_info(dev, "PID:%u(JEP106 %u-%u), Arch v%u Rev %u.",
> +		 SBSA_GWDT_W_IIDR_PID(w_iidr),
> +		 SBSA_GWDT_W_IIDR_VID_BANK(w_iidr),
> +		 SBSA_GWDT_W_IIDR_VID(w_iidr),
> +		 SBSA_GWDT_W_IIDR_ARCH_VER(w_iidr),
> +		 SBSA_GWDT_W_IIDR_REV(w_iidr));

Is this valuable information ?

> +
> +	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;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP

You don't need the #ifdef if you use __maybe_unused with the function declarations.

> +/* Disable watchdog if it is active during suspend */
> +static int sbsa_gwdt_suspend(struct device *dev)
> +{
> +	struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
> +	struct watchdog_device *wdd = &gwdt->wdd;
> +
> +	spin_lock(&gwdt->lock);
> +	gwdt->pm_status_store = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
> +
> +	if (gwdt->pm_status_store & SBSA_GWDT_WCS_EN)
> +		sbsa_gwdt_stop(wdd);
> +	spin_unlock(&gwdt->lock);

Wonder what this lock is protecting against. Can you explain ?
I would assume that suspend and resume are mutually exclusive
and don't require locking against each other.

> +
> +	return 0;
> +}
> +
> +/* Enable watchdog and configure it if necessary */
> +static int sbsa_gwdt_resume(struct device *dev)
> +{
> +	struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
> +	struct watchdog_device *wdd = &gwdt->wdd;
> +
> +	spin_lock(&gwdt->lock);
> +	if (gwdt->pm_status_store & SBSA_GWDT_WCS_EN)
> +		sbsa_gwdt_start(wdd);
> +	else
> +		sbsa_gwdt_stop(wdd);

What is the stop here for ?

> +	spin_unlock(&gwdt->lock);
> +
> +	return 0;
> +}
> +#endif
> +
> +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 dev_pm_ops sbsa_gwdt_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(sbsa_gwdt_suspend, sbsa_gwdt_resume)
> +};
> +
> +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,
> +};
> +
> +module_platform_driver(sbsa_gwdt_driver);
> +
> +MODULE_DESCRIPTION("SBSA Generic Watchdog Driver");
> +MODULE_AUTHOR("Fu Wei <fu.wei@linaro.org>");
> +MODULE_LICENSE("GPL v2");
>


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 5/6] Watchdog: introdouce ARM SBSA watchdog driver
@ 2015-05-15 22:57       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-15 22:57 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	corbet-T1hC0tSOHrs

On 05/15/2015 04:24 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
>      (1)Use linux kernel watchdog framework
>      (2)Work with FDT on ARM64
>      (3)Use "pretimeout" in watchdog framework
>      (4)In first timeout(WS0), do panic to save system context
>      (5)support geting timeout and pretimeout from

getting

>         parameter and FDT at the driver init stage.

Subject: s/introdouce/introduce/

Please find a better description.

Also, please provide revisions numbers for your patch sets, and
list the changes from one revision to the next.

>
> Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>   drivers/watchdog/Kconfig     |  10 +
>   drivers/watchdog/Makefile    |   1 +
>   drivers/watchdog/sbsa_gwdt.c | 553 +++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 564 insertions(+)
>   create mode 100644 drivers/watchdog/sbsa_gwdt.c
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index e5e7c55..1e1bc8b 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -152,6 +152,16 @@ 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
> +	select WATCHDOG_CORE
> +	help
> +	  ARM SBSA Generic Watchdog timer. This has two Watchdog Signal(WS0/WS1),

signals

> +	  will trigger a warnning interrupt(do panic) in the first timeout(WS0);

warning

> +	  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..52838b1
> --- /dev/null
> +++ b/drivers/watchdog/sbsa_gwdt.c
> @@ -0,0 +1,553 @@
> +/*
> + * SBSA(Server Base System Architecture) Generic Watchdog driver
> + *
> + * Copyright (c) 2015, Linaro Ltd.
> + * Author: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
> + *
> + * 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.
> + *       But timeout and pretimeout are set by the different REGs.

Why "But" ?

> + *       The first watch period is set by writing WCV directly,
> + *       that can support more than 10s timeout at the maximum
> + *       system counter frequency.
> + *       And the second watch period is set by WOR(32bit) which will be loaded

s/And the/The/

> + *       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/spinlock.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)
> +
> +/* Watchdog Interface Identification Register */
> +#define SBSA_GWDT_W_IIDR_PID(x)			((x >> 20) & 0xfff)
> +#define SBSA_GWDT_W_IIDR_ARCH_VER(x)		((x >> 16) & 0xf)
> +#define SBSA_GWDT_W_IIDR_REV(x)			((x >> 12) & 0xf)
> +#define SBSA_GWDT_W_IIDR_IMPLEMENTER(x)		(x & 0xfff)
> +#define SBSA_GWDT_W_IIDR_VID_BANK(x)		((x >> 8) & 0xf)
> +#define SBSA_GWDT_W_IIDR_VID(x)			(x & 0x7f)
> +
> +/* Watchdog Identification Register */
> +#define SBSA_GWDT_IDR_W_PIDR2			0xfe8
> +#define SBSA_GWDT_IDR_W_PIDR2_ARCH_VER(x)	((x >> 4) & 0xf)
> +

(x) for all the above macros, please.

> +/**
> + * 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:	VA of the watchdog refresh frame
> + * @control_base:	VA of the watchdog control frame

Please spell out "Virtual address".

> + * @lock:		struct sbsa_gwdt spinlock
> + * @pm_status_store:	store the PM info of WDT
> + */
> +struct sbsa_gwdt {
> +	struct watchdog_device	wdd;
> +	u32			clk;
> +	void __iomem		*refresh_base;
> +	void __iomem		*control_base;
> +#ifdef CONFIG_PM_SLEEP
> +	spinlock_t		lock;
> +	u8			pm_status_store;
> +#endif

Please avoid the #ifdef.

> +};
> +
> +#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
> +
> +#define DEFAULT_TIMEOUT_WS0	10 /* seconds, the 1st watch period*/
> +#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_WS0 + DEFAULT_PRETIMEOUT) ")");
> +
> +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 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 unsigned int pretimeout;
> +module_param(pretimeout, uint, 0);
> +MODULE_PARM_DESC(pretimeout,
> +		 "Watchdog pretimeout in seconds. (>=0, default="
> +		 __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
> +
> +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
> + * mutex_lock must be called prior to calling this function.
> + */
> +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);
> +
> +	pr_debug("sbsa_gwdt: set WCV to %llu, result: %llu\n",
> +		 value, sbsa_gwdt_get_wcv(wdd));

Is this pr_debug still necessary ?

> +}
> +
> +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_set_timeout_limits(struct sbsa_gwdt *gwdt)
> +{
> +	unsigned int first_period_max = (U64_MAX / gwdt->clk);
> +	struct watchdog_device *wdd = &gwdt->wdd;
> +
> +	wdd->min_timeout = wdd->pretimeout + 1;
> +	wdd->max_timeout = min(wdd->pretimeout + first_period_max, max_timeout);
> +
> +	pr_debug("sbsa_gwdt: timeout (%u-%u), pretimeout (%u-%u)\n",
> +		 wdd->min_timeout, wdd->max_timeout,
> +		 wdd->min_pretimeout, wdd->max_pretimeout);

Is this still necessary ?

> +}
> +
> +static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
> +				 unsigned int timeout)
> +{
> +	wdd->timeout = timeout;
> +
> +	return 0;
> +	/* watchdog framework will trigger a ping, after this call */

Unnecessary comment.

> +}
> +
> +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_set_timeout_limits(gwdt);
> +
> +	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);
> +
> +	pr_debug("sbsa_gwdt: set WOR to %x(%us), result: %x\n",
> +		 wor, pretimeout, sbsa_gwdt_cf_read(SBSA_GWDT_WOR, wdd));

Is this still necessary ?

> +
> +	return 0;
> +	/* watchdog framework will trigger a ping, after this call */

Unnecessary comment.

> +}
> +
> +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();
> +
> +	return timeleft / gwdt->clk;

Will this ever be built on a 32 bit target ? That may cause a link error
due to the 64 bit divide operation.

> +}
> +
> +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);
> +
> +	pr_debug("sbsa_gwdt: WCS is %x(%s)\n",
> +		 sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd), __func__);

Another one. If you think you need to keep those, can you at least use dev_dbg ?
I won't comment on the debug messages further, but I really think that even
for debug messages this is a bit noisy.

> +
> +	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);
> +
> +	pr_debug("sbsa_gwdt: WCS is %x(%s)\n",
> +		 sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd), __func__);
> +
> +	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);
> +
> +	pr_debug("sbsa_gwdt: ping, %us left.\n", sbsa_gwdt_get_timeleft(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);
> +
> +	pr_debug("sbsa_gwdt: interrupt routine, WCS@%x\n", status);
> +
> +	if (status & SBSA_GWDT_WCS_WS0) {
> +		pr_debug("sbsa_gwdt WS0: trigger WS1 in %ds!\n",
> +			 sbsa_gwdt_get_timeleft(wdd));
> +		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, w_iidr;
> +
> +	int ret = 0;

Please drop the empty lines above.

> +
> +	/*
> +	 * Try to determine the frequency from the cp15 interface
> +	 */
> +	clk = arch_timer_get_cntfrq();
> +	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);
> +
> +	pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
> +		 res->name, (unsigned long long)res->start,
> +		(unsigned long long)(res->end - res->start + 1), rf_base);

If you think you need to keep those messages, please at least use %pR.

> +
> +	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);
> +
> +	pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
> +		 res->name, (unsigned long long)res->start,
> +		(unsigned long long)(res->end - res->start + 1), cf_base);
> +
> +	irq = platform_get_irq_byname(pdev, "ws0");
> +	if (irq < 0) {
> +		dev_err(dev, "unable to get ws0 interrupt.\n");
> +		return irq;
> +	}
> +
> +	pr_debug("sbsa_gwdt: ws0 irq %d.\n", irq);
> +
> +	gwdt->refresh_base = rf_base;
> +	gwdt->control_base = cf_base;
> +	gwdt->clk = clk;
> +#ifdef CONFIG_PM_SLEEP
> +	spin_lock_init(&gwdt->lock);
> +#endif
> +	platform_set_drvdata(pdev, gwdt);
> +
> +	pr_debug("sbsa_gwdt: hw clk: %uHz--> WOR(32bit) max timeout is %us.\n",
> +		 gwdt->clk, U32_MAX / clk);
> +
> +	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 was reseted by WDT(WCS: %x, WCV: %llx)\n",

"was reseted" is kind of odd. Can you use just "reset" or maybe "restarted" ?

> +			 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!\n");
> +		sbsa_gwdt_keepalive(wdd);
> +	}
> +
> +	pr_debug("sbsa_gwdt: WCS: %x(%s)\n", status, __func__);
> +
> +	wdd->min_pretimeout = 0;
> +	wdd->max_pretimeout = min(U32_MAX / clk, max_timeout - 1);
> +	sbsa_gwdt_set_timeout_limits(gwdt);
> +
> +	watchdog_init_pretimeout(wdd, pretimeout, dev);
> +	if (!wdd->pretimeout) {
> +		wdd->pretimeout = DEFAULT_PRETIMEOUT;
> +		dev_info(dev, "can't get pretimeout param, set default %us.\n",
> +			 wdd->pretimeout);

Unnecessary message. The pretimeout is printed again below.

> +	}
> +	sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
> +
> +	watchdog_init_timeout(wdd, timeout, dev);
> +	if (!wdd->timeout) {
> +		wdd->timeout = wdd->pretimeout + DEFAULT_TIMEOUT_WS0;
> +		dev_info(dev, "can't get timeout param, set default: %us.\n",
> +			 wdd->timeout);

Same here.

> +	}
> +	sbsa_gwdt_set_timeout(wdd, wdd->timeout);
> +
> +	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;
> +
> +	/* get device information from control frame and display */
> +	w_iidr = sbsa_gwdt_cf_read(SBSA_GWDT_W_IIDR, &gwdt->wdd);
> +	dev_info(dev, "PID:%u(JEP106 %u-%u), Arch v%u Rev %u.",
> +		 SBSA_GWDT_W_IIDR_PID(w_iidr),
> +		 SBSA_GWDT_W_IIDR_VID_BANK(w_iidr),
> +		 SBSA_GWDT_W_IIDR_VID(w_iidr),
> +		 SBSA_GWDT_W_IIDR_ARCH_VER(w_iidr),
> +		 SBSA_GWDT_W_IIDR_REV(w_iidr));

Is this valuable information ?

> +
> +	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;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP

You don't need the #ifdef if you use __maybe_unused with the function declarations.

> +/* Disable watchdog if it is active during suspend */
> +static int sbsa_gwdt_suspend(struct device *dev)
> +{
> +	struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
> +	struct watchdog_device *wdd = &gwdt->wdd;
> +
> +	spin_lock(&gwdt->lock);
> +	gwdt->pm_status_store = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
> +
> +	if (gwdt->pm_status_store & SBSA_GWDT_WCS_EN)
> +		sbsa_gwdt_stop(wdd);
> +	spin_unlock(&gwdt->lock);

Wonder what this lock is protecting against. Can you explain ?
I would assume that suspend and resume are mutually exclusive
and don't require locking against each other.

> +
> +	return 0;
> +}
> +
> +/* Enable watchdog and configure it if necessary */
> +static int sbsa_gwdt_resume(struct device *dev)
> +{
> +	struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
> +	struct watchdog_device *wdd = &gwdt->wdd;
> +
> +	spin_lock(&gwdt->lock);
> +	if (gwdt->pm_status_store & SBSA_GWDT_WCS_EN)
> +		sbsa_gwdt_start(wdd);
> +	else
> +		sbsa_gwdt_stop(wdd);

What is the stop here for ?

> +	spin_unlock(&gwdt->lock);
> +
> +	return 0;
> +}
> +#endif
> +
> +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 dev_pm_ops sbsa_gwdt_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(sbsa_gwdt_suspend, sbsa_gwdt_resume)
> +};
> +
> +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,
> +};
> +
> +module_platform_driver(sbsa_gwdt_driver);
> +
> +MODULE_DESCRIPTION("SBSA Generic Watchdog Driver");
> +MODULE_AUTHOR("Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>");
> +MODULE_LICENSE("GPL v2");
>

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 1/6] Documentation: add sbsa-gwdt.txt documentation
  2015-05-15 14:06       ` Arnd Bergmann
@ 2015-05-16 10:29         ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-16 10:29 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, tekkamanninja, graeme.gregory, al.stone,
	hanjun.guo, timur, ashwin.chaugule, linux, vgandhi, wim, jcm,
	leo.duran, corbet

Hi Arnd,

Great thanks for reminding, I should do it earlier.
You will see it in next patchset.

On 05/15/2015 10:06 PM, Arnd Bergmann wrote:
> On Friday 15 May 2015 19:08:05 fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> 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 <fu.wei@linaro.org>
> 
> Looks good, just one minor comment:
> 
>> +Optional properties
>> +- timeout-sec : Watchdog pre-timeout and timeout values (in seconds).
>> +	The first is timeout values, then pre-timeout.
> 
> Please update Documentation/watchdog/watchdog-kernel-api.txt as well, to
> mention the second number in the timeout-sec property.
> 
> 	Arnd
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


-- 
Best regards,

Fu Wei
Software Engineer From Red Hat
LEG Team
Linaro.org | Open source software for ARM SoCs
Ph: +86 186 2020 4684 (mobile)
IRC: fuwei
Skype: tekkamanninja
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021 

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 1/6] Documentation: add sbsa-gwdt.txt documentation
@ 2015-05-16 10:29         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-16 10:29 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs

Hi Arnd,

Great thanks for reminding, I should do it earlier.
You will see it in next patchset.

On 05/15/2015 10:06 PM, Arnd Bergmann wrote:
> On Friday 15 May 2015 19:08:05 fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>
>> 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> 
> Looks good, just one minor comment:
> 
>> +Optional properties
>> +- timeout-sec : Watchdog pre-timeout and timeout values (in seconds).
>> +	The first is timeout values, then pre-timeout.
> 
> Please update Documentation/watchdog/watchdog-kernel-api.txt as well, to
> mention the second number in the timeout-sec property.
> 
> 	Arnd
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


-- 
Best regards,

Fu Wei
Software Engineer From Red Hat
LEG Team
Linaro.org | Open source software for ARM SoCs
Ph: +86 186 2020 4684 (mobile)
IRC: fuwei
Skype: tekkamanninja
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021 
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH 0/6] Watchdog: introdouce ARM SBSA watchdog driver
  2015-05-15 14:07     ` Arnd Bergmann
@ 2015-05-16 10:33       ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-16 10:33 UTC (permalink / raw)
  To: Arnd Bergmann, linaro-acpi
  Cc: Suravee.Suthikulpanit, linux-watchdog, devicetree, linux-kernel,
	linux-doc, corbet, jcm, timur, wim, tekkamanninja, vgandhi,
	linux

Hi Arnd,
OK, Thanks, Will reply those comments soon. 

On 05/15/2015 10:07 PM, Arnd Bergmann wrote:
> On Friday 15 May 2015 19:08:04 fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> This patchset:
>>
>>     (1)Introdouces 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
>>
>>     (2)Introdouce "pretimeout" into the watchdog framework
>>
>>     (3)Introdouces 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
>>
>>     (4)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
>>
>>
> 
> I've had a few very minor comments to the individual patches, otherwise
> looks good. I have not reviewed the ACPI part of the series, as I have
> no knowledge of that.
> 
> 	Arnd
> 


-- 
Best regards,

Fu Wei
Software Engineer From Red Hat
LEG Team
Linaro.org | Open source software for ARM SoCs
Ph: +86 186 2020 4684 (mobile)
IRC: fuwei
Skype: tekkamanninja
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021 

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH 0/6] Watchdog: introdouce ARM SBSA watchdog driver
@ 2015-05-16 10:33       ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-16 10:33 UTC (permalink / raw)
  To: Arnd Bergmann, linaro-acpi-cunTk1MwBs8s++Sfvej+rw
  Cc: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, corbet-T1hC0tSOHrs,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, linux-0h96xk9xTtrk1uMJSBkQmQ

Hi Arnd,
OK, Thanks, Will reply those comments soon. 

On 05/15/2015 10:07 PM, Arnd Bergmann wrote:
> On Friday 15 May 2015 19:08:04 fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>
>> This patchset:
>>
>>     (1)Introdouces 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
>>
>>     (2)Introdouce "pretimeout" into the watchdog framework
>>
>>     (3)Introdouces 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
>>
>>     (4)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
>>
>>
> 
> I've had a few very minor comments to the individual patches, otherwise
> looks good. I have not reviewed the ACPI part of the series, as I have
> no knowledge of that.
> 
> 	Arnd
> 


-- 
Best regards,

Fu Wei
Software Engineer From Red Hat
LEG Team
Linaro.org | Open source software for ARM SoCs
Ph: +86 186 2020 4684 (mobile)
IRC: fuwei
Skype: tekkamanninja
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021 
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 5/6] Watchdog: introdouce ARM SBSA watchdog driver
  2015-05-15 13:57     ` Arnd Bergmann
@ 2015-05-16 12:01         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-16 12:01 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, tekkamanninja, graeme.gregory, al.stone,
	hanjun.guo, timur, ashwin.chaugule, linux, vgandhi, wim, jcm,
	leo.duran, corbet

Hi Arnd,
Great thanks for your review,
The feedback is inline below:

On 05/15/2015 09:57 PM, Arnd Bergmann wrote:
> On Friday 15 May 2015 19:24:49 fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>>     (1)Use linux kernel watchdog framework
>>     (2)Work with FDT on ARM64
>>     (3)Use "pretimeout" in watchdog framework
>>     (4)In first timeout(WS0), do panic to save system context
>>     (5)support geting timeout and pretimeout from
>>        parameter and FDT at the driver init stage.
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> 
> The patch looks good overall. Please try to describe in the patch in 
> full sentences in the changelog, as we normally do.

Sure, you will see changelog in the next version.
 
> 
> A few tiny details that I'd do differently, but don't have to change
> if the watchdog maintainer is fine with your version:
> 
>> +struct sbsa_gwdt {
>> +	struct watchdog_device	wdd;
>> +	u32			clk;
>> +	void __iomem		*refresh_base;
>> +	void __iomem		*control_base;
>> +#ifdef CONFIG_PM_SLEEP
>> +	spinlock_t		lock;
>> +	u8			pm_status_store;
>> +#endif
>> +};
> 
> I would drop the #ifdef here, and favor readability over saving
> a few bytes.
yes, that make sense :-)

> 
>> +	/*
>> +	 * Try to determine the frequency from the cp15 interface
>> +	 */
>> +	clk = arch_timer_get_cntfrq();
>> +	if (!clk) {
>> +		dev_err(dev, "System Counter frequency not available\n");
>> +		return -EINVAL;
>> +	}
> 
> Is it guaranteed that the same clock feeds the arch timer and the
> watchdog? Maybe it would be better to use the clk API to read
> the frequency, so we can avoid this dependency.

yes. you are right. According to SBSA doc, the clocksource of SBSA watchdog is System Counter.
And System Counter is in (arm_)arch_timer. So I think we should do 

	depends on ARM_ARCH_TIMER

and use the relevant interface : 

	clk = arch_timer_get_rate();

will improve it, thanks for your suggestion!

> 
>> +
>> +	pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
>> +		 res->name, (unsigned long long)res->start,
>> +		(unsigned long long)(res->end - res->start + 1), 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);
>> +
>> +	pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
>> +		 res->name, (unsigned long long)res->start,
>> +		(unsigned long long)(res->end - res->start + 1), cf_base);
> 
> I would probably drop the various pr_debug() calls here. Once the driver
> works fine, they are normally not that useful any more.

yes, for this drive, if it works fine, we can drop it, but I keep these info for some reason:
(1)they can help engineer debug GTDT table or DTS, if the info of watchdog goes wrong.
(2)check the memory map
(3)if DEBUG is disable, all pr_debug are no_printk, it won't increase Image size or output any through console.
 
> 
> 	Arnd
> 


-- 
Best regards,

Fu Wei
Software Engineer From Red Hat
LEG Team
Linaro.org | Open source software for ARM SoCs
Ph: +86 186 2020 4684 (mobile)
IRC: fuwei
Skype: tekkamanninja
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021 

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 5/6] Watchdog: introdouce ARM SBSA watchdog driver
@ 2015-05-16 12:01         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-16 12:01 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs

Hi Arnd,
Great thanks for your review,
The feedback is inline below:

On 05/15/2015 09:57 PM, Arnd Bergmann wrote:
> On Friday 15 May 2015 19:24:49 fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>
>>     (1)Use linux kernel watchdog framework
>>     (2)Work with FDT on ARM64
>>     (3)Use "pretimeout" in watchdog framework
>>     (4)In first timeout(WS0), do panic to save system context
>>     (5)support geting timeout and pretimeout from
>>        parameter and FDT at the driver init stage.
>>
>> Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> 
> The patch looks good overall. Please try to describe in the patch in 
> full sentences in the changelog, as we normally do.

Sure, you will see changelog in the next version.
 
> 
> A few tiny details that I'd do differently, but don't have to change
> if the watchdog maintainer is fine with your version:
> 
>> +struct sbsa_gwdt {
>> +	struct watchdog_device	wdd;
>> +	u32			clk;
>> +	void __iomem		*refresh_base;
>> +	void __iomem		*control_base;
>> +#ifdef CONFIG_PM_SLEEP
>> +	spinlock_t		lock;
>> +	u8			pm_status_store;
>> +#endif
>> +};
> 
> I would drop the #ifdef here, and favor readability over saving
> a few bytes.
yes, that make sense :-)

> 
>> +	/*
>> +	 * Try to determine the frequency from the cp15 interface
>> +	 */
>> +	clk = arch_timer_get_cntfrq();
>> +	if (!clk) {
>> +		dev_err(dev, "System Counter frequency not available\n");
>> +		return -EINVAL;
>> +	}
> 
> Is it guaranteed that the same clock feeds the arch timer and the
> watchdog? Maybe it would be better to use the clk API to read
> the frequency, so we can avoid this dependency.

yes. you are right. According to SBSA doc, the clocksource of SBSA watchdog is System Counter.
And System Counter is in (arm_)arch_timer. So I think we should do 

	depends on ARM_ARCH_TIMER

and use the relevant interface : 

	clk = arch_timer_get_rate();

will improve it, thanks for your suggestion!

> 
>> +
>> +	pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
>> +		 res->name, (unsigned long long)res->start,
>> +		(unsigned long long)(res->end - res->start + 1), 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);
>> +
>> +	pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
>> +		 res->name, (unsigned long long)res->start,
>> +		(unsigned long long)(res->end - res->start + 1), cf_base);
> 
> I would probably drop the various pr_debug() calls here. Once the driver
> works fine, they are normally not that useful any more.

yes, for this drive, if it works fine, we can drop it, but I keep these info for some reason:
(1)they can help engineer debug GTDT table or DTS, if the info of watchdog goes wrong.
(2)check the memory map
(3)if DEBUG is disable, all pr_debug are no_printk, it won't increase Image size or output any through console.
 
> 
> 	Arnd
> 


-- 
Best regards,

Fu Wei
Software Engineer From Red Hat
LEG Team
Linaro.org | Open source software for ARM SoCs
Ph: +86 186 2020 4684 (mobile)
IRC: fuwei
Skype: tekkamanninja
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021 
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 5/6] Watchdog: introdouce ARM SBSA watchdog driver
  2015-05-16 12:01         ` Fu Wei
  (?)
@ 2015-05-16 12:26         ` Timur Tabi
  -1 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-16 12:26 UTC (permalink / raw)
  To: Fu Wei, Arnd Bergmann
  Cc: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, tekkamanninja, graeme.gregory, al.stone,
	hanjun.guo, ashwin.chaugule, linux, vgandhi, wim, jcm, leo.duran,
	corbet

Fu Wei wrote:

> yes. you are right. According to SBSA doc, the clocksource of SBSA watchdog is System Counter.
> And System Counter is in (arm_)arch_timer. So I think we should do
>
> 	depends on ARM_ARCH_TIMER
>
> and use the relevant interface :
>
> 	clk = arch_timer_get_rate();
>
> will improve it, thanks for your suggestion!

If you use arch_timer_get_rate(), then you will not be able to compile 
the driver as a module.

The clock API doesn't work for me, either, because no clocks are defined 
(clk_get_sys() always fails).

That's why I use arch_timer_get_cntfrq().

>> I would probably drop the various pr_debug() calls here. Once the driver
>> works fine, they are normally not that useful any more.
>
> yes, for this drive, if it works fine, we can drop it, but I keep these info for some reason:
> (1)they can help engineer debug GTDT table or DTS, if the info of watchdog goes wrong.

Any engineer will add his own printks when debugging.  You don't need to 
do that job for someone else.  You just have too many pr_debug() statements.

-- 
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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
  2015-05-15 14:04   ` Arnd Bergmann
@ 2015-05-18 17:19       ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-18 17:19 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Guenter Roeck, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet

Hi Arnd,

Great thanks for your suggestion :-)

feedback inline below

On 15 May 2015 at 22:04, Arnd Bergmann <arnd@arndb.de> wrote:
> On Friday 15 May 2015 19:24:48 fu.wei@linaro.org wrote:
>> +static void watchdog_check_min_max_pretimeout(struct watchdog_device *wdd)
>> +{
>> +       /*
>> +        * Check that we have valid min and max pretimeout 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;
>> +       }
>> +}
>
> I would probably just fold this function into the existing
> watchdog_check_min_max_timeout() and check both normal and pre-timeout
> there.

yes, I can do that , and that is good idea

>
>> +/**
>> + * watchdog_init_pretimeout() - initialize the pretimeout field
>> + * @pretimeout_parm: pretimeout module parameter
>> + * @dev: Device that stores the timeout-sec property
>> + *
>> + * Initialize the pretimeout field of the watchdog_device struct with either
>> + * the pretimeout 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 pretimeout value.
>> + *
>> + * A zero is returned on success and -EINVAL for failure.
>> + */
>> +int watchdog_init_pretimeout(struct watchdog_device *wdd,
>> +                            unsigned int pretimeout_parm, struct device *dev)
>> +{
>> +       int ret = 0;
>> +       u32 timeouts[2];
>> +
>> +       watchdog_check_min_max_pretimeout(wdd);
>> +
>> +       /* try to get the timeout module parameter first */
>> +       if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm) &&
>> +           pretimeout_parm) {
>> +               wdd->pretimeout = pretimeout_parm;
>> +               return ret;
>> +       }
>> +       if (pretimeout_parm)
>> +               ret = -EINVAL;
>> +
>> +       /* try to get the timeout_sec property */
>> +       if (!dev || !dev->of_node)
>> +               return ret;
>> +       ret = of_property_read_u32_array(dev->of_node,
>> +                                        "timeout-sec", timeouts, 2);
>> +       if (!watchdog_pretimeout_invalid(wdd, timeouts[1]) && timeouts[1])
>> +               wdd->pretimeout = timeouts[1];
>> +       else
>> +               ret = -EINVAL;
>> +
>> +       return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(watchdog_init_pretimeout);
>
> Same here: the function is very similar to the watchdog_init_timeout
> function, and it reads the same property, so just do both here.
>
> The easiest way for that is probably to use of_find_property()
> and of_prop_next_u32() to read the two numbers.

integrate watchdog_init_pretimeout and watchdog_init_timeout will be a
little hard,
we may need to change this API to :

watchdog_init_timeouts(struct watchdog_device *wdd, unsigned int timeout_parm,
                             unsigned int pretimeout_parm, struct device *dev)

then we need to update all the watchdog drivers which use this API,
maybe we can do this in a individual patchset, after this pretimeout
patch is merged.

Is that OK  ? :-)  any thought?


>
>         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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
@ 2015-05-18 17:19       ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-18 17:19 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Guenter Roeck,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet

Hi Arnd,

Great thanks for your suggestion :-)

feedback inline below

On 15 May 2015 at 22:04, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
> On Friday 15 May 2015 19:24:48 fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>> +static void watchdog_check_min_max_pretimeout(struct watchdog_device *wdd)
>> +{
>> +       /*
>> +        * Check that we have valid min and max pretimeout 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;
>> +       }
>> +}
>
> I would probably just fold this function into the existing
> watchdog_check_min_max_timeout() and check both normal and pre-timeout
> there.

yes, I can do that , and that is good idea

>
>> +/**
>> + * watchdog_init_pretimeout() - initialize the pretimeout field
>> + * @pretimeout_parm: pretimeout module parameter
>> + * @dev: Device that stores the timeout-sec property
>> + *
>> + * Initialize the pretimeout field of the watchdog_device struct with either
>> + * the pretimeout 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 pretimeout value.
>> + *
>> + * A zero is returned on success and -EINVAL for failure.
>> + */
>> +int watchdog_init_pretimeout(struct watchdog_device *wdd,
>> +                            unsigned int pretimeout_parm, struct device *dev)
>> +{
>> +       int ret = 0;
>> +       u32 timeouts[2];
>> +
>> +       watchdog_check_min_max_pretimeout(wdd);
>> +
>> +       /* try to get the timeout module parameter first */
>> +       if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm) &&
>> +           pretimeout_parm) {
>> +               wdd->pretimeout = pretimeout_parm;
>> +               return ret;
>> +       }
>> +       if (pretimeout_parm)
>> +               ret = -EINVAL;
>> +
>> +       /* try to get the timeout_sec property */
>> +       if (!dev || !dev->of_node)
>> +               return ret;
>> +       ret = of_property_read_u32_array(dev->of_node,
>> +                                        "timeout-sec", timeouts, 2);
>> +       if (!watchdog_pretimeout_invalid(wdd, timeouts[1]) && timeouts[1])
>> +               wdd->pretimeout = timeouts[1];
>> +       else
>> +               ret = -EINVAL;
>> +
>> +       return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(watchdog_init_pretimeout);
>
> Same here: the function is very similar to the watchdog_init_timeout
> function, and it reads the same property, so just do both here.
>
> The easiest way for that is probably to use of_find_property()
> and of_prop_next_u32() to read the two numbers.

integrate watchdog_init_pretimeout and watchdog_init_timeout will be a
little hard,
we may need to change this API to :

watchdog_init_timeouts(struct watchdog_device *wdd, unsigned int timeout_parm,
                             unsigned int pretimeout_parm, struct device *dev)

then we need to update all the watchdog drivers which use this API,
maybe we can do this in a individual patchset, after this pretimeout
patch is merged.

Is that OK  ? :-)  any thought?


>
>         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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
@ 2015-05-18 17:22           ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-18 17:22 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet

Hi Guenter,

yes, I think it is OK for me,

Once this patchset is merged, I will try to make a new patchset just
for this integration.

On 16 May 2015 at 02:01, Guenter Roeck <linux@roeck-us.net> wrote:
> On Fri, May 15, 2015 at 09:49:07PM +0800, Fu Wei wrote:
>> Hi Guenter,
>>
>> Great thanks for your review,
>> feedback inline below :-)
>>
>> On 15 May 2015 at 21:33, Guenter Roeck <linux@roeck-us.net> wrote:
>
> [ ... ]
>
>> >> +       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;
>> >> +       }
>> >
>> >
>> > I am a bit concerned about the context dependency introduced here. If
>> > someone calls
>> > _init_pretimeout after calling init_timeout, this may result in still
>> > invalid timeout
>> > values.
>>
>> yes, that logic is not very clean, so my thought is :
>> maybe we can integrate watchdog_init_timeout and watchdog_init_pretimeout,
>> if maintainer agree to add pretimeout into framework.
>>
> I think we should just assume that Wim will accept it, and try to find
> the best possible solution (or at least a good one).
>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
@ 2015-05-18 17:22           ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-18 17:22 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet

Hi Guenter,

yes, I think it is OK for me,

Once this patchset is merged, I will try to make a new patchset just
for this integration.

On 16 May 2015 at 02:01, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On Fri, May 15, 2015 at 09:49:07PM +0800, Fu Wei wrote:
>> Hi Guenter,
>>
>> Great thanks for your review,
>> feedback inline below :-)
>>
>> On 15 May 2015 at 21:33, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
>
> [ ... ]
>
>> >> +       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;
>> >> +       }
>> >
>> >
>> > I am a bit concerned about the context dependency introduced here. If
>> > someone calls
>> > _init_pretimeout after calling init_timeout, this may result in still
>> > invalid timeout
>> > values.
>>
>> yes, that logic is not very clean, so my thought is :
>> maybe we can integrate watchdog_init_timeout and watchdog_init_pretimeout,
>> if maintainer agree to add pretimeout into framework.
>>
> I think we should just assume that Wim will accept it, and try to find
> the best possible solution (or at least a good one).
>
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
  2015-05-18 17:19       ` Fu Wei
  (?)
@ 2015-05-18 17:23       ` Guenter Roeck
  2015-05-18 17:39         ` Fu Wei
  2015-05-18 20:03         ` Arnd Bergmann
  -1 siblings, 2 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-18 17:23 UTC (permalink / raw)
  To: Fu Wei
  Cc: Arnd Bergmann, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Timur Tabi, Ashwin Chaugule,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet

On Tue, May 19, 2015 at 01:19:22AM +0800, Fu Wei wrote:
> Hi Arnd,
> 
> Great thanks for your suggestion :-)
> 
> feedback inline below
> 
> On 15 May 2015 at 22:04, Arnd Bergmann <arnd@arndb.de> wrote:
> > On Friday 15 May 2015 19:24:48 fu.wei@linaro.org wrote:
> >> +static void watchdog_check_min_max_pretimeout(struct watchdog_device *wdd)
> >> +{
> >> +       /*
> >> +        * Check that we have valid min and max pretimeout 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;
> >> +       }
> >> +}
> >
> > I would probably just fold this function into the existing
> > watchdog_check_min_max_timeout() and check both normal and pre-timeout
> > there.
> 
> yes, I can do that , and that is good idea
> 
> >
> >> +/**
> >> + * watchdog_init_pretimeout() - initialize the pretimeout field
> >> + * @pretimeout_parm: pretimeout module parameter
> >> + * @dev: Device that stores the timeout-sec property
> >> + *
> >> + * Initialize the pretimeout field of the watchdog_device struct with either
> >> + * the pretimeout 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 pretimeout value.
> >> + *
> >> + * A zero is returned on success and -EINVAL for failure.
> >> + */
> >> +int watchdog_init_pretimeout(struct watchdog_device *wdd,
> >> +                            unsigned int pretimeout_parm, struct device *dev)
> >> +{
> >> +       int ret = 0;
> >> +       u32 timeouts[2];
> >> +
> >> +       watchdog_check_min_max_pretimeout(wdd);
> >> +
> >> +       /* try to get the timeout module parameter first */
> >> +       if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm) &&
> >> +           pretimeout_parm) {
> >> +               wdd->pretimeout = pretimeout_parm;
> >> +               return ret;
> >> +       }
> >> +       if (pretimeout_parm)
> >> +               ret = -EINVAL;
> >> +
> >> +       /* try to get the timeout_sec property */
> >> +       if (!dev || !dev->of_node)
> >> +               return ret;
> >> +       ret = of_property_read_u32_array(dev->of_node,
> >> +                                        "timeout-sec", timeouts, 2);
> >> +       if (!watchdog_pretimeout_invalid(wdd, timeouts[1]) && timeouts[1])
> >> +               wdd->pretimeout = timeouts[1];
> >> +       else
> >> +               ret = -EINVAL;
> >> +
> >> +       return ret;
> >> +}
> >> +EXPORT_SYMBOL_GPL(watchdog_init_pretimeout);
> >
> > Same here: the function is very similar to the watchdog_init_timeout
> > function, and it reads the same property, so just do both here.
> >
> > The easiest way for that is probably to use of_find_property()
> > and of_prop_next_u32() to read the two numbers.
> 
> integrate watchdog_init_pretimeout and watchdog_init_timeout will be a
> little hard,
> we may need to change this API to :
> 
> watchdog_init_timeouts(struct watchdog_device *wdd, unsigned int timeout_parm,
>                              unsigned int pretimeout_parm, struct device *dev)
> 
> then we need to update all the watchdog drivers which use this API,
> maybe we can do this in a individual patchset, after this pretimeout
> patch is merged.
> 
> Is that OK  ? :-)  any thought?
> 
That is what I would recommend.

Guenter

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 5/6] Watchdog: introdouce ARM SBSA watchdog driver
@ 2015-05-18 17:38         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-18 17:38 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet

Hi Grenter,

Great thanks for your review,

On 16 May 2015 at 06:57, Guenter Roeck <linux@roeck-us.net> wrote:
> On 05/15/2015 04:24 AM, fu.wei@linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>>      (1)Use linux kernel watchdog framework
>>      (2)Work with FDT on ARM64
>>      (3)Use "pretimeout" in watchdog framework
>>      (4)In first timeout(WS0), do panic to save system context
>>      (5)support geting timeout and pretimeout from
>
>
> getting
>
>>         parameter and FDT at the driver init stage.
>
>
> Subject: s/introdouce/introduce/
>
> Please find a better description.
>
> Also, please provide revisions numbers for your patch sets, and
> list the changes from one revision to the next.

sorry for those typo, I have fixed them,
and will provide revisions numbers and changelog in next patch

>
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>   drivers/watchdog/Kconfig     |  10 +
>>   drivers/watchdog/Makefile    |   1 +
>>   drivers/watchdog/sbsa_gwdt.c | 553
>> +++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 564 insertions(+)
>>   create mode 100644 drivers/watchdog/sbsa_gwdt.c
>>
>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>> index e5e7c55..1e1bc8b 100644
>> --- a/drivers/watchdog/Kconfig
>> +++ b/drivers/watchdog/Kconfig
>> @@ -152,6 +152,16 @@ 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
>> +       select WATCHDOG_CORE
>> +       help
>> +         ARM SBSA Generic Watchdog timer. This has two Watchdog
>> Signal(WS0/WS1),
>
>
> signals
>
>> +         will trigger a warnning interrupt(do panic) in the first
>> timeout(WS0);
>
>
> warning

sorry for these typoes, I have fixed them,


>
>
>> +         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..52838b1
>> --- /dev/null
>> +++ b/drivers/watchdog/sbsa_gwdt.c
>> @@ -0,0 +1,553 @@
>> +/*
>> + * SBSA(Server Base System Architecture) Generic Watchdog driver
>> + *
>> + * Copyright (c) 2015, Linaro Ltd.
>> + * Author: Fu Wei <fu.wei@linaro.org>
>> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>> + *
>> + * 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.
>> + *       But timeout and pretimeout are set by the different REGs.
>
>
> Why "But" ?

deleted it :-)

>
>> + *       The first watch period is set by writing WCV directly,
>> + *       that can support more than 10s timeout at the maximum
>> + *       system counter frequency.
>> + *       And the second watch period is set by WOR(32bit) which will be
>> loaded
>
>
> s/And the/The/

Thanks,  I have fixed them,

>
>
>> + *       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/spinlock.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)
>> +
>> +/* Watchdog Interface Identification Register */
>> +#define SBSA_GWDT_W_IIDR_PID(x)                        ((x >> 20) &
>> 0xfff)
>> +#define SBSA_GWDT_W_IIDR_ARCH_VER(x)           ((x >> 16) & 0xf)
>> +#define SBSA_GWDT_W_IIDR_REV(x)                        ((x >> 12) & 0xf)
>> +#define SBSA_GWDT_W_IIDR_IMPLEMENTER(x)                (x & 0xfff)
>> +#define SBSA_GWDT_W_IIDR_VID_BANK(x)           ((x >> 8) & 0xf)
>> +#define SBSA_GWDT_W_IIDR_VID(x)                        (x & 0x7f)
>> +
>> +/* Watchdog Identification Register */
>> +#define SBSA_GWDT_IDR_W_PIDR2                  0xfe8
>> +#define SBSA_GWDT_IDR_W_PIDR2_ARCH_VER(x)      ((x >> 4) & 0xf)
>> +
>
>
> (x) for all the above macros, please.

Great thanks , my bad , I have fixed them

>
>> +/**
>> + * 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:      VA of the watchdog refresh frame
>> + * @control_base:      VA of the watchdog control frame
>
>
> Please spell out "Virtual address".

done :-)

>
>> + * @lock:              struct sbsa_gwdt spinlock
>> + * @pm_status_store:   store the PM info of WDT
>> + */
>> +struct sbsa_gwdt {
>> +       struct watchdog_device  wdd;
>> +       u32                     clk;
>> +       void __iomem            *refresh_base;
>> +       void __iomem            *control_base;
>> +#ifdef CONFIG_PM_SLEEP
>> +       spinlock_t              lock;
>> +       u8                      pm_status_store;
>> +#endif
>
>
> Please avoid the #ifdef

I have deleted them , thanks

>
>
>> +};
>> +
>> +#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
>> +
>> +#define DEFAULT_TIMEOUT_WS0    10 /* seconds, the 1st watch period*/
>> +#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_WS0 + DEFAULT_PRETIMEOUT)
>> ")");
>> +
>> +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 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 unsigned int pretimeout;
>> +module_param(pretimeout, uint, 0);
>> +MODULE_PARM_DESC(pretimeout,
>> +                "Watchdog pretimeout in seconds. (>=0, default="
>> +                __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
>> +
>> +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
>> + * mutex_lock must be called prior to calling this function.
>> + */
>> +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);
>> +
>> +       pr_debug("sbsa_gwdt: set WCV to %llu, result: %llu\n",
>> +                value, sbsa_gwdt_get_wcv(wdd));
>
>
> Is this pr_debug still necessary ?

will remove it , Thanks

>
>
>> +}
>> +
>> +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_set_timeout_limits(struct sbsa_gwdt *gwdt)
>> +{
>> +       unsigned int first_period_max = (U64_MAX / gwdt->clk);
>> +       struct watchdog_device *wdd = &gwdt->wdd;
>> +
>> +       wdd->min_timeout = wdd->pretimeout + 1;
>> +       wdd->max_timeout = min(wdd->pretimeout + first_period_max,
>> max_timeout);
>> +
>> +       pr_debug("sbsa_gwdt: timeout (%u-%u), pretimeout (%u-%u)\n",
>> +                wdd->min_timeout, wdd->max_timeout,
>> +                wdd->min_pretimeout, wdd->max_pretimeout);
>
>
> Is this still necessary ?

will remove it , Thanks

>
>> +}
>> +
>> +static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
>> +                                unsigned int timeout)
>> +{
>> +       wdd->timeout = timeout;
>> +
>> +       return 0;
>> +       /* watchdog framework will trigger a ping, after this call */
>
>
> Unnecessary comment.

will remove it , Thanks

>
>> +}
>> +
>> +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_set_timeout_limits(gwdt);
>> +
>> +       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);
>> +
>> +       pr_debug("sbsa_gwdt: set WOR to %x(%us), result: %x\n",
>> +                wor, pretimeout, sbsa_gwdt_cf_read(SBSA_GWDT_WOR, wdd));
>
>
> Is this still necessary ?

will remove it , Thanks

>
>> +
>> +       return 0;
>> +       /* watchdog framework will trigger a ping, after this call */
>
>
> Unnecessary comment.

will remove it , Thanks

>
>> +}
>> +
>> +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();
>> +
>> +       return timeleft / gwdt->clk;
>
>
> Will this ever be built on a 32 bit target ? That may cause a link error
> due to the 64 bit divide operation.

yes, you are right, you found a bug,  I have fixed it by do_div().

Great thanks !!

>
>> +}
>> +
>> +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);
>> +
>> +       pr_debug("sbsa_gwdt: WCS is %x(%s)\n",
>> +                sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd), __func__);
>
>
> Another one. If you think you need to keep those, can you at least use
> dev_dbg ?
> I won't comment on the debug messages further, but I really think that even
> for debug messages this is a bit noisy.

will remove it , Thanks

>
>
>> +
>> +       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);
>> +
>> +       pr_debug("sbsa_gwdt: WCS is %x(%s)\n",
>> +                sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd), __func__);
>> +
>> +       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);
>> +
>> +       pr_debug("sbsa_gwdt: ping, %us left.\n",
>> sbsa_gwdt_get_timeleft(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);
>> +
>> +       pr_debug("sbsa_gwdt: interrupt routine, WCS@%x\n", status);
>> +
>> +       if (status & SBSA_GWDT_WCS_WS0) {
>> +               pr_debug("sbsa_gwdt WS0: trigger WS1 in %ds!\n",
>> +                        sbsa_gwdt_get_timeleft(wdd));
>> +               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, w_iidr;
>> +
>> +       int ret = 0;
>
>
> Please drop the empty lines above.

OK, np, done :-)

>
>> +
>> +       /*
>> +        * Try to determine the frequency from the cp15 interface
>> +        */
>> +       clk = arch_timer_get_cntfrq();
>> +       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);
>> +
>> +       pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
>> +                res->name, (unsigned long long)res->start,
>> +               (unsigned long long)(res->end - res->start + 1), rf_base);
>
>
> If you think you need to keep those messages, please at least use %pR.

thanks for your suggestion, but I will remove it

>
>
>> +
>> +       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);
>> +
>> +       pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
>> +                res->name, (unsigned long long)res->start,
>> +               (unsigned long long)(res->end - res->start + 1), cf_base);
>> +
>> +       irq = platform_get_irq_byname(pdev, "ws0");
>> +       if (irq < 0) {
>> +               dev_err(dev, "unable to get ws0 interrupt.\n");
>> +               return irq;
>> +       }
>> +
>> +       pr_debug("sbsa_gwdt: ws0 irq %d.\n", irq);
>> +
>> +       gwdt->refresh_base = rf_base;
>> +       gwdt->control_base = cf_base;
>> +       gwdt->clk = clk;
>> +#ifdef CONFIG_PM_SLEEP
>> +       spin_lock_init(&gwdt->lock);
>> +#endif
>> +       platform_set_drvdata(pdev, gwdt);
>> +
>> +       pr_debug("sbsa_gwdt: hw clk: %uHz--> WOR(32bit) max timeout is
>> %us.\n",
>> +                gwdt->clk, U32_MAX / clk);
>> +
>> +       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 was reseted by WDT(WCS: %x, WCV:
>> %llx)\n",
>
>
> "was reseted" is kind of odd. Can you use just "reset" or maybe "restarted"
> ?

yes, will do , thanks


>
>> +                        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!\n");
>> +               sbsa_gwdt_keepalive(wdd);
>> +       }
>> +
>> +       pr_debug("sbsa_gwdt: WCS: %x(%s)\n", status, __func__);
>> +
>> +       wdd->min_pretimeout = 0;
>> +       wdd->max_pretimeout = min(U32_MAX / clk, max_timeout - 1);
>> +       sbsa_gwdt_set_timeout_limits(gwdt);
>> +
>> +       watchdog_init_pretimeout(wdd, pretimeout, dev);
>> +       if (!wdd->pretimeout) {
>> +               wdd->pretimeout = DEFAULT_PRETIMEOUT;
>> +               dev_info(dev, "can't get pretimeout param, set default
>> %us.\n",
>> +                        wdd->pretimeout);
>
>
> Unnecessary message. The pretimeout is printed again below.
>
>> +       }
>> +       sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
>> +
>> +       watchdog_init_timeout(wdd, timeout, dev);
>> +       if (!wdd->timeout) {
>> +               wdd->timeout = wdd->pretimeout + DEFAULT_TIMEOUT_WS0;
>> +               dev_info(dev, "can't get timeout param, set default:
>> %us.\n",
>> +                        wdd->timeout);
>
>
> Same here.
>

yes,  I have removed them.


>> +       }
>> +       sbsa_gwdt_set_timeout(wdd, wdd->timeout);
>> +
>> +       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;
>> +
>> +       /* get device information from control frame and display */
>> +       w_iidr = sbsa_gwdt_cf_read(SBSA_GWDT_W_IIDR, &gwdt->wdd);
>> +       dev_info(dev, "PID:%u(JEP106 %u-%u), Arch v%u Rev %u.",
>> +                SBSA_GWDT_W_IIDR_PID(w_iidr),
>> +                SBSA_GWDT_W_IIDR_VID_BANK(w_iidr),
>> +                SBSA_GWDT_W_IIDR_VID(w_iidr),
>> +                SBSA_GWDT_W_IIDR_ARCH_VER(w_iidr),
>> +                SBSA_GWDT_W_IIDR_REV(w_iidr));
>
>
> Is this valuable information ?

not too much value, just tell you the hw info,  should I remove it?

>
>
>> +
>> +       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;
>> +}
>> +
>> +#ifdef CONFIG_PM_SLEEP
>
>
> You don't need the #ifdef if you use __maybe_unused with the function
> declarations.

yes, doing this way now

>
>> +/* Disable watchdog if it is active during suspend */
>> +static int sbsa_gwdt_suspend(struct device *dev)
>> +{
>> +       struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
>> +       struct watchdog_device *wdd = &gwdt->wdd;
>> +
>> +       spin_lock(&gwdt->lock);
>> +       gwdt->pm_status_store = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
>> +
>> +       if (gwdt->pm_status_store & SBSA_GWDT_WCS_EN)
>> +               sbsa_gwdt_stop(wdd);
>> +       spin_unlock(&gwdt->lock);
>
>
> Wonder what this lock is protecting against. Can you explain ?
> I would assume that suspend and resume are mutually exclusive
> and don't require locking against each other.
>
>> +
>> +       return 0;
>> +}
>> +
>> +/* Enable watchdog and configure it if necessary */
>> +static int sbsa_gwdt_resume(struct device *dev)
>> +{
>> +       struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
>> +       struct watchdog_device *wdd = &gwdt->wdd;
>> +
>> +       spin_lock(&gwdt->lock);
>> +       if (gwdt->pm_status_store & SBSA_GWDT_WCS_EN)
>> +               sbsa_gwdt_start(wdd);
>> +       else
>> +               sbsa_gwdt_stop(wdd);
>
>
> What is the stop here for ?

Thanks ,  I have improved this part. :-)


>
>
>> +       spin_unlock(&gwdt->lock);
>> +
>> +       return 0;
>> +}
>> +#endif
>> +
>> +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 dev_pm_ops sbsa_gwdt_pm_ops = {
>> +       SET_SYSTEM_SLEEP_PM_OPS(sbsa_gwdt_suspend, sbsa_gwdt_resume)
>> +};
>> +
>> +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,
>> +};
>> +
>> +module_platform_driver(sbsa_gwdt_driver);
>> +
>> +MODULE_DESCRIPTION("SBSA Generic Watchdog Driver");
>> +MODULE_AUTHOR("Fu Wei <fu.wei@linaro.org>");
>> +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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 5/6] Watchdog: introdouce ARM SBSA watchdog driver
@ 2015-05-18 17:38         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-18 17:38 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet

Hi Grenter,

Great thanks for your review,

On 16 May 2015 at 06:57, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On 05/15/2015 04:24 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>>
>> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>
>>      (1)Use linux kernel watchdog framework
>>      (2)Work with FDT on ARM64
>>      (3)Use "pretimeout" in watchdog framework
>>      (4)In first timeout(WS0), do panic to save system context
>>      (5)support geting timeout and pretimeout from
>
>
> getting
>
>>         parameter and FDT at the driver init stage.
>
>
> Subject: s/introdouce/introduce/
>
> Please find a better description.
>
> Also, please provide revisions numbers for your patch sets, and
> list the changes from one revision to the next.

sorry for those typo, I have fixed them,
and will provide revisions numbers and changelog in next patch

>
>>
>> Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> ---
>>   drivers/watchdog/Kconfig     |  10 +
>>   drivers/watchdog/Makefile    |   1 +
>>   drivers/watchdog/sbsa_gwdt.c | 553
>> +++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 564 insertions(+)
>>   create mode 100644 drivers/watchdog/sbsa_gwdt.c
>>
>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>> index e5e7c55..1e1bc8b 100644
>> --- a/drivers/watchdog/Kconfig
>> +++ b/drivers/watchdog/Kconfig
>> @@ -152,6 +152,16 @@ 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
>> +       select WATCHDOG_CORE
>> +       help
>> +         ARM SBSA Generic Watchdog timer. This has two Watchdog
>> Signal(WS0/WS1),
>
>
> signals
>
>> +         will trigger a warnning interrupt(do panic) in the first
>> timeout(WS0);
>
>
> warning

sorry for these typoes, I have fixed them,


>
>
>> +         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..52838b1
>> --- /dev/null
>> +++ b/drivers/watchdog/sbsa_gwdt.c
>> @@ -0,0 +1,553 @@
>> +/*
>> + * SBSA(Server Base System Architecture) Generic Watchdog driver
>> + *
>> + * Copyright (c) 2015, Linaro Ltd.
>> + * Author: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
>> + *
>> + * 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.
>> + *       But timeout and pretimeout are set by the different REGs.
>
>
> Why "But" ?

deleted it :-)

>
>> + *       The first watch period is set by writing WCV directly,
>> + *       that can support more than 10s timeout at the maximum
>> + *       system counter frequency.
>> + *       And the second watch period is set by WOR(32bit) which will be
>> loaded
>
>
> s/And the/The/

Thanks,  I have fixed them,

>
>
>> + *       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/spinlock.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)
>> +
>> +/* Watchdog Interface Identification Register */
>> +#define SBSA_GWDT_W_IIDR_PID(x)                        ((x >> 20) &
>> 0xfff)
>> +#define SBSA_GWDT_W_IIDR_ARCH_VER(x)           ((x >> 16) & 0xf)
>> +#define SBSA_GWDT_W_IIDR_REV(x)                        ((x >> 12) & 0xf)
>> +#define SBSA_GWDT_W_IIDR_IMPLEMENTER(x)                (x & 0xfff)
>> +#define SBSA_GWDT_W_IIDR_VID_BANK(x)           ((x >> 8) & 0xf)
>> +#define SBSA_GWDT_W_IIDR_VID(x)                        (x & 0x7f)
>> +
>> +/* Watchdog Identification Register */
>> +#define SBSA_GWDT_IDR_W_PIDR2                  0xfe8
>> +#define SBSA_GWDT_IDR_W_PIDR2_ARCH_VER(x)      ((x >> 4) & 0xf)
>> +
>
>
> (x) for all the above macros, please.

Great thanks , my bad , I have fixed them

>
>> +/**
>> + * 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:      VA of the watchdog refresh frame
>> + * @control_base:      VA of the watchdog control frame
>
>
> Please spell out "Virtual address".

done :-)

>
>> + * @lock:              struct sbsa_gwdt spinlock
>> + * @pm_status_store:   store the PM info of WDT
>> + */
>> +struct sbsa_gwdt {
>> +       struct watchdog_device  wdd;
>> +       u32                     clk;
>> +       void __iomem            *refresh_base;
>> +       void __iomem            *control_base;
>> +#ifdef CONFIG_PM_SLEEP
>> +       spinlock_t              lock;
>> +       u8                      pm_status_store;
>> +#endif
>
>
> Please avoid the #ifdef

I have deleted them , thanks

>
>
>> +};
>> +
>> +#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
>> +
>> +#define DEFAULT_TIMEOUT_WS0    10 /* seconds, the 1st watch period*/
>> +#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_WS0 + DEFAULT_PRETIMEOUT)
>> ")");
>> +
>> +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 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 unsigned int pretimeout;
>> +module_param(pretimeout, uint, 0);
>> +MODULE_PARM_DESC(pretimeout,
>> +                "Watchdog pretimeout in seconds. (>=0, default="
>> +                __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
>> +
>> +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
>> + * mutex_lock must be called prior to calling this function.
>> + */
>> +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);
>> +
>> +       pr_debug("sbsa_gwdt: set WCV to %llu, result: %llu\n",
>> +                value, sbsa_gwdt_get_wcv(wdd));
>
>
> Is this pr_debug still necessary ?

will remove it , Thanks

>
>
>> +}
>> +
>> +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_set_timeout_limits(struct sbsa_gwdt *gwdt)
>> +{
>> +       unsigned int first_period_max = (U64_MAX / gwdt->clk);
>> +       struct watchdog_device *wdd = &gwdt->wdd;
>> +
>> +       wdd->min_timeout = wdd->pretimeout + 1;
>> +       wdd->max_timeout = min(wdd->pretimeout + first_period_max,
>> max_timeout);
>> +
>> +       pr_debug("sbsa_gwdt: timeout (%u-%u), pretimeout (%u-%u)\n",
>> +                wdd->min_timeout, wdd->max_timeout,
>> +                wdd->min_pretimeout, wdd->max_pretimeout);
>
>
> Is this still necessary ?

will remove it , Thanks

>
>> +}
>> +
>> +static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
>> +                                unsigned int timeout)
>> +{
>> +       wdd->timeout = timeout;
>> +
>> +       return 0;
>> +       /* watchdog framework will trigger a ping, after this call */
>
>
> Unnecessary comment.

will remove it , Thanks

>
>> +}
>> +
>> +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_set_timeout_limits(gwdt);
>> +
>> +       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);
>> +
>> +       pr_debug("sbsa_gwdt: set WOR to %x(%us), result: %x\n",
>> +                wor, pretimeout, sbsa_gwdt_cf_read(SBSA_GWDT_WOR, wdd));
>
>
> Is this still necessary ?

will remove it , Thanks

>
>> +
>> +       return 0;
>> +       /* watchdog framework will trigger a ping, after this call */
>
>
> Unnecessary comment.

will remove it , Thanks

>
>> +}
>> +
>> +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();
>> +
>> +       return timeleft / gwdt->clk;
>
>
> Will this ever be built on a 32 bit target ? That may cause a link error
> due to the 64 bit divide operation.

yes, you are right, you found a bug,  I have fixed it by do_div().

Great thanks !!

>
>> +}
>> +
>> +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);
>> +
>> +       pr_debug("sbsa_gwdt: WCS is %x(%s)\n",
>> +                sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd), __func__);
>
>
> Another one. If you think you need to keep those, can you at least use
> dev_dbg ?
> I won't comment on the debug messages further, but I really think that even
> for debug messages this is a bit noisy.

will remove it , Thanks

>
>
>> +
>> +       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);
>> +
>> +       pr_debug("sbsa_gwdt: WCS is %x(%s)\n",
>> +                sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd), __func__);
>> +
>> +       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);
>> +
>> +       pr_debug("sbsa_gwdt: ping, %us left.\n",
>> sbsa_gwdt_get_timeleft(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);
>> +
>> +       pr_debug("sbsa_gwdt: interrupt routine, WCS@%x\n", status);
>> +
>> +       if (status & SBSA_GWDT_WCS_WS0) {
>> +               pr_debug("sbsa_gwdt WS0: trigger WS1 in %ds!\n",
>> +                        sbsa_gwdt_get_timeleft(wdd));
>> +               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, w_iidr;
>> +
>> +       int ret = 0;
>
>
> Please drop the empty lines above.

OK, np, done :-)

>
>> +
>> +       /*
>> +        * Try to determine the frequency from the cp15 interface
>> +        */
>> +       clk = arch_timer_get_cntfrq();
>> +       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);
>> +
>> +       pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
>> +                res->name, (unsigned long long)res->start,
>> +               (unsigned long long)(res->end - res->start + 1), rf_base);
>
>
> If you think you need to keep those messages, please at least use %pR.

thanks for your suggestion, but I will remove it

>
>
>> +
>> +       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);
>> +
>> +       pr_debug("sbsa_gwdt: ioremap %s frame 0x%llx(size: %llu)-->%p.\n",
>> +                res->name, (unsigned long long)res->start,
>> +               (unsigned long long)(res->end - res->start + 1), cf_base);
>> +
>> +       irq = platform_get_irq_byname(pdev, "ws0");
>> +       if (irq < 0) {
>> +               dev_err(dev, "unable to get ws0 interrupt.\n");
>> +               return irq;
>> +       }
>> +
>> +       pr_debug("sbsa_gwdt: ws0 irq %d.\n", irq);
>> +
>> +       gwdt->refresh_base = rf_base;
>> +       gwdt->control_base = cf_base;
>> +       gwdt->clk = clk;
>> +#ifdef CONFIG_PM_SLEEP
>> +       spin_lock_init(&gwdt->lock);
>> +#endif
>> +       platform_set_drvdata(pdev, gwdt);
>> +
>> +       pr_debug("sbsa_gwdt: hw clk: %uHz--> WOR(32bit) max timeout is
>> %us.\n",
>> +                gwdt->clk, U32_MAX / clk);
>> +
>> +       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 was reseted by WDT(WCS: %x, WCV:
>> %llx)\n",
>
>
> "was reseted" is kind of odd. Can you use just "reset" or maybe "restarted"
> ?

yes, will do , thanks


>
>> +                        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!\n");
>> +               sbsa_gwdt_keepalive(wdd);
>> +       }
>> +
>> +       pr_debug("sbsa_gwdt: WCS: %x(%s)\n", status, __func__);
>> +
>> +       wdd->min_pretimeout = 0;
>> +       wdd->max_pretimeout = min(U32_MAX / clk, max_timeout - 1);
>> +       sbsa_gwdt_set_timeout_limits(gwdt);
>> +
>> +       watchdog_init_pretimeout(wdd, pretimeout, dev);
>> +       if (!wdd->pretimeout) {
>> +               wdd->pretimeout = DEFAULT_PRETIMEOUT;
>> +               dev_info(dev, "can't get pretimeout param, set default
>> %us.\n",
>> +                        wdd->pretimeout);
>
>
> Unnecessary message. The pretimeout is printed again below.
>
>> +       }
>> +       sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
>> +
>> +       watchdog_init_timeout(wdd, timeout, dev);
>> +       if (!wdd->timeout) {
>> +               wdd->timeout = wdd->pretimeout + DEFAULT_TIMEOUT_WS0;
>> +               dev_info(dev, "can't get timeout param, set default:
>> %us.\n",
>> +                        wdd->timeout);
>
>
> Same here.
>

yes,  I have removed them.


>> +       }
>> +       sbsa_gwdt_set_timeout(wdd, wdd->timeout);
>> +
>> +       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;
>> +
>> +       /* get device information from control frame and display */
>> +       w_iidr = sbsa_gwdt_cf_read(SBSA_GWDT_W_IIDR, &gwdt->wdd);
>> +       dev_info(dev, "PID:%u(JEP106 %u-%u), Arch v%u Rev %u.",
>> +                SBSA_GWDT_W_IIDR_PID(w_iidr),
>> +                SBSA_GWDT_W_IIDR_VID_BANK(w_iidr),
>> +                SBSA_GWDT_W_IIDR_VID(w_iidr),
>> +                SBSA_GWDT_W_IIDR_ARCH_VER(w_iidr),
>> +                SBSA_GWDT_W_IIDR_REV(w_iidr));
>
>
> Is this valuable information ?

not too much value, just tell you the hw info,  should I remove it?

>
>
>> +
>> +       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;
>> +}
>> +
>> +#ifdef CONFIG_PM_SLEEP
>
>
> You don't need the #ifdef if you use __maybe_unused with the function
> declarations.

yes, doing this way now

>
>> +/* Disable watchdog if it is active during suspend */
>> +static int sbsa_gwdt_suspend(struct device *dev)
>> +{
>> +       struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
>> +       struct watchdog_device *wdd = &gwdt->wdd;
>> +
>> +       spin_lock(&gwdt->lock);
>> +       gwdt->pm_status_store = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
>> +
>> +       if (gwdt->pm_status_store & SBSA_GWDT_WCS_EN)
>> +               sbsa_gwdt_stop(wdd);
>> +       spin_unlock(&gwdt->lock);
>
>
> Wonder what this lock is protecting against. Can you explain ?
> I would assume that suspend and resume are mutually exclusive
> and don't require locking against each other.
>
>> +
>> +       return 0;
>> +}
>> +
>> +/* Enable watchdog and configure it if necessary */
>> +static int sbsa_gwdt_resume(struct device *dev)
>> +{
>> +       struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
>> +       struct watchdog_device *wdd = &gwdt->wdd;
>> +
>> +       spin_lock(&gwdt->lock);
>> +       if (gwdt->pm_status_store & SBSA_GWDT_WCS_EN)
>> +               sbsa_gwdt_start(wdd);
>> +       else
>> +               sbsa_gwdt_stop(wdd);
>
>
> What is the stop here for ?

Thanks ,  I have improved this part. :-)


>
>
>> +       spin_unlock(&gwdt->lock);
>> +
>> +       return 0;
>> +}
>> +#endif
>> +
>> +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 dev_pm_ops sbsa_gwdt_pm_ops = {
>> +       SET_SYSTEM_SLEEP_PM_OPS(sbsa_gwdt_suspend, sbsa_gwdt_resume)
>> +};
>> +
>> +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,
>> +};
>> +
>> +module_platform_driver(sbsa_gwdt_driver);
>> +
>> +MODULE_DESCRIPTION("SBSA Generic Watchdog Driver");
>> +MODULE_AUTHOR("Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>");
>> +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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
  2015-05-18 17:23       ` Guenter Roeck
@ 2015-05-18 17:39         ` Fu Wei
  2015-05-18 20:03         ` Arnd Bergmann
  1 sibling, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-18 17:39 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Arnd Bergmann, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Timur Tabi, Ashwin Chaugule,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet

Hi Guenter,

np, will do so  :-)

On 19 May 2015 at 01:23, Guenter Roeck <linux@roeck-us.net> wrote:
> On Tue, May 19, 2015 at 01:19:22AM +0800, Fu Wei wrote:
>> Hi Arnd,
>>
>> Great thanks for your suggestion :-)
>>
>> feedback inline below
>>
>> On 15 May 2015 at 22:04, Arnd Bergmann <arnd@arndb.de> wrote:
>> > On Friday 15 May 2015 19:24:48 fu.wei@linaro.org wrote:
>> >> +static void watchdog_check_min_max_pretimeout(struct watchdog_device *wdd)
>> >> +{
>> >> +       /*
>> >> +        * Check that we have valid min and max pretimeout 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;
>> >> +       }
>> >> +}
>> >
>> > I would probably just fold this function into the existing
>> > watchdog_check_min_max_timeout() and check both normal and pre-timeout
>> > there.
>>
>> yes, I can do that , and that is good idea
>>
>> >
>> >> +/**
>> >> + * watchdog_init_pretimeout() - initialize the pretimeout field
>> >> + * @pretimeout_parm: pretimeout module parameter
>> >> + * @dev: Device that stores the timeout-sec property
>> >> + *
>> >> + * Initialize the pretimeout field of the watchdog_device struct with either
>> >> + * the pretimeout 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 pretimeout value.
>> >> + *
>> >> + * A zero is returned on success and -EINVAL for failure.
>> >> + */
>> >> +int watchdog_init_pretimeout(struct watchdog_device *wdd,
>> >> +                            unsigned int pretimeout_parm, struct device *dev)
>> >> +{
>> >> +       int ret = 0;
>> >> +       u32 timeouts[2];
>> >> +
>> >> +       watchdog_check_min_max_pretimeout(wdd);
>> >> +
>> >> +       /* try to get the timeout module parameter first */
>> >> +       if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm) &&
>> >> +           pretimeout_parm) {
>> >> +               wdd->pretimeout = pretimeout_parm;
>> >> +               return ret;
>> >> +       }
>> >> +       if (pretimeout_parm)
>> >> +               ret = -EINVAL;
>> >> +
>> >> +       /* try to get the timeout_sec property */
>> >> +       if (!dev || !dev->of_node)
>> >> +               return ret;
>> >> +       ret = of_property_read_u32_array(dev->of_node,
>> >> +                                        "timeout-sec", timeouts, 2);
>> >> +       if (!watchdog_pretimeout_invalid(wdd, timeouts[1]) && timeouts[1])
>> >> +               wdd->pretimeout = timeouts[1];
>> >> +       else
>> >> +               ret = -EINVAL;
>> >> +
>> >> +       return ret;
>> >> +}
>> >> +EXPORT_SYMBOL_GPL(watchdog_init_pretimeout);
>> >
>> > Same here: the function is very similar to the watchdog_init_timeout
>> > function, and it reads the same property, so just do both here.
>> >
>> > The easiest way for that is probably to use of_find_property()
>> > and of_prop_next_u32() to read the two numbers.
>>
>> integrate watchdog_init_pretimeout and watchdog_init_timeout will be a
>> little hard,
>> we may need to change this API to :
>>
>> watchdog_init_timeouts(struct watchdog_device *wdd, unsigned int timeout_parm,
>>                              unsigned int pretimeout_parm, struct device *dev)
>>
>> then we need to update all the watchdog drivers which use this API,
>> maybe we can do this in a individual patchset, after this pretimeout
>> patch is merged.
>>
>> Is that OK  ? :-)  any thought?
>>
> That is what I would recommend.
>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
  2015-05-18 17:23       ` Guenter Roeck
  2015-05-18 17:39         ` Fu Wei
@ 2015-05-18 20:03         ` Arnd Bergmann
  2015-05-18 20:14             ` Guenter Roeck
  1 sibling, 1 reply; 550+ messages in thread
From: Arnd Bergmann @ 2015-05-18 20:03 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Fu Wei, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Timur Tabi, Ashwin Chaugule,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet

On Monday 18 May 2015 10:23:30 Guenter Roeck wrote:
> > 
> > integrate watchdog_init_pretimeout and watchdog_init_timeout will be a
> > little hard,
> > we may need to change this API to :
> > 
> > watchdog_init_timeouts(struct watchdog_device *wdd, unsigned int timeout_parm,
> >                              unsigned int pretimeout_parm, struct device *dev)
> > 
> > then we need to update all the watchdog drivers which use this API,
> > maybe we can do this in a individual patchset, after this pretimeout
> > patch is merged.
> > 
> > Is that OK  ?   any thought?
> > 
> That is what I would recommend.
> 

The API change is fine, but I don't think you need to change all drivers.

Just add a small wrapper function in the header file doing the conversion:

static inline int watchdog_init_timeout(struct watchdog_device *wdd,
                                unsigned int timeout_parm, struct device *dev)
{
	return watchdog_init_timeouts(wdd, timeout_parm, ~0ul, dev);
}

Then you can update the drivers that actually use the pretimeout to
use the new function at some point, and leave all other drivers calling
the wrapper function.

	Arnd

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
  2015-05-18 20:03         ` Arnd Bergmann
@ 2015-05-18 20:14             ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-18 20:14 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Fu Wei, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Timur Tabi, Ashwin Chaugule,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet

On Mon, May 18, 2015 at 10:03:52PM +0200, Arnd Bergmann wrote:
> On Monday 18 May 2015 10:23:30 Guenter Roeck wrote:
> > > 
> > > integrate watchdog_init_pretimeout and watchdog_init_timeout will be a
> > > little hard,
> > > we may need to change this API to :
> > > 
> > > watchdog_init_timeouts(struct watchdog_device *wdd, unsigned int timeout_parm,
> > >                              unsigned int pretimeout_parm, struct device *dev)
> > > 
> > > then we need to update all the watchdog drivers which use this API,
> > > maybe we can do this in a individual patchset, after this pretimeout
> > > patch is merged.
> > > 
> > > Is that OK  ?   any thought?
> > > 
> > That is what I would recommend.
> > 
> 
> The API change is fine, but I don't think you need to change all drivers.
> 
> Just add a small wrapper function in the header file doing the conversion:
> 
> static inline int watchdog_init_timeout(struct watchdog_device *wdd,
>                                 unsigned int timeout_parm, struct device *dev)
> {
> 	return watchdog_init_timeouts(wdd, timeout_parm, ~0ul, dev);
> }
> 
> Then you can update the drivers that actually use the pretimeout to
> use the new function at some point, and leave all other drivers calling
> the wrapper function.
> 
Excellent idea.

Guenter

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
@ 2015-05-18 20:14             ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-18 20:14 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Fu Wei, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet

On Mon, May 18, 2015 at 10:03:52PM +0200, Arnd Bergmann wrote:
> On Monday 18 May 2015 10:23:30 Guenter Roeck wrote:
> > > 
> > > integrate watchdog_init_pretimeout and watchdog_init_timeout will be a
> > > little hard,
> > > we may need to change this API to :
> > > 
> > > watchdog_init_timeouts(struct watchdog_device *wdd, unsigned int timeout_parm,
> > >                              unsigned int pretimeout_parm, struct device *dev)
> > > 
> > > then we need to update all the watchdog drivers which use this API,
> > > maybe we can do this in a individual patchset, after this pretimeout
> > > patch is merged.
> > > 
> > > Is that OK  ?   any thought?
> > > 
> > That is what I would recommend.
> > 
> 
> The API change is fine, but I don't think you need to change all drivers.
> 
> Just add a small wrapper function in the header file doing the conversion:
> 
> static inline int watchdog_init_timeout(struct watchdog_device *wdd,
>                                 unsigned int timeout_parm, struct device *dev)
> {
> 	return watchdog_init_timeouts(wdd, timeout_parm, ~0ul, dev);
> }
> 
> Then you can update the drivers that actually use the pretimeout to
> use the new function at some point, and leave all other drivers calling
> the wrapper function.
> 
Excellent idea.

Guenter
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
@ 2015-05-19  1:12               ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-19  1:12 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Arnd Bergmann, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Timur Tabi, Ashwin Chaugule,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet

Hi Arnd, Guenter,

yes, that is brilliant idea!!
I will try to do so , that solve the compatibility problem , so I
guess we can try this time :-)

On 19 May 2015 at 04:14, Guenter Roeck <linux@roeck-us.net> wrote:
> On Mon, May 18, 2015 at 10:03:52PM +0200, Arnd Bergmann wrote:
>> On Monday 18 May 2015 10:23:30 Guenter Roeck wrote:
>> > >
>> > > integrate watchdog_init_pretimeout and watchdog_init_timeout will be a
>> > > little hard,
>> > > we may need to change this API to :
>> > >
>> > > watchdog_init_timeouts(struct watchdog_device *wdd, unsigned int timeout_parm,
>> > >                              unsigned int pretimeout_parm, struct device *dev)
>> > >
>> > > then we need to update all the watchdog drivers which use this API,
>> > > maybe we can do this in a individual patchset, after this pretimeout
>> > > patch is merged.
>> > >
>> > > Is that OK  ?   any thought?
>> > >
>> > That is what I would recommend.
>> >
>>
>> The API change is fine, but I don't think you need to change all drivers.
>>
>> Just add a small wrapper function in the header file doing the conversion:
>>
>> static inline int watchdog_init_timeout(struct watchdog_device *wdd,
>>                                 unsigned int timeout_parm, struct device *dev)
>> {
>>       return watchdog_init_timeouts(wdd, timeout_parm, ~0ul, dev);
>> }
>>
>> Then you can update the drivers that actually use the pretimeout to
>> use the new function at some point, and leave all other drivers calling
>> the wrapper function.
>>
> Excellent idea.
>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework
@ 2015-05-19  1:12               ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-19  1:12 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Arnd Bergmann, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet

Hi Arnd, Guenter,

yes, that is brilliant idea!!
I will try to do so , that solve the compatibility problem , so I
guess we can try this time :-)

On 19 May 2015 at 04:14, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On Mon, May 18, 2015 at 10:03:52PM +0200, Arnd Bergmann wrote:
>> On Monday 18 May 2015 10:23:30 Guenter Roeck wrote:
>> > >
>> > > integrate watchdog_init_pretimeout and watchdog_init_timeout will be a
>> > > little hard,
>> > > we may need to change this API to :
>> > >
>> > > watchdog_init_timeouts(struct watchdog_device *wdd, unsigned int timeout_parm,
>> > >                              unsigned int pretimeout_parm, struct device *dev)
>> > >
>> > > then we need to update all the watchdog drivers which use this API,
>> > > maybe we can do this in a individual patchset, after this pretimeout
>> > > patch is merged.
>> > >
>> > > Is that OK  ?   any thought?
>> > >
>> > That is what I would recommend.
>> >
>>
>> The API change is fine, but I don't think you need to change all drivers.
>>
>> Just add a small wrapper function in the header file doing the conversion:
>>
>> static inline int watchdog_init_timeout(struct watchdog_device *wdd,
>>                                 unsigned int timeout_parm, struct device *dev)
>> {
>>       return watchdog_init_timeouts(wdd, timeout_parm, ~0ul, dev);
>> }
>>
>> Then you can update the drivers that actually use the pretimeout to
>> use the new function at some point, and leave all other drivers calling
>> the wrapper function.
>>
> Excellent idea.
>
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21  8:32   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-05-21  8:32 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21  8:32   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-05-21  8:32 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v2 1/7] clocksource: export "arch_timer_get_rate" for the other drivers
@ 2015-05-21  8:32     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-05-21  8:32 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v2 1/7] clocksource: export "arch_timer_get_rate" for the other drivers
@ 2015-05-21  8:32     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-05-21  8:32 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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

Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 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

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v2 2/7] Documentation: add sbsa-gwdt.txt documentation
  2015-05-21  8:32   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  (?)
  (?)
@ 2015-05-21  8:32   ` fu.wei
  -1 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-05-21  8:32 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 <fu.wei@linaro.org>
---
 .../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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v2 3/7] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
  2015-05-21  8:32   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                     ` (2 preceding siblings ...)
  (?)
@ 2015-05-21  8:32   ` fu.wei
  2015-05-21  8:45     ` Arnd Bergmann
  -1 siblings, 1 reply; 550+ messages in thread
From: fu.wei @ 2015-05-21  8:32 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 <fu.wei@linaro.org>
---
 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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v2 4/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
  2015-05-21  8:32   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                     ` (3 preceding siblings ...)
  (?)
@ 2015-05-21  8:32   ` fu.wei
  2015-05-21 20:33       ` Suravee Suthikulpanit
  -1 siblings, 1 reply; 550+ messages in thread
From: fu.wei @ 2015-05-21  8:32 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 <fu.wei@linaro.org>
---
 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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
  2015-05-21  8:32   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                     ` (4 preceding siblings ...)
  (?)
@ 2015-05-21  8:32   ` fu.wei
  2015-05-21  9:04     ` Guenter Roeck
                       ` (3 more replies)
  -1 siblings, 4 replies; 550+ messages in thread
From: fu.wei @ 2015-05-21  8:32 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 <fu.wei@linaro.org>
---
 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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21  8:32     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-05-21  8:32 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 <fu.wei@linaro.org>
---
 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 <fu.wei@linaro.org>
+ *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
+ *
+ * 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 <fu.wei@linaro.org>");
+MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21  8:32     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-05-21  8:32 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
+ *         Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
+ *
+ * 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>");
+MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v2 7/7] ACPI: import watchdog info of GTDT into platform device
  2015-05-21  8:32   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                     ` (6 preceding siblings ...)
  (?)
@ 2015-05-21  8:32   ` fu.wei
  2015-05-22 15:38       ` Hanjun Guo
  2015-05-23 19:46       ` Timur Tabi
  -1 siblings, 2 replies; 550+ messages in thread
From: fu.wei @ 2015-05-21  8:32 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 <fu.wei@linaro.org>
---
 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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 3/7] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
  2015-05-21  8:32   ` [PATCH v2 3/7] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts fu.wei
@ 2015-05-21  8:45     ` Arnd Bergmann
  2015-05-21  8:49         ` Fu Wei
  0 siblings, 1 reply; 550+ messages in thread
From: Arnd Bergmann @ 2015-05-21  8:45 UTC (permalink / raw)
  To: fu.wei
  Cc: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, tekkamanninja, graeme.gregory, al.stone,
	hanjun.guo, timur, ashwin.chaugule, linux, vgandhi, wim, jcm,
	leo.duran, corbet, mark.rutland

On Thursday 21 May 2015 16:32:32 fu.wei@linaro.org 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21  8:46     ` Arnd Bergmann
  0 siblings, 0 replies; 550+ messages in thread
From: Arnd Bergmann @ 2015-05-21  8:46 UTC (permalink / raw)
  To: linaro-acpi
  Cc: fu.wei, Suravee.Suthikulpanit, linux-watchdog, devicetree,
	linux-kernel, linux-doc, corbet, jcm, timur, wim, tekkamanninja,
	vgandhi, linux

On Thursday 21 May 2015 16:32:29 fu.wei@linaro.org 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 <arnd@arndb.de>

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21  8:46     ` Arnd Bergmann
  0 siblings, 0 replies; 550+ messages in thread
From: Arnd Bergmann @ 2015-05-21  8:46 UTC (permalink / raw)
  To: linaro-acpi-cunTk1MwBs8s++Sfvej+rw
  Cc: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, corbet-T1hC0tSOHrs,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, linux-0h96xk9xTtrk1uMJSBkQmQ

On Thursday 21 May 2015 16:32:29 fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org 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 <arnd-r2nGTMty4D4@public.gmane.org>

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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 3/7] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
  2015-05-21  8:45     ` Arnd Bergmann
@ 2015-05-21  8:49         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-21  8:49 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Guenter Roeck, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, mark.rutland

Hi Arnd,

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

On 21 May 2015 at 16:45, Arnd Bergmann <arnd@arndb.de> wrote:
> On Thursday 21 May 2015 16:32:32 fu.wei@linaro.org 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 3/7] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
@ 2015-05-21  8:49         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-21  8:49 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Guenter Roeck,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, mark.rutland

Hi Arnd,

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

On 21 May 2015 at 16:45, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
> On Thursday 21 May 2015 16:32:32 fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-21  8:46     ` Arnd Bergmann
@ 2015-05-21  9:01       ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-21  9:01 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Linaro ACPI Mailman List, Suravee Suthikulpanit, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Jon Corbet, Jon Masters,
	Timur Tabi, wim, Wei Fu, vgandhi, Guenter Roeck

Hi Arnd,

Great thanks for your review! :-)

On 21 May 2015 at 16:46, Arnd Bergmann <arnd@arndb.de> wrote:
> On Thursday 21 May 2015 16:32:29 fu.wei@linaro.org 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 <arnd@arndb.de>
>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21  9:01       ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-21  9:01 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Linaro ACPI Mailman List, Suravee Suthikulpanit,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Jon Corbet, Jon Masters,
	Timur Tabi, wim-IQzOog9fTRqzQB+pC5nmwQ, Wei Fu,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, Guenter Roeck

Hi Arnd,

Great thanks for your review! :-)

On 21 May 2015 at 16:46, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
> On Thursday 21 May 2015 16:32:29 fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org 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 <arnd-r2nGTMty4D4@public.gmane.org>
>
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
  2015-05-21  8:32   ` [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework fu.wei
@ 2015-05-21  9:04     ` Guenter Roeck
  2015-05-21 10:05         ` Fu Wei
  2015-05-21 10:11     ` Guenter Roeck
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-05-21  9:04 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, vgandhi, wim, jcm, leo.duran, corbet,
	mark.rutland

On 05/21/2015 01:32 AM, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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 <fu.wei@linaro.org>
> ---

[ ... ]

> +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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
@ 2015-05-21 10:05         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-21 10:05 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, mark.rutland

Hi Guenter,

Thanks for review. :-)
feedback inline below

On 21 May 2015 at 17:04, Guenter Roeck <linux@roeck-us.net> wrote:
> On 05/21/2015 01:32 AM, fu.wei@linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> 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 <fu.wei@linaro.org>
>> ---
>
>
> [ ... ]
>
>> +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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
@ 2015-05-21 10:05         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-21 10:05 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, mark.rutland

Hi Guenter,

Thanks for review. :-)
feedback inline below

On 21 May 2015 at 17:04, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On 05/21/2015 01:32 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>>
>> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>
>> 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> ---
>
>
> [ ... ]
>
>> +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
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
  2015-05-21  8:32   ` [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework fu.wei
  2015-05-21  9:04     ` Guenter Roeck
@ 2015-05-21 10:11     ` Guenter Roeck
  2015-05-21 15:32       ` Guenter Roeck
  2015-05-22  6:30     ` Timo Kokkonen
  3 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-21 10:11 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, vgandhi, wim, jcm, leo.duran, corbet,
	mark.rutland

On 05/21/2015 01:32 AM, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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 <fu.wei@linaro.org>
> ---
>   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);
>


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
  2015-05-21 10:05         ` Fu Wei
  (?)
@ 2015-05-21 10:17         ` Guenter Roeck
  2015-05-21 10:50             ` Fu Wei
  -1 siblings, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-05-21 10:17 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, mark.rutland

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 <linux@roeck-us.net> wrote:
>> On 05/21/2015 01:32 AM, fu.wei@linaro.org wrote:
>>>
>>> From: Fu Wei <fu.wei@linaro.org>
>>>
>>> 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 <fu.wei@linaro.org>
>>> ---
>>
>>
>> [ ... ]
>>
>>> +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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21 10:34       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-21 10:34 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, vgandhi, wim, jcm, leo.duran, corbet,
	mark.rutland

On 05/21/2015 01:32 AM, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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 <fu.wei@linaro.org>
> ---
>   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 <fu.wei@linaro.org>
> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> + *
> + * 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 <fu.wei@linaro.org>");
> +MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
> +MODULE_LICENSE("GPL v2");
>


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21 10:34       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-21 10:34 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	corbet-T1hC0tSOHrs, mark.rutland-5wv7dgnIgG8

On 05/21/2015 01:32 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>   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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
> + *
> + * 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>");
> +MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>");
> +MODULE_LICENSE("GPL v2");
>

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
@ 2015-05-21 10:50             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-21 10:50 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, mark.rutland

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 <linux@roeck-us.net> 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 <linux@roeck-us.net> wrote:
>>>
>>> On 05/21/2015 01:32 AM, fu.wei@linaro.org wrote:
>>>>
>>>>
>>>> From: Fu Wei <fu.wei@linaro.org>
>>>>
>>>> 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 <fu.wei@linaro.org>
>>>> ---
>>>
>>>
>>>
>>> [ ... ]
>>>
>>>> +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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
@ 2015-05-21 10:50             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-21 10:50 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, mark.rutland

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 <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> 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 <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
>>>
>>> On 05/21/2015 01:32 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>>>>
>>>>
>>>> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>>>
>>>> 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>>> ---
>>>
>>>
>>>
>>> [ ... ]
>>>
>>>> +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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-21 10:34       ` Guenter Roeck
  (?)
@ 2015-05-21 11:08       ` Fu Wei
  2015-05-21 15:18           ` Guenter Roeck
  -1 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-05-21 11:08 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter,

Thanks for review :-)

On 21 May 2015 at 18:34, Guenter Roeck <linux@roeck-us.net> wrote:
> On 05/21/2015 01:32 AM, fu.wei@linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> 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 <fu.wei@linaro.org>
>> ---
>>   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 <fu.wei@linaro.org>
>> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>> + *
>> + * 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 <fu.wei@linaro.org>");
>> +MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
>> +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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-21 10:34       ` Guenter Roeck
  (?)
  (?)
@ 2015-05-21 13:09       ` Timur Tabi
  2015-05-21 15:28           ` Guenter Roeck
  -1 siblings, 1 reply; 550+ messages in thread
From: Timur Tabi @ 2015-05-21 13:09 UTC (permalink / raw)
  To: Guenter Roeck, fu.wei, Suravee.Suthikulpanit, linaro-acpi,
	linux-watchdog, devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo,
	ashwin.chaugule, arnd, vgandhi, wim, jcm, leo.duran, corbet,
	mark.rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
  2015-05-21 10:50             ` Fu Wei
  (?)
@ 2015-05-21 13:28             ` Guenter Roeck
  -1 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-21 13:28 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, mark.rutland

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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21 15:18           ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-21 15:18 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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 <linux@roeck-us.net> wrote:
> > On 05/21/2015 01:32 AM, fu.wei@linaro.org wrote:
> >>
> >> From: Fu Wei <fu.wei@linaro.org>
> >>
> >> 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 <fu.wei@linaro.org>
> >> ---
> >>   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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21 15:18           ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-21 15:18 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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 <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> > On 05/21/2015 01:32 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> >>
> >> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> >>
> >> 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> >> ---
> >>   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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21 15:28           ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-21 15:28 UTC (permalink / raw)
  To: Timur Tabi
  Cc: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, hanjun.guo, ashwin.chaugule, arnd,
	vgandhi, wim, jcm, leo.duran, corbet, mark.rutland

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21 15:28           ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-21 15:28 UTC (permalink / raw)
  To: Timur Tabi
  Cc: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	corbet-T1hC0tSOHrs, mark.rutland-5wv7dgnIgG8

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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
@ 2015-05-21 15:32       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-21 15:32 UTC (permalink / raw)
  To: fu.wei
  Cc: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, tekkamanninja, graeme.gregory, al.stone,
	hanjun.guo, timur, ashwin.chaugule, arnd, vgandhi, wim, jcm,
	leo.duran, corbet, mark.rutland

On Thu, May 21, 2015 at 04:32:34PM +0800, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> 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 <fu.wei@linaro.org>
> ---

[ ... ]

>  
> +/* 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
@ 2015-05-21 15:32       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-21 15:32 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A
  Cc: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	corbet-T1hC0tSOHrs, mark.rutland-5wv7dgnIgG8

On Thu, May 21, 2015 at 04:32:34PM +0800, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> 
> 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---

[ ... ]

>  
> +/* 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21 15:42       ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-21 15:42 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland

On 05/21/2015 03:32 AM, fu.wei@linaro.org 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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21 15:42       ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-21 15:42 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8

On 05/21/2015 03:32 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org 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.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-21 15:18           ` Guenter Roeck
  (?)
@ 2015-05-21 15:46           ` Fu Wei
  2015-05-21 15:59             ` Guenter Roeck
  -1 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-05-21 15:46 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter,

Great thanks :-)

On 21 May 2015 at 23:18, Guenter Roeck <linux@roeck-us.net> 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 <linux@roeck-us.net> wrote:
>> > On 05/21/2015 01:32 AM, fu.wei@linaro.org wrote:
>> >>
>> >> From: Fu Wei <fu.wei@linaro.org>
>> >>
>> >> 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 <fu.wei@linaro.org>
>> >> ---
>> >>   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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-21 15:46           ` Fu Wei
@ 2015-05-21 15:59             ` Guenter Roeck
  2015-05-21 16:12                 ` Fu Wei
  0 siblings, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-05-21 15:59 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21 16:12                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-21 16:12 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter,



On 21 May 2015 at 23:59, Guenter Roeck <linux@roeck-us.net> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21 16:12                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-21 16:12 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter,



On 21 May 2015 at 23:59, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21 16:33                   ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-21 16:33 UTC (permalink / raw)
  To: Fu Wei, Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21 16:33                   ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-21 16:33 UTC (permalink / raw)
  To: Fu Wei, Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 4/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
  2015-05-21  8:32   ` [PATCH v2 4/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi fu.wei
@ 2015-05-21 20:33       ` Suravee Suthikulpanit
  0 siblings, 0 replies; 550+ messages in thread
From: Suravee Suthikulpanit @ 2015-05-21 20:33 UTC (permalink / raw)
  To: fu.wei, linaro-acpi, linux-watchdog, devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland

On 5/21/15 03:32, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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 <fu.wei@linaro.org>
> ---
>   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 <Suravee.Suthikulpanit@amd.com>
Acked-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 4/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
@ 2015-05-21 20:33       ` Suravee Suthikulpanit
  0 siblings, 0 replies; 550+ messages in thread
From: Suravee Suthikulpanit @ 2015-05-21 20:33 UTC (permalink / raw)
  To: fu.wei, linaro-acpi, linux-watchdog, devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland

On 5/21/15 03:32, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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 <fu.wei@linaro.org>
> ---
>   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 <Suravee.Suthikulpanit@amd.com>
Acked-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-21  8:32   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
@ 2015-05-21 20:36     ` Suravee Suthikulpanit
  -1 siblings, 0 replies; 550+ messages in thread
From: Suravee Suthikulpanit @ 2015-05-21 20:36 UTC (permalink / raw)
  To: fu.wei, linaro-acpi, linux-watchdog, devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland

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

Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>

Thanks,

Suravee

On 5/21/15 03:32, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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
>

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-21 20:36     ` Suravee Suthikulpanit
  0 siblings, 0 replies; 550+ messages in thread
From: Suravee Suthikulpanit @ 2015-05-21 20:36 UTC (permalink / raw)
  To: fu.wei, linaro-acpi, linux-watchdog, devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland

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

Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>

Thanks,

Suravee

On 5/21/15 03:32, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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
>

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-22  5:05                     ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-22  5:05 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Timur.

On 22 May 2015 at 00:33, Timur Tabi <timur@codeaurora.org> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-22  5:05                     ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-22  5:05 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Timur.

On 22 May 2015 at 00:33, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-21 20:36     ` Suravee Suthikulpanit
  (?)
@ 2015-05-22  5:08     ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-22  5:08 UTC (permalink / raw)
  To: Suravee Suthikulpanit
  Cc: Linaro ACPI Mailman List, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone, Hanjun Guo,
	Timur Tabi, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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
<Suravee.Suthikulpanit@amd.com> wrote:
> For patch 1,4,5,6,and 7, I have tested this on AMD Seattle platform.
>
> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>
> Thanks,
>
> Suravee
>
>
> On 5/21/15 03:32, fu.wei@linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
  2015-05-21 15:32       ` Guenter Roeck
  (?)
@ 2015-05-22  5:17       ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-22  5:17 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter,


On 21 May 2015 at 23:32, Guenter Roeck <linux@roeck-us.net> wrote:
> On Thu, May 21, 2015 at 04:32:34PM +0800, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> 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 <fu.wei@linaro.org>
>> ---
>
> [ ... ]
>
>>
>> +/* 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
  2015-05-21  8:32   ` [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework fu.wei
                       ` (2 preceding siblings ...)
  2015-05-21 15:32       ` Guenter Roeck
@ 2015-05-22  6:30     ` Timo Kokkonen
  2015-05-22  8:23       ` Fu Wei
  3 siblings, 1 reply; 550+ messages in thread
From: Timo Kokkonen @ 2015-05-22  6:30 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland

On 21.05.2015 11:32, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
  2015-05-22  6:30     ` Timo Kokkonen
@ 2015-05-22  8:23       ` Fu Wei
  2015-05-22  8:59         ` Timo Kokkonen
  0 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-05-22  8:23 UTC (permalink / raw)
  To: Timo Kokkonen
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Guenter Roeck, vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland

Hi Timo,


On 22 May 2015 at 14:30, Timo Kokkonen <timo.kokkonen@offcode.fi> wrote:
> On 21.05.2015 11:32, fu.wei@linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
  2015-05-22  8:23       ` Fu Wei
@ 2015-05-22  8:59         ` Timo Kokkonen
  2015-05-22 10:46             ` Fu Wei
  0 siblings, 1 reply; 550+ messages in thread
From: Timo Kokkonen @ 2015-05-22  8:59 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Guenter Roeck, vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland

On 22.05.2015 11:23, Fu Wei wrote:
> Hi Timo,
>
>
> On 22 May 2015 at 14:30, Timo Kokkonen <timo.kokkonen@offcode.fi> wrote:
>> On 21.05.2015 11:32, fu.wei@linaro.org wrote:
>>>
>>> From: Fu Wei <fu.wei@linaro.org>
>>>
>>> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
@ 2015-05-22 10:46             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-22 10:46 UTC (permalink / raw)
  To: Timo Kokkonen
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Guenter Roeck, vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland

Hi Timo,

On 22 May 2015 at 16:59, Timo Kokkonen <timo.kokkonen@offcode.fi> wrote:
> On 22.05.2015 11:23, Fu Wei wrote:
>>
>> Hi Timo,
>>
>>
>> On 22 May 2015 at 14:30, Timo Kokkonen <timo.kokkonen@offcode.fi> wrote:
>>>
>>> On 21.05.2015 11:32, fu.wei@linaro.org wrote:
>>>>
>>>>
>>>> From: Fu Wei <fu.wei@linaro.org>
>>>>
>>>> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
@ 2015-05-22 10:46             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-22 10:46 UTC (permalink / raw)
  To: Timo Kokkonen
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Guenter Roeck, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland

Hi Timo,

On 22 May 2015 at 16:59, Timo Kokkonen <timo.kokkonen-20XrK1Fq8EXHOG6cAo2yLw@public.gmane.org> wrote:
> On 22.05.2015 11:23, Fu Wei wrote:
>>
>> Hi Timo,
>>
>>
>> On 22 May 2015 at 14:30, Timo Kokkonen <timo.kokkonen-20XrK1Fq8EXHOG6cAo2yLw@public.gmane.org> wrote:
>>>
>>> On 21.05.2015 11:32, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>>>>
>>>>
>>>> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>>>
>>>> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
  2015-05-22 10:46             ` Fu Wei
  (?)
@ 2015-05-22 12:14             ` Timo Kokkonen
  2015-05-22 13:37               ` Guenter Roeck
  -1 siblings, 1 reply; 550+ messages in thread
From: Timo Kokkonen @ 2015-05-22 12:14 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Guenter Roeck, vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland

On 22.05.2015 13:46, Fu Wei wrote:
> Hi Timo,
>
> On 22 May 2015 at 16:59, Timo Kokkonen <timo.kokkonen@offcode.fi> wrote:
>> On 22.05.2015 11:23, Fu Wei wrote:
>>>
>>> Hi Timo,
>>>
>>>
>>> On 22 May 2015 at 14:30, Timo Kokkonen <timo.kokkonen@offcode.fi> wrote:
>>>>
>>>> On 21.05.2015 11:32, fu.wei@linaro.org wrote:
>>>>>
>>>>>
>>>>> From: Fu Wei <fu.wei@linaro.org>
>>>>>
>>>>> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
  2015-05-22 10:46             ` Fu Wei
  (?)
  (?)
@ 2015-05-22 13:23             ` Guenter Roeck
  2015-05-22 14:38                 ` Fu Wei
  -1 siblings, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-05-22 13:23 UTC (permalink / raw)
  To: Fu Wei, Timo Kokkonen
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
  2015-05-22 12:14             ` Timo Kokkonen
@ 2015-05-22 13:37               ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-22 13:37 UTC (permalink / raw)
  To: Timo Kokkonen, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 1/7] clocksource: export "arch_timer_get_rate" for the other drivers
  2015-05-21  8:32     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  (?)
@ 2015-05-22 14:02     ` Hanjun Guo
  -1 siblings, 0 replies; 550+ messages in thread
From: Hanjun Guo @ 2015-05-22 14:02 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, timur, ashwin.chaugule,
	arnd, linux, vgandhi, wim, jcm, leo.duran, corbet, mark.rutland

On 2015年05月21日 16:32, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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 <fu.wei@linaro.org>

Other than that,

Acked-by: Hanjun Guo <hanjun.guo@linaro.org>

> ---
>   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)
>   {
>

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 1/7] clocksource: export "arch_timer_get_rate" for the other drivers
  2015-05-21  8:32     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  (?)
  (?)
@ 2015-05-22 14:09     ` Timur Tabi
  2015-05-22 15:16       ` Guenter Roeck
  -1 siblings, 1 reply; 550+ messages in thread
From: Timur Tabi @ 2015-05-22 14:09 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland

fu.wei@linaro.org 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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
@ 2015-05-22 14:38                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-22 14:38 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timo Kokkonen, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Timur Tabi, Ashwin Chaugule,
	Arnd Bergmann, vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland

Hi Guenter.

Sorry for my poor English .
let me explain this :

On 22 May 2015 at 21:23, Guenter Roeck <linux@roeck-us.net> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
@ 2015-05-22 14:38                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-22 14:38 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timo Kokkonen, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter.

Sorry for my poor English .
let me explain this :

On 22 May 2015 at 21:23, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-22 14:50       ` Hanjun Guo
  0 siblings, 0 replies; 550+ messages in thread
From: Hanjun Guo @ 2015-05-22 14:50 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, timur, ashwin.chaugule,
	arnd, linux, vgandhi, wim, jcm, leo.duran, corbet, mark.rutland

On 2015年05月21日 16:32, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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 <fu.wei@linaro.org>
> ---
>   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 <fu.wei@linaro.org>
> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> + *
> + * 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-22 14:50       ` Hanjun Guo
  0 siblings, 0 replies; 550+ messages in thread
From: Hanjun Guo @ 2015-05-22 14:50 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8

On 2015年05月21日 16:32, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>   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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
> + *
> + * 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-22 14:50       ` Hanjun Guo
  (?)
@ 2015-05-22 14:55       ` Arnd Bergmann
  2015-05-22 15:01           ` Guenter Roeck
                           ` (2 more replies)
  -1 siblings, 3 replies; 550+ messages in thread
From: Arnd Bergmann @ 2015-05-22 14:55 UTC (permalink / raw)
  To: Hanjun Guo
  Cc: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, timur, ashwin.chaugule, linux, vgandhi,
	wim, jcm, leo.duran, corbet, mark.rutland

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-22 14:55       ` Arnd Bergmann
@ 2015-05-22 15:01           ` Guenter Roeck
  2015-05-22 16:18         ` Timur Tabi
  2015-05-23 15:08           ` Timur Tabi
  2 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-22 15:01 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Hanjun Guo, fu.wei, Suravee.Suthikulpanit, linaro-acpi,
	linux-watchdog, devicetree, linux-kernel, linux-doc,
	tekkamanninja, graeme.gregory, al.stone, timur, ashwin.chaugule,
	vgandhi, wim, jcm, leo.duran, corbet, mark.rutland

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-22 15:01           ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-22 15:01 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Hanjun Guo, fu.wei-QSEj5FYQhm4dnm+yROfE0A,
	Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	corbet-T1hC0tSOHrs, mark.rutland-5wv7dgnIgG8

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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
  2015-05-22 14:38                 ` Fu Wei
  (?)
@ 2015-05-22 15:05                 ` Guenter Roeck
  2015-05-24 16:17                   ` Fu Wei
  -1 siblings, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-05-22 15:05 UTC (permalink / raw)
  To: Fu Wei
  Cc: Timo Kokkonen, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Timur Tabi, Ashwin Chaugule,
	Arnd Bergmann, vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland

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 <linux@roeck-us.net> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 1/7] clocksource: export "arch_timer_get_rate" for the other drivers
  2015-05-22 14:09     ` Timur Tabi
@ 2015-05-22 15:16       ` Guenter Roeck
  2015-05-22 16:22         ` Timur Tabi
  0 siblings, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-05-22 15:16 UTC (permalink / raw)
  To: Timur Tabi
  Cc: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, hanjun.guo, ashwin.chaugule, arnd,
	vgandhi, wim, jcm, leo.duran, corbet, mark.rutland

On Fri, May 22, 2015 at 09:09:10AM -0500, Timur Tabi wrote:
> fu.wei@linaro.org 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-22 15:18             ` Hanjun Guo
  0 siblings, 0 replies; 550+ messages in thread
From: Hanjun Guo @ 2015-05-22 15:18 UTC (permalink / raw)
  To: Guenter Roeck, Arnd Bergmann
  Cc: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, timur, ashwin.chaugule, vgandhi, wim,
	jcm, leo.duran, corbet, mark.rutland

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-22 15:18             ` Hanjun Guo
  0 siblings, 0 replies; 550+ messages in thread
From: Hanjun Guo @ 2015-05-22 15:18 UTC (permalink / raw)
  To: Guenter Roeck, Arnd Bergmann
  Cc: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	corbet-T1hC0tSOHrs, mark.rutland-5wv7dgnIgG8

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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-22 15:24               ` Arnd Bergmann
  0 siblings, 0 replies; 550+ messages in thread
From: Arnd Bergmann @ 2015-05-22 15:24 UTC (permalink / raw)
  To: linaro-acpi
  Cc: Hanjun Guo, Guenter Roeck, corbet, devicetree, linux-watchdog,
	jcm, timur, linux-doc, linux-kernel, wim, tekkamanninja, vgandhi

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-22 15:24               ` Arnd Bergmann
  0 siblings, 0 replies; 550+ messages in thread
From: Arnd Bergmann @ 2015-05-22 15:24 UTC (permalink / raw)
  To: linaro-acpi-cunTk1MwBs8s++Sfvej+rw
  Cc: Hanjun Guo, Guenter Roeck, corbet-T1hC0tSOHrs,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, wim-IQzOog9fTRqzQB+pC5nmwQ,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ

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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 7/7] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-22 15:38       ` Hanjun Guo
  0 siblings, 0 replies; 550+ messages in thread
From: Hanjun Guo @ 2015-05-22 15:38 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, timur, ashwin.chaugule,
	arnd, linux, vgandhi, wim, jcm, leo.duran, corbet, mark.rutland,
	Catalin Marinas, Will Deacon

+CC Catalin and Will

On 2015年05月21日 16:32, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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 <fu.wei@linaro.org>
> ---
>   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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 7/7] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-22 15:38       ` Hanjun Guo
  0 siblings, 0 replies; 550+ messages in thread
From: Hanjun Guo @ 2015-05-22 15:38 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, Catalin Marinas, Will Deacon

+CC Catalin and Will

On 2015年05月21日 16:32, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>   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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-22 14:55       ` Arnd Bergmann
  2015-05-22 15:01           ` Guenter Roeck
@ 2015-05-22 16:18         ` Timur Tabi
  2015-05-23 15:08           ` Timur Tabi
  2 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-22 16:18 UTC (permalink / raw)
  To: Arnd Bergmann, Hanjun Guo
  Cc: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, ashwin.chaugule, linux, vgandhi, wim,
	jcm, leo.duran, corbet, mark.rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-22 15:01           ` Guenter Roeck
  (?)
  (?)
@ 2015-05-22 16:19           ` Timur Tabi
  -1 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-22 16:19 UTC (permalink / raw)
  To: Guenter Roeck, Arnd Bergmann
  Cc: Hanjun Guo, fu.wei, Suravee.Suthikulpanit, linaro-acpi,
	linux-watchdog, devicetree, linux-kernel, linux-doc,
	tekkamanninja, graeme.gregory, al.stone, ashwin.chaugule,
	vgandhi, wim, jcm, leo.duran, corbet, mark.rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-22 15:24               ` Arnd Bergmann
  (?)
@ 2015-05-22 16:19               ` Timur Tabi
  2015-05-22 20:13                 ` Arnd Bergmann
  -1 siblings, 1 reply; 550+ messages in thread
From: Timur Tabi @ 2015-05-22 16:19 UTC (permalink / raw)
  To: Arnd Bergmann, linaro-acpi
  Cc: Hanjun Guo, Guenter Roeck, corbet, devicetree, linux-watchdog,
	jcm, linux-doc, linux-kernel, wim, tekkamanninja, vgandhi

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 1/7] clocksource: export "arch_timer_get_rate" for the other drivers
  2015-05-22 15:16       ` Guenter Roeck
@ 2015-05-22 16:22         ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-22 16:22 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, hanjun.guo, ashwin.chaugule, arnd,
	vgandhi, wim, jcm, leo.duran, corbet, mark.rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-22 16:19               ` Timur Tabi
@ 2015-05-22 20:13                 ` Arnd Bergmann
  2015-05-22 20:17                   ` Timur Tabi
  0 siblings, 1 reply; 550+ messages in thread
From: Arnd Bergmann @ 2015-05-22 20:13 UTC (permalink / raw)
  To: linaro-acpi
  Cc: Timur Tabi, devicetree, linux-watchdog, corbet, jcm, linux-doc,
	linux-kernel, wim, tekkamanninja, vgandhi, Guenter Roeck

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-22 20:13                 ` Arnd Bergmann
@ 2015-05-22 20:17                   ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-22 20:17 UTC (permalink / raw)
  To: Arnd Bergmann, linaro-acpi
  Cc: devicetree, linux-watchdog, corbet, jcm, linux-doc, linux-kernel,
	wim, tekkamanninja, vgandhi, Guenter Roeck

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-22 15:24               ` Arnd Bergmann
@ 2015-05-23  7:25                 ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-23  7:25 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Linaro ACPI Mailman List, devicetree, linux-watchdog, Jon Corbet,
	Jon Masters, Timur Tabi, linux-doc, linux-kernel, wim, Wei Fu,
	vgandhi, Guenter Roeck

Hi Arnd

Thanks :-)

On 22 May 2015 at 23:24, Arnd Bergmann <arnd@arndb.de> 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
> Linaro-acpi@lists.linaro.org
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-23  7:25                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-23  7:25 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Linaro ACPI Mailman List, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA, Jon Corbet, Jon Masters,
	Timur Tabi, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Wei Fu, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, Guenter Roeck

Hi Arnd

Thanks :-)

On 22 May 2015 at 23:24, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> 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
> Linaro-acpi-cunTk1MwBs8s++Sfvej+rw@public.gmane.org
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-22 15:01           ` Guenter Roeck
                             ` (2 preceding siblings ...)
  (?)
@ 2015-05-23 14:47           ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-23 14:47 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone, Timur Tabi,
	Ashwin Chaugule, vgandhi, wim, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland

Hi Guenter,


On 22 May 2015 at 23:01, Guenter Roeck <linux@roeck-us.net> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-22 14:55       ` Arnd Bergmann
@ 2015-05-23 15:08           ` Timur Tabi
  2015-05-22 16:18         ` Timur Tabi
  2015-05-23 15:08           ` Timur Tabi
  2 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-23 15:08 UTC (permalink / raw)
  To: Arnd Bergmann, Hanjun Guo
  Cc: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, ashwin.chaugule, linux, vgandhi, wim,
	jcm, leo.duran, corbet, mark.rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-23 15:08           ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-23 15:08 UTC (permalink / raw)
  To: Arnd Bergmann, Hanjun Guo
  Cc: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8

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.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-21 15:42       ` Timur Tabi
  (?)
@ 2015-05-23 16:28       ` Fu Wei
  2015-05-23 16:50         ` Fu Wei
  2015-05-23 19:40           ` Timur Tabi
  -1 siblings, 2 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-23 16:28 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Timur,



On 21 May 2015 at 23:42, Timur Tabi <timur@codeaurora.org> wrote:
> On 05/21/2015 03:32 AM, fu.wei@linaro.org 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-23 16:28       ` Fu Wei
@ 2015-05-23 16:50         ` Fu Wei
  2015-05-23 19:40           ` Timur Tabi
  1 sibling, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-23 16:50 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Timur,


On 24 May 2015 at 00:28, Fu Wei <fu.wei@linaro.org> wrote:
> Hi Timur,
>
>
>
> On 21 May 2015 at 23:42, Timur Tabi <timur@codeaurora.org> wrote:
>> On 05/21/2015 03:32 AM, fu.wei@linaro.org 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-23 15:08           ` Timur Tabi
  (?)
@ 2015-05-23 17:26           ` Fu Wei
  2015-05-23 18:35             ` Guenter Roeck
  2015-05-23 18:40             ` Timur Tabi
  -1 siblings, 2 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-23 17:26 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, Guenter Roeck, vgandhi, wim, Jon Masters,
	Leo Duran, Jon Corbet, Mark Rutland

Hi Timur,



On 23 May 2015 at 23:08, Timur Tabi <timur@codeaurora.org> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-23 17:26           ` Fu Wei
@ 2015-05-23 18:35             ` Guenter Roeck
  2015-05-23 18:37               ` Timur Tabi
  2015-05-23 18:40             ` Timur Tabi
  1 sibling, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-05-23 18:35 UTC (permalink / raw)
  To: Fu Wei, Timur Tabi
  Cc: Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, vgandhi, wim, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland

On 05/23/2015 10:26 AM, Fu Wei wrote:
> Hi Timur,
>
>
>
> On 23 May 2015 at 23:08, Timur Tabi <timur@codeaurora.org> 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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-23 18:35             ` Guenter Roeck
@ 2015-05-23 18:37               ` Timur Tabi
  2015-05-23 19:03                 ` Fu Wei
  2015-05-23 19:51                 ` Guenter Roeck
  0 siblings, 2 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-23 18:37 UTC (permalink / raw)
  To: Guenter Roeck, Fu Wei
  Cc: Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, vgandhi, wim, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-23 17:26           ` Fu Wei
  2015-05-23 18:35             ` Guenter Roeck
@ 2015-05-23 18:40             ` Timur Tabi
  2015-05-23 19:14                 ` Fu Wei
  1 sibling, 1 reply; 550+ messages in thread
From: Timur Tabi @ 2015-05-23 18:40 UTC (permalink / raw)
  To: Fu Wei
  Cc: Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, Guenter Roeck, vgandhi, wim, Jon Masters,
	Leo Duran, Jon Corbet, Mark Rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-23 18:37               ` Timur Tabi
@ 2015-05-23 19:03                 ` Fu Wei
  2015-05-23 19:51                 ` Guenter Roeck
  1 sibling, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-23 19:03 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, vgandhi, wim, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland

Hi Timur

On 24 May 2015 at 02:37, Timur Tabi <timur@codeaurora.org> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-23 19:14                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-23 19:14 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, Guenter Roeck, vgandhi, wim, Jon Masters,
	Leo Duran, Jon Corbet, Mark Rutland

Hi Timur

On 24 May 2015 at 02:40, Timur Tabi <timur@codeaurora.org> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-23 19:14                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-23 19:14 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, Guenter Roeck, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland

Hi Timur

On 24 May 2015 at 02:40, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> 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
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-23 19:14                 ` Fu Wei
  (?)
@ 2015-05-23 19:21                 ` Timur Tabi
  -1 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-23 19:21 UTC (permalink / raw)
  To: Fu Wei
  Cc: Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, Guenter Roeck, vgandhi, wim, Jon Masters,
	Leo Duran, Jon Corbet, Mark Rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-23 19:40           ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-23 19:40 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Fu Wei wrote:
> Hi Timur,
>
>
>
> On 21 May 2015 at 23:42, Timur Tabi <timur@codeaurora.org> wrote:
>> On 05/21/2015 03:32 AM, fu.wei@linaro.org 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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-23 19:40           ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-23 19:40 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Fu Wei wrote:
> Hi Timur,
>
>
>
> On 21 May 2015 at 23:42, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
>> On 05/21/2015 03:32 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org 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.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 7/7] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-23 19:46       ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-23 19:46 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland

fu.wei@linaro.org wrote:
> From: Fu Wei<fu.wei@linaro.org>
>
> 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<fu.wei@linaro.org>

Tested-by: Timur Tabi <timur@codeaurora.org>

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 7/7] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-23 19:46       ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-23 19:46 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8

fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> From: Fu Wei<fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> 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<fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Tested-by: Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

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.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-23 18:37               ` Timur Tabi
  2015-05-23 19:03                 ` Fu Wei
@ 2015-05-23 19:51                 ` Guenter Roeck
  2015-05-24  9:58                   ` Fu Wei
  1 sibling, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-05-23 19:51 UTC (permalink / raw)
  To: Timur Tabi, Fu Wei
  Cc: Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, vgandhi, wim, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland

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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-23 20:01             ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-23 20:01 UTC (permalink / raw)
  To: Timur Tabi, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-23 20:01             ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-23 20:01 UTC (permalink / raw)
  To: Timur Tabi, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-23 20:27               ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-23 20:27 UTC (permalink / raw)
  To: Guenter Roeck, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-23 20:27               ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-23 20:27 UTC (permalink / raw)
  To: Guenter Roeck, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-23 20:27               ` Timur Tabi
  (?)
@ 2015-05-23 20:44               ` Guenter Roeck
  2015-05-24 10:50                 ` Fu Wei
  -1 siblings, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-05-23 20:44 UTC (permalink / raw)
  To: Timur Tabi, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-23 19:51                 ` Guenter Roeck
@ 2015-05-24  9:58                   ` Fu Wei
  2015-05-24 14:06                       ` Guenter Roeck
  0 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-05-24  9:58 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, vgandhi, wim, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland

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 <linux@roeck-us.net> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-23 20:01             ` Guenter Roeck
  (?)
  (?)
@ 2015-05-24 10:15             ` Fu Wei
  2015-05-24 14:15                 ` Guenter Roeck
  2015-05-24 15:02               ` Timur Tabi
  -1 siblings, 2 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-24 10:15 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter,

On 24 May 2015 at 04:01, Guenter Roeck <linux@roeck-us.net> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-23 20:44               ` Guenter Roeck
@ 2015-05-24 10:50                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-24 10:50 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter,

On 24 May 2015 at 04:44, Guenter Roeck <linux@roeck-us.net> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 14:06                       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-24 14:06 UTC (permalink / raw)
  To: Fu Wei
  Cc: Timur Tabi, Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, vgandhi, wim, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland

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 <linux@roeck-us.net> 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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 14:06                       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-24 14:06 UTC (permalink / raw)
  To: Fu Wei
  Cc: Timur Tabi, Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland

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 <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> 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

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 14:15                 ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-24 14:15 UTC (permalink / raw)
  To: Fu Wei
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

On 05/24/2015 03:15 AM, Fu Wei wrote:
> Hi Guenter,
>
> On 24 May 2015 at 04:01, Guenter Roeck <linux@roeck-us.net> 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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 14:15                 ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-24 14:15 UTC (permalink / raw)
  To: Fu Wei
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

On 05/24/2015 03:15 AM, Fu Wei wrote:
> Hi Guenter,
>
> On 24 May 2015 at 04:01, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> 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

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-24 10:15             ` Fu Wei
  2015-05-24 14:15                 ` Guenter Roeck
@ 2015-05-24 15:02               ` Timur Tabi
  2015-05-24 16:04                   ` Fu Wei
  1 sibling, 1 reply; 550+ messages in thread
From: Timur Tabi @ 2015-05-24 15:02 UTC (permalink / raw)
  To: Fu Wei, Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 15:06                         ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-24 15:06 UTC (permalink / raw)
  To: Guenter Roeck, Fu Wei
  Cc: Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, vgandhi, wim, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 15:06                         ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-24 15:06 UTC (permalink / raw)
  To: Guenter Roeck, Fu Wei
  Cc: Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland

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.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 15:37                         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-24 15:37 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, vgandhi, wim, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland

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 <linux@roeck-us.net> 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 <linux@roeck-us.net> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 15:37                         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-24 15:37 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Arnd Bergmann, Hanjun Guo, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Ashwin Chaugule, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland

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 <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> 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 <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 15:50                   ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-24 15:50 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter,

Thanks for your feedback

On 24 May 2015 at 22:15, Guenter Roeck <linux@roeck-us.net> wrote:
> On 05/24/2015 03:15 AM, Fu Wei wrote:
>>
>> Hi Guenter,
>>
>> On 24 May 2015 at 04:01, Guenter Roeck <linux@roeck-us.net> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 15:50                   ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-24 15:50 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter,

Thanks for your feedback

On 24 May 2015 at 22:15, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On 05/24/2015 03:15 AM, Fu Wei wrote:
>>
>> Hi Guenter,
>>
>> On 24 May 2015 at 04:01, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 16:04                   ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-24 16:04 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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 <timur@codeaurora.org> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 16:04                   ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-24 16:04 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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 <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 16:13                     ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-24 16:13 UTC (permalink / raw)
  To: Fu Wei
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 16:13                     ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-24 16:13 UTC (permalink / raw)
  To: Fu Wei
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
  2015-05-22 15:05                 ` Guenter Roeck
@ 2015-05-24 16:17                   ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-24 16:17 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timo Kokkonen, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Timur Tabi, Ashwin Chaugule,
	Arnd Bergmann, vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland

Hi Guenter,


On 22 May 2015 at 23:05, Guenter Roeck <linux@roeck-us.net> 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 <linux@roeck-us.net> 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 majordomo@vger.kernel.org
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-24 15:50                   ` Fu Wei
  (?)
@ 2015-05-24 16:23                   ` Guenter Roeck
  2015-05-24 16:47                     ` Fu Wei
  -1 siblings, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-05-24 16:23 UTC (permalink / raw)
  To: Fu Wei
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 16:29                       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-24 16:29 UTC (permalink / raw)
  To: Timur Tabi, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 16:29                       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-24 16:29 UTC (permalink / raw)
  To: Timur Tabi, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-24 16:13                     ` Timur Tabi
  (?)
  (?)
@ 2015-05-24 16:29                     ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-24 16:29 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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 <timur@codeaurora.org> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-24 16:29                       ` Guenter Roeck
  (?)
@ 2015-05-24 16:33                       ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-24 16:33 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter

On 25 May 2015 at 00:29, Guenter Roeck <linux@roeck-us.net> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-24 16:29                       ` Guenter Roeck
  (?)
  (?)
@ 2015-05-24 16:44                       ` Timur Tabi
  2015-05-24 16:50                         ` Guenter Roeck
  2015-05-24 16:52                         ` Fu Wei
  -1 siblings, 2 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-24 16:44 UTC (permalink / raw)
  To: Guenter Roeck, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-24 16:23                   ` Guenter Roeck
@ 2015-05-24 16:47                     ` Fu Wei
  2015-05-24 16:58                         ` Guenter Roeck
  0 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-05-24 16:47 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter,

On 25 May 2015 at 00:23, Guenter Roeck <linux@roeck-us.net> 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 majordomo@vger.kernel.org
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-24 16:44                       ` Timur Tabi
@ 2015-05-24 16:50                         ` Guenter Roeck
  2015-05-24 16:52                         ` Fu Wei
  1 sibling, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-24 16:50 UTC (permalink / raw)
  To: Timur Tabi, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-24 16:44                       ` Timur Tabi
  2015-05-24 16:50                         ` Guenter Roeck
@ 2015-05-24 16:52                         ` Fu Wei
  2015-05-24 17:19                             ` Timur Tabi
  1 sibling, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-05-24 16:52 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Timur

On 25 May 2015 at 00:44, Timur Tabi <timur@codeaurora.org> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 16:58                         ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-24 16:58 UTC (permalink / raw)
  To: Fu Wei
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

On 05/24/2015 09:47 AM, Fu Wei wrote:
> Hi Guenter,
>
> On 25 May 2015 at 00:23, Guenter Roeck <linux@roeck-us.net> 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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 16:58                         ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-24 16:58 UTC (permalink / raw)
  To: Fu Wei
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

On 05/24/2015 09:47 AM, Fu Wei wrote:
> Hi Guenter,
>
> On 25 May 2015 at 00:23, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> 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

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 17:04                           ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-24 17:04 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter,



On 25 May 2015 at 00:58, Guenter Roeck <linux@roeck-us.net> wrote:
> On 05/24/2015 09:47 AM, Fu Wei wrote:
>>
>> Hi Guenter,
>>
>> On 25 May 2015 at 00:23, Guenter Roeck <linux@roeck-us.net> 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 majordomo@vger.kernel.org
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 17:04                           ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-24 17:04 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter,



On 25 May 2015 at 00:58, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On 05/24/2015 09:47 AM, Fu Wei wrote:
>>
>> Hi Guenter,
>>
>> On 25 May 2015 at 00:23, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> 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 majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 17:19                             ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-24 17:19 UTC (permalink / raw)
  To: Fu Wei
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 17:19                             ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-24 17:19 UTC (permalink / raw)
  To: Fu Wei
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-24 17:19                             ` Timur Tabi
  (?)
@ 2015-05-24 17:23                             ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-24 17:23 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Timur,

On 25 May 2015 at 01:19, Timur Tabi <timur@codeaurora.org> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 17:32                               ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-24 17:32 UTC (permalink / raw)
  To: Timur Tabi, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-24 17:32                               ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-24 17:32 UTC (permalink / raw)
  To: Timur Tabi, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-24 17:32                               ` Guenter Roeck
  (?)
@ 2015-05-24 17:47                               ` Timur Tabi
  2015-05-25  2:03                                 ` Fu Wei
  -1 siblings, 1 reply; 550+ messages in thread
From: Timur Tabi @ 2015-05-24 17:47 UTC (permalink / raw)
  To: Guenter Roeck, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-24 17:32                               ` Guenter Roeck
  (?)
  (?)
@ 2015-05-25  2:00                               ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-25  2:00 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi, Guenter,



On 25 May 2015 at 01:32, Guenter Roeck <linux@roeck-us.net> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-24 17:47                               ` Timur Tabi
@ 2015-05-25  2:03                                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-25  2:03 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter,


On 25 May 2015 at 01:47, Timur Tabi <timur@codeaurora.org> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
@ 2015-05-25  3:09         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-25  3:09 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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 <linux@roeck-us.net> wrote:
> On Thu, May 21, 2015 at 04:32:34PM +0800, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> 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 <fu.wei@linaro.org>
>> ---
>
> [ ... ]
>
>>
>> +/* 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework
@ 2015-05-25  3:09         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-25  3:09 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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 <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On Thu, May 21, 2015 at 04:32:34PM +0800, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>
>> 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> ---
>
> [ ... ]
>
>>
>> +/* 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-25  3:43             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-25  3:43 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter,

On 21 May 2015 at 23:28, Guenter Roeck <linux@roeck-us.net> 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 majordomo@vger.kernel.org
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-25  3:43             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-25  3:43 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Guenter,

On 21 May 2015 at 23:28, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> 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 majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-25  3:46               ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-25  3:46 UTC (permalink / raw)
  To: Fu Wei, Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-25  3:46               ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-25  3:46 UTC (permalink / raw)
  To: Fu Wei, Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

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.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-25  4:11                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-25  4:11 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Timur.


On 25 May 2015 at 11:46, Timur Tabi <timur@codeaurora.org> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-25  4:11                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-25  4:11 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland

Hi Timur.


On 25 May 2015 at 11:46, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v3 0/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-25 10:03   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-05-25 10:03 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patchset:
    (1)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.

    (2)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".

    (3)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, do panic to save system context;
        e.Support getting timeout and pretimeout from parameter and FDT
          at the driver init stage.

    (4)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:
v3: Delete "export arch_timer_get_rate" patch.
    Driver back to use arch_timer_get_cntfrq.
    Improve watchdog_init_timeouts function and update relevant documentation.
    Improve watchdog_timeout_invalid and watchdog_pretimeout_invalid.
    Improve foundation-v8.dts: delete the unnecessary tag of device node.
    Remove "ARM64 || COMPILE_TEST" from Kconfig.
    Add comments in arch/arm64/kernel/acpi.c
    Fix typoes and incorrect comments.

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 (6):
  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: introdouce "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     |  47 +-
 arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi       |  11 +
 arch/arm64/boot/dts/arm/foundation-v8.dts          |  10 +
 arch/arm64/kernel/acpi.c                           | 145 +++++++
 drivers/watchdog/Kconfig                           |  11 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/sbsa_gwdt.c                       | 474 +++++++++++++++++++++
 drivers/watchdog/watchdog_core.c                   |  95 +++--
 drivers/watchdog/watchdog_dev.c                    |  50 +++
 include/linux/watchdog.h                           |  33 +-
 11 files changed, 880 insertions(+), 33 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

-- 
1.9.1


^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v3 0/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-25 10:03   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-05-25 10:03 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

This patchset:
    (1)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.

    (2)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".

    (3)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, do panic to save system context;
        e.Support getting timeout and pretimeout from parameter and FDT
          at the driver init stage.

    (4)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:
v3: Delete "export arch_timer_get_rate" patch.
    Driver back to use arch_timer_get_cntfrq.
    Improve watchdog_init_timeouts function and update relevant documentation.
    Improve watchdog_timeout_invalid and watchdog_pretimeout_invalid.
    Improve foundation-v8.dts: delete the unnecessary tag of device node.
    Remove "ARM64 || COMPILE_TEST" from Kconfig.
    Add comments in arch/arm64/kernel/acpi.c
    Fix typoes and incorrect comments.

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 (6):
  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: introdouce "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     |  47 +-
 arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi       |  11 +
 arch/arm64/boot/dts/arm/foundation-v8.dts          |  10 +
 arch/arm64/kernel/acpi.c                           | 145 +++++++
 drivers/watchdog/Kconfig                           |  11 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/sbsa_gwdt.c                       | 474 +++++++++++++++++++++
 drivers/watchdog/watchdog_core.c                   |  95 +++--
 drivers/watchdog/watchdog_dev.c                    |  50 +++
 include/linux/watchdog.h                           |  33 +-
 11 files changed, 880 insertions(+), 33 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v3 1/6] Documentation: add sbsa-gwdt.txt documentation
@ 2015-05-25 10:03     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-05-25 10:03 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 .../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..010e5c4
--- /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@2a440000 {
+	compatible = "arm,sbsa-gwdt";
+	reg = <0x0 0x2a440000 0 0x10000>,
+	      <0x0 0x2a450000 0 0x10000>;
+	reg-names = "control", "refresh";
+	interrupts = <0 27 4>;
+	interrupt-names = "ws0";
+	timeout-sec = <10 5>;
+};
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v3 1/6] Documentation: add sbsa-gwdt.txt documentation
@ 2015-05-25 10:03     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-05-25 10:03 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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

Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 .../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..010e5c4
--- /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@2a440000 {
+	compatible = "arm,sbsa-gwdt";
+	reg = <0x0 0x2a440000 0 0x10000>,
+	      <0x0 0x2a450000 0 0x10000>;
+	reg-names = "control", "refresh";
+	interrupts = <0 27 4>;
+	interrupt-names = "ws0";
+	timeout-sec = <10 5>;
+};
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v3 2/6] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
  2015-05-25 10:03   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  (?)
  (?)
@ 2015-05-25 10:03   ` fu.wei
  -1 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-05-25 10:03 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 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..962a07e 100644
--- a/arch/arm64/boot/dts/arm/foundation-v8.dts
+++ b/arch/arm64/boot/dts/arm/foundation-v8.dts
@@ -237,4 +237,14 @@
 			};
 		};
 	};
+	watchdog@2a440000 {
+		compatible = "arm,sbsa-gwdt";
+		reg = <0x0 0x2a440000 0 0x10000>,
+			<0x0 0x2a450000 0 0x10000>;
+		reg-names = "control",
+			"refresh";
+		interrupts = <0 27 4>;
+		interrupt-names = "ws0";
+		timeout-sec = <10 5>;
+	};
 };
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v3 3/6] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
  2015-05-25 10:03   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                     ` (2 preceding siblings ...)
  (?)
@ 2015-05-25 10:03   ` fu.wei
  -1 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-05-25 10:03 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v3 4/6] Watchdog: introdouce "pretimeout" into framework
  2015-05-25 10:03   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                     ` (3 preceding siblings ...)
  (?)
@ 2015-05-25 10:03   ` fu.wei
  2015-05-25 19:28       ` Guenter Roeck
  -1 siblings, 1 reply; 550+ messages in thread
From: fu.wei @ 2015-05-25 10:03 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 drivers are going to use this: ARM SBSA Generic Watchdog

Acked-by: Arnd Bergmann <arnd@arndb.de>
Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 Documentation/watchdog/watchdog-kernel-api.txt | 47 +++++++++++--
 drivers/watchdog/watchdog_core.c               | 95 +++++++++++++++++++-------
 drivers/watchdog/watchdog_dev.c                | 50 ++++++++++++++
 include/linux/watchdog.h                       | 33 ++++++++-
 4 files changed, 192 insertions(+), 33 deletions(-)

diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index a0438f3..95b355d 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.
@@ -219,8 +236,28 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
                                   unsigned int timeout_parm, struct device *dev);
 
 The watchdog_init_timeout function allows you to initialize the timeout field
-using the module timeout parameter or by retrieving the timeout-sec property from
-the device tree (if the module timeout parameter is invalid). Best practice is
-to set the default timeout value as timeout value in the watchdog_device and
-then use this function to set the user "preferred" timeout value.
+using the module timeout parameter or by retrieving the first element of
+the timeout-sec property from the device tree (if the module timeout parameter
+is invalid). Best practice is to set the default timeout value as timeout value
+in the watchdog_device and then use this function to set the user "preferred"
+timeout value.
+This routine returns zero on success and a negative errno code for failure.
+
+Some watchdog timers have two stage of timeouts(timeout and pretimeout),
+to initialize the timeout and pretimeout fields at the same time, the following
+function can be used:
+
+extern int watchdog_init_timeouts(struct watchdog_device *wdd,
+                                  unsigned int pretimeout_parm,
+                                  unsigned int timeout_parm,
+                                  struct device *dev);
+
+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).
+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.
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index cec9b55..85b1d33 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -43,60 +43,105 @@
 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,
+			   struct device *dev)
 {
-	unsigned int t = 0;
-	int ret = 0;
+	u32 timeouts[2];
+	int ret = 0, length = 0;
 
-	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;
+		else
+			ret = -EINVAL;
 	}
-	if (timeout_parm)
+
+	if (timeout_parm) {
+		if (!watchdog_timeout_invalid(wdd, timeout_parm)) {
+			wdd->timeout = timeout_parm;
+			return ret;
+		}
 		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
+
+	of_find_property(dev->of_node, "timeout-sec", &length);
+	if (length > 0 && length <= sizeof(u32) * 2) {
+		of_property_read_u32_array(dev->of_node,
+					   "timeout-sec", timeouts,
+					   length / sizeof(u32));
+		if (length == 2) {
+			if (!watchdog_pretimeout_invalid(wdd, timeouts[1]) &&
+			    timeouts[1])
+				wdd->pretimeout = timeouts[1];
+			else
+				ret = -EINVAL;
+		}
+
+		if (!watchdog_timeout_invalid(wdd, timeouts[0]) && timeouts[0])
+			wdd->timeout = timeouts[0];
+		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 +164,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..a65a9b0 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,24 @@ 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:
+		/* pretimeout == 0 means that we don't know 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..e776e1d 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;
@@ -117,7 +125,17 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
 static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
 {
 	return ((wdd->max_timeout != 0) &&
-		(t < wdd->min_timeout || t > wdd->max_timeout));
+		(t < wdd->min_timeout || t > wdd->max_timeout ||
+			t < wdd->pretimeout));
+}
+
+/* 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 ||
+			(wdd->timeout != 0 && t > wdd->timeout)));
 }
 
 /* Use the following functions to manipulate watchdog driver specific data */
@@ -132,11 +150,20 @@ 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,
+				  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, dev);
+}
+
 #ifdef CONFIG_HARDLOCKUP_DETECTOR
 void watchdog_nmi_disable_all(void);
 void watchdog_nmi_enable_all(void);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-25 10:03   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                     ` (4 preceding siblings ...)
  (?)
@ 2015-05-25 10:03   ` fu.wei
  2015-05-25 19:39       ` Guenter Roeck
  2015-05-26 16:50     ` Timur Tabi
  -1 siblings, 2 replies; 550+ messages in thread
From: fu.wei @ 2015-05-25 10:03 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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, the interrupt routine run panic to save
system context.

Acked-by: Arnd Bergmann <arnd@arndb.de>
Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 drivers/watchdog/Kconfig     |  11 +
 drivers/watchdog/Makefile    |   1 +
 drivers/watchdog/sbsa_gwdt.c | 474 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 486 insertions(+)
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e5e7c55..554f18a 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -152,6 +152,17 @@ 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 ARM64
+	depends on ARM_ARCH_TIMER
+	select WATCHDOG_CORE
+	help
+	  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.
+	  More details: ARM 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..0d1aff1
--- /dev/null
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -0,0 +1,474 @@
+/*
+ * SBSA(Server Base System Architecture) Generic Watchdog driver
+ *
+ * Copyright (c) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei@linaro.org>
+ *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
+ *
+ * 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: ARM DEN0029B - Server Base System Architecture (SBSA)
+ *
+ * Kernel/API:                         P---------| pretimeout
+ *               |-------------------------------T timeout
+ * SBSA GWDT:                          P--WOR---WS1 pretimeout
+ *               |-------WCV----------WS0~~~~~~~~T timeout
+ */
+
+#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>
+#include <asm/arch_timer.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_param;
+module_param(timeout_param, uint, 0);
+MODULE_PARM_DESC(timeout_param,
+		 "Watchdog timeout in seconds. (>=0, default="
+		 __MODULE_STRING(DEFAULT_TIMEOUT) ")");
+
+static unsigned int max_timeout_param = UINT_MAX;
+module_param(max_timeout_param, uint, 0);
+MODULE_PARM_DESC(max_timeout_param,
+		 "Watchdog max timeout in seconds. (>=0, default="
+		 __MODULE_STRING(UINT_MAX) ")");
+
+static unsigned int pretimeout_param;
+module_param(pretimeout_param, uint, 0);
+MODULE_PARM_DESC(pretimeout_param,
+		 "Watchdog pretimeout in seconds. (>=0, default="
+		 __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
+
+static unsigned int max_pretimeout_param = U32_MAX;
+module_param(max_pretimeout_param, uint, 0);
+MODULE_PARM_DESC(max_pretimeout_param,
+		 "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) ")");
+
+/*
+ * help functions for accessing 32bit registers of SBSA Generic Watchdog
+ */
+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 functions 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 update the 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();
+
+	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;
+
+	/*
+	 * Get the frequency of system counter from
+	 * the cp15 interface of ARM Generic timer
+	 */
+	clk = arch_timer_get_cntfrq();
+	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(cf_base))
+		return PTR_ERR(cf_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_param);
+	wdd->min_timeout = 1;
+	do_div(first_period_max, clk);
+	wdd->max_timeout = min((uint)(wdd->pretimeout + first_period_max),
+			       max_timeout_param);
+
+	wdd->pretimeout = DEFAULT_PRETIMEOUT;
+	wdd->timeout = DEFAULT_TIMEOUT;
+	watchdog_init_timeouts(wdd, pretimeout_param, timeout_param, 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 <fu.wei@linaro.org>");
+MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
  2015-05-25 10:03   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                     ` (5 preceding siblings ...)
  (?)
@ 2015-05-25 10:03   ` fu.wei
  2015-05-26  8:28     ` Hanjun Guo
  2015-05-26 12:28       ` Will Deacon
  -1 siblings, 2 replies; 550+ messages in thread
From: fu.wei @ 2015-05-25 10:03 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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.

Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Tested-by: Timur Tabi <timur@codeaurora.org>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 arch/arm64/kernel/acpi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 145 insertions(+)

diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 8b83955..c95deec 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,147 @@ 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_debug("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;
+	}
+
+	/*
+	 * Add a platform device named "sbsa-gwdt" to match the platform driver.
+	 * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
+	 * The platform driver can get device info below by matching this name.
+	 */
+	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;
+
+	/*
+	 * According to SBSA specification the size of refresh and control
+	 * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
+	 */
+	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_warn("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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 4/6] Watchdog: introdouce "pretimeout" into framework
@ 2015-05-25 19:28       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-25 19:28 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, vgandhi, wim, jcm, leo.duran, corbet,
	mark.rutland, catalin.marinas, will.deacon

On 05/25/2015 03:03 AM, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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 drivers are going to use this: ARM SBSA Generic Watchdog
>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---

Comments inline.

Thanks,
Guenter

>   Documentation/watchdog/watchdog-kernel-api.txt | 47 +++++++++++--
>   drivers/watchdog/watchdog_core.c               | 95 +++++++++++++++++++-------
>   drivers/watchdog/watchdog_dev.c                | 50 ++++++++++++++
>   include/linux/watchdog.h                       | 33 ++++++++-
>   4 files changed, 192 insertions(+), 33 deletions(-)
>
> diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
> index a0438f3..95b355d 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.
> @@ -219,8 +236,28 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
>                                     unsigned int timeout_parm, struct device *dev);
>
>   The watchdog_init_timeout function allows you to initialize the timeout field
> -using the module timeout parameter or by retrieving the timeout-sec property from
> -the device tree (if the module timeout parameter is invalid). Best practice is
> -to set the default timeout value as timeout value in the watchdog_device and
> -then use this function to set the user "preferred" timeout value.
> +using the module timeout parameter or by retrieving the first element of
> +the timeout-sec property from the device tree (if the module timeout parameter
> +is invalid). Best practice is to set the default timeout value as timeout value
> +in the watchdog_device and then use this function to set the user "preferred"
> +timeout value.
> +This routine returns zero on success and a negative errno code for failure.
> +
> +Some watchdog timers have two stage of timeouts(timeout and pretimeout),
> +to initialize the timeout and pretimeout fields at the same time, the following
> +function can be used:
> +
> +extern int watchdog_init_timeouts(struct watchdog_device *wdd,
> +                                  unsigned int pretimeout_parm,
> +                                  unsigned int timeout_parm,
> +                                  struct device *dev);
> +
> +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).
> +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.
> diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
> index cec9b55..85b1d33 100644
> --- a/drivers/watchdog/watchdog_core.c
> +++ b/drivers/watchdog/watchdog_core.c
> @@ -43,60 +43,105 @@
>   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;

I think you should rather update max_pretimeout in this case, to
be < max_timeout.

> +	}
>   }
>
>   /**
> - * 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,
> +			   struct device *dev)
>   {
> -	unsigned int t = 0;
> -	int ret = 0;
> +	u32 timeouts[2];
> +	int ret = 0, length = 0;

Please keep the longest variable chain first.

>
> -	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;
> +		else
> +			ret = -EINVAL;
>   	}
> -	if (timeout_parm)
> +
> +	if (timeout_parm) {
> +		if (!watchdog_timeout_invalid(wdd, timeout_parm)) {
> +			wdd->timeout = timeout_parm;
> +			return ret;

This would return -EINVAL if timeout is correct but pretimeout isn't.
How about this ?

		if (!ret)
			return 0;

> +		}
>   		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
> +
> +	of_find_property(dev->of_node, "timeout-sec", &length);
> +	if (length > 0 && length <= sizeof(u32) * 2) {
> +		of_property_read_u32_array(dev->of_node,
> +					   "timeout-sec", timeouts,
> +					   length / sizeof(u32));
> +		if (length == 2) {
> +			if (!watchdog_pretimeout_invalid(wdd, timeouts[1]) &&
> +			    timeouts[1])
> +				wdd->pretimeout = timeouts[1];

A pretimeout of 0 is a valid timeout, so why not use it ?

> +			else
> +				ret = -EINVAL;

and why is pretimeout == 0 considered invalid here ?

> +		}
> +
> +		if (!watchdog_timeout_invalid(wdd, timeouts[0]) && timeouts[0])
> +			wdd->timeout = timeouts[0];
> +		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 +164,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..a65a9b0 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,24 @@ 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

s/keep's/keeps/

> +		 * possible that it takes the new timeout)

new pretimeout

> +		 */
> +		watchdog_ping(wdd);
> +		/* Fall */
> +	case WDIOC_GETPRETIMEOUT:
> +		/* pretimeout == 0 means that we don't know the pretimeout */
> +		if (wdd->pretimeout == 0)
> +			return -EOPNOTSUPP;

pretimeout == 0 is a valid parameter, though, and means that it is disabled.
So we can not return -EOPNOTSUPP here.

Either this code needs to explicitly check for pretimeout support,
or just return 0 if it is disabled / not supported.

> +		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..e776e1d 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;
> @@ -117,7 +125,17 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
>   static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
>   {
>   	return ((wdd->max_timeout != 0) &&
> -		(t < wdd->min_timeout || t > wdd->max_timeout));
> +		(t < wdd->min_timeout || t > wdd->max_timeout ||
> +			t < wdd->pretimeout));

	< or <= ?

timeout == pretimeout implies that the pretimeout would expire immediately,
which doesn't seem to make much sense.

> +}
> +
> +/* 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 ||
> +			(wdd->timeout != 0 && t > wdd->timeout)));

	> or >= ?

>   }
>
>   /* Use the following functions to manipulate watchdog driver specific data */
> @@ -132,11 +150,20 @@ 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,
> +				  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, dev);
> +}
> +
>   #ifdef CONFIG_HARDLOCKUP_DETECTOR
>   void watchdog_nmi_disable_all(void);
>   void watchdog_nmi_enable_all(void);
>


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 4/6] Watchdog: introdouce "pretimeout" into framework
@ 2015-05-25 19:28       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-25 19:28 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	corbet-T1hC0tSOHrs, mark.rutland-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8

On 05/25/2015 03:03 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> 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 drivers are going to use this: ARM SBSA Generic Watchdog
>
> Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
> Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---

Comments inline.

Thanks,
Guenter

>   Documentation/watchdog/watchdog-kernel-api.txt | 47 +++++++++++--
>   drivers/watchdog/watchdog_core.c               | 95 +++++++++++++++++++-------
>   drivers/watchdog/watchdog_dev.c                | 50 ++++++++++++++
>   include/linux/watchdog.h                       | 33 ++++++++-
>   4 files changed, 192 insertions(+), 33 deletions(-)
>
> diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
> index a0438f3..95b355d 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.
> @@ -219,8 +236,28 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
>                                     unsigned int timeout_parm, struct device *dev);
>
>   The watchdog_init_timeout function allows you to initialize the timeout field
> -using the module timeout parameter or by retrieving the timeout-sec property from
> -the device tree (if the module timeout parameter is invalid). Best practice is
> -to set the default timeout value as timeout value in the watchdog_device and
> -then use this function to set the user "preferred" timeout value.
> +using the module timeout parameter or by retrieving the first element of
> +the timeout-sec property from the device tree (if the module timeout parameter
> +is invalid). Best practice is to set the default timeout value as timeout value
> +in the watchdog_device and then use this function to set the user "preferred"
> +timeout value.
> +This routine returns zero on success and a negative errno code for failure.
> +
> +Some watchdog timers have two stage of timeouts(timeout and pretimeout),
> +to initialize the timeout and pretimeout fields at the same time, the following
> +function can be used:
> +
> +extern int watchdog_init_timeouts(struct watchdog_device *wdd,
> +                                  unsigned int pretimeout_parm,
> +                                  unsigned int timeout_parm,
> +                                  struct device *dev);
> +
> +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).
> +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.
> diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
> index cec9b55..85b1d33 100644
> --- a/drivers/watchdog/watchdog_core.c
> +++ b/drivers/watchdog/watchdog_core.c
> @@ -43,60 +43,105 @@
>   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;

I think you should rather update max_pretimeout in this case, to
be < max_timeout.

> +	}
>   }
>
>   /**
> - * 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,
> +			   struct device *dev)
>   {
> -	unsigned int t = 0;
> -	int ret = 0;
> +	u32 timeouts[2];
> +	int ret = 0, length = 0;

Please keep the longest variable chain first.

>
> -	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;
> +		else
> +			ret = -EINVAL;
>   	}
> -	if (timeout_parm)
> +
> +	if (timeout_parm) {
> +		if (!watchdog_timeout_invalid(wdd, timeout_parm)) {
> +			wdd->timeout = timeout_parm;
> +			return ret;

This would return -EINVAL if timeout is correct but pretimeout isn't.
How about this ?

		if (!ret)
			return 0;

> +		}
>   		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
> +
> +	of_find_property(dev->of_node, "timeout-sec", &length);
> +	if (length > 0 && length <= sizeof(u32) * 2) {
> +		of_property_read_u32_array(dev->of_node,
> +					   "timeout-sec", timeouts,
> +					   length / sizeof(u32));
> +		if (length == 2) {
> +			if (!watchdog_pretimeout_invalid(wdd, timeouts[1]) &&
> +			    timeouts[1])
> +				wdd->pretimeout = timeouts[1];

A pretimeout of 0 is a valid timeout, so why not use it ?

> +			else
> +				ret = -EINVAL;

and why is pretimeout == 0 considered invalid here ?

> +		}
> +
> +		if (!watchdog_timeout_invalid(wdd, timeouts[0]) && timeouts[0])
> +			wdd->timeout = timeouts[0];
> +		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 +164,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..a65a9b0 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,24 @@ 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

s/keep's/keeps/

> +		 * possible that it takes the new timeout)

new pretimeout

> +		 */
> +		watchdog_ping(wdd);
> +		/* Fall */
> +	case WDIOC_GETPRETIMEOUT:
> +		/* pretimeout == 0 means that we don't know the pretimeout */
> +		if (wdd->pretimeout == 0)
> +			return -EOPNOTSUPP;

pretimeout == 0 is a valid parameter, though, and means that it is disabled.
So we can not return -EOPNOTSUPP here.

Either this code needs to explicitly check for pretimeout support,
or just return 0 if it is disabled / not supported.

> +		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..e776e1d 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;
> @@ -117,7 +125,17 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
>   static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
>   {
>   	return ((wdd->max_timeout != 0) &&
> -		(t < wdd->min_timeout || t > wdd->max_timeout));
> +		(t < wdd->min_timeout || t > wdd->max_timeout ||
> +			t < wdd->pretimeout));

	< or <= ?

timeout == pretimeout implies that the pretimeout would expire immediately,
which doesn't seem to make much sense.

> +}
> +
> +/* 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 ||
> +			(wdd->timeout != 0 && t > wdd->timeout)));

	> or >= ?

>   }
>
>   /* Use the following functions to manipulate watchdog driver specific data */
> @@ -132,11 +150,20 @@ 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,
> +				  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, dev);
> +}
> +
>   #ifdef CONFIG_HARDLOCKUP_DETECTOR
>   void watchdog_nmi_disable_all(void);
>   void watchdog_nmi_enable_all(void);
>

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-25 19:39       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-25 19:39 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, vgandhi, wim, jcm, leo.duran, corbet,
	mark.rutland, catalin.marinas, will.deacon

On 05/25/2015 03:03 AM, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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, the interrupt routine run panic to save
> system context.
>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---

Comments inline.

Thanks,
Guenter

>   drivers/watchdog/Kconfig     |  11 +
>   drivers/watchdog/Makefile    |   1 +
>   drivers/watchdog/sbsa_gwdt.c | 474 +++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 486 insertions(+)
>   create mode 100644 drivers/watchdog/sbsa_gwdt.c
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index e5e7c55..554f18a 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -152,6 +152,17 @@ 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 ARM64
> +	depends on ARM_ARCH_TIMER
> +	select WATCHDOG_CORE
> +	help
> +	  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.
> +	  More details: ARM 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..0d1aff1
> --- /dev/null
> +++ b/drivers/watchdog/sbsa_gwdt.c
> @@ -0,0 +1,474 @@
> +/*
> + * SBSA(Server Base System Architecture) Generic Watchdog driver
> + *
> + * Copyright (c) 2015, Linaro Ltd.
> + * Author: Fu Wei <fu.wei@linaro.org>
> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> + *
> + * 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: ARM DEN0029B - Server Base System Architecture (SBSA)
> + *
> + * Kernel/API:                         P---------| pretimeout
> + *               |-------------------------------T timeout
> + * SBSA GWDT:                          P--WOR---WS1 pretimeout
> + *               |-------WCV----------WS0~~~~~~~~T timeout
> + */
> +
> +#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>
> +#include <asm/arch_timer.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*/

That is a bit low for a default. Is that on purpose ?
Most drivers use 30 or 60 seconds.

> +#define DEFAULT_PRETIMEOUT	5  /* seconds, the 2nd watch period*/
> +
> +static unsigned int timeout_param;
> +module_param(timeout_param, uint, 0);
> +MODULE_PARM_DESC(timeout_param,
> +		 "Watchdog timeout in seconds. (>=0, default="
> +		 __MODULE_STRING(DEFAULT_TIMEOUT) ")");
> +
Why _param in the module parameter names ? Seems to be redundant.

> +static unsigned int max_timeout_param = UINT_MAX;
> +module_param(max_timeout_param, uint, 0);
> +MODULE_PARM_DESC(max_timeout_param,
> +		 "Watchdog max timeout in seconds. (>=0, default="
> +		 __MODULE_STRING(UINT_MAX) ")");
> +

Why do we want or need this parameter and max_pretimeout ? Those
are determined by the hardware.

> +static unsigned int pretimeout_param;
> +module_param(pretimeout_param, uint, 0);
> +MODULE_PARM_DESC(pretimeout_param,
> +		 "Watchdog pretimeout in seconds. (>=0, default="
> +		 __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
> +
> +static unsigned int max_pretimeout_param = U32_MAX;
> +module_param(max_pretimeout_param, uint, 0);
> +MODULE_PARM_DESC(max_pretimeout_param,
> +		 "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) ")");
> +
> +/*
> + * help functions for accessing 32bit registers of SBSA Generic Watchdog
> + */
> +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 functions 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 update the 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);
> +}
> +

After understanding the watchdog a bit better now, I think you should drop
those updates and set
	min_timeout = 1
	max_timeout = min(UINT_MAX, U64_MAX / clk)
	min_pretimeout = 0
	max_pretimeout = U32_MAX / clk

and then ensure that pretimeout < timeout at runtime (if possible in
the infrastructure code).

Even at maximum clock rate, max_timeout is so large that anything else
is really overkill.

> +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;
> +

So in practice you always have a pretimeout of at least one second,
correct ? That kind of violates the ABI, which says that the pretimeout
should be disabled if set to 0. Is there anything we can do about that ?

What exactly happens if WOR = 0 ? Doesn't that just mean that the second
timeout will happen immediately, and isn't that what we would want if
pretimeout = 0 ?

> +	/* refresh the WOR, that will cause an explicit watchdog refresh */

Except that we use wcv which needs a manual refresh, so this is a bit
misleading, isn't it ?

> +	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);

Should that happen after writing wcv ?

> +
> +	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;
> +
> +	/*
> +	 * Get the frequency of system counter from
> +	 * the cp15 interface of ARM Generic timer
> +	 */
> +	clk = arch_timer_get_cntfrq();

That can not return 0, presumably, from looking into its implementation.
And the system should panic if it is ever 0.

> +	if (!clk) {

Given that, I don't think this check is necessary.

> +		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(cf_base))
> +		return PTR_ERR(cf_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));

Does this message (specifically the WCS / WCV values) have any
useful meaning for the user ?

> +		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);

You have not configured wdd->timeout and wdd->pretimeout here,
yet the function calls reload_timeout_to_wcv which needs it.

> +	}
> +
> +	wdd->min_pretimeout = 0;
> +	wdd->max_pretimeout = min(U32_MAX / clk, max_pretimeout_param);
> +	wdd->min_timeout = 1;
> +	do_div(first_period_max, clk);
> +	wdd->max_timeout = min((uint)(wdd->pretimeout + first_period_max),
> +			       max_timeout_param);
> +
> +	wdd->pretimeout = DEFAULT_PRETIMEOUT;
> +	wdd->timeout = DEFAULT_TIMEOUT;
> +	watchdog_init_timeouts(wdd, pretimeout_param, timeout_param, dev);
> +	/* update pretimeout to WOR */
> +	sbsa_gwdt_cf_write(SBSA_GWDT_WOR, wdd->pretimeout * clk, wdd);

This is interesting because you set WOR to 0 here if pretimeout is 0.
Yet, when pretimeout is updated later on, you always set it to at least
one second. Any reason for doing this differently ?

If the above works, and presumably you have tested it, I don't see why
it would be necessary to set WOR to a value larger than 0 when updating
pretimeout.

> +
> +	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);

400000Hz reads a bit odd. How about a space between the number and Hz ?

> +
> +	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);
> +
I don't think you should do anything here. The driver can only be removed
if closed, and it that case the watchdog will already have been stopped,
or if nowayout was set it won't be stopped. Either case it is already in
the state we want it to be in.

> +	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 <fu.wei@linaro.org>");
> +MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
> +MODULE_LICENSE("GPL v2");
>


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-25 19:39       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-25 19:39 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	corbet-T1hC0tSOHrs, mark.rutland-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8

On 05/25/2015 03:03 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> 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, the interrupt routine run panic to save
> system context.
>
> Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
> Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---

Comments inline.

Thanks,
Guenter

>   drivers/watchdog/Kconfig     |  11 +
>   drivers/watchdog/Makefile    |   1 +
>   drivers/watchdog/sbsa_gwdt.c | 474 +++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 486 insertions(+)
>   create mode 100644 drivers/watchdog/sbsa_gwdt.c
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index e5e7c55..554f18a 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -152,6 +152,17 @@ 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 ARM64
> +	depends on ARM_ARCH_TIMER
> +	select WATCHDOG_CORE
> +	help
> +	  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.
> +	  More details: ARM 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..0d1aff1
> --- /dev/null
> +++ b/drivers/watchdog/sbsa_gwdt.c
> @@ -0,0 +1,474 @@
> +/*
> + * SBSA(Server Base System Architecture) Generic Watchdog driver
> + *
> + * Copyright (c) 2015, Linaro Ltd.
> + * Author: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
> + *
> + * 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: ARM DEN0029B - Server Base System Architecture (SBSA)
> + *
> + * Kernel/API:                         P---------| pretimeout
> + *               |-------------------------------T timeout
> + * SBSA GWDT:                          P--WOR---WS1 pretimeout
> + *               |-------WCV----------WS0~~~~~~~~T timeout
> + */
> +
> +#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>
> +#include <asm/arch_timer.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*/

That is a bit low for a default. Is that on purpose ?
Most drivers use 30 or 60 seconds.

> +#define DEFAULT_PRETIMEOUT	5  /* seconds, the 2nd watch period*/
> +
> +static unsigned int timeout_param;
> +module_param(timeout_param, uint, 0);
> +MODULE_PARM_DESC(timeout_param,
> +		 "Watchdog timeout in seconds. (>=0, default="
> +		 __MODULE_STRING(DEFAULT_TIMEOUT) ")");
> +
Why _param in the module parameter names ? Seems to be redundant.

> +static unsigned int max_timeout_param = UINT_MAX;
> +module_param(max_timeout_param, uint, 0);
> +MODULE_PARM_DESC(max_timeout_param,
> +		 "Watchdog max timeout in seconds. (>=0, default="
> +		 __MODULE_STRING(UINT_MAX) ")");
> +

Why do we want or need this parameter and max_pretimeout ? Those
are determined by the hardware.

> +static unsigned int pretimeout_param;
> +module_param(pretimeout_param, uint, 0);
> +MODULE_PARM_DESC(pretimeout_param,
> +		 "Watchdog pretimeout in seconds. (>=0, default="
> +		 __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
> +
> +static unsigned int max_pretimeout_param = U32_MAX;
> +module_param(max_pretimeout_param, uint, 0);
> +MODULE_PARM_DESC(max_pretimeout_param,
> +		 "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) ")");
> +
> +/*
> + * help functions for accessing 32bit registers of SBSA Generic Watchdog
> + */
> +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 functions 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 update the 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);
> +}
> +

After understanding the watchdog a bit better now, I think you should drop
those updates and set
	min_timeout = 1
	max_timeout = min(UINT_MAX, U64_MAX / clk)
	min_pretimeout = 0
	max_pretimeout = U32_MAX / clk

and then ensure that pretimeout < timeout at runtime (if possible in
the infrastructure code).

Even at maximum clock rate, max_timeout is so large that anything else
is really overkill.

> +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;
> +

So in practice you always have a pretimeout of at least one second,
correct ? That kind of violates the ABI, which says that the pretimeout
should be disabled if set to 0. Is there anything we can do about that ?

What exactly happens if WOR = 0 ? Doesn't that just mean that the second
timeout will happen immediately, and isn't that what we would want if
pretimeout = 0 ?

> +	/* refresh the WOR, that will cause an explicit watchdog refresh */

Except that we use wcv which needs a manual refresh, so this is a bit
misleading, isn't it ?

> +	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);

Should that happen after writing wcv ?

> +
> +	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;
> +
> +	/*
> +	 * Get the frequency of system counter from
> +	 * the cp15 interface of ARM Generic timer
> +	 */
> +	clk = arch_timer_get_cntfrq();

That can not return 0, presumably, from looking into its implementation.
And the system should panic if it is ever 0.

> +	if (!clk) {

Given that, I don't think this check is necessary.

> +		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(cf_base))
> +		return PTR_ERR(cf_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));

Does this message (specifically the WCS / WCV values) have any
useful meaning for the user ?

> +		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);

You have not configured wdd->timeout and wdd->pretimeout here,
yet the function calls reload_timeout_to_wcv which needs it.

> +	}
> +
> +	wdd->min_pretimeout = 0;
> +	wdd->max_pretimeout = min(U32_MAX / clk, max_pretimeout_param);
> +	wdd->min_timeout = 1;
> +	do_div(first_period_max, clk);
> +	wdd->max_timeout = min((uint)(wdd->pretimeout + first_period_max),
> +			       max_timeout_param);
> +
> +	wdd->pretimeout = DEFAULT_PRETIMEOUT;
> +	wdd->timeout = DEFAULT_TIMEOUT;
> +	watchdog_init_timeouts(wdd, pretimeout_param, timeout_param, dev);
> +	/* update pretimeout to WOR */
> +	sbsa_gwdt_cf_write(SBSA_GWDT_WOR, wdd->pretimeout * clk, wdd);

This is interesting because you set WOR to 0 here if pretimeout is 0.
Yet, when pretimeout is updated later on, you always set it to at least
one second. Any reason for doing this differently ?

If the above works, and presumably you have tested it, I don't see why
it would be necessary to set WOR to a value larger than 0 when updating
pretimeout.

> +
> +	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);

400000Hz reads a bit odd. How about a space between the number and Hz ?

> +
> +	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);
> +
I don't think you should do anything here. The driver can only be removed
if closed, and it that case the watchdog will already have been stopped,
or if nowayout was set it won't be stopped. Either case it is already in
the state we want it to be in.

> +	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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>");
> +MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>");
> +MODULE_LICENSE("GPL v2");
>

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
  2015-05-25 10:03   ` [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device fu.wei
@ 2015-05-26  8:28     ` Hanjun Guo
  2015-05-26 16:35       ` Timur Tabi
  2015-05-26 12:28       ` Will Deacon
  1 sibling, 1 reply; 550+ messages in thread
From: Hanjun Guo @ 2015-05-26  8:28 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, timur, ashwin.chaugule,
	arnd, linux, vgandhi, wim, jcm, leo.duran, corbet, mark.rutland,
	catalin.marinas, will.deacon

Hi Fu Wei,

Some minor comments inline.

On 2015年05月25日 18:03, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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.
>
> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> Tested-by: Timur Tabi <timur@codeaurora.org>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>   arch/arm64/kernel/acpi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 145 insertions(+)
>
> diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
> index 8b83955..c95deec 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,147 @@ void __init acpi_gic_init(void)
>
>   	early_acpi_os_unmap_memory((char *)table, tbl_size);
>   }

please add

#ifdef CONFIG_ARM_SBSA_WATCHDOG
(acpi gtdt code)
#endif

> +
> +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_debug("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;
> +	}
> +
> +	/*
> +	 * Add a platform device named "sbsa-gwdt" to match the platform driver.
> +	 * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
> +	 * The platform driver can get device info below by matching this name.

* The platform driver (drivers/watchdog/sbsa_gwdt.c) can get device info 
below by matching this name.

Adding the file name which will help for review and maintain in my
opinion.

> +	 */
> +	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;
> +
> +	/*
> +	 * According to SBSA specification the size of refresh and control
> +	 * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
> +	 */
> +	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;

How about

if (!err)
	return 0;

then no need for goto err_free_res and save two lines of codes.

Other than that,

Acked-by: Hanjun Guo <hanjun.guo@linaro.org>

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-26 12:28       ` Will Deacon
  0 siblings, 0 replies; 550+ messages in thread
From: Will Deacon @ 2015-05-26 12:28 UTC (permalink / raw)
  To: fu.wei
  Cc: suravee.suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, tekkamanninja, graeme.gregory, al.stone,
	hanjun.guo, timur, ashwin.chaugule, arnd, linux, vgandhi, wim,
	jcm, leo.duran, corbet, Mark Rutland, Catalin Marinas

On Mon, May 25, 2015 at 11:03:13AM +0100, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> 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.
> 
> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> Tested-by: Timur Tabi <timur@codeaurora.org>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  arch/arm64/kernel/acpi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 145 insertions(+)

Why does this all need to be under arch/arm64? The GTDT really isn't
architecture-specific, so I'd *much* rather it was parsed in the driver code
itself, like we already do for the architected timer. The GIC is an
exception because it's in the MADT, which we need to parse in the arch code
to configure SMP properly.

Will

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-26 12:28       ` Will Deacon
  0 siblings, 0 replies; 550+ messages in thread
From: Will Deacon @ 2015-05-26 12:28 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A
  Cc: suravee.suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA

On Mon, May 25, 2015 at 11:03:13AM +0100, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> 
> 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.
> 
> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
> Tested-by: Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>  arch/arm64/kernel/acpi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 145 insertions(+)

Why does this all need to be under arch/arm64? The GTDT really isn't
architecture-specific, so I'd *much* rather it was parsed in the driver code
itself, like we already do for the architected timer. The GIC is an
exception because it's in the MADT, which we need to parse in the arch code
to configure SMP properly.

Will
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
  2015-05-26 12:28       ` Will Deacon
@ 2015-05-26 15:02         ` Ashwin Chaugule
  -1 siblings, 0 replies; 550+ messages in thread
From: Ashwin Chaugule @ 2015-05-26 15:02 UTC (permalink / raw)
  To: Will Deacon
  Cc: fu.wei, suravee.suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, hanjun.guo, timur, arnd, linux,
	vgandhi, wim, jcm, leo.duran, corbet, Mark Rutland,
	Catalin Marinas

Hi Will,

On 26 May 2015 at 08:28, Will Deacon <will.deacon@arm.com> wrote:
> On Mon, May 25, 2015 at 11:03:13AM +0100, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> 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.
>>
>> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>> Tested-by: Timur Tabi <timur@codeaurora.org>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  arch/arm64/kernel/acpi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 145 insertions(+)
>
> Why does this all need to be under arch/arm64? The GTDT really isn't
> architecture-specific, so I'd *much* rather it was parsed in the driver code
> itself, like we already do for the architected timer. The GIC is an
> exception because it's in the MADT, which we need to parse in the arch code
> to configure SMP properly.

I'm not really against refactoring the code. But the GTDT looks quite
specific to ARM..

---8<----
5.2.24 Generic Timer Description Table (GTDT)
This section describes the format of the Generic Timer Description
Table (GTDT), which provides
OSPM with information about a system’s Generic Timers configuration.
The Generic Timer (GT) is
a standard timer interface implemented on ARM processor-based systems.
The GT hardware
specification can be found at Links to ACPI-Related Documents
(http://uefi.org/acpi) under the
heading ARM Architecture. The GTDT provides OSPM with information
about a system's GT
interrupt configurations, for both per-processor timers, and platform
(memory-mapped) timers.
The GT specification defines the following per-processor timers:
• Secure privilege level 1 (EL1) timer,
• Non-Secure EL1 timer,
• Non-Secure privilege level 2 (EL2) timer,
• Virtual timer,
and the following Platform (memory-mapped) timers.
• GT Block
• Server Base System Architecture (SBSA) Generic Watchdog
---8<----

Thanks,
Ashwin.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-26 15:02         ` Ashwin Chaugule
  0 siblings, 0 replies; 550+ messages in thread
From: Ashwin Chaugule @ 2015-05-26 15:02 UTC (permalink / raw)
  To: Will Deacon
  Cc: fu.wei, suravee.suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, hanjun.guo, timur, arnd, linux,
	vgandhi, wim, jcm, leo.duran

Hi Will,

On 26 May 2015 at 08:28, Will Deacon <will.deacon@arm.com> wrote:
> On Mon, May 25, 2015 at 11:03:13AM +0100, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> 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.
>>
>> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>> Tested-by: Timur Tabi <timur@codeaurora.org>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  arch/arm64/kernel/acpi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 145 insertions(+)
>
> Why does this all need to be under arch/arm64? The GTDT really isn't
> architecture-specific, so I'd *much* rather it was parsed in the driver code
> itself, like we already do for the architected timer. The GIC is an
> exception because it's in the MADT, which we need to parse in the arch code
> to configure SMP properly.

I'm not really against refactoring the code. But the GTDT looks quite
specific to ARM..

---8<----
5.2.24 Generic Timer Description Table (GTDT)
This section describes the format of the Generic Timer Description
Table (GTDT), which provides
OSPM with information about a system’s Generic Timers configuration.
The Generic Timer (GT) is
a standard timer interface implemented on ARM processor-based systems.
The GT hardware
specification can be found at Links to ACPI-Related Documents
(http://uefi.org/acpi) under the
heading ARM Architecture. The GTDT provides OSPM with information
about a system's GT
interrupt configurations, for both per-processor timers, and platform
(memory-mapped) timers.
The GT specification defines the following per-processor timers:
• Secure privilege level 1 (EL1) timer,
• Non-Secure EL1 timer,
• Non-Secure privilege level 2 (EL2) timer,
• Virtual timer,
and the following Platform (memory-mapped) timers.
• GT Block
• Server Base System Architecture (SBSA) Generic Watchdog
---8<----

Thanks,
Ashwin.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
  2015-05-26 15:02         ` Ashwin Chaugule
@ 2015-05-26 15:18           ` Will Deacon
  -1 siblings, 0 replies; 550+ messages in thread
From: Will Deacon @ 2015-05-26 15:18 UTC (permalink / raw)
  To: Ashwin Chaugule
  Cc: fu.wei, suravee.suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, hanjun.guo, timur, arnd, linux,
	vgandhi, wim, jcm, leo.duran, corbet, Mark Rutland,
	Catalin Marinas

On Tue, May 26, 2015 at 04:02:56PM +0100, Ashwin Chaugule wrote:
> On 26 May 2015 at 08:28, Will Deacon <will.deacon@arm.com> wrote:
> > On Mon, May 25, 2015 at 11:03:13AM +0100, fu.wei@linaro.org wrote:
> >> From: Fu Wei <fu.wei@linaro.org>
> >>
> >> 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.
> >>
> >> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> >> Tested-by: Timur Tabi <timur@codeaurora.org>
> >> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> >> ---
> >>  arch/arm64/kernel/acpi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
> >>  1 file changed, 145 insertions(+)
> >
> > Why does this all need to be under arch/arm64? The GTDT really isn't
> > architecture-specific, so I'd *much* rather it was parsed in the driver code
> > itself, like we already do for the architected timer. The GIC is an
> > exception because it's in the MADT, which we need to parse in the arch code
> > to configure SMP properly.
> 
> I'm not really against refactoring the code. But the GTDT looks quite
> specific to ARM..
> 
> ---8<----
> 5.2.24 Generic Timer Description Table (GTDT)
> This section describes the format of the Generic Timer Description
> Table (GTDT), which provides
> OSPM with information about a system’s Generic Timers configuration.
> The Generic Timer (GT) is
> a standard timer interface implemented on ARM processor-based systems.
> The GT hardware
> specification can be found at Links to ACPI-Related Documents
> (http://uefi.org/acpi) under the
> heading ARM Architecture. The GTDT provides OSPM with information
> about a system's GT
> interrupt configurations, for both per-processor timers, and platform
> (memory-mapped) timers.
> The GT specification defines the following per-processor timers:
> • Secure privilege level 1 (EL1) timer,
> • Non-Secure EL1 timer,
> • Non-Secure privilege level 2 (EL2) timer,
> • Virtual timer,
> and the following Platform (memory-mapped) timers.
> • GT Block
> • Server Base System Architecture (SBSA) Generic Watchdog
> ---8<----

Sure, the device it describes may only ever exist on ARM systems, but by
that logic then we should be moving lots of drivers back under arch/arm[64].

The ARM architecture says precisely *nothing* about ACPI, so we should
try to keep arch/arm64/kernel/acpi.c to a minimum and not shovel all sorts
of table conversion code in there for random peripherals.

Will

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-26 15:18           ` Will Deacon
  0 siblings, 0 replies; 550+ messages in thread
From: Will Deacon @ 2015-05-26 15:18 UTC (permalink / raw)
  To: Ashwin Chaugule
  Cc: fu.wei, suravee.suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, hanjun.guo, timur, arnd, linux,
	vgandhi, wim, jcm, leo.duran

On Tue, May 26, 2015 at 04:02:56PM +0100, Ashwin Chaugule wrote:
> On 26 May 2015 at 08:28, Will Deacon <will.deacon@arm.com> wrote:
> > On Mon, May 25, 2015 at 11:03:13AM +0100, fu.wei@linaro.org wrote:
> >> From: Fu Wei <fu.wei@linaro.org>
> >>
> >> 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.
> >>
> >> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> >> Tested-by: Timur Tabi <timur@codeaurora.org>
> >> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> >> ---
> >>  arch/arm64/kernel/acpi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
> >>  1 file changed, 145 insertions(+)
> >
> > Why does this all need to be under arch/arm64? The GTDT really isn't
> > architecture-specific, so I'd *much* rather it was parsed in the driver code
> > itself, like we already do for the architected timer. The GIC is an
> > exception because it's in the MADT, which we need to parse in the arch code
> > to configure SMP properly.
> 
> I'm not really against refactoring the code. But the GTDT looks quite
> specific to ARM..
> 
> ---8<----
> 5.2.24 Generic Timer Description Table (GTDT)
> This section describes the format of the Generic Timer Description
> Table (GTDT), which provides
> OSPM with information about a system’s Generic Timers configuration.
> The Generic Timer (GT) is
> a standard timer interface implemented on ARM processor-based systems.
> The GT hardware
> specification can be found at Links to ACPI-Related Documents
> (http://uefi.org/acpi) under the
> heading ARM Architecture. The GTDT provides OSPM with information
> about a system's GT
> interrupt configurations, for both per-processor timers, and platform
> (memory-mapped) timers.
> The GT specification defines the following per-processor timers:
> • Secure privilege level 1 (EL1) timer,
> • Non-Secure EL1 timer,
> • Non-Secure privilege level 2 (EL2) timer,
> • Virtual timer,
> and the following Platform (memory-mapped) timers.
> • GT Block
> • Server Base System Architecture (SBSA) Generic Watchdog
> ---8<----

Sure, the device it describes may only ever exist on ARM systems, but by
that logic then we should be moving lots of drivers back under arch/arm[64].

The ARM architecture says precisely *nothing* about ACPI, so we should
try to keep arch/arm64/kernel/acpi.c to a minimum and not shovel all sorts
of table conversion code in there for random peripherals.

Will

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
  2015-05-26 15:18           ` Will Deacon
  (?)
@ 2015-05-26 15:35             ` Ashwin Chaugule
  -1 siblings, 0 replies; 550+ messages in thread
From: Ashwin Chaugule @ 2015-05-26 15:35 UTC (permalink / raw)
  To: Will Deacon
  Cc: fu.wei, suravee.suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, hanjun.guo, timur, arnd, linux,
	vgandhi, wim, jcm, leo.duran, corbet, Mark Rutland,
	Catalin Marinas

On 26 May 2015 at 11:18, Will Deacon <will.deacon@arm.com> wrote:
> On Tue, May 26, 2015 at 04:02:56PM +0100, Ashwin Chaugule wrote:
>> On 26 May 2015 at 08:28, Will Deacon <will.deacon@arm.com> wrote:
>> > On Mon, May 25, 2015 at 11:03:13AM +0100, fu.wei@linaro.org wrote:
>> >> From: Fu Wei <fu.wei@linaro.org>
>> >>
>> >> 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.
>> >>
>> >> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>> >> Tested-by: Timur Tabi <timur@codeaurora.org>
>> >> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> >> ---
>> >>  arch/arm64/kernel/acpi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
>> >>  1 file changed, 145 insertions(+)
>> >
>> > Why does this all need to be under arch/arm64? The GTDT really isn't
>> > architecture-specific, so I'd *much* rather it was parsed in the driver code
>> > itself, like we already do for the architected timer. The GIC is an
>> > exception because it's in the MADT, which we need to parse in the arch code
>> > to configure SMP properly.
>>
>> I'm not really against refactoring the code. But the GTDT looks quite
>> specific to ARM..
>>
>> ---8<----
>> 5.2.24 Generic Timer Description Table (GTDT)
>> This section describes the format of the Generic Timer Description
>> Table (GTDT), which provides
>> OSPM with information about a system’s Generic Timers configuration.
>> The Generic Timer (GT) is
>> a standard timer interface implemented on ARM processor-based systems.
>> The GT hardware
>> specification can be found at Links to ACPI-Related Documents
>> (http://uefi.org/acpi) under the
>> heading ARM Architecture. The GTDT provides OSPM with information
>> about a system's GT
>> interrupt configurations, for both per-processor timers, and platform
>> (memory-mapped) timers.
>> The GT specification defines the following per-processor timers:
>> • Secure privilege level 1 (EL1) timer,
>> • Non-Secure EL1 timer,
>> • Non-Secure privilege level 2 (EL2) timer,
>> • Virtual timer,
>> and the following Platform (memory-mapped) timers.
>> • GT Block
>> • Server Base System Architecture (SBSA) Generic Watchdog
>> ---8<----
>
> Sure, the device it describes may only ever exist on ARM systems, but by
> that logic then we should be moving lots of drivers back under arch/arm[64].

Sure. Not arguing about that. :) You said the GTDT isn't really arch
specific. That was a bit confusing.

>
> The ARM architecture says precisely *nothing* about ACPI, so we should
> try to keep arch/arm64/kernel/acpi.c to a minimum and not shovel all sorts
> of table conversion code in there for random peripherals.
>
> Will

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-26 15:35             ` Ashwin Chaugule
  0 siblings, 0 replies; 550+ messages in thread
From: Ashwin Chaugule @ 2015-05-26 15:35 UTC (permalink / raw)
  To: Will Deacon
  Cc: fu.wei, suravee.suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, hanjun.guo, timur, arnd, linux,
	vgandhi, wim, jcm, leo.duran

On 26 May 2015 at 11:18, Will Deacon <will.deacon@arm.com> wrote:
> On Tue, May 26, 2015 at 04:02:56PM +0100, Ashwin Chaugule wrote:
>> On 26 May 2015 at 08:28, Will Deacon <will.deacon@arm.com> wrote:
>> > On Mon, May 25, 2015 at 11:03:13AM +0100, fu.wei@linaro.org wrote:
>> >> From: Fu Wei <fu.wei@linaro.org>
>> >>
>> >> 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.
>> >>
>> >> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>> >> Tested-by: Timur Tabi <timur@codeaurora.org>
>> >> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> >> ---
>> >>  arch/arm64/kernel/acpi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
>> >>  1 file changed, 145 insertions(+)
>> >
>> > Why does this all need to be under arch/arm64? The GTDT really isn't
>> > architecture-specific, so I'd *much* rather it was parsed in the driver code
>> > itself, like we already do for the architected timer. The GIC is an
>> > exception because it's in the MADT, which we need to parse in the arch code
>> > to configure SMP properly.
>>
>> I'm not really against refactoring the code. But the GTDT looks quite
>> specific to ARM..
>>
>> ---8<----
>> 5.2.24 Generic Timer Description Table (GTDT)
>> This section describes the format of the Generic Timer Description
>> Table (GTDT), which provides
>> OSPM with information about a system’s Generic Timers configuration.
>> The Generic Timer (GT) is
>> a standard timer interface implemented on ARM processor-based systems.
>> The GT hardware
>> specification can be found at Links to ACPI-Related Documents
>> (http://uefi.org/acpi) under the
>> heading ARM Architecture. The GTDT provides OSPM with information
>> about a system's GT
>> interrupt configurations, for both per-processor timers, and platform
>> (memory-mapped) timers.
>> The GT specification defines the following per-processor timers:
>> • Secure privilege level 1 (EL1) timer,
>> • Non-Secure EL1 timer,
>> • Non-Secure privilege level 2 (EL2) timer,
>> • Virtual timer,
>> and the following Platform (memory-mapped) timers.
>> • GT Block
>> • Server Base System Architecture (SBSA) Generic Watchdog
>> ---8<----
>
> Sure, the device it describes may only ever exist on ARM systems, but by
> that logic then we should be moving lots of drivers back under arch/arm[64].

Sure. Not arguing about that. :) You said the GTDT isn't really arch
specific. That was a bit confusing.

>
> The ARM architecture says precisely *nothing* about ACPI, so we should
> try to keep arch/arm64/kernel/acpi.c to a minimum and not shovel all sorts
> of table conversion code in there for random peripherals.
>
> Will

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-26 15:35             ` Ashwin Chaugule
  0 siblings, 0 replies; 550+ messages in thread
From: Ashwin Chaugule @ 2015-05-26 15:35 UTC (permalink / raw)
  To: Will Deacon
  Cc: fu.wei, suravee.suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, hanjun.guo, timur, arnd, linux,
	vgandhi, wim, jcm, leo.duran, corbet, Mark Rutland,
	Catalin Marinas

On 26 May 2015 at 11:18, Will Deacon <will.deacon@arm.com> wrote:
> On Tue, May 26, 2015 at 04:02:56PM +0100, Ashwin Chaugule wrote:
>> On 26 May 2015 at 08:28, Will Deacon <will.deacon@arm.com> wrote:
>> > On Mon, May 25, 2015 at 11:03:13AM +0100, fu.wei@linaro.org wrote:
>> >> From: Fu Wei <fu.wei@linaro.org>
>> >>
>> >> 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.
>> >>
>> >> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>> >> Tested-by: Timur Tabi <timur@codeaurora.org>
>> >> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> >> ---
>> >>  arch/arm64/kernel/acpi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
>> >>  1 file changed, 145 insertions(+)
>> >
>> > Why does this all need to be under arch/arm64? The GTDT really isn't
>> > architecture-specific, so I'd *much* rather it was parsed in the driver code
>> > itself, like we already do for the architected timer. The GIC is an
>> > exception because it's in the MADT, which we need to parse in the arch code
>> > to configure SMP properly.
>>
>> I'm not really against refactoring the code. But the GTDT looks quite
>> specific to ARM..
>>
>> ---8<----
>> 5.2.24 Generic Timer Description Table (GTDT)
>> This section describes the format of the Generic Timer Description
>> Table (GTDT), which provides
>> OSPM with information about a system’s Generic Timers configuration.
>> The Generic Timer (GT) is
>> a standard timer interface implemented on ARM processor-based systems.
>> The GT hardware
>> specification can be found at Links to ACPI-Related Documents
>> (http://uefi.org/acpi) under the
>> heading ARM Architecture. The GTDT provides OSPM with information
>> about a system's GT
>> interrupt configurations, for both per-processor timers, and platform
>> (memory-mapped) timers.
>> The GT specification defines the following per-processor timers:
>> • Secure privilege level 1 (EL1) timer,
>> • Non-Secure EL1 timer,
>> • Non-Secure privilege level 2 (EL2) timer,
>> • Virtual timer,
>> and the following Platform (memory-mapped) timers.
>> • GT Block
>> • Server Base System Architecture (SBSA) Generic Watchdog
>> ---8<----
>
> Sure, the device it describes may only ever exist on ARM systems, but by
> that logic then we should be moving lots of drivers back under arch/arm[64].

Sure. Not arguing about that. :) You said the GTDT isn't really arch
specific. That was a bit confusing.

>
> The ARM architecture says precisely *nothing* about ACPI, so we should
> try to keep arch/arm64/kernel/acpi.c to a minimum and not shovel all sorts
> of table conversion code in there for random peripherals.
>
> Will
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
  2015-05-26 15:18           ` Will Deacon
@ 2015-05-26 15:36             ` Guenter Roeck
  -1 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-26 15:36 UTC (permalink / raw)
  To: Will Deacon
  Cc: Ashwin Chaugule, fu.wei, suravee.suthikulpanit, linaro-acpi,
	linux-watchdog, devicetree, linux-kernel, linux-doc,
	tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur, arnd,
	vgandhi, wim, jcm, leo.duran, corbet, Mark Rutland,
	Catalin Marinas

On Tue, May 26, 2015 at 04:18:42PM +0100, Will Deacon wrote:
> On Tue, May 26, 2015 at 04:02:56PM +0100, Ashwin Chaugule wrote:
> > On 26 May 2015 at 08:28, Will Deacon <will.deacon@arm.com> wrote:
> > > On Mon, May 25, 2015 at 11:03:13AM +0100, fu.wei@linaro.org wrote:
> > >> From: Fu Wei <fu.wei@linaro.org>
> > >>
> > >> 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.
> > >>
> > >> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> > >> Tested-by: Timur Tabi <timur@codeaurora.org>
> > >> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> > >> ---
> > >>  arch/arm64/kernel/acpi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
> > >>  1 file changed, 145 insertions(+)
> > >
> > > Why does this all need to be under arch/arm64? The GTDT really isn't
> > > architecture-specific, so I'd *much* rather it was parsed in the driver code
> > > itself, like we already do for the architected timer. The GIC is an
> > > exception because it's in the MADT, which we need to parse in the arch code
> > > to configure SMP properly.
> > 
> > I'm not really against refactoring the code. But the GTDT looks quite
> > specific to ARM..
> > 
> > ---8<----
> > 5.2.24 Generic Timer Description Table (GTDT)
> > This section describes the format of the Generic Timer Description
> > Table (GTDT), which provides
> > OSPM with information about a system’s Generic Timers configuration.
> > The Generic Timer (GT) is
> > a standard timer interface implemented on ARM processor-based systems.
> > The GT hardware
> > specification can be found at Links to ACPI-Related Documents
> > (http://uefi.org/acpi) under the
> > heading ARM Architecture. The GTDT provides OSPM with information
> > about a system's GT
> > interrupt configurations, for both per-processor timers, and platform
> > (memory-mapped) timers.
> > The GT specification defines the following per-processor timers:
> > • Secure privilege level 1 (EL1) timer,
> > • Non-Secure EL1 timer,
> > • Non-Secure privilege level 2 (EL2) timer,
> > • Virtual timer,
> > and the following Platform (memory-mapped) timers.
> > • GT Block
> > • Server Base System Architecture (SBSA) Generic Watchdog
> > ---8<----
> 
> Sure, the device it describes may only ever exist on ARM systems, but by
> that logic then we should be moving lots of drivers back under arch/arm[64].
> 
It is nt the driver, but its instantiation. The question here would be
how and where to instantiate the driver, not where the driver itself
is located. The driver itself is ACPI agnostic.

What you are really saying is that you want the driver instantiation
to be moved into the driver.

Guenter

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-26 15:36             ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-26 15:36 UTC (permalink / raw)
  To: Will Deacon
  Cc: Ashwin Chaugule, fu.wei, suravee.suthikulpanit, linaro-acpi,
	linux-watchdog, devicetree, linux-kernel, linux-doc,
	tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur, arnd,
	vgandhi, wim, jcm, leo.duran

On Tue, May 26, 2015 at 04:18:42PM +0100, Will Deacon wrote:
> On Tue, May 26, 2015 at 04:02:56PM +0100, Ashwin Chaugule wrote:
> > On 26 May 2015 at 08:28, Will Deacon <will.deacon@arm.com> wrote:
> > > On Mon, May 25, 2015 at 11:03:13AM +0100, fu.wei@linaro.org wrote:
> > >> From: Fu Wei <fu.wei@linaro.org>
> > >>
> > >> 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.
> > >>
> > >> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> > >> Tested-by: Timur Tabi <timur@codeaurora.org>
> > >> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> > >> ---
> > >>  arch/arm64/kernel/acpi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
> > >>  1 file changed, 145 insertions(+)
> > >
> > > Why does this all need to be under arch/arm64? The GTDT really isn't
> > > architecture-specific, so I'd *much* rather it was parsed in the driver code
> > > itself, like we already do for the architected timer. The GIC is an
> > > exception because it's in the MADT, which we need to parse in the arch code
> > > to configure SMP properly.
> > 
> > I'm not really against refactoring the code. But the GTDT looks quite
> > specific to ARM..
> > 
> > ---8<----
> > 5.2.24 Generic Timer Description Table (GTDT)
> > This section describes the format of the Generic Timer Description
> > Table (GTDT), which provides
> > OSPM with information about a system’s Generic Timers configuration.
> > The Generic Timer (GT) is
> > a standard timer interface implemented on ARM processor-based systems.
> > The GT hardware
> > specification can be found at Links to ACPI-Related Documents
> > (http://uefi.org/acpi) under the
> > heading ARM Architecture. The GTDT provides OSPM with information
> > about a system's GT
> > interrupt configurations, for both per-processor timers, and platform
> > (memory-mapped) timers.
> > The GT specification defines the following per-processor timers:
> > • Secure privilege level 1 (EL1) timer,
> > • Non-Secure EL1 timer,
> > • Non-Secure privilege level 2 (EL2) timer,
> > • Virtual timer,
> > and the following Platform (memory-mapped) timers.
> > • GT Block
> > • Server Base System Architecture (SBSA) Generic Watchdog
> > ---8<----
> 
> Sure, the device it describes may only ever exist on ARM systems, but by
> that logic then we should be moving lots of drivers back under arch/arm[64].
> 
It is nt the driver, but its instantiation. The question here would be
how and where to instantiate the driver, not where the driver itself
is located. The driver itself is ACPI agnostic.

What you are really saying is that you want the driver instantiation
to be moved into the driver.

Guenter

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-26 16:27               ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-26 16:27 UTC (permalink / raw)
  To: Will Deacon
  Cc: Guenter Roeck, Ashwin Chaugule, suravee.suthikulpanit,
	linaro-acpi, linux-watchdog, devicetree, linux-kernel, linux-doc,
	tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur, arnd,
	vgandhi, wim, jcm, leo.duran, corbet, Mark Rutland,
	Catalin Marinas

On 26 May 2015 at 23:36, Guenter Roeck <linux@roeck-us.net> wrote:
> On Tue, May 26, 2015 at 04:18:42PM +0100, Will Deacon wrote:
>> On Tue, May 26, 2015 at 04:02:56PM +0100, Ashwin Chaugule wrote:
>> > On 26 May 2015 at 08:28, Will Deacon <will.deacon@arm.com> wrote:
>> > > On Mon, May 25, 2015 at 11:03:13AM +0100, fu.wei@linaro.org wrote:
>> > >> From: Fu Wei <fu.wei@linaro.org>
>> > >>
>> > >> 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.
>> > >>
>> > >> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>> > >> Tested-by: Timur Tabi <timur@codeaurora.org>
>> > >> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> > >> ---
>> > >>  arch/arm64/kernel/acpi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
>> > >>  1 file changed, 145 insertions(+)
>> > >
>> > > Why does this all need to be under arch/arm64? The GTDT really isn't
>> > > architecture-specific, so I'd *much* rather it was parsed in the driver code
>> > > itself, like we already do for the architected timer. The GIC is an
>> > > exception because it's in the MADT, which we need to parse in the arch code
>> > > to configure SMP properly.
>> >
>> > I'm not really against refactoring the code. But the GTDT looks quite
>> > specific to ARM..
>> >
>> > ---8<----
>> > 5.2.24 Generic Timer Description Table (GTDT)
>> > This section describes the format of the Generic Timer Description
>> > Table (GTDT), which provides
>> > OSPM with information about a system’s Generic Timers configuration.
>> > The Generic Timer (GT) is
>> > a standard timer interface implemented on ARM processor-based systems.
>> > The GT hardware
>> > specification can be found at Links to ACPI-Related Documents
>> > (http://uefi.org/acpi) under the
>> > heading ARM Architecture. The GTDT provides OSPM with information
>> > about a system's GT
>> > interrupt configurations, for both per-processor timers, and platform
>> > (memory-mapped) timers.
>> > The GT specification defines the following per-processor timers:
>> > • Secure privilege level 1 (EL1) timer,
>> > • Non-Secure EL1 timer,
>> > • Non-Secure privilege level 2 (EL2) timer,
>> > • Virtual timer,
>> > and the following Platform (memory-mapped) timers.
>> > • GT Block
>> > • Server Base System Architecture (SBSA) Generic Watchdog
>> > ---8<----
>>
>> Sure, the device it describes may only ever exist on ARM systems, but by
>> that logic then we should be moving lots of drivers back under arch/arm[64].
>>
> It is nt the driver, but its instantiation. The question here would be
> how and where to instantiate the driver, not where the driver itself
> is located. The driver itself is ACPI agnostic.

Hi Will,

I really don't mind to refactor the code, If we can make this patch better.

But for now, I can't see the good reason to move ACPI-relevant code
into a watchdog driver.

The reasons I put the code here are
(1)SBSA watchdog only for ARM64
(2)GTDT only for ARM, design for ARM,
(3)For ARM Architecture, only ARM64 support ACPI.

For minimizing arch/arm64/kernel/acpi.c, we can't put the code here,
and we had better keep these code outside the driver,

So do you have any suggestion for the better location of the GTDT code?

Great thanks for your help.

>
> What you are really saying is that you want the driver instantiation
> to be moved into the driver.
>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-26 16:27               ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-26 16:27 UTC (permalink / raw)
  To: Will Deacon
  Cc: Guenter Roeck, Ashwin Chaugule,
	suravee.suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA

On 26 May 2015 at 23:36, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On Tue, May 26, 2015 at 04:18:42PM +0100, Will Deacon wrote:
>> On Tue, May 26, 2015 at 04:02:56PM +0100, Ashwin Chaugule wrote:
>> > On 26 May 2015 at 08:28, Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org> wrote:
>> > > On Mon, May 25, 2015 at 11:03:13AM +0100, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>> > >> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> > >>
>> > >> 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.
>> > >>
>> > >> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
>> > >> Tested-by: Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
>> > >> Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> > >> ---
>> > >>  arch/arm64/kernel/acpi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
>> > >>  1 file changed, 145 insertions(+)
>> > >
>> > > Why does this all need to be under arch/arm64? The GTDT really isn't
>> > > architecture-specific, so I'd *much* rather it was parsed in the driver code
>> > > itself, like we already do for the architected timer. The GIC is an
>> > > exception because it's in the MADT, which we need to parse in the arch code
>> > > to configure SMP properly.
>> >
>> > I'm not really against refactoring the code. But the GTDT looks quite
>> > specific to ARM..
>> >
>> > ---8<----
>> > 5.2.24 Generic Timer Description Table (GTDT)
>> > This section describes the format of the Generic Timer Description
>> > Table (GTDT), which provides
>> > OSPM with information about a system’s Generic Timers configuration.
>> > The Generic Timer (GT) is
>> > a standard timer interface implemented on ARM processor-based systems.
>> > The GT hardware
>> > specification can be found at Links to ACPI-Related Documents
>> > (http://uefi.org/acpi) under the
>> > heading ARM Architecture. The GTDT provides OSPM with information
>> > about a system's GT
>> > interrupt configurations, for both per-processor timers, and platform
>> > (memory-mapped) timers.
>> > The GT specification defines the following per-processor timers:
>> > • Secure privilege level 1 (EL1) timer,
>> > • Non-Secure EL1 timer,
>> > • Non-Secure privilege level 2 (EL2) timer,
>> > • Virtual timer,
>> > and the following Platform (memory-mapped) timers.
>> > • GT Block
>> > • Server Base System Architecture (SBSA) Generic Watchdog
>> > ---8<----
>>
>> Sure, the device it describes may only ever exist on ARM systems, but by
>> that logic then we should be moving lots of drivers back under arch/arm[64].
>>
> It is nt the driver, but its instantiation. The question here would be
> how and where to instantiate the driver, not where the driver itself
> is located. The driver itself is ACPI agnostic.

Hi Will,

I really don't mind to refactor the code, If we can make this patch better.

But for now, I can't see the good reason to move ACPI-relevant code
into a watchdog driver.

The reasons I put the code here are
(1)SBSA watchdog only for ARM64
(2)GTDT only for ARM, design for ARM,
(3)For ARM Architecture, only ARM64 support ACPI.

For minimizing arch/arm64/kernel/acpi.c, we can't put the code here,
and we had better keep these code outside the driver,

So do you have any suggestion for the better location of the GTDT code?

Great thanks for your help.

>
> What you are really saying is that you want the driver instantiation
> to be moved into the driver.
>
> 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
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
  2015-05-26  8:28     ` Hanjun Guo
@ 2015-05-26 16:35       ` Timur Tabi
  2015-05-26 18:24           ` Guenter Roeck
  2015-05-27  3:01         ` Hanjun Guo
  0 siblings, 2 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-26 16:35 UTC (permalink / raw)
  To: Hanjun Guo, fu.wei, Suravee.Suthikulpanit, linaro-acpi,
	linux-watchdog, devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, ashwin.chaugule, arnd,
	linux, vgandhi, wim, jcm, leo.duran, corbet, mark.rutland,
	catalin.marinas, will.deacon

On 05/26/2015 03:28 AM, Hanjun Guo wrote:

>>       early_acpi_os_unmap_memory((char *)table, tbl_size);
>>   }
>
> please add
>
> #ifdef CONFIG_ARM_SBSA_WATCHDOG
> (acpi gtdt code)
> #endif

I don't agree with this.  The GTDT should be parsed even if there's no 
watchdog driver compiled for this kernel.  There are no other #ifdefs in 
this file.

>> +     * Add a platform device named "sbsa-gwdt" to match the platform
>> driver.
>> +     * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic
>> Watchdog
>> +     * The platform driver can get device info below by matching this
>> name.
>
> * The platform driver (drivers/watchdog/sbsa_gwdt.c) can get device info
> below by matching this name.
>
> Adding the file name which will help for review and maintain in my
> opinion.

Except it will cause problems if the driver is renamed or moved.  I 
don't think this is a good idea, either (sorry!)

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-25 10:03   ` [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver fu.wei
  2015-05-25 19:39       ` Guenter Roeck
@ 2015-05-26 16:50     ` Timur Tabi
  2015-05-29 10:17         ` Fu Wei
  1 sibling, 1 reply; 550+ messages in thread
From: Timur Tabi @ 2015-05-26 16:50 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon

On 05/25/2015 05:03 AM, fu.wei@linaro.org wrote:

> +/*
> + * help functions for accessing 32bit registers of SBSA Generic Watchdog
> + */
> +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);
> +}

I don't understand the value of these functions.  You're just adding 
overhead to each read and write by dereferencing wdd every time.  I 
would get rid of them and just call readl_relaxed() and writel_relaxed() 
directly.

> +/*
> + * help functions 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));

Please add a comment indicating that you're trying to read WCV atomically.

> +
> +	return (((u64)wcv_hi << 32) | wcv_lo);
> +}

How about defining this macro:

#define make64(high, low) (((u64)(high) << 32) | (low))

and using it instead?  That makes the code easier to read.

> +
> +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;

Use upper_32_bits() and lower_32_bits() instead.

> +
> +	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)

This should be sbsa_gwdt_reload_timeout_to_wcv()

> +{
> +	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);

Shouldn't you program WCV and WOR together?

> +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);

Why not just ping the watchdog explicitely?

> +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)

This should always be true.  Instead of reading WCS, I think you should 
just panic().

> +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;
> +
> +	/*
> +	 * Get the frequency of system counter from
> +	 * the cp15 interface of ARM Generic timer
> +	 */
> +	clk = arch_timer_get_cntfrq();
> +	if (!clk) {

You have

	depends on ARM_ARCH_TIMER

in your Kconfig, so you don't need to check the return of 
arch_timer_get_cntfrq().  It can never be zero.

Also, I would not use the variable name 'clk', because that's usually 
used for a "struct clk" object.  I would call this "freq" instead.

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-26 18:24           ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-26 18:24 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Hanjun Guo, fu.wei, Suravee.Suthikulpanit, linaro-acpi,
	linux-watchdog, devicetree, linux-kernel, linux-doc,
	tekkamanninja, graeme.gregory, al.stone, ashwin.chaugule, arnd,
	vgandhi, wim, jcm, leo.duran, corbet, mark.rutland,
	catalin.marinas, will.deacon

On Tue, May 26, 2015 at 11:35:19AM -0500, Timur Tabi wrote:
> On 05/26/2015 03:28 AM, Hanjun Guo wrote:
> 
> >>      early_acpi_os_unmap_memory((char *)table, tbl_size);
> >>  }
> >
> >please add
> >
> >#ifdef CONFIG_ARM_SBSA_WATCHDOG
> >(acpi gtdt code)
> >#endif
> 
> I don't agree with this.  The GTDT should be parsed even if there's no
> watchdog driver compiled for this kernel.  There are no other #ifdefs in
> this file.
> 

Me not either, but then I thought this is really a maintainer question.
If the maintainers want out-of-subsystem #ifdefs in the code, who am I
to complain.

Should be "#if IS_ENABLED(CONFIG_ARM_SBSA_WATCHDOG)", though, if we go
along that route.

Guenter

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-26 18:24           ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-26 18:24 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Hanjun Guo, fu.wei-QSEj5FYQhm4dnm+yROfE0A,
	Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	corbet-T1hC0tSOHrs, mark.rutland-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8

On Tue, May 26, 2015 at 11:35:19AM -0500, Timur Tabi wrote:
> On 05/26/2015 03:28 AM, Hanjun Guo wrote:
> 
> >>      early_acpi_os_unmap_memory((char *)table, tbl_size);
> >>  }
> >
> >please add
> >
> >#ifdef CONFIG_ARM_SBSA_WATCHDOG
> >(acpi gtdt code)
> >#endif
> 
> I don't agree with this.  The GTDT should be parsed even if there's no
> watchdog driver compiled for this kernel.  There are no other #ifdefs in
> this file.
> 

Me not either, but then I thought this is really a maintainer question.
If the maintainers want out-of-subsystem #ifdefs in the code, who am I
to complain.

Should be "#if IS_ENABLED(CONFIG_ARM_SBSA_WATCHDOG)", though, if we go
along that route.

Guenter
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
  2015-05-26 16:35       ` Timur Tabi
  2015-05-26 18:24           ` Guenter Roeck
@ 2015-05-27  3:01         ` Hanjun Guo
  2015-05-27  3:08             ` Timur Tabi
  1 sibling, 1 reply; 550+ messages in thread
From: Hanjun Guo @ 2015-05-27  3:01 UTC (permalink / raw)
  To: Timur Tabi, fu.wei, Suravee.Suthikulpanit, linaro-acpi,
	linux-watchdog, devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, ashwin.chaugule, arnd,
	linux, vgandhi, wim, jcm, leo.duran, corbet, mark.rutland,
	catalin.marinas, will.deacon

On 2015年05月27日 00:35, Timur Tabi wrote:
> On 05/26/2015 03:28 AM, Hanjun Guo wrote:
>
>>>       early_acpi_os_unmap_memory((char *)table, tbl_size);
>>>   }
>>
>> please add
>>
>> #ifdef CONFIG_ARM_SBSA_WATCHDOG
>> (acpi gtdt code)
>> #endif
>
> I don't agree with this.  The GTDT should be parsed even if there's no
> watchdog driver compiled for this kernel.  There are no other #ifdefs in
> this file.

So what's the point of parse GTDT and alloc memories for it if there
is no watchdog driver compiled for the kernel? will the module insmod
later even if the CONFIG_ARM_SBSA_WATCHDOG=n?

>
>>> +     * Add a platform device named "sbsa-gwdt" to match the platform
>>> driver.
>>> +     * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic
>>> Watchdog
>>> +     * The platform driver can get device info below by matching this
>>> name.
>>
>> * The platform driver (drivers/watchdog/sbsa_gwdt.c) can get device info
>> below by matching this name.
>>
>> Adding the file name which will help for review and maintain in my
>> opinion.
>
> Except it will cause problems if the driver is renamed or moved.  I
> don't think this is a good idea, either (sorry!)

OK, that's good point. but what I proposed is some hint to which driver
will use the data prepared in this file, we can easily understand it
in this patchset, but if just review the code in this fiel, I think
people will be confused without detail comments.

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-27  3:08             ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-27  3:08 UTC (permalink / raw)
  To: Hanjun Guo, fu.wei, Suravee.Suthikulpanit, linaro-acpi,
	linux-watchdog, devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, ashwin.chaugule, arnd,
	linux, vgandhi, wim, jcm, leo.duran, corbet, mark.rutland,
	catalin.marinas, will.deacon

Hanjun Guo wrote:
>> I don't agree with this.  The GTDT should be parsed even if there's no
>> watchdog driver compiled for this kernel.  There are no other #ifdefs in
>> this file.
>
> So what's the point of parse GTDT and alloc memories for it if there
> is no watchdog driver compiled for the kernel?

I don't think it's normal policy to generate a platform only if one 
specific driver is enabled.

 > will the module insmod
> later even if the CONFIG_ARM_SBSA_WATCHDOG=n?

I think that actually can work, but it's not a good reason by itself.

> OK, that's good point. but what I proposed is some hint to which driver
> will use the data prepared in this file, we can easily understand it
> in this patchset, but if just review the code in this fiel, I think
> people will be confused without detail comments.

All anyone needs to is

	git grep "sbsa-gwdt"

And you'll find the 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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-27  3:08             ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-27  3:08 UTC (permalink / raw)
  To: Hanjun Guo, fu.wei-QSEj5FYQhm4dnm+yROfE0A,
	Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8

Hanjun Guo wrote:
>> I don't agree with this.  The GTDT should be parsed even if there's no
>> watchdog driver compiled for this kernel.  There are no other #ifdefs in
>> this file.
>
> So what's the point of parse GTDT and alloc memories for it if there
> is no watchdog driver compiled for the kernel?

I don't think it's normal policy to generate a platform only if one 
specific driver is enabled.

 > will the module insmod
> later even if the CONFIG_ARM_SBSA_WATCHDOG=n?

I think that actually can work, but it's not a good reason by itself.

> OK, that's good point. but what I proposed is some hint to which driver
> will use the data prepared in this file, we can easily understand it
> in this patchset, but if just review the code in this fiel, I think
> people will be confused without detail comments.

All anyone needs to is

	git grep "sbsa-gwdt"

And you'll find the 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.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-27 10:44                 ` Will Deacon
  0 siblings, 0 replies; 550+ messages in thread
From: Will Deacon @ 2015-05-27 10:44 UTC (permalink / raw)
  To: Fu Wei
  Cc: Guenter Roeck, Ashwin Chaugule, suravee.suthikulpanit,
	linaro-acpi, linux-watchdog, devicetree, linux-kernel, linux-doc,
	tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur, arnd,
	vgandhi, wim, jcm, leo.duran, corbet, Mark Rutland,
	Catalin Marinas

On Tue, May 26, 2015 at 05:27:33PM +0100, Fu Wei wrote:
> On 26 May 2015 at 23:36, Guenter Roeck <linux@roeck-us.net> wrote:
> > On Tue, May 26, 2015 at 04:18:42PM +0100, Will Deacon wrote:
> >> Sure, the device it describes may only ever exist on ARM systems, but by
> >> that logic then we should be moving lots of drivers back under arch/arm[64].
> >>
> > It is nt the driver, but its instantiation. The question here would be
> > how and where to instantiate the driver, not where the driver itself
> > is located. The driver itself is ACPI agnostic.
> 
> I really don't mind to refactor the code, If we can make this patch better.
> 
> But for now, I can't see the good reason to move ACPI-relevant code
> into a watchdog driver.

I don't really mind where you move it, just as long as it's outside of
arch/arm64.

> The reasons I put the code here are
> (1)SBSA watchdog only for ARM64
> (2)GTDT only for ARM, design for ARM,
> (3)For ARM Architecture, only ARM64 support ACPI.
> 
> For minimizing arch/arm64/kernel/acpi.c, we can't put the code here,
> and we had better keep these code outside the driver,
> 
> So do you have any suggestion for the better location of the GTDT code?

I don't understand why you can't do the same as
drivers/clocksource/arm_arch_timer.c and parse the table directly in the
driver. If there are objections from the driver/subsystem maintainers then
it sounds like we need a mechanical ACPI table -> platform device
conversion in the core, like we have for device-tree.

Will

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-27 10:44                 ` Will Deacon
  0 siblings, 0 replies; 550+ messages in thread
From: Will Deacon @ 2015-05-27 10:44 UTC (permalink / raw)
  To: Fu Wei
  Cc: Guenter Roeck, Ashwin Chaugule,
	suravee.suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA

On Tue, May 26, 2015 at 05:27:33PM +0100, Fu Wei wrote:
> On 26 May 2015 at 23:36, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> > On Tue, May 26, 2015 at 04:18:42PM +0100, Will Deacon wrote:
> >> Sure, the device it describes may only ever exist on ARM systems, but by
> >> that logic then we should be moving lots of drivers back under arch/arm[64].
> >>
> > It is nt the driver, but its instantiation. The question here would be
> > how and where to instantiate the driver, not where the driver itself
> > is located. The driver itself is ACPI agnostic.
> 
> I really don't mind to refactor the code, If we can make this patch better.
> 
> But for now, I can't see the good reason to move ACPI-relevant code
> into a watchdog driver.

I don't really mind where you move it, just as long as it's outside of
arch/arm64.

> The reasons I put the code here are
> (1)SBSA watchdog only for ARM64
> (2)GTDT only for ARM, design for ARM,
> (3)For ARM Architecture, only ARM64 support ACPI.
> 
> For minimizing arch/arm64/kernel/acpi.c, we can't put the code here,
> and we had better keep these code outside the driver,
> 
> So do you have any suggestion for the better location of the GTDT code?

I don't understand why you can't do the same as
drivers/clocksource/arm_arch_timer.c and parse the table directly in the
driver. If there are objections from the driver/subsystem maintainers then
it sounds like we need a mechanical ACPI table -> platform device
conversion in the core, like we have for device-tree.

Will
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-29  9:11         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-29  9:11 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

Hi Guenter,
Great thanks,  feedback inline

On 26 May 2015 at 03:39, Guenter Roeck <linux@roeck-us.net> wrote:
> On 05/25/2015 03:03 AM, fu.wei@linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> 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, the interrupt routine run panic to save
>> system context.
>>
>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>
>
> Comments inline.
>
> Thanks,
> Guenter
>
>
>>   drivers/watchdog/Kconfig     |  11 +
>>   drivers/watchdog/Makefile    |   1 +
>>   drivers/watchdog/sbsa_gwdt.c | 474
>> +++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 486 insertions(+)
>>   create mode 100644 drivers/watchdog/sbsa_gwdt.c
>>
>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>> index e5e7c55..554f18a 100644
>> --- a/drivers/watchdog/Kconfig
>> +++ b/drivers/watchdog/Kconfig
>> @@ -152,6 +152,17 @@ 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 ARM64
>> +       depends on ARM_ARCH_TIMER
>> +       select WATCHDOG_CORE
>> +       help
>> +         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.
>> +         More details: ARM 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..0d1aff1
>> --- /dev/null
>> +++ b/drivers/watchdog/sbsa_gwdt.c
>> @@ -0,0 +1,474 @@
>> +/*
>> + * SBSA(Server Base System Architecture) Generic Watchdog driver
>> + *
>> + * Copyright (c) 2015, Linaro Ltd.
>> + * Author: Fu Wei <fu.wei@linaro.org>
>> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>> + *
>> + * 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: ARM DEN0029B - Server Base System Architecture
>> (SBSA)
>> + *
>> + * Kernel/API:                         P---------| pretimeout
>> + *               |-------------------------------T timeout
>> + * SBSA GWDT:                          P--WOR---WS1 pretimeout
>> + *               |-------WCV----------WS0~~~~~~~~T timeout
>> + */
>> +
>> +#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>
>> +#include <asm/arch_timer.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*/
>
>
> That is a bit low for a default. Is that on purpose ?
> Most drivers use 30 or 60 seconds.

That is not on purpose. will fixed them :
#define DEFAULT_TIMEOUT 30 /* seconds, the 1st + 2nd watch periods*/
#define DEFAULT_PRETIMEOUT 10 /* seconds, the 2nd watch period*/

>
>> +#define DEFAULT_PRETIMEOUT     5  /* seconds, the 2nd watch period*/
>> +
>> +static unsigned int timeout_param;
>> +module_param(timeout_param, uint, 0);
>> +MODULE_PARM_DESC(timeout_param,
>> +                "Watchdog timeout in seconds. (>=0, default="
>> +                __MODULE_STRING(DEFAULT_TIMEOUT) ")");
>> +
>
> Why _param in the module parameter names ? Seems to be redundant.

sorry, I shouldn't add _param , fixed it

>
>> +static unsigned int max_timeout_param = UINT_MAX;
>> +module_param(max_timeout_param, uint, 0);
>> +MODULE_PARM_DESC(max_timeout_param,
>> +                "Watchdog max timeout in seconds. (>=0, default="
>> +                __MODULE_STRING(UINT_MAX) ")");
>> +
>
>
> Why do we want or need this parameter and max_pretimeout ? Those
> are determined by the hardware.

Sorry, I thought we can also allow user setup a max value when insmod
the module or by boot cmdline. but I was wrong, have deleted them.

>
>
>> +static unsigned int pretimeout_param;
>> +module_param(pretimeout_param, uint, 0);
>> +MODULE_PARM_DESC(pretimeout_param,
>> +                "Watchdog pretimeout in seconds. (>=0, default="
>> +                __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
>> +
>> +static unsigned int max_pretimeout_param = U32_MAX;
>> +module_param(max_pretimeout_param, uint, 0);
>> +MODULE_PARM_DESC(max_pretimeout_param,
>> +                "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) ")");
>> +
>> +/*
>> + * help functions for accessing 32bit registers of SBSA Generic Watchdog
>> + */
>> +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 functions 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 update the 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);
>> +}
>> +
>
>
> After understanding the watchdog a bit better now, I think you should drop
> those updates and set
>         min_timeout = 1
>         max_timeout = min(UINT_MAX, U64_MAX / clk)
>         min_pretimeout = 0
>         max_pretimeout = U32_MAX / clk
>
> and then ensure that pretimeout < timeout at runtime (if possible in
> the infrastructure code).
>
> Even at maximum clock rate, max_timeout is so large that anything else
> is really overkill.

you are right, fixed it, thanks

>
>> +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;
>> +
>
>
> So in practice you always have a pretimeout of at least one second,
> correct ? That kind of violates the ABI, which says that the pretimeout
> should be disabled if set to 0. Is there anything we can do about that ?
>
> What exactly happens if WOR = 0 ? Doesn't that just mean that the second
> timeout will happen immediately, and isn't that what we would want if
> pretimeout = 0

Accroding to SBSA, in theory,
if WOR == 0, once we write WRR(refresh), we will get WS0 and WS1 immediately .
that means timeout == 0.

So I will add more comment here to explain this.

>
>> +       /* refresh the WOR, that will cause an explicit watchdog refresh
>> */
>
>
> Except that we use wcv which needs a manual refresh, so this is a bit
> misleading, isn't it ?

if we setup  wcv manually, we maybe don't need a manual refresh.
I will test it later.

>
>
>> +       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);
>
>
> Should that happen after writing wcv ?

no, if so, WOR + current_time will be loaded into wcv. I put this
before writing wcv on purpose.
maybe we can just update wcv without a force refresh.

will test it later


>
>
>> +
>> +       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;
>> +
>> +       /*
>> +        * Get the frequency of system counter from
>> +        * the cp15 interface of ARM Generic timer
>> +        */
>> +       clk = arch_timer_get_cntfrq();
>
>
> That can not return 0, presumably, from looking into its implementation.
> And the system should panic if it is ever 0.
>
>> +       if (!clk) {
>
>
> Given that, I don't think this check is necessary.

yes, you are right , I have got your point, and improved it .

>
>
>> +               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(cf_base))
>> +               return PTR_ERR(cf_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));
>
>
> Does this message (specifically the WCS / WCV values) have any
> useful meaning for the user ?

I think so, according to SBSA spec:
If WS0 is asserted and a timeout refresh occurs then the following must occur:
    If the system is compliant to SBSA level 2 or higher the compare
value must retain its current value. This means that the compare value
records the time that WS1 is asserted.

So, I think WCV can log the time when system reset by WDT, that may
help user figure out the problem. but WCS can be delete I think.


>
>> +               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);
>
>
> You have not configured wdd->timeout and wdd->pretimeout here,
> yet the function calls reload_timeout_to_wcv which needs it.

Ah, sorry, that is a bug, have reordered the code, Thanks

>
>> +       }
>> +
>> +       wdd->min_pretimeout = 0;
>> +       wdd->max_pretimeout = min(U32_MAX / clk, max_pretimeout_param);
>> +       wdd->min_timeout = 1;
>> +       do_div(first_period_max, clk);
>> +       wdd->max_timeout = min((uint)(wdd->pretimeout + first_period_max),
>> +                              max_timeout_param);
>> +
>> +       wdd->pretimeout = DEFAULT_PRETIMEOUT;
>> +       wdd->timeout = DEFAULT_TIMEOUT;
>> +       watchdog_init_timeouts(wdd, pretimeout_param, timeout_param, dev);
>> +       /* update pretimeout to WOR */
>> +       sbsa_gwdt_cf_write(SBSA_GWDT_WOR, wdd->pretimeout * clk, wdd);
>
>
> This is interesting because you set WOR to 0 here if pretimeout is 0.
> Yet, when pretimeout is updated later on, you always set it to at least
> one second. Any reason for doing this differently ?
>
> If the above works, and presumably you have tested it, I don't see why
> it would be necessary to set WOR to a value larger than 0 when updating
> pretimeout.

Ah I should tested more in extreme case, but here, I can use
sbsa_gwdt_set_pretimeout directly.


>
>> +
>> +       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);
>
>
> 400000Hz reads a bit odd. How about a space between the number and Hz ?

np, fixed it , thanks :-)

>
>> +
>> +       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);
>> +
>
> I don't think you should do anything here. The driver can only be removed
> if closed, and it that case the watchdog will already have been stopped,
> or if nowayout was set it won't be stopped. Either case it is already in
> the state we want it to be in.

Sorry, I should delete it. Fixed

>
>
>> +       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 <fu.wei@linaro.org>");
>> +MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
>> +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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-29  9:11         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-29  9:11 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

Hi Guenter,
Great thanks,  feedback inline

On 26 May 2015 at 03:39, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On 05/25/2015 03:03 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>>
>> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>
>> 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, the interrupt routine run panic to save
>> system context.
>>
>> Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
>> Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
>> Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> ---
>
>
> Comments inline.
>
> Thanks,
> Guenter
>
>
>>   drivers/watchdog/Kconfig     |  11 +
>>   drivers/watchdog/Makefile    |   1 +
>>   drivers/watchdog/sbsa_gwdt.c | 474
>> +++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 486 insertions(+)
>>   create mode 100644 drivers/watchdog/sbsa_gwdt.c
>>
>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>> index e5e7c55..554f18a 100644
>> --- a/drivers/watchdog/Kconfig
>> +++ b/drivers/watchdog/Kconfig
>> @@ -152,6 +152,17 @@ 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 ARM64
>> +       depends on ARM_ARCH_TIMER
>> +       select WATCHDOG_CORE
>> +       help
>> +         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.
>> +         More details: ARM 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..0d1aff1
>> --- /dev/null
>> +++ b/drivers/watchdog/sbsa_gwdt.c
>> @@ -0,0 +1,474 @@
>> +/*
>> + * SBSA(Server Base System Architecture) Generic Watchdog driver
>> + *
>> + * Copyright (c) 2015, Linaro Ltd.
>> + * Author: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
>> + *
>> + * 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: ARM DEN0029B - Server Base System Architecture
>> (SBSA)
>> + *
>> + * Kernel/API:                         P---------| pretimeout
>> + *               |-------------------------------T timeout
>> + * SBSA GWDT:                          P--WOR---WS1 pretimeout
>> + *               |-------WCV----------WS0~~~~~~~~T timeout
>> + */
>> +
>> +#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>
>> +#include <asm/arch_timer.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*/
>
>
> That is a bit low for a default. Is that on purpose ?
> Most drivers use 30 or 60 seconds.

That is not on purpose. will fixed them :
#define DEFAULT_TIMEOUT 30 /* seconds, the 1st + 2nd watch periods*/
#define DEFAULT_PRETIMEOUT 10 /* seconds, the 2nd watch period*/

>
>> +#define DEFAULT_PRETIMEOUT     5  /* seconds, the 2nd watch period*/
>> +
>> +static unsigned int timeout_param;
>> +module_param(timeout_param, uint, 0);
>> +MODULE_PARM_DESC(timeout_param,
>> +                "Watchdog timeout in seconds. (>=0, default="
>> +                __MODULE_STRING(DEFAULT_TIMEOUT) ")");
>> +
>
> Why _param in the module parameter names ? Seems to be redundant.

sorry, I shouldn't add _param , fixed it

>
>> +static unsigned int max_timeout_param = UINT_MAX;
>> +module_param(max_timeout_param, uint, 0);
>> +MODULE_PARM_DESC(max_timeout_param,
>> +                "Watchdog max timeout in seconds. (>=0, default="
>> +                __MODULE_STRING(UINT_MAX) ")");
>> +
>
>
> Why do we want or need this parameter and max_pretimeout ? Those
> are determined by the hardware.

Sorry, I thought we can also allow user setup a max value when insmod
the module or by boot cmdline. but I was wrong, have deleted them.

>
>
>> +static unsigned int pretimeout_param;
>> +module_param(pretimeout_param, uint, 0);
>> +MODULE_PARM_DESC(pretimeout_param,
>> +                "Watchdog pretimeout in seconds. (>=0, default="
>> +                __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
>> +
>> +static unsigned int max_pretimeout_param = U32_MAX;
>> +module_param(max_pretimeout_param, uint, 0);
>> +MODULE_PARM_DESC(max_pretimeout_param,
>> +                "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) ")");
>> +
>> +/*
>> + * help functions for accessing 32bit registers of SBSA Generic Watchdog
>> + */
>> +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 functions 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 update the 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);
>> +}
>> +
>
>
> After understanding the watchdog a bit better now, I think you should drop
> those updates and set
>         min_timeout = 1
>         max_timeout = min(UINT_MAX, U64_MAX / clk)
>         min_pretimeout = 0
>         max_pretimeout = U32_MAX / clk
>
> and then ensure that pretimeout < timeout at runtime (if possible in
> the infrastructure code).
>
> Even at maximum clock rate, max_timeout is so large that anything else
> is really overkill.

you are right, fixed it, thanks

>
>> +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;
>> +
>
>
> So in practice you always have a pretimeout of at least one second,
> correct ? That kind of violates the ABI, which says that the pretimeout
> should be disabled if set to 0. Is there anything we can do about that ?
>
> What exactly happens if WOR = 0 ? Doesn't that just mean that the second
> timeout will happen immediately, and isn't that what we would want if
> pretimeout = 0

Accroding to SBSA, in theory,
if WOR == 0, once we write WRR(refresh), we will get WS0 and WS1 immediately .
that means timeout == 0.

So I will add more comment here to explain this.

>
>> +       /* refresh the WOR, that will cause an explicit watchdog refresh
>> */
>
>
> Except that we use wcv which needs a manual refresh, so this is a bit
> misleading, isn't it ?

if we setup  wcv manually, we maybe don't need a manual refresh.
I will test it later.

>
>
>> +       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);
>
>
> Should that happen after writing wcv ?

no, if so, WOR + current_time will be loaded into wcv. I put this
before writing wcv on purpose.
maybe we can just update wcv without a force refresh.

will test it later


>
>
>> +
>> +       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;
>> +
>> +       /*
>> +        * Get the frequency of system counter from
>> +        * the cp15 interface of ARM Generic timer
>> +        */
>> +       clk = arch_timer_get_cntfrq();
>
>
> That can not return 0, presumably, from looking into its implementation.
> And the system should panic if it is ever 0.
>
>> +       if (!clk) {
>
>
> Given that, I don't think this check is necessary.

yes, you are right , I have got your point, and improved it .

>
>
>> +               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(cf_base))
>> +               return PTR_ERR(cf_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));
>
>
> Does this message (specifically the WCS / WCV values) have any
> useful meaning for the user ?

I think so, according to SBSA spec:
If WS0 is asserted and a timeout refresh occurs then the following must occur:
    If the system is compliant to SBSA level 2 or higher the compare
value must retain its current value. This means that the compare value
records the time that WS1 is asserted.

So, I think WCV can log the time when system reset by WDT, that may
help user figure out the problem. but WCS can be delete I think.


>
>> +               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);
>
>
> You have not configured wdd->timeout and wdd->pretimeout here,
> yet the function calls reload_timeout_to_wcv which needs it.

Ah, sorry, that is a bug, have reordered the code, Thanks

>
>> +       }
>> +
>> +       wdd->min_pretimeout = 0;
>> +       wdd->max_pretimeout = min(U32_MAX / clk, max_pretimeout_param);
>> +       wdd->min_timeout = 1;
>> +       do_div(first_period_max, clk);
>> +       wdd->max_timeout = min((uint)(wdd->pretimeout + first_period_max),
>> +                              max_timeout_param);
>> +
>> +       wdd->pretimeout = DEFAULT_PRETIMEOUT;
>> +       wdd->timeout = DEFAULT_TIMEOUT;
>> +       watchdog_init_timeouts(wdd, pretimeout_param, timeout_param, dev);
>> +       /* update pretimeout to WOR */
>> +       sbsa_gwdt_cf_write(SBSA_GWDT_WOR, wdd->pretimeout * clk, wdd);
>
>
> This is interesting because you set WOR to 0 here if pretimeout is 0.
> Yet, when pretimeout is updated later on, you always set it to at least
> one second. Any reason for doing this differently ?
>
> If the above works, and presumably you have tested it, I don't see why
> it would be necessary to set WOR to a value larger than 0 when updating
> pretimeout.

Ah I should tested more in extreme case, but here, I can use
sbsa_gwdt_set_pretimeout directly.


>
>> +
>> +       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);
>
>
> 400000Hz reads a bit odd. How about a space between the number and Hz ?

np, fixed it , thanks :-)

>
>> +
>> +       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);
>> +
>
> I don't think you should do anything here. The driver can only be removed
> if closed, and it that case the watchdog will already have been stopped,
> or if nowayout was set it won't be stopped. Either case it is already in
> the state we want it to be in.

Sorry, I should delete it. Fixed

>
>
>> +       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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>");
>> +MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>");
>> +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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-29 10:17         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-29 10:17 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

Hi Timur,

On 27 May 2015 at 00:50, Timur Tabi <timur@codeaurora.org> wrote:
> On 05/25/2015 05:03 AM, fu.wei@linaro.org wrote:
>
>> +/*
>> + * help functions for accessing 32bit registers of SBSA Generic Watchdog
>> + */
>> +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);
>> +}
>
>
> I don't understand the value of these functions.  You're just adding
> overhead to each read and write by dereferencing wdd every time.  I would
> get rid of them and just call readl_relaxed() and writel_relaxed() directly.

yes, that makes sense, sometimes , I also feel these functions are a
little redundant,
let me see if I can improve it.

>
>> +/*
>> + * help functions 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));
>
>
> Please add a comment indicating that you're trying to read WCV atomically.

OK , that makes sense

>
>> +
>> +       return (((u64)wcv_hi << 32) | wcv_lo);
>> +}
>
>
> How about defining this macro:
>
> #define make64(high, low) (((u64)(high) << 32) | (low))
>
> and using it instead?  That makes the code easier to read.

good idea, but it's  just  used once, not sure if it's worthy
Actually, I have seen some macro in some driver, but not in kernel header file.

>
>> +
>> +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;
>
>
> Use upper_32_bits() and lower_32_bits() instead.

cool, thanks ,  fixed it

>
>> +
>> +       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)
>
>
> This should be sbsa_gwdt_reload_timeout_to_wcv()
>
>> +{
>> +       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);
>
>
> Shouldn't you program WCV and WOR together?

why? WOR just for pretimeout in this driver.

>
>> +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);
>
>
> Why not just ping the watchdog explicitely?

we just setup WOR, but we don't need to load pretimeout to WCV now, right ?

>
>> +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)
>
>
> This should always be true.  Instead of reading WCS, I think you should just
> panic().

I thinks I need to confirm it , in case this has been cleaned.

>
>> +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;
>> +
>> +       /*
>> +        * Get the frequency of system counter from
>> +        * the cp15 interface of ARM Generic timer
>> +        */
>> +       clk = arch_timer_get_cntfrq();
>> +       if (!clk) {
>
>
> You have
>
>         depends on ARM_ARCH_TIMER
>
> in your Kconfig, so you don't need to check the return of
> arch_timer_get_cntfrq().  It can never be zero.
>
> Also, I would not use the variable name 'clk', because that's usually used
> for a "struct clk" object.  I would call this "freq" instead.

yes, I have fixed it .

>
>
> --
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-29 10:17         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-29 10:17 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

Hi Timur,

On 27 May 2015 at 00:50, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
> On 05/25/2015 05:03 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>
>> +/*
>> + * help functions for accessing 32bit registers of SBSA Generic Watchdog
>> + */
>> +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);
>> +}
>
>
> I don't understand the value of these functions.  You're just adding
> overhead to each read and write by dereferencing wdd every time.  I would
> get rid of them and just call readl_relaxed() and writel_relaxed() directly.

yes, that makes sense, sometimes , I also feel these functions are a
little redundant,
let me see if I can improve it.

>
>> +/*
>> + * help functions 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));
>
>
> Please add a comment indicating that you're trying to read WCV atomically.

OK , that makes sense

>
>> +
>> +       return (((u64)wcv_hi << 32) | wcv_lo);
>> +}
>
>
> How about defining this macro:
>
> #define make64(high, low) (((u64)(high) << 32) | (low))
>
> and using it instead?  That makes the code easier to read.

good idea, but it's  just  used once, not sure if it's worthy
Actually, I have seen some macro in some driver, but not in kernel header file.

>
>> +
>> +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;
>
>
> Use upper_32_bits() and lower_32_bits() instead.

cool, thanks ,  fixed it

>
>> +
>> +       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)
>
>
> This should be sbsa_gwdt_reload_timeout_to_wcv()
>
>> +{
>> +       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);
>
>
> Shouldn't you program WCV and WOR together?

why? WOR just for pretimeout in this driver.

>
>> +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);
>
>
> Why not just ping the watchdog explicitely?

we just setup WOR, but we don't need to load pretimeout to WCV now, right ?

>
>> +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)
>
>
> This should always be true.  Instead of reading WCS, I think you should just
> panic().

I thinks I need to confirm it , in case this has been cleaned.

>
>> +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;
>> +
>> +       /*
>> +        * Get the frequency of system counter from
>> +        * the cp15 interface of ARM Generic timer
>> +        */
>> +       clk = arch_timer_get_cntfrq();
>> +       if (!clk) {
>
>
> You have
>
>         depends on ARM_ARCH_TIMER
>
> in your Kconfig, so you don't need to check the return of
> arch_timer_get_cntfrq().  It can never be zero.
>
> Also, I would not use the variable name 'clk', because that's usually used
> for a "struct clk" object.  I would call this "freq" instead.

yes, I have fixed it .

>
>
> --
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-29 11:13                   ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-29 11:13 UTC (permalink / raw)
  To: Will Deacon
  Cc: Guenter Roeck, Ashwin Chaugule, suravee.suthikulpanit,
	linaro-acpi, linux-watchdog, devicetree, linux-kernel, linux-doc,
	tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur, arnd,
	vgandhi, wim, jcm, leo.duran, corbet, Mark Rutland,
	Catalin Marinas

Hi Will,

As you know, I have moved all the GTDT code to ACPI driver , and
simplify the GTDT relevant code in arm_arch_timer.c. That will be in
my next patchset.
but you can check here :
https://git.linaro.org/people/fu.wei/linux.git/shortlog/refs/heads/acpi-topic-sbsa-watchdog_upstream_v4_devel

Great thanks for your suggestion!

On 27 May 2015 at 18:44, Will Deacon <will.deacon@arm.com> wrote:
> On Tue, May 26, 2015 at 05:27:33PM +0100, Fu Wei wrote:
>> On 26 May 2015 at 23:36, Guenter Roeck <linux@roeck-us.net> wrote:
>> > On Tue, May 26, 2015 at 04:18:42PM +0100, Will Deacon wrote:
>> >> Sure, the device it describes may only ever exist on ARM systems, but by
>> >> that logic then we should be moving lots of drivers back under arch/arm[64].
>> >>
>> > It is nt the driver, but its instantiation. The question here would be
>> > how and where to instantiate the driver, not where the driver itself
>> > is located. The driver itself is ACPI agnostic.
>>
>> I really don't mind to refactor the code, If we can make this patch better.
>>
>> But for now, I can't see the good reason to move ACPI-relevant code
>> into a watchdog driver.
>
> I don't really mind where you move it, just as long as it's outside of
> arch/arm64.
>
>> The reasons I put the code here are
>> (1)SBSA watchdog only for ARM64
>> (2)GTDT only for ARM, design for ARM,
>> (3)For ARM Architecture, only ARM64 support ACPI.
>>
>> For minimizing arch/arm64/kernel/acpi.c, we can't put the code here,
>> and we had better keep these code outside the driver,
>>
>> So do you have any suggestion for the better location of the GTDT code?
>
> I don't understand why you can't do the same as
> drivers/clocksource/arm_arch_timer.c and parse the table directly in the
> driver. If there are objections from the driver/subsystem maintainers then
> it sounds like we need a mechanical ACPI table -> platform device
> conversion in the core, like we have for device-tree.
>
> Will



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device
@ 2015-05-29 11:13                   ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-29 11:13 UTC (permalink / raw)
  To: Will Deacon
  Cc: Guenter Roeck, Ashwin Chaugule,
	suravee.suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA

Hi Will,

As you know, I have moved all the GTDT code to ACPI driver , and
simplify the GTDT relevant code in arm_arch_timer.c. That will be in
my next patchset.
but you can check here :
https://git.linaro.org/people/fu.wei/linux.git/shortlog/refs/heads/acpi-topic-sbsa-watchdog_upstream_v4_devel

Great thanks for your suggestion!

On 27 May 2015 at 18:44, Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org> wrote:
> On Tue, May 26, 2015 at 05:27:33PM +0100, Fu Wei wrote:
>> On 26 May 2015 at 23:36, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
>> > On Tue, May 26, 2015 at 04:18:42PM +0100, Will Deacon wrote:
>> >> Sure, the device it describes may only ever exist on ARM systems, but by
>> >> that logic then we should be moving lots of drivers back under arch/arm[64].
>> >>
>> > It is nt the driver, but its instantiation. The question here would be
>> > how and where to instantiate the driver, not where the driver itself
>> > is located. The driver itself is ACPI agnostic.
>>
>> I really don't mind to refactor the code, If we can make this patch better.
>>
>> But for now, I can't see the good reason to move ACPI-relevant code
>> into a watchdog driver.
>
> I don't really mind where you move it, just as long as it's outside of
> arch/arm64.
>
>> The reasons I put the code here are
>> (1)SBSA watchdog only for ARM64
>> (2)GTDT only for ARM, design for ARM,
>> (3)For ARM Architecture, only ARM64 support ACPI.
>>
>> For minimizing arch/arm64/kernel/acpi.c, we can't put the code here,
>> and we had better keep these code outside the driver,
>>
>> So do you have any suggestion for the better location of the GTDT code?
>
> I don't understand why you can't do the same as
> drivers/clocksource/arm_arch_timer.c and parse the table directly in the
> driver. If there are objections from the driver/subsystem maintainers then
> it sounds like we need a mechanical ACPI table -> platform device
> conversion in the core, like we have for device-tree.
>
> Will



-- 
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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-29 13:28           ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-29 13:28 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

Fu Wei wrote:
>> This should always be true.  Instead of reading WCS, I think you should just
>> >panic().

> I thinks I need to confirm it , in case this has been cleaned.

I don't see how it's possible for you to receive the interrupt and have 
WCS be cleared.

-- 
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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-29 13:28           ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-29 13:28 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

Fu Wei wrote:
>> This should always be true.  Instead of reading WCS, I think you should just
>> >panic().

> I thinks I need to confirm it , in case this has been cleaned.

I don't see how it's possible for you to receive the interrupt and have 
WCS be cleared.

-- 
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.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-29 14:32             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-29 14:32 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

Hi Timur

On 29 May 2015 at 21:28, Timur Tabi <timur@codeaurora.org> wrote:
> Fu Wei wrote:
>>>
>>> This should always be true.  Instead of reading WCS, I think you should
>>> just
>>> >panic().
>
>
>> I thinks I need to confirm it , in case this has been cleaned.
>
>
> I don't see how it's possible for you to receive the interrupt and have WCS
> be cleared.

It is a SPI, every CPU can get it,
But maybe I miss something, but please let me know if other CPU can
not get the interrupt.

>
> --
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-29 14:32             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-29 14:32 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

Hi Timur

On 29 May 2015 at 21:28, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
> Fu Wei wrote:
>>>
>>> This should always be true.  Instead of reading WCS, I think you should
>>> just
>>> >panic().
>
>
>> I thinks I need to confirm it , in case this has been cleaned.
>
>
> I don't see how it's possible for you to receive the interrupt and have WCS
> be cleared.

It is a SPI, every CPU can get it,
But maybe I miss something, but please let me know if other CPU can
not get the interrupt.

>
> --
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-29  9:11         ` Fu Wei
  (?)
@ 2015-05-29 14:54         ` Guenter Roeck
  2015-05-29 15:05           ` Fu Wei
  -1 siblings, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-05-29 14:54 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

On 05/29/2015 02:11 AM, Fu Wei wrote:
[ ... ]

>>> +
>>> +       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));
>>
>>
>> Does this message (specifically the WCS / WCV values) have any
>> useful meaning for the user ?
>
> I think so, according to SBSA spec:
> If WS0 is asserted and a timeout refresh occurs then the following must occur:
>      If the system is compliant to SBSA level 2 or higher the compare
> value must retain its current value. This means that the compare value
> records the time that WS1 is asserted.
>
> So, I think WCV can log the time when system reset by WDT, that may
> help user figure out the problem. but WCS can be delete I think.
>

How would that help ? It is just a number with no reference to anything.

Thanks,
Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-29 14:54         ` Guenter Roeck
@ 2015-05-29 15:05           ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-05-29 15:05 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

Hi Guenter,



On 29 May 2015 at 22:54, Guenter Roeck <linux@roeck-us.net> wrote:
> On 05/29/2015 02:11 AM, Fu Wei wrote:
> [ ... ]
>
>>>> +
>>>> +       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));
>>>
>>>
>>>
>>> Does this message (specifically the WCS / WCV values) have any
>>> useful meaning for the user ?
>>
>>
>> I think so, according to SBSA spec:
>> If WS0 is asserted and a timeout refresh occurs then the following must
>> occur:
>>      If the system is compliant to SBSA level 2 or higher the compare
>> value must retain its current value. This means that the compare value
>> records the time that WS1 is asserted.
>>
>> So, I think WCV can log the time when system reset by WDT, that may
>> help user figure out the problem. but WCS can be delete I think.
>>
>
> How would that help ? It is just a number with no reference to anything.

This number is the time, when system reset by watchdog
WCV : the number of clock, from system boot  to system reset.
Is that worthy to be logged? any suggestion ? :-)

>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-29 15:46               ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-29 15:46 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

On 05/29/2015 09:32 AM, Fu Wei wrote:
> It is a SPI, every CPU can get it,
> But maybe I miss something, but please let me know if other CPU can
> not get the interrupt.

There's only one watchdog device, so there's only one interrupt.  I 
don't know which CPU will get the interrupt, but the watchdog is not a 
per-CPU device.

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-29 15:46               ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-29 15:46 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

On 05/29/2015 09:32 AM, Fu Wei wrote:
> It is a SPI, every CPU can get it,
> But maybe I miss something, but please let me know if other CPU can
> not get the interrupt.

There's only one watchdog device, so there's only one interrupt.  I 
don't know which CPU will get the interrupt, but the watchdog is not a 
per-CPU device.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-29 15:46               ` Timur Tabi
  (?)
@ 2015-05-29 17:53               ` Fu Wei
  2015-05-29 18:27                   ` Timur Tabi
  -1 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-05-29 17:53 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

Hi Timur

On 29 May 2015 at 23:46, Timur Tabi <timur@codeaurora.org> wrote:
> On 05/29/2015 09:32 AM, Fu Wei wrote:
>>
>> It is a SPI, every CPU can get it,
>> But maybe I miss something, but please let me know if other CPU can
>> not get the interrupt.
>
>
> There's only one watchdog device, so there's only one interrupt.  I don't
> know which CPU will get the interrupt, but the watchdog is not a per-CPU
> device.
>

OK, first of all, I know, there maybe only watchdog in the system, but
the Interrupter is SPI,
that means maybe some other device can also trigger the same
Interrupter or maybe(in SMP) other CPU will handle it.

If this interrupter is triggered, that means system has goes wrong,
who knows what is wrong ,
I have to make sure that  system get into that routine ,because of the
WS0, if not I won't do panic.

And in a interrupter routine , checking the Interrupter status
register is right way to do.


> --
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-29 18:27                   ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-29 18:27 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

On 05/29/2015 12:53 PM, Fu Wei wrote:
> If this interrupter is triggered, that means system has goes wrong,
> who knows what is wrong ,
> I have to make sure that  system get into that routine ,because of the
> WS0, if not I won't do panic.

But the interrupt handler is not registered as shared, which means that 
it cannot be generated by another device.

> And in a interrupter routine , checking the Interrupter status
> register is right way to do.

If you get an interrupt, but WS0 is not set, then you should return 
IRQ_NONE instead of IRQ_HANDLED.

Also, I don't think IRQF_TIMER is correct.  It's not a timer interrupt. 
  Watchdogs are *not* timers.

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-29 18:27                   ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-05-29 18:27 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

On 05/29/2015 12:53 PM, Fu Wei wrote:
> If this interrupter is triggered, that means system has goes wrong,
> who knows what is wrong ,
> I have to make sure that  system get into that routine ,because of the
> WS0, if not I won't do panic.

But the interrupt handler is not registered as shared, which means that 
it cannot be generated by another device.

> And in a interrupter routine , checking the Interrupter status
> register is right way to do.

If you get an interrupt, but WS0 is not set, then you should return 
IRQ_NONE instead of IRQ_HANDLED.

Also, I don't think IRQF_TIMER is correct.  It's not a timer interrupt. 
  Watchdogs are *not* timers.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-29 22:10                 ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-29 22:10 UTC (permalink / raw)
  To: Timur Tabi, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

On 05/29/2015 08:46 AM, Timur Tabi wrote:
> On 05/29/2015 09:32 AM, Fu Wei wrote:
>> It is a SPI, every CPU can get it,
>> But maybe I miss something, but please let me know if other CPU can
>> not get the interrupt.
>
> There's only one watchdog device, so there's only one interrupt.  I don't know which CPU will get the interrupt, but the watchdog is not a per-CPU device.
>
Plus, that one interrupt is not shared, and the driver returns
IRQ_HANDLED even if the bit is not set. So _something_ is definitely
wrong. Either the interrupt is shared, then it needs to be requested
as shared and the handler should only return IRQ_HANDLED if it actually
handles the interrupt. Or it is not shared and the handler should always
handle it.

Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-05-29 22:10                 ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-05-29 22:10 UTC (permalink / raw)
  To: Timur Tabi, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

On 05/29/2015 08:46 AM, Timur Tabi wrote:
> On 05/29/2015 09:32 AM, Fu Wei wrote:
>> It is a SPI, every CPU can get it,
>> But maybe I miss something, but please let me know if other CPU can
>> not get the interrupt.
>
> There's only one watchdog device, so there's only one interrupt.  I don't know which CPU will get the interrupt, but the watchdog is not a per-CPU device.
>
Plus, that one interrupt is not shared, and the driver returns
IRQ_HANDLED even if the bit is not set. So _something_ is definitely
wrong. Either the interrupt is shared, then it needs to be requested
as shared and the handler should only return IRQ_HANDLED if it actually
handles the interrupt. Or it is not shared and the handler should always
handle it.

Guenter

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver
  2015-05-29 22:10                 ` Guenter Roeck
  (?)
@ 2015-06-01  7:50                 ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-01  7:50 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon

Hi Guenter , Timur

On 30 May 2015 at 06:10, Guenter Roeck <linux@roeck-us.net> wrote:
> On 05/29/2015 08:46 AM, Timur Tabi wrote:
>>
>> On 05/29/2015 09:32 AM, Fu Wei wrote:
>>>
>>> It is a SPI, every CPU can get it,
>>> But maybe I miss something, but please let me know if other CPU can
>>> not get the interrupt.
>>
>>
>> There's only one watchdog device, so there's only one interrupt.  I don't
>> know which CPU will get the interrupt, but the watchdog is not a per-CPU
>> device.
>>
> Plus, that one interrupt is not shared, and the driver returns
> IRQ_HANDLED even if the bit is not set. So _something_ is definitely
> wrong. Either the interrupt is shared, then it needs to be requested
> as shared and the handler should only return IRQ_HANDLED if it actually
> handles the interrupt. Or it is not shared and the handler should always
> handle it.

I have thought about this again, For now, I did not find any reason to
keep that "if (status & SBSA_GWDT_WCS_WS0)"

So you are right, I should delete it.

and for IRQF_TIMER,  I will delete it.

Thanks for your correction.

>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v4 0/7] Watchdog: introduce ARM SBSA watchdog driver
       [not found] <=fu.wei@linaro.org>
                   ` (3 preceding siblings ...)
  2015-05-25 10:03   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
@ 2015-06-02  4:05 ` fu.wei
  2015-06-02  4:05   ` [PATCH v4 1/7] Documentation: add sbsa-gwdt.txt documentation fu.wei
                     ` (6 more replies)
  2015-06-10 13:41   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                   ` (9 subsequent siblings)
  14 siblings, 7 replies; 550+ messages in thread
From: fu.wei @ 2015-06-02  4:05 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patchset:
    (1)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.

    (2)Introduce ACPI GTDT parser: drivers/acpi/gtdt.c
    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.
    drivers/clocksource/arm_arch_timer.c is simplified by this GTDT support.

    (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, do panic to save system context;
        e.Support getting timeout and pretimeout from parameter and FDT
          at the driver init stage.

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

Changelog:
v4: Refactor GTDT support code: remove it from arch/arm64/kernel/acpi.c,
    put it into drivers/acpi/gtdt.c file.
    Integrate the GTDT code of drivers/clocksource/arm_arch_timer.c into
    drivers/acpi/gtdt.c.
    Improve pretimeout support, fix "pretimeout == 0" problem.
    Simplify sbsa_gwdt driver:
        (1)timeout/pretimeout limits setup;
        (2)keepalive function;
        (3)delete "clk == 0" check;
        (4)delete WS0 status bit check in interrupt routine;
        (5)sbsa_gwdt_set_wcv function.

v3: Delete "export arch_timer_get_rate" patch.
    Driver back to use arch_timer_get_cntfrq.
    Improve watchdog_init_timeouts function and update relevant documentation.
    Improve watchdog_timeout_invalid and watchdog_pretimeout_invalid.
    Improve foundation-v8.dts: delete the unnecessary tag of device node.
    Remove "ARM64 || COMPILE_TEST" from Kconfig.
    Add comments in arch/arm64/kernel/acpi.c
    Fix typoes and incorrect comments.

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):
  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: introdouce "pretimeout" into framework
  Watchdog: introduce ARM SBSA watchdog driver
  ACPI: add GTDT table parse driver into ACPI driver
  clocksource: simplify ACPI code in arm_arch_timer.c

 .../devicetree/bindings/watchdog/sbsa-gwdt.txt     |  36 ++
 Documentation/watchdog/watchdog-kernel-api.txt     |  47 ++-
 arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi       |  11 +
 arch/arm64/boot/dts/arm/foundation-v8.dts          |  10 +
 arch/arm64/kernel/time.c                           |   4 +-
 drivers/acpi/Kconfig                               |   9 +
 drivers/acpi/Makefile                              |   1 +
 drivers/acpi/gtdt.c                                | 180 +++++++++
 drivers/clocksource/Kconfig                        |   1 +
 drivers/clocksource/arm_arch_timer.c               |  60 +--
 drivers/watchdog/Kconfig                           |  12 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/sbsa_gwdt.c                       | 426 +++++++++++++++++++++
 drivers/watchdog/watchdog_core.c                   | 115 ++++--
 drivers/watchdog/watchdog_dev.c                    |  53 +++
 include/clocksource/arm_arch_timer.h               |   8 +
 include/linux/acpi.h                               |   5 +
 include/linux/clocksource.h                        |   4 +-
 include/linux/watchdog.h                           |  33 +-
 19 files changed, 927 insertions(+), 89 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
 create mode 100644 drivers/acpi/gtdt.c
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v4 1/7] Documentation: add sbsa-gwdt.txt documentation
  2015-06-02  4:05 ` [PATCH v4 0/7] Watchdog: introduce ARM SBSA watchdog driver fu.wei
@ 2015-06-02  4:05   ` fu.wei
  2015-06-02  4:05   ` [PATCH v4 2/7] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts fu.wei
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-02  4:05 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 .../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..010e5c4
--- /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@2a440000 {
+	compatible = "arm,sbsa-gwdt";
+	reg = <0x0 0x2a440000 0 0x10000>,
+	      <0x0 0x2a450000 0 0x10000>;
+	reg-names = "control", "refresh";
+	interrupts = <0 27 4>;
+	interrupt-names = "ws0";
+	timeout-sec = <10 5>;
+};
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v4 2/7] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
  2015-06-02  4:05 ` [PATCH v4 0/7] Watchdog: introduce ARM SBSA watchdog driver fu.wei
  2015-06-02  4:05   ` [PATCH v4 1/7] Documentation: add sbsa-gwdt.txt documentation fu.wei
@ 2015-06-02  4:05   ` fu.wei
  2015-06-02  4:05     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-02  4:05 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 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..962a07e 100644
--- a/arch/arm64/boot/dts/arm/foundation-v8.dts
+++ b/arch/arm64/boot/dts/arm/foundation-v8.dts
@@ -237,4 +237,14 @@
 			};
 		};
 	};
+	watchdog@2a440000 {
+		compatible = "arm,sbsa-gwdt";
+		reg = <0x0 0x2a440000 0 0x10000>,
+			<0x0 0x2a450000 0 0x10000>;
+		reg-names = "control",
+			"refresh";
+		interrupts = <0 27 4>;
+		interrupt-names = "ws0";
+		timeout-sec = <10 5>;
+	};
 };
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v4 3/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
@ 2015-06-02  4:05     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-02  4:05 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v4 3/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
@ 2015-06-02  4:05     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-02  4:05 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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

Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Acked-by: Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 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

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v4 4/7] Watchdog: introdouce "pretimeout" into framework
@ 2015-06-02  4:05     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-02  4:05 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 drivers are going to use this: ARM SBSA Generic Watchdog

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 Documentation/watchdog/watchdog-kernel-api.txt |  47 ++++++++--
 drivers/watchdog/watchdog_core.c               | 115 +++++++++++++++++++------
 drivers/watchdog/watchdog_dev.c                |  53 ++++++++++++
 include/linux/watchdog.h                       |  33 ++++++-
 4 files changed, 212 insertions(+), 36 deletions(-)

diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index a0438f3..95b355d 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.
@@ -219,8 +236,28 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
                                   unsigned int timeout_parm, struct device *dev);
 
 The watchdog_init_timeout function allows you to initialize the timeout field
-using the module timeout parameter or by retrieving the timeout-sec property from
-the device tree (if the module timeout parameter is invalid). Best practice is
-to set the default timeout value as timeout value in the watchdog_device and
-then use this function to set the user "preferred" timeout value.
+using the module timeout parameter or by retrieving the first element of
+the timeout-sec property from the device tree (if the module timeout parameter
+is invalid). Best practice is to set the default timeout value as timeout value
+in the watchdog_device and then use this function to set the user "preferred"
+timeout value.
+This routine returns zero on success and a negative errno code for failure.
+
+Some watchdog timers have two stage of timeouts(timeout and pretimeout),
+to initialize the timeout and pretimeout fields at the same time, the following
+function can be used:
+
+extern int watchdog_init_timeouts(struct watchdog_device *wdd,
+                                  unsigned int pretimeout_parm,
+                                  unsigned int timeout_parm,
+                                  struct device *dev);
+
+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).
+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.
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index cec9b55..ff18db3 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -43,60 +43,119 @@
 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 timeout and max pretimeout values,
+	 * if not reset them.
+	 */
+	if (wdd->min_pretimeout && wdd->min_timeout < wdd->min_pretimeout) {
+		pr_info("Invalid min_timeout, resetting to min_pretimeout+1\n");
+		wdd->min_timeout = wdd->min_pretimeout + 1;
+	}
+	if (wdd->max_pretimeout && wdd->max_timeout < wdd->max_pretimeout) {
+		pr_info("Invalid max_pretimeout, resetting to max_timeout-1\n");
+		wdd->max_pretimeout = wdd->max_timeout - 1;
+	}
 }
 
 /**
- * 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,
+			   struct device *dev)
 {
-	unsigned int t = 0;
-	int ret = 0;
+	int ret = 0, length = 0;
+	u32 timeouts[2] = {0};
 
-	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 pretimeout module parameter first,
+	 * but it can be "0", that means we don't use pretimeout.
+	 */
+	if (pretimeout_parm) {
+		if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm))
+			timeouts[1] = pretimeout_parm;
+		ret = -EINVAL; /* pretimeout_parm is not "0", and invalid */
 	}
-	if (timeout_parm)
+
+	/*
+	 * Try to get the timeout module parameter,
+	 * if it's valid and pretimeout is ont invalid(ret == 0),
+	 * assignment and return zero. Otherwise, try dtb.
+	 */
+	if (timeout_parm) {
+		if (!watchdog_timeout_invalid(wdd, timeout_parm) && !ret) {
+			wdd->timeout = timeout_parm;
+			wdd->pretimeout = timeouts[1];
+			return 0;
+		}
 		ret = -EINVAL;
+	}
 
-	/* try to get the timeout_sec property */
+	/*
+	 * We get here, the situation is one of them:
+	 * (1)at least one of parameters is invalid(ret = -EINVAL);
+	 * (2)both of them are 0.(ret = 0)
+	 * So give up the module parameter(at least drop the invalid one),
+	 * try to get the timeout_sec property from dtb.
+	 */
 	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
-		ret = -EINVAL;
 
-	return ret;
+	/*
+	 * We get here, that means maybe we can get timeouts from dtb,
+	 * if "timeout-sec" is available and the data is valid.
+	 */
+	of_find_property(dev->of_node, "timeout-sec", &length);
+	if (length > 0 && length <= sizeof(u32) * 2) {
+		of_property_read_u32_array(dev->of_node,
+					   "timeout-sec", timeouts,
+					   length / sizeof(u32));
+		if (length == sizeof(u32) * 2 && timeouts[1] &&
+		    watchdog_pretimeout_invalid(wdd, timeouts[1]))
+				return -EINVAL; /* pretimeout is invalid */
+
+		if (!watchdog_timeout_invalid(wdd, timeouts[0]) &&
+		    timeouts[0]) {
+			wdd->timeout = timeouts[0];
+			wdd->pretimeout = timeouts[1];
+			return 0;
+		}
+	}
+
+	return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(watchdog_init_timeout);
+EXPORT_SYMBOL_GPL(watchdog_init_timeouts);
 
 /**
  * watchdog_register_device() - register a watchdog device
@@ -119,7 +178,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..af0777e 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,27 @@ 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:
+		/* check if we support the pretimeout */
+		if (!(wdd->info->options & WDIOF_PRETIMEOUT))
+			return -EOPNOTSUPP;
+		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 keeps running (and if
+		 * possible that it takes the new pretimeout)
+		 */
+		watchdog_ping(wdd);
+		/* Fall */
+	case WDIOC_GETPRETIMEOUT:
+		/* check if we support the pretimeout */
+		if (wdd->info->options & WDIOF_PRETIMEOUT)
+			return put_user(wdd->pretimeout, p);
+		return -EOPNOTSUPP;
 	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..b1e325d 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;
@@ -117,7 +125,17 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
 static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
 {
 	return ((wdd->max_timeout != 0) &&
-		(t < wdd->min_timeout || t > wdd->max_timeout));
+		(t < wdd->min_timeout || t > wdd->max_timeout ||
+			t <= wdd->pretimeout));
+}
+
+/* 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 ||
+			(wdd->timeout != 0 && t >= wdd->timeout)));
 }
 
 /* Use the following functions to manipulate watchdog driver specific data */
@@ -132,11 +150,20 @@ 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,
+				  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, dev);
+}
+
 #ifdef CONFIG_HARDLOCKUP_DETECTOR
 void watchdog_nmi_disable_all(void);
 void watchdog_nmi_enable_all(void);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v4 4/7] Watchdog: introdouce "pretimeout" into framework
@ 2015-06-02  4:05     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-02  4:05 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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 drivers are going to use this: ARM SBSA Generic Watchdog

Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 Documentation/watchdog/watchdog-kernel-api.txt |  47 ++++++++--
 drivers/watchdog/watchdog_core.c               | 115 +++++++++++++++++++------
 drivers/watchdog/watchdog_dev.c                |  53 ++++++++++++
 include/linux/watchdog.h                       |  33 ++++++-
 4 files changed, 212 insertions(+), 36 deletions(-)

diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index a0438f3..95b355d 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.
@@ -219,8 +236,28 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
                                   unsigned int timeout_parm, struct device *dev);
 
 The watchdog_init_timeout function allows you to initialize the timeout field
-using the module timeout parameter or by retrieving the timeout-sec property from
-the device tree (if the module timeout parameter is invalid). Best practice is
-to set the default timeout value as timeout value in the watchdog_device and
-then use this function to set the user "preferred" timeout value.
+using the module timeout parameter or by retrieving the first element of
+the timeout-sec property from the device tree (if the module timeout parameter
+is invalid). Best practice is to set the default timeout value as timeout value
+in the watchdog_device and then use this function to set the user "preferred"
+timeout value.
+This routine returns zero on success and a negative errno code for failure.
+
+Some watchdog timers have two stage of timeouts(timeout and pretimeout),
+to initialize the timeout and pretimeout fields at the same time, the following
+function can be used:
+
+extern int watchdog_init_timeouts(struct watchdog_device *wdd,
+                                  unsigned int pretimeout_parm,
+                                  unsigned int timeout_parm,
+                                  struct device *dev);
+
+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).
+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.
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index cec9b55..ff18db3 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -43,60 +43,119 @@
 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 timeout and max pretimeout values,
+	 * if not reset them.
+	 */
+	if (wdd->min_pretimeout && wdd->min_timeout < wdd->min_pretimeout) {
+		pr_info("Invalid min_timeout, resetting to min_pretimeout+1\n");
+		wdd->min_timeout = wdd->min_pretimeout + 1;
+	}
+	if (wdd->max_pretimeout && wdd->max_timeout < wdd->max_pretimeout) {
+		pr_info("Invalid max_pretimeout, resetting to max_timeout-1\n");
+		wdd->max_pretimeout = wdd->max_timeout - 1;
+	}
 }
 
 /**
- * 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,
+			   struct device *dev)
 {
-	unsigned int t = 0;
-	int ret = 0;
+	int ret = 0, length = 0;
+	u32 timeouts[2] = {0};
 
-	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 pretimeout module parameter first,
+	 * but it can be "0", that means we don't use pretimeout.
+	 */
+	if (pretimeout_parm) {
+		if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm))
+			timeouts[1] = pretimeout_parm;
+		ret = -EINVAL; /* pretimeout_parm is not "0", and invalid */
 	}
-	if (timeout_parm)
+
+	/*
+	 * Try to get the timeout module parameter,
+	 * if it's valid and pretimeout is ont invalid(ret == 0),
+	 * assignment and return zero. Otherwise, try dtb.
+	 */
+	if (timeout_parm) {
+		if (!watchdog_timeout_invalid(wdd, timeout_parm) && !ret) {
+			wdd->timeout = timeout_parm;
+			wdd->pretimeout = timeouts[1];
+			return 0;
+		}
 		ret = -EINVAL;
+	}
 
-	/* try to get the timeout_sec property */
+	/*
+	 * We get here, the situation is one of them:
+	 * (1)at least one of parameters is invalid(ret = -EINVAL);
+	 * (2)both of them are 0.(ret = 0)
+	 * So give up the module parameter(at least drop the invalid one),
+	 * try to get the timeout_sec property from dtb.
+	 */
 	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
-		ret = -EINVAL;
 
-	return ret;
+	/*
+	 * We get here, that means maybe we can get timeouts from dtb,
+	 * if "timeout-sec" is available and the data is valid.
+	 */
+	of_find_property(dev->of_node, "timeout-sec", &length);
+	if (length > 0 && length <= sizeof(u32) * 2) {
+		of_property_read_u32_array(dev->of_node,
+					   "timeout-sec", timeouts,
+					   length / sizeof(u32));
+		if (length == sizeof(u32) * 2 && timeouts[1] &&
+		    watchdog_pretimeout_invalid(wdd, timeouts[1]))
+				return -EINVAL; /* pretimeout is invalid */
+
+		if (!watchdog_timeout_invalid(wdd, timeouts[0]) &&
+		    timeouts[0]) {
+			wdd->timeout = timeouts[0];
+			wdd->pretimeout = timeouts[1];
+			return 0;
+		}
+	}
+
+	return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(watchdog_init_timeout);
+EXPORT_SYMBOL_GPL(watchdog_init_timeouts);
 
 /**
  * watchdog_register_device() - register a watchdog device
@@ -119,7 +178,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..af0777e 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,27 @@ 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:
+		/* check if we support the pretimeout */
+		if (!(wdd->info->options & WDIOF_PRETIMEOUT))
+			return -EOPNOTSUPP;
+		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 keeps running (and if
+		 * possible that it takes the new pretimeout)
+		 */
+		watchdog_ping(wdd);
+		/* Fall */
+	case WDIOC_GETPRETIMEOUT:
+		/* check if we support the pretimeout */
+		if (wdd->info->options & WDIOF_PRETIMEOUT)
+			return put_user(wdd->pretimeout, p);
+		return -EOPNOTSUPP;
 	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..b1e325d 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;
@@ -117,7 +125,17 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
 static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
 {
 	return ((wdd->max_timeout != 0) &&
-		(t < wdd->min_timeout || t > wdd->max_timeout));
+		(t < wdd->min_timeout || t > wdd->max_timeout ||
+			t <= wdd->pretimeout));
+}
+
+/* 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 ||
+			(wdd->timeout != 0 && t >= wdd->timeout)));
 }
 
 /* Use the following functions to manipulate watchdog driver specific data */
@@ -132,11 +150,20 @@ 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,
+				  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, dev);
+}
+
 #ifdef CONFIG_HARDLOCKUP_DETECTOR
 void watchdog_nmi_disable_all(void);
 void watchdog_nmi_enable_all(void);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-02  4:05     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-02  4:05 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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, the interrupt routine run panic to save
system context.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 drivers/watchdog/Kconfig     |  12 ++
 drivers/watchdog/Makefile    |   1 +
 drivers/watchdog/sbsa_gwdt.c | 426 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 439 insertions(+)
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e5e7c55..20f9980 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 ARM64
+	depends on ARM_ARCH_TIMER
+	select WATCHDOG_CORE
+	select ACPI_GTDT if ACPI
+	help
+	  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.
+	  More details: ARM 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..76b6763
--- /dev/null
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -0,0 +1,426 @@
+/*
+ * SBSA(Server Base System Architecture) Generic Watchdog driver
+ *
+ * Copyright (c) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei@linaro.org>
+ *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
+ *
+ * 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: ARM DEN0029B - Server Base System Architecture (SBSA)
+ *
+ * Kernel/API:                         P---------| pretimeout
+ *               |-------------------------------T timeout
+ * SBSA GWDT:                          P--WOR---WS1 pretimeout
+ *               |-------WCV----------WS0~~~~~~~~T timeout
+ */
+
+#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>
+#include <asm/arch_timer.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		30 /* seconds, the 1st + 2nd watch periods*/
+#define DEFAULT_PRETIMEOUT	10 /* 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 pretimeout;
+module_param(pretimeout, uint, 0);
+MODULE_PARM_DESC(pretimeout,
+		 "Watchdog pretimeout in seconds. (>=0, default="
+		 __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
+
+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) ")");
+
+/*
+ * help functions for accessing 32bit registers of SBSA Generic Watchdog
+ */
+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 functions 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)
+{
+	sbsa_gwdt_cf_write(SBSA_GWDT_WCV_HI, upper_32_bits(value), wdd);
+	sbsa_gwdt_cf_write(SBSA_GWDT_WCV_LO, lower_32_bits(value), 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);
+}
+
+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;
+
+	if (!pretimeout)
+		/*
+		 * If pretimeout is 0, it gives driver a timeslot(1s)
+		 * to update WCV after an explicit refresh(sbsa_gwdt_start)
+		 */
+		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_keepalive(struct watchdog_device *wdd)
+{
+	reload_timeout_to_wcv(wdd);
+
+	return 0;
+}
+
+static int sbsa_gwdt_start(struct watchdog_device *wdd)
+{
+	/*
+	 * Writing WRR for an explicit watchdog refresh.
+	 * You can write anyting(like 0xc0ffee).
+	 * Force refresh due to hardware bug found in certain Soc.
+	 */
+	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);
+
+	return sbsa_gwdt_keepalive(wdd);
+}
+
+static int sbsa_gwdt_stop(struct watchdog_device *wdd)
+{
+	sbsa_gwdt_cf_write(SBSA_GWDT_WCS, 0, 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;
+
+	if (wdd->pretimeout)
+		/* The pretimeout is valid, go panic */
+		panic("SBSA Watchdog pre-timeout");
+	else
+		/* We don't use pretimeout, trigger WS1 now*/
+		sbsa_gwdt_set_wcv(wdd, 0);
+
+	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)
+{
+	u64 first_period_max = U64_MAX;
+	struct device *dev = &pdev->dev;
+	struct watchdog_device *wdd;
+	struct sbsa_gwdt *gwdt;
+	struct resource *res;
+	void *rf_base, *cf_base;
+	int ret, irq;
+	u32 status;
+
+	gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
+	if (!gwdt)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, gwdt);
+
+	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(cf_base))
+		return PTR_ERR(cf_base);
+
+	irq = platform_get_irq_byname(pdev, "ws0");
+	if (irq < 0) {
+		dev_err(dev, "unable to get ws0 interrupt.\n");
+		return irq;
+	}
+
+	/*
+	 * Get the frequency of system counter from the cp15 interface of ARM
+	 * Generic timer. We don't need to check it, because if it returns "0",
+	 * system would panic in very early stage.
+	 */
+	gwdt->clk = arch_timer_get_cntfrq();
+	gwdt->refresh_base = rf_base;
+	gwdt->control_base = cf_base;
+
+	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);
+
+	wdd->min_pretimeout = 0;
+	wdd->max_pretimeout = U32_MAX / gwdt->clk;
+	wdd->min_timeout = 1;
+	do_div(first_period_max, gwdt->clk);
+	wdd->max_timeout = first_period_max;
+
+	wdd->pretimeout = DEFAULT_PRETIMEOUT;
+	wdd->timeout = DEFAULT_TIMEOUT;
+	watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
+
+	status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
+	if (status & SBSA_GWDT_WCS_WS1) {
+		dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
+			 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!\n");
+		sbsa_gwdt_keepalive(wdd);
+	}
+
+	/* update pretimeout to WOR */
+	sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
+
+	ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
+			       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 @ %u Hz\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);
+
+	watchdog_unregister_device(&gwdt->wdd);
+
+	return 0;
+}
+
+/* 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 <fu.wei@linaro.org>");
+MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-02  4:05     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-02  4:05 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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, the interrupt routine run panic to save
system context.

Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/watchdog/Kconfig     |  12 ++
 drivers/watchdog/Makefile    |   1 +
 drivers/watchdog/sbsa_gwdt.c | 426 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 439 insertions(+)
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e5e7c55..20f9980 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 ARM64
+	depends on ARM_ARCH_TIMER
+	select WATCHDOG_CORE
+	select ACPI_GTDT if ACPI
+	help
+	  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.
+	  More details: ARM 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..76b6763
--- /dev/null
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -0,0 +1,426 @@
+/*
+ * SBSA(Server Base System Architecture) Generic Watchdog driver
+ *
+ * Copyright (c) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
+ *         Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
+ *
+ * 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: ARM DEN0029B - Server Base System Architecture (SBSA)
+ *
+ * Kernel/API:                         P---------| pretimeout
+ *               |-------------------------------T timeout
+ * SBSA GWDT:                          P--WOR---WS1 pretimeout
+ *               |-------WCV----------WS0~~~~~~~~T timeout
+ */
+
+#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>
+#include <asm/arch_timer.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		30 /* seconds, the 1st + 2nd watch periods*/
+#define DEFAULT_PRETIMEOUT	10 /* 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 pretimeout;
+module_param(pretimeout, uint, 0);
+MODULE_PARM_DESC(pretimeout,
+		 "Watchdog pretimeout in seconds. (>=0, default="
+		 __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
+
+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) ")");
+
+/*
+ * help functions for accessing 32bit registers of SBSA Generic Watchdog
+ */
+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 functions 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)
+{
+	sbsa_gwdt_cf_write(SBSA_GWDT_WCV_HI, upper_32_bits(value), wdd);
+	sbsa_gwdt_cf_write(SBSA_GWDT_WCV_LO, lower_32_bits(value), 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);
+}
+
+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;
+
+	if (!pretimeout)
+		/*
+		 * If pretimeout is 0, it gives driver a timeslot(1s)
+		 * to update WCV after an explicit refresh(sbsa_gwdt_start)
+		 */
+		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_keepalive(struct watchdog_device *wdd)
+{
+	reload_timeout_to_wcv(wdd);
+
+	return 0;
+}
+
+static int sbsa_gwdt_start(struct watchdog_device *wdd)
+{
+	/*
+	 * Writing WRR for an explicit watchdog refresh.
+	 * You can write anyting(like 0xc0ffee).
+	 * Force refresh due to hardware bug found in certain Soc.
+	 */
+	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);
+
+	return sbsa_gwdt_keepalive(wdd);
+}
+
+static int sbsa_gwdt_stop(struct watchdog_device *wdd)
+{
+	sbsa_gwdt_cf_write(SBSA_GWDT_WCS, 0, 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;
+
+	if (wdd->pretimeout)
+		/* The pretimeout is valid, go panic */
+		panic("SBSA Watchdog pre-timeout");
+	else
+		/* We don't use pretimeout, trigger WS1 now*/
+		sbsa_gwdt_set_wcv(wdd, 0);
+
+	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)
+{
+	u64 first_period_max = U64_MAX;
+	struct device *dev = &pdev->dev;
+	struct watchdog_device *wdd;
+	struct sbsa_gwdt *gwdt;
+	struct resource *res;
+	void *rf_base, *cf_base;
+	int ret, irq;
+	u32 status;
+
+	gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
+	if (!gwdt)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, gwdt);
+
+	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(cf_base))
+		return PTR_ERR(cf_base);
+
+	irq = platform_get_irq_byname(pdev, "ws0");
+	if (irq < 0) {
+		dev_err(dev, "unable to get ws0 interrupt.\n");
+		return irq;
+	}
+
+	/*
+	 * Get the frequency of system counter from the cp15 interface of ARM
+	 * Generic timer. We don't need to check it, because if it returns "0",
+	 * system would panic in very early stage.
+	 */
+	gwdt->clk = arch_timer_get_cntfrq();
+	gwdt->refresh_base = rf_base;
+	gwdt->control_base = cf_base;
+
+	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);
+
+	wdd->min_pretimeout = 0;
+	wdd->max_pretimeout = U32_MAX / gwdt->clk;
+	wdd->min_timeout = 1;
+	do_div(first_period_max, gwdt->clk);
+	wdd->max_timeout = first_period_max;
+
+	wdd->pretimeout = DEFAULT_PRETIMEOUT;
+	wdd->timeout = DEFAULT_TIMEOUT;
+	watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
+
+	status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
+	if (status & SBSA_GWDT_WCS_WS1) {
+		dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
+			 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!\n");
+		sbsa_gwdt_keepalive(wdd);
+	}
+
+	/* update pretimeout to WOR */
+	sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
+
+	ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
+			       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 @ %u Hz\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);
+
+	watchdog_unregister_device(&gwdt->wdd);
+
+	return 0;
+}
+
+/* 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>");
+MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v4 6/7] ACPI: add GTDT table parse driver into ACPI driver
  2015-06-02  4:05 ` [PATCH v4 0/7] Watchdog: introduce ARM SBSA watchdog driver fu.wei
                     ` (4 preceding siblings ...)
  2015-06-02  4:05     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
@ 2015-06-02  4:05   ` fu.wei
  2015-06-02  4:05   ` [PATCH v4 7/7] clocksource: simplify ACPI code in arm_arch_timer.c fu.wei
  6 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-02  4:05 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This driver adds support for parsing SBSA Generic Watchdog
Structure in GTDT, and creating a platform device with that
information. This allows the operating system to obtain device
data from the resource of platform device.

The platform device named "sbsa-gwdt" can be used by the
ARM SBSA Generic Watchdog driver.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/acpi/Kconfig  |   9 ++++
 drivers/acpi/Makefile |   1 +
 drivers/acpi/gtdt.c   | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 147 insertions(+)
 create mode 100644 drivers/acpi/gtdt.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 1bbaa3d..e125698 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -433,4 +433,13 @@ config XPOWER_PMIC_OPREGION
 
 endif
 
+config ACPI_GTDT
+	bool "ACPI GTDT Support"
+	depends on ARM64
+	help
+	  GTDT (Generic Timer Description Table) provides information
+	  for per-processor timers and Platform (memory-mapped) timers
+	  for ARM platforms. Select this option to provide information
+	  needed for the timers init.
+
 endif	# ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 431e587..2c5a194 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -96,3 +96,4 @@ obj-$(CONFIG_ACPI_EXTLOG)	+= acpi_extlog.o
 obj-$(CONFIG_PMIC_OPREGION)	+= pmic/intel_pmic.o
 obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
 obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
+obj-$(CONFIG_ACPI_GTDT)		+= gtdt.o
diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
new file mode 100644
index 0000000..a92abf2
--- /dev/null
+++ b/drivers/acpi/gtdt.c
@@ -0,0 +1,137 @@
+/*
+ * ARM Specific GTDT table Support
+ *
+ * Copyright (C) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei@linaro.org>
+ *         Hanjun Guo <hanjun.guo@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
+{
+	int trigger, polarity;
+
+	if (!interrupt)
+		return 0;
+
+	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+			: ACPI_LEVEL_SENSITIVE;
+
+	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+			: ACPI_ACTIVE_HIGH;
+
+	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
+}
+
+/*
+ * Initialize a SBSA generic Watchdog platform device info from GTDT
+ * According to SBSA specification the size of refresh and control
+ * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
+ */
+static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
+					int index)
+{
+	struct platform_device *pdev;
+	int irq = map_generic_timer_interrupt(wd->timer_interrupt,
+					      wd->timer_flags);
+	struct resource res[] = {
+		DEFINE_RES_IRQ_NAMED(irq, "ws0"),
+		DEFINE_RES_MEM_NAMED(wd->refresh_frame_address, SZ_4K,
+				     "refresh"),
+		DEFINE_RES_MEM_NAMED(wd->control_frame_address, SZ_4K,
+				     "control"),
+	};
+
+	pr_debug("GTDT: a Watchdog GT(0x%llx/0x%llx gsi:%u flags:0x%x)\n",
+		 wd->refresh_frame_address, wd->control_frame_address,
+		 wd->timer_interrupt, wd->timer_flags);
+
+	if (!(wd->refresh_frame_address &&
+	      wd->control_frame_address &&
+	      wd->timer_interrupt)) {
+		pr_err("GTDT: failed geting the device info.\n");
+		return -EINVAL;
+	}
+
+	if (irq < 0) {
+		pr_err("GTDT: failed to register GSI of the Watchdog GT.\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Add a platform device named "sbsa-gwdt" to match the platform driver.
+	 * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
+	 * The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get device
+	 * info below by matching this name.
+	 */
+	pdev = platform_device_register_simple("sbsa-gwdt", index, res,
+					       ARRAY_SIZE(res));
+	if (IS_ERR(pdev)) {
+		acpi_unregister_gsi(wd->timer_interrupt);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
+
+static int __init gtdt_platform_timer_parse(struct acpi_table_header *table)
+{
+	struct acpi_gtdt_header *header;
+	struct acpi_table_gtdt *gtdt;
+	void *gtdt_subtable;
+	int i, gwdt_index;
+	int ret = 0;
+
+	if (table->revision < 2) {
+		pr_warn("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 = 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;
+}
+
+static int __init gtdt_platform_timer_init(void)
+{
+	if (acpi_disabled)
+		return 0;
+
+	return acpi_table_parse(ACPI_SIG_GTDT, gtdt_platform_timer_parse);
+}
+
+device_initcall(gtdt_platform_timer_init);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v4 7/7] clocksource: simplify ACPI code in arm_arch_timer.c
  2015-06-02  4:05 ` [PATCH v4 0/7] Watchdog: introduce ARM SBSA watchdog driver fu.wei
                     ` (5 preceding siblings ...)
  2015-06-02  4:05   ` [PATCH v4 6/7] ACPI: add GTDT table parse driver into ACPI driver fu.wei
@ 2015-06-02  4:05   ` fu.wei
  6 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-02  4:05 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

The patch update arm_arch_timer driver to use the function
provided by the new GTDT driver of ACPI.
By this way, arm_arch_timer.c can be simplified, and separate
all the ACPI GTDT knowledge from this timer driver.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 arch/arm64/kernel/time.c             |  4 +--
 drivers/acpi/gtdt.c                  | 43 ++++++++++++++++++++++++++
 drivers/clocksource/Kconfig          |  1 +
 drivers/clocksource/arm_arch_timer.c | 60 +++++++-----------------------------
 include/clocksource/arm_arch_timer.h |  8 +++++
 include/linux/acpi.h                 |  5 +++
 include/linux/clocksource.h          |  4 +--
 7 files changed, 72 insertions(+), 53 deletions(-)

diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 42f9195..2cabea6 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -75,9 +75,9 @@ void __init time_init(void)
 
 	/*
 	 * Since ACPI or FDT will only one be available in the system,
-	 * we can use acpi_generic_timer_init() here safely
+	 * we can use arch_timer_acpi_init() here safely
 	 */
-	acpi_generic_timer_init();
+	arch_timer_acpi_init();
 
 	arch_timer_rate = arch_timer_get_rate();
 	if (!arch_timer_rate)
diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
index a92abf2..699c9fd 100644
--- a/drivers/acpi/gtdt.c
+++ b/drivers/acpi/gtdt.c
@@ -17,6 +17,8 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
+#include <clocksource/arm_arch_timer.h>
+
 static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 {
 	int trigger, polarity;
@@ -33,6 +35,47 @@ static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
 }
 
+struct arch_timer_data __initdata *arch_timer_data_p;
+
+static int __init arch_timer_data_init(struct acpi_table_header *table)
+{
+	struct acpi_table_gtdt *gtdt;
+
+	gtdt = container_of(table, struct acpi_table_gtdt, header);
+
+	arch_timer_data_p->phys_secure_ppi =
+		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
+					    gtdt->secure_el1_flags);
+
+	arch_timer_data_p->phys_nonsecure_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
+					    gtdt->non_secure_el1_flags);
+
+	arch_timer_data_p->virt_ppi =
+		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
+					    gtdt->virtual_timer_flags);
+
+	arch_timer_data_p->hyp_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
+					    gtdt->non_secure_el2_flags);
+
+	arch_timer_data_p->c3stop = !(gtdt->non_secure_el1_flags &
+				      ACPI_GTDT_ALWAYS_ON);
+
+	return 0;
+}
+
+/* Initialize the arch_timer_data struct for arm_arch_timer by GTDT info */
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data)
+{
+	if (acpi_disabled || !data)
+		return -EINVAL;
+
+	arch_timer_data_p = data;
+
+	return acpi_table_parse(ACPI_SIG_GTDT, arch_timer_data_init);
+}
+
 /*
  * Initialize a SBSA generic Watchdog platform device info from GTDT
  * According to SBSA specification the size of refresh and control
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 51d7865f..ea94a6f 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -109,6 +109,7 @@ config CLKSRC_EFM32
 config ARM_ARCH_TIMER
 	bool
 	select CLKSRC_OF if OF
+	select ACPI_GTDT if ACPI
 
 config ARM_ARCH_TIMER_EVTSTREAM
 	bool "Support for ARM architected timer event stream generation"
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 0aa135d..99505bb 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -817,68 +817,30 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
 		       arch_timer_mem_init);
 
 #ifdef CONFIG_ACPI
-static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
-{
-	int trigger, polarity;
-
-	if (!interrupt)
-		return 0;
-
-	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
-			: ACPI_LEVEL_SENSITIVE;
-
-	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
-			: ACPI_ACTIVE_HIGH;
-
-	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
-}
-
 /* Initialize per-processor generic timer */
-static int __init arch_timer_acpi_init(struct acpi_table_header *table)
+void __init arch_timer_acpi_init(void)
 {
-	struct acpi_table_gtdt *gtdt;
+	struct arch_timer_data data;
 
 	if (arch_timers_present & ARCH_CP15_TIMER) {
 		pr_warn("arch_timer: already initialized, skipping\n");
-		return -EINVAL;
+		return;
 	}
 
-	gtdt = container_of(table, struct acpi_table_gtdt, header);
-
 	arch_timers_present |= ARCH_CP15_TIMER;
 
-	arch_timer_ppi[PHYS_SECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
-		gtdt->secure_el1_flags);
-
-	arch_timer_ppi[PHYS_NONSECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
-		gtdt->non_secure_el1_flags);
-
-	arch_timer_ppi[VIRT_PPI] =
-		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
-		gtdt->virtual_timer_flags);
+	if (gtdt_arch_timer_data_init(&data))
+		return;
 
-	arch_timer_ppi[HYP_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
-		gtdt->non_secure_el2_flags);
+	arch_timer_ppi[PHYS_SECURE_PPI] = data.phys_secure_ppi;
+	arch_timer_ppi[PHYS_NONSECURE_PPI] = data.phys_nonsecure_ppi;
+	arch_timer_ppi[VIRT_PPI] = data.virt_ppi;
+	arch_timer_ppi[HYP_PPI] = data.hyp_ppi;
+	/* Always-on capability */
+	arch_timer_c3stop = data.c3stop;
 
 	/* Get the frequency from CNTFRQ */
 	arch_timer_detect_rate(NULL, NULL);
-
-	/* Always-on capability */
-	arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
-
 	arch_timer_init();
-	return 0;
-}
-
-/* Initialize all the generic timers presented in GTDT */
-void __init acpi_generic_timer_init(void)
-{
-	if (acpi_disabled)
-		return;
-
-	acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init);
 }
 #endif
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 9916d0e..5deed9d 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -43,6 +43,14 @@ enum arch_timer_reg {
 
 #define ARCH_TIMER_EVT_STREAM_FREQ	10000	/* 100us */
 
+struct arch_timer_data {
+	int phys_secure_ppi;
+	int phys_nonsecure_ppi;
+	int virt_ppi;
+	int hyp_ppi;
+	bool c3stop;
+};
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 598f0f1..7213c0d 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -458,6 +458,11 @@ void acpi_walk_dep_device_list(acpi_handle handle);
 struct platform_device *acpi_create_platform_device(struct acpi_device *);
 #define ACPI_PTR(_ptr)	(_ptr)
 
+#ifdef CONFIG_ACPI_GTDT
+struct arch_timer_data;
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data);
+#endif
+
 #else	/* !CONFIG_ACPI */
 
 #define acpi_disabled 1
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index d27d015..264e553 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -254,9 +254,9 @@ static inline void clocksource_of_init(void) {}
 #endif
 
 #ifdef CONFIG_ACPI
-void acpi_generic_timer_init(void);
+void arch_timer_acpi_init(void);
 #else
-static inline void acpi_generic_timer_init(void) { }
+static inline void arch_timer_acpi_init(void) { }
 #endif
 
 #endif /* _LINUX_CLOCKSOURCE_H */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-02 15:32       ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-02 15:32 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw

On 06/01/2015 11:05 PM, fu.wei@linaro.org wrote:

> +/*
> + * help functions for accessing 32bit registers of SBSA Generic Watchdog
> + */
> +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);
> +}

I still think you should get rid of these functions and just call 
readl_relaxed() and writel_relaxed() every time, but I won't complain 
again if you keep them.

> +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;
> +
> +	if (wdd->pretimeout)
> +		/* The pretimeout is valid, go panic */
> +		panic("SBSA Watchdog pre-timeout");
> +	else
> +		/* We don't use pretimeout, trigger WS1 now*/
> +		sbsa_gwdt_set_wcv(wdd, 0);

I don't like this.  The triggering of the hardware reset should never 
depend on an interrupt being handled properly.  You should always 
program WCV correctly in advance.  This is especially true since 
pre-timeout will probably rarely be used.  So what happens if the CPU is 
totally hung and this interrupt handler is never called?  When will the 
timeout occur?

> +static int sbsa_gwdt_probe(struct platform_device *pdev)
> +{
> +	u64 first_period_max = U64_MAX;
> +	struct device *dev = &pdev->dev;
> +	struct watchdog_device *wdd;
> +	struct sbsa_gwdt *gwdt;
> +	struct resource *res;
> +	void *rf_base, *cf_base;
> +	int ret, irq;
> +	u32 status;
> +
> +	gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
> +	if (!gwdt)
> +		return -ENOMEM;
> +	platform_set_drvdata(pdev, gwdt);

You should probably do this *after* calling platform_get_irq_byname().

> +
> +	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(cf_base))
> +		return PTR_ERR(cf_base);
> +
> +	irq = platform_get_irq_byname(pdev, "ws0");
> +	if (irq < 0) {
> +		dev_err(dev, "unable to get ws0 interrupt.\n");
> +		return irq;
> +	}
> +
> +	/*
> +	 * Get the frequency of system counter from the cp15 interface of ARM
> +	 * Generic timer. We don't need to check it, because if it returns "0",
> +	 * system would panic in very early stage.
> +	 */
> +	gwdt->clk = arch_timer_get_cntfrq();
> +	gwdt->refresh_base = rf_base;
> +	gwdt->control_base = cf_base;
> +
> +	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);
> +
> +	wdd->min_pretimeout = 0;
> +	wdd->max_pretimeout = U32_MAX / gwdt->clk;
> +	wdd->min_timeout = 1;
> +	do_div(first_period_max, gwdt->clk);
> +	wdd->max_timeout = first_period_max;
> +
> +	wdd->pretimeout = DEFAULT_PRETIMEOUT;
> +	wdd->timeout = DEFAULT_TIMEOUT;
> +	watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
> +
> +	status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
> +	if (status & SBSA_GWDT_WCS_WS1) {
> +		dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
> +			 sbsa_gwdt_get_wcv(wdd));

"System was previously reset via watchdog" is much clearer.

> +		wdd->bootstatus |= WDIOF_CARDRESET;
> +	}
> +	/* Check if watchdog is already enabled */
> +	if (status & SBSA_GWDT_WCS_EN) {
> +		dev_warn(dev, "already enabled!\n");

"watchdog is already enabled".  Never use exclamation marks in kernel 
messages.

> +		sbsa_gwdt_keepalive(wdd);
> +	}
> +
> +	/* update pretimeout to WOR */
> +	sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
> +
> +	ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
> +			       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 @ %u Hz\n",
> +		 wdd->timeout, wdd->pretimeout, gwdt->clk);

if (wdd->pretimeout)
	"watchdog initialized to %us timeout and %us pre-timeout at %u Hz\n", 
wdd->timeout, wdd->pretimeout, gwdt->clk
else
	"watchdog initialized to %us timeout at %u Hz\n", wdd->timeout, gwdt->clk

I think it's unlikely that users will use pre-timeout, so your code 
should treat pre-timeout as a special case, not the normal usage.

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-02 15:32       ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-02 15:32 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA

On 06/01/2015 11:05 PM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:

> +/*
> + * help functions for accessing 32bit registers of SBSA Generic Watchdog
> + */
> +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);
> +}

I still think you should get rid of these functions and just call 
readl_relaxed() and writel_relaxed() every time, but I won't complain 
again if you keep them.

> +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;
> +
> +	if (wdd->pretimeout)
> +		/* The pretimeout is valid, go panic */
> +		panic("SBSA Watchdog pre-timeout");
> +	else
> +		/* We don't use pretimeout, trigger WS1 now*/
> +		sbsa_gwdt_set_wcv(wdd, 0);

I don't like this.  The triggering of the hardware reset should never 
depend on an interrupt being handled properly.  You should always 
program WCV correctly in advance.  This is especially true since 
pre-timeout will probably rarely be used.  So what happens if the CPU is 
totally hung and this interrupt handler is never called?  When will the 
timeout occur?

> +static int sbsa_gwdt_probe(struct platform_device *pdev)
> +{
> +	u64 first_period_max = U64_MAX;
> +	struct device *dev = &pdev->dev;
> +	struct watchdog_device *wdd;
> +	struct sbsa_gwdt *gwdt;
> +	struct resource *res;
> +	void *rf_base, *cf_base;
> +	int ret, irq;
> +	u32 status;
> +
> +	gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
> +	if (!gwdt)
> +		return -ENOMEM;
> +	platform_set_drvdata(pdev, gwdt);

You should probably do this *after* calling platform_get_irq_byname().

> +
> +	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(cf_base))
> +		return PTR_ERR(cf_base);
> +
> +	irq = platform_get_irq_byname(pdev, "ws0");
> +	if (irq < 0) {
> +		dev_err(dev, "unable to get ws0 interrupt.\n");
> +		return irq;
> +	}
> +
> +	/*
> +	 * Get the frequency of system counter from the cp15 interface of ARM
> +	 * Generic timer. We don't need to check it, because if it returns "0",
> +	 * system would panic in very early stage.
> +	 */
> +	gwdt->clk = arch_timer_get_cntfrq();
> +	gwdt->refresh_base = rf_base;
> +	gwdt->control_base = cf_base;
> +
> +	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);
> +
> +	wdd->min_pretimeout = 0;
> +	wdd->max_pretimeout = U32_MAX / gwdt->clk;
> +	wdd->min_timeout = 1;
> +	do_div(first_period_max, gwdt->clk);
> +	wdd->max_timeout = first_period_max;
> +
> +	wdd->pretimeout = DEFAULT_PRETIMEOUT;
> +	wdd->timeout = DEFAULT_TIMEOUT;
> +	watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
> +
> +	status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
> +	if (status & SBSA_GWDT_WCS_WS1) {
> +		dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
> +			 sbsa_gwdt_get_wcv(wdd));

"System was previously reset via watchdog" is much clearer.

> +		wdd->bootstatus |= WDIOF_CARDRESET;
> +	}
> +	/* Check if watchdog is already enabled */
> +	if (status & SBSA_GWDT_WCS_EN) {
> +		dev_warn(dev, "already enabled!\n");

"watchdog is already enabled".  Never use exclamation marks in kernel 
messages.

> +		sbsa_gwdt_keepalive(wdd);
> +	}
> +
> +	/* update pretimeout to WOR */
> +	sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
> +
> +	ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
> +			       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 @ %u Hz\n",
> +		 wdd->timeout, wdd->pretimeout, gwdt->clk);

if (wdd->pretimeout)
	"watchdog initialized to %us timeout and %us pre-timeout at %u Hz\n", 
wdd->timeout, wdd->pretimeout, gwdt->clk
else
	"watchdog initialized to %us timeout at %u Hz\n", wdd->timeout, gwdt->clk

I think it's unlikely that users will use pre-timeout, so your code 
should treat pre-timeout as a special case, not the normal usage.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-02 15:37         ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-02 15:37 UTC (permalink / raw)
  To: Timur Tabi, fu.wei, Suravee.Suthikulpanit, linaro-acpi,
	linux-watchdog, devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo,
	ashwin.chaugule, arnd, vgandhi, wim, jcm, leo.duran, corbet,
	mark.rutland, catalin.marinas, will.deacon, rjw

On 06/02/2015 08:32 AM, Timur Tabi wrote:
> On 06/01/2015 11:05 PM, fu.wei@linaro.org wrote:
>
>> +/*
>> + * help functions for accessing 32bit registers of SBSA Generic Watchdog
>> + */
>> +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);
>> +}
>
> I still think you should get rid of these functions and just call readl_relaxed() and writel_relaxed() every time, but I won't complain again if you keep them.
>
>> +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;
>> +
>> +    if (wdd->pretimeout)
>> +        /* The pretimeout is valid, go panic */
>> +        panic("SBSA Watchdog pre-timeout");
>> +    else
>> +        /* We don't use pretimeout, trigger WS1 now*/
>> +        sbsa_gwdt_set_wcv(wdd, 0);
>
> I don't like this.  The triggering of the hardware reset should never depend on an interrupt being handled properly.  You should always program WCV correctly in advance.  This is especially true since pre-timeout will probably rarely be used.  So what happens if the CPU is totally hung and this interrupt handler is never called?  When will the timeout occur?
>
>> +static int sbsa_gwdt_probe(struct platform_device *pdev)
>> +{
>> +    u64 first_period_max = U64_MAX;
>> +    struct device *dev = &pdev->dev;
>> +    struct watchdog_device *wdd;
>> +    struct sbsa_gwdt *gwdt;
>> +    struct resource *res;
>> +    void *rf_base, *cf_base;
>> +    int ret, irq;
>> +    u32 status;
>> +
>> +    gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
>> +    if (!gwdt)
>> +        return -ENOMEM;
>> +    platform_set_drvdata(pdev, gwdt);
>
> You should probably do this *after* calling platform_get_irq_byname().
>
>> +
>> +    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(cf_base))
>> +        return PTR_ERR(cf_base);
>> +
>> +    irq = platform_get_irq_byname(pdev, "ws0");
>> +    if (irq < 0) {
>> +        dev_err(dev, "unable to get ws0 interrupt.\n");
>> +        return irq;
>> +    }
>> +
>> +    /*
>> +     * Get the frequency of system counter from the cp15 interface of ARM
>> +     * Generic timer. We don't need to check it, because if it returns "0",
>> +     * system would panic in very early stage.
>> +     */
>> +    gwdt->clk = arch_timer_get_cntfrq();
>> +    gwdt->refresh_base = rf_base;
>> +    gwdt->control_base = cf_base;
>> +
>> +    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);
>> +
>> +    wdd->min_pretimeout = 0;
>> +    wdd->max_pretimeout = U32_MAX / gwdt->clk;
>> +    wdd->min_timeout = 1;
>> +    do_div(first_period_max, gwdt->clk);
>> +    wdd->max_timeout = first_period_max;
>> +
>> +    wdd->pretimeout = DEFAULT_PRETIMEOUT;
>> +    wdd->timeout = DEFAULT_TIMEOUT;
>> +    watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
>> +
>> +    status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
>> +    if (status & SBSA_GWDT_WCS_WS1) {
>> +        dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
>> +             sbsa_gwdt_get_wcv(wdd));
>
> "System was previously reset via watchdog" is much clearer.
>
>> +        wdd->bootstatus |= WDIOF_CARDRESET;
>> +    }
>> +    /* Check if watchdog is already enabled */
>> +    if (status & SBSA_GWDT_WCS_EN) {
>> +        dev_warn(dev, "already enabled!\n");
>
> "watchdog is already enabled".  Never use exclamation marks in kernel messages.
>
>> +        sbsa_gwdt_keepalive(wdd);
>> +    }
>> +
>> +    /* update pretimeout to WOR */
>> +    sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
>> +
>> +    ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
>> +                   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 @ %u Hz\n",
>> +         wdd->timeout, wdd->pretimeout, gwdt->clk);
>
> if (wdd->pretimeout)
>      "watchdog initialized to %us timeout and %us pre-timeout at %u Hz\n", wdd->timeout, wdd->pretimeout, gwdt->clk
> else
>      "watchdog initialized to %us timeout at %u Hz\n", wdd->timeout, gwdt->clk
>
> I think it's unlikely that users will use pre-timeout, so your code should treat pre-timeout as a special case, not the normal usage.
>
+1 to all your comments.

Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-02 15:37         ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-02 15:37 UTC (permalink / raw)
  To: Timur Tabi, fu.wei-QSEj5FYQhm4dnm+yROfE0A,
	Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	corbet-T1hC0tSOHrs, mark.rutland-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	rjw-LthD3rsA81gm4RdzfppkhA

On 06/02/2015 08:32 AM, Timur Tabi wrote:
> On 06/01/2015 11:05 PM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>
>> +/*
>> + * help functions for accessing 32bit registers of SBSA Generic Watchdog
>> + */
>> +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);
>> +}
>
> I still think you should get rid of these functions and just call readl_relaxed() and writel_relaxed() every time, but I won't complain again if you keep them.
>
>> +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;
>> +
>> +    if (wdd->pretimeout)
>> +        /* The pretimeout is valid, go panic */
>> +        panic("SBSA Watchdog pre-timeout");
>> +    else
>> +        /* We don't use pretimeout, trigger WS1 now*/
>> +        sbsa_gwdt_set_wcv(wdd, 0);
>
> I don't like this.  The triggering of the hardware reset should never depend on an interrupt being handled properly.  You should always program WCV correctly in advance.  This is especially true since pre-timeout will probably rarely be used.  So what happens if the CPU is totally hung and this interrupt handler is never called?  When will the timeout occur?
>
>> +static int sbsa_gwdt_probe(struct platform_device *pdev)
>> +{
>> +    u64 first_period_max = U64_MAX;
>> +    struct device *dev = &pdev->dev;
>> +    struct watchdog_device *wdd;
>> +    struct sbsa_gwdt *gwdt;
>> +    struct resource *res;
>> +    void *rf_base, *cf_base;
>> +    int ret, irq;
>> +    u32 status;
>> +
>> +    gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
>> +    if (!gwdt)
>> +        return -ENOMEM;
>> +    platform_set_drvdata(pdev, gwdt);
>
> You should probably do this *after* calling platform_get_irq_byname().
>
>> +
>> +    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(cf_base))
>> +        return PTR_ERR(cf_base);
>> +
>> +    irq = platform_get_irq_byname(pdev, "ws0");
>> +    if (irq < 0) {
>> +        dev_err(dev, "unable to get ws0 interrupt.\n");
>> +        return irq;
>> +    }
>> +
>> +    /*
>> +     * Get the frequency of system counter from the cp15 interface of ARM
>> +     * Generic timer. We don't need to check it, because if it returns "0",
>> +     * system would panic in very early stage.
>> +     */
>> +    gwdt->clk = arch_timer_get_cntfrq();
>> +    gwdt->refresh_base = rf_base;
>> +    gwdt->control_base = cf_base;
>> +
>> +    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);
>> +
>> +    wdd->min_pretimeout = 0;
>> +    wdd->max_pretimeout = U32_MAX / gwdt->clk;
>> +    wdd->min_timeout = 1;
>> +    do_div(first_period_max, gwdt->clk);
>> +    wdd->max_timeout = first_period_max;
>> +
>> +    wdd->pretimeout = DEFAULT_PRETIMEOUT;
>> +    wdd->timeout = DEFAULT_TIMEOUT;
>> +    watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
>> +
>> +    status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
>> +    if (status & SBSA_GWDT_WCS_WS1) {
>> +        dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
>> +             sbsa_gwdt_get_wcv(wdd));
>
> "System was previously reset via watchdog" is much clearer.
>
>> +        wdd->bootstatus |= WDIOF_CARDRESET;
>> +    }
>> +    /* Check if watchdog is already enabled */
>> +    if (status & SBSA_GWDT_WCS_EN) {
>> +        dev_warn(dev, "already enabled!\n");
>
> "watchdog is already enabled".  Never use exclamation marks in kernel messages.
>
>> +        sbsa_gwdt_keepalive(wdd);
>> +    }
>> +
>> +    /* update pretimeout to WOR */
>> +    sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
>> +
>> +    ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
>> +                   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 @ %u Hz\n",
>> +         wdd->timeout, wdd->pretimeout, gwdt->clk);
>
> if (wdd->pretimeout)
>      "watchdog initialized to %us timeout and %us pre-timeout at %u Hz\n", wdd->timeout, wdd->pretimeout, gwdt->clk
> else
>      "watchdog initialized to %us timeout at %u Hz\n", wdd->timeout, gwdt->clk
>
> I think it's unlikely that users will use pre-timeout, so your code should treat pre-timeout as a special case, not the normal usage.
>
+1 to all your comments.

Guenter

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 4/7] Watchdog: introdouce "pretimeout" into framework
@ 2015-06-02 16:12       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-02 16:12 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, vgandhi, wim, jcm, leo.duran, corbet,
	mark.rutland, catalin.marinas, will.deacon, rjw

On 06/01/2015 09:05 PM, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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 drivers are going to use this: ARM SBSA Generic Watchdog
>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>   Documentation/watchdog/watchdog-kernel-api.txt |  47 ++++++++--
>   drivers/watchdog/watchdog_core.c               | 115 +++++++++++++++++++------
>   drivers/watchdog/watchdog_dev.c                |  53 ++++++++++++
>   include/linux/watchdog.h                       |  33 ++++++-
>   4 files changed, 212 insertions(+), 36 deletions(-)
>
> diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
> index a0438f3..95b355d 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.
> @@ -219,8 +236,28 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
>                                     unsigned int timeout_parm, struct device *dev);
>
>   The watchdog_init_timeout function allows you to initialize the timeout field
> -using the module timeout parameter or by retrieving the timeout-sec property from
> -the device tree (if the module timeout parameter is invalid). Best practice is
> -to set the default timeout value as timeout value in the watchdog_device and
> -then use this function to set the user "preferred" timeout value.
> +using the module timeout parameter or by retrieving the first element of
> +the timeout-sec property from the device tree (if the module timeout parameter
> +is invalid). Best practice is to set the default timeout value as timeout value
> +in the watchdog_device and then use this function to set the user "preferred"
> +timeout value.
> +This routine returns zero on success and a negative errno code for failure.
> +
> +Some watchdog timers have two stage of timeouts(timeout and pretimeout),
> +to initialize the timeout and pretimeout fields at the same time, the following
> +function can be used:
> +
> +extern int watchdog_init_timeouts(struct watchdog_device *wdd,
> +                                  unsigned int pretimeout_parm,
> +                                  unsigned int timeout_parm,
> +                                  struct device *dev);
> +
> +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).
> +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.
> diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
> index cec9b55..ff18db3 100644
> --- a/drivers/watchdog/watchdog_core.c
> +++ b/drivers/watchdog/watchdog_core.c
> @@ -43,60 +43,119 @@
>   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 timeout and max pretimeout values,
> +	 * if not reset them.
> +	 */
> +	if (wdd->min_pretimeout && wdd->min_timeout < wdd->min_pretimeout) {
> +		pr_info("Invalid min_timeout, resetting to min_pretimeout+1\n");
> +		wdd->min_timeout = wdd->min_pretimeout + 1;
> +	}

min_timeout = 10
max_timeout = 20
min_pretimeout = 30
max_pretimeout = 40

will result in min_timeout set to 31.

> +	if (wdd->max_pretimeout && wdd->max_timeout < wdd->max_pretimeout) {
> +		pr_info("Invalid max_pretimeout, resetting to max_timeout-1\n");
> +		wdd->max_pretimeout = wdd->max_timeout - 1;

and then you set max_pretimeout to 19.

So we'll end up with

min_timeout = 31
max_timeout = 20
min_pretimeout = 30
max_pretimeout = 19

Another example: max_pretimeout = 10, max_timeout = 0 -> max_pretimeout = -1.

> +	}

You'll need to determine valid ranges and then enforce those.
Maybe something like
	min_pretimeout < min_timeout < max_timeout
and
	min_pretimeout < max_pretimeout < max_timeout

Not sure if we should adjust anything to a value different to 0.
Seems to me this is just asking for trouble.

>   }
>
>   /**
> - * 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

just 'if it is valid', or 'if it is a valid value' in both cases.

> + * pretimeout_parm and timeout_parm is out of bounds). If none of them are

s/and/or/

> + * 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,
> +			   struct device *dev)
>   {
> -	unsigned int t = 0;
> -	int ret = 0;
> +	int ret = 0, length = 0;
> +	u32 timeouts[2] = {0};
>
> -	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 pretimeout module parameter first,
> +	 * but it can be "0", that means we don't use pretimeout.
> +	 */
> +	if (pretimeout_parm) {
> +		if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm))
> +			timeouts[1] = pretimeout_parm;
> +		ret = -EINVAL; /* pretimeout_parm is not "0", and invalid */

pretimeout_parm is always invalid ? Why ?

>   	}
> -	if (timeout_parm)
> +
> +	/*
> +	 * Try to get the timeout module parameter,
> +	 * if it's valid and pretimeout is ont invalid(ret == 0),

s/ont/not/

> +	 * assignment and return zero. Otherwise, try dtb.
> +	 */
> +	if (timeout_parm) {
> +		if (!watchdog_timeout_invalid(wdd, timeout_parm) && !ret) {

Unless I am missing something, you'll never get here if the pretimeout module
parameter is set.

> +			wdd->timeout = timeout_parm;
> +			wdd->pretimeout = timeouts[1];
> +			return 0;
> +		}
>   		ret = -EINVAL;
> +	}
>
> -	/* try to get the timeout_sec property */
> +	/*
> +	 * We get here, the situation is one of them:
> +	 * (1)at least one of parameters is invalid(ret = -EINVAL);
> +	 * (2)both of them are 0.(ret = 0)
> +	 * So give up the module parameter(at least drop the invalid one),
> +	 * try to get the timeout_sec property from dtb.

Please simplify the comment.

	Either at least one of the module parameters is invalid,
	or both of them are 0. 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
> -		ret = -EINVAL;
>
> -	return ret;
> +	/*
> +	 * We get here, that means maybe we can get timeouts from dtb,
> +	 * if "timeout-sec" is available and the data is valid.
> +	 */

That comment is not needed; it is obvious.

> +	of_find_property(dev->of_node, "timeout-sec", &length);
> +	if (length > 0 && length <= sizeof(u32) * 2) {

You need to check the return value of of_find_property() instead of assuming
that length will be 0 if it is not found.

> +		of_property_read_u32_array(dev->of_node,
> +					   "timeout-sec", timeouts,
> +					   length / sizeof(u32));
> +		if (length == sizeof(u32) * 2 && timeouts[1] &&
> +		    watchdog_pretimeout_invalid(wdd, timeouts[1]))
> +				return -EINVAL; /* pretimeout is invalid */

Obvious comment.

> +
> +		if (!watchdog_timeout_invalid(wdd, timeouts[0]) &&
> +		    timeouts[0]) {
> +			wdd->timeout = timeouts[0];
> +			wdd->pretimeout = timeouts[1];
> +			return 0;
> +		}
> +	}
> +
> +	return -EINVAL;
>   }
> -EXPORT_SYMBOL_GPL(watchdog_init_timeout);
> +EXPORT_SYMBOL_GPL(watchdog_init_timeouts);
>
>   /**
>    * watchdog_register_device() - register a watchdog device
> @@ -119,7 +178,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..af0777e 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,27 @@ 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:
> +		/* check if we support the pretimeout */
> +		if (!(wdd->info->options & WDIOF_PRETIMEOUT))
> +			return -EOPNOTSUPP;
> +		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 keeps running (and if
> +		 * possible that it takes the new pretimeout)
> +		 */
> +		watchdog_ping(wdd);
> +		/* Fall */
> +	case WDIOC_GETPRETIMEOUT:
> +		/* check if we support the pretimeout */
> +		if (wdd->info->options & WDIOF_PRETIMEOUT)
> +			return put_user(wdd->pretimeout, p);
> +		return -EOPNOTSUPP;
>   	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..b1e325d 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;
> @@ -117,7 +125,17 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
>   static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
>   {
>   	return ((wdd->max_timeout != 0) &&
> -		(t < wdd->min_timeout || t > wdd->max_timeout));
> +		(t < wdd->min_timeout || t > wdd->max_timeout ||
> +			t <= wdd->pretimeout));
> +}
> +
> +/* 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 ||
> +			(wdd->timeout != 0 && t >= wdd->timeout)));

This validates a pretimeout as valid if max_pretimeout == 0,
no matter what timeout is set to.

Do we really need to check if timeout == 0 ? Can that ever happen ?

>   }
>
>   /* Use the following functions to manipulate watchdog driver specific data */
> @@ -132,11 +150,20 @@ 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,
> +				  struct device *dev);

No 'extern' here, please. Yes, we'll need to fix that for the other
function declarations, but that is not a reason to introduce new ones.

Thanks,
Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 4/7] Watchdog: introdouce "pretimeout" into framework
@ 2015-06-02 16:12       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-02 16:12 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	corbet-T1hC0tSOHrs, mark.rutland-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	rjw-LthD3rsA81gm4RdzfppkhA

On 06/01/2015 09:05 PM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> 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 drivers are going to use this: ARM SBSA Generic Watchdog
>
> Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>   Documentation/watchdog/watchdog-kernel-api.txt |  47 ++++++++--
>   drivers/watchdog/watchdog_core.c               | 115 +++++++++++++++++++------
>   drivers/watchdog/watchdog_dev.c                |  53 ++++++++++++
>   include/linux/watchdog.h                       |  33 ++++++-
>   4 files changed, 212 insertions(+), 36 deletions(-)
>
> diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
> index a0438f3..95b355d 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.
> @@ -219,8 +236,28 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
>                                     unsigned int timeout_parm, struct device *dev);
>
>   The watchdog_init_timeout function allows you to initialize the timeout field
> -using the module timeout parameter or by retrieving the timeout-sec property from
> -the device tree (if the module timeout parameter is invalid). Best practice is
> -to set the default timeout value as timeout value in the watchdog_device and
> -then use this function to set the user "preferred" timeout value.
> +using the module timeout parameter or by retrieving the first element of
> +the timeout-sec property from the device tree (if the module timeout parameter
> +is invalid). Best practice is to set the default timeout value as timeout value
> +in the watchdog_device and then use this function to set the user "preferred"
> +timeout value.
> +This routine returns zero on success and a negative errno code for failure.
> +
> +Some watchdog timers have two stage of timeouts(timeout and pretimeout),
> +to initialize the timeout and pretimeout fields at the same time, the following
> +function can be used:
> +
> +extern int watchdog_init_timeouts(struct watchdog_device *wdd,
> +                                  unsigned int pretimeout_parm,
> +                                  unsigned int timeout_parm,
> +                                  struct device *dev);
> +
> +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).
> +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.
> diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
> index cec9b55..ff18db3 100644
> --- a/drivers/watchdog/watchdog_core.c
> +++ b/drivers/watchdog/watchdog_core.c
> @@ -43,60 +43,119 @@
>   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 timeout and max pretimeout values,
> +	 * if not reset them.
> +	 */
> +	if (wdd->min_pretimeout && wdd->min_timeout < wdd->min_pretimeout) {
> +		pr_info("Invalid min_timeout, resetting to min_pretimeout+1\n");
> +		wdd->min_timeout = wdd->min_pretimeout + 1;
> +	}

min_timeout = 10
max_timeout = 20
min_pretimeout = 30
max_pretimeout = 40

will result in min_timeout set to 31.

> +	if (wdd->max_pretimeout && wdd->max_timeout < wdd->max_pretimeout) {
> +		pr_info("Invalid max_pretimeout, resetting to max_timeout-1\n");
> +		wdd->max_pretimeout = wdd->max_timeout - 1;

and then you set max_pretimeout to 19.

So we'll end up with

min_timeout = 31
max_timeout = 20
min_pretimeout = 30
max_pretimeout = 19

Another example: max_pretimeout = 10, max_timeout = 0 -> max_pretimeout = -1.

> +	}

You'll need to determine valid ranges and then enforce those.
Maybe something like
	min_pretimeout < min_timeout < max_timeout
and
	min_pretimeout < max_pretimeout < max_timeout

Not sure if we should adjust anything to a value different to 0.
Seems to me this is just asking for trouble.

>   }
>
>   /**
> - * 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

just 'if it is valid', or 'if it is a valid value' in both cases.

> + * pretimeout_parm and timeout_parm is out of bounds). If none of them are

s/and/or/

> + * 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,
> +			   struct device *dev)
>   {
> -	unsigned int t = 0;
> -	int ret = 0;
> +	int ret = 0, length = 0;
> +	u32 timeouts[2] = {0};
>
> -	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 pretimeout module parameter first,
> +	 * but it can be "0", that means we don't use pretimeout.
> +	 */
> +	if (pretimeout_parm) {
> +		if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm))
> +			timeouts[1] = pretimeout_parm;
> +		ret = -EINVAL; /* pretimeout_parm is not "0", and invalid */

pretimeout_parm is always invalid ? Why ?

>   	}
> -	if (timeout_parm)
> +
> +	/*
> +	 * Try to get the timeout module parameter,
> +	 * if it's valid and pretimeout is ont invalid(ret == 0),

s/ont/not/

> +	 * assignment and return zero. Otherwise, try dtb.
> +	 */
> +	if (timeout_parm) {
> +		if (!watchdog_timeout_invalid(wdd, timeout_parm) && !ret) {

Unless I am missing something, you'll never get here if the pretimeout module
parameter is set.

> +			wdd->timeout = timeout_parm;
> +			wdd->pretimeout = timeouts[1];
> +			return 0;
> +		}
>   		ret = -EINVAL;
> +	}
>
> -	/* try to get the timeout_sec property */
> +	/*
> +	 * We get here, the situation is one of them:
> +	 * (1)at least one of parameters is invalid(ret = -EINVAL);
> +	 * (2)both of them are 0.(ret = 0)
> +	 * So give up the module parameter(at least drop the invalid one),
> +	 * try to get the timeout_sec property from dtb.

Please simplify the comment.

	Either at least one of the module parameters is invalid,
	or both of them are 0. 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
> -		ret = -EINVAL;
>
> -	return ret;
> +	/*
> +	 * We get here, that means maybe we can get timeouts from dtb,
> +	 * if "timeout-sec" is available and the data is valid.
> +	 */

That comment is not needed; it is obvious.

> +	of_find_property(dev->of_node, "timeout-sec", &length);
> +	if (length > 0 && length <= sizeof(u32) * 2) {

You need to check the return value of of_find_property() instead of assuming
that length will be 0 if it is not found.

> +		of_property_read_u32_array(dev->of_node,
> +					   "timeout-sec", timeouts,
> +					   length / sizeof(u32));
> +		if (length == sizeof(u32) * 2 && timeouts[1] &&
> +		    watchdog_pretimeout_invalid(wdd, timeouts[1]))
> +				return -EINVAL; /* pretimeout is invalid */

Obvious comment.

> +
> +		if (!watchdog_timeout_invalid(wdd, timeouts[0]) &&
> +		    timeouts[0]) {
> +			wdd->timeout = timeouts[0];
> +			wdd->pretimeout = timeouts[1];
> +			return 0;
> +		}
> +	}
> +
> +	return -EINVAL;
>   }
> -EXPORT_SYMBOL_GPL(watchdog_init_timeout);
> +EXPORT_SYMBOL_GPL(watchdog_init_timeouts);
>
>   /**
>    * watchdog_register_device() - register a watchdog device
> @@ -119,7 +178,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..af0777e 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,27 @@ 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:
> +		/* check if we support the pretimeout */
> +		if (!(wdd->info->options & WDIOF_PRETIMEOUT))
> +			return -EOPNOTSUPP;
> +		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 keeps running (and if
> +		 * possible that it takes the new pretimeout)
> +		 */
> +		watchdog_ping(wdd);
> +		/* Fall */
> +	case WDIOC_GETPRETIMEOUT:
> +		/* check if we support the pretimeout */
> +		if (wdd->info->options & WDIOF_PRETIMEOUT)
> +			return put_user(wdd->pretimeout, p);
> +		return -EOPNOTSUPP;
>   	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..b1e325d 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;
> @@ -117,7 +125,17 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
>   static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
>   {
>   	return ((wdd->max_timeout != 0) &&
> -		(t < wdd->min_timeout || t > wdd->max_timeout));
> +		(t < wdd->min_timeout || t > wdd->max_timeout ||
> +			t <= wdd->pretimeout));
> +}
> +
> +/* 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 ||
> +			(wdd->timeout != 0 && t >= wdd->timeout)));

This validates a pretimeout as valid if max_pretimeout == 0,
no matter what timeout is set to.

Do we really need to check if timeout == 0 ? Can that ever happen ?

>   }
>
>   /* Use the following functions to manipulate watchdog driver specific data */
> @@ -132,11 +150,20 @@ 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,
> +				  struct device *dev);

No 'extern' here, please. Yes, we'll need to fix that for the other
function declarations, but that is not a reason to introduce new ones.

Thanks,
Guenter

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-02 16:55         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-02 16:55 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

Hi Timur,

Thanks , feedback inline

On 2 June 2015 at 23:32, Timur Tabi <timur@codeaurora.org> wrote:
> On 06/01/2015 11:05 PM, fu.wei@linaro.org wrote:
>
>> +/*
>> + * help functions for accessing 32bit registers of SBSA Generic Watchdog
>> + */
>> +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);
>> +}
>
>
> I still think you should get rid of these functions and just call
> readl_relaxed() and writel_relaxed() every time, but I won't complain again
> if you keep them.

yes, that make sense, and will reduce the size of code, and I think
the code's readability will be OK too.
will try in my next patch,

>
>> +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;
>> +
>> +       if (wdd->pretimeout)
>> +               /* The pretimeout is valid, go panic */
>> +               panic("SBSA Watchdog pre-timeout");
>> +       else
>> +               /* We don't use pretimeout, trigger WS1 now*/
>> +               sbsa_gwdt_set_wcv(wdd, 0);
>
>
> I don't like this.

If so, what is your idea ,if pretimeout == 0?

the reason of using WCV as (timout - pretimeout): it can provide the
longer timeout period,
(1)If we use WOR, it can only provide 10s @ 400MHz(max).
as Guenter said earlier, the default timer out for most watchdog will
be 30s, so I think 10s limit will be a little short
(2)we can always program WCV just like ping.
(3)if a timeout arrives, WOR will be use, so use it as pretimeout, but
we still can make this pretimeout longer by programming WCV(I don't
think it's necessary)


> The triggering of the hardware reset should never depend
> on an interrupt being handled properly.

if this fail, system reset in 1S, because WOR == (1s)

> You should always program WCV
> correctly in advance.  This is especially true since pre-timeout will
> probably rarely be used.

always programming WCV is doable.  But I absolutely can not agree "
pre-timeout will probably rarely be used"
If so, SBSA watchdog is just a normal watchdog,  This use case just
makes this HW useless.
If so, go to use SP805.
you still don't see the importance of this warning and pretimeout to a
real server.

If the software of a real server goes wrong, then you just directly restart it ,
never try to sync/protect the current data, never try to figure out
what is wrong with it.
I don't think that is a good server software.

At least, I don't thinks " pre-timeout will probably rarely be used"
is a good idea for a server.
in another word, in a server ,pre-timeout should always be used.

> So what happens if the CPU is totally hung and

Again, system reset in 1S, because WOR == (1s).

> this interrupt handler is never called?  When will the timeout occur?

if this interrupt hardler is never called,  what I can see is "some
one is feeding the dog".
OK, in case, WS0 is triggered, but  this interrupt hardler isn't
called, then software really goes wrong.  Then , Again, Again system
reset in 1S, because WOR == (1s).

>
>> +static int sbsa_gwdt_probe(struct platform_device *pdev)
>> +{
>> +       u64 first_period_max = U64_MAX;
>> +       struct device *dev = &pdev->dev;
>> +       struct watchdog_device *wdd;
>> +       struct sbsa_gwdt *gwdt;
>> +       struct resource *res;
>> +       void *rf_base, *cf_base;
>> +       int ret, irq;
>> +       u32 status;
>> +
>> +       gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
>> +       if (!gwdt)
>> +               return -ENOMEM;
>> +       platform_set_drvdata(pdev, gwdt);
>
>
> You should probably do this *after* calling platform_get_irq_byname().

 it just dose (pdev->) dev->driver_data = gwdt
If we got gwdt, we can do that.

But maybe I miss something(or a rule of usage),  so please let know
why this has to be called  *after* calling platform_get_irq_byname().

>
>> +
>> +       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(cf_base))
>> +               return PTR_ERR(cf_base);
>> +
>> +       irq = platform_get_irq_byname(pdev, "ws0");
>> +       if (irq < 0) {
>> +               dev_err(dev, "unable to get ws0 interrupt.\n");
>> +               return irq;
>> +       }
>> +
>> +       /*
>> +        * Get the frequency of system counter from the cp15 interface of
>> ARM
>> +        * Generic timer. We don't need to check it, because if it returns
>> "0",
>> +        * system would panic in very early stage.
>> +        */
>> +       gwdt->clk = arch_timer_get_cntfrq();
>> +       gwdt->refresh_base = rf_base;
>> +       gwdt->control_base = cf_base;
>> +
>> +       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);
>> +
>> +       wdd->min_pretimeout = 0;
>> +       wdd->max_pretimeout = U32_MAX / gwdt->clk;
>> +       wdd->min_timeout = 1;
>> +       do_div(first_period_max, gwdt->clk);
>> +       wdd->max_timeout = first_period_max;
>> +
>> +       wdd->pretimeout = DEFAULT_PRETIMEOUT;
>> +       wdd->timeout = DEFAULT_TIMEOUT;
>> +       watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
>> +
>> +       status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
>> +       if (status & SBSA_GWDT_WCS_WS1) {
>> +               dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
>> +                        sbsa_gwdt_get_wcv(wdd));
>
>
> "System was previously reset via watchdog" is much clearer.

OK

>
>> +               wdd->bootstatus |= WDIOF_CARDRESET;
>> +       }
>> +       /* Check if watchdog is already enabled */
>> +       if (status & SBSA_GWDT_WCS_EN) {
>> +               dev_warn(dev, "already enabled!\n");
>
>
> "watchdog is already enabled".

I think I don't need to print "watchdog",   dev_warn(dev,  has help us on this.
If you do so , the message will be "watchdog: watchdog0: watchdog is
already enabled"

 > Never use exclamation marks in kernel
> messages.

that make sense , will delete it.

>
>> +               sbsa_gwdt_keepalive(wdd);
>> +       }
>> +
>> +       /* update pretimeout to WOR */
>> +       sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
>> +
>> +       ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
>> +                              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 @ %u
>> Hz\n",
>> +                wdd->timeout, wdd->pretimeout, gwdt->clk);
>
>
> if (wdd->pretimeout)
>         "watchdog initialized to %us timeout and %us pre-timeout at %u
> Hz\n", wdd->timeout, wdd->pretimeout, gwdt->clk
> else
>         "watchdog initialized to %us timeout at %u Hz\n", wdd->timeout,
> gwdt->clk
>
> I think it's unlikely that users will use pre-timeout, so your code should
> treat pre-timeout as a special case, not the normal usage.

I don't think so, that why you didn't use pretimeout in your driver.
Because you don't see the meaning of "pretimeout" to a  server.

>
> --
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-02 16:55         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-02 16:55 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw-LthD3rsA81gm4RdzfppkhA

Hi Timur,

Thanks , feedback inline

On 2 June 2015 at 23:32, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
> On 06/01/2015 11:05 PM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>
>> +/*
>> + * help functions for accessing 32bit registers of SBSA Generic Watchdog
>> + */
>> +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);
>> +}
>
>
> I still think you should get rid of these functions and just call
> readl_relaxed() and writel_relaxed() every time, but I won't complain again
> if you keep them.

yes, that make sense, and will reduce the size of code, and I think
the code's readability will be OK too.
will try in my next patch,

>
>> +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;
>> +
>> +       if (wdd->pretimeout)
>> +               /* The pretimeout is valid, go panic */
>> +               panic("SBSA Watchdog pre-timeout");
>> +       else
>> +               /* We don't use pretimeout, trigger WS1 now*/
>> +               sbsa_gwdt_set_wcv(wdd, 0);
>
>
> I don't like this.

If so, what is your idea ,if pretimeout == 0?

the reason of using WCV as (timout - pretimeout): it can provide the
longer timeout period,
(1)If we use WOR, it can only provide 10s @ 400MHz(max).
as Guenter said earlier, the default timer out for most watchdog will
be 30s, so I think 10s limit will be a little short
(2)we can always program WCV just like ping.
(3)if a timeout arrives, WOR will be use, so use it as pretimeout, but
we still can make this pretimeout longer by programming WCV(I don't
think it's necessary)


> The triggering of the hardware reset should never depend
> on an interrupt being handled properly.

if this fail, system reset in 1S, because WOR == (1s)

> You should always program WCV
> correctly in advance.  This is especially true since pre-timeout will
> probably rarely be used.

always programming WCV is doable.  But I absolutely can not agree "
pre-timeout will probably rarely be used"
If so, SBSA watchdog is just a normal watchdog,  This use case just
makes this HW useless.
If so, go to use SP805.
you still don't see the importance of this warning and pretimeout to a
real server.

If the software of a real server goes wrong, then you just directly restart it ,
never try to sync/protect the current data, never try to figure out
what is wrong with it.
I don't think that is a good server software.

At least, I don't thinks " pre-timeout will probably rarely be used"
is a good idea for a server.
in another word, in a server ,pre-timeout should always be used.

> So what happens if the CPU is totally hung and

Again, system reset in 1S, because WOR == (1s).

> this interrupt handler is never called?  When will the timeout occur?

if this interrupt hardler is never called,  what I can see is "some
one is feeding the dog".
OK, in case, WS0 is triggered, but  this interrupt hardler isn't
called, then software really goes wrong.  Then , Again, Again system
reset in 1S, because WOR == (1s).

>
>> +static int sbsa_gwdt_probe(struct platform_device *pdev)
>> +{
>> +       u64 first_period_max = U64_MAX;
>> +       struct device *dev = &pdev->dev;
>> +       struct watchdog_device *wdd;
>> +       struct sbsa_gwdt *gwdt;
>> +       struct resource *res;
>> +       void *rf_base, *cf_base;
>> +       int ret, irq;
>> +       u32 status;
>> +
>> +       gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
>> +       if (!gwdt)
>> +               return -ENOMEM;
>> +       platform_set_drvdata(pdev, gwdt);
>
>
> You should probably do this *after* calling platform_get_irq_byname().

 it just dose (pdev->) dev->driver_data = gwdt
If we got gwdt, we can do that.

But maybe I miss something(or a rule of usage),  so please let know
why this has to be called  *after* calling platform_get_irq_byname().

>
>> +
>> +       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(cf_base))
>> +               return PTR_ERR(cf_base);
>> +
>> +       irq = platform_get_irq_byname(pdev, "ws0");
>> +       if (irq < 0) {
>> +               dev_err(dev, "unable to get ws0 interrupt.\n");
>> +               return irq;
>> +       }
>> +
>> +       /*
>> +        * Get the frequency of system counter from the cp15 interface of
>> ARM
>> +        * Generic timer. We don't need to check it, because if it returns
>> "0",
>> +        * system would panic in very early stage.
>> +        */
>> +       gwdt->clk = arch_timer_get_cntfrq();
>> +       gwdt->refresh_base = rf_base;
>> +       gwdt->control_base = cf_base;
>> +
>> +       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);
>> +
>> +       wdd->min_pretimeout = 0;
>> +       wdd->max_pretimeout = U32_MAX / gwdt->clk;
>> +       wdd->min_timeout = 1;
>> +       do_div(first_period_max, gwdt->clk);
>> +       wdd->max_timeout = first_period_max;
>> +
>> +       wdd->pretimeout = DEFAULT_PRETIMEOUT;
>> +       wdd->timeout = DEFAULT_TIMEOUT;
>> +       watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
>> +
>> +       status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
>> +       if (status & SBSA_GWDT_WCS_WS1) {
>> +               dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
>> +                        sbsa_gwdt_get_wcv(wdd));
>
>
> "System was previously reset via watchdog" is much clearer.

OK

>
>> +               wdd->bootstatus |= WDIOF_CARDRESET;
>> +       }
>> +       /* Check if watchdog is already enabled */
>> +       if (status & SBSA_GWDT_WCS_EN) {
>> +               dev_warn(dev, "already enabled!\n");
>
>
> "watchdog is already enabled".

I think I don't need to print "watchdog",   dev_warn(dev,  has help us on this.
If you do so , the message will be "watchdog: watchdog0: watchdog is
already enabled"

 > Never use exclamation marks in kernel
> messages.

that make sense , will delete it.

>
>> +               sbsa_gwdt_keepalive(wdd);
>> +       }
>> +
>> +       /* update pretimeout to WOR */
>> +       sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
>> +
>> +       ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
>> +                              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 @ %u
>> Hz\n",
>> +                wdd->timeout, wdd->pretimeout, gwdt->clk);
>
>
> if (wdd->pretimeout)
>         "watchdog initialized to %us timeout and %us pre-timeout at %u
> Hz\n", wdd->timeout, wdd->pretimeout, gwdt->clk
> else
>         "watchdog initialized to %us timeout at %u Hz\n", wdd->timeout,
> gwdt->clk
>
> I think it's unlikely that users will use pre-timeout, so your code should
> treat pre-timeout as a special case, not the normal usage.

I don't think so, that why you didn't use pretimeout in your driver.
Because you don't see the meaning of "pretimeout" to a  server.

>
> --
> 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
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-02 17:07           ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-02 17:07 UTC (permalink / raw)
  To: Fu Wei, Timur Tabi
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

On 06/02/2015 09:55 AM, Fu Wei wrote:
> Hi Timur,
>
> Thanks , feedback inline
>
> On 2 June 2015 at 23:32, Timur Tabi <timur@codeaurora.org> wrote:
>> On 06/01/2015 11:05 PM, fu.wei@linaro.org wrote:
>>
>>> +/*
>>> + * help functions for accessing 32bit registers of SBSA Generic Watchdog
>>> + */
>>> +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);
>>> +}
>>
>>
>> I still think you should get rid of these functions and just call
>> readl_relaxed() and writel_relaxed() every time, but I won't complain again
>> if you keep them.
>
> yes, that make sense, and will reduce the size of code, and I think
> the code's readability will be OK too.
> will try in my next patch,
>
>>
>>> +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;
>>> +
>>> +       if (wdd->pretimeout)
>>> +               /* The pretimeout is valid, go panic */
>>> +               panic("SBSA Watchdog pre-timeout");
>>> +       else
>>> +               /* We don't use pretimeout, trigger WS1 now*/
>>> +               sbsa_gwdt_set_wcv(wdd, 0);
>>
>>
>> I don't like this.
>
> If so, what is your idea ,if pretimeout == 0?
>
> the reason of using WCV as (timout - pretimeout): it can provide the
> longer timeout period,
> (1)If we use WOR, it can only provide 10s @ 400MHz(max).
> as Guenter said earlier, the default timer out for most watchdog will
> be 30s, so I think 10s limit will be a little short
> (2)we can always program WCV just like ping.
> (3)if a timeout arrives, WOR will be use, so use it as pretimeout, but
> we still can make this pretimeout longer by programming WCV(I don't
> think it's necessary)
>
>
>> The triggering of the hardware reset should never depend
>> on an interrupt being handled properly.
>
> if this fail, system reset in 1S, because WOR == (1s)
>
So ?

>> You should always program WCV
>> correctly in advance.  This is especially true since pre-timeout will
>> probably rarely be used.
>
> always programming WCV is doable.  But I absolutely can not agree "
> pre-timeout will probably rarely be used"
> If so, SBSA watchdog is just a normal watchdog,  This use case just
> makes this HW useless.
> If so, go to use SP805.
> you still don't see the importance of this warning and pretimeout to a
> real server.
>

If pretimeout isn't used, why not just set WCV = timeout, WOR = 0 ?

Guenter

> If the software of a real server goes wrong, then you just directly restart it ,
> never try to sync/protect the current data, never try to figure out
> what is wrong with it.
> I don't think that is a good server software.
>
> At least, I don't thinks " pre-timeout will probably rarely be used"
> is a good idea for a server.
> in another word, in a server ,pre-timeout should always be used.
>
>> So what happens if the CPU is totally hung and
>
> Again, system reset in 1S, because WOR == (1s).
>
>> this interrupt handler is never called?  When will the timeout occur?
>
> if this interrupt hardler is never called,  what I can see is "some
> one is feeding the dog".
> OK, in case, WS0 is triggered, but  this interrupt hardler isn't
> called, then software really goes wrong.  Then , Again, Again system
> reset in 1S, because WOR == (1s).
>
>>
>>> +static int sbsa_gwdt_probe(struct platform_device *pdev)
>>> +{
>>> +       u64 first_period_max = U64_MAX;
>>> +       struct device *dev = &pdev->dev;
>>> +       struct watchdog_device *wdd;
>>> +       struct sbsa_gwdt *gwdt;
>>> +       struct resource *res;
>>> +       void *rf_base, *cf_base;
>>> +       int ret, irq;
>>> +       u32 status;
>>> +
>>> +       gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
>>> +       if (!gwdt)
>>> +               return -ENOMEM;
>>> +       platform_set_drvdata(pdev, gwdt);
>>
>>
>> You should probably do this *after* calling platform_get_irq_byname().
>
>   it just dose (pdev->) dev->driver_data = gwdt
> If we got gwdt, we can do that.
>
> But maybe I miss something(or a rule of usage),  so please let know
> why this has to be called  *after* calling platform_get_irq_byname().
>
>>
>>> +
>>> +       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(cf_base))
>>> +               return PTR_ERR(cf_base);
>>> +
>>> +       irq = platform_get_irq_byname(pdev, "ws0");
>>> +       if (irq < 0) {
>>> +               dev_err(dev, "unable to get ws0 interrupt.\n");
>>> +               return irq;
>>> +       }
>>> +
>>> +       /*
>>> +        * Get the frequency of system counter from the cp15 interface of
>>> ARM
>>> +        * Generic timer. We don't need to check it, because if it returns
>>> "0",
>>> +        * system would panic in very early stage.
>>> +        */
>>> +       gwdt->clk = arch_timer_get_cntfrq();
>>> +       gwdt->refresh_base = rf_base;
>>> +       gwdt->control_base = cf_base;
>>> +
>>> +       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);
>>> +
>>> +       wdd->min_pretimeout = 0;
>>> +       wdd->max_pretimeout = U32_MAX / gwdt->clk;
>>> +       wdd->min_timeout = 1;
>>> +       do_div(first_period_max, gwdt->clk);
>>> +       wdd->max_timeout = first_period_max;
>>> +
>>> +       wdd->pretimeout = DEFAULT_PRETIMEOUT;
>>> +       wdd->timeout = DEFAULT_TIMEOUT;
>>> +       watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
>>> +
>>> +       status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
>>> +       if (status & SBSA_GWDT_WCS_WS1) {
>>> +               dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
>>> +                        sbsa_gwdt_get_wcv(wdd));
>>
>>
>> "System was previously reset via watchdog" is much clearer.
>
> OK
>
>>
>>> +               wdd->bootstatus |= WDIOF_CARDRESET;
>>> +       }
>>> +       /* Check if watchdog is already enabled */
>>> +       if (status & SBSA_GWDT_WCS_EN) {
>>> +               dev_warn(dev, "already enabled!\n");
>>
>>
>> "watchdog is already enabled".
>
> I think I don't need to print "watchdog",   dev_warn(dev,  has help us on this.
> If you do so , the message will be "watchdog: watchdog0: watchdog is
> already enabled"
>
>   > Never use exclamation marks in kernel
>> messages.
>
> that make sense , will delete it.
>
>>
>>> +               sbsa_gwdt_keepalive(wdd);
>>> +       }
>>> +
>>> +       /* update pretimeout to WOR */
>>> +       sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
>>> +
>>> +       ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
>>> +                              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 @ %u
>>> Hz\n",
>>> +                wdd->timeout, wdd->pretimeout, gwdt->clk);
>>
>>
>> if (wdd->pretimeout)
>>          "watchdog initialized to %us timeout and %us pre-timeout at %u
>> Hz\n", wdd->timeout, wdd->pretimeout, gwdt->clk
>> else
>>          "watchdog initialized to %us timeout at %u Hz\n", wdd->timeout,
>> gwdt->clk
>>
>> I think it's unlikely that users will use pre-timeout, so your code should
>> treat pre-timeout as a special case, not the normal usage.
>
> I don't think so, that why you didn't use pretimeout in your driver.
> Because you don't see the meaning of "pretimeout" to a  server.
>
>>
>> --
>> Qualcomm Innovation Center, Inc.
>> The Qualcomm Innovation Center, Inc. is a member of the
>> Code Aurora Forum, a Linux Foundation Collaborative Project.
>
>
>


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-02 17:07           ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-02 17:07 UTC (permalink / raw)
  To: Fu Wei, Timur Tabi
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw-LthD3rsA81gm4RdzfppkhA

On 06/02/2015 09:55 AM, Fu Wei wrote:
> Hi Timur,
>
> Thanks , feedback inline
>
> On 2 June 2015 at 23:32, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
>> On 06/01/2015 11:05 PM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>>
>>> +/*
>>> + * help functions for accessing 32bit registers of SBSA Generic Watchdog
>>> + */
>>> +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);
>>> +}
>>
>>
>> I still think you should get rid of these functions and just call
>> readl_relaxed() and writel_relaxed() every time, but I won't complain again
>> if you keep them.
>
> yes, that make sense, and will reduce the size of code, and I think
> the code's readability will be OK too.
> will try in my next patch,
>
>>
>>> +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;
>>> +
>>> +       if (wdd->pretimeout)
>>> +               /* The pretimeout is valid, go panic */
>>> +               panic("SBSA Watchdog pre-timeout");
>>> +       else
>>> +               /* We don't use pretimeout, trigger WS1 now*/
>>> +               sbsa_gwdt_set_wcv(wdd, 0);
>>
>>
>> I don't like this.
>
> If so, what is your idea ,if pretimeout == 0?
>
> the reason of using WCV as (timout - pretimeout): it can provide the
> longer timeout period,
> (1)If we use WOR, it can only provide 10s @ 400MHz(max).
> as Guenter said earlier, the default timer out for most watchdog will
> be 30s, so I think 10s limit will be a little short
> (2)we can always program WCV just like ping.
> (3)if a timeout arrives, WOR will be use, so use it as pretimeout, but
> we still can make this pretimeout longer by programming WCV(I don't
> think it's necessary)
>
>
>> The triggering of the hardware reset should never depend
>> on an interrupt being handled properly.
>
> if this fail, system reset in 1S, because WOR == (1s)
>
So ?

>> You should always program WCV
>> correctly in advance.  This is especially true since pre-timeout will
>> probably rarely be used.
>
> always programming WCV is doable.  But I absolutely can not agree "
> pre-timeout will probably rarely be used"
> If so, SBSA watchdog is just a normal watchdog,  This use case just
> makes this HW useless.
> If so, go to use SP805.
> you still don't see the importance of this warning and pretimeout to a
> real server.
>

If pretimeout isn't used, why not just set WCV = timeout, WOR = 0 ?

Guenter

> If the software of a real server goes wrong, then you just directly restart it ,
> never try to sync/protect the current data, never try to figure out
> what is wrong with it.
> I don't think that is a good server software.
>
> At least, I don't thinks " pre-timeout will probably rarely be used"
> is a good idea for a server.
> in another word, in a server ,pre-timeout should always be used.
>
>> So what happens if the CPU is totally hung and
>
> Again, system reset in 1S, because WOR == (1s).
>
>> this interrupt handler is never called?  When will the timeout occur?
>
> if this interrupt hardler is never called,  what I can see is "some
> one is feeding the dog".
> OK, in case, WS0 is triggered, but  this interrupt hardler isn't
> called, then software really goes wrong.  Then , Again, Again system
> reset in 1S, because WOR == (1s).
>
>>
>>> +static int sbsa_gwdt_probe(struct platform_device *pdev)
>>> +{
>>> +       u64 first_period_max = U64_MAX;
>>> +       struct device *dev = &pdev->dev;
>>> +       struct watchdog_device *wdd;
>>> +       struct sbsa_gwdt *gwdt;
>>> +       struct resource *res;
>>> +       void *rf_base, *cf_base;
>>> +       int ret, irq;
>>> +       u32 status;
>>> +
>>> +       gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
>>> +       if (!gwdt)
>>> +               return -ENOMEM;
>>> +       platform_set_drvdata(pdev, gwdt);
>>
>>
>> You should probably do this *after* calling platform_get_irq_byname().
>
>   it just dose (pdev->) dev->driver_data = gwdt
> If we got gwdt, we can do that.
>
> But maybe I miss something(or a rule of usage),  so please let know
> why this has to be called  *after* calling platform_get_irq_byname().
>
>>
>>> +
>>> +       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(cf_base))
>>> +               return PTR_ERR(cf_base);
>>> +
>>> +       irq = platform_get_irq_byname(pdev, "ws0");
>>> +       if (irq < 0) {
>>> +               dev_err(dev, "unable to get ws0 interrupt.\n");
>>> +               return irq;
>>> +       }
>>> +
>>> +       /*
>>> +        * Get the frequency of system counter from the cp15 interface of
>>> ARM
>>> +        * Generic timer. We don't need to check it, because if it returns
>>> "0",
>>> +        * system would panic in very early stage.
>>> +        */
>>> +       gwdt->clk = arch_timer_get_cntfrq();
>>> +       gwdt->refresh_base = rf_base;
>>> +       gwdt->control_base = cf_base;
>>> +
>>> +       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);
>>> +
>>> +       wdd->min_pretimeout = 0;
>>> +       wdd->max_pretimeout = U32_MAX / gwdt->clk;
>>> +       wdd->min_timeout = 1;
>>> +       do_div(first_period_max, gwdt->clk);
>>> +       wdd->max_timeout = first_period_max;
>>> +
>>> +       wdd->pretimeout = DEFAULT_PRETIMEOUT;
>>> +       wdd->timeout = DEFAULT_TIMEOUT;
>>> +       watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
>>> +
>>> +       status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
>>> +       if (status & SBSA_GWDT_WCS_WS1) {
>>> +               dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
>>> +                        sbsa_gwdt_get_wcv(wdd));
>>
>>
>> "System was previously reset via watchdog" is much clearer.
>
> OK
>
>>
>>> +               wdd->bootstatus |= WDIOF_CARDRESET;
>>> +       }
>>> +       /* Check if watchdog is already enabled */
>>> +       if (status & SBSA_GWDT_WCS_EN) {
>>> +               dev_warn(dev, "already enabled!\n");
>>
>>
>> "watchdog is already enabled".
>
> I think I don't need to print "watchdog",   dev_warn(dev,  has help us on this.
> If you do so , the message will be "watchdog: watchdog0: watchdog is
> already enabled"
>
>   > Never use exclamation marks in kernel
>> messages.
>
> that make sense , will delete it.
>
>>
>>> +               sbsa_gwdt_keepalive(wdd);
>>> +       }
>>> +
>>> +       /* update pretimeout to WOR */
>>> +       sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
>>> +
>>> +       ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
>>> +                              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 @ %u
>>> Hz\n",
>>> +                wdd->timeout, wdd->pretimeout, gwdt->clk);
>>
>>
>> if (wdd->pretimeout)
>>          "watchdog initialized to %us timeout and %us pre-timeout at %u
>> Hz\n", wdd->timeout, wdd->pretimeout, gwdt->clk
>> else
>>          "watchdog initialized to %us timeout at %u Hz\n", wdd->timeout,
>> gwdt->clk
>>
>> I think it's unlikely that users will use pre-timeout, so your code should
>> treat pre-timeout as a special case, not the normal usage.
>
> I don't think so, that why you didn't use pretimeout in your driver.
> Because you don't see the meaning of "pretimeout" to a  server.
>
>>
>> --
>> Qualcomm Innovation Center, Inc.
>> The Qualcomm Innovation Center, Inc. is a member of the
>> Code Aurora Forum, a Linux Foundation Collaborative Project.
>
>
>

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-02 17:21           ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-02 17:21 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

On 06/02/2015 11:55 AM, Fu Wei wrote:

>>> +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;
>>> +
>>> +       if (wdd->pretimeout)
>>> +               /* The pretimeout is valid, go panic */
>>> +               panic("SBSA Watchdog pre-timeout");
>>> +       else
>>> +               /* We don't use pretimeout, trigger WS1 now*/
>>> +               sbsa_gwdt_set_wcv(wdd, 0);
>>
>>
>> I don't like this.
>
> If so, what is your idea ,if pretimeout == 0?

If pretimeout == 0, then WCV should be set to timeout/2.  The WS0 
timeout will occur after timeout/2 seconds, and the driver will ignore 
it in the interrupt handler.  Then after another timeout/2 seconds, WS1 
will timeout and the system will reset.

> the reason of using WCV as (timout - pretimeout): it can provide the
> longer timeout period,
> (1)If we use WOR, it can only provide 10s @ 400MHz(max).
> as Guenter said earlier, the default timer out for most watchdog will
> be 30s, so I think 10s limit will be a little short
> (2)we can always program WCV just like ping.
> (3)if a timeout arrives, WOR will be use, so use it as pretimeout, but
> we still can make this pretimeout longer by programming WCV(I don't
> think it's necessary)

I understand that, but like I said, I think pretimeout will be rarely 
used, and so the driver should work best with pre-timeout enabled.

>> The triggering of the hardware reset should never depend
>> on an interrupt being handled properly.
>
> if this fail, system reset in 1S, because WOR == (1s)
>
>> You should always program WCV
>> correctly in advance.  This is especially true since pre-timeout will
>> probably rarely be used.
>
> always programming WCV is doable.  But I absolutely can not agree "
> pre-timeout will probably rarely be used"
> If so, SBSA watchdog is just a normal watchdog,

So what? What's wrong with that?  Users don't have any control over 
which watchdog hardware is on the SOC, and they don't care.  They will 
use the same watchdog software as they do on x86.

Users *want* a normal watchdog.  Pre-timeout is only supported on time 
watchdog hardware, so no one will standardize on it.  ARM servers 
supposed to be interchangeable with x86 servers.  Customers are not 
going to do anything special on an ARM server that they don't do on an 
x86 server.  I've been working in the ARM server industry for over two 
years, and that's why everyone says.

> This use case just
> makes this HW useless.
> If so, go to use SP805.
> you still don't see the importance of this warning and pretimeout to a
> real server.
>
> If the software of a real server goes wrong, then you just directly restart it ,
> never try to sync/protect the current data, never try to figure out
> what is wrong with it.
> I don't think that is a good server software.

And that is exactly why my driver treats WS0 as the real timeout, and 
WS1 as a "backup" timeout.  When WS0 expires, the system tries to do a 
"polite" reset.  If that doesn't work, then WS1 will do a hard reset.

This also allows me to have a timeout that's twice as long as your 
driver, so my timeout occurs in WS0, not WS1.

> At least, I don't thinks " pre-timeout will probably rarely be used"
> is a good idea for a server.
> in another word, in a server ,pre-timeout should always be used.

Except that few servers today support pre-timeout, so customers won't 
depend on it.

>> You should probably do this *after* calling platform_get_irq_byname().
>
>   it just dose (pdev->) dev->driver_data = gwdt
> If we got gwdt, we can do that.
>
> But maybe I miss something(or a rule of usage),  so please let know
> why this has to be called  *after* calling platform_get_irq_byname().

It's just so that you can avoid calling kzalloc() if the 
platform_get_irq_byname() fails.  It's not important.

> I think I don't need to print "watchdog",   dev_warn(dev,  has help us on this.
> If you do so , the message will be "watchdog: watchdog0: watchdog is
> already enabled"

Ok.

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-02 17:21           ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-02 17:21 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw-LthD3rsA81gm4RdzfppkhA

On 06/02/2015 11:55 AM, Fu Wei wrote:

>>> +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;
>>> +
>>> +       if (wdd->pretimeout)
>>> +               /* The pretimeout is valid, go panic */
>>> +               panic("SBSA Watchdog pre-timeout");
>>> +       else
>>> +               /* We don't use pretimeout, trigger WS1 now*/
>>> +               sbsa_gwdt_set_wcv(wdd, 0);
>>
>>
>> I don't like this.
>
> If so, what is your idea ,if pretimeout == 0?

If pretimeout == 0, then WCV should be set to timeout/2.  The WS0 
timeout will occur after timeout/2 seconds, and the driver will ignore 
it in the interrupt handler.  Then after another timeout/2 seconds, WS1 
will timeout and the system will reset.

> the reason of using WCV as (timout - pretimeout): it can provide the
> longer timeout period,
> (1)If we use WOR, it can only provide 10s @ 400MHz(max).
> as Guenter said earlier, the default timer out for most watchdog will
> be 30s, so I think 10s limit will be a little short
> (2)we can always program WCV just like ping.
> (3)if a timeout arrives, WOR will be use, so use it as pretimeout, but
> we still can make this pretimeout longer by programming WCV(I don't
> think it's necessary)

I understand that, but like I said, I think pretimeout will be rarely 
used, and so the driver should work best with pre-timeout enabled.

>> The triggering of the hardware reset should never depend
>> on an interrupt being handled properly.
>
> if this fail, system reset in 1S, because WOR == (1s)
>
>> You should always program WCV
>> correctly in advance.  This is especially true since pre-timeout will
>> probably rarely be used.
>
> always programming WCV is doable.  But I absolutely can not agree "
> pre-timeout will probably rarely be used"
> If so, SBSA watchdog is just a normal watchdog,

So what? What's wrong with that?  Users don't have any control over 
which watchdog hardware is on the SOC, and they don't care.  They will 
use the same watchdog software as they do on x86.

Users *want* a normal watchdog.  Pre-timeout is only supported on time 
watchdog hardware, so no one will standardize on it.  ARM servers 
supposed to be interchangeable with x86 servers.  Customers are not 
going to do anything special on an ARM server that they don't do on an 
x86 server.  I've been working in the ARM server industry for over two 
years, and that's why everyone says.

> This use case just
> makes this HW useless.
> If so, go to use SP805.
> you still don't see the importance of this warning and pretimeout to a
> real server.
>
> If the software of a real server goes wrong, then you just directly restart it ,
> never try to sync/protect the current data, never try to figure out
> what is wrong with it.
> I don't think that is a good server software.

And that is exactly why my driver treats WS0 as the real timeout, and 
WS1 as a "backup" timeout.  When WS0 expires, the system tries to do a 
"polite" reset.  If that doesn't work, then WS1 will do a hard reset.

This also allows me to have a timeout that's twice as long as your 
driver, so my timeout occurs in WS0, not WS1.

> At least, I don't thinks " pre-timeout will probably rarely be used"
> is a good idea for a server.
> in another word, in a server ,pre-timeout should always be used.

Except that few servers today support pre-timeout, so customers won't 
depend on it.

>> You should probably do this *after* calling platform_get_irq_byname().
>
>   it just dose (pdev->) dev->driver_data = gwdt
> If we got gwdt, we can do that.
>
> But maybe I miss something(or a rule of usage),  so please let know
> why this has to be called  *after* calling platform_get_irq_byname().

It's just so that you can avoid calling kzalloc() if the 
platform_get_irq_byname() fails.  It's not important.

> I think I don't need to print "watchdog",   dev_warn(dev,  has help us on this.
> If you do so , the message will be "watchdog: watchdog0: watchdog is
> already enabled"

Ok.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-03 18:16       ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-03 18:16 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw

On 06/01/2015 11:05 PM, fu.wei@linaro.org wrote:
> +	if (wdd->pretimeout)
> +		/* The pretimeout is valid, go panic */
> +		panic("SBSA Watchdog pre-timeout");

The problem with this is that WS1 will still occur.  So a few seconds 
after the panic() call, the hardware will reset.  There won't be any 
time to debug or log anything.

> +		/* We don't use pretimeout, trigger WS1 now*/
> +		sbsa_gwdt_set_wcv(wdd, 0);

Are you sure this will work?   This will set WCV to 0, which means it 
the WS1 reset won't happen until the timestamp counter wraps around to 
0.  That could be a very long time from now.

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-03 18:16       ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-03 18:16 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA

On 06/01/2015 11:05 PM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> +	if (wdd->pretimeout)
> +		/* The pretimeout is valid, go panic */
> +		panic("SBSA Watchdog pre-timeout");

The problem with this is that WS1 will still occur.  So a few seconds 
after the panic() call, the hardware will reset.  There won't be any 
time to debug or log anything.

> +		/* We don't use pretimeout, trigger WS1 now*/
> +		sbsa_gwdt_set_wcv(wdd, 0);

Are you sure this will work?   This will set WCV to 0, which means it 
the WS1 reset won't happen until the timestamp counter wraps around to 
0.  That could be a very long time from now.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-03 18:25         ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-03 18:25 UTC (permalink / raw)
  To: Timur Tabi
  Cc: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, hanjun.guo, ashwin.chaugule, arnd,
	vgandhi, wim, jcm, leo.duran, corbet, mark.rutland,
	catalin.marinas, will.deacon, rjw

On Wed, Jun 03, 2015 at 01:16:41PM -0500, Timur Tabi wrote:
> On 06/01/2015 11:05 PM, fu.wei@linaro.org wrote:
> >+	if (wdd->pretimeout)
> >+		/* The pretimeout is valid, go panic */
> >+		panic("SBSA Watchdog pre-timeout");
> 
> The problem with this is that WS1 will still occur.  So a few seconds after
> the panic() call, the hardware will reset.  There won't be any time to debug
> or log anything.
> 

In general the idea here would be to use a crashdump kernel, which,
when loaded, would reset the watchdog before it fires. This kernel
would then write a core dump to a specified location. 

If arm64 doesn't support a crashdump kernel, it might still be possible
to log the backtrace somewhere (eg in nvram using pstore if that is
supported via acpi or efi).

Is there reason to believe that this all won't work on arm64 ?

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-03 18:25         ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-03 18:25 UTC (permalink / raw)
  To: Timur Tabi
  Cc: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	corbet-T1hC0tSOHrs, mark.rutland-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	rjw-LthD3rsA81gm4RdzfppkhA

On Wed, Jun 03, 2015 at 01:16:41PM -0500, Timur Tabi wrote:
> On 06/01/2015 11:05 PM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> >+	if (wdd->pretimeout)
> >+		/* The pretimeout is valid, go panic */
> >+		panic("SBSA Watchdog pre-timeout");
> 
> The problem with this is that WS1 will still occur.  So a few seconds after
> the panic() call, the hardware will reset.  There won't be any time to debug
> or log anything.
> 

In general the idea here would be to use a crashdump kernel, which,
when loaded, would reset the watchdog before it fires. This kernel
would then write a core dump to a specified location. 

If arm64 doesn't support a crashdump kernel, it might still be possible
to log the backtrace somewhere (eg in nvram using pstore if that is
supported via acpi or efi).

Is there reason to believe that this all won't work on arm64 ?

Thanks,
Guenter
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-03 18:53           ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-03 18:53 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, hanjun.guo, ashwin.chaugule, arnd,
	vgandhi, wim, jcm, leo.duran, corbet, mark.rutland,
	catalin.marinas, will.deacon, rjw

On 06/03/2015 01:25 PM, Guenter Roeck wrote:
> In general the idea here would be to use a crashdump kernel, which,
> when loaded, would reset the watchdog before it fires. This kernel
> would then write a core dump to a specified location.

What is the mechanism for resetting the watchdog?  The only code that 
knows about the hardware registers is this driver.  Does the crashdump 
kernel call the watchdog stop function?

> If arm64 doesn't support a crashdump kernel, it might still be possible
> to log the backtrace somewhere (eg in nvram using pstore if that is
> supported via acpi or efi).

I think it's expected that the firmware support a crash dump mechanism 
of some kind.  But if we're talking about firmware support, then why 
bother with the panic() in the first place?

> Is there reason to believe that this all won't work on arm64 ?

No, but I'm still trying to figure out why pre-timeout is valuable.  If 
we don't disable WS1, then we risk having the hardware reset before we 
can take advantage of what the panic() offers.  In which case, what's 
the point of pre-timeout?

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-03 18:53           ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-03 18:53 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	corbet-T1hC0tSOHrs, mark.rutland-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	rjw-LthD3rsA81gm4RdzfppkhA

On 06/03/2015 01:25 PM, Guenter Roeck wrote:
> In general the idea here would be to use a crashdump kernel, which,
> when loaded, would reset the watchdog before it fires. This kernel
> would then write a core dump to a specified location.

What is the mechanism for resetting the watchdog?  The only code that 
knows about the hardware registers is this driver.  Does the crashdump 
kernel call the watchdog stop function?

> If arm64 doesn't support a crashdump kernel, it might still be possible
> to log the backtrace somewhere (eg in nvram using pstore if that is
> supported via acpi or efi).

I think it's expected that the firmware support a crash dump mechanism 
of some kind.  But if we're talking about firmware support, then why 
bother with the panic() in the first place?

> Is there reason to believe that this all won't work on arm64 ?

No, but I'm still trying to figure out why pre-timeout is valuable.  If 
we don't disable WS1, then we risk having the hardware reset before we 
can take advantage of what the panic() offers.  In which case, what's 
the point of pre-timeout?

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-03 18:53           ` Timur Tabi
  (?)
@ 2015-06-03 19:29           ` Arnd Bergmann
  -1 siblings, 0 replies; 550+ messages in thread
From: Arnd Bergmann @ 2015-06-03 19:29 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, fu.wei, Suravee.Suthikulpanit, linaro-acpi,
	linux-watchdog, devicetree, linux-kernel, linux-doc,
	tekkamanninja, graeme.gregory, al.stone, hanjun.guo,
	ashwin.chaugule, vgandhi, wim, jcm, leo.duran, corbet,
	mark.rutland, catalin.marinas, will.deacon, rjw

On Wednesday 03 June 2015 13:53:29 Timur Tabi wrote:
> On 06/03/2015 01:25 PM, Guenter Roeck wrote:
> > In general the idea here would be to use a crashdump kernel, which,
> > when loaded, would reset the watchdog before it fires. This kernel
> > would then write a core dump to a specified location.
> 
> What is the mechanism for resetting the watchdog?  The only code that 
> knows about the hardware registers is this driver.  Does the crashdump 
> kernel call the watchdog stop function?

It might or might not, depending on what you want to achieve. In most
cases, I'd expect the crashdump kernel to have it enabled if we want
to let the user set a pretimeout, but that is a policy question that
is not for the kernel to decide.

> > If arm64 doesn't support a crashdump kernel, it might still be possible
> > to log the backtrace somewhere (eg in nvram using pstore if that is
> > supported via acpi or efi).
> 
> I think it's expected that the firmware support a crash dump mechanism 
> of some kind.  But if we're talking about firmware support, then why 
> bother with the panic() in the first place?

panic() is what triggers all the crash dump or pstore mechanisms, it
has to do that anyway.

> > Is there reason to believe that this all won't work on arm64 ?
> 
> No, but I'm still trying to figure out why pre-timeout is valuable.  If 
> we don't disable WS1, then we risk having the hardware reset before we 
> can take advantage of what the panic() offers.  In which case, what's 
> the point of pre-timeout?

The timeouts are both configurable, so the sysadmin has to make sure that
the time between them is long enough to do whatever is necessary.

	Arnd

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-08 16:05             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-08 16:05 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

Hi Gurnter

On 3 June 2015 at 01:07, Guenter Roeck <linux@roeck-us.net> wrote:
> On 06/02/2015 09:55 AM, Fu Wei wrote:
>>
>> Hi Timur,
>>
>> Thanks , feedback inline
>>
>> On 2 June 2015 at 23:32, Timur Tabi <timur@codeaurora.org> wrote:
>>>
>>> On 06/01/2015 11:05 PM, fu.wei@linaro.org wrote:
>>>
>>>> +/*
>>>> + * help functions for accessing 32bit registers of SBSA Generic
>>>> Watchdog
>>>> + */
>>>> +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);
>>>> +}
>>>
>>>
>>>
>>> I still think you should get rid of these functions and just call
>>> readl_relaxed() and writel_relaxed() every time, but I won't complain
>>> again
>>> if you keep them.
>>
>>
>> yes, that make sense, and will reduce the size of code, and I think
>> the code's readability will be OK too.
>> will try in my next patch,
>>
>>>
>>>> +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;
>>>> +
>>>> +       if (wdd->pretimeout)
>>>> +               /* The pretimeout is valid, go panic */
>>>> +               panic("SBSA Watchdog pre-timeout");
>>>> +       else
>>>> +               /* We don't use pretimeout, trigger WS1 now*/
>>>> +               sbsa_gwdt_set_wcv(wdd, 0);
>>>
>>>
>>>
>>> I don't like this.
>>
>>
>> If so, what is your idea ,if pretimeout == 0?
>>
>> the reason of using WCV as (timout - pretimeout): it can provide the
>> longer timeout period,
>> (1)If we use WOR, it can only provide 10s @ 400MHz(max).
>> as Guenter said earlier, the default timer out for most watchdog will
>> be 30s, so I think 10s limit will be a little short
>> (2)we can always program WCV just like ping.
>> (3)if a timeout arrives, WOR will be use, so use it as pretimeout, but
>> we still can make this pretimeout longer by programming WCV(I don't
>> think it's necessary)
>>
>>
>>> The triggering of the hardware reset should never depend
>>> on an interrupt being handled properly.
>>
>>
>> if this fail, system reset in 1S, because WOR == (1s)
>>
> So ?

Even the interrupt routine isn't triggered,  (WOR + system counter) --> WCV,
then, sy system reset in 1S.

the hardware reset doesn't depend on an interrupt.


>
>>> You should always program WCV
>>> correctly in advance.  This is especially true since pre-timeout will
>>> probably rarely be used.
>>
>>
>> always programming WCV is doable.  But I absolutely can not agree "
>> pre-timeout will probably rarely be used"
>> If so, SBSA watchdog is just a normal watchdog,  This use case just
>> makes this HW useless.
>> If so, go to use SP805.
>> you still don't see the importance of this warning and pretimeout to a
>> real server.
>>
>
> If pretimeout isn't used, why not just set WCV = timeout, WOR = 0 ?

Because if WOR = 0 , according to SBSA,  once you want to enable watchdog,
(0 + system counter) --> WCV , then , WS0 and WS1 will be triggered immediately.
we have not a chance(a time slot) to update WCV.

>
> Guenter
>
>
>> If the software of a real server goes wrong, then you just directly
>> restart it ,
>> never try to sync/protect the current data, never try to figure out
>> what is wrong with it.
>> I don't think that is a good server software.
>>
>> At least, I don't thinks " pre-timeout will probably rarely be used"
>> is a good idea for a server.
>> in another word, in a server ,pre-timeout should always be used.
>>
>>> So what happens if the CPU is totally hung and
>>
>>
>> Again, system reset in 1S, because WOR == (1s).
>>
>>> this interrupt handler is never called?  When will the timeout occur?
>>
>>
>> if this interrupt hardler is never called,  what I can see is "some
>> one is feeding the dog".
>> OK, in case, WS0 is triggered, but  this interrupt hardler isn't
>> called, then software really goes wrong.  Then , Again, Again system
>> reset in 1S, because WOR == (1s).
>>
>>>
>>>> +static int sbsa_gwdt_probe(struct platform_device *pdev)
>>>> +{
>>>> +       u64 first_period_max = U64_MAX;
>>>> +       struct device *dev = &pdev->dev;
>>>> +       struct watchdog_device *wdd;
>>>> +       struct sbsa_gwdt *gwdt;
>>>> +       struct resource *res;
>>>> +       void *rf_base, *cf_base;
>>>> +       int ret, irq;
>>>> +       u32 status;
>>>> +
>>>> +       gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
>>>> +       if (!gwdt)
>>>> +               return -ENOMEM;
>>>> +       platform_set_drvdata(pdev, gwdt);
>>>
>>>
>>>
>>> You should probably do this *after* calling platform_get_irq_byname().
>>
>>
>>   it just dose (pdev->) dev->driver_data = gwdt
>> If we got gwdt, we can do that.
>>
>> But maybe I miss something(or a rule of usage),  so please let know
>> why this has to be called  *after* calling platform_get_irq_byname().
>>
>>>
>>>> +
>>>> +       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(cf_base))
>>>> +               return PTR_ERR(cf_base);
>>>> +
>>>> +       irq = platform_get_irq_byname(pdev, "ws0");
>>>> +       if (irq < 0) {
>>>> +               dev_err(dev, "unable to get ws0 interrupt.\n");
>>>> +               return irq;
>>>> +       }
>>>> +
>>>> +       /*
>>>> +        * Get the frequency of system counter from the cp15 interface
>>>> of
>>>> ARM
>>>> +        * Generic timer. We don't need to check it, because if it
>>>> returns
>>>> "0",
>>>> +        * system would panic in very early stage.
>>>> +        */
>>>> +       gwdt->clk = arch_timer_get_cntfrq();
>>>> +       gwdt->refresh_base = rf_base;
>>>> +       gwdt->control_base = cf_base;
>>>> +
>>>> +       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);
>>>> +
>>>> +       wdd->min_pretimeout = 0;
>>>> +       wdd->max_pretimeout = U32_MAX / gwdt->clk;
>>>> +       wdd->min_timeout = 1;
>>>> +       do_div(first_period_max, gwdt->clk);
>>>> +       wdd->max_timeout = first_period_max;
>>>> +
>>>> +       wdd->pretimeout = DEFAULT_PRETIMEOUT;
>>>> +       wdd->timeout = DEFAULT_TIMEOUT;
>>>> +       watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
>>>> +
>>>> +       status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
>>>> +       if (status & SBSA_GWDT_WCS_WS1) {
>>>> +               dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
>>>> +                        sbsa_gwdt_get_wcv(wdd));
>>>
>>>
>>>
>>> "System was previously reset via watchdog" is much clearer.
>>
>>
>> OK
>>
>>>
>>>> +               wdd->bootstatus |= WDIOF_CARDRESET;
>>>> +       }
>>>> +       /* Check if watchdog is already enabled */
>>>> +       if (status & SBSA_GWDT_WCS_EN) {
>>>> +               dev_warn(dev, "already enabled!\n");
>>>
>>>
>>>
>>> "watchdog is already enabled".
>>
>>
>> I think I don't need to print "watchdog",   dev_warn(dev,  has help us on
>> this.
>> If you do so , the message will be "watchdog: watchdog0: watchdog is
>> already enabled"
>>
>>   > Never use exclamation marks in kernel
>>>
>>> messages.
>>
>>
>> that make sense , will delete it.
>>
>>>
>>>> +               sbsa_gwdt_keepalive(wdd);
>>>> +       }
>>>> +
>>>> +       /* update pretimeout to WOR */
>>>> +       sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
>>>> +
>>>> +       ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
>>>> +                              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 @ %u
>>>> Hz\n",
>>>> +                wdd->timeout, wdd->pretimeout, gwdt->clk);
>>>
>>>
>>>
>>> if (wdd->pretimeout)
>>>          "watchdog initialized to %us timeout and %us pre-timeout at %u
>>> Hz\n", wdd->timeout, wdd->pretimeout, gwdt->clk
>>> else
>>>          "watchdog initialized to %us timeout at %u Hz\n", wdd->timeout,
>>> gwdt->clk
>>>
>>> I think it's unlikely that users will use pre-timeout, so your code
>>> should
>>> treat pre-timeout as a special case, not the normal usage.
>>
>>
>> I don't think so, that why you didn't use pretimeout in your driver.
>> Because you don't see the meaning of "pretimeout" to a  server.
>>
>>>
>>> --
>>> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-08 16:05             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-08 16:05 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw-LthD3rsA81gm4RdzfppkhA

Hi Gurnter

On 3 June 2015 at 01:07, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On 06/02/2015 09:55 AM, Fu Wei wrote:
>>
>> Hi Timur,
>>
>> Thanks , feedback inline
>>
>> On 2 June 2015 at 23:32, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
>>>
>>> On 06/01/2015 11:05 PM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>>>
>>>> +/*
>>>> + * help functions for accessing 32bit registers of SBSA Generic
>>>> Watchdog
>>>> + */
>>>> +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);
>>>> +}
>>>
>>>
>>>
>>> I still think you should get rid of these functions and just call
>>> readl_relaxed() and writel_relaxed() every time, but I won't complain
>>> again
>>> if you keep them.
>>
>>
>> yes, that make sense, and will reduce the size of code, and I think
>> the code's readability will be OK too.
>> will try in my next patch,
>>
>>>
>>>> +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;
>>>> +
>>>> +       if (wdd->pretimeout)
>>>> +               /* The pretimeout is valid, go panic */
>>>> +               panic("SBSA Watchdog pre-timeout");
>>>> +       else
>>>> +               /* We don't use pretimeout, trigger WS1 now*/
>>>> +               sbsa_gwdt_set_wcv(wdd, 0);
>>>
>>>
>>>
>>> I don't like this.
>>
>>
>> If so, what is your idea ,if pretimeout == 0?
>>
>> the reason of using WCV as (timout - pretimeout): it can provide the
>> longer timeout period,
>> (1)If we use WOR, it can only provide 10s @ 400MHz(max).
>> as Guenter said earlier, the default timer out for most watchdog will
>> be 30s, so I think 10s limit will be a little short
>> (2)we can always program WCV just like ping.
>> (3)if a timeout arrives, WOR will be use, so use it as pretimeout, but
>> we still can make this pretimeout longer by programming WCV(I don't
>> think it's necessary)
>>
>>
>>> The triggering of the hardware reset should never depend
>>> on an interrupt being handled properly.
>>
>>
>> if this fail, system reset in 1S, because WOR == (1s)
>>
> So ?

Even the interrupt routine isn't triggered,  (WOR + system counter) --> WCV,
then, sy system reset in 1S.

the hardware reset doesn't depend on an interrupt.


>
>>> You should always program WCV
>>> correctly in advance.  This is especially true since pre-timeout will
>>> probably rarely be used.
>>
>>
>> always programming WCV is doable.  But I absolutely can not agree "
>> pre-timeout will probably rarely be used"
>> If so, SBSA watchdog is just a normal watchdog,  This use case just
>> makes this HW useless.
>> If so, go to use SP805.
>> you still don't see the importance of this warning and pretimeout to a
>> real server.
>>
>
> If pretimeout isn't used, why not just set WCV = timeout, WOR = 0 ?

Because if WOR = 0 , according to SBSA,  once you want to enable watchdog,
(0 + system counter) --> WCV , then , WS0 and WS1 will be triggered immediately.
we have not a chance(a time slot) to update WCV.

>
> Guenter
>
>
>> If the software of a real server goes wrong, then you just directly
>> restart it ,
>> never try to sync/protect the current data, never try to figure out
>> what is wrong with it.
>> I don't think that is a good server software.
>>
>> At least, I don't thinks " pre-timeout will probably rarely be used"
>> is a good idea for a server.
>> in another word, in a server ,pre-timeout should always be used.
>>
>>> So what happens if the CPU is totally hung and
>>
>>
>> Again, system reset in 1S, because WOR == (1s).
>>
>>> this interrupt handler is never called?  When will the timeout occur?
>>
>>
>> if this interrupt hardler is never called,  what I can see is "some
>> one is feeding the dog".
>> OK, in case, WS0 is triggered, but  this interrupt hardler isn't
>> called, then software really goes wrong.  Then , Again, Again system
>> reset in 1S, because WOR == (1s).
>>
>>>
>>>> +static int sbsa_gwdt_probe(struct platform_device *pdev)
>>>> +{
>>>> +       u64 first_period_max = U64_MAX;
>>>> +       struct device *dev = &pdev->dev;
>>>> +       struct watchdog_device *wdd;
>>>> +       struct sbsa_gwdt *gwdt;
>>>> +       struct resource *res;
>>>> +       void *rf_base, *cf_base;
>>>> +       int ret, irq;
>>>> +       u32 status;
>>>> +
>>>> +       gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
>>>> +       if (!gwdt)
>>>> +               return -ENOMEM;
>>>> +       platform_set_drvdata(pdev, gwdt);
>>>
>>>
>>>
>>> You should probably do this *after* calling platform_get_irq_byname().
>>
>>
>>   it just dose (pdev->) dev->driver_data = gwdt
>> If we got gwdt, we can do that.
>>
>> But maybe I miss something(or a rule of usage),  so please let know
>> why this has to be called  *after* calling platform_get_irq_byname().
>>
>>>
>>>> +
>>>> +       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(cf_base))
>>>> +               return PTR_ERR(cf_base);
>>>> +
>>>> +       irq = platform_get_irq_byname(pdev, "ws0");
>>>> +       if (irq < 0) {
>>>> +               dev_err(dev, "unable to get ws0 interrupt.\n");
>>>> +               return irq;
>>>> +       }
>>>> +
>>>> +       /*
>>>> +        * Get the frequency of system counter from the cp15 interface
>>>> of
>>>> ARM
>>>> +        * Generic timer. We don't need to check it, because if it
>>>> returns
>>>> "0",
>>>> +        * system would panic in very early stage.
>>>> +        */
>>>> +       gwdt->clk = arch_timer_get_cntfrq();
>>>> +       gwdt->refresh_base = rf_base;
>>>> +       gwdt->control_base = cf_base;
>>>> +
>>>> +       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);
>>>> +
>>>> +       wdd->min_pretimeout = 0;
>>>> +       wdd->max_pretimeout = U32_MAX / gwdt->clk;
>>>> +       wdd->min_timeout = 1;
>>>> +       do_div(first_period_max, gwdt->clk);
>>>> +       wdd->max_timeout = first_period_max;
>>>> +
>>>> +       wdd->pretimeout = DEFAULT_PRETIMEOUT;
>>>> +       wdd->timeout = DEFAULT_TIMEOUT;
>>>> +       watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
>>>> +
>>>> +       status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
>>>> +       if (status & SBSA_GWDT_WCS_WS1) {
>>>> +               dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
>>>> +                        sbsa_gwdt_get_wcv(wdd));
>>>
>>>
>>>
>>> "System was previously reset via watchdog" is much clearer.
>>
>>
>> OK
>>
>>>
>>>> +               wdd->bootstatus |= WDIOF_CARDRESET;
>>>> +       }
>>>> +       /* Check if watchdog is already enabled */
>>>> +       if (status & SBSA_GWDT_WCS_EN) {
>>>> +               dev_warn(dev, "already enabled!\n");
>>>
>>>
>>>
>>> "watchdog is already enabled".
>>
>>
>> I think I don't need to print "watchdog",   dev_warn(dev,  has help us on
>> this.
>> If you do so , the message will be "watchdog: watchdog0: watchdog is
>> already enabled"
>>
>>   > Never use exclamation marks in kernel
>>>
>>> messages.
>>
>>
>> that make sense , will delete it.
>>
>>>
>>>> +               sbsa_gwdt_keepalive(wdd);
>>>> +       }
>>>> +
>>>> +       /* update pretimeout to WOR */
>>>> +       sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
>>>> +
>>>> +       ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
>>>> +                              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 @ %u
>>>> Hz\n",
>>>> +                wdd->timeout, wdd->pretimeout, gwdt->clk);
>>>
>>>
>>>
>>> if (wdd->pretimeout)
>>>          "watchdog initialized to %us timeout and %us pre-timeout at %u
>>> Hz\n", wdd->timeout, wdd->pretimeout, gwdt->clk
>>> else
>>>          "watchdog initialized to %us timeout at %u Hz\n", wdd->timeout,
>>> gwdt->clk
>>>
>>> I think it's unlikely that users will use pre-timeout, so your code
>>> should
>>> treat pre-timeout as a special case, not the normal usage.
>>
>>
>> I don't think so, that why you didn't use pretimeout in your driver.
>> Because you don't see the meaning of "pretimeout" to a  server.
>>
>>>
>>> --
>>> 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
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-03 18:25         ` Guenter Roeck
  (?)
  (?)
@ 2015-06-08 16:10         ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-08 16:10 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

Hi Guenter,


On 4 June 2015 at 02:25, Guenter Roeck <linux@roeck-us.net> wrote:
> On Wed, Jun 03, 2015 at 01:16:41PM -0500, Timur Tabi wrote:
>> On 06/01/2015 11:05 PM, fu.wei@linaro.org wrote:
>> >+    if (wdd->pretimeout)
>> >+            /* The pretimeout is valid, go panic */
>> >+            panic("SBSA Watchdog pre-timeout");
>>
>> The problem with this is that WS1 will still occur.  So a few seconds after
>> the panic() call, the hardware will reset.  There won't be any time to debug
>> or log anything.
>>
>
> In general the idea here would be to use a crashdump kernel, which,
> when loaded, would reset the watchdog before it fires. This kernel
> would then write a core dump to a specified location.
>
> If arm64 doesn't support a crashdump kernel, it might still be possible
> to log the backtrace somewhere (eg in nvram using pstore if that is
> supported via acpi or efi).

yes, you are right , thanks for explaining this.

>
> Is there reason to believe that this all won't work on arm64 ?

I don't think there is a reason.

>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 4/7] Watchdog: introdouce "pretimeout" into framework
  2015-06-02 16:12       ` Guenter Roeck
  (?)
@ 2015-06-08 16:44       ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-08 16:44 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann, vgandhi,
	wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

Hi Guenter,

Great thanks for your review,


On 3 June 2015 at 00:12, Guenter Roeck <linux@roeck-us.net> wrote:
> On 06/01/2015 09:05 PM, fu.wei@linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> 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 drivers are going to use this: ARM SBSA Generic Watchdog
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>   Documentation/watchdog/watchdog-kernel-api.txt |  47 ++++++++--
>>   drivers/watchdog/watchdog_core.c               | 115
>> +++++++++++++++++++------
>>   drivers/watchdog/watchdog_dev.c                |  53 ++++++++++++
>>   include/linux/watchdog.h                       |  33 ++++++-
>>   4 files changed, 212 insertions(+), 36 deletions(-)
>>
>> diff --git a/Documentation/watchdog/watchdog-kernel-api.txt
>> b/Documentation/watchdog/watchdog-kernel-api.txt
>> index a0438f3..95b355d 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.
>> @@ -219,8 +236,28 @@ extern int watchdog_init_timeout(struct
>> watchdog_device *wdd,
>>                                     unsigned int timeout_parm, struct
>> device *dev);
>>
>>   The watchdog_init_timeout function allows you to initialize the timeout
>> field
>> -using the module timeout parameter or by retrieving the timeout-sec
>> property from
>> -the device tree (if the module timeout parameter is invalid). Best
>> practice is
>> -to set the default timeout value as timeout value in the watchdog_device
>> and
>> -then use this function to set the user "preferred" timeout value.
>> +using the module timeout parameter or by retrieving the first element of
>> +the timeout-sec property from the device tree (if the module timeout
>> parameter
>> +is invalid). Best practice is to set the default timeout value as timeout
>> value
>> +in the watchdog_device and then use this function to set the user
>> "preferred"
>> +timeout value.
>> +This routine returns zero on success and a negative errno code for
>> failure.
>> +
>> +Some watchdog timers have two stage of timeouts(timeout and pretimeout),
>> +to initialize the timeout and pretimeout fields at the same time, the
>> following
>> +function can be used:
>> +
>> +extern int watchdog_init_timeouts(struct watchdog_device *wdd,
>> +                                  unsigned int pretimeout_parm,
>> +                                  unsigned int timeout_parm,
>> +                                  struct device *dev);
>> +
>> +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).
>> +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.
>> diff --git a/drivers/watchdog/watchdog_core.c
>> b/drivers/watchdog/watchdog_core.c
>> index cec9b55..ff18db3 100644
>> --- a/drivers/watchdog/watchdog_core.c
>> +++ b/drivers/watchdog/watchdog_core.c
>> @@ -43,60 +43,119 @@
>>   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 timeout and max pretimeout values,
>> +        * if not reset them.
>> +        */
>> +       if (wdd->min_pretimeout && wdd->min_timeout < wdd->min_pretimeout)
>> {
>> +               pr_info("Invalid min_timeout, resetting to
>> min_pretimeout+1\n");
>> +               wdd->min_timeout = wdd->min_pretimeout + 1;
>> +       }
>
>
> min_timeout = 10
> max_timeout = 20
> min_pretimeout = 30
> max_pretimeout = 40
>
> will result in min_timeout set to 31.
>
>> +       if (wdd->max_pretimeout && wdd->max_timeout < wdd->max_pretimeout)
>> {
>> +               pr_info("Invalid max_pretimeout, resetting to
>> max_timeout-1\n");
>> +               wdd->max_pretimeout = wdd->max_timeout - 1;
>
>
> and then you set max_pretimeout to 19.
>
> So we'll end up with
>
> min_timeout = 31
> max_timeout = 20
> min_pretimeout = 30
> max_pretimeout = 19
>
> Another example: max_pretimeout = 10, max_timeout = 0 -> max_pretimeout =
> -1.
>
>> +       }
>
>
> You'll need to determine valid ranges and then enforce those.
> Maybe something like
>         min_pretimeout < min_timeout < max_timeout
> and
>         min_pretimeout < max_pretimeout < max_timeout
>
> Not sure if we should adjust anything to a value different to 0.
> Seems to me this is just asking for trouble.

yes, this is a new problem, but let me fix this in my new patchset:
(1)these values is set by driver in the initialization procedure,
according to hardware info.
(2) I thinks there is not any driver should call this function after
initialization.
 So if we find any incorrect value, I think the hardware info we got
is wrong , maybe we can just give up

any suggestion ?

>
>>   }
>>
>>   /**
>> - * 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
>
>
> just 'if it is valid', or 'if it is a valid value' in both cases.

OK. np,. Thanks

>
>> + * pretimeout_parm and timeout_parm is out of bounds). If none of them
>> are
>
>
> s/and/or/

Thanks , fixed

>
>
>> + * 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,
>> +                          struct device *dev)
>>   {
>> -       unsigned int t = 0;
>> -       int ret = 0;
>> +       int ret = 0, length = 0;
>> +       u32 timeouts[2] = {0};
>>
>> -       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 pretimeout module parameter first,
>> +        * but it can be "0", that means we don't use pretimeout.
>> +        */
>> +       if (pretimeout_parm) {
>> +               if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm))
>> +                       timeouts[1] = pretimeout_parm;
>> +               ret = -EINVAL; /* pretimeout_parm is not "0", and invalid
>> */
>
>
> pretimeout_parm is always invalid ? Why ?

Sorry, I lost a "else" , this is a bug/typo

>
>>         }
>> -       if (timeout_parm)
>> +
>> +       /*
>> +        * Try to get the timeout module parameter,
>> +        * if it's valid and pretimeout is ont invalid(ret == 0),
>
>
> s/ont/not/

Thanks , fixed

>
>> +        * assignment and return zero. Otherwise, try dtb.
>> +        */
>> +       if (timeout_parm) {
>> +               if (!watchdog_timeout_invalid(wdd, timeout_parm) && !ret)
>> {
>
>
> Unless I am missing something, you'll never get here if the pretimeout
> module
> parameter is set.

yes, because of the bug above.
Will fix it in my next patchset , thanks :-)

>
>> +                       wdd->timeout = timeout_parm;
>> +                       wdd->pretimeout = timeouts[1];
>> +                       return 0;
>> +               }
>>                 ret = -EINVAL;
>> +       }
>>
>> -       /* try to get the timeout_sec property */
>> +       /*
>> +        * We get here, the situation is one of them:
>> +        * (1)at least one of parameters is invalid(ret = -EINVAL);
>> +        * (2)both of them are 0.(ret = 0)
>> +        * So give up the module parameter(at least drop the invalid one),
>> +        * try to get the timeout_sec property from dtb.
>
>
> Please simplify the comment.
>
>         Either at least one of the module parameters is invalid,
>         or both of them are 0. Try to get the timeout_sec property.

Thanks , will do.

>
>> +        */
>>         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
>> -               ret = -EINVAL;
>>
>> -       return ret;
>> +       /*
>> +        * We get here, that means maybe we can get timeouts from dtb,
>> +        * if "timeout-sec" is available and the data is valid.
>> +        */
>
>
> That comment is not needed; it is obvious.

OK, will remove it

>
>> +       of_find_property(dev->of_node, "timeout-sec", &length);
>> +       if (length > 0 && length <= sizeof(u32) * 2) {
>
>
> You need to check the return value of of_find_property() instead of assuming
> that length will be 0 if it is not found.

you are right, will do, thanks

>
>> +               of_property_read_u32_array(dev->of_node,
>> +                                          "timeout-sec", timeouts,
>> +                                          length / sizeof(u32));
>> +               if (length == sizeof(u32) * 2 && timeouts[1] &&
>> +                   watchdog_pretimeout_invalid(wdd, timeouts[1]))
>> +                               return -EINVAL; /* pretimeout is invalid
>> */
>
>
> Obvious comment.

OK, will remove it

>
>
>> +
>> +               if (!watchdog_timeout_invalid(wdd, timeouts[0]) &&
>> +                   timeouts[0]) {
>> +                       wdd->timeout = timeouts[0];
>> +                       wdd->pretimeout = timeouts[1];
>> +                       return 0;
>> +               }
>> +       }
>> +
>> +       return -EINVAL;
>>   }
>> -EXPORT_SYMBOL_GPL(watchdog_init_timeout);
>> +EXPORT_SYMBOL_GPL(watchdog_init_timeouts);
>>
>>   /**
>>    * watchdog_register_device() - register a watchdog device
>> @@ -119,7 +178,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..af0777e 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,27 @@ 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:
>> +               /* check if we support the pretimeout */
>> +               if (!(wdd->info->options & WDIOF_PRETIMEOUT))
>> +                       return -EOPNOTSUPP;
>> +               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 keeps running (and if
>> +                * possible that it takes the new pretimeout)
>> +                */
>> +               watchdog_ping(wdd);
>> +               /* Fall */
>> +       case WDIOC_GETPRETIMEOUT:
>> +               /* check if we support the pretimeout */
>> +               if (wdd->info->options & WDIOF_PRETIMEOUT)
>> +                       return put_user(wdd->pretimeout, p);
>> +               return -EOPNOTSUPP;
>>         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..b1e325d 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;
>> @@ -117,7 +125,17 @@ static inline void watchdog_set_nowayout(struct
>> watchdog_device *wdd, bool noway
>>   static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd,
>> unsigned int t)
>>   {
>>         return ((wdd->max_timeout != 0) &&
>> -               (t < wdd->min_timeout || t > wdd->max_timeout));
>> +               (t < wdd->min_timeout || t > wdd->max_timeout ||
>> +                       t <= wdd->pretimeout));
>> +}
>> +
>> +/* 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 ||
>> +                       (wdd->timeout != 0 && t >= wdd->timeout)));
>
>
> This validates a pretimeout as valid if max_pretimeout == 0,
> no matter what timeout is set to.
>
> Do we really need to check if timeout == 0 ? Can that ever happen ?

(wdd->timeout != 0 && t >= wdd->timeout)

if we have set timeout(wdd->timeout != 0), and t(pretimeout) >
wdd->timeout, t is a invalid value.
Am I correct?

the reason of adding "wdd->timeout != 0": if driver calls this
function before setting up  wdd->timeout.


>
>>   }
>>
>>   /* Use the following functions to manipulate watchdog driver specific
>> data */
>> @@ -132,11 +150,20 @@ 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,
>> +                                 struct device *dev);
>
>
> No 'extern' here, please. Yes, we'll need to fix that for the other
> function declarations, but that is not a reason to introduce new ones.

OK, I do agree with you on this, have fixed it in my next patchset.

>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-08 18:26               ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-08 18:26 UTC (permalink / raw)
  To: Fu Wei
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

On 06/08/2015 09:05 AM, Fu Wei wrote:
> Hi Gurnter
>
> On 3 June 2015 at 01:07, Guenter Roeck <linux@roeck-us.net> wrote:
>> On 06/02/2015 09:55 AM, Fu Wei wrote:
>>>
>>> Hi Timur,
>>>
>>> Thanks , feedback inline
>>>
>>> On 2 June 2015 at 23:32, Timur Tabi <timur@codeaurora.org> wrote:
>>>>
>>>> On 06/01/2015 11:05 PM, fu.wei@linaro.org wrote:
>>>>
>>>>> +/*
>>>>> + * help functions for accessing 32bit registers of SBSA Generic
>>>>> Watchdog
>>>>> + */
>>>>> +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);
>>>>> +}
>>>>
>>>>
>>>>
>>>> I still think you should get rid of these functions and just call
>>>> readl_relaxed() and writel_relaxed() every time, but I won't complain
>>>> again
>>>> if you keep them.
>>>
>>>
>>> yes, that make sense, and will reduce the size of code, and I think
>>> the code's readability will be OK too.
>>> will try in my next patch,
>>>
>>>>
>>>>> +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;
>>>>> +
>>>>> +       if (wdd->pretimeout)
>>>>> +               /* The pretimeout is valid, go panic */
>>>>> +               panic("SBSA Watchdog pre-timeout");
>>>>> +       else
>>>>> +               /* We don't use pretimeout, trigger WS1 now*/
>>>>> +               sbsa_gwdt_set_wcv(wdd, 0);
>>>>
>>>>
>>>>
>>>> I don't like this.
>>>
>>>
>>> If so, what is your idea ,if pretimeout == 0?
>>>
>>> the reason of using WCV as (timout - pretimeout): it can provide the
>>> longer timeout period,
>>> (1)If we use WOR, it can only provide 10s @ 400MHz(max).
>>> as Guenter said earlier, the default timer out for most watchdog will
>>> be 30s, so I think 10s limit will be a little short
>>> (2)we can always program WCV just like ping.
>>> (3)if a timeout arrives, WOR will be use, so use it as pretimeout, but
>>> we still can make this pretimeout longer by programming WCV(I don't
>>> think it's necessary)
>>>
>>>
>>>> The triggering of the hardware reset should never depend
>>>> on an interrupt being handled properly.
>>>
>>>
>>> if this fail, system reset in 1S, because WOR == (1s)
>>>
>> So ?
>
> Even the interrupt routine isn't triggered,  (WOR + system counter) --> WCV,
> then, sy system reset in 1S.
>
> the hardware reset doesn't depend on an interrupt.
>
>
>>
>>>> You should always program WCV
>>>> correctly in advance.  This is especially true since pre-timeout will
>>>> probably rarely be used.
>>>
>>>
>>> always programming WCV is doable.  But I absolutely can not agree "
>>> pre-timeout will probably rarely be used"
>>> If so, SBSA watchdog is just a normal watchdog,  This use case just
>>> makes this HW useless.
>>> If so, go to use SP805.
>>> you still don't see the importance of this warning and pretimeout to a
>>> real server.
>>>
>>
>> If pretimeout isn't used, why not just set WCV = timeout, WOR = 0 ?
>
> Because if WOR = 0 , according to SBSA,  once you want to enable watchdog,
> (0 + system counter) --> WCV , then , WS0 and WS1 will be triggered immediately.
> we have not a chance(a time slot) to update WCV.
>

I would have thought that this is exactly what we want if pretimeout is not used.
What am I missing here ?

Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-08 18:26               ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-08 18:26 UTC (permalink / raw)
  To: Fu Wei
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw-LthD3rsA81gm4RdzfppkhA

On 06/08/2015 09:05 AM, Fu Wei wrote:
> Hi Gurnter
>
> On 3 June 2015 at 01:07, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
>> On 06/02/2015 09:55 AM, Fu Wei wrote:
>>>
>>> Hi Timur,
>>>
>>> Thanks , feedback inline
>>>
>>> On 2 June 2015 at 23:32, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
>>>>
>>>> On 06/01/2015 11:05 PM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>>>>
>>>>> +/*
>>>>> + * help functions for accessing 32bit registers of SBSA Generic
>>>>> Watchdog
>>>>> + */
>>>>> +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);
>>>>> +}
>>>>
>>>>
>>>>
>>>> I still think you should get rid of these functions and just call
>>>> readl_relaxed() and writel_relaxed() every time, but I won't complain
>>>> again
>>>> if you keep them.
>>>
>>>
>>> yes, that make sense, and will reduce the size of code, and I think
>>> the code's readability will be OK too.
>>> will try in my next patch,
>>>
>>>>
>>>>> +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;
>>>>> +
>>>>> +       if (wdd->pretimeout)
>>>>> +               /* The pretimeout is valid, go panic */
>>>>> +               panic("SBSA Watchdog pre-timeout");
>>>>> +       else
>>>>> +               /* We don't use pretimeout, trigger WS1 now*/
>>>>> +               sbsa_gwdt_set_wcv(wdd, 0);
>>>>
>>>>
>>>>
>>>> I don't like this.
>>>
>>>
>>> If so, what is your idea ,if pretimeout == 0?
>>>
>>> the reason of using WCV as (timout - pretimeout): it can provide the
>>> longer timeout period,
>>> (1)If we use WOR, it can only provide 10s @ 400MHz(max).
>>> as Guenter said earlier, the default timer out for most watchdog will
>>> be 30s, so I think 10s limit will be a little short
>>> (2)we can always program WCV just like ping.
>>> (3)if a timeout arrives, WOR will be use, so use it as pretimeout, but
>>> we still can make this pretimeout longer by programming WCV(I don't
>>> think it's necessary)
>>>
>>>
>>>> The triggering of the hardware reset should never depend
>>>> on an interrupt being handled properly.
>>>
>>>
>>> if this fail, system reset in 1S, because WOR == (1s)
>>>
>> So ?
>
> Even the interrupt routine isn't triggered,  (WOR + system counter) --> WCV,
> then, sy system reset in 1S.
>
> the hardware reset doesn't depend on an interrupt.
>
>
>>
>>>> You should always program WCV
>>>> correctly in advance.  This is especially true since pre-timeout will
>>>> probably rarely be used.
>>>
>>>
>>> always programming WCV is doable.  But I absolutely can not agree "
>>> pre-timeout will probably rarely be used"
>>> If so, SBSA watchdog is just a normal watchdog,  This use case just
>>> makes this HW useless.
>>> If so, go to use SP805.
>>> you still don't see the importance of this warning and pretimeout to a
>>> real server.
>>>
>>
>> If pretimeout isn't used, why not just set WCV = timeout, WOR = 0 ?
>
> Because if WOR = 0 , according to SBSA,  once you want to enable watchdog,
> (0 + system counter) --> WCV , then , WS0 and WS1 will be triggered immediately.
> we have not a chance(a time slot) to update WCV.
>

I would have thought that this is exactly what we want if pretimeout is not used.
What am I missing here ?

Guenter

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-08 18:26               ` Guenter Roeck
  (?)
@ 2015-06-09  3:59               ` Fu Wei
  2015-06-09  4:37                   ` Guenter Roeck
  -1 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-06-09  3:59 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

Hi Guenter,


On 9 June 2015 at 02:26, Guenter Roeck <linux@roeck-us.net> wrote:
> On 06/08/2015 09:05 AM, Fu Wei wrote:
>>
>> Hi Gurnter
>>
>> On 3 June 2015 at 01:07, Guenter Roeck <linux@roeck-us.net> wrote:
>>>
>>> On 06/02/2015 09:55 AM, Fu Wei wrote:
>>>>
>>>>
>>>> Hi Timur,
>>>>
>>>> Thanks , feedback inline
>>>>
>>>> On 2 June 2015 at 23:32, Timur Tabi <timur@codeaurora.org> wrote:
>>>>>
>>>>>
>>>>> On 06/01/2015 11:05 PM, fu.wei@linaro.org wrote:
>>>>>
>>>>>> +/*
>>>>>> + * help functions for accessing 32bit registers of SBSA Generic
>>>>>> Watchdog
>>>>>> + */
>>>>>> +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);
>>>>>> +}
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> I still think you should get rid of these functions and just call
>>>>> readl_relaxed() and writel_relaxed() every time, but I won't complain
>>>>> again
>>>>> if you keep them.
>>>>
>>>>
>>>>
>>>> yes, that make sense, and will reduce the size of code, and I think
>>>> the code's readability will be OK too.
>>>> will try in my next patch,
>>>>
>>>>>
>>>>>> +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;
>>>>>> +
>>>>>> +       if (wdd->pretimeout)
>>>>>> +               /* The pretimeout is valid, go panic */
>>>>>> +               panic("SBSA Watchdog pre-timeout");
>>>>>> +       else
>>>>>> +               /* We don't use pretimeout, trigger WS1 now*/
>>>>>> +               sbsa_gwdt_set_wcv(wdd, 0);
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> I don't like this.
>>>>
>>>>
>>>>
>>>> If so, what is your idea ,if pretimeout == 0?
>>>>
>>>> the reason of using WCV as (timout - pretimeout): it can provide the
>>>> longer timeout period,
>>>> (1)If we use WOR, it can only provide 10s @ 400MHz(max).
>>>> as Guenter said earlier, the default timer out for most watchdog will
>>>> be 30s, so I think 10s limit will be a little short
>>>> (2)we can always program WCV just like ping.
>>>> (3)if a timeout arrives, WOR will be use, so use it as pretimeout, but
>>>> we still can make this pretimeout longer by programming WCV(I don't
>>>> think it's necessary)
>>>>
>>>>
>>>>> The triggering of the hardware reset should never depend
>>>>> on an interrupt being handled properly.
>>>>
>>>>
>>>>
>>>> if this fail, system reset in 1S, because WOR == (1s)
>>>>
>>> So ?
>>
>>
>> Even the interrupt routine isn't triggered,  (WOR + system counter) -->
>> WCV,
>> then, sy system reset in 1S.
>>
>> the hardware reset doesn't depend on an interrupt.
>>
>>
>>>
>>>>> You should always program WCV
>>>>> correctly in advance.  This is especially true since pre-timeout will
>>>>> probably rarely be used.
>>>>
>>>>
>>>>
>>>> always programming WCV is doable.  But I absolutely can not agree "
>>>> pre-timeout will probably rarely be used"
>>>> If so, SBSA watchdog is just a normal watchdog,  This use case just
>>>> makes this HW useless.
>>>> If so, go to use SP805.
>>>> you still don't see the importance of this warning and pretimeout to a
>>>> real server.
>>>>
>>>
>>> If pretimeout isn't used, why not just set WCV = timeout, WOR = 0 ?
>>
>>
>> Because if WOR = 0 , according to SBSA,  once you want to enable watchdog,
>> (0 + system counter) --> WCV , then , WS0 and WS1 will be triggered
>> immediately.
>> we have not a chance(a time slot) to update WCV.
>>
>
> I would have thought that this is exactly what we want if pretimeout is not
> used.

Although pretimeout == 0 is not good for a server, but If
administrator set up pretimeout == 0. *I thinks we should trigger WS1
ASAP* . Because  WS1 maybe a interrupter or a reboot signal, that is
why we can not reboot system directly.

This driver is SBSA watchdog driver, that means we need to follow SBSA spec:
(1) SBSA watchdog has two stage timeouts --> timeout and pretimeout is
the best solution in watchdog framework, at least for now.
(2) The watchdog has the following output signals:
    Watchdog Signal 0 (WS0)---> "The initial signal is typically wired
to an interrupt and alerts the system."(original word from spec), I
thinks the key work should be "interrupt" and "alerts". So in WS0
interrupt routine, reset is absolutely a wrong operation. Although I
think we should make this "alerts" more useful. But for the first
version of driver, I thinks panic is useful enough.
    Watchdog Signal 1 (WS1). ---> "The signal is fed to a higher agent
as an interrupt or reset for it to take executive action." (original
word from spec) . The key work should be "interrupt", "or" and "reset"
. So  WS1 maybe a interrupt.
so even in the WS0 interrupt routine, if  pretimeout == 0 , we need to
trigger WS1(that is what my patch is doing now, set WCV to 0, so WCV
is always less than SystemCounter, and in this situation(WS0 = TRUE),
WS1 will be trigger immediately), but definitely not a reset too.

But in worst case,  if the WS0 is triggered, but the interrupt routine
doesn't work(can not set up WCV), it doesn't matter, we just need to
wait for a WOR(1s in my driver) timeout, then WS1 will be triggered.
That is hardware mechanism, once we config SBSA watchdog correctly,
that should work.  If it doesn't, I think the chip design doesn't
follow the SBSA spec.

Make a summary here, for SBSA watchdog driver,  it need to support two
stage timeouts and need to trigger WS0/1 when timeouts occur(can not
simply reset system in interrupt routines).
If a driver doesn't do these above, the driver can not be called SBSA
watchdog driver.

But according to SBSA, even pretimeout == 0, we can not setup WOR = 0.
if we make WOR = 0 , once we set up WCS(enabling watchdog), that cause
a explicit watchdog refresh, then WCV = (0 + system counter), so WS0
and WS1 will be triggered serially and immediately(in theory, the
"delay" also depend on implementation). So in my patchset , if
pretimeout == 0, WOR will be 1s at least to make sure we have time to
setup WCV. I have made comments in the patch for explaining this.

Maybe some people want to ask: if we can not set up WOR = 0, but
pretimeout can be 0 and timeout can not, why I still want to use WOR
for pretimeout and using WCV as (timout - pretimeout) ??
For this:
(1)WCV can provide the longer timeout period, If we use WOR, it can
only provide 10s @ 400MHz(max). The default timer out for most
watchdog will be 30s, so I think 10s limit will be a little short.
(2)we can always program(write) WCV just like ping.
(3)if the first timeout occurs, WOR will be loaded to WCV(WOR + system
counter)  automatically , so why not just use WOR as pretimeout?
Although we still can make this pretimeout longer by programming WCV,
I don't think it's necessary for now.


> What am I missing here ?
>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-09  4:37                   ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-09  4:37 UTC (permalink / raw)
  To: Fu Wei
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

On 06/08/2015 08:59 PM, Fu Wei wrote:
> Hi Guenter,
>
>
> On 9 June 2015 at 02:26, Guenter Roeck <linux@roeck-us.net> wrote:
>> On 06/08/2015 09:05 AM, Fu Wei wrote:
>>>
>>> Hi Gurnter
>>>
>>> On 3 June 2015 at 01:07, Guenter Roeck <linux@roeck-us.net> wrote:
>>>>
>>>> On 06/02/2015 09:55 AM, Fu Wei wrote:
>>>>>
>>>>>
>>>>> Hi Timur,
>>>>>
>>>>> Thanks , feedback inline
>>>>>
>>>>> On 2 June 2015 at 23:32, Timur Tabi <timur@codeaurora.org> wrote:
>>>>>>
>>>>>>
>>>>>> On 06/01/2015 11:05 PM, fu.wei@linaro.org wrote:
>>>>>>
>>>>>>> +/*
>>>>>>> + * help functions for accessing 32bit registers of SBSA Generic
>>>>>>> Watchdog
>>>>>>> + */
>>>>>>> +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);
>>>>>>> +}
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> I still think you should get rid of these functions and just call
>>>>>> readl_relaxed() and writel_relaxed() every time, but I won't complain
>>>>>> again
>>>>>> if you keep them.
>>>>>
>>>>>
>>>>>
>>>>> yes, that make sense, and will reduce the size of code, and I think
>>>>> the code's readability will be OK too.
>>>>> will try in my next patch,
>>>>>
>>>>>>
>>>>>>> +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;
>>>>>>> +
>>>>>>> +       if (wdd->pretimeout)
>>>>>>> +               /* The pretimeout is valid, go panic */
>>>>>>> +               panic("SBSA Watchdog pre-timeout");
>>>>>>> +       else
>>>>>>> +               /* We don't use pretimeout, trigger WS1 now*/
>>>>>>> +               sbsa_gwdt_set_wcv(wdd, 0);
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> I don't like this.
>>>>>
>>>>>
>>>>>
>>>>> If so, what is your idea ,if pretimeout == 0?
>>>>>
>>>>> the reason of using WCV as (timout - pretimeout): it can provide the
>>>>> longer timeout period,
>>>>> (1)If we use WOR, it can only provide 10s @ 400MHz(max).
>>>>> as Guenter said earlier, the default timer out for most watchdog will
>>>>> be 30s, so I think 10s limit will be a little short
>>>>> (2)we can always program WCV just like ping.
>>>>> (3)if a timeout arrives, WOR will be use, so use it as pretimeout, but
>>>>> we still can make this pretimeout longer by programming WCV(I don't
>>>>> think it's necessary)
>>>>>
>>>>>
>>>>>> The triggering of the hardware reset should never depend
>>>>>> on an interrupt being handled properly.
>>>>>
>>>>>
>>>>>
>>>>> if this fail, system reset in 1S, because WOR == (1s)
>>>>>
>>>> So ?
>>>
>>>
>>> Even the interrupt routine isn't triggered,  (WOR + system counter) -->
>>> WCV,
>>> then, sy system reset in 1S.
>>>
>>> the hardware reset doesn't depend on an interrupt.
>>>
>>>
>>>>
>>>>>> You should always program WCV
>>>>>> correctly in advance.  This is especially true since pre-timeout will
>>>>>> probably rarely be used.
>>>>>
>>>>>
>>>>>
>>>>> always programming WCV is doable.  But I absolutely can not agree "
>>>>> pre-timeout will probably rarely be used"
>>>>> If so, SBSA watchdog is just a normal watchdog,  This use case just
>>>>> makes this HW useless.
>>>>> If so, go to use SP805.
>>>>> you still don't see the importance of this warning and pretimeout to a
>>>>> real server.
>>>>>
>>>>
>>>> If pretimeout isn't used, why not just set WCV = timeout, WOR = 0 ?
>>>
>>>
>>> Because if WOR = 0 , according to SBSA,  once you want to enable watchdog,
>>> (0 + system counter) --> WCV , then , WS0 and WS1 will be triggered
>>> immediately.
>>> we have not a chance(a time slot) to update WCV.
>>>
>>
>> I would have thought that this is exactly what we want if pretimeout is not
>> used.
>
> Although pretimeout == 0 is not good for a server, but If
> administrator set up pretimeout == 0. *I thinks we should trigger WS1
> ASAP* . Because  WS1 maybe a interrupter or a reboot signal, that is
> why we can not reboot system directly.
>
> This driver is SBSA watchdog driver, that means we need to follow SBSA spec:
> (1) SBSA watchdog has two stage timeouts --> timeout and pretimeout is
> the best solution in watchdog framework, at least for now.
> (2) The watchdog has the following output signals:
>      Watchdog Signal 0 (WS0)---> "The initial signal is typically wired
> to an interrupt and alerts the system."(original word from spec), I
> thinks the key work should be "interrupt" and "alerts". So in WS0
> interrupt routine, reset is absolutely a wrong operation. Although I
> think we should make this "alerts" more useful. But for the first
> version of driver, I thinks panic is useful enough.
>      Watchdog Signal 1 (WS1). ---> "The signal is fed to a higher agent
> as an interrupt or reset for it to take executive action." (original
> word from spec) . The key work should be "interrupt", "or" and "reset"
> . So  WS1 maybe a interrupt.
> so even in the WS0 interrupt routine, if  pretimeout == 0 , we need to
> trigger WS1(that is what my patch is doing now, set WCV to 0, so WCV
> is always less than SystemCounter, and in this situation(WS0 = TRUE),
> WS1 will be trigger immediately), but definitely not a reset too.
>
> But in worst case,  if the WS0 is triggered, but the interrupt routine
> doesn't work(can not set up WCV), it doesn't matter, we just need to
> wait for a WOR(1s in my driver) timeout, then WS1 will be triggered.
> That is hardware mechanism, once we config SBSA watchdog correctly,
> that should work.  If it doesn't, I think the chip design doesn't
> follow the SBSA spec.
>
> Make a summary here, for SBSA watchdog driver,  it need to support two
> stage timeouts and need to trigger WS0/1 when timeouts occur(can not
> simply reset system in interrupt routines).
> If a driver doesn't do these above, the driver can not be called SBSA
> watchdog driver.
>
> But according to SBSA, even pretimeout == 0, we can not setup WOR = 0.
> if we make WOR = 0 , once we set up WCS(enabling watchdog), that cause
> a explicit watchdog refresh, then WCV = (0 + system counter), so WS0
> and WS1 will be triggered serially and immediately(in theory, the

I still don't understand why this would be a problem.

> "delay" also depend on implementation). So in my patchset , if
> pretimeout == 0, WOR will be 1s at least to make sure we have time to
> setup WCV. I have made comments in the patch for explaining this.
>
> Maybe some people want to ask: if we can not set up WOR = 0, but
> pretimeout can be 0 and timeout can not, why I still want to use WOR
> for pretimeout and using WCV as (timout - pretimeout) ??
> For this:
> (1)WCV can provide the longer timeout period, If we use WOR, it can
> only provide 10s @ 400MHz(max). The default timer out for most
> watchdog will be 30s, so I think 10s limit will be a little short.
> (2)we can always program(write) WCV just like ping.
> (3)if the first timeout occurs, WOR will be loaded to WCV(WOR + system
> counter)  automatically , so why not just use WOR as pretimeout?
> Although we still can make this pretimeout longer by programming WCV,
> I don't think it's necessary for now.
>

Too bad I don't have an arm64 system to test myself. I am not sure
I understand why WOR must be set to > 0 if pretimeout == 0, and even
if it must be set to a value > 0 I don't understand why
setting it to 1 (instead of 1 second) would not be sufficient.

Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-09  4:37                   ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-09  4:37 UTC (permalink / raw)
  To: Fu Wei
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw-LthD3rsA81gm4RdzfppkhA

On 06/08/2015 08:59 PM, Fu Wei wrote:
> Hi Guenter,
>
>
> On 9 June 2015 at 02:26, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
>> On 06/08/2015 09:05 AM, Fu Wei wrote:
>>>
>>> Hi Gurnter
>>>
>>> On 3 June 2015 at 01:07, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
>>>>
>>>> On 06/02/2015 09:55 AM, Fu Wei wrote:
>>>>>
>>>>>
>>>>> Hi Timur,
>>>>>
>>>>> Thanks , feedback inline
>>>>>
>>>>> On 2 June 2015 at 23:32, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
>>>>>>
>>>>>>
>>>>>> On 06/01/2015 11:05 PM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>>>>>>
>>>>>>> +/*
>>>>>>> + * help functions for accessing 32bit registers of SBSA Generic
>>>>>>> Watchdog
>>>>>>> + */
>>>>>>> +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);
>>>>>>> +}
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> I still think you should get rid of these functions and just call
>>>>>> readl_relaxed() and writel_relaxed() every time, but I won't complain
>>>>>> again
>>>>>> if you keep them.
>>>>>
>>>>>
>>>>>
>>>>> yes, that make sense, and will reduce the size of code, and I think
>>>>> the code's readability will be OK too.
>>>>> will try in my next patch,
>>>>>
>>>>>>
>>>>>>> +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;
>>>>>>> +
>>>>>>> +       if (wdd->pretimeout)
>>>>>>> +               /* The pretimeout is valid, go panic */
>>>>>>> +               panic("SBSA Watchdog pre-timeout");
>>>>>>> +       else
>>>>>>> +               /* We don't use pretimeout, trigger WS1 now*/
>>>>>>> +               sbsa_gwdt_set_wcv(wdd, 0);
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> I don't like this.
>>>>>
>>>>>
>>>>>
>>>>> If so, what is your idea ,if pretimeout == 0?
>>>>>
>>>>> the reason of using WCV as (timout - pretimeout): it can provide the
>>>>> longer timeout period,
>>>>> (1)If we use WOR, it can only provide 10s @ 400MHz(max).
>>>>> as Guenter said earlier, the default timer out for most watchdog will
>>>>> be 30s, so I think 10s limit will be a little short
>>>>> (2)we can always program WCV just like ping.
>>>>> (3)if a timeout arrives, WOR will be use, so use it as pretimeout, but
>>>>> we still can make this pretimeout longer by programming WCV(I don't
>>>>> think it's necessary)
>>>>>
>>>>>
>>>>>> The triggering of the hardware reset should never depend
>>>>>> on an interrupt being handled properly.
>>>>>
>>>>>
>>>>>
>>>>> if this fail, system reset in 1S, because WOR == (1s)
>>>>>
>>>> So ?
>>>
>>>
>>> Even the interrupt routine isn't triggered,  (WOR + system counter) -->
>>> WCV,
>>> then, sy system reset in 1S.
>>>
>>> the hardware reset doesn't depend on an interrupt.
>>>
>>>
>>>>
>>>>>> You should always program WCV
>>>>>> correctly in advance.  This is especially true since pre-timeout will
>>>>>> probably rarely be used.
>>>>>
>>>>>
>>>>>
>>>>> always programming WCV is doable.  But I absolutely can not agree "
>>>>> pre-timeout will probably rarely be used"
>>>>> If so, SBSA watchdog is just a normal watchdog,  This use case just
>>>>> makes this HW useless.
>>>>> If so, go to use SP805.
>>>>> you still don't see the importance of this warning and pretimeout to a
>>>>> real server.
>>>>>
>>>>
>>>> If pretimeout isn't used, why not just set WCV = timeout, WOR = 0 ?
>>>
>>>
>>> Because if WOR = 0 , according to SBSA,  once you want to enable watchdog,
>>> (0 + system counter) --> WCV , then , WS0 and WS1 will be triggered
>>> immediately.
>>> we have not a chance(a time slot) to update WCV.
>>>
>>
>> I would have thought that this is exactly what we want if pretimeout is not
>> used.
>
> Although pretimeout == 0 is not good for a server, but If
> administrator set up pretimeout == 0. *I thinks we should trigger WS1
> ASAP* . Because  WS1 maybe a interrupter or a reboot signal, that is
> why we can not reboot system directly.
>
> This driver is SBSA watchdog driver, that means we need to follow SBSA spec:
> (1) SBSA watchdog has two stage timeouts --> timeout and pretimeout is
> the best solution in watchdog framework, at least for now.
> (2) The watchdog has the following output signals:
>      Watchdog Signal 0 (WS0)---> "The initial signal is typically wired
> to an interrupt and alerts the system."(original word from spec), I
> thinks the key work should be "interrupt" and "alerts". So in WS0
> interrupt routine, reset is absolutely a wrong operation. Although I
> think we should make this "alerts" more useful. But for the first
> version of driver, I thinks panic is useful enough.
>      Watchdog Signal 1 (WS1). ---> "The signal is fed to a higher agent
> as an interrupt or reset for it to take executive action." (original
> word from spec) . The key work should be "interrupt", "or" and "reset"
> . So  WS1 maybe a interrupt.
> so even in the WS0 interrupt routine, if  pretimeout == 0 , we need to
> trigger WS1(that is what my patch is doing now, set WCV to 0, so WCV
> is always less than SystemCounter, and in this situation(WS0 = TRUE),
> WS1 will be trigger immediately), but definitely not a reset too.
>
> But in worst case,  if the WS0 is triggered, but the interrupt routine
> doesn't work(can not set up WCV), it doesn't matter, we just need to
> wait for a WOR(1s in my driver) timeout, then WS1 will be triggered.
> That is hardware mechanism, once we config SBSA watchdog correctly,
> that should work.  If it doesn't, I think the chip design doesn't
> follow the SBSA spec.
>
> Make a summary here, for SBSA watchdog driver,  it need to support two
> stage timeouts and need to trigger WS0/1 when timeouts occur(can not
> simply reset system in interrupt routines).
> If a driver doesn't do these above, the driver can not be called SBSA
> watchdog driver.
>
> But according to SBSA, even pretimeout == 0, we can not setup WOR = 0.
> if we make WOR = 0 , once we set up WCS(enabling watchdog), that cause
> a explicit watchdog refresh, then WCV = (0 + system counter), so WS0
> and WS1 will be triggered serially and immediately(in theory, the

I still don't understand why this would be a problem.

> "delay" also depend on implementation). So in my patchset , if
> pretimeout == 0, WOR will be 1s at least to make sure we have time to
> setup WCV. I have made comments in the patch for explaining this.
>
> Maybe some people want to ask: if we can not set up WOR = 0, but
> pretimeout can be 0 and timeout can not, why I still want to use WOR
> for pretimeout and using WCV as (timout - pretimeout) ??
> For this:
> (1)WCV can provide the longer timeout period, If we use WOR, it can
> only provide 10s @ 400MHz(max). The default timer out for most
> watchdog will be 30s, so I think 10s limit will be a little short.
> (2)we can always program(write) WCV just like ping.
> (3)if the first timeout occurs, WOR will be loaded to WCV(WOR + system
> counter)  automatically , so why not just use WOR as pretimeout?
> Although we still can make this pretimeout longer by programming WCV,
> I don't think it's necessary for now.
>

Too bad I don't have an arm64 system to test myself. I am not sure
I understand why WOR must be set to > 0 if pretimeout == 0, and even
if it must be set to a value > 0 I don't understand why
setting it to 1 (instead of 1 second) would not be sufficient.

Guenter

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-09  6:37                     ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-09  6:37 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

Hi Guenter,

Thanks for reply so quickly.

On 9 June 2015 at 12:37, Guenter Roeck <linux@roeck-us.net> wrote:
> On 06/08/2015 08:59 PM, Fu Wei wrote:
>>
>> Hi Guenter,
>>
>>
>> On 9 June 2015 at 02:26, Guenter Roeck <linux@roeck-us.net> wrote:
>>>
>>> On 06/08/2015 09:05 AM, Fu Wei wrote:
>>>>
>>>>
>>>> Hi Gurnter
>>>>
>>>> On 3 June 2015 at 01:07, Guenter Roeck <linux@roeck-us.net> wrote:
>>>>>
>>>>>
>>>>> On 06/02/2015 09:55 AM, Fu Wei wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> Hi Timur,
>>>>>>
>>>>>> Thanks , feedback inline
>>>>>>
>>>>>> On 2 June 2015 at 23:32, Timur Tabi <timur@codeaurora.org> wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 06/01/2015 11:05 PM, fu.wei@linaro.org wrote:
>>>>>>>
>>>>>>>> +/*
>>>>>>>> + * help functions for accessing 32bit registers of SBSA Generic
>>>>>>>> Watchdog
>>>>>>>> + */
>>>>>>>> +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);
>>>>>>>> +}
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> I still think you should get rid of these functions and just call
>>>>>>> readl_relaxed() and writel_relaxed() every time, but I won't complain
>>>>>>> again
>>>>>>> if you keep them.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> yes, that make sense, and will reduce the size of code, and I think
>>>>>> the code's readability will be OK too.
>>>>>> will try in my next patch,
>>>>>>
>>>>>>>
>>>>>>>> +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;
>>>>>>>> +
>>>>>>>> +       if (wdd->pretimeout)
>>>>>>>> +               /* The pretimeout is valid, go panic */
>>>>>>>> +               panic("SBSA Watchdog pre-timeout");
>>>>>>>> +       else
>>>>>>>> +               /* We don't use pretimeout, trigger WS1 now*/
>>>>>>>> +               sbsa_gwdt_set_wcv(wdd, 0);
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> I don't like this.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> If so, what is your idea ,if pretimeout == 0?
>>>>>>
>>>>>> the reason of using WCV as (timout - pretimeout): it can provide the
>>>>>> longer timeout period,
>>>>>> (1)If we use WOR, it can only provide 10s @ 400MHz(max).
>>>>>> as Guenter said earlier, the default timer out for most watchdog will
>>>>>> be 30s, so I think 10s limit will be a little short
>>>>>> (2)we can always program WCV just like ping.
>>>>>> (3)if a timeout arrives, WOR will be use, so use it as pretimeout, but
>>>>>> we still can make this pretimeout longer by programming WCV(I don't
>>>>>> think it's necessary)
>>>>>>
>>>>>>
>>>>>>> The triggering of the hardware reset should never depend
>>>>>>> on an interrupt being handled properly.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> if this fail, system reset in 1S, because WOR == (1s)
>>>>>>
>>>>> So ?
>>>>
>>>>
>>>>
>>>> Even the interrupt routine isn't triggered,  (WOR + system counter) -->
>>>> WCV,
>>>> then, sy system reset in 1S.
>>>>
>>>> the hardware reset doesn't depend on an interrupt.
>>>>
>>>>
>>>>>
>>>>>>> You should always program WCV
>>>>>>> correctly in advance.  This is especially true since pre-timeout will
>>>>>>> probably rarely be used.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> always programming WCV is doable.  But I absolutely can not agree "
>>>>>> pre-timeout will probably rarely be used"
>>>>>> If so, SBSA watchdog is just a normal watchdog,  This use case just
>>>>>> makes this HW useless.
>>>>>> If so, go to use SP805.
>>>>>> you still don't see the importance of this warning and pretimeout to a
>>>>>> real server.
>>>>>>
>>>>>
>>>>> If pretimeout isn't used, why not just set WCV = timeout, WOR = 0 ?
>>>>
>>>>
>>>>
>>>> Because if WOR = 0 , according to SBSA,  once you want to enable
>>>> watchdog,
>>>> (0 + system counter) --> WCV , then , WS0 and WS1 will be triggered
>>>> immediately.
>>>> we have not a chance(a time slot) to update WCV.
>>>>
>>>
>>> I would have thought that this is exactly what we want if pretimeout is
>>> not
>>> used.
>>
>>
>> Although pretimeout == 0 is not good for a server, but If
>> administrator set up pretimeout == 0. *I thinks we should trigger WS1
>> ASAP* . Because  WS1 maybe a interrupter or a reboot signal, that is
>> why we can not reboot system directly.
>>
>> This driver is SBSA watchdog driver, that means we need to follow SBSA
>> spec:
>> (1) SBSA watchdog has two stage timeouts --> timeout and pretimeout is
>> the best solution in watchdog framework, at least for now.
>> (2) The watchdog has the following output signals:
>>      Watchdog Signal 0 (WS0)---> "The initial signal is typically wired
>> to an interrupt and alerts the system."(original word from spec), I
>> thinks the key work should be "interrupt" and "alerts". So in WS0
>> interrupt routine, reset is absolutely a wrong operation. Although I
>> think we should make this "alerts" more useful. But for the first
>> version of driver, I thinks panic is useful enough.
>>      Watchdog Signal 1 (WS1). ---> "The signal is fed to a higher agent
>> as an interrupt or reset for it to take executive action." (original
>> word from spec) . The key work should be "interrupt", "or" and "reset"
>> . So  WS1 maybe a interrupt.
>> so even in the WS0 interrupt routine, if  pretimeout == 0 , we need to
>> trigger WS1(that is what my patch is doing now, set WCV to 0, so WCV
>> is always less than SystemCounter, and in this situation(WS0 = TRUE),
>> WS1 will be trigger immediately), but definitely not a reset too.
>>
>> But in worst case,  if the WS0 is triggered, but the interrupt routine
>> doesn't work(can not set up WCV), it doesn't matter, we just need to
>> wait for a WOR(1s in my driver) timeout, then WS1 will be triggered.
>> That is hardware mechanism, once we config SBSA watchdog correctly,
>> that should work.  If it doesn't, I think the chip design doesn't
>> follow the SBSA spec.
>>
>> Make a summary here, for SBSA watchdog driver,  it need to support two
>> stage timeouts and need to trigger WS0/1 when timeouts occur(can not
>> simply reset system in interrupt routines).
>> If a driver doesn't do these above, the driver can not be called SBSA
>> watchdog driver.
>>
>> But according to SBSA, even pretimeout == 0, we can not setup WOR = 0.
>> if we make WOR = 0 , once we set up WCS(enabling watchdog), that cause
>> a explicit watchdog refresh, then WCV = (0 + system counter), so WS0
>> and WS1 will be triggered serially and immediately(in theory, the
>
>
> I still don't understand why this would be a problem.

that 20+ lines pseudocode from the page 23 of SBSA spec 2.3 can
explain this well.
Please let me know which line confuse you, I will explain them one by one below.

>
>> "delay" also depend on implementation). So in my patchset , if
>> pretimeout == 0, WOR will be 1s at least to make sure we have time to
>> setup WCV. I have made comments in the patch for explaining this.
>>
>> Maybe some people want to ask: if we can not set up WOR = 0, but
>> pretimeout can be 0 and timeout can not, why I still want to use WOR
>> for pretimeout and using WCV as (timout - pretimeout) ??
>> For this:
>> (1)WCV can provide the longer timeout period, If we use WOR, it can
>> only provide 10s @ 400MHz(max). The default timer out for most
>> watchdog will be 30s, so I think 10s limit will be a little short.
>> (2)we can always program(write) WCV just like ping.
>> (3)if the first timeout occurs, WOR will be loaded to WCV(WOR + system
>> counter)  automatically , so why not just use WOR as pretimeout?
>> Although we still can make this pretimeout longer by programming WCV,
>> I don't think it's necessary for now.
>>
>
> Too bad I don't have an arm64 system to test myself. I am not sure
> I understand why WOR must be set to > 0 if pretimeout == 0, and even

Although SBSA spec has published for years(2.2 was published at 15th
Jan 2014), but this is still a relatively new spec of hardware, for
now . I only has Foundation model and FAST model for testing.
But I would like to suggest: this driver should follow the SBSA spec
first, but not a specific hardware, even some of hardware has this
watchdog, but there maybe some hardware bug in it(at least I know
there is one).

I am using 1 second, just because I think 1 second is safe enough to
reload WCV. (from write "1" in WCS  to reload WCV[31:0] and WCV[63:32]
)
Actually,  in most of case , we need WOR > 1, only when we enable the
watchdog( write "1" to WCS, this causes a ExplicitRefresh, see Line 7
"ExplicitRefresh == TRUE" and Line 8 below).
in this cause , we just need a time slot to reload WCV, the driver
doesn't really spend 1s on this.
But If WOR ==0, (Line 1) TimeoutRefresh = TRUE in a very short time,
the minimum time depends on the implementation. Then The first timeout
stage occur(see Line 7 (TimeoutRefresh == TRUE and WS0 == FALSE), and
Line 8 below again ) and  WS0 was triggered(Line 16~18).  Because WOR
==0 too, (Line 1) TimeoutRefresh = TRUE occur in a very short time
again, then see Line 16, 17, 20

In worst case, if pretimeout is 0, First timeout stage occur(see Line
7 (TimeoutRefresh == TRUE and WS0 == FALSE), and Line 8 below,  then
Line 16~18)   but the interrupt routine doesn't work, we can still got
WS1 in the time we configured in WOR. (Line 1) TimeoutRefresh = TRUE
occur when SystemCounter[63:0] > SystemCounter[63:0] +
ZeroExtend(WOR[31:0]), then  Line 16, 17, 20

---------------------------------------------------
CompareValue : WCV
WatchdogOffsetValue : WOR


1    TimeoutRefresh = (SystemCounter[63:0] > CompareValue[63:0])

2    If WatchdogColdReset
3            WatchdogEnable = DISABLED
4    Endif

5    If LoadNewCompareValue
6            CompareValue = new_value
7    ElseIf ExplicitRefresh == TRUE or (TimeoutRefresh == TRUE and WS0 == FALSE)
8           CompareValue = SystemCounter[63:0] +
ZeroExtend(WatchdogOffsetValue[31:0])
9    Endif

10  If WatchdogEnable == DISABLED
11          WS0 = FALSE
12          WS1 = FALSE
13  ElseIf ExplicitRefresh == TRUE
14         WS0 = FALSE
15         WS1 = FALSE
16  ElseIf TimeoutRefresh == TRUE
17         If WS0 == FALSE
18                   WS0 = TRUE
19         Else
20                   WS1 = TRUE
21         Endif
22  Endif
---------------------------------------------------

I would like to stress that  pretimeout == 0 should not happen in a
real server system,  that is why we defined  a SBSA watchdog, but not
a normal one
But we still need to thinking about the situation that administrator
want to do this on a very special purpose.

maybe we can set min_pretimeout = 1 for this driver. that is just a suggestion.


> if it must be set to a value > 0 I don't understand why
> setting it to 1 (instead of 1 second) would not be sufficient.

it don't have to be 1 second , it can be 0.1, 0.5 or 0.01 second. like
I said before, we just need a time slot to setup WCV in
sbsa_gwdt_start. I have commented this in sbsa_gwdt_set_pretimeout in
this patchset.
But I think the minimum time slot depend on implementation, the spec
doesn't mention about this.
If pretimeout == 0, and we set up WOR a little bigger,  it *ONLY*
affect "the worst case" I mention above. in this case, a administrator
set up pretimeout == 0 which should not happen in a real server, then
the system goes very wrong. I don't think it is important that this
server system reset in 1 second or 0.0001 second, at this time, this
server can not provide any useful info anyway(because we don't use
pretimeout).
If system may go wrong,  the administrator should set up pretimeout >
0 to figure out what is wrong with it just like he always should do.

>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-09  6:37                     ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-09  6:37 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw-LthD3rsA81gm4RdzfppkhA

Hi Guenter,

Thanks for reply so quickly.

On 9 June 2015 at 12:37, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On 06/08/2015 08:59 PM, Fu Wei wrote:
>>
>> Hi Guenter,
>>
>>
>> On 9 June 2015 at 02:26, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
>>>
>>> On 06/08/2015 09:05 AM, Fu Wei wrote:
>>>>
>>>>
>>>> Hi Gurnter
>>>>
>>>> On 3 June 2015 at 01:07, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
>>>>>
>>>>>
>>>>> On 06/02/2015 09:55 AM, Fu Wei wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> Hi Timur,
>>>>>>
>>>>>> Thanks , feedback inline
>>>>>>
>>>>>> On 2 June 2015 at 23:32, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 06/01/2015 11:05 PM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>>>>>>>
>>>>>>>> +/*
>>>>>>>> + * help functions for accessing 32bit registers of SBSA Generic
>>>>>>>> Watchdog
>>>>>>>> + */
>>>>>>>> +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);
>>>>>>>> +}
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> I still think you should get rid of these functions and just call
>>>>>>> readl_relaxed() and writel_relaxed() every time, but I won't complain
>>>>>>> again
>>>>>>> if you keep them.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> yes, that make sense, and will reduce the size of code, and I think
>>>>>> the code's readability will be OK too.
>>>>>> will try in my next patch,
>>>>>>
>>>>>>>
>>>>>>>> +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;
>>>>>>>> +
>>>>>>>> +       if (wdd->pretimeout)
>>>>>>>> +               /* The pretimeout is valid, go panic */
>>>>>>>> +               panic("SBSA Watchdog pre-timeout");
>>>>>>>> +       else
>>>>>>>> +               /* We don't use pretimeout, trigger WS1 now*/
>>>>>>>> +               sbsa_gwdt_set_wcv(wdd, 0);
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> I don't like this.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> If so, what is your idea ,if pretimeout == 0?
>>>>>>
>>>>>> the reason of using WCV as (timout - pretimeout): it can provide the
>>>>>> longer timeout period,
>>>>>> (1)If we use WOR, it can only provide 10s @ 400MHz(max).
>>>>>> as Guenter said earlier, the default timer out for most watchdog will
>>>>>> be 30s, so I think 10s limit will be a little short
>>>>>> (2)we can always program WCV just like ping.
>>>>>> (3)if a timeout arrives, WOR will be use, so use it as pretimeout, but
>>>>>> we still can make this pretimeout longer by programming WCV(I don't
>>>>>> think it's necessary)
>>>>>>
>>>>>>
>>>>>>> The triggering of the hardware reset should never depend
>>>>>>> on an interrupt being handled properly.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> if this fail, system reset in 1S, because WOR == (1s)
>>>>>>
>>>>> So ?
>>>>
>>>>
>>>>
>>>> Even the interrupt routine isn't triggered,  (WOR + system counter) -->
>>>> WCV,
>>>> then, sy system reset in 1S.
>>>>
>>>> the hardware reset doesn't depend on an interrupt.
>>>>
>>>>
>>>>>
>>>>>>> You should always program WCV
>>>>>>> correctly in advance.  This is especially true since pre-timeout will
>>>>>>> probably rarely be used.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> always programming WCV is doable.  But I absolutely can not agree "
>>>>>> pre-timeout will probably rarely be used"
>>>>>> If so, SBSA watchdog is just a normal watchdog,  This use case just
>>>>>> makes this HW useless.
>>>>>> If so, go to use SP805.
>>>>>> you still don't see the importance of this warning and pretimeout to a
>>>>>> real server.
>>>>>>
>>>>>
>>>>> If pretimeout isn't used, why not just set WCV = timeout, WOR = 0 ?
>>>>
>>>>
>>>>
>>>> Because if WOR = 0 , according to SBSA,  once you want to enable
>>>> watchdog,
>>>> (0 + system counter) --> WCV , then , WS0 and WS1 will be triggered
>>>> immediately.
>>>> we have not a chance(a time slot) to update WCV.
>>>>
>>>
>>> I would have thought that this is exactly what we want if pretimeout is
>>> not
>>> used.
>>
>>
>> Although pretimeout == 0 is not good for a server, but If
>> administrator set up pretimeout == 0. *I thinks we should trigger WS1
>> ASAP* . Because  WS1 maybe a interrupter or a reboot signal, that is
>> why we can not reboot system directly.
>>
>> This driver is SBSA watchdog driver, that means we need to follow SBSA
>> spec:
>> (1) SBSA watchdog has two stage timeouts --> timeout and pretimeout is
>> the best solution in watchdog framework, at least for now.
>> (2) The watchdog has the following output signals:
>>      Watchdog Signal 0 (WS0)---> "The initial signal is typically wired
>> to an interrupt and alerts the system."(original word from spec), I
>> thinks the key work should be "interrupt" and "alerts". So in WS0
>> interrupt routine, reset is absolutely a wrong operation. Although I
>> think we should make this "alerts" more useful. But for the first
>> version of driver, I thinks panic is useful enough.
>>      Watchdog Signal 1 (WS1). ---> "The signal is fed to a higher agent
>> as an interrupt or reset for it to take executive action." (original
>> word from spec) . The key work should be "interrupt", "or" and "reset"
>> . So  WS1 maybe a interrupt.
>> so even in the WS0 interrupt routine, if  pretimeout == 0 , we need to
>> trigger WS1(that is what my patch is doing now, set WCV to 0, so WCV
>> is always less than SystemCounter, and in this situation(WS0 = TRUE),
>> WS1 will be trigger immediately), but definitely not a reset too.
>>
>> But in worst case,  if the WS0 is triggered, but the interrupt routine
>> doesn't work(can not set up WCV), it doesn't matter, we just need to
>> wait for a WOR(1s in my driver) timeout, then WS1 will be triggered.
>> That is hardware mechanism, once we config SBSA watchdog correctly,
>> that should work.  If it doesn't, I think the chip design doesn't
>> follow the SBSA spec.
>>
>> Make a summary here, for SBSA watchdog driver,  it need to support two
>> stage timeouts and need to trigger WS0/1 when timeouts occur(can not
>> simply reset system in interrupt routines).
>> If a driver doesn't do these above, the driver can not be called SBSA
>> watchdog driver.
>>
>> But according to SBSA, even pretimeout == 0, we can not setup WOR = 0.
>> if we make WOR = 0 , once we set up WCS(enabling watchdog), that cause
>> a explicit watchdog refresh, then WCV = (0 + system counter), so WS0
>> and WS1 will be triggered serially and immediately(in theory, the
>
>
> I still don't understand why this would be a problem.

that 20+ lines pseudocode from the page 23 of SBSA spec 2.3 can
explain this well.
Please let me know which line confuse you, I will explain them one by one below.

>
>> "delay" also depend on implementation). So in my patchset , if
>> pretimeout == 0, WOR will be 1s at least to make sure we have time to
>> setup WCV. I have made comments in the patch for explaining this.
>>
>> Maybe some people want to ask: if we can not set up WOR = 0, but
>> pretimeout can be 0 and timeout can not, why I still want to use WOR
>> for pretimeout and using WCV as (timout - pretimeout) ??
>> For this:
>> (1)WCV can provide the longer timeout period, If we use WOR, it can
>> only provide 10s @ 400MHz(max). The default timer out for most
>> watchdog will be 30s, so I think 10s limit will be a little short.
>> (2)we can always program(write) WCV just like ping.
>> (3)if the first timeout occurs, WOR will be loaded to WCV(WOR + system
>> counter)  automatically , so why not just use WOR as pretimeout?
>> Although we still can make this pretimeout longer by programming WCV,
>> I don't think it's necessary for now.
>>
>
> Too bad I don't have an arm64 system to test myself. I am not sure
> I understand why WOR must be set to > 0 if pretimeout == 0, and even

Although SBSA spec has published for years(2.2 was published at 15th
Jan 2014), but this is still a relatively new spec of hardware, for
now . I only has Foundation model and FAST model for testing.
But I would like to suggest: this driver should follow the SBSA spec
first, but not a specific hardware, even some of hardware has this
watchdog, but there maybe some hardware bug in it(at least I know
there is one).

I am using 1 second, just because I think 1 second is safe enough to
reload WCV. (from write "1" in WCS  to reload WCV[31:0] and WCV[63:32]
)
Actually,  in most of case , we need WOR > 1, only when we enable the
watchdog( write "1" to WCS, this causes a ExplicitRefresh, see Line 7
"ExplicitRefresh == TRUE" and Line 8 below).
in this cause , we just need a time slot to reload WCV, the driver
doesn't really spend 1s on this.
But If WOR ==0, (Line 1) TimeoutRefresh = TRUE in a very short time,
the minimum time depends on the implementation. Then The first timeout
stage occur(see Line 7 (TimeoutRefresh == TRUE and WS0 == FALSE), and
Line 8 below again ) and  WS0 was triggered(Line 16~18).  Because WOR
==0 too, (Line 1) TimeoutRefresh = TRUE occur in a very short time
again, then see Line 16, 17, 20

In worst case, if pretimeout is 0, First timeout stage occur(see Line
7 (TimeoutRefresh == TRUE and WS0 == FALSE), and Line 8 below,  then
Line 16~18)   but the interrupt routine doesn't work, we can still got
WS1 in the time we configured in WOR. (Line 1) TimeoutRefresh = TRUE
occur when SystemCounter[63:0] > SystemCounter[63:0] +
ZeroExtend(WOR[31:0]), then  Line 16, 17, 20

---------------------------------------------------
CompareValue : WCV
WatchdogOffsetValue : WOR


1    TimeoutRefresh = (SystemCounter[63:0] > CompareValue[63:0])

2    If WatchdogColdReset
3            WatchdogEnable = DISABLED
4    Endif

5    If LoadNewCompareValue
6            CompareValue = new_value
7    ElseIf ExplicitRefresh == TRUE or (TimeoutRefresh == TRUE and WS0 == FALSE)
8           CompareValue = SystemCounter[63:0] +
ZeroExtend(WatchdogOffsetValue[31:0])
9    Endif

10  If WatchdogEnable == DISABLED
11          WS0 = FALSE
12          WS1 = FALSE
13  ElseIf ExplicitRefresh == TRUE
14         WS0 = FALSE
15         WS1 = FALSE
16  ElseIf TimeoutRefresh == TRUE
17         If WS0 == FALSE
18                   WS0 = TRUE
19         Else
20                   WS1 = TRUE
21         Endif
22  Endif
---------------------------------------------------

I would like to stress that  pretimeout == 0 should not happen in a
real server system,  that is why we defined  a SBSA watchdog, but not
a normal one
But we still need to thinking about the situation that administrator
want to do this on a very special purpose.

maybe we can set min_pretimeout = 1 for this driver. that is just a suggestion.


> if it must be set to a value > 0 I don't understand why
> setting it to 1 (instead of 1 second) would not be sufficient.

it don't have to be 1 second , it can be 0.1, 0.5 or 0.01 second. like
I said before, we just need a time slot to setup WCV in
sbsa_gwdt_start. I have commented this in sbsa_gwdt_set_pretimeout in
this patchset.
But I think the minimum time slot depend on implementation, the spec
doesn't mention about this.
If pretimeout == 0, and we set up WOR a little bigger,  it *ONLY*
affect "the worst case" I mention above. in this case, a administrator
set up pretimeout == 0 which should not happen in a real server, then
the system goes very wrong. I don't think it is important that this
server system reset in 1 second or 0.0001 second, at this time, this
server can not provide any useful info anyway(because we don't use
pretimeout).
If system may go wrong,  the administrator should set up pretimeout >
0 to figure out what is wrong with it just like he always should do.

>
> 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
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-09  8:04                       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-09  8:04 UTC (permalink / raw)
  To: Fu Wei
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

On 06/08/2015 11:37 PM, Fu Wei wrote:

>
> I would like to stress that  pretimeout == 0 should not happen in a
> real server system,  that is why we defined  a SBSA watchdog, but not
> a normal one

Clarification - In _your opinion_, a server should always use pretimeout.

> But we still need to thinking about the situation that administrator
> want to do this on a very special purpose.
>
I could as well argue that setting pretimeout is the special situation.
Some administrators may not want to bother but just want the system to reset
if  a watchdog timeout occurs. _Maybe_ if it happens multiple times,
they might want to set up pretimeout to figure out why.

Declaring that one _has_ to configure pretimeout is just a personal
opinion, nothing else. We don't know what server administrators want,
and we should not dictate anything unless technically necessary.

> maybe we can set min_pretimeout = 1 for this driver. that is just a suggestion.
>
No. It is not technically necessary.

>
>> if it must be set to a value > 0 I don't understand why
>> setting it to 1 (instead of 1 second) would not be sufficient.
>
> it don't have to be 1 second , it can be 0.1, 0.5 or 0.01 second. like
> I said before, we just need a time slot to setup WCV in
> sbsa_gwdt_start. I have commented this in sbsa_gwdt_set_pretimeout in
> this patchset.

I think what you really want to say is that you want to have time to
handle the interrupt. But handling the interrupt is not asked for if
pretimeout == 0.

> But I think the minimum time slot depend on implementation, the spec
> doesn't mention about this.

Yes, because a minimum value does not exist.

> If pretimeout == 0, and we set up WOR a little bigger,  it *ONLY*
> affect "the worst case" I mention above. in this case, a administrator
> set up pretimeout == 0 which should not happen in a real server, then
> the system goes very wrong. I don't think it is important that this
> server system reset in 1 second or 0.0001 second, at this time, this
> server can not provide any useful info anyway(because we don't use
> pretimeout).
> If system may go wrong,  the administrator should set up pretimeout >
> 0 to figure out what is wrong with it just like he always should do.
>

Yes, exactly. But otherwise, if pretimeout is set to 0, we want
to reset immediately as directed.

As I interpret the specification, WOR=0 forces WS1 immediately after WS0.

1) if TimeoutRefresh = True:
	CompareValue := SystemCounter + WOR (= SystemCounter
	WS0 := True
2) TimeoutRefresh is True again, WS0 == True:
	WS1 = True

This is exactly the behavior we want if pretimeout == 0. In this situation,
we don't want to handle the interrupt, we just want to reset the system as
fast as possible.

Having said that, have you tested what happens in your system if you
set WOR=0 ?

Thanks,
Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-09  8:04                       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-09  8:04 UTC (permalink / raw)
  To: Fu Wei
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw-LthD3rsA81gm4RdzfppkhA

On 06/08/2015 11:37 PM, Fu Wei wrote:

>
> I would like to stress that  pretimeout == 0 should not happen in a
> real server system,  that is why we defined  a SBSA watchdog, but not
> a normal one

Clarification - In _your opinion_, a server should always use pretimeout.

> But we still need to thinking about the situation that administrator
> want to do this on a very special purpose.
>
I could as well argue that setting pretimeout is the special situation.
Some administrators may not want to bother but just want the system to reset
if  a watchdog timeout occurs. _Maybe_ if it happens multiple times,
they might want to set up pretimeout to figure out why.

Declaring that one _has_ to configure pretimeout is just a personal
opinion, nothing else. We don't know what server administrators want,
and we should not dictate anything unless technically necessary.

> maybe we can set min_pretimeout = 1 for this driver. that is just a suggestion.
>
No. It is not technically necessary.

>
>> if it must be set to a value > 0 I don't understand why
>> setting it to 1 (instead of 1 second) would not be sufficient.
>
> it don't have to be 1 second , it can be 0.1, 0.5 or 0.01 second. like
> I said before, we just need a time slot to setup WCV in
> sbsa_gwdt_start. I have commented this in sbsa_gwdt_set_pretimeout in
> this patchset.

I think what you really want to say is that you want to have time to
handle the interrupt. But handling the interrupt is not asked for if
pretimeout == 0.

> But I think the minimum time slot depend on implementation, the spec
> doesn't mention about this.

Yes, because a minimum value does not exist.

> If pretimeout == 0, and we set up WOR a little bigger,  it *ONLY*
> affect "the worst case" I mention above. in this case, a administrator
> set up pretimeout == 0 which should not happen in a real server, then
> the system goes very wrong. I don't think it is important that this
> server system reset in 1 second or 0.0001 second, at this time, this
> server can not provide any useful info anyway(because we don't use
> pretimeout).
> If system may go wrong,  the administrator should set up pretimeout >
> 0 to figure out what is wrong with it just like he always should do.
>

Yes, exactly. But otherwise, if pretimeout is set to 0, we want
to reset immediately as directed.

As I interpret the specification, WOR=0 forces WS1 immediately after WS0.

1) if TimeoutRefresh = True:
	CompareValue := SystemCounter + WOR (= SystemCounter
	WS0 := True
2) TimeoutRefresh is True again, WS0 == True:
	WS1 = True

This is exactly the behavior we want if pretimeout == 0. In this situation,
we don't want to handle the interrupt, we just want to reset the system as
fast as possible.

Having said that, have you tested what happens in your system if you
set WOR=0 ?

Thanks,
Guenter

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-09  8:04                       ` Guenter Roeck
  (?)
@ 2015-06-09 10:46                       ` Fu Wei
  2015-06-09 16:22                         ` Guenter Roeck
  -1 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-06-09 10:46 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

Hi Guenter,

Thanks for your feedback

On 9 June 2015 at 16:04, Guenter Roeck <linux@roeck-us.net> wrote:
> On 06/08/2015 11:37 PM, Fu Wei wrote:
>
>>
>> I would like to stress that  pretimeout == 0 should not happen in a
>> real server system,  that is why we defined  a SBSA watchdog, but not
>> a normal one
>
>
> Clarification - In _your opinion_, a server should always use pretimeout.
>
>> But we still need to thinking about the situation that administrator
>> want to do this on a very special purpose.
>>
> I could as well argue that setting pretimeout is the special situation.
> Some administrators may not want to bother but just want the system to reset
> if  a watchdog timeout occurs. _Maybe_ if it happens multiple times,
> they might want to set up pretimeout to figure out why.

you are right,
before this driver and device are really used in some server, we don't
know How do administrators use this pretimeout,
and the percentage of using pretimeout, But here you did mention a
good usage of pretimeout: we can figure out what is wrong with system.

except the usages,  this two stage timeouts is a main feature of SBSA
watchdog, if we drop this feature, I don't think that is a  SBSA
watchdog driver. it becomes normal watchdog driver using SBSA watchdog
hardware.

>
> Declaring that one _has_ to configure pretimeout is just a personal
> opinion, nothing else. We don't know what server administrators want,
> and we should not dictate anything unless technically necessary.

yes, agree with you on "we should not dictate anything unless
technically necessary."

>
>> maybe we can set min_pretimeout = 1 for this driver. that is just a
>> suggestion.
>>
> No. It is not technically necessary.

it is just a thought. but I never do that , because min_pretimeout = 0
is technically doable in this driver.

>
>>
>>> if it must be set to a value > 0 I don't understand why
>>> setting it to 1 (instead of 1 second) would not be sufficient.
>>
>>
>> it don't have to be 1 second , it can be 0.1, 0.5 or 0.01 second. like
>> I said before, we just need a time slot to setup WCV in
>> sbsa_gwdt_start. I have commented this in sbsa_gwdt_set_pretimeout in
>> this patchset.
>
>
> I think what you really want to say is that you want to have time to
> handle the interrupt. But handling the interrupt is not asked for if
> pretimeout == 0.

No, that is not what I want to say. pretimeout == 0 but WOR can not be
0 is nothing to do with interrupt.
In another word,  pretimeout == 0 we should trigger WS1 ASAP, we don't
need to handle the interrupt.
I have explained this in  previous email:

"
we need WOR > 1, only when we enable the watchdog( write "1" to WCS,
this causes a ExplicitRefresh, see Line 7 "ExplicitRefresh == TRUE"
and Line 8 below).
in this cause , we just need a time slot to reload WCV, the driver
doesn't really spend 1s on this.
But If WOR ==0, (Line 1) TimeoutRefresh = TRUE in a very short time,
the minimum time depends on the implementation. Then The first timeout
stage occur(see Line 7 (TimeoutRefresh == TRUE and WS0 == FALSE), and
Line 8 below again ) and  WS0 was triggered(Line 16~18).  Because WOR
==0 too, (Line 1) TimeoutRefresh = TRUE occur in a very short time
again, then see Line 16, 17, 20
"
in one word, according to SBSA,  If we make WOR == 0, once we enable
watchdog, WS0 and WS1 will be triggered immediately, we have not
chance to set up WCV for (timeout - pretimeout).
In another word,  WOR == 0, we can not enable watchdog, enabling
become a warn reset button.

>
>> But I think the minimum time slot depend on implementation, the spec
>> doesn't mention about this.
>
>
> Yes, because a minimum value does not exist.
>
>> If pretimeout == 0, and we set up WOR a little bigger,  it *ONLY*
>> affect "the worst case" I mention above. in this case, a administrator
>> set up pretimeout == 0 which should not happen in a real server, then
>> the system goes very wrong. I don't think it is important that this
>> server system reset in 1 second or 0.0001 second, at this time, this
>> server can not provide any useful info anyway(because we don't use
>> pretimeout).
>> If system may go wrong,  the administrator should set up pretimeout >
>> 0 to figure out what is wrong with it just like he always should do.
>>
>
> Yes, exactly. But otherwise, if pretimeout is set to 0, we want
> to reset immediately as directed.

In this driver, if pretimeout is set to 0, we want to *trigger WS1*
immediately as directed.
Yes, If we could.

>
> As I interpret the specification, WOR=0 forces WS1 immediately after WS0.
>
> 1) if TimeoutRefresh = True:
>         CompareValue := SystemCounter + WOR (= SystemCounter
>         WS0 := True
> 2) TimeoutRefresh is True again, WS0 == True:
>         WS1 = True
>
> This is exactly the behavior we want if pretimeout == 0. In this situation,
> we don't want to handle the interrupt, we just want to reset the system as
> fast as possible.

Yes, if WOR only affect in TimeoutRefresh, we cat always make WOR == pretimeout
But the problem is  if we enable watchdog (write 0x01 to WCS will
cause an explicit watchdog refresh), then
1) if ExplicitRefresh = True:
         CompareValue := SystemCounter + WOR
         WS0 := True
2) TimeoutRefresh is True again, WS0 == True:
         WS1 = True

so once we enable watchdog, system reset, that is not what we want.
this behavior is following SBSA spec.

FYI:
-----
An explicit watchdog refresh occurs when one of a number of different
events occur:
 The Watchdog Refresh Register is written.
 The Watchdog Offset Register is written.
 The Watchdog Control and Status register is written.
-----

>
> Having said that, have you tested what happens in your system if you
> set WOR=0 ?

I have not HW, but I have tested it on Foundation model, the result is
just what I expect:
-------------------------------------
pretimeout=0 ,

and

static int sbsa_gwdt_set_pretimeout(struct watchdog_device *wdd,
                    unsigned int pretimeout)
{
    struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);

    wdd->pretimeout = pretimeout;

    /* refresh the WOR, that will cause an explicit watchdog refresh */
    sbsa_gwdt_cf_write(SBSA_GWDT_WOR,  pretimeout * gwdt->clk, wdd);

    return 0;
}
-------------------------------------
Once I enable watchdog, system down(there is a WS1 interrupter in
Foundation model, but not more info for that), there is not panic(if
ws0 is triggered).

>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-09 10:46                       ` Fu Wei
@ 2015-06-09 16:22                         ` Guenter Roeck
  2015-06-09 16:29                             ` Timur Tabi
  0 siblings, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-06-09 16:22 UTC (permalink / raw)
  To: Fu Wei
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

On 06/09/2015 03:46 AM, Fu Wei wrote:

> Yes, if WOR only affect in TimeoutRefresh, we cat always make WOR == pretimeout
> But the problem is  if we enable watchdog (write 0x01 to WCS will
> cause an explicit watchdog refresh), then
> 1) if ExplicitRefresh = True:
>           CompareValue := SystemCounter + WOR
>           WS0 := True
> 2) TimeoutRefresh is True again, WS0 == True:
>           WS1 = True
>
> so once we enable watchdog, system reset, that is not what we want.
> this behavior is following SBSA spec.
>

Ok, I admit I am a bit slow ;-).

WS0 := True would be set the next time around, since

	if ExplicitRefresh == True
		WS0 = False
		WS1 = False

but I see your point. Essentially, the specification is broken
for all practical purposes, since, as you point out, enabling
the watchdog overwrites and explicitly sets WCV. Effectively
this means that just using WCV to program the timeout period
is not really possible.

I am not really sure how to address this. We can either only use WOR,
and forget about pretimeout, or we can enforce a minimum pretimeout.
In the latter case, we'll have to write WCV after writing WOR.

Thanks,
Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-09 16:29                             ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-09 16:29 UTC (permalink / raw)
  To: Guenter Roeck, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

On 06/09/2015 11:22 AM, Guenter Roeck wrote:
>
>
> but I see your point. Essentially, the specification is broken
> for all practical purposes, since, as you point out, enabling
> the watchdog overwrites and explicitly sets WCV. Effectively
> this means that just using WCV to program the timeout period
> is not really possible.
>
> I am not really sure how to address this. We can either only use WOR,
> and forget about pretimeout, or we can enforce a minimum pretimeout.
> In the latter case, we'll have to write WCV after writing WOR.

In talking with our hardware engineers, using WCV to program the timeout 
period is not a valid operation.  This is why I keep arguing against the 
pre-timeout feature, and I don't agree that servers should always use 
pre-timeout.

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-09 16:29                             ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-09 16:29 UTC (permalink / raw)
  To: Guenter Roeck, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw-LthD3rsA81gm4RdzfppkhA

On 06/09/2015 11:22 AM, Guenter Roeck wrote:
>
>
> but I see your point. Essentially, the specification is broken
> for all practical purposes, since, as you point out, enabling
> the watchdog overwrites and explicitly sets WCV. Effectively
> this means that just using WCV to program the timeout period
> is not really possible.
>
> I am not really sure how to address this. We can either only use WOR,
> and forget about pretimeout, or we can enforce a minimum pretimeout.
> In the latter case, we'll have to write WCV after writing WOR.

In talking with our hardware engineers, using WCV to program the timeout 
period is not a valid operation.  This is why I keep arguing against the 
pre-timeout feature, and I don't agree that servers should always use 
pre-timeout.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-09 16:29                             ` Timur Tabi
  (?)
@ 2015-06-09 16:45                             ` Guenter Roeck
  2015-06-09 16:53                                 ` Timur Tabi
  2015-06-10  3:41                                 ` Fu Wei
  -1 siblings, 2 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-09 16:45 UTC (permalink / raw)
  To: Timur Tabi, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

On 06/09/2015 09:29 AM, Timur Tabi wrote:
> On 06/09/2015 11:22 AM, Guenter Roeck wrote:
>>
>>
>> but I see your point. Essentially, the specification is broken
>> for all practical purposes, since, as you point out, enabling
>> the watchdog overwrites and explicitly sets WCV. Effectively
>> this means that just using WCV to program the timeout period
>> is not really possible.
>>
>> I am not really sure how to address this. We can either only use WOR,
>> and forget about pretimeout, or we can enforce a minimum pretimeout.
>> In the latter case, we'll have to write WCV after writing WOR.
>
> In talking with our hardware engineers, using WCV to program the timeout period is not a valid operation.  This is why I keep arguing against the pre-timeout feature, and I don't agree that servers should always use pre-timeout.
>

Not sure if "not valid" is correct - after all, it is mentioned in the
specification. However, it is at the very least fragile.

I tend to agree that we should just forget about pretimeout and
use your original approach, where the timeout value is used
to program WOR. Everything else is really just asking for trouble.

Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-09 16:53                                 ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-09 16:53 UTC (permalink / raw)
  To: Guenter Roeck, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

On 06/09/2015 11:45 AM, Guenter Roeck wrote:

> I tend to agree that we should just forget about pretimeout and
> use your original approach, where the timeout value is used
> to program WOR. Everything else is really just asking for trouble.

The driver that I submitted is effectively the same as Fu's, except 
without pre-timeout support.

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-09 16:53                                 ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-09 16:53 UTC (permalink / raw)
  To: Guenter Roeck, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw-LthD3rsA81gm4RdzfppkhA

On 06/09/2015 11:45 AM, Guenter Roeck wrote:

> I tend to agree that we should just forget about pretimeout and
> use your original approach, where the timeout value is used
> to program WOR. Everything else is really just asking for trouble.

The driver that I submitted is effectively the same as Fu's, except 
without pre-timeout support.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10  3:41                                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-10  3:41 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

Hi Guenter,

On 10 June 2015 at 00:45, Guenter Roeck <linux@roeck-us.net> wrote:
> On 06/09/2015 09:29 AM, Timur Tabi wrote:
>>
>> On 06/09/2015 11:22 AM, Guenter Roeck wrote:
>>>
>>>
>>>
>>> but I see your point. Essentially, the specification is broken
>>> for all practical purposes, since, as you point out, enabling
>>> the watchdog overwrites and explicitly sets WCV. Effectively
>>> this means that just using WCV to program the timeout period
>>> is not really possible.
>>>
>>> I am not really sure how to address this. We can either only use WOR,
>>> and forget about pretimeout, or we can enforce a minimum pretimeout.
>>> In the latter case, we'll have to write WCV after writing WOR.
>>
>>
>> In talking with our hardware engineers, using WCV to program the timeout
>> period is not a valid operation.  This is why I keep arguing against the
>> pre-timeout feature, and I don't agree that servers should always use
>> pre-timeout.
>>
>
> Not sure if "not valid" is correct - after all, it is mentioned in the
> specification. However, it is at the very least fragile.

I think we should focus on SBSA spec, but not a specific chip design,
because this is SBSA watchdog, not a driver for an IP core from a
specific chip vendor.
this operation is mentioned in the spec,
and I have tested my driver on Foundation model(from ARM) and a real hardware.

>
> I tend to agree that we should just forget about pretimeout and
> use your original approach, where the timeout value is used
> to program WOR. Everything else is really just asking for trouble.

I don't mind if we give up pretimeout, The reason I use pretimeout is:
this concept matches the function of two stage timeouts.

but, If we give up pretimeout, could you give me a suggestion:

How to config the two stage timeouts
(1)from enabling watchdog to WS0
(2)the time from WS1 to WS0

If we only have one timeout parameter,  How to config the two stage timeouts?
Any suggestion ?

If we make the first stage timeout is timeout/2,  this violates the
definition of timeout.
I don't think users expect interrupt, panic or reboot at timeout/2.

And WS1  definitely isn't a backup of WS0.

>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10  3:41                                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-10  3:41 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw-LthD3rsA81gm4RdzfppkhA

Hi Guenter,

On 10 June 2015 at 00:45, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On 06/09/2015 09:29 AM, Timur Tabi wrote:
>>
>> On 06/09/2015 11:22 AM, Guenter Roeck wrote:
>>>
>>>
>>>
>>> but I see your point. Essentially, the specification is broken
>>> for all practical purposes, since, as you point out, enabling
>>> the watchdog overwrites and explicitly sets WCV. Effectively
>>> this means that just using WCV to program the timeout period
>>> is not really possible.
>>>
>>> I am not really sure how to address this. We can either only use WOR,
>>> and forget about pretimeout, or we can enforce a minimum pretimeout.
>>> In the latter case, we'll have to write WCV after writing WOR.
>>
>>
>> In talking with our hardware engineers, using WCV to program the timeout
>> period is not a valid operation.  This is why I keep arguing against the
>> pre-timeout feature, and I don't agree that servers should always use
>> pre-timeout.
>>
>
> Not sure if "not valid" is correct - after all, it is mentioned in the
> specification. However, it is at the very least fragile.

I think we should focus on SBSA spec, but not a specific chip design,
because this is SBSA watchdog, not a driver for an IP core from a
specific chip vendor.
this operation is mentioned in the spec,
and I have tested my driver on Foundation model(from ARM) and a real hardware.

>
> I tend to agree that we should just forget about pretimeout and
> use your original approach, where the timeout value is used
> to program WOR. Everything else is really just asking for trouble.

I don't mind if we give up pretimeout, The reason I use pretimeout is:
this concept matches the function of two stage timeouts.

but, If we give up pretimeout, could you give me a suggestion:

How to config the two stage timeouts
(1)from enabling watchdog to WS0
(2)the time from WS1 to WS0

If we only have one timeout parameter,  How to config the two stage timeouts?
Any suggestion ?

If we make the first stage timeout is timeout/2,  this violates the
definition of timeout.
I don't think users expect interrupt, panic or reboot at timeout/2.

And WS1  definitely isn't a backup of WS0.

>
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-10  3:41                                 ` Fu Wei
  (?)
@ 2015-06-10  4:20                                 ` Fu Wei
  2015-06-10 14:22                                     ` Timur Tabi
  -1 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-06-10  4:20 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

Hi Guenter,

On 10 June 2015 at 11:41, Fu Wei <fu.wei@linaro.org> wrote:
> Hi Guenter,
>
> On 10 June 2015 at 00:45, Guenter Roeck <linux@roeck-us.net> wrote:
>> On 06/09/2015 09:29 AM, Timur Tabi wrote:
>>>
>>> On 06/09/2015 11:22 AM, Guenter Roeck wrote:
>>>>
>>>>
>>>>
>>>> but I see your point. Essentially, the specification is broken
>>>> for all practical purposes, since, as you point out, enabling
>>>> the watchdog overwrites and explicitly sets WCV. Effectively
>>>> this means that just using WCV to program the timeout period
>>>> is not really possible.
>>>>
>>>> I am not really sure how to address this. We can either only use WOR,
>>>> and forget about pretimeout, or we can enforce a minimum pretimeout.
>>>> In the latter case, we'll have to write WCV after writing WOR.
>>>
>>>
>>> In talking with our hardware engineers, using WCV to program the timeout
>>> period is not a valid operation.  This is why I keep arguing against the
>>> pre-timeout feature, and I don't agree that servers should always use
>>> pre-timeout.
>>>
>>
>> Not sure if "not valid" is correct - after all, it is mentioned in the
>> specification. However, it is at the very least fragile.
>
> I think we should focus on SBSA spec, but not a specific chip design,
> because this is SBSA watchdog, not a driver for an IP core from a
> specific chip vendor.
> this operation is mentioned in the spec,
> and I have tested my driver on Foundation model(from ARM) and a real hardware.
>
>>
>> I tend to agree that we should just forget about pretimeout and
>> use your original approach, where the timeout value is used
>> to program WOR. Everything else is really just asking for trouble.

Another weakness of only using WOR is the timeout limited by this
32bit register.
10s @400MHz generic Timer

I don't think this limit is good for a server, once the server is in a
heavy load

>
> I don't mind if we give up pretimeout, The reason I use pretimeout is:
> this concept matches the function of two stage timeouts.
>
> but, If we give up pretimeout, could you give me a suggestion:
>
> How to config the two stage timeouts
> (1)from enabling watchdog to WS0
> (2)the time from WS1 to WS0
>
> If we only have one timeout parameter,  How to config the two stage timeouts?
> Any suggestion ?
>
> If we make the first stage timeout is timeout/2,  this violates the
> definition of timeout.
> I don't think users expect interrupt, panic or reboot at timeout/2.
>
> And WS1  definitely isn't a backup of WS0.
>
>>
>> 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



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v5 0/8] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 13:41   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-10 13:41 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patchset:
    (1)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.

    (2)Introduce ACPI GTDT parser: drivers/acpi/gtdt.c
    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.
    drivers/clocksource/arm_arch_timer.c is simplified by this GTDT support.

    (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, do panic to save system context;
        e.Support getting timeout and pretimeout from parameter and FDT
          at the driver init stage.

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

Changelog:
v5: Improve pretimeout support:
        (1)fix typo in documentation and comments.
	(2)fix the timeout limits validation bug.
    Simplify sbsa_gwdt driver:
	(1)integrate all the registers access functions into caller.

v4: Refactor GTDT support code: remove it from arch/arm64/kernel/acpi.c,
    put it into drivers/acpi/gtdt.c file.
    Integrate the GTDT code of drivers/clocksource/arm_arch_timer.c into
    drivers/acpi/gtdt.c.
    Improve pretimeout support, fix "pretimeout == 0" problem.
    Simplify sbsa_gwdt driver:
        (1)timeout/pretimeout limits setup;
        (2)keepalive function;
        (3)delete "clk == 0" check;
        (4)delete WS0 status bit check in interrupt routine;
        (5)sbsa_gwdt_set_wcv function.

v3: Delete "export arch_timer_get_rate" patch.
    Driver back to use arch_timer_get_cntfrq.
    Improve watchdog_init_timeouts function and update relevant documentation.
    Improve watchdog_timeout_invalid and watchdog_pretimeout_invalid.
    Improve foundation-v8.dts: delete the unnecessary tag of device node.
    Remove "ARM64 || COMPILE_TEST" from Kconfig.
    Add comments in arch/arm64/kernel/acpi.c
    Fix typoes and incorrect comments.

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 (8):
  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: introdouce "pretimeout" into framework
  Watchdog: introduce ARM SBSA watchdog driver
  ACPI: add GTDT table parse driver into ACPI driver
  Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
  clocksource: simplify ACPI code in arm_arch_timer.c

 .../devicetree/bindings/watchdog/sbsa-gwdt.txt     |  36 ++
 Documentation/watchdog/watchdog-kernel-api.txt     |  47 ++-
 arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi       |  11 +
 arch/arm64/boot/dts/arm/foundation-v8.dts          |  10 +
 arch/arm64/kernel/time.c                           |   4 +-
 drivers/acpi/Kconfig                               |   9 +
 drivers/acpi/Makefile                              |   1 +
 drivers/acpi/gtdt.c                                | 180 +++++++++
 drivers/clocksource/Kconfig                        |   1 +
 drivers/clocksource/arm_arch_timer.c               |  60 +--
 drivers/watchdog/Kconfig                           |  12 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/sbsa_gwdt.c                       | 409 +++++++++++++++++++++
 drivers/watchdog/watchdog_core.c                   | 100 +++--
 drivers/watchdog/watchdog_dev.c                    |  53 +++
 include/clocksource/arm_arch_timer.h               |   8 +
 include/linux/acpi.h                               |   5 +
 include/linux/clocksource.h                        |   4 +-
 include/linux/watchdog.h                           |  36 +-
 19 files changed, 895 insertions(+), 92 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
 create mode 100644 drivers/acpi/gtdt.c
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

-- 
1.9.1


^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v5 0/8] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 13:41   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-10 13:41 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

This patchset:
    (1)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.

    (2)Introduce ACPI GTDT parser: drivers/acpi/gtdt.c
    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.
    drivers/clocksource/arm_arch_timer.c is simplified by this GTDT support.

    (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, do panic to save system context;
        e.Support getting timeout and pretimeout from parameter and FDT
          at the driver init stage.

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

Changelog:
v5: Improve pretimeout support:
        (1)fix typo in documentation and comments.
	(2)fix the timeout limits validation bug.
    Simplify sbsa_gwdt driver:
	(1)integrate all the registers access functions into caller.

v4: Refactor GTDT support code: remove it from arch/arm64/kernel/acpi.c,
    put it into drivers/acpi/gtdt.c file.
    Integrate the GTDT code of drivers/clocksource/arm_arch_timer.c into
    drivers/acpi/gtdt.c.
    Improve pretimeout support, fix "pretimeout == 0" problem.
    Simplify sbsa_gwdt driver:
        (1)timeout/pretimeout limits setup;
        (2)keepalive function;
        (3)delete "clk == 0" check;
        (4)delete WS0 status bit check in interrupt routine;
        (5)sbsa_gwdt_set_wcv function.

v3: Delete "export arch_timer_get_rate" patch.
    Driver back to use arch_timer_get_cntfrq.
    Improve watchdog_init_timeouts function and update relevant documentation.
    Improve watchdog_timeout_invalid and watchdog_pretimeout_invalid.
    Improve foundation-v8.dts: delete the unnecessary tag of device node.
    Remove "ARM64 || COMPILE_TEST" from Kconfig.
    Add comments in arch/arm64/kernel/acpi.c
    Fix typoes and incorrect comments.

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 (8):
  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: introdouce "pretimeout" into framework
  Watchdog: introduce ARM SBSA watchdog driver
  ACPI: add GTDT table parse driver into ACPI driver
  Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
  clocksource: simplify ACPI code in arm_arch_timer.c

 .../devicetree/bindings/watchdog/sbsa-gwdt.txt     |  36 ++
 Documentation/watchdog/watchdog-kernel-api.txt     |  47 ++-
 arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi       |  11 +
 arch/arm64/boot/dts/arm/foundation-v8.dts          |  10 +
 arch/arm64/kernel/time.c                           |   4 +-
 drivers/acpi/Kconfig                               |   9 +
 drivers/acpi/Makefile                              |   1 +
 drivers/acpi/gtdt.c                                | 180 +++++++++
 drivers/clocksource/Kconfig                        |   1 +
 drivers/clocksource/arm_arch_timer.c               |  60 +--
 drivers/watchdog/Kconfig                           |  12 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/sbsa_gwdt.c                       | 409 +++++++++++++++++++++
 drivers/watchdog/watchdog_core.c                   | 100 +++--
 drivers/watchdog/watchdog_dev.c                    |  53 +++
 include/clocksource/arm_arch_timer.h               |   8 +
 include/linux/acpi.h                               |   5 +
 include/linux/clocksource.h                        |   4 +-
 include/linux/watchdog.h                           |  36 +-
 19 files changed, 895 insertions(+), 92 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
 create mode 100644 drivers/acpi/gtdt.c
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v5 1/8] Documentation: add sbsa-gwdt.txt documentation
  2015-06-10 13:41   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  (?)
@ 2015-06-10 13:41   ` fu.wei
  -1 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-10 13:41 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 .../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..010e5c4
--- /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@2a440000 {
+	compatible = "arm,sbsa-gwdt";
+	reg = <0x0 0x2a440000 0 0x10000>,
+	      <0x0 0x2a450000 0 0x10000>;
+	reg-names = "control", "refresh";
+	interrupts = <0 27 4>;
+	interrupt-names = "ws0";
+	timeout-sec = <10 5>;
+};
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v5 2/8] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
@ 2015-06-10 13:41     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-10 13:41 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 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..962a07e 100644
--- a/arch/arm64/boot/dts/arm/foundation-v8.dts
+++ b/arch/arm64/boot/dts/arm/foundation-v8.dts
@@ -237,4 +237,14 @@
 			};
 		};
 	};
+	watchdog@2a440000 {
+		compatible = "arm,sbsa-gwdt";
+		reg = <0x0 0x2a440000 0 0x10000>,
+			<0x0 0x2a450000 0 0x10000>;
+		reg-names = "control",
+			"refresh";
+		interrupts = <0 27 4>;
+		interrupt-names = "ws0";
+		timeout-sec = <10 5>;
+	};
 };
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v5 2/8] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
@ 2015-06-10 13:41     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-10 13:41 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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

Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 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..962a07e 100644
--- a/arch/arm64/boot/dts/arm/foundation-v8.dts
+++ b/arch/arm64/boot/dts/arm/foundation-v8.dts
@@ -237,4 +237,14 @@
 			};
 		};
 	};
+	watchdog@2a440000 {
+		compatible = "arm,sbsa-gwdt";
+		reg = <0x0 0x2a440000 0 0x10000>,
+			<0x0 0x2a450000 0 0x10000>;
+		reg-names = "control",
+			"refresh";
+		interrupts = <0 27 4>;
+		interrupt-names = "ws0";
+		timeout-sec = <10 5>;
+	};
 };
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v5 3/8] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
@ 2015-06-10 13:41     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-10 13:41 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v5 3/8] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
@ 2015-06-10 13:41     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-10 13:41 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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

Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Acked-by: Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 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

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v5 4/8] Watchdog: introdouce "pretimeout" into framework
  2015-06-10 13:41   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                     ` (3 preceding siblings ...)
  (?)
@ 2015-06-10 13:41   ` fu.wei
  2015-06-10 16:21       ` Guenter Roeck
  -1 siblings, 1 reply; 550+ messages in thread
From: fu.wei @ 2015-06-10 13:41 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 drivers are going to use this: ARM SBSA Generic Watchdog

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 Documentation/watchdog/watchdog-kernel-api.txt |  47 ++++++++++--
 drivers/watchdog/watchdog_core.c               | 100 +++++++++++++++++--------
 drivers/watchdog/watchdog_dev.c                |  53 +++++++++++++
 include/linux/watchdog.h                       |  36 ++++++++-
 4 files changed, 197 insertions(+), 39 deletions(-)

diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index a0438f3..95b355d 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.
@@ -219,8 +236,28 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
                                   unsigned int timeout_parm, struct device *dev);
 
 The watchdog_init_timeout function allows you to initialize the timeout field
-using the module timeout parameter or by retrieving the timeout-sec property from
-the device tree (if the module timeout parameter is invalid). Best practice is
-to set the default timeout value as timeout value in the watchdog_device and
-then use this function to set the user "preferred" timeout value.
+using the module timeout parameter or by retrieving the first element of
+the timeout-sec property from the device tree (if the module timeout parameter
+is invalid). Best practice is to set the default timeout value as timeout value
+in the watchdog_device and then use this function to set the user "preferred"
+timeout value.
+This routine returns zero on success and a negative errno code for failure.
+
+Some watchdog timers have two stage of timeouts(timeout and pretimeout),
+to initialize the timeout and pretimeout fields at the same time, the following
+function can be used:
+
+extern int watchdog_init_timeouts(struct watchdog_device *wdd,
+                                  unsigned int pretimeout_parm,
+                                  unsigned int timeout_parm,
+                                  struct device *dev);
+
+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).
+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.
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index cec9b55..bdd4e43 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -43,60 +43,98 @@
 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 all to 0 (=not used or unknown)
 	 */
-	if (wdd->min_timeout > wdd->max_timeout) {
-		pr_info("Invalid min and max timeout values, resetting to 0!\n");
+	if (wdd->min_pretimeout > wdd->max_pretimeout ||
+	    wdd->min_timeout > wdd->max_timeout ||
+	    wdd->min_timeout < wdd->min_pretimeout ||
+	    wdd->max_timeout < wdd->max_pretimeout) {
+		pr_info("Invalid min and max timeouts, resetting to 0\n");
+		wdd->min_pretimeout = 0;
+		wdd->max_pretimeout = 0;
 		wdd->min_timeout = 0;
 		wdd->max_timeout = 0;
 	}
 }
 
 /**
- * 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) or
+ * the timeout-sec property (only if it is valid and the pretimeout_parm or
+ * timeout_parm is out of bounds). If none of them is 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,
+			   struct device *dev)
 {
-	unsigned int t = 0;
-	int ret = 0;
+	int ret = 0, length = 0;
+	u32 timeouts[2] = {0};
+	struct property *prop;
 
-	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;
-	}
-	if (timeout_parm)
+	/*
+	 * Try to get the pretimeout module parameter first
+	 */
+	if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm))
+		timeouts[1] = pretimeout_parm;
+	else
+		ret = -EINVAL; /* pretimeout_parm is invalid */
+
+	/*
+	 * Try to get the timeout module parameter,
+	 * if it's valid and pretimeout is valid(ret == 0),
+	 * assignment and return zero. Otherwise, try dtb.
+	 */
+	if (timeout_parm) {
+		if (!watchdog_timeout_invalid(wdd, timeout_parm) && !ret) {
+			wdd->timeout = timeout_parm;
+			wdd->pretimeout = timeouts[1];
+			return 0;
+		}
 		ret = -EINVAL;
+	}
 
-	/* try to get the timeout_sec property */
+	/*
+	 * Either at least one of the module parameters is invalid,
+	 * or timeout_parm is 0. 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
-		ret = -EINVAL;
 
-	return ret;
+	prop = of_find_property(dev->of_node, "timeout-sec", &length);
+	if (prop && length > 0 && length <= sizeof(u32) * 2) {
+		of_property_read_u32_array(dev->of_node,
+					   "timeout-sec", timeouts,
+					   length / sizeof(u32));
+		if (length == sizeof(u32) * 2 &&
+		    watchdog_pretimeout_invalid(wdd, timeouts[1]))
+				return -EINVAL;
+
+		if (!watchdog_timeout_invalid(wdd, timeouts[0]) &&
+		    timeouts[0]) {
+			wdd->timeout = timeouts[0];
+			wdd->pretimeout = timeouts[1];
+			return 0;
+		}
+	}
+
+	return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(watchdog_init_timeout);
+EXPORT_SYMBOL_GPL(watchdog_init_timeouts);
 
 /**
  * watchdog_register_device() - register a watchdog device
@@ -119,7 +157,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..af0777e 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,27 @@ 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:
+		/* check if we support the pretimeout */
+		if (!(wdd->info->options & WDIOF_PRETIMEOUT))
+			return -EOPNOTSUPP;
+		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 keeps running (and if
+		 * possible that it takes the new pretimeout)
+		 */
+		watchdog_ping(wdd);
+		/* Fall */
+	case WDIOC_GETPRETIMEOUT:
+		/* check if we support the pretimeout */
+		if (wdd->info->options & WDIOF_PRETIMEOUT)
+			return put_user(wdd->pretimeout, p);
+		return -EOPNOTSUPP;
 	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..0a7acf0 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;
@@ -117,7 +125,20 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
 static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
 {
 	return ((wdd->max_timeout != 0) &&
-		(t < wdd->min_timeout || t > wdd->max_timeout));
+		(t < wdd->min_timeout || t > wdd->max_timeout ||
+			t <= wdd->pretimeout));
+}
+
+/*
+ * Use the following function to check if a pretimeout value is invalid.
+ * It can be "0", that means we don't use pretimeout.
+ */
+static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd,
+					       unsigned int t)
+{
+	return (wdd->pretimeout != 0 && wdd->max_pretimeout != 0 &&
+		(t < wdd->min_pretimeout || t > wdd->max_pretimeout ||
+			(wdd->timeout != 0 && t >= wdd->timeout)));
 }
 
 /* Use the following functions to manipulate watchdog driver specific data */
@@ -132,11 +153,20 @@ 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);
+int watchdog_init_timeouts(struct watchdog_device *wdd,
+				  unsigned int pretimeout_parm,
+				  unsigned int timeout_parm,
+				  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, dev);
+}
+
 #ifdef CONFIG_HARDLOCKUP_DETECTOR
 void watchdog_nmi_disable_all(void);
 void watchdog_nmi_enable_all(void);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v5 5/8] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 13:41     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-10 13:41 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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, the interrupt routine run panic to save
system context.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 drivers/watchdog/Kconfig     |  11 ++
 drivers/watchdog/Makefile    |   1 +
 drivers/watchdog/sbsa_gwdt.c | 409 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 421 insertions(+)
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e5e7c55..554f18a 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -152,6 +152,17 @@ 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 ARM64
+	depends on ARM_ARCH_TIMER
+	select WATCHDOG_CORE
+	help
+	  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.
+	  More details: ARM 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..d7990b2
--- /dev/null
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -0,0 +1,409 @@
+/*
+ * SBSA(Server Base System Architecture) Generic Watchdog driver
+ *
+ * Copyright (c) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei@linaro.org>
+ *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
+ *
+ * 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: ARM DEN0029B - Server Base System Architecture (SBSA)
+ *
+ * Kernel/API:                         P---------| pretimeout
+ *               |-------------------------------T timeout
+ * SBSA GWDT:                          P--WOR---WS1 pretimeout
+ *               |-------WCV----------WS0~~~~~~~~T timeout
+ */
+
+#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>
+#include <asm/arch_timer.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		30 /* seconds, the 1st + 2nd watch periods*/
+#define DEFAULT_PRETIMEOUT	10 /* 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 pretimeout;
+module_param(pretimeout, uint, 0);
+MODULE_PARM_DESC(pretimeout,
+		 "Watchdog pretimeout in seconds. (>=0, default="
+		 __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
+
+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) ")");
+
+/*
+ * help functions for accessing 64bit WCV register
+ */
+static u64 sbsa_gwdt_get_wcv(struct watchdog_device *wdd)
+{
+	u32 wcv_lo, wcv_hi;
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	do {
+		wcv_hi = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_HI);
+		wcv_lo = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_LO);
+	} while (wcv_hi != readl_relaxed(gwdt->control_base +
+					 SBSA_GWDT_WCV_HI));
+
+	return (((u64)wcv_hi << 32) | wcv_lo);
+}
+
+static void sbsa_gwdt_set_wcv(struct watchdog_device *wdd, u64 value)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	writel_relaxed(upper_32_bits(value),
+		       gwdt->control_base + SBSA_GWDT_WCV_HI);
+	writel_relaxed(lower_32_bits(value),
+		       gwdt->control_base + SBSA_GWDT_WCV_LO);
+}
+
+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 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;
+
+	if (!pretimeout)
+		/*
+		 * If pretimeout is 0, it gives driver a timeslot(1s)
+		 * to update WCV after an explicit refresh(sbsa_gwdt_start)
+		 */
+		wor = gwdt->clk;
+	else
+		wor = pretimeout * gwdt->clk;
+
+	/* refresh the WOR, that will cause an explicit watchdog refresh */
+	writel_relaxed(wor, gwdt->control_base + SBSA_GWDT_WOR);
+
+	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_keepalive(struct watchdog_device *wdd)
+{
+	reload_timeout_to_wcv(wdd);
+
+	return 0;
+}
+
+static int sbsa_gwdt_start(struct watchdog_device *wdd)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+	/*
+	 * Writing WRR for an explicit watchdog refresh.
+	 * You can write anyting(like 0xc0ffee).
+	 * Force refresh due to hardware bug found in certain Soc.
+	 */
+	writel_relaxed(0xc0ffee, gwdt->refresh_base + SBSA_GWDT_WRR);
+	/* writing WCS will cause an explicit watchdog refresh */
+	writel_relaxed(SBSA_GWDT_WCS_EN, gwdt->control_base + SBSA_GWDT_WCS);
+
+	return sbsa_gwdt_keepalive(wdd);
+}
+
+static int sbsa_gwdt_stop(struct watchdog_device *wdd)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	writel_relaxed(0, gwdt->control_base + SBSA_GWDT_WCS);
+
+	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;
+
+	if (wdd->pretimeout)
+		/* The pretimeout is valid, go panic */
+		panic("SBSA Watchdog pre-timeout");
+	else
+		/* We don't use pretimeout, trigger WS1 now*/
+		sbsa_gwdt_set_wcv(wdd, 0);
+
+	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)
+{
+	u64 first_period_max = U64_MAX;
+	struct device *dev = &pdev->dev;
+	struct watchdog_device *wdd;
+	struct sbsa_gwdt *gwdt;
+	struct resource *res;
+	void *rf_base, *cf_base;
+	int ret, irq;
+	u32 status;
+
+	gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
+	if (!gwdt)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, gwdt);
+
+	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(cf_base))
+		return PTR_ERR(cf_base);
+
+	irq = platform_get_irq_byname(pdev, "ws0");
+	if (irq < 0) {
+		dev_err(dev, "unable to get ws0 interrupt.\n");
+		return irq;
+	}
+
+	/*
+	 * Get the frequency of system counter from the cp15 interface of ARM
+	 * Generic timer. We don't need to check it, because if it returns "0",
+	 * system would panic in very early stage.
+	 */
+	gwdt->clk = arch_timer_get_cntfrq();
+	gwdt->refresh_base = rf_base;
+	gwdt->control_base = cf_base;
+
+	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);
+
+	wdd->min_pretimeout = 0;
+	wdd->max_pretimeout = U32_MAX / gwdt->clk;
+	wdd->min_timeout = 1;
+	do_div(first_period_max, gwdt->clk);
+	wdd->max_timeout = first_period_max;
+
+	wdd->pretimeout = DEFAULT_PRETIMEOUT;
+	wdd->timeout = DEFAULT_TIMEOUT;
+	watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
+
+	status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
+	if (status & SBSA_GWDT_WCS_WS1) {
+		dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
+			 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\n");
+		sbsa_gwdt_keepalive(wdd);
+	}
+
+	/* update pretimeout to WOR */
+	sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
+
+	ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
+			       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 @ %u Hz\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);
+
+	watchdog_unregister_device(&gwdt->wdd);
+
+	return 0;
+}
+
+/* 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 <fu.wei@linaro.org>");
+MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v5 5/8] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 13:41     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-10 13:41 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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, the interrupt routine run panic to save
system context.

Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/watchdog/Kconfig     |  11 ++
 drivers/watchdog/Makefile    |   1 +
 drivers/watchdog/sbsa_gwdt.c | 409 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 421 insertions(+)
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e5e7c55..554f18a 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -152,6 +152,17 @@ 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 ARM64
+	depends on ARM_ARCH_TIMER
+	select WATCHDOG_CORE
+	help
+	  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.
+	  More details: ARM 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..d7990b2
--- /dev/null
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -0,0 +1,409 @@
+/*
+ * SBSA(Server Base System Architecture) Generic Watchdog driver
+ *
+ * Copyright (c) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
+ *         Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
+ *
+ * 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: ARM DEN0029B - Server Base System Architecture (SBSA)
+ *
+ * Kernel/API:                         P---------| pretimeout
+ *               |-------------------------------T timeout
+ * SBSA GWDT:                          P--WOR---WS1 pretimeout
+ *               |-------WCV----------WS0~~~~~~~~T timeout
+ */
+
+#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>
+#include <asm/arch_timer.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		30 /* seconds, the 1st + 2nd watch periods*/
+#define DEFAULT_PRETIMEOUT	10 /* 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 pretimeout;
+module_param(pretimeout, uint, 0);
+MODULE_PARM_DESC(pretimeout,
+		 "Watchdog pretimeout in seconds. (>=0, default="
+		 __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
+
+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) ")");
+
+/*
+ * help functions for accessing 64bit WCV register
+ */
+static u64 sbsa_gwdt_get_wcv(struct watchdog_device *wdd)
+{
+	u32 wcv_lo, wcv_hi;
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	do {
+		wcv_hi = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_HI);
+		wcv_lo = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_LO);
+	} while (wcv_hi != readl_relaxed(gwdt->control_base +
+					 SBSA_GWDT_WCV_HI));
+
+	return (((u64)wcv_hi << 32) | wcv_lo);
+}
+
+static void sbsa_gwdt_set_wcv(struct watchdog_device *wdd, u64 value)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	writel_relaxed(upper_32_bits(value),
+		       gwdt->control_base + SBSA_GWDT_WCV_HI);
+	writel_relaxed(lower_32_bits(value),
+		       gwdt->control_base + SBSA_GWDT_WCV_LO);
+}
+
+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 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;
+
+	if (!pretimeout)
+		/*
+		 * If pretimeout is 0, it gives driver a timeslot(1s)
+		 * to update WCV after an explicit refresh(sbsa_gwdt_start)
+		 */
+		wor = gwdt->clk;
+	else
+		wor = pretimeout * gwdt->clk;
+
+	/* refresh the WOR, that will cause an explicit watchdog refresh */
+	writel_relaxed(wor, gwdt->control_base + SBSA_GWDT_WOR);
+
+	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_keepalive(struct watchdog_device *wdd)
+{
+	reload_timeout_to_wcv(wdd);
+
+	return 0;
+}
+
+static int sbsa_gwdt_start(struct watchdog_device *wdd)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+	/*
+	 * Writing WRR for an explicit watchdog refresh.
+	 * You can write anyting(like 0xc0ffee).
+	 * Force refresh due to hardware bug found in certain Soc.
+	 */
+	writel_relaxed(0xc0ffee, gwdt->refresh_base + SBSA_GWDT_WRR);
+	/* writing WCS will cause an explicit watchdog refresh */
+	writel_relaxed(SBSA_GWDT_WCS_EN, gwdt->control_base + SBSA_GWDT_WCS);
+
+	return sbsa_gwdt_keepalive(wdd);
+}
+
+static int sbsa_gwdt_stop(struct watchdog_device *wdd)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	writel_relaxed(0, gwdt->control_base + SBSA_GWDT_WCS);
+
+	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;
+
+	if (wdd->pretimeout)
+		/* The pretimeout is valid, go panic */
+		panic("SBSA Watchdog pre-timeout");
+	else
+		/* We don't use pretimeout, trigger WS1 now*/
+		sbsa_gwdt_set_wcv(wdd, 0);
+
+	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)
+{
+	u64 first_period_max = U64_MAX;
+	struct device *dev = &pdev->dev;
+	struct watchdog_device *wdd;
+	struct sbsa_gwdt *gwdt;
+	struct resource *res;
+	void *rf_base, *cf_base;
+	int ret, irq;
+	u32 status;
+
+	gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
+	if (!gwdt)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, gwdt);
+
+	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(cf_base))
+		return PTR_ERR(cf_base);
+
+	irq = platform_get_irq_byname(pdev, "ws0");
+	if (irq < 0) {
+		dev_err(dev, "unable to get ws0 interrupt.\n");
+		return irq;
+	}
+
+	/*
+	 * Get the frequency of system counter from the cp15 interface of ARM
+	 * Generic timer. We don't need to check it, because if it returns "0",
+	 * system would panic in very early stage.
+	 */
+	gwdt->clk = arch_timer_get_cntfrq();
+	gwdt->refresh_base = rf_base;
+	gwdt->control_base = cf_base;
+
+	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);
+
+	wdd->min_pretimeout = 0;
+	wdd->max_pretimeout = U32_MAX / gwdt->clk;
+	wdd->min_timeout = 1;
+	do_div(first_period_max, gwdt->clk);
+	wdd->max_timeout = first_period_max;
+
+	wdd->pretimeout = DEFAULT_PRETIMEOUT;
+	wdd->timeout = DEFAULT_TIMEOUT;
+	watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
+
+	status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
+	if (status & SBSA_GWDT_WCS_WS1) {
+		dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
+			 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\n");
+		sbsa_gwdt_keepalive(wdd);
+	}
+
+	/* update pretimeout to WOR */
+	sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
+
+	ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
+			       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 @ %u Hz\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);
+
+	watchdog_unregister_device(&gwdt->wdd);
+
+	return 0;
+}
+
+/* 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 <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>");
+MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v5 6/8] ACPI: add GTDT table parse driver into ACPI driver
@ 2015-06-10 13:41     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-10 13:41 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This driver adds support for parsing SBSA Generic Watchdog
Structure in GTDT, and creating a platform device with that
information. This allows the operating system to obtain device
data from the resource of platform device.

The platform device named "sbsa-gwdt" can be used by the
ARM SBSA Generic Watchdog driver.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/acpi/Kconfig  |   9 ++++
 drivers/acpi/Makefile |   1 +
 drivers/acpi/gtdt.c   | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 147 insertions(+)
 create mode 100644 drivers/acpi/gtdt.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 1bbaa3d..e125698 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -433,4 +433,13 @@ config XPOWER_PMIC_OPREGION
 
 endif
 
+config ACPI_GTDT
+	bool "ACPI GTDT Support"
+	depends on ARM64
+	help
+	  GTDT (Generic Timer Description Table) provides information
+	  for per-processor timers and Platform (memory-mapped) timers
+	  for ARM platforms. Select this option to provide information
+	  needed for the timers init.
+
 endif	# ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 431e587..2c5a194 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -96,3 +96,4 @@ obj-$(CONFIG_ACPI_EXTLOG)	+= acpi_extlog.o
 obj-$(CONFIG_PMIC_OPREGION)	+= pmic/intel_pmic.o
 obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
 obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
+obj-$(CONFIG_ACPI_GTDT)		+= gtdt.o
diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
new file mode 100644
index 0000000..a92abf2
--- /dev/null
+++ b/drivers/acpi/gtdt.c
@@ -0,0 +1,137 @@
+/*
+ * ARM Specific GTDT table Support
+ *
+ * Copyright (C) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei@linaro.org>
+ *         Hanjun Guo <hanjun.guo@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
+{
+	int trigger, polarity;
+
+	if (!interrupt)
+		return 0;
+
+	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+			: ACPI_LEVEL_SENSITIVE;
+
+	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+			: ACPI_ACTIVE_HIGH;
+
+	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
+}
+
+/*
+ * Initialize a SBSA generic Watchdog platform device info from GTDT
+ * According to SBSA specification the size of refresh and control
+ * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
+ */
+static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
+					int index)
+{
+	struct platform_device *pdev;
+	int irq = map_generic_timer_interrupt(wd->timer_interrupt,
+					      wd->timer_flags);
+	struct resource res[] = {
+		DEFINE_RES_IRQ_NAMED(irq, "ws0"),
+		DEFINE_RES_MEM_NAMED(wd->refresh_frame_address, SZ_4K,
+				     "refresh"),
+		DEFINE_RES_MEM_NAMED(wd->control_frame_address, SZ_4K,
+				     "control"),
+	};
+
+	pr_debug("GTDT: a Watchdog GT(0x%llx/0x%llx gsi:%u flags:0x%x)\n",
+		 wd->refresh_frame_address, wd->control_frame_address,
+		 wd->timer_interrupt, wd->timer_flags);
+
+	if (!(wd->refresh_frame_address &&
+	      wd->control_frame_address &&
+	      wd->timer_interrupt)) {
+		pr_err("GTDT: failed geting the device info.\n");
+		return -EINVAL;
+	}
+
+	if (irq < 0) {
+		pr_err("GTDT: failed to register GSI of the Watchdog GT.\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Add a platform device named "sbsa-gwdt" to match the platform driver.
+	 * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
+	 * The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get device
+	 * info below by matching this name.
+	 */
+	pdev = platform_device_register_simple("sbsa-gwdt", index, res,
+					       ARRAY_SIZE(res));
+	if (IS_ERR(pdev)) {
+		acpi_unregister_gsi(wd->timer_interrupt);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
+
+static int __init gtdt_platform_timer_parse(struct acpi_table_header *table)
+{
+	struct acpi_gtdt_header *header;
+	struct acpi_table_gtdt *gtdt;
+	void *gtdt_subtable;
+	int i, gwdt_index;
+	int ret = 0;
+
+	if (table->revision < 2) {
+		pr_warn("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 = 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;
+}
+
+static int __init gtdt_platform_timer_init(void)
+{
+	if (acpi_disabled)
+		return 0;
+
+	return acpi_table_parse(ACPI_SIG_GTDT, gtdt_platform_timer_parse);
+}
+
+device_initcall(gtdt_platform_timer_init);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v5 6/8] ACPI: add GTDT table parse driver into ACPI driver
@ 2015-06-10 13:41     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-10 13:41 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

This driver adds support for parsing SBSA Generic Watchdog
Structure in GTDT, and creating a platform device with that
information. This allows the operating system to obtain device
data from the resource of platform device.

The platform device named "sbsa-gwdt" can be used by the
ARM SBSA Generic Watchdog driver.

Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/acpi/Kconfig  |   9 ++++
 drivers/acpi/Makefile |   1 +
 drivers/acpi/gtdt.c   | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 147 insertions(+)
 create mode 100644 drivers/acpi/gtdt.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 1bbaa3d..e125698 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -433,4 +433,13 @@ config XPOWER_PMIC_OPREGION
 
 endif
 
+config ACPI_GTDT
+	bool "ACPI GTDT Support"
+	depends on ARM64
+	help
+	  GTDT (Generic Timer Description Table) provides information
+	  for per-processor timers and Platform (memory-mapped) timers
+	  for ARM platforms. Select this option to provide information
+	  needed for the timers init.
+
 endif	# ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 431e587..2c5a194 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -96,3 +96,4 @@ obj-$(CONFIG_ACPI_EXTLOG)	+= acpi_extlog.o
 obj-$(CONFIG_PMIC_OPREGION)	+= pmic/intel_pmic.o
 obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
 obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
+obj-$(CONFIG_ACPI_GTDT)		+= gtdt.o
diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
new file mode 100644
index 0000000..a92abf2
--- /dev/null
+++ b/drivers/acpi/gtdt.c
@@ -0,0 +1,137 @@
+/*
+ * ARM Specific GTDT table Support
+ *
+ * Copyright (C) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
+ *         Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
+{
+	int trigger, polarity;
+
+	if (!interrupt)
+		return 0;
+
+	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+			: ACPI_LEVEL_SENSITIVE;
+
+	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+			: ACPI_ACTIVE_HIGH;
+
+	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
+}
+
+/*
+ * Initialize a SBSA generic Watchdog platform device info from GTDT
+ * According to SBSA specification the size of refresh and control
+ * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
+ */
+static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
+					int index)
+{
+	struct platform_device *pdev;
+	int irq = map_generic_timer_interrupt(wd->timer_interrupt,
+					      wd->timer_flags);
+	struct resource res[] = {
+		DEFINE_RES_IRQ_NAMED(irq, "ws0"),
+		DEFINE_RES_MEM_NAMED(wd->refresh_frame_address, SZ_4K,
+				     "refresh"),
+		DEFINE_RES_MEM_NAMED(wd->control_frame_address, SZ_4K,
+				     "control"),
+	};
+
+	pr_debug("GTDT: a Watchdog GT(0x%llx/0x%llx gsi:%u flags:0x%x)\n",
+		 wd->refresh_frame_address, wd->control_frame_address,
+		 wd->timer_interrupt, wd->timer_flags);
+
+	if (!(wd->refresh_frame_address &&
+	      wd->control_frame_address &&
+	      wd->timer_interrupt)) {
+		pr_err("GTDT: failed geting the device info.\n");
+		return -EINVAL;
+	}
+
+	if (irq < 0) {
+		pr_err("GTDT: failed to register GSI of the Watchdog GT.\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Add a platform device named "sbsa-gwdt" to match the platform driver.
+	 * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
+	 * The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get device
+	 * info below by matching this name.
+	 */
+	pdev = platform_device_register_simple("sbsa-gwdt", index, res,
+					       ARRAY_SIZE(res));
+	if (IS_ERR(pdev)) {
+		acpi_unregister_gsi(wd->timer_interrupt);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
+
+static int __init gtdt_platform_timer_parse(struct acpi_table_header *table)
+{
+	struct acpi_gtdt_header *header;
+	struct acpi_table_gtdt *gtdt;
+	void *gtdt_subtable;
+	int i, gwdt_index;
+	int ret = 0;
+
+	if (table->revision < 2) {
+		pr_warn("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 = 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;
+}
+
+static int __init gtdt_platform_timer_init(void)
+{
+	if (acpi_disabled)
+		return 0;
+
+	return acpi_table_parse(ACPI_SIG_GTDT, gtdt_platform_timer_parse);
+}
+
+device_initcall(gtdt_platform_timer_init);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v5 7/8] Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
@ 2015-06-10 13:41     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-10 13:41 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patch enables ACPI GTDT support for ARM SBSA
watchdog driver automatically, if ACPI support is enabled.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 drivers/watchdog/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 554f18a..20f9980 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -157,6 +157,7 @@ config ARM_SBSA_WATCHDOG
 	depends on ARM64
 	depends on ARM_ARCH_TIMER
 	select WATCHDOG_CORE
+	select ACPI_GTDT if ACPI
 	help
 	  ARM SBSA Generic Watchdog. This watchdog has two Watchdog timeouts.
 	  The first timeout will trigger a panic; the second timeout will
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v5 7/8] Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
@ 2015-06-10 13:41     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-10 13:41 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

This patch enables ACPI GTDT support for ARM SBSA
watchdog driver automatically, if ACPI support is enabled.

Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/watchdog/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 554f18a..20f9980 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -157,6 +157,7 @@ config ARM_SBSA_WATCHDOG
 	depends on ARM64
 	depends on ARM_ARCH_TIMER
 	select WATCHDOG_CORE
+	select ACPI_GTDT if ACPI
 	help
 	  ARM SBSA Generic Watchdog. This watchdog has two Watchdog timeouts.
 	  The first timeout will trigger a panic; the second timeout will
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v5 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
  2015-06-10 13:41   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                     ` (7 preceding siblings ...)
  (?)
@ 2015-06-10 13:41   ` fu.wei
  -1 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-10 13:41 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

The patch update arm_arch_timer driver to use the function
provided by the new GTDT driver of ACPI.
By this way, arm_arch_timer.c can be simplified, and separate
all the ACPI GTDT knowledge from this timer driver.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 arch/arm64/kernel/time.c             |  4 +--
 drivers/acpi/gtdt.c                  | 43 ++++++++++++++++++++++++++
 drivers/clocksource/Kconfig          |  1 +
 drivers/clocksource/arm_arch_timer.c | 60 +++++++-----------------------------
 include/clocksource/arm_arch_timer.h |  8 +++++
 include/linux/acpi.h                 |  5 +++
 include/linux/clocksource.h          |  4 +--
 7 files changed, 72 insertions(+), 53 deletions(-)

diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 42f9195..2cabea6 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -75,9 +75,9 @@ void __init time_init(void)
 
 	/*
 	 * Since ACPI or FDT will only one be available in the system,
-	 * we can use acpi_generic_timer_init() here safely
+	 * we can use arch_timer_acpi_init() here safely
 	 */
-	acpi_generic_timer_init();
+	arch_timer_acpi_init();
 
 	arch_timer_rate = arch_timer_get_rate();
 	if (!arch_timer_rate)
diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
index a92abf2..699c9fd 100644
--- a/drivers/acpi/gtdt.c
+++ b/drivers/acpi/gtdt.c
@@ -17,6 +17,8 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
+#include <clocksource/arm_arch_timer.h>
+
 static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 {
 	int trigger, polarity;
@@ -33,6 +35,47 @@ static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
 }
 
+struct arch_timer_data __initdata *arch_timer_data_p;
+
+static int __init arch_timer_data_init(struct acpi_table_header *table)
+{
+	struct acpi_table_gtdt *gtdt;
+
+	gtdt = container_of(table, struct acpi_table_gtdt, header);
+
+	arch_timer_data_p->phys_secure_ppi =
+		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
+					    gtdt->secure_el1_flags);
+
+	arch_timer_data_p->phys_nonsecure_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
+					    gtdt->non_secure_el1_flags);
+
+	arch_timer_data_p->virt_ppi =
+		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
+					    gtdt->virtual_timer_flags);
+
+	arch_timer_data_p->hyp_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
+					    gtdt->non_secure_el2_flags);
+
+	arch_timer_data_p->c3stop = !(gtdt->non_secure_el1_flags &
+				      ACPI_GTDT_ALWAYS_ON);
+
+	return 0;
+}
+
+/* Initialize the arch_timer_data struct for arm_arch_timer by GTDT info */
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data)
+{
+	if (acpi_disabled || !data)
+		return -EINVAL;
+
+	arch_timer_data_p = data;
+
+	return acpi_table_parse(ACPI_SIG_GTDT, arch_timer_data_init);
+}
+
 /*
  * Initialize a SBSA generic Watchdog platform device info from GTDT
  * According to SBSA specification the size of refresh and control
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 51d7865f..ea94a6f 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -109,6 +109,7 @@ config CLKSRC_EFM32
 config ARM_ARCH_TIMER
 	bool
 	select CLKSRC_OF if OF
+	select ACPI_GTDT if ACPI
 
 config ARM_ARCH_TIMER_EVTSTREAM
 	bool "Support for ARM architected timer event stream generation"
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 0aa135d..99505bb 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -817,68 +817,30 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
 		       arch_timer_mem_init);
 
 #ifdef CONFIG_ACPI
-static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
-{
-	int trigger, polarity;
-
-	if (!interrupt)
-		return 0;
-
-	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
-			: ACPI_LEVEL_SENSITIVE;
-
-	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
-			: ACPI_ACTIVE_HIGH;
-
-	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
-}
-
 /* Initialize per-processor generic timer */
-static int __init arch_timer_acpi_init(struct acpi_table_header *table)
+void __init arch_timer_acpi_init(void)
 {
-	struct acpi_table_gtdt *gtdt;
+	struct arch_timer_data data;
 
 	if (arch_timers_present & ARCH_CP15_TIMER) {
 		pr_warn("arch_timer: already initialized, skipping\n");
-		return -EINVAL;
+		return;
 	}
 
-	gtdt = container_of(table, struct acpi_table_gtdt, header);
-
 	arch_timers_present |= ARCH_CP15_TIMER;
 
-	arch_timer_ppi[PHYS_SECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
-		gtdt->secure_el1_flags);
-
-	arch_timer_ppi[PHYS_NONSECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
-		gtdt->non_secure_el1_flags);
-
-	arch_timer_ppi[VIRT_PPI] =
-		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
-		gtdt->virtual_timer_flags);
+	if (gtdt_arch_timer_data_init(&data))
+		return;
 
-	arch_timer_ppi[HYP_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
-		gtdt->non_secure_el2_flags);
+	arch_timer_ppi[PHYS_SECURE_PPI] = data.phys_secure_ppi;
+	arch_timer_ppi[PHYS_NONSECURE_PPI] = data.phys_nonsecure_ppi;
+	arch_timer_ppi[VIRT_PPI] = data.virt_ppi;
+	arch_timer_ppi[HYP_PPI] = data.hyp_ppi;
+	/* Always-on capability */
+	arch_timer_c3stop = data.c3stop;
 
 	/* Get the frequency from CNTFRQ */
 	arch_timer_detect_rate(NULL, NULL);
-
-	/* Always-on capability */
-	arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
-
 	arch_timer_init();
-	return 0;
-}
-
-/* Initialize all the generic timers presented in GTDT */
-void __init acpi_generic_timer_init(void)
-{
-	if (acpi_disabled)
-		return;
-
-	acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init);
 }
 #endif
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 9916d0e..5deed9d 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -43,6 +43,14 @@ enum arch_timer_reg {
 
 #define ARCH_TIMER_EVT_STREAM_FREQ	10000	/* 100us */
 
+struct arch_timer_data {
+	int phys_secure_ppi;
+	int phys_nonsecure_ppi;
+	int virt_ppi;
+	int hyp_ppi;
+	bool c3stop;
+};
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 598f0f1..7213c0d 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -458,6 +458,11 @@ void acpi_walk_dep_device_list(acpi_handle handle);
 struct platform_device *acpi_create_platform_device(struct acpi_device *);
 #define ACPI_PTR(_ptr)	(_ptr)
 
+#ifdef CONFIG_ACPI_GTDT
+struct arch_timer_data;
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data);
+#endif
+
 #else	/* !CONFIG_ACPI */
 
 #define acpi_disabled 1
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index d27d015..264e553 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -254,9 +254,9 @@ static inline void clocksource_of_init(void) {}
 #endif
 
 #ifdef CONFIG_ACPI
-void acpi_generic_timer_init(void);
+void arch_timer_acpi_init(void);
 #else
-static inline void acpi_generic_timer_init(void) { }
+static inline void arch_timer_acpi_init(void) { }
 #endif
 
 #endif /* _LINUX_CLOCKSOURCE_H */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 14:22                                     ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-10 14:22 UTC (permalink / raw)
  To: Fu Wei, Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

Fu Wei wrote:
> Another weakness of only using WOR is the timeout limited by this
> 32bit register.
> 10s @400MHz generic Timer
>
> I don't think this limit is good for a server, once the server is in a
> heavy load

Perhaps, but if that's the limitation of the hardware, then so be it.

-- 
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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 14:22                                     ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-10 14:22 UTC (permalink / raw)
  To: Fu Wei, Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw-LthD3rsA81gm4RdzfppkhA

Fu Wei wrote:
> Another weakness of only using WOR is the timeout limited by this
> 32bit register.
> 10s @400MHz generic Timer
>
> I don't think this limit is good for a server, once the server is in a
> heavy load

Perhaps, but if that's the limitation of the hardware, then so be it.

-- 
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.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 14:36                                       ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-10 14:36 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

On 10 June 2015 at 22:22, Timur Tabi <timur@codeaurora.org> wrote:
> Fu Wei wrote:
>>
>> Another weakness of only using WOR is the timeout limited by this
>> 32bit register.
>> 10s @400MHz generic Timer
>>
>> I don't think this limit is good for a server, once the server is in a
>> heavy load
>
>
> Perhaps, but if that's the limitation of the hardware, then so be it.

it is not the real limitation, if we use WCV, SBSA spec has mentioned that.

------ SBSA 2.3-------Page 23 ----------
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
------ SBSA 2.3-------Page 23 ----------

if some hardware doesn't support writing WCV,
that means this hardware is non-standard SBSA 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.



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 14:36                                       ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-10 14:36 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw-LthD3rsA81gm4RdzfppkhA

On 10 June 2015 at 22:22, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
> Fu Wei wrote:
>>
>> Another weakness of only using WOR is the timeout limited by this
>> 32bit register.
>> 10s @400MHz generic Timer
>>
>> I don't think this limit is good for a server, once the server is in a
>> heavy load
>
>
> Perhaps, but if that's the limitation of the hardware, then so be it.

it is not the real limitation, if we use WCV, SBSA spec has mentioned that.

------ SBSA 2.3-------Page 23 ----------
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
------ SBSA 2.3-------Page 23 ----------

if some hardware doesn't support writing WCV,
that means this hardware is non-standard SBSA 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.



-- 
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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 14:41                                         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-10 14:41 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

On 10 June 2015 at 22:36, Fu Wei <fu.wei@linaro.org> wrote:
> On 10 June 2015 at 22:22, Timur Tabi <timur@codeaurora.org> wrote:
>> Fu Wei wrote:
>>>
>>> Another weakness of only using WOR is the timeout limited by this
>>> 32bit register.
>>> 10s @400MHz generic Timer
>>>
>>> I don't think this limit is good for a server, once the server is in a
>>> heavy load
>>
>>
>> Perhaps, but if that's the limitation of the hardware, then so be it.
>
> it is not the real limitation, if we use WCV, SBSA spec has mentioned that.
>
> ------ SBSA 2.3-------Page 23 ----------
> 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
> ------ SBSA 2.3-------Page 23 ----------

------ SBSA 2.3-------Page 24 ----------
0x010 – 0x013 WCV[31:0]
0x014 – 0x017 WCV[63:32]
Watchdog compare value.
*Read/Write* registers
containing the current value in the watchdog compare
register.
------ SBSA 2.3-------Page 24 ----------

>
> if some hardware doesn't support writing WCV,
> that means this hardware is non-standard SBSA 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.
>
>
>
> --
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 14:41                                         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-10 14:41 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw-LthD3rsA81gm4RdzfppkhA

On 10 June 2015 at 22:36, Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> On 10 June 2015 at 22:22, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
>> Fu Wei wrote:
>>>
>>> Another weakness of only using WOR is the timeout limited by this
>>> 32bit register.
>>> 10s @400MHz generic Timer
>>>
>>> I don't think this limit is good for a server, once the server is in a
>>> heavy load
>>
>>
>> Perhaps, but if that's the limitation of the hardware, then so be it.
>
> it is not the real limitation, if we use WCV, SBSA spec has mentioned that.
>
> ------ SBSA 2.3-------Page 23 ----------
> 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
> ------ SBSA 2.3-------Page 23 ----------

------ SBSA 2.3-------Page 24 ----------
0x010 – 0x013 WCV[31:0]
0x014 – 0x017 WCV[63:32]
Watchdog compare value.
*Read/Write* registers
containing the current value in the watchdog compare
register.
------ SBSA 2.3-------Page 24 ----------

>
> if some hardware doesn't support writing WCV,
> that means this hardware is non-standard SBSA 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.
>
>
>
> --
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 14:41                                         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-10 14:41 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	vgandhi, wim, Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

On 10 June 2015 at 22:36, Fu Wei <fu.wei@linaro.org> wrote:
> On 10 June 2015 at 22:22, Timur Tabi <timur@codeaurora.org> wrote:
>> Fu Wei wrote:
>>>
>>> Another weakness of only using WOR is the timeout limited by this
>>> 32bit register.
>>> 10s @400MHz generic Timer
>>>
>>> I don't think this limit is good for a server, once the server is in a
>>> heavy load
>>
>>
>> Perhaps, but if that's the limitation of the hardware, then so be it.
>
> it is not the real limitation, if we use WCV, SBSA spec has mentioned that.
>
> ------ SBSA 2.3-------Page 23 ----------
> 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
> ------ SBSA 2.3-------Page 23 ----------

------ SBSA 2.3-------Page 24 ----------
0x010 – 0x013 WCV[31:0]
0x014 – 0x017 WCV[63:32]
Watchdog compare value.
*Read/Write* registers
containing the current value in the watchdog compare
register.
------ SBSA 2.3-------Page 24 ----------

>
> if some hardware doesn't support writing WCV,
> that means this hardware is non-standard SBSA 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.
>
>
>
> --
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 15:38                                   ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-10 15:38 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

Hi Guenter,


On 10 June 2015 at 11:41, Fu Wei <fu.wei@linaro.org> wrote:
> Hi Guenter,
>
> On 10 June 2015 at 00:45, Guenter Roeck <linux@roeck-us.net> wrote:
>> On 06/09/2015 09:29 AM, Timur Tabi wrote:
>>>
>>> On 06/09/2015 11:22 AM, Guenter Roeck wrote:
>>>>
>>>>
>>>>
>>>> but I see your point. Essentially, the specification is broken
>>>> for all practical purposes, since, as you point out, enabling
>>>> the watchdog overwrites and explicitly sets WCV. Effectively
>>>> this means that just using WCV to program the timeout period
>>>> is not really possible.
>>>>
>>>> I am not really sure how to address this. We can either only use WOR,
>>>> and forget about pretimeout, or we can enforce a minimum pretimeout.
>>>> In the latter case, we'll have to write WCV after writing WOR.
>>>
>>>
>>> In talking with our hardware engineers, using WCV to program the timeout
>>> period is not a valid operation.  This is why I keep arguing against the
>>> pre-timeout feature, and I don't agree that servers should always use
>>> pre-timeout.
>>>
>>
>> Not sure if "not valid" is correct - after all, it is mentioned in the
>> specification. However, it is at the very least fragile.
>
> I think we should focus on SBSA spec, but not a specific chip design,
> because this is SBSA watchdog, not a driver for an IP core from a
> specific chip vendor.
> this operation is mentioned in the spec,
> and I have tested my driver on Foundation model(from ARM) and a real hardware.
>
>>
>> I tend to agree that we should just forget about pretimeout and
>> use your original approach, where the timeout value is used
>> to program WOR. Everything else is really just asking for trouble.
>
> I don't mind if we give up pretimeout, The reason I use pretimeout is:
> this concept matches the function of two stage timeouts.
>
> but, If we give up pretimeout, could you give me a suggestion:
>
> How to config the two stage timeouts
> (1)from enabling watchdog to WS0
> (2)the time from WS1 to WS0
>
> If we only have one timeout parameter,  How to config the two stage timeouts?
> Any suggestion ?

I have another thought for this, please allow me to sent anther
patchset in a day. see if you like it.

>
> If we make the first stage timeout is timeout/2,  this violates the
> definition of timeout.
> I don't think users expect interrupt, panic or reboot at timeout/2.
>
> And WS1  definitely isn't a backup of WS0.
>
>>
>> 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



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 15:38                                   ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-10 15:38 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon,
	rjw-LthD3rsA81gm4RdzfppkhA

Hi Guenter,


On 10 June 2015 at 11:41, Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> Hi Guenter,
>
> On 10 June 2015 at 00:45, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
>> On 06/09/2015 09:29 AM, Timur Tabi wrote:
>>>
>>> On 06/09/2015 11:22 AM, Guenter Roeck wrote:
>>>>
>>>>
>>>>
>>>> but I see your point. Essentially, the specification is broken
>>>> for all practical purposes, since, as you point out, enabling
>>>> the watchdog overwrites and explicitly sets WCV. Effectively
>>>> this means that just using WCV to program the timeout period
>>>> is not really possible.
>>>>
>>>> I am not really sure how to address this. We can either only use WOR,
>>>> and forget about pretimeout, or we can enforce a minimum pretimeout.
>>>> In the latter case, we'll have to write WCV after writing WOR.
>>>
>>>
>>> In talking with our hardware engineers, using WCV to program the timeout
>>> period is not a valid operation.  This is why I keep arguing against the
>>> pre-timeout feature, and I don't agree that servers should always use
>>> pre-timeout.
>>>
>>
>> Not sure if "not valid" is correct - after all, it is mentioned in the
>> specification. However, it is at the very least fragile.
>
> I think we should focus on SBSA spec, but not a specific chip design,
> because this is SBSA watchdog, not a driver for an IP core from a
> specific chip vendor.
> this operation is mentioned in the spec,
> and I have tested my driver on Foundation model(from ARM) and a real hardware.
>
>>
>> I tend to agree that we should just forget about pretimeout and
>> use your original approach, where the timeout value is used
>> to program WOR. Everything else is really just asking for trouble.
>
> I don't mind if we give up pretimeout, The reason I use pretimeout is:
> this concept matches the function of two stage timeouts.
>
> but, If we give up pretimeout, could you give me a suggestion:
>
> How to config the two stage timeouts
> (1)from enabling watchdog to WS0
> (2)the time from WS1 to WS0
>
> If we only have one timeout parameter,  How to config the two stage timeouts?
> Any suggestion ?

I have another thought for this, please allow me to sent anther
patchset in a day. see if you like it.

>
> If we make the first stage timeout is timeout/2,  this violates the
> definition of timeout.
> I don't think users expect interrupt, panic or reboot at timeout/2.
>
> And WS1  definitely isn't a backup of WS0.
>
>>
>> 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



-- 
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
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v5 4/8] Watchdog: introdouce "pretimeout" into framework
@ 2015-06-10 16:21       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-10 16:21 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, vgandhi, wim, jcm, leo.duran, corbet,
	mark.rutland, catalin.marinas, will.deacon, rjw

On 06/10/2015 06:41 AM, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> 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 drivers are going to use this: ARM SBSA Generic Watchdog
>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>   Documentation/watchdog/watchdog-kernel-api.txt |  47 ++++++++++--
>   drivers/watchdog/watchdog_core.c               | 100 +++++++++++++++++--------
>   drivers/watchdog/watchdog_dev.c                |  53 +++++++++++++
>   include/linux/watchdog.h                       |  36 ++++++++-
>   4 files changed, 197 insertions(+), 39 deletions(-)
>
> diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
> index a0438f3..95b355d 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.
> @@ -219,8 +236,28 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
>                                     unsigned int timeout_parm, struct device *dev);
>
>   The watchdog_init_timeout function allows you to initialize the timeout field
> -using the module timeout parameter or by retrieving the timeout-sec property from
> -the device tree (if the module timeout parameter is invalid). Best practice is
> -to set the default timeout value as timeout value in the watchdog_device and
> -then use this function to set the user "preferred" timeout value.
> +using the module timeout parameter or by retrieving the first element of
> +the timeout-sec property from the device tree (if the module timeout parameter

Missing space before (.

> +is invalid). Best practice is to set the default timeout value as timeout value
> +in the watchdog_device and then use this function to set the user "preferred"
> +timeout value.
> +This routine returns zero on success and a negative errno code for failure.
> +
> +Some watchdog timers have two stage of timeouts(timeout and pretimeout),
> +to initialize the timeout and pretimeout fields at the same time, the following
> +function can be used:
> +
> +extern int watchdog_init_timeouts(struct watchdog_device *wdd,
> +                                  unsigned int pretimeout_parm,
> +                                  unsigned int timeout_parm,
> +                                  struct device *dev);
> +
> +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).

Missing spaces before (.

> +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.
> diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
> index cec9b55..bdd4e43 100644
> --- a/drivers/watchdog/watchdog_core.c
> +++ b/drivers/watchdog/watchdog_core.c
> @@ -43,60 +43,98 @@
>   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)

Please don't rename this function. This avoids conflicts with other pending
patches.

>   {
>   	/*
> -	 * 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 all to 0 (=not used or unknown)
>   	 */
> -	if (wdd->min_timeout > wdd->max_timeout) {
> -		pr_info("Invalid min and max timeout values, resetting to 0!\n");
> +	if (wdd->min_pretimeout > wdd->max_pretimeout ||
> +	    wdd->min_timeout > wdd->max_timeout ||
> +	    wdd->min_timeout < wdd->min_pretimeout ||
> +	    wdd->max_timeout < wdd->max_pretimeout) {
> +		pr_info("Invalid min and max timeouts, resetting to 0\n");

timeouts or pretimeouts.

> +		wdd->min_pretimeout = 0;
> +		wdd->max_pretimeout = 0;
>   		wdd->min_timeout = 0;
>   		wdd->max_timeout = 0;
>   	}
>   }
>
>   /**
> - * 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) or
> + * the timeout-sec property (only if it is valid and the pretimeout_parm or
> + * timeout_parm is out of bounds). If none of them is 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,
> +			   struct device *dev)
>   {
> -	unsigned int t = 0;
> -	int ret = 0;
> +	int ret = 0, length = 0;
> +	u32 timeouts[2] = {0};
> +	struct property *prop;
>
> -	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;
> -	}
> -	if (timeout_parm)
> +	/*
> +	 * Try to get the pretimeout module parameter first
> +	 */
> +	if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm))
> +		timeouts[1] = pretimeout_parm;
> +	else
> +		ret = -EINVAL; /* pretimeout_parm is invalid */
> +
If I understand the code correctly, this permits for pretimeout being specified
as module parameter and timeout as devicetree property. I don't think this
is a good idea. Use either one or the other, but not both. So this can be
simplified to

	if (watchdog_pretimeout_invalid(wdd, pretimeout_parm)
		ret = _EINVAL;

if you use pretimeout directly below.

> +	/*
> +	 * Try to get the timeout module parameter,
> +	 * if it's valid and pretimeout is valid(ret == 0),
> +	 * assignment and return zero. Otherwise, try dtb.
> +	 */
> +	if (timeout_parm) {

You can use
	if (timeout_parm && !ret) {

> +		if (!watchdog_timeout_invalid(wdd, timeout_parm) && !ret) {

instead of checking ret here.

> +			wdd->timeout = timeout_parm;
> +			wdd->pretimeout = timeouts[1];

This is really pretimeout_parm here, which should be used.
Then you don't need timeouts[1].

> +			return 0;
> +		}
>   		ret = -EINVAL;
> +	}
>

Unfortunately this does not set wdd->pretimeout if pretimeout_parm
is set but timeout_parm isn't. So I think you need

	} else if (pretimeout_parm && !ret) {
		wdd->pretimeout = pretimeout;
		return 0;
	}

However, that actually won't work as we may try to set both timeout
and pretimeout, but the current checks validate against the previous
values. I'll need to think about that.

Also, this is getting a bit complicated. Wonder if the code can be simplified.
Something else to think about.

> -	/* try to get the timeout_sec property */
> +	/*
> +	 * Either at least one of the module parameters is invalid,
> +	 * or timeout_parm is 0. 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
> -		ret = -EINVAL;
>
> -	return ret;
> +	prop = of_find_property(dev->of_node, "timeout-sec", &length);
> +	if (prop && length > 0 && length <= sizeof(u32) * 2) {
> +		of_property_read_u32_array(dev->of_node,
> +					   "timeout-sec", timeouts,
> +					   length / sizeof(u32));
> +		if (length == sizeof(u32) * 2 &&
> +		    watchdog_pretimeout_invalid(wdd, timeouts[1]))
> +				return -EINVAL;
> +
> +		if (!watchdog_timeout_invalid(wdd, timeouts[0]) &&
> +		    timeouts[0]) {
> +			wdd->timeout = timeouts[0];
> +			wdd->pretimeout = timeouts[1];

Please only set pretimeout here if specified in devicetree.

> +			return 0;
> +		}
> +	}
> +
> +	return -EINVAL;
>   }
> -EXPORT_SYMBOL_GPL(watchdog_init_timeout);
> +EXPORT_SYMBOL_GPL(watchdog_init_timeouts);
>
>   /**
>    * watchdog_register_device() - register a watchdog device
> @@ -119,7 +157,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..af0777e 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,27 @@ 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:
> +		/* check if we support the pretimeout */
> +		if (!(wdd->info->options & WDIOF_PRETIMEOUT))
> +			return -EOPNOTSUPP;
> +		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 keeps running (and if
> +		 * possible that it takes the new pretimeout)
> +		 */
> +		watchdog_ping(wdd);
> +		/* Fall */
> +	case WDIOC_GETPRETIMEOUT:
> +		/* check if we support the pretimeout */
> +		if (wdd->info->options & WDIOF_PRETIMEOUT)
> +			return put_user(wdd->pretimeout, p);
> +		return -EOPNOTSUPP;
>   	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..0a7acf0 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;
> @@ -117,7 +125,20 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
>   static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
>   {
>   	return ((wdd->max_timeout != 0) &&
> -		(t < wdd->min_timeout || t > wdd->max_timeout));
> +		(t < wdd->min_timeout || t > wdd->max_timeout ||
> +			t <= wdd->pretimeout));

pretimeout can be 0, and t needs to be evaluated against pretimeout even if
max_timeout is 0.

Try
	return (wdd->max_timeout &&
		(t < wdd->min_timeout || t > wdd->max_timeout)) ||
	       (wdd->pretimeout && t <= wdd->pretimeout);

> +}
> +
> +/*
> + * Use the following function to check if a pretimeout value is invalid.
> + * It can be "0", that means we don't use pretimeout.
> + */
> +static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd,
> +					       unsigned int t)
> +{
> +	return (wdd->pretimeout != 0 && wdd->max_pretimeout != 0 &&
> +		(t < wdd->min_pretimeout || t > wdd->max_pretimeout ||
> +			(wdd->timeout != 0 && t >= wdd->timeout)));

The check for wdd->pretimeout doesn't make much sense here, as this is the
value we are trying to set. Effectively the above accepts every pretimeout
if wdd->pretimeout is 0. It also accepts every pretimeout if
max_pretimeout == 0, even if wdd->timeout is set and t >= wdd->timeout.

Try

	return (wdd->max_pretimeout && (t < wdd->min_pretimeout ||
					t > wdd->max_pretimeout)) ||
		(wdd->timeout && t >= wdd->timeout);

>   }
>
>   /* Use the following functions to manipulate watchdog driver specific data */
> @@ -132,11 +153,20 @@ 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);
> +int watchdog_init_timeouts(struct watchdog_device *wdd,
> +				  unsigned int pretimeout_parm,
> +				  unsigned int timeout_parm,
> +				  struct device *dev);

Please align continuation lines with '('.

>   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, dev);
> +}
> +
>   #ifdef CONFIG_HARDLOCKUP_DETECTOR
>   void watchdog_nmi_disable_all(void);
>   void watchdog_nmi_enable_all(void);
>


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v5 4/8] Watchdog: introdouce "pretimeout" into framework
@ 2015-06-10 16:21       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-10 16:21 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	corbet-T1hC0tSOHrs, mark.rutland-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	rjw-LthD3rsA81gm4RdzfppkhA

On 06/10/2015 06:41 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> 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 drivers are going to use this: ARM SBSA Generic Watchdog
>
> Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>   Documentation/watchdog/watchdog-kernel-api.txt |  47 ++++++++++--
>   drivers/watchdog/watchdog_core.c               | 100 +++++++++++++++++--------
>   drivers/watchdog/watchdog_dev.c                |  53 +++++++++++++
>   include/linux/watchdog.h                       |  36 ++++++++-
>   4 files changed, 197 insertions(+), 39 deletions(-)
>
> diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
> index a0438f3..95b355d 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.
> @@ -219,8 +236,28 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
>                                     unsigned int timeout_parm, struct device *dev);
>
>   The watchdog_init_timeout function allows you to initialize the timeout field
> -using the module timeout parameter or by retrieving the timeout-sec property from
> -the device tree (if the module timeout parameter is invalid). Best practice is
> -to set the default timeout value as timeout value in the watchdog_device and
> -then use this function to set the user "preferred" timeout value.
> +using the module timeout parameter or by retrieving the first element of
> +the timeout-sec property from the device tree (if the module timeout parameter

Missing space before (.

> +is invalid). Best practice is to set the default timeout value as timeout value
> +in the watchdog_device and then use this function to set the user "preferred"
> +timeout value.
> +This routine returns zero on success and a negative errno code for failure.
> +
> +Some watchdog timers have two stage of timeouts(timeout and pretimeout),
> +to initialize the timeout and pretimeout fields at the same time, the following
> +function can be used:
> +
> +extern int watchdog_init_timeouts(struct watchdog_device *wdd,
> +                                  unsigned int pretimeout_parm,
> +                                  unsigned int timeout_parm,
> +                                  struct device *dev);
> +
> +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).

Missing spaces before (.

> +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.
> diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
> index cec9b55..bdd4e43 100644
> --- a/drivers/watchdog/watchdog_core.c
> +++ b/drivers/watchdog/watchdog_core.c
> @@ -43,60 +43,98 @@
>   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)

Please don't rename this function. This avoids conflicts with other pending
patches.

>   {
>   	/*
> -	 * 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 all to 0 (=not used or unknown)
>   	 */
> -	if (wdd->min_timeout > wdd->max_timeout) {
> -		pr_info("Invalid min and max timeout values, resetting to 0!\n");
> +	if (wdd->min_pretimeout > wdd->max_pretimeout ||
> +	    wdd->min_timeout > wdd->max_timeout ||
> +	    wdd->min_timeout < wdd->min_pretimeout ||
> +	    wdd->max_timeout < wdd->max_pretimeout) {
> +		pr_info("Invalid min and max timeouts, resetting to 0\n");

timeouts or pretimeouts.

> +		wdd->min_pretimeout = 0;
> +		wdd->max_pretimeout = 0;
>   		wdd->min_timeout = 0;
>   		wdd->max_timeout = 0;
>   	}
>   }
>
>   /**
> - * 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) or
> + * the timeout-sec property (only if it is valid and the pretimeout_parm or
> + * timeout_parm is out of bounds). If none of them is 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,
> +			   struct device *dev)
>   {
> -	unsigned int t = 0;
> -	int ret = 0;
> +	int ret = 0, length = 0;
> +	u32 timeouts[2] = {0};
> +	struct property *prop;
>
> -	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;
> -	}
> -	if (timeout_parm)
> +	/*
> +	 * Try to get the pretimeout module parameter first
> +	 */
> +	if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm))
> +		timeouts[1] = pretimeout_parm;
> +	else
> +		ret = -EINVAL; /* pretimeout_parm is invalid */
> +
If I understand the code correctly, this permits for pretimeout being specified
as module parameter and timeout as devicetree property. I don't think this
is a good idea. Use either one or the other, but not both. So this can be
simplified to

	if (watchdog_pretimeout_invalid(wdd, pretimeout_parm)
		ret = _EINVAL;

if you use pretimeout directly below.

> +	/*
> +	 * Try to get the timeout module parameter,
> +	 * if it's valid and pretimeout is valid(ret == 0),
> +	 * assignment and return zero. Otherwise, try dtb.
> +	 */
> +	if (timeout_parm) {

You can use
	if (timeout_parm && !ret) {

> +		if (!watchdog_timeout_invalid(wdd, timeout_parm) && !ret) {

instead of checking ret here.

> +			wdd->timeout = timeout_parm;
> +			wdd->pretimeout = timeouts[1];

This is really pretimeout_parm here, which should be used.
Then you don't need timeouts[1].

> +			return 0;
> +		}
>   		ret = -EINVAL;
> +	}
>

Unfortunately this does not set wdd->pretimeout if pretimeout_parm
is set but timeout_parm isn't. So I think you need

	} else if (pretimeout_parm && !ret) {
		wdd->pretimeout = pretimeout;
		return 0;
	}

However, that actually won't work as we may try to set both timeout
and pretimeout, but the current checks validate against the previous
values. I'll need to think about that.

Also, this is getting a bit complicated. Wonder if the code can be simplified.
Something else to think about.

> -	/* try to get the timeout_sec property */
> +	/*
> +	 * Either at least one of the module parameters is invalid,
> +	 * or timeout_parm is 0. 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
> -		ret = -EINVAL;
>
> -	return ret;
> +	prop = of_find_property(dev->of_node, "timeout-sec", &length);
> +	if (prop && length > 0 && length <= sizeof(u32) * 2) {
> +		of_property_read_u32_array(dev->of_node,
> +					   "timeout-sec", timeouts,
> +					   length / sizeof(u32));
> +		if (length == sizeof(u32) * 2 &&
> +		    watchdog_pretimeout_invalid(wdd, timeouts[1]))
> +				return -EINVAL;
> +
> +		if (!watchdog_timeout_invalid(wdd, timeouts[0]) &&
> +		    timeouts[0]) {
> +			wdd->timeout = timeouts[0];
> +			wdd->pretimeout = timeouts[1];

Please only set pretimeout here if specified in devicetree.

> +			return 0;
> +		}
> +	}
> +
> +	return -EINVAL;
>   }
> -EXPORT_SYMBOL_GPL(watchdog_init_timeout);
> +EXPORT_SYMBOL_GPL(watchdog_init_timeouts);
>
>   /**
>    * watchdog_register_device() - register a watchdog device
> @@ -119,7 +157,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..af0777e 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,27 @@ 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:
> +		/* check if we support the pretimeout */
> +		if (!(wdd->info->options & WDIOF_PRETIMEOUT))
> +			return -EOPNOTSUPP;
> +		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 keeps running (and if
> +		 * possible that it takes the new pretimeout)
> +		 */
> +		watchdog_ping(wdd);
> +		/* Fall */
> +	case WDIOC_GETPRETIMEOUT:
> +		/* check if we support the pretimeout */
> +		if (wdd->info->options & WDIOF_PRETIMEOUT)
> +			return put_user(wdd->pretimeout, p);
> +		return -EOPNOTSUPP;
>   	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..0a7acf0 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;
> @@ -117,7 +125,20 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
>   static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
>   {
>   	return ((wdd->max_timeout != 0) &&
> -		(t < wdd->min_timeout || t > wdd->max_timeout));
> +		(t < wdd->min_timeout || t > wdd->max_timeout ||
> +			t <= wdd->pretimeout));

pretimeout can be 0, and t needs to be evaluated against pretimeout even if
max_timeout is 0.

Try
	return (wdd->max_timeout &&
		(t < wdd->min_timeout || t > wdd->max_timeout)) ||
	       (wdd->pretimeout && t <= wdd->pretimeout);

> +}
> +
> +/*
> + * Use the following function to check if a pretimeout value is invalid.
> + * It can be "0", that means we don't use pretimeout.
> + */
> +static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd,
> +					       unsigned int t)
> +{
> +	return (wdd->pretimeout != 0 && wdd->max_pretimeout != 0 &&
> +		(t < wdd->min_pretimeout || t > wdd->max_pretimeout ||
> +			(wdd->timeout != 0 && t >= wdd->timeout)));

The check for wdd->pretimeout doesn't make much sense here, as this is the
value we are trying to set. Effectively the above accepts every pretimeout
if wdd->pretimeout is 0. It also accepts every pretimeout if
max_pretimeout == 0, even if wdd->timeout is set and t >= wdd->timeout.

Try

	return (wdd->max_pretimeout && (t < wdd->min_pretimeout ||
					t > wdd->max_pretimeout)) ||
		(wdd->timeout && t >= wdd->timeout);

>   }
>
>   /* Use the following functions to manipulate watchdog driver specific data */
> @@ -132,11 +153,20 @@ 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);
> +int watchdog_init_timeouts(struct watchdog_device *wdd,
> +				  unsigned int pretimeout_parm,
> +				  unsigned int timeout_parm,
> +				  struct device *dev);

Please align continuation lines with '('.

>   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, dev);
> +}
> +
>   #ifdef CONFIG_HARDLOCKUP_DETECTOR
>   void watchdog_nmi_disable_all(void);
>   void watchdog_nmi_enable_all(void);
>

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH non-pretimeout 0/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 17:47   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-10 17:47 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patchset:
    (1)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.

    (2)Introduce ACPI GTDT parser: drivers/acpi/gtdt.c
    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.
    drivers/clocksource/arm_arch_timer.c is simplified by this GTDT support.

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

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

Changelog:
non_pretimeout: Delete all pretimeout code
                The time from enabling watchdog to WS0 is the same with
		the time from WS0 to WS1, they are both timeout value.

v5: Improve pretimeout support:
        (1)fix typo in documentation and comments.
	(2)fix the timeout limits validation bug.
    Simplify sbsa_gwdt driver:
	(1)integrate all the registers access functions into caller.

v4: Refactor GTDT support code: remove it from arch/arm64/kernel/acpi.c,
    put it into drivers/acpi/gtdt.c file.
    Integrate the GTDT code of drivers/clocksource/arm_arch_timer.c into
    drivers/acpi/gtdt.c.
    Improve pretimeout support, fix "pretimeout == 0" problem.
    Simplify sbsa_gwdt driver:
        (1)timeout/pretimeout limits setup;
        (2)keepalive function;
        (3)delete "clk == 0" check;
        (4)delete WS0 status bit check in interrupt routine;
        (5)sbsa_gwdt_set_wcv function.

v3: Delete "export arch_timer_get_rate" patch.
    Driver back to use arch_timer_get_cntfrq.
    Improve watchdog_init_timeouts function and update relevant documentation.
    Improve watchdog_timeout_invalid and watchdog_pretimeout_invalid.
    Improve foundation-v8.dts: delete the unnecessary tag of device node.
    Remove "ARM64 || COMPILE_TEST" from Kconfig.
    Add comments in arch/arm64/kernel/acpi.c
    Fix typoes and incorrect comments.

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):
  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 ARM SBSA watchdog driver
  ACPI: add GTDT table parse driver into ACPI driver
  Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
  clocksource: simplify ACPI code in arm_arch_timer.c

 .../devicetree/bindings/watchdog/sbsa-gwdt.txt     |  35 ++
 arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi       |  11 +
 arch/arm64/boot/dts/arm/foundation-v8.dts          |  10 +
 arch/arm64/kernel/time.c                           |   4 +-
 drivers/acpi/Kconfig                               |   9 +
 drivers/acpi/Makefile                              |   1 +
 drivers/acpi/gtdt.c                                | 180 ++++++++++
 drivers/clocksource/Kconfig                        |   1 +
 drivers/clocksource/arm_arch_timer.c               |  60 +---
 drivers/watchdog/Kconfig                           |  12 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/sbsa_gwdt.c                       | 383 +++++++++++++++++++++
 include/clocksource/arm_arch_timer.h               |   8 +
 include/linux/acpi.h                               |   5 +
 include/linux/clocksource.h                        |   4 +-
 15 files changed, 671 insertions(+), 53 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
 create mode 100644 drivers/acpi/gtdt.c
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

-- 
1.9.1


^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH non-pretimeout 0/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 17:47   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-10 17:47 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

This patchset:
    (1)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.

    (2)Introduce ACPI GTDT parser: drivers/acpi/gtdt.c
    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.
    drivers/clocksource/arm_arch_timer.c is simplified by this GTDT support.

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

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

Changelog:
non_pretimeout: Delete all pretimeout code
                The time from enabling watchdog to WS0 is the same with
		the time from WS0 to WS1, they are both timeout value.

v5: Improve pretimeout support:
        (1)fix typo in documentation and comments.
	(2)fix the timeout limits validation bug.
    Simplify sbsa_gwdt driver:
	(1)integrate all the registers access functions into caller.

v4: Refactor GTDT support code: remove it from arch/arm64/kernel/acpi.c,
    put it into drivers/acpi/gtdt.c file.
    Integrate the GTDT code of drivers/clocksource/arm_arch_timer.c into
    drivers/acpi/gtdt.c.
    Improve pretimeout support, fix "pretimeout == 0" problem.
    Simplify sbsa_gwdt driver:
        (1)timeout/pretimeout limits setup;
        (2)keepalive function;
        (3)delete "clk == 0" check;
        (4)delete WS0 status bit check in interrupt routine;
        (5)sbsa_gwdt_set_wcv function.

v3: Delete "export arch_timer_get_rate" patch.
    Driver back to use arch_timer_get_cntfrq.
    Improve watchdog_init_timeouts function and update relevant documentation.
    Improve watchdog_timeout_invalid and watchdog_pretimeout_invalid.
    Improve foundation-v8.dts: delete the unnecessary tag of device node.
    Remove "ARM64 || COMPILE_TEST" from Kconfig.
    Add comments in arch/arm64/kernel/acpi.c
    Fix typoes and incorrect comments.

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):
  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 ARM SBSA watchdog driver
  ACPI: add GTDT table parse driver into ACPI driver
  Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
  clocksource: simplify ACPI code in arm_arch_timer.c

 .../devicetree/bindings/watchdog/sbsa-gwdt.txt     |  35 ++
 arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi       |  11 +
 arch/arm64/boot/dts/arm/foundation-v8.dts          |  10 +
 arch/arm64/kernel/time.c                           |   4 +-
 drivers/acpi/Kconfig                               |   9 +
 drivers/acpi/Makefile                              |   1 +
 drivers/acpi/gtdt.c                                | 180 ++++++++++
 drivers/clocksource/Kconfig                        |   1 +
 drivers/clocksource/arm_arch_timer.c               |  60 +---
 drivers/watchdog/Kconfig                           |  12 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/sbsa_gwdt.c                       | 383 +++++++++++++++++++++
 include/clocksource/arm_arch_timer.h               |   8 +
 include/linux/acpi.h                               |   5 +
 include/linux/clocksource.h                        |   4 +-
 15 files changed, 671 insertions(+), 53 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
 create mode 100644 drivers/acpi/gtdt.c
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH non-pretimeout 1/7] Documentation: add sbsa-gwdt.txt documentation
@ 2015-06-10 17:47     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-10 17:47 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 .../devicetree/bindings/watchdog/sbsa-gwdt.txt     | 35 ++++++++++++++++++++++
 1 file changed, 35 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..164ee98
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
@@ -0,0 +1,35 @@
+* 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 timeout value (in seconds).
+
+Example for FVP Foundation Model v8:
+
+watchdog@2a440000 {
+	compatible = "arm,sbsa-gwdt";
+	reg = <0x0 0x2a440000 0 0x10000>,
+	      <0x0 0x2a450000 0 0x10000>;
+	reg-names = "control", "refresh";
+	interrupts = <0 27 4>;
+	interrupt-names = "ws0";
+	timeout-sec = <10>;
+};
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH non-pretimeout 1/7] Documentation: add sbsa-gwdt.txt documentation
@ 2015-06-10 17:47     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-10 17:47 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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

Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 .../devicetree/bindings/watchdog/sbsa-gwdt.txt     | 35 ++++++++++++++++++++++
 1 file changed, 35 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..164ee98
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
@@ -0,0 +1,35 @@
+* 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 timeout value (in seconds).
+
+Example for FVP Foundation Model v8:
+
+watchdog@2a440000 {
+	compatible = "arm,sbsa-gwdt";
+	reg = <0x0 0x2a440000 0 0x10000>,
+	      <0x0 0x2a450000 0 0x10000>;
+	reg-names = "control", "refresh";
+	interrupts = <0 27 4>;
+	interrupt-names = "ws0";
+	timeout-sec = <10>;
+};
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH non-pretimeout 2/7] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
  2015-06-10 17:47   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  (?)
  (?)
@ 2015-06-10 17:47   ` fu.wei
  -1 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-10 17:47 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 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..dfc799e 100644
--- a/arch/arm64/boot/dts/arm/foundation-v8.dts
+++ b/arch/arm64/boot/dts/arm/foundation-v8.dts
@@ -237,4 +237,14 @@
 			};
 		};
 	};
+	watchdog@2a440000 {
+		compatible = "arm,sbsa-gwdt";
+		reg = <0x0 0x2a440000 0 0x10000>,
+			<0x0 0x2a450000 0 0x10000>;
+		reg-names = "control",
+			"refresh";
+		interrupts = <0 27 4>;
+		interrupt-names = "ws0";
+		timeout-sec = <10>;
+	};
 };
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH non-pretimeout 3/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
@ 2015-06-10 17:47     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-10 17:47 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 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..3fc2746 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>;
+		};
+
 		spi0: ssp@e1020000 {
 			status = "disabled";
 			compatible = "arm,pl022", "arm,primecell";
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH non-pretimeout 3/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
@ 2015-06-10 17:47     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-10 17:47 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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

Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Acked-by: Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 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..3fc2746 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>;
+		};
+
 		spi0: ssp@e1020000 {
 			status = "disabled";
 			compatible = "arm,pl022", "arm,primecell";
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH non-pretimeout 4/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-10 17:47   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                     ` (3 preceding siblings ...)
  (?)
@ 2015-06-10 17:47   ` fu.wei
  2015-06-11  5:33       ` Guenter Roeck
                       ` (2 more replies)
  -1 siblings, 3 replies; 550+ messages in thread
From: fu.wei @ 2015-06-10 17:47 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This driver bases on linux kernel watchdog framework.
It supports getting timeout from parameter and FDT
at the driver init stage.
The first timeout period expires, the interrupt routine
got another timeout period to run panic for saving
system context.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 drivers/watchdog/Kconfig     |  11 ++
 drivers/watchdog/Makefile    |   1 +
 drivers/watchdog/sbsa_gwdt.c | 383 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 395 insertions(+)
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e5e7c55..554f18a 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -152,6 +152,17 @@ 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 ARM64
+	depends on ARM_ARCH_TIMER
+	select WATCHDOG_CORE
+	help
+	  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.
+	  More details: ARM 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..1ddc10f
--- /dev/null
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -0,0 +1,383 @@
+/*
+ * SBSA(Server Base System Architecture) Generic Watchdog driver
+ *
+ * Copyright (c) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei@linaro.org>
+ *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
+ *
+ * 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 has two stage timeouts,
+ *       When the first timeout occurs, WS0(SPI or LPI) is triggered,
+ *       the second timeout period(as long as the first timeout period) starts.
+ *       In WS0 interrupt routine, panic() will be called for collecting
+ *       crashdown info.
+ *       If system can not recover from WS0 interrupt routine, then second
+ *       timeout occurs, WS1(reset or higher level interrupt) is triggered.
+ *       The two timeout period can be set by WOR(32bit).
+ *       WOR gives a maximum watch period of around 10s at the maximum
+ *       system counter frequency.
+ *       The System Counter shall run at maximum of 400MHz.
+ *
+ *       But If we need a larger timeout period, this driver will programme WCV
+ *       directly. That can support more than 10s timeout at the maximum
+ *       system counter frequency.
+ *       More details: ARM DEN0029B - Server Base System Architecture (SBSA)
+ *
+ * SBSA GWDT:    |---WOR(or WCV)---WS0---WOR(or WCV)---WS1
+ *               |-----timeout-----WS0-----timeout-----WS1
+ */
+
+#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>
+#include <asm/arch_timer.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.
+ * @max_wor_timeout:	the maximum timeout value for WOR (in seconds).
+ * @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;
+	int			max_wor_timeout;
+	void __iomem		*refresh_base;
+	void __iomem		*control_base;
+};
+
+#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
+
+#define DEFAULT_TIMEOUT		30 /* seconds */
+
+static unsigned int timeout;
+module_param(timeout, uint, 0);
+MODULE_PARM_DESC(timeout,
+		 "Watchdog timeout in seconds. (>=0, default="
+		 __MODULE_STRING(DEFAULT_TIMEOUT) ")");
+
+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) ")");
+
+/*
+ * help functions for accessing 64bit WCV register
+ */
+static u64 sbsa_gwdt_get_wcv(struct watchdog_device *wdd)
+{
+	u32 wcv_lo, wcv_hi;
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	do {
+		wcv_hi = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_HI);
+		wcv_lo = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_LO);
+	} while (wcv_hi != readl_relaxed(gwdt->control_base +
+					 SBSA_GWDT_WCV_HI));
+
+	return (((u64)wcv_hi << 32) | wcv_lo);
+}
+
+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 * gwdt->clk;
+
+	writel_relaxed(upper_32_bits(wcv),
+		       gwdt->control_base + SBSA_GWDT_WCV_HI);
+	writel_relaxed(lower_32_bits(wcv),
+		       gwdt->control_base + SBSA_GWDT_WCV_LO);
+}
+
+static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
+				 unsigned int timeout)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	wdd->timeout = timeout;
+
+	if (timeout <= gwdt->max_wor_timeout)
+		writel_relaxed(timeout * gwdt->clk,
+			       gwdt->control_base + SBSA_GWDT_WOR);
+	else
+		writel_relaxed(gwdt->max_wor_timeout * gwdt->clk,
+			       gwdt->control_base + SBSA_GWDT_WOR);
+
+	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_keepalive(struct watchdog_device *wdd)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	if (wdd->timeout <= gwdt->max_wor_timeout)
+		/*
+		 * Writing WRR for an explicit watchdog refresh.
+		 * You can write anyting(like 0xc0ffee).
+		 */
+		writel_relaxed(0xc0ffee, gwdt->refresh_base + SBSA_GWDT_WRR);
+	else
+		reload_timeout_to_wcv(wdd);
+
+	return 0;
+}
+
+static int sbsa_gwdt_start(struct watchdog_device *wdd)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+	/* Force refresh due to hardware bug found in certain Soc. */
+	writel_relaxed(0xc0ffee, gwdt->refresh_base + SBSA_GWDT_WRR);
+	/* writing WCS will cause an explicit watchdog refresh */
+	writel_relaxed(SBSA_GWDT_WCS_EN, gwdt->control_base + SBSA_GWDT_WCS);
+
+	return sbsa_gwdt_keepalive(wdd);
+}
+
+static int sbsa_gwdt_stop(struct watchdog_device *wdd)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	writel_relaxed(0, gwdt->control_base + SBSA_GWDT_WCS);
+
+	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;
+
+	if (wdd->timeout > gwdt->max_wor_timeout)
+		reload_timeout_to_wcv(wdd);
+
+	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_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,
+	.get_timeleft	= sbsa_gwdt_get_timeleft,
+};
+
+static int sbsa_gwdt_probe(struct platform_device *pdev)
+{
+	u64 first_period_max = U64_MAX;
+	struct device *dev = &pdev->dev;
+	struct watchdog_device *wdd;
+	struct sbsa_gwdt *gwdt;
+	struct resource *res;
+	void *rf_base, *cf_base;
+	int ret, irq;
+	u32 status;
+
+	gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
+	if (!gwdt)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, gwdt);
+
+	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(cf_base))
+		return PTR_ERR(cf_base);
+
+	irq = platform_get_irq_byname(pdev, "ws0");
+	if (irq < 0) {
+		dev_err(dev, "unable to get ws0 interrupt.\n");
+		return irq;
+	}
+
+	/*
+	 * Get the frequency of system counter from the cp15 interface of ARM
+	 * Generic timer. We don't need to check it, because if it returns "0",
+	 * system would panic in very early stage.
+	 */
+	gwdt->clk = arch_timer_get_cntfrq();
+	gwdt->refresh_base = rf_base;
+	gwdt->control_base = cf_base;
+	gwdt->max_wor_timeout = U32_MAX / gwdt->clk;
+
+	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);
+
+	wdd->min_timeout = 1;
+	do_div(first_period_max, gwdt->clk);
+	wdd->max_timeout = first_period_max;
+
+	wdd->timeout = DEFAULT_TIMEOUT;
+	watchdog_init_timeout(wdd, timeout, dev);
+
+	status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
+	if (status & SBSA_GWDT_WCS_WS1) {
+		dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
+			 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\n");
+		sbsa_gwdt_keepalive(wdd);
+	}
+
+	/* update timeout to WOR */
+	sbsa_gwdt_set_timeout(wdd, wdd->timeout);
+
+	ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
+			       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 @ %u Hz\n", wdd->timeout,
+		 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);
+
+	watchdog_unregister_device(&gwdt->wdd);
+
+	return 0;
+}
+
+/* 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 <fu.wei@linaro.org>");
+MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH non-pretimeout 5/7] ACPI: add GTDT table parse driver into ACPI driver
  2015-06-10 17:47   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                     ` (4 preceding siblings ...)
  (?)
@ 2015-06-10 17:47   ` fu.wei
  2015-06-11 11:14     ` Hanjun Guo
  -1 siblings, 1 reply; 550+ messages in thread
From: fu.wei @ 2015-06-10 17:47 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This driver adds support for parsing SBSA Generic Watchdog
Structure in GTDT, and creating a platform device with that
information. This allows the operating system to obtain device
data from the resource of platform device.

The platform device named "sbsa-gwdt" can be used by the
ARM SBSA Generic Watchdog driver.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/acpi/Kconfig  |   9 ++++
 drivers/acpi/Makefile |   1 +
 drivers/acpi/gtdt.c   | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 147 insertions(+)
 create mode 100644 drivers/acpi/gtdt.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 1bbaa3d..e125698 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -433,4 +433,13 @@ config XPOWER_PMIC_OPREGION
 
 endif
 
+config ACPI_GTDT
+	bool "ACPI GTDT Support"
+	depends on ARM64
+	help
+	  GTDT (Generic Timer Description Table) provides information
+	  for per-processor timers and Platform (memory-mapped) timers
+	  for ARM platforms. Select this option to provide information
+	  needed for the timers init.
+
 endif	# ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 431e587..2c5a194 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -96,3 +96,4 @@ obj-$(CONFIG_ACPI_EXTLOG)	+= acpi_extlog.o
 obj-$(CONFIG_PMIC_OPREGION)	+= pmic/intel_pmic.o
 obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
 obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
+obj-$(CONFIG_ACPI_GTDT)		+= gtdt.o
diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
new file mode 100644
index 0000000..a92abf2
--- /dev/null
+++ b/drivers/acpi/gtdt.c
@@ -0,0 +1,137 @@
+/*
+ * ARM Specific GTDT table Support
+ *
+ * Copyright (C) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei@linaro.org>
+ *         Hanjun Guo <hanjun.guo@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
+{
+	int trigger, polarity;
+
+	if (!interrupt)
+		return 0;
+
+	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+			: ACPI_LEVEL_SENSITIVE;
+
+	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+			: ACPI_ACTIVE_HIGH;
+
+	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
+}
+
+/*
+ * Initialize a SBSA generic Watchdog platform device info from GTDT
+ * According to SBSA specification the size of refresh and control
+ * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
+ */
+static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
+					int index)
+{
+	struct platform_device *pdev;
+	int irq = map_generic_timer_interrupt(wd->timer_interrupt,
+					      wd->timer_flags);
+	struct resource res[] = {
+		DEFINE_RES_IRQ_NAMED(irq, "ws0"),
+		DEFINE_RES_MEM_NAMED(wd->refresh_frame_address, SZ_4K,
+				     "refresh"),
+		DEFINE_RES_MEM_NAMED(wd->control_frame_address, SZ_4K,
+				     "control"),
+	};
+
+	pr_debug("GTDT: a Watchdog GT(0x%llx/0x%llx gsi:%u flags:0x%x)\n",
+		 wd->refresh_frame_address, wd->control_frame_address,
+		 wd->timer_interrupt, wd->timer_flags);
+
+	if (!(wd->refresh_frame_address &&
+	      wd->control_frame_address &&
+	      wd->timer_interrupt)) {
+		pr_err("GTDT: failed geting the device info.\n");
+		return -EINVAL;
+	}
+
+	if (irq < 0) {
+		pr_err("GTDT: failed to register GSI of the Watchdog GT.\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Add a platform device named "sbsa-gwdt" to match the platform driver.
+	 * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
+	 * The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get device
+	 * info below by matching this name.
+	 */
+	pdev = platform_device_register_simple("sbsa-gwdt", index, res,
+					       ARRAY_SIZE(res));
+	if (IS_ERR(pdev)) {
+		acpi_unregister_gsi(wd->timer_interrupt);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
+
+static int __init gtdt_platform_timer_parse(struct acpi_table_header *table)
+{
+	struct acpi_gtdt_header *header;
+	struct acpi_table_gtdt *gtdt;
+	void *gtdt_subtable;
+	int i, gwdt_index;
+	int ret = 0;
+
+	if (table->revision < 2) {
+		pr_warn("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 = 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;
+}
+
+static int __init gtdt_platform_timer_init(void)
+{
+	if (acpi_disabled)
+		return 0;
+
+	return acpi_table_parse(ACPI_SIG_GTDT, gtdt_platform_timer_parse);
+}
+
+device_initcall(gtdt_platform_timer_init);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH non-pretimeout 6/7] Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
@ 2015-06-10 17:47     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-10 17:47 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patch enables ACPI GTDT support for ARM SBSA
watchdog driver automatically, if ACPI support is enabled.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 drivers/watchdog/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 554f18a..20f9980 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -157,6 +157,7 @@ config ARM_SBSA_WATCHDOG
 	depends on ARM64
 	depends on ARM_ARCH_TIMER
 	select WATCHDOG_CORE
+	select ACPI_GTDT if ACPI
 	help
 	  ARM SBSA Generic Watchdog. This watchdog has two Watchdog timeouts.
 	  The first timeout will trigger a panic; the second timeout will
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH non-pretimeout 6/7] Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
@ 2015-06-10 17:47     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-10 17:47 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

This patch enables ACPI GTDT support for ARM SBSA
watchdog driver automatically, if ACPI support is enabled.

Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/watchdog/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 554f18a..20f9980 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -157,6 +157,7 @@ config ARM_SBSA_WATCHDOG
 	depends on ARM64
 	depends on ARM_ARCH_TIMER
 	select WATCHDOG_CORE
+	select ACPI_GTDT if ACPI
 	help
 	  ARM SBSA Generic Watchdog. This watchdog has two Watchdog timeouts.
 	  The first timeout will trigger a panic; the second timeout will
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH non-pretimeout 7/7] clocksource: simplify ACPI code in arm_arch_timer.c
@ 2015-06-10 17:47     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-10 17:47 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

The patch update arm_arch_timer driver to use the function
provided by the new GTDT driver of ACPI.
By this way, arm_arch_timer.c can be simplified, and separate
all the ACPI GTDT knowledge from this timer driver.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 arch/arm64/kernel/time.c             |  4 +--
 drivers/acpi/gtdt.c                  | 43 ++++++++++++++++++++++++++
 drivers/clocksource/Kconfig          |  1 +
 drivers/clocksource/arm_arch_timer.c | 60 +++++++-----------------------------
 include/clocksource/arm_arch_timer.h |  8 +++++
 include/linux/acpi.h                 |  5 +++
 include/linux/clocksource.h          |  4 +--
 7 files changed, 72 insertions(+), 53 deletions(-)

diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 42f9195..2cabea6 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -75,9 +75,9 @@ void __init time_init(void)
 
 	/*
 	 * Since ACPI or FDT will only one be available in the system,
-	 * we can use acpi_generic_timer_init() here safely
+	 * we can use arch_timer_acpi_init() here safely
 	 */
-	acpi_generic_timer_init();
+	arch_timer_acpi_init();
 
 	arch_timer_rate = arch_timer_get_rate();
 	if (!arch_timer_rate)
diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
index a92abf2..699c9fd 100644
--- a/drivers/acpi/gtdt.c
+++ b/drivers/acpi/gtdt.c
@@ -17,6 +17,8 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
+#include <clocksource/arm_arch_timer.h>
+
 static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 {
 	int trigger, polarity;
@@ -33,6 +35,47 @@ static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
 }
 
+struct arch_timer_data __initdata *arch_timer_data_p;
+
+static int __init arch_timer_data_init(struct acpi_table_header *table)
+{
+	struct acpi_table_gtdt *gtdt;
+
+	gtdt = container_of(table, struct acpi_table_gtdt, header);
+
+	arch_timer_data_p->phys_secure_ppi =
+		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
+					    gtdt->secure_el1_flags);
+
+	arch_timer_data_p->phys_nonsecure_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
+					    gtdt->non_secure_el1_flags);
+
+	arch_timer_data_p->virt_ppi =
+		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
+					    gtdt->virtual_timer_flags);
+
+	arch_timer_data_p->hyp_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
+					    gtdt->non_secure_el2_flags);
+
+	arch_timer_data_p->c3stop = !(gtdt->non_secure_el1_flags &
+				      ACPI_GTDT_ALWAYS_ON);
+
+	return 0;
+}
+
+/* Initialize the arch_timer_data struct for arm_arch_timer by GTDT info */
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data)
+{
+	if (acpi_disabled || !data)
+		return -EINVAL;
+
+	arch_timer_data_p = data;
+
+	return acpi_table_parse(ACPI_SIG_GTDT, arch_timer_data_init);
+}
+
 /*
  * Initialize a SBSA generic Watchdog platform device info from GTDT
  * According to SBSA specification the size of refresh and control
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 51d7865f..ea94a6f 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -109,6 +109,7 @@ config CLKSRC_EFM32
 config ARM_ARCH_TIMER
 	bool
 	select CLKSRC_OF if OF
+	select ACPI_GTDT if ACPI
 
 config ARM_ARCH_TIMER_EVTSTREAM
 	bool "Support for ARM architected timer event stream generation"
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 0aa135d..99505bb 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -817,68 +817,30 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
 		       arch_timer_mem_init);
 
 #ifdef CONFIG_ACPI
-static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
-{
-	int trigger, polarity;
-
-	if (!interrupt)
-		return 0;
-
-	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
-			: ACPI_LEVEL_SENSITIVE;
-
-	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
-			: ACPI_ACTIVE_HIGH;
-
-	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
-}
-
 /* Initialize per-processor generic timer */
-static int __init arch_timer_acpi_init(struct acpi_table_header *table)
+void __init arch_timer_acpi_init(void)
 {
-	struct acpi_table_gtdt *gtdt;
+	struct arch_timer_data data;
 
 	if (arch_timers_present & ARCH_CP15_TIMER) {
 		pr_warn("arch_timer: already initialized, skipping\n");
-		return -EINVAL;
+		return;
 	}
 
-	gtdt = container_of(table, struct acpi_table_gtdt, header);
-
 	arch_timers_present |= ARCH_CP15_TIMER;
 
-	arch_timer_ppi[PHYS_SECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
-		gtdt->secure_el1_flags);
-
-	arch_timer_ppi[PHYS_NONSECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
-		gtdt->non_secure_el1_flags);
-
-	arch_timer_ppi[VIRT_PPI] =
-		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
-		gtdt->virtual_timer_flags);
+	if (gtdt_arch_timer_data_init(&data))
+		return;
 
-	arch_timer_ppi[HYP_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
-		gtdt->non_secure_el2_flags);
+	arch_timer_ppi[PHYS_SECURE_PPI] = data.phys_secure_ppi;
+	arch_timer_ppi[PHYS_NONSECURE_PPI] = data.phys_nonsecure_ppi;
+	arch_timer_ppi[VIRT_PPI] = data.virt_ppi;
+	arch_timer_ppi[HYP_PPI] = data.hyp_ppi;
+	/* Always-on capability */
+	arch_timer_c3stop = data.c3stop;
 
 	/* Get the frequency from CNTFRQ */
 	arch_timer_detect_rate(NULL, NULL);
-
-	/* Always-on capability */
-	arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
-
 	arch_timer_init();
-	return 0;
-}
-
-/* Initialize all the generic timers presented in GTDT */
-void __init acpi_generic_timer_init(void)
-{
-	if (acpi_disabled)
-		return;
-
-	acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init);
 }
 #endif
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 9916d0e..5deed9d 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -43,6 +43,14 @@ enum arch_timer_reg {
 
 #define ARCH_TIMER_EVT_STREAM_FREQ	10000	/* 100us */
 
+struct arch_timer_data {
+	int phys_secure_ppi;
+	int phys_nonsecure_ppi;
+	int virt_ppi;
+	int hyp_ppi;
+	bool c3stop;
+};
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 598f0f1..7213c0d 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -458,6 +458,11 @@ void acpi_walk_dep_device_list(acpi_handle handle);
 struct platform_device *acpi_create_platform_device(struct acpi_device *);
 #define ACPI_PTR(_ptr)	(_ptr)
 
+#ifdef CONFIG_ACPI_GTDT
+struct arch_timer_data;
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data);
+#endif
+
 #else	/* !CONFIG_ACPI */
 
 #define acpi_disabled 1
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index d27d015..264e553 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -254,9 +254,9 @@ static inline void clocksource_of_init(void) {}
 #endif
 
 #ifdef CONFIG_ACPI
-void acpi_generic_timer_init(void);
+void arch_timer_acpi_init(void);
 #else
-static inline void acpi_generic_timer_init(void) { }
+static inline void arch_timer_acpi_init(void) { }
 #endif
 
 #endif /* _LINUX_CLOCKSOURCE_H */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH non-pretimeout 7/7] clocksource: simplify ACPI code in arm_arch_timer.c
@ 2015-06-10 17:47     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-10 17:47 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA, Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

The patch update arm_arch_timer driver to use the function
provided by the new GTDT driver of ACPI.
By this way, arm_arch_timer.c can be simplified, and separate
all the ACPI GTDT knowledge from this timer driver.

Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm64/kernel/time.c             |  4 +--
 drivers/acpi/gtdt.c                  | 43 ++++++++++++++++++++++++++
 drivers/clocksource/Kconfig          |  1 +
 drivers/clocksource/arm_arch_timer.c | 60 +++++++-----------------------------
 include/clocksource/arm_arch_timer.h |  8 +++++
 include/linux/acpi.h                 |  5 +++
 include/linux/clocksource.h          |  4 +--
 7 files changed, 72 insertions(+), 53 deletions(-)

diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 42f9195..2cabea6 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -75,9 +75,9 @@ void __init time_init(void)
 
 	/*
 	 * Since ACPI or FDT will only one be available in the system,
-	 * we can use acpi_generic_timer_init() here safely
+	 * we can use arch_timer_acpi_init() here safely
 	 */
-	acpi_generic_timer_init();
+	arch_timer_acpi_init();
 
 	arch_timer_rate = arch_timer_get_rate();
 	if (!arch_timer_rate)
diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
index a92abf2..699c9fd 100644
--- a/drivers/acpi/gtdt.c
+++ b/drivers/acpi/gtdt.c
@@ -17,6 +17,8 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
+#include <clocksource/arm_arch_timer.h>
+
 static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 {
 	int trigger, polarity;
@@ -33,6 +35,47 @@ static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
 }
 
+struct arch_timer_data __initdata *arch_timer_data_p;
+
+static int __init arch_timer_data_init(struct acpi_table_header *table)
+{
+	struct acpi_table_gtdt *gtdt;
+
+	gtdt = container_of(table, struct acpi_table_gtdt, header);
+
+	arch_timer_data_p->phys_secure_ppi =
+		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
+					    gtdt->secure_el1_flags);
+
+	arch_timer_data_p->phys_nonsecure_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
+					    gtdt->non_secure_el1_flags);
+
+	arch_timer_data_p->virt_ppi =
+		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
+					    gtdt->virtual_timer_flags);
+
+	arch_timer_data_p->hyp_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
+					    gtdt->non_secure_el2_flags);
+
+	arch_timer_data_p->c3stop = !(gtdt->non_secure_el1_flags &
+				      ACPI_GTDT_ALWAYS_ON);
+
+	return 0;
+}
+
+/* Initialize the arch_timer_data struct for arm_arch_timer by GTDT info */
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data)
+{
+	if (acpi_disabled || !data)
+		return -EINVAL;
+
+	arch_timer_data_p = data;
+
+	return acpi_table_parse(ACPI_SIG_GTDT, arch_timer_data_init);
+}
+
 /*
  * Initialize a SBSA generic Watchdog platform device info from GTDT
  * According to SBSA specification the size of refresh and control
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 51d7865f..ea94a6f 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -109,6 +109,7 @@ config CLKSRC_EFM32
 config ARM_ARCH_TIMER
 	bool
 	select CLKSRC_OF if OF
+	select ACPI_GTDT if ACPI
 
 config ARM_ARCH_TIMER_EVTSTREAM
 	bool "Support for ARM architected timer event stream generation"
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 0aa135d..99505bb 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -817,68 +817,30 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
 		       arch_timer_mem_init);
 
 #ifdef CONFIG_ACPI
-static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
-{
-	int trigger, polarity;
-
-	if (!interrupt)
-		return 0;
-
-	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
-			: ACPI_LEVEL_SENSITIVE;
-
-	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
-			: ACPI_ACTIVE_HIGH;
-
-	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
-}
-
 /* Initialize per-processor generic timer */
-static int __init arch_timer_acpi_init(struct acpi_table_header *table)
+void __init arch_timer_acpi_init(void)
 {
-	struct acpi_table_gtdt *gtdt;
+	struct arch_timer_data data;
 
 	if (arch_timers_present & ARCH_CP15_TIMER) {
 		pr_warn("arch_timer: already initialized, skipping\n");
-		return -EINVAL;
+		return;
 	}
 
-	gtdt = container_of(table, struct acpi_table_gtdt, header);
-
 	arch_timers_present |= ARCH_CP15_TIMER;
 
-	arch_timer_ppi[PHYS_SECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
-		gtdt->secure_el1_flags);
-
-	arch_timer_ppi[PHYS_NONSECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
-		gtdt->non_secure_el1_flags);
-
-	arch_timer_ppi[VIRT_PPI] =
-		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
-		gtdt->virtual_timer_flags);
+	if (gtdt_arch_timer_data_init(&data))
+		return;
 
-	arch_timer_ppi[HYP_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
-		gtdt->non_secure_el2_flags);
+	arch_timer_ppi[PHYS_SECURE_PPI] = data.phys_secure_ppi;
+	arch_timer_ppi[PHYS_NONSECURE_PPI] = data.phys_nonsecure_ppi;
+	arch_timer_ppi[VIRT_PPI] = data.virt_ppi;
+	arch_timer_ppi[HYP_PPI] = data.hyp_ppi;
+	/* Always-on capability */
+	arch_timer_c3stop = data.c3stop;
 
 	/* Get the frequency from CNTFRQ */
 	arch_timer_detect_rate(NULL, NULL);
-
-	/* Always-on capability */
-	arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
-
 	arch_timer_init();
-	return 0;
-}
-
-/* Initialize all the generic timers presented in GTDT */
-void __init acpi_generic_timer_init(void)
-{
-	if (acpi_disabled)
-		return;
-
-	acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init);
 }
 #endif
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 9916d0e..5deed9d 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -43,6 +43,14 @@ enum arch_timer_reg {
 
 #define ARCH_TIMER_EVT_STREAM_FREQ	10000	/* 100us */
 
+struct arch_timer_data {
+	int phys_secure_ppi;
+	int phys_nonsecure_ppi;
+	int virt_ppi;
+	int hyp_ppi;
+	bool c3stop;
+};
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 598f0f1..7213c0d 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -458,6 +458,11 @@ void acpi_walk_dep_device_list(acpi_handle handle);
 struct platform_device *acpi_create_platform_device(struct acpi_device *);
 #define ACPI_PTR(_ptr)	(_ptr)
 
+#ifdef CONFIG_ACPI_GTDT
+struct arch_timer_data;
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data);
+#endif
+
 #else	/* !CONFIG_ACPI */
 
 #define acpi_disabled 1
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index d27d015..264e553 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -254,9 +254,9 @@ static inline void clocksource_of_init(void) {}
 #endif
 
 #ifdef CONFIG_ACPI
-void acpi_generic_timer_init(void);
+void arch_timer_acpi_init(void);
 #else
-static inline void acpi_generic_timer_init(void) { }
+static inline void arch_timer_acpi_init(void) { }
 #endif
 
 #endif /* _LINUX_CLOCKSOURCE_H */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 17:54                                     ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-10 17:54 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

Hi Guenter,

On 10 June 2015 at 23:38, Fu Wei <fu.wei@linaro.org> wrote:
> Hi Guenter,
>
>
> On 10 June 2015 at 11:41, Fu Wei <fu.wei@linaro.org> wrote:
>> Hi Guenter,
>>
>> On 10 June 2015 at 00:45, Guenter Roeck <linux@roeck-us.net> wrote:
>>> On 06/09/2015 09:29 AM, Timur Tabi wrote:
>>>>
>>>> On 06/09/2015 11:22 AM, Guenter Roeck wrote:
>>>>>
>>>>>
>>>>>
>>>>> but I see your point. Essentially, the specification is broken
>>>>> for all practical purposes, since, as you point out, enabling
>>>>> the watchdog overwrites and explicitly sets WCV. Effectively
>>>>> this means that just using WCV to program the timeout period
>>>>> is not really possible.
>>>>>
>>>>> I am not really sure how to address this. We can either only use WOR,
>>>>> and forget about pretimeout, or we can enforce a minimum pretimeout.
>>>>> In the latter case, we'll have to write WCV after writing WOR.
>>>>
>>>>
>>>> In talking with our hardware engineers, using WCV to program the timeout
>>>> period is not a valid operation.  This is why I keep arguing against the
>>>> pre-timeout feature, and I don't agree that servers should always use
>>>> pre-timeout.
>>>>
>>>
>>> Not sure if "not valid" is correct - after all, it is mentioned in the
>>> specification. However, it is at the very least fragile.
>>
>> I think we should focus on SBSA spec, but not a specific chip design,
>> because this is SBSA watchdog, not a driver for an IP core from a
>> specific chip vendor.
>> this operation is mentioned in the spec,
>> and I have tested my driver on Foundation model(from ARM) and a real hardware.
>>
>>>
>>> I tend to agree that we should just forget about pretimeout and
>>> use your original approach, where the timeout value is used
>>> to program WOR. Everything else is really just asking for trouble.
>>
>> I don't mind if we give up pretimeout, The reason I use pretimeout is:
>> this concept matches the function of two stage timeouts.
>>
>> but, If we give up pretimeout, could you give me a suggestion:
>>
>> How to config the two stage timeouts
>> (1)from enabling watchdog to WS0
>> (2)the time from WS1 to WS0
>>
>> If we only have one timeout parameter,  How to config the two stage timeouts?
>> Any suggestion ?
>
> I have another thought for this, please allow me to sent anther
> patchset in a day. see if you like it.

I have sent a non-pretimeout version patchset, please let me know if
you like the non-pretimeout version more.

Great thanks for your time. :-)

>
>>
>> If we make the first stage timeout is timeout/2,  this violates the
>> definition of timeout.
>> I don't think users expect interrupt, panic or reboot at timeout/2.
>>
>> And WS1  definitely isn't a backup of WS0.
>>
>>>
>>> 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
>
>
>
> --
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-10 17:54                                     ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-10 17:54 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon,
	rjw-LthD3rsA81gm4RdzfppkhA

Hi Guenter,

On 10 June 2015 at 23:38, Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> Hi Guenter,
>
>
> On 10 June 2015 at 11:41, Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
>> Hi Guenter,
>>
>> On 10 June 2015 at 00:45, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
>>> On 06/09/2015 09:29 AM, Timur Tabi wrote:
>>>>
>>>> On 06/09/2015 11:22 AM, Guenter Roeck wrote:
>>>>>
>>>>>
>>>>>
>>>>> but I see your point. Essentially, the specification is broken
>>>>> for all practical purposes, since, as you point out, enabling
>>>>> the watchdog overwrites and explicitly sets WCV. Effectively
>>>>> this means that just using WCV to program the timeout period
>>>>> is not really possible.
>>>>>
>>>>> I am not really sure how to address this. We can either only use WOR,
>>>>> and forget about pretimeout, or we can enforce a minimum pretimeout.
>>>>> In the latter case, we'll have to write WCV after writing WOR.
>>>>
>>>>
>>>> In talking with our hardware engineers, using WCV to program the timeout
>>>> period is not a valid operation.  This is why I keep arguing against the
>>>> pre-timeout feature, and I don't agree that servers should always use
>>>> pre-timeout.
>>>>
>>>
>>> Not sure if "not valid" is correct - after all, it is mentioned in the
>>> specification. However, it is at the very least fragile.
>>
>> I think we should focus on SBSA spec, but not a specific chip design,
>> because this is SBSA watchdog, not a driver for an IP core from a
>> specific chip vendor.
>> this operation is mentioned in the spec,
>> and I have tested my driver on Foundation model(from ARM) and a real hardware.
>>
>>>
>>> I tend to agree that we should just forget about pretimeout and
>>> use your original approach, where the timeout value is used
>>> to program WOR. Everything else is really just asking for trouble.
>>
>> I don't mind if we give up pretimeout, The reason I use pretimeout is:
>> this concept matches the function of two stage timeouts.
>>
>> but, If we give up pretimeout, could you give me a suggestion:
>>
>> How to config the two stage timeouts
>> (1)from enabling watchdog to WS0
>> (2)the time from WS1 to WS0
>>
>> If we only have one timeout parameter,  How to config the two stage timeouts?
>> Any suggestion ?
>
> I have another thought for this, please allow me to sent anther
> patchset in a day. see if you like it.

I have sent a non-pretimeout version patchset, please let me know if
you like the non-pretimeout version more.

Great thanks for your time. :-)

>
>>
>> If we make the first stage timeout is timeout/2,  this violates the
>> definition of timeout.
>> I don't think users expect interrupt, panic or reboot at timeout/2.
>>
>> And WS1  definitely isn't a backup of WS0.
>>
>>>
>>> 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
>
>
>
> --
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-10  3:41                                 ` Fu Wei
@ 2015-06-11  0:22                                   ` Timur Tabi
  -1 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-11  0:22 UTC (permalink / raw)
  To: Fu Wei, Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

Fu Wei wrote:
> If we make the first stage timeout is timeout/2,  this violates the
> definition of timeout.

The documentation says that the hardware needs to reset after the 
timeout expires.  If you program the hardware to timeout/2, the driver 
can ignore WS0 and allow WS1 to reset the hardware.  That conforms to 
the documentation.

-- 
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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-11  0:22                                   ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-11  0:22 UTC (permalink / raw)
  To: Fu Wei, Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, vgandhi, wim,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw

Fu Wei wrote:
> If we make the first stage timeout is timeout/2,  this violates the
> definition of timeout.

The documentation says that the hardware needs to reset after the 
timeout expires.  If you program the hardware to timeout/2, the driver 
can ignore WS0 and allow WS1 to reset the hardware.  That conforms to 
the documentation.

-- 
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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-11  0:22                                   ` Timur Tabi
  (?)
@ 2015-06-11  3:00                                   ` Fu Wei
  2015-06-11  3:45                                       ` Timur Tabi
  -1 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-06-11  3:00 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

On 11 June 2015 at 08:22, Timur Tabi <timur@codeaurora.org> wrote:
> Fu Wei wrote:
>>
>> If we make the first stage timeout is timeout/2,  this violates the
>> definition of timeout.
>
>
> The documentation says that the hardware needs to reset after the timeout
> expires.

yes , you are absolutely on this. Great thanks for point out this.
my patch is doing this way: trigger WS1 at the timeout expires
Before that, using pretimeout for WS0 as an warning.


> If you program the hardware to timeout/2, the driver can ignore
> WS0 and allow WS1 to reset the hardware.  That conforms to the
> documentation.

yes, technically we can do nothing in WS0, and just wait for WS1.
So SBSA watchdog become a one stage timeout watchdog, right?
So if user want the WS0 warning, How to make driver know that, and do
something in WS0 routine?
I think by this way,  two stage timeouts, WS0 "alert" will be meaningless.

Could you suggest a good way to use WS0, so we can follow SBSA 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.



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-11  3:00                                   ` Fu Wei
@ 2015-06-11  3:45                                       ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-11  3:45 UTC (permalink / raw)
  To: Fu Wei
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

Fu Wei wrote:
> Could you suggest a good way to use WS0, so we can follow SBSA spec?

To avoid the timeout/2 problem, WS0 calls panic, which is the "real" 
timeout/reset.  WS1 is then a "backup" that is ignored by the driver. 
That is, the driver doesn't do anything with WS1 and it doesn't tell the 
kernel about WS1.

I know you don't like the idea of WS1 as a backup timeout, but this is 
one way to solve the problem.

-- 
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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-11  3:45                                       ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-11  3:45 UTC (permalink / raw)
  To: Fu Wei
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

Fu Wei wrote:
> Could you suggest a good way to use WS0, so we can follow SBSA spec?

To avoid the timeout/2 problem, WS0 calls panic, which is the "real" 
timeout/reset.  WS1 is then a "backup" that is ignored by the driver. 
That is, the driver doesn't do anything with WS1 and it doesn't tell the 
kernel about WS1.

I know you don't like the idea of WS1 as a backup timeout, but this is 
one way to solve the problem.

-- 
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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-11  3:45                                       ` Timur Tabi
@ 2015-06-11  5:13                                         ` Guenter Roeck
  -1 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-11  5:13 UTC (permalink / raw)
  To: Timur Tabi, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, rjw

On 06/10/2015 08:45 PM, Timur Tabi wrote:
> Fu Wei wrote:
>> Could you suggest a good way to use WS0, so we can follow SBSA spec?
>
> To avoid the timeout/2 problem, WS0 calls panic, which is the "real" timeout/reset.  WS1 is then a "backup" that is ignored by the driver. That is, the driver doesn't do anything with WS1 and it doesn't tell the kernel about WS1.
>
> I know you don't like the idea of WS1 as a backup timeout, but this is one way to solve the problem.
>
This is what I would do.

Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-11  5:13                                         ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-11  5:13 UTC (permalink / raw)
  To: Timur Tabi, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, rjw

On 06/10/2015 08:45 PM, Timur Tabi wrote:
> Fu Wei wrote:
>> Could you suggest a good way to use WS0, so we can follow SBSA spec?
>
> To avoid the timeout/2 problem, WS0 calls panic, which is the "real" timeout/reset.  WS1 is then a "backup" that is ignored by the driver. That is, the driver doesn't do anything with WS1 and it doesn't tell the kernel about WS1.
>
> I know you don't like the idea of WS1 as a backup timeout, but this is one way to solve the problem.
>
This is what I would do.

Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-11  5:32                                         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-11  5:32 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

On 11 June 2015 at 11:45, Timur Tabi <timur@codeaurora.org> wrote:
> Fu Wei wrote:
>>
>> Could you suggest a good way to use WS0, so we can follow SBSA spec?
>
>
> To avoid the timeout/2 problem, WS0 calls panic, which is the "real"
> timeout/reset.  WS1 is then a "backup" that is ignored by the driver. That
> is, the driver doesn't do anything with WS1 and it doesn't tell the kernel
> about WS1.

could you suggestion :
(1) how to config the time from WS0 to WS1 without touching timeout.
(2) if we don't config the time from WS0 to WS1, what is the better
time for ALL server and ALL situation

>
> I know you don't like the idea of WS1 as a backup timeout, but this is one
> way to solve the problem.

It is not "I don't like"
WS1 is not a backup in SBSA spec. Page 21 :
"The initial signal is typically wired to an interrupt and alerts the system. "

If this is the backup, it should say "reset the system"

>
>
> --
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-11  5:32                                         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-11  5:32 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Guenter Roeck, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon,
	rjw-LthD3rsA81gm4RdzfppkhA

On 11 June 2015 at 11:45, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
> Fu Wei wrote:
>>
>> Could you suggest a good way to use WS0, so we can follow SBSA spec?
>
>
> To avoid the timeout/2 problem, WS0 calls panic, which is the "real"
> timeout/reset.  WS1 is then a "backup" that is ignored by the driver. That
> is, the driver doesn't do anything with WS1 and it doesn't tell the kernel
> about WS1.

could you suggestion :
(1) how to config the time from WS0 to WS1 without touching timeout.
(2) if we don't config the time from WS0 to WS1, what is the better
time for ALL server and ALL situation

>
> I know you don't like the idea of WS1 as a backup timeout, but this is one
> way to solve the problem.

It is not "I don't like"
WS1 is not a backup in SBSA spec. Page 21 :
"The initial signal is typically wired to an interrupt and alerts the system. "

If this is the backup, it should say "reset the system"

>
>
> --
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-11  5:13                                         ` Guenter Roeck
  (?)
@ 2015-06-11  5:33                                         ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-11  5:33 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

Hi Guenter

On 11 June 2015 at 13:13, Guenter Roeck <linux@roeck-us.net> wrote:
> On 06/10/2015 08:45 PM, Timur Tabi wrote:
>>
>> Fu Wei wrote:
>>>
>>> Could you suggest a good way to use WS0, so we can follow SBSA spec?
>>
>>
>> To avoid the timeout/2 problem, WS0 calls panic, which is the "real"
>> timeout/reset.  WS1 is then a "backup" that is ignored by the driver. That
>> is, the driver doesn't do anything with WS1 and it doesn't tell the kernel
>> about WS1.
>>
>> I know you don't like the idea of WS1 as a backup timeout, but this is one
>> way to solve the problem.
>>
> This is what I would do.

If so, Please check the non-pretimeout version.  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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 4/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-11  5:33       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-11  5:33 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, vgandhi, wim, jcm, leo.duran, corbet,
	mark.rutland, catalin.marinas, will.deacon, rjw

On 06/10/2015 10:47 AM, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> This driver bases on linux kernel watchdog framework.
> It supports getting timeout from parameter and FDT
> at the driver init stage.
> The first timeout period expires, the interrupt routine
> got another timeout period to run panic for saving
> system context.
>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>   drivers/watchdog/Kconfig     |  11 ++
>   drivers/watchdog/Makefile    |   1 +
>   drivers/watchdog/sbsa_gwdt.c | 383 +++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 395 insertions(+)
>   create mode 100644 drivers/watchdog/sbsa_gwdt.c
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index e5e7c55..554f18a 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -152,6 +152,17 @@ 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 ARM64
> +	depends on ARM_ARCH_TIMER
> +	select WATCHDOG_CORE
> +	help
> +	  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.
> +	  More details: ARM 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..1ddc10f
> --- /dev/null
> +++ b/drivers/watchdog/sbsa_gwdt.c
> @@ -0,0 +1,383 @@
> +/*
> + * SBSA(Server Base System Architecture) Generic Watchdog driver
> + *
> + * Copyright (c) 2015, Linaro Ltd.
> + * Author: Fu Wei <fu.wei@linaro.org>
> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> + *
> + * 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 has two stage timeouts,
> + *       When the first timeout occurs, WS0(SPI or LPI) is triggered,
> + *       the second timeout period(as long as the first timeout period) starts.
> + *       In WS0 interrupt routine, panic() will be called for collecting
> + *       crashdown info.
> + *       If system can not recover from WS0 interrupt routine, then second
> + *       timeout occurs, WS1(reset or higher level interrupt) is triggered.
> + *       The two timeout period can be set by WOR(32bit).
> + *       WOR gives a maximum watch period of around 10s at the maximum
> + *       system counter frequency.
> + *       The System Counter shall run at maximum of 400MHz.
> + *
> + *       But If we need a larger timeout period, this driver will programme WCV
> + *       directly. That can support more than 10s timeout at the maximum
> + *       system counter frequency.
> + *       More details: ARM DEN0029B - Server Base System Architecture (SBSA)
> + *
> + * SBSA GWDT:    |---WOR(or WCV)---WS0---WOR(or WCV)---WS1
> + *               |-----timeout-----WS0-----timeout-----WS1

If we use WCV at all, I would like to see something like

  * SBSA GWDT:    |---WOR(or WCV)---WS0--------WOR------WS1
  *               |-----timeout-----WS0-----------------WS1
  *                                 panic               hw reset

where WOR would be used up to its maximum, to be replaced by WCV
(but kept at maximum) if the selected timeout is larger than the
maximum timeout selectable with WOR. Would this be possible ?

Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 4/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-11  5:33       ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-11  5:33 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	corbet-T1hC0tSOHrs, mark.rutland-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	rjw-LthD3rsA81gm4RdzfppkhA

On 06/10/2015 10:47 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> This driver bases on linux kernel watchdog framework.
> It supports getting timeout from parameter and FDT
> at the driver init stage.
> The first timeout period expires, the interrupt routine
> got another timeout period to run panic for saving
> system context.
>
> Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>   drivers/watchdog/Kconfig     |  11 ++
>   drivers/watchdog/Makefile    |   1 +
>   drivers/watchdog/sbsa_gwdt.c | 383 +++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 395 insertions(+)
>   create mode 100644 drivers/watchdog/sbsa_gwdt.c
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index e5e7c55..554f18a 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -152,6 +152,17 @@ 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 ARM64
> +	depends on ARM_ARCH_TIMER
> +	select WATCHDOG_CORE
> +	help
> +	  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.
> +	  More details: ARM 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..1ddc10f
> --- /dev/null
> +++ b/drivers/watchdog/sbsa_gwdt.c
> @@ -0,0 +1,383 @@
> +/*
> + * SBSA(Server Base System Architecture) Generic Watchdog driver
> + *
> + * Copyright (c) 2015, Linaro Ltd.
> + * Author: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
> + *
> + * 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 has two stage timeouts,
> + *       When the first timeout occurs, WS0(SPI or LPI) is triggered,
> + *       the second timeout period(as long as the first timeout period) starts.
> + *       In WS0 interrupt routine, panic() will be called for collecting
> + *       crashdown info.
> + *       If system can not recover from WS0 interrupt routine, then second
> + *       timeout occurs, WS1(reset or higher level interrupt) is triggered.
> + *       The two timeout period can be set by WOR(32bit).
> + *       WOR gives a maximum watch period of around 10s at the maximum
> + *       system counter frequency.
> + *       The System Counter shall run at maximum of 400MHz.
> + *
> + *       But If we need a larger timeout period, this driver will programme WCV
> + *       directly. That can support more than 10s timeout at the maximum
> + *       system counter frequency.
> + *       More details: ARM DEN0029B - Server Base System Architecture (SBSA)
> + *
> + * SBSA GWDT:    |---WOR(or WCV)---WS0---WOR(or WCV)---WS1
> + *               |-----timeout-----WS0-----timeout-----WS1

If we use WCV at all, I would like to see something like

  * SBSA GWDT:    |---WOR(or WCV)---WS0--------WOR------WS1
  *               |-----timeout-----WS0-----------------WS1
  *                                 panic               hw reset

where WOR would be used up to its maximum, to be replaced by WCV
(but kept at maximum) if the selected timeout is larger than the
maximum timeout selectable with WOR. Would this be possible ?

Guenter

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 4/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-11  5:33       ` Guenter Roeck
  (?)
@ 2015-06-11  5:44       ` Fu Wei
  2015-06-11  5:49         ` Guenter Roeck
  -1 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-06-11  5:44 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

Hi Guenter,

On 11 June 2015 at 13:33, Guenter Roeck <linux@roeck-us.net> wrote:
> On 06/10/2015 10:47 AM, fu.wei@linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> This driver bases on linux kernel watchdog framework.
>> It supports getting timeout from parameter and FDT
>> at the driver init stage.
>> The first timeout period expires, the interrupt routine
>> got another timeout period to run panic for saving
>> system context.
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>   drivers/watchdog/Kconfig     |  11 ++
>>   drivers/watchdog/Makefile    |   1 +
>>   drivers/watchdog/sbsa_gwdt.c | 383
>> +++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 395 insertions(+)
>>   create mode 100644 drivers/watchdog/sbsa_gwdt.c
>>
>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>> index e5e7c55..554f18a 100644
>> --- a/drivers/watchdog/Kconfig
>> +++ b/drivers/watchdog/Kconfig
>> @@ -152,6 +152,17 @@ 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 ARM64
>> +       depends on ARM_ARCH_TIMER
>> +       select WATCHDOG_CORE
>> +       help
>> +         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.
>> +         More details: ARM 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..1ddc10f
>> --- /dev/null
>> +++ b/drivers/watchdog/sbsa_gwdt.c
>> @@ -0,0 +1,383 @@
>> +/*
>> + * SBSA(Server Base System Architecture) Generic Watchdog driver
>> + *
>> + * Copyright (c) 2015, Linaro Ltd.
>> + * Author: Fu Wei <fu.wei@linaro.org>
>> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>> + *
>> + * 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 has two stage timeouts,
>> + *       When the first timeout occurs, WS0(SPI or LPI) is triggered,
>> + *       the second timeout period(as long as the first timeout period)
>> starts.
>> + *       In WS0 interrupt routine, panic() will be called for collecting
>> + *       crashdown info.
>> + *       If system can not recover from WS0 interrupt routine, then
>> second
>> + *       timeout occurs, WS1(reset or higher level interrupt) is
>> triggered.
>> + *       The two timeout period can be set by WOR(32bit).
>> + *       WOR gives a maximum watch period of around 10s at the maximum
>> + *       system counter frequency.
>> + *       The System Counter shall run at maximum of 400MHz.
>> + *
>> + *       But If we need a larger timeout period, this driver will
>> programme WCV
>> + *       directly. That can support more than 10s timeout at the maximum
>> + *       system counter frequency.
>> + *       More details: ARM DEN0029B - Server Base System Architecture
>> (SBSA)
>> + *
>> + * SBSA GWDT:    |---WOR(or WCV)---WS0---WOR(or WCV)---WS1
>> + *               |-----timeout-----WS0-----timeout-----WS1
>
>
> If we use WCV at all, I would like to see something like
>
>  * SBSA GWDT:    |---WOR(or WCV)---WS0--------WOR------WS1
>  *               |-----timeout-----WS0-----------------WS1
>  *                                 panic               hw reset
>
> where WOR would be used up to its maximum, to be replaced by WCV
> (but kept at maximum) if the selected timeout is larger than the
> maximum timeout selectable with WOR. Would this be possible ?

for this part |-----timeout-----WS0,  I am doing this way in
non-pretimeout version.

but for WS0-----------------WS1, do you mean WOR would always be used
up to its maximum???
I don't see any variable attached on it. So I would like to confirm
what is this value

>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 4/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-11  5:44       ` Fu Wei
@ 2015-06-11  5:49         ` Guenter Roeck
  2015-06-11  5:59             ` Fu Wei
  0 siblings, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-06-11  5:49 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

On 06/10/2015 10:44 PM, Fu Wei wrote:
> Hi Guenter,
>
> On 11 June 2015 at 13:33, Guenter Roeck <linux@roeck-us.net> wrote:
>> On 06/10/2015 10:47 AM, fu.wei@linaro.org wrote:
>>>
>>> From: Fu Wei <fu.wei@linaro.org>
>>>
>>> This driver bases on linux kernel watchdog framework.
>>> It supports getting timeout from parameter and FDT
>>> at the driver init stage.
>>> The first timeout period expires, the interrupt routine
>>> got another timeout period to run panic for saving
>>> system context.
>>>
>>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>>> ---
>>>    drivers/watchdog/Kconfig     |  11 ++
>>>    drivers/watchdog/Makefile    |   1 +
>>>    drivers/watchdog/sbsa_gwdt.c | 383
>>> +++++++++++++++++++++++++++++++++++++++++++
>>>    3 files changed, 395 insertions(+)
>>>    create mode 100644 drivers/watchdog/sbsa_gwdt.c
>>>
>>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>>> index e5e7c55..554f18a 100644
>>> --- a/drivers/watchdog/Kconfig
>>> +++ b/drivers/watchdog/Kconfig
>>> @@ -152,6 +152,17 @@ 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 ARM64
>>> +       depends on ARM_ARCH_TIMER
>>> +       select WATCHDOG_CORE
>>> +       help
>>> +         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.
>>> +         More details: ARM 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..1ddc10f
>>> --- /dev/null
>>> +++ b/drivers/watchdog/sbsa_gwdt.c
>>> @@ -0,0 +1,383 @@
>>> +/*
>>> + * SBSA(Server Base System Architecture) Generic Watchdog driver
>>> + *
>>> + * Copyright (c) 2015, Linaro Ltd.
>>> + * Author: Fu Wei <fu.wei@linaro.org>
>>> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>>> + *
>>> + * 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 has two stage timeouts,
>>> + *       When the first timeout occurs, WS0(SPI or LPI) is triggered,
>>> + *       the second timeout period(as long as the first timeout period)
>>> starts.
>>> + *       In WS0 interrupt routine, panic() will be called for collecting
>>> + *       crashdown info.
>>> + *       If system can not recover from WS0 interrupt routine, then
>>> second
>>> + *       timeout occurs, WS1(reset or higher level interrupt) is
>>> triggered.
>>> + *       The two timeout period can be set by WOR(32bit).
>>> + *       WOR gives a maximum watch period of around 10s at the maximum
>>> + *       system counter frequency.
>>> + *       The System Counter shall run at maximum of 400MHz.
>>> + *
>>> + *       But If we need a larger timeout period, this driver will
>>> programme WCV
>>> + *       directly. That can support more than 10s timeout at the maximum
>>> + *       system counter frequency.
>>> + *       More details: ARM DEN0029B - Server Base System Architecture
>>> (SBSA)
>>> + *
>>> + * SBSA GWDT:    |---WOR(or WCV)---WS0---WOR(or WCV)---WS1
>>> + *               |-----timeout-----WS0-----timeout-----WS1
>>
>>
>> If we use WCV at all, I would like to see something like
>>
>>   * SBSA GWDT:    |---WOR(or WCV)---WS0--------WOR------WS1
>>   *               |-----timeout-----WS0-----------------WS1
>>   *                                 panic               hw reset
>>
>> where WOR would be used up to its maximum, to be replaced by WCV
>> (but kept at maximum) if the selected timeout is larger than the
>> maximum timeout selectable with WOR. Would this be possible ?
>
> for this part |-----timeout-----WS0,  I am doing this way in
> non-pretimeout version.
>
> but for WS0-----------------WS1, do you mean WOR would always be used
> up to its maximum???

yes

> I don't see any variable attached on it. So I would like to confirm
> what is this value
>

min(timeout, max_wor_timeout)

Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 4/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-11  5:59             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-11  5:59 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

Hi Guenter,


On 11 June 2015 at 13:49, Guenter Roeck <linux@roeck-us.net> wrote:
> On 06/10/2015 10:44 PM, Fu Wei wrote:
>>
>> Hi Guenter,
>>
>> On 11 June 2015 at 13:33, Guenter Roeck <linux@roeck-us.net> wrote:
>>>
>>> On 06/10/2015 10:47 AM, fu.wei@linaro.org wrote:
>>>>
>>>>
>>>> From: Fu Wei <fu.wei@linaro.org>
>>>>
>>>> This driver bases on linux kernel watchdog framework.
>>>> It supports getting timeout from parameter and FDT
>>>> at the driver init stage.
>>>> The first timeout period expires, the interrupt routine
>>>> got another timeout period to run panic for saving
>>>> system context.
>>>>
>>>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>>>> ---
>>>>    drivers/watchdog/Kconfig     |  11 ++
>>>>    drivers/watchdog/Makefile    |   1 +
>>>>    drivers/watchdog/sbsa_gwdt.c | 383
>>>> +++++++++++++++++++++++++++++++++++++++++++
>>>>    3 files changed, 395 insertions(+)
>>>>    create mode 100644 drivers/watchdog/sbsa_gwdt.c
>>>>
>>>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>>>> index e5e7c55..554f18a 100644
>>>> --- a/drivers/watchdog/Kconfig
>>>> +++ b/drivers/watchdog/Kconfig
>>>> @@ -152,6 +152,17 @@ 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 ARM64
>>>> +       depends on ARM_ARCH_TIMER
>>>> +       select WATCHDOG_CORE
>>>> +       help
>>>> +         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.
>>>> +         More details: ARM 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..1ddc10f
>>>> --- /dev/null
>>>> +++ b/drivers/watchdog/sbsa_gwdt.c
>>>> @@ -0,0 +1,383 @@
>>>> +/*
>>>> + * SBSA(Server Base System Architecture) Generic Watchdog driver
>>>> + *
>>>> + * Copyright (c) 2015, Linaro Ltd.
>>>> + * Author: Fu Wei <fu.wei@linaro.org>
>>>> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>>>> + *
>>>> + * 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 has two stage timeouts,
>>>> + *       When the first timeout occurs, WS0(SPI or LPI) is triggered,
>>>> + *       the second timeout period(as long as the first timeout period)
>>>> starts.
>>>> + *       In WS0 interrupt routine, panic() will be called for
>>>> collecting
>>>> + *       crashdown info.
>>>> + *       If system can not recover from WS0 interrupt routine, then
>>>> second
>>>> + *       timeout occurs, WS1(reset or higher level interrupt) is
>>>> triggered.
>>>> + *       The two timeout period can be set by WOR(32bit).
>>>> + *       WOR gives a maximum watch period of around 10s at the maximum
>>>> + *       system counter frequency.
>>>> + *       The System Counter shall run at maximum of 400MHz.
>>>> + *
>>>> + *       But If we need a larger timeout period, this driver will
>>>> programme WCV
>>>> + *       directly. That can support more than 10s timeout at the
>>>> maximum
>>>> + *       system counter frequency.
>>>> + *       More details: ARM DEN0029B - Server Base System Architecture
>>>> (SBSA)
>>>> + *
>>>> + * SBSA GWDT:    |---WOR(or WCV)---WS0---WOR(or WCV)---WS1
>>>> + *               |-----timeout-----WS0-----timeout-----WS1
>>>
>>>
>>>
>>> If we use WCV at all, I would like to see something like
>>>
>>>   * SBSA GWDT:    |---WOR(or WCV)---WS0--------WOR------WS1
>>>   *               |-----timeout-----WS0-----------------WS1
>>>   *                                 panic               hw reset
>>>
>>> where WOR would be used up to its maximum, to be replaced by WCV
>>> (but kept at maximum) if the selected timeout is larger than the
>>> maximum timeout selectable with WOR. Would this be possible ?
>>
>>
>> for this part |-----timeout-----WS0,  I am doing this way in
>> non-pretimeout version.
>>
>> but for WS0-----------------WS1, do you mean WOR would always be used
>> up to its maximum???
>
>
> yes
>
>> I don't see any variable attached on it. So I would like to confirm
>> what is this value
>>
>
> min(timeout, max_wor_timeout)

Sure, no problem. just need a very little fix in non-pretimout version

Just delete several lines in "sbsa_gwdt_interrupt", become like this:
+static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
+{
+    panic("SBSA Watchdog pre-timeout");
+
+    return IRQ_HANDLED;
+}

this matches your thought.

Any other code I need to improve ? If It is OK for you, I can sent a
new patchset soon.
Please let me know anything else I need to improve.

Great thanks for your time

>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 4/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-11  5:59             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-11  5:59 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon,
	rjw-LthD3rsA81gm4RdzfppkhA

Hi Guenter,


On 11 June 2015 at 13:49, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On 06/10/2015 10:44 PM, Fu Wei wrote:
>>
>> Hi Guenter,
>>
>> On 11 June 2015 at 13:33, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
>>>
>>> On 06/10/2015 10:47 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>>>>
>>>>
>>>> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>>>
>>>> This driver bases on linux kernel watchdog framework.
>>>> It supports getting timeout from parameter and FDT
>>>> at the driver init stage.
>>>> The first timeout period expires, the interrupt routine
>>>> got another timeout period to run panic for saving
>>>> system context.
>>>>
>>>> Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>>> ---
>>>>    drivers/watchdog/Kconfig     |  11 ++
>>>>    drivers/watchdog/Makefile    |   1 +
>>>>    drivers/watchdog/sbsa_gwdt.c | 383
>>>> +++++++++++++++++++++++++++++++++++++++++++
>>>>    3 files changed, 395 insertions(+)
>>>>    create mode 100644 drivers/watchdog/sbsa_gwdt.c
>>>>
>>>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>>>> index e5e7c55..554f18a 100644
>>>> --- a/drivers/watchdog/Kconfig
>>>> +++ b/drivers/watchdog/Kconfig
>>>> @@ -152,6 +152,17 @@ 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 ARM64
>>>> +       depends on ARM_ARCH_TIMER
>>>> +       select WATCHDOG_CORE
>>>> +       help
>>>> +         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.
>>>> +         More details: ARM 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..1ddc10f
>>>> --- /dev/null
>>>> +++ b/drivers/watchdog/sbsa_gwdt.c
>>>> @@ -0,0 +1,383 @@
>>>> +/*
>>>> + * SBSA(Server Base System Architecture) Generic Watchdog driver
>>>> + *
>>>> + * Copyright (c) 2015, Linaro Ltd.
>>>> + * Author: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>>> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
>>>> + *
>>>> + * 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 has two stage timeouts,
>>>> + *       When the first timeout occurs, WS0(SPI or LPI) is triggered,
>>>> + *       the second timeout period(as long as the first timeout period)
>>>> starts.
>>>> + *       In WS0 interrupt routine, panic() will be called for
>>>> collecting
>>>> + *       crashdown info.
>>>> + *       If system can not recover from WS0 interrupt routine, then
>>>> second
>>>> + *       timeout occurs, WS1(reset or higher level interrupt) is
>>>> triggered.
>>>> + *       The two timeout period can be set by WOR(32bit).
>>>> + *       WOR gives a maximum watch period of around 10s at the maximum
>>>> + *       system counter frequency.
>>>> + *       The System Counter shall run at maximum of 400MHz.
>>>> + *
>>>> + *       But If we need a larger timeout period, this driver will
>>>> programme WCV
>>>> + *       directly. That can support more than 10s timeout at the
>>>> maximum
>>>> + *       system counter frequency.
>>>> + *       More details: ARM DEN0029B - Server Base System Architecture
>>>> (SBSA)
>>>> + *
>>>> + * SBSA GWDT:    |---WOR(or WCV)---WS0---WOR(or WCV)---WS1
>>>> + *               |-----timeout-----WS0-----timeout-----WS1
>>>
>>>
>>>
>>> If we use WCV at all, I would like to see something like
>>>
>>>   * SBSA GWDT:    |---WOR(or WCV)---WS0--------WOR------WS1
>>>   *               |-----timeout-----WS0-----------------WS1
>>>   *                                 panic               hw reset
>>>
>>> where WOR would be used up to its maximum, to be replaced by WCV
>>> (but kept at maximum) if the selected timeout is larger than the
>>> maximum timeout selectable with WOR. Would this be possible ?
>>
>>
>> for this part |-----timeout-----WS0,  I am doing this way in
>> non-pretimeout version.
>>
>> but for WS0-----------------WS1, do you mean WOR would always be used
>> up to its maximum???
>
>
> yes
>
>> I don't see any variable attached on it. So I would like to confirm
>> what is this value
>>
>
> min(timeout, max_wor_timeout)

Sure, no problem. just need a very little fix in non-pretimout version

Just delete several lines in "sbsa_gwdt_interrupt", become like this:
+static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
+{
+    panic("SBSA Watchdog pre-timeout");
+
+    return IRQ_HANDLED;
+}

this matches your thought.

Any other code I need to improve ? If It is OK for you, I can sent a
new patchset soon.
Please let me know anything else I need to improve.

Great thanks for your time

>
> 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
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 5/7] ACPI: add GTDT table parse driver into ACPI driver
  2015-06-10 17:47   ` [PATCH non-pretimeout 5/7] ACPI: add GTDT table parse driver into ACPI driver fu.wei
@ 2015-06-11 11:14     ` Hanjun Guo
  0 siblings, 0 replies; 550+ messages in thread
From: Hanjun Guo @ 2015-06-11 11:14 UTC (permalink / raw)
  To: rjw
  Cc: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, timur, ashwin.chaugule, arnd, linux,
	vgandhi, wim, jcm, leo.duran, corbet, mark.rutland,
	catalin.marinas, will.deacon

Hi Rafael,

Any comments on patch 5,6,7/7 of this patch set?

Thanks
Hanjun


On 06/11/2015 01:47 AM, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> This driver adds support for parsing SBSA Generic Watchdog
> Structure in GTDT, and creating a platform device with that
> information. This allows the operating system to obtain device
> data from the resource of platform device.
>
> The platform device named "sbsa-gwdt" can be used by the
> ARM SBSA Generic Watchdog driver.
>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> ---
>   drivers/acpi/Kconfig  |   9 ++++
>   drivers/acpi/Makefile |   1 +
>   drivers/acpi/gtdt.c   | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 147 insertions(+)
>   create mode 100644 drivers/acpi/gtdt.c
>
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index 1bbaa3d..e125698 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -433,4 +433,13 @@ config XPOWER_PMIC_OPREGION
>
>   endif
>
> +config ACPI_GTDT
> +	bool "ACPI GTDT Support"
> +	depends on ARM64
> +	help
> +	  GTDT (Generic Timer Description Table) provides information
> +	  for per-processor timers and Platform (memory-mapped) timers
> +	  for ARM platforms. Select this option to provide information
> +	  needed for the timers init.
> +
>   endif	# ACPI
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index 431e587..2c5a194 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -96,3 +96,4 @@ obj-$(CONFIG_ACPI_EXTLOG)	+= acpi_extlog.o
>   obj-$(CONFIG_PMIC_OPREGION)	+= pmic/intel_pmic.o
>   obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
>   obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
> +obj-$(CONFIG_ACPI_GTDT)		+= gtdt.o
> diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
> new file mode 100644
> index 0000000..a92abf2
> --- /dev/null
> +++ b/drivers/acpi/gtdt.c
> @@ -0,0 +1,137 @@
> +/*
> + * ARM Specific GTDT table Support
> + *
> + * Copyright (C) 2015, Linaro Ltd.
> + * Author: Fu Wei <fu.wei@linaro.org>
> + *         Hanjun Guo <hanjun.guo@linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/device.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
> +{
> +	int trigger, polarity;
> +
> +	if (!interrupt)
> +		return 0;
> +
> +	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
> +			: ACPI_LEVEL_SENSITIVE;
> +
> +	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
> +			: ACPI_ACTIVE_HIGH;
> +
> +	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
> +}
> +
> +/*
> + * Initialize a SBSA generic Watchdog platform device info from GTDT
> + * According to SBSA specification the size of refresh and control
> + * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
> + */
> +static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
> +					int index)
> +{
> +	struct platform_device *pdev;
> +	int irq = map_generic_timer_interrupt(wd->timer_interrupt,
> +					      wd->timer_flags);
> +	struct resource res[] = {
> +		DEFINE_RES_IRQ_NAMED(irq, "ws0"),
> +		DEFINE_RES_MEM_NAMED(wd->refresh_frame_address, SZ_4K,
> +				     "refresh"),
> +		DEFINE_RES_MEM_NAMED(wd->control_frame_address, SZ_4K,
> +				     "control"),
> +	};
> +
> +	pr_debug("GTDT: a Watchdog GT(0x%llx/0x%llx gsi:%u flags:0x%x)\n",
> +		 wd->refresh_frame_address, wd->control_frame_address,
> +		 wd->timer_interrupt, wd->timer_flags);
> +
> +	if (!(wd->refresh_frame_address &&
> +	      wd->control_frame_address &&
> +	      wd->timer_interrupt)) {
> +		pr_err("GTDT: failed geting the device info.\n");
> +		return -EINVAL;
> +	}
> +
> +	if (irq < 0) {
> +		pr_err("GTDT: failed to register GSI of the Watchdog GT.\n");
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * Add a platform device named "sbsa-gwdt" to match the platform driver.
> +	 * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
> +	 * The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get device
> +	 * info below by matching this name.
> +	 */
> +	pdev = platform_device_register_simple("sbsa-gwdt", index, res,
> +					       ARRAY_SIZE(res));
> +	if (IS_ERR(pdev)) {
> +		acpi_unregister_gsi(wd->timer_interrupt);
> +		return PTR_ERR(pdev);
> +	}
> +
> +	return 0;
> +}
> +
> +static int __init gtdt_platform_timer_parse(struct acpi_table_header *table)
> +{
> +	struct acpi_gtdt_header *header;
> +	struct acpi_table_gtdt *gtdt;
> +	void *gtdt_subtable;
> +	int i, gwdt_index;
> +	int ret = 0;
> +
> +	if (table->revision < 2) {
> +		pr_warn("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 = 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;
> +}
> +
> +static int __init gtdt_platform_timer_init(void)
> +{
> +	if (acpi_disabled)
> +		return 0;
> +
> +	return acpi_table_parse(ACPI_SIG_GTDT, gtdt_platform_timer_parse);
> +}
> +
> +device_initcall(gtdt_platform_timer_init);
>

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v5 4/8] Watchdog: introdouce "pretimeout" into framework
  2015-06-10 16:21       ` Guenter Roeck
  (?)
@ 2015-06-11 11:22       ` Fu Wei
  2015-06-11 16:38           ` Guenter Roeck
  -1 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-06-11 11:22 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

Hi Guenter,

Great thanks for your time.

On 11 June 2015 at 00:21, Guenter Roeck <linux@roeck-us.net> wrote:
> On 06/10/2015 06:41 AM, fu.wei@linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> 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 drivers are going to use this: ARM SBSA Generic Watchdog
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>   Documentation/watchdog/watchdog-kernel-api.txt |  47 ++++++++++--
>>   drivers/watchdog/watchdog_core.c               | 100
>> +++++++++++++++++--------
>>   drivers/watchdog/watchdog_dev.c                |  53 +++++++++++++
>>   include/linux/watchdog.h                       |  36 ++++++++-
>>   4 files changed, 197 insertions(+), 39 deletions(-)
>>
>> diff --git a/Documentation/watchdog/watchdog-kernel-api.txt
>> b/Documentation/watchdog/watchdog-kernel-api.txt
>> index a0438f3..95b355d 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.
>> @@ -219,8 +236,28 @@ extern int watchdog_init_timeout(struct
>> watchdog_device *wdd,
>>                                     unsigned int timeout_parm, struct
>> device *dev);
>>
>>   The watchdog_init_timeout function allows you to initialize the timeout
>> field
>> -using the module timeout parameter or by retrieving the timeout-sec
>> property from
>> -the device tree (if the module timeout parameter is invalid). Best
>> practice is
>> -to set the default timeout value as timeout value in the watchdog_device
>> and
>> -then use this function to set the user "preferred" timeout value.
>> +using the module timeout parameter or by retrieving the first element of
>> +the timeout-sec property from the device tree (if the module timeout
>> parameter
>
>
> Missing space before (.
>
>> +is invalid). Best practice is to set the default timeout value as timeout
>> value
>> +in the watchdog_device and then use this function to set the user
>> "preferred"
>> +timeout value.
>> +This routine returns zero on success and a negative errno code for
>> failure.
>> +
>> +Some watchdog timers have two stage of timeouts(timeout and pretimeout),
>> +to initialize the timeout and pretimeout fields at the same time, the
>> following
>> +function can be used:
>> +
>> +extern int watchdog_init_timeouts(struct watchdog_device *wdd,
>> +                                  unsigned int pretimeout_parm,
>> +                                  unsigned int timeout_parm,
>> +                                  struct device *dev);
>> +
>> +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).
>
>
> Missing spaces before (.

Fixed these problem above , thanks

>
>> +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.
>> diff --git a/drivers/watchdog/watchdog_core.c
>> b/drivers/watchdog/watchdog_core.c
>> index cec9b55..bdd4e43 100644
>> --- a/drivers/watchdog/watchdog_core.c
>> +++ b/drivers/watchdog/watchdog_core.c
>> @@ -43,60 +43,98 @@
>>   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)
>
>
> Please don't rename this function. This avoids conflicts with other pending
> patches.

OK, changed it back.  Fixed.

>
>>   {
>>         /*
>> -        * 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 all to 0 (=not used or unknown)
>>          */
>> -       if (wdd->min_timeout > wdd->max_timeout) {
>> -               pr_info("Invalid min and max timeout values, resetting to
>> 0!\n");
>> +       if (wdd->min_pretimeout > wdd->max_pretimeout ||
>> +           wdd->min_timeout > wdd->max_timeout ||
>> +           wdd->min_timeout < wdd->min_pretimeout ||
>> +           wdd->max_timeout < wdd->max_pretimeout) {
>> +               pr_info("Invalid min and max timeouts, resetting to 0\n");
>
>
> timeouts or pretimeouts.

OK , thanks

>
>
>> +               wdd->min_pretimeout = 0;
>> +               wdd->max_pretimeout = 0;
>>                 wdd->min_timeout = 0;
>>                 wdd->max_timeout = 0;
>>         }
>>   }
>>
>>   /**
>> - * 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) or
>> + * the timeout-sec property (only if it is valid and the pretimeout_parm
>> or
>> + * timeout_parm is out of bounds). If none of them is 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,
>> +                          struct device *dev)
>>   {
>> -       unsigned int t = 0;
>> -       int ret = 0;
>> +       int ret = 0, length = 0;
>> +       u32 timeouts[2] = {0};
>> +       struct property *prop;
>>
>> -       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;
>> -       }
>> -       if (timeout_parm)
>> +       /*
>> +        * Try to get the pretimeout module parameter first
>> +        */
>> +       if (!watchdog_pretimeout_invalid(wdd, pretimeout_parm))
>> +               timeouts[1] = pretimeout_parm;
>> +       else
>> +               ret = -EINVAL; /* pretimeout_parm is invalid */
>> +
>
> If I understand the code correctly, this permits for pretimeout being
> specified
> as module parameter and timeout as devicetree property. I don't think this
> is a good idea. Use either one or the other, but not both. So this can be
> simplified to
>
>         if (watchdog_pretimeout_invalid(wdd, pretimeout_parm)
>                 ret = _EINVAL;
>
> if you use pretimeout directly below.
>
>> +       /*
>> +        * Try to get the timeout module parameter,
>> +        * if it's valid and pretimeout is valid(ret == 0),
>> +        * assignment and return zero. Otherwise, try dtb.
>> +        */
>> +       if (timeout_parm) {
>
>
> You can use
>         if (timeout_parm && !ret) {
>
>> +               if (!watchdog_timeout_invalid(wdd, timeout_parm) && !ret)
>> {
>
>
> instead of checking ret here.
>
>> +                       wdd->timeout = timeout_parm;
>> +                       wdd->pretimeout = timeouts[1];
>
>
> This is really pretimeout_parm here, which should be used.
> Then you don't need timeouts[1].

yes, you are right on this,  I have improved it  :-)

>
>> +                       return 0;
>> +               }
>>                 ret = -EINVAL;
>> +       }
>>
>
> Unfortunately this does not set wdd->pretimeout if pretimeout_parm
> is set but timeout_parm isn't. So I think you need
>
>         } else if (pretimeout_parm && !ret) {
>                 wdd->pretimeout = pretimeout;
>                 return 0;
>         }
>
> However, that actually won't work as we may try to set both timeout
> and pretimeout, but the current checks validate against the previous
> values. I'll need to think about that.
>
> Also, this is getting a bit complicated. Wonder if the code can be
> simplified.
> Something else to think about.

I think we don't need this, because only if both parameters are valid,
we can update the  wdd->pretimeout and wdd->timeout.
otherwise we ret = -EINVAL; then try devicetree.

>
>
>> -       /* try to get the timeout_sec property */
>> +       /*
>> +        * Either at least one of the module parameters is invalid,
>> +        * or timeout_parm is 0. 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
>> -               ret = -EINVAL;
>>
>> -       return ret;
>> +       prop = of_find_property(dev->of_node, "timeout-sec", &length);
>> +       if (prop && length > 0 && length <= sizeof(u32) * 2) {
>> +               of_property_read_u32_array(dev->of_node,
>> +                                          "timeout-sec", timeouts,
>> +                                          length / sizeof(u32));
>> +               if (length == sizeof(u32) * 2 &&
>> +                   watchdog_pretimeout_invalid(wdd, timeouts[1]))
>> +                               return -EINVAL;
>> +
>> +               if (!watchdog_timeout_invalid(wdd, timeouts[0]) &&
>> +                   timeouts[0]) {
>> +                       wdd->timeout = timeouts[0];
>> +                       wdd->pretimeout = timeouts[1];
>
>
> Please only set pretimeout here if specified in devicetree.

yes , fixed this problem

>
>
>> +                       return 0;
>> +               }
>> +       }
>> +
>> +       return -EINVAL;
>>   }
>> -EXPORT_SYMBOL_GPL(watchdog_init_timeout);
>> +EXPORT_SYMBOL_GPL(watchdog_init_timeouts);
>>
>>   /**
>>    * watchdog_register_device() - register a watchdog device
>> @@ -119,7 +157,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..af0777e 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,27 @@ 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:
>> +               /* check if we support the pretimeout */
>> +               if (!(wdd->info->options & WDIOF_PRETIMEOUT))
>> +                       return -EOPNOTSUPP;
>> +               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 keeps running (and if
>> +                * possible that it takes the new pretimeout)
>> +                */
>> +               watchdog_ping(wdd);
>> +               /* Fall */
>> +       case WDIOC_GETPRETIMEOUT:
>> +               /* check if we support the pretimeout */
>> +               if (wdd->info->options & WDIOF_PRETIMEOUT)
>> +                       return put_user(wdd->pretimeout, p);
>> +               return -EOPNOTSUPP;
>>         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..0a7acf0 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;
>> @@ -117,7 +125,20 @@ static inline void watchdog_set_nowayout(struct
>> watchdog_device *wdd, bool noway
>>   static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd,
>> unsigned int t)
>>   {
>>         return ((wdd->max_timeout != 0) &&
>> -               (t < wdd->min_timeout || t > wdd->max_timeout));
>> +               (t < wdd->min_timeout || t > wdd->max_timeout ||
>> +                       t <= wdd->pretimeout));
>
>
> pretimeout can be 0, and t needs to be evaluated against pretimeout even if
> max_timeout is 0.
>
> Try
>         return (wdd->max_timeout &&
>                 (t < wdd->min_timeout || t > wdd->max_timeout)) ||
>                (wdd->pretimeout && t <= wdd->pretimeout);

yes, you are right . fixed.

>
>> +}
>> +
>> +/*
>> + * Use the following function to check if a pretimeout value is invalid.
>> + * It can be "0", that means we don't use pretimeout.
>> + */
>> +static inline bool watchdog_pretimeout_invalid(struct watchdog_device
>> *wdd,
>> +                                              unsigned int t)
>> +{
>> +       return (wdd->pretimeout != 0 && wdd->max_pretimeout != 0 &&
>> +               (t < wdd->min_pretimeout || t > wdd->max_pretimeout ||
>> +                       (wdd->timeout != 0 && t >= wdd->timeout)));
>
>
> The check for wdd->pretimeout doesn't make much sense here, as this is the

sorry , that is typo, I mean "t" here.

if t == 0 , return 0. because 0 is a valid value of pretimeout.

> value we are trying to set. Effectively the above accepts every pretimeout
> if wdd->pretimeout is 0. It also accepts every pretimeout if
> max_pretimeout == 0, even if wdd->timeout is set and t >= wdd->timeout.
>
> Try
>
>         return (wdd->max_pretimeout && (t < wdd->min_pretimeout ||
>                                         t > wdd->max_pretimeout)) ||
>                 (wdd->timeout && t >= wdd->timeout);
>
>>   }

/*
 * Use the following function to check if a pretimeout value is invalid.
 * It can be "0", that means we don't use pretimeout.
 * This function returns 0, when pretimeout is 0.
 */
static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd,
                           unsigned int t)
{
    return t && (wdd->max_pretimeout &&
        (t < wdd->min_pretimeout || t > wdd->max_pretimeout)) ||
           (wdd->timeout && t >= wdd->timeout);
}


>>
>>   /* Use the following functions to manipulate watchdog driver specific
>> data */
>> @@ -132,11 +153,20 @@ 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);
>> +int watchdog_init_timeouts(struct watchdog_device *wdd,
>> +                                 unsigned int pretimeout_parm,
>> +                                 unsigned int timeout_parm,
>> +                                 struct device *dev);
>
>
> Please align continuation lines with '('.

Fixed , thanks

>
>
>>   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, dev);
>> +}
>> +
>>   #ifdef CONFIG_HARDLOCKUP_DETECTOR
>>   void watchdog_nmi_disable_all(void);
>>   void watchdog_nmi_enable_all(void);
>>
>



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [non-pretimeout,4/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-10 17:47   ` [PATCH non-pretimeout 4/7] Watchdog: introduce ARM SBSA watchdog driver fu.wei
  2015-06-11  5:33       ` Guenter Roeck
@ 2015-06-11 16:28     ` Guenter Roeck
  2015-06-23 13:26       ` Fu Wei
  2015-06-12  3:57       ` Timur Tabi
  2 siblings, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-06-11 16:28 UTC (permalink / raw)
  To: fu.wei
  Cc: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, tekkamanninja, graeme.gregory, al.stone,
	hanjun.guo, timur, ashwin.chaugule, arnd, vgandhi, wim, jcm,
	leo.duran, corbet, mark.rutland, catalin.marinas, will.deacon,
	rjw

On Thu, Jun 11, 2015 at 01:47:29AM +0800, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> This driver bases on linux kernel watchdog framework.
> It supports getting timeout from parameter and FDT
> at the driver init stage.
> The first timeout period expires, the interrupt routine
> got another timeout period to run panic for saving
> system context.
> 
Comments inline.

Thanks,
Guenter

> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  drivers/watchdog/Kconfig     |  11 ++
>  drivers/watchdog/Makefile    |   1 +
>  drivers/watchdog/sbsa_gwdt.c | 383 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 395 insertions(+)
>  create mode 100644 drivers/watchdog/sbsa_gwdt.c
> 
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index e5e7c55..554f18a 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -152,6 +152,17 @@ 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 ARM64
> +	depends on ARM_ARCH_TIMER
> +	select WATCHDOG_CORE
> +	help
> +	  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.
> +	  More details: ARM DEN0029B - Server Base System Architecture (SBSA)
> +
	  To compile this driver as module, choose M here: The module
	  will be called sbsa_gwdt.

>  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..1ddc10f
> --- /dev/null
> +++ b/drivers/watchdog/sbsa_gwdt.c
> @@ -0,0 +1,383 @@
> +/*
> + * SBSA(Server Base System Architecture) Generic Watchdog driver
> + *
> + * Copyright (c) 2015, Linaro Ltd.
> + * Author: Fu Wei <fu.wei@linaro.org>
> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> + *
> + * 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 has two stage timeouts,

s/This/The/

"has two stages".

I would suggest to drop "Note:", but that is up to you.

> + *       When the first timeout occurs, WS0(SPI or LPI) is triggered,
> + *       the second timeout period(as long as the first timeout period) starts.

no longer accurate if WOR is used for the second period.

> + *       In WS0 interrupt routine, panic() will be called for collecting
> + *       crashdown info.
> + *       If system can not recover from WS0 interrupt routine, then second
> + *       timeout occurs, WS1(reset or higher level interrupt) is triggered.
> + *       The two timeout period can be set by WOR(32bit).

The second timeout period is determined by ...

> + *       WOR gives a maximum watch period of around 10s at the maximum
> + *       system counter frequency.
> + *       The System Counter shall run at maximum of 400MHz.

"... at the maximum system counter frequency of 400 MHz.", and drop the
last sentence.

Please uses spaces before '('.

> + *
> + *       But If we need a larger timeout period, this driver will programme WCV

s/But //
s/this/the/
s/programme/program/

> + *       directly. That can support more than 10s timeout at the maximum
> + *       system counter frequency.

Drop the last sentence.

> + *       More details: ARM DEN0029B - Server Base System Architecture (SBSA)
> + *
> + * SBSA GWDT:    |---WOR(or WCV)---WS0---WOR(or WCV)---WS1
> + *               |-----timeout-----WS0-----timeout-----WS1
> + */
> +
> +#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>
> +#include <asm/arch_timer.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.
> + * @max_wor_timeout:	the maximum timeout value for WOR (in seconds).
> + * @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;
> +	int			max_wor_timeout;
> +	void __iomem		*refresh_base;
> +	void __iomem		*control_base;
> +};
> +
> +#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
> +
> +#define DEFAULT_TIMEOUT		30 /* seconds */
> +
> +static unsigned int timeout;
> +module_param(timeout, uint, 0);
> +MODULE_PARM_DESC(timeout,
> +		 "Watchdog timeout in seconds. (>=0, default="
> +		 __MODULE_STRING(DEFAULT_TIMEOUT) ")");
> +
> +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) ")");
> +
> +/*
> + * help functions for accessing 64bit WCV register
> + */
> +static u64 sbsa_gwdt_get_wcv(struct watchdog_device *wdd)
> +{
> +	u32 wcv_lo, wcv_hi;
> +	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +
> +	do {
> +		wcv_hi = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_HI);
> +		wcv_lo = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_LO);
> +	} while (wcv_hi != readl_relaxed(gwdt->control_base +
> +					 SBSA_GWDT_WCV_HI));
> +
> +	return (((u64)wcv_hi << 32) | wcv_lo);
> +}
> +
> +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 * gwdt->clk;
> +
> +	writel_relaxed(upper_32_bits(wcv),
> +		       gwdt->control_base + SBSA_GWDT_WCV_HI);
> +	writel_relaxed(lower_32_bits(wcv),
> +		       gwdt->control_base + SBSA_GWDT_WCV_LO);
> +}
> +
> +static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
> +				 unsigned int timeout)
> +{
> +	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +
> +	wdd->timeout = timeout;
> +
> +	if (timeout <= gwdt->max_wor_timeout)
> +		writel_relaxed(timeout * gwdt->clk,
> +			       gwdt->control_base + SBSA_GWDT_WOR);
> +	else
> +		writel_relaxed(gwdt->max_wor_timeout * gwdt->clk,
> +			       gwdt->control_base + SBSA_GWDT_WOR);
> +

This can be simplified a bit to
	if (timeout > gwdt->max_wor_timeout)
		timeout = gwdt->max_wor_timeout;
	writel_relaxed(timeout * gwdt->clk,
		       gwdt->control_base + SBSA_GWDT_WOR);

> +	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_keepalive(struct watchdog_device *wdd)
> +{
> +	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +
> +	if (wdd->timeout <= gwdt->max_wor_timeout)
> +		/*
> +		 * Writing WRR for an explicit watchdog refresh.
> +		 * You can write anyting(like 0xc0ffee).
> +		 */
> +		writel_relaxed(0xc0ffee, gwdt->refresh_base + SBSA_GWDT_WRR);
> +	else
> +		reload_timeout_to_wcv(wdd);
> +
> +	return 0;
> +}
> +
> +static int sbsa_gwdt_start(struct watchdog_device *wdd)
> +{
> +	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +	/* Force refresh due to hardware bug found in certain Soc. */

Can you specify which SOC(s) are known to need this, and explain the bug
a bit better ?

> +	writel_relaxed(0xc0ffee, gwdt->refresh_base + SBSA_GWDT_WRR);
> +	/* writing WCS will cause an explicit watchdog refresh */
> +	writel_relaxed(SBSA_GWDT_WCS_EN, gwdt->control_base + SBSA_GWDT_WCS);
> +
> +	return sbsa_gwdt_keepalive(wdd);
> +}
> +
> +static int sbsa_gwdt_stop(struct watchdog_device *wdd)
> +{
> +	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +
> +	writel_relaxed(0, gwdt->control_base + SBSA_GWDT_WCS);
> +
> +	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;
> +
> +	if (wdd->timeout > gwdt->max_wor_timeout)
> +		reload_timeout_to_wcv(wdd);
> +
Please drop the above.

> +	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_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,
> +	.get_timeleft	= sbsa_gwdt_get_timeleft,
> +};
> +
> +static int sbsa_gwdt_probe(struct platform_device *pdev)
> +{
> +	u64 first_period_max = U64_MAX;
> +	struct device *dev = &pdev->dev;
> +	struct watchdog_device *wdd;
> +	struct sbsa_gwdt *gwdt;
> +	struct resource *res;
> +	void *rf_base, *cf_base;
> +	int ret, irq;
> +	u32 status;
> +
> +	gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
> +	if (!gwdt)
> +		return -ENOMEM;
> +	platform_set_drvdata(pdev, gwdt);
> +
> +	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(cf_base))
> +		return PTR_ERR(cf_base);
> +
> +	irq = platform_get_irq_byname(pdev, "ws0");
> +	if (irq < 0) {
> +		dev_err(dev, "unable to get ws0 interrupt.\n");
> +		return irq;
> +	}
> +
> +	/*
> +	 * Get the frequency of system counter from the cp15 interface of ARM
> +	 * Generic timer. We don't need to check it, because if it returns "0",
> +	 * system would panic in very early stage.
> +	 */
> +	gwdt->clk = arch_timer_get_cntfrq();
> +	gwdt->refresh_base = rf_base;
> +	gwdt->control_base = cf_base;
> +	gwdt->max_wor_timeout = U32_MAX / gwdt->clk;
> +
> +	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);
> +
> +	wdd->min_timeout = 1;
> +	do_div(first_period_max, gwdt->clk);
> +	wdd->max_timeout = first_period_max;
> +
> +	wdd->timeout = DEFAULT_TIMEOUT;
> +	watchdog_init_timeout(wdd, timeout, dev);
> +
> +	status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
> +	if (status & SBSA_GWDT_WCS_WS1) {
> +		dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
> +			 sbsa_gwdt_get_wcv(wdd));

WCV here only tells us how many clock cycles were executed since the
system started (or something like that). So I still don't understand
why it is valuable to print that number.

> +		wdd->bootstatus |= WDIOF_CARDRESET;
> +	}
> +	/* Check if watchdog is already enabled */
> +	if (status & SBSA_GWDT_WCS_EN) {
> +		dev_warn(dev, "already enabled\n");
> +		sbsa_gwdt_keepalive(wdd);
> +	}

Can you merge the message with the info message below ?
Something like
	dev_info(dev, "Initialized with %ds timeout @ %u Hz%s\n", wdd->timeout,
		 gwdt->clk, status & SBSA_GWDT_WCS_EN ? " [enabled]" : "");

I don't think that should be a warning.

> +
> +	/* update timeout to WOR */
> +	sbsa_gwdt_set_timeout(wdd, wdd->timeout);
> +

That will trigger a refresh if the watchdog is active, meaning the timeout
will occur at time + WOR, not at time + timeout. I think keepalive has to be
called later, preferrably after calling watchdog_register_device().

> +	ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
> +			       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 @ %u Hz\n", wdd->timeout,
> +		 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);
> +
> +	watchdog_unregister_device(&gwdt->wdd);
> +
> +	return 0;
> +}
> +
> +/* 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");

Version numbers tend to be out of date constantly, and there is no well
defined mechanism or protocol when increase them. I would suggest to drop it.

> +MODULE_AUTHOR("Fu Wei <fu.wei@linaro.org>");
> +MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
> +MODULE_LICENSE("GPL v2");

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v5 4/8] Watchdog: introdouce "pretimeout" into framework
@ 2015-06-11 16:38           ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-11 16:38 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

On Thu, Jun 11, 2015 at 07:22:44PM +0800, Fu Wei wrote:
> Hi Guenter,
> 
[ ... ]
> 
> > value we are trying to set. Effectively the above accepts every pretimeout
> > if wdd->pretimeout is 0. It also accepts every pretimeout if
> > max_pretimeout == 0, even if wdd->timeout is set and t >= wdd->timeout.
> >
> > Try
> >
> >         return (wdd->max_pretimeout && (t < wdd->min_pretimeout ||
> >                                         t > wdd->max_pretimeout)) ||
> >                 (wdd->timeout && t >= wdd->timeout);
> >
> >>   }
> 
> /*
>  * Use the following function to check if a pretimeout value is invalid.
>  * It can be "0", that means we don't use pretimeout.
>  * This function returns 0, when pretimeout is 0.

returns false if pretimeout is 0.

>  */
> static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd,
>                            unsigned int t)
> {
>     return t && (wdd->max_pretimeout &&
>         (t < wdd->min_pretimeout || t > wdd->max_pretimeout)) ||
>            (wdd->timeout && t >= wdd->timeout);
> }
> 
Makes sense. Be careful with (), though. This evaluates to

	return t && (...) || (wdd->timeout && t >= wdd->timeout);

but it should probably be
	return t && ((...) || (wdd->timeout && t >= wdd->timeout));

That doesn't make a difference in practice (if t == 0, it is never >= timeout
if timeout is > 0), but it would be a bit cleaner.

> 
> >>
> >>   /* Use the following functions to manipulate watchdog driver specific
> >> data */
> >> @@ -132,11 +153,20 @@ 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);
> >> +int watchdog_init_timeouts(struct watchdog_device *wdd,
> >> +                                 unsigned int pretimeout_parm,
> >> +                                 unsigned int timeout_parm,
> >> +                                 struct device *dev);
> >
> >
> > Please align continuation lines with '('.
> 
> Fixed , thanks
> 
> >
> >
> >>   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, dev);
> >> +}
> >> +
> >>   #ifdef CONFIG_HARDLOCKUP_DETECTOR
> >>   void watchdog_nmi_disable_all(void);
> >>   void watchdog_nmi_enable_all(void);
> >>
> >
> 
> 
> 
> -- 
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v5 4/8] Watchdog: introdouce "pretimeout" into framework
@ 2015-06-11 16:38           ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-11 16:38 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon,
	rjw-LthD3rsA81gm4RdzfppkhA

On Thu, Jun 11, 2015 at 07:22:44PM +0800, Fu Wei wrote:
> Hi Guenter,
> 
[ ... ]
> 
> > value we are trying to set. Effectively the above accepts every pretimeout
> > if wdd->pretimeout is 0. It also accepts every pretimeout if
> > max_pretimeout == 0, even if wdd->timeout is set and t >= wdd->timeout.
> >
> > Try
> >
> >         return (wdd->max_pretimeout && (t < wdd->min_pretimeout ||
> >                                         t > wdd->max_pretimeout)) ||
> >                 (wdd->timeout && t >= wdd->timeout);
> >
> >>   }
> 
> /*
>  * Use the following function to check if a pretimeout value is invalid.
>  * It can be "0", that means we don't use pretimeout.
>  * This function returns 0, when pretimeout is 0.

returns false if pretimeout is 0.

>  */
> static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd,
>                            unsigned int t)
> {
>     return t && (wdd->max_pretimeout &&
>         (t < wdd->min_pretimeout || t > wdd->max_pretimeout)) ||
>            (wdd->timeout && t >= wdd->timeout);
> }
> 
Makes sense. Be careful with (), though. This evaluates to

	return t && (...) || (wdd->timeout && t >= wdd->timeout);

but it should probably be
	return t && ((...) || (wdd->timeout && t >= wdd->timeout));

That doesn't make a difference in practice (if t == 0, it is never >= timeout
if timeout is > 0), but it would be a bit cleaner.

> 
> >>
> >>   /* Use the following functions to manipulate watchdog driver specific
> >> data */
> >> @@ -132,11 +153,20 @@ 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);
> >> +int watchdog_init_timeouts(struct watchdog_device *wdd,
> >> +                                 unsigned int pretimeout_parm,
> >> +                                 unsigned int timeout_parm,
> >> +                                 struct device *dev);
> >
> >
> > Please align continuation lines with '('.
> 
> Fixed , thanks
> 
> >
> >
> >>   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, dev);
> >> +}
> >> +
> >>   #ifdef CONFIG_HARDLOCKUP_DETECTOR
> >>   void watchdog_nmi_disable_all(void);
> >>   void watchdog_nmi_enable_all(void);
> >>
> >
> 
> 
> 
> -- 
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 4/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-12  3:57       ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-12  3:57 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw

fu.wei@linaro.org wrote:
> +	if (timeout <= gwdt->max_wor_timeout)
> +		writel_relaxed(timeout * gwdt->clk,
> +			       gwdt->control_base + SBSA_GWDT_WOR);
> +	else
> +		writel_relaxed(gwdt->max_wor_timeout * gwdt->clk,
> +			       gwdt->control_base + SBSA_GWDT_WOR);

You pre-calculate the maximum timeout possible already, so why do you 
need the if-statement?

Frankly, your non-pretimeout driver is almost identical to mine, which 
was posted weeks ago.  At this point, you're really just copying my 
driver but putting your name on it.

-- 
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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 4/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-12  3:57       ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-12  3:57 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA

fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> +	if (timeout <= gwdt->max_wor_timeout)
> +		writel_relaxed(timeout * gwdt->clk,
> +			       gwdt->control_base + SBSA_GWDT_WOR);
> +	else
> +		writel_relaxed(gwdt->max_wor_timeout * gwdt->clk,
> +			       gwdt->control_base + SBSA_GWDT_WOR);

You pre-calculate the maximum timeout possible already, so why do you 
need the if-statement?

Frankly, your non-pretimeout driver is almost identical to mine, which 
was posted weeks ago.  At this point, you're really just copying my 
driver but putting your name on it.

-- 
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.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 6/7] Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
  2015-06-10 17:47     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  (?)
@ 2015-06-12 13:16     ` Timur Tabi
  -1 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-12 13:16 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw

fu.wei@linaro.org wrote:
> This patch enables ACPI GTDT support for ARM SBSA
> watchdog driver automatically, if ACPI support is enabled.

You don't need this patch if you reorder your patches, like this:

#4 ACPI: add GTDT table parse driver into ACPI driver
#5 Watchdog: introduce ARM SBSA watchdog driver

And then this patch becomes part of patch #5.

-- 
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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 3/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
@ 2015-06-12 20:54       ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-12 20:54 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw

On 06/10/2015 12:47 PM, fu.wei@linaro.org wrote:
> +			reg = <0x0 0xe0bb0000 0 0x10000>,
> +				<0x0 0xe0bc0000 0 0x10000>;

I think the sizes are wrong.  They should be 0x1000 instead of 0x10000.

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 3/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
@ 2015-06-12 20:54       ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-12 20:54 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A, Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA

On 06/10/2015 12:47 PM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> +			reg = <0x0 0xe0bb0000 0 0x10000>,
> +				<0x0 0xe0bc0000 0 0x10000>;

I think the sizes are wrong.  They should be 0x1000 instead of 0x10000.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 3/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
  2015-06-12 20:54       ` Timur Tabi
  (?)
@ 2015-06-14 10:05       ` Fu Wei
  2015-06-14 13:17           ` Timur Tabi
  2015-06-14 13:57         ` Guenter Roeck
  -1 siblings, 2 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-14 10:05 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

On 13 June 2015 at 04:54, Timur Tabi <timur@codeaurora.org> wrote:
> On 06/10/2015 12:47 PM, fu.wei@linaro.org wrote:
>>
>> +                       reg = <0x0 0xe0bb0000 0 0x10000>,
>> +                               <0x0 0xe0bc0000 0 0x10000>;
>
>
> I think the sizes are wrong.  They should be 0x1000 instead of 0x10000.

This has been proved by test, it works well on Seattle
Foundation model has same value. So I don't think it is wrong

otherwise someone has the data sheet of Seattle B0, and it shows that is wrong.


>
> --
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 4/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-14 10:15         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-14 10:15 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

Hi Timur

On 12 June 2015 at 11:57, Timur Tabi <timur@codeaurora.org> wrote:
> fu.wei@linaro.org wrote:
>>
>> +       if (timeout <= gwdt->max_wor_timeout)
>> +               writel_relaxed(timeout * gwdt->clk,
>> +                              gwdt->control_base + SBSA_GWDT_WOR);
>> +       else
>> +               writel_relaxed(gwdt->max_wor_timeout * gwdt->clk,
>> +                              gwdt->control_base + SBSA_GWDT_WOR);
>
>
> You pre-calculate the maximum timeout possible already, so why do you need
> the if-statement?

Have took Guenter's suggestion on this.

>
> Frankly, your non-pretimeout driver is almost identical to mine, which was
> posted weeks ago.  At this point, you're really just copying my driver but
> putting your name on it.

Everyone can see how this driver become to this one gradually. For
non-pretimeout, if there is not pretimeout variable, I can only use
timeout to config both of them.
This is  definitely not the copy of yours(check yours again, you never
programme WCV, and from the comment from you , you didn't believe
driver can do that. you use panic because of my patch),  and I posted
my patchset(with pretimeout) to linaro-acpi list before you posted
yours to linux mailing list.  And I always focus on mine.

Let people judge from all these patchset, I don't want to argue with
you on this any more.


>
>
> --
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 4/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-14 10:15         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-14 10:15 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon,
	rjw-LthD3rsA81gm4RdzfppkhA

Hi Timur

On 12 June 2015 at 11:57, Timur Tabi <timur-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
> fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>>
>> +       if (timeout <= gwdt->max_wor_timeout)
>> +               writel_relaxed(timeout * gwdt->clk,
>> +                              gwdt->control_base + SBSA_GWDT_WOR);
>> +       else
>> +               writel_relaxed(gwdt->max_wor_timeout * gwdt->clk,
>> +                              gwdt->control_base + SBSA_GWDT_WOR);
>
>
> You pre-calculate the maximum timeout possible already, so why do you need
> the if-statement?

Have took Guenter's suggestion on this.

>
> Frankly, your non-pretimeout driver is almost identical to mine, which was
> posted weeks ago.  At this point, you're really just copying my driver but
> putting your name on it.

Everyone can see how this driver become to this one gradually. For
non-pretimeout, if there is not pretimeout variable, I can only use
timeout to config both of them.
This is  definitely not the copy of yours(check yours again, you never
programme WCV, and from the comment from you , you didn't believe
driver can do that. you use panic because of my patch),  and I posted
my patchset(with pretimeout) to linaro-acpi list before you posted
yours to linux mailing list.  And I always focus on mine.

Let people judge from all these patchset, I don't want to argue with
you on this any more.


>
>
> --
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 3/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
@ 2015-06-14 13:17           ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-14 13:17 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

Fu Wei wrote:
>> >I think the sizes are wrong.  They should be 0x1000 instead of 0x10000.
> This has been proved by test, it works well on Seattle
> Foundation model has same value. So I don't think it is wrong
>
> otherwise someone has the data sheet of Seattle B0, and it shows that is wrong.

The registers block is only 0x1000 bytes long.  So you're wasting 63KB 
of virtual address space for each block.

-- 
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.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 3/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
@ 2015-06-14 13:17           ` Timur Tabi
  0 siblings, 0 replies; 550+ messages in thread
From: Timur Tabi @ 2015-06-14 13:17 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon,
	rjw-LthD3rsA81gm4RdzfppkhA

Fu Wei wrote:
>> >I think the sizes are wrong.  They should be 0x1000 instead of 0x10000.
> This has been proved by test, it works well on Seattle
> Foundation model has same value. So I don't think it is wrong
>
> otherwise someone has the data sheet of Seattle B0, and it shows that is wrong.

The registers block is only 0x1000 bytes long.  So you're wasting 63KB 
of virtual address space for each block.

-- 
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.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 3/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
  2015-06-14 10:05       ` Fu Wei
  2015-06-14 13:17           ` Timur Tabi
@ 2015-06-14 13:57         ` Guenter Roeck
  2015-06-15 11:00           ` Fu Wei
  1 sibling, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-06-14 13:57 UTC (permalink / raw)
  To: Fu Wei, Timur Tabi
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, rjw

On 06/14/2015 03:05 AM, Fu Wei wrote:
> On 13 June 2015 at 04:54, Timur Tabi <timur@codeaurora.org> wrote:
>> On 06/10/2015 12:47 PM, fu.wei@linaro.org wrote:
>>>
>>> +                       reg = <0x0 0xe0bb0000 0 0x10000>,
>>> +                               <0x0 0xe0bc0000 0 0x10000>;
>>
>>
>> I think the sizes are wrong.  They should be 0x1000 instead of 0x10000.
>
> This has been proved by test, it works well on Seattle
> Foundation model has same value. So I don't think it is wrong
>
> otherwise someone has the data sheet of Seattle B0, and it shows that is wrong.
>

If only 0x1000 is used, why would you have to reserve 0x10000 ?
You never access any higher addresses, so no matter what the datasheet
says, 0x1000 should be sufficient. What matters is what the driver uses.

Guenter



^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH non-pretimeout 3/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
  2015-06-14 13:57         ` Guenter Roeck
@ 2015-06-15 11:00           ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-15 11:00 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Timur Tabi, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

Hi Guenter,

On 14 June 2015 at 21:57, Guenter Roeck <linux@roeck-us.net> wrote:
> On 06/14/2015 03:05 AM, Fu Wei wrote:
>>
>> On 13 June 2015 at 04:54, Timur Tabi <timur@codeaurora.org> wrote:
>>>
>>> On 06/10/2015 12:47 PM, fu.wei@linaro.org wrote:
>>>>
>>>>
>>>> +                       reg = <0x0 0xe0bb0000 0 0x10000>,
>>>> +                               <0x0 0xe0bc0000 0 0x10000>;
>>>
>>>
>>>
>>> I think the sizes are wrong.  They should be 0x1000 instead of 0x10000.
>>
>>
>> This has been proved by test, it works well on Seattle
>> Foundation model has same value. So I don't think it is wrong
>>
>> otherwise someone has the data sheet of Seattle B0, and it shows that is
>> wrong.
>>
>
> If only 0x1000 is used, why would you have to reserve 0x10000 ?
> You never access any higher addresses, so no matter what the datasheet
> says, 0x1000 should be sufficient. What matters is what the driver uses.

the reason for using 0x10000 before is :
(1)in <ARM v8-A Foundation Platform User Guide(Version: 9.1)> page 20
0x00_2A44_0000 0x00_2A44_FFFF - EL2 Generic Watchdog Control 64KB S/NS
0x00_2A45_0000 0x00_2A45_FFFF - EL2 Generic Watchdog Refresh 64KB S/NS
(2)It is also confirmed by Suravee, in Seattle,  the size is 64KB also.
(3) these configuration has passed the test in Foundation model and Seattle B0.

Not sure the reason, maybe because of the 64KB page size.

But, yes, in SBSA, the device only has 4KB register area, and the
driver only need to use 4KB.

So you are right,  "What matters is what the driver uses." , so will use 0x1000.
I think there is not problem, because ACPI uses this size.


>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [non-pretimeout,4/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-11 16:28     ` [non-pretimeout,4/7] " Guenter Roeck
@ 2015-06-23 13:26       ` Fu Wei
  2015-06-23 15:21           ` Guenter Roeck
  0 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-06-23 13:26 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

Hi Guenter,

On 12 June 2015 at 00:28, Guenter Roeck <linux@roeck-us.net> wrote:
> On Thu, Jun 11, 2015 at 01:47:29AM +0800, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> This driver bases on linux kernel watchdog framework.
>> It supports getting timeout from parameter and FDT
>> at the driver init stage.
>> The first timeout period expires, the interrupt routine
>> got another timeout period to run panic for saving
>> system context.
>>
> Comments inline.
>
> Thanks,
> Guenter
>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  drivers/watchdog/Kconfig     |  11 ++
>>  drivers/watchdog/Makefile    |   1 +
>>  drivers/watchdog/sbsa_gwdt.c | 383 +++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 395 insertions(+)
>>  create mode 100644 drivers/watchdog/sbsa_gwdt.c
>>
>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>> index e5e7c55..554f18a 100644
>> --- a/drivers/watchdog/Kconfig
>> +++ b/drivers/watchdog/Kconfig
>> @@ -152,6 +152,17 @@ 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 ARM64
>> +     depends on ARM_ARCH_TIMER
>> +     select WATCHDOG_CORE
>> +     help
>> +       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.
>> +       More details: ARM DEN0029B - Server Base System Architecture (SBSA)
>> +
>           To compile this driver as module, choose M here: The module
>           will be called sbsa_gwdt.

Thanks! added it.

>
>>  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..1ddc10f
>> --- /dev/null
>> +++ b/drivers/watchdog/sbsa_gwdt.c
>> @@ -0,0 +1,383 @@
>> +/*
>> + * SBSA(Server Base System Architecture) Generic Watchdog driver
>> + *
>> + * Copyright (c) 2015, Linaro Ltd.
>> + * Author: Fu Wei <fu.wei@linaro.org>
>> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>> + *
>> + * 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 has two stage timeouts,
>
> s/This/The/
>
> "has two stages".
>
> I would suggest to drop "Note:", but that is up to you.

Thanks :-)  fixed it

>
>> + *       When the first timeout occurs, WS0(SPI or LPI) is triggered,
>> + *       the second timeout period(as long as the first timeout period) starts.
>
> no longer accurate if WOR is used for the second period.
>
>> + *       In WS0 interrupt routine, panic() will be called for collecting
>> + *       crashdown info.
>> + *       If system can not recover from WS0 interrupt routine, then second
>> + *       timeout occurs, WS1(reset or higher level interrupt) is triggered.
>> + *       The two timeout period can be set by WOR(32bit).
>
> The second timeout period is determined by ...
>
>> + *       WOR gives a maximum watch period of around 10s at the maximum
>> + *       system counter frequency.
>> + *       The System Counter shall run at maximum of 400MHz.
>
> "... at the maximum system counter frequency of 400 MHz.", and drop the
> last sentence.

For the second timeout period,  I have discussed with a kdump developers,
(1)10s maybe not good enough for all the case of panic + kdump, so
maybe we still need to use WCV in the second timeout period
(2)in the second timeout period, maybe we need to programme WCV for
two reason: a, trigger WS1 to reboot system ASAP; b, feed the watchdog
without cleanning WS0 flag.

WHY we want to feed the watchdog (keepalive) without cleanning WS0 flag??
REASON:
(1)if the system context is large, we may need to feed the dog until
we get all the things backed up.
(2)if system goes wrong,  WS0 triggered, then panic--> kdump. if we
feed the dog by WRR or programming WOR, WS0 flag will be cleaned. Once
system goes wrong again, then panic again.....
So this system will be in a panic--kdump--panic--kdump loop, have not
chance to reset.

So if we are in the second timeout period, we may need to always programme WCV.

>
> Please uses spaces before '('.
>
>> + *
>> + *       But If we need a larger timeout period, this driver will programme WCV
>
> s/But //
> s/this/the/
> s/programme/program/
>
>> + *       directly. That can support more than 10s timeout at the maximum
>> + *       system counter frequency.
>
> Drop the last sentence.

Thanks , fixed it

>
>> + *       More details: ARM DEN0029B - Server Base System Architecture (SBSA)
>> + *
>> + * SBSA GWDT:    |---WOR(or WCV)---WS0---WOR(or WCV)---WS1
>> + *               |-----timeout-----WS0-----timeout-----WS1
>> + */
>> +
>> +#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>
>> +#include <asm/arch_timer.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.
>> + * @max_wor_timeout: the maximum timeout value for WOR (in seconds).
>> + * @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;
>> +     int                     max_wor_timeout;
>> +     void __iomem            *refresh_base;
>> +     void __iomem            *control_base;
>> +};
>> +
>> +#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
>> +
>> +#define DEFAULT_TIMEOUT              30 /* seconds */
>> +
>> +static unsigned int timeout;
>> +module_param(timeout, uint, 0);
>> +MODULE_PARM_DESC(timeout,
>> +              "Watchdog timeout in seconds. (>=0, default="
>> +              __MODULE_STRING(DEFAULT_TIMEOUT) ")");
>> +
>> +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) ")");
>> +
>> +/*
>> + * help functions for accessing 64bit WCV register
>> + */
>> +static u64 sbsa_gwdt_get_wcv(struct watchdog_device *wdd)
>> +{
>> +     u32 wcv_lo, wcv_hi;
>> +     struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> +
>> +     do {
>> +             wcv_hi = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_HI);
>> +             wcv_lo = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_LO);
>> +     } while (wcv_hi != readl_relaxed(gwdt->control_base +
>> +                                      SBSA_GWDT_WCV_HI));
>> +
>> +     return (((u64)wcv_hi << 32) | wcv_lo);
>> +}
>> +
>> +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 * gwdt->clk;
>> +
>> +     writel_relaxed(upper_32_bits(wcv),
>> +                    gwdt->control_base + SBSA_GWDT_WCV_HI);
>> +     writel_relaxed(lower_32_bits(wcv),
>> +                    gwdt->control_base + SBSA_GWDT_WCV_LO);
>> +}
>> +
>> +static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
>> +                              unsigned int timeout)
>> +{
>> +     struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> +
>> +     wdd->timeout = timeout;
>> +
>> +     if (timeout <= gwdt->max_wor_timeout)
>> +             writel_relaxed(timeout * gwdt->clk,
>> +                            gwdt->control_base + SBSA_GWDT_WOR);
>> +     else
>> +             writel_relaxed(gwdt->max_wor_timeout * gwdt->clk,
>> +                            gwdt->control_base + SBSA_GWDT_WOR);
>> +
>
> This can be simplified a bit to
>         if (timeout > gwdt->max_wor_timeout)
>                 timeout = gwdt->max_wor_timeout;
>         writel_relaxed(timeout * gwdt->clk,
>                        gwdt->control_base + SBSA_GWDT_WOR);

yes, good idea, thanks , fixed

>
>> +     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_keepalive(struct watchdog_device *wdd)
>> +{
>> +     struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> +
>> +     if (wdd->timeout <= gwdt->max_wor_timeout)
>> +             /*
>> +              * Writing WRR for an explicit watchdog refresh.
>> +              * You can write anyting(like 0xc0ffee).
>> +              */
>> +             writel_relaxed(0xc0ffee, gwdt->refresh_base + SBSA_GWDT_WRR);
>> +     else
>> +             reload_timeout_to_wcv(wdd);
>> +
>> +     return 0;
>> +}
>> +
>> +static int sbsa_gwdt_start(struct watchdog_device *wdd)
>> +{
>> +     struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> +     /* Force refresh due to hardware bug found in certain Soc. */
>
> Can you specify which SOC(s) are known to need this, and explain the bug
> a bit better ?

please ignore this, I have deleted it after discussing this with the
engineer of that chip vendor.
we don't need it now.

>
>> +     writel_relaxed(0xc0ffee, gwdt->refresh_base + SBSA_GWDT_WRR);
>> +     /* writing WCS will cause an explicit watchdog refresh */
>> +     writel_relaxed(SBSA_GWDT_WCS_EN, gwdt->control_base + SBSA_GWDT_WCS);
>> +
>> +     return sbsa_gwdt_keepalive(wdd);
>> +}
>> +
>> +static int sbsa_gwdt_stop(struct watchdog_device *wdd)
>> +{
>> +     struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> +
>> +     writel_relaxed(0, gwdt->control_base + SBSA_GWDT_WCS);
>> +
>> +     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;
>> +
>> +     if (wdd->timeout > gwdt->max_wor_timeout)
>> +             reload_timeout_to_wcv(wdd);
>> +
> Please drop the above.

as I mentioned above, I thinks we can keep this.
But please check my new patchset for this support

>
>> +     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_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,
>> +     .get_timeleft   = sbsa_gwdt_get_timeleft,
>> +};
>> +
>> +static int sbsa_gwdt_probe(struct platform_device *pdev)
>> +{
>> +     u64 first_period_max = U64_MAX;
>> +     struct device *dev = &pdev->dev;
>> +     struct watchdog_device *wdd;
>> +     struct sbsa_gwdt *gwdt;
>> +     struct resource *res;
>> +     void *rf_base, *cf_base;
>> +     int ret, irq;
>> +     u32 status;
>> +
>> +     gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
>> +     if (!gwdt)
>> +             return -ENOMEM;
>> +     platform_set_drvdata(pdev, gwdt);
>> +
>> +     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(cf_base))
>> +             return PTR_ERR(cf_base);
>> +
>> +     irq = platform_get_irq_byname(pdev, "ws0");
>> +     if (irq < 0) {
>> +             dev_err(dev, "unable to get ws0 interrupt.\n");
>> +             return irq;
>> +     }
>> +
>> +     /*
>> +      * Get the frequency of system counter from the cp15 interface of ARM
>> +      * Generic timer. We don't need to check it, because if it returns "0",
>> +      * system would panic in very early stage.
>> +      */
>> +     gwdt->clk = arch_timer_get_cntfrq();
>> +     gwdt->refresh_base = rf_base;
>> +     gwdt->control_base = cf_base;
>> +     gwdt->max_wor_timeout = U32_MAX / gwdt->clk;
>> +
>> +     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);
>> +
>> +     wdd->min_timeout = 1;
>> +     do_div(first_period_max, gwdt->clk);
>> +     wdd->max_timeout = first_period_max;
>> +
>> +     wdd->timeout = DEFAULT_TIMEOUT;
>> +     watchdog_init_timeout(wdd, timeout, dev);
>> +
>> +     status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
>> +     if (status & SBSA_GWDT_WCS_WS1) {
>> +             dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
>> +                      sbsa_gwdt_get_wcv(wdd));
>
> WCV here only tells us how many clock cycles were executed since the
> system started (or something like that). So I still don't understand
> why it is valuable to print that number.

this number provides the time of system reset, I thinks that may help
admin to analyse the system failure.

>
>> +             wdd->bootstatus |= WDIOF_CARDRESET;
>> +     }
>> +     /* Check if watchdog is already enabled */
>> +     if (status & SBSA_GWDT_WCS_EN) {
>> +             dev_warn(dev, "already enabled\n");
>> +             sbsa_gwdt_keepalive(wdd);
>> +     }
>
> Can you merge the message with the info message below ?
> Something like
>         dev_info(dev, "Initialized with %ds timeout @ %u Hz%s\n", wdd->timeout,
>                  gwdt->clk, status & SBSA_GWDT_WCS_EN ? " [enabled]" : "");
>
> I don't think that should be a warning.

yes, good idea, will do

>
>> +
>> +     /* update timeout to WOR */
>> +     sbsa_gwdt_set_timeout(wdd, wdd->timeout);
>> +
>
> That will trigger a refresh if the watchdog is active, meaning the timeout
> will occur at time + WOR, not at time + timeout. I think keepalive has to be
> called later, preferrably after calling watchdog_register_device().

yes, you are right, will fix it

>
>> +     ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
>> +                            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 @ %u Hz\n", wdd->timeout,
>> +              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);
>> +
>> +     watchdog_unregister_device(&gwdt->wdd);
>> +
>> +     return 0;
>> +}
>> +
>> +/* 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");
>
> Version numbers tend to be out of date constantly, and there is no well
> defined mechanism or protocol when increase them. I would suggest to drop it.

Ok, will drop it

>
>> +MODULE_AUTHOR("Fu Wei <fu.wei@linaro.org>");
>> +MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
>> +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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v6 0/8] Watchdog: introduce ARM SBSA watchdog driver
       [not found] <=fu.wei@linaro.org>
                   ` (6 preceding siblings ...)
  2015-06-10 17:47   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
@ 2015-06-23 14:16 ` fu.wei
  2015-06-23 14:16     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                     ` (4 more replies)
  2015-06-23 15:59 ` [PATCH v6 5/8] " fu.wei
                   ` (6 subsequent siblings)
  14 siblings, 5 replies; 550+ messages in thread
From: fu.wei @ 2015-06-23 14:16 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, dyoung,
	panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patchset:
    (1)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.

    (2)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".

    (3)Introduce ARM SBSA watchdog driver:
        a.Use linux kernel watchdog framework;
        b.Work with FDT on ARM64;
        c.Use "pretimeout" in watchdog framework;
        d.Support getting timeout and pretimeout from parameter and FDT
          at the driver init stage.
        e.In the first timeout, do panic to save system context;
        f.In the second stage, user can still feed the dog without
          cleaning WS0. By this feature, we can avoid the panic infinite
          loops, while backing up a large system context in a server.
        g.In the second stage, can trigger WS1 by setting pretimeout = 0
          if necessary.

    (4)Introduce ACPI GTDT parser: drivers/acpi/gtdt.c
    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.
    drivers/clocksource/arm_arch_timer.c is simplified by this GTDT support.

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

Changelog:
v6: Improve the dtb example files: reduce the register frame size to 4K.
    Improve pretimeout support:
        (1) improve watchdog_init_timeouts function
	(2) rename watchdog_check_min_max_timeouts back to the original name
        (1) improve watchdog_timeout_invalid/watchdog_pretimeout_invalid
    Add the new features in the sbsa_gwdt driver:
	(1) In the second stage, user can feed the dog without cleaning WS0.
	(2) In the second stage, user can trigger WS1 by setting pretimeout = 0.
	(3) expand the max value of pretimeout, in case 10 second is not enough
	    for a kdump kernel reboot in panic.

v5: Improve pretimeout support:
        (1)fix typo in documentation and comments.
	(2)fix the timeout limits validation bug.
    Simplify sbsa_gwdt driver:
	(1)integrate all the registers access functions into caller.

v4: Refactor GTDT support code: remove it from arch/arm64/kernel/acpi.c,
    put it into drivers/acpi/gtdt.c file.
    Integrate the GTDT code of drivers/clocksource/arm_arch_timer.c into
    drivers/acpi/gtdt.c.
    Improve pretimeout support, fix "pretimeout == 0" problem.
    Simplify sbsa_gwdt driver:
        (1)timeout/pretimeout limits setup;
        (2)keepalive function;
        (3)delete "clk == 0" check;
        (4)delete WS0 status bit check in interrupt routine;
        (5)sbsa_gwdt_set_wcv function.

v3: Delete "export arch_timer_get_rate" patch.
    Driver back to use arch_timer_get_cntfrq.
    Improve watchdog_init_timeouts function and update relevant documentation.
    Improve watchdog_timeout_invalid and watchdog_pretimeout_invalid.
    Improve foundation-v8.dts: delete the unnecessary tag of device node.
    Remove "ARM64 || COMPILE_TEST" from Kconfig.
    Add comments in arch/arm64/kernel/acpi.c
    Fix typoes and incorrect comments.

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 (8):
  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: introdouce "pretimeout" into framework
  Watchdog: introduce ARM SBSA watchdog driver
  ACPI: add GTDT table parse driver into ACPI driver
  Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
  clocksource: simplify ACPI code in arm_arch_timer.c

 .../devicetree/bindings/watchdog/sbsa-gwdt.txt     |  36 ++
 Documentation/watchdog/watchdog-kernel-api.txt     |  47 ++-
 arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi       |  11 +
 arch/arm64/boot/dts/arm/foundation-v8.dts          |  10 +
 arch/arm64/kernel/time.c                           |   4 +-
 drivers/acpi/Kconfig                               |   9 +
 drivers/acpi/Makefile                              |   1 +
 drivers/acpi/gtdt.c                                | 180 ++++++++
 drivers/clocksource/Kconfig                        |   1 +
 drivers/clocksource/arm_arch_timer.c               |  60 +--
 drivers/watchdog/Kconfig                           |  15 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/sbsa_gwdt.c                       | 455 +++++++++++++++++++++
 drivers/watchdog/watchdog_core.c                   |  98 +++--
 drivers/watchdog/watchdog_dev.c                    |  53 +++
 include/clocksource/arm_arch_timer.h               |   8 +
 include/linux/acpi.h                               |   5 +
 include/linux/clocksource.h                        |   4 +-
 include/linux/watchdog.h                           |  39 +-
 19 files changed, 947 insertions(+), 90 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
 create mode 100644 drivers/acpi/gtdt.c
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

-- 
1.9.1


^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v6 1/8] Documentation: add sbsa-gwdt.txt documentation
@ 2015-06-23 14:16     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-23 14:16 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, dyoung,
	panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 .../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..010e5c4
--- /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@2a440000 {
+	compatible = "arm,sbsa-gwdt";
+	reg = <0x0 0x2a440000 0 0x1000>,
+	      <0x0 0x2a450000 0 0x1000>;
+	reg-names = "control", "refresh";
+	interrupts = <0 27 4>;
+	interrupt-names = "ws0";
+	timeout-sec = <10 5>;
+};
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v6 1/8] Documentation: add sbsa-gwdt.txt documentation
@ 2015-06-23 14:16     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-23 14:16 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA, panand-H+wXaHxf7aLQT0dZR+AlfA,
	Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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

Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 .../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..010e5c4
--- /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@2a440000 {
+	compatible = "arm,sbsa-gwdt";
+	reg = <0x0 0x2a440000 0 0x1000>,
+	      <0x0 0x2a450000 0 0x1000>;
+	reg-names = "control", "refresh";
+	interrupts = <0 27 4>;
+	interrupt-names = "ws0";
+	timeout-sec = <10 5>;
+};
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v6 2/8] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
@ 2015-06-23 14:16     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-23 14:16 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, dyoung,
	panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 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..7b80203 100644
--- a/arch/arm64/boot/dts/arm/foundation-v8.dts
+++ b/arch/arm64/boot/dts/arm/foundation-v8.dts
@@ -237,4 +237,14 @@
 			};
 		};
 	};
+	watchdog@2a440000 {
+		compatible = "arm,sbsa-gwdt";
+		reg = <0x0 0x2a440000 0 0x1000>,
+			<0x0 0x2a450000 0 0x1000>;
+		reg-names = "control",
+			"refresh";
+		interrupts = <0 27 4>;
+		interrupt-names = "ws0";
+		timeout-sec = <10 5>;
+	};
 };
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v6 2/8] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
@ 2015-06-23 14:16     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-23 14:16 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA, panand-H+wXaHxf7aLQT0dZR+AlfA,
	Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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

Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 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..7b80203 100644
--- a/arch/arm64/boot/dts/arm/foundation-v8.dts
+++ b/arch/arm64/boot/dts/arm/foundation-v8.dts
@@ -237,4 +237,14 @@
 			};
 		};
 	};
+	watchdog@2a440000 {
+		compatible = "arm,sbsa-gwdt";
+		reg = <0x0 0x2a440000 0 0x1000>,
+			<0x0 0x2a450000 0 0x1000>;
+		reg-names = "control",
+			"refresh";
+		interrupts = <0 27 4>;
+		interrupt-names = "ws0";
+		timeout-sec = <10 5>;
+	};
 };
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v6 3/8] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
  2015-06-23 14:16 ` [PATCH v6 0/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
  2015-06-23 14:16     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  2015-06-23 14:16     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
@ 2015-06-23 14:16   ` fu.wei
  2015-06-23 14:16     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  2015-06-29 16:53     ` Fu Wei
  4 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-23 14:16 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, dyoung,
	panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 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..4be7019 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 0x1000>,
+				<0x0 0xe0bc0000 0 0x1000>;
+			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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v6 4/8] Watchdog: introdouce "pretimeout" into framework
@ 2015-06-23 14:16     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-23 14:16 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, dyoung,
	panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 drivers are going to use this: ARM SBSA Generic Watchdog

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 Documentation/watchdog/watchdog-kernel-api.txt | 47 ++++++++++--
 drivers/watchdog/watchdog_core.c               | 98 ++++++++++++++++++--------
 drivers/watchdog/watchdog_dev.c                | 53 ++++++++++++++
 include/linux/watchdog.h                       | 39 ++++++++--
 4 files changed, 200 insertions(+), 37 deletions(-)

diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index a0438f3..d1b1238 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.
@@ -219,8 +236,28 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
                                   unsigned int timeout_parm, struct device *dev);
 
 The watchdog_init_timeout function allows you to initialize the timeout field
-using the module timeout parameter or by retrieving the timeout-sec property from
-the device tree (if the module timeout parameter is invalid). Best practice is
-to set the default timeout value as timeout value in the watchdog_device and
-then use this function to set the user "preferred" timeout value.
+using the module timeout parameter or by retrieving the first element of
+the timeout-sec property from the device tree (if the module timeout parameter
+is invalid). Best practice is to set the default timeout value as timeout value
+in the watchdog_device and then use this function to set the user "preferred"
+timeout value.
+This routine returns zero on success and a negative errno code for failure.
+
+Some watchdog timers have two stage of timeouts (timeout and pretimeout),
+to initialize the timeout and pretimeout fields at the same time, the following
+function can be used:
+
+int watchdog_init_timeouts(struct watchdog_device *wdd,
+                                  unsigned int pretimeout_parm,
+                                  unsigned int timeout_parm,
+                                  struct device *dev);
+
+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).
+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.
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index cec9b55..a45e8bb 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -46,57 +46,99 @@ static struct class *watchdog_class;
 static void watchdog_check_min_max_timeout(struct watchdog_device *wdd)
 {
 	/*
-	 * Check that we have valid min and max timeout values, if
-	 * not reset them both to 0 (=not used or unknown)
+	 * Check that we have valid min and max pretimeout and timeout values,
+	 * if not, reset them all to 0 (=not used or unknown)
 	 */
-	if (wdd->min_timeout > wdd->max_timeout) {
-		pr_info("Invalid min and max timeout values, resetting to 0!\n");
+	if (wdd->min_pretimeout > wdd->max_pretimeout ||
+	    wdd->min_timeout > wdd->max_timeout ||
+	    wdd->min_timeout < wdd->min_pretimeout ||
+	    wdd->max_timeout < wdd->max_pretimeout) {
+		pr_info("Invalid min or max timeouts, resetting to 0\n");
+		wdd->min_pretimeout = 0;
+		wdd->max_pretimeout = 0;
 		wdd->min_timeout = 0;
 		wdd->max_timeout = 0;
 	}
 }
 
 /**
- * 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 both the pretimeout and timeout module parameters (if they are valid) or
+ * the timeout-sec property (only if they are valid and the pretimeout_parm or
+ * timeout_parm is out of bounds). If one of them is invalid, 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,
+			   struct device *dev)
 {
-	unsigned int t = 0;
-	int ret = 0;
+	int ret = 0, length = 0;
+	u32 timeouts[2] = {0};
+	struct property *prop;
 
 	watchdog_check_min_max_timeout(wdd);
 
-	/* try to get the timeout module parameter first */
-	if (!watchdog_timeout_invalid(wdd, timeout_parm) && timeout_parm) {
-		wdd->timeout = timeout_parm;
-		return ret;
-	}
-	if (timeout_parm)
+	/*
+	 * Try to get the pretimeout module parameter first.
+	 * Note: zero is a valid value for pretimeout.
+	 */
+	if (watchdog_pretimeout_invalid(wdd, pretimeout_parm))
+		ret = -EINVAL;
+
+	/*
+	 * Try to get the timeout module parameter,
+	 * if it's valid and pretimeout is valid(ret == 0),
+	 * assignment and return zero. Otherwise, try dtb.
+	 */
+	if (timeout_parm && !ret) {
+		if (!watchdog_timeout_invalid(wdd, timeout_parm)) {
+			wdd->timeout = timeout_parm;
+			wdd->pretimeout = pretimeout_parm;
+			return 0;
+		}
 		ret = -EINVAL;
+	}
 
-	/* try to get the timeout_sec property */
+	/*
+	 * Either at least one of the module parameters is invalid,
+	 * or timeout_parm is 0. 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
-		ret = -EINVAL;
 
-	return ret;
+	prop = of_find_property(dev->of_node, "timeout-sec", &length);
+	if (prop && length > 0 && length <= sizeof(u32) * 2) {
+		of_property_read_u32_array(dev->of_node,
+					   "timeout-sec", timeouts,
+					   length / sizeof(u32));
+		if (length == sizeof(u32) * 2) {
+			if (watchdog_pretimeout_invalid(wdd, timeouts[1]))
+				return -EINVAL;
+			ret = 0;
+		} else {
+			ret = -EINVAL;
+		}
+
+		if (!watchdog_timeout_invalid(wdd, timeouts[0]) &&
+		    timeouts[0]) {
+			wdd->timeout = timeouts[0];
+			if (!ret)
+				wdd->pretimeout = timeouts[1];
+			return 0;
+		}
+	}
+
+	return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(watchdog_init_timeout);
+EXPORT_SYMBOL_GPL(watchdog_init_timeouts);
 
 /**
  * watchdog_register_device() - register a watchdog device
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 6aaefba..af0777e 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,27 @@ 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:
+		/* check if we support the pretimeout */
+		if (!(wdd->info->options & WDIOF_PRETIMEOUT))
+			return -EOPNOTSUPP;
+		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 keeps running (and if
+		 * possible that it takes the new pretimeout)
+		 */
+		watchdog_ping(wdd);
+		/* Fall */
+	case WDIOC_GETPRETIMEOUT:
+		/* check if we support the pretimeout */
+		if (wdd->info->options & WDIOF_PRETIMEOUT)
+			return put_user(wdd->pretimeout, p);
+		return -EOPNOTSUPP;
 	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..47a87cb 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;
@@ -116,8 +124,22 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
 /* Use the following function to check if a timeout value is invalid */
 static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
 {
-	return ((wdd->max_timeout != 0) &&
-		(t < wdd->min_timeout || t > wdd->max_timeout));
+	return (wdd->max_timeout &&
+		(t < wdd->min_timeout || t > wdd->max_timeout)) ||
+	       (wdd->pretimeout && t <= wdd->pretimeout);
+}
+
+/*
+ * Use the following function to check if a pretimeout value is invalid.
+ * It can be "0", that means we don't use pretimeout.
+ * This function returns false, when pretimeout is 0.
+ */
+static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd,
+					       unsigned int t)
+{
+	return t && ((wdd->max_pretimeout &&
+		      (t < wdd->min_pretimeout || t > wdd->max_pretimeout)) ||
+		     (wdd->timeout && t >= wdd->timeout));
 }
 
 /* Use the following functions to manipulate watchdog driver specific data */
@@ -132,8 +154,17 @@ 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);
+int watchdog_init_timeouts(struct watchdog_device *wdd,
+			   unsigned int pretimeout_parm,
+			   unsigned int timeout_parm,
+			   struct device *dev);
+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, dev);
+}
+
 extern int watchdog_register_device(struct watchdog_device *);
 extern void watchdog_unregister_device(struct watchdog_device *);
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v6 4/8] Watchdog: introdouce "pretimeout" into framework
@ 2015-06-23 14:16     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-23 14:16 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA, panand-H+wXaHxf7aLQT0dZR+AlfA,
	Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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 drivers are going to use this: ARM SBSA Generic Watchdog

Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 Documentation/watchdog/watchdog-kernel-api.txt | 47 ++++++++++--
 drivers/watchdog/watchdog_core.c               | 98 ++++++++++++++++++--------
 drivers/watchdog/watchdog_dev.c                | 53 ++++++++++++++
 include/linux/watchdog.h                       | 39 ++++++++--
 4 files changed, 200 insertions(+), 37 deletions(-)

diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index a0438f3..d1b1238 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.
@@ -219,8 +236,28 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
                                   unsigned int timeout_parm, struct device *dev);
 
 The watchdog_init_timeout function allows you to initialize the timeout field
-using the module timeout parameter or by retrieving the timeout-sec property from
-the device tree (if the module timeout parameter is invalid). Best practice is
-to set the default timeout value as timeout value in the watchdog_device and
-then use this function to set the user "preferred" timeout value.
+using the module timeout parameter or by retrieving the first element of
+the timeout-sec property from the device tree (if the module timeout parameter
+is invalid). Best practice is to set the default timeout value as timeout value
+in the watchdog_device and then use this function to set the user "preferred"
+timeout value.
+This routine returns zero on success and a negative errno code for failure.
+
+Some watchdog timers have two stage of timeouts (timeout and pretimeout),
+to initialize the timeout and pretimeout fields at the same time, the following
+function can be used:
+
+int watchdog_init_timeouts(struct watchdog_device *wdd,
+                                  unsigned int pretimeout_parm,
+                                  unsigned int timeout_parm,
+                                  struct device *dev);
+
+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).
+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.
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index cec9b55..a45e8bb 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -46,57 +46,99 @@ static struct class *watchdog_class;
 static void watchdog_check_min_max_timeout(struct watchdog_device *wdd)
 {
 	/*
-	 * Check that we have valid min and max timeout values, if
-	 * not reset them both to 0 (=not used or unknown)
+	 * Check that we have valid min and max pretimeout and timeout values,
+	 * if not, reset them all to 0 (=not used or unknown)
 	 */
-	if (wdd->min_timeout > wdd->max_timeout) {
-		pr_info("Invalid min and max timeout values, resetting to 0!\n");
+	if (wdd->min_pretimeout > wdd->max_pretimeout ||
+	    wdd->min_timeout > wdd->max_timeout ||
+	    wdd->min_timeout < wdd->min_pretimeout ||
+	    wdd->max_timeout < wdd->max_pretimeout) {
+		pr_info("Invalid min or max timeouts, resetting to 0\n");
+		wdd->min_pretimeout = 0;
+		wdd->max_pretimeout = 0;
 		wdd->min_timeout = 0;
 		wdd->max_timeout = 0;
 	}
 }
 
 /**
- * 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 both the pretimeout and timeout module parameters (if they are valid) or
+ * the timeout-sec property (only if they are valid and the pretimeout_parm or
+ * timeout_parm is out of bounds). If one of them is invalid, 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,
+			   struct device *dev)
 {
-	unsigned int t = 0;
-	int ret = 0;
+	int ret = 0, length = 0;
+	u32 timeouts[2] = {0};
+	struct property *prop;
 
 	watchdog_check_min_max_timeout(wdd);
 
-	/* try to get the timeout module parameter first */
-	if (!watchdog_timeout_invalid(wdd, timeout_parm) && timeout_parm) {
-		wdd->timeout = timeout_parm;
-		return ret;
-	}
-	if (timeout_parm)
+	/*
+	 * Try to get the pretimeout module parameter first.
+	 * Note: zero is a valid value for pretimeout.
+	 */
+	if (watchdog_pretimeout_invalid(wdd, pretimeout_parm))
+		ret = -EINVAL;
+
+	/*
+	 * Try to get the timeout module parameter,
+	 * if it's valid and pretimeout is valid(ret == 0),
+	 * assignment and return zero. Otherwise, try dtb.
+	 */
+	if (timeout_parm && !ret) {
+		if (!watchdog_timeout_invalid(wdd, timeout_parm)) {
+			wdd->timeout = timeout_parm;
+			wdd->pretimeout = pretimeout_parm;
+			return 0;
+		}
 		ret = -EINVAL;
+	}
 
-	/* try to get the timeout_sec property */
+	/*
+	 * Either at least one of the module parameters is invalid,
+	 * or timeout_parm is 0. 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
-		ret = -EINVAL;
 
-	return ret;
+	prop = of_find_property(dev->of_node, "timeout-sec", &length);
+	if (prop && length > 0 && length <= sizeof(u32) * 2) {
+		of_property_read_u32_array(dev->of_node,
+					   "timeout-sec", timeouts,
+					   length / sizeof(u32));
+		if (length == sizeof(u32) * 2) {
+			if (watchdog_pretimeout_invalid(wdd, timeouts[1]))
+				return -EINVAL;
+			ret = 0;
+		} else {
+			ret = -EINVAL;
+		}
+
+		if (!watchdog_timeout_invalid(wdd, timeouts[0]) &&
+		    timeouts[0]) {
+			wdd->timeout = timeouts[0];
+			if (!ret)
+				wdd->pretimeout = timeouts[1];
+			return 0;
+		}
+	}
+
+	return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(watchdog_init_timeout);
+EXPORT_SYMBOL_GPL(watchdog_init_timeouts);
 
 /**
  * watchdog_register_device() - register a watchdog device
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 6aaefba..af0777e 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,27 @@ 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:
+		/* check if we support the pretimeout */
+		if (!(wdd->info->options & WDIOF_PRETIMEOUT))
+			return -EOPNOTSUPP;
+		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 keeps running (and if
+		 * possible that it takes the new pretimeout)
+		 */
+		watchdog_ping(wdd);
+		/* Fall */
+	case WDIOC_GETPRETIMEOUT:
+		/* check if we support the pretimeout */
+		if (wdd->info->options & WDIOF_PRETIMEOUT)
+			return put_user(wdd->pretimeout, p);
+		return -EOPNOTSUPP;
 	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..47a87cb 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;
@@ -116,8 +124,22 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
 /* Use the following function to check if a timeout value is invalid */
 static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
 {
-	return ((wdd->max_timeout != 0) &&
-		(t < wdd->min_timeout || t > wdd->max_timeout));
+	return (wdd->max_timeout &&
+		(t < wdd->min_timeout || t > wdd->max_timeout)) ||
+	       (wdd->pretimeout && t <= wdd->pretimeout);
+}
+
+/*
+ * Use the following function to check if a pretimeout value is invalid.
+ * It can be "0", that means we don't use pretimeout.
+ * This function returns false, when pretimeout is 0.
+ */
+static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd,
+					       unsigned int t)
+{
+	return t && ((wdd->max_pretimeout &&
+		      (t < wdd->min_pretimeout || t > wdd->max_pretimeout)) ||
+		     (wdd->timeout && t >= wdd->timeout));
 }
 
 /* Use the following functions to manipulate watchdog driver specific data */
@@ -132,8 +154,17 @@ 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);
+int watchdog_init_timeouts(struct watchdog_device *wdd,
+			   unsigned int pretimeout_parm,
+			   unsigned int timeout_parm,
+			   struct device *dev);
+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, dev);
+}
+
 extern int watchdog_register_device(struct watchdog_device *);
 extern void watchdog_unregister_device(struct watchdog_device *);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [non-pretimeout,4/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-23 15:21           ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-23 15:21 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

On Tue, Jun 23, 2015 at 09:26:35PM +0800, Fu Wei wrote:
> Hi Guenter,
[ ...]

> >
> >> + *       When the first timeout occurs, WS0(SPI or LPI) is triggered,
> >> + *       the second timeout period(as long as the first timeout period) starts.
> >
> > no longer accurate if WOR is used for the second period.
> >
> >> + *       In WS0 interrupt routine, panic() will be called for collecting
> >> + *       crashdown info.
> >> + *       If system can not recover from WS0 interrupt routine, then second
> >> + *       timeout occurs, WS1(reset or higher level interrupt) is triggered.
> >> + *       The two timeout period can be set by WOR(32bit).
> >
> > The second timeout period is determined by ...
> >
> >> + *       WOR gives a maximum watch period of around 10s at the maximum
> >> + *       system counter frequency.
> >> + *       The System Counter shall run at maximum of 400MHz.
> >
> > "... at the maximum system counter frequency of 400 MHz.", and drop the
> > last sentence.
> 
> For the second timeout period,  I have discussed with a kdump developers,
> (1)10s maybe not good enough for all the case of panic + kdump, so
> maybe we still need to use WCV in the second timeout period
> (2)in the second timeout period, maybe we need to programme WCV for
> two reason: a, trigger WS1 to reboot system ASAP; b, feed the watchdog
> without cleanning WS0 flag.
> 
> WHY we want to feed the watchdog (keepalive) without cleanning WS0 flag??
> REASON:
> (1)if the system context is large, we may need to feed the dog until
> we get all the things backed up.
> (2)if system goes wrong,  WS0 triggered, then panic--> kdump. if we
> feed the dog by WRR or programming WOR, WS0 flag will be cleaned. Once
> system goes wrong again, then panic again.....
> So this system will be in a panic--kdump--panic--kdump loop, have not
> chance to reset.
> 
> So if we are in the second timeout period, we may need to always programme WCV.
> 
The crashdump kernel is supposed to reload the watchdog driver, which will ping
the watchdog. If it isn't able to do that in 10 seconds, something is wrong.

> >> +
> >> +     status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
> >> +     if (status & SBSA_GWDT_WCS_WS1) {
> >> +             dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
> >> +                      sbsa_gwdt_get_wcv(wdd));
> >
> > WCV here only tells us how many clock cycles were executed since the
> > system started (or something like that). So I still don't understand
> > why it is valuable to print that number.
> 
> this number provides the time of system reset, I thinks that may help
> admin to analyse the system failure.
> 
It doesn't mean anything to anyone but you since it is not in a well defined
time scale. Also, I would be somewhat surprised if WCV would retain its value
on reset. Much more likely it is the time (in clock cycles) since reset.

Guenter

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [non-pretimeout,4/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-23 15:21           ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-23 15:21 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon,
	rjw-LthD3rsA81gm4RdzfppkhA

On Tue, Jun 23, 2015 at 09:26:35PM +0800, Fu Wei wrote:
> Hi Guenter,
[ ...]

> >
> >> + *       When the first timeout occurs, WS0(SPI or LPI) is triggered,
> >> + *       the second timeout period(as long as the first timeout period) starts.
> >
> > no longer accurate if WOR is used for the second period.
> >
> >> + *       In WS0 interrupt routine, panic() will be called for collecting
> >> + *       crashdown info.
> >> + *       If system can not recover from WS0 interrupt routine, then second
> >> + *       timeout occurs, WS1(reset or higher level interrupt) is triggered.
> >> + *       The two timeout period can be set by WOR(32bit).
> >
> > The second timeout period is determined by ...
> >
> >> + *       WOR gives a maximum watch period of around 10s at the maximum
> >> + *       system counter frequency.
> >> + *       The System Counter shall run at maximum of 400MHz.
> >
> > "... at the maximum system counter frequency of 400 MHz.", and drop the
> > last sentence.
> 
> For the second timeout period,  I have discussed with a kdump developers,
> (1)10s maybe not good enough for all the case of panic + kdump, so
> maybe we still need to use WCV in the second timeout period
> (2)in the second timeout period, maybe we need to programme WCV for
> two reason: a, trigger WS1 to reboot system ASAP; b, feed the watchdog
> without cleanning WS0 flag.
> 
> WHY we want to feed the watchdog (keepalive) without cleanning WS0 flag??
> REASON:
> (1)if the system context is large, we may need to feed the dog until
> we get all the things backed up.
> (2)if system goes wrong,  WS0 triggered, then panic--> kdump. if we
> feed the dog by WRR or programming WOR, WS0 flag will be cleaned. Once
> system goes wrong again, then panic again.....
> So this system will be in a panic--kdump--panic--kdump loop, have not
> chance to reset.
> 
> So if we are in the second timeout period, we may need to always programme WCV.
> 
The crashdump kernel is supposed to reload the watchdog driver, which will ping
the watchdog. If it isn't able to do that in 10 seconds, something is wrong.

> >> +
> >> +     status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
> >> +     if (status & SBSA_GWDT_WCS_WS1) {
> >> +             dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
> >> +                      sbsa_gwdt_get_wcv(wdd));
> >
> > WCV here only tells us how many clock cycles were executed since the
> > system started (or something like that). So I still don't understand
> > why it is valuable to print that number.
> 
> this number provides the time of system reset, I thinks that may help
> admin to analyse the system failure.
> 
It doesn't mean anything to anyone but you since it is not in a well defined
time scale. Also, I would be somewhat surprised if WCV would retain its value
on reset. Much more likely it is the time (in clock cycles) since reset.

Guenter
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v6 5/8] Watchdog: introduce ARM SBSA watchdog driver
       [not found] <=fu.wei@linaro.org>
                   ` (7 preceding siblings ...)
  2015-06-23 14:16 ` [PATCH v6 0/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
@ 2015-06-23 15:59 ` fu.wei
  2015-06-23 15:59     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
                     ` (2 more replies)
  2015-07-13  8:53 ` [PATCH v2 0/3] arm64: Add multiboot support (via fdt) for Xen boot fu.wei
                   ` (5 subsequent siblings)
  14 siblings, 3 replies; 550+ messages in thread
From: fu.wei @ 2015-06-23 15:59 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, dyoung,
	panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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, the interrupt routine run panic to save
system context.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 drivers/watchdog/Kconfig     |  14 ++
 drivers/watchdog/Makefile    |   1 +
 drivers/watchdog/sbsa_gwdt.c | 455 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 470 insertions(+)
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e5e7c55..e059850 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -152,6 +152,20 @@ 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 ARM64
+	depends on ARM_ARCH_TIMER
+	select WATCHDOG_CORE
+	help
+	  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.
+	  More details: ARM DEN0029B - Server Base System Architecture (SBSA)
+
+	  To compile this driver as module, choose M here: The module
+	  will be called sbsa_gwdt.
+
 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..2de5899
--- /dev/null
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -0,0 +1,455 @@
+/*
+ * SBSA(Server Base System Architecture) Generic Watchdog driver
+ *
+ * Copyright (c) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei@linaro.org>
+ *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
+ *
+ * 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.
+ *
+ * The SBSA Generic watchdog driver is compatible with the pretimeout
+ * concept of Linux kernel.
+ * The timeout and pretimeout are determined by WCV or WOR.
+ * The first watch period is set by writing WCV directly, that can
+ * support more than 10s timeout at the maximum system counter
+ * frequency (400MHz).
+ * When WS0 is triggered, the second watch period (pretimeout) is
+ * determined by one of these registers:
+ * (1)WOR: 32bit register, this gives a maximum watch period of
+ * around 10s at the maximum system counter frequency. It's loaded
+ * automatically by hardware.
+ * (2)WCV: If the pretimeout value is greater then "max_wor_timeout",
+ * it will be loaded in WS0 interrupt routine. If system is in
+ * ws0_mode (reboot by kexec/kdump in panic with watchdog enabled
+ * and WS0 == true), the ping operation will only reload WCV.
+ * More details about the hardware specification of this device:
+ * ARM DEN0029B - Server Base System Architecture (SBSA)
+ *
+ * Kernel/API:                         P------------------| pretimeout
+ *               |----------------------------------------T timeout
+ * SBSA GWDT:                          P---WOR (or WCV)---WS1 pretimeout
+ *               |-------WCV----------WS0~~~(ws0_mode)~~~~T timeout
+ */
+
+#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>
+#include <asm/arch_timer.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.
+ * @ws0_mode:		indicate the system boot in the second stage timeout.
+ * @max_wor_timeout:	the maximum timeout value for WOR (in seconds).
+ * @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;
+	bool			ws0_mode;
+	int			max_wor_timeout;
+	void __iomem		*refresh_base;
+	void __iomem		*control_base;
+};
+
+#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
+
+#define DEFAULT_TIMEOUT		30 /* seconds, the 1st + 2nd watch periods*/
+#define DEFAULT_PRETIMEOUT	10 /* 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 pretimeout;
+module_param(pretimeout, uint, 0);
+MODULE_PARM_DESC(pretimeout,
+		 "Watchdog pretimeout in seconds. (>=0, default="
+		 __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
+
+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) ")");
+
+/*
+ * help functions for accessing 64bit WCV register
+ */
+static u64 sbsa_gwdt_get_wcv(struct watchdog_device *wdd)
+{
+	u32 wcv_lo, wcv_hi;
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	do {
+		wcv_hi = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_HI);
+		wcv_lo = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_LO);
+	} while (wcv_hi != readl_relaxed(gwdt->control_base +
+					 SBSA_GWDT_WCV_HI));
+
+	return (((u64)wcv_hi << 32) | wcv_lo);
+}
+
+static void sbsa_gwdt_set_wcv(struct watchdog_device *wdd, unsigned int t)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+	u64 wcv;
+
+	wcv = arch_counter_get_cntvct() + (u64)t * gwdt->clk;
+
+	writel_relaxed(upper_32_bits(wcv),
+		       gwdt->control_base + SBSA_GWDT_WCV_HI);
+	writel_relaxed(lower_32_bits(wcv),
+		       gwdt->control_base + SBSA_GWDT_WCV_LO);
+}
+
+/*
+ * inline functions for reloading 64bit WCV register
+ */
+static inline void reload_pretimeout_to_wcv(struct watchdog_device *wdd)
+{
+	sbsa_gwdt_set_wcv(wdd, wdd->pretimeout);
+}
+
+static inline void reload_first_stage_to_wcv(struct watchdog_device *wdd)
+{
+	sbsa_gwdt_set_wcv(wdd, wdd->timeout - wdd->pretimeout);
+}
+
+/*
+ * watchdog operation functions
+ */
+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;
+
+	/* If ws0_mode == true, we won't touch WOR */
+	if (!gwdt->ws0_mode) {
+		if (!pretimeout)
+			/*
+			 * If pretimeout is 0, it gives driver a timeslot (1s)
+			 * to update WCV after an explicit refresh
+			 * (sbsa_gwdt_start)
+			 */
+			wor = gwdt->clk;
+		else
+			if (pretimeout > gwdt->max_wor_timeout)
+				wor = U32_MAX;
+			else
+				wor = pretimeout * gwdt->clk;
+
+		/* wtite WOR, that will cause an explicit watchdog refresh */
+		writel_relaxed(wor, gwdt->control_base + SBSA_GWDT_WOR);
+	}
+
+	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_keepalive(struct watchdog_device *wdd)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	if (gwdt->ws0_mode)
+		reload_pretimeout_to_wcv(wdd);
+	else
+		reload_first_stage_to_wcv(wdd);
+
+	return 0;
+}
+
+static int sbsa_gwdt_start(struct watchdog_device *wdd)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	/* If ws0_mode == true, the watchdog is enabled */
+	if (!gwdt->ws0_mode)
+		/* writing WCS will cause an explicit watchdog refresh */
+		writel_relaxed(SBSA_GWDT_WCS_EN,
+			       gwdt->control_base + SBSA_GWDT_WCS);
+
+	return sbsa_gwdt_keepalive(wdd);
+}
+
+static int sbsa_gwdt_stop(struct watchdog_device *wdd)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	writel_relaxed(0, gwdt->control_base + SBSA_GWDT_WCS);
+	/*
+	 * Writing WCS has caused an explicit watchdog refresh.
+	 * Both watchdog signals are deasserted, so clean ws0_mode flag.
+	 */
+	gwdt->ws0_mode = false;
+
+	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;
+
+	/* We don't use pretimeout, trigger WS1 now */
+	if (!wdd->pretimeout)
+		sbsa_gwdt_set_wcv(wdd, 0);
+
+	/*
+	 * The pretimeout is valid, go panic
+	 * If pretimeout is greater then "max_wor_timeout",
+	 * reload the right value to WCV, then panic
+	 */
+	if (wdd->pretimeout > gwdt->max_wor_timeout)
+		reload_pretimeout_to_wcv(wdd);
+	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 watchdog_device *wdd;
+	struct sbsa_gwdt *gwdt;
+	struct resource *res;
+	u64 max_wcv_timeout = U64_MAX;
+	void *rf_base, *cf_base;
+	int ret, irq;
+	u32 status;
+
+	gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
+	if (!gwdt)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, gwdt);
+
+	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(cf_base))
+		return PTR_ERR(cf_base);
+
+	irq = platform_get_irq_byname(pdev, "ws0");
+	if (irq < 0) {
+		dev_err(dev, "unable to get ws0 interrupt.\n");
+		return irq;
+	}
+
+	/*
+	 * Get the frequency of system counter from the cp15 interface of ARM
+	 * Generic timer. We don't need to check it, because if it returns "0",
+	 * system would panic in very early stage.
+	 */
+	gwdt->clk = arch_timer_get_cntfrq();
+	gwdt->refresh_base = rf_base;
+	gwdt->control_base = cf_base;
+	gwdt->max_wor_timeout = U32_MAX / gwdt->clk;
+	gwdt->ws0_mode = false;
+
+	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);
+
+	wdd->min_pretimeout = 0;
+	wdd->min_timeout = 1;
+	do_div(max_wcv_timeout, gwdt->clk);
+	wdd->max_pretimeout = max_wcv_timeout;
+	wdd->max_timeout = max_wcv_timeout * 2;
+
+	wdd->pretimeout = DEFAULT_PRETIMEOUT;
+	wdd->timeout = DEFAULT_TIMEOUT;
+	watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
+
+	status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
+	if (status & SBSA_GWDT_WCS_WS1) {
+		dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
+			 sbsa_gwdt_get_wcv(wdd));
+		wdd->bootstatus |= WDIOF_CARDRESET;
+	} else if (status == (SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_EN)) {
+		gwdt->ws0_mode = true;
+	}
+
+	ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
+			       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;
+
+	/* If ws0_mode == true, the line won't update WOR */
+	sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
+
+	/*
+	 * If watchdog is already enabled, do a ping operation
+	 * to keep system running
+	 */
+	if (status & SBSA_GWDT_WCS_EN)
+		sbsa_gwdt_keepalive(wdd);
+
+	dev_info(dev, "Initialized with %ds timeout, %ds pretimeout @ %u Hz%s\n",
+		 wdd->timeout, wdd->pretimeout, gwdt->clk,
+		 status & SBSA_GWDT_WCS_EN ?
+			gwdt->ws0_mode ? " [second stage]" : " [enabled]" :
+			"");
+
+	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);
+
+	watchdog_unregister_device(&gwdt->wdd);
+
+	return 0;
+}
+
+/* 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_AUTHOR("Fu Wei <fu.wei@linaro.org>");
+MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v6 6/8] ACPI: add GTDT table parse driver into ACPI driver
@ 2015-06-23 15:59     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-23 15:59 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, dyoung,
	panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This driver adds support for parsing SBSA Generic Watchdog
Structure in GTDT, and creating a platform device with that
information. This allows the operating system to obtain device
data from the resource of platform device.

The platform device named "sbsa-gwdt" can be used by the
ARM SBSA Generic Watchdog driver.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/acpi/Kconfig  |   9 ++++
 drivers/acpi/Makefile |   1 +
 drivers/acpi/gtdt.c   | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 147 insertions(+)
 create mode 100644 drivers/acpi/gtdt.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 1bbaa3d..e125698 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -433,4 +433,13 @@ config XPOWER_PMIC_OPREGION
 
 endif
 
+config ACPI_GTDT
+	bool "ACPI GTDT Support"
+	depends on ARM64
+	help
+	  GTDT (Generic Timer Description Table) provides information
+	  for per-processor timers and Platform (memory-mapped) timers
+	  for ARM platforms. Select this option to provide information
+	  needed for the timers init.
+
 endif	# ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 431e587..2c5a194 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -96,3 +96,4 @@ obj-$(CONFIG_ACPI_EXTLOG)	+= acpi_extlog.o
 obj-$(CONFIG_PMIC_OPREGION)	+= pmic/intel_pmic.o
 obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
 obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
+obj-$(CONFIG_ACPI_GTDT)		+= gtdt.o
diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
new file mode 100644
index 0000000..a92abf2
--- /dev/null
+++ b/drivers/acpi/gtdt.c
@@ -0,0 +1,137 @@
+/*
+ * ARM Specific GTDT table Support
+ *
+ * Copyright (C) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei@linaro.org>
+ *         Hanjun Guo <hanjun.guo@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
+{
+	int trigger, polarity;
+
+	if (!interrupt)
+		return 0;
+
+	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+			: ACPI_LEVEL_SENSITIVE;
+
+	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+			: ACPI_ACTIVE_HIGH;
+
+	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
+}
+
+/*
+ * Initialize a SBSA generic Watchdog platform device info from GTDT
+ * According to SBSA specification the size of refresh and control
+ * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
+ */
+static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
+					int index)
+{
+	struct platform_device *pdev;
+	int irq = map_generic_timer_interrupt(wd->timer_interrupt,
+					      wd->timer_flags);
+	struct resource res[] = {
+		DEFINE_RES_IRQ_NAMED(irq, "ws0"),
+		DEFINE_RES_MEM_NAMED(wd->refresh_frame_address, SZ_4K,
+				     "refresh"),
+		DEFINE_RES_MEM_NAMED(wd->control_frame_address, SZ_4K,
+				     "control"),
+	};
+
+	pr_debug("GTDT: a Watchdog GT(0x%llx/0x%llx gsi:%u flags:0x%x)\n",
+		 wd->refresh_frame_address, wd->control_frame_address,
+		 wd->timer_interrupt, wd->timer_flags);
+
+	if (!(wd->refresh_frame_address &&
+	      wd->control_frame_address &&
+	      wd->timer_interrupt)) {
+		pr_err("GTDT: failed geting the device info.\n");
+		return -EINVAL;
+	}
+
+	if (irq < 0) {
+		pr_err("GTDT: failed to register GSI of the Watchdog GT.\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Add a platform device named "sbsa-gwdt" to match the platform driver.
+	 * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
+	 * The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get device
+	 * info below by matching this name.
+	 */
+	pdev = platform_device_register_simple("sbsa-gwdt", index, res,
+					       ARRAY_SIZE(res));
+	if (IS_ERR(pdev)) {
+		acpi_unregister_gsi(wd->timer_interrupt);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
+
+static int __init gtdt_platform_timer_parse(struct acpi_table_header *table)
+{
+	struct acpi_gtdt_header *header;
+	struct acpi_table_gtdt *gtdt;
+	void *gtdt_subtable;
+	int i, gwdt_index;
+	int ret = 0;
+
+	if (table->revision < 2) {
+		pr_warn("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 = 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;
+}
+
+static int __init gtdt_platform_timer_init(void)
+{
+	if (acpi_disabled)
+		return 0;
+
+	return acpi_table_parse(ACPI_SIG_GTDT, gtdt_platform_timer_parse);
+}
+
+device_initcall(gtdt_platform_timer_init);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v6 6/8] ACPI: add GTDT table parse driver into ACPI driver
@ 2015-06-23 15:59     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-23 15:59 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA, panand-H+wXaHxf7aLQT0dZR+AlfA,
	Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

This driver adds support for parsing SBSA Generic Watchdog
Structure in GTDT, and creating a platform device with that
information. This allows the operating system to obtain device
data from the resource of platform device.

The platform device named "sbsa-gwdt" can be used by the
ARM SBSA Generic Watchdog driver.

Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/acpi/Kconfig  |   9 ++++
 drivers/acpi/Makefile |   1 +
 drivers/acpi/gtdt.c   | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 147 insertions(+)
 create mode 100644 drivers/acpi/gtdt.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 1bbaa3d..e125698 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -433,4 +433,13 @@ config XPOWER_PMIC_OPREGION
 
 endif
 
+config ACPI_GTDT
+	bool "ACPI GTDT Support"
+	depends on ARM64
+	help
+	  GTDT (Generic Timer Description Table) provides information
+	  for per-processor timers and Platform (memory-mapped) timers
+	  for ARM platforms. Select this option to provide information
+	  needed for the timers init.
+
 endif	# ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 431e587..2c5a194 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -96,3 +96,4 @@ obj-$(CONFIG_ACPI_EXTLOG)	+= acpi_extlog.o
 obj-$(CONFIG_PMIC_OPREGION)	+= pmic/intel_pmic.o
 obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
 obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
+obj-$(CONFIG_ACPI_GTDT)		+= gtdt.o
diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
new file mode 100644
index 0000000..a92abf2
--- /dev/null
+++ b/drivers/acpi/gtdt.c
@@ -0,0 +1,137 @@
+/*
+ * ARM Specific GTDT table Support
+ *
+ * Copyright (C) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
+ *         Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
+{
+	int trigger, polarity;
+
+	if (!interrupt)
+		return 0;
+
+	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+			: ACPI_LEVEL_SENSITIVE;
+
+	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+			: ACPI_ACTIVE_HIGH;
+
+	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
+}
+
+/*
+ * Initialize a SBSA generic Watchdog platform device info from GTDT
+ * According to SBSA specification the size of refresh and control
+ * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
+ */
+static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
+					int index)
+{
+	struct platform_device *pdev;
+	int irq = map_generic_timer_interrupt(wd->timer_interrupt,
+					      wd->timer_flags);
+	struct resource res[] = {
+		DEFINE_RES_IRQ_NAMED(irq, "ws0"),
+		DEFINE_RES_MEM_NAMED(wd->refresh_frame_address, SZ_4K,
+				     "refresh"),
+		DEFINE_RES_MEM_NAMED(wd->control_frame_address, SZ_4K,
+				     "control"),
+	};
+
+	pr_debug("GTDT: a Watchdog GT(0x%llx/0x%llx gsi:%u flags:0x%x)\n",
+		 wd->refresh_frame_address, wd->control_frame_address,
+		 wd->timer_interrupt, wd->timer_flags);
+
+	if (!(wd->refresh_frame_address &&
+	      wd->control_frame_address &&
+	      wd->timer_interrupt)) {
+		pr_err("GTDT: failed geting the device info.\n");
+		return -EINVAL;
+	}
+
+	if (irq < 0) {
+		pr_err("GTDT: failed to register GSI of the Watchdog GT.\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Add a platform device named "sbsa-gwdt" to match the platform driver.
+	 * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
+	 * The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get device
+	 * info below by matching this name.
+	 */
+	pdev = platform_device_register_simple("sbsa-gwdt", index, res,
+					       ARRAY_SIZE(res));
+	if (IS_ERR(pdev)) {
+		acpi_unregister_gsi(wd->timer_interrupt);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
+
+static int __init gtdt_platform_timer_parse(struct acpi_table_header *table)
+{
+	struct acpi_gtdt_header *header;
+	struct acpi_table_gtdt *gtdt;
+	void *gtdt_subtable;
+	int i, gwdt_index;
+	int ret = 0;
+
+	if (table->revision < 2) {
+		pr_warn("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 = 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;
+}
+
+static int __init gtdt_platform_timer_init(void)
+{
+	if (acpi_disabled)
+		return 0;
+
+	return acpi_table_parse(ACPI_SIG_GTDT, gtdt_platform_timer_parse);
+}
+
+device_initcall(gtdt_platform_timer_init);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v6 7/8] Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
@ 2015-06-23 15:59     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-23 15:59 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, dyoung,
	panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patch enables ACPI GTDT support for ARM SBSA
watchdog driver automatically, if ACPI support is enabled.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 drivers/watchdog/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e059850..50a70f7 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -157,6 +157,7 @@ config ARM_SBSA_WATCHDOG
 	depends on ARM64
 	depends on ARM_ARCH_TIMER
 	select WATCHDOG_CORE
+	select ACPI_GTDT if ACPI
 	help
 	  ARM SBSA Generic Watchdog. This watchdog has two Watchdog timeouts.
 	  The first timeout will trigger a panic; the second timeout will
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v6 7/8] Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
@ 2015-06-23 15:59     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-23 15:59 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA, panand-H+wXaHxf7aLQT0dZR+AlfA,
	Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

This patch enables ACPI GTDT support for ARM SBSA
watchdog driver automatically, if ACPI support is enabled.

Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/watchdog/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e059850..50a70f7 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -157,6 +157,7 @@ config ARM_SBSA_WATCHDOG
 	depends on ARM64
 	depends on ARM_ARCH_TIMER
 	select WATCHDOG_CORE
+	select ACPI_GTDT if ACPI
 	help
 	  ARM SBSA Generic Watchdog. This watchdog has two Watchdog timeouts.
 	  The first timeout will trigger a panic; the second timeout will
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v6 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
@ 2015-06-23 15:59     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-06-23 15:59 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, timur,
	ashwin.chaugule, arnd, linux, vgandhi, wim, jcm, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw, dyoung,
	panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

The patch update arm_arch_timer driver to use the function
provided by the new GTDT driver of ACPI.
By this way, arm_arch_timer.c can be simplified, and separate
all the ACPI GTDT knowledge from this timer driver.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 arch/arm64/kernel/time.c             |  4 +--
 drivers/acpi/gtdt.c                  | 43 ++++++++++++++++++++++++++
 drivers/clocksource/Kconfig          |  1 +
 drivers/clocksource/arm_arch_timer.c | 60 +++++++-----------------------------
 include/clocksource/arm_arch_timer.h |  8 +++++
 include/linux/acpi.h                 |  5 +++
 include/linux/clocksource.h          |  4 +--
 7 files changed, 72 insertions(+), 53 deletions(-)

diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 42f9195..2cabea6 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -75,9 +75,9 @@ void __init time_init(void)
 
 	/*
 	 * Since ACPI or FDT will only one be available in the system,
-	 * we can use acpi_generic_timer_init() here safely
+	 * we can use arch_timer_acpi_init() here safely
 	 */
-	acpi_generic_timer_init();
+	arch_timer_acpi_init();
 
 	arch_timer_rate = arch_timer_get_rate();
 	if (!arch_timer_rate)
diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
index a92abf2..699c9fd 100644
--- a/drivers/acpi/gtdt.c
+++ b/drivers/acpi/gtdt.c
@@ -17,6 +17,8 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
+#include <clocksource/arm_arch_timer.h>
+
 static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 {
 	int trigger, polarity;
@@ -33,6 +35,47 @@ static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
 }
 
+struct arch_timer_data __initdata *arch_timer_data_p;
+
+static int __init arch_timer_data_init(struct acpi_table_header *table)
+{
+	struct acpi_table_gtdt *gtdt;
+
+	gtdt = container_of(table, struct acpi_table_gtdt, header);
+
+	arch_timer_data_p->phys_secure_ppi =
+		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
+					    gtdt->secure_el1_flags);
+
+	arch_timer_data_p->phys_nonsecure_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
+					    gtdt->non_secure_el1_flags);
+
+	arch_timer_data_p->virt_ppi =
+		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
+					    gtdt->virtual_timer_flags);
+
+	arch_timer_data_p->hyp_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
+					    gtdt->non_secure_el2_flags);
+
+	arch_timer_data_p->c3stop = !(gtdt->non_secure_el1_flags &
+				      ACPI_GTDT_ALWAYS_ON);
+
+	return 0;
+}
+
+/* Initialize the arch_timer_data struct for arm_arch_timer by GTDT info */
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data)
+{
+	if (acpi_disabled || !data)
+		return -EINVAL;
+
+	arch_timer_data_p = data;
+
+	return acpi_table_parse(ACPI_SIG_GTDT, arch_timer_data_init);
+}
+
 /*
  * Initialize a SBSA generic Watchdog platform device info from GTDT
  * According to SBSA specification the size of refresh and control
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 51d7865f..ea94a6f 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -109,6 +109,7 @@ config CLKSRC_EFM32
 config ARM_ARCH_TIMER
 	bool
 	select CLKSRC_OF if OF
+	select ACPI_GTDT if ACPI
 
 config ARM_ARCH_TIMER_EVTSTREAM
 	bool "Support for ARM architected timer event stream generation"
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 0aa135d..99505bb 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -817,68 +817,30 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
 		       arch_timer_mem_init);
 
 #ifdef CONFIG_ACPI
-static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
-{
-	int trigger, polarity;
-
-	if (!interrupt)
-		return 0;
-
-	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
-			: ACPI_LEVEL_SENSITIVE;
-
-	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
-			: ACPI_ACTIVE_HIGH;
-
-	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
-}
-
 /* Initialize per-processor generic timer */
-static int __init arch_timer_acpi_init(struct acpi_table_header *table)
+void __init arch_timer_acpi_init(void)
 {
-	struct acpi_table_gtdt *gtdt;
+	struct arch_timer_data data;
 
 	if (arch_timers_present & ARCH_CP15_TIMER) {
 		pr_warn("arch_timer: already initialized, skipping\n");
-		return -EINVAL;
+		return;
 	}
 
-	gtdt = container_of(table, struct acpi_table_gtdt, header);
-
 	arch_timers_present |= ARCH_CP15_TIMER;
 
-	arch_timer_ppi[PHYS_SECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
-		gtdt->secure_el1_flags);
-
-	arch_timer_ppi[PHYS_NONSECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
-		gtdt->non_secure_el1_flags);
-
-	arch_timer_ppi[VIRT_PPI] =
-		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
-		gtdt->virtual_timer_flags);
+	if (gtdt_arch_timer_data_init(&data))
+		return;
 
-	arch_timer_ppi[HYP_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
-		gtdt->non_secure_el2_flags);
+	arch_timer_ppi[PHYS_SECURE_PPI] = data.phys_secure_ppi;
+	arch_timer_ppi[PHYS_NONSECURE_PPI] = data.phys_nonsecure_ppi;
+	arch_timer_ppi[VIRT_PPI] = data.virt_ppi;
+	arch_timer_ppi[HYP_PPI] = data.hyp_ppi;
+	/* Always-on capability */
+	arch_timer_c3stop = data.c3stop;
 
 	/* Get the frequency from CNTFRQ */
 	arch_timer_detect_rate(NULL, NULL);
-
-	/* Always-on capability */
-	arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
-
 	arch_timer_init();
-	return 0;
-}
-
-/* Initialize all the generic timers presented in GTDT */
-void __init acpi_generic_timer_init(void)
-{
-	if (acpi_disabled)
-		return;
-
-	acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init);
 }
 #endif
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 9916d0e..5deed9d 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -43,6 +43,14 @@ enum arch_timer_reg {
 
 #define ARCH_TIMER_EVT_STREAM_FREQ	10000	/* 100us */
 
+struct arch_timer_data {
+	int phys_secure_ppi;
+	int phys_nonsecure_ppi;
+	int virt_ppi;
+	int hyp_ppi;
+	bool c3stop;
+};
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 598f0f1..7213c0d 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -458,6 +458,11 @@ void acpi_walk_dep_device_list(acpi_handle handle);
 struct platform_device *acpi_create_platform_device(struct acpi_device *);
 #define ACPI_PTR(_ptr)	(_ptr)
 
+#ifdef CONFIG_ACPI_GTDT
+struct arch_timer_data;
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data);
+#endif
+
 #else	/* !CONFIG_ACPI */
 
 #define acpi_disabled 1
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index d27d015..264e553 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -254,9 +254,9 @@ static inline void clocksource_of_init(void) {}
 #endif
 
 #ifdef CONFIG_ACPI
-void acpi_generic_timer_init(void);
+void arch_timer_acpi_init(void);
 #else
-static inline void acpi_generic_timer_init(void) { }
+static inline void arch_timer_acpi_init(void) { }
 #endif
 
 #endif /* _LINUX_CLOCKSOURCE_H */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v6 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
@ 2015-06-23 15:59     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-06-23 15:59 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A, timur-sgV2jX0FEOL9JmXXK+q4OQ,
	ashwin.chaugule-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA, panand-H+wXaHxf7aLQT0dZR+AlfA,
	Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

The patch update arm_arch_timer driver to use the function
provided by the new GTDT driver of ACPI.
By this way, arm_arch_timer.c can be simplified, and separate
all the ACPI GTDT knowledge from this timer driver.

Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm64/kernel/time.c             |  4 +--
 drivers/acpi/gtdt.c                  | 43 ++++++++++++++++++++++++++
 drivers/clocksource/Kconfig          |  1 +
 drivers/clocksource/arm_arch_timer.c | 60 +++++++-----------------------------
 include/clocksource/arm_arch_timer.h |  8 +++++
 include/linux/acpi.h                 |  5 +++
 include/linux/clocksource.h          |  4 +--
 7 files changed, 72 insertions(+), 53 deletions(-)

diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 42f9195..2cabea6 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -75,9 +75,9 @@ void __init time_init(void)
 
 	/*
 	 * Since ACPI or FDT will only one be available in the system,
-	 * we can use acpi_generic_timer_init() here safely
+	 * we can use arch_timer_acpi_init() here safely
 	 */
-	acpi_generic_timer_init();
+	arch_timer_acpi_init();
 
 	arch_timer_rate = arch_timer_get_rate();
 	if (!arch_timer_rate)
diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
index a92abf2..699c9fd 100644
--- a/drivers/acpi/gtdt.c
+++ b/drivers/acpi/gtdt.c
@@ -17,6 +17,8 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
+#include <clocksource/arm_arch_timer.h>
+
 static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 {
 	int trigger, polarity;
@@ -33,6 +35,47 @@ static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
 }
 
+struct arch_timer_data __initdata *arch_timer_data_p;
+
+static int __init arch_timer_data_init(struct acpi_table_header *table)
+{
+	struct acpi_table_gtdt *gtdt;
+
+	gtdt = container_of(table, struct acpi_table_gtdt, header);
+
+	arch_timer_data_p->phys_secure_ppi =
+		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
+					    gtdt->secure_el1_flags);
+
+	arch_timer_data_p->phys_nonsecure_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
+					    gtdt->non_secure_el1_flags);
+
+	arch_timer_data_p->virt_ppi =
+		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
+					    gtdt->virtual_timer_flags);
+
+	arch_timer_data_p->hyp_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
+					    gtdt->non_secure_el2_flags);
+
+	arch_timer_data_p->c3stop = !(gtdt->non_secure_el1_flags &
+				      ACPI_GTDT_ALWAYS_ON);
+
+	return 0;
+}
+
+/* Initialize the arch_timer_data struct for arm_arch_timer by GTDT info */
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data)
+{
+	if (acpi_disabled || !data)
+		return -EINVAL;
+
+	arch_timer_data_p = data;
+
+	return acpi_table_parse(ACPI_SIG_GTDT, arch_timer_data_init);
+}
+
 /*
  * Initialize a SBSA generic Watchdog platform device info from GTDT
  * According to SBSA specification the size of refresh and control
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 51d7865f..ea94a6f 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -109,6 +109,7 @@ config CLKSRC_EFM32
 config ARM_ARCH_TIMER
 	bool
 	select CLKSRC_OF if OF
+	select ACPI_GTDT if ACPI
 
 config ARM_ARCH_TIMER_EVTSTREAM
 	bool "Support for ARM architected timer event stream generation"
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 0aa135d..99505bb 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -817,68 +817,30 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
 		       arch_timer_mem_init);
 
 #ifdef CONFIG_ACPI
-static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
-{
-	int trigger, polarity;
-
-	if (!interrupt)
-		return 0;
-
-	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
-			: ACPI_LEVEL_SENSITIVE;
-
-	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
-			: ACPI_ACTIVE_HIGH;
-
-	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
-}
-
 /* Initialize per-processor generic timer */
-static int __init arch_timer_acpi_init(struct acpi_table_header *table)
+void __init arch_timer_acpi_init(void)
 {
-	struct acpi_table_gtdt *gtdt;
+	struct arch_timer_data data;
 
 	if (arch_timers_present & ARCH_CP15_TIMER) {
 		pr_warn("arch_timer: already initialized, skipping\n");
-		return -EINVAL;
+		return;
 	}
 
-	gtdt = container_of(table, struct acpi_table_gtdt, header);
-
 	arch_timers_present |= ARCH_CP15_TIMER;
 
-	arch_timer_ppi[PHYS_SECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
-		gtdt->secure_el1_flags);
-
-	arch_timer_ppi[PHYS_NONSECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
-		gtdt->non_secure_el1_flags);
-
-	arch_timer_ppi[VIRT_PPI] =
-		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
-		gtdt->virtual_timer_flags);
+	if (gtdt_arch_timer_data_init(&data))
+		return;
 
-	arch_timer_ppi[HYP_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
-		gtdt->non_secure_el2_flags);
+	arch_timer_ppi[PHYS_SECURE_PPI] = data.phys_secure_ppi;
+	arch_timer_ppi[PHYS_NONSECURE_PPI] = data.phys_nonsecure_ppi;
+	arch_timer_ppi[VIRT_PPI] = data.virt_ppi;
+	arch_timer_ppi[HYP_PPI] = data.hyp_ppi;
+	/* Always-on capability */
+	arch_timer_c3stop = data.c3stop;
 
 	/* Get the frequency from CNTFRQ */
 	arch_timer_detect_rate(NULL, NULL);
-
-	/* Always-on capability */
-	arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
-
 	arch_timer_init();
-	return 0;
-}
-
-/* Initialize all the generic timers presented in GTDT */
-void __init acpi_generic_timer_init(void)
-{
-	if (acpi_disabled)
-		return;
-
-	acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init);
 }
 #endif
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 9916d0e..5deed9d 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -43,6 +43,14 @@ enum arch_timer_reg {
 
 #define ARCH_TIMER_EVT_STREAM_FREQ	10000	/* 100us */
 
+struct arch_timer_data {
+	int phys_secure_ppi;
+	int phys_nonsecure_ppi;
+	int virt_ppi;
+	int hyp_ppi;
+	bool c3stop;
+};
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 598f0f1..7213c0d 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -458,6 +458,11 @@ void acpi_walk_dep_device_list(acpi_handle handle);
 struct platform_device *acpi_create_platform_device(struct acpi_device *);
 #define ACPI_PTR(_ptr)	(_ptr)
 
+#ifdef CONFIG_ACPI_GTDT
+struct arch_timer_data;
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data);
+#endif
+
 #else	/* !CONFIG_ACPI */
 
 #define acpi_disabled 1
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index d27d015..264e553 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -254,9 +254,9 @@ static inline void clocksource_of_init(void) {}
 #endif
 
 #ifdef CONFIG_ACPI
-void acpi_generic_timer_init(void);
+void arch_timer_acpi_init(void);
 #else
-static inline void acpi_generic_timer_init(void) { }
+static inline void arch_timer_acpi_init(void) { }
 #endif
 
 #endif /* _LINUX_CLOCKSOURCE_H */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [non-pretimeout,4/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-23 15:21           ` Guenter Roeck
  (?)
@ 2015-06-23 16:17           ` Fu Wei
  2015-06-23 16:43             ` Guenter Roeck
  -1 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-06-23 16:17 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

Hi Guenter,

you always can provide help very quickly, thank you very much :-)

On 23 June 2015 at 23:21, Guenter Roeck <linux@roeck-us.net> wrote:
> On Tue, Jun 23, 2015 at 09:26:35PM +0800, Fu Wei wrote:
>> Hi Guenter,
> [ ...]
>
>> >
>> >> + *       When the first timeout occurs, WS0(SPI or LPI) is triggered,
>> >> + *       the second timeout period(as long as the first timeout period) starts.
>> >
>> > no longer accurate if WOR is used for the second period.
>> >
>> >> + *       In WS0 interrupt routine, panic() will be called for collecting
>> >> + *       crashdown info.
>> >> + *       If system can not recover from WS0 interrupt routine, then second
>> >> + *       timeout occurs, WS1(reset or higher level interrupt) is triggered.
>> >> + *       The two timeout period can be set by WOR(32bit).
>> >
>> > The second timeout period is determined by ...
>> >
>> >> + *       WOR gives a maximum watch period of around 10s at the maximum
>> >> + *       system counter frequency.
>> >> + *       The System Counter shall run at maximum of 400MHz.
>> >
>> > "... at the maximum system counter frequency of 400 MHz.", and drop the
>> > last sentence.
>>
>> For the second timeout period,  I have discussed with a kdump developers,
>> (1)10s maybe not good enough for all the case of panic + kdump, so
>> maybe we still need to use WCV in the second timeout period
>> (2)in the second timeout period, maybe we need to programme WCV for
>> two reason: a, trigger WS1 to reboot system ASAP; b, feed the watchdog
>> without cleanning WS0 flag.
>>
>> WHY we want to feed the watchdog (keepalive) without cleanning WS0 flag??
>> REASON:
>> (1)if the system context is large, we may need to feed the dog until
>> we get all the things backed up.
>> (2)if system goes wrong,  WS0 triggered, then panic--> kdump. if we
>> feed the dog by WRR or programming WOR, WS0 flag will be cleaned. Once
>> system goes wrong again, then panic again.....
>> So this system will be in a panic--kdump--panic--kdump loop, have not
>> chance to reset.
>>
>> So if we are in the second timeout period, we may need to always programme WCV.
>>
> The crashdump kernel is supposed to reload the watchdog driver, which will ping
> the watchdog. If it isn't able to do that in 10 seconds, something is wrong.

yes, 10s maybe not enough for all case.
When I tested kdump on arm64, sometimes , it took 20s. So I am
thinking : can we make the max value of pretimeout > 10s in this
driver.


>
>> >> +
>> >> +     status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
>> >> +     if (status & SBSA_GWDT_WCS_WS1) {
>> >> +             dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
>> >> +                      sbsa_gwdt_get_wcv(wdd));
>> >
>> > WCV here only tells us how many clock cycles were executed since the
>> > system started (or something like that). So I still don't understand
>> > why it is valuable to print that number.
>>
>> this number provides the time of system reset, I thinks that may help
>> admin to analyse the system failure.
>>
> It doesn't mean anything to anyone but you since it is not in a well defined
> time scale.

maybe I should convert it to second?
I think the original value is better?

> Also, I would be somewhat surprised if WCV would retain its value
> on reset. Much more likely it is the time (in clock cycles) since reset.

yes, It has been mentioned in SBSA:
---------------------
If WS0 is asserted and a timeout refresh occurs then the following must occur:
 If the system is compliant to SBSA level 0 or level 1 then it is
IMPLEMENTATION DEFINED as to whether the
   compare value is loaded with the sum of the zero-extended watchdog
offset register and the current
  generic timer system count value, or whether it retains its current value.
 If the system is compliant to SBSA level 2 or higher the compare
value must retain its current value. This
   means that the compare value records the time that WS1 is asserted.
---------------------

Hope I understand it correctly. please let me know , if I
misunderstand something, 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [non-pretimeout,4/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-23 16:17           ` Fu Wei
@ 2015-06-23 16:43             ` Guenter Roeck
  2015-06-23 17:01                 ` Fu Wei
  0 siblings, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-06-23 16:43 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

On Wed, Jun 24, 2015 at 12:17:19AM +0800, Fu Wei wrote:
> Hi Guenter,
> 
> you always can provide help very quickly, thank you very much :-)
> 
> On 23 June 2015 at 23:21, Guenter Roeck <linux@roeck-us.net> wrote:
> > On Tue, Jun 23, 2015 at 09:26:35PM +0800, Fu Wei wrote:
> >> Hi Guenter,
> > [ ...]
> >
> >> >
> >> >> + *       When the first timeout occurs, WS0(SPI or LPI) is triggered,
> >> >> + *       the second timeout period(as long as the first timeout period) starts.
> >> >
> >> > no longer accurate if WOR is used for the second period.
> >> >
> >> >> + *       In WS0 interrupt routine, panic() will be called for collecting
> >> >> + *       crashdown info.
> >> >> + *       If system can not recover from WS0 interrupt routine, then second
> >> >> + *       timeout occurs, WS1(reset or higher level interrupt) is triggered.
> >> >> + *       The two timeout period can be set by WOR(32bit).
> >> >
> >> > The second timeout period is determined by ...
> >> >
> >> >> + *       WOR gives a maximum watch period of around 10s at the maximum
> >> >> + *       system counter frequency.
> >> >> + *       The System Counter shall run at maximum of 400MHz.
> >> >
> >> > "... at the maximum system counter frequency of 400 MHz.", and drop the
> >> > last sentence.
> >>
> >> For the second timeout period,  I have discussed with a kdump developers,
> >> (1)10s maybe not good enough for all the case of panic + kdump, so
> >> maybe we still need to use WCV in the second timeout period
> >> (2)in the second timeout period, maybe we need to programme WCV for
> >> two reason: a, trigger WS1 to reboot system ASAP; b, feed the watchdog
> >> without cleanning WS0 flag.
> >>
> >> WHY we want to feed the watchdog (keepalive) without cleanning WS0 flag??
> >> REASON:
> >> (1)if the system context is large, we may need to feed the dog until
> >> we get all the things backed up.
> >> (2)if system goes wrong,  WS0 triggered, then panic--> kdump. if we
> >> feed the dog by WRR or programming WOR, WS0 flag will be cleaned. Once
> >> system goes wrong again, then panic again.....
> >> So this system will be in a panic--kdump--panic--kdump loop, have not
> >> chance to reset.
> >>
> >> So if we are in the second timeout period, we may need to always programme WCV.
> >>
> > The crashdump kernel is supposed to reload the watchdog driver, which will ping
> > the watchdog. If it isn't able to do that in 10 seconds, something is wrong.
> 
> yes, 10s maybe not enough for all case.
> When I tested kdump on arm64, sometimes , it took 20s. So I am
> thinking : can we make the max value of pretimeout > 10s in this
> driver.
> 
It takes more than 10 seconds to load the crashdump kernel,
or it takes more than 10 seconds to complete the dump ?

> 
> >
> >> >> +
> >> >> +     status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
> >> >> +     if (status & SBSA_GWDT_WCS_WS1) {
> >> >> +             dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
> >> >> +                      sbsa_gwdt_get_wcv(wdd));
> >> >
> >> > WCV here only tells us how many clock cycles were executed since the
> >> > system started (or something like that). So I still don't understand
> >> > why it is valuable to print that number.
> >>
> >> this number provides the time of system reset, I thinks that may help
> >> admin to analyse the system failure.
> >>
> > It doesn't mean anything to anyone but you since it is not in a well defined
> > time scale.
> 
> maybe I should convert it to second?
> I think the original value is better?
> 

I think you should drop it.

Guenter

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [non-pretimeout,4/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-23 17:01                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-23 17:01 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw

Hi Guenter

On 24 June 2015 at 00:43, Guenter Roeck <linux@roeck-us.net> wrote:
> On Wed, Jun 24, 2015 at 12:17:19AM +0800, Fu Wei wrote:
>> Hi Guenter,
>>
>> you always can provide help very quickly, thank you very much :-)
>>
>> On 23 June 2015 at 23:21, Guenter Roeck <linux@roeck-us.net> wrote:
>> > On Tue, Jun 23, 2015 at 09:26:35PM +0800, Fu Wei wrote:
>> >> Hi Guenter,
>> > [ ...]
>> >
>> >> >
>> >> >> + *       When the first timeout occurs, WS0(SPI or LPI) is triggered,
>> >> >> + *       the second timeout period(as long as the first timeout period) starts.
>> >> >
>> >> > no longer accurate if WOR is used for the second period.
>> >> >
>> >> >> + *       In WS0 interrupt routine, panic() will be called for collecting
>> >> >> + *       crashdown info.
>> >> >> + *       If system can not recover from WS0 interrupt routine, then second
>> >> >> + *       timeout occurs, WS1(reset or higher level interrupt) is triggered.
>> >> >> + *       The two timeout period can be set by WOR(32bit).
>> >> >
>> >> > The second timeout period is determined by ...
>> >> >
>> >> >> + *       WOR gives a maximum watch period of around 10s at the maximum
>> >> >> + *       system counter frequency.
>> >> >> + *       The System Counter shall run at maximum of 400MHz.
>> >> >
>> >> > "... at the maximum system counter frequency of 400 MHz.", and drop the
>> >> > last sentence.
>> >>
>> >> For the second timeout period,  I have discussed with a kdump developers,
>> >> (1)10s maybe not good enough for all the case of panic + kdump, so
>> >> maybe we still need to use WCV in the second timeout period
>> >> (2)in the second timeout period, maybe we need to programme WCV for
>> >> two reason: a, trigger WS1 to reboot system ASAP; b, feed the watchdog
>> >> without cleanning WS0 flag.
>> >>
>> >> WHY we want to feed the watchdog (keepalive) without cleanning WS0 flag??
>> >> REASON:
>> >> (1)if the system context is large, we may need to feed the dog until
>> >> we get all the things backed up.
>> >> (2)if system goes wrong,  WS0 triggered, then panic--> kdump. if we
>> >> feed the dog by WRR or programming WOR, WS0 flag will be cleaned. Once
>> >> system goes wrong again, then panic again.....
>> >> So this system will be in a panic--kdump--panic--kdump loop, have not
>> >> chance to reset.
>> >>
>> >> So if we are in the second timeout period, we may need to always programme WCV.
>> >>
>> > The crashdump kernel is supposed to reload the watchdog driver, which will ping
>> > the watchdog. If it isn't able to do that in 10 seconds, something is wrong.
>>
>> yes, 10s maybe not enough for all case.
>> When I tested kdump on arm64, sometimes , it took 20s. So I am
>> thinking : can we make the max value of pretimeout > 10s in this
>> driver.
>>
> It takes more than 10 seconds to load the crashdump kernel,
> or it takes more than 10 seconds to complete the dump ?

It takes more than 10 seconds to boot into kernel(from panic to finish
devices init in crashdump kernel).
I thinks that maybe depend on hardware or soc.
As I said, 10 seconds maybe not enough for all cases.

For completing the dump, 10 seconds maybe not enough for some case(big
RAM, dump to network and so on),
that is why I added "ping without cleaning WS0" support in the second stage.

>
>>
>> >
>> >> >> +
>> >> >> +     status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
>> >> >> +     if (status & SBSA_GWDT_WCS_WS1) {
>> >> >> +             dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
>> >> >> +                      sbsa_gwdt_get_wcv(wdd));
>> >> >
>> >> > WCV here only tells us how many clock cycles were executed since the
>> >> > system started (or something like that). So I still don't understand
>> >> > why it is valuable to print that number.
>> >>
>> >> this number provides the time of system reset, I thinks that may help
>> >> admin to analyse the system failure.
>> >>
>> > It doesn't mean anything to anyone but you since it is not in a well defined
>> > time scale.
>>
>> maybe I should convert it to second?
>> I think the original value is better?
>>
>
> I think you should drop it.

OK, will do in my next patchset.

But my option is if hardware provide this info, and it can let admin
know the crash time.  maybe it can help to debug.
 :-)

>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [non-pretimeout,4/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-23 17:01                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-23 17:01 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon,
	rjw-LthD3rsA81gm4RdzfppkhA

Hi Guenter

On 24 June 2015 at 00:43, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On Wed, Jun 24, 2015 at 12:17:19AM +0800, Fu Wei wrote:
>> Hi Guenter,
>>
>> you always can provide help very quickly, thank you very much :-)
>>
>> On 23 June 2015 at 23:21, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
>> > On Tue, Jun 23, 2015 at 09:26:35PM +0800, Fu Wei wrote:
>> >> Hi Guenter,
>> > [ ...]
>> >
>> >> >
>> >> >> + *       When the first timeout occurs, WS0(SPI or LPI) is triggered,
>> >> >> + *       the second timeout period(as long as the first timeout period) starts.
>> >> >
>> >> > no longer accurate if WOR is used for the second period.
>> >> >
>> >> >> + *       In WS0 interrupt routine, panic() will be called for collecting
>> >> >> + *       crashdown info.
>> >> >> + *       If system can not recover from WS0 interrupt routine, then second
>> >> >> + *       timeout occurs, WS1(reset or higher level interrupt) is triggered.
>> >> >> + *       The two timeout period can be set by WOR(32bit).
>> >> >
>> >> > The second timeout period is determined by ...
>> >> >
>> >> >> + *       WOR gives a maximum watch period of around 10s at the maximum
>> >> >> + *       system counter frequency.
>> >> >> + *       The System Counter shall run at maximum of 400MHz.
>> >> >
>> >> > "... at the maximum system counter frequency of 400 MHz.", and drop the
>> >> > last sentence.
>> >>
>> >> For the second timeout period,  I have discussed with a kdump developers,
>> >> (1)10s maybe not good enough for all the case of panic + kdump, so
>> >> maybe we still need to use WCV in the second timeout period
>> >> (2)in the second timeout period, maybe we need to programme WCV for
>> >> two reason: a, trigger WS1 to reboot system ASAP; b, feed the watchdog
>> >> without cleanning WS0 flag.
>> >>
>> >> WHY we want to feed the watchdog (keepalive) without cleanning WS0 flag??
>> >> REASON:
>> >> (1)if the system context is large, we may need to feed the dog until
>> >> we get all the things backed up.
>> >> (2)if system goes wrong,  WS0 triggered, then panic--> kdump. if we
>> >> feed the dog by WRR or programming WOR, WS0 flag will be cleaned. Once
>> >> system goes wrong again, then panic again.....
>> >> So this system will be in a panic--kdump--panic--kdump loop, have not
>> >> chance to reset.
>> >>
>> >> So if we are in the second timeout period, we may need to always programme WCV.
>> >>
>> > The crashdump kernel is supposed to reload the watchdog driver, which will ping
>> > the watchdog. If it isn't able to do that in 10 seconds, something is wrong.
>>
>> yes, 10s maybe not enough for all case.
>> When I tested kdump on arm64, sometimes , it took 20s. So I am
>> thinking : can we make the max value of pretimeout > 10s in this
>> driver.
>>
> It takes more than 10 seconds to load the crashdump kernel,
> or it takes more than 10 seconds to complete the dump ?

It takes more than 10 seconds to boot into kernel(from panic to finish
devices init in crashdump kernel).
I thinks that maybe depend on hardware or soc.
As I said, 10 seconds maybe not enough for all cases.

For completing the dump, 10 seconds maybe not enough for some case(big
RAM, dump to network and so on),
that is why I added "ping without cleaning WS0" support in the second stage.

>
>>
>> >
>> >> >> +
>> >> >> +     status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
>> >> >> +     if (status & SBSA_GWDT_WCS_WS1) {
>> >> >> +             dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
>> >> >> +                      sbsa_gwdt_get_wcv(wdd));
>> >> >
>> >> > WCV here only tells us how many clock cycles were executed since the
>> >> > system started (or something like that). So I still don't understand
>> >> > why it is valuable to print that number.
>> >>
>> >> this number provides the time of system reset, I thinks that may help
>> >> admin to analyse the system failure.
>> >>
>> > It doesn't mean anything to anyone but you since it is not in a well defined
>> > time scale.
>>
>> maybe I should convert it to second?
>> I think the original value is better?
>>
>
> I think you should drop it.

OK, will do in my next patchset.

But my option is if hardware provide this info, and it can let admin
know the crash time.  maybe it can help to debug.
 :-)

>
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 0/8] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-29 16:53     ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-29 16:53 UTC (permalink / raw)
  To: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: Wei Fu, G Gregory, Al Stone, Hanjun Guo, Timur Tabi,
	Ashwin Chaugule, Arnd Bergmann, Guenter Roeck, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, rjw, dyoung, panand,
	Fu Wei

Hi Guenter,

Any suggestion on this v6 patchset, for now , I only got :
(1) delete WCV output:
diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
index 2de5899..c42883b 100644
--- a/drivers/watchdog/sbsa_gwdt.c
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -344,8 +342,7 @@ static int sbsa_gwdt_probe(struct platform_device *pdev)

        status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
        if (status & SBSA_GWDT_WCS_WS1) {
-               dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
-                        sbsa_gwdt_get_wcv(wdd));
+               dev_warn(dev, "System reset by WDT.\n");
                wdd->bootstatus |= WDIOF_CARDRESET;
        } else if (status == (SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_EN)) {
                gwdt->ws0_mode = true;

any question or anything I can improve for this patchset?

Great thanks for your help.


On 23 June 2015 at 22:16,  <fu.wei@linaro.org> wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> This patchset:
>     (1)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.
>
>     (2)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".
>
>     (3)Introduce ARM SBSA watchdog driver:
>         a.Use linux kernel watchdog framework;
>         b.Work with FDT on ARM64;
>         c.Use "pretimeout" in watchdog framework;
>         d.Support getting timeout and pretimeout from parameter and FDT
>           at the driver init stage.
>         e.In the first timeout, do panic to save system context;
>         f.In the second stage, user can still feed the dog without
>           cleaning WS0. By this feature, we can avoid the panic infinite
>           loops, while backing up a large system context in a server.
>         g.In the second stage, can trigger WS1 by setting pretimeout = 0
>           if necessary.
>
>     (4)Introduce ACPI GTDT parser: drivers/acpi/gtdt.c
>     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.
>     drivers/clocksource/arm_arch_timer.c is simplified by this GTDT support.
>
> This patchset has been tested with watchdog daemon
> (ACPI/FDT, module/build-in) on the following platforms:
>     (1)ARM Foundation v8 model
>
> Changelog:
> v6: Improve the dtb example files: reduce the register frame size to 4K.
>     Improve pretimeout support:
>         (1) improve watchdog_init_timeouts function
>         (2) rename watchdog_check_min_max_timeouts back to the original name
>         (1) improve watchdog_timeout_invalid/watchdog_pretimeout_invalid
>     Add the new features in the sbsa_gwdt driver:
>         (1) In the second stage, user can feed the dog without cleaning WS0.
>         (2) In the second stage, user can trigger WS1 by setting pretimeout = 0.
>         (3) expand the max value of pretimeout, in case 10 second is not enough
>             for a kdump kernel reboot in panic.
>
> v5: Improve pretimeout support:
>         (1)fix typo in documentation and comments.
>         (2)fix the timeout limits validation bug.
>     Simplify sbsa_gwdt driver:
>         (1)integrate all the registers access functions into caller.
>
> v4: Refactor GTDT support code: remove it from arch/arm64/kernel/acpi.c,
>     put it into drivers/acpi/gtdt.c file.
>     Integrate the GTDT code of drivers/clocksource/arm_arch_timer.c into
>     drivers/acpi/gtdt.c.
>     Improve pretimeout support, fix "pretimeout == 0" problem.
>     Simplify sbsa_gwdt driver:
>         (1)timeout/pretimeout limits setup;
>         (2)keepalive function;
>         (3)delete "clk == 0" check;
>         (4)delete WS0 status bit check in interrupt routine;
>         (5)sbsa_gwdt_set_wcv function.
>
> v3: Delete "export arch_timer_get_rate" patch.
>     Driver back to use arch_timer_get_cntfrq.
>     Improve watchdog_init_timeouts function and update relevant documentation.
>     Improve watchdog_timeout_invalid and watchdog_pretimeout_invalid.
>     Improve foundation-v8.dts: delete the unnecessary tag of device node.
>     Remove "ARM64 || COMPILE_TEST" from Kconfig.
>     Add comments in arch/arm64/kernel/acpi.c
>     Fix typoes and incorrect comments.
>
> 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 (8):
>   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: introdouce "pretimeout" into framework
>   Watchdog: introduce ARM SBSA watchdog driver
>   ACPI: add GTDT table parse driver into ACPI driver
>   Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
>   clocksource: simplify ACPI code in arm_arch_timer.c
>
>  .../devicetree/bindings/watchdog/sbsa-gwdt.txt     |  36 ++
>  Documentation/watchdog/watchdog-kernel-api.txt     |  47 ++-
>  arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi       |  11 +
>  arch/arm64/boot/dts/arm/foundation-v8.dts          |  10 +
>  arch/arm64/kernel/time.c                           |   4 +-
>  drivers/acpi/Kconfig                               |   9 +
>  drivers/acpi/Makefile                              |   1 +
>  drivers/acpi/gtdt.c                                | 180 ++++++++
>  drivers/clocksource/Kconfig                        |   1 +
>  drivers/clocksource/arm_arch_timer.c               |  60 +--
>  drivers/watchdog/Kconfig                           |  15 +
>  drivers/watchdog/Makefile                          |   1 +
>  drivers/watchdog/sbsa_gwdt.c                       | 455 +++++++++++++++++++++
>  drivers/watchdog/watchdog_core.c                   |  98 +++--
>  drivers/watchdog/watchdog_dev.c                    |  53 +++
>  include/clocksource/arm_arch_timer.h               |   8 +
>  include/linux/acpi.h                               |   5 +
>  include/linux/clocksource.h                        |   4 +-
>  include/linux/watchdog.h                           |  39 +-
>  19 files changed, 947 insertions(+), 90 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
>  create mode 100644 drivers/acpi/gtdt.c
>  create mode 100644 drivers/watchdog/sbsa_gwdt.c
>
> --
> 1.9.1
>



-- 
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

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 0/8] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-06-29 16:53     ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-29 16:53 UTC (permalink / raw)
  To: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: Wei Fu, G Gregory, Al Stone, Hanjun Guo, Timur Tabi,
	Ashwin Chaugule, Arnd Bergmann, Guenter Roeck, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon,
	rjw-LthD3rsA81gm4RdzfppkhA, dyoung-H+wXaHxf7aLQT0dZR+AlfA,
	panand-H+wXaHxf7aLQT0dZR+AlfA, Fu Wei

Hi Guenter,

Any suggestion on this v6 patchset, for now , I only got :
(1) delete WCV output:
diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
index 2de5899..c42883b 100644
--- a/drivers/watchdog/sbsa_gwdt.c
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -344,8 +342,7 @@ static int sbsa_gwdt_probe(struct platform_device *pdev)

        status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
        if (status & SBSA_GWDT_WCS_WS1) {
-               dev_warn(dev, "System reset by WDT(WCV: %llx)\n",
-                        sbsa_gwdt_get_wcv(wdd));
+               dev_warn(dev, "System reset by WDT.\n");
                wdd->bootstatus |= WDIOF_CARDRESET;
        } else if (status == (SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_EN)) {
                gwdt->ws0_mode = true;

any question or anything I can improve for this patchset?

Great thanks for your help.


On 23 June 2015 at 22:16,  <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> This patchset:
>     (1)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.
>
>     (2)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".
>
>     (3)Introduce ARM SBSA watchdog driver:
>         a.Use linux kernel watchdog framework;
>         b.Work with FDT on ARM64;
>         c.Use "pretimeout" in watchdog framework;
>         d.Support getting timeout and pretimeout from parameter and FDT
>           at the driver init stage.
>         e.In the first timeout, do panic to save system context;
>         f.In the second stage, user can still feed the dog without
>           cleaning WS0. By this feature, we can avoid the panic infinite
>           loops, while backing up a large system context in a server.
>         g.In the second stage, can trigger WS1 by setting pretimeout = 0
>           if necessary.
>
>     (4)Introduce ACPI GTDT parser: drivers/acpi/gtdt.c
>     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.
>     drivers/clocksource/arm_arch_timer.c is simplified by this GTDT support.
>
> This patchset has been tested with watchdog daemon
> (ACPI/FDT, module/build-in) on the following platforms:
>     (1)ARM Foundation v8 model
>
> Changelog:
> v6: Improve the dtb example files: reduce the register frame size to 4K.
>     Improve pretimeout support:
>         (1) improve watchdog_init_timeouts function
>         (2) rename watchdog_check_min_max_timeouts back to the original name
>         (1) improve watchdog_timeout_invalid/watchdog_pretimeout_invalid
>     Add the new features in the sbsa_gwdt driver:
>         (1) In the second stage, user can feed the dog without cleaning WS0.
>         (2) In the second stage, user can trigger WS1 by setting pretimeout = 0.
>         (3) expand the max value of pretimeout, in case 10 second is not enough
>             for a kdump kernel reboot in panic.
>
> v5: Improve pretimeout support:
>         (1)fix typo in documentation and comments.
>         (2)fix the timeout limits validation bug.
>     Simplify sbsa_gwdt driver:
>         (1)integrate all the registers access functions into caller.
>
> v4: Refactor GTDT support code: remove it from arch/arm64/kernel/acpi.c,
>     put it into drivers/acpi/gtdt.c file.
>     Integrate the GTDT code of drivers/clocksource/arm_arch_timer.c into
>     drivers/acpi/gtdt.c.
>     Improve pretimeout support, fix "pretimeout == 0" problem.
>     Simplify sbsa_gwdt driver:
>         (1)timeout/pretimeout limits setup;
>         (2)keepalive function;
>         (3)delete "clk == 0" check;
>         (4)delete WS0 status bit check in interrupt routine;
>         (5)sbsa_gwdt_set_wcv function.
>
> v3: Delete "export arch_timer_get_rate" patch.
>     Driver back to use arch_timer_get_cntfrq.
>     Improve watchdog_init_timeouts function and update relevant documentation.
>     Improve watchdog_timeout_invalid and watchdog_pretimeout_invalid.
>     Improve foundation-v8.dts: delete the unnecessary tag of device node.
>     Remove "ARM64 || COMPILE_TEST" from Kconfig.
>     Add comments in arch/arm64/kernel/acpi.c
>     Fix typoes and incorrect comments.
>
> 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 (8):
>   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: introdouce "pretimeout" into framework
>   Watchdog: introduce ARM SBSA watchdog driver
>   ACPI: add GTDT table parse driver into ACPI driver
>   Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
>   clocksource: simplify ACPI code in arm_arch_timer.c
>
>  .../devicetree/bindings/watchdog/sbsa-gwdt.txt     |  36 ++
>  Documentation/watchdog/watchdog-kernel-api.txt     |  47 ++-
>  arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi       |  11 +
>  arch/arm64/boot/dts/arm/foundation-v8.dts          |  10 +
>  arch/arm64/kernel/time.c                           |   4 +-
>  drivers/acpi/Kconfig                               |   9 +
>  drivers/acpi/Makefile                              |   1 +
>  drivers/acpi/gtdt.c                                | 180 ++++++++
>  drivers/clocksource/Kconfig                        |   1 +
>  drivers/clocksource/arm_arch_timer.c               |  60 +--
>  drivers/watchdog/Kconfig                           |  15 +
>  drivers/watchdog/Makefile                          |   1 +
>  drivers/watchdog/sbsa_gwdt.c                       | 455 +++++++++++++++++++++
>  drivers/watchdog/watchdog_core.c                   |  98 +++--
>  drivers/watchdog/watchdog_dev.c                    |  53 +++
>  include/clocksource/arm_arch_timer.h               |   8 +
>  include/linux/acpi.h                               |   5 +
>  include/linux/clocksource.h                        |   4 +-
>  include/linux/watchdog.h                           |  39 +-
>  19 files changed, 947 insertions(+), 90 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
>  create mode 100644 drivers/acpi/gtdt.c
>  create mode 100644 drivers/watchdog/sbsa_gwdt.c
>
> --
> 1.9.1
>



-- 
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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 0/8] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-29 16:53     ` Fu Wei
  (?)
@ 2015-06-29 19:16     ` Guenter Roeck
  2015-06-30 23:47       ` Fu Wei
  2015-07-13  9:09         ` Fu Wei
  -1 siblings, 2 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-06-29 19:16 UTC (permalink / raw)
  To: Fu Wei, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, linux-kernel, linux-doc
  Cc: Wei Fu, G Gregory, Al Stone, Hanjun Guo, Timur Tabi,
	Ashwin Chaugule, Arnd Bergmann, Vipul Gandhi, Wim Van Sebroeck,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, rjw, dyoung, panand

On 06/29/2015 09:53 AM, Fu Wei wrote:
> Hi Guenter,
>
> Any suggestion on this v6 patchset, for now , I only got :

Problem is that each version of your patchset tends to introduce substantially
new or different functionality, meaning the review has to pretty much start
from scratch. Right now I just don't have time to do that, so you'll have
to be a bit patient.

Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 0/8] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-29 19:16     ` Guenter Roeck
@ 2015-06-30 23:47       ` Fu Wei
  2015-07-13  9:09         ` Fu Wei
  1 sibling, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-06-30 23:47 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw,
	dyoung, panand

Hi Guenter,

Great thanks for your time,
I can't tell you how much I appreciate your review! :-)

np, I will improve my patchset, once I get your suggestion. :-)

On 30 June 2015 at 03:16, Guenter Roeck <linux@roeck-us.net> wrote:
> On 06/29/2015 09:53 AM, Fu Wei wrote:
>>
>> Hi Guenter,
>>
>> Any suggestion on this v6 patchset, for now , I only got :
>
>
> Problem is that each version of your patchset tends to introduce
> substantially
> new or different functionality, meaning the review has to pretty much start
> from scratch. Right now I just don't have time to do that, so you'll have
> to be a bit patient.
>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v2 0/3] arm64: Add multiboot support (via fdt) for Xen boot
       [not found] <=fu.wei@linaro.org>
                   ` (8 preceding siblings ...)
  2015-06-23 15:59 ` [PATCH v6 5/8] " fu.wei
@ 2015-07-13  8:53 ` fu.wei
  2015-07-13  8:53   ` [PATCH v2 1/3] arm64: Add Xen boot support file fu.wei
                     ` (4 more replies)
  2015-07-23  5:16 ` [PATCH v3 0/4] arm64: Add Xen boot support (via fdt) fu.wei
                   ` (4 subsequent siblings)
  14 siblings, 5 replies; 550+ messages in thread
From: fu.wei @ 2015-07-13  8:53 UTC (permalink / raw)
  To: grub-devel, arvidjaar, phcoder
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

  - This adds support for the Xen boot on ARM specification for arm64.

  - The implementation for Xen is following  <Multiboot on ARM Specification>:
    http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
    and xen/docs/misc/arm/device-tree/booting.txt in Xen source code.

  - The multiboot/module commands have existed, so we use 
    xen_hypervisor/xen_module instead.

  - This Xen boot support is built into linux module for aarch64,
    and can not be used alone.

  - Adding this functionality to the existing "linux" module is for
    reusing the existing code of devicetree.

  - Add the support of xen_hypervisor/xen_module commands in util/grub.d/20_linux_xen.in

  - Add the introduction of xen_hypervisor/xen_module commands in docs/grub.texi

  - The example of this support is <How to boot Xen with GRUB on AArch64 the Foundation FVP model>
    https://wiki.linaro.org/LEG/Engineering/Grub2/Xen_booting_on_Foundation_FVP_model_by_GRUB

Changelog:
v2: remove the patches which have been accepted.
    according to Vladimir's suggestion, change the command manes
    and relevant code:
        multiboot-->xen_hypervisor
        module-->xen_module
    improve the option parsing support for xen_hypervisor/xen_module commands.
    add a patch for adding xen_hypervisor/xen_module support
    in util/grub.d/20_linux_xen.in.
    update docs/grub.texi patch for the new command names.

v1: The first version upstream patchset to grub-devel mailing list


Fu Wei (3):
  arm64: Add Xen boot support file
  * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
  arm64: Add the introduction of xen_hypervisor/xen_module command in
    docs/grub.texi

 docs/grub.texi                    |  27 ++
 grub-core/Makefile.core.def       |   1 +
 grub-core/loader/arm64/linux.c    |   6 +
 grub-core/loader/arm64/xen_boot.c | 615 ++++++++++++++++++++++++++++++++++++++
 include/grub/arm64/xen_boot.h     | 115 +++++++
 util/grub.d/20_linux_xen.in       |  14 +-
 6 files changed, 775 insertions(+), 3 deletions(-)
 create mode 100644 grub-core/loader/arm64/xen_boot.c
 create mode 100644 include/grub/arm64/xen_boot.h

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v2 1/3] arm64: Add Xen boot support file
  2015-07-13  8:53 ` [PATCH v2 0/3] arm64: Add multiboot support (via fdt) for Xen boot fu.wei
@ 2015-07-13  8:53   ` fu.wei
  2015-07-15 16:18       ` Vladimir 'φ-coder/phcoder' Serbinenko
  2015-07-13  8:53   ` [PATCH v2 2/3] util/grub.d/20_linux_xen.in: Add arm64 support fu.wei
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 550+ messages in thread
From: fu.wei @ 2015-07-13  8:53 UTC (permalink / raw)
  To: grub-devel, arvidjaar, phcoder
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patch adds Xen boot support file:
grub-core/loader/arm64/xen_boot.c
include/grub/arm64/xen_boot.h

This patch also adds commands register code and hearder file into
grub-core/loader/arm64/linux.c

  - This adds support for the Xen boot on ARM specification for arm64.
  - The implementation for Xen is following  <Multiboot on ARM Specification>:
      http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
    and xen/docs/misc/arm/device-tree/booting.txt in Xen source code.
  - The multiboot/module commands have existed,
    so we use xen_hypervisor/xen_module instead.
  - This Xen boot support is built into linux module for aarch64.
  - Adding this functionality to the existing "linux" module is for
    reusing the existing code of devicetree.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 grub-core/Makefile.core.def       |   1 +
 grub-core/loader/arm64/linux.c    |   6 +
 grub-core/loader/arm64/xen_boot.c | 615 ++++++++++++++++++++++++++++++++++++++
 include/grub/arm64/xen_boot.h     | 115 +++++++
 4 files changed, 737 insertions(+)
 create mode 100644 grub-core/loader/arm64/xen_boot.c
 create mode 100644 include/grub/arm64/xen_boot.h

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index a6101de..01f8261 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1659,6 +1659,7 @@ module = {
   ia64_efi = loader/ia64/efi/linux.c;
   arm = loader/arm/linux.c;
   arm64 = loader/arm64/linux.c;
+  arm64 = loader/arm64/xen_boot.c;
   fdt = lib/fdt.c;
   common = loader/linux.c;
   common = lib/cmdline.c;
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
index 987f5b9..7ae9bde 100644
--- a/grub-core/loader/arm64/linux.c
+++ b/grub-core/loader/arm64/linux.c
@@ -26,6 +26,7 @@
 #include <grub/mm.h>
 #include <grub/types.h>
 #include <grub/cpu/linux.h>
+#include <grub/cpu/xen_boot.h>
 #include <grub/efi/efi.h>
 #include <grub/efi/pe32.h>
 #include <grub/i18n.h>
@@ -477,6 +478,9 @@ GRUB_MOD_INIT (linux)
   cmd_devicetree =
     grub_register_command ("devicetree", grub_cmd_devicetree, 0,
 			   N_("Load DTB file."));
+
+  grub_arm64_linux_register_xen_boot_command (mod, &loaded);
+
   my_mod = mod;
 }
 
@@ -485,4 +489,6 @@ GRUB_MOD_FINI (linux)
   grub_unregister_command (cmd_linux);
   grub_unregister_command (cmd_initrd);
   grub_unregister_command (cmd_devicetree);
+
+  grub_arm64_linux_unregister_xen_boot_command ();
 }
diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
new file mode 100644
index 0000000..23bd00e
--- /dev/null
+++ b/grub-core/loader/arm64/xen_boot.c
@@ -0,0 +1,615 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2014  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/cache.h>
+#include <grub/charset.h>
+#include <grub/command.h>
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/fdt.h>
+#include <grub/linux.h>
+#include <grub/list.h>
+#include <grub/loader.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/cpu/linux.h>
+#include <grub/cpu/xen_boot.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/pe32.h>
+#include <grub/i18n.h>
+#include <grub/lib/cmdline.h>
+
+static grub_dl_t linux_mod;
+static int *loaded;
+
+static struct xen_boot_binary *xen_hypervisor;
+static struct xen_boot_binary *module_head;
+static const grub_size_t module_default_align[] = {
+  MODULE_IMAGE_MIN_ALIGN,
+  MODULE_INITRD_MIN_ALIGN,
+  MODULE_OTHER_MIN_ALIGN,
+  MODULE_CUSTOM_MIN_ALIGN
+};
+
+static void *xen_boot_fdt;
+static const compat_string_struct_t default_compat_string[] = {
+  FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
+  FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
+  FDT_COMPATIBLE (MODULE_OTHER_COMPATIBLE)
+};
+
+
+/* Parse all the options of xen_module command. For now, we support
+   (1) --type <the compatible stream>
+   (2) --nounzip
+   We also set up the type of module in this function.
+   If there are some "--type" options in the command line,
+   we make a custom compatible stream in this function. */
+static grub_err_t
+set_module_type (struct xen_boot_binary *module, int argc, char *argv[],
+		 int *file_name_index)
+{
+  char **compat_string_temp_array =
+    (char **) grub_zalloc (sizeof (char *) * argc);
+  static module_type_t default_type = MODULE_IMAGE;
+  grub_size_t total_size = 0;
+  int num_types = 0, i;
+  char *temp = NULL;
+
+  *file_name_index = 0;
+
+  /* if there are some options we need to process. */
+  while (argc > 1 && !grub_strncmp (argv[0], "--", 2))
+    {
+      if (!grub_strcmp (argv[0], "--type"))
+	{
+	  module->node_info.type = MODULE_CUSTOM;
+	  ARG_SHIFT (argc, argv);
+	  total_size += grub_strlen (argv[0]) + 1;
+	  compat_string_temp_array[num_types++] = argv[0];
+	  ARG_SHIFT (argc, argv);
+	  (*file_name_index) += 2;
+	}
+      else if (!grub_strcmp (argv[0], "--nounzip"))
+	{
+	  grub_file_filter_disable_compression ();
+	  ARG_SHIFT (argc, argv);
+	  (*file_name_index) += 1;
+	}
+      else			/* we can add more options process code here. */
+	{
+	  grub_dprintf ("xen_boot_loader",
+			"Unknown option %s, skip.\n", argv[0]);
+	  ARG_SHIFT (argc, argv);
+	  (*file_name_index) += 1;
+	}
+    }
+
+  /* To prevent some wrong command lines using "--type" option */
+  if (!argc)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+
+  /* For the default module type :
+     The implementation is following <Multiboot on ARM Specification>:
+     Each module will be given a default compatibility property
+     based on the order in which the modules are added.
+     The 1st module: compatible = "multiboot,kernel", "multiboot,module"
+     The 2nd module: compatible = "multiboot,ramdisk", "multiboot,module"
+     All subsequent modules: compatible = "multiboot,module"
+     But this order will NOT be interfered with "--type"(MODULE_CUSTOM)
+     For more detail, please refer to:
+     http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot */
+  if (module->node_info.type != MODULE_CUSTOM)
+    {
+      /* the module type is set by the load order */
+      module->node_info.type = default_type;
+      switch (default_type)
+	{
+	case MODULE_IMAGE:
+	  default_type = MODULE_INITRD;
+	  break;
+
+	case MODULE_INITRD:
+	  default_type = MODULE_OTHER;
+	  break;
+
+	case MODULE_OTHER:
+	  break;
+
+	default:
+	  default_type = MODULE_IMAGE;	/* error, reset the type */
+	  return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
+	}
+    }
+  else
+    {
+      /* the module type is set by "--type"(MODULE_CUSTOM) */
+      module->node_info.compat_string = temp =
+	(char *) grub_zalloc (total_size);
+      module->node_info.compat_string_size = total_size;
+      for (i = 0; num_types > 0; num_types--, i++, temp++)
+	{
+	  grub_strcpy (temp, compat_string_temp_array[i]);
+	  temp += grub_strlen (compat_string_temp_array[i]);
+	}
+    }
+
+  grub_free (compat_string_temp_array);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+prepare_xen_hypervisor_params (void)
+{
+  int chosen_node = 0;
+  int retval;
+
+  xen_boot_fdt = grub_linux_get_fdt ();
+  if (!xen_boot_fdt)
+    return grub_error (GRUB_ERR_BAD_OS, "failed to get FDT");
+
+  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
+  if (chosen_node < 0)
+    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
+  if (chosen_node < 1)
+    return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT");
+
+  grub_dprintf ("xen_boot_loader",
+		"Xen Hypervisor cmdline : %s @ %p size:%d\n",
+		xen_hypervisor->cmdline, xen_hypervisor->cmdline,
+		xen_hypervisor->cmdline_size);
+
+  retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
+			      xen_hypervisor->cmdline,
+			      xen_hypervisor->cmdline_size);
+  if (retval)
+    return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT");
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+prepare_xen_module_params (struct xen_boot_binary *module)
+{
+  int retval, chosen_node = 0, module_node = 0;
+  char module_name[FDT_NODE_NAME_MAX_SIZE];
+
+  retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
+			  xen_boot_address_align (module->start,
+						  module->align));
+  grub_dprintf ("xen_boot_loader", "Module node name %s \n", module_name);
+
+  if (retval < (int) sizeof ("module@"))
+    return grub_error (GRUB_ERR_BAD_OS, N_("failed to get FDT"));
+
+  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
+  if (chosen_node < 0)
+    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
+  if (chosen_node < 1)
+    return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT");
+
+  module_node =
+    grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
+  if (module_node < 0)
+    module_node =
+      grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
+
+  retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
+			      module->node_info.compat_string,
+			      (grub_uint32_t) module->node_info.
+			      compat_string_size);
+  if (retval)
+    return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT"));
+
+  grub_dprintf ("xen_boot_loader", "Module %s compatible = %s size = 0x%lx\n",
+		module->name, module->node_info.compat_string,
+		module->node_info.compat_string_size);
+
+  retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
+			       xen_boot_address_align (module->start,
+						       module->align),
+			       module->size);
+  if (retval)
+    return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT"));
+
+  if (module->cmdline && module->cmdline_size > 0)
+    {
+      grub_dprintf ("xen_boot_loader",
+		    "Module %s cmdline : %s @ %p size:%d\n", module->name,
+		    module->cmdline, module->cmdline, module->cmdline_size);
+
+      retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
+				  module->cmdline, module->cmdline_size + 1);
+      if (retval)
+	return grub_error (GRUB_ERR_BAD_OS, "failed to update FDT");
+    }
+  else
+    {
+      grub_dprintf ("xen_boot_loader", "Module %s has not bootargs!\n",
+		    module->name);
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+install_all_params (void)
+{
+  grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
+  grub_efi_boot_services_t *b;
+  grub_efi_status_t status;
+
+  b = grub_efi_system_table->boot_services;
+  status = b->install_configuration_table (&fdt_guid, xen_boot_fdt);
+  if (status != GRUB_EFI_SUCCESS)
+    return grub_error (GRUB_ERR_BAD_OS, "failed to install FDT");
+
+  grub_dprintf ("xen_boot_loader",
+		"Installed/updated FDT configuration table @ %p\n",
+		xen_boot_fdt);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+clean_all_params (void)
+{
+  if (xen_boot_fdt)
+    {
+      grub_efi_free_pages ((grub_efi_physical_address_t) xen_boot_fdt,
+			   BYTES_TO_PAGES (grub_fdt_get_totalsize
+					   (xen_boot_fdt)));
+      xen_boot_fdt = NULL;
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+finalize_params_xen_boot (void)
+{
+  struct xen_boot_binary *module;
+
+  if (xen_hypervisor)
+    {
+      if (prepare_xen_hypervisor_params () != GRUB_ERR_NONE)
+	goto fail;
+    }
+  else
+    {
+      grub_dprintf ("xen_boot_loader",
+		    "Failed to get Xen Hypervisor info!\n");
+      goto fail;
+    }
+
+  /* Set module params info */
+  FOR_LIST_ELEMENTS (module, module_head)
+  {
+    if (module->start && module->size > 0)
+      {
+	grub_dprintf ("xen_boot_loader", "Module %s @ 0x%lx size:0x%lx\n",
+		      module->name,
+		      xen_boot_address_align (module->start, module->align),
+		      module->size);
+	if (prepare_xen_module_params (module) != GRUB_ERR_NONE)
+	  goto fail;
+      }
+    else
+      {
+	grub_dprintf ("xen_boot_loader", "Module info error: %s!\n",
+		      module->name);
+	goto fail;
+      }
+  }
+
+  if (install_all_params () == GRUB_ERR_NONE)
+    return GRUB_ERR_NONE;
+
+fail:
+  clean_all_params ();
+
+  return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT");
+}
+
+
+static grub_err_t
+xen_boot (void)
+{
+  if (finalize_params_xen_boot () != GRUB_ERR_NONE)
+    return grub_errno;
+
+  return grub_arm64_uefi_boot_image (xen_hypervisor->start,
+				     xen_hypervisor->size,
+				     xen_hypervisor->cmdline);
+}
+
+static void
+single_binary_unload (struct xen_boot_binary *binary)
+{
+  if (binary && binary->start && binary->size > 0)
+    {
+      grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
+			   BYTES_TO_PAGES (binary->size + binary->align));
+    }
+
+  if (binary && binary->cmdline && binary->cmdline_size > 0)
+    {
+      grub_free (binary->cmdline);
+      grub_dprintf ("xen_boot_loader",
+		    "Module %s cmdline memory free @ %p size: %d\n",
+		    binary->name, binary->cmdline, binary->cmdline_size);
+    }
+
+  if (binary)
+    {
+      if (binary->node_info.type == MODULE_CUSTOM)
+	grub_free ((void *) binary->node_info.compat_string);
+      if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
+	grub_list_remove (GRUB_AS_LIST (binary));
+      grub_dprintf ("xen_boot_loader",
+		    "Module %s struct memory free @ %p size: 0x%lx\n",
+		    binary->name, binary, sizeof (binary));
+      grub_free (binary);
+    }
+
+  return;
+}
+
+static void
+all_binaries_unload (void)
+{
+  struct xen_boot_binary *binary;
+
+  FOR_LIST_ELEMENTS (binary, module_head)
+  {
+    single_binary_unload (binary);
+  }
+
+  if (xen_hypervisor)
+    single_binary_unload (xen_hypervisor);
+
+  return;
+}
+
+static grub_err_t
+xen_unload (void)
+{
+  *loaded = 0;
+  all_binaries_unload ();
+  clean_all_params ();
+  grub_dl_unref (linux_mod);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
+		      int argc, char *argv[])
+{
+  binary->size = grub_file_size (file);
+  grub_dprintf ("xen_boot_loader", "Xen_boot %s file size: 0x%lx\n",
+		binary->name, binary->size);
+
+  binary->start = (grub_addr_t) grub_efi_allocate_pages (0,
+							 (BYTES_TO_PAGES
+							  (binary->size +
+							   binary->align)));
+  if (!binary->start)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+
+  grub_dprintf ("xen_boot_loader", "Xen_boot %s numpages: 0x%lx\n",
+		binary->name, BYTES_TO_PAGES (binary->size + binary->align));
+
+  if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
+							     binary->align),
+		      binary->size) < (grub_ssize_t) binary->size)
+    {
+      single_binary_unload (binary);
+      return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+			 argv[0]);
+    }
+
+  /* Skip the xen_boot binary file name */
+  ARG_SHIFT (argc, argv);
+
+  if (argc > 0)
+    {
+      binary->cmdline_size = grub_loader_cmdline_size (argc, argv);
+      binary->cmdline = grub_zalloc (binary->cmdline_size);
+      if (!binary->cmdline)
+	{
+	  single_binary_unload (binary);
+	  return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+	}
+      grub_create_loader_cmdline (argc, argv, binary->cmdline,
+				  binary->cmdline_size);
+      grub_dprintf ("xen_boot_loader",
+		    "Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
+		    binary->cmdline, binary->cmdline, binary->cmdline_size);
+    }
+  else
+    {
+      binary->cmdline_size = 0;
+      binary->cmdline = NULL;
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_xen_module (grub_command_t cmd __attribute__ ((unused)),
+		     int argc, char *argv[])
+{
+
+  struct xen_boot_binary *module = NULL;
+  int file_name_index = 0;
+  grub_file_t file = 0;
+
+  if (!argc)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+      goto fail;
+    }
+
+  if (!*loaded)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT,
+		  N_("you need to load the Xen Hypervisor first"));
+      goto fail;
+    }
+
+  module =
+    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
+  if (!module)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+
+  /* process all the options and get module type */
+  if (set_module_type (module, argc, argv, &file_name_index) != GRUB_ERR_NONE)
+    goto fail;
+  switch (module->node_info.type)
+    {
+    case MODULE_IMAGE:
+    case MODULE_INITRD:
+    case MODULE_OTHER:
+      module->node_info.compat_string =
+	default_compat_string[module->node_info.type].compat_string;
+      module->node_info.compat_string_size =
+	default_compat_string[module->node_info.type].size;
+      break;
+
+    case MODULE_CUSTOM:
+      /* we have set the node_info in set_module_type */
+      break;
+
+    default:
+      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
+    }
+  module->name = module->node_info.compat_string;
+  module->align = module_default_align[module->node_info.type];
+
+  grub_dprintf ("xen_boot_loader", "Init %s module and node info:\n"
+		"compatible %s\ncompat_string_size 0x%lx\n",
+		module->name, module->node_info.compat_string,
+		module->node_info.compat_string_size);
+
+  file = grub_file_open (argv[file_name_index]);
+  if (!file)
+    goto fail;
+
+  grub_errno = xen_boot_binary_load (module, file, argc - file_name_index,
+				     argv + file_name_index);
+
+  if (grub_errno == GRUB_ERR_NONE)
+    grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
+
+fail:
+  if (file)
+    grub_file_close (file);
+  if (grub_errno != GRUB_ERR_NONE)
+    single_binary_unload (module);
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
+			 int argc, char *argv[])
+{
+  struct xen_hypervisor_header sh;
+  grub_file_t file = NULL;
+
+  grub_dl_ref (linux_mod);
+
+  if (!argc)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+      goto fail;
+    }
+
+  /* For now, we don't support any option in xen_hypervisor command.
+     If there are some options, we skip them. */
+  while (argc > 1 && !grub_strncmp (argv[0], "--", 2))
+    {
+      grub_dprintf ("xen_boot_loader", "Unknown option %s, skip.\n", argv[0]);
+      ARG_SHIFT (argc, argv);
+    }
+
+  file = grub_file_open (argv[0]);
+  if (!file)
+    goto fail;
+
+  if (grub_file_read (file, &sh, sizeof (sh)) < (long) sizeof (sh))
+    goto fail;
+  if (grub_arm64_uefi_check_image
+      ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
+    goto fail;
+  grub_file_seek (file, 0);
+
+  grub_loader_unset ();
+
+  xen_hypervisor =
+    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
+  if (!xen_hypervisor)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+
+  xen_hypervisor->name = XEN_HYPERVISOR_NAME;
+  xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
+
+  grub_errno = xen_boot_binary_load (xen_hypervisor, file, argc, argv);
+  if (grub_errno == GRUB_ERR_NONE)
+    {
+      grub_loader_set (xen_boot, xen_unload, 0);
+      *loaded = 1;
+    }
+
+fail:
+  if (file)
+    grub_file_close (file);
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      *loaded = 0;
+      all_binaries_unload ();
+      grub_dl_unref (linux_mod);
+    }
+
+  return grub_errno;
+}
+
+static grub_command_t cmd_xen_hypervisor, cmd_xen_module;
+
+void
+grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *linux_loaded)
+{
+  cmd_xen_hypervisor =
+    grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
+			   N_("Load a xen hypervisor."));
+  cmd_xen_module =
+    grub_register_command ("xen_module", grub_cmd_xen_module, 0,
+			   N_("Load a xen module."));
+  linux_mod = mod;
+  loaded = linux_loaded;
+}
+
+void
+grub_arm64_linux_unregister_xen_boot_command (void)
+{
+  grub_unregister_command (cmd_xen_hypervisor);
+  grub_unregister_command (cmd_xen_module);
+}
diff --git a/include/grub/arm64/xen_boot.h b/include/grub/arm64/xen_boot.h
new file mode 100644
index 0000000..8e8f6cb
--- /dev/null
+++ b/include/grub/arm64/xen_boot.h
@@ -0,0 +1,115 @@
+/*
+ *  xen_boot.h - Xen boot header file for Xen boot via FDT
+ *  on AArch64 architecture.
+ *  Copyright (C) 2014  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef XEN_BOOT_HEADER
+#define XEN_BOOT_HEADER 1
+
+#include <grub/list.h>
+#include <grub/types.h>
+#include <grub/efi/pe32.h>	/* required by struct xen_hypervisor_header */
+
+#define XEN_HYPERVISOR_NAME  "xen_hypervisor"
+
+#define MODULE_DEFAULT_ALIGN  (0x0)
+#define MODULE_IMAGE_MIN_ALIGN  MODULE_DEFAULT_ALIGN
+#define MODULE_INITRD_MIN_ALIGN  MODULE_DEFAULT_ALIGN
+#define MODULE_OTHER_MIN_ALIGN  MODULE_DEFAULT_ALIGN
+#define MODULE_CUSTOM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
+
+#define MODULE_IMAGE_COMPATIBLE  "multiboot,kernel\0multiboot,module"
+#define MODULE_INITRD_COMPATIBLE  "multiboot,ramdisk\0multiboot,module"
+#define MODULE_OTHER_COMPATIBLE  "multiboot,module"
+
+/* This maximum size is defined in Power.org ePAPR V1.1
+ * https://www.power.org/documentation/epapr-version-1-1/
+ * 2.2.1.1 Node Name Requirements
+ * node-name@unit-address
+ * 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
+ */
+#define FDT_NODE_NAME_MAX_SIZE  (49)
+
+#define ARG_SHIFT(argc, argv) \
+  do { \
+    (argc)--; \
+    (argv)++; \
+  } while (0)
+
+struct compat_string_struct
+{
+  grub_size_t size;
+  const char *compat_string;
+};
+typedef struct compat_string_struct compat_string_struct_t;
+#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
+
+enum module_type
+{
+  MODULE_IMAGE,
+  MODULE_INITRD,
+  MODULE_OTHER,
+  MODULE_CUSTOM
+};
+typedef enum module_type module_type_t;
+
+struct fdt_node_info
+{
+  module_type_t type;
+
+  const char *compat_string;
+  grub_size_t compat_string_size;
+};
+
+struct xen_hypervisor_header
+{
+  struct grub_arm64_linux_kernel_header efi_head;
+
+  /* This is always PE\0\0.  */
+  grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
+  /* The COFF file header.  */
+  struct grub_pe32_coff_header coff_header;
+  /* The Optional header.  */
+  struct grub_pe64_optional_header optional_header;
+};
+
+struct xen_boot_binary
+{
+  struct xen_boot_binary *next;
+  struct xen_boot_binary **prev;
+  const char *name;
+
+  grub_addr_t start;
+  grub_size_t size;
+  grub_size_t align;
+
+  char *cmdline;
+  int cmdline_size;
+
+  struct fdt_node_info node_info;
+};
+
+void grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *loaded);
+void grub_arm64_linux_unregister_xen_boot_command (void);
+
+static __inline grub_addr_t
+xen_boot_address_align (grub_addr_t start, grub_size_t align)
+{
+  return (align ? (ALIGN_UP (start, align)) : start);
+}
+
+#endif /* ! XEN_BOOT_HEADER */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v2 2/3] util/grub.d/20_linux_xen.in: Add arm64 support
  2015-07-13  8:53 ` [PATCH v2 0/3] arm64: Add multiboot support (via fdt) for Xen boot fu.wei
  2015-07-13  8:53   ` [PATCH v2 1/3] arm64: Add Xen boot support file fu.wei
@ 2015-07-13  8:53   ` fu.wei
  2015-07-14  3:53       ` Andrei Borzenkov
  2015-07-13  8:54   ` [PATCH v2 3/3] arm64: Add the introduction of Xen boot command fu.wei
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 550+ messages in thread
From: fu.wei @ 2015-07-13  8:53 UTC (permalink / raw)
  To: grub-devel, arvidjaar, phcoder
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patch adds the support of boot command on arm64 for XEN:
    xen_hypervisor
    xen_module

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 util/grub.d/20_linux_xen.in | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
index f532fb9..b52c50d 100644
--- a/util/grub.d/20_linux_xen.in
+++ b/util/grub.d/20_linux_xen.in
@@ -120,16 +120,16 @@ linux_entry ()
         else
             xen_rm_opts="no-real-mode edd=off"
         fi
-	multiboot	${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
+	${multiboot_cmd}	${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
 	echo	'$(echo "$lmessage" | grub_quote)'
-	module	${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
+	${module_cmd}	${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
 EOF
   if test -n "${initrd}" ; then
     # TRANSLATORS: ramdisk isn't identifier. Should be translated.
     message="$(gettext_printf "Loading initial ramdisk ...")"
     sed "s/^/$submenu_indentation/" << EOF
 	echo	'$(echo "$message" | grub_quote)'
-	module	--nounzip   ${rel_dirname}/${initrd}
+	${module_cmd}	--nounzip   ${rel_dirname}/${initrd}
 EOF
   fi
   sed "s/^/$submenu_indentation/" << EOF
@@ -185,6 +185,14 @@ case "$machine" in
     *) GENKERNEL_ARCH="$machine" ;;
 esac
 
+if [ "x$machine" != xaarch64 ]; then
+	multiboot_cmd="multiboot"
+	module_cmd="module"
+else
+	multiboot_cmd="xen_hypervisor"
+	module_cmd="xen_module"
+fi
+
 # Extra indentation to add to menu entries in a submenu. We're not in a submenu
 # yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
 submenu_indentation=""
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v2 3/3] arm64: Add the introduction of Xen boot command
  2015-07-13  8:53 ` [PATCH v2 0/3] arm64: Add multiboot support (via fdt) for Xen boot fu.wei
  2015-07-13  8:53   ` [PATCH v2 1/3] arm64: Add Xen boot support file fu.wei
  2015-07-13  8:53   ` [PATCH v2 2/3] util/grub.d/20_linux_xen.in: Add arm64 support fu.wei
@ 2015-07-13  8:54   ` fu.wei
  2015-07-14  9:29     ` Ian Campbell
  2015-07-15 15:56     ` Vladimir 'φ-coder/phcoder' Serbinenko
  4 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-07-13  8:54 UTC (permalink / raw)
  To: grub-devel, arvidjaar, phcoder
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patch adds the introduction of xen_hypervisor/xen_module commands
in docs/grub.texi

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 docs/grub.texi | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/docs/grub.texi b/docs/grub.texi
index b9f41a7..3bd2fc3 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3839,6 +3839,9 @@ you forget a command, you can run the command @command{help}
 @comment * vbeinfo::                     List available video modes
 * verify_detached::             Verify detached digital signature
 * videoinfo::                   List available video modes
+@comment * xen_hypervisor/xen_module::   Xen boot command, for arm64 only
+* xen_hypervisor::              Load xen hypervisor binary on arm64
+* xen_module::                  Load module for xen hypervisor on arm64
 @end menu
 
 
@@ -5102,6 +5105,30 @@ successfully.  If validation fails, it is set to a non-zero value.
 List available video modes. If resolution is given, show only matching modes.
 @end deffn
 
+@node xen_hypervisor
+@subsection xen_hypervisor
+
+@deffn Command xen_hypervisor file  [arguments] @dots{}
+Load a Xen hypervisor binary from @var{file}. The rest of the
+line is passed verbatim as the @dfn{kernel command-line}. Any Xen module must
+be reloaded after using this command (@pxref{xen_module}).
+This command is only available on ARM64 systems.
+@end deffn
+
+@node xen_module
+@subsection xen_module
+
+@deffn Command xen_module [--type <compatible stream>] file [arguments]
+Load a module for xen hypervisor binary. The rest of the
+line is passed verbatim as the module command line.
+This command is only available on ARM64 systems.
+
+--type is an option which allow the module command to take "compatible" string.
+This would override default compatible string for this module.
+See @uref{http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot},
+to obtain more information.
+@end deffn
+
 @node Networking commands
 @section The list of networking commands
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 0/8] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-07-13  9:09         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-13  9:09 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw,
	dyoung, panand

Hi Guenter,

If you get some time, could you help me on this patchset again?
Great thanks for your help!

On 30 June 2015 at 03:16, Guenter Roeck <linux@roeck-us.net> wrote:
> On 06/29/2015 09:53 AM, Fu Wei wrote:
>>
>> Hi Guenter,
>>
>> Any suggestion on this v6 patchset, for now , I only got :
>
>
> Problem is that each version of your patchset tends to introduce
> substantially
> new or different functionality, meaning the review has to pretty much start
> from scratch. Right now I just don't have time to do that, so you'll have
> to be a bit patient.
>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 0/8] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-07-13  9:09         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-13  9:09 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon,
	rjw-LthD3rsA81gm4RdzfppkhA, dyoung-H+wXaHxf7aLQT0dZR+AlfA,
	panand-H+wXaHxf7aLQT0dZR+AlfA

Hi Guenter,

If you get some time, could you help me on this patchset again?
Great thanks for your help!

On 30 June 2015 at 03:16, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On 06/29/2015 09:53 AM, Fu Wei wrote:
>>
>> Hi Guenter,
>>
>> Any suggestion on this v6 patchset, for now , I only got :
>
>
> Problem is that each version of your patchset tends to introduce
> substantially
> new or different functionality, meaning the review has to pretty much start
> from scratch. Right now I just don't have time to do that, so you'll have
> to be a bit patient.
>
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 0/8] Watchdog: introduce ARM SBSA watchdog driver
  2015-07-13  9:09         ` Fu Wei
  (?)
@ 2015-07-13 15:34         ` Guenter Roeck
  2015-07-14  0:42             ` Fu Wei
  -1 siblings, 1 reply; 550+ messages in thread
From: Guenter Roeck @ 2015-07-13 15:34 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw,
	dyoung, panand

On Mon, Jul 13, 2015 at 05:09:57PM +0800, Fu Wei wrote:
> Hi Guenter,
> 
> If you get some time, could you help me on this patchset again?
> Great thanks for your help!
> 
I am on vacation this week. Hopefully next week or two weeks from now,
depending on my work load.

Guenter

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 0/8] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-07-14  0:42             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-14  0:42 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon, rjw,
	dyoung, panand

Hi Guenter,

Great thanks for your info, looking forward to your feedback. :-)

Have a good vacation! :-)

On 13 July 2015 at 23:34, Guenter Roeck <linux@roeck-us.net> wrote:
> On Mon, Jul 13, 2015 at 05:09:57PM +0800, Fu Wei wrote:
>> Hi Guenter,
>>
>> If you get some time, could you help me on this patchset again?
>> Great thanks for your help!
>>
> I am on vacation this week. Hopefully next week or two weeks from now,
> depending on my work load.
>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 0/8] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-07-14  0:42             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-14  0:42 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Jon Masters, Leo Duran,
	Jon Corbet, Mark Rutland, Catalin Marinas, Will Deacon,
	rjw-LthD3rsA81gm4RdzfppkhA, dyoung-H+wXaHxf7aLQT0dZR+AlfA,
	panand-H+wXaHxf7aLQT0dZR+AlfA

Hi Guenter,

Great thanks for your info, looking forward to your feedback. :-)

Have a good vacation! :-)

On 13 July 2015 at 23:34, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
> On Mon, Jul 13, 2015 at 05:09:57PM +0800, Fu Wei wrote:
>> Hi Guenter,
>>
>> If you get some time, could you help me on this patchset again?
>> Great thanks for your help!
>>
> I am on vacation this week. Hopefully next week or two weeks from now,
> depending on my work load.
>
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 2/3] util/grub.d/20_linux_xen.in: Add arm64 support
  2015-07-13  8:53   ` [PATCH v2 2/3] util/grub.d/20_linux_xen.in: Add arm64 support fu.wei
@ 2015-07-14  3:53       ` Andrei Borzenkov
  0 siblings, 0 replies; 550+ messages in thread
From: Andrei Borzenkov @ 2015-07-14  3:53 UTC (permalink / raw)
  To: fu.wei
  Cc: grub-devel, xen-devel, Ian.Campbell, stefano.stabellini, phcoder,
	leif.lindholm, ryan.harkin, linaro-uefi, jcm

В Mon, 13 Jul 2015 16:53:59 +0800
fu.wei@linaro.org пишет:

> From: Fu Wei <fu.wei@linaro.org>
> 
> This patch adds the support of boot command on arm64 for XEN:
>     xen_hypervisor
>     xen_module
> 
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  util/grub.d/20_linux_xen.in | 14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
> index f532fb9..b52c50d 100644
> --- a/util/grub.d/20_linux_xen.in
> +++ b/util/grub.d/20_linux_xen.in
> @@ -120,16 +120,16 @@ linux_entry ()
>          else
>              xen_rm_opts="no-real-mode edd=off"
>          fi
> -	multiboot	${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
> +	${multiboot_cmd}	${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
>  	echo	'$(echo "$lmessage" | grub_quote)'
> -	module	${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
> +	${module_cmd}	${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
>  EOF
>    if test -n "${initrd}" ; then
>      # TRANSLATORS: ramdisk isn't identifier. Should be translated.
>      message="$(gettext_printf "Loading initial ramdisk ...")"
>      sed "s/^/$submenu_indentation/" << EOF
>  	echo	'$(echo "$message" | grub_quote)'
> -	module	--nounzip   ${rel_dirname}/${initrd}
> +	${module_cmd}	--nounzip   ${rel_dirname}/${initrd}
>  EOF
>    fi
>    sed "s/^/$submenu_indentation/" << EOF
> @@ -185,6 +185,14 @@ case "$machine" in
>      *) GENKERNEL_ARCH="$machine" ;;
>  esac
>  
> +if [ "x$machine" != xaarch64 ]; then
> +	multiboot_cmd="multiboot"
> +	module_cmd="module"
> +else
> +	multiboot_cmd="xen_hypervisor"
> +	module_cmd="xen_module"
> +fi
> +

Strictly speaking, this is boot-time decision. As mentioned by
Vladimir, better would be to provide alias xen_hypervisor and
xen_module in multiboot for platforms supporting Xen (is MIPS really
supported?) and use it consistently.

>  # Extra indentation to add to menu entries in a submenu. We're not in a submenu
>  # yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
>  submenu_indentation=""


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 2/3] util/grub.d/20_linux_xen.in: Add arm64 support
@ 2015-07-14  3:53       ` Andrei Borzenkov
  0 siblings, 0 replies; 550+ messages in thread
From: Andrei Borzenkov @ 2015-07-14  3:53 UTC (permalink / raw)
  To: fu.wei
  Cc: grub-devel, xen-devel, Ian.Campbell, stefano.stabellini, phcoder,
	leif.lindholm, ryan.harkin, linaro-uefi, jcm

В Mon, 13 Jul 2015 16:53:59 +0800
fu.wei@linaro.org пишет:

> From: Fu Wei <fu.wei@linaro.org>
> 
> This patch adds the support of boot command on arm64 for XEN:
>     xen_hypervisor
>     xen_module
> 
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  util/grub.d/20_linux_xen.in | 14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
> index f532fb9..b52c50d 100644
> --- a/util/grub.d/20_linux_xen.in
> +++ b/util/grub.d/20_linux_xen.in
> @@ -120,16 +120,16 @@ linux_entry ()
>          else
>              xen_rm_opts="no-real-mode edd=off"
>          fi
> -	multiboot	${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
> +	${multiboot_cmd}	${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
>  	echo	'$(echo "$lmessage" | grub_quote)'
> -	module	${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
> +	${module_cmd}	${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
>  EOF
>    if test -n "${initrd}" ; then
>      # TRANSLATORS: ramdisk isn't identifier. Should be translated.
>      message="$(gettext_printf "Loading initial ramdisk ...")"
>      sed "s/^/$submenu_indentation/" << EOF
>  	echo	'$(echo "$message" | grub_quote)'
> -	module	--nounzip   ${rel_dirname}/${initrd}
> +	${module_cmd}	--nounzip   ${rel_dirname}/${initrd}
>  EOF
>    fi
>    sed "s/^/$submenu_indentation/" << EOF
> @@ -185,6 +185,14 @@ case "$machine" in
>      *) GENKERNEL_ARCH="$machine" ;;
>  esac
>  
> +if [ "x$machine" != xaarch64 ]; then
> +	multiboot_cmd="multiboot"
> +	module_cmd="module"
> +else
> +	multiboot_cmd="xen_hypervisor"
> +	module_cmd="xen_module"
> +fi
> +

Strictly speaking, this is boot-time decision. As mentioned by
Vladimir, better would be to provide alias xen_hypervisor and
xen_module in multiboot for platforms supporting Xen (is MIPS really
supported?) and use it consistently.

>  # Extra indentation to add to menu entries in a submenu. We're not in a submenu
>  # yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
>  submenu_indentation=""



^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Xen-devel] [PATCH v2 0/3] arm64: Add multiboot support (via fdt) for Xen boot
  2015-07-13  8:53 ` [PATCH v2 0/3] arm64: Add multiboot support (via fdt) for Xen boot fu.wei
@ 2015-07-14  9:29     ` Ian Campbell
  2015-07-13  8:53   ` [PATCH v2 2/3] util/grub.d/20_linux_xen.in: Add arm64 support fu.wei
                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 550+ messages in thread
From: Ian Campbell @ 2015-07-14  9:29 UTC (permalink / raw)
  To: fu.wei
  Cc: grub-devel, xen-devel, stefano.stabellini, arvidjaar, jcm,
	linaro-uefi, leif.lindholm, ryan.harkin, phcoder

On Mon, 2015-07-13 at 16:53 +0800, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
>   - This adds support for the Xen boot on ARM specification for arm64.

I have used this to PXE boot Xen on a mustang board. My (handcrafted)
grub.cfg was:

        set default=0
        set timeout=5
        menuentry 'pxe multiboot xen' {
          echo "xen_hypervisor /trap/xen.efi"
          xen_hypervisor /trap/xen.efi conswitch=x watchdog console=dtuart dtuart=/soc/serial@1c020000 dom0_mem=512M,max:512M
          echo "xen_module /trap/vmlinuz"
          xen_module /trap/vmlinuz root=/dev/mapper/trap--vg-root ro  console=hvc0
          echo "xen_module /trap/initrd.gz"
          xen_module /trap/initrd.gz
          boot
        }
        
Tested-by: Ian Campbell <ian.campbell@citrix.com>

I didn't yet try a local boot from hdd since I'm sure it would work
equivalently and there still seems to be some discussion around how the
update-grub side should fit together.

Thanks!

Ian.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Xen-devel] [PATCH v2 0/3] arm64: Add multiboot support (via fdt) for Xen boot
@ 2015-07-14  9:29     ` Ian Campbell
  0 siblings, 0 replies; 550+ messages in thread
From: Ian Campbell @ 2015-07-14  9:29 UTC (permalink / raw)
  To: fu.wei
  Cc: grub-devel, xen-devel, stefano.stabellini, arvidjaar, jcm,
	linaro-uefi, leif.lindholm, ryan.harkin, phcoder

On Mon, 2015-07-13 at 16:53 +0800, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
>   - This adds support for the Xen boot on ARM specification for arm64.

I have used this to PXE boot Xen on a mustang board. My (handcrafted)
grub.cfg was:

        set default=0
        set timeout=5
        menuentry 'pxe multiboot xen' {
          echo "xen_hypervisor /trap/xen.efi"
          xen_hypervisor /trap/xen.efi conswitch=x watchdog console=dtuart dtuart=/soc/serial@1c020000 dom0_mem=512M,max:512M
          echo "xen_module /trap/vmlinuz"
          xen_module /trap/vmlinuz root=/dev/mapper/trap--vg-root ro  console=hvc0
          echo "xen_module /trap/initrd.gz"
          xen_module /trap/initrd.gz
          boot
        }
        
Tested-by: Ian Campbell <ian.campbell@citrix.com>

I didn't yet try a local boot from hdd since I'm sure it would work
equivalently and there still seems to be some discussion around how the
update-grub side should fit together.

Thanks!

Ian.



^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 2/3] util/grub.d/20_linux_xen.in: Add arm64 support
  2015-07-14  3:53       ` Andrei Borzenkov
  (?)
@ 2015-07-14  9:41       ` Ian Campbell
  2015-07-14 15:23         ` [Xen-devel] " Konrad Rzeszutek Wilk
  -1 siblings, 1 reply; 550+ messages in thread
From: Ian Campbell @ 2015-07-14  9:41 UTC (permalink / raw)
  To: Andrei Borzenkov
  Cc: grub-devel, xen-devel, jcm, stefano.stabellini, phcoder,
	leif.lindholm, ryan.harkin, linaro-uefi, fu.wei

On Tue, 2015-07-14 at 06:53 +0300, Andrei Borzenkov wrote:
> > +if [ "x$machine" != xaarch64 ]; then
> > +	multiboot_cmd="multiboot"
> > +	module_cmd="module"
> > +else
> > +	multiboot_cmd="xen_hypervisor"
> > +	module_cmd="xen_module"
> > +fi
> > +
> 
> Strictly speaking, this is boot-time decision. As mentioned by
> Vladimir, better would be to provide alias xen_hypervisor and
> xen_module in multiboot for platforms supporting Xen (is MIPS really
> supported?) and use it consistently.

I had been thinking of this the other way around, e.g. on platforms
which support Xen but not multiboot1 "multiboot" would be added as an
alias for xen_hypervisor.

However so long as grub-mkconfig (via 20_linux_xen) work for everyone
and that peoples existing hand-crafted x86/multiboot/Xen grub.cfg's
continue to work then I think having the alias go either way would be
fine.

BTW I had been going to suggest a function at the grub.cfg level which
dispatched to the correct command, but I suppose an actual alias is
better.

Ian.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Xen-devel] [PATCH v2 0/3] arm64: Add multiboot support (via fdt) for Xen boot
  2015-07-14  9:29     ` Ian Campbell
  (?)
@ 2015-07-14 11:56     ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-14 11:56 UTC (permalink / raw)
  To: Ian Campbell
  Cc: The development of GNU GRUB, xen-devel, Stefano Stabellini,
	Andrei Borzenkov, Jon Masters, Linaro UEFI Mailman List,
	Leif Lindholm, Ryan Harkin, Vladimir Serbinenko

Hi Ian,
Great thanks for your testing, will add your tested-by in my next patchset :-)

On 14 July 2015 at 17:29, Ian Campbell <ian.campbell@citrix.com> wrote:
> On Mon, 2015-07-13 at 16:53 +0800, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>>   - This adds support for the Xen boot on ARM specification for arm64.
>
> I have used this to PXE boot Xen on a mustang board. My (handcrafted)
> grub.cfg was:
>
>         set default=0
>         set timeout=5
>         menuentry 'pxe multiboot xen' {
>           echo "xen_hypervisor /trap/xen.efi"
>           xen_hypervisor /trap/xen.efi conswitch=x watchdog console=dtuart dtuart=/soc/serial@1c020000 dom0_mem=512M,max:512M
>           echo "xen_module /trap/vmlinuz"
>           xen_module /trap/vmlinuz root=/dev/mapper/trap--vg-root ro  console=hvc0
>           echo "xen_module /trap/initrd.gz"
>           xen_module /trap/initrd.gz
>           boot
>         }
>
> Tested-by: Ian Campbell <ian.campbell@citrix.com>
>
> I didn't yet try a local boot from hdd since I'm sure it would work
> equivalently and there still seems to be some discussion around how the
> update-grub side should fit together.
>
> Thanks!
>
> Ian.
>



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 2/3] util/grub.d/20_linux_xen.in: Add arm64 support
  2015-07-14  3:53       ` Andrei Borzenkov
@ 2015-07-14 13:09         ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-14 13:09 UTC (permalink / raw)
  To: Andrei Borzenkov
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Vladimir Serbinenko, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List, Jon Masters

Hi Andrei,

Great thanks for your review.

So Are you suggesting this:
(1) in util/grub.d/20_linux_xen.in, we only use xen_hypervisor/xen_module.
(2) in xen_boot.c, we only register command xen_hypervisor/xen_module.
(3) in grub-core/loader/i386/xen.c, we *add*
---------------
  cmd_xen_hypervisort = grub_register_command ("xen_hypervisor", grub_cmd_xen,
0, N_("Load Linux."));
  cmd_xen_module = grub_register_command ("xen_module", grub_cmd_module,
     0, N_("Load module."));
---------------
(4)in grub-core/loader/multiboot.c, we *add*
---------------
#if defined (__i386__) || defined (__aarch64__)
  cmd_xen_hypervisort =
    grub_register_command ("xen_hypervisor", grub_cmd_multiboot,
  0, N_("Load a multiboot kernel."));
  cmd_xen_module =
    grub_register_command ("xen_module", grub_cmd_module,
  0, N_("Load a multiboot module."));
#endif
---------------

BTW, from the source code, MIPS isn't supported by multiboot,  IS
supported by multiboot2.

Please correct me. If I misunderstand your suggestion. :-)

Thanks again!


On 14 July 2015 at 11:53, Andrei Borzenkov <arvidjaar@gmail.com> wrote:
> В Mon, 13 Jul 2015 16:53:59 +0800
> fu.wei@linaro.org пишет:
>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> This patch adds the support of boot command on arm64 for XEN:
>>     xen_hypervisor
>>     xen_module
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  util/grub.d/20_linux_xen.in | 14 +++++++++++---
>>  1 file changed, 11 insertions(+), 3 deletions(-)
>>
>> diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
>> index f532fb9..b52c50d 100644
>> --- a/util/grub.d/20_linux_xen.in
>> +++ b/util/grub.d/20_linux_xen.in
>> @@ -120,16 +120,16 @@ linux_entry ()
>>          else
>>              xen_rm_opts="no-real-mode edd=off"
>>          fi
>> -     multiboot       ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
>> +     ${multiboot_cmd}        ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
>>       echo    '$(echo "$lmessage" | grub_quote)'
>> -     module  ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
>> +     ${module_cmd}   ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
>>  EOF
>>    if test -n "${initrd}" ; then
>>      # TRANSLATORS: ramdisk isn't identifier. Should be translated.
>>      message="$(gettext_printf "Loading initial ramdisk ...")"
>>      sed "s/^/$submenu_indentation/" << EOF
>>       echo    '$(echo "$message" | grub_quote)'
>> -     module  --nounzip   ${rel_dirname}/${initrd}
>> +     ${module_cmd}   --nounzip   ${rel_dirname}/${initrd}
>>  EOF
>>    fi
>>    sed "s/^/$submenu_indentation/" << EOF
>> @@ -185,6 +185,14 @@ case "$machine" in
>>      *) GENKERNEL_ARCH="$machine" ;;
>>  esac
>>
>> +if [ "x$machine" != xaarch64 ]; then
>> +     multiboot_cmd="multiboot"
>> +     module_cmd="module"
>> +else
>> +     multiboot_cmd="xen_hypervisor"
>> +     module_cmd="xen_module"
>> +fi
>> +
>
> Strictly speaking, this is boot-time decision. As mentioned by
> Vladimir, better would be to provide alias xen_hypervisor and
> xen_module in multiboot for platforms supporting Xen (is MIPS really
> supported?) and use it consistently.
>
>>  # Extra indentation to add to menu entries in a submenu. We're not in a submenu
>>  # yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
>>  submenu_indentation=""
>



-- 
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

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 2/3] util/grub.d/20_linux_xen.in: Add arm64 support
@ 2015-07-14 13:09         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-14 13:09 UTC (permalink / raw)
  To: Andrei Borzenkov
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Vladimir Serbinenko, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List, Jon Masters

Hi Andrei,

Great thanks for your review.

So Are you suggesting this:
(1) in util/grub.d/20_linux_xen.in, we only use xen_hypervisor/xen_module.
(2) in xen_boot.c, we only register command xen_hypervisor/xen_module.
(3) in grub-core/loader/i386/xen.c, we *add*
---------------
  cmd_xen_hypervisort = grub_register_command ("xen_hypervisor", grub_cmd_xen,
0, N_("Load Linux."));
  cmd_xen_module = grub_register_command ("xen_module", grub_cmd_module,
     0, N_("Load module."));
---------------
(4)in grub-core/loader/multiboot.c, we *add*
---------------
#if defined (__i386__) || defined (__aarch64__)
  cmd_xen_hypervisort =
    grub_register_command ("xen_hypervisor", grub_cmd_multiboot,
  0, N_("Load a multiboot kernel."));
  cmd_xen_module =
    grub_register_command ("xen_module", grub_cmd_module,
  0, N_("Load a multiboot module."));
#endif
---------------

BTW, from the source code, MIPS isn't supported by multiboot,  IS
supported by multiboot2.

Please correct me. If I misunderstand your suggestion. :-)

Thanks again!


On 14 July 2015 at 11:53, Andrei Borzenkov <arvidjaar@gmail.com> wrote:
> В Mon, 13 Jul 2015 16:53:59 +0800
> fu.wei@linaro.org пишет:
>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> This patch adds the support of boot command on arm64 for XEN:
>>     xen_hypervisor
>>     xen_module
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  util/grub.d/20_linux_xen.in | 14 +++++++++++---
>>  1 file changed, 11 insertions(+), 3 deletions(-)
>>
>> diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
>> index f532fb9..b52c50d 100644
>> --- a/util/grub.d/20_linux_xen.in
>> +++ b/util/grub.d/20_linux_xen.in
>> @@ -120,16 +120,16 @@ linux_entry ()
>>          else
>>              xen_rm_opts="no-real-mode edd=off"
>>          fi
>> -     multiboot       ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
>> +     ${multiboot_cmd}        ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
>>       echo    '$(echo "$lmessage" | grub_quote)'
>> -     module  ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
>> +     ${module_cmd}   ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
>>  EOF
>>    if test -n "${initrd}" ; then
>>      # TRANSLATORS: ramdisk isn't identifier. Should be translated.
>>      message="$(gettext_printf "Loading initial ramdisk ...")"
>>      sed "s/^/$submenu_indentation/" << EOF
>>       echo    '$(echo "$message" | grub_quote)'
>> -     module  --nounzip   ${rel_dirname}/${initrd}
>> +     ${module_cmd}   --nounzip   ${rel_dirname}/${initrd}
>>  EOF
>>    fi
>>    sed "s/^/$submenu_indentation/" << EOF
>> @@ -185,6 +185,14 @@ case "$machine" in
>>      *) GENKERNEL_ARCH="$machine" ;;
>>  esac
>>
>> +if [ "x$machine" != xaarch64 ]; then
>> +     multiboot_cmd="multiboot"
>> +     module_cmd="module"
>> +else
>> +     multiboot_cmd="xen_hypervisor"
>> +     module_cmd="xen_module"
>> +fi
>> +
>
> Strictly speaking, this is boot-time decision. As mentioned by
> Vladimir, better would be to provide alias xen_hypervisor and
> xen_module in multiboot for platforms supporting Xen (is MIPS really
> supported?) and use it consistently.
>
>>  # Extra indentation to add to menu entries in a submenu. We're not in a submenu
>>  # yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
>>  submenu_indentation=""
>



-- 
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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 1/8] Documentation: add sbsa-gwdt.txt documentation
@ 2015-07-14 14:49       ` Rob Herring
  0 siblings, 0 replies; 550+ messages in thread
From: Rob Herring @ 2015-07-14 14:49 UTC (permalink / raw)
  To: fu.wei
  Cc: Suravee Suthikulanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, tekkamanninja, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Guenter Roeck, vgandhi, Wim Van Sebroeck, jcm, leo.duran,
	Jonathan Corbet, Mark Rutland, Catalin Marinas, Will Deacon,
	Rafael Wysocki, dyoung, panand

On Tue, Jun 23, 2015 at 9:16 AM,  <fu.wei@linaro.org> wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> The sbsa-gwdt.txt documentation in devicetree/bindings/watchdog is for
> introducing SBSA(Server Base System Architecture) Generic Watchdog
> device node info into FDT.
>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  .../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..010e5c4
> --- /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.

This needs to specify the ordering of refresh and control.

> +
> +- reg-names : Should contain the resource reg names to show the order of
> +  the values in "reg".
> +  Must include the following entries : "refresh", "control".

This should be optional.

> +- interrupts : Should at least contain WS0 interrupt,
> +  the WS1 Signal is optional.

s/Signal/interrupt/ ?

> +
> +- interrupt-names : Should contain the resource interrupt names.
> +  Must include the following entries : "ws0". "ws1" is optional.

This should be 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@2a440000 {
> +       compatible = "arm,sbsa-gwdt";
> +       reg = <0x0 0x2a440000 0 0x1000>,
> +             <0x0 0x2a450000 0 0x1000>;
> +       reg-names = "control", "refresh";
> +       interrupts = <0 27 4>;
> +       interrupt-names = "ws0";
> +       timeout-sec = <10 5>;
> +};
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 1/8] Documentation: add sbsa-gwdt.txt documentation
@ 2015-07-14 14:49       ` Rob Herring
  0 siblings, 0 replies; 550+ messages in thread
From: Rob Herring @ 2015-07-14 14:49 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A
  Cc: Suravee Suthikulanit, linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w, G Gregory, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Guenter Roeck, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, Wim Van Sebroeck,
	jcm-H+wXaHxf7aLQT0dZR+AlfA, leo.duran-5C7GfCeVMHo,
	Jonathan Corbet, Mark Rutland, Catalin Marinas, Will Deacon,
	Rafael

On Tue, Jun 23, 2015 at 9:16 AM,  <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> The sbsa-gwdt.txt documentation in devicetree/bindings/watchdog is for
> introducing SBSA(Server Base System Architecture) Generic Watchdog
> device node info into FDT.
>
> Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>  .../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..010e5c4
> --- /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.

This needs to specify the ordering of refresh and control.

> +
> +- reg-names : Should contain the resource reg names to show the order of
> +  the values in "reg".
> +  Must include the following entries : "refresh", "control".

This should be optional.

> +- interrupts : Should at least contain WS0 interrupt,
> +  the WS1 Signal is optional.

s/Signal/interrupt/ ?

> +
> +- interrupt-names : Should contain the resource interrupt names.
> +  Must include the following entries : "ws0". "ws1" is optional.

This should be 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@2a440000 {
> +       compatible = "arm,sbsa-gwdt";
> +       reg = <0x0 0x2a440000 0 0x1000>,
> +             <0x0 0x2a450000 0 0x1000>;
> +       reg-names = "control", "refresh";
> +       interrupts = <0 27 4>;
> +       interrupt-names = "ws0";
> +       timeout-sec = <10 5>;
> +};
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Xen-devel] [PATCH v2 2/3] util/grub.d/20_linux_xen.in: Add arm64 support
  2015-07-14  9:41       ` Ian Campbell
@ 2015-07-14 15:23         ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 550+ messages in thread
From: Konrad Rzeszutek Wilk @ 2015-07-14 15:23 UTC (permalink / raw)
  To: Ian Campbell
  Cc: grub-devel, xen-devel, stefano.stabellini, Andrei Borzenkov,
	phcoder, linaro-uefi, leif.lindholm, ryan.harkin, jcm, fu.wei

On Tue, Jul 14, 2015 at 10:41:28AM +0100, Ian Campbell wrote:
> On Tue, 2015-07-14 at 06:53 +0300, Andrei Borzenkov wrote:
> > > +if [ "x$machine" != xaarch64 ]; then
> > > +	multiboot_cmd="multiboot"
> > > +	module_cmd="module"

And we should use the grub-file --is-multiboot2 to figure out if the
Xen binary can also do that - and use multiboot2 protocol.

But that patch I can cobble after this one is done.

> > > +else
> > > +	multiboot_cmd="xen_hypervisor"
> > > +	module_cmd="xen_module"
> > > +fi
> > > +
> > 
> > Strictly speaking, this is boot-time decision. As mentioned by
> > Vladimir, better would be to provide alias xen_hypervisor and
> > xen_module in multiboot for platforms supporting Xen (is MIPS really
> > supported?) and use it consistently.
> 
> I had been thinking of this the other way around, e.g. on platforms
> which support Xen but not multiboot1 "multiboot" would be added as an
> alias for xen_hypervisor.
> 
> However so long as grub-mkconfig (via 20_linux_xen) work for everyone
> and that peoples existing hand-crafted x86/multiboot/Xen grub.cfg's
> continue to work then I think having the alias go either way would be
> fine.
> 
> BTW I had been going to suggest a function at the grub.cfg level which
> dispatched to the correct command, but I suppose an actual alias is
> better.
> 
> Ian.
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 1/8] Documentation: add sbsa-gwdt.txt documentation
  2015-07-14 14:49       ` Rob Herring
@ 2015-07-14 15:48         ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-14 15:48 UTC (permalink / raw)
  To: Rob Herring
  Cc: Suravee Suthikulanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone, Hanjun Guo,
	Timur Tabi, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	Vipul Gandhi, Wim Van Sebroeck, jcm, Leo Duran, Jonathan Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung, panand

Hi Rob,

Great thanks for your review :-)

On 14 July 2015 at 22:49, Rob Herring <robherring2@gmail.com> wrote:
> On Tue, Jun 23, 2015 at 9:16 AM,  <fu.wei@linaro.org> wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> The sbsa-gwdt.txt documentation in devicetree/bindings/watchdog is for
>> introducing SBSA(Server Base System Architecture) Generic Watchdog
>> device node info into FDT.
>>
>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  .../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..010e5c4
>> --- /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.
>
> This needs to specify the ordering of refresh and control.

In the FDT binding, Do we have to use ordering? Is the name always optional?
Sorry for questioning this, I just want to confirm that is a rule in
the FDT binding.
If that is a rule, would you let me know : where is it?

In my driver, I get these resource by name, but not ordering, for now

Thanks for your help :-)

>
>> +
>> +- reg-names : Should contain the resource reg names to show the order of
>> +  the values in "reg".
>> +  Must include the following entries : "refresh", "control".
>
> This should be optional.
>
>> +- interrupts : Should at least contain WS0 interrupt,
>> +  the WS1 Signal is optional.
>
> s/Signal/interrupt/ ?

yes, thanks,  will fix it.

>
>> +
>> +- interrupt-names : Should contain the resource interrupt names.
>> +  Must include the following entries : "ws0". "ws1" is optional.
>
> This should be 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@2a440000 {
>> +       compatible = "arm,sbsa-gwdt";
>> +       reg = <0x0 0x2a440000 0 0x1000>,
>> +             <0x0 0x2a450000 0 0x1000>;
>> +       reg-names = "control", "refresh";
>> +       interrupts = <0 27 4>;
>> +       interrupt-names = "ws0";
>> +       timeout-sec = <10 5>;
>> +};
>> --
>> 1.9.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe devicetree" in
>> the body of a message to majordomo@vger.kernel.org
>> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 1/8] Documentation: add sbsa-gwdt.txt documentation
@ 2015-07-14 15:48         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-14 15:48 UTC (permalink / raw)
  To: Rob Herring
  Cc: Suravee Suthikulanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone, Hanjun Guo,
	Timur Tabi, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	Vipul Gandhi, Wim Van Sebroeck, jcm, Leo Duran, Jonathan Corbet,
	Mark Rutland, Catalin Marinas, Will

Hi Rob,

Great thanks for your review :-)

On 14 July 2015 at 22:49, Rob Herring <robherring2@gmail.com> wrote:
> On Tue, Jun 23, 2015 at 9:16 AM,  <fu.wei@linaro.org> wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> The sbsa-gwdt.txt documentation in devicetree/bindings/watchdog is for
>> introducing SBSA(Server Base System Architecture) Generic Watchdog
>> device node info into FDT.
>>
>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  .../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..010e5c4
>> --- /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.
>
> This needs to specify the ordering of refresh and control.

In the FDT binding, Do we have to use ordering? Is the name always optional?
Sorry for questioning this, I just want to confirm that is a rule in
the FDT binding.
If that is a rule, would you let me know : where is it?

In my driver, I get these resource by name, but not ordering, for now

Thanks for your help :-)

>
>> +
>> +- reg-names : Should contain the resource reg names to show the order of
>> +  the values in "reg".
>> +  Must include the following entries : "refresh", "control".
>
> This should be optional.
>
>> +- interrupts : Should at least contain WS0 interrupt,
>> +  the WS1 Signal is optional.
>
> s/Signal/interrupt/ ?

yes, thanks,  will fix it.

>
>> +
>> +- interrupt-names : Should contain the resource interrupt names.
>> +  Must include the following entries : "ws0". "ws1" is optional.
>
> This should be 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@2a440000 {
>> +       compatible = "arm,sbsa-gwdt";
>> +       reg = <0x0 0x2a440000 0 0x1000>,
>> +             <0x0 0x2a450000 0 0x1000>;
>> +       reg-names = "control", "refresh";
>> +       interrupts = <0 27 4>;
>> +       interrupt-names = "ws0";
>> +       timeout-sec = <10 5>;
>> +};
>> --
>> 1.9.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe devicetree" in
>> the body of a message to majordomo@vger.kernel.org
>> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 1/8] Documentation: add sbsa-gwdt.txt documentation
  2015-07-14 15:48         ` Fu Wei
@ 2015-07-15 12:52           ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-15 12:52 UTC (permalink / raw)
  To: Rob Herring
  Cc: Suravee Suthikulanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone, Hanjun Guo,
	Timur Tabi, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	Vipul Gandhi, Wim Van Sebroeck, jcm, Leo Duran, Jonathan Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung, panand

Hi Rob,

I have got your point by chatting with you though IRC,
I will improve my patch according to your suggestion.

Thanks for your help.

On 14 July 2015 at 23:48, Fu Wei <fu.wei@linaro.org> wrote:
> Hi Rob,
>
> Great thanks for your review :-)
>
> On 14 July 2015 at 22:49, Rob Herring <robherring2@gmail.com> wrote:
>> On Tue, Jun 23, 2015 at 9:16 AM,  <fu.wei@linaro.org> wrote:
>>> From: Fu Wei <fu.wei@linaro.org>
>>>
>>> The sbsa-gwdt.txt documentation in devicetree/bindings/watchdog is for
>>> introducing SBSA(Server Base System Architecture) Generic Watchdog
>>> device node info into FDT.
>>>
>>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>>> ---
>>>  .../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..010e5c4
>>> --- /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.
>>
>> This needs to specify the ordering of refresh and control.
>
> In the FDT binding, Do we have to use ordering? Is the name always optional?
> Sorry for questioning this, I just want to confirm that is a rule in
> the FDT binding.
> If that is a rule, would you let me know : where is it?
>
> In my driver, I get these resource by name, but not ordering, for now
>
> Thanks for your help :-)
>
>>
>>> +
>>> +- reg-names : Should contain the resource reg names to show the order of
>>> +  the values in "reg".
>>> +  Must include the following entries : "refresh", "control".
>>
>> This should be optional.
>>
>>> +- interrupts : Should at least contain WS0 interrupt,
>>> +  the WS1 Signal is optional.
>>
>> s/Signal/interrupt/ ?
>
> yes, thanks,  will fix it.
>
>>
>>> +
>>> +- interrupt-names : Should contain the resource interrupt names.
>>> +  Must include the following entries : "ws0". "ws1" is optional.
>>
>> This should be 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@2a440000 {
>>> +       compatible = "arm,sbsa-gwdt";
>>> +       reg = <0x0 0x2a440000 0 0x1000>,
>>> +             <0x0 0x2a450000 0 0x1000>;
>>> +       reg-names = "control", "refresh";
>>> +       interrupts = <0 27 4>;
>>> +       interrupt-names = "ws0";
>>> +       timeout-sec = <10 5>;
>>> +};
>>> --
>>> 1.9.1
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe devicetree" in
>>> the body of a message to majordomo@vger.kernel.org
>>> 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



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 1/8] Documentation: add sbsa-gwdt.txt documentation
@ 2015-07-15 12:52           ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-15 12:52 UTC (permalink / raw)
  To: Rob Herring
  Cc: Suravee Suthikulanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, Wei Fu, G Gregory, Al Stone, Hanjun Guo,
	Timur Tabi, Ashwin Chaugule, Arnd Bergmann, Guenter Roeck,
	Vipul Gandhi, Wim Van Sebroeck, jcm, Leo Duran, Jonathan Corbet,
	Mark Rutland, Catalin Marinas, Will

Hi Rob,

I have got your point by chatting with you though IRC,
I will improve my patch according to your suggestion.

Thanks for your help.

On 14 July 2015 at 23:48, Fu Wei <fu.wei@linaro.org> wrote:
> Hi Rob,
>
> Great thanks for your review :-)
>
> On 14 July 2015 at 22:49, Rob Herring <robherring2@gmail.com> wrote:
>> On Tue, Jun 23, 2015 at 9:16 AM,  <fu.wei@linaro.org> wrote:
>>> From: Fu Wei <fu.wei@linaro.org>
>>>
>>> The sbsa-gwdt.txt documentation in devicetree/bindings/watchdog is for
>>> introducing SBSA(Server Base System Architecture) Generic Watchdog
>>> device node info into FDT.
>>>
>>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>>> ---
>>>  .../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..010e5c4
>>> --- /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.
>>
>> This needs to specify the ordering of refresh and control.
>
> In the FDT binding, Do we have to use ordering? Is the name always optional?
> Sorry for questioning this, I just want to confirm that is a rule in
> the FDT binding.
> If that is a rule, would you let me know : where is it?
>
> In my driver, I get these resource by name, but not ordering, for now
>
> Thanks for your help :-)
>
>>
>>> +
>>> +- reg-names : Should contain the resource reg names to show the order of
>>> +  the values in "reg".
>>> +  Must include the following entries : "refresh", "control".
>>
>> This should be optional.
>>
>>> +- interrupts : Should at least contain WS0 interrupt,
>>> +  the WS1 Signal is optional.
>>
>> s/Signal/interrupt/ ?
>
> yes, thanks,  will fix it.
>
>>
>>> +
>>> +- interrupt-names : Should contain the resource interrupt names.
>>> +  Must include the following entries : "ws0". "ws1" is optional.
>>
>> This should be 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@2a440000 {
>>> +       compatible = "arm,sbsa-gwdt";
>>> +       reg = <0x0 0x2a440000 0 0x1000>,
>>> +             <0x0 0x2a450000 0 0x1000>;
>>> +       reg-names = "control", "refresh";
>>> +       interrupts = <0 27 4>;
>>> +       interrupt-names = "ws0";
>>> +       timeout-sec = <10 5>;
>>> +};
>>> --
>>> 1.9.1
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe devicetree" in
>>> the body of a message to majordomo@vger.kernel.org
>>> 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



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 0/3] arm64: Add multiboot support (via fdt) for Xen boot
  2015-07-13  8:53 ` [PATCH v2 0/3] arm64: Add multiboot support (via fdt) for Xen boot fu.wei
@ 2015-07-15 15:56     ` Vladimir 'φ-coder/phcoder' Serbinenko
  2015-07-13  8:53   ` [PATCH v2 2/3] util/grub.d/20_linux_xen.in: Add arm64 support fu.wei
                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 550+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2015-07-15 15:56 UTC (permalink / raw)
  To: fu.wei, grub-devel, arvidjaar
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi


[-- Attachment #1.1: Type: text/plain, Size: 2639 bytes --]

On 13.07.2015 10:53, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
>   - This adds support for the Xen boot on ARM specification for arm64.
> 
>   - The implementation for Xen is following  <Multiboot on ARM Specification>:
>     http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
>     and xen/docs/misc/arm/device-tree/booting.txt in Xen source code.
> 
>   - The multiboot/module commands have existed, so we use 
>     xen_hypervisor/xen_module instead.
> 
>   - This Xen boot support is built into linux module for aarch64,
>     and can not be used alone.
> 
>   - Adding this functionality to the existing "linux" module is for
>     reusing the existing code of devicetree.
> 
This is a misguided decision. Modules can depend on other modules.
Ideally shared functionality should be in a separate module but having
xen depend on linux is an OK stopgap solution. Putting everything in one
module is bad.
>   - Add the support of xen_hypervisor/xen_module commands in util/grub.d/20_linux_xen.in
> 
>   - Add the introduction of xen_hypervisor/xen_module commands in docs/grub.texi
> 
>   - The example of this support is <How to boot Xen with GRUB on AArch64 the Foundation FVP model>
>     https://wiki.linaro.org/LEG/Engineering/Grub2/Xen_booting_on_Foundation_FVP_model_by_GRUB
> 
> Changelog:
> v2: remove the patches which have been accepted.
>     according to Vladimir's suggestion, change the command manes
>     and relevant code:
>         multiboot-->xen_hypervisor
>         module-->xen_module
>     improve the option parsing support for xen_hypervisor/xen_module commands.
>     add a patch for adding xen_hypervisor/xen_module support
>     in util/grub.d/20_linux_xen.in.
>     update docs/grub.texi patch for the new command names.
> 
> v1: The first version upstream patchset to grub-devel mailing list
> 
> 
> Fu Wei (3):
>   arm64: Add Xen boot support file
>   * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
>   arm64: Add the introduction of xen_hypervisor/xen_module command in
>     docs/grub.texi
> 
>  docs/grub.texi                    |  27 ++
>  grub-core/Makefile.core.def       |   1 +
>  grub-core/loader/arm64/linux.c    |   6 +
>  grub-core/loader/arm64/xen_boot.c | 615 ++++++++++++++++++++++++++++++++++++++
>  include/grub/arm64/xen_boot.h     | 115 +++++++
>  util/grub.d/20_linux_xen.in       |  14 +-
>  6 files changed, 775 insertions(+), 3 deletions(-)
>  create mode 100644 grub-core/loader/arm64/xen_boot.c
>  create mode 100644 include/grub/arm64/xen_boot.h
> 



[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

[-- Attachment #2: Type: text/plain, Size: 141 bytes --]

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 0/3] arm64: Add multiboot support (via fdt) for Xen boot
@ 2015-07-15 15:56     ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 0 replies; 550+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2015-07-15 15:56 UTC (permalink / raw)
  To: fu.wei, grub-devel, arvidjaar
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi

[-- Attachment #1: Type: text/plain, Size: 2639 bytes --]

On 13.07.2015 10:53, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
>   - This adds support for the Xen boot on ARM specification for arm64.
> 
>   - The implementation for Xen is following  <Multiboot on ARM Specification>:
>     http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
>     and xen/docs/misc/arm/device-tree/booting.txt in Xen source code.
> 
>   - The multiboot/module commands have existed, so we use 
>     xen_hypervisor/xen_module instead.
> 
>   - This Xen boot support is built into linux module for aarch64,
>     and can not be used alone.
> 
>   - Adding this functionality to the existing "linux" module is for
>     reusing the existing code of devicetree.
> 
This is a misguided decision. Modules can depend on other modules.
Ideally shared functionality should be in a separate module but having
xen depend on linux is an OK stopgap solution. Putting everything in one
module is bad.
>   - Add the support of xen_hypervisor/xen_module commands in util/grub.d/20_linux_xen.in
> 
>   - Add the introduction of xen_hypervisor/xen_module commands in docs/grub.texi
> 
>   - The example of this support is <How to boot Xen with GRUB on AArch64 the Foundation FVP model>
>     https://wiki.linaro.org/LEG/Engineering/Grub2/Xen_booting_on_Foundation_FVP_model_by_GRUB
> 
> Changelog:
> v2: remove the patches which have been accepted.
>     according to Vladimir's suggestion, change the command manes
>     and relevant code:
>         multiboot-->xen_hypervisor
>         module-->xen_module
>     improve the option parsing support for xen_hypervisor/xen_module commands.
>     add a patch for adding xen_hypervisor/xen_module support
>     in util/grub.d/20_linux_xen.in.
>     update docs/grub.texi patch for the new command names.
> 
> v1: The first version upstream patchset to grub-devel mailing list
> 
> 
> Fu Wei (3):
>   arm64: Add Xen boot support file
>   * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
>   arm64: Add the introduction of xen_hypervisor/xen_module command in
>     docs/grub.texi
> 
>  docs/grub.texi                    |  27 ++
>  grub-core/Makefile.core.def       |   1 +
>  grub-core/loader/arm64/linux.c    |   6 +
>  grub-core/loader/arm64/xen_boot.c | 615 ++++++++++++++++++++++++++++++++++++++
>  include/grub/arm64/xen_boot.h     | 115 +++++++
>  util/grub.d/20_linux_xen.in       |  14 +-
>  6 files changed, 775 insertions(+), 3 deletions(-)
>  create mode 100644 grub-core/loader/arm64/xen_boot.c
>  create mode 100644 include/grub/arm64/xen_boot.h
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 1/3] arm64: Add Xen boot support file
  2015-07-13  8:53   ` [PATCH v2 1/3] arm64: Add Xen boot support file fu.wei
@ 2015-07-15 16:18       ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 0 replies; 550+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2015-07-15 16:18 UTC (permalink / raw)
  To: fu.wei, grub-devel, arvidjaar
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi


[-- Attachment #1.1: Type: text/plain, Size: 27720 bytes --]

On 13.07.2015 10:53, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> This patch adds Xen boot support file:
> grub-core/loader/arm64/xen_boot.c
> include/grub/arm64/xen_boot.h
> 
> This patch also adds commands register code and hearder file into
> grub-core/loader/arm64/linux.c
> 
>   - This adds support for the Xen boot on ARM specification for arm64.
>   - The implementation for Xen is following  <Multiboot on ARM Specification>:
>       http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
Please don't refer to this protocol as multiboot anywhere in grub or
around because it's NOT multiboot and we don't want to confuse those 2
protocols.
>     and xen/docs/misc/arm/device-tree/booting.txt in Xen source code.
>   - The multiboot/module commands have existed,
>     so we use xen_hypervisor/xen_module instead.
>   - This Xen boot support is built into linux module for aarch64.
>   - Adding this functionality to the existing "linux" module is for
>     reusing the existing code of devicetree.
> 
Please create separate module. Modules are dynamically linked.
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  grub-core/Makefile.core.def       |   1 +
>  grub-core/loader/arm64/linux.c    |   6 +
>  grub-core/loader/arm64/xen_boot.c | 615 ++++++++++++++++++++++++++++++++++++++
>  include/grub/arm64/xen_boot.h     | 115 +++++++
>  4 files changed, 737 insertions(+)
>  create mode 100644 grub-core/loader/arm64/xen_boot.c
>  create mode 100644 include/grub/arm64/xen_boot.h
> 
> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
> index a6101de..01f8261 100644
> --- a/grub-core/Makefile.core.def
> +++ b/grub-core/Makefile.core.def
> @@ -1659,6 +1659,7 @@ module = {
>    ia64_efi = loader/ia64/efi/linux.c;
>    arm = loader/arm/linux.c;
>    arm64 = loader/arm64/linux.c;
> +  arm64 = loader/arm64/xen_boot.c;
>    fdt = lib/fdt.c;
>    common = loader/linux.c;
>    common = lib/cmdline.c;
> diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
> index 987f5b9..7ae9bde 100644
> --- a/grub-core/loader/arm64/linux.c
> +++ b/grub-core/loader/arm64/linux.c
> @@ -26,6 +26,7 @@
>  #include <grub/mm.h>
>  #include <grub/types.h>
>  #include <grub/cpu/linux.h>
> +#include <grub/cpu/xen_boot.h>
>  #include <grub/efi/efi.h>
>  #include <grub/efi/pe32.h>
>  #include <grub/i18n.h>
> @@ -477,6 +478,9 @@ GRUB_MOD_INIT (linux)
>    cmd_devicetree =
>      grub_register_command ("devicetree", grub_cmd_devicetree, 0,
>  			   N_("Load DTB file."));
> +
> +  grub_arm64_linux_register_xen_boot_command (mod, &loaded);
> +
>    my_mod = mod;
>  }
>  
> @@ -485,4 +489,6 @@ GRUB_MOD_FINI (linux)
>    grub_unregister_command (cmd_linux);
>    grub_unregister_command (cmd_initrd);
>    grub_unregister_command (cmd_devicetree);
> +
> +  grub_arm64_linux_unregister_xen_boot_command ();
>  }
Not needed with separate module.
> diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
> new file mode 100644
> index 0000000..23bd00e
> --- /dev/null
> +++ b/grub-core/loader/arm64/xen_boot.c
> @@ -0,0 +1,615 @@
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2014  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB 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.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/cache.h>
> +#include <grub/charset.h>
> +#include <grub/command.h>
> +#include <grub/err.h>
> +#include <grub/file.h>
> +#include <grub/fdt.h>
> +#include <grub/linux.h>
> +#include <grub/list.h>
> +#include <grub/loader.h>
> +#include <grub/misc.h>
> +#include <grub/mm.h>
> +#include <grub/types.h>
> +#include <grub/cpu/linux.h>
> +#include <grub/cpu/xen_boot.h>
> +#include <grub/efi/efi.h>
> +#include <grub/efi/pe32.h>
> +#include <grub/i18n.h>
> +#include <grub/lib/cmdline.h>
> +
> +static grub_dl_t linux_mod;
> +static int *loaded;
> +
> +static struct xen_boot_binary *xen_hypervisor;
> +static struct xen_boot_binary *module_head;
> +static const grub_size_t module_default_align[] = {
> +  MODULE_IMAGE_MIN_ALIGN,
> +  MODULE_INITRD_MIN_ALIGN,
> +  MODULE_OTHER_MIN_ALIGN,
> +  MODULE_CUSTOM_MIN_ALIGN
> +};
> +
> +static void *xen_boot_fdt;
> +static const compat_string_struct_t default_compat_string[] = {
> +  FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
> +  FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
> +  FDT_COMPATIBLE (MODULE_OTHER_COMPATIBLE)
> +};
> +
> +
> +/* Parse all the options of xen_module command. For now, we support
> +   (1) --type <the compatible stream>
> +   (2) --nounzip
> +   We also set up the type of module in this function.
> +   If there are some "--type" options in the command line,
> +   we make a custom compatible stream in this function. */
> +static grub_err_t
> +set_module_type (struct xen_boot_binary *module, int argc, char *argv[],
> +		 int *file_name_index)
> +{
> +  char **compat_string_temp_array =
> +    (char **) grub_zalloc (sizeof (char *) * argc);
> +  static module_type_t default_type = MODULE_IMAGE;
> +  grub_size_t total_size = 0;
> +  int num_types = 0, i;
> +  char *temp = NULL;
> +
> +  *file_name_index = 0;
> +
> +  /* if there are some options we need to process. */
> +  while (argc > 1 && !grub_strncmp (argv[0], "--", 2))
> +    {
> +      if (!grub_strcmp (argv[0], "--type"))
> +	{
> +	  module->node_info.type = MODULE_CUSTOM;
> +	  ARG_SHIFT (argc, argv);
> +	  total_size += grub_strlen (argv[0]) + 1;
> +	  compat_string_temp_array[num_types++] = argv[0];
> +	  ARG_SHIFT (argc, argv);
> +	  (*file_name_index) += 2;
This (and subsequent) parsing is unecessarily complicated. Please create
separate commands for different types
> +	}
> +      else if (!grub_strcmp (argv[0], "--nounzip"))
> +	{
> +	  grub_file_filter_disable_compression ();
> +	  ARG_SHIFT (argc, argv);
> +	  (*file_name_index) += 1;
> +	}
> +      else			/* we can add more options process code here. */
> +	{
> +	  grub_dprintf ("xen_boot_loader",
> +			"Unknown option %s, skip.\n", argv[0]);
> +	  ARG_SHIFT (argc, argv);
> +	  (*file_name_index) += 1;
> +	}
> +    }
> +
> +  /* To prevent some wrong command lines using "--type" option */
> +  if (!argc)
> +    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
> +
> +  /* For the default module type :
> +     The implementation is following <Multiboot on ARM Specification>:
> +     Each module will be given a default compatibility property
> +     based on the order in which the modules are added.
> +     The 1st module: compatible = "multiboot,kernel", "multiboot,module"
> +     The 2nd module: compatible = "multiboot,ramdisk", "multiboot,module"
> +     All subsequent modules: compatible = "multiboot,module"
> +     But this order will NOT be interfered with "--type"(MODULE_CUSTOM)
> +     For more detail, please refer to:
> +     http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot */
> +  if (module->node_info.type != MODULE_CUSTOM)
> +    {
> +      /* the module type is set by the load order */
> +      module->node_info.type = default_type;
Please don't make it order-dependent more than necessarry.
> +      switch (default_type)
> +	{
> +	case MODULE_IMAGE:
> +	  default_type = MODULE_INITRD;
> +	  break;
> +
> +	case MODULE_INITRD:
> +	  default_type = MODULE_OTHER;
> +	  break;
> +
> +	case MODULE_OTHER:
> +	  break;
> +
> +	default:
> +	  default_type = MODULE_IMAGE;	/* error, reset the type */
> +	  return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
> +	}
> +    }
> +  else
> +    {
> +      /* the module type is set by "--type"(MODULE_CUSTOM) */
> +      module->node_info.compat_string = temp =
> +	(char *) grub_zalloc (total_size);
> +      module->node_info.compat_string_size = total_size;
> +      for (i = 0; num_types > 0; num_types--, i++, temp++)
> +	{
> +	  grub_strcpy (temp, compat_string_temp_array[i]);
> +	  temp += grub_strlen (compat_string_temp_array[i]);
> +	}
> +    }
> +
> +  grub_free (compat_string_temp_array);
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +prepare_xen_hypervisor_params (void)
> +{
> +  int chosen_node = 0;
> +  int retval;
> +
> +  xen_boot_fdt = grub_linux_get_fdt ();
> +  if (!xen_boot_fdt)
> +    return grub_error (GRUB_ERR_BAD_OS, "failed to get FDT");
> +
> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 0)
> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 1)
> +    return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT");
> +
BAD_OS means that OS images are invalid. ERR_IO is a generic error for
such cases.
> +  grub_dprintf ("xen_boot_loader",
> +		"Xen Hypervisor cmdline : %s @ %p size:%d\n",
> +		xen_hypervisor->cmdline, xen_hypervisor->cmdline,
> +		xen_hypervisor->cmdline_size);
> +
No need for "boot_". xen_loader is fine and mre consistent.
> +  retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
> +			      xen_hypervisor->cmdline,
> +			      xen_hypervisor->cmdline_size);
> +  if (retval)
> +    return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT");
> +
ditto
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +prepare_xen_module_params (struct xen_boot_binary *module)
> +{
> +  int retval, chosen_node = 0, module_node = 0;
> +  char module_name[FDT_NODE_NAME_MAX_SIZE];
> +
> +  retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
> +			  xen_boot_address_align (module->start,
> +						  module->align));
> +  grub_dprintf ("xen_boot_loader", "Module node name %s \n", module_name);
> +
> +  if (retval < (int) sizeof ("module@"))
> +    return grub_error (GRUB_ERR_BAD_OS, N_("failed to get FDT"));
> +
> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 0)
> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 1)
> +    return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT");
> +
> +  module_node =
> +    grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
> +  if (module_node < 0)
> +    module_node =
> +      grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
> +
> +  retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
> +			      module->node_info.compat_string,
> +			      (grub_uint32_t) module->node_info.
> +			      compat_string_size);
> +  if (retval)
> +    return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT"));
> +
> +  grub_dprintf ("xen_boot_loader", "Module %s compatible = %s size = 0x%lx\n",
> +		module->name, module->node_info.compat_string,
> +		module->node_info.compat_string_size);
> +
> +  retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
> +			       xen_boot_address_align (module->start,
> +						       module->align),
> +			       module->size);
> +  if (retval)
> +    return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT"));
> +
> +  if (module->cmdline && module->cmdline_size > 0)
> +    {
> +      grub_dprintf ("xen_boot_loader",
> +		    "Module %s cmdline : %s @ %p size:%d\n", module->name,
> +		    module->cmdline, module->cmdline, module->cmdline_size);
> +
> +      retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
> +				  module->cmdline, module->cmdline_size + 1);
> +      if (retval)
> +	return grub_error (GRUB_ERR_BAD_OS, "failed to update FDT");
> +    }
> +  else
> +    {
> +      grub_dprintf ("xen_boot_loader", "Module %s has not bootargs!\n",
> +		    module->name);
> +    }
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +install_all_params (void)
> +{
> +  grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
> +  grub_efi_boot_services_t *b;
> +  grub_efi_status_t status;
> +
> +  b = grub_efi_system_table->boot_services;
> +  status = b->install_configuration_table (&fdt_guid, xen_boot_fdt);
> +  if (status != GRUB_EFI_SUCCESS)
> +    return grub_error (GRUB_ERR_BAD_OS, "failed to install FDT");
> +
> +  grub_dprintf ("xen_boot_loader",
> +		"Installed/updated FDT configuration table @ %p\n",
> +		xen_boot_fdt);
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +clean_all_params (void)
> +{
> +  if (xen_boot_fdt)
> +    {
> +      grub_efi_free_pages ((grub_efi_physical_address_t) xen_boot_fdt,
> +			   BYTES_TO_PAGES (grub_fdt_get_totalsize
> +					   (xen_boot_fdt)));
> +      xen_boot_fdt = NULL;
> +    }
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +finalize_params_xen_boot (void)
> +{
> +  struct xen_boot_binary *module;
> +
> +  if (xen_hypervisor)
> +    {
> +      if (prepare_xen_hypervisor_params () != GRUB_ERR_NONE)
> +	goto fail;
> +    }
> +  else
> +    {
> +      grub_dprintf ("xen_boot_loader",
> +		    "Failed to get Xen Hypervisor info!\n");
> +      goto fail;
> +    }
> +
> +  /* Set module params info */
> +  FOR_LIST_ELEMENTS (module, module_head)
> +  {
> +    if (module->start && module->size > 0)
> +      {
> +	grub_dprintf ("xen_boot_loader", "Module %s @ 0x%lx size:0x%lx\n",
> +		      module->name,
> +		      xen_boot_address_align (module->start, module->align),
> +		      module->size);
> +	if (prepare_xen_module_params (module) != GRUB_ERR_NONE)
> +	  goto fail;
> +      }
> +    else
> +      {
> +	grub_dprintf ("xen_boot_loader", "Module info error: %s!\n",
> +		      module->name);
> +	goto fail;
> +      }
> +  }
> +
> +  if (install_all_params () == GRUB_ERR_NONE)
> +    return GRUB_ERR_NONE;
> +
> +fail:
> +  clean_all_params ();
> +
> +  return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT");
> +}
> +
> +
> +static grub_err_t
> +xen_boot (void)
> +{
> +  if (finalize_params_xen_boot () != GRUB_ERR_NONE)
> +    return grub_errno;
> +
Better use err = finalize_params_xen_boot (); if (err) return err;
> +  return grub_arm64_uefi_boot_image (xen_hypervisor->start,
> +				     xen_hypervisor->size,
> +				     xen_hypervisor->cmdline);
> +}
> +
> +static void
> +single_binary_unload (struct xen_boot_binary *binary)
> +{
Just put if (!binary) return; It will save a lot of if's.
> +  if (binary && binary->start && binary->size > 0)
> +    {
> +      grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
> +			   BYTES_TO_PAGES (binary->size + binary->align));
> +    }
> +
> +  if (binary && binary->cmdline && binary->cmdline_size > 0)
> +    {
> +      grub_free (binary->cmdline);
> +      grub_dprintf ("xen_boot_loader",
> +		    "Module %s cmdline memory free @ %p size: %d\n",
> +		    binary->name, binary->cmdline, binary->cmdline_size);
> +    }
> +
> +  if (binary)
> +    {
> +      if (binary->node_info.type == MODULE_CUSTOM)
> +	grub_free ((void *) binary->node_info.compat_string);
> +      if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
> +	grub_list_remove (GRUB_AS_LIST (binary));
> +      grub_dprintf ("xen_boot_loader",
> +		    "Module %s struct memory free @ %p size: 0x%lx\n",
> +		    binary->name, binary, sizeof (binary));
> +      grub_free (binary);
> +    }
> +
> +  return;
> +}
> +
> +static void
> +all_binaries_unload (void)
> +{
> +  struct xen_boot_binary *binary;
> +
> +  FOR_LIST_ELEMENTS (binary, module_head)
> +  {
> +    single_binary_unload (binary);
> +  }
> +
> +  if (xen_hypervisor)
> +    single_binary_unload (xen_hypervisor);
> +
> +  return;
> +}
> +
> +static grub_err_t
> +xen_unload (void)
> +{
> +  *loaded = 0;
> +  all_binaries_unload ();
> +  clean_all_params ();
> +  grub_dl_unref (linux_mod);
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
> +		      int argc, char *argv[])
> +{
> +  binary->size = grub_file_size (file);
> +  grub_dprintf ("xen_boot_loader", "Xen_boot %s file size: 0x%lx\n",
> +		binary->name, binary->size);
> +
> +  binary->start = (grub_addr_t) grub_efi_allocate_pages (0,
> +							 (BYTES_TO_PAGES
> +							  (binary->size +
> +							   binary->align)));
> +  if (!binary->start)
> +    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
> +
> +  grub_dprintf ("xen_boot_loader", "Xen_boot %s numpages: 0x%lx\n",
> +		binary->name, BYTES_TO_PAGES (binary->size + binary->align));
> +
> +  if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
> +							     binary->align),
> +		      binary->size) < (grub_ssize_t) binary->size)
> +    {
We use != throughout. It's safer.
> +      single_binary_unload (binary);
> +      return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
> +			 argv[0]);
> +    }
> +
> +  /* Skip the xen_boot binary file name */
> +  ARG_SHIFT (argc, argv);
> +
There shouldn't be any need for shifting. Just use argc - 1 and argv + 1
> +  if (argc > 0)
> +    {
> +      binary->cmdline_size = grub_loader_cmdline_size (argc, argv);
> +      binary->cmdline = grub_zalloc (binary->cmdline_size);
> +      if (!binary->cmdline)
> +	{
> +	  single_binary_unload (binary);
> +	  return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
> +	}
> +      grub_create_loader_cmdline (argc, argv, binary->cmdline,
> +				  binary->cmdline_size);
> +      grub_dprintf ("xen_boot_loader",
> +		    "Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
> +		    binary->cmdline, binary->cmdline, binary->cmdline_size);
> +    }
> +  else
> +    {
> +      binary->cmdline_size = 0;
> +      binary->cmdline = NULL;
> +    }
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +grub_cmd_xen_module (grub_command_t cmd __attribute__ ((unused)),
> +		     int argc, char *argv[])
> +{
> +
> +  struct xen_boot_binary *module = NULL;
> +  int file_name_index = 0;
> +  grub_file_t file = 0;
> +
> +  if (!argc)
> +    {
> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
> +      goto fail;
> +    }
> +
> +  if (!*loaded)
> +    {
> +      grub_error (GRUB_ERR_BAD_ARGUMENT,
> +		  N_("you need to load the Xen Hypervisor first"));
> +      goto fail;
> +    }
> +
> +  module =
> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
> +  if (!module)
> +    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
> +
Just return grub_errno; zalloc already calls grub_error
> +  /* process all the options and get module type */
> +  if (set_module_type (module, argc, argv, &file_name_index) != GRUB_ERR_NONE)
> +    goto fail;
> +  switch (module->node_info.type)
> +    {
> +    case MODULE_IMAGE:
> +    case MODULE_INITRD:
> +    case MODULE_OTHER:
> +      module->node_info.compat_string =
> +	default_compat_string[module->node_info.type].compat_string;
> +      module->node_info.compat_string_size =
> +	default_compat_string[module->node_info.type].size;
> +      break;
> +
> +    case MODULE_CUSTOM:
> +      /* we have set the node_info in set_module_type */
> +      break;
> +
> +    default:
> +      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
> +    }
> +  module->name = module->node_info.compat_string;
> +  module->align = module_default_align[module->node_info.type];
> +
> +  grub_dprintf ("xen_boot_loader", "Init %s module and node info:\n"
> +		"compatible %s\ncompat_string_size 0x%lx\n",
> +		module->name, module->node_info.compat_string,
> +		module->node_info.compat_string_size);
> +
> +  file = grub_file_open (argv[file_name_index]);
> +  if (!file)
> +    goto fail;
> +
> +  grub_errno = xen_boot_binary_load (module, file, argc - file_name_index,
> +				     argv + file_name_index);
> +
When you call grub_error. grub_errno is already set
> +  if (grub_errno == GRUB_ERR_NONE)
> +    grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
> +
> +fail:
> +  if (file)
> +    grub_file_close (file);
> +  if (grub_errno != GRUB_ERR_NONE)
> +    single_binary_unload (module);
> +
> +  return grub_errno;
> +}
> +
> +static grub_err_t
> +grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
> +			 int argc, char *argv[])
> +{
> +  struct xen_hypervisor_header sh;
> +  grub_file_t file = NULL;
> +
> +  grub_dl_ref (linux_mod);
> +
> +  if (!argc)
> +    {
> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
> +      goto fail;
> +    }
> +
> +  /* For now, we don't support any option in xen_hypervisor command.
> +     If there are some options, we skip them. */
> +  while (argc > 1 && !grub_strncmp (argv[0], "--", 2))
> +    {
> +      grub_dprintf ("xen_boot_loader", "Unknown option %s, skip.\n", argv[0]);
> +      ARG_SHIFT (argc, argv);
> +    }
> +
Why do you need this? Just delete it.
> +  file = grub_file_open (argv[0]);
> +  if (!file)
> +    goto fail;
> +
> +  if (grub_file_read (file, &sh, sizeof (sh)) < (long) sizeof (sh))
> +    goto fail;
> +  if (grub_arm64_uefi_check_image
> +      ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
> +    goto fail;
> +  grub_file_seek (file, 0);
> +
> +  grub_loader_unset ();
> +
This is implicit in loader_set. Please add a comment why it needs to be
explicit. I suppose it's to avoid unloading oneself.
> +  xen_hypervisor =
> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
> +  if (!xen_hypervisor)
> +    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
> +
Ditto
> +  xen_hypervisor->name = XEN_HYPERVISOR_NAME;
> +  xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
> +
> +  grub_errno = xen_boot_binary_load (xen_hypervisor, file, argc, argv);
> +  if (grub_errno == GRUB_ERR_NONE)
> +    {
> +      grub_loader_set (xen_boot, xen_unload, 0);
> +      *loaded = 1;
> +    }
> +
> +fail:
> +  if (file)
> +    grub_file_close (file);
> +  if (grub_errno != GRUB_ERR_NONE)
> +    {
> +      *loaded = 0;
> +      all_binaries_unload ();
> +      grub_dl_unref (linux_mod);
> +    }
> +
> +  return grub_errno;
> +}
> +
> +static grub_command_t cmd_xen_hypervisor, cmd_xen_module;
> +
> +void
> +grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *linux_loaded)
> +{
> +  cmd_xen_hypervisor =
> +    grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
> +			   N_("Load a xen hypervisor."));
> +  cmd_xen_module =
> +    grub_register_command ("xen_module", grub_cmd_xen_module, 0,
> +			   N_("Load a xen module."));
> +  linux_mod = mod;
> +  loaded = linux_loaded;
> +}
> +
> +void
> +grub_arm64_linux_unregister_xen_boot_command (void)
> +{
> +  grub_unregister_command (cmd_xen_hypervisor);
> +  grub_unregister_command (cmd_xen_module);
> +}
> diff --git a/include/grub/arm64/xen_boot.h b/include/grub/arm64/xen_boot.h
> new file mode 100644
> index 0000000..8e8f6cb
> --- /dev/null
> +++ b/include/grub/arm64/xen_boot.h
> @@ -0,0 +1,115 @@
> +/*
> + *  xen_boot.h - Xen boot header file for Xen boot via FDT
> + *  on AArch64 architecture.
> + *  Copyright (C) 2014  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB 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.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef XEN_BOOT_HEADER
> +#define XEN_BOOT_HEADER 1
> +
> +#include <grub/list.h>
> +#include <grub/types.h>
> +#include <grub/efi/pe32.h>	/* required by struct xen_hypervisor_header */
> +
This file doesn't really look like having anything reusable. Please put
it directly into .c
> +#define XEN_HYPERVISOR_NAME  "xen_hypervisor"
> +
> +#define MODULE_DEFAULT_ALIGN  (0x0)
> +#define MODULE_IMAGE_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +#define MODULE_INITRD_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +#define MODULE_OTHER_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +#define MODULE_CUSTOM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +
> +#define MODULE_IMAGE_COMPATIBLE  "multiboot,kernel\0multiboot,module"
> +#define MODULE_INITRD_COMPATIBLE  "multiboot,ramdisk\0multiboot,module"
> +#define MODULE_OTHER_COMPATIBLE  "multiboot,module"
> +
> +/* This maximum size is defined in Power.org ePAPR V1.1
> + * https://www.power.org/documentation/epapr-version-1-1/
> + * 2.2.1.1 Node Name Requirements
> + * node-name@unit-address
> + * 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
> + */
> +#define FDT_NODE_NAME_MAX_SIZE  (49)
> +
> +#define ARG_SHIFT(argc, argv) \
> +  do { \
> +    (argc)--; \
> +    (argv)++; \
> +  } while (0)
> +
> +struct compat_string_struct
> +{
> +  grub_size_t size;
> +  const char *compat_string;
> +};
> +typedef struct compat_string_struct compat_string_struct_t;
> +#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
> +
> +enum module_type
> +{
> +  MODULE_IMAGE,
> +  MODULE_INITRD,
> +  MODULE_OTHER,
> +  MODULE_CUSTOM
> +};
> +typedef enum module_type module_type_t;
> +
> +struct fdt_node_info
> +{
> +  module_type_t type;
> +
> +  const char *compat_string;
> +  grub_size_t compat_string_size;
> +};
> +
> +struct xen_hypervisor_header
> +{
> +  struct grub_arm64_linux_kernel_header efi_head;
> +
> +  /* This is always PE\0\0.  */
> +  grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
> +  /* The COFF file header.  */
> +  struct grub_pe32_coff_header coff_header;
> +  /* The Optional header.  */
> +  struct grub_pe64_optional_header optional_header;
> +};
> +
> +struct xen_boot_binary
> +{
> +  struct xen_boot_binary *next;
> +  struct xen_boot_binary **prev;
> +  const char *name;
> +
> +  grub_addr_t start;
> +  grub_size_t size;
> +  grub_size_t align;
> +
> +  char *cmdline;
> +  int cmdline_size;
> +
> +  struct fdt_node_info node_info;
> +};
> +
> +void grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *loaded);
> +void grub_arm64_linux_unregister_xen_boot_command (void);
> +
> +static __inline grub_addr_t
> +xen_boot_address_align (grub_addr_t start, grub_size_t align)
> +{
> +  return (align ? (ALIGN_UP (start, align)) : start);
> +}
> +
> +#endif /* ! XEN_BOOT_HEADER */
> 



[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

[-- Attachment #2: Type: text/plain, Size: 141 bytes --]

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 1/3] arm64: Add Xen boot support file
@ 2015-07-15 16:18       ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 0 replies; 550+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2015-07-15 16:18 UTC (permalink / raw)
  To: fu.wei, grub-devel, arvidjaar
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi

[-- Attachment #1: Type: text/plain, Size: 27720 bytes --]

On 13.07.2015 10:53, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> This patch adds Xen boot support file:
> grub-core/loader/arm64/xen_boot.c
> include/grub/arm64/xen_boot.h
> 
> This patch also adds commands register code and hearder file into
> grub-core/loader/arm64/linux.c
> 
>   - This adds support for the Xen boot on ARM specification for arm64.
>   - The implementation for Xen is following  <Multiboot on ARM Specification>:
>       http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
Please don't refer to this protocol as multiboot anywhere in grub or
around because it's NOT multiboot and we don't want to confuse those 2
protocols.
>     and xen/docs/misc/arm/device-tree/booting.txt in Xen source code.
>   - The multiboot/module commands have existed,
>     so we use xen_hypervisor/xen_module instead.
>   - This Xen boot support is built into linux module for aarch64.
>   - Adding this functionality to the existing "linux" module is for
>     reusing the existing code of devicetree.
> 
Please create separate module. Modules are dynamically linked.
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  grub-core/Makefile.core.def       |   1 +
>  grub-core/loader/arm64/linux.c    |   6 +
>  grub-core/loader/arm64/xen_boot.c | 615 ++++++++++++++++++++++++++++++++++++++
>  include/grub/arm64/xen_boot.h     | 115 +++++++
>  4 files changed, 737 insertions(+)
>  create mode 100644 grub-core/loader/arm64/xen_boot.c
>  create mode 100644 include/grub/arm64/xen_boot.h
> 
> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
> index a6101de..01f8261 100644
> --- a/grub-core/Makefile.core.def
> +++ b/grub-core/Makefile.core.def
> @@ -1659,6 +1659,7 @@ module = {
>    ia64_efi = loader/ia64/efi/linux.c;
>    arm = loader/arm/linux.c;
>    arm64 = loader/arm64/linux.c;
> +  arm64 = loader/arm64/xen_boot.c;
>    fdt = lib/fdt.c;
>    common = loader/linux.c;
>    common = lib/cmdline.c;
> diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
> index 987f5b9..7ae9bde 100644
> --- a/grub-core/loader/arm64/linux.c
> +++ b/grub-core/loader/arm64/linux.c
> @@ -26,6 +26,7 @@
>  #include <grub/mm.h>
>  #include <grub/types.h>
>  #include <grub/cpu/linux.h>
> +#include <grub/cpu/xen_boot.h>
>  #include <grub/efi/efi.h>
>  #include <grub/efi/pe32.h>
>  #include <grub/i18n.h>
> @@ -477,6 +478,9 @@ GRUB_MOD_INIT (linux)
>    cmd_devicetree =
>      grub_register_command ("devicetree", grub_cmd_devicetree, 0,
>  			   N_("Load DTB file."));
> +
> +  grub_arm64_linux_register_xen_boot_command (mod, &loaded);
> +
>    my_mod = mod;
>  }
>  
> @@ -485,4 +489,6 @@ GRUB_MOD_FINI (linux)
>    grub_unregister_command (cmd_linux);
>    grub_unregister_command (cmd_initrd);
>    grub_unregister_command (cmd_devicetree);
> +
> +  grub_arm64_linux_unregister_xen_boot_command ();
>  }
Not needed with separate module.
> diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
> new file mode 100644
> index 0000000..23bd00e
> --- /dev/null
> +++ b/grub-core/loader/arm64/xen_boot.c
> @@ -0,0 +1,615 @@
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2014  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB 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.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/cache.h>
> +#include <grub/charset.h>
> +#include <grub/command.h>
> +#include <grub/err.h>
> +#include <grub/file.h>
> +#include <grub/fdt.h>
> +#include <grub/linux.h>
> +#include <grub/list.h>
> +#include <grub/loader.h>
> +#include <grub/misc.h>
> +#include <grub/mm.h>
> +#include <grub/types.h>
> +#include <grub/cpu/linux.h>
> +#include <grub/cpu/xen_boot.h>
> +#include <grub/efi/efi.h>
> +#include <grub/efi/pe32.h>
> +#include <grub/i18n.h>
> +#include <grub/lib/cmdline.h>
> +
> +static grub_dl_t linux_mod;
> +static int *loaded;
> +
> +static struct xen_boot_binary *xen_hypervisor;
> +static struct xen_boot_binary *module_head;
> +static const grub_size_t module_default_align[] = {
> +  MODULE_IMAGE_MIN_ALIGN,
> +  MODULE_INITRD_MIN_ALIGN,
> +  MODULE_OTHER_MIN_ALIGN,
> +  MODULE_CUSTOM_MIN_ALIGN
> +};
> +
> +static void *xen_boot_fdt;
> +static const compat_string_struct_t default_compat_string[] = {
> +  FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
> +  FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
> +  FDT_COMPATIBLE (MODULE_OTHER_COMPATIBLE)
> +};
> +
> +
> +/* Parse all the options of xen_module command. For now, we support
> +   (1) --type <the compatible stream>
> +   (2) --nounzip
> +   We also set up the type of module in this function.
> +   If there are some "--type" options in the command line,
> +   we make a custom compatible stream in this function. */
> +static grub_err_t
> +set_module_type (struct xen_boot_binary *module, int argc, char *argv[],
> +		 int *file_name_index)
> +{
> +  char **compat_string_temp_array =
> +    (char **) grub_zalloc (sizeof (char *) * argc);
> +  static module_type_t default_type = MODULE_IMAGE;
> +  grub_size_t total_size = 0;
> +  int num_types = 0, i;
> +  char *temp = NULL;
> +
> +  *file_name_index = 0;
> +
> +  /* if there are some options we need to process. */
> +  while (argc > 1 && !grub_strncmp (argv[0], "--", 2))
> +    {
> +      if (!grub_strcmp (argv[0], "--type"))
> +	{
> +	  module->node_info.type = MODULE_CUSTOM;
> +	  ARG_SHIFT (argc, argv);
> +	  total_size += grub_strlen (argv[0]) + 1;
> +	  compat_string_temp_array[num_types++] = argv[0];
> +	  ARG_SHIFT (argc, argv);
> +	  (*file_name_index) += 2;
This (and subsequent) parsing is unecessarily complicated. Please create
separate commands for different types
> +	}
> +      else if (!grub_strcmp (argv[0], "--nounzip"))
> +	{
> +	  grub_file_filter_disable_compression ();
> +	  ARG_SHIFT (argc, argv);
> +	  (*file_name_index) += 1;
> +	}
> +      else			/* we can add more options process code here. */
> +	{
> +	  grub_dprintf ("xen_boot_loader",
> +			"Unknown option %s, skip.\n", argv[0]);
> +	  ARG_SHIFT (argc, argv);
> +	  (*file_name_index) += 1;
> +	}
> +    }
> +
> +  /* To prevent some wrong command lines using "--type" option */
> +  if (!argc)
> +    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
> +
> +  /* For the default module type :
> +     The implementation is following <Multiboot on ARM Specification>:
> +     Each module will be given a default compatibility property
> +     based on the order in which the modules are added.
> +     The 1st module: compatible = "multiboot,kernel", "multiboot,module"
> +     The 2nd module: compatible = "multiboot,ramdisk", "multiboot,module"
> +     All subsequent modules: compatible = "multiboot,module"
> +     But this order will NOT be interfered with "--type"(MODULE_CUSTOM)
> +     For more detail, please refer to:
> +     http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot */
> +  if (module->node_info.type != MODULE_CUSTOM)
> +    {
> +      /* the module type is set by the load order */
> +      module->node_info.type = default_type;
Please don't make it order-dependent more than necessarry.
> +      switch (default_type)
> +	{
> +	case MODULE_IMAGE:
> +	  default_type = MODULE_INITRD;
> +	  break;
> +
> +	case MODULE_INITRD:
> +	  default_type = MODULE_OTHER;
> +	  break;
> +
> +	case MODULE_OTHER:
> +	  break;
> +
> +	default:
> +	  default_type = MODULE_IMAGE;	/* error, reset the type */
> +	  return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
> +	}
> +    }
> +  else
> +    {
> +      /* the module type is set by "--type"(MODULE_CUSTOM) */
> +      module->node_info.compat_string = temp =
> +	(char *) grub_zalloc (total_size);
> +      module->node_info.compat_string_size = total_size;
> +      for (i = 0; num_types > 0; num_types--, i++, temp++)
> +	{
> +	  grub_strcpy (temp, compat_string_temp_array[i]);
> +	  temp += grub_strlen (compat_string_temp_array[i]);
> +	}
> +    }
> +
> +  grub_free (compat_string_temp_array);
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +prepare_xen_hypervisor_params (void)
> +{
> +  int chosen_node = 0;
> +  int retval;
> +
> +  xen_boot_fdt = grub_linux_get_fdt ();
> +  if (!xen_boot_fdt)
> +    return grub_error (GRUB_ERR_BAD_OS, "failed to get FDT");
> +
> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 0)
> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 1)
> +    return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT");
> +
BAD_OS means that OS images are invalid. ERR_IO is a generic error for
such cases.
> +  grub_dprintf ("xen_boot_loader",
> +		"Xen Hypervisor cmdline : %s @ %p size:%d\n",
> +		xen_hypervisor->cmdline, xen_hypervisor->cmdline,
> +		xen_hypervisor->cmdline_size);
> +
No need for "boot_". xen_loader is fine and mre consistent.
> +  retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
> +			      xen_hypervisor->cmdline,
> +			      xen_hypervisor->cmdline_size);
> +  if (retval)
> +    return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT");
> +
ditto
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +prepare_xen_module_params (struct xen_boot_binary *module)
> +{
> +  int retval, chosen_node = 0, module_node = 0;
> +  char module_name[FDT_NODE_NAME_MAX_SIZE];
> +
> +  retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
> +			  xen_boot_address_align (module->start,
> +						  module->align));
> +  grub_dprintf ("xen_boot_loader", "Module node name %s \n", module_name);
> +
> +  if (retval < (int) sizeof ("module@"))
> +    return grub_error (GRUB_ERR_BAD_OS, N_("failed to get FDT"));
> +
> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 0)
> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 1)
> +    return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT");
> +
> +  module_node =
> +    grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
> +  if (module_node < 0)
> +    module_node =
> +      grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
> +
> +  retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
> +			      module->node_info.compat_string,
> +			      (grub_uint32_t) module->node_info.
> +			      compat_string_size);
> +  if (retval)
> +    return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT"));
> +
> +  grub_dprintf ("xen_boot_loader", "Module %s compatible = %s size = 0x%lx\n",
> +		module->name, module->node_info.compat_string,
> +		module->node_info.compat_string_size);
> +
> +  retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
> +			       xen_boot_address_align (module->start,
> +						       module->align),
> +			       module->size);
> +  if (retval)
> +    return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT"));
> +
> +  if (module->cmdline && module->cmdline_size > 0)
> +    {
> +      grub_dprintf ("xen_boot_loader",
> +		    "Module %s cmdline : %s @ %p size:%d\n", module->name,
> +		    module->cmdline, module->cmdline, module->cmdline_size);
> +
> +      retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
> +				  module->cmdline, module->cmdline_size + 1);
> +      if (retval)
> +	return grub_error (GRUB_ERR_BAD_OS, "failed to update FDT");
> +    }
> +  else
> +    {
> +      grub_dprintf ("xen_boot_loader", "Module %s has not bootargs!\n",
> +		    module->name);
> +    }
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +install_all_params (void)
> +{
> +  grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
> +  grub_efi_boot_services_t *b;
> +  grub_efi_status_t status;
> +
> +  b = grub_efi_system_table->boot_services;
> +  status = b->install_configuration_table (&fdt_guid, xen_boot_fdt);
> +  if (status != GRUB_EFI_SUCCESS)
> +    return grub_error (GRUB_ERR_BAD_OS, "failed to install FDT");
> +
> +  grub_dprintf ("xen_boot_loader",
> +		"Installed/updated FDT configuration table @ %p\n",
> +		xen_boot_fdt);
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +clean_all_params (void)
> +{
> +  if (xen_boot_fdt)
> +    {
> +      grub_efi_free_pages ((grub_efi_physical_address_t) xen_boot_fdt,
> +			   BYTES_TO_PAGES (grub_fdt_get_totalsize
> +					   (xen_boot_fdt)));
> +      xen_boot_fdt = NULL;
> +    }
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +finalize_params_xen_boot (void)
> +{
> +  struct xen_boot_binary *module;
> +
> +  if (xen_hypervisor)
> +    {
> +      if (prepare_xen_hypervisor_params () != GRUB_ERR_NONE)
> +	goto fail;
> +    }
> +  else
> +    {
> +      grub_dprintf ("xen_boot_loader",
> +		    "Failed to get Xen Hypervisor info!\n");
> +      goto fail;
> +    }
> +
> +  /* Set module params info */
> +  FOR_LIST_ELEMENTS (module, module_head)
> +  {
> +    if (module->start && module->size > 0)
> +      {
> +	grub_dprintf ("xen_boot_loader", "Module %s @ 0x%lx size:0x%lx\n",
> +		      module->name,
> +		      xen_boot_address_align (module->start, module->align),
> +		      module->size);
> +	if (prepare_xen_module_params (module) != GRUB_ERR_NONE)
> +	  goto fail;
> +      }
> +    else
> +      {
> +	grub_dprintf ("xen_boot_loader", "Module info error: %s!\n",
> +		      module->name);
> +	goto fail;
> +      }
> +  }
> +
> +  if (install_all_params () == GRUB_ERR_NONE)
> +    return GRUB_ERR_NONE;
> +
> +fail:
> +  clean_all_params ();
> +
> +  return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT");
> +}
> +
> +
> +static grub_err_t
> +xen_boot (void)
> +{
> +  if (finalize_params_xen_boot () != GRUB_ERR_NONE)
> +    return grub_errno;
> +
Better use err = finalize_params_xen_boot (); if (err) return err;
> +  return grub_arm64_uefi_boot_image (xen_hypervisor->start,
> +				     xen_hypervisor->size,
> +				     xen_hypervisor->cmdline);
> +}
> +
> +static void
> +single_binary_unload (struct xen_boot_binary *binary)
> +{
Just put if (!binary) return; It will save a lot of if's.
> +  if (binary && binary->start && binary->size > 0)
> +    {
> +      grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
> +			   BYTES_TO_PAGES (binary->size + binary->align));
> +    }
> +
> +  if (binary && binary->cmdline && binary->cmdline_size > 0)
> +    {
> +      grub_free (binary->cmdline);
> +      grub_dprintf ("xen_boot_loader",
> +		    "Module %s cmdline memory free @ %p size: %d\n",
> +		    binary->name, binary->cmdline, binary->cmdline_size);
> +    }
> +
> +  if (binary)
> +    {
> +      if (binary->node_info.type == MODULE_CUSTOM)
> +	grub_free ((void *) binary->node_info.compat_string);
> +      if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
> +	grub_list_remove (GRUB_AS_LIST (binary));
> +      grub_dprintf ("xen_boot_loader",
> +		    "Module %s struct memory free @ %p size: 0x%lx\n",
> +		    binary->name, binary, sizeof (binary));
> +      grub_free (binary);
> +    }
> +
> +  return;
> +}
> +
> +static void
> +all_binaries_unload (void)
> +{
> +  struct xen_boot_binary *binary;
> +
> +  FOR_LIST_ELEMENTS (binary, module_head)
> +  {
> +    single_binary_unload (binary);
> +  }
> +
> +  if (xen_hypervisor)
> +    single_binary_unload (xen_hypervisor);
> +
> +  return;
> +}
> +
> +static grub_err_t
> +xen_unload (void)
> +{
> +  *loaded = 0;
> +  all_binaries_unload ();
> +  clean_all_params ();
> +  grub_dl_unref (linux_mod);
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
> +		      int argc, char *argv[])
> +{
> +  binary->size = grub_file_size (file);
> +  grub_dprintf ("xen_boot_loader", "Xen_boot %s file size: 0x%lx\n",
> +		binary->name, binary->size);
> +
> +  binary->start = (grub_addr_t) grub_efi_allocate_pages (0,
> +							 (BYTES_TO_PAGES
> +							  (binary->size +
> +							   binary->align)));
> +  if (!binary->start)
> +    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
> +
> +  grub_dprintf ("xen_boot_loader", "Xen_boot %s numpages: 0x%lx\n",
> +		binary->name, BYTES_TO_PAGES (binary->size + binary->align));
> +
> +  if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
> +							     binary->align),
> +		      binary->size) < (grub_ssize_t) binary->size)
> +    {
We use != throughout. It's safer.
> +      single_binary_unload (binary);
> +      return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
> +			 argv[0]);
> +    }
> +
> +  /* Skip the xen_boot binary file name */
> +  ARG_SHIFT (argc, argv);
> +
There shouldn't be any need for shifting. Just use argc - 1 and argv + 1
> +  if (argc > 0)
> +    {
> +      binary->cmdline_size = grub_loader_cmdline_size (argc, argv);
> +      binary->cmdline = grub_zalloc (binary->cmdline_size);
> +      if (!binary->cmdline)
> +	{
> +	  single_binary_unload (binary);
> +	  return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
> +	}
> +      grub_create_loader_cmdline (argc, argv, binary->cmdline,
> +				  binary->cmdline_size);
> +      grub_dprintf ("xen_boot_loader",
> +		    "Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
> +		    binary->cmdline, binary->cmdline, binary->cmdline_size);
> +    }
> +  else
> +    {
> +      binary->cmdline_size = 0;
> +      binary->cmdline = NULL;
> +    }
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +grub_cmd_xen_module (grub_command_t cmd __attribute__ ((unused)),
> +		     int argc, char *argv[])
> +{
> +
> +  struct xen_boot_binary *module = NULL;
> +  int file_name_index = 0;
> +  grub_file_t file = 0;
> +
> +  if (!argc)
> +    {
> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
> +      goto fail;
> +    }
> +
> +  if (!*loaded)
> +    {
> +      grub_error (GRUB_ERR_BAD_ARGUMENT,
> +		  N_("you need to load the Xen Hypervisor first"));
> +      goto fail;
> +    }
> +
> +  module =
> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
> +  if (!module)
> +    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
> +
Just return grub_errno; zalloc already calls grub_error
> +  /* process all the options and get module type */
> +  if (set_module_type (module, argc, argv, &file_name_index) != GRUB_ERR_NONE)
> +    goto fail;
> +  switch (module->node_info.type)
> +    {
> +    case MODULE_IMAGE:
> +    case MODULE_INITRD:
> +    case MODULE_OTHER:
> +      module->node_info.compat_string =
> +	default_compat_string[module->node_info.type].compat_string;
> +      module->node_info.compat_string_size =
> +	default_compat_string[module->node_info.type].size;
> +      break;
> +
> +    case MODULE_CUSTOM:
> +      /* we have set the node_info in set_module_type */
> +      break;
> +
> +    default:
> +      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
> +    }
> +  module->name = module->node_info.compat_string;
> +  module->align = module_default_align[module->node_info.type];
> +
> +  grub_dprintf ("xen_boot_loader", "Init %s module and node info:\n"
> +		"compatible %s\ncompat_string_size 0x%lx\n",
> +		module->name, module->node_info.compat_string,
> +		module->node_info.compat_string_size);
> +
> +  file = grub_file_open (argv[file_name_index]);
> +  if (!file)
> +    goto fail;
> +
> +  grub_errno = xen_boot_binary_load (module, file, argc - file_name_index,
> +				     argv + file_name_index);
> +
When you call grub_error. grub_errno is already set
> +  if (grub_errno == GRUB_ERR_NONE)
> +    grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
> +
> +fail:
> +  if (file)
> +    grub_file_close (file);
> +  if (grub_errno != GRUB_ERR_NONE)
> +    single_binary_unload (module);
> +
> +  return grub_errno;
> +}
> +
> +static grub_err_t
> +grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
> +			 int argc, char *argv[])
> +{
> +  struct xen_hypervisor_header sh;
> +  grub_file_t file = NULL;
> +
> +  grub_dl_ref (linux_mod);
> +
> +  if (!argc)
> +    {
> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
> +      goto fail;
> +    }
> +
> +  /* For now, we don't support any option in xen_hypervisor command.
> +     If there are some options, we skip them. */
> +  while (argc > 1 && !grub_strncmp (argv[0], "--", 2))
> +    {
> +      grub_dprintf ("xen_boot_loader", "Unknown option %s, skip.\n", argv[0]);
> +      ARG_SHIFT (argc, argv);
> +    }
> +
Why do you need this? Just delete it.
> +  file = grub_file_open (argv[0]);
> +  if (!file)
> +    goto fail;
> +
> +  if (grub_file_read (file, &sh, sizeof (sh)) < (long) sizeof (sh))
> +    goto fail;
> +  if (grub_arm64_uefi_check_image
> +      ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
> +    goto fail;
> +  grub_file_seek (file, 0);
> +
> +  grub_loader_unset ();
> +
This is implicit in loader_set. Please add a comment why it needs to be
explicit. I suppose it's to avoid unloading oneself.
> +  xen_hypervisor =
> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
> +  if (!xen_hypervisor)
> +    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
> +
Ditto
> +  xen_hypervisor->name = XEN_HYPERVISOR_NAME;
> +  xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
> +
> +  grub_errno = xen_boot_binary_load (xen_hypervisor, file, argc, argv);
> +  if (grub_errno == GRUB_ERR_NONE)
> +    {
> +      grub_loader_set (xen_boot, xen_unload, 0);
> +      *loaded = 1;
> +    }
> +
> +fail:
> +  if (file)
> +    grub_file_close (file);
> +  if (grub_errno != GRUB_ERR_NONE)
> +    {
> +      *loaded = 0;
> +      all_binaries_unload ();
> +      grub_dl_unref (linux_mod);
> +    }
> +
> +  return grub_errno;
> +}
> +
> +static grub_command_t cmd_xen_hypervisor, cmd_xen_module;
> +
> +void
> +grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *linux_loaded)
> +{
> +  cmd_xen_hypervisor =
> +    grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
> +			   N_("Load a xen hypervisor."));
> +  cmd_xen_module =
> +    grub_register_command ("xen_module", grub_cmd_xen_module, 0,
> +			   N_("Load a xen module."));
> +  linux_mod = mod;
> +  loaded = linux_loaded;
> +}
> +
> +void
> +grub_arm64_linux_unregister_xen_boot_command (void)
> +{
> +  grub_unregister_command (cmd_xen_hypervisor);
> +  grub_unregister_command (cmd_xen_module);
> +}
> diff --git a/include/grub/arm64/xen_boot.h b/include/grub/arm64/xen_boot.h
> new file mode 100644
> index 0000000..8e8f6cb
> --- /dev/null
> +++ b/include/grub/arm64/xen_boot.h
> @@ -0,0 +1,115 @@
> +/*
> + *  xen_boot.h - Xen boot header file for Xen boot via FDT
> + *  on AArch64 architecture.
> + *  Copyright (C) 2014  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB 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.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef XEN_BOOT_HEADER
> +#define XEN_BOOT_HEADER 1
> +
> +#include <grub/list.h>
> +#include <grub/types.h>
> +#include <grub/efi/pe32.h>	/* required by struct xen_hypervisor_header */
> +
This file doesn't really look like having anything reusable. Please put
it directly into .c
> +#define XEN_HYPERVISOR_NAME  "xen_hypervisor"
> +
> +#define MODULE_DEFAULT_ALIGN  (0x0)
> +#define MODULE_IMAGE_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +#define MODULE_INITRD_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +#define MODULE_OTHER_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +#define MODULE_CUSTOM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +
> +#define MODULE_IMAGE_COMPATIBLE  "multiboot,kernel\0multiboot,module"
> +#define MODULE_INITRD_COMPATIBLE  "multiboot,ramdisk\0multiboot,module"
> +#define MODULE_OTHER_COMPATIBLE  "multiboot,module"
> +
> +/* This maximum size is defined in Power.org ePAPR V1.1
> + * https://www.power.org/documentation/epapr-version-1-1/
> + * 2.2.1.1 Node Name Requirements
> + * node-name@unit-address
> + * 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
> + */
> +#define FDT_NODE_NAME_MAX_SIZE  (49)
> +
> +#define ARG_SHIFT(argc, argv) \
> +  do { \
> +    (argc)--; \
> +    (argv)++; \
> +  } while (0)
> +
> +struct compat_string_struct
> +{
> +  grub_size_t size;
> +  const char *compat_string;
> +};
> +typedef struct compat_string_struct compat_string_struct_t;
> +#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
> +
> +enum module_type
> +{
> +  MODULE_IMAGE,
> +  MODULE_INITRD,
> +  MODULE_OTHER,
> +  MODULE_CUSTOM
> +};
> +typedef enum module_type module_type_t;
> +
> +struct fdt_node_info
> +{
> +  module_type_t type;
> +
> +  const char *compat_string;
> +  grub_size_t compat_string_size;
> +};
> +
> +struct xen_hypervisor_header
> +{
> +  struct grub_arm64_linux_kernel_header efi_head;
> +
> +  /* This is always PE\0\0.  */
> +  grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
> +  /* The COFF file header.  */
> +  struct grub_pe32_coff_header coff_header;
> +  /* The Optional header.  */
> +  struct grub_pe64_optional_header optional_header;
> +};
> +
> +struct xen_boot_binary
> +{
> +  struct xen_boot_binary *next;
> +  struct xen_boot_binary **prev;
> +  const char *name;
> +
> +  grub_addr_t start;
> +  grub_size_t size;
> +  grub_size_t align;
> +
> +  char *cmdline;
> +  int cmdline_size;
> +
> +  struct fdt_node_info node_info;
> +};
> +
> +void grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *loaded);
> +void grub_arm64_linux_unregister_xen_boot_command (void);
> +
> +static __inline grub_addr_t
> +xen_boot_address_align (grub_addr_t start, grub_size_t align)
> +{
> +  return (align ? (ALIGN_UP (start, align)) : start);
> +}
> +
> +#endif /* ! XEN_BOOT_HEADER */
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 2/3] util/grub.d/20_linux_xen.in: Add arm64 support
  2015-07-14 13:09         ` Fu Wei
@ 2015-07-15 16:24           ` Vladimir 'φ-coder/phcoder' Serbinenko
  -1 siblings, 0 replies; 550+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2015-07-15 16:24 UTC (permalink / raw)
  To: Fu Wei, Andrei Borzenkov
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Jon Masters, Leif Lindholm, Ryan Harkin,
	Linaro UEFI Mailman List


[-- Attachment #1.1: Type: text/plain, Size: 3850 bytes --]

On 14.07.2015 15:09, Fu Wei wrote:
> Hi Andrei,
> 
> Great thanks for your review.
> 
> So Are you suggesting this:
> (1) in util/grub.d/20_linux_xen.in, we only use xen_hypervisor/xen_module.
> (2) in xen_boot.c, we only register command xen_hypervisor/xen_module.
> (3) in grub-core/loader/i386/xen.c, we *add*
> ---------------
>   cmd_xen_hypervisort = grub_register_command ("xen_hypervisor", grub_cmd_xen,
> 0, N_("Load Linux."));
>   cmd_xen_module = grub_register_command ("xen_module", grub_cmd_module,
>      0, N_("Load module."));
No. This is for pvgrub2.
> ---------------
> (4)in grub-core/loader/multiboot.c, we *add*
> ---------------
> #if defined (__i386__) || defined (__aarch64__)
>   cmd_xen_hypervisort =
>     grub_register_command ("xen_hypervisor", grub_cmd_multiboot,
>   0, N_("Load a multiboot kernel."));
>   cmd_xen_module =
>     grub_register_command ("xen_module", grub_cmd_module,
>   0, N_("Load a multiboot module."));
> #endif
No. Don't mix arm64 xen with multiboot. Neither in command names nor in
the descriptions.
> ---------------
> 
> BTW, from the source code, MIPS isn't supported by multiboot,  IS
> supported by multiboot2.
> 
> Please correct me. If I misunderstand your suggestion. :-)
> 
> Thanks again!
> 
> 
> On 14 July 2015 at 11:53, Andrei Borzenkov <arvidjaar@gmail.com> wrote:
>> В Mon, 13 Jul 2015 16:53:59 +0800
>> fu.wei@linaro.org пишет:
>>
>>> From: Fu Wei <fu.wei@linaro.org>
>>>
>>> This patch adds the support of boot command on arm64 for XEN:
>>>     xen_hypervisor
>>>     xen_module
>>>
>>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>>> ---
>>>  util/grub.d/20_linux_xen.in | 14 +++++++++++---
>>>  1 file changed, 11 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
>>> index f532fb9..b52c50d 100644
>>> --- a/util/grub.d/20_linux_xen.in
>>> +++ b/util/grub.d/20_linux_xen.in
>>> @@ -120,16 +120,16 @@ linux_entry ()
>>>          else
>>>              xen_rm_opts="no-real-mode edd=off"
>>>          fi
>>> -     multiboot       ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
>>> +     ${multiboot_cmd}        ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
>>>       echo    '$(echo "$lmessage" | grub_quote)'
>>> -     module  ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
>>> +     ${module_cmd}   ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
>>>  EOF
>>>    if test -n "${initrd}" ; then
>>>      # TRANSLATORS: ramdisk isn't identifier. Should be translated.
>>>      message="$(gettext_printf "Loading initial ramdisk ...")"
>>>      sed "s/^/$submenu_indentation/" << EOF
>>>       echo    '$(echo "$message" | grub_quote)'
>>> -     module  --nounzip   ${rel_dirname}/${initrd}
>>> +     ${module_cmd}   --nounzip   ${rel_dirname}/${initrd}
>>>  EOF
>>>    fi
>>>    sed "s/^/$submenu_indentation/" << EOF
>>> @@ -185,6 +185,14 @@ case "$machine" in
>>>      *) GENKERNEL_ARCH="$machine" ;;
>>>  esac
>>>
>>> +if [ "x$machine" != xaarch64 ]; then
>>> +     multiboot_cmd="multiboot"
>>> +     module_cmd="module"
>>> +else
>>> +     multiboot_cmd="xen_hypervisor"
>>> +     module_cmd="xen_module"
>>> +fi
>>> +
>>
>> Strictly speaking, this is boot-time decision. As mentioned by
>> Vladimir, better would be to provide alias xen_hypervisor and
>> xen_module in multiboot for platforms supporting Xen (is MIPS really
>> supported?) and use it consistently.
>>
>>>  # Extra indentation to add to menu entries in a submenu. We're not in a submenu
>>>  # yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
>>>  submenu_indentation=""
>>
> 
> 
> 



[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

[-- Attachment #2: Type: text/plain, Size: 141 bytes --]

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 2/3] util/grub.d/20_linux_xen.in: Add arm64 support
@ 2015-07-15 16:24           ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 0 replies; 550+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2015-07-15 16:24 UTC (permalink / raw)
  To: Fu Wei, Andrei Borzenkov
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Jon Masters, Leif Lindholm, Ryan Harkin,
	Linaro UEFI Mailman List

[-- Attachment #1: Type: text/plain, Size: 3850 bytes --]

On 14.07.2015 15:09, Fu Wei wrote:
> Hi Andrei,
> 
> Great thanks for your review.
> 
> So Are you suggesting this:
> (1) in util/grub.d/20_linux_xen.in, we only use xen_hypervisor/xen_module.
> (2) in xen_boot.c, we only register command xen_hypervisor/xen_module.
> (3) in grub-core/loader/i386/xen.c, we *add*
> ---------------
>   cmd_xen_hypervisort = grub_register_command ("xen_hypervisor", grub_cmd_xen,
> 0, N_("Load Linux."));
>   cmd_xen_module = grub_register_command ("xen_module", grub_cmd_module,
>      0, N_("Load module."));
No. This is for pvgrub2.
> ---------------
> (4)in grub-core/loader/multiboot.c, we *add*
> ---------------
> #if defined (__i386__) || defined (__aarch64__)
>   cmd_xen_hypervisort =
>     grub_register_command ("xen_hypervisor", grub_cmd_multiboot,
>   0, N_("Load a multiboot kernel."));
>   cmd_xen_module =
>     grub_register_command ("xen_module", grub_cmd_module,
>   0, N_("Load a multiboot module."));
> #endif
No. Don't mix arm64 xen with multiboot. Neither in command names nor in
the descriptions.
> ---------------
> 
> BTW, from the source code, MIPS isn't supported by multiboot,  IS
> supported by multiboot2.
> 
> Please correct me. If I misunderstand your suggestion. :-)
> 
> Thanks again!
> 
> 
> On 14 July 2015 at 11:53, Andrei Borzenkov <arvidjaar@gmail.com> wrote:
>> В Mon, 13 Jul 2015 16:53:59 +0800
>> fu.wei@linaro.org пишет:
>>
>>> From: Fu Wei <fu.wei@linaro.org>
>>>
>>> This patch adds the support of boot command on arm64 for XEN:
>>>     xen_hypervisor
>>>     xen_module
>>>
>>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>>> ---
>>>  util/grub.d/20_linux_xen.in | 14 +++++++++++---
>>>  1 file changed, 11 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
>>> index f532fb9..b52c50d 100644
>>> --- a/util/grub.d/20_linux_xen.in
>>> +++ b/util/grub.d/20_linux_xen.in
>>> @@ -120,16 +120,16 @@ linux_entry ()
>>>          else
>>>              xen_rm_opts="no-real-mode edd=off"
>>>          fi
>>> -     multiboot       ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
>>> +     ${multiboot_cmd}        ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
>>>       echo    '$(echo "$lmessage" | grub_quote)'
>>> -     module  ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
>>> +     ${module_cmd}   ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
>>>  EOF
>>>    if test -n "${initrd}" ; then
>>>      # TRANSLATORS: ramdisk isn't identifier. Should be translated.
>>>      message="$(gettext_printf "Loading initial ramdisk ...")"
>>>      sed "s/^/$submenu_indentation/" << EOF
>>>       echo    '$(echo "$message" | grub_quote)'
>>> -     module  --nounzip   ${rel_dirname}/${initrd}
>>> +     ${module_cmd}   --nounzip   ${rel_dirname}/${initrd}
>>>  EOF
>>>    fi
>>>    sed "s/^/$submenu_indentation/" << EOF
>>> @@ -185,6 +185,14 @@ case "$machine" in
>>>      *) GENKERNEL_ARCH="$machine" ;;
>>>  esac
>>>
>>> +if [ "x$machine" != xaarch64 ]; then
>>> +     multiboot_cmd="multiboot"
>>> +     module_cmd="module"
>>> +else
>>> +     multiboot_cmd="xen_hypervisor"
>>> +     module_cmd="xen_module"
>>> +fi
>>> +
>>
>> Strictly speaking, this is boot-time decision. As mentioned by
>> Vladimir, better would be to provide alias xen_hypervisor and
>> xen_module in multiboot for platforms supporting Xen (is MIPS really
>> supported?) and use it consistently.
>>
>>>  # Extra indentation to add to menu entries in a submenu. We're not in a submenu
>>>  # yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
>>>  submenu_indentation=""
>>
> 
> 
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 1/3] arm64: Add Xen boot support file
  2015-07-15 16:18       ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2015-07-16 16:46         ` Ian Campbell
  -1 siblings, 0 replies; 550+ messages in thread
From: Ian Campbell @ 2015-07-16 16:46 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: grub-devel, xen-devel, stefano.stabellini, arvidjaar, jcm,
	leif.lindholm, ryan.harkin, linaro-uefi, fu.wei

On Wed, 2015-07-15 at 18:18 +0200, Vladimir 'φ-coder/phcoder' Serbinenko
wrote:
> On 13.07.2015 10:53, fu.wei@linaro.org wrote:
> > From: Fu Wei <fu.wei@linaro.org>
> > 
> > This patch adds Xen boot support file:
> > grub-core/loader/arm64/xen_boot.c
> > include/grub/arm64/xen_boot.h
> > 
> > This patch also adds commands register code and hearder file into
> > grub-core/loader/arm64/linux.c
> > 
> >   - This adds support for the Xen boot on ARM specification for arm64.
> >   - The implementation for Xen is following  <Multiboot on ARM Specification>:
> >       http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
> Please don't refer to this protocol as multiboot anywhere in grub or
> around because it's NOT multiboot and we don't want to confuse those 2
> protocols.

That's fair enough, my hope was that the docs and communal knowledge
about how to write a grub.cfg for Xen x86/multiboot could remain
unchanged for Xen on arm (e.g. by using the same multiboot1 command
names, which surely won't be reused on arm), but I can see why you would
object to that and updating 20_linux_xen to DTRT on both arches solves
the majority of that concern.

WRT to what to call it instead: I did try and design it[0] to not be Xen
specific, so it would be nice to avoid making it so in the command names
if possible. I suspect this may lead to a certain amount of
bikeshedding, if so we should just call it something Xen specific and
move on I think.

For a non-Xen specific name how about "fbm -- fdt boot module" protocol
and associated commands fbm_kernel + fbm_module?

Ian.

[0]
http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 1/3] arm64: Add Xen boot support file
@ 2015-07-16 16:46         ` Ian Campbell
  0 siblings, 0 replies; 550+ messages in thread
From: Ian Campbell @ 2015-07-16 16:46 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: grub-devel, xen-devel, stefano.stabellini, arvidjaar, jcm,
	leif.lindholm, ryan.harkin, linaro-uefi, fu.wei

On Wed, 2015-07-15 at 18:18 +0200, Vladimir 'φ-coder/phcoder' Serbinenko
wrote:
> On 13.07.2015 10:53, fu.wei@linaro.org wrote:
> > From: Fu Wei <fu.wei@linaro.org>
> > 
> > This patch adds Xen boot support file:
> > grub-core/loader/arm64/xen_boot.c
> > include/grub/arm64/xen_boot.h
> > 
> > This patch also adds commands register code and hearder file into
> > grub-core/loader/arm64/linux.c
> > 
> >   - This adds support for the Xen boot on ARM specification for arm64.
> >   - The implementation for Xen is following  <Multiboot on ARM Specification>:
> >       http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
> Please don't refer to this protocol as multiboot anywhere in grub or
> around because it's NOT multiboot and we don't want to confuse those 2
> protocols.

That's fair enough, my hope was that the docs and communal knowledge
about how to write a grub.cfg for Xen x86/multiboot could remain
unchanged for Xen on arm (e.g. by using the same multiboot1 command
names, which surely won't be reused on arm), but I can see why you would
object to that and updating 20_linux_xen to DTRT on both arches solves
the majority of that concern.

WRT to what to call it instead: I did try and design it[0] to not be Xen
specific, so it would be nice to avoid making it so in the command names
if possible. I suspect this may lead to a certain amount of
bikeshedding, if so we should just call it something Xen specific and
move on I think.

For a non-Xen specific name how about "fbm -- fdt boot module" protocol
and associated commands fbm_kernel + fbm_module?

Ian.

[0]
http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot



^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v3 0/4] arm64: Add Xen boot support (via fdt)
       [not found] <=fu.wei@linaro.org>
                   ` (9 preceding siblings ...)
  2015-07-13  8:53 ` [PATCH v2 0/3] arm64: Add multiboot support (via fdt) for Xen boot fu.wei
@ 2015-07-23  5:16 ` fu.wei
  2015-07-23  5:16   ` [PATCH v3 1/4] arm64: Add and export some accessor functions for xen boot fu.wei
                     ` (4 more replies)
  2015-08-14 12:35 ` [PATCH] acpi, apei, arm64: APEI initial support for aarch64 fu.wei
                   ` (3 subsequent siblings)
  14 siblings, 5 replies; 550+ messages in thread
From: fu.wei @ 2015-07-23  5:16 UTC (permalink / raw)
  To: grub-devel, arvidjaar, phcoder
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

  - This adds support for the Xen boot on ARM specification for arm64.

  - Add and export some accessor functions of "loaded" flag and
    grub_linux_get_fdt function in include/grub/arm64/linux.h for xen boot.

  - Introduce xen_hypervisor, xen_linux, xen_initrd and xen_xsm
    to load different binaries for xen boot.
    Introduce xen_module to load common or custom module for xen boot.

  - This Xen boot support is a separated  module for aarch64,
    but reuse the existing code of devicetree in linux module.

  - Add the support of xen_hypervisor, xen_linux and xen_initrd
    in util/grub.d/20_linux_xen.in

  - Add the introduction of all xen boot commands in docs/grub.texi

  - The example of this support is <How to boot Xen with GRUB on AArch64 the Foundation FVP model>
    https://wiki.linaro.org/LEG/Engineering/Grub2/Xen_booting_on_Foundation_FVP_model_by_GRUB

Changelog:
v3: create separate module for xen boot: xen_boot
    create separate commands for different types of module
    delete order-dependent for commands of xen module
    simplify the code

v2: remove the patches which have been accepted.
    according to Vladimir's suggestion, change the command manes
    and relevant code:
        multiboot-->xen_hypervisor
        module-->xen_module
    improve the option parsing support for xen_hypervisor/xen_module commands.
    add a patch for adding xen_hypervisor/xen_module support
    in util/grub.d/20_linux_xen.in.
    update docs/grub.texi patch for the new command names.

v1: The first version upstream patchset to grub-devel mailing list


Fu Wei (4):
  arm64: Add and export some accessor functions for xen boot
  arm64: Add xen_boot module file
  * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
  arm64: Add the introduction of xen boot commands in docs/grub.texi

 docs/grub.texi                    |  56 ++++
 grub-core/Makefile.core.def       |   7 +
 grub-core/loader/arm64/linux.c    |  13 +
 grub-core/loader/arm64/xen_boot.c | 685 ++++++++++++++++++++++++++++++++++++++
 include/grub/arm64/linux.h        |   6 +-
 util/grub.d/20_linux_xen.in       |  16 +-
 6 files changed, 779 insertions(+), 4 deletions(-)
 create mode 100644 grub-core/loader/arm64/xen_boot.c

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v3 1/4] arm64: Add and export some accessor functions for xen boot
  2015-07-23  5:16 ` [PATCH v3 0/4] arm64: Add Xen boot support (via fdt) fu.wei
@ 2015-07-23  5:16   ` fu.wei
  2015-10-29 12:03       ` Vladimir 'φ-coder/phcoder' Serbinenko
  2015-07-23  5:16   ` [PATCH v3 2/4] arm64: Add xen_boot module file fu.wei
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 550+ messages in thread
From: fu.wei @ 2015-07-23  5:16 UTC (permalink / raw)
  To: grub-devel, arvidjaar, phcoder
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

Add accessor functions of "loaded" flag in
grub-core/loader/arm64/linux.c.

Export accessor functions of "loaded" flag and
grub_linux_get_fdt function in include/grub/arm64/linux.h.

Purpose: Reuse the existing code of devicetree in linux module.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 grub-core/loader/arm64/linux.c | 13 +++++++++++++
 include/grub/arm64/linux.h     |  6 +++++-
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
index 987f5b9..cf6026e 100644
--- a/grub-core/loader/arm64/linux.c
+++ b/grub-core/loader/arm64/linux.c
@@ -48,6 +48,19 @@ static grub_addr_t initrd_end;
 static void *loaded_fdt;
 static void *fdt;
 
+/* The accessor functions for "loaded" flag */
+int
+grub_linux_get_loaded (void)
+{
+  return loaded;
+}
+
+void
+grub_linux_set_loaded (int loaded_flag)
+{
+  loaded = loaded_flag;
+}
+
 static void *
 get_firmware_fdt (void)
 {
diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h
index 65796d9..20058f3 100644
--- a/include/grub/arm64/linux.h
+++ b/include/grub/arm64/linux.h
@@ -43,10 +43,14 @@ struct grub_arm64_linux_kernel_header
 };
 
 /* Declare the functions for getting dtb and checking/booting image */
-void *grub_linux_get_fdt (void);
 grub_err_t grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header
                                         *lh);
 grub_err_t grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size,
                                        char *args);
 
+/* Export the accessor functions for gettin dtb and "loaded" flag */
+void EXPORT_FUNC (*grub_linux_get_fdt) (void);
+int EXPORT_FUNC (grub_linux_get_loaded) (void);
+void EXPORT_FUNC (grub_linux_set_loaded) (int loaded_flag);
+
 #endif /* ! GRUB_LINUX_CPU_HEADER */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v3 2/4] arm64: Add xen_boot module file
  2015-07-23  5:16 ` [PATCH v3 0/4] arm64: Add Xen boot support (via fdt) fu.wei
  2015-07-23  5:16   ` [PATCH v3 1/4] arm64: Add and export some accessor functions for xen boot fu.wei
@ 2015-07-23  5:16   ` fu.wei
  2015-10-29 14:27       ` Vladimir 'φ-coder/phcoder' Serbinenko
  2015-07-23  5:16   ` [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64 fu.wei
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 550+ messages in thread
From: fu.wei @ 2015-07-23  5:16 UTC (permalink / raw)
  To: grub-devel, arvidjaar, phcoder
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

grub-core/loader/arm64/xen_boot.c

  - This adds support for the Xen boot on ARM specification for arm64.
  - Introduce xen_hypervisor, xen_linux, xen_initrd and xen_xsm
    to load different binaries for xen boot;
    Introduce xen_module to load common or custom module for xen boot.
  - This Xen boot support is a separated  module for aarch64,
    but reuse the existing code of devicetree in linux module.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 grub-core/Makefile.core.def       |   7 +
 grub-core/loader/arm64/xen_boot.c | 685 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 692 insertions(+)

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index a6101de..796f7e9 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1648,6 +1648,13 @@ module = {
 };
 
 module = {
+  name = xen_boot;
+  common = lib/cmdline.c;
+  arm64 = loader/arm64/xen_boot.c;
+  enable = arm64;
+};
+
+module = {
   name = linux;
   x86 = loader/i386/linux.c;
   xen = loader/i386/xen.c;
diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
new file mode 100644
index 0000000..33a65dd
--- /dev/null
+++ b/grub-core/loader/arm64/xen_boot.c
@@ -0,0 +1,685 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2014  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/cache.h>
+#include <grub/charset.h>
+#include <grub/command.h>
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/fdt.h>
+#include <grub/linux.h>
+#include <grub/list.h>
+#include <grub/loader.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/cpu/linux.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/pe32.h>	/* required by struct xen_hypervisor_header */
+#include <grub/i18n.h>
+#include <grub/lib/cmdline.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define XEN_HYPERVISOR_NAME  "xen_hypervisor"
+
+#define MODULE_DEFAULT_ALIGN  (0x0)
+#define MODULE_IMAGE_MIN_ALIGN  MODULE_DEFAULT_ALIGN
+#define MODULE_INITRD_MIN_ALIGN  MODULE_DEFAULT_ALIGN
+#define MODULE_XSM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
+#define MODULE_CUSTOM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
+
+/* #define MODULE_IMAGE_COMPATIBLE  "xen,linux-image\0xen,module"
+#define MODULE_INITRD_COMPATIBLE  "xen,linux-image\0xen,module"
+#define MODULE_XSM_COMPATIBLE  "xen,xsm-policy\0xen,module"
+#define MODULE_CUSTOM_COMPATIBLE  "xen,module" */
+#define MODULE_IMAGE_COMPATIBLE  "multiboot,kernel\0multiboot,module"
+#define MODULE_INITRD_COMPATIBLE  "multiboot,ramdisk\0multiboot,module"
+#define MODULE_XSM_COMPATIBLE  "xen,xsm-policy\0multiboot,module"
+#define MODULE_CUSTOM_COMPATIBLE  "multiboot,module"
+
+/* This maximum size is defined in Power.org ePAPR V1.1
+ * https://www.power.org/documentation/epapr-version-1-1/
+ * 2.2.1.1 Node Name Requirements
+ * node-name@unit-address
+ * 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
+ */
+#define FDT_NODE_NAME_MAX_SIZE  (49)
+
+#define ARG_SHIFT(argc, argv) \
+  do { \
+    (argc)--; \
+    (argv)++; \
+  } while (0)
+
+struct compat_string_struct
+{
+  grub_size_t size;
+  const char *compat_string;
+};
+typedef struct compat_string_struct compat_string_struct_t;
+#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
+
+enum module_type
+{
+  MODULE_IMAGE,
+  MODULE_INITRD,
+  MODULE_XSM,
+  MODULE_CUSTOM
+};
+typedef enum module_type module_type_t;
+
+struct fdt_node_info
+{
+  module_type_t type;
+
+  const char *compat_string;
+  grub_size_t compat_string_size;
+};
+
+struct xen_hypervisor_header
+{
+  struct grub_arm64_linux_kernel_header efi_head;
+
+  /* This is always PE\0\0.  */
+  grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
+  /* The COFF file header.  */
+  struct grub_pe32_coff_header coff_header;
+  /* The Optional header.  */
+  struct grub_pe64_optional_header optional_header;
+};
+
+struct xen_boot_binary
+{
+  struct xen_boot_binary *next;
+  struct xen_boot_binary **prev;
+  const char *name;
+
+  grub_addr_t start;
+  grub_size_t size;
+  grub_size_t align;
+
+  char *cmdline;
+  int cmdline_size;
+
+  struct fdt_node_info node_info;
+};
+
+static grub_dl_t my_mod;
+
+static struct xen_boot_binary *xen_hypervisor;
+static struct xen_boot_binary *module_head;
+static const grub_size_t module_default_align[] = {
+  MODULE_IMAGE_MIN_ALIGN,
+  MODULE_INITRD_MIN_ALIGN,
+  MODULE_XSM_MIN_ALIGN,
+  MODULE_CUSTOM_MIN_ALIGN
+};
+
+static void *xen_boot_fdt;
+static const compat_string_struct_t default_compat_string[] = {
+  FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
+  FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
+  FDT_COMPATIBLE (MODULE_XSM_COMPATIBLE),
+  FDT_COMPATIBLE (MODULE_CUSTOM_COMPATIBLE)
+};
+
+static __inline grub_addr_t
+xen_boot_address_align (grub_addr_t start, grub_size_t align)
+{
+  return (align ? (ALIGN_UP (start, align)) : start);
+}
+
+/* Parse the option of xen_module command. For now, we support
+   (1) --type <the compatible stream>
+   We also set up the type of module in this function.
+   If there are some "--type" options in the command line,
+   we make a custom compatible stream in this function. */
+static grub_err_t
+set_module_type (grub_command_t cmd, struct xen_boot_binary *module,
+		 int argc, char *argv[], int *file_name_index)
+{
+  char **compat_string_temp_array;
+  grub_size_t total_size = 0;
+  int num_types = 0, i;
+  char *temp = NULL;
+
+  *file_name_index = 0;
+
+  if (!grub_strcmp (cmd->name, "xen_linux"))
+    module->node_info.type = MODULE_IMAGE;
+  else if (!grub_strcmp (cmd->name, "xen_initrd"))
+    module->node_info.type = MODULE_INITRD;
+  else if (!grub_strcmp (cmd->name, "xen_xsm"))
+    module->node_info.type = MODULE_XSM;
+  else if (!grub_strcmp (cmd->name, "xen_module"))
+    module->node_info.type = MODULE_CUSTOM;
+
+  /* if there are some options we need to process. */
+  if (module->node_info.type == MODULE_CUSTOM)
+    {
+      compat_string_temp_array =
+	(char **) grub_zalloc (sizeof (char *) * argc);
+      if (!compat_string_temp_array)
+	return grub_errno;
+      /* the module type is set by "--type"(MODULE_CUSTOM) */
+      while (argc > 2 && !grub_strcmp (argv[0], "--type"))
+	{
+	  module->node_info.type = MODULE_CUSTOM;
+	  ARG_SHIFT (argc, argv);
+	  total_size += grub_strlen (argv[0]) + 1;
+	  compat_string_temp_array[num_types++] = argv[0];
+	  ARG_SHIFT (argc, argv);
+	  (*file_name_index) += 2;
+	}
+
+      if (total_size)
+	{
+	  module->node_info.compat_string = temp =
+	    (char *) grub_zalloc (total_size);
+	  if (!temp)
+	    {
+	      grub_free (compat_string_temp_array);
+	      return grub_errno;
+	    }
+
+	  module->node_info.compat_string_size = total_size;
+	  for (i = 0; num_types > 0; num_types--, i++, temp++)
+	    {
+	      grub_strcpy (temp, compat_string_temp_array[i]);
+	      temp += grub_strlen (compat_string_temp_array[i]);
+	    }
+	}
+      else
+	{
+	  module->node_info.compat_string =
+	    default_compat_string[MODULE_CUSTOM].compat_string;
+	  module->node_info.compat_string_size =
+	    default_compat_string[MODULE_CUSTOM].size;
+	}
+
+      grub_free (compat_string_temp_array);
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+prepare_xen_hypervisor_params (void)
+{
+  int chosen_node = 0;
+  int retval;
+
+  xen_boot_fdt = grub_linux_get_fdt ();
+  if (!xen_boot_fdt)
+    return grub_error (GRUB_ERR_IO, "failed to get FDT");
+
+  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
+  if (chosen_node < 0)
+    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
+  if (chosen_node < 1)
+    return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
+
+  grub_dprintf ("xen_loader",
+		"Xen Hypervisor cmdline : %s @ %p size:%d\n",
+		xen_hypervisor->cmdline, xen_hypervisor->cmdline,
+		xen_hypervisor->cmdline_size);
+
+  retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
+			      xen_hypervisor->cmdline,
+			      xen_hypervisor->cmdline_size);
+  if (retval)
+    return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+prepare_xen_module_params (struct xen_boot_binary *module)
+{
+  int retval, chosen_node = 0, module_node = 0;
+  char module_name[FDT_NODE_NAME_MAX_SIZE];
+
+  retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
+			  xen_boot_address_align (module->start,
+						  module->align));
+  grub_dprintf ("xen_loader", "Module node name %s \n", module_name);
+
+  if (retval < (int) sizeof ("module@"))
+    return grub_error (GRUB_ERR_IO, N_("failed to get FDT"));
+
+  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
+  if (chosen_node < 0)
+    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
+  if (chosen_node < 1)
+    return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
+
+  module_node =
+    grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
+  if (module_node < 0)
+    module_node =
+      grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
+
+  retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
+			      module->node_info.compat_string,
+			      (grub_uint32_t) module->
+			      node_info.compat_string_size);
+  if (retval)
+    return grub_error (GRUB_ERR_IO, N_("failed to update FDT"));
+
+  grub_dprintf ("xen_loader", "Module %s compatible = %s size = 0x%lx\n",
+		module->name, module->node_info.compat_string,
+		module->node_info.compat_string_size);
+
+  retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
+			       xen_boot_address_align (module->start,
+						       module->align),
+			       module->size);
+  if (retval)
+    return grub_error (GRUB_ERR_IO, N_("failed to update FDT"));
+
+  if (module->cmdline && module->cmdline_size > 0)
+    {
+      grub_dprintf ("xen_loader",
+		    "Module %s cmdline : %s @ %p size:%d\n", module->name,
+		    module->cmdline, module->cmdline, module->cmdline_size);
+
+      retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
+				  module->cmdline, module->cmdline_size + 1);
+      if (retval)
+	return grub_error (GRUB_ERR_IO, "failed to update FDT");
+    }
+  else
+    {
+      grub_dprintf ("xen_loader", "Module %s has not bootargs!\n",
+		    module->name);
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+install_all_params (void)
+{
+  grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
+  grub_efi_boot_services_t *b;
+  grub_efi_status_t status;
+
+  b = grub_efi_system_table->boot_services;
+  status = b->install_configuration_table (&fdt_guid, xen_boot_fdt);
+  if (status != GRUB_EFI_SUCCESS)
+    return grub_error (GRUB_ERR_IO, "failed to install FDT");
+
+  grub_dprintf ("xen_loader",
+		"Installed/updated FDT configuration table @ %p\n",
+		xen_boot_fdt);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+clean_all_params (void)
+{
+  if (xen_boot_fdt)
+    {
+      grub_efi_free_pages ((grub_efi_physical_address_t) xen_boot_fdt,
+			   BYTES_TO_PAGES (grub_fdt_get_totalsize
+					   (xen_boot_fdt)));
+      xen_boot_fdt = NULL;
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+finalize_params_xen_boot (void)
+{
+  struct xen_boot_binary *module;
+
+  if (xen_hypervisor)
+    {
+      if (prepare_xen_hypervisor_params () != GRUB_ERR_NONE)
+	goto fail;
+    }
+  else
+    {
+      grub_dprintf ("xen_loader", "Failed to get Xen Hypervisor info!\n");
+      goto fail;
+    }
+
+  /* Set module params info */
+  FOR_LIST_ELEMENTS (module, module_head)
+  {
+    if (module->start && module->size > 0)
+      {
+	grub_dprintf ("xen_loader", "Module %s @ 0x%lx size:0x%lx\n",
+		      module->name,
+		      xen_boot_address_align (module->start, module->align),
+		      module->size);
+	if (prepare_xen_module_params (module) != GRUB_ERR_NONE)
+	  goto fail;
+      }
+    else
+      {
+	grub_dprintf ("xen_loader", "Module info error: %s!\n", module->name);
+	goto fail;
+      }
+  }
+
+  if (install_all_params () == GRUB_ERR_NONE)
+    return GRUB_ERR_NONE;
+
+fail:
+  clean_all_params ();
+
+  return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
+}
+
+
+static grub_err_t
+xen_boot (void)
+{
+  grub_err_t err = finalize_params_xen_boot ();
+  if (err)
+    return err;
+
+  return grub_arm64_uefi_boot_image (xen_hypervisor->start,
+				     xen_hypervisor->size,
+				     xen_hypervisor->cmdline);
+}
+
+static void
+single_binary_unload (struct xen_boot_binary *binary)
+{
+  if (!binary)
+    return;
+
+  if (binary->start && binary->size > 0)
+    {
+      grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
+			   BYTES_TO_PAGES (binary->size + binary->align));
+    }
+
+  if (binary->cmdline && binary->cmdline_size > 0)
+    {
+      grub_free (binary->cmdline);
+      grub_dprintf ("xen_loader",
+		    "Module %s cmdline memory free @ %p size: %d\n",
+		    binary->name, binary->cmdline, binary->cmdline_size);
+    }
+
+  if (binary->node_info.type == MODULE_CUSTOM)
+    grub_free ((void *) binary->node_info.compat_string);
+
+  if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
+    grub_list_remove (GRUB_AS_LIST (binary));
+
+  grub_dprintf ("xen_loader",
+		"Module %s struct memory free @ %p size: 0x%lx\n",
+		binary->name, binary, sizeof (binary));
+  grub_free (binary);
+
+  return;
+}
+
+static void
+all_binaries_unload (void)
+{
+  struct xen_boot_binary *binary;
+
+  FOR_LIST_ELEMENTS (binary, module_head)
+  {
+    single_binary_unload (binary);
+  }
+
+  if (xen_hypervisor)
+    single_binary_unload (xen_hypervisor);
+
+  return;
+}
+
+static grub_err_t
+xen_unload (void)
+{
+  grub_linux_set_loaded (0);
+  all_binaries_unload ();
+  clean_all_params ();
+  grub_dl_unref (my_mod);
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
+		      int argc, char *argv[])
+{
+  binary->size = grub_file_size (file);
+  grub_dprintf ("xen_loader", "Xen_boot %s file size: 0x%lx\n",
+		binary->name, binary->size);
+
+  binary->start = (grub_addr_t) grub_efi_allocate_pages (0,
+							 (BYTES_TO_PAGES
+							  (binary->size +
+							   binary->align)));
+  if (!binary->start)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+      return;
+    }
+
+  grub_dprintf ("xen_loader", "Xen_boot %s numpages: 0x%lx\n",
+		binary->name, BYTES_TO_PAGES (binary->size + binary->align));
+
+  if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
+							     binary->align),
+		      binary->size) != (grub_ssize_t) binary->size)
+    {
+      single_binary_unload (binary);
+      grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
+      return;
+    }
+
+  if (argc > 1)
+    {
+      binary->cmdline_size = grub_loader_cmdline_size (argc - 1, argv + 1);
+      binary->cmdline = grub_zalloc (binary->cmdline_size);
+      if (!binary->cmdline)
+	{
+	  single_binary_unload (binary);
+	  grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+	  return;
+	}
+      grub_create_loader_cmdline (argc - 1, argv + 1, binary->cmdline,
+				  binary->cmdline_size);
+      grub_dprintf ("xen_loader",
+		    "Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
+		    binary->cmdline, binary->cmdline, binary->cmdline_size);
+    }
+  else
+    {
+      binary->cmdline_size = 0;
+      binary->cmdline = NULL;
+    }
+
+  grub_errno = GRUB_ERR_NONE;
+  return;
+}
+
+static grub_err_t
+grub_cmd_xen_module (grub_command_t cmd, int argc, char *argv[])
+{
+
+  struct xen_boot_binary *module = NULL;
+  int file_name_index = 0;
+  grub_file_t file = 0;
+
+  if (!argc)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+      goto fail;
+    }
+
+  if (!grub_linux_get_loaded ())
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT,
+		  N_("you need to load the Xen Hypervisor first"));
+      goto fail;
+    }
+
+  module =
+    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
+  if (!module)
+    return grub_errno;
+
+  /* process all the options and get module type */
+  if (set_module_type (cmd, module, argc, argv, &file_name_index) !=
+      GRUB_ERR_NONE)
+    goto fail;
+  switch (module->node_info.type)
+    {
+    case MODULE_IMAGE:
+    case MODULE_INITRD:
+    case MODULE_XSM:
+      module->node_info.compat_string =
+	default_compat_string[module->node_info.type].compat_string;
+      module->node_info.compat_string_size =
+	default_compat_string[module->node_info.type].size;
+      break;
+
+    case MODULE_CUSTOM:
+      /* we have set the node_info in set_module_type */
+      break;
+
+    default:
+      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
+    }
+  module->name = module->node_info.compat_string;
+  module->align = module_default_align[module->node_info.type];
+
+  grub_dprintf ("xen_loader", "Init %s module and node info:\n"
+		"compatible %s\ncompat_string_size 0x%lx\n",
+		module->name, module->node_info.compat_string,
+		module->node_info.compat_string_size);
+
+  file = grub_file_open (argv[file_name_index]);
+  if (!file)
+    goto fail;
+
+  xen_boot_binary_load (module, file, argc - file_name_index,
+			argv + file_name_index);
+  if (grub_errno == GRUB_ERR_NONE)
+    grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
+
+fail:
+  if (file)
+    grub_file_close (file);
+  if (grub_errno != GRUB_ERR_NONE)
+    single_binary_unload (module);
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
+			 int argc, char *argv[])
+{
+  struct xen_hypervisor_header sh;
+  grub_file_t file = NULL;
+
+  grub_dl_ref (my_mod);
+
+  if (!argc)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+      goto fail;
+    }
+
+  file = grub_file_open (argv[0]);
+  if (!file)
+    goto fail;
+
+  if (grub_file_read (file, &sh, sizeof (sh)) != (long) sizeof (sh))
+    goto fail;
+  if (grub_arm64_uefi_check_image
+      ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
+    goto fail;
+  grub_file_seek (file, 0);
+
+  /* if another module has called grub_loader_set,
+     we need to make sure that another module is unloaded properly */
+  grub_loader_unset ();
+
+  xen_hypervisor =
+    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
+  if (!xen_hypervisor)
+    return grub_errno;
+
+  xen_hypervisor->name = XEN_HYPERVISOR_NAME;
+  xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
+
+  xen_boot_binary_load (xen_hypervisor, file, argc, argv);
+  if (grub_errno == GRUB_ERR_NONE)
+    {
+      grub_loader_set (xen_boot, xen_unload, 0);
+      grub_linux_set_loaded (1);
+    }
+
+fail:
+  if (file)
+    grub_file_close (file);
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_linux_set_loaded (0);
+      all_binaries_unload ();
+      grub_dl_unref (my_mod);
+    }
+
+  return grub_errno;
+}
+
+static grub_command_t cmd_xen_hypervisor, cmd_xen_module;
+static grub_command_t cmd_xen_linux, cmd_xen_initrd, cmd_xen_xsm;
+
+GRUB_MOD_INIT (xen_boot)
+{
+  cmd_xen_hypervisor =
+    grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
+			   N_("Load a xen hypervisor."));
+  cmd_xen_linux =
+    grub_register_command ("xen_linux", grub_cmd_xen_module, 0,
+			   N_("Load a xen linux kernel for dom0."));
+  cmd_xen_initrd =
+    grub_register_command ("xen_initrd", grub_cmd_xen_module, 0,
+			   N_("Load a xen initrd for dom0."));
+  cmd_xen_xsm =
+    grub_register_command ("xen_xsm", grub_cmd_xen_module, 0,
+			   N_("Load a xen security module."));
+  cmd_xen_module =
+    grub_register_command ("xen_module", grub_cmd_xen_module, 0,
+			   N_("Load a xen module."));
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI (xen_boot)
+{
+  grub_unregister_command (cmd_xen_hypervisor);
+  grub_unregister_command (cmd_xen_linux);
+  grub_unregister_command (cmd_xen_initrd);
+  grub_unregister_command (cmd_xen_xsm);
+  grub_unregister_command (cmd_xen_module);
+}
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
  2015-07-23  5:16 ` [PATCH v3 0/4] arm64: Add Xen boot support (via fdt) fu.wei
  2015-07-23  5:16   ` [PATCH v3 1/4] arm64: Add and export some accessor functions for xen boot fu.wei
  2015-07-23  5:16   ` [PATCH v3 2/4] arm64: Add xen_boot module file fu.wei
@ 2015-07-23  5:16   ` fu.wei
  2015-10-29 15:25       ` Vladimir 'φ-coder/phcoder' Serbinenko
  2015-07-23  5:16   ` [PATCH v3 4/4] arm64: Add the introduction of xen boot commands in docs/grub.texi fu.wei
  2015-08-04  8:34   ` [PATCH v3 0/4] arm64: Add Xen boot support (via fdt) Fu Wei
  4 siblings, 1 reply; 550+ messages in thread
From: fu.wei @ 2015-07-23  5:16 UTC (permalink / raw)
  To: grub-devel, arvidjaar, phcoder
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patch adds the support of boot command on aarch64 for XEN:
    xen_hypervisor
    xen_linux
    xen_initrd

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 util/grub.d/20_linux_xen.in | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
index f532fb9..49aa709 100644
--- a/util/grub.d/20_linux_xen.in
+++ b/util/grub.d/20_linux_xen.in
@@ -120,16 +120,16 @@ linux_entry ()
         else
             xen_rm_opts="no-real-mode edd=off"
         fi
-	multiboot	${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
+	${multiboot_cmd}	${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
 	echo	'$(echo "$lmessage" | grub_quote)'
-	module	${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
+	${module_linux_cmd}	${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
 EOF
   if test -n "${initrd}" ; then
     # TRANSLATORS: ramdisk isn't identifier. Should be translated.
     message="$(gettext_printf "Loading initial ramdisk ...")"
     sed "s/^/$submenu_indentation/" << EOF
 	echo	'$(echo "$message" | grub_quote)'
-	module	--nounzip   ${rel_dirname}/${initrd}
+	${module_initrd_cmd}  ${rel_dirname}/${initrd}
 EOF
   fi
   sed "s/^/$submenu_indentation/" << EOF
@@ -185,6 +185,16 @@ case "$machine" in
     *) GENKERNEL_ARCH="$machine" ;;
 esac
 
+if [ "x$machine" != xaarch64 ]; then
+	multiboot_cmd="multiboot"
+	module_linux_cmd="module"
+	module_initrd_cmd="module --nounzip"
+else
+	multiboot_cmd="xen_hypervisor"
+	module_linux_cmd="xen_linux"
+	module_initrd_cmd="xen_initrd"
+fi
+
 # Extra indentation to add to menu entries in a submenu. We're not in a submenu
 # yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
 submenu_indentation=""
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v3 4/4] arm64: Add the introduction of xen boot commands in docs/grub.texi
  2015-07-23  5:16 ` [PATCH v3 0/4] arm64: Add Xen boot support (via fdt) fu.wei
                     ` (2 preceding siblings ...)
  2015-07-23  5:16   ` [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64 fu.wei
@ 2015-07-23  5:16   ` fu.wei
  2015-08-04  8:34   ` [PATCH v3 0/4] arm64: Add Xen boot support (via fdt) Fu Wei
  4 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-07-23  5:16 UTC (permalink / raw)
  To: grub-devel, arvidjaar, phcoder
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

    xen_hypervisor
    xen_linux
    xen_initrd
    xen_xsm
    xen_module

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 docs/grub.texi | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/docs/grub.texi b/docs/grub.texi
index b9f41a7..e94b03c 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3839,6 +3839,12 @@ you forget a command, you can run the command @command{help}
 @comment * vbeinfo::                     List available video modes
 * verify_detached::             Verify detached digital signature
 * videoinfo::                   List available video modes
+@comment * xen_*::   Xen boot commands, for arm64 only
+* xen_hypervisor::              Load xen hypervisor binary on arm64
+* xen_linux::                   Load dom0 kernel for xen hypervisor on arm64
+* xen_initrd::                  Load dom0 initrd for xen hypervisor on arm64
+* xen_xsm::                     Load xen security module for xen hypervisor on arm64
+* xen_module::                  Load custom module for xen hypervisor on arm64
 @end menu
 
 
@@ -5102,6 +5108,56 @@ successfully.  If validation fails, it is set to a non-zero value.
 List available video modes. If resolution is given, show only matching modes.
 @end deffn
 
+@node xen_hypervisor
+@subsection xen_hypervisor
+
+@deffn Command xen_hypervisor file  [arguments] @dots{}
+Load a Xen hypervisor binary from @var{file}. The rest of the
+line is passed verbatim as the @dfn{kernel command-line}. Any Xen module must
+be reloaded after using this command (@pxref{xen_module}).
+This command is only available on ARM64 systems.
+@end deffn
+
+@node xen_linux
+@subsection xen_linux
+
+@deffn Command xen_linux file [arguments]
+Load a dom0 kernel image for xen hypervisor binary. The rest of the
+line is passed verbatim as the module command line.
+This command is only available on ARM64 systems.
+@end deffn
+
+@node xen_initrd
+@subsection xen_initrd
+
+@deffn Command xen_initrd file
+Load a dom0 initrd image for xen hypervisor binary.
+This command is only available on ARM64 systems.
+@end deffn
+
+@node xen_xsm
+@subsection xen_xsm
+
+@deffn Command xen_xsm file
+Load a xen security module for xen hypervisor binary.
+This command is only available on ARM64 systems.
+@end deffn
+
+
+@node xen_module
+@subsection xen_module
+
+@deffn Command xen_module [--type <compatible stream>] file [arguments]
+Load a custom module for xen hypervisor binary. The rest of the
+line is passed verbatim as the module command line.
+This command is only available on ARM64 systems.
+
+--type is an option which allow the module command to take "compatible" string.
+This would override default compatible string:"xen,module". The rest of the
+line is passed verbatim as the module command line.
+This command is only available on ARM64 systems.
+@end deffn
+
 @node Networking commands
 @section The list of networking commands
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 6/8] ACPI: add GTDT table parse driver into ACPI driver
@ 2015-07-23  8:32       ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-23  8:32 UTC (permalink / raw)
  To: Rafael Wysocki
  Cc: devicetree, linux-watchdog, Linaro ACPI Mailman List,
	Suravee Suthikulpanit, linux-kernel, G Gregory, linux-doc,
	Al Stone, Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Guenter Roeck, Vipul Gandhi, Wim Van Sebroeck, Jon Masters,
	Leo Duran, Jon Corbet, Mark Rutland, Catalin Marinas,
	Will Deacon, dyoung, panand

Hi Rafael,

Any suggestion on the  GTDT patch of this patch set?
Please let me know if I can do anything to improve it.
If it is OK for you, could you add a "Acked-by:"?

Great thanks for your time! :-)


On 23 June 2015 at 23:59,  <fu.wei@linaro.org> wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> This driver adds support for parsing SBSA Generic Watchdog
> Structure in GTDT, and creating a platform device with that
> information. This allows the operating system to obtain device
> data from the resource of platform device.
>
> The platform device named "sbsa-gwdt" can be used by the
> ARM SBSA Generic Watchdog driver.
>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> ---
>  drivers/acpi/Kconfig  |   9 ++++
>  drivers/acpi/Makefile |   1 +
>  drivers/acpi/gtdt.c   | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 147 insertions(+)
>  create mode 100644 drivers/acpi/gtdt.c
>
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index 1bbaa3d..e125698 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -433,4 +433,13 @@ config XPOWER_PMIC_OPREGION
>
>  endif
>
> +config ACPI_GTDT
> +       bool "ACPI GTDT Support"
> +       depends on ARM64
> +       help
> +         GTDT (Generic Timer Description Table) provides information
> +         for per-processor timers and Platform (memory-mapped) timers
> +         for ARM platforms. Select this option to provide information
> +         needed for the timers init.
> +
>  endif  # ACPI
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index 431e587..2c5a194 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -96,3 +96,4 @@ obj-$(CONFIG_ACPI_EXTLOG)     += acpi_extlog.o
>  obj-$(CONFIG_PMIC_OPREGION)    += pmic/intel_pmic.o
>  obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
>  obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
> +obj-$(CONFIG_ACPI_GTDT)                += gtdt.o
> diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
> new file mode 100644
> index 0000000..a92abf2
> --- /dev/null
> +++ b/drivers/acpi/gtdt.c
> @@ -0,0 +1,137 @@
> +/*
> + * ARM Specific GTDT table Support
> + *
> + * Copyright (C) 2015, Linaro Ltd.
> + * Author: Fu Wei <fu.wei@linaro.org>
> + *         Hanjun Guo <hanjun.guo@linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/device.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
> +{
> +       int trigger, polarity;
> +
> +       if (!interrupt)
> +               return 0;
> +
> +       trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
> +                       : ACPI_LEVEL_SENSITIVE;
> +
> +       polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
> +                       : ACPI_ACTIVE_HIGH;
> +
> +       return acpi_register_gsi(NULL, interrupt, trigger, polarity);
> +}
> +
> +/*
> + * Initialize a SBSA generic Watchdog platform device info from GTDT
> + * According to SBSA specification the size of refresh and control
> + * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
> + */
> +static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
> +                                       int index)
> +{
> +       struct platform_device *pdev;
> +       int irq = map_generic_timer_interrupt(wd->timer_interrupt,
> +                                             wd->timer_flags);
> +       struct resource res[] = {
> +               DEFINE_RES_IRQ_NAMED(irq, "ws0"),
> +               DEFINE_RES_MEM_NAMED(wd->refresh_frame_address, SZ_4K,
> +                                    "refresh"),
> +               DEFINE_RES_MEM_NAMED(wd->control_frame_address, SZ_4K,
> +                                    "control"),
> +       };
> +
> +       pr_debug("GTDT: a Watchdog GT(0x%llx/0x%llx gsi:%u flags:0x%x)\n",
> +                wd->refresh_frame_address, wd->control_frame_address,
> +                wd->timer_interrupt, wd->timer_flags);
> +
> +       if (!(wd->refresh_frame_address &&
> +             wd->control_frame_address &&
> +             wd->timer_interrupt)) {
> +               pr_err("GTDT: failed geting the device info.\n");
> +               return -EINVAL;
> +       }
> +
> +       if (irq < 0) {
> +               pr_err("GTDT: failed to register GSI of the Watchdog GT.\n");
> +               return -EINVAL;
> +       }
> +
> +       /*
> +        * Add a platform device named "sbsa-gwdt" to match the platform driver.
> +        * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
> +        * The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get device
> +        * info below by matching this name.
> +        */
> +       pdev = platform_device_register_simple("sbsa-gwdt", index, res,
> +                                              ARRAY_SIZE(res));
> +       if (IS_ERR(pdev)) {
> +               acpi_unregister_gsi(wd->timer_interrupt);
> +               return PTR_ERR(pdev);
> +       }
> +
> +       return 0;
> +}
> +
> +static int __init gtdt_platform_timer_parse(struct acpi_table_header *table)
> +{
> +       struct acpi_gtdt_header *header;
> +       struct acpi_table_gtdt *gtdt;
> +       void *gtdt_subtable;
> +       int i, gwdt_index;
> +       int ret = 0;
> +
> +       if (table->revision < 2) {
> +               pr_warn("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 = 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;
> +}
> +
> +static int __init gtdt_platform_timer_init(void)
> +{
> +       if (acpi_disabled)
> +               return 0;
> +
> +       return acpi_table_parse(ACPI_SIG_GTDT, gtdt_platform_timer_parse);
> +}
> +
> +device_initcall(gtdt_platform_timer_init);
> --
> 1.9.1
>



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 6/8] ACPI: add GTDT table parse driver into ACPI driver
@ 2015-07-23  8:32       ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-23  8:32 UTC (permalink / raw)
  To: Rafael Wysocki
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA, Linaro ACPI Mailman List,
	Suravee Suthikulpanit, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	G Gregory, linux-doc-u79uwXL29TY76Z2rM5mHXA, Al Stone,
	Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Guenter Roeck, Vipul Gandhi, Wim Van Sebroeck, Jon Masters,
	Leo Duran, Jon Corbet, Mark Rutland, Catalin Marinas,
	Will Deacon, dyoung-H+wXaHxf7aLQT0dZR+AlfA,
	panand-H+wXaHxf7aLQT0dZR+AlfA

Hi Rafael,

Any suggestion on the  GTDT patch of this patch set?
Please let me know if I can do anything to improve it.
If it is OK for you, could you add a "Acked-by:"?

Great thanks for your time! :-)


On 23 June 2015 at 23:59,  <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> This driver adds support for parsing SBSA Generic Watchdog
> Structure in GTDT, and creating a platform device with that
> information. This allows the operating system to obtain device
> data from the resource of platform device.
>
> The platform device named "sbsa-gwdt" can be used by the
> ARM SBSA Generic Watchdog driver.
>
> Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Signed-off-by: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>  drivers/acpi/Kconfig  |   9 ++++
>  drivers/acpi/Makefile |   1 +
>  drivers/acpi/gtdt.c   | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 147 insertions(+)
>  create mode 100644 drivers/acpi/gtdt.c
>
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index 1bbaa3d..e125698 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -433,4 +433,13 @@ config XPOWER_PMIC_OPREGION
>
>  endif
>
> +config ACPI_GTDT
> +       bool "ACPI GTDT Support"
> +       depends on ARM64
> +       help
> +         GTDT (Generic Timer Description Table) provides information
> +         for per-processor timers and Platform (memory-mapped) timers
> +         for ARM platforms. Select this option to provide information
> +         needed for the timers init.
> +
>  endif  # ACPI
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index 431e587..2c5a194 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -96,3 +96,4 @@ obj-$(CONFIG_ACPI_EXTLOG)     += acpi_extlog.o
>  obj-$(CONFIG_PMIC_OPREGION)    += pmic/intel_pmic.o
>  obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
>  obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
> +obj-$(CONFIG_ACPI_GTDT)                += gtdt.o
> diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
> new file mode 100644
> index 0000000..a92abf2
> --- /dev/null
> +++ b/drivers/acpi/gtdt.c
> @@ -0,0 +1,137 @@
> +/*
> + * ARM Specific GTDT table Support
> + *
> + * Copyright (C) 2015, Linaro Ltd.
> + * Author: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> + *         Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/device.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
> +{
> +       int trigger, polarity;
> +
> +       if (!interrupt)
> +               return 0;
> +
> +       trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
> +                       : ACPI_LEVEL_SENSITIVE;
> +
> +       polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
> +                       : ACPI_ACTIVE_HIGH;
> +
> +       return acpi_register_gsi(NULL, interrupt, trigger, polarity);
> +}
> +
> +/*
> + * Initialize a SBSA generic Watchdog platform device info from GTDT
> + * According to SBSA specification the size of refresh and control
> + * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
> + */
> +static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
> +                                       int index)
> +{
> +       struct platform_device *pdev;
> +       int irq = map_generic_timer_interrupt(wd->timer_interrupt,
> +                                             wd->timer_flags);
> +       struct resource res[] = {
> +               DEFINE_RES_IRQ_NAMED(irq, "ws0"),
> +               DEFINE_RES_MEM_NAMED(wd->refresh_frame_address, SZ_4K,
> +                                    "refresh"),
> +               DEFINE_RES_MEM_NAMED(wd->control_frame_address, SZ_4K,
> +                                    "control"),
> +       };
> +
> +       pr_debug("GTDT: a Watchdog GT(0x%llx/0x%llx gsi:%u flags:0x%x)\n",
> +                wd->refresh_frame_address, wd->control_frame_address,
> +                wd->timer_interrupt, wd->timer_flags);
> +
> +       if (!(wd->refresh_frame_address &&
> +             wd->control_frame_address &&
> +             wd->timer_interrupt)) {
> +               pr_err("GTDT: failed geting the device info.\n");
> +               return -EINVAL;
> +       }
> +
> +       if (irq < 0) {
> +               pr_err("GTDT: failed to register GSI of the Watchdog GT.\n");
> +               return -EINVAL;
> +       }
> +
> +       /*
> +        * Add a platform device named "sbsa-gwdt" to match the platform driver.
> +        * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
> +        * The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get device
> +        * info below by matching this name.
> +        */
> +       pdev = platform_device_register_simple("sbsa-gwdt", index, res,
> +                                              ARRAY_SIZE(res));
> +       if (IS_ERR(pdev)) {
> +               acpi_unregister_gsi(wd->timer_interrupt);
> +               return PTR_ERR(pdev);
> +       }
> +
> +       return 0;
> +}
> +
> +static int __init gtdt_platform_timer_parse(struct acpi_table_header *table)
> +{
> +       struct acpi_gtdt_header *header;
> +       struct acpi_table_gtdt *gtdt;
> +       void *gtdt_subtable;
> +       int i, gwdt_index;
> +       int ret = 0;
> +
> +       if (table->revision < 2) {
> +               pr_warn("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 = 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;
> +}
> +
> +static int __init gtdt_platform_timer_init(void)
> +{
> +       if (acpi_disabled)
> +               return 0;
> +
> +       return acpi_table_parse(ACPI_SIG_GTDT, gtdt_platform_timer_parse);
> +}
> +
> +device_initcall(gtdt_platform_timer_init);
> --
> 1.9.1
>



-- 
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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v6 6/8] ACPI: add GTDT table parse driver into ACPI driver
@ 2015-07-23  8:32       ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-23  8:32 UTC (permalink / raw)
  To: Rafael Wysocki
  Cc: devicetree, linux-watchdog, Linaro ACPI Mailman List,
	Suravee Suthikulpanit, linux-kernel, G Gregory, linux-doc,
	Al Stone, Hanjun Guo, Timur Tabi, Ashwin Chaugule, Arnd Bergmann,
	Guenter Roeck, Vipul Gandhi, Wim Van Sebroeck, Jon Masters,
	Leo Duran, Jon Corbet, Mark Rutland, Catalin Marinas,
	Will Deacon, dyoung, panand

Hi Rafael,

Any suggestion on the  GTDT patch of this patch set?
Please let me know if I can do anything to improve it.
If it is OK for you, could you add a "Acked-by:"?

Great thanks for your time! :-)


On 23 June 2015 at 23:59,  <fu.wei@linaro.org> wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> This driver adds support for parsing SBSA Generic Watchdog
> Structure in GTDT, and creating a platform device with that
> information. This allows the operating system to obtain device
> data from the resource of platform device.
>
> The platform device named "sbsa-gwdt" can be used by the
> ARM SBSA Generic Watchdog driver.
>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> ---
>  drivers/acpi/Kconfig  |   9 ++++
>  drivers/acpi/Makefile |   1 +
>  drivers/acpi/gtdt.c   | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 147 insertions(+)
>  create mode 100644 drivers/acpi/gtdt.c
>
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index 1bbaa3d..e125698 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -433,4 +433,13 @@ config XPOWER_PMIC_OPREGION
>
>  endif
>
> +config ACPI_GTDT
> +       bool "ACPI GTDT Support"
> +       depends on ARM64
> +       help
> +         GTDT (Generic Timer Description Table) provides information
> +         for per-processor timers and Platform (memory-mapped) timers
> +         for ARM platforms. Select this option to provide information
> +         needed for the timers init.
> +
>  endif  # ACPI
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index 431e587..2c5a194 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -96,3 +96,4 @@ obj-$(CONFIG_ACPI_EXTLOG)     += acpi_extlog.o
>  obj-$(CONFIG_PMIC_OPREGION)    += pmic/intel_pmic.o
>  obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
>  obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
> +obj-$(CONFIG_ACPI_GTDT)                += gtdt.o
> diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
> new file mode 100644
> index 0000000..a92abf2
> --- /dev/null
> +++ b/drivers/acpi/gtdt.c
> @@ -0,0 +1,137 @@
> +/*
> + * ARM Specific GTDT table Support
> + *
> + * Copyright (C) 2015, Linaro Ltd.
> + * Author: Fu Wei <fu.wei@linaro.org>
> + *         Hanjun Guo <hanjun.guo@linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/device.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
> +{
> +       int trigger, polarity;
> +
> +       if (!interrupt)
> +               return 0;
> +
> +       trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
> +                       : ACPI_LEVEL_SENSITIVE;
> +
> +       polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
> +                       : ACPI_ACTIVE_HIGH;
> +
> +       return acpi_register_gsi(NULL, interrupt, trigger, polarity);
> +}
> +
> +/*
> + * Initialize a SBSA generic Watchdog platform device info from GTDT
> + * According to SBSA specification the size of refresh and control
> + * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
> + */
> +static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
> +                                       int index)
> +{
> +       struct platform_device *pdev;
> +       int irq = map_generic_timer_interrupt(wd->timer_interrupt,
> +                                             wd->timer_flags);
> +       struct resource res[] = {
> +               DEFINE_RES_IRQ_NAMED(irq, "ws0"),
> +               DEFINE_RES_MEM_NAMED(wd->refresh_frame_address, SZ_4K,
> +                                    "refresh"),
> +               DEFINE_RES_MEM_NAMED(wd->control_frame_address, SZ_4K,
> +                                    "control"),
> +       };
> +
> +       pr_debug("GTDT: a Watchdog GT(0x%llx/0x%llx gsi:%u flags:0x%x)\n",
> +                wd->refresh_frame_address, wd->control_frame_address,
> +                wd->timer_interrupt, wd->timer_flags);
> +
> +       if (!(wd->refresh_frame_address &&
> +             wd->control_frame_address &&
> +             wd->timer_interrupt)) {
> +               pr_err("GTDT: failed geting the device info.\n");
> +               return -EINVAL;
> +       }
> +
> +       if (irq < 0) {
> +               pr_err("GTDT: failed to register GSI of the Watchdog GT.\n");
> +               return -EINVAL;
> +       }
> +
> +       /*
> +        * Add a platform device named "sbsa-gwdt" to match the platform driver.
> +        * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
> +        * The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get device
> +        * info below by matching this name.
> +        */
> +       pdev = platform_device_register_simple("sbsa-gwdt", index, res,
> +                                              ARRAY_SIZE(res));
> +       if (IS_ERR(pdev)) {
> +               acpi_unregister_gsi(wd->timer_interrupt);
> +               return PTR_ERR(pdev);
> +       }
> +
> +       return 0;
> +}
> +
> +static int __init gtdt_platform_timer_parse(struct acpi_table_header *table)
> +{
> +       struct acpi_gtdt_header *header;
> +       struct acpi_table_gtdt *gtdt;
> +       void *gtdt_subtable;
> +       int i, gwdt_index;
> +       int ret = 0;
> +
> +       if (table->revision < 2) {
> +               pr_warn("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 = 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;
> +}
> +
> +static int __init gtdt_platform_timer_init(void)
> +{
> +       if (acpi_disabled)
> +               return 0;
> +
> +       return acpi_table_parse(ACPI_SIG_GTDT, gtdt_platform_timer_parse);
> +}
> +
> +device_initcall(gtdt_platform_timer_init);
> --
> 1.9.1
>



-- 
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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 1/3] arm64: Add Xen boot support file
  2015-07-15 16:18       ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2015-07-23 10:16         ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-23 10:16 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Andrei Borzenkov, Jon Masters, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List

Hi Vladimir,

I have submitted a new patchset (v3) for xen boot.
this patchset follows all your comment here.

please help me again on this, Great thanks for your help.

On 16 July 2015 at 00:18, Vladimir 'φ-coder/phcoder' Serbinenko
<phcoder@gmail.com> wrote:
> On 13.07.2015 10:53, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> This patch adds Xen boot support file:
>> grub-core/loader/arm64/xen_boot.c
>> include/grub/arm64/xen_boot.h
>>
>> This patch also adds commands register code and hearder file into
>> grub-core/loader/arm64/linux.c
>>
>>   - This adds support for the Xen boot on ARM specification for arm64.
>>   - The implementation for Xen is following  <Multiboot on ARM Specification>:
>>       http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
> Please don't refer to this protocol as multiboot anywhere in grub or
> around because it's NOT multiboot and we don't want to confuse those 2
> protocols.
>>     and xen/docs/misc/arm/device-tree/booting.txt in Xen source code.
>>   - The multiboot/module commands have existed,
>>     so we use xen_hypervisor/xen_module instead.
>>   - This Xen boot support is built into linux module for aarch64.
>>   - Adding this functionality to the existing "linux" module is for
>>     reusing the existing code of devicetree.
>>
> Please create separate module. Modules are dynamically linked.
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  grub-core/Makefile.core.def       |   1 +
>>  grub-core/loader/arm64/linux.c    |   6 +
>>  grub-core/loader/arm64/xen_boot.c | 615 ++++++++++++++++++++++++++++++++++++++
>>  include/grub/arm64/xen_boot.h     | 115 +++++++
>>  4 files changed, 737 insertions(+)
>>  create mode 100644 grub-core/loader/arm64/xen_boot.c
>>  create mode 100644 include/grub/arm64/xen_boot.h
>>
>> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
>> index a6101de..01f8261 100644
>> --- a/grub-core/Makefile.core.def
>> +++ b/grub-core/Makefile.core.def
>> @@ -1659,6 +1659,7 @@ module = {
>>    ia64_efi = loader/ia64/efi/linux.c;
>>    arm = loader/arm/linux.c;
>>    arm64 = loader/arm64/linux.c;
>> +  arm64 = loader/arm64/xen_boot.c;
>>    fdt = lib/fdt.c;
>>    common = loader/linux.c;
>>    common = lib/cmdline.c;
>> diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
>> index 987f5b9..7ae9bde 100644
>> --- a/grub-core/loader/arm64/linux.c
>> +++ b/grub-core/loader/arm64/linux.c
>> @@ -26,6 +26,7 @@
>>  #include <grub/mm.h>
>>  #include <grub/types.h>
>>  #include <grub/cpu/linux.h>
>> +#include <grub/cpu/xen_boot.h>
>>  #include <grub/efi/efi.h>
>>  #include <grub/efi/pe32.h>
>>  #include <grub/i18n.h>
>> @@ -477,6 +478,9 @@ GRUB_MOD_INIT (linux)
>>    cmd_devicetree =
>>      grub_register_command ("devicetree", grub_cmd_devicetree, 0,
>>                          N_("Load DTB file."));
>> +
>> +  grub_arm64_linux_register_xen_boot_command (mod, &loaded);
>> +
>>    my_mod = mod;
>>  }
>>
>> @@ -485,4 +489,6 @@ GRUB_MOD_FINI (linux)
>>    grub_unregister_command (cmd_linux);
>>    grub_unregister_command (cmd_initrd);
>>    grub_unregister_command (cmd_devicetree);
>> +
>> +  grub_arm64_linux_unregister_xen_boot_command ();
>>  }
> Not needed with separate module.
>> diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
>> new file mode 100644
>> index 0000000..23bd00e
>> --- /dev/null
>> +++ b/grub-core/loader/arm64/xen_boot.c
>> @@ -0,0 +1,615 @@
>> +/*
>> + *  GRUB  --  GRand Unified Bootloader
>> + *  Copyright (C) 2014  Free Software Foundation, Inc.
>> + *
>> + *  GRUB is free software: you can redistribute it and/or modify
>> + *  it under the terms of the GNU General Public License as published by
>> + *  the Free Software Foundation, either version 3 of the License, or
>> + *  (at your option) any later version.
>> + *
>> + *  GRUB 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.
>> + *
>> + *  You should have received a copy of the GNU General Public License
>> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <grub/cache.h>
>> +#include <grub/charset.h>
>> +#include <grub/command.h>
>> +#include <grub/err.h>
>> +#include <grub/file.h>
>> +#include <grub/fdt.h>
>> +#include <grub/linux.h>
>> +#include <grub/list.h>
>> +#include <grub/loader.h>
>> +#include <grub/misc.h>
>> +#include <grub/mm.h>
>> +#include <grub/types.h>
>> +#include <grub/cpu/linux.h>
>> +#include <grub/cpu/xen_boot.h>
>> +#include <grub/efi/efi.h>
>> +#include <grub/efi/pe32.h>
>> +#include <grub/i18n.h>
>> +#include <grub/lib/cmdline.h>
>> +
>> +static grub_dl_t linux_mod;
>> +static int *loaded;
>> +
>> +static struct xen_boot_binary *xen_hypervisor;
>> +static struct xen_boot_binary *module_head;
>> +static const grub_size_t module_default_align[] = {
>> +  MODULE_IMAGE_MIN_ALIGN,
>> +  MODULE_INITRD_MIN_ALIGN,
>> +  MODULE_OTHER_MIN_ALIGN,
>> +  MODULE_CUSTOM_MIN_ALIGN
>> +};
>> +
>> +static void *xen_boot_fdt;
>> +static const compat_string_struct_t default_compat_string[] = {
>> +  FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
>> +  FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
>> +  FDT_COMPATIBLE (MODULE_OTHER_COMPATIBLE)
>> +};
>> +
>> +
>> +/* Parse all the options of xen_module command. For now, we support
>> +   (1) --type <the compatible stream>
>> +   (2) --nounzip
>> +   We also set up the type of module in this function.
>> +   If there are some "--type" options in the command line,
>> +   we make a custom compatible stream in this function. */
>> +static grub_err_t
>> +set_module_type (struct xen_boot_binary *module, int argc, char *argv[],
>> +              int *file_name_index)
>> +{
>> +  char **compat_string_temp_array =
>> +    (char **) grub_zalloc (sizeof (char *) * argc);
>> +  static module_type_t default_type = MODULE_IMAGE;
>> +  grub_size_t total_size = 0;
>> +  int num_types = 0, i;
>> +  char *temp = NULL;
>> +
>> +  *file_name_index = 0;
>> +
>> +  /* if there are some options we need to process. */
>> +  while (argc > 1 && !grub_strncmp (argv[0], "--", 2))
>> +    {
>> +      if (!grub_strcmp (argv[0], "--type"))
>> +     {
>> +       module->node_info.type = MODULE_CUSTOM;
>> +       ARG_SHIFT (argc, argv);
>> +       total_size += grub_strlen (argv[0]) + 1;
>> +       compat_string_temp_array[num_types++] = argv[0];
>> +       ARG_SHIFT (argc, argv);
>> +       (*file_name_index) += 2;
> This (and subsequent) parsing is unecessarily complicated. Please create
> separate commands for different types
>> +     }
>> +      else if (!grub_strcmp (argv[0], "--nounzip"))
>> +     {
>> +       grub_file_filter_disable_compression ();
>> +       ARG_SHIFT (argc, argv);
>> +       (*file_name_index) += 1;
>> +     }
>> +      else                   /* we can add more options process code here. */
>> +     {
>> +       grub_dprintf ("xen_boot_loader",
>> +                     "Unknown option %s, skip.\n", argv[0]);
>> +       ARG_SHIFT (argc, argv);
>> +       (*file_name_index) += 1;
>> +     }
>> +    }
>> +
>> +  /* To prevent some wrong command lines using "--type" option */
>> +  if (!argc)
>> +    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
>> +
>> +  /* For the default module type :
>> +     The implementation is following <Multiboot on ARM Specification>:
>> +     Each module will be given a default compatibility property
>> +     based on the order in which the modules are added.
>> +     The 1st module: compatible = "multiboot,kernel", "multiboot,module"
>> +     The 2nd module: compatible = "multiboot,ramdisk", "multiboot,module"
>> +     All subsequent modules: compatible = "multiboot,module"
>> +     But this order will NOT be interfered with "--type"(MODULE_CUSTOM)
>> +     For more detail, please refer to:
>> +     http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot */
>> +  if (module->node_info.type != MODULE_CUSTOM)
>> +    {
>> +      /* the module type is set by the load order */
>> +      module->node_info.type = default_type;
> Please don't make it order-dependent more than necessarry.
>> +      switch (default_type)
>> +     {
>> +     case MODULE_IMAGE:
>> +       default_type = MODULE_INITRD;
>> +       break;
>> +
>> +     case MODULE_INITRD:
>> +       default_type = MODULE_OTHER;
>> +       break;
>> +
>> +     case MODULE_OTHER:
>> +       break;
>> +
>> +     default:
>> +       default_type = MODULE_IMAGE;  /* error, reset the type */
>> +       return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
>> +     }
>> +    }
>> +  else
>> +    {
>> +      /* the module type is set by "--type"(MODULE_CUSTOM) */
>> +      module->node_info.compat_string = temp =
>> +     (char *) grub_zalloc (total_size);
>> +      module->node_info.compat_string_size = total_size;
>> +      for (i = 0; num_types > 0; num_types--, i++, temp++)
>> +     {
>> +       grub_strcpy (temp, compat_string_temp_array[i]);
>> +       temp += grub_strlen (compat_string_temp_array[i]);
>> +     }
>> +    }
>> +
>> +  grub_free (compat_string_temp_array);
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +prepare_xen_hypervisor_params (void)
>> +{
>> +  int chosen_node = 0;
>> +  int retval;
>> +
>> +  xen_boot_fdt = grub_linux_get_fdt ();
>> +  if (!xen_boot_fdt)
>> +    return grub_error (GRUB_ERR_BAD_OS, "failed to get FDT");
>> +
>> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 0)
>> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 1)
>> +    return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT");
>> +
> BAD_OS means that OS images are invalid. ERR_IO is a generic error for
> such cases.
>> +  grub_dprintf ("xen_boot_loader",
>> +             "Xen Hypervisor cmdline : %s @ %p size:%d\n",
>> +             xen_hypervisor->cmdline, xen_hypervisor->cmdline,
>> +             xen_hypervisor->cmdline_size);
>> +
> No need for "boot_". xen_loader is fine and mre consistent.
>> +  retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
>> +                           xen_hypervisor->cmdline,
>> +                           xen_hypervisor->cmdline_size);
>> +  if (retval)
>> +    return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT");
>> +
> ditto
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +prepare_xen_module_params (struct xen_boot_binary *module)
>> +{
>> +  int retval, chosen_node = 0, module_node = 0;
>> +  char module_name[FDT_NODE_NAME_MAX_SIZE];
>> +
>> +  retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
>> +                       xen_boot_address_align (module->start,
>> +                                               module->align));
>> +  grub_dprintf ("xen_boot_loader", "Module node name %s \n", module_name);
>> +
>> +  if (retval < (int) sizeof ("module@"))
>> +    return grub_error (GRUB_ERR_BAD_OS, N_("failed to get FDT"));
>> +
>> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 0)
>> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 1)
>> +    return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT");
>> +
>> +  module_node =
>> +    grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
>> +  if (module_node < 0)
>> +    module_node =
>> +      grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
>> +
>> +  retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
>> +                           module->node_info.compat_string,
>> +                           (grub_uint32_t) module->node_info.
>> +                           compat_string_size);
>> +  if (retval)
>> +    return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT"));
>> +
>> +  grub_dprintf ("xen_boot_loader", "Module %s compatible = %s size = 0x%lx\n",
>> +             module->name, module->node_info.compat_string,
>> +             module->node_info.compat_string_size);
>> +
>> +  retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
>> +                            xen_boot_address_align (module->start,
>> +                                                    module->align),
>> +                            module->size);
>> +  if (retval)
>> +    return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT"));
>> +
>> +  if (module->cmdline && module->cmdline_size > 0)
>> +    {
>> +      grub_dprintf ("xen_boot_loader",
>> +                 "Module %s cmdline : %s @ %p size:%d\n", module->name,
>> +                 module->cmdline, module->cmdline, module->cmdline_size);
>> +
>> +      retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
>> +                               module->cmdline, module->cmdline_size + 1);
>> +      if (retval)
>> +     return grub_error (GRUB_ERR_BAD_OS, "failed to update FDT");
>> +    }
>> +  else
>> +    {
>> +      grub_dprintf ("xen_boot_loader", "Module %s has not bootargs!\n",
>> +                 module->name);
>> +    }
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +install_all_params (void)
>> +{
>> +  grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
>> +  grub_efi_boot_services_t *b;
>> +  grub_efi_status_t status;
>> +
>> +  b = grub_efi_system_table->boot_services;
>> +  status = b->install_configuration_table (&fdt_guid, xen_boot_fdt);
>> +  if (status != GRUB_EFI_SUCCESS)
>> +    return grub_error (GRUB_ERR_BAD_OS, "failed to install FDT");
>> +
>> +  grub_dprintf ("xen_boot_loader",
>> +             "Installed/updated FDT configuration table @ %p\n",
>> +             xen_boot_fdt);
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +clean_all_params (void)
>> +{
>> +  if (xen_boot_fdt)
>> +    {
>> +      grub_efi_free_pages ((grub_efi_physical_address_t) xen_boot_fdt,
>> +                        BYTES_TO_PAGES (grub_fdt_get_totalsize
>> +                                        (xen_boot_fdt)));
>> +      xen_boot_fdt = NULL;
>> +    }
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +finalize_params_xen_boot (void)
>> +{
>> +  struct xen_boot_binary *module;
>> +
>> +  if (xen_hypervisor)
>> +    {
>> +      if (prepare_xen_hypervisor_params () != GRUB_ERR_NONE)
>> +     goto fail;
>> +    }
>> +  else
>> +    {
>> +      grub_dprintf ("xen_boot_loader",
>> +                 "Failed to get Xen Hypervisor info!\n");
>> +      goto fail;
>> +    }
>> +
>> +  /* Set module params info */
>> +  FOR_LIST_ELEMENTS (module, module_head)
>> +  {
>> +    if (module->start && module->size > 0)
>> +      {
>> +     grub_dprintf ("xen_boot_loader", "Module %s @ 0x%lx size:0x%lx\n",
>> +                   module->name,
>> +                   xen_boot_address_align (module->start, module->align),
>> +                   module->size);
>> +     if (prepare_xen_module_params (module) != GRUB_ERR_NONE)
>> +       goto fail;
>> +      }
>> +    else
>> +      {
>> +     grub_dprintf ("xen_boot_loader", "Module info error: %s!\n",
>> +                   module->name);
>> +     goto fail;
>> +      }
>> +  }
>> +
>> +  if (install_all_params () == GRUB_ERR_NONE)
>> +    return GRUB_ERR_NONE;
>> +
>> +fail:
>> +  clean_all_params ();
>> +
>> +  return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT");
>> +}
>> +
>> +
>> +static grub_err_t
>> +xen_boot (void)
>> +{
>> +  if (finalize_params_xen_boot () != GRUB_ERR_NONE)
>> +    return grub_errno;
>> +
> Better use err = finalize_params_xen_boot (); if (err) return err;
>> +  return grub_arm64_uefi_boot_image (xen_hypervisor->start,
>> +                                  xen_hypervisor->size,
>> +                                  xen_hypervisor->cmdline);
>> +}
>> +
>> +static void
>> +single_binary_unload (struct xen_boot_binary *binary)
>> +{
> Just put if (!binary) return; It will save a lot of if's.
>> +  if (binary && binary->start && binary->size > 0)
>> +    {
>> +      grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
>> +                        BYTES_TO_PAGES (binary->size + binary->align));
>> +    }
>> +
>> +  if (binary && binary->cmdline && binary->cmdline_size > 0)
>> +    {
>> +      grub_free (binary->cmdline);
>> +      grub_dprintf ("xen_boot_loader",
>> +                 "Module %s cmdline memory free @ %p size: %d\n",
>> +                 binary->name, binary->cmdline, binary->cmdline_size);
>> +    }
>> +
>> +  if (binary)
>> +    {
>> +      if (binary->node_info.type == MODULE_CUSTOM)
>> +     grub_free ((void *) binary->node_info.compat_string);
>> +      if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
>> +     grub_list_remove (GRUB_AS_LIST (binary));
>> +      grub_dprintf ("xen_boot_loader",
>> +                 "Module %s struct memory free @ %p size: 0x%lx\n",
>> +                 binary->name, binary, sizeof (binary));
>> +      grub_free (binary);
>> +    }
>> +
>> +  return;
>> +}
>> +
>> +static void
>> +all_binaries_unload (void)
>> +{
>> +  struct xen_boot_binary *binary;
>> +
>> +  FOR_LIST_ELEMENTS (binary, module_head)
>> +  {
>> +    single_binary_unload (binary);
>> +  }
>> +
>> +  if (xen_hypervisor)
>> +    single_binary_unload (xen_hypervisor);
>> +
>> +  return;
>> +}
>> +
>> +static grub_err_t
>> +xen_unload (void)
>> +{
>> +  *loaded = 0;
>> +  all_binaries_unload ();
>> +  clean_all_params ();
>> +  grub_dl_unref (linux_mod);
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
>> +                   int argc, char *argv[])
>> +{
>> +  binary->size = grub_file_size (file);
>> +  grub_dprintf ("xen_boot_loader", "Xen_boot %s file size: 0x%lx\n",
>> +             binary->name, binary->size);
>> +
>> +  binary->start = (grub_addr_t) grub_efi_allocate_pages (0,
>> +                                                      (BYTES_TO_PAGES
>> +                                                       (binary->size +
>> +                                                        binary->align)));
>> +  if (!binary->start)
>> +    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>> +
>> +  grub_dprintf ("xen_boot_loader", "Xen_boot %s numpages: 0x%lx\n",
>> +             binary->name, BYTES_TO_PAGES (binary->size + binary->align));
>> +
>> +  if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
>> +                                                          binary->align),
>> +                   binary->size) < (grub_ssize_t) binary->size)
>> +    {
> We use != throughout. It's safer.
>> +      single_binary_unload (binary);
>> +      return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
>> +                      argv[0]);
>> +    }
>> +
>> +  /* Skip the xen_boot binary file name */
>> +  ARG_SHIFT (argc, argv);
>> +
> There shouldn't be any need for shifting. Just use argc - 1 and argv + 1
>> +  if (argc > 0)
>> +    {
>> +      binary->cmdline_size = grub_loader_cmdline_size (argc, argv);
>> +      binary->cmdline = grub_zalloc (binary->cmdline_size);
>> +      if (!binary->cmdline)
>> +     {
>> +       single_binary_unload (binary);
>> +       return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>> +     }
>> +      grub_create_loader_cmdline (argc, argv, binary->cmdline,
>> +                               binary->cmdline_size);
>> +      grub_dprintf ("xen_boot_loader",
>> +                 "Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
>> +                 binary->cmdline, binary->cmdline, binary->cmdline_size);
>> +    }
>> +  else
>> +    {
>> +      binary->cmdline_size = 0;
>> +      binary->cmdline = NULL;
>> +    }
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +grub_cmd_xen_module (grub_command_t cmd __attribute__ ((unused)),
>> +                  int argc, char *argv[])
>> +{
>> +
>> +  struct xen_boot_binary *module = NULL;
>> +  int file_name_index = 0;
>> +  grub_file_t file = 0;
>> +
>> +  if (!argc)
>> +    {
>> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
>> +      goto fail;
>> +    }
>> +
>> +  if (!*loaded)
>> +    {
>> +      grub_error (GRUB_ERR_BAD_ARGUMENT,
>> +               N_("you need to load the Xen Hypervisor first"));
>> +      goto fail;
>> +    }
>> +
>> +  module =
>> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
>> +  if (!module)
>> +    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>> +
> Just return grub_errno; zalloc already calls grub_error
>> +  /* process all the options and get module type */
>> +  if (set_module_type (module, argc, argv, &file_name_index) != GRUB_ERR_NONE)
>> +    goto fail;
>> +  switch (module->node_info.type)
>> +    {
>> +    case MODULE_IMAGE:
>> +    case MODULE_INITRD:
>> +    case MODULE_OTHER:
>> +      module->node_info.compat_string =
>> +     default_compat_string[module->node_info.type].compat_string;
>> +      module->node_info.compat_string_size =
>> +     default_compat_string[module->node_info.type].size;
>> +      break;
>> +
>> +    case MODULE_CUSTOM:
>> +      /* we have set the node_info in set_module_type */
>> +      break;
>> +
>> +    default:
>> +      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
>> +    }
>> +  module->name = module->node_info.compat_string;
>> +  module->align = module_default_align[module->node_info.type];
>> +
>> +  grub_dprintf ("xen_boot_loader", "Init %s module and node info:\n"
>> +             "compatible %s\ncompat_string_size 0x%lx\n",
>> +             module->name, module->node_info.compat_string,
>> +             module->node_info.compat_string_size);
>> +
>> +  file = grub_file_open (argv[file_name_index]);
>> +  if (!file)
>> +    goto fail;
>> +
>> +  grub_errno = xen_boot_binary_load (module, file, argc - file_name_index,
>> +                                  argv + file_name_index);
>> +
> When you call grub_error. grub_errno is already set
>> +  if (grub_errno == GRUB_ERR_NONE)
>> +    grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
>> +
>> +fail:
>> +  if (file)
>> +    grub_file_close (file);
>> +  if (grub_errno != GRUB_ERR_NONE)
>> +    single_binary_unload (module);
>> +
>> +  return grub_errno;
>> +}
>> +
>> +static grub_err_t
>> +grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
>> +                      int argc, char *argv[])
>> +{
>> +  struct xen_hypervisor_header sh;
>> +  grub_file_t file = NULL;
>> +
>> +  grub_dl_ref (linux_mod);
>> +
>> +  if (!argc)
>> +    {
>> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
>> +      goto fail;
>> +    }
>> +
>> +  /* For now, we don't support any option in xen_hypervisor command.
>> +     If there are some options, we skip them. */
>> +  while (argc > 1 && !grub_strncmp (argv[0], "--", 2))
>> +    {
>> +      grub_dprintf ("xen_boot_loader", "Unknown option %s, skip.\n", argv[0]);
>> +      ARG_SHIFT (argc, argv);
>> +    }
>> +
> Why do you need this? Just delete it.
>> +  file = grub_file_open (argv[0]);
>> +  if (!file)
>> +    goto fail;
>> +
>> +  if (grub_file_read (file, &sh, sizeof (sh)) < (long) sizeof (sh))
>> +    goto fail;
>> +  if (grub_arm64_uefi_check_image
>> +      ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
>> +    goto fail;
>> +  grub_file_seek (file, 0);
>> +
>> +  grub_loader_unset ();
>> +
> This is implicit in loader_set. Please add a comment why it needs to be
> explicit. I suppose it's to avoid unloading oneself.
>> +  xen_hypervisor =
>> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
>> +  if (!xen_hypervisor)
>> +    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>> +
> Ditto
>> +  xen_hypervisor->name = XEN_HYPERVISOR_NAME;
>> +  xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
>> +
>> +  grub_errno = xen_boot_binary_load (xen_hypervisor, file, argc, argv);
>> +  if (grub_errno == GRUB_ERR_NONE)
>> +    {
>> +      grub_loader_set (xen_boot, xen_unload, 0);
>> +      *loaded = 1;
>> +    }
>> +
>> +fail:
>> +  if (file)
>> +    grub_file_close (file);
>> +  if (grub_errno != GRUB_ERR_NONE)
>> +    {
>> +      *loaded = 0;
>> +      all_binaries_unload ();
>> +      grub_dl_unref (linux_mod);
>> +    }
>> +
>> +  return grub_errno;
>> +}
>> +
>> +static grub_command_t cmd_xen_hypervisor, cmd_xen_module;
>> +
>> +void
>> +grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *linux_loaded)
>> +{
>> +  cmd_xen_hypervisor =
>> +    grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
>> +                        N_("Load a xen hypervisor."));
>> +  cmd_xen_module =
>> +    grub_register_command ("xen_module", grub_cmd_xen_module, 0,
>> +                        N_("Load a xen module."));
>> +  linux_mod = mod;
>> +  loaded = linux_loaded;
>> +}
>> +
>> +void
>> +grub_arm64_linux_unregister_xen_boot_command (void)
>> +{
>> +  grub_unregister_command (cmd_xen_hypervisor);
>> +  grub_unregister_command (cmd_xen_module);
>> +}
>> diff --git a/include/grub/arm64/xen_boot.h b/include/grub/arm64/xen_boot.h
>> new file mode 100644
>> index 0000000..8e8f6cb
>> --- /dev/null
>> +++ b/include/grub/arm64/xen_boot.h
>> @@ -0,0 +1,115 @@
>> +/*
>> + *  xen_boot.h - Xen boot header file for Xen boot via FDT
>> + *  on AArch64 architecture.
>> + *  Copyright (C) 2014  Free Software Foundation, Inc.
>> + *
>> + *  GRUB is free software: you can redistribute it and/or modify
>> + *  it under the terms of the GNU General Public License as published by
>> + *  the Free Software Foundation, either version 3 of the License, or
>> + *  (at your option) any later version.
>> + *
>> + *  GRUB 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.
>> + *
>> + *  You should have received a copy of the GNU General Public License
>> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef XEN_BOOT_HEADER
>> +#define XEN_BOOT_HEADER 1
>> +
>> +#include <grub/list.h>
>> +#include <grub/types.h>
>> +#include <grub/efi/pe32.h>   /* required by struct xen_hypervisor_header */
>> +
> This file doesn't really look like having anything reusable. Please put
> it directly into .c
>> +#define XEN_HYPERVISOR_NAME  "xen_hypervisor"
>> +
>> +#define MODULE_DEFAULT_ALIGN  (0x0)
>> +#define MODULE_IMAGE_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +#define MODULE_INITRD_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +#define MODULE_OTHER_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +#define MODULE_CUSTOM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +
>> +#define MODULE_IMAGE_COMPATIBLE  "multiboot,kernel\0multiboot,module"
>> +#define MODULE_INITRD_COMPATIBLE  "multiboot,ramdisk\0multiboot,module"
>> +#define MODULE_OTHER_COMPATIBLE  "multiboot,module"
>> +
>> +/* This maximum size is defined in Power.org ePAPR V1.1
>> + * https://www.power.org/documentation/epapr-version-1-1/
>> + * 2.2.1.1 Node Name Requirements
>> + * node-name@unit-address
>> + * 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
>> + */
>> +#define FDT_NODE_NAME_MAX_SIZE  (49)
>> +
>> +#define ARG_SHIFT(argc, argv) \
>> +  do { \
>> +    (argc)--; \
>> +    (argv)++; \
>> +  } while (0)
>> +
>> +struct compat_string_struct
>> +{
>> +  grub_size_t size;
>> +  const char *compat_string;
>> +};
>> +typedef struct compat_string_struct compat_string_struct_t;
>> +#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
>> +
>> +enum module_type
>> +{
>> +  MODULE_IMAGE,
>> +  MODULE_INITRD,
>> +  MODULE_OTHER,
>> +  MODULE_CUSTOM
>> +};
>> +typedef enum module_type module_type_t;
>> +
>> +struct fdt_node_info
>> +{
>> +  module_type_t type;
>> +
>> +  const char *compat_string;
>> +  grub_size_t compat_string_size;
>> +};
>> +
>> +struct xen_hypervisor_header
>> +{
>> +  struct grub_arm64_linux_kernel_header efi_head;
>> +
>> +  /* This is always PE\0\0.  */
>> +  grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
>> +  /* The COFF file header.  */
>> +  struct grub_pe32_coff_header coff_header;
>> +  /* The Optional header.  */
>> +  struct grub_pe64_optional_header optional_header;
>> +};
>> +
>> +struct xen_boot_binary
>> +{
>> +  struct xen_boot_binary *next;
>> +  struct xen_boot_binary **prev;
>> +  const char *name;
>> +
>> +  grub_addr_t start;
>> +  grub_size_t size;
>> +  grub_size_t align;
>> +
>> +  char *cmdline;
>> +  int cmdline_size;
>> +
>> +  struct fdt_node_info node_info;
>> +};
>> +
>> +void grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *loaded);
>> +void grub_arm64_linux_unregister_xen_boot_command (void);
>> +
>> +static __inline grub_addr_t
>> +xen_boot_address_align (grub_addr_t start, grub_size_t align)
>> +{
>> +  return (align ? (ALIGN_UP (start, align)) : start);
>> +}
>> +
>> +#endif /* ! XEN_BOOT_HEADER */
>>
>
>



-- 
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

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 1/3] arm64: Add Xen boot support file
@ 2015-07-23 10:16         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-07-23 10:16 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Andrei Borzenkov, Jon Masters, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List

Hi Vladimir,

I have submitted a new patchset (v3) for xen boot.
this patchset follows all your comment here.

please help me again on this, Great thanks for your help.

On 16 July 2015 at 00:18, Vladimir 'φ-coder/phcoder' Serbinenko
<phcoder@gmail.com> wrote:
> On 13.07.2015 10:53, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> This patch adds Xen boot support file:
>> grub-core/loader/arm64/xen_boot.c
>> include/grub/arm64/xen_boot.h
>>
>> This patch also adds commands register code and hearder file into
>> grub-core/loader/arm64/linux.c
>>
>>   - This adds support for the Xen boot on ARM specification for arm64.
>>   - The implementation for Xen is following  <Multiboot on ARM Specification>:
>>       http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
> Please don't refer to this protocol as multiboot anywhere in grub or
> around because it's NOT multiboot and we don't want to confuse those 2
> protocols.
>>     and xen/docs/misc/arm/device-tree/booting.txt in Xen source code.
>>   - The multiboot/module commands have existed,
>>     so we use xen_hypervisor/xen_module instead.
>>   - This Xen boot support is built into linux module for aarch64.
>>   - Adding this functionality to the existing "linux" module is for
>>     reusing the existing code of devicetree.
>>
> Please create separate module. Modules are dynamically linked.
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  grub-core/Makefile.core.def       |   1 +
>>  grub-core/loader/arm64/linux.c    |   6 +
>>  grub-core/loader/arm64/xen_boot.c | 615 ++++++++++++++++++++++++++++++++++++++
>>  include/grub/arm64/xen_boot.h     | 115 +++++++
>>  4 files changed, 737 insertions(+)
>>  create mode 100644 grub-core/loader/arm64/xen_boot.c
>>  create mode 100644 include/grub/arm64/xen_boot.h
>>
>> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
>> index a6101de..01f8261 100644
>> --- a/grub-core/Makefile.core.def
>> +++ b/grub-core/Makefile.core.def
>> @@ -1659,6 +1659,7 @@ module = {
>>    ia64_efi = loader/ia64/efi/linux.c;
>>    arm = loader/arm/linux.c;
>>    arm64 = loader/arm64/linux.c;
>> +  arm64 = loader/arm64/xen_boot.c;
>>    fdt = lib/fdt.c;
>>    common = loader/linux.c;
>>    common = lib/cmdline.c;
>> diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
>> index 987f5b9..7ae9bde 100644
>> --- a/grub-core/loader/arm64/linux.c
>> +++ b/grub-core/loader/arm64/linux.c
>> @@ -26,6 +26,7 @@
>>  #include <grub/mm.h>
>>  #include <grub/types.h>
>>  #include <grub/cpu/linux.h>
>> +#include <grub/cpu/xen_boot.h>
>>  #include <grub/efi/efi.h>
>>  #include <grub/efi/pe32.h>
>>  #include <grub/i18n.h>
>> @@ -477,6 +478,9 @@ GRUB_MOD_INIT (linux)
>>    cmd_devicetree =
>>      grub_register_command ("devicetree", grub_cmd_devicetree, 0,
>>                          N_("Load DTB file."));
>> +
>> +  grub_arm64_linux_register_xen_boot_command (mod, &loaded);
>> +
>>    my_mod = mod;
>>  }
>>
>> @@ -485,4 +489,6 @@ GRUB_MOD_FINI (linux)
>>    grub_unregister_command (cmd_linux);
>>    grub_unregister_command (cmd_initrd);
>>    grub_unregister_command (cmd_devicetree);
>> +
>> +  grub_arm64_linux_unregister_xen_boot_command ();
>>  }
> Not needed with separate module.
>> diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
>> new file mode 100644
>> index 0000000..23bd00e
>> --- /dev/null
>> +++ b/grub-core/loader/arm64/xen_boot.c
>> @@ -0,0 +1,615 @@
>> +/*
>> + *  GRUB  --  GRand Unified Bootloader
>> + *  Copyright (C) 2014  Free Software Foundation, Inc.
>> + *
>> + *  GRUB is free software: you can redistribute it and/or modify
>> + *  it under the terms of the GNU General Public License as published by
>> + *  the Free Software Foundation, either version 3 of the License, or
>> + *  (at your option) any later version.
>> + *
>> + *  GRUB 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.
>> + *
>> + *  You should have received a copy of the GNU General Public License
>> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <grub/cache.h>
>> +#include <grub/charset.h>
>> +#include <grub/command.h>
>> +#include <grub/err.h>
>> +#include <grub/file.h>
>> +#include <grub/fdt.h>
>> +#include <grub/linux.h>
>> +#include <grub/list.h>
>> +#include <grub/loader.h>
>> +#include <grub/misc.h>
>> +#include <grub/mm.h>
>> +#include <grub/types.h>
>> +#include <grub/cpu/linux.h>
>> +#include <grub/cpu/xen_boot.h>
>> +#include <grub/efi/efi.h>
>> +#include <grub/efi/pe32.h>
>> +#include <grub/i18n.h>
>> +#include <grub/lib/cmdline.h>
>> +
>> +static grub_dl_t linux_mod;
>> +static int *loaded;
>> +
>> +static struct xen_boot_binary *xen_hypervisor;
>> +static struct xen_boot_binary *module_head;
>> +static const grub_size_t module_default_align[] = {
>> +  MODULE_IMAGE_MIN_ALIGN,
>> +  MODULE_INITRD_MIN_ALIGN,
>> +  MODULE_OTHER_MIN_ALIGN,
>> +  MODULE_CUSTOM_MIN_ALIGN
>> +};
>> +
>> +static void *xen_boot_fdt;
>> +static const compat_string_struct_t default_compat_string[] = {
>> +  FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
>> +  FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
>> +  FDT_COMPATIBLE (MODULE_OTHER_COMPATIBLE)
>> +};
>> +
>> +
>> +/* Parse all the options of xen_module command. For now, we support
>> +   (1) --type <the compatible stream>
>> +   (2) --nounzip
>> +   We also set up the type of module in this function.
>> +   If there are some "--type" options in the command line,
>> +   we make a custom compatible stream in this function. */
>> +static grub_err_t
>> +set_module_type (struct xen_boot_binary *module, int argc, char *argv[],
>> +              int *file_name_index)
>> +{
>> +  char **compat_string_temp_array =
>> +    (char **) grub_zalloc (sizeof (char *) * argc);
>> +  static module_type_t default_type = MODULE_IMAGE;
>> +  grub_size_t total_size = 0;
>> +  int num_types = 0, i;
>> +  char *temp = NULL;
>> +
>> +  *file_name_index = 0;
>> +
>> +  /* if there are some options we need to process. */
>> +  while (argc > 1 && !grub_strncmp (argv[0], "--", 2))
>> +    {
>> +      if (!grub_strcmp (argv[0], "--type"))
>> +     {
>> +       module->node_info.type = MODULE_CUSTOM;
>> +       ARG_SHIFT (argc, argv);
>> +       total_size += grub_strlen (argv[0]) + 1;
>> +       compat_string_temp_array[num_types++] = argv[0];
>> +       ARG_SHIFT (argc, argv);
>> +       (*file_name_index) += 2;
> This (and subsequent) parsing is unecessarily complicated. Please create
> separate commands for different types
>> +     }
>> +      else if (!grub_strcmp (argv[0], "--nounzip"))
>> +     {
>> +       grub_file_filter_disable_compression ();
>> +       ARG_SHIFT (argc, argv);
>> +       (*file_name_index) += 1;
>> +     }
>> +      else                   /* we can add more options process code here. */
>> +     {
>> +       grub_dprintf ("xen_boot_loader",
>> +                     "Unknown option %s, skip.\n", argv[0]);
>> +       ARG_SHIFT (argc, argv);
>> +       (*file_name_index) += 1;
>> +     }
>> +    }
>> +
>> +  /* To prevent some wrong command lines using "--type" option */
>> +  if (!argc)
>> +    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
>> +
>> +  /* For the default module type :
>> +     The implementation is following <Multiboot on ARM Specification>:
>> +     Each module will be given a default compatibility property
>> +     based on the order in which the modules are added.
>> +     The 1st module: compatible = "multiboot,kernel", "multiboot,module"
>> +     The 2nd module: compatible = "multiboot,ramdisk", "multiboot,module"
>> +     All subsequent modules: compatible = "multiboot,module"
>> +     But this order will NOT be interfered with "--type"(MODULE_CUSTOM)
>> +     For more detail, please refer to:
>> +     http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot */
>> +  if (module->node_info.type != MODULE_CUSTOM)
>> +    {
>> +      /* the module type is set by the load order */
>> +      module->node_info.type = default_type;
> Please don't make it order-dependent more than necessarry.
>> +      switch (default_type)
>> +     {
>> +     case MODULE_IMAGE:
>> +       default_type = MODULE_INITRD;
>> +       break;
>> +
>> +     case MODULE_INITRD:
>> +       default_type = MODULE_OTHER;
>> +       break;
>> +
>> +     case MODULE_OTHER:
>> +       break;
>> +
>> +     default:
>> +       default_type = MODULE_IMAGE;  /* error, reset the type */
>> +       return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
>> +     }
>> +    }
>> +  else
>> +    {
>> +      /* the module type is set by "--type"(MODULE_CUSTOM) */
>> +      module->node_info.compat_string = temp =
>> +     (char *) grub_zalloc (total_size);
>> +      module->node_info.compat_string_size = total_size;
>> +      for (i = 0; num_types > 0; num_types--, i++, temp++)
>> +     {
>> +       grub_strcpy (temp, compat_string_temp_array[i]);
>> +       temp += grub_strlen (compat_string_temp_array[i]);
>> +     }
>> +    }
>> +
>> +  grub_free (compat_string_temp_array);
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +prepare_xen_hypervisor_params (void)
>> +{
>> +  int chosen_node = 0;
>> +  int retval;
>> +
>> +  xen_boot_fdt = grub_linux_get_fdt ();
>> +  if (!xen_boot_fdt)
>> +    return grub_error (GRUB_ERR_BAD_OS, "failed to get FDT");
>> +
>> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 0)
>> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 1)
>> +    return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT");
>> +
> BAD_OS means that OS images are invalid. ERR_IO is a generic error for
> such cases.
>> +  grub_dprintf ("xen_boot_loader",
>> +             "Xen Hypervisor cmdline : %s @ %p size:%d\n",
>> +             xen_hypervisor->cmdline, xen_hypervisor->cmdline,
>> +             xen_hypervisor->cmdline_size);
>> +
> No need for "boot_". xen_loader is fine and mre consistent.
>> +  retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
>> +                           xen_hypervisor->cmdline,
>> +                           xen_hypervisor->cmdline_size);
>> +  if (retval)
>> +    return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT");
>> +
> ditto
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +prepare_xen_module_params (struct xen_boot_binary *module)
>> +{
>> +  int retval, chosen_node = 0, module_node = 0;
>> +  char module_name[FDT_NODE_NAME_MAX_SIZE];
>> +
>> +  retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
>> +                       xen_boot_address_align (module->start,
>> +                                               module->align));
>> +  grub_dprintf ("xen_boot_loader", "Module node name %s \n", module_name);
>> +
>> +  if (retval < (int) sizeof ("module@"))
>> +    return grub_error (GRUB_ERR_BAD_OS, N_("failed to get FDT"));
>> +
>> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 0)
>> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 1)
>> +    return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT");
>> +
>> +  module_node =
>> +    grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
>> +  if (module_node < 0)
>> +    module_node =
>> +      grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
>> +
>> +  retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
>> +                           module->node_info.compat_string,
>> +                           (grub_uint32_t) module->node_info.
>> +                           compat_string_size);
>> +  if (retval)
>> +    return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT"));
>> +
>> +  grub_dprintf ("xen_boot_loader", "Module %s compatible = %s size = 0x%lx\n",
>> +             module->name, module->node_info.compat_string,
>> +             module->node_info.compat_string_size);
>> +
>> +  retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
>> +                            xen_boot_address_align (module->start,
>> +                                                    module->align),
>> +                            module->size);
>> +  if (retval)
>> +    return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT"));
>> +
>> +  if (module->cmdline && module->cmdline_size > 0)
>> +    {
>> +      grub_dprintf ("xen_boot_loader",
>> +                 "Module %s cmdline : %s @ %p size:%d\n", module->name,
>> +                 module->cmdline, module->cmdline, module->cmdline_size);
>> +
>> +      retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
>> +                               module->cmdline, module->cmdline_size + 1);
>> +      if (retval)
>> +     return grub_error (GRUB_ERR_BAD_OS, "failed to update FDT");
>> +    }
>> +  else
>> +    {
>> +      grub_dprintf ("xen_boot_loader", "Module %s has not bootargs!\n",
>> +                 module->name);
>> +    }
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +install_all_params (void)
>> +{
>> +  grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
>> +  grub_efi_boot_services_t *b;
>> +  grub_efi_status_t status;
>> +
>> +  b = grub_efi_system_table->boot_services;
>> +  status = b->install_configuration_table (&fdt_guid, xen_boot_fdt);
>> +  if (status != GRUB_EFI_SUCCESS)
>> +    return grub_error (GRUB_ERR_BAD_OS, "failed to install FDT");
>> +
>> +  grub_dprintf ("xen_boot_loader",
>> +             "Installed/updated FDT configuration table @ %p\n",
>> +             xen_boot_fdt);
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +clean_all_params (void)
>> +{
>> +  if (xen_boot_fdt)
>> +    {
>> +      grub_efi_free_pages ((grub_efi_physical_address_t) xen_boot_fdt,
>> +                        BYTES_TO_PAGES (grub_fdt_get_totalsize
>> +                                        (xen_boot_fdt)));
>> +      xen_boot_fdt = NULL;
>> +    }
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +finalize_params_xen_boot (void)
>> +{
>> +  struct xen_boot_binary *module;
>> +
>> +  if (xen_hypervisor)
>> +    {
>> +      if (prepare_xen_hypervisor_params () != GRUB_ERR_NONE)
>> +     goto fail;
>> +    }
>> +  else
>> +    {
>> +      grub_dprintf ("xen_boot_loader",
>> +                 "Failed to get Xen Hypervisor info!\n");
>> +      goto fail;
>> +    }
>> +
>> +  /* Set module params info */
>> +  FOR_LIST_ELEMENTS (module, module_head)
>> +  {
>> +    if (module->start && module->size > 0)
>> +      {
>> +     grub_dprintf ("xen_boot_loader", "Module %s @ 0x%lx size:0x%lx\n",
>> +                   module->name,
>> +                   xen_boot_address_align (module->start, module->align),
>> +                   module->size);
>> +     if (prepare_xen_module_params (module) != GRUB_ERR_NONE)
>> +       goto fail;
>> +      }
>> +    else
>> +      {
>> +     grub_dprintf ("xen_boot_loader", "Module info error: %s!\n",
>> +                   module->name);
>> +     goto fail;
>> +      }
>> +  }
>> +
>> +  if (install_all_params () == GRUB_ERR_NONE)
>> +    return GRUB_ERR_NONE;
>> +
>> +fail:
>> +  clean_all_params ();
>> +
>> +  return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT");
>> +}
>> +
>> +
>> +static grub_err_t
>> +xen_boot (void)
>> +{
>> +  if (finalize_params_xen_boot () != GRUB_ERR_NONE)
>> +    return grub_errno;
>> +
> Better use err = finalize_params_xen_boot (); if (err) return err;
>> +  return grub_arm64_uefi_boot_image (xen_hypervisor->start,
>> +                                  xen_hypervisor->size,
>> +                                  xen_hypervisor->cmdline);
>> +}
>> +
>> +static void
>> +single_binary_unload (struct xen_boot_binary *binary)
>> +{
> Just put if (!binary) return; It will save a lot of if's.
>> +  if (binary && binary->start && binary->size > 0)
>> +    {
>> +      grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
>> +                        BYTES_TO_PAGES (binary->size + binary->align));
>> +    }
>> +
>> +  if (binary && binary->cmdline && binary->cmdline_size > 0)
>> +    {
>> +      grub_free (binary->cmdline);
>> +      grub_dprintf ("xen_boot_loader",
>> +                 "Module %s cmdline memory free @ %p size: %d\n",
>> +                 binary->name, binary->cmdline, binary->cmdline_size);
>> +    }
>> +
>> +  if (binary)
>> +    {
>> +      if (binary->node_info.type == MODULE_CUSTOM)
>> +     grub_free ((void *) binary->node_info.compat_string);
>> +      if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
>> +     grub_list_remove (GRUB_AS_LIST (binary));
>> +      grub_dprintf ("xen_boot_loader",
>> +                 "Module %s struct memory free @ %p size: 0x%lx\n",
>> +                 binary->name, binary, sizeof (binary));
>> +      grub_free (binary);
>> +    }
>> +
>> +  return;
>> +}
>> +
>> +static void
>> +all_binaries_unload (void)
>> +{
>> +  struct xen_boot_binary *binary;
>> +
>> +  FOR_LIST_ELEMENTS (binary, module_head)
>> +  {
>> +    single_binary_unload (binary);
>> +  }
>> +
>> +  if (xen_hypervisor)
>> +    single_binary_unload (xen_hypervisor);
>> +
>> +  return;
>> +}
>> +
>> +static grub_err_t
>> +xen_unload (void)
>> +{
>> +  *loaded = 0;
>> +  all_binaries_unload ();
>> +  clean_all_params ();
>> +  grub_dl_unref (linux_mod);
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
>> +                   int argc, char *argv[])
>> +{
>> +  binary->size = grub_file_size (file);
>> +  grub_dprintf ("xen_boot_loader", "Xen_boot %s file size: 0x%lx\n",
>> +             binary->name, binary->size);
>> +
>> +  binary->start = (grub_addr_t) grub_efi_allocate_pages (0,
>> +                                                      (BYTES_TO_PAGES
>> +                                                       (binary->size +
>> +                                                        binary->align)));
>> +  if (!binary->start)
>> +    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>> +
>> +  grub_dprintf ("xen_boot_loader", "Xen_boot %s numpages: 0x%lx\n",
>> +             binary->name, BYTES_TO_PAGES (binary->size + binary->align));
>> +
>> +  if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
>> +                                                          binary->align),
>> +                   binary->size) < (grub_ssize_t) binary->size)
>> +    {
> We use != throughout. It's safer.
>> +      single_binary_unload (binary);
>> +      return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
>> +                      argv[0]);
>> +    }
>> +
>> +  /* Skip the xen_boot binary file name */
>> +  ARG_SHIFT (argc, argv);
>> +
> There shouldn't be any need for shifting. Just use argc - 1 and argv + 1
>> +  if (argc > 0)
>> +    {
>> +      binary->cmdline_size = grub_loader_cmdline_size (argc, argv);
>> +      binary->cmdline = grub_zalloc (binary->cmdline_size);
>> +      if (!binary->cmdline)
>> +     {
>> +       single_binary_unload (binary);
>> +       return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>> +     }
>> +      grub_create_loader_cmdline (argc, argv, binary->cmdline,
>> +                               binary->cmdline_size);
>> +      grub_dprintf ("xen_boot_loader",
>> +                 "Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
>> +                 binary->cmdline, binary->cmdline, binary->cmdline_size);
>> +    }
>> +  else
>> +    {
>> +      binary->cmdline_size = 0;
>> +      binary->cmdline = NULL;
>> +    }
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +grub_cmd_xen_module (grub_command_t cmd __attribute__ ((unused)),
>> +                  int argc, char *argv[])
>> +{
>> +
>> +  struct xen_boot_binary *module = NULL;
>> +  int file_name_index = 0;
>> +  grub_file_t file = 0;
>> +
>> +  if (!argc)
>> +    {
>> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
>> +      goto fail;
>> +    }
>> +
>> +  if (!*loaded)
>> +    {
>> +      grub_error (GRUB_ERR_BAD_ARGUMENT,
>> +               N_("you need to load the Xen Hypervisor first"));
>> +      goto fail;
>> +    }
>> +
>> +  module =
>> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
>> +  if (!module)
>> +    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>> +
> Just return grub_errno; zalloc already calls grub_error
>> +  /* process all the options and get module type */
>> +  if (set_module_type (module, argc, argv, &file_name_index) != GRUB_ERR_NONE)
>> +    goto fail;
>> +  switch (module->node_info.type)
>> +    {
>> +    case MODULE_IMAGE:
>> +    case MODULE_INITRD:
>> +    case MODULE_OTHER:
>> +      module->node_info.compat_string =
>> +     default_compat_string[module->node_info.type].compat_string;
>> +      module->node_info.compat_string_size =
>> +     default_compat_string[module->node_info.type].size;
>> +      break;
>> +
>> +    case MODULE_CUSTOM:
>> +      /* we have set the node_info in set_module_type */
>> +      break;
>> +
>> +    default:
>> +      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
>> +    }
>> +  module->name = module->node_info.compat_string;
>> +  module->align = module_default_align[module->node_info.type];
>> +
>> +  grub_dprintf ("xen_boot_loader", "Init %s module and node info:\n"
>> +             "compatible %s\ncompat_string_size 0x%lx\n",
>> +             module->name, module->node_info.compat_string,
>> +             module->node_info.compat_string_size);
>> +
>> +  file = grub_file_open (argv[file_name_index]);
>> +  if (!file)
>> +    goto fail;
>> +
>> +  grub_errno = xen_boot_binary_load (module, file, argc - file_name_index,
>> +                                  argv + file_name_index);
>> +
> When you call grub_error. grub_errno is already set
>> +  if (grub_errno == GRUB_ERR_NONE)
>> +    grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
>> +
>> +fail:
>> +  if (file)
>> +    grub_file_close (file);
>> +  if (grub_errno != GRUB_ERR_NONE)
>> +    single_binary_unload (module);
>> +
>> +  return grub_errno;
>> +}
>> +
>> +static grub_err_t
>> +grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
>> +                      int argc, char *argv[])
>> +{
>> +  struct xen_hypervisor_header sh;
>> +  grub_file_t file = NULL;
>> +
>> +  grub_dl_ref (linux_mod);
>> +
>> +  if (!argc)
>> +    {
>> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
>> +      goto fail;
>> +    }
>> +
>> +  /* For now, we don't support any option in xen_hypervisor command.
>> +     If there are some options, we skip them. */
>> +  while (argc > 1 && !grub_strncmp (argv[0], "--", 2))
>> +    {
>> +      grub_dprintf ("xen_boot_loader", "Unknown option %s, skip.\n", argv[0]);
>> +      ARG_SHIFT (argc, argv);
>> +    }
>> +
> Why do you need this? Just delete it.
>> +  file = grub_file_open (argv[0]);
>> +  if (!file)
>> +    goto fail;
>> +
>> +  if (grub_file_read (file, &sh, sizeof (sh)) < (long) sizeof (sh))
>> +    goto fail;
>> +  if (grub_arm64_uefi_check_image
>> +      ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
>> +    goto fail;
>> +  grub_file_seek (file, 0);
>> +
>> +  grub_loader_unset ();
>> +
> This is implicit in loader_set. Please add a comment why it needs to be
> explicit. I suppose it's to avoid unloading oneself.
>> +  xen_hypervisor =
>> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
>> +  if (!xen_hypervisor)
>> +    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>> +
> Ditto
>> +  xen_hypervisor->name = XEN_HYPERVISOR_NAME;
>> +  xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
>> +
>> +  grub_errno = xen_boot_binary_load (xen_hypervisor, file, argc, argv);
>> +  if (grub_errno == GRUB_ERR_NONE)
>> +    {
>> +      grub_loader_set (xen_boot, xen_unload, 0);
>> +      *loaded = 1;
>> +    }
>> +
>> +fail:
>> +  if (file)
>> +    grub_file_close (file);
>> +  if (grub_errno != GRUB_ERR_NONE)
>> +    {
>> +      *loaded = 0;
>> +      all_binaries_unload ();
>> +      grub_dl_unref (linux_mod);
>> +    }
>> +
>> +  return grub_errno;
>> +}
>> +
>> +static grub_command_t cmd_xen_hypervisor, cmd_xen_module;
>> +
>> +void
>> +grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *linux_loaded)
>> +{
>> +  cmd_xen_hypervisor =
>> +    grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
>> +                        N_("Load a xen hypervisor."));
>> +  cmd_xen_module =
>> +    grub_register_command ("xen_module", grub_cmd_xen_module, 0,
>> +                        N_("Load a xen module."));
>> +  linux_mod = mod;
>> +  loaded = linux_loaded;
>> +}
>> +
>> +void
>> +grub_arm64_linux_unregister_xen_boot_command (void)
>> +{
>> +  grub_unregister_command (cmd_xen_hypervisor);
>> +  grub_unregister_command (cmd_xen_module);
>> +}
>> diff --git a/include/grub/arm64/xen_boot.h b/include/grub/arm64/xen_boot.h
>> new file mode 100644
>> index 0000000..8e8f6cb
>> --- /dev/null
>> +++ b/include/grub/arm64/xen_boot.h
>> @@ -0,0 +1,115 @@
>> +/*
>> + *  xen_boot.h - Xen boot header file for Xen boot via FDT
>> + *  on AArch64 architecture.
>> + *  Copyright (C) 2014  Free Software Foundation, Inc.
>> + *
>> + *  GRUB is free software: you can redistribute it and/or modify
>> + *  it under the terms of the GNU General Public License as published by
>> + *  the Free Software Foundation, either version 3 of the License, or
>> + *  (at your option) any later version.
>> + *
>> + *  GRUB 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.
>> + *
>> + *  You should have received a copy of the GNU General Public License
>> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef XEN_BOOT_HEADER
>> +#define XEN_BOOT_HEADER 1
>> +
>> +#include <grub/list.h>
>> +#include <grub/types.h>
>> +#include <grub/efi/pe32.h>   /* required by struct xen_hypervisor_header */
>> +
> This file doesn't really look like having anything reusable. Please put
> it directly into .c
>> +#define XEN_HYPERVISOR_NAME  "xen_hypervisor"
>> +
>> +#define MODULE_DEFAULT_ALIGN  (0x0)
>> +#define MODULE_IMAGE_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +#define MODULE_INITRD_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +#define MODULE_OTHER_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +#define MODULE_CUSTOM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +
>> +#define MODULE_IMAGE_COMPATIBLE  "multiboot,kernel\0multiboot,module"
>> +#define MODULE_INITRD_COMPATIBLE  "multiboot,ramdisk\0multiboot,module"
>> +#define MODULE_OTHER_COMPATIBLE  "multiboot,module"
>> +
>> +/* This maximum size is defined in Power.org ePAPR V1.1
>> + * https://www.power.org/documentation/epapr-version-1-1/
>> + * 2.2.1.1 Node Name Requirements
>> + * node-name@unit-address
>> + * 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
>> + */
>> +#define FDT_NODE_NAME_MAX_SIZE  (49)
>> +
>> +#define ARG_SHIFT(argc, argv) \
>> +  do { \
>> +    (argc)--; \
>> +    (argv)++; \
>> +  } while (0)
>> +
>> +struct compat_string_struct
>> +{
>> +  grub_size_t size;
>> +  const char *compat_string;
>> +};
>> +typedef struct compat_string_struct compat_string_struct_t;
>> +#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
>> +
>> +enum module_type
>> +{
>> +  MODULE_IMAGE,
>> +  MODULE_INITRD,
>> +  MODULE_OTHER,
>> +  MODULE_CUSTOM
>> +};
>> +typedef enum module_type module_type_t;
>> +
>> +struct fdt_node_info
>> +{
>> +  module_type_t type;
>> +
>> +  const char *compat_string;
>> +  grub_size_t compat_string_size;
>> +};
>> +
>> +struct xen_hypervisor_header
>> +{
>> +  struct grub_arm64_linux_kernel_header efi_head;
>> +
>> +  /* This is always PE\0\0.  */
>> +  grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
>> +  /* The COFF file header.  */
>> +  struct grub_pe32_coff_header coff_header;
>> +  /* The Optional header.  */
>> +  struct grub_pe64_optional_header optional_header;
>> +};
>> +
>> +struct xen_boot_binary
>> +{
>> +  struct xen_boot_binary *next;
>> +  struct xen_boot_binary **prev;
>> +  const char *name;
>> +
>> +  grub_addr_t start;
>> +  grub_size_t size;
>> +  grub_size_t align;
>> +
>> +  char *cmdline;
>> +  int cmdline_size;
>> +
>> +  struct fdt_node_info node_info;
>> +};
>> +
>> +void grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *loaded);
>> +void grub_arm64_linux_unregister_xen_boot_command (void);
>> +
>> +static __inline grub_addr_t
>> +xen_boot_address_align (grub_addr_t start, grub_size_t align)
>> +{
>> +  return (align ? (ALIGN_UP (start, align)) : start);
>> +}
>> +
>> +#endif /* ! XEN_BOOT_HEADER */
>>
>
>



-- 
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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 0/4] arm64: Add Xen boot support (via fdt)
  2015-07-23  5:16 ` [PATCH v3 0/4] arm64: Add Xen boot support (via fdt) fu.wei
                     ` (3 preceding siblings ...)
  2015-07-23  5:16   ` [PATCH v3 4/4] arm64: Add the introduction of xen boot commands in docs/grub.texi fu.wei
@ 2015-08-04  8:34   ` Fu Wei
  2015-09-08  3:38     ` Fu Wei
  4 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-08-04  8:34 UTC (permalink / raw)
  To: The development of GNU GRUB, Andrei Borzenkov, Vladimir Serbinenko
  Cc: xen-devel, Ian Campbell, Stefano Stabellini, Jon Masters,
	Leif Lindholm, Ryan Harkin, Linaro UEFI Mailman List, Fu Wei

Hi Vladimir,

this patchset follows all your comment of v2 patchset.
Do you have any suggestion on this patchset?

Great thanks for your help.


On 23 July 2015 at 13:16,  <fu.wei@linaro.org> wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
>   - This adds support for the Xen boot on ARM specification for arm64.
>
>   - Add and export some accessor functions of "loaded" flag and
>     grub_linux_get_fdt function in include/grub/arm64/linux.h for xen boot.
>
>   - Introduce xen_hypervisor, xen_linux, xen_initrd and xen_xsm
>     to load different binaries for xen boot.
>     Introduce xen_module to load common or custom module for xen boot.
>
>   - This Xen boot support is a separated  module for aarch64,
>     but reuse the existing code of devicetree in linux module.
>
>   - Add the support of xen_hypervisor, xen_linux and xen_initrd
>     in util/grub.d/20_linux_xen.in
>
>   - Add the introduction of all xen boot commands in docs/grub.texi
>
>   - The example of this support is <How to boot Xen with GRUB on AArch64 the Foundation FVP model>
>     https://wiki.linaro.org/LEG/Engineering/Grub2/Xen_booting_on_Foundation_FVP_model_by_GRUB
>
> Changelog:
> v3: create separate module for xen boot: xen_boot
>     create separate commands for different types of module
>     delete order-dependent for commands of xen module
>     simplify the code
>
> v2: remove the patches which have been accepted.
>     according to Vladimir's suggestion, change the command manes
>     and relevant code:
>         multiboot-->xen_hypervisor
>         module-->xen_module
>     improve the option parsing support for xen_hypervisor/xen_module commands.
>     add a patch for adding xen_hypervisor/xen_module support
>     in util/grub.d/20_linux_xen.in.
>     update docs/grub.texi patch for the new command names.
>
> v1: The first version upstream patchset to grub-devel mailing list
>
>
> Fu Wei (4):
>   arm64: Add and export some accessor functions for xen boot
>   arm64: Add xen_boot module file
>   * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
>   arm64: Add the introduction of xen boot commands in docs/grub.texi
>
>  docs/grub.texi                    |  56 ++++
>  grub-core/Makefile.core.def       |   7 +
>  grub-core/loader/arm64/linux.c    |  13 +
>  grub-core/loader/arm64/xen_boot.c | 685 ++++++++++++++++++++++++++++++++++++++
>  include/grub/arm64/linux.h        |   6 +-
>  util/grub.d/20_linux_xen.in       |  16 +-
>  6 files changed, 779 insertions(+), 4 deletions(-)
>  create mode 100644 grub-core/loader/arm64/xen_boot.c
>
> --
> 1.8.3.1
>



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH] acpi, apei, arm64: APEI initial support for aarch64.
       [not found] <=fu.wei@linaro.org>
                   ` (10 preceding siblings ...)
  2015-07-23  5:16 ` [PATCH v3 0/4] arm64: Add Xen boot support (via fdt) fu.wei
@ 2015-08-14 12:35 ` fu.wei
  2015-08-14 12:39   ` Fu Wei
  2015-08-17 10:01   ` Will Deacon
  2015-08-18 16:44 ` [PATCH v2 0/2] acpi, apei: add BERT support fu.wei
                   ` (2 subsequent siblings)
  14 siblings, 2 replies; 550+ messages in thread
From: fu.wei @ 2015-08-14 12:35 UTC (permalink / raw)
  To: linaro-acpi, linux-kernel, zjzhang, matt.fleming
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, jcm,
	mark.rutland, catalin.marinas, will.deacon, rjw, bp,
	Tomasz Nowicki, Fu Wei

From: Tomasz Nowicki <tomasz.nowicki@linaro.org>

This commit provides APEI arch-specific bits for aarch64

Changelog:
  Fu Wei:
    Move arch_apei_flush_tlb_one() to arch/arm64/include/asm/apci.h.
    Delete arch/arm64/kernel/apei.c.
    Add "#ifdef CONFIG_ACPI_APEI" for "acpi_disable_cmcff".

Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 arch/arm64/Kconfig            |  1 +
 arch/arm64/include/asm/acpi.h | 11 +++++++++++
 arch/arm64/kernel/acpi.c      |  4 ++++
 3 files changed, 16 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 318175f..6144c9d 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -3,6 +3,7 @@ config ARM64
 	select ACPI_CCA_REQUIRED if ACPI
 	select ACPI_GENERIC_GSI if ACPI
 	select ACPI_REDUCED_HARDWARE_ONLY if ACPI
+	select HAVE_ACPI_APEI if ACPI
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select ARCH_HAS_ELF_RANDOMIZE
 	select ARCH_HAS_GCOV_PROFILE_ALL
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index a17b623..ced6e25 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -22,6 +22,7 @@
 #ifdef CONFIG_ACPI_APEI
 #include <linux/efi.h>
 #include <asm/pgtable.h>
+#include <asm/tlbflush.h>
 #endif
 
 /* Macros for consistency checks of the GICC subtable of MADT */
@@ -52,6 +53,9 @@ typedef u64 phys_cpuid_t;
 extern int acpi_disabled;
 extern int acpi_noirq;
 extern int acpi_pci_disabled;
+#ifdef CONFIG_ACPI_APEI
+extern int acpi_disable_cmcff;
+#endif
 
 static inline void disable_acpi(void)
 {
@@ -89,6 +93,13 @@ static inline bool acpi_has_cpu_in_madt(void)
 static inline void arch_fix_phys_package_id(int num, u32 slot) { }
 void __init acpi_init_cpus(void);
 
+#ifdef CONFIG_ACPI_APEI
+static inline void arch_apei_flush_tlb_one(unsigned long addr)
+{
+	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+}
+#endif
+
 #else
 static inline void acpi_init_cpus(void) { }
 #endif /* CONFIG_ACPI */
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 19de753..bd1be9a 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -36,6 +36,10 @@ EXPORT_SYMBOL(acpi_disabled);
 int acpi_pci_disabled = 1;	/* skip ACPI PCI scan and IRQ initialization */
 EXPORT_SYMBOL(acpi_pci_disabled);
 
+#ifdef CONFIG_ACPI_APEI
+int acpi_disable_cmcff;
+#endif
+
 static bool param_acpi_off __initdata;
 static bool param_acpi_force __initdata;
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [PATCH] acpi, apei, arm64: APEI initial support for aarch64.
  2015-08-14 12:35 ` [PATCH] acpi, apei, arm64: APEI initial support for aarch64 fu.wei
@ 2015-08-14 12:39   ` Fu Wei
  2015-08-14 18:27     ` Zhang, Jonathan Zhixiong
  2015-08-17 10:01   ` Will Deacon
  1 sibling, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-08-14 12:39 UTC (permalink / raw)
  To: Linaro ACPI Mailman List, linux-kernel, Zhang, Jonathan Zhixiong,
	matt.fleming
  Cc: Wei Fu, G Gregory, Al Stone, Hanjun Guo, Jon Masters,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki, bp,
	Tomasz Nowicki, Fu Wei

Hi all,

This patch depends on https://lkml.org/lkml/2015/8/8/169
[PATCH V11 4/5] arm64: apei: implement arch_apei_get_mem_attributes(),
which has been in the "next" branch of
git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git

FYI
Thanks

On 14 August 2015 at 20:35,  <fu.wei@linaro.org> wrote:
> From: Tomasz Nowicki <tomasz.nowicki@linaro.org>
>
> This commit provides APEI arch-specific bits for aarch64
>
> Changelog:
>   Fu Wei:
>     Move arch_apei_flush_tlb_one() to arch/arm64/include/asm/apci.h.
>     Delete arch/arm64/kernel/apei.c.
>     Add "#ifdef CONFIG_ACPI_APEI" for "acpi_disable_cmcff".
>
> Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  arch/arm64/Kconfig            |  1 +
>  arch/arm64/include/asm/acpi.h | 11 +++++++++++
>  arch/arm64/kernel/acpi.c      |  4 ++++
>  3 files changed, 16 insertions(+)
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 318175f..6144c9d 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -3,6 +3,7 @@ config ARM64
>         select ACPI_CCA_REQUIRED if ACPI
>         select ACPI_GENERIC_GSI if ACPI
>         select ACPI_REDUCED_HARDWARE_ONLY if ACPI
> +       select HAVE_ACPI_APEI if ACPI
>         select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
>         select ARCH_HAS_ELF_RANDOMIZE
>         select ARCH_HAS_GCOV_PROFILE_ALL
> diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
> index a17b623..ced6e25 100644
> --- a/arch/arm64/include/asm/acpi.h
> +++ b/arch/arm64/include/asm/acpi.h
> @@ -22,6 +22,7 @@
>  #ifdef CONFIG_ACPI_APEI
>  #include <linux/efi.h>
>  #include <asm/pgtable.h>
> +#include <asm/tlbflush.h>
>  #endif
>
>  /* Macros for consistency checks of the GICC subtable of MADT */
> @@ -52,6 +53,9 @@ typedef u64 phys_cpuid_t;
>  extern int acpi_disabled;
>  extern int acpi_noirq;
>  extern int acpi_pci_disabled;
> +#ifdef CONFIG_ACPI_APEI
> +extern int acpi_disable_cmcff;
> +#endif
>
>  static inline void disable_acpi(void)
>  {
> @@ -89,6 +93,13 @@ static inline bool acpi_has_cpu_in_madt(void)
>  static inline void arch_fix_phys_package_id(int num, u32 slot) { }
>  void __init acpi_init_cpus(void);
>
> +#ifdef CONFIG_ACPI_APEI
> +static inline void arch_apei_flush_tlb_one(unsigned long addr)
> +{
> +       flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
> +}
> +#endif
> +
>  #else
>  static inline void acpi_init_cpus(void) { }
>  #endif /* CONFIG_ACPI */
> diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
> index 19de753..bd1be9a 100644
> --- a/arch/arm64/kernel/acpi.c
> +++ b/arch/arm64/kernel/acpi.c
> @@ -36,6 +36,10 @@ EXPORT_SYMBOL(acpi_disabled);
>  int acpi_pci_disabled = 1;     /* skip ACPI PCI scan and IRQ initialization */
>  EXPORT_SYMBOL(acpi_pci_disabled);
>
> +#ifdef CONFIG_ACPI_APEI
> +int acpi_disable_cmcff;
> +#endif
> +
>  static bool param_acpi_off __initdata;
>  static bool param_acpi_force __initdata;
>
> --
> 1.9.1
>



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH] acpi, apei, arm64: APEI initial support for aarch64.
  2015-08-14 12:39   ` Fu Wei
@ 2015-08-14 18:27     ` Zhang, Jonathan Zhixiong
  2015-08-15  6:45       ` Fu Wei
  0 siblings, 1 reply; 550+ messages in thread
From: Zhang, Jonathan Zhixiong @ 2015-08-14 18:27 UTC (permalink / raw)
  To: Fu Wei, Linaro ACPI Mailman List, linux-kernel, matt.fleming
  Cc: Wei Fu, G Gregory, Al Stone, Hanjun Guo, Jon Masters,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki, bp,
	Tomasz Nowicki


On 8/14/2015 5:39 AM, Fu Wei wrote:
> Hi all,
>
> This patch depends on https://lkml.org/lkml/2015/8/8/169
> [PATCH V11 4/5] arm64: apei: implement arch_apei_get_mem_attributes(),
> which has been in the "next" branch of
> git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git
>
> FYI
> Thanks
>
> On 14 August 2015 at 20:35,  <fu.wei@linaro.org> wrote:
>> From: Tomasz Nowicki <tomasz.nowicki@linaro.org>
>>
>> This commit provides APEI arch-specific bits for aarch64
>>
>> Changelog:
>>    Fu Wei:
>>      Move arch_apei_flush_tlb_one() to arch/arm64/include/asm/apci.h.
>>      Delete arch/arm64/kernel/apei.c.
>>      Add "#ifdef CONFIG_ACPI_APEI" for "acpi_disable_cmcff".
>>
>> Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>   arch/arm64/Kconfig            |  1 +
>>   arch/arm64/include/asm/acpi.h | 11 +++++++++++
>>   arch/arm64/kernel/acpi.c      |  4 ++++
>>   3 files changed, 16 insertions(+)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 318175f..6144c9d 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -3,6 +3,7 @@ config ARM64
>>          select ACPI_CCA_REQUIRED if ACPI
>>          select ACPI_GENERIC_GSI if ACPI
>>          select ACPI_REDUCED_HARDWARE_ONLY if ACPI
>> +       select HAVE_ACPI_APEI if ACPI
>>          select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
>>          select ARCH_HAS_ELF_RANDOMIZE
>>          select ARCH_HAS_GCOV_PROFILE_ALL
>> diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
>> index a17b623..ced6e25 100644
>> --- a/arch/arm64/include/asm/acpi.h
>> +++ b/arch/arm64/include/asm/acpi.h
>> @@ -22,6 +22,7 @@
>>   #ifdef CONFIG_ACPI_APEI
>>   #include <linux/efi.h>
>>   #include <asm/pgtable.h>
>> +#include <asm/tlbflush.h>
>>   #endif
>>
>>   /* Macros for consistency checks of the GICC subtable of MADT */
>> @@ -52,6 +53,9 @@ typedef u64 phys_cpuid_t;
>>   extern int acpi_disabled;
>>   extern int acpi_noirq;
>>   extern int acpi_pci_disabled;
>> +#ifdef CONFIG_ACPI_APEI
>> +extern int acpi_disable_cmcff;
>> +#endif
>>
>>   static inline void disable_acpi(void)
>>   {
>> @@ -89,6 +93,13 @@ static inline bool acpi_has_cpu_in_madt(void)
>>   static inline void arch_fix_phys_package_id(int num, u32 slot) { }
>>   void __init acpi_init_cpus(void);
>>
>> +#ifdef CONFIG_ACPI_APEI
>> +static inline void arch_apei_flush_tlb_one(unsigned long addr)
>> +{
>> +       flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
>> +}
>> +#endif
>> +
>>   #else
>>   static inline void acpi_init_cpus(void) { }
>>   #endif /* CONFIG_ACPI */
>> diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
>> index 19de753..bd1be9a 100644
>> --- a/arch/arm64/kernel/acpi.c
>> +++ b/arch/arm64/kernel/acpi.c
>> @@ -36,6 +36,10 @@ EXPORT_SYMBOL(acpi_disabled);
>>   int acpi_pci_disabled = 1;     /* skip ACPI PCI scan and IRQ initialization */
>>   EXPORT_SYMBOL(acpi_pci_disabled);
>>
>> +#ifdef CONFIG_ACPI_APEI
>> +int acpi_disable_cmcff;
>> +#endif
>> +
>>   static bool param_acpi_off __initdata;
>>   static bool param_acpi_force __initdata;
>>
>> --
>> 1.9.1
>>
>
>
>
I tested this patch on an arm64 platform, the APEI functionalities
work as expected.
   Tested-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH] acpi, apei, arm64: APEI initial support for aarch64.
  2015-08-14 18:27     ` Zhang, Jonathan Zhixiong
@ 2015-08-15  6:45       ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-08-15  6:45 UTC (permalink / raw)
  To: Zhang, Jonathan Zhixiong, Tomasz Nowicki
  Cc: Linaro ACPI Mailman List, linux-kernel, matt.fleming, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Jon Masters, Mark Rutland,
	Catalin Marinas, Will Deacon, Rafael Wysocki, bp, Tomasz Nowicki

Hi all
Add Tomasz Nowicki <tn@semihalf.com> in the loop

On 15 August 2015 at 02:27, Zhang, Jonathan Zhixiong
<zjzhang@codeaurora.org> wrote:
>
> On 8/14/2015 5:39 AM, Fu Wei wrote:
>>
>> Hi all,
>>
>> This patch depends on https://lkml.org/lkml/2015/8/8/169
>> [PATCH V11 4/5] arm64: apei: implement arch_apei_get_mem_attributes(),
>> which has been in the "next" branch of
>> git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git
>>
>> FYI
>> Thanks
>>
>> On 14 August 2015 at 20:35,  <fu.wei@linaro.org> wrote:
>>>
>>> From: Tomasz Nowicki <tomasz.nowicki@linaro.org>
>>>
>>> This commit provides APEI arch-specific bits for aarch64
>>>
>>> Changelog:
>>>    Fu Wei:
>>>      Move arch_apei_flush_tlb_one() to arch/arm64/include/asm/apci.h.
>>>      Delete arch/arm64/kernel/apei.c.
>>>      Add "#ifdef CONFIG_ACPI_APEI" for "acpi_disable_cmcff".
>>>
>>> Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
>>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>>> ---
>>>   arch/arm64/Kconfig            |  1 +
>>>   arch/arm64/include/asm/acpi.h | 11 +++++++++++
>>>   arch/arm64/kernel/acpi.c      |  4 ++++
>>>   3 files changed, 16 insertions(+)
>>>
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index 318175f..6144c9d 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -3,6 +3,7 @@ config ARM64
>>>          select ACPI_CCA_REQUIRED if ACPI
>>>          select ACPI_GENERIC_GSI if ACPI
>>>          select ACPI_REDUCED_HARDWARE_ONLY if ACPI
>>> +       select HAVE_ACPI_APEI if ACPI
>>>          select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
>>>          select ARCH_HAS_ELF_RANDOMIZE
>>>          select ARCH_HAS_GCOV_PROFILE_ALL
>>> diff --git a/arch/arm64/include/asm/acpi.h
>>> b/arch/arm64/include/asm/acpi.h
>>> index a17b623..ced6e25 100644
>>> --- a/arch/arm64/include/asm/acpi.h
>>> +++ b/arch/arm64/include/asm/acpi.h
>>> @@ -22,6 +22,7 @@
>>>   #ifdef CONFIG_ACPI_APEI
>>>   #include <linux/efi.h>
>>>   #include <asm/pgtable.h>
>>> +#include <asm/tlbflush.h>
>>>   #endif
>>>
>>>   /* Macros for consistency checks of the GICC subtable of MADT */
>>> @@ -52,6 +53,9 @@ typedef u64 phys_cpuid_t;
>>>   extern int acpi_disabled;
>>>   extern int acpi_noirq;
>>>   extern int acpi_pci_disabled;
>>> +#ifdef CONFIG_ACPI_APEI
>>> +extern int acpi_disable_cmcff;
>>> +#endif
>>>
>>>   static inline void disable_acpi(void)
>>>   {
>>> @@ -89,6 +93,13 @@ static inline bool acpi_has_cpu_in_madt(void)
>>>   static inline void arch_fix_phys_package_id(int num, u32 slot) { }
>>>   void __init acpi_init_cpus(void);
>>>
>>> +#ifdef CONFIG_ACPI_APEI
>>> +static inline void arch_apei_flush_tlb_one(unsigned long addr)
>>> +{
>>> +       flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
>>> +}
>>> +#endif
>>> +
>>>   #else
>>>   static inline void acpi_init_cpus(void) { }
>>>   #endif /* CONFIG_ACPI */
>>> diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
>>> index 19de753..bd1be9a 100644
>>> --- a/arch/arm64/kernel/acpi.c
>>> +++ b/arch/arm64/kernel/acpi.c
>>> @@ -36,6 +36,10 @@ EXPORT_SYMBOL(acpi_disabled);
>>>   int acpi_pci_disabled = 1;     /* skip ACPI PCI scan and IRQ
>>> initialization */
>>>   EXPORT_SYMBOL(acpi_pci_disabled);
>>>
>>> +#ifdef CONFIG_ACPI_APEI
>>> +int acpi_disable_cmcff;
>>> +#endif
>>> +
>>>   static bool param_acpi_off __initdata;
>>>   static bool param_acpi_force __initdata;
>>>
>>> --
>>> 1.9.1
>>>
>>
>>
>>
> I tested this patch on an arm64 platform, the APEI functionalities
> work as expected.
>   Tested-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
>
> --
> Jonathan (Zhixiong) Zhang
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH] acpi, apei, arm64: APEI initial support for aarch64.
  2015-08-14 12:35 ` [PATCH] acpi, apei, arm64: APEI initial support for aarch64 fu.wei
  2015-08-14 12:39   ` Fu Wei
@ 2015-08-17 10:01   ` Will Deacon
  2015-08-17 23:19     ` Zhang, Jonathan Zhixiong
  1 sibling, 1 reply; 550+ messages in thread
From: Will Deacon @ 2015-08-17 10:01 UTC (permalink / raw)
  To: fu.wei
  Cc: linaro-acpi, linux-kernel, zjzhang, matt.fleming, tekkamanninja,
	graeme.gregory, al.stone, hanjun.guo, jcm, Mark Rutland,
	Catalin Marinas, rjw, bp, Tomasz Nowicki

On Fri, Aug 14, 2015 at 01:35:53PM +0100, fu.wei@linaro.org wrote:
> From: Tomasz Nowicki <tomasz.nowicki@linaro.org>
> 
> This commit provides APEI arch-specific bits for aarch64
> 
> Changelog:
>   Fu Wei:
>     Move arch_apei_flush_tlb_one() to arch/arm64/include/asm/apci.h.
>     Delete arch/arm64/kernel/apei.c.
>     Add "#ifdef CONFIG_ACPI_APEI" for "acpi_disable_cmcff".
> 
> Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  arch/arm64/Kconfig            |  1 +
>  arch/arm64/include/asm/acpi.h | 11 +++++++++++
>  arch/arm64/kernel/acpi.c      |  4 ++++
>  3 files changed, 16 insertions(+)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 318175f..6144c9d 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -3,6 +3,7 @@ config ARM64
>  	select ACPI_CCA_REQUIRED if ACPI
>  	select ACPI_GENERIC_GSI if ACPI
>  	select ACPI_REDUCED_HARDWARE_ONLY if ACPI
> +	select HAVE_ACPI_APEI if ACPI
>  	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
>  	select ARCH_HAS_ELF_RANDOMIZE
>  	select ARCH_HAS_GCOV_PROFILE_ALL
> diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
> index a17b623..ced6e25 100644
> --- a/arch/arm64/include/asm/acpi.h
> +++ b/arch/arm64/include/asm/acpi.h
> @@ -22,6 +22,7 @@
>  #ifdef CONFIG_ACPI_APEI
>  #include <linux/efi.h>
>  #include <asm/pgtable.h>
> +#include <asm/tlbflush.h>
>  #endif
>  
>  /* Macros for consistency checks of the GICC subtable of MADT */
> @@ -52,6 +53,9 @@ typedef u64 phys_cpuid_t;
>  extern int acpi_disabled;
>  extern int acpi_noirq;
>  extern int acpi_pci_disabled;
> +#ifdef CONFIG_ACPI_APEI
> +extern int acpi_disable_cmcff;
> +#endif
>  
>  static inline void disable_acpi(void)
>  {
> @@ -89,6 +93,13 @@ static inline bool acpi_has_cpu_in_madt(void)
>  static inline void arch_fix_phys_package_id(int num, u32 slot) { }
>  void __init acpi_init_cpus(void);
>  
> +#ifdef CONFIG_ACPI_APEI
> +static inline void arch_apei_flush_tlb_one(unsigned long addr)
> +{
> +	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
> +}
> +#endif

Looking at the callers of this function, I suspect we could downgrade it
to a local CPU invalidation if we wanted. However, this isn't a hot-path
so it's fine to stay like it is for now.

Will

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH] acpi, apei, arm64: APEI initial support for aarch64.
  2015-08-17 10:01   ` Will Deacon
@ 2015-08-17 23:19     ` Zhang, Jonathan Zhixiong
  2015-08-18  8:31       ` Will Deacon
  0 siblings, 1 reply; 550+ messages in thread
From: Zhang, Jonathan Zhixiong @ 2015-08-17 23:19 UTC (permalink / raw)
  To: Will Deacon, fu.wei, harba
  Cc: linaro-acpi, linux-kernel, matt.fleming, tekkamanninja,
	graeme.gregory, al.stone, hanjun.guo, jcm, Mark Rutland,
	Catalin Marinas, rjw, bp, Tomasz Nowicki



On 8/17/2015 3:01 AM, Will Deacon wrote:
> On Fri, Aug 14, 2015 at 01:35:53PM +0100, fu.wei@linaro.org wrote:
>> From: Tomasz Nowicki <tomasz.nowicki@linaro.org>
>>
>> This commit provides APEI arch-specific bits for aarch64
>>
>> Changelog:
>>    Fu Wei:
>>      Move arch_apei_flush_tlb_one() to arch/arm64/include/asm/apci.h.
>>      Delete arch/arm64/kernel/apei.c.
>>      Add "#ifdef CONFIG_ACPI_APEI" for "acpi_disable_cmcff".
>>
>> Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>   arch/arm64/Kconfig            |  1 +
>>   arch/arm64/include/asm/acpi.h | 11 +++++++++++
>>   arch/arm64/kernel/acpi.c      |  4 ++++
>>   3 files changed, 16 insertions(+)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 318175f..6144c9d 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -3,6 +3,7 @@ config ARM64
>>   	select ACPI_CCA_REQUIRED if ACPI
>>   	select ACPI_GENERIC_GSI if ACPI
>>   	select ACPI_REDUCED_HARDWARE_ONLY if ACPI
>> +	select HAVE_ACPI_APEI if ACPI
>>   	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
>>   	select ARCH_HAS_ELF_RANDOMIZE
>>   	select ARCH_HAS_GCOV_PROFILE_ALL
>> diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
>> index a17b623..ced6e25 100644
>> --- a/arch/arm64/include/asm/acpi.h
>> +++ b/arch/arm64/include/asm/acpi.h
>> @@ -22,6 +22,7 @@
>>   #ifdef CONFIG_ACPI_APEI
>>   #include <linux/efi.h>
>>   #include <asm/pgtable.h>
>> +#include <asm/tlbflush.h>
>>   #endif
>>
>>   /* Macros for consistency checks of the GICC subtable of MADT */
>> @@ -52,6 +53,9 @@ typedef u64 phys_cpuid_t;
>>   extern int acpi_disabled;
>>   extern int acpi_noirq;
>>   extern int acpi_pci_disabled;
>> +#ifdef CONFIG_ACPI_APEI
>> +extern int acpi_disable_cmcff;
>> +#endif
>>
>>   static inline void disable_acpi(void)
>>   {
>> @@ -89,6 +93,13 @@ static inline bool acpi_has_cpu_in_madt(void)
>>   static inline void arch_fix_phys_package_id(int num, u32 slot) { }
>>   void __init acpi_init_cpus(void);
>>
>> +#ifdef CONFIG_ACPI_APEI
>> +static inline void arch_apei_flush_tlb_one(unsigned long addr)
>> +{
>> +	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
>> +}
>> +#endif
>
> Looking at the callers of this function, I suspect we could downgrade it
> to a local CPU invalidation if we wanted. However, this isn't a hot-path
> so it's fine to stay like it is for now.
I suppose if we run "tlbi vae1" instead of "tlbi vae1is", it will be
more efficient without side effect, since both ghes_ioremap_pfn_irq()
and ghes_iounmap_irq() happen in same atomic context. However, today
arch/arm64/include/asm/tlbflush.h does not have a function tailored for
such performance optimization. Does it make sense to add a parameter to
flush_tlb_kernel_range() to allow caller to make a choice?
   static inline void flush_tlb_kernel_range(unsigned long start,
	unsigned long end, bool local)
There are only two others callers of flush_tlb_kernel_range().
>
> Will
>

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH] acpi, apei, arm64: APEI initial support for aarch64.
  2015-08-17 23:19     ` Zhang, Jonathan Zhixiong
@ 2015-08-18  8:31       ` Will Deacon
  2015-08-18  9:26         ` Fu Wei
  0 siblings, 1 reply; 550+ messages in thread
From: Will Deacon @ 2015-08-18  8:31 UTC (permalink / raw)
  To: Zhang, Jonathan Zhixiong
  Cc: fu.wei, harba, linaro-acpi, linux-kernel, matt.fleming,
	tekkamanninja, graeme.gregory, al.stone, hanjun.guo, jcm,
	Mark Rutland, Catalin Marinas, rjw, bp, Tomasz Nowicki

On Tue, Aug 18, 2015 at 12:19:13AM +0100, Zhang, Jonathan Zhixiong wrote:
> On 8/17/2015 3:01 AM, Will Deacon wrote:
> > On Fri, Aug 14, 2015 at 01:35:53PM +0100, fu.wei@linaro.org wrote:
> >> diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
> >> index a17b623..ced6e25 100644
> >> --- a/arch/arm64/include/asm/acpi.h
> >> +++ b/arch/arm64/include/asm/acpi.h
> >> @@ -22,6 +22,7 @@
> >>   #ifdef CONFIG_ACPI_APEI
> >>   #include <linux/efi.h>
> >>   #include <asm/pgtable.h>
> >> +#include <asm/tlbflush.h>
> >>   #endif
> >>
> >>   /* Macros for consistency checks of the GICC subtable of MADT */
> >> @@ -52,6 +53,9 @@ typedef u64 phys_cpuid_t;
> >>   extern int acpi_disabled;
> >>   extern int acpi_noirq;
> >>   extern int acpi_pci_disabled;
> >> +#ifdef CONFIG_ACPI_APEI
> >> +extern int acpi_disable_cmcff;
> >> +#endif
> >>
> >>   static inline void disable_acpi(void)
> >>   {
> >> @@ -89,6 +93,13 @@ static inline bool acpi_has_cpu_in_madt(void)
> >>   static inline void arch_fix_phys_package_id(int num, u32 slot) { }
> >>   void __init acpi_init_cpus(void);
> >>
> >> +#ifdef CONFIG_ACPI_APEI
> >> +static inline void arch_apei_flush_tlb_one(unsigned long addr)
> >> +{
> >> +	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
> >> +}
> >> +#endif
> >
> > Looking at the callers of this function, I suspect we could downgrade it
> > to a local CPU invalidation if we wanted. However, this isn't a hot-path
> > so it's fine to stay like it is for now.
> I suppose if we run "tlbi vae1" instead of "tlbi vae1is", it will be
> more efficient without side effect, since both ghes_ioremap_pfn_irq()
> and ghes_iounmap_irq() happen in same atomic context. However, today
> arch/arm64/include/asm/tlbflush.h does not have a function tailored for
> such performance optimization. Does it make sense to add a parameter to
> flush_tlb_kernel_range() to allow caller to make a choice?
>    static inline void flush_tlb_kernel_range(unsigned long start,
> 	unsigned long end, bool local)
> There are only two others callers of flush_tlb_kernel_range().

I've already got some patches to add things like local_flush_tlb_all,
which I'll post after the merge window (I'm currently rewriting a bunch
of the switch_mm code to try to reduce the TLBI traffic).

If this isn't a hotpath (I don't think it is), then it's probably not
worth making the optimisation without a system to benchmark it on.

Will

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH] acpi, apei, arm64: APEI initial support for aarch64.
  2015-08-18  8:31       ` Will Deacon
@ 2015-08-18  9:26         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-08-18  9:26 UTC (permalink / raw)
  To: Will Deacon
  Cc: Zhang, Jonathan Zhixiong, harba, linaro-acpi, linux-kernel,
	matt.fleming, tekkamanninja, graeme.gregory, al.stone,
	hanjun.guo, jcm, Mark Rutland, Catalin Marinas, rjw, bp,
	Tomasz Nowicki

Hi

On 18 August 2015 at 16:31, Will Deacon <will.deacon@arm.com> wrote:
> On Tue, Aug 18, 2015 at 12:19:13AM +0100, Zhang, Jonathan Zhixiong wrote:
>> On 8/17/2015 3:01 AM, Will Deacon wrote:
>> > On Fri, Aug 14, 2015 at 01:35:53PM +0100, fu.wei@linaro.org wrote:
>> >> diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
>> >> index a17b623..ced6e25 100644
>> >> --- a/arch/arm64/include/asm/acpi.h
>> >> +++ b/arch/arm64/include/asm/acpi.h
>> >> @@ -22,6 +22,7 @@
>> >>   #ifdef CONFIG_ACPI_APEI
>> >>   #include <linux/efi.h>
>> >>   #include <asm/pgtable.h>
>> >> +#include <asm/tlbflush.h>
>> >>   #endif
>> >>
>> >>   /* Macros for consistency checks of the GICC subtable of MADT */
>> >> @@ -52,6 +53,9 @@ typedef u64 phys_cpuid_t;
>> >>   extern int acpi_disabled;
>> >>   extern int acpi_noirq;
>> >>   extern int acpi_pci_disabled;
>> >> +#ifdef CONFIG_ACPI_APEI
>> >> +extern int acpi_disable_cmcff;
>> >> +#endif
>> >>
>> >>   static inline void disable_acpi(void)
>> >>   {
>> >> @@ -89,6 +93,13 @@ static inline bool acpi_has_cpu_in_madt(void)
>> >>   static inline void arch_fix_phys_package_id(int num, u32 slot) { }
>> >>   void __init acpi_init_cpus(void);
>> >>
>> >> +#ifdef CONFIG_ACPI_APEI
>> >> +static inline void arch_apei_flush_tlb_one(unsigned long addr)
>> >> +{
>> >> +  flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
>> >> +}
>> >> +#endif
>> >
>> > Looking at the callers of this function, I suspect we could downgrade it
>> > to a local CPU invalidation if we wanted. However, this isn't a hot-path
>> > so it's fine to stay like it is for now.
>> I suppose if we run "tlbi vae1" instead of "tlbi vae1is", it will be
>> more efficient without side effect, since both ghes_ioremap_pfn_irq()
>> and ghes_iounmap_irq() happen in same atomic context. However, today
>> arch/arm64/include/asm/tlbflush.h does not have a function tailored for
>> such performance optimization. Does it make sense to add a parameter to
>> flush_tlb_kernel_range() to allow caller to make a choice?
>>    static inline void flush_tlb_kernel_range(unsigned long start,
>>       unsigned long end, bool local)
>> There are only two others callers of flush_tlb_kernel_range().
>
> I've already got some patches to add things like local_flush_tlb_all,
> which I'll post after the merge window (I'm currently rewriting a bunch
> of the switch_mm code to try to reduce the TLBI traffic).

If I understand correctly, these patches add new  functions, instead
of changing the existent one.
I thinks this way is better.

If we have new patch for optimizing TLB flushing, we can make a new
patchset for this in the future.
Because this patch is only for enabling APEI on aarch64.

>
> If this isn't a hotpath (I don't think it is), then it's probably not
> worth making the optimisation without a system to benchmark it on.

agree.

But please let me know if you have any suggestion on this patch.
is this patch OK for you?

>
> Will



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v2 0/2] acpi, apei: add BERT support
       [not found] <=fu.wei@linaro.org>
                   ` (11 preceding siblings ...)
  2015-08-14 12:35 ` [PATCH] acpi, apei, arm64: APEI initial support for aarch64 fu.wei
@ 2015-08-18 16:44 ` fu.wei
  2015-08-18 16:44   ` [PATCH v2 1/2] acpi, apei: add Boot Error Record Table (BERT) support fu.wei
                     ` (2 more replies)
  2015-08-24 17:01 ` [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
  2016-02-25  6:50 ` [PATCH v2 0/4] arm64,xen: add xen_boot support into grup-mkconfig fu.wei
  14 siblings, 3 replies; 550+ messages in thread
From: fu.wei @ 2015-08-18 16:44 UTC (permalink / raw)
  To: linaro-acpi, linux-kernel, zjzhang, tony.luck, gong.chen,
	ying.huang, tomasz.nowicki
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, jcm,
	mark.rutland, catalin.marinas, will.deacon, rjw, bp,
	matt.fleming, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

ACPI/APEI is designed to verifiy/report H/W errors, like Corrected
Error(CE) and Uncorrected Error(UC). It contains four tables: HEST,
ERST, EINJ and BERT. The first three tables have been merged for
a long time, but because of lacking BIOS support for BERT, the
support for BERT is pending until now. Recently on ARM 64 platform
it is has been supported. So here we come.

The following log is a BERT record after system reboot because of
hitting a fatal error.

BERT: Obtained BERT iomem region <00000000fe801000-00000000fe802000> for BERT.
[Hardware Error]: Error record from previous boot:
[Hardware Error]: event severity: fatal
[Hardware Error]:  Error 0, type: fatal
[Hardware Error]:   section_type: memory error
[Hardware Error]:   physical_address: 0x00000000fe800000
[Hardware Error]:   physical_address_mask: 0x0000000000000fff
[Hardware Error]:   card: 0 module: 1 bank: 0 device: 1 row: 1 column: 1 bit_pos

Changelog:
v2: Delete EXPORT_SYMBOL_GPL(bert_disable), because "bert_disable" is only used
    in bert.c for now.
    Do some code-style cleanups.

v1: The first upstream version submitted in linux-acpi mailing list:
    http://www.spinics.net/lists/linux-acpi/msg57384.html

Huang Ying (1):
  ACPI, APEI, Boot Error Record Table (BERT) support

Tomasz Nowicki (1):
  acpi, apei, bert: Clear error status at the end of error handling

 Documentation/kernel-parameters.txt |   3 +
 drivers/acpi/apei/Makefile          |   2 +-
 drivers/acpi/apei/bert.c            | 165 ++++++++++++++++++++++++++++++++++++
 include/acpi/apei.h                 |   1 +
 4 files changed, 170 insertions(+), 1 deletion(-)
 create mode 100644 drivers/acpi/apei/bert.c

-- 
2.4.3


^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v2 1/2] acpi, apei: add Boot Error Record Table (BERT) support
  2015-08-18 16:44 ` [PATCH v2 0/2] acpi, apei: add BERT support fu.wei
@ 2015-08-18 16:44   ` fu.wei
  2015-12-16 10:29     ` Borislav Petkov
  2015-08-18 16:44   ` [PATCH v2 2/2] acpi, apei, bert: Clear error status at the end of error handling fu.wei
  2015-12-15 16:39   ` [Linaro-acpi] [PATCH v2 0/2] acpi, apei: add BERT support Timur Tabi
  2 siblings, 1 reply; 550+ messages in thread
From: fu.wei @ 2015-08-18 16:44 UTC (permalink / raw)
  To: linaro-acpi, linux-kernel, zjzhang, tony.luck, gong.chen,
	ying.huang, tomasz.nowicki
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, jcm,
	mark.rutland, catalin.marinas, will.deacon, rjw, bp,
	matt.fleming, Chen, Gong, Fu Wei

From: Huang Ying <ying.huang@intel.com>

Under normal circumstances, when a hardware error occurs, kernel will
be notified via NMI, MCE or some other method, then kernel will
process the error condition, report it, and recover it if possible.
But sometime, the situation is so bad, so that firmware may choose to
reset directly without notifying Linux kernel.

Linux kernel can use the Boot Error Record Table (BERT) to get the
un-notified hardware errors that occurred in a previous boot. In this
patch, the error information is reported via printk.

For more information about BERT, please refer to ACPI Specification
version 6.0, section 18.3.1:
  http://www.uefi.org/sites/default/files/resources/ACPI_6.0.pdf

[Tony: Applied some cleanups suggested by Fu Wei]
[Fu Wei: delete EXPORT_SYMBOL_GPL(bert_disable), and do some cleanups]

Signed-off-by: Huang Ying <ying.huang@intel.com>
Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
Signed-off-by: Chen, Gong <gong.chen@linux.intel.com>
Tested-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Tested-by: Fu Wei <fu.wei@linaro.org>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 Documentation/kernel-parameters.txt |   3 +
 drivers/acpi/apei/Makefile          |   2 +-
 drivers/acpi/apei/bert.c            | 162 ++++++++++++++++++++++++++++++++++++
 include/acpi/apei.h                 |   1 +
 4 files changed, 167 insertions(+), 1 deletion(-)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 1d6f045..7c6402c 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -554,6 +554,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
 	bootmem_debug	[KNL] Enable bootmem allocator debug messages.
 
+	bert_disable	[ACPI]
+			Disable Boot Error Record Table (BERT) support.
+
 	bttv.card=	[HW,V4L] bttv (bt848 + bt878 based grabber cards)
 	bttv.radio=	Most important insmod options are available as
 			kernel args too.
diff --git a/drivers/acpi/apei/Makefile b/drivers/acpi/apei/Makefile
index 5d575a9..e50573d 100644
--- a/drivers/acpi/apei/Makefile
+++ b/drivers/acpi/apei/Makefile
@@ -3,4 +3,4 @@ obj-$(CONFIG_ACPI_APEI_GHES)	+= ghes.o
 obj-$(CONFIG_ACPI_APEI_EINJ)	+= einj.o
 obj-$(CONFIG_ACPI_APEI_ERST_DEBUG) += erst-dbg.o
 
-apei-y := apei-base.o hest.o erst.o
+apei-y := apei-base.o hest.o erst.o bert.o
diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c
new file mode 100644
index 0000000..1426227
--- /dev/null
+++ b/drivers/acpi/apei/bert.c
@@ -0,0 +1,162 @@
+/*
+ * APEI Boot Error Record Table (BERT) support
+ *
+ * Copyright 2011 Intel Corp.
+ *   Author: Huang Ying <ying.huang@intel.com>
+ *
+ * Under normal circumstances, when a hardware error occurs, kernel
+ * will be notified via NMI, MCE or some other method, then kernel
+ * will process the error condition, report it, and recover it if
+ * possible. But sometime, the situation is so bad, so that firmware
+ * may choose to reset directly without notifying Linux kernel.
+ *
+ * Linux kernel can use the Boot Error Record Table (BERT) to get the
+ * un-notified hardware errors that occurred in a previous boot.
+ *
+ * For more information about BERT, please refer to ACPI Specification
+ * version 4.0, section 17.3.1
+ *
+ * This file is licensed under GPLv2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/io.h>
+
+#include "apei-internal.h"
+
+#define BERT_PFX "BERT: "
+
+static int bert_disable;
+
+static void __init bert_print_all(struct acpi_hest_generic_status *region,
+				  unsigned int region_len)
+{
+	struct acpi_hest_generic_status *estatus = region;
+	int remain = region_len;
+	u32 estatus_len;
+	int first = 1;
+
+	while (remain > sizeof(struct acpi_hest_generic_status)) {
+		/* No more error record */
+		if (!estatus->block_status)
+			break;
+
+		estatus_len = cper_estatus_len(estatus);
+		if (estatus_len < sizeof(struct acpi_hest_generic_status) ||
+		    remain < estatus_len) {
+			pr_err(FW_BUG BERT_PFX
+			       "Invalid error status block with length %u\n",
+			       estatus_len);
+			return;
+		}
+
+		if (cper_estatus_check(estatus)) {
+			pr_err(FW_BUG BERT_PFX "Invalid error status block\n");
+			goto next;
+		}
+
+		if (first) {
+			pr_info(HW_ERR "Error record from previous boot:\n");
+			first = 0;
+		}
+
+		cper_estatus_print(KERN_INFO HW_ERR, estatus);
+next:
+		estatus = (void *)estatus + estatus_len;
+		remain -= estatus_len;
+	}
+}
+
+static int __init setup_bert_disable(char *str)
+{
+	bert_disable = 1;
+
+	return 0;
+}
+__setup("bert_disable", setup_bert_disable);
+
+static int __init bert_check_table(struct acpi_table_bert *bert_tab)
+{
+	if (bert_tab->header.length < sizeof(struct acpi_table_bert))
+		return -EINVAL;
+	if (bert_tab->region_length &&
+	    bert_tab->region_length < sizeof(struct acpi_bert_region))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int __init bert_init(void)
+{
+	struct acpi_hest_generic_status *bert_region;
+	struct acpi_table_bert *bert_tab;
+	unsigned int region_len;
+	acpi_status status;
+	struct resource *r;
+	int rc = -EINVAL;
+
+	if (acpi_disabled)
+		goto out;
+
+	if (bert_disable) {
+		pr_info(BERT_PFX "Boot Error Record Table (BERT) support is disabled.\n");
+		goto out;
+	}
+
+	status = acpi_get_table(ACPI_SIG_BERT, 0,
+				(struct acpi_table_header **)&bert_tab);
+	if (status == AE_NOT_FOUND) {
+		pr_err(BERT_PFX "Table is not found!\n");
+		goto out;
+	} else if (ACPI_FAILURE(status)) {
+		const char *msg = acpi_format_exception(status);
+
+		pr_err(BERT_PFX "Failed to get table, %s\n", msg);
+		goto out;
+	}
+
+	rc = bert_check_table(bert_tab);
+	if (rc) {
+		pr_err(FW_BUG BERT_PFX "BERT table is invalid\n");
+		goto out;
+	}
+
+	region_len = bert_tab->region_length;
+	if (!region_len) {
+		rc = 0;
+		goto out;
+	}
+
+	r = request_mem_region(bert_tab->address, region_len, "APEI BERT");
+	if (!r) {
+		pr_err(BERT_PFX "Can't request iomem region <%016llx-%016llx>\n",
+		       (unsigned long long)bert_tab->address,
+		       (unsigned long long)bert_tab->address + region_len - 1);
+		rc = -EIO;
+		goto out;
+	}
+
+	bert_region = ioremap_cache(bert_tab->address, region_len);
+	if (!bert_region) {
+		rc = -ENOMEM;
+		goto out_release;
+	}
+
+	bert_print_all(bert_region, region_len);
+
+	iounmap(bert_region);
+
+out_release:
+	release_mem_region(bert_tab->address, region_len);
+out:
+	if (rc)
+		bert_disable = 1;
+
+	return rc;
+}
+
+late_initcall(bert_init);
diff --git a/include/acpi/apei.h b/include/acpi/apei.h
index 76284bb..284801a 100644
--- a/include/acpi/apei.h
+++ b/include/acpi/apei.h
@@ -23,6 +23,7 @@ extern bool ghes_disable;
 #else
 #define ghes_disable 1
 #endif
+extern int bert_disable;
 
 #ifdef CONFIG_ACPI_APEI
 void __init acpi_hest_init(void);
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v2 2/2] acpi, apei, bert: Clear error status at the end of error handling
  2015-08-18 16:44 ` [PATCH v2 0/2] acpi, apei: add BERT support fu.wei
  2015-08-18 16:44   ` [PATCH v2 1/2] acpi, apei: add Boot Error Record Table (BERT) support fu.wei
@ 2015-08-18 16:44   ` fu.wei
  2015-12-16 10:30     ` Borislav Petkov
  2015-12-15 16:39   ` [Linaro-acpi] [PATCH v2 0/2] acpi, apei: add BERT support Timur Tabi
  2 siblings, 1 reply; 550+ messages in thread
From: fu.wei @ 2015-08-18 16:44 UTC (permalink / raw)
  To: linaro-acpi, linux-kernel, zjzhang, tony.luck, gong.chen,
	ying.huang, tomasz.nowicki
  Cc: tekkamanninja, graeme.gregory, al.stone, hanjun.guo, jcm,
	mark.rutland, catalin.marinas, will.deacon, rjw, bp,
	matt.fleming, Chen, Gong

From: Tomasz Nowicki <tomasz.nowicki@linaro.org>

Once error log is printed out clear error status so it would not be
print during next boot again.

Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
Signed-off-by: Chen, Gong <gong.chen@linux.intel.com>
Tested-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 drivers/acpi/apei/bert.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c
index 1426227..dc2b79f 100644
--- a/drivers/acpi/apei/bert.c
+++ b/drivers/acpi/apei/bert.c
@@ -65,6 +65,9 @@ static void __init bert_print_all(struct acpi_hest_generic_status *region,
 		}
 
 		cper_estatus_print(KERN_INFO HW_ERR, estatus);
+
+		/* Clear error status */
+		estatus->block_status = 0;
 next:
 		estatus = (void *)estatus + estatus_len;
 		remain -= estatus_len;
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver
       [not found] <=fu.wei@linaro.org>
                   ` (12 preceding siblings ...)
  2015-08-18 16:44 ` [PATCH v2 0/2] acpi, apei: add BERT support fu.wei
@ 2015-08-24 17:01 ` fu.wei
  2015-08-24 17:01   ` [PATCH v7 1/8] Documentation: add sbsa-gwdt.txt documentation fu.wei
                     ` (8 more replies)
  2016-02-25  6:50 ` [PATCH v2 0/4] arm64,xen: add xen_boot support into grup-mkconfig fu.wei
  14 siblings, 9 replies; 550+ messages in thread
From: fu.wei @ 2015-08-24 17:01 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, hanjun.guo, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, arnd, linux, vgandhi,
	wim, jcm, leo.duran, corbet, mark.rutland, catalin.marinas,
	will.deacon, rjw, dyoung, panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patchset:
    (1)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.

    (2)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".

    (3)Introduce ARM SBSA watchdog driver:
        a.Use linux kernel watchdog framework;
        b.Work with FDT on ARM64;
        c.Use "pretimeout" in watchdog framework;
        d.Support getting timeout and pretimeout from parameter and FDT
          at the driver init stage.
        e.In the first timeout, do panic to save system context;
        f.In the second stage, user can still feed the dog without
          cleaning WS0. By this feature, we can avoid the panic infinite
          loops, while backing up a large system context in a server.
        g.In the second stage, can trigger WS1 by setting pretimeout = 0
          if necessary.

    (4)Introduce ACPI GTDT parser: drivers/acpi/gtdt.c
    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.
    drivers/clocksource/arm_arch_timer.c is simplified by this GTDT support.

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

Changelog:
v7: Rebase to latest kernel version(4.2-rc7).
    Improve FDT support: geting resource by order, instead of name.
    According to the FDT support, Update the example dts file, gtdt.c
    and sbsa_gwdt.c.
    Pass the sparse test, and fix the warning.
    Fix the max_pretimeout and max_timeout value overflow bug.
    Delete the WCV output value.
    

v6: Improve the dtb example files: reduce the register frame size to 4K.
    Improve pretimeout support:
        (1) improve watchdog_init_timeouts function
	(2) rename watchdog_check_min_max_timeouts back to the original name
        (1) improve watchdog_timeout_invalid/watchdog_pretimeout_invalid
    Add the new features in the sbsa_gwdt driver:
	(1) In the second stage, user can feed the dog without cleaning WS0.
	(2) In the second stage, user can trigger WS1 by setting pretimeout = 0.
	(3) expand the max value of pretimeout, in case 10 second is not enough
	    for a kdump kernel reboot in panic.

v5: Improve pretimeout support:
        (1)fix typo in documentation and comments.
	(2)fix the timeout limits validation bug.
    Simplify sbsa_gwdt driver:
	(1)integrate all the registers access functions into caller.

v4: Refactor GTDT support code: remove it from arch/arm64/kernel/acpi.c,
    put it into drivers/acpi/gtdt.c file.
    Integrate the GTDT code of drivers/clocksource/arm_arch_timer.c into
    drivers/acpi/gtdt.c.
    Improve pretimeout support, fix "pretimeout == 0" problem.
    Simplify sbsa_gwdt driver:
        (1)timeout/pretimeout limits setup;
        (2)keepalive function;
        (3)delete "clk == 0" check;
        (4)delete WS0 status bit check in interrupt routine;
        (5)sbsa_gwdt_set_wcv function.

v3: Delete "export arch_timer_get_rate" patch.
    Driver back to use arch_timer_get_cntfrq.
    Improve watchdog_init_timeouts function and update relevant documentation.
    Improve watchdog_timeout_invalid and watchdog_pretimeout_invalid.
    Improve foundation-v8.dts: delete the unnecessary tag of device node.
    Remove "ARM64 || COMPILE_TEST" from Kconfig.
    Add comments in arch/arm64/kernel/acpi.c
    Fix typoes and incorrect comments.

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 (8):
  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: introdouce "pretimeout" into framework
  Watchdog: introduce ARM SBSA watchdog driver
  ACPI: add GTDT table parse driver into ACPI driver
  Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
  clocksource: simplify ACPI code in arm_arch_timer.c

 .../devicetree/bindings/watchdog/sbsa-gwdt.txt     |  32 ++
 Documentation/watchdog/watchdog-kernel-api.txt     |  47 ++-
 arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi       |   8 +
 arch/arm64/boot/dts/arm/foundation-v8.dts          |   7 +
 arch/arm64/kernel/time.c                           |   4 +-
 drivers/acpi/Kconfig                               |   9 +
 drivers/acpi/Makefile                              |   1 +
 drivers/acpi/gtdt.c                                | 178 ++++++++
 drivers/clocksource/Kconfig                        |   1 +
 drivers/clocksource/arm_arch_timer.c               |  60 +--
 drivers/watchdog/Kconfig                           |  15 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/sbsa_gwdt.c                       | 459 +++++++++++++++++++++
 drivers/watchdog/watchdog_core.c                   |  98 +++--
 drivers/watchdog/watchdog_dev.c                    |  53 +++
 include/clocksource/arm_arch_timer.h               |   8 +
 include/linux/acpi.h                               |   5 +
 include/linux/clocksource.h                        |   4 +-
 include/linux/watchdog.h                           |  39 +-
 19 files changed, 939 insertions(+), 90 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
 create mode 100644 drivers/acpi/gtdt.c
 create mode 100644 drivers/watchdog/sbsa_gwdt.c

-- 
2.4.3


^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v7 1/8] Documentation: add sbsa-gwdt.txt documentation
  2015-08-24 17:01 ` [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
@ 2015-08-24 17:01   ` fu.wei
  2015-08-24 17:01   ` [PATCH v7 2/8] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts fu.wei
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-08-24 17:01 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, hanjun.guo, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, arnd, linux, vgandhi,
	wim, jcm, leo.duran, corbet, mark.rutland, catalin.marinas,
	will.deacon, rjw, dyoung, panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 .../devicetree/bindings/watchdog/sbsa-gwdt.txt     | 32 ++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt b/Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
new file mode 100644
index 0000000..8b43640
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt
@@ -0,0 +1,32 @@
+* 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 : Specifies base physical address of the two register frames
+  and length of memory mapped region, order:
+  1: Watchdog control frame
+  2: Refresh frame.
+
+- interrupts : Should at least contain WS0 interrupt,
+  the WS1 interrupt is optional, order:
+  1: WS0 interrupt
+  2: WS1 interrupt
+
+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@2a440000 {
+	compatible = "arm,sbsa-gwdt";
+	reg = <0x0 0x2a440000 0 0x1000>,
+	      <0x0 0x2a450000 0 0x1000>;
+	interrupts = <0 27 4>;
+	timeout-sec = <10 5>;
+};
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v7 2/8] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
  2015-08-24 17:01 ` [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
  2015-08-24 17:01   ` [PATCH v7 1/8] Documentation: add sbsa-gwdt.txt documentation fu.wei
@ 2015-08-24 17:01   ` fu.wei
  2015-09-15  8:43       ` Dave Young
  2015-08-24 17:01   ` [PATCH v7 3/8] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi fu.wei
                     ` (6 subsequent siblings)
  8 siblings, 1 reply; 550+ messages in thread
From: fu.wei @ 2015-08-24 17:01 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, hanjun.guo, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, arnd, linux, vgandhi,
	wim, jcm, leo.duran, corbet, mark.rutland, catalin.marinas,
	will.deacon, rjw, dyoung, panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 arch/arm64/boot/dts/arm/foundation-v8.dts | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dts b/arch/arm64/boot/dts/arm/foundation-v8.dts
index 4eac8dc..824431f 100644
--- a/arch/arm64/boot/dts/arm/foundation-v8.dts
+++ b/arch/arm64/boot/dts/arm/foundation-v8.dts
@@ -237,4 +237,11 @@
 			};
 		};
 	};
+	watchdog@2a440000 {
+		compatible = "arm,sbsa-gwdt";
+		reg = <0x0 0x2a440000 0 0x1000>,
+			<0x0 0x2a450000 0 0x1000>;
+		interrupts = <0 27 4>;
+		timeout-sec = <10 5>;
+	};
 };
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v7 3/8] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi
  2015-08-24 17:01 ` [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
  2015-08-24 17:01   ` [PATCH v7 1/8] Documentation: add sbsa-gwdt.txt documentation fu.wei
  2015-08-24 17:01   ` [PATCH v7 2/8] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts fu.wei
@ 2015-08-24 17:01   ` fu.wei
  2015-08-24 17:01   ` [PATCH v7 4/8] Watchdog: introdouce "pretimeout" into framework fu.wei
                     ` (5 subsequent siblings)
  8 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-08-24 17:01 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, hanjun.guo, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, arnd, linux, vgandhi,
	wim, jcm, leo.duran, corbet, mark.rutland, catalin.marinas,
	will.deacon, rjw, dyoung, panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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

Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi | 8 ++++++++
 1 file changed, 8 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..259430f 100644
--- a/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi
+++ b/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi
@@ -84,6 +84,14 @@
 			clock-names = "uartclk", "apb_pclk";
 		};
 
+		watchdog0: watchdog@e0bb0000 {
+			compatible = "arm,sbsa-gwdt";
+			reg = <0x0 0xe0bc0000 0 0x1000>,
+				<0x0 0xe0bb0000 0 0x1000>;
+			interrupts = <0 337 4>;
+			timeout-sec = <10 5>;
+		};
+
 		spi0: ssp@e1020000 {
 			status = "disabled";
 			compatible = "arm,pl022", "arm,primecell";
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v7 4/8] Watchdog: introdouce "pretimeout" into framework
  2015-08-24 17:01 ` [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
                     ` (2 preceding siblings ...)
  2015-08-24 17:01   ` [PATCH v7 3/8] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi fu.wei
@ 2015-08-24 17:01   ` fu.wei
  2015-08-24 17:01   ` [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
                     ` (4 subsequent siblings)
  8 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-08-24 17:01 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, hanjun.guo, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, arnd, linux, vgandhi,
	wim, jcm, leo.duran, corbet, mark.rutland, catalin.marinas,
	will.deacon, rjw, dyoung, panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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 drivers are going to use this: ARM SBSA Generic Watchdog

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 Documentation/watchdog/watchdog-kernel-api.txt | 47 ++++++++++--
 drivers/watchdog/watchdog_core.c               | 98 ++++++++++++++++++--------
 drivers/watchdog/watchdog_dev.c                | 53 ++++++++++++++
 include/linux/watchdog.h                       | 39 ++++++++--
 4 files changed, 200 insertions(+), 37 deletions(-)

diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index d8b0d33..1fadeb9 100644
--- a/Documentation/watchdog/watchdog-kernel-api.txt
+++ b/Documentation/watchdog/watchdog-kernel-api.txt
@@ -53,6 +53,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;
@@ -75,6 +78,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.
@@ -99,6 +105,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 *);
@@ -160,9 +167,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.
@@ -226,8 +243,28 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
                                   unsigned int timeout_parm, struct device *dev);
 
 The watchdog_init_timeout function allows you to initialize the timeout field
-using the module timeout parameter or by retrieving the timeout-sec property from
-the device tree (if the module timeout parameter is invalid). Best practice is
-to set the default timeout value as timeout value in the watchdog_device and
-then use this function to set the user "preferred" timeout value.
+using the module timeout parameter or by retrieving the first element of
+the timeout-sec property from the device tree (if the module timeout parameter
+is invalid). Best practice is to set the default timeout value as timeout value
+in the watchdog_device and then use this function to set the user "preferred"
+timeout value.
+This routine returns zero on success and a negative errno code for failure.
+
+Some watchdog timers have two stage of timeouts (timeout and pretimeout),
+to initialize the timeout and pretimeout fields at the same time, the following
+function can be used:
+
+int watchdog_init_timeouts(struct watchdog_device *wdd,
+                                  unsigned int pretimeout_parm,
+                                  unsigned int timeout_parm,
+                                  struct device *dev);
+
+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).
+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.
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index 1a80594..280c399 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -85,57 +85,99 @@ static void watchdog_deferred_registration_del(struct watchdog_device *wdd)
 static void watchdog_check_min_max_timeout(struct watchdog_device *wdd)
 {
 	/*
-	 * Check that we have valid min and max timeout values, if
-	 * not reset them both to 0 (=not used or unknown)
+	 * Check that we have valid min and max pretimeout and timeout values,
+	 * if not, reset them all to 0 (=not used or unknown)
 	 */
-	if (wdd->min_timeout > wdd->max_timeout) {
-		pr_info("Invalid min and max timeout values, resetting to 0!\n");
+	if (wdd->min_pretimeout > wdd->max_pretimeout ||
+	    wdd->min_timeout > wdd->max_timeout ||
+	    wdd->min_timeout < wdd->min_pretimeout ||
+	    wdd->max_timeout < wdd->max_pretimeout) {
+		pr_info("Invalid min or max timeouts, resetting to 0\n");
+		wdd->min_pretimeout = 0;
+		wdd->max_pretimeout = 0;
 		wdd->min_timeout = 0;
 		wdd->max_timeout = 0;
 	}
 }
 
 /**
- * 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 both the pretimeout and timeout module parameters (if they are valid) or
+ * the timeout-sec property (only if they are valid and the pretimeout_parm or
+ * timeout_parm is out of bounds). If one of them is invalid, 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,
+			   struct device *dev)
 {
-	unsigned int t = 0;
-	int ret = 0;
+	int ret = 0, length = 0;
+	u32 timeouts[2] = {0};
+	struct property *prop;
 
 	watchdog_check_min_max_timeout(wdd);
 
-	/* try to get the timeout module parameter first */
-	if (!watchdog_timeout_invalid(wdd, timeout_parm) && timeout_parm) {
-		wdd->timeout = timeout_parm;
-		return ret;
-	}
-	if (timeout_parm)
+	/*
+	 * Try to get the pretimeout module parameter first.
+	 * Note: zero is a valid value for pretimeout.
+	 */
+	if (watchdog_pretimeout_invalid(wdd, pretimeout_parm))
+		ret = -EINVAL;
+
+	/*
+	 * Try to get the timeout module parameter,
+	 * if it's valid and pretimeout is valid(ret == 0),
+	 * assignment and return zero. Otherwise, try dtb.
+	 */
+	if (timeout_parm && !ret) {
+		if (!watchdog_timeout_invalid(wdd, timeout_parm)) {
+			wdd->timeout = timeout_parm;
+			wdd->pretimeout = pretimeout_parm;
+			return 0;
+		}
 		ret = -EINVAL;
+	}
 
-	/* try to get the timeout_sec property */
+	/*
+	 * Either at least one of the module parameters is invalid,
+	 * or timeout_parm is 0. 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
-		ret = -EINVAL;
 
-	return ret;
+	prop = of_find_property(dev->of_node, "timeout-sec", &length);
+	if (prop && length > 0 && length <= sizeof(u32) * 2) {
+		of_property_read_u32_array(dev->of_node,
+					   "timeout-sec", timeouts,
+					   length / sizeof(u32));
+		if (length == sizeof(u32) * 2) {
+			if (watchdog_pretimeout_invalid(wdd, timeouts[1]))
+				return -EINVAL;
+			ret = 0;
+		} else {
+			ret = -EINVAL;
+		}
+
+		if (!watchdog_timeout_invalid(wdd, timeouts[0]) &&
+		    timeouts[0]) {
+			wdd->timeout = timeouts[0];
+			if (!ret)
+				wdd->pretimeout = timeouts[1];
+			return 0;
+		}
+	}
+
+	return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(watchdog_init_timeout);
+EXPORT_SYMBOL_GPL(watchdog_init_timeouts);
 
 static int __watchdog_register_device(struct watchdog_device *wdd)
 {
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 6aaefba..af0777e 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,27 @@ 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:
+		/* check if we support the pretimeout */
+		if (!(wdd->info->options & WDIOF_PRETIMEOUT))
+			return -EOPNOTSUPP;
+		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 keeps running (and if
+		 * possible that it takes the new pretimeout)
+		 */
+		watchdog_ping(wdd);
+		/* Fall */
+	case WDIOC_GETPRETIMEOUT:
+		/* check if we support the pretimeout */
+		if (wdd->info->options & WDIOF_PRETIMEOUT)
+			return put_user(wdd->pretimeout, p);
+		return -EOPNOTSUPP;
 	case WDIOC_GETTIMELEFT:
 		err = watchdog_get_timeleft(wdd, &val);
 		if (err)
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index f47fead..bf2d9e9 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.
@@ -88,6 +93,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;
@@ -119,8 +127,22 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
 /* Use the following function to check if a timeout value is invalid */
 static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
 {
-	return ((wdd->max_timeout != 0) &&
-		(t < wdd->min_timeout || t > wdd->max_timeout));
+	return (wdd->max_timeout &&
+		(t < wdd->min_timeout || t > wdd->max_timeout)) ||
+	       (wdd->pretimeout && t <= wdd->pretimeout);
+}
+
+/*
+ * Use the following function to check if a pretimeout value is invalid.
+ * It can be "0", that means we don't use pretimeout.
+ * This function returns false, when pretimeout is 0.
+ */
+static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd,
+					       unsigned int t)
+{
+	return t && ((wdd->max_pretimeout &&
+		      (t < wdd->min_pretimeout || t > wdd->max_pretimeout)) ||
+		     (wdd->timeout && t >= wdd->timeout));
 }
 
 /* Use the following functions to manipulate watchdog driver specific data */
@@ -135,8 +157,17 @@ 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);
+int watchdog_init_timeouts(struct watchdog_device *wdd,
+			   unsigned int pretimeout_parm,
+			   unsigned int timeout_parm,
+			   struct device *dev);
+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, dev);
+}
+
 extern int watchdog_register_device(struct watchdog_device *);
 extern void watchdog_unregister_device(struct watchdog_device *);
 
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver
  2015-08-24 17:01 ` [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
                     ` (3 preceding siblings ...)
  2015-08-24 17:01   ` [PATCH v7 4/8] Watchdog: introdouce "pretimeout" into framework fu.wei
@ 2015-08-24 17:01   ` fu.wei
  2015-09-10 22:29     ` Jon Masters
  2015-09-15  8:38     ` Dave Young
  2015-08-24 17:01   ` [PATCH v7 6/8] ACPI: add GTDT table parse driver into ACPI driver fu.wei
                     ` (3 subsequent siblings)
  8 siblings, 2 replies; 550+ messages in thread
From: fu.wei @ 2015-08-24 17:01 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, hanjun.guo, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, arnd, linux, vgandhi,
	wim, jcm, leo.duran, corbet, mark.rutland, catalin.marinas,
	will.deacon, rjw, dyoung, panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

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, the interrupt routine run panic to save
system context.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 drivers/watchdog/Kconfig     |  14 ++
 drivers/watchdog/Makefile    |   1 +
 drivers/watchdog/sbsa_gwdt.c | 459 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 474 insertions(+)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 241fafd..b2734f0 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -173,6 +173,20 @@ 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 ARM64
+	depends on ARM_ARCH_TIMER
+	select WATCHDOG_CORE
+	help
+	  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.
+	  More details: ARM DEN0029B - Server Base System Architecture (SBSA)
+
+	  To compile this driver as module, choose M here: The module
+	  will be called sbsa_gwdt.
+
 config AT91RM9200_WATCHDOG
 	tristate "AT91RM9200 watchdog"
 	depends on SOC_AT91RM9200 && MFD_SYSCON
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 59ea9a1..be8e7c5 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..7ae45cc
--- /dev/null
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -0,0 +1,459 @@
+/*
+ * SBSA(Server Base System Architecture) Generic Watchdog driver
+ *
+ * Copyright (c) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei@linaro.org>
+ *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
+ *
+ * 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.
+ *
+ * The SBSA Generic watchdog driver is compatible with the pretimeout
+ * concept of Linux kernel.
+ * The timeout and pretimeout are determined by WCV or WOR.
+ * The first watch period is set by writing WCV directly, that can
+ * support more than 10s timeout at the maximum system counter
+ * frequency (400MHz).
+ * When WS0 is triggered, the second watch period (pretimeout) is
+ * determined by one of these registers:
+ * (1)WOR: 32bit register, this gives a maximum watch period of
+ * around 10s at the maximum system counter frequency. It's loaded
+ * automatically by hardware.
+ * (2)WCV: If the pretimeout value is greater then "max_wor_timeout",
+ * it will be loaded in WS0 interrupt routine. If system is in
+ * ws0_mode (reboot by kexec/kdump in panic with watchdog enabled
+ * and WS0 == true), the ping operation will only reload WCV.
+ * More details about the hardware specification of this device:
+ * ARM DEN0029B - Server Base System Architecture (SBSA)
+ *
+ * Kernel/API:                         P------------------| pretimeout
+ *               |----------------------------------------T timeout
+ * SBSA GWDT:                          P---WOR (or WCV)---WS1 pretimeout
+ *               |-------WCV----------WS0~~~(ws0_mode)~~~~T timeout
+ */
+
+#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>
+#include <asm/arch_timer.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.
+ * @ws0_mode:		indicate the system boot in the second stage timeout.
+ * @max_wor_timeout:	the maximum timeout value for WOR (in seconds).
+ * @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;
+	bool			ws0_mode;
+	int			max_wor_timeout;
+	void __iomem		*refresh_base;
+	void __iomem		*control_base;
+};
+
+#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
+
+#define DEFAULT_TIMEOUT		30 /* seconds, the 1st + 2nd watch periods*/
+#define DEFAULT_PRETIMEOUT	10 /* 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 pretimeout;
+module_param(pretimeout, uint, 0);
+MODULE_PARM_DESC(pretimeout,
+		 "Watchdog pretimeout in seconds. (>=0, default="
+		 __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
+
+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) ")");
+
+/*
+ * help functions for accessing 64bit WCV register
+ */
+static u64 sbsa_gwdt_get_wcv(struct watchdog_device *wdd)
+{
+	u32 wcv_lo, wcv_hi;
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	do {
+		wcv_hi = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_HI);
+		wcv_lo = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_LO);
+	} while (wcv_hi != readl_relaxed(gwdt->control_base +
+					 SBSA_GWDT_WCV_HI));
+
+	return (((u64)wcv_hi << 32) | wcv_lo);
+}
+
+static void sbsa_gwdt_set_wcv(struct watchdog_device *wdd, unsigned int t)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+	u64 wcv;
+
+	wcv = arch_counter_get_cntvct() + (u64)t * gwdt->clk;
+
+	writel_relaxed(upper_32_bits(wcv),
+		       gwdt->control_base + SBSA_GWDT_WCV_HI);
+	writel_relaxed(lower_32_bits(wcv),
+		       gwdt->control_base + SBSA_GWDT_WCV_LO);
+}
+
+/*
+ * inline functions for reloading 64bit WCV register
+ */
+static inline void reload_pretimeout_to_wcv(struct watchdog_device *wdd)
+{
+	sbsa_gwdt_set_wcv(wdd, wdd->pretimeout);
+}
+
+static inline void reload_first_stage_to_wcv(struct watchdog_device *wdd)
+{
+	sbsa_gwdt_set_wcv(wdd, wdd->timeout - wdd->pretimeout);
+}
+
+/*
+ * watchdog operation functions
+ */
+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;
+
+	/* If ws0_mode == true, we won't touch WOR */
+	if (!gwdt->ws0_mode) {
+		if (!pretimeout)
+			/*
+			 * If pretimeout is 0, it gives driver a timeslot (1s)
+			 * to update WCV after an explicit refresh
+			 * (sbsa_gwdt_start)
+			 */
+			wor = gwdt->clk;
+		else
+			if (pretimeout > gwdt->max_wor_timeout)
+				wor = U32_MAX;
+			else
+				wor = pretimeout * gwdt->clk;
+
+		/* wtite WOR, that will cause an explicit watchdog refresh */
+		writel_relaxed(wor, gwdt->control_base + SBSA_GWDT_WOR);
+	}
+
+	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_keepalive(struct watchdog_device *wdd)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	if (gwdt->ws0_mode)
+		reload_pretimeout_to_wcv(wdd);
+	else
+		reload_first_stage_to_wcv(wdd);
+
+	return 0;
+}
+
+static int sbsa_gwdt_start(struct watchdog_device *wdd)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	/* If ws0_mode == true, the watchdog is enabled */
+	if (!gwdt->ws0_mode)
+		/* writing WCS will cause an explicit watchdog refresh */
+		writel_relaxed(SBSA_GWDT_WCS_EN,
+			       gwdt->control_base + SBSA_GWDT_WCS);
+
+	return sbsa_gwdt_keepalive(wdd);
+}
+
+static int sbsa_gwdt_stop(struct watchdog_device *wdd)
+{
+	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+	writel_relaxed(0, gwdt->control_base + SBSA_GWDT_WCS);
+	/*
+	 * Writing WCS has caused an explicit watchdog refresh.
+	 * Both watchdog signals are deasserted, so clean ws0_mode flag.
+	 */
+	gwdt->ws0_mode = false;
+
+	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;
+
+	/* We don't use pretimeout, trigger WS1 now */
+	if (!wdd->pretimeout)
+		sbsa_gwdt_set_wcv(wdd, 0);
+
+	/*
+	 * The pretimeout is valid, go panic
+	 * If pretimeout is greater then "max_wor_timeout",
+	 * reload the right value to WCV, then panic
+	 */
+	if (wdd->pretimeout > gwdt->max_wor_timeout)
+		reload_pretimeout_to_wcv(wdd);
+	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)
+{
+	void __iomem *rf_base, *cf_base;
+	struct device *dev = &pdev->dev;
+	struct watchdog_device *wdd;
+	struct sbsa_gwdt *gwdt;
+	struct resource *res;
+	int ret, irq;
+	u32 status;
+
+	gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
+	if (!gwdt)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, gwdt);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	cf_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(cf_base))
+		return PTR_ERR(cf_base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	rf_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(rf_base))
+		return PTR_ERR(rf_base);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(dev, "unable to get ws0 interrupt.\n");
+		return irq;
+	}
+
+	/*
+	 * Get the frequency of system counter from the cp15 interface of ARM
+	 * Generic timer. We don't need to check it, because if it returns "0",
+	 * system would panic in very early stage.
+	 */
+	gwdt->clk = arch_timer_get_cntfrq();
+	gwdt->refresh_base = rf_base;
+	gwdt->control_base = cf_base;
+	gwdt->max_wor_timeout = U32_MAX / gwdt->clk;
+	gwdt->ws0_mode = false;
+
+	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);
+
+	wdd->min_pretimeout = 0;
+	wdd->min_timeout = 1;
+
+	/*
+	 * Because the maximum of gwdt->clk is 400MHz and the maximum of WCV is
+	 * U64_MAX, so the result of (U64_MAX / gwdt->clk) is always greater
+	 * than U32_MAX. And the maximum of "unsigned int" is U32_MAX on ARM64.
+	 * So we set the maximum value of pretimeout and timeout below.
+	 */
+	wdd->max_pretimeout = U32_MAX - 1;
+	wdd->max_timeout = U32_MAX;
+
+	wdd->pretimeout = DEFAULT_PRETIMEOUT;
+	wdd->timeout = DEFAULT_TIMEOUT;
+	watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
+
+	status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
+	if (status & SBSA_GWDT_WCS_WS1) {
+		dev_warn(dev, "System reset by WDT.\n");
+		wdd->bootstatus |= WDIOF_CARDRESET;
+	} else if (status == (SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_EN)) {
+		gwdt->ws0_mode = true;
+	}
+
+	ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
+			       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;
+
+	/* If ws0_mode == true, the line won't update WOR */
+	sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
+
+	/*
+	 * If watchdog is already enabled, do a ping operation
+	 * to keep system running
+	 */
+	if (status & SBSA_GWDT_WCS_EN)
+		sbsa_gwdt_keepalive(wdd);
+
+	dev_info(dev, "Initialized with %ds timeout, %ds pretimeout @ %u Hz%s\n",
+		 wdd->timeout, wdd->pretimeout, gwdt->clk,
+		 status & SBSA_GWDT_WCS_EN ?
+			gwdt->ws0_mode ? " [second stage]" : " [enabled]" :
+			"");
+
+	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);
+
+	watchdog_unregister_device(&gwdt->wdd);
+
+	return 0;
+}
+
+/* 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_AUTHOR("Fu Wei <fu.wei@linaro.org>");
+MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
+MODULE_LICENSE("GPL v2");
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v7 6/8] ACPI: add GTDT table parse driver into ACPI driver
  2015-08-24 17:01 ` [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
                     ` (4 preceding siblings ...)
  2015-08-24 17:01   ` [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
@ 2015-08-24 17:01   ` fu.wei
  2015-08-24 17:01   ` [PATCH v7 7/8] Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver fu.wei
                     ` (2 subsequent siblings)
  8 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-08-24 17:01 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, hanjun.guo, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, arnd, linux, vgandhi,
	wim, jcm, leo.duran, corbet, mark.rutland, catalin.marinas,
	will.deacon, rjw, dyoung, panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This driver adds support for parsing SBSA Generic Watchdog
Structure in GTDT, and creating a platform device with that
information. This allows the operating system to obtain device
data from the resource of platform device.

The platform device named "sbsa-gwdt" can be used by the
ARM SBSA Generic Watchdog driver.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/acpi/Kconfig  |   9 ++++
 drivers/acpi/Makefile |   1 +
 drivers/acpi/gtdt.c   | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 145 insertions(+)

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 114cf48..2e7e162 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -479,4 +479,13 @@ config XPOWER_PMIC_OPREGION
 
 endif
 
+config ACPI_GTDT
+	bool "ACPI GTDT Support"
+	depends on ARM64
+	help
+	  GTDT (Generic Timer Description Table) provides information
+	  for per-processor timers and Platform (memory-mapped) timers
+	  for ARM platforms. Select this option to provide information
+	  needed for the timers init.
+
 endif	# ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 8321430..9a7966e 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -93,5 +93,6 @@ obj-$(CONFIG_ACPI_EXTLOG)	+= acpi_extlog.o
 obj-$(CONFIG_PMIC_OPREGION)	+= pmic/intel_pmic.o
 obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
 obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
+obj-$(CONFIG_ACPI_GTDT)		+= gtdt.o
 
 video-objs			+= acpi_video.o video_detect.o
diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
new file mode 100644
index 0000000..bbe3a2e
--- /dev/null
+++ b/drivers/acpi/gtdt.c
@@ -0,0 +1,135 @@
+/*
+ * ARM Specific GTDT table Support
+ *
+ * Copyright (C) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei@linaro.org>
+ *         Hanjun Guo <hanjun.guo@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
+{
+	int trigger, polarity;
+
+	if (!interrupt)
+		return 0;
+
+	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+			: ACPI_LEVEL_SENSITIVE;
+
+	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+			: ACPI_ACTIVE_HIGH;
+
+	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
+}
+
+/*
+ * Initialize a SBSA generic Watchdog platform device info from GTDT
+ * According to SBSA specification the size of refresh and control
+ * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
+ */
+static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
+					int index)
+{
+	struct platform_device *pdev;
+	int irq = map_generic_timer_interrupt(wd->timer_interrupt,
+					      wd->timer_flags);
+	struct resource res[] = {
+		DEFINE_RES_IRQ(irq),
+		DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
+		DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
+	};
+
+	pr_debug("GTDT: a Watchdog GT(0x%llx/0x%llx gsi:%u flags:0x%x)\n",
+		 wd->refresh_frame_address, wd->control_frame_address,
+		 wd->timer_interrupt, wd->timer_flags);
+
+	if (!(wd->refresh_frame_address &&
+	      wd->control_frame_address &&
+	      wd->timer_interrupt)) {
+		pr_err("GTDT: failed geting the device info.\n");
+		return -EINVAL;
+	}
+
+	if (irq < 0) {
+		pr_err("GTDT: failed to register GSI of the Watchdog GT.\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Add a platform device named "sbsa-gwdt" to match the platform driver.
+	 * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
+	 * The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get device
+	 * info below by matching this name.
+	 */
+	pdev = platform_device_register_simple("sbsa-gwdt", index, res,
+					       ARRAY_SIZE(res));
+	if (IS_ERR(pdev)) {
+		acpi_unregister_gsi(wd->timer_interrupt);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
+
+static int __init gtdt_platform_timer_parse(struct acpi_table_header *table)
+{
+	struct acpi_gtdt_header *header;
+	struct acpi_table_gtdt *gtdt;
+	void *gtdt_subtable;
+	int i, gwdt_index;
+	int ret = 0;
+
+	if (table->revision < 2) {
+		pr_warn("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 = 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;
+}
+
+static int __init gtdt_platform_timer_init(void)
+{
+	if (acpi_disabled)
+		return 0;
+
+	return acpi_table_parse(ACPI_SIG_GTDT, gtdt_platform_timer_parse);
+}
+
+device_initcall(gtdt_platform_timer_init);
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v7 7/8] Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver
  2015-08-24 17:01 ` [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
                     ` (5 preceding siblings ...)
  2015-08-24 17:01   ` [PATCH v7 6/8] ACPI: add GTDT table parse driver into ACPI driver fu.wei
@ 2015-08-24 17:01   ` fu.wei
  2015-08-24 17:01     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  2015-09-30 17:13   ` [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver Pratyush Anand
  8 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-08-24 17:01 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, hanjun.guo, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, arnd, linux, vgandhi,
	wim, jcm, leo.duran, corbet, mark.rutland, catalin.marinas,
	will.deacon, rjw, dyoung, panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patch enables ACPI GTDT support for ARM SBSA
watchdog driver automatically, if ACPI support is enabled.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 drivers/watchdog/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index b2734f0..2719093 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -178,6 +178,7 @@ config ARM_SBSA_WATCHDOG
 	depends on ARM64
 	depends on ARM_ARCH_TIMER
 	select WATCHDOG_CORE
+	select ACPI_GTDT if ACPI
 	help
 	  ARM SBSA Generic Watchdog. This watchdog has two Watchdog timeouts.
 	  The first timeout will trigger a panic; the second timeout will
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
@ 2015-08-24 17:01     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2015-08-24 17:01 UTC (permalink / raw)
  To: Suravee.Suthikulpanit, hanjun.guo, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, arnd, linux, vgandhi,
	wim, jcm, leo.duran, corbet, mark.rutland, catalin.marinas,
	will.deacon, rjw, dyoung, panand, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

The patch update arm_arch_timer driver to use the function
provided by the new GTDT driver of ACPI.
By this way, arm_arch_timer.c can be simplified, and separate
all the ACPI GTDT knowledge from this timer driver.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 arch/arm64/kernel/time.c             |  4 +--
 drivers/acpi/gtdt.c                  | 43 ++++++++++++++++++++++++++
 drivers/clocksource/Kconfig          |  1 +
 drivers/clocksource/arm_arch_timer.c | 60 +++++++-----------------------------
 include/clocksource/arm_arch_timer.h |  8 +++++
 include/linux/acpi.h                 |  5 +++
 include/linux/clocksource.h          |  4 +--
 7 files changed, 72 insertions(+), 53 deletions(-)

diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 42f9195..2cabea6 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -75,9 +75,9 @@ void __init time_init(void)
 
 	/*
 	 * Since ACPI or FDT will only one be available in the system,
-	 * we can use acpi_generic_timer_init() here safely
+	 * we can use arch_timer_acpi_init() here safely
 	 */
-	acpi_generic_timer_init();
+	arch_timer_acpi_init();
 
 	arch_timer_rate = arch_timer_get_rate();
 	if (!arch_timer_rate)
diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
index bbe3a2e..3559babf 100644
--- a/drivers/acpi/gtdt.c
+++ b/drivers/acpi/gtdt.c
@@ -17,6 +17,8 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
+#include <clocksource/arm_arch_timer.h>
+
 static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 {
 	int trigger, polarity;
@@ -33,6 +35,47 @@ static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
 }
 
+static struct arch_timer_data __initdata *arch_timer_data_p;
+
+static int __init arch_timer_data_init(struct acpi_table_header *table)
+{
+	struct acpi_table_gtdt *gtdt;
+
+	gtdt = container_of(table, struct acpi_table_gtdt, header);
+
+	arch_timer_data_p->phys_secure_ppi =
+		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
+					    gtdt->secure_el1_flags);
+
+	arch_timer_data_p->phys_nonsecure_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
+					    gtdt->non_secure_el1_flags);
+
+	arch_timer_data_p->virt_ppi =
+		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
+					    gtdt->virtual_timer_flags);
+
+	arch_timer_data_p->hyp_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
+					    gtdt->non_secure_el2_flags);
+
+	arch_timer_data_p->c3stop = !(gtdt->non_secure_el1_flags &
+				      ACPI_GTDT_ALWAYS_ON);
+
+	return 0;
+}
+
+/* Initialize the arch_timer_data struct for arm_arch_timer by GTDT info */
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data)
+{
+	if (acpi_disabled || !data)
+		return -EINVAL;
+
+	arch_timer_data_p = data;
+
+	return acpi_table_parse(ACPI_SIG_GTDT, arch_timer_data_init);
+}
+
 /*
  * Initialize a SBSA generic Watchdog platform device info from GTDT
  * According to SBSA specification the size of refresh and control
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 4e57730..e111025 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -119,6 +119,7 @@ config CLKSRC_STM32
 config ARM_ARCH_TIMER
 	bool
 	select CLKSRC_OF if OF
+	select ACPI_GTDT if ACPI
 
 config ARM_ARCH_TIMER_EVTSTREAM
 	bool "Support for ARM architected timer event stream generation"
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 0aa135d..99505bb 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -817,68 +817,30 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
 		       arch_timer_mem_init);
 
 #ifdef CONFIG_ACPI
-static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
-{
-	int trigger, polarity;
-
-	if (!interrupt)
-		return 0;
-
-	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
-			: ACPI_LEVEL_SENSITIVE;
-
-	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
-			: ACPI_ACTIVE_HIGH;
-
-	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
-}
-
 /* Initialize per-processor generic timer */
-static int __init arch_timer_acpi_init(struct acpi_table_header *table)
+void __init arch_timer_acpi_init(void)
 {
-	struct acpi_table_gtdt *gtdt;
+	struct arch_timer_data data;
 
 	if (arch_timers_present & ARCH_CP15_TIMER) {
 		pr_warn("arch_timer: already initialized, skipping\n");
-		return -EINVAL;
+		return;
 	}
 
-	gtdt = container_of(table, struct acpi_table_gtdt, header);
-
 	arch_timers_present |= ARCH_CP15_TIMER;
 
-	arch_timer_ppi[PHYS_SECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
-		gtdt->secure_el1_flags);
-
-	arch_timer_ppi[PHYS_NONSECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
-		gtdt->non_secure_el1_flags);
-
-	arch_timer_ppi[VIRT_PPI] =
-		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
-		gtdt->virtual_timer_flags);
+	if (gtdt_arch_timer_data_init(&data))
+		return;
 
-	arch_timer_ppi[HYP_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
-		gtdt->non_secure_el2_flags);
+	arch_timer_ppi[PHYS_SECURE_PPI] = data.phys_secure_ppi;
+	arch_timer_ppi[PHYS_NONSECURE_PPI] = data.phys_nonsecure_ppi;
+	arch_timer_ppi[VIRT_PPI] = data.virt_ppi;
+	arch_timer_ppi[HYP_PPI] = data.hyp_ppi;
+	/* Always-on capability */
+	arch_timer_c3stop = data.c3stop;
 
 	/* Get the frequency from CNTFRQ */
 	arch_timer_detect_rate(NULL, NULL);
-
-	/* Always-on capability */
-	arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
-
 	arch_timer_init();
-	return 0;
-}
-
-/* Initialize all the generic timers presented in GTDT */
-void __init acpi_generic_timer_init(void)
-{
-	if (acpi_disabled)
-		return;
-
-	acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init);
 }
 #endif
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 9916d0e..5deed9d 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -43,6 +43,14 @@ enum arch_timer_reg {
 
 #define ARCH_TIMER_EVT_STREAM_FREQ	10000	/* 100us */
 
+struct arch_timer_data {
+	int phys_secure_ppi;
+	int phys_nonsecure_ppi;
+	int virt_ppi;
+	int hyp_ppi;
+	bool c3stop;
+};
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 57c13df..6d7a290 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -449,6 +449,11 @@ void acpi_walk_dep_device_list(acpi_handle handle);
 struct platform_device *acpi_create_platform_device(struct acpi_device *);
 #define ACPI_PTR(_ptr)	(_ptr)
 
+#ifdef CONFIG_ACPI_GTDT
+struct arch_timer_data;
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data);
+#endif
+
 #else	/* !CONFIG_ACPI */
 
 #define acpi_disabled 1
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 278dd27..b250b75 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -253,9 +253,9 @@ static inline void clocksource_of_init(void) {}
 #endif
 
 #ifdef CONFIG_ACPI
-void acpi_generic_timer_init(void);
+void arch_timer_acpi_init(void);
 #else
-static inline void acpi_generic_timer_init(void) { }
+static inline void arch_timer_acpi_init(void) { }
 #endif
 
 #endif /* _LINUX_CLOCKSOURCE_H */
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
@ 2015-08-24 17:01     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  0 siblings, 0 replies; 550+ messages in thread
From: fu.wei-QSEj5FYQhm4dnm+yROfE0A @ 2015-08-24 17:01 UTC (permalink / raw)
  To: Suravee.Suthikulpanit-5C7GfCeVMHo,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA, panand-H+wXaHxf7aLQT0dZR+AlfA,
	Fu Wei

From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

The patch update arm_arch_timer driver to use the function
provided by the new GTDT driver of ACPI.
By this way, arm_arch_timer.c can be simplified, and separate
all the ACPI GTDT knowledge from this timer driver.

Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm64/kernel/time.c             |  4 +--
 drivers/acpi/gtdt.c                  | 43 ++++++++++++++++++++++++++
 drivers/clocksource/Kconfig          |  1 +
 drivers/clocksource/arm_arch_timer.c | 60 +++++++-----------------------------
 include/clocksource/arm_arch_timer.h |  8 +++++
 include/linux/acpi.h                 |  5 +++
 include/linux/clocksource.h          |  4 +--
 7 files changed, 72 insertions(+), 53 deletions(-)

diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 42f9195..2cabea6 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -75,9 +75,9 @@ void __init time_init(void)
 
 	/*
 	 * Since ACPI or FDT will only one be available in the system,
-	 * we can use acpi_generic_timer_init() here safely
+	 * we can use arch_timer_acpi_init() here safely
 	 */
-	acpi_generic_timer_init();
+	arch_timer_acpi_init();
 
 	arch_timer_rate = arch_timer_get_rate();
 	if (!arch_timer_rate)
diff --git a/drivers/acpi/gtdt.c b/drivers/acpi/gtdt.c
index bbe3a2e..3559babf 100644
--- a/drivers/acpi/gtdt.c
+++ b/drivers/acpi/gtdt.c
@@ -17,6 +17,8 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
+#include <clocksource/arm_arch_timer.h>
+
 static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 {
 	int trigger, polarity;
@@ -33,6 +35,47 @@ static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
 	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
 }
 
+static struct arch_timer_data __initdata *arch_timer_data_p;
+
+static int __init arch_timer_data_init(struct acpi_table_header *table)
+{
+	struct acpi_table_gtdt *gtdt;
+
+	gtdt = container_of(table, struct acpi_table_gtdt, header);
+
+	arch_timer_data_p->phys_secure_ppi =
+		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
+					    gtdt->secure_el1_flags);
+
+	arch_timer_data_p->phys_nonsecure_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
+					    gtdt->non_secure_el1_flags);
+
+	arch_timer_data_p->virt_ppi =
+		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
+					    gtdt->virtual_timer_flags);
+
+	arch_timer_data_p->hyp_ppi =
+		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
+					    gtdt->non_secure_el2_flags);
+
+	arch_timer_data_p->c3stop = !(gtdt->non_secure_el1_flags &
+				      ACPI_GTDT_ALWAYS_ON);
+
+	return 0;
+}
+
+/* Initialize the arch_timer_data struct for arm_arch_timer by GTDT info */
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data)
+{
+	if (acpi_disabled || !data)
+		return -EINVAL;
+
+	arch_timer_data_p = data;
+
+	return acpi_table_parse(ACPI_SIG_GTDT, arch_timer_data_init);
+}
+
 /*
  * Initialize a SBSA generic Watchdog platform device info from GTDT
  * According to SBSA specification the size of refresh and control
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 4e57730..e111025 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -119,6 +119,7 @@ config CLKSRC_STM32
 config ARM_ARCH_TIMER
 	bool
 	select CLKSRC_OF if OF
+	select ACPI_GTDT if ACPI
 
 config ARM_ARCH_TIMER_EVTSTREAM
 	bool "Support for ARM architected timer event stream generation"
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 0aa135d..99505bb 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -817,68 +817,30 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
 		       arch_timer_mem_init);
 
 #ifdef CONFIG_ACPI
-static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
-{
-	int trigger, polarity;
-
-	if (!interrupt)
-		return 0;
-
-	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
-			: ACPI_LEVEL_SENSITIVE;
-
-	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
-			: ACPI_ACTIVE_HIGH;
-
-	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
-}
-
 /* Initialize per-processor generic timer */
-static int __init arch_timer_acpi_init(struct acpi_table_header *table)
+void __init arch_timer_acpi_init(void)
 {
-	struct acpi_table_gtdt *gtdt;
+	struct arch_timer_data data;
 
 	if (arch_timers_present & ARCH_CP15_TIMER) {
 		pr_warn("arch_timer: already initialized, skipping\n");
-		return -EINVAL;
+		return;
 	}
 
-	gtdt = container_of(table, struct acpi_table_gtdt, header);
-
 	arch_timers_present |= ARCH_CP15_TIMER;
 
-	arch_timer_ppi[PHYS_SECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
-		gtdt->secure_el1_flags);
-
-	arch_timer_ppi[PHYS_NONSECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
-		gtdt->non_secure_el1_flags);
-
-	arch_timer_ppi[VIRT_PPI] =
-		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
-		gtdt->virtual_timer_flags);
+	if (gtdt_arch_timer_data_init(&data))
+		return;
 
-	arch_timer_ppi[HYP_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
-		gtdt->non_secure_el2_flags);
+	arch_timer_ppi[PHYS_SECURE_PPI] = data.phys_secure_ppi;
+	arch_timer_ppi[PHYS_NONSECURE_PPI] = data.phys_nonsecure_ppi;
+	arch_timer_ppi[VIRT_PPI] = data.virt_ppi;
+	arch_timer_ppi[HYP_PPI] = data.hyp_ppi;
+	/* Always-on capability */
+	arch_timer_c3stop = data.c3stop;
 
 	/* Get the frequency from CNTFRQ */
 	arch_timer_detect_rate(NULL, NULL);
-
-	/* Always-on capability */
-	arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
-
 	arch_timer_init();
-	return 0;
-}
-
-/* Initialize all the generic timers presented in GTDT */
-void __init acpi_generic_timer_init(void)
-{
-	if (acpi_disabled)
-		return;
-
-	acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init);
 }
 #endif
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 9916d0e..5deed9d 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -43,6 +43,14 @@ enum arch_timer_reg {
 
 #define ARCH_TIMER_EVT_STREAM_FREQ	10000	/* 100us */
 
+struct arch_timer_data {
+	int phys_secure_ppi;
+	int phys_nonsecure_ppi;
+	int virt_ppi;
+	int hyp_ppi;
+	bool c3stop;
+};
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 57c13df..6d7a290 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -449,6 +449,11 @@ void acpi_walk_dep_device_list(acpi_handle handle);
 struct platform_device *acpi_create_platform_device(struct acpi_device *);
 #define ACPI_PTR(_ptr)	(_ptr)
 
+#ifdef CONFIG_ACPI_GTDT
+struct arch_timer_data;
+int __init gtdt_arch_timer_data_init(struct arch_timer_data *data);
+#endif
+
 #else	/* !CONFIG_ACPI */
 
 #define acpi_disabled 1
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 278dd27..b250b75 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -253,9 +253,9 @@ static inline void clocksource_of_init(void) {}
 #endif
 
 #ifdef CONFIG_ACPI
-void acpi_generic_timer_init(void);
+void arch_timer_acpi_init(void);
 #else
-static inline void acpi_generic_timer_init(void) { }
+static inline void arch_timer_acpi_init(void) { }
 #endif
 
 #endif /* _LINUX_CLOCKSOURCE_H */
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
  2015-08-24 17:01     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
  (?)
@ 2015-08-24 17:50     ` Thomas Gleixner
  2015-08-25 17:19       ` Fu Wei
  -1 siblings, 1 reply; 550+ messages in thread
From: Thomas Gleixner @ 2015-08-24 17:50 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee.Suthikulpanit, hanjun.guo, linaro-acpi, linux-watchdog,
	devicetree, LKML, linux-doc, tekkamanninja, graeme.gregory,
	al.stone, Arnd Bergmann, linux, vgandhi, wim, Jon Masters,
	leo.duran, Jonathan Corbet, mark.rutland, catalin.marinas,
	will.deacon, rjw, dyoung, panand, Daniel Lezcano

On Tue, 25 Aug 2015, fu.wei@linaro.org wrote:

You Cc the world and some more on your patch, but you fail to add the
maintainers of the clocksource code to the Cc list. Sigh.

> From: Fu Wei <fu.wei@linaro.org>
> 
> The patch update arm_arch_timer driver to use the function
> provided by the new GTDT driver of ACPI.
> By this way, arm_arch_timer.c can be simplified, and separate
> all the ACPI GTDT knowledge from this timer driver.

That's not a proper changelog and this patch want's to be split in two:

1) Implement the new ACPI function

2) Make use of it
 
> index 0aa135d..99505bb 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -817,68 +817,30 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
>  		       arch_timer_mem_init);
>  
>  #ifdef CONFIG_ACPI
> -static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
> -{
> -	int trigger, polarity;
> -
> -	if (!interrupt)
> -		return 0;
> -
> -	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
> -			: ACPI_LEVEL_SENSITIVE;
> -
> -	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
> -			: ACPI_ACTIVE_HIGH;
> -
> -	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
> -}
> -
>  /* Initialize per-processor generic timer */
> -static int __init arch_timer_acpi_init(struct acpi_table_header *table)
> +void __init arch_timer_acpi_init(void)
>  {

And how is that supposed to work when we have next generation CPUs
which implement a different timer? You break multisystem kernels that
way.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
  2015-08-24 17:50     ` Thomas Gleixner
@ 2015-08-25 17:19       ` Fu Wei
  2015-08-25 19:17           ` Thomas Gleixner
  0 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-08-25 17:19 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Suravee Suthikulpanit, Hanjun Guo, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, LKML, linux-doc, Wei Fu, G Gregory,
	Al Stone, Arnd Bergmann, Guenter Roeck, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jonathan Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung, panand, Daniel Lezcano

Hi Thomas,


On 25 August 2015 at 01:50, Thomas Gleixner <tglx@linutronix.de> wrote:
> On Tue, 25 Aug 2015, fu.wei@linaro.org wrote:
>
> You Cc the world and some more on your patch, but you fail to add the
> maintainers of the clocksource code to the Cc list. Sigh.

my fault
So sorry for that, I will add the maintainers of clocksource into cc list.

>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> The patch update arm_arch_timer driver to use the function
>> provided by the new GTDT driver of ACPI.
>> By this way, arm_arch_timer.c can be simplified, and separate
>> all the ACPI GTDT knowledge from this timer driver.
>
> That's not a proper changelog and this patch want's to be split in two:
>
> 1) Implement the new ACPI function
>
> 2) Make use of it

Yes, you are right , will improve this

>
>> index 0aa135d..99505bb 100644
>> --- a/drivers/clocksource/arm_arch_timer.c
>> +++ b/drivers/clocksource/arm_arch_timer.c
>> @@ -817,68 +817,30 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
>>                      arch_timer_mem_init);
>>
>>  #ifdef CONFIG_ACPI
>> -static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
>> -{
>> -     int trigger, polarity;
>> -
>> -     if (!interrupt)
>> -             return 0;
>> -
>> -     trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
>> -                     : ACPI_LEVEL_SENSITIVE;
>> -
>> -     polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
>> -                     : ACPI_ACTIVE_HIGH;
>> -
>> -     return acpi_register_gsi(NULL, interrupt, trigger, polarity);
>> -}
>> -
>>  /* Initialize per-processor generic timer */
>> -static int __init arch_timer_acpi_init(struct acpi_table_header *table)
>> +void __init arch_timer_acpi_init(void)
>>  {
>
> And how is that supposed to work when we have next generation CPUs
> which implement a different timer? You break multisystem kernels that
> way.

yes, you are right, If there is a  next generation CPUs  which
implement a different timer, (maybe) this driver can not work.
we may need a new timer driver.

But,
(1) for now,  aarch64  core always has the arch timer(this timer is
part of aarch64 architecture).
and the existing code make  ARM64 kernel "select ARM_ARCH_TIMER "
(2) GTDT is designed for generic timer, so in this call "
arch_timer_acpi_init"  we  parse the gtdt info.

(3) once we have a ARM64 CPUs which implement a different timer, we
may need to select a right timer in the config stage.
and this timer may not be described in GTDT.  So we can implement
another arch_timer_acpi_init by that time in new timer driver..
if the new time still uses GTDT(or new version GTDT), we may need to
update gtdt.c for new timer by that time.

but before we really have this new timer, I think this code is OK to use.

Do I understand your comment correctly? :-)

>
> Thanks,
>
>         tglx



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
@ 2015-08-25 19:17           ` Thomas Gleixner
  0 siblings, 0 replies; 550+ messages in thread
From: Thomas Gleixner @ 2015-08-25 19:17 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Hanjun Guo, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, LKML, linux-doc, Wei Fu, G Gregory,
	Al Stone, Arnd Bergmann, Guenter Roeck, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jonathan Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung, panand, Daniel Lezcano

On Wed, 26 Aug 2015, Fu Wei wrote:
> >>  /* Initialize per-processor generic timer */
> >> -static int __init arch_timer_acpi_init(struct acpi_table_header *table)
> >> +void __init arch_timer_acpi_init(void)
> >>  {
> >
> > And how is that supposed to work when we have next generation CPUs
> > which implement a different timer? You break multisystem kernels that
> > way.
> 
> yes, you are right, If there is a  next generation CPUs  which
> implement a different timer, (maybe) this driver can not work.
> we may need a new timer driver.
> 
> But,
> (1) for now,  aarch64  core always has the arch timer(this timer is
> part of aarch64 architecture).
> and the existing code make  ARM64 kernel "select ARM_ARCH_TIMER "
> (2) GTDT is designed for generic timer, so in this call "
> arch_timer_acpi_init"  we  parse the gtdt info.
> (3) once we have a ARM64 CPUs which implement a different timer, we
> may need to select a right timer in the config stage.
> and this timer may not be described in GTDT.  So we can implement
> another arch_timer_acpi_init by that time in new timer driver..
> if the new time still uses GTDT(or new version GTDT), we may need to
> update gtdt.c for new timer by that time.

That's simply wrong. You want to build kernels which run on both cpus
and the selection of the timer happens at runtime depending on the
ACPI info. We do the same thing with device tree.
 
> but before we really have this new timer, I think this code is OK to use.

I don't think so, but I leave this decision to the ARM64 maintainers.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
@ 2015-08-25 19:17           ` Thomas Gleixner
  0 siblings, 0 replies; 550+ messages in thread
From: Thomas Gleixner @ 2015-08-25 19:17 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Hanjun Guo, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, LKML,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Arnd Bergmann, Guenter Roeck, Vipul Gandhi, Wim Van Sebroeck,
	Jon Masters, Leo Duran, Jonathan Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA, panand-H+wXaHxf7aLQT0dZR+AlfA,
	Daniel Lezcano

On Wed, 26 Aug 2015, Fu Wei wrote:
> >>  /* Initialize per-processor generic timer */
> >> -static int __init arch_timer_acpi_init(struct acpi_table_header *table)
> >> +void __init arch_timer_acpi_init(void)
> >>  {
> >
> > And how is that supposed to work when we have next generation CPUs
> > which implement a different timer? You break multisystem kernels that
> > way.
> 
> yes, you are right, If there is a  next generation CPUs  which
> implement a different timer, (maybe) this driver can not work.
> we may need a new timer driver.
> 
> But,
> (1) for now,  aarch64  core always has the arch timer(this timer is
> part of aarch64 architecture).
> and the existing code make  ARM64 kernel "select ARM_ARCH_TIMER "
> (2) GTDT is designed for generic timer, so in this call "
> arch_timer_acpi_init"  we  parse the gtdt info.
> (3) once we have a ARM64 CPUs which implement a different timer, we
> may need to select a right timer in the config stage.
> and this timer may not be described in GTDT.  So we can implement
> another arch_timer_acpi_init by that time in new timer driver..
> if the new time still uses GTDT(or new version GTDT), we may need to
> update gtdt.c for new timer by that time.

That's simply wrong. You want to build kernels which run on both cpus
and the selection of the timer happens at runtime depending on the
ACPI info. We do the same thing with device tree.
 
> but before we really have this new timer, I think this code is OK to use.

I don't think so, but I leave this decision to the ARM64 maintainers.

Thanks,

	tglx
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
  2015-08-25 19:17           ` Thomas Gleixner
@ 2015-08-27 12:02             ` Hanjun Guo
  -1 siblings, 0 replies; 550+ messages in thread
From: Hanjun Guo @ 2015-08-27 12:02 UTC (permalink / raw)
  To: Thomas Gleixner, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List, linux-watchdog,
	devicetree, LKML, linux-doc, Wei Fu, G Gregory, Al Stone,
	Arnd Bergmann, Guenter Roeck, Vipul Gandhi, Wim Van Sebroeck,
	Jon Masters, Leo Duran, Jonathan Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, Rafael Wysocki, dyoung, panand,
	Daniel Lezcano

Hi Thomas,

Thanks for the comments, I got some questions and
reply below.

On 08/26/2015 03:17 AM, Thomas Gleixner wrote:
> On Wed, 26 Aug 2015, Fu Wei wrote:
>>>>   /* Initialize per-processor generic timer */
>>>> -static int __init arch_timer_acpi_init(struct acpi_table_header *table)
>>>> +void __init arch_timer_acpi_init(void)
>>>>   {
>>>
>>> And how is that supposed to work when we have next generation CPUs
>>> which implement a different timer? You break multisystem kernels that
>>> way.

Sorry, I think I missed some context here that I don't understand
why the code here will break multisystem kernels? I'm trying to
understand the problem here and update the code :)

>>
>> yes, you are right, If there is a  next generation CPUs  which
>> implement a different timer, (maybe) this driver can not work.
>> we may need a new timer driver.
>>
>> But,
>> (1) for now,  aarch64  core always has the arch timer(this timer is
>> part of aarch64 architecture).
>> and the existing code make  ARM64 kernel "select ARM_ARCH_TIMER "
>> (2) GTDT is designed for generic timer, so in this call "
>> arch_timer_acpi_init"  we  parse the gtdt info.
>> (3) once we have a ARM64 CPUs which implement a different timer, we
>> may need to select a right timer in the config stage.
>> and this timer may not be described in GTDT.  So we can implement
>> another arch_timer_acpi_init by that time in new timer driver..
>> if the new time still uses GTDT(or new version GTDT), we may need to
>> update gtdt.c for new timer by that time.
>
> That's simply wrong. You want to build kernels which run on both cpus
> and the selection of the timer happens at runtime depending on the
> ACPI info. We do the same thing with device tree.

I think the code can do that if I understand correctly. The code for
now is that we only support arch timer on ARM64, and this patch set
is adding SBSA watchdog timer support which need same function in
arch timer, so we move that function to common place.

We will load the driver (arch timer, memory mapped timer) when the
ACPI table defines them, which when new timer is coming, that will
defined in the ACPI table and load the driver as needed.

Please correct me if I misse something, thanks.

Hanjun

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
@ 2015-08-27 12:02             ` Hanjun Guo
  0 siblings, 0 replies; 550+ messages in thread
From: Hanjun Guo @ 2015-08-27 12:02 UTC (permalink / raw)
  To: Thomas Gleixner, Fu Wei
  Cc: Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, LKML,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Arnd Bergmann, Guenter Roeck, Vipul Gandhi, Wim Van Sebroeck,
	Jon Masters, Leo Duran, Jonathan Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA, panand-H+wXaHxf7aLQT0dZR+AlfA,
	Daniel Lezcano

Hi Thomas,

Thanks for the comments, I got some questions and
reply below.

On 08/26/2015 03:17 AM, Thomas Gleixner wrote:
> On Wed, 26 Aug 2015, Fu Wei wrote:
>>>>   /* Initialize per-processor generic timer */
>>>> -static int __init arch_timer_acpi_init(struct acpi_table_header *table)
>>>> +void __init arch_timer_acpi_init(void)
>>>>   {
>>>
>>> And how is that supposed to work when we have next generation CPUs
>>> which implement a different timer? You break multisystem kernels that
>>> way.

Sorry, I think I missed some context here that I don't understand
why the code here will break multisystem kernels? I'm trying to
understand the problem here and update the code :)

>>
>> yes, you are right, If there is a  next generation CPUs  which
>> implement a different timer, (maybe) this driver can not work.
>> we may need a new timer driver.
>>
>> But,
>> (1) for now,  aarch64  core always has the arch timer(this timer is
>> part of aarch64 architecture).
>> and the existing code make  ARM64 kernel "select ARM_ARCH_TIMER "
>> (2) GTDT is designed for generic timer, so in this call "
>> arch_timer_acpi_init"  we  parse the gtdt info.
>> (3) once we have a ARM64 CPUs which implement a different timer, we
>> may need to select a right timer in the config stage.
>> and this timer may not be described in GTDT.  So we can implement
>> another arch_timer_acpi_init by that time in new timer driver..
>> if the new time still uses GTDT(or new version GTDT), we may need to
>> update gtdt.c for new timer by that time.
>
> That's simply wrong. You want to build kernels which run on both cpus
> and the selection of the timer happens at runtime depending on the
> ACPI info. We do the same thing with device tree.

I think the code can do that if I understand correctly. The code for
now is that we only support arch timer on ARM64, and this patch set
is adding SBSA watchdog timer support which need same function in
arch timer, so we move that function to common place.

We will load the driver (arch timer, memory mapped timer) when the
ACPI table defines them, which when new timer is coming, that will
defined in the ACPI table and load the driver as needed.

Please correct me if I misse something, thanks.

Hanjun
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
  2015-08-27 12:02             ` Hanjun Guo
  (?)
@ 2015-08-27 12:08             ` Thomas Gleixner
  2015-08-27 12:28                 ` Hanjun Guo
  -1 siblings, 1 reply; 550+ messages in thread
From: Thomas Gleixner @ 2015-08-27 12:08 UTC (permalink / raw)
  To: Hanjun Guo
  Cc: Fu Wei, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, LKML, linux-doc, Wei Fu, G Gregory,
	Al Stone, Arnd Bergmann, Guenter Roeck, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jonathan Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung, panand, Daniel Lezcano

On Thu, 27 Aug 2015, Hanjun Guo wrote:
> On 08/26/2015 03:17 AM, Thomas Gleixner wrote:
> > On Wed, 26 Aug 2015, Fu Wei wrote:
> > > > >   /* Initialize per-processor generic timer */
> > > > > -static int __init arch_timer_acpi_init(struct acpi_table_header
> > > > > *table)
> > > > > +void __init arch_timer_acpi_init(void)
> > > > >   {
> > > > 
> > > > And how is that supposed to work when we have next generation CPUs
> > > > which implement a different timer? You break multisystem kernels that
> > > > way.
> 
> Sorry, I think I missed some context here that I don't understand
> why the code here will break multisystem kernels? I'm trying to
> understand the problem here and update the code :)
> 
> > > 
> > > yes, you are right, If there is a  next generation CPUs  which
> > > implement a different timer, (maybe) this driver can not work.
> > > we may need a new timer driver.
> > > 
> > > But,
> > > (1) for now,  aarch64  core always has the arch timer(this timer is
> > > part of aarch64 architecture).
> > > and the existing code make  ARM64 kernel "select ARM_ARCH_TIMER "
> > > (2) GTDT is designed for generic timer, so in this call "
> > > arch_timer_acpi_init"  we  parse the gtdt info.
> > > (3) once we have a ARM64 CPUs which implement a different timer, we
> > > may need to select a right timer in the config stage.
> > > and this timer may not be described in GTDT.  So we can implement
> > > another arch_timer_acpi_init by that time in new timer driver..
> > > if the new time still uses GTDT(or new version GTDT), we may need to
> > > update gtdt.c for new timer by that time.
> > 
> > That's simply wrong. You want to build kernels which run on both cpus
> > and the selection of the timer happens at runtime depending on the
> > ACPI info. We do the same thing with device tree.
> 
> I think the code can do that if I understand correctly. The code for
> now is that we only support arch timer on ARM64, and this patch set
> is adding SBSA watchdog timer support which need same function in
> arch timer, so we move that function to common place.
> 
> We will load the driver (arch timer, memory mapped timer) when the
> ACPI table defines them, which when new timer is coming, that will
> defined in the ACPI table and load the driver as needed.
> 
> Please correct me if I misse something, thanks.

arch_timer_acpi_init() is called from the architecture boot code. So
how is that supposed to work with different timers?

Are you going to have bla_timer_acpi_init() and foo_timer_acpi_init()
calls as well?

Why not having a something like DT has: DECLARE_....

and the arch_timer_acpi_init() using that to figure out which of the
timers to initialize.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
  2015-08-27 12:08             ` Thomas Gleixner
@ 2015-08-27 12:28                 ` Hanjun Guo
  0 siblings, 0 replies; 550+ messages in thread
From: Hanjun Guo @ 2015-08-27 12:28 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Fu Wei, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, LKML, linux-doc, Wei Fu, G Gregory,
	Al Stone, Arnd Bergmann, Guenter Roeck, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jonathan Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung, panand, Daniel Lezcano

On 08/27/2015 08:08 PM, Thomas Gleixner wrote:
> On Thu, 27 Aug 2015, Hanjun Guo wrote:
>> On 08/26/2015 03:17 AM, Thomas Gleixner wrote:
>>> On Wed, 26 Aug 2015, Fu Wei wrote:
>>>>>>    /* Initialize per-processor generic timer */
>>>>>> -static int __init arch_timer_acpi_init(struct acpi_table_header
>>>>>> *table)
>>>>>> +void __init arch_timer_acpi_init(void)
>>>>>>    {
>>>>>
>>>>> And how is that supposed to work when we have next generation CPUs
>>>>> which implement a different timer? You break multisystem kernels that
>>>>> way.
>>
>> Sorry, I think I missed some context here that I don't understand
>> why the code here will break multisystem kernels? I'm trying to
>> understand the problem here and update the code :)
>>
>>>>
>>>> yes, you are right, If there is a  next generation CPUs  which
>>>> implement a different timer, (maybe) this driver can not work.
>>>> we may need a new timer driver.
>>>>
>>>> But,
>>>> (1) for now,  aarch64  core always has the arch timer(this timer is
>>>> part of aarch64 architecture).
>>>> and the existing code make  ARM64 kernel "select ARM_ARCH_TIMER "
>>>> (2) GTDT is designed for generic timer, so in this call "
>>>> arch_timer_acpi_init"  we  parse the gtdt info.
>>>> (3) once we have a ARM64 CPUs which implement a different timer, we
>>>> may need to select a right timer in the config stage.
>>>> and this timer may not be described in GTDT.  So we can implement
>>>> another arch_timer_acpi_init by that time in new timer driver..
>>>> if the new time still uses GTDT(or new version GTDT), we may need to
>>>> update gtdt.c for new timer by that time.
>>>
>>> That's simply wrong. You want to build kernels which run on both cpus
>>> and the selection of the timer happens at runtime depending on the
>>> ACPI info. We do the same thing with device tree.
>>
>> I think the code can do that if I understand correctly. The code for
>> now is that we only support arch timer on ARM64, and this patch set
>> is adding SBSA watchdog timer support which need same function in
>> arch timer, so we move that function to common place.
>>
>> We will load the driver (arch timer, memory mapped timer) when the
>> ACPI table defines them, which when new timer is coming, that will
>> defined in the ACPI table and load the driver as needed.
>>
>> Please correct me if I misse something, thanks.
>
> arch_timer_acpi_init() is called from the architecture boot code. So
> how is that supposed to work with different timers?
>
> Are you going to have bla_timer_acpi_init() and foo_timer_acpi_init()
> calls as well?
>
> Why not having a something like DT has: DECLARE_....
>
> and the arch_timer_acpi_init() using that to figure out which of the
> timers to initialize.

Ah, ok, I can fully understand you now, thanks for your patience.

Yes, I agree with you, so this is not a problem for this patch, but
for the code implementation of previous code. Actually we are on the
road to do as you suggested, we introduced something like
#define ACPI_DECLARE(table, name, table_id, subtable, data, fn) [1]
in the GICv3 and GIC self probe patch set, and I said that
infrastructure can be used as clock declare too, we just trying
to not add such dependence on that patch set (it's still on discussion),

[1]: https://lkml.org/lkml/2015/7/29/236

If that is ok with you, we will introduce similar DECLARE_ thing
for clock declare.

Thanks
Hanjun



^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
@ 2015-08-27 12:28                 ` Hanjun Guo
  0 siblings, 0 replies; 550+ messages in thread
From: Hanjun Guo @ 2015-08-27 12:28 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Fu Wei, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, LKML,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Arnd Bergmann, Guenter Roeck, Vipul Gandhi, Wim Van Sebroeck,
	Jon Masters, Leo Duran, Jonathan Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA, panand-H+wXaHxf7aLQT0dZR+AlfA,
	Daniel Lezcano

On 08/27/2015 08:08 PM, Thomas Gleixner wrote:
> On Thu, 27 Aug 2015, Hanjun Guo wrote:
>> On 08/26/2015 03:17 AM, Thomas Gleixner wrote:
>>> On Wed, 26 Aug 2015, Fu Wei wrote:
>>>>>>    /* Initialize per-processor generic timer */
>>>>>> -static int __init arch_timer_acpi_init(struct acpi_table_header
>>>>>> *table)
>>>>>> +void __init arch_timer_acpi_init(void)
>>>>>>    {
>>>>>
>>>>> And how is that supposed to work when we have next generation CPUs
>>>>> which implement a different timer? You break multisystem kernels that
>>>>> way.
>>
>> Sorry, I think I missed some context here that I don't understand
>> why the code here will break multisystem kernels? I'm trying to
>> understand the problem here and update the code :)
>>
>>>>
>>>> yes, you are right, If there is a  next generation CPUs  which
>>>> implement a different timer, (maybe) this driver can not work.
>>>> we may need a new timer driver.
>>>>
>>>> But,
>>>> (1) for now,  aarch64  core always has the arch timer(this timer is
>>>> part of aarch64 architecture).
>>>> and the existing code make  ARM64 kernel "select ARM_ARCH_TIMER "
>>>> (2) GTDT is designed for generic timer, so in this call "
>>>> arch_timer_acpi_init"  we  parse the gtdt info.
>>>> (3) once we have a ARM64 CPUs which implement a different timer, we
>>>> may need to select a right timer in the config stage.
>>>> and this timer may not be described in GTDT.  So we can implement
>>>> another arch_timer_acpi_init by that time in new timer driver..
>>>> if the new time still uses GTDT(or new version GTDT), we may need to
>>>> update gtdt.c for new timer by that time.
>>>
>>> That's simply wrong. You want to build kernels which run on both cpus
>>> and the selection of the timer happens at runtime depending on the
>>> ACPI info. We do the same thing with device tree.
>>
>> I think the code can do that if I understand correctly. The code for
>> now is that we only support arch timer on ARM64, and this patch set
>> is adding SBSA watchdog timer support which need same function in
>> arch timer, so we move that function to common place.
>>
>> We will load the driver (arch timer, memory mapped timer) when the
>> ACPI table defines them, which when new timer is coming, that will
>> defined in the ACPI table and load the driver as needed.
>>
>> Please correct me if I misse something, thanks.
>
> arch_timer_acpi_init() is called from the architecture boot code. So
> how is that supposed to work with different timers?
>
> Are you going to have bla_timer_acpi_init() and foo_timer_acpi_init()
> calls as well?
>
> Why not having a something like DT has: DECLARE_....
>
> and the arch_timer_acpi_init() using that to figure out which of the
> timers to initialize.

Ah, ok, I can fully understand you now, thanks for your patience.

Yes, I agree with you, so this is not a problem for this patch, but
for the code implementation of previous code. Actually we are on the
road to do as you suggested, we introduced something like
#define ACPI_DECLARE(table, name, table_id, subtable, data, fn) [1]
in the GICv3 and GIC self probe patch set, and I said that
infrastructure can be used as clock declare too, we just trying
to not add such dependence on that patch set (it's still on discussion),

[1]: https://lkml.org/lkml/2015/7/29/236

If that is ok with you, we will introduce similar DECLARE_ thing
for clock declare.

Thanks
Hanjun


--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
  2015-08-27 12:28                 ` Hanjun Guo
  (?)
@ 2015-08-27 13:36                 ` Hanjun Guo
  2015-08-27 13:40                     ` Thomas Gleixner
  -1 siblings, 1 reply; 550+ messages in thread
From: Hanjun Guo @ 2015-08-27 13:36 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Fu Wei, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, LKML, linux-doc, Wei Fu, G Gregory,
	Al Stone, Arnd Bergmann, Guenter Roeck, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jonathan Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung, panand, Daniel Lezcano

On 08/27/2015 08:28 PM, Hanjun Guo wrote:
> On 08/27/2015 08:08 PM, Thomas Gleixner wrote:
>> On Thu, 27 Aug 2015, Hanjun Guo wrote:
>>> On 08/26/2015 03:17 AM, Thomas Gleixner wrote:
>>>> On Wed, 26 Aug 2015, Fu Wei wrote:
>>>>>>>    /* Initialize per-processor generic timer */
>>>>>>> -static int __init arch_timer_acpi_init(struct acpi_table_header
>>>>>>> *table)
>>>>>>> +void __init arch_timer_acpi_init(void)
>>>>>>>    {
>>>>>>
>>>>>> And how is that supposed to work when we have next generation CPUs
>>>>>> which implement a different timer? You break multisystem kernels that
>>>>>> way.
>>>
>>> Sorry, I think I missed some context here that I don't understand
>>> why the code here will break multisystem kernels? I'm trying to
>>> understand the problem here and update the code :)
>>>
>>>>>
>>>>> yes, you are right, If there is a  next generation CPUs  which
>>>>> implement a different timer, (maybe) this driver can not work.
>>>>> we may need a new timer driver.
>>>>>
>>>>> But,
>>>>> (1) for now,  aarch64  core always has the arch timer(this timer is
>>>>> part of aarch64 architecture).
>>>>> and the existing code make  ARM64 kernel "select ARM_ARCH_TIMER "
>>>>> (2) GTDT is designed for generic timer, so in this call "
>>>>> arch_timer_acpi_init"  we  parse the gtdt info.
>>>>> (3) once we have a ARM64 CPUs which implement a different timer, we
>>>>> may need to select a right timer in the config stage.
>>>>> and this timer may not be described in GTDT.  So we can implement
>>>>> another arch_timer_acpi_init by that time in new timer driver..
>>>>> if the new time still uses GTDT(or new version GTDT), we may need to
>>>>> update gtdt.c for new timer by that time.
>>>>
>>>> That's simply wrong. You want to build kernels which run on both cpus
>>>> and the selection of the timer happens at runtime depending on the
>>>> ACPI info. We do the same thing with device tree.
>>>
>>> I think the code can do that if I understand correctly. The code for
>>> now is that we only support arch timer on ARM64, and this patch set
>>> is adding SBSA watchdog timer support which need same function in
>>> arch timer, so we move that function to common place.
>>>
>>> We will load the driver (arch timer, memory mapped timer) when the
>>> ACPI table defines them, which when new timer is coming, that will
>>> defined in the ACPI table and load the driver as needed.
>>>
>>> Please correct me if I misse something, thanks.
>>
>> arch_timer_acpi_init() is called from the architecture boot code. So
>> how is that supposed to work with different timers?
>>
>> Are you going to have bla_timer_acpi_init() and foo_timer_acpi_init()
>> calls as well?
>>
>> Why not having a something like DT has: DECLARE_....
>>
>> and the arch_timer_acpi_init() using that to figure out which of the
>> timers to initialize.
>
> Ah, ok, I can fully understand you now, thanks for your patience.
>
> Yes, I agree with you, so this is not a problem for this patch, but
> for the code implementation of previous code. Actually we are on the
> road to do as you suggested, we introduced something like
> #define ACPI_DECLARE(table, name, table_id, subtable, data, fn) [1]
> in the GICv3 and GIC self probe patch set, and I said that
> infrastructure can be used as clock declare too, we just trying
> to not add such dependence on that patch set (it's still on discussion),
>
> [1]: https://lkml.org/lkml/2015/7/29/236
>
> If that is ok with you, we will introduce similar DECLARE_ thing
> for clock declare.

Or we can drop this patch from this patch set, and clean up this
patch when the ACPI_DECLARE() infrastructure is ready for upstream.

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
@ 2015-08-27 13:40                     ` Thomas Gleixner
  0 siblings, 0 replies; 550+ messages in thread
From: Thomas Gleixner @ 2015-08-27 13:40 UTC (permalink / raw)
  To: Hanjun Guo
  Cc: Fu Wei, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, LKML, linux-doc, Wei Fu, G Gregory,
	Al Stone, Arnd Bergmann, Guenter Roeck, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jonathan Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung, panand, Daniel Lezcano

On Thu, 27 Aug 2015, Hanjun Guo wrote:
> > [1]: https://lkml.org/lkml/2015/7/29/236
> > 
> > If that is ok with you, we will introduce similar DECLARE_ thing
> > for clock declare.

Yes.
 
> Or we can drop this patch from this patch set, and clean up this
> patch when the ACPI_DECLARE() infrastructure is ready for upstream.

Works either way. I just noticed that hard coded init thing and
decided to rant about it :)

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
@ 2015-08-27 13:40                     ` Thomas Gleixner
  0 siblings, 0 replies; 550+ messages in thread
From: Thomas Gleixner @ 2015-08-27 13:40 UTC (permalink / raw)
  To: Hanjun Guo
  Cc: Fu Wei, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, LKML,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Arnd Bergmann, Guenter Roeck, Vipul Gandhi, Wim Van Sebroeck,
	Jon Masters, Leo Duran, Jonathan Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA, panand-H+wXaHxf7aLQT0dZR+AlfA,
	Daniel Lezcano

On Thu, 27 Aug 2015, Hanjun Guo wrote:
> > [1]: https://lkml.org/lkml/2015/7/29/236
> > 
> > If that is ok with you, we will introduce similar DECLARE_ thing
> > for clock declare.

Yes.
 
> Or we can drop this patch from this patch set, and clean up this
> patch when the ACPI_DECLARE() infrastructure is ready for upstream.

Works either way. I just noticed that hard coded init thing and
decided to rant about it :)

Thanks,

	tglx
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
  2015-08-27 13:40                     ` Thomas Gleixner
  (?)
@ 2015-08-27 13:51                     ` Fu Wei
  2015-09-14 18:05                         ` Marc Zyngier
  -1 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-08-27 13:51 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Hanjun Guo, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, LKML, linux-doc, Wei Fu, G Gregory,
	Al Stone, Arnd Bergmann, Guenter Roeck, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jonathan Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung, panand, Daniel Lezcano

Hi Thomas, Hanjun

On 27 August 2015 at 21:40, Thomas Gleixner <tglx@linutronix.de> wrote:
> On Thu, 27 Aug 2015, Hanjun Guo wrote:
>> > [1]: https://lkml.org/lkml/2015/7/29/236
>> >
>> > If that is ok with you, we will introduce similar DECLARE_ thing
>> > for clock declare.
>
> Yes.

Thanks

>
>> Or we can drop this patch from this patch set, and clean up this
>> patch when the ACPI_DECLARE() infrastructure is ready for upstream.
>
> Works either way. I just noticed that hard coded init thing and
> decided to rant about it :)

OK, good idea, this patch will be improve by DECLARE_ thing, then upstream.
drop this from this patchset.

Great thanks for your help


>
> Thanks,
>
>         tglx
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 0/4] arm64: Add Xen boot support (via fdt)
  2015-08-04  8:34   ` [PATCH v3 0/4] arm64: Add Xen boot support (via fdt) Fu Wei
@ 2015-09-08  3:38     ` Fu Wei
  2015-09-30 16:00       ` Stefano Stabellini
  0 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-09-08  3:38 UTC (permalink / raw)
  To: The development of GNU GRUB, Andrei Borzenkov, Vladimir Serbinenko
  Cc: xen-devel, Ian Campbell, Stefano Stabellini, Jon Masters,
	Leif Lindholm, Ryan Harkin, Linaro UEFI Mailman List, Fu Wei

Hi Vladimir,

Do you have any suggestion on this patchset?
Do I need to improve anything?

Great thanks for your help.

On 4 August 2015 at 16:34, Fu Wei <fu.wei@linaro.org> wrote:
> Hi Vladimir,
>
> this patchset follows all your comment of v2 patchset.
> Do you have any suggestion on this patchset?
>
> Great thanks for your help.
>
>
> On 23 July 2015 at 13:16,  <fu.wei@linaro.org> wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>>   - This adds support for the Xen boot on ARM specification for arm64.
>>
>>   - Add and export some accessor functions of "loaded" flag and
>>     grub_linux_get_fdt function in include/grub/arm64/linux.h for xen boot.
>>
>>   - Introduce xen_hypervisor, xen_linux, xen_initrd and xen_xsm
>>     to load different binaries for xen boot.
>>     Introduce xen_module to load common or custom module for xen boot.
>>
>>   - This Xen boot support is a separated  module for aarch64,
>>     but reuse the existing code of devicetree in linux module.
>>
>>   - Add the support of xen_hypervisor, xen_linux and xen_initrd
>>     in util/grub.d/20_linux_xen.in
>>
>>   - Add the introduction of all xen boot commands in docs/grub.texi
>>
>>   - The example of this support is <How to boot Xen with GRUB on AArch64 the Foundation FVP model>
>>     https://wiki.linaro.org/LEG/Engineering/Grub2/Xen_booting_on_Foundation_FVP_model_by_GRUB
>>
>> Changelog:
>> v3: create separate module for xen boot: xen_boot
>>     create separate commands for different types of module
>>     delete order-dependent for commands of xen module
>>     simplify the code
>>
>> v2: remove the patches which have been accepted.
>>     according to Vladimir's suggestion, change the command manes
>>     and relevant code:
>>         multiboot-->xen_hypervisor
>>         module-->xen_module
>>     improve the option parsing support for xen_hypervisor/xen_module commands.
>>     add a patch for adding xen_hypervisor/xen_module support
>>     in util/grub.d/20_linux_xen.in.
>>     update docs/grub.texi patch for the new command names.
>>
>> v1: The first version upstream patchset to grub-devel mailing list
>>
>>
>> Fu Wei (4):
>>   arm64: Add and export some accessor functions for xen boot
>>   arm64: Add xen_boot module file
>>   * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
>>   arm64: Add the introduction of xen boot commands in docs/grub.texi
>>
>>  docs/grub.texi                    |  56 ++++
>>  grub-core/Makefile.core.def       |   7 +
>>  grub-core/loader/arm64/linux.c    |  13 +
>>  grub-core/loader/arm64/xen_boot.c | 685 ++++++++++++++++++++++++++++++++++++++
>>  include/grub/arm64/linux.h        |   6 +-
>>  util/grub.d/20_linux_xen.in       |  16 +-
>>  6 files changed, 779 insertions(+), 4 deletions(-)
>>  create mode 100644 grub-core/loader/arm64/xen_boot.c
>>
>> --
>> 1.8.3.1
>>
>
>
>
> --
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver
  2015-08-24 17:01   ` [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
@ 2015-09-10 22:29     ` Jon Masters
  2015-09-11  2:05       ` Guenter Roeck
  2015-09-11  2:50         ` Guenter Roeck
  2015-09-15  8:38     ` Dave Young
  1 sibling, 2 replies; 550+ messages in thread
From: Jon Masters @ 2015-09-10 22:29 UTC (permalink / raw)
  To: fu.wei, Suravee.Suthikulpanit, hanjun.guo, linaro-acpi,
	linux-watchdog, devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, arnd, linux, vgandhi,
	wim, leo.duran, corbet, mark.rutland, catalin.marinas,
	will.deacon, rjw, dyoung, panand

On 08/24/2015 01:01 PM, fu.wei@linaro.org wrote:

> +	/*
> +	 * Get the frequency of system counter from the cp15 interface of ARM
> +	 * Generic timer. We don't need to check it, because if it returns "0",
> +	 * system would panic in very early stage.
> +	 */
> +	gwdt->clk = arch_timer_get_cntfrq();

Just thinking out loud...

What happens later if we virtualize this device within KVM/QEMU/Xen and
then live migrate to another system in which the frequency changes?

Jon.


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-06-03 18:53           ` Timur Tabi
  (?)
  (?)
@ 2015-09-10 22:45           ` Jon Masters
  2015-09-14  4:21             ` Pratyush Anand
                               ` (2 more replies)
  -1 siblings, 3 replies; 550+ messages in thread
From: Jon Masters @ 2015-09-10 22:45 UTC (permalink / raw)
  To: Timur Tabi, Guenter Roeck
  Cc: fu.wei, Suravee.Suthikulpanit, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, hanjun.guo, ashwin.chaugule, arnd,
	vgandhi, wim, leo.duran, corbet, mark.rutland, catalin.marinas,
	will.deacon, rjw

On 06/03/2015 02:53 PM, Timur Tabi wrote:
> On 06/03/2015 01:25 PM, Guenter Roeck wrote:
>> In general the idea here would be to use a crashdump kernel, which,
>> when loaded, would reset the watchdog before it fires. This kernel
>> would then write a core dump to a specified location.
> 
> What is the mechanism for resetting the watchdog?  The only code that 
> knows about the hardware registers is this driver.  Does the crashdump 
> kernel call the watchdog stop function?
> 
>> If arm64 doesn't support a crashdump kernel, it might still be possible
>> to log the backtrace somewhere (eg in nvram using pstore if that is
>> supported via acpi or efi).

Just to go back and explicitly answer this, arm64 does have support for
crashdump, using the standard kexec/kdump approach, exactly as on x86.
There's still some more work to be done to get the ACPI case fully
upstream (e.g. on X-Gene platforms such as the HP ProLiant Moonshot m400
we need non-PSCI CPU parking protocol offlining when booting in
UEFI/ACPI mode), but it's what we are doing in RHEL(SA) and the goal is
to help clean up the remaining pieces upstream there.

Jon.


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver
  2015-09-10 22:29     ` Jon Masters
@ 2015-09-11  2:05       ` Guenter Roeck
  2015-09-11  2:50         ` Guenter Roeck
  1 sibling, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-09-11  2:05 UTC (permalink / raw)
  To: Jon Masters
  Cc: fu.wei, Suravee.Suthikulpanit, hanjun.guo, linaro-acpi,
	linux-watchdog, devicetree, linux-kernel, linux-doc,
	tekkamanninja, graeme.gregory, al.stone, arnd, vgandhi, wim,
	leo.duran, corbet, mark.rutland, catalin.marinas, will.deacon,
	rjw, dyoung, panand

On Thu, Sep 10, 2015 at 06:29:53PM -0400, Jon Masters wrote:
> On 08/24/2015 01:01 PM, fu.wei@linaro.org wrote:
> 
> > +	/*
> > +	 * Get the frequency of system counter from the cp15 interface of ARM
> > +	 * Generic timer. We don't need to check it, because if it returns "0",
> > +	 * system would panic in very early stage.
> > +	 */
> > +	gwdt->clk = arch_timer_get_cntfrq();
> 
> Just thinking out loud...
> 
> What happens later if we virtualize this device within KVM/QEMU/Xen and
> then live migrate to another system in which the frequency changes?
> 
I don't know, but I would suspect that we might end up in all kinds of
trouble if clocks can change like that, and not just in this driver.
Many drivers make the assumption that clock rates are not changed
under the hood. If it can happen, shouldn't there be a callback into
the drivers using the affected clock(s) ?

Also, it seems to me that changing a clock like that would be inherently
unsafe. For example, what will happen if the system is stopped and migrated
right after the clock frequency is read, but before the returned value
is used ? Can that happen ? Or does it only happen during suspend/resume
cycles, if it happens ?

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-09-11  2:50         ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-09-11  2:50 UTC (permalink / raw)
  To: Jon Masters, fu.wei, Suravee.Suthikulpanit, hanjun.guo,
	linaro-acpi, linux-watchdog, devicetree, linux-kernel, linux-doc
  Cc: tekkamanninja, graeme.gregory, al.stone, arnd, vgandhi, wim,
	leo.duran, corbet, mark.rutland, catalin.marinas, will.deacon,
	rjw, dyoung, panand

On 09/10/2015 03:29 PM, Jon Masters wrote:
> On 08/24/2015 01:01 PM, fu.wei@linaro.org wrote:
>
>> +	/*
>> +	 * Get the frequency of system counter from the cp15 interface of ARM
>> +	 * Generic timer. We don't need to check it, because if it returns "0",
>> +	 * system would panic in very early stage.
>> +	 */
>> +	gwdt->clk = arch_timer_get_cntfrq();
>
> Just thinking out loud...
>
> What happens later if we virtualize this device within KVM/QEMU/Xen and
> then live migrate to another system in which the frequency changes?
>

Thinking about it, this scenario would cause severe trouble. I think clocks
(like I would assume pretty much all other hardware parameters / registers)
need to be virtualized and must not change.

Example: clock is set to 100 kHz on original system, and 400 kHz on new
system. Timeout is set to 30s, and registers are programmed accordingly.
User space sends heartbeats every 15 seconds.

In this scenario, the watchdog would time out after 30/4 = 7.5 seconds
on the new system, or in other words almost immediately.

This would be even worse if the original system had a clock of, say,
10 kHz and the new system would use 400 kHz. This just doesn't work.

Guenter


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-09-11  2:50         ` Guenter Roeck
  0 siblings, 0 replies; 550+ messages in thread
From: Guenter Roeck @ 2015-09-11  2:50 UTC (permalink / raw)
  To: Jon Masters, fu.wei-QSEj5FYQhm4dnm+yROfE0A,
	Suravee.Suthikulpanit-5C7GfCeVMHo,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	vgandhi-sgV2jX0FEOL9JmXXK+q4OQ, wim-IQzOog9fTRqzQB+pC5nmwQ,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA, panand-H+wXaHxf7aLQT0dZR+AlfA

On 09/10/2015 03:29 PM, Jon Masters wrote:
> On 08/24/2015 01:01 PM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
>
>> +	/*
>> +	 * Get the frequency of system counter from the cp15 interface of ARM
>> +	 * Generic timer. We don't need to check it, because if it returns "0",
>> +	 * system would panic in very early stage.
>> +	 */
>> +	gwdt->clk = arch_timer_get_cntfrq();
>
> Just thinking out loud...
>
> What happens later if we virtualize this device within KVM/QEMU/Xen and
> then live migrate to another system in which the frequency changes?
>

Thinking about it, this scenario would cause severe trouble. I think clocks
(like I would assume pretty much all other hardware parameters / registers)
need to be virtualized and must not change.

Example: clock is set to 100 kHz on original system, and 400 kHz on new
system. Timeout is set to 30s, and registers are programmed accordingly.
User space sends heartbeats every 15 seconds.

In this scenario, the watchdog would time out after 30/4 = 7.5 seconds
on the new system, or in other words almost immediately.

This would be even worse if the original system had a clock of, say,
10 kHz and the new system would use 400 kHz. This just doesn't work.

Guenter

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-09-10 22:45           ` Jon Masters
@ 2015-09-14  4:21             ` Pratyush Anand
  2015-09-14 15:27                 ` Fu Wei
  2015-09-14  8:51             ` Catalin Marinas
  2015-09-15  3:16               ` Fu Wei
  2 siblings, 1 reply; 550+ messages in thread
From: Pratyush Anand @ 2015-09-14  4:21 UTC (permalink / raw)
  To: Jon Masters, Timur Tabi, Guenter Roeck, fu.wei
  Cc: Suravee.Suthikulpanit, linaro-acpi, linux-watchdog, devicetree,
	linux-kernel, linux-doc, tekkamanninja, graeme.gregory, al.stone,
	hanjun.guo, ashwin.chaugule, arnd, vgandhi, wim, leo.duran,
	corbet, mark.rutland, catalin.marinas, will.deacon, rjw

On 10/09/2015:06:45:17 PM, Jon Masters wrote:
> On 06/03/2015 02:53 PM, Timur Tabi wrote:
> > On 06/03/2015 01:25 PM, Guenter Roeck wrote:
> >> In general the idea here would be to use a crashdump kernel, which,
> >> when loaded, would reset the watchdog before it fires. This kernel
> >> would then write a core dump to a specified location.

And this is what we do in fedora or RHEL. There had been some work ongoing in
fedora [1][2] which will help to reset any active watchdog in kdump kernel(if
the watchdog driver has been registered to watchdog_class). It will eventually
help a watchdog on ARM64 platform as well.

[1] https://lists.fedoraproject.org/pipermail/kexec/2015-September/002295.html
[2] https://github.com/pratyushanand/kexec-tools/commits/watchdog_fmaster

~Pratyush

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
  2015-09-10 22:45           ` Jon Masters
  2015-09-14  4:21             ` Pratyush Anand
@ 2015-09-14  8:51             ` Catalin Marinas
  2015-09-15  3:16               ` Fu Wei
  2 siblings, 0 replies; 550+ messages in thread
From: Catalin Marinas @ 2015-09-14  8:51 UTC (permalink / raw)
  To: Jon Masters
  Cc: Timur Tabi, Guenter Roeck, fu.wei, Suravee.Suthikulpanit,
	linaro-acpi, linux-watchdog, devicetree, linux-kernel, linux-doc,
	tekkamanninja, graeme.gregory, al.stone, hanjun.guo,
	ashwin.chaugule, arnd, vgandhi, wim, leo.duran, corbet,
	mark.rutland, will.deacon, rjw

On Thu, Sep 10, 2015 at 06:45:17PM -0400, Jon Masters wrote:
> On 06/03/2015 02:53 PM, Timur Tabi wrote:
> > On 06/03/2015 01:25 PM, Guenter Roeck wrote:
> >> In general the idea here would be to use a crashdump kernel, which,
> >> when loaded, would reset the watchdog before it fires. This kernel
> >> would then write a core dump to a specified location.
> > 
> > What is the mechanism for resetting the watchdog?  The only code that 
> > knows about the hardware registers is this driver.  Does the crashdump 
> > kernel call the watchdog stop function?
> > 
> >> If arm64 doesn't support a crashdump kernel, it might still be possible
> >> to log the backtrace somewhere (eg in nvram using pstore if that is
> >> supported via acpi or efi).
> 
> Just to go back and explicitly answer this, arm64 does have support for
> crashdump, using the standard kexec/kdump approach, exactly as on x86.

Just a clarification - this is not (yet) supported in mainline, not even
with DT.

-- 
Catalin


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-09-14 15:27                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-09-14 15:27 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: Jon Masters, Timur Tabi, Guenter Roeck, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog, devicetree, LKML,
	linux-doc, Wei Fu, G Gregory, Al Stone, Hanjun Guo,
	Ashwin Chaugule, Arnd Bergmann, Vipul Gandhi, Wim Van Sebroeck,
	Leo Duran, Jon Corbet, Mark Rutland, Catalin Marinas,
	Will Deacon, Rafael Wysocki

Hi Pratyush,

Great thanks for your help on some update for watchdog framework.

For " Fix parent of watchdog_devices", I will update my patchset.
For the upstreaming patchset"Sysfs status read support", will make a
patch. But upstream it when your patchset is merged.

On 14 September 2015 at 12:21, Pratyush Anand <panand@redhat.com> wrote:
> On 10/09/2015:06:45:17 PM, Jon Masters wrote:
>> On 06/03/2015 02:53 PM, Timur Tabi wrote:
>> > On 06/03/2015 01:25 PM, Guenter Roeck wrote:
>> >> In general the idea here would be to use a crashdump kernel, which,
>> >> when loaded, would reset the watchdog before it fires. This kernel
>> >> would then write a core dump to a specified location.
>
> And this is what we do in fedora or RHEL. There had been some work ongoing in
> fedora [1][2] which will help to reset any active watchdog in kdump kernel(if
> the watchdog driver has been registered to watchdog_class). It will eventually
> help a watchdog on ARM64 platform as well.
>
> [1] https://lists.fedoraproject.org/pipermail/kexec/2015-September/002295.html
> [2] https://github.com/pratyushanand/kexec-tools/commits/watchdog_fmaster
>
> ~Pratyush



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-09-14 15:27                 ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-09-14 15:27 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: Jon Masters, Timur Tabi, Guenter Roeck, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, LKML,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Vipul Gandhi,
	Wim Van Sebroeck, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, Rafael Wysocki

Hi Pratyush,

Great thanks for your help on some update for watchdog framework.

For " Fix parent of watchdog_devices", I will update my patchset.
For the upstreaming patchset"Sysfs status read support", will make a
patch. But upstream it when your patchset is merged.

On 14 September 2015 at 12:21, Pratyush Anand <panand-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> On 10/09/2015:06:45:17 PM, Jon Masters wrote:
>> On 06/03/2015 02:53 PM, Timur Tabi wrote:
>> > On 06/03/2015 01:25 PM, Guenter Roeck wrote:
>> >> In general the idea here would be to use a crashdump kernel, which,
>> >> when loaded, would reset the watchdog before it fires. This kernel
>> >> would then write a core dump to a specified location.
>
> And this is what we do in fedora or RHEL. There had been some work ongoing in
> fedora [1][2] which will help to reset any active watchdog in kdump kernel(if
> the watchdog driver has been registered to watchdog_class). It will eventually
> help a watchdog on ARM64 platform as well.
>
> [1] https://lists.fedoraproject.org/pipermail/kexec/2015-September/002295.html
> [2] https://github.com/pratyushanand/kexec-tools/commits/watchdog_fmaster
>
> ~Pratyush



-- 
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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver
  2015-09-11  2:50         ` Guenter Roeck
  (?)
@ 2015-09-14 17:11         ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-09-14 17:11 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Jon Masters, Suravee Suthikulpanit, Hanjun Guo,
	Linaro ACPI Mailman List, linux-watchdog, devicetree, LKML,
	linux-doc, Wei Fu, G Gregory, Al Stone, Arnd Bergmann,
	Vipul Gandhi, Wim Van Sebroeck, Leo Duran, Jon Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung, Pratyush Anand

Hi Guenter, Jon,

On 11 September 2015 at 10:50, Guenter Roeck <linux@roeck-us.net> wrote:
> On 09/10/2015 03:29 PM, Jon Masters wrote:
>>
>> On 08/24/2015 01:01 PM, fu.wei@linaro.org wrote:
>>
>>> +       /*
>>> +        * Get the frequency of system counter from the cp15 interface of
>>> ARM
>>> +        * Generic timer. We don't need to check it, because if it
>>> returns "0",
>>> +        * system would panic in very early stage.
>>> +        */
>>> +       gwdt->clk = arch_timer_get_cntfrq();
>>
>>
>> Just thinking out loud...
>>
>> What happens later if we virtualize this device within KVM/QEMU/Xen and
>> then live migrate to another system in which the frequency changes?
>>
>
> Thinking about it, this scenario would cause severe trouble. I think clocks
> (like I would assume pretty much all other hardware parameters / registers)
> need to be virtualized and must not change.
>
> Example: clock is set to 100 kHz on original system, and 400 kHz on new
> system. Timeout is set to 30s, and registers are programmed accordingly.
> User space sends heartbeats every 15 seconds.
>
> In this scenario, the watchdog would time out after 30/4 = 7.5 seconds
> on the new system, or in other words almost immediately.
>
> This would be even worse if the original system had a clock of, say,
> 10 kHz and the new system would use 400 kHz. This just doesn't work.

I have rechecked the SBSA spec and "Architecture Reference Manual(ARM)",
I think we don't need to worry about "the frequency changes", let me
explain this, but if I misunderstand something, please correct me!

(1) what is the clock source (or reference) of SBSA watchdog timer?
SBSA spec(2.3) has answered this well at page 23:
---------------------------
The Watchdog uses the Generic Timer system count value as the timebase
against which the decision to trigger an interrupt is made.
---------------------------

(2) Can the frequency of the Generic Timer System counter be changed?
At ARMv8 ARM,  D6.1.1 System counter :
---------------------------
The Generic Timer provides a system counter with the following specification:
Frequency
Increments at *a fixed frequency*, typically in the range 1-50MHz.
Can support one or more alternative operating modes in which it
increments by larger amounts at a lower frequency, typically for
power-saving.

To support lower-power operating modes, the counter can increment by
larger amounts at a lower frequency. For example, a 10MHz system
counter might either increment either:
• By 1 at 10MHz.
• By 500 at 20kHz,
when the system lowers the clock frequency, to reduce power consumption.
In this case, the counter must support transitions between
high-frequency, high-precision operation, and lower-frequency,
lower-precision operation, without any impact on the required accuracy
of the counter.
---------------------------
So even the frequency of the Generic Timer System counter be changed
by some reason(typically for power-saving), this won't affect the
timeout(and pretimeout) of watchdog, the actual time will be always
right.

*we were talking about real hardware above. Now we think about virtualization.*
(3) if the virtual watchdog device in KVM/QEMU/Xen is migrated to
another system in which the frequency changes, will it affect the "dog
feeding procedure"?

I don't think so.
if the frequency changes, the frequency of System counter is changed.
But in ARM system, System counter is a global reference for all clocks
or timers(per-cpu and Memory-mapped).
So if   System counter is getting faster, everything in this  virtual
machine is getting faster, and vice versa.

Now we use the example above
if  clock is set to 100 kHz on original system, and 400 kHz on new system.
Timeout is set to 30s, and registers are programmed accordingly. User
space sends heartbeats every 15 seconds.
In this scenario, On the new system, the watchdog would time out after
30/4 = 7.5 seconds.
* User space sends heartbeats every 15/4 = 3.25 second now , but NOT
15 seconds.*
If everything goes well,  system will keep running.

Hope I understand the question correctly, please  correct me if I miss
something or said anything wrong.

Great thanks for your feedback!

>
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
@ 2015-09-14 18:05                         ` Marc Zyngier
  0 siblings, 0 replies; 550+ messages in thread
From: Marc Zyngier @ 2015-09-14 18:05 UTC (permalink / raw)
  To: Fu Wei, Thomas Gleixner
  Cc: Hanjun Guo, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, LKML, linux-doc, Wei Fu, G Gregory,
	Al Stone, Arnd Bergmann, Guenter Roeck, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jonathan Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung, panand, Daniel Lezcano

On 27/08/15 14:51, Fu Wei wrote:
> Hi Thomas, Hanjun
> 
> On 27 August 2015 at 21:40, Thomas Gleixner <tglx@linutronix.de> wrote:
>> On Thu, 27 Aug 2015, Hanjun Guo wrote:
>>>> [1]: https://lkml.org/lkml/2015/7/29/236
>>>>
>>>> If that is ok with you, we will introduce similar DECLARE_ thing
>>>> for clock declare.
>>
>> Yes.
> 
> Thanks
> 
>>
>>> Or we can drop this patch from this patch set, and clean up this
>>> patch when the ACPI_DECLARE() infrastructure is ready for upstream.
>>
>> Works either way. I just noticed that hard coded init thing and
>> decided to rant about it :)
> 
> OK, good idea, this patch will be improve by DECLARE_ thing, then upstream.
> drop this from this patchset.
> 
> Great thanks for your help

You probably want to keep an eye on this:

https://lwn.net/Articles/657238/

which implements the necessary infrastructure. I'd appreciate if you
could give it a go to find out if it works for you.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c
@ 2015-09-14 18:05                         ` Marc Zyngier
  0 siblings, 0 replies; 550+ messages in thread
From: Marc Zyngier @ 2015-09-14 18:05 UTC (permalink / raw)
  To: Fu Wei, Thomas Gleixner
  Cc: Hanjun Guo, Suravee Suthikulpanit, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, LKML,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Arnd Bergmann, Guenter Roeck, Vipul Gandhi, Wim Van Sebroeck,
	Jon Masters, Leo Duran, Jonathan Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, Rafael Wysocki,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA, panand-H+wXaHxf7aLQT0dZR+AlfA,
	Daniel Lezcano

On 27/08/15 14:51, Fu Wei wrote:
> Hi Thomas, Hanjun
> 
> On 27 August 2015 at 21:40, Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org> wrote:
>> On Thu, 27 Aug 2015, Hanjun Guo wrote:
>>>> [1]: https://lkml.org/lkml/2015/7/29/236
>>>>
>>>> If that is ok with you, we will introduce similar DECLARE_ thing
>>>> for clock declare.
>>
>> Yes.
> 
> Thanks
> 
>>
>>> Or we can drop this patch from this patch set, and clean up this
>>> patch when the ACPI_DECLARE() infrastructure is ready for upstream.
>>
>> Works either way. I just noticed that hard coded init thing and
>> decided to rant about it :)
> 
> OK, good idea, this patch will be improve by DECLARE_ thing, then upstream.
> drop this from this patchset.
> 
> Great thanks for your help

You probably want to keep an eye on this:

https://lwn.net/Articles/657238/

which implements the necessary infrastructure. I'd appreciate if you
could give it a go to find out if it works for you.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-09-15  3:16               ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-09-15  3:16 UTC (permalink / raw)
  To: Jon Masters
  Cc: Timur Tabi, Guenter Roeck, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog, devicetree, LKML,
	linux-doc, Wei Fu, G Gregory, Al Stone, Hanjun Guo,
	Ashwin Chaugule, Arnd Bergmann, Vipul Gandhi, Wim Van Sebroeck,
	Leo Duran, Jon Corbet, Mark Rutland, Catalin Marinas,
	Will Deacon, Rafael Wysocki

Hi Jon,

On 11 September 2015 at 06:45, Jon Masters <jcm@redhat.com> wrote:
> On 06/03/2015 02:53 PM, Timur Tabi wrote:
>> On 06/03/2015 01:25 PM, Guenter Roeck wrote:
>>> In general the idea here would be to use a crashdump kernel, which,
>>> when loaded, would reset the watchdog before it fires. This kernel
>>> would then write a core dump to a specified location.
>>
>> What is the mechanism for resetting the watchdog?  The only code that
>> knows about the hardware registers is this driver.  Does the crashdump
>> kernel call the watchdog stop function?
>>
>>> If arm64 doesn't support a crashdump kernel, it might still be possible
>>> to log the backtrace somewhere (eg in nvram using pstore if that is
>>> supported via acpi or efi).
>
> Just to go back and explicitly answer this, arm64 does have support for
> crashdump, using the standard kexec/kdump approach, exactly as on x86.
> There's still some more work to be done to get the ACPI case fully
> upstream (e.g. on X-Gene platforms such as the HP ProLiant Moonshot m400
> we need non-PSCI CPU parking protocol offlining when booting in
> UEFI/ACPI mode), but it's what we are doing in RHEL(SA) and the goal is
> to help clean up the remaining pieces upstream there.

Great thanks for your info.

I have tried kexec/kdump on a real aarch64 hardware, that works well.
Although it's still under development and upstreaming, the support is there.

After discussing with some kexec/kdump  developer, I think this driver
can cooperate with kexec/kdump.

>
> Jon.
>



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-09-15  3:16               ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-09-15  3:16 UTC (permalink / raw)
  To: Jon Masters
  Cc: Timur Tabi, Guenter Roeck, Suravee Suthikulpanit,
	Linaro ACPI Mailman List, linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, LKML,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Hanjun Guo, Ashwin Chaugule, Arnd Bergmann, Vipul Gandhi,
	Wim Van Sebroeck, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, Rafael Wysocki

Hi Jon,

On 11 September 2015 at 06:45, Jon Masters <jcm-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> On 06/03/2015 02:53 PM, Timur Tabi wrote:
>> On 06/03/2015 01:25 PM, Guenter Roeck wrote:
>>> In general the idea here would be to use a crashdump kernel, which,
>>> when loaded, would reset the watchdog before it fires. This kernel
>>> would then write a core dump to a specified location.
>>
>> What is the mechanism for resetting the watchdog?  The only code that
>> knows about the hardware registers is this driver.  Does the crashdump
>> kernel call the watchdog stop function?
>>
>>> If arm64 doesn't support a crashdump kernel, it might still be possible
>>> to log the backtrace somewhere (eg in nvram using pstore if that is
>>> supported via acpi or efi).
>
> Just to go back and explicitly answer this, arm64 does have support for
> crashdump, using the standard kexec/kdump approach, exactly as on x86.
> There's still some more work to be done to get the ACPI case fully
> upstream (e.g. on X-Gene platforms such as the HP ProLiant Moonshot m400
> we need non-PSCI CPU parking protocol offlining when booting in
> UEFI/ACPI mode), but it's what we are doing in RHEL(SA) and the goal is
> to help clean up the remaining pieces upstream there.

Great thanks for your info.

I have tried kexec/kdump on a real aarch64 hardware, that works well.
Although it's still under development and upstreaming, the support is there.

After discussing with some kexec/kdump  developer, I think this driver
can cooperate with kexec/kdump.

>
> Jon.
>



-- 
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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver
  2015-08-24 17:01   ` [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
  2015-09-10 22:29     ` Jon Masters
@ 2015-09-15  8:38     ` Dave Young
  2015-09-15 10:07       ` Fu Wei
  1 sibling, 1 reply; 550+ messages in thread
From: Dave Young @ 2015-09-15  8:38 UTC (permalink / raw)
  To: fu.wei
  Cc: Suravee.Suthikulpanit, hanjun.guo, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, arnd, linux, vgandhi, wim, jcm,
	leo.duran, corbet, mark.rutland, catalin.marinas, will.deacon,
	rjw, panand

On 08/25/15 at 01:01am, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> 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, the interrupt routine run panic to save
> system context.
> 
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  drivers/watchdog/Kconfig     |  14 ++
>  drivers/watchdog/Makefile    |   1 +
>  drivers/watchdog/sbsa_gwdt.c | 459 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 474 insertions(+)
> 
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 241fafd..b2734f0 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -173,6 +173,20 @@ 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 ARM64
> +	depends on ARM_ARCH_TIMER
> +	select WATCHDOG_CORE
> +	help
> +	  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.
> +	  More details: ARM DEN0029B - Server Base System Architecture (SBSA)
> +
> +	  To compile this driver as module, choose M here: The module
> +	  will be called sbsa_gwdt.
> +
>  config AT91RM9200_WATCHDOG
>  	tristate "AT91RM9200 watchdog"
>  	depends on SOC_AT91RM9200 && MFD_SYSCON
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index 59ea9a1..be8e7c5 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..7ae45cc
> --- /dev/null
> +++ b/drivers/watchdog/sbsa_gwdt.c
> @@ -0,0 +1,459 @@
> +/*
> + * SBSA(Server Base System Architecture) Generic Watchdog driver
> + *
> + * Copyright (c) 2015, Linaro Ltd.
> + * Author: Fu Wei <fu.wei@linaro.org>
> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> + *
> + * 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.
> + *
> + * The SBSA Generic watchdog driver is compatible with the pretimeout
> + * concept of Linux kernel.
> + * The timeout and pretimeout are determined by WCV or WOR.
> + * The first watch period is set by writing WCV directly, that can
> + * support more than 10s timeout at the maximum system counter
> + * frequency (400MHz).
> + * When WS0 is triggered, the second watch period (pretimeout) is
> + * determined by one of these registers:
> + * (1)WOR: 32bit register, this gives a maximum watch period of
> + * around 10s at the maximum system counter frequency. It's loaded
> + * automatically by hardware.
> + * (2)WCV: If the pretimeout value is greater then "max_wor_timeout",
> + * it will be loaded in WS0 interrupt routine. If system is in
> + * ws0_mode (reboot by kexec/kdump in panic with watchdog enabled
> + * and WS0 == true), the ping operation will only reload WCV.

Below is the field comment about ws0_mode, it says ws0_mode is only
for rebooting in second stage timeout, but kexec/kdump can reboot in
either first or second stage
 * @ws0_mode:		indicate the system boot in the second stage timeout.


> + * More details about the hardware specification of this device:
> + * ARM DEN0029B - Server Base System Architecture (SBSA)
> + *
> + * Kernel/API:                         P------------------| pretimeout
> + *               |----------------------------------------T timeout
> + * SBSA GWDT:                          P---WOR (or WCV)---WS1 pretimeout
> + *               |-------WCV----------WS0~~~(ws0_mode)~~~~T timeout
> + */
> +
> +#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>
> +#include <asm/arch_timer.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.
> + * @ws0_mode:		indicate the system boot in the second stage timeout.
> + * @max_wor_timeout:	the maximum timeout value for WOR (in seconds).
> + * @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;
> +	bool			ws0_mode;
> +	int			max_wor_timeout;
> +	void __iomem		*refresh_base;
> +	void __iomem		*control_base;
> +};
> +
> +#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
> +
> +#define DEFAULT_TIMEOUT		30 /* seconds, the 1st + 2nd watch periods*/
> +#define DEFAULT_PRETIMEOUT	10 /* 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 pretimeout;
> +module_param(pretimeout, uint, 0);
> +MODULE_PARM_DESC(pretimeout,
> +		 "Watchdog pretimeout in seconds. (>=0, default="
> +		 __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
> +
> +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) ")");
> +
> +/*
> + * help functions for accessing 64bit WCV register
> + */
> +static u64 sbsa_gwdt_get_wcv(struct watchdog_device *wdd)
> +{
> +	u32 wcv_lo, wcv_hi;
> +	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +
> +	do {
> +		wcv_hi = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_HI);
> +		wcv_lo = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_LO);
> +	} while (wcv_hi != readl_relaxed(gwdt->control_base +
> +					 SBSA_GWDT_WCV_HI));
> +
> +	return (((u64)wcv_hi << 32) | wcv_lo);
> +}
> +
> +static void sbsa_gwdt_set_wcv(struct watchdog_device *wdd, unsigned int t)
> +{
> +	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +	u64 wcv;
> +
> +	wcv = arch_counter_get_cntvct() + (u64)t * gwdt->clk;
> +
> +	writel_relaxed(upper_32_bits(wcv),
> +		       gwdt->control_base + SBSA_GWDT_WCV_HI);
> +	writel_relaxed(lower_32_bits(wcv),
> +		       gwdt->control_base + SBSA_GWDT_WCV_LO);
> +}
> +
> +/*
> + * inline functions for reloading 64bit WCV register
> + */
> +static inline void reload_pretimeout_to_wcv(struct watchdog_device *wdd)
> +{
> +	sbsa_gwdt_set_wcv(wdd, wdd->pretimeout);
> +}
> +
> +static inline void reload_first_stage_to_wcv(struct watchdog_device *wdd)
> +{
> +	sbsa_gwdt_set_wcv(wdd, wdd->timeout - wdd->pretimeout);
> +}
> +
> +/*
> + * watchdog operation functions
> + */
> +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;
> +
> +	/* If ws0_mode == true, we won't touch WOR */
> +	if (!gwdt->ws0_mode) {
> +		if (!pretimeout)
> +			/*
> +			 * If pretimeout is 0, it gives driver a timeslot (1s)
> +			 * to update WCV after an explicit refresh
> +			 * (sbsa_gwdt_start)
> +			 */
> +			wor = gwdt->clk;
> +		else
> +			if (pretimeout > gwdt->max_wor_timeout)
> +				wor = U32_MAX;
> +			else
> +				wor = pretimeout * gwdt->clk;
> +
> +		/* wtite WOR, that will cause an explicit watchdog refresh */
> +		writel_relaxed(wor, gwdt->control_base + SBSA_GWDT_WOR);
> +	}
> +
> +	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_keepalive(struct watchdog_device *wdd)
> +{
> +	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +
> +	if (gwdt->ws0_mode)
> +		reload_pretimeout_to_wcv(wdd);
> +	else
> +		reload_first_stage_to_wcv(wdd);
> +
> +	return 0;
> +}
> +
> +static int sbsa_gwdt_start(struct watchdog_device *wdd)
> +{
> +	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +
> +	/* If ws0_mode == true, the watchdog is enabled */
> +	if (!gwdt->ws0_mode)
> +		/* writing WCS will cause an explicit watchdog refresh */
> +		writel_relaxed(SBSA_GWDT_WCS_EN,
> +			       gwdt->control_base + SBSA_GWDT_WCS);
> +
> +	return sbsa_gwdt_keepalive(wdd);
> +}
> +
> +static int sbsa_gwdt_stop(struct watchdog_device *wdd)
> +{
> +	struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
> +
> +	writel_relaxed(0, gwdt->control_base + SBSA_GWDT_WCS);
> +	/*
> +	 * Writing WCS has caused an explicit watchdog refresh.
> +	 * Both watchdog signals are deasserted, so clean ws0_mode flag.
> +	 */
> +	gwdt->ws0_mode = false;
> +
> +	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;
> +
> +	/* We don't use pretimeout, trigger WS1 now */
> +	if (!wdd->pretimeout)
> +		sbsa_gwdt_set_wcv(wdd, 0);
> +
> +	/*
> +	 * The pretimeout is valid, go panic
> +	 * If pretimeout is greater then "max_wor_timeout",
> +	 * reload the right value to WCV, then panic
> +	 */
> +	if (wdd->pretimeout > gwdt->max_wor_timeout)
> +		reload_pretimeout_to_wcv(wdd);
> +	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)
> +{
> +	void __iomem *rf_base, *cf_base;
> +	struct device *dev = &pdev->dev;
> +	struct watchdog_device *wdd;
> +	struct sbsa_gwdt *gwdt;
> +	struct resource *res;
> +	int ret, irq;
> +	u32 status;
> +
> +	gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
> +	if (!gwdt)
> +		return -ENOMEM;
> +	platform_set_drvdata(pdev, gwdt);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	cf_base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(cf_base))
> +		return PTR_ERR(cf_base);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	rf_base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(rf_base))
> +		return PTR_ERR(rf_base);
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0) {
> +		dev_err(dev, "unable to get ws0 interrupt.\n");
> +		return irq;
> +	}
> +
> +	/*
> +	 * Get the frequency of system counter from the cp15 interface of ARM
> +	 * Generic timer. We don't need to check it, because if it returns "0",
> +	 * system would panic in very early stage.
> +	 */
> +	gwdt->clk = arch_timer_get_cntfrq();
> +	gwdt->refresh_base = rf_base;
> +	gwdt->control_base = cf_base;
> +	gwdt->max_wor_timeout = U32_MAX / gwdt->clk;
> +	gwdt->ws0_mode = false;
> +
> +	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);
> +
> +	wdd->min_pretimeout = 0;
> +	wdd->min_timeout = 1;
> +
> +	/*
> +	 * Because the maximum of gwdt->clk is 400MHz and the maximum of WCV is
> +	 * U64_MAX, so the result of (U64_MAX / gwdt->clk) is always greater
> +	 * than U32_MAX. And the maximum of "unsigned int" is U32_MAX on ARM64.
> +	 * So we set the maximum value of pretimeout and timeout below.
> +	 */
> +	wdd->max_pretimeout = U32_MAX - 1;
> +	wdd->max_timeout = U32_MAX;
> +
> +	wdd->pretimeout = DEFAULT_PRETIMEOUT;
> +	wdd->timeout = DEFAULT_TIMEOUT;
> +	watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
> +
> +	status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
> +	if (status & SBSA_GWDT_WCS_WS1) {
> +		dev_warn(dev, "System reset by WDT.\n");
> +		wdd->bootstatus |= WDIOF_CARDRESET;
> +	} else if (status == (SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_EN)) {
> +		gwdt->ws0_mode = true;
> +	}
> +
> +	ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
> +			       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;
> +
> +	/* If ws0_mode == true, the line won't update WOR */
> +	sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
> +
> +	/*
> +	 * If watchdog is already enabled, do a ping operation
> +	 * to keep system running
> +	 */
> +	if (status & SBSA_GWDT_WCS_EN)
> +		sbsa_gwdt_keepalive(wdd);
> +
> +	dev_info(dev, "Initialized with %ds timeout, %ds pretimeout @ %u Hz%s\n",
> +		 wdd->timeout, wdd->pretimeout, gwdt->clk,
> +		 status & SBSA_GWDT_WCS_EN ?
> +			gwdt->ws0_mode ? " [second stage]" : " [enabled]" :
> +			"");
> +
> +	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);
> +
> +	watchdog_unregister_device(&gwdt->wdd);
> +
> +	return 0;
> +}
> +
> +/* 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_AUTHOR("Fu Wei <fu.wei@linaro.org>");
> +MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
> +MODULE_LICENSE("GPL v2");
> -- 
> 2.4.3
> 

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 2/8] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
@ 2015-09-15  8:43       ` Dave Young
  0 siblings, 0 replies; 550+ messages in thread
From: Dave Young @ 2015-09-15  8:43 UTC (permalink / raw)
  To: fu.wei
  Cc: Suravee.Suthikulpanit, hanjun.guo, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, arnd, linux, vgandhi, wim, jcm,
	leo.duran, corbet, mark.rutland, catalin.marinas, will.deacon,
	rjw, panand

On 08/25/15 at 01:01am, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> This can be a example of adding SBSA Generic Watchdog device node
> into some dts files for the Soc which contains SBSA Generic Watchdog.
> 
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  arch/arm64/boot/dts/arm/foundation-v8.dts | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dts b/arch/arm64/boot/dts/arm/foundation-v8.dts
> index 4eac8dc..824431f 100644
> --- a/arch/arm64/boot/dts/arm/foundation-v8.dts
> +++ b/arch/arm64/boot/dts/arm/foundation-v8.dts
> @@ -237,4 +237,11 @@
>  			};
>  		};
>  	};
> +	watchdog@2a440000 {
> +		compatible = "arm,sbsa-gwdt";
> +		reg = <0x0 0x2a440000 0 0x1000>,
> +			<0x0 0x2a450000 0 0x1000>;
> +		interrupts = <0 27 4>;
> +		timeout-sec = <10 5>;

I assume 10 is timeout, 5 is pre timeout, but in the driver code the default
value is 30/10, I think the example dts[i] should use same default values as in code.

BTW, for kdump kernel Pratyush is working on kdump on wdt enabled system. 
Basiclly we expect one configure longer timeout, and kick it in shorter
period so we can get a chance to save vmcore. 10s sounds too short for the case..

> +	};
>  };
> -- 
> 2.4.3
> 

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 2/8] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
@ 2015-09-15  8:43       ` Dave Young
  0 siblings, 0 replies; 550+ messages in thread
From: Dave Young @ 2015-09-15  8:43 UTC (permalink / raw)
  To: fu.wei-QSEj5FYQhm4dnm+yROfE0A
  Cc: Suravee.Suthikulpanit-5C7GfCeVMHo,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A,
	linaro-acpi-cunTk1MwBs8s++Sfvej+rw,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	tekkamanninja-Re5JQEeQqe8AvxtiuMwx3w,
	graeme.gregory-QSEj5FYQhm4dnm+yROfE0A,
	al.stone-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-0h96xk9xTtrk1uMJSBkQmQ, vgandhi-sgV2jX0FEOL9JmXXK+q4OQ,
	wim-IQzOog9fTRqzQB+pC5nmwQ, jcm-H+wXaHxf7aLQT0dZR+AlfA,
	leo.duran-5C7GfCeVMHo, corbet-T1hC0tSOHrs,
	mark.rutland-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, rjw-LthD3rsA81gm4RdzfppkhA,
	panand-H+wXaHxf7aLQT0dZR+AlfA

On 08/25/15 at 01:01am, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> From: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> 
> This can be a example of adding SBSA Generic Watchdog device node
> into some dts files for the Soc which contains SBSA Generic Watchdog.
> 
> Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> Signed-off-by: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>  arch/arm64/boot/dts/arm/foundation-v8.dts | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dts b/arch/arm64/boot/dts/arm/foundation-v8.dts
> index 4eac8dc..824431f 100644
> --- a/arch/arm64/boot/dts/arm/foundation-v8.dts
> +++ b/arch/arm64/boot/dts/arm/foundation-v8.dts
> @@ -237,4 +237,11 @@
>  			};
>  		};
>  	};
> +	watchdog@2a440000 {
> +		compatible = "arm,sbsa-gwdt";
> +		reg = <0x0 0x2a440000 0 0x1000>,
> +			<0x0 0x2a450000 0 0x1000>;
> +		interrupts = <0 27 4>;
> +		timeout-sec = <10 5>;

I assume 10 is timeout, 5 is pre timeout, but in the driver code the default
value is 30/10, I think the example dts[i] should use same default values as in code.

BTW, for kdump kernel Pratyush is working on kdump on wdt enabled system. 
Basiclly we expect one configure longer timeout, and kick it in shorter
period so we can get a chance to save vmcore. 10s sounds too short for the case..

> +	};
>  };
> -- 
> 2.4.3
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 2/8] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
  2015-09-15  8:43       ` Dave Young
  (?)
@ 2015-09-15  9:44       ` Pratyush Anand
  2015-09-15 10:23         ` Fu Wei
  -1 siblings, 1 reply; 550+ messages in thread
From: Pratyush Anand @ 2015-09-15  9:44 UTC (permalink / raw)
  To: Dave Young
  Cc: fu.wei, Suravee.Suthikulpanit, hanjun.guo, linaro-acpi,
	linux-watchdog, devicetree, linux-kernel, linux-doc,
	tekkamanninja, graeme.gregory, al.stone, arnd, linux, vgandhi,
	wim, jcm, leo.duran, corbet, mark.rutland, catalin.marinas,
	will.deacon, rjw, Geoff Levand

On 15/09/2015:04:43:32 PM, Dave Young wrote:
> On 08/25/15 at 01:01am, fu.wei@linaro.org wrote:
> > From: Fu Wei <fu.wei@linaro.org>
> > 
> > This can be a example of adding SBSA Generic Watchdog device node
> > into some dts files for the Soc which contains SBSA Generic Watchdog.
> > 
> > Acked-by: Arnd Bergmann <arnd@arndb.de>
> > Signed-off-by: Fu Wei <fu.wei@linaro.org>
> > ---
> >  arch/arm64/boot/dts/arm/foundation-v8.dts | 7 +++++++
> >  1 file changed, 7 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dts b/arch/arm64/boot/dts/arm/foundation-v8.dts
> > index 4eac8dc..824431f 100644
> > --- a/arch/arm64/boot/dts/arm/foundation-v8.dts
> > +++ b/arch/arm64/boot/dts/arm/foundation-v8.dts
> > @@ -237,4 +237,11 @@
> >  			};
> >  		};
> >  	};
> > +	watchdog@2a440000 {
> > +		compatible = "arm,sbsa-gwdt";
> > +		reg = <0x0 0x2a440000 0 0x1000>,
> > +			<0x0 0x2a450000 0 0x1000>;
> > +		interrupts = <0 27 4>;
> > +		timeout-sec = <10 5>;
> 
> I assume 10 is timeout, 5 is pre timeout, but in the driver code the default
> value is 30/10, I think the example dts[i] should use same default values as in code.
> 
> BTW, for kdump kernel Pratyush is working on kdump on wdt enabled system. 
> Basiclly we expect one configure longer timeout, and kick it in shorter
> period so we can get a chance to save vmcore. 10s sounds too short for the case..

Specially if D-cache is not enabled in ARM64 kexec-tool/purgatory then its more
than 2 min. Geoff has yet not agreed [1] to take D-cache support in purgatory.

[1] https://www.mail-archive.com/kexec@lists.infradead.org/msg12881.html

~Pratyush

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver
  2015-09-15  8:38     ` Dave Young
@ 2015-09-15 10:07       ` Fu Wei
  2015-09-16  1:57         ` Dave Young
  0 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-09-15 10:07 UTC (permalink / raw)
  To: Dave Young
  Cc: Suravee Suthikulpanit, Hanjun Guo, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, LKML, linux-doc, Wei Fu, G Gregory,
	Al Stone, Arnd Bergmann, Guenter Roeck, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	Pratyush Anand

Hi Dave,

On 15 September 2015 at 16:38, Dave Young <dyoung@redhat.com> wrote:
> On 08/25/15 at 01:01am, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> 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, the interrupt routine run panic to save
>> system context.
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  drivers/watchdog/Kconfig     |  14 ++
>>  drivers/watchdog/Makefile    |   1 +
>>  drivers/watchdog/sbsa_gwdt.c | 459 +++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 474 insertions(+)
>>
>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>> index 241fafd..b2734f0 100644
>> --- a/drivers/watchdog/Kconfig
>> +++ b/drivers/watchdog/Kconfig
>> @@ -173,6 +173,20 @@ 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 ARM64
>> +     depends on ARM_ARCH_TIMER
>> +     select WATCHDOG_CORE
>> +     help
>> +       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.
>> +       More details: ARM DEN0029B - Server Base System Architecture (SBSA)
>> +
>> +       To compile this driver as module, choose M here: The module
>> +       will be called sbsa_gwdt.
>> +
>>  config AT91RM9200_WATCHDOG
>>       tristate "AT91RM9200 watchdog"
>>       depends on SOC_AT91RM9200 && MFD_SYSCON
>> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
>> index 59ea9a1..be8e7c5 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..7ae45cc
>> --- /dev/null
>> +++ b/drivers/watchdog/sbsa_gwdt.c
>> @@ -0,0 +1,459 @@
>> +/*
>> + * SBSA(Server Base System Architecture) Generic Watchdog driver
>> + *
>> + * Copyright (c) 2015, Linaro Ltd.
>> + * Author: Fu Wei <fu.wei@linaro.org>
>> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>> + *
>> + * 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.
>> + *
>> + * The SBSA Generic watchdog driver is compatible with the pretimeout
>> + * concept of Linux kernel.
>> + * The timeout and pretimeout are determined by WCV or WOR.
>> + * The first watch period is set by writing WCV directly, that can
>> + * support more than 10s timeout at the maximum system counter
>> + * frequency (400MHz).
>> + * When WS0 is triggered, the second watch period (pretimeout) is
>> + * determined by one of these registers:
>> + * (1)WOR: 32bit register, this gives a maximum watch period of
>> + * around 10s at the maximum system counter frequency. It's loaded
>> + * automatically by hardware.
>> + * (2)WCV: If the pretimeout value is greater then "max_wor_timeout",
>> + * it will be loaded in WS0 interrupt routine. If system is in
>> + * ws0_mode (reboot by kexec/kdump in panic with watchdog enabled
>> + * and WS0 == true), the ping operation will only reload WCV.
>
> Below is the field comment about ws0_mode, it says ws0_mode is only
> for rebooting in second stage timeout, but kexec/kdump can reboot in
> either first or second stage

Great thanks for your feedback.

yes, if kexec/kdump reboot the system before the WS0, ws0_mode may not be set.
in this case, if WS0 is triggered during the reboot(AFAIK, panic will
disable irq, and in the early boot stage of system, irq is disabled,
too.), ws0_mode will be set at the next "open" in kdump kernel
if WS0 haven't triggered until the watchdog is opened again in kdump
kernel , ws0_mode won't  be set.

ws0_mode doesn't indicate if the system is in the kdump kernel, it
indicates that if WS0 is triggered, when the watchdog is initialized.

Do I answer your question?

>  * @ws0_mode:           indicate the system boot in the second stage timeout.
>
>
>> + * More details about the hardware specification of this device:
>> + * ARM DEN0029B - Server Base System Architecture (SBSA)
>> + *
>> + * Kernel/API:                         P------------------| pretimeout
>> + *               |----------------------------------------T timeout
>> + * SBSA GWDT:                          P---WOR (or WCV)---WS1 pretimeout
>> + *               |-------WCV----------WS0~~~(ws0_mode)~~~~T timeout
>> + */
>> +
>> +#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>
>> +#include <asm/arch_timer.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.
>> + * @ws0_mode:                indicate the system boot in the second stage timeout.
>> + * @max_wor_timeout: the maximum timeout value for WOR (in seconds).
>> + * @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;
>> +     bool                    ws0_mode;
>> +     int                     max_wor_timeout;
>> +     void __iomem            *refresh_base;
>> +     void __iomem            *control_base;
>> +};
>> +
>> +#define to_sbsa_gwdt(e) container_of(e, struct sbsa_gwdt, wdd)
>> +
>> +#define DEFAULT_TIMEOUT              30 /* seconds, the 1st + 2nd watch periods*/
>> +#define DEFAULT_PRETIMEOUT   10 /* 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 pretimeout;
>> +module_param(pretimeout, uint, 0);
>> +MODULE_PARM_DESC(pretimeout,
>> +              "Watchdog pretimeout in seconds. (>=0, default="
>> +              __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
>> +
>> +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) ")");
>> +
>> +/*
>> + * help functions for accessing 64bit WCV register
>> + */
>> +static u64 sbsa_gwdt_get_wcv(struct watchdog_device *wdd)
>> +{
>> +     u32 wcv_lo, wcv_hi;
>> +     struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> +
>> +     do {
>> +             wcv_hi = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_HI);
>> +             wcv_lo = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCV_LO);
>> +     } while (wcv_hi != readl_relaxed(gwdt->control_base +
>> +                                      SBSA_GWDT_WCV_HI));
>> +
>> +     return (((u64)wcv_hi << 32) | wcv_lo);
>> +}
>> +
>> +static void sbsa_gwdt_set_wcv(struct watchdog_device *wdd, unsigned int t)
>> +{
>> +     struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> +     u64 wcv;
>> +
>> +     wcv = arch_counter_get_cntvct() + (u64)t * gwdt->clk;
>> +
>> +     writel_relaxed(upper_32_bits(wcv),
>> +                    gwdt->control_base + SBSA_GWDT_WCV_HI);
>> +     writel_relaxed(lower_32_bits(wcv),
>> +                    gwdt->control_base + SBSA_GWDT_WCV_LO);
>> +}
>> +
>> +/*
>> + * inline functions for reloading 64bit WCV register
>> + */
>> +static inline void reload_pretimeout_to_wcv(struct watchdog_device *wdd)
>> +{
>> +     sbsa_gwdt_set_wcv(wdd, wdd->pretimeout);
>> +}
>> +
>> +static inline void reload_first_stage_to_wcv(struct watchdog_device *wdd)
>> +{
>> +     sbsa_gwdt_set_wcv(wdd, wdd->timeout - wdd->pretimeout);
>> +}
>> +
>> +/*
>> + * watchdog operation functions
>> + */
>> +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;
>> +
>> +     /* If ws0_mode == true, we won't touch WOR */
>> +     if (!gwdt->ws0_mode) {
>> +             if (!pretimeout)
>> +                     /*
>> +                      * If pretimeout is 0, it gives driver a timeslot (1s)
>> +                      * to update WCV after an explicit refresh
>> +                      * (sbsa_gwdt_start)
>> +                      */
>> +                     wor = gwdt->clk;
>> +             else
>> +                     if (pretimeout > gwdt->max_wor_timeout)
>> +                             wor = U32_MAX;
>> +                     else
>> +                             wor = pretimeout * gwdt->clk;
>> +
>> +             /* wtite WOR, that will cause an explicit watchdog refresh */
>> +             writel_relaxed(wor, gwdt->control_base + SBSA_GWDT_WOR);
>> +     }
>> +
>> +     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_keepalive(struct watchdog_device *wdd)
>> +{
>> +     struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> +
>> +     if (gwdt->ws0_mode)
>> +             reload_pretimeout_to_wcv(wdd);
>> +     else
>> +             reload_first_stage_to_wcv(wdd);
>> +
>> +     return 0;
>> +}
>> +
>> +static int sbsa_gwdt_start(struct watchdog_device *wdd)
>> +{
>> +     struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> +
>> +     /* If ws0_mode == true, the watchdog is enabled */
>> +     if (!gwdt->ws0_mode)
>> +             /* writing WCS will cause an explicit watchdog refresh */
>> +             writel_relaxed(SBSA_GWDT_WCS_EN,
>> +                            gwdt->control_base + SBSA_GWDT_WCS);
>> +
>> +     return sbsa_gwdt_keepalive(wdd);
>> +}
>> +
>> +static int sbsa_gwdt_stop(struct watchdog_device *wdd)
>> +{
>> +     struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
>> +
>> +     writel_relaxed(0, gwdt->control_base + SBSA_GWDT_WCS);
>> +     /*
>> +      * Writing WCS has caused an explicit watchdog refresh.
>> +      * Both watchdog signals are deasserted, so clean ws0_mode flag.
>> +      */
>> +     gwdt->ws0_mode = false;
>> +
>> +     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;
>> +
>> +     /* We don't use pretimeout, trigger WS1 now */
>> +     if (!wdd->pretimeout)
>> +             sbsa_gwdt_set_wcv(wdd, 0);
>> +
>> +     /*
>> +      * The pretimeout is valid, go panic
>> +      * If pretimeout is greater then "max_wor_timeout",
>> +      * reload the right value to WCV, then panic
>> +      */
>> +     if (wdd->pretimeout > gwdt->max_wor_timeout)
>> +             reload_pretimeout_to_wcv(wdd);
>> +     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)
>> +{
>> +     void __iomem *rf_base, *cf_base;
>> +     struct device *dev = &pdev->dev;
>> +     struct watchdog_device *wdd;
>> +     struct sbsa_gwdt *gwdt;
>> +     struct resource *res;
>> +     int ret, irq;
>> +     u32 status;
>> +
>> +     gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
>> +     if (!gwdt)
>> +             return -ENOMEM;
>> +     platform_set_drvdata(pdev, gwdt);
>> +
>> +     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +     cf_base = devm_ioremap_resource(dev, res);
>> +     if (IS_ERR(cf_base))
>> +             return PTR_ERR(cf_base);
>> +
>> +     res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
>> +     rf_base = devm_ioremap_resource(dev, res);
>> +     if (IS_ERR(rf_base))
>> +             return PTR_ERR(rf_base);
>> +
>> +     irq = platform_get_irq(pdev, 0);
>> +     if (irq < 0) {
>> +             dev_err(dev, "unable to get ws0 interrupt.\n");
>> +             return irq;
>> +     }
>> +
>> +     /*
>> +      * Get the frequency of system counter from the cp15 interface of ARM
>> +      * Generic timer. We don't need to check it, because if it returns "0",
>> +      * system would panic in very early stage.
>> +      */
>> +     gwdt->clk = arch_timer_get_cntfrq();
>> +     gwdt->refresh_base = rf_base;
>> +     gwdt->control_base = cf_base;
>> +     gwdt->max_wor_timeout = U32_MAX / gwdt->clk;
>> +     gwdt->ws0_mode = false;
>> +
>> +     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);
>> +
>> +     wdd->min_pretimeout = 0;
>> +     wdd->min_timeout = 1;
>> +
>> +     /*
>> +      * Because the maximum of gwdt->clk is 400MHz and the maximum of WCV is
>> +      * U64_MAX, so the result of (U64_MAX / gwdt->clk) is always greater
>> +      * than U32_MAX. And the maximum of "unsigned int" is U32_MAX on ARM64.
>> +      * So we set the maximum value of pretimeout and timeout below.
>> +      */
>> +     wdd->max_pretimeout = U32_MAX - 1;
>> +     wdd->max_timeout = U32_MAX;
>> +
>> +     wdd->pretimeout = DEFAULT_PRETIMEOUT;
>> +     wdd->timeout = DEFAULT_TIMEOUT;
>> +     watchdog_init_timeouts(wdd, pretimeout, timeout, dev);
>> +
>> +     status = readl_relaxed(gwdt->control_base + SBSA_GWDT_WCS);
>> +     if (status & SBSA_GWDT_WCS_WS1) {
>> +             dev_warn(dev, "System reset by WDT.\n");
>> +             wdd->bootstatus |= WDIOF_CARDRESET;
>> +     } else if (status == (SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_EN)) {
>> +             gwdt->ws0_mode = true;
>> +     }
>> +
>> +     ret = devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
>> +                            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;
>> +
>> +     /* If ws0_mode == true, the line won't update WOR */
>> +     sbsa_gwdt_set_pretimeout(wdd, wdd->pretimeout);
>> +
>> +     /*
>> +      * If watchdog is already enabled, do a ping operation
>> +      * to keep system running
>> +      */
>> +     if (status & SBSA_GWDT_WCS_EN)
>> +             sbsa_gwdt_keepalive(wdd);
>> +
>> +     dev_info(dev, "Initialized with %ds timeout, %ds pretimeout @ %u Hz%s\n",
>> +              wdd->timeout, wdd->pretimeout, gwdt->clk,
>> +              status & SBSA_GWDT_WCS_EN ?
>> +                     gwdt->ws0_mode ? " [second stage]" : " [enabled]" :
>> +                     "");
>> +
>> +     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);
>> +
>> +     watchdog_unregister_device(&gwdt->wdd);
>> +
>> +     return 0;
>> +}
>> +
>> +/* 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_AUTHOR("Fu Wei <fu.wei@linaro.org>");
>> +MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
>> +MODULE_LICENSE("GPL v2");
>> --
>> 2.4.3
>>



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 2/8] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
  2015-09-15  8:43       ` Dave Young
  (?)
  (?)
@ 2015-09-15 10:15       ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-09-15 10:15 UTC (permalink / raw)
  To: Dave Young
  Cc: Suravee Suthikulpanit, Hanjun Guo, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, LKML, linux-doc, Wei Fu, G Gregory,
	Al Stone, Arnd Bergmann, Guenter Roeck, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	Pratyush Anand

Hi Dave,

On 15 September 2015 at 16:43, Dave Young <dyoung@redhat.com> wrote:
> On 08/25/15 at 01:01am, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> This can be a example of adding SBSA Generic Watchdog device node
>> into some dts files for the Soc which contains SBSA Generic Watchdog.
>>
>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  arch/arm64/boot/dts/arm/foundation-v8.dts | 7 +++++++
>>  1 file changed, 7 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dts b/arch/arm64/boot/dts/arm/foundation-v8.dts
>> index 4eac8dc..824431f 100644
>> --- a/arch/arm64/boot/dts/arm/foundation-v8.dts
>> +++ b/arch/arm64/boot/dts/arm/foundation-v8.dts
>> @@ -237,4 +237,11 @@
>>                       };
>>               };
>>       };
>> +     watchdog@2a440000 {
>> +             compatible = "arm,sbsa-gwdt";
>> +             reg = <0x0 0x2a440000 0 0x1000>,
>> +                     <0x0 0x2a450000 0 0x1000>;
>> +             interrupts = <0 27 4>;
>> +             timeout-sec = <10 5>;
>
> I assume 10 is timeout, 5 is pre timeout, but in the driver code the default
> value is 30/10, I think the example dts[i] should use same default values as in code.

yes, that is good idea, will make them to be the same.  :-)

>
> BTW, for kdump kernel Pratyush is working on kdump on wdt enabled system.
> Basiclly we expect one configure longer timeout, and kick it in shorter
> period so we can get a chance to save vmcore. 10s sounds too short for the case..

Thanks for your info.

So that means: we may need that long timeout support in the second stage.
WOR is not enough for  the second stage in most of kdump case.

>
>> +     };
>>  };
>> --
>> 2.4.3
>>



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 2/8] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts
  2015-09-15  9:44       ` Pratyush Anand
@ 2015-09-15 10:23         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-09-15 10:23 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: Dave Young, Suravee Suthikulpanit, Hanjun Guo,
	Linaro ACPI Mailman List, linux-watchdog, devicetree, LKML,
	linux-doc, Wei Fu, G Gregory, Al Stone, Arnd Bergmann,
	Guenter Roeck, Vipul Gandhi, Wim Van Sebroeck, Jon Masters,
	Leo Duran, Jon Corbet, Mark Rutland, Catalin Marinas,
	Will Deacon, Rafael Wysocki, Geoff Levand

Hi Pratyush,



On 15 September 2015 at 17:44, Pratyush Anand <panand@redhat.com> wrote:
> On 15/09/2015:04:43:32 PM, Dave Young wrote:
>> On 08/25/15 at 01:01am, fu.wei@linaro.org wrote:
>> > From: Fu Wei <fu.wei@linaro.org>
>> >
>> > This can be a example of adding SBSA Generic Watchdog device node
>> > into some dts files for the Soc which contains SBSA Generic Watchdog.
>> >
>> > Acked-by: Arnd Bergmann <arnd@arndb.de>
>> > Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> > ---
>> >  arch/arm64/boot/dts/arm/foundation-v8.dts | 7 +++++++
>> >  1 file changed, 7 insertions(+)
>> >
>> > diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dts b/arch/arm64/boot/dts/arm/foundation-v8.dts
>> > index 4eac8dc..824431f 100644
>> > --- a/arch/arm64/boot/dts/arm/foundation-v8.dts
>> > +++ b/arch/arm64/boot/dts/arm/foundation-v8.dts
>> > @@ -237,4 +237,11 @@
>> >                     };
>> >             };
>> >     };
>> > +   watchdog@2a440000 {
>> > +           compatible = "arm,sbsa-gwdt";
>> > +           reg = <0x0 0x2a440000 0 0x1000>,
>> > +                   <0x0 0x2a450000 0 0x1000>;
>> > +           interrupts = <0 27 4>;
>> > +           timeout-sec = <10 5>;
>>
>> I assume 10 is timeout, 5 is pre timeout, but in the driver code the default
>> value is 30/10, I think the example dts[i] should use same default values as in code.
>>
>> BTW, for kdump kernel Pratyush is working on kdump on wdt enabled system.
>> Basiclly we expect one configure longer timeout, and kick it in shorter
>> period so we can get a chance to save vmcore. 10s sounds too short for the case..
>
> Specially if D-cache is not enabled in ARM64 kexec-tool/purgatory then its more
> than 2 min. Geoff has yet not agreed [1] to take D-cache support in purgatory.
>
> [1] https://www.mail-archive.com/kexec@lists.infradead.org/msg12881.html

Great thanks for your info.
I thinks I may need to make the default pretimeout longer in example,
may be at least 30s(for kdump kernel  with  D-cache)

any thought?

>
> ~Pratyush



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver
  2015-09-15 10:07       ` Fu Wei
@ 2015-09-16  1:57         ` Dave Young
  2015-10-13  8:34             ` Fu Wei
  0 siblings, 1 reply; 550+ messages in thread
From: Dave Young @ 2015-09-16  1:57 UTC (permalink / raw)
  To: Fu Wei
  Cc: Suravee Suthikulpanit, Hanjun Guo, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, LKML, linux-doc, Wei Fu, G Gregory,
	Al Stone, Arnd Bergmann, Guenter Roeck, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	Pratyush Anand

> >> diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
> >> new file mode 100644
> >> index 0000000..7ae45cc
> >> --- /dev/null
> >> +++ b/drivers/watchdog/sbsa_gwdt.c
> >> @@ -0,0 +1,459 @@
> >> +/*
> >> + * SBSA(Server Base System Architecture) Generic Watchdog driver
> >> + *
> >> + * Copyright (c) 2015, Linaro Ltd.
> >> + * Author: Fu Wei <fu.wei@linaro.org>
> >> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> >> + *
> >> + * 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.
> >> + *
> >> + * The SBSA Generic watchdog driver is compatible with the pretimeout
> >> + * concept of Linux kernel.
> >> + * The timeout and pretimeout are determined by WCV or WOR.
> >> + * The first watch period is set by writing WCV directly, that can
> >> + * support more than 10s timeout at the maximum system counter
> >> + * frequency (400MHz).
> >> + * When WS0 is triggered, the second watch period (pretimeout) is
> >> + * determined by one of these registers:
> >> + * (1)WOR: 32bit register, this gives a maximum watch period of
> >> + * around 10s at the maximum system counter frequency. It's loaded
> >> + * automatically by hardware.
> >> + * (2)WCV: If the pretimeout value is greater then "max_wor_timeout",
> >> + * it will be loaded in WS0 interrupt routine. If system is in
> >> + * ws0_mode (reboot by kexec/kdump in panic with watchdog enabled
> >> + * and WS0 == true), the ping operation will only reload WCV.
> >
> > Below is the field comment about ws0_mode, it says ws0_mode is only
> > for rebooting in second stage timeout, but kexec/kdump can reboot in
> > either first or second stage
> 
> Great thanks for your feedback.
> 
> yes, if kexec/kdump reboot the system before the WS0, ws0_mode may not be set.
> in this case, if WS0 is triggered during the reboot(AFAIK, panic will
> disable irq, and in the early boot stage of system, irq is disabled,
> too.), ws0_mode will be set at the next "open" in kdump kernel
> if WS0 haven't triggered until the watchdog is opened again in kdump
> kernel , ws0_mode won't  be set.
> 
> ws0_mode doesn't indicate if the system is in the kdump kernel, it
> indicates that if WS0 is triggered, when the watchdog is initialized.
> 
> Do I answer your question?

Yes, thanks for explanation. So it sounds better to change the comment like below?
from
(reboot by kexec/kdump in panic with watchdog enabled and WS0 == true)
to
(reboot in the pre-timeout stage and WS0 == true)

Thanks
Dave

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 0/4] arm64: Add Xen boot support (via fdt)
  2015-09-08  3:38     ` Fu Wei
@ 2015-09-30 16:00       ` Stefano Stabellini
  2015-10-01 16:19         ` Stefano Stabellini
  2015-10-29  6:06         ` Fu Wei
  0 siblings, 2 replies; 550+ messages in thread
From: Stefano Stabellini @ 2015-09-30 16:00 UTC (permalink / raw)
  To: Fu Wei
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Andrei Borzenkov, Vladimir Serbinenko,
	Leif Lindholm, Ryan Harkin, Linaro UEFI Mailman List,
	Jon Masters

Hi Fu,

I backported your patches to the CentOS aarch64 grub2 rpm.  I am testing
it on X-Gene with EFI firmware. It works fine when booting Xen, but
booting native kernels (no Xen) doesn't work anymore. Grub prints

error: out of memory.

Press any key to continue...

grub is still able to continue and load Linux, but then the kernel fails
to boot with "Cannot open root device", even though the grub config is
still same as before and the rootfs (which is xfs) hasn't changed.
Reverting the patches solved the problem.

Do you have any ideas on what is causing the issue? Maybe the initramfs
hasn't been properly loaded?


Thanks,

Stefano


On Tue, 8 Sep 2015, Fu Wei wrote:
> Hi Vladimir,
> 
> Do you have any suggestion on this patchset?
> Do I need to improve anything?
> 
> Great thanks for your help.
> 
> On 4 August 2015 at 16:34, Fu Wei <fu.wei@linaro.org> wrote:
> > Hi Vladimir,
> >
> > this patchset follows all your comment of v2 patchset.
> > Do you have any suggestion on this patchset?
> >
> > Great thanks for your help.
> >
> >
> > On 23 July 2015 at 13:16,  <fu.wei@linaro.org> wrote:
> >> From: Fu Wei <fu.wei@linaro.org>
> >>
> >>   - This adds support for the Xen boot on ARM specification for arm64.
> >>
> >>   - Add and export some accessor functions of "loaded" flag and
> >>     grub_linux_get_fdt function in include/grub/arm64/linux.h for xen boot.
> >>
> >>   - Introduce xen_hypervisor, xen_linux, xen_initrd and xen_xsm
> >>     to load different binaries for xen boot.
> >>     Introduce xen_module to load common or custom module for xen boot.
> >>
> >>   - This Xen boot support is a separated  module for aarch64,
> >>     but reuse the existing code of devicetree in linux module.
> >>
> >>   - Add the support of xen_hypervisor, xen_linux and xen_initrd
> >>     in util/grub.d/20_linux_xen.in
> >>
> >>   - Add the introduction of all xen boot commands in docs/grub.texi
> >>
> >>   - The example of this support is <How to boot Xen with GRUB on AArch64 the Foundation FVP model>
> >>     https://wiki.linaro.org/LEG/Engineering/Grub2/Xen_booting_on_Foundation_FVP_model_by_GRUB
> >>
> >> Changelog:
> >> v3: create separate module for xen boot: xen_boot
> >>     create separate commands for different types of module
> >>     delete order-dependent for commands of xen module
> >>     simplify the code
> >>
> >> v2: remove the patches which have been accepted.
> >>     according to Vladimir's suggestion, change the command manes
> >>     and relevant code:
> >>         multiboot-->xen_hypervisor
> >>         module-->xen_module
> >>     improve the option parsing support for xen_hypervisor/xen_module commands.
> >>     add a patch for adding xen_hypervisor/xen_module support
> >>     in util/grub.d/20_linux_xen.in.
> >>     update docs/grub.texi patch for the new command names.
> >>
> >> v1: The first version upstream patchset to grub-devel mailing list
> >>
> >>
> >> Fu Wei (4):
> >>   arm64: Add and export some accessor functions for xen boot
> >>   arm64: Add xen_boot module file
> >>   * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
> >>   arm64: Add the introduction of xen boot commands in docs/grub.texi
> >>
> >>  docs/grub.texi                    |  56 ++++
> >>  grub-core/Makefile.core.def       |   7 +
> >>  grub-core/loader/arm64/linux.c    |  13 +
> >>  grub-core/loader/arm64/xen_boot.c | 685 ++++++++++++++++++++++++++++++++++++++
> >>  include/grub/arm64/linux.h        |   6 +-
> >>  util/grub.d/20_linux_xen.in       |  16 +-
> >>  6 files changed, 779 insertions(+), 4 deletions(-)
> >>  create mode 100644 grub-core/loader/arm64/xen_boot.c
> >>
> >> --
> >> 1.8.3.1
> >>
> >
> >
> >
> > --
> > 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
> 

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver
  2015-08-24 17:01 ` [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
                     ` (7 preceding siblings ...)
  2015-08-24 17:01     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
@ 2015-09-30 17:13   ` Pratyush Anand
  2015-09-30 17:22     ` Fu Wei
  8 siblings, 1 reply; 550+ messages in thread
From: Pratyush Anand @ 2015-09-30 17:13 UTC (permalink / raw)
  To: fu.wei
  Cc: Suravee.Suthikulpanit, hanjun.guo, linaro-acpi, linux-watchdog,
	devicetree, linux-kernel, linux-doc, tekkamanninja,
	graeme.gregory, al.stone, arnd, linux, vgandhi, wim, jcm,
	leo.duran, corbet, mark.rutland, catalin.marinas, will.deacon,
	rjw, dyoung

Hi Fu Wei,

On 25/08/2015:01:01:15 AM, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> This patchset:
>     (1)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.
> 
>     (2)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".
> 
>     (3)Introduce ARM SBSA watchdog driver:
>         a.Use linux kernel watchdog framework;
>         b.Work with FDT on ARM64;
>         c.Use "pretimeout" in watchdog framework;
>         d.Support getting timeout and pretimeout from parameter and FDT
>           at the driver init stage.
>         e.In the first timeout, do panic to save system context;
>         f.In the second stage, user can still feed the dog without
>           cleaning WS0. By this feature, we can avoid the panic infinite
>           loops, while backing up a large system context in a server.
>         g.In the second stage, can trigger WS1 by setting pretimeout = 0
>           if necessary.
> 
>     (4)Introduce ACPI GTDT parser: drivers/acpi/gtdt.c
>     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.
>     drivers/clocksource/arm_arch_timer.c is simplified by this GTDT support.
> 
> This patchset has been tested with watchdog daemon
> (ACPI/FDT, module/build-in) on the following platforms:
>     (1)ARM Foundation v8 model
> 

I tested it with kdump on fedora-arm64 Seattle platform. I enabled watchdog
using systemd (with 30s timeout), insured that watchdog is active and then
crashed the system. I can see that kdump kernel loads sbsa_wdt and activates
watchdog, still vmcore copy is done successfully.
My test kernel is here [1]

~Pratyush

[1] https://github.com/pratyushanand/linux/commits/wdt/sbsa-test-kexec 

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver
  2015-09-30 17:13   ` [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver Pratyush Anand
@ 2015-09-30 17:22     ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-09-30 17:22 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: Suravee Suthikulpanit, Hanjun Guo, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, LKML, linux-doc, Wei Fu, G Gregory,
	Al Stone, Arnd Bergmann, Guenter Roeck, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	Dave Young

Hi Pratyush,

Great thanks for your testing, this info is very helpful. :-)
my new patchset will come out soon.

On 30 September 2015 at 13:13, Pratyush Anand <panand@redhat.com> wrote:
> Hi Fu Wei,
>
> On 25/08/2015:01:01:15 AM, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> This patchset:
>>     (1)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.
>>
>>     (2)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".
>>
>>     (3)Introduce ARM SBSA watchdog driver:
>>         a.Use linux kernel watchdog framework;
>>         b.Work with FDT on ARM64;
>>         c.Use "pretimeout" in watchdog framework;
>>         d.Support getting timeout and pretimeout from parameter and FDT
>>           at the driver init stage.
>>         e.In the first timeout, do panic to save system context;
>>         f.In the second stage, user can still feed the dog without
>>           cleaning WS0. By this feature, we can avoid the panic infinite
>>           loops, while backing up a large system context in a server.
>>         g.In the second stage, can trigger WS1 by setting pretimeout = 0
>>           if necessary.
>>
>>     (4)Introduce ACPI GTDT parser: drivers/acpi/gtdt.c
>>     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.
>>     drivers/clocksource/arm_arch_timer.c is simplified by this GTDT support.
>>
>> This patchset has been tested with watchdog daemon
>> (ACPI/FDT, module/build-in) on the following platforms:
>>     (1)ARM Foundation v8 model
>>
>
> I tested it with kdump on fedora-arm64 Seattle platform. I enabled watchdog
> using systemd (with 30s timeout), insured that watchdog is active and then
> crashed the system. I can see that kdump kernel loads sbsa_wdt and activates
> watchdog, still vmcore copy is done successfully.
> My test kernel is here [1]
>
> ~Pratyush
>
> [1] https://github.com/pratyushanand/linux/commits/wdt/sbsa-test-kexec



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 0/4] arm64: Add Xen boot support (via fdt)
  2015-09-30 16:00       ` Stefano Stabellini
@ 2015-10-01 16:19         ` Stefano Stabellini
  2015-10-29  2:43           ` Fu Wei
  2015-10-29  6:06         ` Fu Wei
  1 sibling, 1 reply; 550+ messages in thread
From: Stefano Stabellini @ 2015-10-01 16:19 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Andrei Borzenkov, Vladimir Serbinenko, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List, Jon Masters, Fu Wei

On Wed, 30 Sep 2015, Stefano Stabellini wrote:
> Hi Fu,
> 
> I backported your patches to the CentOS aarch64 grub2 rpm.  I am testing
> it on X-Gene with EFI firmware. It works fine when booting Xen, but
> booting native kernels (no Xen) doesn't work anymore. Grub prints
> 
> error: out of memory.
> 
> Press any key to continue...
> 
> grub is still able to continue and load Linux, but then the kernel fails
> to boot with "Cannot open root device", even though the grub config is
> still same as before and the rootfs (which is xfs) hasn't changed.
> Reverting the patches solved the problem.
> 
> Do you have any ideas on what is causing the issue? Maybe the initramfs
> hasn't been properly loaded?

It looks like the following chunk of commit
f8451af8251a3866cb8b7307b9917dd5d34fbd0a "arm64: Export useful functions
from linux.c" causes troubles:


diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
index 117232f..a63a11a 100644
--- a/grub-core/loader/linux.c
+++ b/grub-core/loader/linux.c
@@ -205,7 +205,8 @@ grub_initrd_init (int argc, char *argv[],
       initrd_ctx->nfiles++;
       initrd_ctx->components[i].size
        = grub_file_size (initrd_ctx->components[i].file);
-      initrd_ctx->size += ALIGN_UP (initrd_ctx->components[i].size, 4);
+      if (argc != 1)
+       initrd_ctx->size += ALIGN_UP (initrd_ctx->components[i].size, 4);
     }
 
   if (newc)


Simply removing this change seems to fix the issue and Xen still boots
fine.

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-10-13  8:34             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-10-13  8:34 UTC (permalink / raw)
  To: Dave Young
  Cc: Suravee Suthikulpanit, Hanjun Guo, Linaro ACPI Mailman List,
	linux-watchdog, devicetree, LKML, linux-doc, Wei Fu, G Gregory,
	Al Stone, Arnd Bergmann, Guenter Roeck, Vipul Gandhi,
	Wim Van Sebroeck, Jon Masters, Leo Duran, Jon Corbet,
	Mark Rutland, Catalin Marinas, Will Deacon, Rafael Wysocki,
	Pratyush Anand

Hi Dave,

On 16 September 2015 at 09:57, Dave Young <dyoung@redhat.com> wrote:
>> >> diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
>> >> new file mode 100644
>> >> index 0000000..7ae45cc
>> >> --- /dev/null
>> >> +++ b/drivers/watchdog/sbsa_gwdt.c
>> >> @@ -0,0 +1,459 @@
>> >> +/*
>> >> + * SBSA(Server Base System Architecture) Generic Watchdog driver
>> >> + *
>> >> + * Copyright (c) 2015, Linaro Ltd.
>> >> + * Author: Fu Wei <fu.wei@linaro.org>
>> >> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
>> >> + *
>> >> + * 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.
>> >> + *
>> >> + * The SBSA Generic watchdog driver is compatible with the pretimeout
>> >> + * concept of Linux kernel.
>> >> + * The timeout and pretimeout are determined by WCV or WOR.
>> >> + * The first watch period is set by writing WCV directly, that can
>> >> + * support more than 10s timeout at the maximum system counter
>> >> + * frequency (400MHz).
>> >> + * When WS0 is triggered, the second watch period (pretimeout) is
>> >> + * determined by one of these registers:
>> >> + * (1)WOR: 32bit register, this gives a maximum watch period of
>> >> + * around 10s at the maximum system counter frequency. It's loaded
>> >> + * automatically by hardware.
>> >> + * (2)WCV: If the pretimeout value is greater then "max_wor_timeout",
>> >> + * it will be loaded in WS0 interrupt routine. If system is in
>> >> + * ws0_mode (reboot by kexec/kdump in panic with watchdog enabled
>> >> + * and WS0 == true), the ping operation will only reload WCV.
>> >
>> > Below is the field comment about ws0_mode, it says ws0_mode is only
>> > for rebooting in second stage timeout, but kexec/kdump can reboot in
>> > either first or second stage
>>
>> Great thanks for your feedback.
>>
>> yes, if kexec/kdump reboot the system before the WS0, ws0_mode may not be set.
>> in this case, if WS0 is triggered during the reboot(AFAIK, panic will
>> disable irq, and in the early boot stage of system, irq is disabled,
>> too.), ws0_mode will be set at the next "open" in kdump kernel
>> if WS0 haven't triggered until the watchdog is opened again in kdump
>> kernel , ws0_mode won't  be set.
>>
>> ws0_mode doesn't indicate if the system is in the kdump kernel, it
>> indicates that if WS0 is triggered, when the watchdog is initialized.
>>
>> Do I answer your question?
>
> Yes, thanks for explanation. So it sounds better to change the comment like below?
> from
> (reboot by kexec/kdump in panic with watchdog enabled and WS0 == true)
> to
> (reboot in the pre-timeout stage and WS0 == true)

" in the pre-timeout stage" means " WS0 == true", so I think we should say:
(reboot with watchdog enabled and WS0 == true)

Thanks for your suggestion.

>
> Thanks
> Dave



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver
@ 2015-10-13  8:34             ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-10-13  8:34 UTC (permalink / raw)
  To: Dave Young
  Cc: Suravee Suthikulpanit, Hanjun Guo, Linaro ACPI Mailman List,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, LKML,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Wei Fu, G Gregory, Al Stone,
	Arnd Bergmann, Guenter Roeck, Vipul Gandhi, Wim Van Sebroeck,
	Jon Masters, Leo Duran, Jon Corbet, Mark Rutland,
	Catalin Marinas, Will Deacon, Rafael Wysocki, Pratyush Anand

Hi Dave,

On 16 September 2015 at 09:57, Dave Young <dyoung-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>> >> diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
>> >> new file mode 100644
>> >> index 0000000..7ae45cc
>> >> --- /dev/null
>> >> +++ b/drivers/watchdog/sbsa_gwdt.c
>> >> @@ -0,0 +1,459 @@
>> >> +/*
>> >> + * SBSA(Server Base System Architecture) Generic Watchdog driver
>> >> + *
>> >> + * Copyright (c) 2015, Linaro Ltd.
>> >> + * Author: Fu Wei <fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> >> + *         Suravee Suthikulpanit <Suravee.Suthikulpanit-5C7GfCeVMHo@public.gmane.org>
>> >> + *
>> >> + * 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.
>> >> + *
>> >> + * The SBSA Generic watchdog driver is compatible with the pretimeout
>> >> + * concept of Linux kernel.
>> >> + * The timeout and pretimeout are determined by WCV or WOR.
>> >> + * The first watch period is set by writing WCV directly, that can
>> >> + * support more than 10s timeout at the maximum system counter
>> >> + * frequency (400MHz).
>> >> + * When WS0 is triggered, the second watch period (pretimeout) is
>> >> + * determined by one of these registers:
>> >> + * (1)WOR: 32bit register, this gives a maximum watch period of
>> >> + * around 10s at the maximum system counter frequency. It's loaded
>> >> + * automatically by hardware.
>> >> + * (2)WCV: If the pretimeout value is greater then "max_wor_timeout",
>> >> + * it will be loaded in WS0 interrupt routine. If system is in
>> >> + * ws0_mode (reboot by kexec/kdump in panic with watchdog enabled
>> >> + * and WS0 == true), the ping operation will only reload WCV.
>> >
>> > Below is the field comment about ws0_mode, it says ws0_mode is only
>> > for rebooting in second stage timeout, but kexec/kdump can reboot in
>> > either first or second stage
>>
>> Great thanks for your feedback.
>>
>> yes, if kexec/kdump reboot the system before the WS0, ws0_mode may not be set.
>> in this case, if WS0 is triggered during the reboot(AFAIK, panic will
>> disable irq, and in the early boot stage of system, irq is disabled,
>> too.), ws0_mode will be set at the next "open" in kdump kernel
>> if WS0 haven't triggered until the watchdog is opened again in kdump
>> kernel , ws0_mode won't  be set.
>>
>> ws0_mode doesn't indicate if the system is in the kdump kernel, it
>> indicates that if WS0 is triggered, when the watchdog is initialized.
>>
>> Do I answer your question?
>
> Yes, thanks for explanation. So it sounds better to change the comment like below?
> from
> (reboot by kexec/kdump in panic with watchdog enabled and WS0 == true)
> to
> (reboot in the pre-timeout stage and WS0 == true)

" in the pre-timeout stage" means " WS0 == true", so I think we should say:
(reboot with watchdog enabled and WS0 == true)

Thanks for your suggestion.

>
> Thanks
> Dave



-- 
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
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 0/4] arm64: Add Xen boot support (via fdt)
  2015-10-01 16:19         ` Stefano Stabellini
@ 2015-10-29  2:43           ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-10-29  2:43 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Andrei Borzenkov, Vladimir Serbinenko, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List, Jon Masters

Hi Stefano,

Sorry for late response, I will try to test my latest patch ASAP. but
I don't see this problem before.
will let you know the result , thanks for your testing

On 2 October 2015 at 00:19, Stefano Stabellini
<stefano.stabellini@eu.citrix.com> wrote:
> On Wed, 30 Sep 2015, Stefano Stabellini wrote:
>> Hi Fu,
>>
>> I backported your patches to the CentOS aarch64 grub2 rpm.  I am testing
>> it on X-Gene with EFI firmware. It works fine when booting Xen, but
>> booting native kernels (no Xen) doesn't work anymore. Grub prints
>>
>> error: out of memory.
>>
>> Press any key to continue...
>>
>> grub is still able to continue and load Linux, but then the kernel fails
>> to boot with "Cannot open root device", even though the grub config is
>> still same as before and the rootfs (which is xfs) hasn't changed.
>> Reverting the patches solved the problem.
>>
>> Do you have any ideas on what is causing the issue? Maybe the initramfs
>> hasn't been properly loaded?
>
> It looks like the following chunk of commit
> f8451af8251a3866cb8b7307b9917dd5d34fbd0a "arm64: Export useful functions
> from linux.c" causes troubles:
>
>
> diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
> index 117232f..a63a11a 100644
> --- a/grub-core/loader/linux.c
> +++ b/grub-core/loader/linux.c
> @@ -205,7 +205,8 @@ grub_initrd_init (int argc, char *argv[],
>        initrd_ctx->nfiles++;
>        initrd_ctx->components[i].size
>         = grub_file_size (initrd_ctx->components[i].file);
> -      initrd_ctx->size += ALIGN_UP (initrd_ctx->components[i].size, 4);
> +      if (argc != 1)
> +       initrd_ctx->size += ALIGN_UP (initrd_ctx->components[i].size, 4);
>      }
>
>    if (newc)
>
>
> Simply removing this change seems to fix the issue and Xen still boots
> fine.



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 0/4] arm64: Add Xen boot support (via fdt)
  2015-09-30 16:00       ` Stefano Stabellini
  2015-10-01 16:19         ` Stefano Stabellini
@ 2015-10-29  6:06         ` Fu Wei
  2015-10-29 11:00           ` Stefano Stabellini
  1 sibling, 1 reply; 550+ messages in thread
From: Fu Wei @ 2015-10-29  6:06 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Andrei Borzenkov, Vladimir Serbinenko, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List, Jon Masters

Hi Stefano,

I have tried my grub on Foundation model, but I did not get this
error, I guess that is the UEFI problem ?

On 1 October 2015 at 00:00, Stefano Stabellini
<stefano.stabellini@eu.citrix.com> wrote:
> Hi Fu,
>
> I backported your patches to the CentOS aarch64 grub2 rpm.  I am testing
> it on X-Gene with EFI firmware. It works fine when booting Xen, but
> booting native kernels (no Xen) doesn't work anymore. Grub prints
>
> error: out of memory.
>
> Press any key to continue...
>
> grub is still able to continue and load Linux, but then the kernel fails
> to boot with "Cannot open root device", even though the grub config is
> still same as before and the rootfs (which is xfs) hasn't changed.
> Reverting the patches solved the problem.
>
> Do you have any ideas on what is causing the issue? Maybe the initramfs
> hasn't been properly loaded?
>
>
> Thanks,
>
> Stefano
>
>
> On Tue, 8 Sep 2015, Fu Wei wrote:
>> Hi Vladimir,
>>
>> Do you have any suggestion on this patchset?
>> Do I need to improve anything?
>>
>> Great thanks for your help.
>>
>> On 4 August 2015 at 16:34, Fu Wei <fu.wei@linaro.org> wrote:
>> > Hi Vladimir,
>> >
>> > this patchset follows all your comment of v2 patchset.
>> > Do you have any suggestion on this patchset?
>> >
>> > Great thanks for your help.
>> >
>> >
>> > On 23 July 2015 at 13:16,  <fu.wei@linaro.org> wrote:
>> >> From: Fu Wei <fu.wei@linaro.org>
>> >>
>> >>   - This adds support for the Xen boot on ARM specification for arm64.
>> >>
>> >>   - Add and export some accessor functions of "loaded" flag and
>> >>     grub_linux_get_fdt function in include/grub/arm64/linux.h for xen boot.
>> >>
>> >>   - Introduce xen_hypervisor, xen_linux, xen_initrd and xen_xsm
>> >>     to load different binaries for xen boot.
>> >>     Introduce xen_module to load common or custom module for xen boot.
>> >>
>> >>   - This Xen boot support is a separated  module for aarch64,
>> >>     but reuse the existing code of devicetree in linux module.
>> >>
>> >>   - Add the support of xen_hypervisor, xen_linux and xen_initrd
>> >>     in util/grub.d/20_linux_xen.in
>> >>
>> >>   - Add the introduction of all xen boot commands in docs/grub.texi
>> >>
>> >>   - The example of this support is <How to boot Xen with GRUB on AArch64 the Foundation FVP model>
>> >>     https://wiki.linaro.org/LEG/Engineering/Grub2/Xen_booting_on_Foundation_FVP_model_by_GRUB
>> >>
>> >> Changelog:
>> >> v3: create separate module for xen boot: xen_boot
>> >>     create separate commands for different types of module
>> >>     delete order-dependent for commands of xen module
>> >>     simplify the code
>> >>
>> >> v2: remove the patches which have been accepted.
>> >>     according to Vladimir's suggestion, change the command manes
>> >>     and relevant code:
>> >>         multiboot-->xen_hypervisor
>> >>         module-->xen_module
>> >>     improve the option parsing support for xen_hypervisor/xen_module commands.
>> >>     add a patch for adding xen_hypervisor/xen_module support
>> >>     in util/grub.d/20_linux_xen.in.
>> >>     update docs/grub.texi patch for the new command names.
>> >>
>> >> v1: The first version upstream patchset to grub-devel mailing list
>> >>
>> >>
>> >> Fu Wei (4):
>> >>   arm64: Add and export some accessor functions for xen boot
>> >>   arm64: Add xen_boot module file
>> >>   * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
>> >>   arm64: Add the introduction of xen boot commands in docs/grub.texi
>> >>
>> >>  docs/grub.texi                    |  56 ++++
>> >>  grub-core/Makefile.core.def       |   7 +
>> >>  grub-core/loader/arm64/linux.c    |  13 +
>> >>  grub-core/loader/arm64/xen_boot.c | 685 ++++++++++++++++++++++++++++++++++++++
>> >>  include/grub/arm64/linux.h        |   6 +-
>> >>  util/grub.d/20_linux_xen.in       |  16 +-
>> >>  6 files changed, 779 insertions(+), 4 deletions(-)
>> >>  create mode 100644 grub-core/loader/arm64/xen_boot.c
>> >>
>> >> --
>> >> 1.8.3.1
>> >>
>> >
>> >
>> >
>> > --
>> > 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
>>



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 0/4] arm64: Add Xen boot support (via fdt)
  2015-10-29  6:06         ` Fu Wei
@ 2015-10-29 11:00           ` Stefano Stabellini
  0 siblings, 0 replies; 550+ messages in thread
From: Stefano Stabellini @ 2015-10-29 11:00 UTC (permalink / raw)
  To: Fu Wei
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Andrei Borzenkov, Vladimir Serbinenko,
	Leif Lindholm, Ryan Harkin, Linaro UEFI Mailman List,
	Jon Masters

Yes, it happens when booting from grub from UEFI firmware: I tested it
on X-Gene.

Cheers,

Stefano

On Thu, 29 Oct 2015, Fu Wei wrote:
> Hi Stefano,
> 
> I have tried my grub on Foundation model, but I did not get this
> error, I guess that is the UEFI problem ?
> 
> On 1 October 2015 at 00:00, Stefano Stabellini
> <stefano.stabellini@eu.citrix.com> wrote:
> > Hi Fu,
> >
> > I backported your patches to the CentOS aarch64 grub2 rpm.  I am testing
> > it on X-Gene with EFI firmware. It works fine when booting Xen, but
> > booting native kernels (no Xen) doesn't work anymore. Grub prints
> >
> > error: out of memory.
> >
> > Press any key to continue...
> >
> > grub is still able to continue and load Linux, but then the kernel fails
> > to boot with "Cannot open root device", even though the grub config is
> > still same as before and the rootfs (which is xfs) hasn't changed.
> > Reverting the patches solved the problem.
> >
> > Do you have any ideas on what is causing the issue? Maybe the initramfs
> > hasn't been properly loaded?
> >
> >
> > Thanks,
> >
> > Stefano
> >
> >
> > On Tue, 8 Sep 2015, Fu Wei wrote:
> >> Hi Vladimir,
> >>
> >> Do you have any suggestion on this patchset?
> >> Do I need to improve anything?
> >>
> >> Great thanks for your help.
> >>
> >> On 4 August 2015 at 16:34, Fu Wei <fu.wei@linaro.org> wrote:
> >> > Hi Vladimir,
> >> >
> >> > this patchset follows all your comment of v2 patchset.
> >> > Do you have any suggestion on this patchset?
> >> >
> >> > Great thanks for your help.
> >> >
> >> >
> >> > On 23 July 2015 at 13:16,  <fu.wei@linaro.org> wrote:
> >> >> From: Fu Wei <fu.wei@linaro.org>
> >> >>
> >> >>   - This adds support for the Xen boot on ARM specification for arm64.
> >> >>
> >> >>   - Add and export some accessor functions of "loaded" flag and
> >> >>     grub_linux_get_fdt function in include/grub/arm64/linux.h for xen boot.
> >> >>
> >> >>   - Introduce xen_hypervisor, xen_linux, xen_initrd and xen_xsm
> >> >>     to load different binaries for xen boot.
> >> >>     Introduce xen_module to load common or custom module for xen boot.
> >> >>
> >> >>   - This Xen boot support is a separated  module for aarch64,
> >> >>     but reuse the existing code of devicetree in linux module.
> >> >>
> >> >>   - Add the support of xen_hypervisor, xen_linux and xen_initrd
> >> >>     in util/grub.d/20_linux_xen.in
> >> >>
> >> >>   - Add the introduction of all xen boot commands in docs/grub.texi
> >> >>
> >> >>   - The example of this support is <How to boot Xen with GRUB on AArch64 the Foundation FVP model>
> >> >>     https://wiki.linaro.org/LEG/Engineering/Grub2/Xen_booting_on_Foundation_FVP_model_by_GRUB
> >> >>
> >> >> Changelog:
> >> >> v3: create separate module for xen boot: xen_boot
> >> >>     create separate commands for different types of module
> >> >>     delete order-dependent for commands of xen module
> >> >>     simplify the code
> >> >>
> >> >> v2: remove the patches which have been accepted.
> >> >>     according to Vladimir's suggestion, change the command manes
> >> >>     and relevant code:
> >> >>         multiboot-->xen_hypervisor
> >> >>         module-->xen_module
> >> >>     improve the option parsing support for xen_hypervisor/xen_module commands.
> >> >>     add a patch for adding xen_hypervisor/xen_module support
> >> >>     in util/grub.d/20_linux_xen.in.
> >> >>     update docs/grub.texi patch for the new command names.
> >> >>
> >> >> v1: The first version upstream patchset to grub-devel mailing list
> >> >>
> >> >>
> >> >> Fu Wei (4):
> >> >>   arm64: Add and export some accessor functions for xen boot
> >> >>   arm64: Add xen_boot module file
> >> >>   * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
> >> >>   arm64: Add the introduction of xen boot commands in docs/grub.texi
> >> >>
> >> >>  docs/grub.texi                    |  56 ++++
> >> >>  grub-core/Makefile.core.def       |   7 +
> >> >>  grub-core/loader/arm64/linux.c    |  13 +
> >> >>  grub-core/loader/arm64/xen_boot.c | 685 ++++++++++++++++++++++++++++++++++++++
> >> >>  include/grub/arm64/linux.h        |   6 +-
> >> >>  util/grub.d/20_linux_xen.in       |  16 +-
> >> >>  6 files changed, 779 insertions(+), 4 deletions(-)
> >> >>  create mode 100644 grub-core/loader/arm64/xen_boot.c
> >> >>
> >> >> --
> >> >> 1.8.3.1
> >> >>
> >> >
> >> >
> >> >
> >> > --
> >> > 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
> >>
> 
> 
> 
> -- 
> 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
> 

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 1/4] arm64: Add and export some accessor functions for xen boot
  2015-07-23  5:16   ` [PATCH v3 1/4] arm64: Add and export some accessor functions for xen boot fu.wei
@ 2015-10-29 12:03       ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 0 replies; 550+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2015-10-29 12:03 UTC (permalink / raw)
  To: fu.wei, grub-devel, arvidjaar
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi


[-- Attachment #1.1: Type: text/plain, Size: 2408 bytes --]

On 23.07.2015 07:16, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> Add accessor functions of "loaded" flag in
> grub-core/loader/arm64/linux.c.
> 
> Export accessor functions of "loaded" flag and
> grub_linux_get_fdt function in include/grub/arm64/linux.h.
> 
> Purpose: Reuse the existing code of devicetree in linux module.
> 
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  grub-core/loader/arm64/linux.c | 13 +++++++++++++
>  include/grub/arm64/linux.h     |  6 +++++-
>  2 files changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
> index 987f5b9..cf6026e 100644
> --- a/grub-core/loader/arm64/linux.c
> +++ b/grub-core/loader/arm64/linux.c
> @@ -48,6 +48,19 @@ static grub_addr_t initrd_end;
>  static void *loaded_fdt;
>  static void *fdt;
>  
> +/* The accessor functions for "loaded" flag */
> +int
> +grub_linux_get_loaded (void)
> +{
> +  return loaded;
> +}
> +
> +void
> +grub_linux_set_loaded (int loaded_flag)
> +{
> +  loaded = loaded_flag;
> +}
> +
Accessor functions are usually useless in GRUB. We have no public API to
respect. So it only adds clutter. Also "loaded" flag is static for а
good reason: it's specific to linux.c. I'm going to move fdt part to
fdt.c and have uniform interface for both linux and xen.
>  static void *
>  get_firmware_fdt (void)
>  {
> diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h
> index 65796d9..20058f3 100644
> --- a/include/grub/arm64/linux.h
> +++ b/include/grub/arm64/linux.h
> @@ -43,10 +43,14 @@ struct grub_arm64_linux_kernel_header
>  };
>  
>  /* Declare the functions for getting dtb and checking/booting image */
> -void *grub_linux_get_fdt (void);
>  grub_err_t grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header
>                                          *lh);
>  grub_err_t grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size,
>                                         char *args);
>  
> +/* Export the accessor functions for gettin dtb and "loaded" flag */
> +void EXPORT_FUNC (*grub_linux_get_fdt) (void);
> +int EXPORT_FUNC (grub_linux_get_loaded) (void);
> +void EXPORT_FUNC (grub_linux_set_loaded) (int loaded_flag);
> +
EXPORT_* are necessary only for core. Not for modules.
>  #endif /* ! GRUB_LINUX_CPU_HEADER */
> 



[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

[-- Attachment #2: Type: text/plain, Size: 141 bytes --]

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 1/4] arm64: Add and export some accessor functions for xen boot
@ 2015-10-29 12:03       ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 0 replies; 550+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2015-10-29 12:03 UTC (permalink / raw)
  To: fu.wei, grub-devel, arvidjaar
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi

[-- Attachment #1: Type: text/plain, Size: 2408 bytes --]

On 23.07.2015 07:16, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> Add accessor functions of "loaded" flag in
> grub-core/loader/arm64/linux.c.
> 
> Export accessor functions of "loaded" flag and
> grub_linux_get_fdt function in include/grub/arm64/linux.h.
> 
> Purpose: Reuse the existing code of devicetree in linux module.
> 
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  grub-core/loader/arm64/linux.c | 13 +++++++++++++
>  include/grub/arm64/linux.h     |  6 +++++-
>  2 files changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
> index 987f5b9..cf6026e 100644
> --- a/grub-core/loader/arm64/linux.c
> +++ b/grub-core/loader/arm64/linux.c
> @@ -48,6 +48,19 @@ static grub_addr_t initrd_end;
>  static void *loaded_fdt;
>  static void *fdt;
>  
> +/* The accessor functions for "loaded" flag */
> +int
> +grub_linux_get_loaded (void)
> +{
> +  return loaded;
> +}
> +
> +void
> +grub_linux_set_loaded (int loaded_flag)
> +{
> +  loaded = loaded_flag;
> +}
> +
Accessor functions are usually useless in GRUB. We have no public API to
respect. So it only adds clutter. Also "loaded" flag is static for а
good reason: it's specific to linux.c. I'm going to move fdt part to
fdt.c and have uniform interface for both linux and xen.
>  static void *
>  get_firmware_fdt (void)
>  {
> diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h
> index 65796d9..20058f3 100644
> --- a/include/grub/arm64/linux.h
> +++ b/include/grub/arm64/linux.h
> @@ -43,10 +43,14 @@ struct grub_arm64_linux_kernel_header
>  };
>  
>  /* Declare the functions for getting dtb and checking/booting image */
> -void *grub_linux_get_fdt (void);
>  grub_err_t grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header
>                                          *lh);
>  grub_err_t grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size,
>                                         char *args);
>  
> +/* Export the accessor functions for gettin dtb and "loaded" flag */
> +void EXPORT_FUNC (*grub_linux_get_fdt) (void);
> +int EXPORT_FUNC (grub_linux_get_loaded) (void);
> +void EXPORT_FUNC (grub_linux_set_loaded) (int loaded_flag);
> +
EXPORT_* are necessary only for core. Not for modules.
>  #endif /* ! GRUB_LINUX_CPU_HEADER */
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 2/4] arm64: Add xen_boot module file
  2015-07-23  5:16   ` [PATCH v3 2/4] arm64: Add xen_boot module file fu.wei
@ 2015-10-29 14:27       ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 0 replies; 550+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2015-10-29 14:27 UTC (permalink / raw)
  To: fu.wei, grub-devel, arvidjaar
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi


[-- Attachment #1.1: Type: text/plain, Size: 23108 bytes --]

Committed without the xen_module command. Its argument parsing was
non-trivial and I don't quite get what its intent is. Can you resubmit?
On 23.07.2015 07:16, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> grub-core/loader/arm64/xen_boot.c
> 
>   - This adds support for the Xen boot on ARM specification for arm64.
>   - Introduce xen_hypervisor, xen_linux, xen_initrd and xen_xsm
>     to load different binaries for xen boot;
>     Introduce xen_module to load common or custom module for xen boot.
>   - This Xen boot support is a separated  module for aarch64,
>     but reuse the existing code of devicetree in linux module.
> 
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  grub-core/Makefile.core.def       |   7 +
>  grub-core/loader/arm64/xen_boot.c | 685 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 692 insertions(+)
> 
> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
> index a6101de..796f7e9 100644
> --- a/grub-core/Makefile.core.def
> +++ b/grub-core/Makefile.core.def
> @@ -1648,6 +1648,13 @@ module = {
>  };
>  
>  module = {
> +  name = xen_boot;
> +  common = lib/cmdline.c;
> +  arm64 = loader/arm64/xen_boot.c;
> +  enable = arm64;
> +};
> +
> +module = {
>    name = linux;
>    x86 = loader/i386/linux.c;
>    xen = loader/i386/xen.c;
> diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
> new file mode 100644
> index 0000000..33a65dd
> --- /dev/null
> +++ b/grub-core/loader/arm64/xen_boot.c
> @@ -0,0 +1,685 @@
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2014  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB 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.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/cache.h>
> +#include <grub/charset.h>
> +#include <grub/command.h>
> +#include <grub/err.h>
> +#include <grub/file.h>
> +#include <grub/fdt.h>
> +#include <grub/linux.h>
> +#include <grub/list.h>
> +#include <grub/loader.h>
> +#include <grub/misc.h>
> +#include <grub/mm.h>
> +#include <grub/types.h>
> +#include <grub/cpu/linux.h>
> +#include <grub/efi/efi.h>
> +#include <grub/efi/pe32.h>	/* required by struct xen_hypervisor_header */
> +#include <grub/i18n.h>
> +#include <grub/lib/cmdline.h>
> +
> +GRUB_MOD_LICENSE ("GPLv3+");
> +
> +#define XEN_HYPERVISOR_NAME  "xen_hypervisor"
> +
> +#define MODULE_DEFAULT_ALIGN  (0x0)
> +#define MODULE_IMAGE_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +#define MODULE_INITRD_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +#define MODULE_XSM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +#define MODULE_CUSTOM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +
> +/* #define MODULE_IMAGE_COMPATIBLE  "xen,linux-image\0xen,module"
> +#define MODULE_INITRD_COMPATIBLE  "xen,linux-image\0xen,module"
> +#define MODULE_XSM_COMPATIBLE  "xen,xsm-policy\0xen,module"
> +#define MODULE_CUSTOM_COMPATIBLE  "xen,module" */
> +#define MODULE_IMAGE_COMPATIBLE  "multiboot,kernel\0multiboot,module"
> +#define MODULE_INITRD_COMPATIBLE  "multiboot,ramdisk\0multiboot,module"
> +#define MODULE_XSM_COMPATIBLE  "xen,xsm-policy\0multiboot,module"
> +#define MODULE_CUSTOM_COMPATIBLE  "multiboot,module"
> +
> +/* This maximum size is defined in Power.org ePAPR V1.1
> + * https://www.power.org/documentation/epapr-version-1-1/
> + * 2.2.1.1 Node Name Requirements
> + * node-name@unit-address
> + * 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
> + */
> +#define FDT_NODE_NAME_MAX_SIZE  (49)
> +
> +#define ARG_SHIFT(argc, argv) \
> +  do { \
> +    (argc)--; \
> +    (argv)++; \
> +  } while (0)
> +
> +struct compat_string_struct
> +{
> +  grub_size_t size;
> +  const char *compat_string;
> +};
> +typedef struct compat_string_struct compat_string_struct_t;
> +#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
> +
> +enum module_type
> +{
> +  MODULE_IMAGE,
> +  MODULE_INITRD,
> +  MODULE_XSM,
> +  MODULE_CUSTOM
> +};
> +typedef enum module_type module_type_t;
> +
> +struct fdt_node_info
> +{
> +  module_type_t type;
> +
> +  const char *compat_string;
> +  grub_size_t compat_string_size;
> +};
> +
> +struct xen_hypervisor_header
> +{
> +  struct grub_arm64_linux_kernel_header efi_head;
> +
> +  /* This is always PE\0\0.  */
> +  grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
> +  /* The COFF file header.  */
> +  struct grub_pe32_coff_header coff_header;
> +  /* The Optional header.  */
> +  struct grub_pe64_optional_header optional_header;
> +};
> +
> +struct xen_boot_binary
> +{
> +  struct xen_boot_binary *next;
> +  struct xen_boot_binary **prev;
> +  const char *name;
> +
> +  grub_addr_t start;
> +  grub_size_t size;
> +  grub_size_t align;
> +
> +  char *cmdline;
> +  int cmdline_size;
> +
> +  struct fdt_node_info node_info;
> +};
> +
> +static grub_dl_t my_mod;
> +
> +static struct xen_boot_binary *xen_hypervisor;
> +static struct xen_boot_binary *module_head;
> +static const grub_size_t module_default_align[] = {
> +  MODULE_IMAGE_MIN_ALIGN,
> +  MODULE_INITRD_MIN_ALIGN,
> +  MODULE_XSM_MIN_ALIGN,
> +  MODULE_CUSTOM_MIN_ALIGN
> +};
> +
> +static void *xen_boot_fdt;
> +static const compat_string_struct_t default_compat_string[] = {
> +  FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
> +  FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
> +  FDT_COMPATIBLE (MODULE_XSM_COMPATIBLE),
> +  FDT_COMPATIBLE (MODULE_CUSTOM_COMPATIBLE)
> +};
> +
> +static __inline grub_addr_t
> +xen_boot_address_align (grub_addr_t start, grub_size_t align)
> +{
> +  return (align ? (ALIGN_UP (start, align)) : start);
> +}
> +
> +/* Parse the option of xen_module command. For now, we support
> +   (1) --type <the compatible stream>
> +   We also set up the type of module in this function.
> +   If there are some "--type" options in the command line,
> +   we make a custom compatible stream in this function. */
> +static grub_err_t
> +set_module_type (grub_command_t cmd, struct xen_boot_binary *module,
> +		 int argc, char *argv[], int *file_name_index)
> +{
> +  char **compat_string_temp_array;
> +  grub_size_t total_size = 0;
> +  int num_types = 0, i;
> +  char *temp = NULL;
> +
> +  *file_name_index = 0;
> +
> +  if (!grub_strcmp (cmd->name, "xen_linux"))
> +    module->node_info.type = MODULE_IMAGE;
> +  else if (!grub_strcmp (cmd->name, "xen_initrd"))
> +    module->node_info.type = MODULE_INITRD;
> +  else if (!grub_strcmp (cmd->name, "xen_xsm"))
> +    module->node_info.type = MODULE_XSM;
> +  else if (!grub_strcmp (cmd->name, "xen_module"))
> +    module->node_info.type = MODULE_CUSTOM;
> +
> +  /* if there are some options we need to process. */
> +  if (module->node_info.type == MODULE_CUSTOM)
> +    {
> +      compat_string_temp_array =
> +	(char **) grub_zalloc (sizeof (char *) * argc);
> +      if (!compat_string_temp_array)
> +	return grub_errno;
> +      /* the module type is set by "--type"(MODULE_CUSTOM) */
> +      while (argc > 2 && !grub_strcmp (argv[0], "--type"))
> +	{
> +	  module->node_info.type = MODULE_CUSTOM;
> +	  ARG_SHIFT (argc, argv);
> +	  total_size += grub_strlen (argv[0]) + 1;
> +	  compat_string_temp_array[num_types++] = argv[0];
> +	  ARG_SHIFT (argc, argv);
> +	  (*file_name_index) += 2;
> +	}
> +
> +      if (total_size)
> +	{
> +	  module->node_info.compat_string = temp =
> +	    (char *) grub_zalloc (total_size);
> +	  if (!temp)
> +	    {
> +	      grub_free (compat_string_temp_array);
> +	      return grub_errno;
> +	    }
> +
> +	  module->node_info.compat_string_size = total_size;
> +	  for (i = 0; num_types > 0; num_types--, i++, temp++)
> +	    {
> +	      grub_strcpy (temp, compat_string_temp_array[i]);
> +	      temp += grub_strlen (compat_string_temp_array[i]);
> +	    }
> +	}
> +      else
> +	{
> +	  module->node_info.compat_string =
> +	    default_compat_string[MODULE_CUSTOM].compat_string;
> +	  module->node_info.compat_string_size =
> +	    default_compat_string[MODULE_CUSTOM].size;
> +	}
> +
> +      grub_free (compat_string_temp_array);
> +    }
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +prepare_xen_hypervisor_params (void)
> +{
> +  int chosen_node = 0;
> +  int retval;
> +
> +  xen_boot_fdt = grub_linux_get_fdt ();
> +  if (!xen_boot_fdt)
> +    return grub_error (GRUB_ERR_IO, "failed to get FDT");
> +
> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 0)
> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 1)
> +    return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
> +
> +  grub_dprintf ("xen_loader",
> +		"Xen Hypervisor cmdline : %s @ %p size:%d\n",
> +		xen_hypervisor->cmdline, xen_hypervisor->cmdline,
> +		xen_hypervisor->cmdline_size);
> +
> +  retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
> +			      xen_hypervisor->cmdline,
> +			      xen_hypervisor->cmdline_size);
> +  if (retval)
> +    return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +prepare_xen_module_params (struct xen_boot_binary *module)
> +{
> +  int retval, chosen_node = 0, module_node = 0;
> +  char module_name[FDT_NODE_NAME_MAX_SIZE];
> +
> +  retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
> +			  xen_boot_address_align (module->start,
> +						  module->align));
> +  grub_dprintf ("xen_loader", "Module node name %s \n", module_name);
> +
> +  if (retval < (int) sizeof ("module@"))
> +    return grub_error (GRUB_ERR_IO, N_("failed to get FDT"));
> +
> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 0)
> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 1)
> +    return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
> +
> +  module_node =
> +    grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
> +  if (module_node < 0)
> +    module_node =
> +      grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
> +
> +  retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
> +			      module->node_info.compat_string,
> +			      (grub_uint32_t) module->
> +			      node_info.compat_string_size);
> +  if (retval)
> +    return grub_error (GRUB_ERR_IO, N_("failed to update FDT"));
> +
> +  grub_dprintf ("xen_loader", "Module %s compatible = %s size = 0x%lx\n",
> +		module->name, module->node_info.compat_string,
> +		module->node_info.compat_string_size);
> +
> +  retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
> +			       xen_boot_address_align (module->start,
> +						       module->align),
> +			       module->size);
> +  if (retval)
> +    return grub_error (GRUB_ERR_IO, N_("failed to update FDT"));
> +
> +  if (module->cmdline && module->cmdline_size > 0)
> +    {
> +      grub_dprintf ("xen_loader",
> +		    "Module %s cmdline : %s @ %p size:%d\n", module->name,
> +		    module->cmdline, module->cmdline, module->cmdline_size);
> +
> +      retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
> +				  module->cmdline, module->cmdline_size + 1);
> +      if (retval)
> +	return grub_error (GRUB_ERR_IO, "failed to update FDT");
> +    }
> +  else
> +    {
> +      grub_dprintf ("xen_loader", "Module %s has not bootargs!\n",
> +		    module->name);
> +    }
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +install_all_params (void)
> +{
> +  grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
> +  grub_efi_boot_services_t *b;
> +  grub_efi_status_t status;
> +
> +  b = grub_efi_system_table->boot_services;
> +  status = b->install_configuration_table (&fdt_guid, xen_boot_fdt);
> +  if (status != GRUB_EFI_SUCCESS)
> +    return grub_error (GRUB_ERR_IO, "failed to install FDT");
> +
> +  grub_dprintf ("xen_loader",
> +		"Installed/updated FDT configuration table @ %p\n",
> +		xen_boot_fdt);
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +clean_all_params (void)
> +{
> +  if (xen_boot_fdt)
> +    {
> +      grub_efi_free_pages ((grub_efi_physical_address_t) xen_boot_fdt,
> +			   BYTES_TO_PAGES (grub_fdt_get_totalsize
> +					   (xen_boot_fdt)));
> +      xen_boot_fdt = NULL;
> +    }
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +finalize_params_xen_boot (void)
> +{
> +  struct xen_boot_binary *module;
> +
> +  if (xen_hypervisor)
> +    {
> +      if (prepare_xen_hypervisor_params () != GRUB_ERR_NONE)
> +	goto fail;
> +    }
> +  else
> +    {
> +      grub_dprintf ("xen_loader", "Failed to get Xen Hypervisor info!\n");
> +      goto fail;
> +    }
> +
> +  /* Set module params info */
> +  FOR_LIST_ELEMENTS (module, module_head)
> +  {
> +    if (module->start && module->size > 0)
> +      {
> +	grub_dprintf ("xen_loader", "Module %s @ 0x%lx size:0x%lx\n",
> +		      module->name,
> +		      xen_boot_address_align (module->start, module->align),
> +		      module->size);
> +	if (prepare_xen_module_params (module) != GRUB_ERR_NONE)
> +	  goto fail;
> +      }
> +    else
> +      {
> +	grub_dprintf ("xen_loader", "Module info error: %s!\n", module->name);
> +	goto fail;
> +      }
> +  }
> +
> +  if (install_all_params () == GRUB_ERR_NONE)
> +    return GRUB_ERR_NONE;
> +
> +fail:
> +  clean_all_params ();
> +
> +  return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
> +}
> +
> +
> +static grub_err_t
> +xen_boot (void)
> +{
> +  grub_err_t err = finalize_params_xen_boot ();
> +  if (err)
> +    return err;
> +
> +  return grub_arm64_uefi_boot_image (xen_hypervisor->start,
> +				     xen_hypervisor->size,
> +				     xen_hypervisor->cmdline);
> +}
> +
> +static void
> +single_binary_unload (struct xen_boot_binary *binary)
> +{
> +  if (!binary)
> +    return;
> +
> +  if (binary->start && binary->size > 0)
> +    {
> +      grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
> +			   BYTES_TO_PAGES (binary->size + binary->align));
> +    }
> +
> +  if (binary->cmdline && binary->cmdline_size > 0)
> +    {
> +      grub_free (binary->cmdline);
> +      grub_dprintf ("xen_loader",
> +		    "Module %s cmdline memory free @ %p size: %d\n",
> +		    binary->name, binary->cmdline, binary->cmdline_size);
> +    }
> +
> +  if (binary->node_info.type == MODULE_CUSTOM)
> +    grub_free ((void *) binary->node_info.compat_string);
> +
> +  if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
> +    grub_list_remove (GRUB_AS_LIST (binary));
> +
> +  grub_dprintf ("xen_loader",
> +		"Module %s struct memory free @ %p size: 0x%lx\n",
> +		binary->name, binary, sizeof (binary));
> +  grub_free (binary);
> +
> +  return;
> +}
> +
> +static void
> +all_binaries_unload (void)
> +{
> +  struct xen_boot_binary *binary;
> +
> +  FOR_LIST_ELEMENTS (binary, module_head)
> +  {
> +    single_binary_unload (binary);
> +  }
> +
> +  if (xen_hypervisor)
> +    single_binary_unload (xen_hypervisor);
> +
> +  return;
> +}
> +
> +static grub_err_t
> +xen_unload (void)
> +{
> +  grub_linux_set_loaded (0);
> +  all_binaries_unload ();
> +  clean_all_params ();
> +  grub_dl_unref (my_mod);
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static void
> +xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
> +		      int argc, char *argv[])
> +{
> +  binary->size = grub_file_size (file);
> +  grub_dprintf ("xen_loader", "Xen_boot %s file size: 0x%lx\n",
> +		binary->name, binary->size);
> +
> +  binary->start = (grub_addr_t) grub_efi_allocate_pages (0,
> +							 (BYTES_TO_PAGES
> +							  (binary->size +
> +							   binary->align)));
> +  if (!binary->start)
> +    {
> +      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
> +      return;
> +    }
> +
> +  grub_dprintf ("xen_loader", "Xen_boot %s numpages: 0x%lx\n",
> +		binary->name, BYTES_TO_PAGES (binary->size + binary->align));
> +
> +  if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
> +							     binary->align),
> +		      binary->size) != (grub_ssize_t) binary->size)
> +    {
> +      single_binary_unload (binary);
> +      grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
> +      return;
> +    }
> +
> +  if (argc > 1)
> +    {
> +      binary->cmdline_size = grub_loader_cmdline_size (argc - 1, argv + 1);
> +      binary->cmdline = grub_zalloc (binary->cmdline_size);
> +      if (!binary->cmdline)
> +	{
> +	  single_binary_unload (binary);
> +	  grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
> +	  return;
> +	}
> +      grub_create_loader_cmdline (argc - 1, argv + 1, binary->cmdline,
> +				  binary->cmdline_size);
> +      grub_dprintf ("xen_loader",
> +		    "Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
> +		    binary->cmdline, binary->cmdline, binary->cmdline_size);
> +    }
> +  else
> +    {
> +      binary->cmdline_size = 0;
> +      binary->cmdline = NULL;
> +    }
> +
> +  grub_errno = GRUB_ERR_NONE;
> +  return;
> +}
> +
> +static grub_err_t
> +grub_cmd_xen_module (grub_command_t cmd, int argc, char *argv[])
> +{
> +
> +  struct xen_boot_binary *module = NULL;
> +  int file_name_index = 0;
> +  grub_file_t file = 0;
> +
> +  if (!argc)
> +    {
> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
> +      goto fail;
> +    }
> +
> +  if (!grub_linux_get_loaded ())
> +    {
> +      grub_error (GRUB_ERR_BAD_ARGUMENT,
> +		  N_("you need to load the Xen Hypervisor first"));
> +      goto fail;
> +    }
> +
> +  module =
> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
> +  if (!module)
> +    return grub_errno;
> +
> +  /* process all the options and get module type */
> +  if (set_module_type (cmd, module, argc, argv, &file_name_index) !=
> +      GRUB_ERR_NONE)
> +    goto fail;
> +  switch (module->node_info.type)
> +    {
> +    case MODULE_IMAGE:
> +    case MODULE_INITRD:
> +    case MODULE_XSM:
> +      module->node_info.compat_string =
> +	default_compat_string[module->node_info.type].compat_string;
> +      module->node_info.compat_string_size =
> +	default_compat_string[module->node_info.type].size;
> +      break;
> +
> +    case MODULE_CUSTOM:
> +      /* we have set the node_info in set_module_type */
> +      break;
> +
> +    default:
> +      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
> +    }
> +  module->name = module->node_info.compat_string;
> +  module->align = module_default_align[module->node_info.type];
> +
> +  grub_dprintf ("xen_loader", "Init %s module and node info:\n"
> +		"compatible %s\ncompat_string_size 0x%lx\n",
> +		module->name, module->node_info.compat_string,
> +		module->node_info.compat_string_size);
> +
> +  file = grub_file_open (argv[file_name_index]);
> +  if (!file)
> +    goto fail;
> +
> +  xen_boot_binary_load (module, file, argc - file_name_index,
> +			argv + file_name_index);
> +  if (grub_errno == GRUB_ERR_NONE)
> +    grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
> +
> +fail:
> +  if (file)
> +    grub_file_close (file);
> +  if (grub_errno != GRUB_ERR_NONE)
> +    single_binary_unload (module);
> +
> +  return grub_errno;
> +}
> +
> +static grub_err_t
> +grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
> +			 int argc, char *argv[])
> +{
> +  struct xen_hypervisor_header sh;
> +  grub_file_t file = NULL;
> +
> +  grub_dl_ref (my_mod);
> +
> +  if (!argc)
> +    {
> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
> +      goto fail;
> +    }
> +
> +  file = grub_file_open (argv[0]);
> +  if (!file)
> +    goto fail;
> +
> +  if (grub_file_read (file, &sh, sizeof (sh)) != (long) sizeof (sh))
> +    goto fail;
> +  if (grub_arm64_uefi_check_image
> +      ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
> +    goto fail;
> +  grub_file_seek (file, 0);
> +
> +  /* if another module has called grub_loader_set,
> +     we need to make sure that another module is unloaded properly */
> +  grub_loader_unset ();
> +
> +  xen_hypervisor =
> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
> +  if (!xen_hypervisor)
> +    return grub_errno;
> +
> +  xen_hypervisor->name = XEN_HYPERVISOR_NAME;
> +  xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
> +
> +  xen_boot_binary_load (xen_hypervisor, file, argc, argv);
> +  if (grub_errno == GRUB_ERR_NONE)
> +    {
> +      grub_loader_set (xen_boot, xen_unload, 0);
> +      grub_linux_set_loaded (1);
> +    }
> +
> +fail:
> +  if (file)
> +    grub_file_close (file);
> +  if (grub_errno != GRUB_ERR_NONE)
> +    {
> +      grub_linux_set_loaded (0);
> +      all_binaries_unload ();
> +      grub_dl_unref (my_mod);
> +    }
> +
> +  return grub_errno;
> +}
> +
> +static grub_command_t cmd_xen_hypervisor, cmd_xen_module;
> +static grub_command_t cmd_xen_linux, cmd_xen_initrd, cmd_xen_xsm;
> +
> +GRUB_MOD_INIT (xen_boot)
> +{
> +  cmd_xen_hypervisor =
> +    grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
> +			   N_("Load a xen hypervisor."));
> +  cmd_xen_linux =
> +    grub_register_command ("xen_linux", grub_cmd_xen_module, 0,
> +			   N_("Load a xen linux kernel for dom0."));
> +  cmd_xen_initrd =
> +    grub_register_command ("xen_initrd", grub_cmd_xen_module, 0,
> +			   N_("Load a xen initrd for dom0."));
> +  cmd_xen_xsm =
> +    grub_register_command ("xen_xsm", grub_cmd_xen_module, 0,
> +			   N_("Load a xen security module."));
> +  cmd_xen_module =
> +    grub_register_command ("xen_module", grub_cmd_xen_module, 0,
> +			   N_("Load a xen module."));
> +  my_mod = mod;
> +}
> +
> +GRUB_MOD_FINI (xen_boot)
> +{
> +  grub_unregister_command (cmd_xen_hypervisor);
> +  grub_unregister_command (cmd_xen_linux);
> +  grub_unregister_command (cmd_xen_initrd);
> +  grub_unregister_command (cmd_xen_xsm);
> +  grub_unregister_command (cmd_xen_module);
> +}
> 



[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

[-- Attachment #2: Type: text/plain, Size: 141 bytes --]

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 2/4] arm64: Add xen_boot module file
@ 2015-10-29 14:27       ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 0 replies; 550+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2015-10-29 14:27 UTC (permalink / raw)
  To: fu.wei, grub-devel, arvidjaar
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi

[-- Attachment #1: Type: text/plain, Size: 23108 bytes --]

Committed without the xen_module command. Its argument parsing was
non-trivial and I don't quite get what its intent is. Can you resubmit?
On 23.07.2015 07:16, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> grub-core/loader/arm64/xen_boot.c
> 
>   - This adds support for the Xen boot on ARM specification for arm64.
>   - Introduce xen_hypervisor, xen_linux, xen_initrd and xen_xsm
>     to load different binaries for xen boot;
>     Introduce xen_module to load common or custom module for xen boot.
>   - This Xen boot support is a separated  module for aarch64,
>     but reuse the existing code of devicetree in linux module.
> 
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  grub-core/Makefile.core.def       |   7 +
>  grub-core/loader/arm64/xen_boot.c | 685 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 692 insertions(+)
> 
> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
> index a6101de..796f7e9 100644
> --- a/grub-core/Makefile.core.def
> +++ b/grub-core/Makefile.core.def
> @@ -1648,6 +1648,13 @@ module = {
>  };
>  
>  module = {
> +  name = xen_boot;
> +  common = lib/cmdline.c;
> +  arm64 = loader/arm64/xen_boot.c;
> +  enable = arm64;
> +};
> +
> +module = {
>    name = linux;
>    x86 = loader/i386/linux.c;
>    xen = loader/i386/xen.c;
> diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
> new file mode 100644
> index 0000000..33a65dd
> --- /dev/null
> +++ b/grub-core/loader/arm64/xen_boot.c
> @@ -0,0 +1,685 @@
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2014  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB 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.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/cache.h>
> +#include <grub/charset.h>
> +#include <grub/command.h>
> +#include <grub/err.h>
> +#include <grub/file.h>
> +#include <grub/fdt.h>
> +#include <grub/linux.h>
> +#include <grub/list.h>
> +#include <grub/loader.h>
> +#include <grub/misc.h>
> +#include <grub/mm.h>
> +#include <grub/types.h>
> +#include <grub/cpu/linux.h>
> +#include <grub/efi/efi.h>
> +#include <grub/efi/pe32.h>	/* required by struct xen_hypervisor_header */
> +#include <grub/i18n.h>
> +#include <grub/lib/cmdline.h>
> +
> +GRUB_MOD_LICENSE ("GPLv3+");
> +
> +#define XEN_HYPERVISOR_NAME  "xen_hypervisor"
> +
> +#define MODULE_DEFAULT_ALIGN  (0x0)
> +#define MODULE_IMAGE_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +#define MODULE_INITRD_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +#define MODULE_XSM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +#define MODULE_CUSTOM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
> +
> +/* #define MODULE_IMAGE_COMPATIBLE  "xen,linux-image\0xen,module"
> +#define MODULE_INITRD_COMPATIBLE  "xen,linux-image\0xen,module"
> +#define MODULE_XSM_COMPATIBLE  "xen,xsm-policy\0xen,module"
> +#define MODULE_CUSTOM_COMPATIBLE  "xen,module" */
> +#define MODULE_IMAGE_COMPATIBLE  "multiboot,kernel\0multiboot,module"
> +#define MODULE_INITRD_COMPATIBLE  "multiboot,ramdisk\0multiboot,module"
> +#define MODULE_XSM_COMPATIBLE  "xen,xsm-policy\0multiboot,module"
> +#define MODULE_CUSTOM_COMPATIBLE  "multiboot,module"
> +
> +/* This maximum size is defined in Power.org ePAPR V1.1
> + * https://www.power.org/documentation/epapr-version-1-1/
> + * 2.2.1.1 Node Name Requirements
> + * node-name@unit-address
> + * 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
> + */
> +#define FDT_NODE_NAME_MAX_SIZE  (49)
> +
> +#define ARG_SHIFT(argc, argv) \
> +  do { \
> +    (argc)--; \
> +    (argv)++; \
> +  } while (0)
> +
> +struct compat_string_struct
> +{
> +  grub_size_t size;
> +  const char *compat_string;
> +};
> +typedef struct compat_string_struct compat_string_struct_t;
> +#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
> +
> +enum module_type
> +{
> +  MODULE_IMAGE,
> +  MODULE_INITRD,
> +  MODULE_XSM,
> +  MODULE_CUSTOM
> +};
> +typedef enum module_type module_type_t;
> +
> +struct fdt_node_info
> +{
> +  module_type_t type;
> +
> +  const char *compat_string;
> +  grub_size_t compat_string_size;
> +};
> +
> +struct xen_hypervisor_header
> +{
> +  struct grub_arm64_linux_kernel_header efi_head;
> +
> +  /* This is always PE\0\0.  */
> +  grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
> +  /* The COFF file header.  */
> +  struct grub_pe32_coff_header coff_header;
> +  /* The Optional header.  */
> +  struct grub_pe64_optional_header optional_header;
> +};
> +
> +struct xen_boot_binary
> +{
> +  struct xen_boot_binary *next;
> +  struct xen_boot_binary **prev;
> +  const char *name;
> +
> +  grub_addr_t start;
> +  grub_size_t size;
> +  grub_size_t align;
> +
> +  char *cmdline;
> +  int cmdline_size;
> +
> +  struct fdt_node_info node_info;
> +};
> +
> +static grub_dl_t my_mod;
> +
> +static struct xen_boot_binary *xen_hypervisor;
> +static struct xen_boot_binary *module_head;
> +static const grub_size_t module_default_align[] = {
> +  MODULE_IMAGE_MIN_ALIGN,
> +  MODULE_INITRD_MIN_ALIGN,
> +  MODULE_XSM_MIN_ALIGN,
> +  MODULE_CUSTOM_MIN_ALIGN
> +};
> +
> +static void *xen_boot_fdt;
> +static const compat_string_struct_t default_compat_string[] = {
> +  FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
> +  FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
> +  FDT_COMPATIBLE (MODULE_XSM_COMPATIBLE),
> +  FDT_COMPATIBLE (MODULE_CUSTOM_COMPATIBLE)
> +};
> +
> +static __inline grub_addr_t
> +xen_boot_address_align (grub_addr_t start, grub_size_t align)
> +{
> +  return (align ? (ALIGN_UP (start, align)) : start);
> +}
> +
> +/* Parse the option of xen_module command. For now, we support
> +   (1) --type <the compatible stream>
> +   We also set up the type of module in this function.
> +   If there are some "--type" options in the command line,
> +   we make a custom compatible stream in this function. */
> +static grub_err_t
> +set_module_type (grub_command_t cmd, struct xen_boot_binary *module,
> +		 int argc, char *argv[], int *file_name_index)
> +{
> +  char **compat_string_temp_array;
> +  grub_size_t total_size = 0;
> +  int num_types = 0, i;
> +  char *temp = NULL;
> +
> +  *file_name_index = 0;
> +
> +  if (!grub_strcmp (cmd->name, "xen_linux"))
> +    module->node_info.type = MODULE_IMAGE;
> +  else if (!grub_strcmp (cmd->name, "xen_initrd"))
> +    module->node_info.type = MODULE_INITRD;
> +  else if (!grub_strcmp (cmd->name, "xen_xsm"))
> +    module->node_info.type = MODULE_XSM;
> +  else if (!grub_strcmp (cmd->name, "xen_module"))
> +    module->node_info.type = MODULE_CUSTOM;
> +
> +  /* if there are some options we need to process. */
> +  if (module->node_info.type == MODULE_CUSTOM)
> +    {
> +      compat_string_temp_array =
> +	(char **) grub_zalloc (sizeof (char *) * argc);
> +      if (!compat_string_temp_array)
> +	return grub_errno;
> +      /* the module type is set by "--type"(MODULE_CUSTOM) */
> +      while (argc > 2 && !grub_strcmp (argv[0], "--type"))
> +	{
> +	  module->node_info.type = MODULE_CUSTOM;
> +	  ARG_SHIFT (argc, argv);
> +	  total_size += grub_strlen (argv[0]) + 1;
> +	  compat_string_temp_array[num_types++] = argv[0];
> +	  ARG_SHIFT (argc, argv);
> +	  (*file_name_index) += 2;
> +	}
> +
> +      if (total_size)
> +	{
> +	  module->node_info.compat_string = temp =
> +	    (char *) grub_zalloc (total_size);
> +	  if (!temp)
> +	    {
> +	      grub_free (compat_string_temp_array);
> +	      return grub_errno;
> +	    }
> +
> +	  module->node_info.compat_string_size = total_size;
> +	  for (i = 0; num_types > 0; num_types--, i++, temp++)
> +	    {
> +	      grub_strcpy (temp, compat_string_temp_array[i]);
> +	      temp += grub_strlen (compat_string_temp_array[i]);
> +	    }
> +	}
> +      else
> +	{
> +	  module->node_info.compat_string =
> +	    default_compat_string[MODULE_CUSTOM].compat_string;
> +	  module->node_info.compat_string_size =
> +	    default_compat_string[MODULE_CUSTOM].size;
> +	}
> +
> +      grub_free (compat_string_temp_array);
> +    }
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +prepare_xen_hypervisor_params (void)
> +{
> +  int chosen_node = 0;
> +  int retval;
> +
> +  xen_boot_fdt = grub_linux_get_fdt ();
> +  if (!xen_boot_fdt)
> +    return grub_error (GRUB_ERR_IO, "failed to get FDT");
> +
> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 0)
> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 1)
> +    return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
> +
> +  grub_dprintf ("xen_loader",
> +		"Xen Hypervisor cmdline : %s @ %p size:%d\n",
> +		xen_hypervisor->cmdline, xen_hypervisor->cmdline,
> +		xen_hypervisor->cmdline_size);
> +
> +  retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
> +			      xen_hypervisor->cmdline,
> +			      xen_hypervisor->cmdline_size);
> +  if (retval)
> +    return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +prepare_xen_module_params (struct xen_boot_binary *module)
> +{
> +  int retval, chosen_node = 0, module_node = 0;
> +  char module_name[FDT_NODE_NAME_MAX_SIZE];
> +
> +  retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
> +			  xen_boot_address_align (module->start,
> +						  module->align));
> +  grub_dprintf ("xen_loader", "Module node name %s \n", module_name);
> +
> +  if (retval < (int) sizeof ("module@"))
> +    return grub_error (GRUB_ERR_IO, N_("failed to get FDT"));
> +
> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 0)
> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
> +  if (chosen_node < 1)
> +    return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
> +
> +  module_node =
> +    grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
> +  if (module_node < 0)
> +    module_node =
> +      grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
> +
> +  retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
> +			      module->node_info.compat_string,
> +			      (grub_uint32_t) module->
> +			      node_info.compat_string_size);
> +  if (retval)
> +    return grub_error (GRUB_ERR_IO, N_("failed to update FDT"));
> +
> +  grub_dprintf ("xen_loader", "Module %s compatible = %s size = 0x%lx\n",
> +		module->name, module->node_info.compat_string,
> +		module->node_info.compat_string_size);
> +
> +  retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
> +			       xen_boot_address_align (module->start,
> +						       module->align),
> +			       module->size);
> +  if (retval)
> +    return grub_error (GRUB_ERR_IO, N_("failed to update FDT"));
> +
> +  if (module->cmdline && module->cmdline_size > 0)
> +    {
> +      grub_dprintf ("xen_loader",
> +		    "Module %s cmdline : %s @ %p size:%d\n", module->name,
> +		    module->cmdline, module->cmdline, module->cmdline_size);
> +
> +      retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
> +				  module->cmdline, module->cmdline_size + 1);
> +      if (retval)
> +	return grub_error (GRUB_ERR_IO, "failed to update FDT");
> +    }
> +  else
> +    {
> +      grub_dprintf ("xen_loader", "Module %s has not bootargs!\n",
> +		    module->name);
> +    }
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +install_all_params (void)
> +{
> +  grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
> +  grub_efi_boot_services_t *b;
> +  grub_efi_status_t status;
> +
> +  b = grub_efi_system_table->boot_services;
> +  status = b->install_configuration_table (&fdt_guid, xen_boot_fdt);
> +  if (status != GRUB_EFI_SUCCESS)
> +    return grub_error (GRUB_ERR_IO, "failed to install FDT");
> +
> +  grub_dprintf ("xen_loader",
> +		"Installed/updated FDT configuration table @ %p\n",
> +		xen_boot_fdt);
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +clean_all_params (void)
> +{
> +  if (xen_boot_fdt)
> +    {
> +      grub_efi_free_pages ((grub_efi_physical_address_t) xen_boot_fdt,
> +			   BYTES_TO_PAGES (grub_fdt_get_totalsize
> +					   (xen_boot_fdt)));
> +      xen_boot_fdt = NULL;
> +    }
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +finalize_params_xen_boot (void)
> +{
> +  struct xen_boot_binary *module;
> +
> +  if (xen_hypervisor)
> +    {
> +      if (prepare_xen_hypervisor_params () != GRUB_ERR_NONE)
> +	goto fail;
> +    }
> +  else
> +    {
> +      grub_dprintf ("xen_loader", "Failed to get Xen Hypervisor info!\n");
> +      goto fail;
> +    }
> +
> +  /* Set module params info */
> +  FOR_LIST_ELEMENTS (module, module_head)
> +  {
> +    if (module->start && module->size > 0)
> +      {
> +	grub_dprintf ("xen_loader", "Module %s @ 0x%lx size:0x%lx\n",
> +		      module->name,
> +		      xen_boot_address_align (module->start, module->align),
> +		      module->size);
> +	if (prepare_xen_module_params (module) != GRUB_ERR_NONE)
> +	  goto fail;
> +      }
> +    else
> +      {
> +	grub_dprintf ("xen_loader", "Module info error: %s!\n", module->name);
> +	goto fail;
> +      }
> +  }
> +
> +  if (install_all_params () == GRUB_ERR_NONE)
> +    return GRUB_ERR_NONE;
> +
> +fail:
> +  clean_all_params ();
> +
> +  return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
> +}
> +
> +
> +static grub_err_t
> +xen_boot (void)
> +{
> +  grub_err_t err = finalize_params_xen_boot ();
> +  if (err)
> +    return err;
> +
> +  return grub_arm64_uefi_boot_image (xen_hypervisor->start,
> +				     xen_hypervisor->size,
> +				     xen_hypervisor->cmdline);
> +}
> +
> +static void
> +single_binary_unload (struct xen_boot_binary *binary)
> +{
> +  if (!binary)
> +    return;
> +
> +  if (binary->start && binary->size > 0)
> +    {
> +      grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
> +			   BYTES_TO_PAGES (binary->size + binary->align));
> +    }
> +
> +  if (binary->cmdline && binary->cmdline_size > 0)
> +    {
> +      grub_free (binary->cmdline);
> +      grub_dprintf ("xen_loader",
> +		    "Module %s cmdline memory free @ %p size: %d\n",
> +		    binary->name, binary->cmdline, binary->cmdline_size);
> +    }
> +
> +  if (binary->node_info.type == MODULE_CUSTOM)
> +    grub_free ((void *) binary->node_info.compat_string);
> +
> +  if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
> +    grub_list_remove (GRUB_AS_LIST (binary));
> +
> +  grub_dprintf ("xen_loader",
> +		"Module %s struct memory free @ %p size: 0x%lx\n",
> +		binary->name, binary, sizeof (binary));
> +  grub_free (binary);
> +
> +  return;
> +}
> +
> +static void
> +all_binaries_unload (void)
> +{
> +  struct xen_boot_binary *binary;
> +
> +  FOR_LIST_ELEMENTS (binary, module_head)
> +  {
> +    single_binary_unload (binary);
> +  }
> +
> +  if (xen_hypervisor)
> +    single_binary_unload (xen_hypervisor);
> +
> +  return;
> +}
> +
> +static grub_err_t
> +xen_unload (void)
> +{
> +  grub_linux_set_loaded (0);
> +  all_binaries_unload ();
> +  clean_all_params ();
> +  grub_dl_unref (my_mod);
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static void
> +xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
> +		      int argc, char *argv[])
> +{
> +  binary->size = grub_file_size (file);
> +  grub_dprintf ("xen_loader", "Xen_boot %s file size: 0x%lx\n",
> +		binary->name, binary->size);
> +
> +  binary->start = (grub_addr_t) grub_efi_allocate_pages (0,
> +							 (BYTES_TO_PAGES
> +							  (binary->size +
> +							   binary->align)));
> +  if (!binary->start)
> +    {
> +      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
> +      return;
> +    }
> +
> +  grub_dprintf ("xen_loader", "Xen_boot %s numpages: 0x%lx\n",
> +		binary->name, BYTES_TO_PAGES (binary->size + binary->align));
> +
> +  if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
> +							     binary->align),
> +		      binary->size) != (grub_ssize_t) binary->size)
> +    {
> +      single_binary_unload (binary);
> +      grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
> +      return;
> +    }
> +
> +  if (argc > 1)
> +    {
> +      binary->cmdline_size = grub_loader_cmdline_size (argc - 1, argv + 1);
> +      binary->cmdline = grub_zalloc (binary->cmdline_size);
> +      if (!binary->cmdline)
> +	{
> +	  single_binary_unload (binary);
> +	  grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
> +	  return;
> +	}
> +      grub_create_loader_cmdline (argc - 1, argv + 1, binary->cmdline,
> +				  binary->cmdline_size);
> +      grub_dprintf ("xen_loader",
> +		    "Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
> +		    binary->cmdline, binary->cmdline, binary->cmdline_size);
> +    }
> +  else
> +    {
> +      binary->cmdline_size = 0;
> +      binary->cmdline = NULL;
> +    }
> +
> +  grub_errno = GRUB_ERR_NONE;
> +  return;
> +}
> +
> +static grub_err_t
> +grub_cmd_xen_module (grub_command_t cmd, int argc, char *argv[])
> +{
> +
> +  struct xen_boot_binary *module = NULL;
> +  int file_name_index = 0;
> +  grub_file_t file = 0;
> +
> +  if (!argc)
> +    {
> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
> +      goto fail;
> +    }
> +
> +  if (!grub_linux_get_loaded ())
> +    {
> +      grub_error (GRUB_ERR_BAD_ARGUMENT,
> +		  N_("you need to load the Xen Hypervisor first"));
> +      goto fail;
> +    }
> +
> +  module =
> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
> +  if (!module)
> +    return grub_errno;
> +
> +  /* process all the options and get module type */
> +  if (set_module_type (cmd, module, argc, argv, &file_name_index) !=
> +      GRUB_ERR_NONE)
> +    goto fail;
> +  switch (module->node_info.type)
> +    {
> +    case MODULE_IMAGE:
> +    case MODULE_INITRD:
> +    case MODULE_XSM:
> +      module->node_info.compat_string =
> +	default_compat_string[module->node_info.type].compat_string;
> +      module->node_info.compat_string_size =
> +	default_compat_string[module->node_info.type].size;
> +      break;
> +
> +    case MODULE_CUSTOM:
> +      /* we have set the node_info in set_module_type */
> +      break;
> +
> +    default:
> +      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
> +    }
> +  module->name = module->node_info.compat_string;
> +  module->align = module_default_align[module->node_info.type];
> +
> +  grub_dprintf ("xen_loader", "Init %s module and node info:\n"
> +		"compatible %s\ncompat_string_size 0x%lx\n",
> +		module->name, module->node_info.compat_string,
> +		module->node_info.compat_string_size);
> +
> +  file = grub_file_open (argv[file_name_index]);
> +  if (!file)
> +    goto fail;
> +
> +  xen_boot_binary_load (module, file, argc - file_name_index,
> +			argv + file_name_index);
> +  if (grub_errno == GRUB_ERR_NONE)
> +    grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
> +
> +fail:
> +  if (file)
> +    grub_file_close (file);
> +  if (grub_errno != GRUB_ERR_NONE)
> +    single_binary_unload (module);
> +
> +  return grub_errno;
> +}
> +
> +static grub_err_t
> +grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
> +			 int argc, char *argv[])
> +{
> +  struct xen_hypervisor_header sh;
> +  grub_file_t file = NULL;
> +
> +  grub_dl_ref (my_mod);
> +
> +  if (!argc)
> +    {
> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
> +      goto fail;
> +    }
> +
> +  file = grub_file_open (argv[0]);
> +  if (!file)
> +    goto fail;
> +
> +  if (grub_file_read (file, &sh, sizeof (sh)) != (long) sizeof (sh))
> +    goto fail;
> +  if (grub_arm64_uefi_check_image
> +      ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
> +    goto fail;
> +  grub_file_seek (file, 0);
> +
> +  /* if another module has called grub_loader_set,
> +     we need to make sure that another module is unloaded properly */
> +  grub_loader_unset ();
> +
> +  xen_hypervisor =
> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
> +  if (!xen_hypervisor)
> +    return grub_errno;
> +
> +  xen_hypervisor->name = XEN_HYPERVISOR_NAME;
> +  xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
> +
> +  xen_boot_binary_load (xen_hypervisor, file, argc, argv);
> +  if (grub_errno == GRUB_ERR_NONE)
> +    {
> +      grub_loader_set (xen_boot, xen_unload, 0);
> +      grub_linux_set_loaded (1);
> +    }
> +
> +fail:
> +  if (file)
> +    grub_file_close (file);
> +  if (grub_errno != GRUB_ERR_NONE)
> +    {
> +      grub_linux_set_loaded (0);
> +      all_binaries_unload ();
> +      grub_dl_unref (my_mod);
> +    }
> +
> +  return grub_errno;
> +}
> +
> +static grub_command_t cmd_xen_hypervisor, cmd_xen_module;
> +static grub_command_t cmd_xen_linux, cmd_xen_initrd, cmd_xen_xsm;
> +
> +GRUB_MOD_INIT (xen_boot)
> +{
> +  cmd_xen_hypervisor =
> +    grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
> +			   N_("Load a xen hypervisor."));
> +  cmd_xen_linux =
> +    grub_register_command ("xen_linux", grub_cmd_xen_module, 0,
> +			   N_("Load a xen linux kernel for dom0."));
> +  cmd_xen_initrd =
> +    grub_register_command ("xen_initrd", grub_cmd_xen_module, 0,
> +			   N_("Load a xen initrd for dom0."));
> +  cmd_xen_xsm =
> +    grub_register_command ("xen_xsm", grub_cmd_xen_module, 0,
> +			   N_("Load a xen security module."));
> +  cmd_xen_module =
> +    grub_register_command ("xen_module", grub_cmd_xen_module, 0,
> +			   N_("Load a xen module."));
> +  my_mod = mod;
> +}
> +
> +GRUB_MOD_FINI (xen_boot)
> +{
> +  grub_unregister_command (cmd_xen_hypervisor);
> +  grub_unregister_command (cmd_xen_linux);
> +  grub_unregister_command (cmd_xen_initrd);
> +  grub_unregister_command (cmd_xen_xsm);
> +  grub_unregister_command (cmd_xen_module);
> +}
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
  2015-07-23  5:16   ` [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64 fu.wei
@ 2015-10-29 15:25       ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 0 replies; 550+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2015-10-29 15:25 UTC (permalink / raw)
  To: fu.wei, grub-devel, arvidjaar
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi


[-- Attachment #1.1: Type: text/plain, Size: 632 bytes --]

> +if [ "x$machine" != xaarch64 ]; then
> +	multiboot_cmd="multiboot"
> +	module_linux_cmd="module"
> +	module_initrd_cmd="module --nounzip"
> +else
> +	multiboot_cmd="xen_hypervisor"
> +	module_linux_cmd="xen_linux"
> +	module_initrd_cmd="xen_initrd"
> +fi
> +
Please do not hardcode an assumption that grub-mkconfig is executed on
the same machine as GRUB is booted. I know that we have instances of
such assumption in some cases but we'd like to eliminate them. Alternatives:
- Check arch on boot time
- Check that new xen commands are supported (define a new feature)
Please add xen_* aliases on x86 as well



[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

[-- Attachment #2: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
@ 2015-10-29 15:25       ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 0 replies; 550+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2015-10-29 15:25 UTC (permalink / raw)
  To: fu.wei, grub-devel, arvidjaar
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi

[-- Attachment #1: Type: text/plain, Size: 632 bytes --]

> +if [ "x$machine" != xaarch64 ]; then
> +	multiboot_cmd="multiboot"
> +	module_linux_cmd="module"
> +	module_initrd_cmd="module --nounzip"
> +else
> +	multiboot_cmd="xen_hypervisor"
> +	module_linux_cmd="xen_linux"
> +	module_initrd_cmd="xen_initrd"
> +fi
> +
Please do not hardcode an assumption that grub-mkconfig is executed on
the same machine as GRUB is booted. I know that we have instances of
such assumption in some cases but we'd like to eliminate them. Alternatives:
- Check arch on boot time
- Check that new xen commands are supported (define a new feature)
Please add xen_* aliases on x86 as well



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
  2015-10-29 15:25       ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2015-10-29 19:53         ` Andrei Borzenkov
  -1 siblings, 0 replies; 550+ messages in thread
From: Andrei Borzenkov @ 2015-10-29 19:53 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko, fu.wei, grub-devel
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi

29.10.2015 18:25, Vladimir 'φ-coder/phcoder' Serbinenko пишет:
>> +if [ "x$machine" != xaarch64 ]; then
>> +	multiboot_cmd="multiboot"
>> +	module_linux_cmd="module"
>> +	module_initrd_cmd="module --nounzip"
>> +else
>> +	multiboot_cmd="xen_hypervisor"
>> +	module_linux_cmd="xen_linux"
>> +	module_initrd_cmd="xen_initrd"
>> +fi
>> +
> Please do not hardcode an assumption that grub-mkconfig is executed on
> the same machine as GRUB is booted. I know that we have instances of
> such assumption in some cases but we'd like to eliminate them. Alternatives:
> - Check arch on boot time

This makes it even more difficult for os-prober to parse grub.cfg. We 
need some alternative before going this route.

> - Check that new xen commands are supported (define a new feature)
> Please add xen_* aliases on x86 as well
>
>

Yes, that's better.

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
@ 2015-10-29 19:53         ` Andrei Borzenkov
  0 siblings, 0 replies; 550+ messages in thread
From: Andrei Borzenkov @ 2015-10-29 19:53 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko, fu.wei, grub-devel
  Cc: xen-devel, Ian.Campbell, stefano.stabellini, jcm, leif.lindholm,
	ryan.harkin, linaro-uefi

29.10.2015 18:25, Vladimir 'φ-coder/phcoder' Serbinenko пишет:
>> +if [ "x$machine" != xaarch64 ]; then
>> +	multiboot_cmd="multiboot"
>> +	module_linux_cmd="module"
>> +	module_initrd_cmd="module --nounzip"
>> +else
>> +	multiboot_cmd="xen_hypervisor"
>> +	module_linux_cmd="xen_linux"
>> +	module_initrd_cmd="xen_initrd"
>> +fi
>> +
> Please do not hardcode an assumption that grub-mkconfig is executed on
> the same machine as GRUB is booted. I know that we have instances of
> such assumption in some cases but we'd like to eliminate them. Alternatives:
> - Check arch on boot time

This makes it even more difficult for os-prober to parse grub.cfg. We 
need some alternative before going this route.

> - Check that new xen commands are supported (define a new feature)
> Please add xen_* aliases on x86 as well
>
>

Yes, that's better.


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 1/4] arm64: Add and export some accessor functions for xen boot
  2015-10-29 12:03       ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2015-10-30  7:11         ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-10-30  7:11 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Andrei Borzenkov, Jon Masters, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List

Hi Vladimir,

Good idea! I can see your patch for it in master branch.

Great thanks for your help, I will try this ASAP :-)


On 29 October 2015 at 20:03, Vladimir 'φ-coder/phcoder' Serbinenko
<phcoder@gmail.com> wrote:
> On 23.07.2015 07:16, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> Add accessor functions of "loaded" flag in
>> grub-core/loader/arm64/linux.c.
>>
>> Export accessor functions of "loaded" flag and
>> grub_linux_get_fdt function in include/grub/arm64/linux.h.
>>
>> Purpose: Reuse the existing code of devicetree in linux module.
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  grub-core/loader/arm64/linux.c | 13 +++++++++++++
>>  include/grub/arm64/linux.h     |  6 +++++-
>>  2 files changed, 18 insertions(+), 1 deletion(-)
>>
>> diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
>> index 987f5b9..cf6026e 100644
>> --- a/grub-core/loader/arm64/linux.c
>> +++ b/grub-core/loader/arm64/linux.c
>> @@ -48,6 +48,19 @@ static grub_addr_t initrd_end;
>>  static void *loaded_fdt;
>>  static void *fdt;
>>
>> +/* The accessor functions for "loaded" flag */
>> +int
>> +grub_linux_get_loaded (void)
>> +{
>> +  return loaded;
>> +}
>> +
>> +void
>> +grub_linux_set_loaded (int loaded_flag)
>> +{
>> +  loaded = loaded_flag;
>> +}
>> +
> Accessor functions are usually useless in GRUB. We have no public API to
> respect. So it only adds clutter. Also "loaded" flag is static for а
> good reason: it's specific to linux.c. I'm going to move fdt part to
> fdt.c and have uniform interface for both linux and xen.
>>  static void *
>>  get_firmware_fdt (void)
>>  {
>> diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h
>> index 65796d9..20058f3 100644
>> --- a/include/grub/arm64/linux.h
>> +++ b/include/grub/arm64/linux.h
>> @@ -43,10 +43,14 @@ struct grub_arm64_linux_kernel_header
>>  };
>>
>>  /* Declare the functions for getting dtb and checking/booting image */
>> -void *grub_linux_get_fdt (void);
>>  grub_err_t grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header
>>                                          *lh);
>>  grub_err_t grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size,
>>                                         char *args);
>>
>> +/* Export the accessor functions for gettin dtb and "loaded" flag */
>> +void EXPORT_FUNC (*grub_linux_get_fdt) (void);
>> +int EXPORT_FUNC (grub_linux_get_loaded) (void);
>> +void EXPORT_FUNC (grub_linux_set_loaded) (int loaded_flag);
>> +
> EXPORT_* are necessary only for core. Not for modules.
>>  #endif /* ! GRUB_LINUX_CPU_HEADER */
>>
>
>



-- 
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

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 1/4] arm64: Add and export some accessor functions for xen boot
@ 2015-10-30  7:11         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-10-30  7:11 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Andrei Borzenkov, Jon Masters, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List

Hi Vladimir,

Good idea! I can see your patch for it in master branch.

Great thanks for your help, I will try this ASAP :-)


On 29 October 2015 at 20:03, Vladimir 'φ-coder/phcoder' Serbinenko
<phcoder@gmail.com> wrote:
> On 23.07.2015 07:16, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> Add accessor functions of "loaded" flag in
>> grub-core/loader/arm64/linux.c.
>>
>> Export accessor functions of "loaded" flag and
>> grub_linux_get_fdt function in include/grub/arm64/linux.h.
>>
>> Purpose: Reuse the existing code of devicetree in linux module.
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  grub-core/loader/arm64/linux.c | 13 +++++++++++++
>>  include/grub/arm64/linux.h     |  6 +++++-
>>  2 files changed, 18 insertions(+), 1 deletion(-)
>>
>> diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
>> index 987f5b9..cf6026e 100644
>> --- a/grub-core/loader/arm64/linux.c
>> +++ b/grub-core/loader/arm64/linux.c
>> @@ -48,6 +48,19 @@ static grub_addr_t initrd_end;
>>  static void *loaded_fdt;
>>  static void *fdt;
>>
>> +/* The accessor functions for "loaded" flag */
>> +int
>> +grub_linux_get_loaded (void)
>> +{
>> +  return loaded;
>> +}
>> +
>> +void
>> +grub_linux_set_loaded (int loaded_flag)
>> +{
>> +  loaded = loaded_flag;
>> +}
>> +
> Accessor functions are usually useless in GRUB. We have no public API to
> respect. So it only adds clutter. Also "loaded" flag is static for а
> good reason: it's specific to linux.c. I'm going to move fdt part to
> fdt.c and have uniform interface for both linux and xen.
>>  static void *
>>  get_firmware_fdt (void)
>>  {
>> diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h
>> index 65796d9..20058f3 100644
>> --- a/include/grub/arm64/linux.h
>> +++ b/include/grub/arm64/linux.h
>> @@ -43,10 +43,14 @@ struct grub_arm64_linux_kernel_header
>>  };
>>
>>  /* Declare the functions for getting dtb and checking/booting image */
>> -void *grub_linux_get_fdt (void);
>>  grub_err_t grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header
>>                                          *lh);
>>  grub_err_t grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size,
>>                                         char *args);
>>
>> +/* Export the accessor functions for gettin dtb and "loaded" flag */
>> +void EXPORT_FUNC (*grub_linux_get_fdt) (void);
>> +int EXPORT_FUNC (grub_linux_get_loaded) (void);
>> +void EXPORT_FUNC (grub_linux_set_loaded) (int loaded_flag);
>> +
> EXPORT_* are necessary only for core. Not for modules.
>>  #endif /* ! GRUB_LINUX_CPU_HEADER */
>>
>
>



-- 
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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 2/4] arm64: Add xen_boot module file
  2015-10-29 14:27       ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2015-10-30  8:08         ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-10-30  8:08 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Andrei Borzenkov, Jon Masters, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List

Hi Vladimir,

yes, Thanks for your modification :-)

I just follow the xen boot protocol :
http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot

xen_module is just for "--type" option, I will discuss this with Xen
developer for this.
If we need this option, I will resubmit  it :-)

Great thanks!

On 29 October 2015 at 22:27, Vladimir 'φ-coder/phcoder' Serbinenko
<phcoder@gmail.com> wrote:
> Committed without the xen_module command. Its argument parsing was
> non-trivial and I don't quite get what its intent is. Can you resubmit?
> On 23.07.2015 07:16, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> grub-core/loader/arm64/xen_boot.c
>>
>>   - This adds support for the Xen boot on ARM specification for arm64.
>>   - Introduce xen_hypervisor, xen_linux, xen_initrd and xen_xsm
>>     to load different binaries for xen boot;
>>     Introduce xen_module to load common or custom module for xen boot.
>>   - This Xen boot support is a separated  module for aarch64,
>>     but reuse the existing code of devicetree in linux module.
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  grub-core/Makefile.core.def       |   7 +
>>  grub-core/loader/arm64/xen_boot.c | 685 ++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 692 insertions(+)
>>
>> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
>> index a6101de..796f7e9 100644
>> --- a/grub-core/Makefile.core.def
>> +++ b/grub-core/Makefile.core.def
>> @@ -1648,6 +1648,13 @@ module = {
>>  };
>>
>>  module = {
>> +  name = xen_boot;
>> +  common = lib/cmdline.c;
>> +  arm64 = loader/arm64/xen_boot.c;
>> +  enable = arm64;
>> +};
>> +
>> +module = {
>>    name = linux;
>>    x86 = loader/i386/linux.c;
>>    xen = loader/i386/xen.c;
>> diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
>> new file mode 100644
>> index 0000000..33a65dd
>> --- /dev/null
>> +++ b/grub-core/loader/arm64/xen_boot.c
>> @@ -0,0 +1,685 @@
>> +/*
>> + *  GRUB  --  GRand Unified Bootloader
>> + *  Copyright (C) 2014  Free Software Foundation, Inc.
>> + *
>> + *  GRUB is free software: you can redistribute it and/or modify
>> + *  it under the terms of the GNU General Public License as published by
>> + *  the Free Software Foundation, either version 3 of the License, or
>> + *  (at your option) any later version.
>> + *
>> + *  GRUB 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.
>> + *
>> + *  You should have received a copy of the GNU General Public License
>> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <grub/cache.h>
>> +#include <grub/charset.h>
>> +#include <grub/command.h>
>> +#include <grub/err.h>
>> +#include <grub/file.h>
>> +#include <grub/fdt.h>
>> +#include <grub/linux.h>
>> +#include <grub/list.h>
>> +#include <grub/loader.h>
>> +#include <grub/misc.h>
>> +#include <grub/mm.h>
>> +#include <grub/types.h>
>> +#include <grub/cpu/linux.h>
>> +#include <grub/efi/efi.h>
>> +#include <grub/efi/pe32.h>   /* required by struct xen_hypervisor_header */
>> +#include <grub/i18n.h>
>> +#include <grub/lib/cmdline.h>
>> +
>> +GRUB_MOD_LICENSE ("GPLv3+");
>> +
>> +#define XEN_HYPERVISOR_NAME  "xen_hypervisor"
>> +
>> +#define MODULE_DEFAULT_ALIGN  (0x0)
>> +#define MODULE_IMAGE_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +#define MODULE_INITRD_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +#define MODULE_XSM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +#define MODULE_CUSTOM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +
>> +/* #define MODULE_IMAGE_COMPATIBLE  "xen,linux-image\0xen,module"
>> +#define MODULE_INITRD_COMPATIBLE  "xen,linux-image\0xen,module"
>> +#define MODULE_XSM_COMPATIBLE  "xen,xsm-policy\0xen,module"
>> +#define MODULE_CUSTOM_COMPATIBLE  "xen,module" */
>> +#define MODULE_IMAGE_COMPATIBLE  "multiboot,kernel\0multiboot,module"
>> +#define MODULE_INITRD_COMPATIBLE  "multiboot,ramdisk\0multiboot,module"
>> +#define MODULE_XSM_COMPATIBLE  "xen,xsm-policy\0multiboot,module"
>> +#define MODULE_CUSTOM_COMPATIBLE  "multiboot,module"
>> +
>> +/* This maximum size is defined in Power.org ePAPR V1.1
>> + * https://www.power.org/documentation/epapr-version-1-1/
>> + * 2.2.1.1 Node Name Requirements
>> + * node-name@unit-address
>> + * 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
>> + */
>> +#define FDT_NODE_NAME_MAX_SIZE  (49)
>> +
>> +#define ARG_SHIFT(argc, argv) \
>> +  do { \
>> +    (argc)--; \
>> +    (argv)++; \
>> +  } while (0)
>> +
>> +struct compat_string_struct
>> +{
>> +  grub_size_t size;
>> +  const char *compat_string;
>> +};
>> +typedef struct compat_string_struct compat_string_struct_t;
>> +#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
>> +
>> +enum module_type
>> +{
>> +  MODULE_IMAGE,
>> +  MODULE_INITRD,
>> +  MODULE_XSM,
>> +  MODULE_CUSTOM
>> +};
>> +typedef enum module_type module_type_t;
>> +
>> +struct fdt_node_info
>> +{
>> +  module_type_t type;
>> +
>> +  const char *compat_string;
>> +  grub_size_t compat_string_size;
>> +};
>> +
>> +struct xen_hypervisor_header
>> +{
>> +  struct grub_arm64_linux_kernel_header efi_head;
>> +
>> +  /* This is always PE\0\0.  */
>> +  grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
>> +  /* The COFF file header.  */
>> +  struct grub_pe32_coff_header coff_header;
>> +  /* The Optional header.  */
>> +  struct grub_pe64_optional_header optional_header;
>> +};
>> +
>> +struct xen_boot_binary
>> +{
>> +  struct xen_boot_binary *next;
>> +  struct xen_boot_binary **prev;
>> +  const char *name;
>> +
>> +  grub_addr_t start;
>> +  grub_size_t size;
>> +  grub_size_t align;
>> +
>> +  char *cmdline;
>> +  int cmdline_size;
>> +
>> +  struct fdt_node_info node_info;
>> +};
>> +
>> +static grub_dl_t my_mod;
>> +
>> +static struct xen_boot_binary *xen_hypervisor;
>> +static struct xen_boot_binary *module_head;
>> +static const grub_size_t module_default_align[] = {
>> +  MODULE_IMAGE_MIN_ALIGN,
>> +  MODULE_INITRD_MIN_ALIGN,
>> +  MODULE_XSM_MIN_ALIGN,
>> +  MODULE_CUSTOM_MIN_ALIGN
>> +};
>> +
>> +static void *xen_boot_fdt;
>> +static const compat_string_struct_t default_compat_string[] = {
>> +  FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
>> +  FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
>> +  FDT_COMPATIBLE (MODULE_XSM_COMPATIBLE),
>> +  FDT_COMPATIBLE (MODULE_CUSTOM_COMPATIBLE)
>> +};
>> +
>> +static __inline grub_addr_t
>> +xen_boot_address_align (grub_addr_t start, grub_size_t align)
>> +{
>> +  return (align ? (ALIGN_UP (start, align)) : start);
>> +}
>> +
>> +/* Parse the option of xen_module command. For now, we support
>> +   (1) --type <the compatible stream>
>> +   We also set up the type of module in this function.
>> +   If there are some "--type" options in the command line,
>> +   we make a custom compatible stream in this function. */
>> +static grub_err_t
>> +set_module_type (grub_command_t cmd, struct xen_boot_binary *module,
>> +              int argc, char *argv[], int *file_name_index)
>> +{
>> +  char **compat_string_temp_array;
>> +  grub_size_t total_size = 0;
>> +  int num_types = 0, i;
>> +  char *temp = NULL;
>> +
>> +  *file_name_index = 0;
>> +
>> +  if (!grub_strcmp (cmd->name, "xen_linux"))
>> +    module->node_info.type = MODULE_IMAGE;
>> +  else if (!grub_strcmp (cmd->name, "xen_initrd"))
>> +    module->node_info.type = MODULE_INITRD;
>> +  else if (!grub_strcmp (cmd->name, "xen_xsm"))
>> +    module->node_info.type = MODULE_XSM;
>> +  else if (!grub_strcmp (cmd->name, "xen_module"))
>> +    module->node_info.type = MODULE_CUSTOM;
>> +
>> +  /* if there are some options we need to process. */
>> +  if (module->node_info.type == MODULE_CUSTOM)
>> +    {
>> +      compat_string_temp_array =
>> +     (char **) grub_zalloc (sizeof (char *) * argc);
>> +      if (!compat_string_temp_array)
>> +     return grub_errno;
>> +      /* the module type is set by "--type"(MODULE_CUSTOM) */
>> +      while (argc > 2 && !grub_strcmp (argv[0], "--type"))
>> +     {
>> +       module->node_info.type = MODULE_CUSTOM;
>> +       ARG_SHIFT (argc, argv);
>> +       total_size += grub_strlen (argv[0]) + 1;
>> +       compat_string_temp_array[num_types++] = argv[0];
>> +       ARG_SHIFT (argc, argv);
>> +       (*file_name_index) += 2;
>> +     }
>> +
>> +      if (total_size)
>> +     {
>> +       module->node_info.compat_string = temp =
>> +         (char *) grub_zalloc (total_size);
>> +       if (!temp)
>> +         {
>> +           grub_free (compat_string_temp_array);
>> +           return grub_errno;
>> +         }
>> +
>> +       module->node_info.compat_string_size = total_size;
>> +       for (i = 0; num_types > 0; num_types--, i++, temp++)
>> +         {
>> +           grub_strcpy (temp, compat_string_temp_array[i]);
>> +           temp += grub_strlen (compat_string_temp_array[i]);
>> +         }
>> +     }
>> +      else
>> +     {
>> +       module->node_info.compat_string =
>> +         default_compat_string[MODULE_CUSTOM].compat_string;
>> +       module->node_info.compat_string_size =
>> +         default_compat_string[MODULE_CUSTOM].size;
>> +     }
>> +
>> +      grub_free (compat_string_temp_array);
>> +    }
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +prepare_xen_hypervisor_params (void)
>> +{
>> +  int chosen_node = 0;
>> +  int retval;
>> +
>> +  xen_boot_fdt = grub_linux_get_fdt ();
>> +  if (!xen_boot_fdt)
>> +    return grub_error (GRUB_ERR_IO, "failed to get FDT");
>> +
>> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 0)
>> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 1)
>> +    return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
>> +
>> +  grub_dprintf ("xen_loader",
>> +             "Xen Hypervisor cmdline : %s @ %p size:%d\n",
>> +             xen_hypervisor->cmdline, xen_hypervisor->cmdline,
>> +             xen_hypervisor->cmdline_size);
>> +
>> +  retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
>> +                           xen_hypervisor->cmdline,
>> +                           xen_hypervisor->cmdline_size);
>> +  if (retval)
>> +    return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +prepare_xen_module_params (struct xen_boot_binary *module)
>> +{
>> +  int retval, chosen_node = 0, module_node = 0;
>> +  char module_name[FDT_NODE_NAME_MAX_SIZE];
>> +
>> +  retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
>> +                       xen_boot_address_align (module->start,
>> +                                               module->align));
>> +  grub_dprintf ("xen_loader", "Module node name %s \n", module_name);
>> +
>> +  if (retval < (int) sizeof ("module@"))
>> +    return grub_error (GRUB_ERR_IO, N_("failed to get FDT"));
>> +
>> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 0)
>> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 1)
>> +    return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
>> +
>> +  module_node =
>> +    grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
>> +  if (module_node < 0)
>> +    module_node =
>> +      grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
>> +
>> +  retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
>> +                           module->node_info.compat_string,
>> +                           (grub_uint32_t) module->
>> +                           node_info.compat_string_size);
>> +  if (retval)
>> +    return grub_error (GRUB_ERR_IO, N_("failed to update FDT"));
>> +
>> +  grub_dprintf ("xen_loader", "Module %s compatible = %s size = 0x%lx\n",
>> +             module->name, module->node_info.compat_string,
>> +             module->node_info.compat_string_size);
>> +
>> +  retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
>> +                            xen_boot_address_align (module->start,
>> +                                                    module->align),
>> +                            module->size);
>> +  if (retval)
>> +    return grub_error (GRUB_ERR_IO, N_("failed to update FDT"));
>> +
>> +  if (module->cmdline && module->cmdline_size > 0)
>> +    {
>> +      grub_dprintf ("xen_loader",
>> +                 "Module %s cmdline : %s @ %p size:%d\n", module->name,
>> +                 module->cmdline, module->cmdline, module->cmdline_size);
>> +
>> +      retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
>> +                               module->cmdline, module->cmdline_size + 1);
>> +      if (retval)
>> +     return grub_error (GRUB_ERR_IO, "failed to update FDT");
>> +    }
>> +  else
>> +    {
>> +      grub_dprintf ("xen_loader", "Module %s has not bootargs!\n",
>> +                 module->name);
>> +    }
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +install_all_params (void)
>> +{
>> +  grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
>> +  grub_efi_boot_services_t *b;
>> +  grub_efi_status_t status;
>> +
>> +  b = grub_efi_system_table->boot_services;
>> +  status = b->install_configuration_table (&fdt_guid, xen_boot_fdt);
>> +  if (status != GRUB_EFI_SUCCESS)
>> +    return grub_error (GRUB_ERR_IO, "failed to install FDT");
>> +
>> +  grub_dprintf ("xen_loader",
>> +             "Installed/updated FDT configuration table @ %p\n",
>> +             xen_boot_fdt);
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +clean_all_params (void)
>> +{
>> +  if (xen_boot_fdt)
>> +    {
>> +      grub_efi_free_pages ((grub_efi_physical_address_t) xen_boot_fdt,
>> +                        BYTES_TO_PAGES (grub_fdt_get_totalsize
>> +                                        (xen_boot_fdt)));
>> +      xen_boot_fdt = NULL;
>> +    }
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +finalize_params_xen_boot (void)
>> +{
>> +  struct xen_boot_binary *module;
>> +
>> +  if (xen_hypervisor)
>> +    {
>> +      if (prepare_xen_hypervisor_params () != GRUB_ERR_NONE)
>> +     goto fail;
>> +    }
>> +  else
>> +    {
>> +      grub_dprintf ("xen_loader", "Failed to get Xen Hypervisor info!\n");
>> +      goto fail;
>> +    }
>> +
>> +  /* Set module params info */
>> +  FOR_LIST_ELEMENTS (module, module_head)
>> +  {
>> +    if (module->start && module->size > 0)
>> +      {
>> +     grub_dprintf ("xen_loader", "Module %s @ 0x%lx size:0x%lx\n",
>> +                   module->name,
>> +                   xen_boot_address_align (module->start, module->align),
>> +                   module->size);
>> +     if (prepare_xen_module_params (module) != GRUB_ERR_NONE)
>> +       goto fail;
>> +      }
>> +    else
>> +      {
>> +     grub_dprintf ("xen_loader", "Module info error: %s!\n", module->name);
>> +     goto fail;
>> +      }
>> +  }
>> +
>> +  if (install_all_params () == GRUB_ERR_NONE)
>> +    return GRUB_ERR_NONE;
>> +
>> +fail:
>> +  clean_all_params ();
>> +
>> +  return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
>> +}
>> +
>> +
>> +static grub_err_t
>> +xen_boot (void)
>> +{
>> +  grub_err_t err = finalize_params_xen_boot ();
>> +  if (err)
>> +    return err;
>> +
>> +  return grub_arm64_uefi_boot_image (xen_hypervisor->start,
>> +                                  xen_hypervisor->size,
>> +                                  xen_hypervisor->cmdline);
>> +}
>> +
>> +static void
>> +single_binary_unload (struct xen_boot_binary *binary)
>> +{
>> +  if (!binary)
>> +    return;
>> +
>> +  if (binary->start && binary->size > 0)
>> +    {
>> +      grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
>> +                        BYTES_TO_PAGES (binary->size + binary->align));
>> +    }
>> +
>> +  if (binary->cmdline && binary->cmdline_size > 0)
>> +    {
>> +      grub_free (binary->cmdline);
>> +      grub_dprintf ("xen_loader",
>> +                 "Module %s cmdline memory free @ %p size: %d\n",
>> +                 binary->name, binary->cmdline, binary->cmdline_size);
>> +    }
>> +
>> +  if (binary->node_info.type == MODULE_CUSTOM)
>> +    grub_free ((void *) binary->node_info.compat_string);
>> +
>> +  if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
>> +    grub_list_remove (GRUB_AS_LIST (binary));
>> +
>> +  grub_dprintf ("xen_loader",
>> +             "Module %s struct memory free @ %p size: 0x%lx\n",
>> +             binary->name, binary, sizeof (binary));
>> +  grub_free (binary);
>> +
>> +  return;
>> +}
>> +
>> +static void
>> +all_binaries_unload (void)
>> +{
>> +  struct xen_boot_binary *binary;
>> +
>> +  FOR_LIST_ELEMENTS (binary, module_head)
>> +  {
>> +    single_binary_unload (binary);
>> +  }
>> +
>> +  if (xen_hypervisor)
>> +    single_binary_unload (xen_hypervisor);
>> +
>> +  return;
>> +}
>> +
>> +static grub_err_t
>> +xen_unload (void)
>> +{
>> +  grub_linux_set_loaded (0);
>> +  all_binaries_unload ();
>> +  clean_all_params ();
>> +  grub_dl_unref (my_mod);
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static void
>> +xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
>> +                   int argc, char *argv[])
>> +{
>> +  binary->size = grub_file_size (file);
>> +  grub_dprintf ("xen_loader", "Xen_boot %s file size: 0x%lx\n",
>> +             binary->name, binary->size);
>> +
>> +  binary->start = (grub_addr_t) grub_efi_allocate_pages (0,
>> +                                                      (BYTES_TO_PAGES
>> +                                                       (binary->size +
>> +                                                        binary->align)));
>> +  if (!binary->start)
>> +    {
>> +      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>> +      return;
>> +    }
>> +
>> +  grub_dprintf ("xen_loader", "Xen_boot %s numpages: 0x%lx\n",
>> +             binary->name, BYTES_TO_PAGES (binary->size + binary->align));
>> +
>> +  if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
>> +                                                          binary->align),
>> +                   binary->size) != (grub_ssize_t) binary->size)
>> +    {
>> +      single_binary_unload (binary);
>> +      grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
>> +      return;
>> +    }
>> +
>> +  if (argc > 1)
>> +    {
>> +      binary->cmdline_size = grub_loader_cmdline_size (argc - 1, argv + 1);
>> +      binary->cmdline = grub_zalloc (binary->cmdline_size);
>> +      if (!binary->cmdline)
>> +     {
>> +       single_binary_unload (binary);
>> +       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>> +       return;
>> +     }
>> +      grub_create_loader_cmdline (argc - 1, argv + 1, binary->cmdline,
>> +                               binary->cmdline_size);
>> +      grub_dprintf ("xen_loader",
>> +                 "Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
>> +                 binary->cmdline, binary->cmdline, binary->cmdline_size);
>> +    }
>> +  else
>> +    {
>> +      binary->cmdline_size = 0;
>> +      binary->cmdline = NULL;
>> +    }
>> +
>> +  grub_errno = GRUB_ERR_NONE;
>> +  return;
>> +}
>> +
>> +static grub_err_t
>> +grub_cmd_xen_module (grub_command_t cmd, int argc, char *argv[])
>> +{
>> +
>> +  struct xen_boot_binary *module = NULL;
>> +  int file_name_index = 0;
>> +  grub_file_t file = 0;
>> +
>> +  if (!argc)
>> +    {
>> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
>> +      goto fail;
>> +    }
>> +
>> +  if (!grub_linux_get_loaded ())
>> +    {
>> +      grub_error (GRUB_ERR_BAD_ARGUMENT,
>> +               N_("you need to load the Xen Hypervisor first"));
>> +      goto fail;
>> +    }
>> +
>> +  module =
>> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
>> +  if (!module)
>> +    return grub_errno;
>> +
>> +  /* process all the options and get module type */
>> +  if (set_module_type (cmd, module, argc, argv, &file_name_index) !=
>> +      GRUB_ERR_NONE)
>> +    goto fail;
>> +  switch (module->node_info.type)
>> +    {
>> +    case MODULE_IMAGE:
>> +    case MODULE_INITRD:
>> +    case MODULE_XSM:
>> +      module->node_info.compat_string =
>> +     default_compat_string[module->node_info.type].compat_string;
>> +      module->node_info.compat_string_size =
>> +     default_compat_string[module->node_info.type].size;
>> +      break;
>> +
>> +    case MODULE_CUSTOM:
>> +      /* we have set the node_info in set_module_type */
>> +      break;
>> +
>> +    default:
>> +      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
>> +    }
>> +  module->name = module->node_info.compat_string;
>> +  module->align = module_default_align[module->node_info.type];
>> +
>> +  grub_dprintf ("xen_loader", "Init %s module and node info:\n"
>> +             "compatible %s\ncompat_string_size 0x%lx\n",
>> +             module->name, module->node_info.compat_string,
>> +             module->node_info.compat_string_size);
>> +
>> +  file = grub_file_open (argv[file_name_index]);
>> +  if (!file)
>> +    goto fail;
>> +
>> +  xen_boot_binary_load (module, file, argc - file_name_index,
>> +                     argv + file_name_index);
>> +  if (grub_errno == GRUB_ERR_NONE)
>> +    grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
>> +
>> +fail:
>> +  if (file)
>> +    grub_file_close (file);
>> +  if (grub_errno != GRUB_ERR_NONE)
>> +    single_binary_unload (module);
>> +
>> +  return grub_errno;
>> +}
>> +
>> +static grub_err_t
>> +grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
>> +                      int argc, char *argv[])
>> +{
>> +  struct xen_hypervisor_header sh;
>> +  grub_file_t file = NULL;
>> +
>> +  grub_dl_ref (my_mod);
>> +
>> +  if (!argc)
>> +    {
>> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
>> +      goto fail;
>> +    }
>> +
>> +  file = grub_file_open (argv[0]);
>> +  if (!file)
>> +    goto fail;
>> +
>> +  if (grub_file_read (file, &sh, sizeof (sh)) != (long) sizeof (sh))
>> +    goto fail;
>> +  if (grub_arm64_uefi_check_image
>> +      ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
>> +    goto fail;
>> +  grub_file_seek (file, 0);
>> +
>> +  /* if another module has called grub_loader_set,
>> +     we need to make sure that another module is unloaded properly */
>> +  grub_loader_unset ();
>> +
>> +  xen_hypervisor =
>> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
>> +  if (!xen_hypervisor)
>> +    return grub_errno;
>> +
>> +  xen_hypervisor->name = XEN_HYPERVISOR_NAME;
>> +  xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
>> +
>> +  xen_boot_binary_load (xen_hypervisor, file, argc, argv);
>> +  if (grub_errno == GRUB_ERR_NONE)
>> +    {
>> +      grub_loader_set (xen_boot, xen_unload, 0);
>> +      grub_linux_set_loaded (1);
>> +    }
>> +
>> +fail:
>> +  if (file)
>> +    grub_file_close (file);
>> +  if (grub_errno != GRUB_ERR_NONE)
>> +    {
>> +      grub_linux_set_loaded (0);
>> +      all_binaries_unload ();
>> +      grub_dl_unref (my_mod);
>> +    }
>> +
>> +  return grub_errno;
>> +}
>> +
>> +static grub_command_t cmd_xen_hypervisor, cmd_xen_module;
>> +static grub_command_t cmd_xen_linux, cmd_xen_initrd, cmd_xen_xsm;
>> +
>> +GRUB_MOD_INIT (xen_boot)
>> +{
>> +  cmd_xen_hypervisor =
>> +    grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
>> +                        N_("Load a xen hypervisor."));
>> +  cmd_xen_linux =
>> +    grub_register_command ("xen_linux", grub_cmd_xen_module, 0,
>> +                        N_("Load a xen linux kernel for dom0."));
>> +  cmd_xen_initrd =
>> +    grub_register_command ("xen_initrd", grub_cmd_xen_module, 0,
>> +                        N_("Load a xen initrd for dom0."));
>> +  cmd_xen_xsm =
>> +    grub_register_command ("xen_xsm", grub_cmd_xen_module, 0,
>> +                        N_("Load a xen security module."));
>> +  cmd_xen_module =
>> +    grub_register_command ("xen_module", grub_cmd_xen_module, 0,
>> +                        N_("Load a xen module."));
>> +  my_mod = mod;
>> +}
>> +
>> +GRUB_MOD_FINI (xen_boot)
>> +{
>> +  grub_unregister_command (cmd_xen_hypervisor);
>> +  grub_unregister_command (cmd_xen_linux);
>> +  grub_unregister_command (cmd_xen_initrd);
>> +  grub_unregister_command (cmd_xen_xsm);
>> +  grub_unregister_command (cmd_xen_module);
>> +}
>>
>
>



-- 
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

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 2/4] arm64: Add xen_boot module file
@ 2015-10-30  8:08         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-10-30  8:08 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Andrei Borzenkov, Jon Masters, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List

Hi Vladimir,

yes, Thanks for your modification :-)

I just follow the xen boot protocol :
http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot

xen_module is just for "--type" option, I will discuss this with Xen
developer for this.
If we need this option, I will resubmit  it :-)

Great thanks!

On 29 October 2015 at 22:27, Vladimir 'φ-coder/phcoder' Serbinenko
<phcoder@gmail.com> wrote:
> Committed without the xen_module command. Its argument parsing was
> non-trivial and I don't quite get what its intent is. Can you resubmit?
> On 23.07.2015 07:16, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> grub-core/loader/arm64/xen_boot.c
>>
>>   - This adds support for the Xen boot on ARM specification for arm64.
>>   - Introduce xen_hypervisor, xen_linux, xen_initrd and xen_xsm
>>     to load different binaries for xen boot;
>>     Introduce xen_module to load common or custom module for xen boot.
>>   - This Xen boot support is a separated  module for aarch64,
>>     but reuse the existing code of devicetree in linux module.
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  grub-core/Makefile.core.def       |   7 +
>>  grub-core/loader/arm64/xen_boot.c | 685 ++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 692 insertions(+)
>>
>> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
>> index a6101de..796f7e9 100644
>> --- a/grub-core/Makefile.core.def
>> +++ b/grub-core/Makefile.core.def
>> @@ -1648,6 +1648,13 @@ module = {
>>  };
>>
>>  module = {
>> +  name = xen_boot;
>> +  common = lib/cmdline.c;
>> +  arm64 = loader/arm64/xen_boot.c;
>> +  enable = arm64;
>> +};
>> +
>> +module = {
>>    name = linux;
>>    x86 = loader/i386/linux.c;
>>    xen = loader/i386/xen.c;
>> diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
>> new file mode 100644
>> index 0000000..33a65dd
>> --- /dev/null
>> +++ b/grub-core/loader/arm64/xen_boot.c
>> @@ -0,0 +1,685 @@
>> +/*
>> + *  GRUB  --  GRand Unified Bootloader
>> + *  Copyright (C) 2014  Free Software Foundation, Inc.
>> + *
>> + *  GRUB is free software: you can redistribute it and/or modify
>> + *  it under the terms of the GNU General Public License as published by
>> + *  the Free Software Foundation, either version 3 of the License, or
>> + *  (at your option) any later version.
>> + *
>> + *  GRUB 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.
>> + *
>> + *  You should have received a copy of the GNU General Public License
>> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <grub/cache.h>
>> +#include <grub/charset.h>
>> +#include <grub/command.h>
>> +#include <grub/err.h>
>> +#include <grub/file.h>
>> +#include <grub/fdt.h>
>> +#include <grub/linux.h>
>> +#include <grub/list.h>
>> +#include <grub/loader.h>
>> +#include <grub/misc.h>
>> +#include <grub/mm.h>
>> +#include <grub/types.h>
>> +#include <grub/cpu/linux.h>
>> +#include <grub/efi/efi.h>
>> +#include <grub/efi/pe32.h>   /* required by struct xen_hypervisor_header */
>> +#include <grub/i18n.h>
>> +#include <grub/lib/cmdline.h>
>> +
>> +GRUB_MOD_LICENSE ("GPLv3+");
>> +
>> +#define XEN_HYPERVISOR_NAME  "xen_hypervisor"
>> +
>> +#define MODULE_DEFAULT_ALIGN  (0x0)
>> +#define MODULE_IMAGE_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +#define MODULE_INITRD_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +#define MODULE_XSM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +#define MODULE_CUSTOM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>> +
>> +/* #define MODULE_IMAGE_COMPATIBLE  "xen,linux-image\0xen,module"
>> +#define MODULE_INITRD_COMPATIBLE  "xen,linux-image\0xen,module"
>> +#define MODULE_XSM_COMPATIBLE  "xen,xsm-policy\0xen,module"
>> +#define MODULE_CUSTOM_COMPATIBLE  "xen,module" */
>> +#define MODULE_IMAGE_COMPATIBLE  "multiboot,kernel\0multiboot,module"
>> +#define MODULE_INITRD_COMPATIBLE  "multiboot,ramdisk\0multiboot,module"
>> +#define MODULE_XSM_COMPATIBLE  "xen,xsm-policy\0multiboot,module"
>> +#define MODULE_CUSTOM_COMPATIBLE  "multiboot,module"
>> +
>> +/* This maximum size is defined in Power.org ePAPR V1.1
>> + * https://www.power.org/documentation/epapr-version-1-1/
>> + * 2.2.1.1 Node Name Requirements
>> + * node-name@unit-address
>> + * 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
>> + */
>> +#define FDT_NODE_NAME_MAX_SIZE  (49)
>> +
>> +#define ARG_SHIFT(argc, argv) \
>> +  do { \
>> +    (argc)--; \
>> +    (argv)++; \
>> +  } while (0)
>> +
>> +struct compat_string_struct
>> +{
>> +  grub_size_t size;
>> +  const char *compat_string;
>> +};
>> +typedef struct compat_string_struct compat_string_struct_t;
>> +#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
>> +
>> +enum module_type
>> +{
>> +  MODULE_IMAGE,
>> +  MODULE_INITRD,
>> +  MODULE_XSM,
>> +  MODULE_CUSTOM
>> +};
>> +typedef enum module_type module_type_t;
>> +
>> +struct fdt_node_info
>> +{
>> +  module_type_t type;
>> +
>> +  const char *compat_string;
>> +  grub_size_t compat_string_size;
>> +};
>> +
>> +struct xen_hypervisor_header
>> +{
>> +  struct grub_arm64_linux_kernel_header efi_head;
>> +
>> +  /* This is always PE\0\0.  */
>> +  grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
>> +  /* The COFF file header.  */
>> +  struct grub_pe32_coff_header coff_header;
>> +  /* The Optional header.  */
>> +  struct grub_pe64_optional_header optional_header;
>> +};
>> +
>> +struct xen_boot_binary
>> +{
>> +  struct xen_boot_binary *next;
>> +  struct xen_boot_binary **prev;
>> +  const char *name;
>> +
>> +  grub_addr_t start;
>> +  grub_size_t size;
>> +  grub_size_t align;
>> +
>> +  char *cmdline;
>> +  int cmdline_size;
>> +
>> +  struct fdt_node_info node_info;
>> +};
>> +
>> +static grub_dl_t my_mod;
>> +
>> +static struct xen_boot_binary *xen_hypervisor;
>> +static struct xen_boot_binary *module_head;
>> +static const grub_size_t module_default_align[] = {
>> +  MODULE_IMAGE_MIN_ALIGN,
>> +  MODULE_INITRD_MIN_ALIGN,
>> +  MODULE_XSM_MIN_ALIGN,
>> +  MODULE_CUSTOM_MIN_ALIGN
>> +};
>> +
>> +static void *xen_boot_fdt;
>> +static const compat_string_struct_t default_compat_string[] = {
>> +  FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
>> +  FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
>> +  FDT_COMPATIBLE (MODULE_XSM_COMPATIBLE),
>> +  FDT_COMPATIBLE (MODULE_CUSTOM_COMPATIBLE)
>> +};
>> +
>> +static __inline grub_addr_t
>> +xen_boot_address_align (grub_addr_t start, grub_size_t align)
>> +{
>> +  return (align ? (ALIGN_UP (start, align)) : start);
>> +}
>> +
>> +/* Parse the option of xen_module command. For now, we support
>> +   (1) --type <the compatible stream>
>> +   We also set up the type of module in this function.
>> +   If there are some "--type" options in the command line,
>> +   we make a custom compatible stream in this function. */
>> +static grub_err_t
>> +set_module_type (grub_command_t cmd, struct xen_boot_binary *module,
>> +              int argc, char *argv[], int *file_name_index)
>> +{
>> +  char **compat_string_temp_array;
>> +  grub_size_t total_size = 0;
>> +  int num_types = 0, i;
>> +  char *temp = NULL;
>> +
>> +  *file_name_index = 0;
>> +
>> +  if (!grub_strcmp (cmd->name, "xen_linux"))
>> +    module->node_info.type = MODULE_IMAGE;
>> +  else if (!grub_strcmp (cmd->name, "xen_initrd"))
>> +    module->node_info.type = MODULE_INITRD;
>> +  else if (!grub_strcmp (cmd->name, "xen_xsm"))
>> +    module->node_info.type = MODULE_XSM;
>> +  else if (!grub_strcmp (cmd->name, "xen_module"))
>> +    module->node_info.type = MODULE_CUSTOM;
>> +
>> +  /* if there are some options we need to process. */
>> +  if (module->node_info.type == MODULE_CUSTOM)
>> +    {
>> +      compat_string_temp_array =
>> +     (char **) grub_zalloc (sizeof (char *) * argc);
>> +      if (!compat_string_temp_array)
>> +     return grub_errno;
>> +      /* the module type is set by "--type"(MODULE_CUSTOM) */
>> +      while (argc > 2 && !grub_strcmp (argv[0], "--type"))
>> +     {
>> +       module->node_info.type = MODULE_CUSTOM;
>> +       ARG_SHIFT (argc, argv);
>> +       total_size += grub_strlen (argv[0]) + 1;
>> +       compat_string_temp_array[num_types++] = argv[0];
>> +       ARG_SHIFT (argc, argv);
>> +       (*file_name_index) += 2;
>> +     }
>> +
>> +      if (total_size)
>> +     {
>> +       module->node_info.compat_string = temp =
>> +         (char *) grub_zalloc (total_size);
>> +       if (!temp)
>> +         {
>> +           grub_free (compat_string_temp_array);
>> +           return grub_errno;
>> +         }
>> +
>> +       module->node_info.compat_string_size = total_size;
>> +       for (i = 0; num_types > 0; num_types--, i++, temp++)
>> +         {
>> +           grub_strcpy (temp, compat_string_temp_array[i]);
>> +           temp += grub_strlen (compat_string_temp_array[i]);
>> +         }
>> +     }
>> +      else
>> +     {
>> +       module->node_info.compat_string =
>> +         default_compat_string[MODULE_CUSTOM].compat_string;
>> +       module->node_info.compat_string_size =
>> +         default_compat_string[MODULE_CUSTOM].size;
>> +     }
>> +
>> +      grub_free (compat_string_temp_array);
>> +    }
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +prepare_xen_hypervisor_params (void)
>> +{
>> +  int chosen_node = 0;
>> +  int retval;
>> +
>> +  xen_boot_fdt = grub_linux_get_fdt ();
>> +  if (!xen_boot_fdt)
>> +    return grub_error (GRUB_ERR_IO, "failed to get FDT");
>> +
>> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 0)
>> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 1)
>> +    return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
>> +
>> +  grub_dprintf ("xen_loader",
>> +             "Xen Hypervisor cmdline : %s @ %p size:%d\n",
>> +             xen_hypervisor->cmdline, xen_hypervisor->cmdline,
>> +             xen_hypervisor->cmdline_size);
>> +
>> +  retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
>> +                           xen_hypervisor->cmdline,
>> +                           xen_hypervisor->cmdline_size);
>> +  if (retval)
>> +    return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +prepare_xen_module_params (struct xen_boot_binary *module)
>> +{
>> +  int retval, chosen_node = 0, module_node = 0;
>> +  char module_name[FDT_NODE_NAME_MAX_SIZE];
>> +
>> +  retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
>> +                       xen_boot_address_align (module->start,
>> +                                               module->align));
>> +  grub_dprintf ("xen_loader", "Module node name %s \n", module_name);
>> +
>> +  if (retval < (int) sizeof ("module@"))
>> +    return grub_error (GRUB_ERR_IO, N_("failed to get FDT"));
>> +
>> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 0)
>> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
>> +  if (chosen_node < 1)
>> +    return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
>> +
>> +  module_node =
>> +    grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
>> +  if (module_node < 0)
>> +    module_node =
>> +      grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
>> +
>> +  retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
>> +                           module->node_info.compat_string,
>> +                           (grub_uint32_t) module->
>> +                           node_info.compat_string_size);
>> +  if (retval)
>> +    return grub_error (GRUB_ERR_IO, N_("failed to update FDT"));
>> +
>> +  grub_dprintf ("xen_loader", "Module %s compatible = %s size = 0x%lx\n",
>> +             module->name, module->node_info.compat_string,
>> +             module->node_info.compat_string_size);
>> +
>> +  retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
>> +                            xen_boot_address_align (module->start,
>> +                                                    module->align),
>> +                            module->size);
>> +  if (retval)
>> +    return grub_error (GRUB_ERR_IO, N_("failed to update FDT"));
>> +
>> +  if (module->cmdline && module->cmdline_size > 0)
>> +    {
>> +      grub_dprintf ("xen_loader",
>> +                 "Module %s cmdline : %s @ %p size:%d\n", module->name,
>> +                 module->cmdline, module->cmdline, module->cmdline_size);
>> +
>> +      retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
>> +                               module->cmdline, module->cmdline_size + 1);
>> +      if (retval)
>> +     return grub_error (GRUB_ERR_IO, "failed to update FDT");
>> +    }
>> +  else
>> +    {
>> +      grub_dprintf ("xen_loader", "Module %s has not bootargs!\n",
>> +                 module->name);
>> +    }
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +install_all_params (void)
>> +{
>> +  grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
>> +  grub_efi_boot_services_t *b;
>> +  grub_efi_status_t status;
>> +
>> +  b = grub_efi_system_table->boot_services;
>> +  status = b->install_configuration_table (&fdt_guid, xen_boot_fdt);
>> +  if (status != GRUB_EFI_SUCCESS)
>> +    return grub_error (GRUB_ERR_IO, "failed to install FDT");
>> +
>> +  grub_dprintf ("xen_loader",
>> +             "Installed/updated FDT configuration table @ %p\n",
>> +             xen_boot_fdt);
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +clean_all_params (void)
>> +{
>> +  if (xen_boot_fdt)
>> +    {
>> +      grub_efi_free_pages ((grub_efi_physical_address_t) xen_boot_fdt,
>> +                        BYTES_TO_PAGES (grub_fdt_get_totalsize
>> +                                        (xen_boot_fdt)));
>> +      xen_boot_fdt = NULL;
>> +    }
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +finalize_params_xen_boot (void)
>> +{
>> +  struct xen_boot_binary *module;
>> +
>> +  if (xen_hypervisor)
>> +    {
>> +      if (prepare_xen_hypervisor_params () != GRUB_ERR_NONE)
>> +     goto fail;
>> +    }
>> +  else
>> +    {
>> +      grub_dprintf ("xen_loader", "Failed to get Xen Hypervisor info!\n");
>> +      goto fail;
>> +    }
>> +
>> +  /* Set module params info */
>> +  FOR_LIST_ELEMENTS (module, module_head)
>> +  {
>> +    if (module->start && module->size > 0)
>> +      {
>> +     grub_dprintf ("xen_loader", "Module %s @ 0x%lx size:0x%lx\n",
>> +                   module->name,
>> +                   xen_boot_address_align (module->start, module->align),
>> +                   module->size);
>> +     if (prepare_xen_module_params (module) != GRUB_ERR_NONE)
>> +       goto fail;
>> +      }
>> +    else
>> +      {
>> +     grub_dprintf ("xen_loader", "Module info error: %s!\n", module->name);
>> +     goto fail;
>> +      }
>> +  }
>> +
>> +  if (install_all_params () == GRUB_ERR_NONE)
>> +    return GRUB_ERR_NONE;
>> +
>> +fail:
>> +  clean_all_params ();
>> +
>> +  return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
>> +}
>> +
>> +
>> +static grub_err_t
>> +xen_boot (void)
>> +{
>> +  grub_err_t err = finalize_params_xen_boot ();
>> +  if (err)
>> +    return err;
>> +
>> +  return grub_arm64_uefi_boot_image (xen_hypervisor->start,
>> +                                  xen_hypervisor->size,
>> +                                  xen_hypervisor->cmdline);
>> +}
>> +
>> +static void
>> +single_binary_unload (struct xen_boot_binary *binary)
>> +{
>> +  if (!binary)
>> +    return;
>> +
>> +  if (binary->start && binary->size > 0)
>> +    {
>> +      grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
>> +                        BYTES_TO_PAGES (binary->size + binary->align));
>> +    }
>> +
>> +  if (binary->cmdline && binary->cmdline_size > 0)
>> +    {
>> +      grub_free (binary->cmdline);
>> +      grub_dprintf ("xen_loader",
>> +                 "Module %s cmdline memory free @ %p size: %d\n",
>> +                 binary->name, binary->cmdline, binary->cmdline_size);
>> +    }
>> +
>> +  if (binary->node_info.type == MODULE_CUSTOM)
>> +    grub_free ((void *) binary->node_info.compat_string);
>> +
>> +  if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
>> +    grub_list_remove (GRUB_AS_LIST (binary));
>> +
>> +  grub_dprintf ("xen_loader",
>> +             "Module %s struct memory free @ %p size: 0x%lx\n",
>> +             binary->name, binary, sizeof (binary));
>> +  grub_free (binary);
>> +
>> +  return;
>> +}
>> +
>> +static void
>> +all_binaries_unload (void)
>> +{
>> +  struct xen_boot_binary *binary;
>> +
>> +  FOR_LIST_ELEMENTS (binary, module_head)
>> +  {
>> +    single_binary_unload (binary);
>> +  }
>> +
>> +  if (xen_hypervisor)
>> +    single_binary_unload (xen_hypervisor);
>> +
>> +  return;
>> +}
>> +
>> +static grub_err_t
>> +xen_unload (void)
>> +{
>> +  grub_linux_set_loaded (0);
>> +  all_binaries_unload ();
>> +  clean_all_params ();
>> +  grub_dl_unref (my_mod);
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static void
>> +xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
>> +                   int argc, char *argv[])
>> +{
>> +  binary->size = grub_file_size (file);
>> +  grub_dprintf ("xen_loader", "Xen_boot %s file size: 0x%lx\n",
>> +             binary->name, binary->size);
>> +
>> +  binary->start = (grub_addr_t) grub_efi_allocate_pages (0,
>> +                                                      (BYTES_TO_PAGES
>> +                                                       (binary->size +
>> +                                                        binary->align)));
>> +  if (!binary->start)
>> +    {
>> +      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>> +      return;
>> +    }
>> +
>> +  grub_dprintf ("xen_loader", "Xen_boot %s numpages: 0x%lx\n",
>> +             binary->name, BYTES_TO_PAGES (binary->size + binary->align));
>> +
>> +  if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
>> +                                                          binary->align),
>> +                   binary->size) != (grub_ssize_t) binary->size)
>> +    {
>> +      single_binary_unload (binary);
>> +      grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
>> +      return;
>> +    }
>> +
>> +  if (argc > 1)
>> +    {
>> +      binary->cmdline_size = grub_loader_cmdline_size (argc - 1, argv + 1);
>> +      binary->cmdline = grub_zalloc (binary->cmdline_size);
>> +      if (!binary->cmdline)
>> +     {
>> +       single_binary_unload (binary);
>> +       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>> +       return;
>> +     }
>> +      grub_create_loader_cmdline (argc - 1, argv + 1, binary->cmdline,
>> +                               binary->cmdline_size);
>> +      grub_dprintf ("xen_loader",
>> +                 "Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
>> +                 binary->cmdline, binary->cmdline, binary->cmdline_size);
>> +    }
>> +  else
>> +    {
>> +      binary->cmdline_size = 0;
>> +      binary->cmdline = NULL;
>> +    }
>> +
>> +  grub_errno = GRUB_ERR_NONE;
>> +  return;
>> +}
>> +
>> +static grub_err_t
>> +grub_cmd_xen_module (grub_command_t cmd, int argc, char *argv[])
>> +{
>> +
>> +  struct xen_boot_binary *module = NULL;
>> +  int file_name_index = 0;
>> +  grub_file_t file = 0;
>> +
>> +  if (!argc)
>> +    {
>> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
>> +      goto fail;
>> +    }
>> +
>> +  if (!grub_linux_get_loaded ())
>> +    {
>> +      grub_error (GRUB_ERR_BAD_ARGUMENT,
>> +               N_("you need to load the Xen Hypervisor first"));
>> +      goto fail;
>> +    }
>> +
>> +  module =
>> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
>> +  if (!module)
>> +    return grub_errno;
>> +
>> +  /* process all the options and get module type */
>> +  if (set_module_type (cmd, module, argc, argv, &file_name_index) !=
>> +      GRUB_ERR_NONE)
>> +    goto fail;
>> +  switch (module->node_info.type)
>> +    {
>> +    case MODULE_IMAGE:
>> +    case MODULE_INITRD:
>> +    case MODULE_XSM:
>> +      module->node_info.compat_string =
>> +     default_compat_string[module->node_info.type].compat_string;
>> +      module->node_info.compat_string_size =
>> +     default_compat_string[module->node_info.type].size;
>> +      break;
>> +
>> +    case MODULE_CUSTOM:
>> +      /* we have set the node_info in set_module_type */
>> +      break;
>> +
>> +    default:
>> +      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
>> +    }
>> +  module->name = module->node_info.compat_string;
>> +  module->align = module_default_align[module->node_info.type];
>> +
>> +  grub_dprintf ("xen_loader", "Init %s module and node info:\n"
>> +             "compatible %s\ncompat_string_size 0x%lx\n",
>> +             module->name, module->node_info.compat_string,
>> +             module->node_info.compat_string_size);
>> +
>> +  file = grub_file_open (argv[file_name_index]);
>> +  if (!file)
>> +    goto fail;
>> +
>> +  xen_boot_binary_load (module, file, argc - file_name_index,
>> +                     argv + file_name_index);
>> +  if (grub_errno == GRUB_ERR_NONE)
>> +    grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
>> +
>> +fail:
>> +  if (file)
>> +    grub_file_close (file);
>> +  if (grub_errno != GRUB_ERR_NONE)
>> +    single_binary_unload (module);
>> +
>> +  return grub_errno;
>> +}
>> +
>> +static grub_err_t
>> +grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
>> +                      int argc, char *argv[])
>> +{
>> +  struct xen_hypervisor_header sh;
>> +  grub_file_t file = NULL;
>> +
>> +  grub_dl_ref (my_mod);
>> +
>> +  if (!argc)
>> +    {
>> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
>> +      goto fail;
>> +    }
>> +
>> +  file = grub_file_open (argv[0]);
>> +  if (!file)
>> +    goto fail;
>> +
>> +  if (grub_file_read (file, &sh, sizeof (sh)) != (long) sizeof (sh))
>> +    goto fail;
>> +  if (grub_arm64_uefi_check_image
>> +      ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
>> +    goto fail;
>> +  grub_file_seek (file, 0);
>> +
>> +  /* if another module has called grub_loader_set,
>> +     we need to make sure that another module is unloaded properly */
>> +  grub_loader_unset ();
>> +
>> +  xen_hypervisor =
>> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
>> +  if (!xen_hypervisor)
>> +    return grub_errno;
>> +
>> +  xen_hypervisor->name = XEN_HYPERVISOR_NAME;
>> +  xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
>> +
>> +  xen_boot_binary_load (xen_hypervisor, file, argc, argv);
>> +  if (grub_errno == GRUB_ERR_NONE)
>> +    {
>> +      grub_loader_set (xen_boot, xen_unload, 0);
>> +      grub_linux_set_loaded (1);
>> +    }
>> +
>> +fail:
>> +  if (file)
>> +    grub_file_close (file);
>> +  if (grub_errno != GRUB_ERR_NONE)
>> +    {
>> +      grub_linux_set_loaded (0);
>> +      all_binaries_unload ();
>> +      grub_dl_unref (my_mod);
>> +    }
>> +
>> +  return grub_errno;
>> +}
>> +
>> +static grub_command_t cmd_xen_hypervisor, cmd_xen_module;
>> +static grub_command_t cmd_xen_linux, cmd_xen_initrd, cmd_xen_xsm;
>> +
>> +GRUB_MOD_INIT (xen_boot)
>> +{
>> +  cmd_xen_hypervisor =
>> +    grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
>> +                        N_("Load a xen hypervisor."));
>> +  cmd_xen_linux =
>> +    grub_register_command ("xen_linux", grub_cmd_xen_module, 0,
>> +                        N_("Load a xen linux kernel for dom0."));
>> +  cmd_xen_initrd =
>> +    grub_register_command ("xen_initrd", grub_cmd_xen_module, 0,
>> +                        N_("Load a xen initrd for dom0."));
>> +  cmd_xen_xsm =
>> +    grub_register_command ("xen_xsm", grub_cmd_xen_module, 0,
>> +                        N_("Load a xen security module."));
>> +  cmd_xen_module =
>> +    grub_register_command ("xen_module", grub_cmd_xen_module, 0,
>> +                        N_("Load a xen module."));
>> +  my_mod = mod;
>> +}
>> +
>> +GRUB_MOD_FINI (xen_boot)
>> +{
>> +  grub_unregister_command (cmd_xen_hypervisor);
>> +  grub_unregister_command (cmd_xen_linux);
>> +  grub_unregister_command (cmd_xen_initrd);
>> +  grub_unregister_command (cmd_xen_xsm);
>> +  grub_unregister_command (cmd_xen_module);
>> +}
>>
>
>



-- 
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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
  2015-10-29 15:25       ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2015-10-30  8:44         ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-10-30  8:44 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Andrei Borzenkov, Jon Masters, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List

Hi Vladimir,

Great thanks for your suggestion! :-)

On 29 October 2015 at 23:25, Vladimir 'φ-coder/phcoder' Serbinenko
<phcoder@gmail.com> wrote:
>> +if [ "x$machine" != xaarch64 ]; then
>> +     multiboot_cmd="multiboot"
>> +     module_linux_cmd="module"
>> +     module_initrd_cmd="module --nounzip"
>> +else
>> +     multiboot_cmd="xen_hypervisor"
>> +     module_linux_cmd="xen_linux"
>> +     module_initrd_cmd="xen_initrd"
>> +fi
>> +
> Please do not hardcode an assumption that grub-mkconfig is executed on
> the same machine as GRUB is booted. I know that we have instances of
> such assumption in some cases but we'd like to eliminate them. Alternatives:
> - Check arch on boot time


> - Check that new xen commands are supported (define a new feature)
> Please add xen_* aliases on x86 as well
I would like to go this way, but could you provide some help or a
little example for :
(1) How to check the new xen commands(or xen_boot module)
(2)add xen_* aliases on x86, is that like something below?

diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
index c4d9689..b88d51b 100644
--- a/grub-core/loader/i386/xen.c
+++ b/grub-core/loader/i386/xen.c
@@ -696,10 +696,14 @@ GRUB_MOD_INIT (xen)
                                   0, N_("Load Linux."));
   cmd_multiboot = grub_register_command ("multiboot", grub_cmd_xen,
                                         0, N_("Load Linux."));
+  cmd_multiboot = grub_register_command ("xen_hypervisor", grub_cmd_xen,
+                                        0, N_("Load Linux."));
   cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
                                      0, N_("Load initrd."));
   cmd_module = grub_register_command ("module", grub_cmd_module,
                                      0, N_("Load module."));
+  cmd_module = grub_register_command ("xen_linux", grub_cmd_module,
+                                     0, N_("Load module."));
   my_mod = mod;
 }

But how to deal with xen_initrd ?
Could you help me ?

Great thanks !!

>
>



-- 
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

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
@ 2015-10-30  8:44         ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-10-30  8:44 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Andrei Borzenkov, Jon Masters, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List

Hi Vladimir,

Great thanks for your suggestion! :-)

On 29 October 2015 at 23:25, Vladimir 'φ-coder/phcoder' Serbinenko
<phcoder@gmail.com> wrote:
>> +if [ "x$machine" != xaarch64 ]; then
>> +     multiboot_cmd="multiboot"
>> +     module_linux_cmd="module"
>> +     module_initrd_cmd="module --nounzip"
>> +else
>> +     multiboot_cmd="xen_hypervisor"
>> +     module_linux_cmd="xen_linux"
>> +     module_initrd_cmd="xen_initrd"
>> +fi
>> +
> Please do not hardcode an assumption that grub-mkconfig is executed on
> the same machine as GRUB is booted. I know that we have instances of
> such assumption in some cases but we'd like to eliminate them. Alternatives:
> - Check arch on boot time


> - Check that new xen commands are supported (define a new feature)
> Please add xen_* aliases on x86 as well
I would like to go this way, but could you provide some help or a
little example for :
(1) How to check the new xen commands(or xen_boot module)
(2)add xen_* aliases on x86, is that like something below?

diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
index c4d9689..b88d51b 100644
--- a/grub-core/loader/i386/xen.c
+++ b/grub-core/loader/i386/xen.c
@@ -696,10 +696,14 @@ GRUB_MOD_INIT (xen)
                                   0, N_("Load Linux."));
   cmd_multiboot = grub_register_command ("multiboot", grub_cmd_xen,
                                         0, N_("Load Linux."));
+  cmd_multiboot = grub_register_command ("xen_hypervisor", grub_cmd_xen,
+                                        0, N_("Load Linux."));
   cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
                                      0, N_("Load initrd."));
   cmd_module = grub_register_command ("module", grub_cmd_module,
                                      0, N_("Load module."));
+  cmd_module = grub_register_command ("xen_linux", grub_cmd_module,
+                                     0, N_("Load module."));
   my_mod = mod;
 }

But how to deal with xen_initrd ?
Could you help me ?

Great thanks !!

>
>



-- 
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


^ permalink raw reply related	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
  2015-10-30  8:44         ` Fu Wei
@ 2015-10-30  9:50           ` Vladimir 'φ-coder/phcoder' Serbinenko
  -1 siblings, 0 replies; 550+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2015-10-30  9:50 UTC (permalink / raw)
  To: Fu Wei
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Andrei Borzenkov, Jon Masters, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List


[-- Attachment #1.1: Type: text/plain, Size: 2410 bytes --]

On 30.10.2015 09:44, Fu Wei wrote:
> Hi Vladimir,
> 
> Great thanks for your suggestion! :-)
> 
> On 29 October 2015 at 23:25, Vladimir 'φ-coder/phcoder' Serbinenko
> <phcoder@gmail.com> wrote:
>>> +if [ "x$machine" != xaarch64 ]; then
>>> +     multiboot_cmd="multiboot"
>>> +     module_linux_cmd="module"
>>> +     module_initrd_cmd="module --nounzip"
>>> +else
>>> +     multiboot_cmd="xen_hypervisor"
>>> +     module_linux_cmd="xen_linux"
>>> +     module_initrd_cmd="xen_initrd"
>>> +fi
>>> +
>> Please do not hardcode an assumption that grub-mkconfig is executed on
>> the same machine as GRUB is booted. I know that we have instances of
>> such assumption in some cases but we'd like to eliminate them. Alternatives:
>> - Check arch on boot time
> 
> 
>> - Check that new xen commands are supported (define a new feature)
>> Please add xen_* aliases on x86 as well
> I would like to go this way, but could you provide some help or a
> little example for :
> (1) How to check the new xen commands(or xen_boot module)
> (2)add xen_* aliases on x86, is that like something below?
> 
see grub-core/normal/main.c the features array.
> diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
> index c4d9689..b88d51b 100644
> --- a/grub-core/loader/i386/xen.c
> +++ b/grub-core/loader/i386/xen.c
> @@ -696,10 +696,14 @@ GRUB_MOD_INIT (xen)
>                                    0, N_("Load Linux."));
>    cmd_multiboot = grub_register_command ("multiboot", grub_cmd_xen,
>                                          0, N_("Load Linux."));
> +  cmd_multiboot = grub_register_command ("xen_hypervisor", grub_cmd_xen,
> +                                        0, N_("Load Linux."));
>    cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
>                                       0, N_("Load initrd."));
>    cmd_module = grub_register_command ("module", grub_cmd_module,
>                                       0, N_("Load module."));
> +  cmd_module = grub_register_command ("xen_linux", grub_cmd_module,
> +                                     0, N_("Load module."));
>    my_mod = mod;
>  }
> 
> But how to deal with xen_initrd ?
> Could you help me ?
> 
Just another alias to module. Possibly you might want to add a code to
xen_initrd tto check that xen_linux was already run
> Great thanks !!
> 
>>
>>
> 
> 
> 



[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

[-- Attachment #2: Type: text/plain, Size: 141 bytes --]

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
@ 2015-10-30  9:50           ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 0 replies; 550+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2015-10-30  9:50 UTC (permalink / raw)
  To: Fu Wei
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Andrei Borzenkov, Jon Masters, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List

[-- Attachment #1: Type: text/plain, Size: 2410 bytes --]

On 30.10.2015 09:44, Fu Wei wrote:
> Hi Vladimir,
> 
> Great thanks for your suggestion! :-)
> 
> On 29 October 2015 at 23:25, Vladimir 'φ-coder/phcoder' Serbinenko
> <phcoder@gmail.com> wrote:
>>> +if [ "x$machine" != xaarch64 ]; then
>>> +     multiboot_cmd="multiboot"
>>> +     module_linux_cmd="module"
>>> +     module_initrd_cmd="module --nounzip"
>>> +else
>>> +     multiboot_cmd="xen_hypervisor"
>>> +     module_linux_cmd="xen_linux"
>>> +     module_initrd_cmd="xen_initrd"
>>> +fi
>>> +
>> Please do not hardcode an assumption that grub-mkconfig is executed on
>> the same machine as GRUB is booted. I know that we have instances of
>> such assumption in some cases but we'd like to eliminate them. Alternatives:
>> - Check arch on boot time
> 
> 
>> - Check that new xen commands are supported (define a new feature)
>> Please add xen_* aliases on x86 as well
> I would like to go this way, but could you provide some help or a
> little example for :
> (1) How to check the new xen commands(or xen_boot module)
> (2)add xen_* aliases on x86, is that like something below?
> 
see grub-core/normal/main.c the features array.
> diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
> index c4d9689..b88d51b 100644
> --- a/grub-core/loader/i386/xen.c
> +++ b/grub-core/loader/i386/xen.c
> @@ -696,10 +696,14 @@ GRUB_MOD_INIT (xen)
>                                    0, N_("Load Linux."));
>    cmd_multiboot = grub_register_command ("multiboot", grub_cmd_xen,
>                                          0, N_("Load Linux."));
> +  cmd_multiboot = grub_register_command ("xen_hypervisor", grub_cmd_xen,
> +                                        0, N_("Load Linux."));
>    cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
>                                       0, N_("Load initrd."));
>    cmd_module = grub_register_command ("module", grub_cmd_module,
>                                       0, N_("Load module."));
> +  cmd_module = grub_register_command ("xen_linux", grub_cmd_module,
> +                                     0, N_("Load module."));
>    my_mod = mod;
>  }
> 
> But how to deal with xen_initrd ?
> Could you help me ?
> 
Just another alias to module. Possibly you might want to add a code to
xen_initrd tto check that xen_linux was already run
> Great thanks !!
> 
>>
>>
> 
> 
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
  2015-10-30  9:50           ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2015-10-30 10:07             ` Andrei Borzenkov
  -1 siblings, 0 replies; 550+ messages in thread
From: Andrei Borzenkov @ 2015-10-30 10:07 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Jon Masters, Leif Lindholm, Ryan Harkin,
	Linaro UEFI Mailman List, Fu Wei

On Fri, Oct 30, 2015 at 12:50 PM, Vladimir 'φ-coder/phcoder'
Serbinenko <phcoder@gmail.com> wrote:
>>
>> But how to deal with xen_initrd ?
>> Could you help me ?
>>
> Just another alias to module. Possibly you might want to add a code to
> xen_initrd tto check that xen_linux was already run

I think we need to be careful here. We need to think about future
extenstions (in particular to other architectures) and options
handling. E.g. initrd never accepted any option and we cannot really
add one probably now; but xen_initrd did IIRC (or may be I was
mistaken with xen_module). What I mean, we should allow additional
options from the very beginning, not just making it exact alias.

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
@ 2015-10-30 10:07             ` Andrei Borzenkov
  0 siblings, 0 replies; 550+ messages in thread
From: Andrei Borzenkov @ 2015-10-30 10:07 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Jon Masters, Leif Lindholm, Ryan Harkin,
	Linaro UEFI Mailman List, Fu Wei

On Fri, Oct 30, 2015 at 12:50 PM, Vladimir 'φ-coder/phcoder'
Serbinenko <phcoder@gmail.com> wrote:
>>
>> But how to deal with xen_initrd ?
>> Could you help me ?
>>
> Just another alias to module. Possibly you might want to add a code to
> xen_initrd tto check that xen_linux was already run

I think we need to be careful here. We need to think about future
extenstions (in particular to other architectures) and options
handling. E.g. initrd never accepted any option and we cannot really
add one probably now; but xen_initrd did IIRC (or may be I was
mistaken with xen_module). What I mean, we should allow additional
options from the very beginning, not just making it exact alias.


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 2/4] arm64: Add xen_boot module file
  2015-10-30  8:08         ` Fu Wei
@ 2015-11-03 14:57           ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-11-03 14:57 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Andrei Borzenkov, Jon Masters, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List

Hi Vladimir,

After discussing with Ian Campbell,   Since we already can load all
the necessary binaries for Xen boot on arm64 for now,  we don't really
need "xen_module" command now.
But maybe someday , xen need a new type of binary in boot time, then
we still need this support.

So I will submit  a   "xen_module" command patch soon, in case we need it.

Great thanks ! :-)

On 30 October 2015 at 16:08, Fu Wei <fu.wei@linaro.org> wrote:
> Hi Vladimir,
>
> yes, Thanks for your modification :-)
>
> I just follow the xen boot protocol :
> http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
>
> xen_module is just for "--type" option, I will discuss this with Xen
> developer for this.
> If we need this option, I will resubmit  it :-)
>
> Great thanks!
>
> On 29 October 2015 at 22:27, Vladimir 'φ-coder/phcoder' Serbinenko
> <phcoder@gmail.com> wrote:
>> Committed without the xen_module command. Its argument parsing was
>> non-trivial and I don't quite get what its intent is. Can you resubmit?
>> On 23.07.2015 07:16, fu.wei@linaro.org wrote:
>>> From: Fu Wei <fu.wei@linaro.org>
>>>
>>> grub-core/loader/arm64/xen_boot.c
>>>
>>>   - This adds support for the Xen boot on ARM specification for arm64.
>>>   - Introduce xen_hypervisor, xen_linux, xen_initrd and xen_xsm
>>>     to load different binaries for xen boot;
>>>     Introduce xen_module to load common or custom module for xen boot.
>>>   - This Xen boot support is a separated  module for aarch64,
>>>     but reuse the existing code of devicetree in linux module.
>>>
>>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>>> ---
>>>  grub-core/Makefile.core.def       |   7 +
>>>  grub-core/loader/arm64/xen_boot.c | 685 ++++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 692 insertions(+)
>>>
>>> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
>>> index a6101de..796f7e9 100644
>>> --- a/grub-core/Makefile.core.def
>>> +++ b/grub-core/Makefile.core.def
>>> @@ -1648,6 +1648,13 @@ module = {
>>>  };
>>>
>>>  module = {
>>> +  name = xen_boot;
>>> +  common = lib/cmdline.c;
>>> +  arm64 = loader/arm64/xen_boot.c;
>>> +  enable = arm64;
>>> +};
>>> +
>>> +module = {
>>>    name = linux;
>>>    x86 = loader/i386/linux.c;
>>>    xen = loader/i386/xen.c;
>>> diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
>>> new file mode 100644
>>> index 0000000..33a65dd
>>> --- /dev/null
>>> +++ b/grub-core/loader/arm64/xen_boot.c
>>> @@ -0,0 +1,685 @@
>>> +/*
>>> + *  GRUB  --  GRand Unified Bootloader
>>> + *  Copyright (C) 2014  Free Software Foundation, Inc.
>>> + *
>>> + *  GRUB is free software: you can redistribute it and/or modify
>>> + *  it under the terms of the GNU General Public License as published by
>>> + *  the Free Software Foundation, either version 3 of the License, or
>>> + *  (at your option) any later version.
>>> + *
>>> + *  GRUB 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.
>>> + *
>>> + *  You should have received a copy of the GNU General Public License
>>> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#include <grub/cache.h>
>>> +#include <grub/charset.h>
>>> +#include <grub/command.h>
>>> +#include <grub/err.h>
>>> +#include <grub/file.h>
>>> +#include <grub/fdt.h>
>>> +#include <grub/linux.h>
>>> +#include <grub/list.h>
>>> +#include <grub/loader.h>
>>> +#include <grub/misc.h>
>>> +#include <grub/mm.h>
>>> +#include <grub/types.h>
>>> +#include <grub/cpu/linux.h>
>>> +#include <grub/efi/efi.h>
>>> +#include <grub/efi/pe32.h>   /* required by struct xen_hypervisor_header */
>>> +#include <grub/i18n.h>
>>> +#include <grub/lib/cmdline.h>
>>> +
>>> +GRUB_MOD_LICENSE ("GPLv3+");
>>> +
>>> +#define XEN_HYPERVISOR_NAME  "xen_hypervisor"
>>> +
>>> +#define MODULE_DEFAULT_ALIGN  (0x0)
>>> +#define MODULE_IMAGE_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>>> +#define MODULE_INITRD_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>>> +#define MODULE_XSM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>>> +#define MODULE_CUSTOM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>>> +
>>> +/* #define MODULE_IMAGE_COMPATIBLE  "xen,linux-image\0xen,module"
>>> +#define MODULE_INITRD_COMPATIBLE  "xen,linux-image\0xen,module"
>>> +#define MODULE_XSM_COMPATIBLE  "xen,xsm-policy\0xen,module"
>>> +#define MODULE_CUSTOM_COMPATIBLE  "xen,module" */
>>> +#define MODULE_IMAGE_COMPATIBLE  "multiboot,kernel\0multiboot,module"
>>> +#define MODULE_INITRD_COMPATIBLE  "multiboot,ramdisk\0multiboot,module"
>>> +#define MODULE_XSM_COMPATIBLE  "xen,xsm-policy\0multiboot,module"
>>> +#define MODULE_CUSTOM_COMPATIBLE  "multiboot,module"
>>> +
>>> +/* This maximum size is defined in Power.org ePAPR V1.1
>>> + * https://www.power.org/documentation/epapr-version-1-1/
>>> + * 2.2.1.1 Node Name Requirements
>>> + * node-name@unit-address
>>> + * 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
>>> + */
>>> +#define FDT_NODE_NAME_MAX_SIZE  (49)
>>> +
>>> +#define ARG_SHIFT(argc, argv) \
>>> +  do { \
>>> +    (argc)--; \
>>> +    (argv)++; \
>>> +  } while (0)
>>> +
>>> +struct compat_string_struct
>>> +{
>>> +  grub_size_t size;
>>> +  const char *compat_string;
>>> +};
>>> +typedef struct compat_string_struct compat_string_struct_t;
>>> +#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
>>> +
>>> +enum module_type
>>> +{
>>> +  MODULE_IMAGE,
>>> +  MODULE_INITRD,
>>> +  MODULE_XSM,
>>> +  MODULE_CUSTOM
>>> +};
>>> +typedef enum module_type module_type_t;
>>> +
>>> +struct fdt_node_info
>>> +{
>>> +  module_type_t type;
>>> +
>>> +  const char *compat_string;
>>> +  grub_size_t compat_string_size;
>>> +};
>>> +
>>> +struct xen_hypervisor_header
>>> +{
>>> +  struct grub_arm64_linux_kernel_header efi_head;
>>> +
>>> +  /* This is always PE\0\0.  */
>>> +  grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
>>> +  /* The COFF file header.  */
>>> +  struct grub_pe32_coff_header coff_header;
>>> +  /* The Optional header.  */
>>> +  struct grub_pe64_optional_header optional_header;
>>> +};
>>> +
>>> +struct xen_boot_binary
>>> +{
>>> +  struct xen_boot_binary *next;
>>> +  struct xen_boot_binary **prev;
>>> +  const char *name;
>>> +
>>> +  grub_addr_t start;
>>> +  grub_size_t size;
>>> +  grub_size_t align;
>>> +
>>> +  char *cmdline;
>>> +  int cmdline_size;
>>> +
>>> +  struct fdt_node_info node_info;
>>> +};
>>> +
>>> +static grub_dl_t my_mod;
>>> +
>>> +static struct xen_boot_binary *xen_hypervisor;
>>> +static struct xen_boot_binary *module_head;
>>> +static const grub_size_t module_default_align[] = {
>>> +  MODULE_IMAGE_MIN_ALIGN,
>>> +  MODULE_INITRD_MIN_ALIGN,
>>> +  MODULE_XSM_MIN_ALIGN,
>>> +  MODULE_CUSTOM_MIN_ALIGN
>>> +};
>>> +
>>> +static void *xen_boot_fdt;
>>> +static const compat_string_struct_t default_compat_string[] = {
>>> +  FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
>>> +  FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
>>> +  FDT_COMPATIBLE (MODULE_XSM_COMPATIBLE),
>>> +  FDT_COMPATIBLE (MODULE_CUSTOM_COMPATIBLE)
>>> +};
>>> +
>>> +static __inline grub_addr_t
>>> +xen_boot_address_align (grub_addr_t start, grub_size_t align)
>>> +{
>>> +  return (align ? (ALIGN_UP (start, align)) : start);
>>> +}
>>> +
>>> +/* Parse the option of xen_module command. For now, we support
>>> +   (1) --type <the compatible stream>
>>> +   We also set up the type of module in this function.
>>> +   If there are some "--type" options in the command line,
>>> +   we make a custom compatible stream in this function. */
>>> +static grub_err_t
>>> +set_module_type (grub_command_t cmd, struct xen_boot_binary *module,
>>> +              int argc, char *argv[], int *file_name_index)
>>> +{
>>> +  char **compat_string_temp_array;
>>> +  grub_size_t total_size = 0;
>>> +  int num_types = 0, i;
>>> +  char *temp = NULL;
>>> +
>>> +  *file_name_index = 0;
>>> +
>>> +  if (!grub_strcmp (cmd->name, "xen_linux"))
>>> +    module->node_info.type = MODULE_IMAGE;
>>> +  else if (!grub_strcmp (cmd->name, "xen_initrd"))
>>> +    module->node_info.type = MODULE_INITRD;
>>> +  else if (!grub_strcmp (cmd->name, "xen_xsm"))
>>> +    module->node_info.type = MODULE_XSM;
>>> +  else if (!grub_strcmp (cmd->name, "xen_module"))
>>> +    module->node_info.type = MODULE_CUSTOM;
>>> +
>>> +  /* if there are some options we need to process. */
>>> +  if (module->node_info.type == MODULE_CUSTOM)
>>> +    {
>>> +      compat_string_temp_array =
>>> +     (char **) grub_zalloc (sizeof (char *) * argc);
>>> +      if (!compat_string_temp_array)
>>> +     return grub_errno;
>>> +      /* the module type is set by "--type"(MODULE_CUSTOM) */
>>> +      while (argc > 2 && !grub_strcmp (argv[0], "--type"))
>>> +     {
>>> +       module->node_info.type = MODULE_CUSTOM;
>>> +       ARG_SHIFT (argc, argv);
>>> +       total_size += grub_strlen (argv[0]) + 1;
>>> +       compat_string_temp_array[num_types++] = argv[0];
>>> +       ARG_SHIFT (argc, argv);
>>> +       (*file_name_index) += 2;
>>> +     }
>>> +
>>> +      if (total_size)
>>> +     {
>>> +       module->node_info.compat_string = temp =
>>> +         (char *) grub_zalloc (total_size);
>>> +       if (!temp)
>>> +         {
>>> +           grub_free (compat_string_temp_array);
>>> +           return grub_errno;
>>> +         }
>>> +
>>> +       module->node_info.compat_string_size = total_size;
>>> +       for (i = 0; num_types > 0; num_types--, i++, temp++)
>>> +         {
>>> +           grub_strcpy (temp, compat_string_temp_array[i]);
>>> +           temp += grub_strlen (compat_string_temp_array[i]);
>>> +         }
>>> +     }
>>> +      else
>>> +     {
>>> +       module->node_info.compat_string =
>>> +         default_compat_string[MODULE_CUSTOM].compat_string;
>>> +       module->node_info.compat_string_size =
>>> +         default_compat_string[MODULE_CUSTOM].size;
>>> +     }
>>> +
>>> +      grub_free (compat_string_temp_array);
>>> +    }
>>> +
>>> +  return GRUB_ERR_NONE;
>>> +}
>>> +
>>> +static grub_err_t
>>> +prepare_xen_hypervisor_params (void)
>>> +{
>>> +  int chosen_node = 0;
>>> +  int retval;
>>> +
>>> +  xen_boot_fdt = grub_linux_get_fdt ();
>>> +  if (!xen_boot_fdt)
>>> +    return grub_error (GRUB_ERR_IO, "failed to get FDT");
>>> +
>>> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
>>> +  if (chosen_node < 0)
>>> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
>>> +  if (chosen_node < 1)
>>> +    return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
>>> +
>>> +  grub_dprintf ("xen_loader",
>>> +             "Xen Hypervisor cmdline : %s @ %p size:%d\n",
>>> +             xen_hypervisor->cmdline, xen_hypervisor->cmdline,
>>> +             xen_hypervisor->cmdline_size);
>>> +
>>> +  retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
>>> +                           xen_hypervisor->cmdline,
>>> +                           xen_hypervisor->cmdline_size);
>>> +  if (retval)
>>> +    return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
>>> +
>>> +  return GRUB_ERR_NONE;
>>> +}
>>> +
>>> +static grub_err_t
>>> +prepare_xen_module_params (struct xen_boot_binary *module)
>>> +{
>>> +  int retval, chosen_node = 0, module_node = 0;
>>> +  char module_name[FDT_NODE_NAME_MAX_SIZE];
>>> +
>>> +  retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
>>> +                       xen_boot_address_align (module->start,
>>> +                                               module->align));
>>> +  grub_dprintf ("xen_loader", "Module node name %s \n", module_name);
>>> +
>>> +  if (retval < (int) sizeof ("module@"))
>>> +    return grub_error (GRUB_ERR_IO, N_("failed to get FDT"));
>>> +
>>> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
>>> +  if (chosen_node < 0)
>>> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
>>> +  if (chosen_node < 1)
>>> +    return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
>>> +
>>> +  module_node =
>>> +    grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
>>> +  if (module_node < 0)
>>> +    module_node =
>>> +      grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
>>> +
>>> +  retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
>>> +                           module->node_info.compat_string,
>>> +                           (grub_uint32_t) module->
>>> +                           node_info.compat_string_size);
>>> +  if (retval)
>>> +    return grub_error (GRUB_ERR_IO, N_("failed to update FDT"));
>>> +
>>> +  grub_dprintf ("xen_loader", "Module %s compatible = %s size = 0x%lx\n",
>>> +             module->name, module->node_info.compat_string,
>>> +             module->node_info.compat_string_size);
>>> +
>>> +  retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
>>> +                            xen_boot_address_align (module->start,
>>> +                                                    module->align),
>>> +                            module->size);
>>> +  if (retval)
>>> +    return grub_error (GRUB_ERR_IO, N_("failed to update FDT"));
>>> +
>>> +  if (module->cmdline && module->cmdline_size > 0)
>>> +    {
>>> +      grub_dprintf ("xen_loader",
>>> +                 "Module %s cmdline : %s @ %p size:%d\n", module->name,
>>> +                 module->cmdline, module->cmdline, module->cmdline_size);
>>> +
>>> +      retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
>>> +                               module->cmdline, module->cmdline_size + 1);
>>> +      if (retval)
>>> +     return grub_error (GRUB_ERR_IO, "failed to update FDT");
>>> +    }
>>> +  else
>>> +    {
>>> +      grub_dprintf ("xen_loader", "Module %s has not bootargs!\n",
>>> +                 module->name);
>>> +    }
>>> +
>>> +  return GRUB_ERR_NONE;
>>> +}
>>> +
>>> +static grub_err_t
>>> +install_all_params (void)
>>> +{
>>> +  grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
>>> +  grub_efi_boot_services_t *b;
>>> +  grub_efi_status_t status;
>>> +
>>> +  b = grub_efi_system_table->boot_services;
>>> +  status = b->install_configuration_table (&fdt_guid, xen_boot_fdt);
>>> +  if (status != GRUB_EFI_SUCCESS)
>>> +    return grub_error (GRUB_ERR_IO, "failed to install FDT");
>>> +
>>> +  grub_dprintf ("xen_loader",
>>> +             "Installed/updated FDT configuration table @ %p\n",
>>> +             xen_boot_fdt);
>>> +
>>> +  return GRUB_ERR_NONE;
>>> +}
>>> +
>>> +static grub_err_t
>>> +clean_all_params (void)
>>> +{
>>> +  if (xen_boot_fdt)
>>> +    {
>>> +      grub_efi_free_pages ((grub_efi_physical_address_t) xen_boot_fdt,
>>> +                        BYTES_TO_PAGES (grub_fdt_get_totalsize
>>> +                                        (xen_boot_fdt)));
>>> +      xen_boot_fdt = NULL;
>>> +    }
>>> +
>>> +  return GRUB_ERR_NONE;
>>> +}
>>> +
>>> +static grub_err_t
>>> +finalize_params_xen_boot (void)
>>> +{
>>> +  struct xen_boot_binary *module;
>>> +
>>> +  if (xen_hypervisor)
>>> +    {
>>> +      if (prepare_xen_hypervisor_params () != GRUB_ERR_NONE)
>>> +     goto fail;
>>> +    }
>>> +  else
>>> +    {
>>> +      grub_dprintf ("xen_loader", "Failed to get Xen Hypervisor info!\n");
>>> +      goto fail;
>>> +    }
>>> +
>>> +  /* Set module params info */
>>> +  FOR_LIST_ELEMENTS (module, module_head)
>>> +  {
>>> +    if (module->start && module->size > 0)
>>> +      {
>>> +     grub_dprintf ("xen_loader", "Module %s @ 0x%lx size:0x%lx\n",
>>> +                   module->name,
>>> +                   xen_boot_address_align (module->start, module->align),
>>> +                   module->size);
>>> +     if (prepare_xen_module_params (module) != GRUB_ERR_NONE)
>>> +       goto fail;
>>> +      }
>>> +    else
>>> +      {
>>> +     grub_dprintf ("xen_loader", "Module info error: %s!\n", module->name);
>>> +     goto fail;
>>> +      }
>>> +  }
>>> +
>>> +  if (install_all_params () == GRUB_ERR_NONE)
>>> +    return GRUB_ERR_NONE;
>>> +
>>> +fail:
>>> +  clean_all_params ();
>>> +
>>> +  return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
>>> +}
>>> +
>>> +
>>> +static grub_err_t
>>> +xen_boot (void)
>>> +{
>>> +  grub_err_t err = finalize_params_xen_boot ();
>>> +  if (err)
>>> +    return err;
>>> +
>>> +  return grub_arm64_uefi_boot_image (xen_hypervisor->start,
>>> +                                  xen_hypervisor->size,
>>> +                                  xen_hypervisor->cmdline);
>>> +}
>>> +
>>> +static void
>>> +single_binary_unload (struct xen_boot_binary *binary)
>>> +{
>>> +  if (!binary)
>>> +    return;
>>> +
>>> +  if (binary->start && binary->size > 0)
>>> +    {
>>> +      grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
>>> +                        BYTES_TO_PAGES (binary->size + binary->align));
>>> +    }
>>> +
>>> +  if (binary->cmdline && binary->cmdline_size > 0)
>>> +    {
>>> +      grub_free (binary->cmdline);
>>> +      grub_dprintf ("xen_loader",
>>> +                 "Module %s cmdline memory free @ %p size: %d\n",
>>> +                 binary->name, binary->cmdline, binary->cmdline_size);
>>> +    }
>>> +
>>> +  if (binary->node_info.type == MODULE_CUSTOM)
>>> +    grub_free ((void *) binary->node_info.compat_string);
>>> +
>>> +  if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
>>> +    grub_list_remove (GRUB_AS_LIST (binary));
>>> +
>>> +  grub_dprintf ("xen_loader",
>>> +             "Module %s struct memory free @ %p size: 0x%lx\n",
>>> +             binary->name, binary, sizeof (binary));
>>> +  grub_free (binary);
>>> +
>>> +  return;
>>> +}
>>> +
>>> +static void
>>> +all_binaries_unload (void)
>>> +{
>>> +  struct xen_boot_binary *binary;
>>> +
>>> +  FOR_LIST_ELEMENTS (binary, module_head)
>>> +  {
>>> +    single_binary_unload (binary);
>>> +  }
>>> +
>>> +  if (xen_hypervisor)
>>> +    single_binary_unload (xen_hypervisor);
>>> +
>>> +  return;
>>> +}
>>> +
>>> +static grub_err_t
>>> +xen_unload (void)
>>> +{
>>> +  grub_linux_set_loaded (0);
>>> +  all_binaries_unload ();
>>> +  clean_all_params ();
>>> +  grub_dl_unref (my_mod);
>>> +
>>> +  return GRUB_ERR_NONE;
>>> +}
>>> +
>>> +static void
>>> +xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
>>> +                   int argc, char *argv[])
>>> +{
>>> +  binary->size = grub_file_size (file);
>>> +  grub_dprintf ("xen_loader", "Xen_boot %s file size: 0x%lx\n",
>>> +             binary->name, binary->size);
>>> +
>>> +  binary->start = (grub_addr_t) grub_efi_allocate_pages (0,
>>> +                                                      (BYTES_TO_PAGES
>>> +                                                       (binary->size +
>>> +                                                        binary->align)));
>>> +  if (!binary->start)
>>> +    {
>>> +      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>>> +      return;
>>> +    }
>>> +
>>> +  grub_dprintf ("xen_loader", "Xen_boot %s numpages: 0x%lx\n",
>>> +             binary->name, BYTES_TO_PAGES (binary->size + binary->align));
>>> +
>>> +  if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
>>> +                                                          binary->align),
>>> +                   binary->size) != (grub_ssize_t) binary->size)
>>> +    {
>>> +      single_binary_unload (binary);
>>> +      grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
>>> +      return;
>>> +    }
>>> +
>>> +  if (argc > 1)
>>> +    {
>>> +      binary->cmdline_size = grub_loader_cmdline_size (argc - 1, argv + 1);
>>> +      binary->cmdline = grub_zalloc (binary->cmdline_size);
>>> +      if (!binary->cmdline)
>>> +     {
>>> +       single_binary_unload (binary);
>>> +       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>>> +       return;
>>> +     }
>>> +      grub_create_loader_cmdline (argc - 1, argv + 1, binary->cmdline,
>>> +                               binary->cmdline_size);
>>> +      grub_dprintf ("xen_loader",
>>> +                 "Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
>>> +                 binary->cmdline, binary->cmdline, binary->cmdline_size);
>>> +    }
>>> +  else
>>> +    {
>>> +      binary->cmdline_size = 0;
>>> +      binary->cmdline = NULL;
>>> +    }
>>> +
>>> +  grub_errno = GRUB_ERR_NONE;
>>> +  return;
>>> +}
>>> +
>>> +static grub_err_t
>>> +grub_cmd_xen_module (grub_command_t cmd, int argc, char *argv[])
>>> +{
>>> +
>>> +  struct xen_boot_binary *module = NULL;
>>> +  int file_name_index = 0;
>>> +  grub_file_t file = 0;
>>> +
>>> +  if (!argc)
>>> +    {
>>> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
>>> +      goto fail;
>>> +    }
>>> +
>>> +  if (!grub_linux_get_loaded ())
>>> +    {
>>> +      grub_error (GRUB_ERR_BAD_ARGUMENT,
>>> +               N_("you need to load the Xen Hypervisor first"));
>>> +      goto fail;
>>> +    }
>>> +
>>> +  module =
>>> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
>>> +  if (!module)
>>> +    return grub_errno;
>>> +
>>> +  /* process all the options and get module type */
>>> +  if (set_module_type (cmd, module, argc, argv, &file_name_index) !=
>>> +      GRUB_ERR_NONE)
>>> +    goto fail;
>>> +  switch (module->node_info.type)
>>> +    {
>>> +    case MODULE_IMAGE:
>>> +    case MODULE_INITRD:
>>> +    case MODULE_XSM:
>>> +      module->node_info.compat_string =
>>> +     default_compat_string[module->node_info.type].compat_string;
>>> +      module->node_info.compat_string_size =
>>> +     default_compat_string[module->node_info.type].size;
>>> +      break;
>>> +
>>> +    case MODULE_CUSTOM:
>>> +      /* we have set the node_info in set_module_type */
>>> +      break;
>>> +
>>> +    default:
>>> +      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
>>> +    }
>>> +  module->name = module->node_info.compat_string;
>>> +  module->align = module_default_align[module->node_info.type];
>>> +
>>> +  grub_dprintf ("xen_loader", "Init %s module and node info:\n"
>>> +             "compatible %s\ncompat_string_size 0x%lx\n",
>>> +             module->name, module->node_info.compat_string,
>>> +             module->node_info.compat_string_size);
>>> +
>>> +  file = grub_file_open (argv[file_name_index]);
>>> +  if (!file)
>>> +    goto fail;
>>> +
>>> +  xen_boot_binary_load (module, file, argc - file_name_index,
>>> +                     argv + file_name_index);
>>> +  if (grub_errno == GRUB_ERR_NONE)
>>> +    grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
>>> +
>>> +fail:
>>> +  if (file)
>>> +    grub_file_close (file);
>>> +  if (grub_errno != GRUB_ERR_NONE)
>>> +    single_binary_unload (module);
>>> +
>>> +  return grub_errno;
>>> +}
>>> +
>>> +static grub_err_t
>>> +grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
>>> +                      int argc, char *argv[])
>>> +{
>>> +  struct xen_hypervisor_header sh;
>>> +  grub_file_t file = NULL;
>>> +
>>> +  grub_dl_ref (my_mod);
>>> +
>>> +  if (!argc)
>>> +    {
>>> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
>>> +      goto fail;
>>> +    }
>>> +
>>> +  file = grub_file_open (argv[0]);
>>> +  if (!file)
>>> +    goto fail;
>>> +
>>> +  if (grub_file_read (file, &sh, sizeof (sh)) != (long) sizeof (sh))
>>> +    goto fail;
>>> +  if (grub_arm64_uefi_check_image
>>> +      ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
>>> +    goto fail;
>>> +  grub_file_seek (file, 0);
>>> +
>>> +  /* if another module has called grub_loader_set,
>>> +     we need to make sure that another module is unloaded properly */
>>> +  grub_loader_unset ();
>>> +
>>> +  xen_hypervisor =
>>> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
>>> +  if (!xen_hypervisor)
>>> +    return grub_errno;
>>> +
>>> +  xen_hypervisor->name = XEN_HYPERVISOR_NAME;
>>> +  xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
>>> +
>>> +  xen_boot_binary_load (xen_hypervisor, file, argc, argv);
>>> +  if (grub_errno == GRUB_ERR_NONE)
>>> +    {
>>> +      grub_loader_set (xen_boot, xen_unload, 0);
>>> +      grub_linux_set_loaded (1);
>>> +    }
>>> +
>>> +fail:
>>> +  if (file)
>>> +    grub_file_close (file);
>>> +  if (grub_errno != GRUB_ERR_NONE)
>>> +    {
>>> +      grub_linux_set_loaded (0);
>>> +      all_binaries_unload ();
>>> +      grub_dl_unref (my_mod);
>>> +    }
>>> +
>>> +  return grub_errno;
>>> +}
>>> +
>>> +static grub_command_t cmd_xen_hypervisor, cmd_xen_module;
>>> +static grub_command_t cmd_xen_linux, cmd_xen_initrd, cmd_xen_xsm;
>>> +
>>> +GRUB_MOD_INIT (xen_boot)
>>> +{
>>> +  cmd_xen_hypervisor =
>>> +    grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
>>> +                        N_("Load a xen hypervisor."));
>>> +  cmd_xen_linux =
>>> +    grub_register_command ("xen_linux", grub_cmd_xen_module, 0,
>>> +                        N_("Load a xen linux kernel for dom0."));
>>> +  cmd_xen_initrd =
>>> +    grub_register_command ("xen_initrd", grub_cmd_xen_module, 0,
>>> +                        N_("Load a xen initrd for dom0."));
>>> +  cmd_xen_xsm =
>>> +    grub_register_command ("xen_xsm", grub_cmd_xen_module, 0,
>>> +                        N_("Load a xen security module."));
>>> +  cmd_xen_module =
>>> +    grub_register_command ("xen_module", grub_cmd_xen_module, 0,
>>> +                        N_("Load a xen module."));
>>> +  my_mod = mod;
>>> +}
>>> +
>>> +GRUB_MOD_FINI (xen_boot)
>>> +{
>>> +  grub_unregister_command (cmd_xen_hypervisor);
>>> +  grub_unregister_command (cmd_xen_linux);
>>> +  grub_unregister_command (cmd_xen_initrd);
>>> +  grub_unregister_command (cmd_xen_xsm);
>>> +  grub_unregister_command (cmd_xen_module);
>>> +}
>>>
>>
>>
>
>
>
> --
> 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

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 2/4] arm64: Add xen_boot module file
@ 2015-11-03 14:57           ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-11-03 14:57 UTC (permalink / raw)
  To: Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: The development of GNU GRUB, xen-devel, Ian Campbell,
	Stefano Stabellini, Andrei Borzenkov, Jon Masters, Leif Lindholm,
	Ryan Harkin, Linaro UEFI Mailman List

Hi Vladimir,

After discussing with Ian Campbell,   Since we already can load all
the necessary binaries for Xen boot on arm64 for now,  we don't really
need "xen_module" command now.
But maybe someday , xen need a new type of binary in boot time, then
we still need this support.

So I will submit  a   "xen_module" command patch soon, in case we need it.

Great thanks ! :-)

On 30 October 2015 at 16:08, Fu Wei <fu.wei@linaro.org> wrote:
> Hi Vladimir,
>
> yes, Thanks for your modification :-)
>
> I just follow the xen boot protocol :
> http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
>
> xen_module is just for "--type" option, I will discuss this with Xen
> developer for this.
> If we need this option, I will resubmit  it :-)
>
> Great thanks!
>
> On 29 October 2015 at 22:27, Vladimir 'φ-coder/phcoder' Serbinenko
> <phcoder@gmail.com> wrote:
>> Committed without the xen_module command. Its argument parsing was
>> non-trivial and I don't quite get what its intent is. Can you resubmit?
>> On 23.07.2015 07:16, fu.wei@linaro.org wrote:
>>> From: Fu Wei <fu.wei@linaro.org>
>>>
>>> grub-core/loader/arm64/xen_boot.c
>>>
>>>   - This adds support for the Xen boot on ARM specification for arm64.
>>>   - Introduce xen_hypervisor, xen_linux, xen_initrd and xen_xsm
>>>     to load different binaries for xen boot;
>>>     Introduce xen_module to load common or custom module for xen boot.
>>>   - This Xen boot support is a separated  module for aarch64,
>>>     but reuse the existing code of devicetree in linux module.
>>>
>>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>>> ---
>>>  grub-core/Makefile.core.def       |   7 +
>>>  grub-core/loader/arm64/xen_boot.c | 685 ++++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 692 insertions(+)
>>>
>>> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
>>> index a6101de..796f7e9 100644
>>> --- a/grub-core/Makefile.core.def
>>> +++ b/grub-core/Makefile.core.def
>>> @@ -1648,6 +1648,13 @@ module = {
>>>  };
>>>
>>>  module = {
>>> +  name = xen_boot;
>>> +  common = lib/cmdline.c;
>>> +  arm64 = loader/arm64/xen_boot.c;
>>> +  enable = arm64;
>>> +};
>>> +
>>> +module = {
>>>    name = linux;
>>>    x86 = loader/i386/linux.c;
>>>    xen = loader/i386/xen.c;
>>> diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
>>> new file mode 100644
>>> index 0000000..33a65dd
>>> --- /dev/null
>>> +++ b/grub-core/loader/arm64/xen_boot.c
>>> @@ -0,0 +1,685 @@
>>> +/*
>>> + *  GRUB  --  GRand Unified Bootloader
>>> + *  Copyright (C) 2014  Free Software Foundation, Inc.
>>> + *
>>> + *  GRUB is free software: you can redistribute it and/or modify
>>> + *  it under the terms of the GNU General Public License as published by
>>> + *  the Free Software Foundation, either version 3 of the License, or
>>> + *  (at your option) any later version.
>>> + *
>>> + *  GRUB 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.
>>> + *
>>> + *  You should have received a copy of the GNU General Public License
>>> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#include <grub/cache.h>
>>> +#include <grub/charset.h>
>>> +#include <grub/command.h>
>>> +#include <grub/err.h>
>>> +#include <grub/file.h>
>>> +#include <grub/fdt.h>
>>> +#include <grub/linux.h>
>>> +#include <grub/list.h>
>>> +#include <grub/loader.h>
>>> +#include <grub/misc.h>
>>> +#include <grub/mm.h>
>>> +#include <grub/types.h>
>>> +#include <grub/cpu/linux.h>
>>> +#include <grub/efi/efi.h>
>>> +#include <grub/efi/pe32.h>   /* required by struct xen_hypervisor_header */
>>> +#include <grub/i18n.h>
>>> +#include <grub/lib/cmdline.h>
>>> +
>>> +GRUB_MOD_LICENSE ("GPLv3+");
>>> +
>>> +#define XEN_HYPERVISOR_NAME  "xen_hypervisor"
>>> +
>>> +#define MODULE_DEFAULT_ALIGN  (0x0)
>>> +#define MODULE_IMAGE_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>>> +#define MODULE_INITRD_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>>> +#define MODULE_XSM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>>> +#define MODULE_CUSTOM_MIN_ALIGN  MODULE_DEFAULT_ALIGN
>>> +
>>> +/* #define MODULE_IMAGE_COMPATIBLE  "xen,linux-image\0xen,module"
>>> +#define MODULE_INITRD_COMPATIBLE  "xen,linux-image\0xen,module"
>>> +#define MODULE_XSM_COMPATIBLE  "xen,xsm-policy\0xen,module"
>>> +#define MODULE_CUSTOM_COMPATIBLE  "xen,module" */
>>> +#define MODULE_IMAGE_COMPATIBLE  "multiboot,kernel\0multiboot,module"
>>> +#define MODULE_INITRD_COMPATIBLE  "multiboot,ramdisk\0multiboot,module"
>>> +#define MODULE_XSM_COMPATIBLE  "xen,xsm-policy\0multiboot,module"
>>> +#define MODULE_CUSTOM_COMPATIBLE  "multiboot,module"
>>> +
>>> +/* This maximum size is defined in Power.org ePAPR V1.1
>>> + * https://www.power.org/documentation/epapr-version-1-1/
>>> + * 2.2.1.1 Node Name Requirements
>>> + * node-name@unit-address
>>> + * 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
>>> + */
>>> +#define FDT_NODE_NAME_MAX_SIZE  (49)
>>> +
>>> +#define ARG_SHIFT(argc, argv) \
>>> +  do { \
>>> +    (argc)--; \
>>> +    (argv)++; \
>>> +  } while (0)
>>> +
>>> +struct compat_string_struct
>>> +{
>>> +  grub_size_t size;
>>> +  const char *compat_string;
>>> +};
>>> +typedef struct compat_string_struct compat_string_struct_t;
>>> +#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
>>> +
>>> +enum module_type
>>> +{
>>> +  MODULE_IMAGE,
>>> +  MODULE_INITRD,
>>> +  MODULE_XSM,
>>> +  MODULE_CUSTOM
>>> +};
>>> +typedef enum module_type module_type_t;
>>> +
>>> +struct fdt_node_info
>>> +{
>>> +  module_type_t type;
>>> +
>>> +  const char *compat_string;
>>> +  grub_size_t compat_string_size;
>>> +};
>>> +
>>> +struct xen_hypervisor_header
>>> +{
>>> +  struct grub_arm64_linux_kernel_header efi_head;
>>> +
>>> +  /* This is always PE\0\0.  */
>>> +  grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
>>> +  /* The COFF file header.  */
>>> +  struct grub_pe32_coff_header coff_header;
>>> +  /* The Optional header.  */
>>> +  struct grub_pe64_optional_header optional_header;
>>> +};
>>> +
>>> +struct xen_boot_binary
>>> +{
>>> +  struct xen_boot_binary *next;
>>> +  struct xen_boot_binary **prev;
>>> +  const char *name;
>>> +
>>> +  grub_addr_t start;
>>> +  grub_size_t size;
>>> +  grub_size_t align;
>>> +
>>> +  char *cmdline;
>>> +  int cmdline_size;
>>> +
>>> +  struct fdt_node_info node_info;
>>> +};
>>> +
>>> +static grub_dl_t my_mod;
>>> +
>>> +static struct xen_boot_binary *xen_hypervisor;
>>> +static struct xen_boot_binary *module_head;
>>> +static const grub_size_t module_default_align[] = {
>>> +  MODULE_IMAGE_MIN_ALIGN,
>>> +  MODULE_INITRD_MIN_ALIGN,
>>> +  MODULE_XSM_MIN_ALIGN,
>>> +  MODULE_CUSTOM_MIN_ALIGN
>>> +};
>>> +
>>> +static void *xen_boot_fdt;
>>> +static const compat_string_struct_t default_compat_string[] = {
>>> +  FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
>>> +  FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
>>> +  FDT_COMPATIBLE (MODULE_XSM_COMPATIBLE),
>>> +  FDT_COMPATIBLE (MODULE_CUSTOM_COMPATIBLE)
>>> +};
>>> +
>>> +static __inline grub_addr_t
>>> +xen_boot_address_align (grub_addr_t start, grub_size_t align)
>>> +{
>>> +  return (align ? (ALIGN_UP (start, align)) : start);
>>> +}
>>> +
>>> +/* Parse the option of xen_module command. For now, we support
>>> +   (1) --type <the compatible stream>
>>> +   We also set up the type of module in this function.
>>> +   If there are some "--type" options in the command line,
>>> +   we make a custom compatible stream in this function. */
>>> +static grub_err_t
>>> +set_module_type (grub_command_t cmd, struct xen_boot_binary *module,
>>> +              int argc, char *argv[], int *file_name_index)
>>> +{
>>> +  char **compat_string_temp_array;
>>> +  grub_size_t total_size = 0;
>>> +  int num_types = 0, i;
>>> +  char *temp = NULL;
>>> +
>>> +  *file_name_index = 0;
>>> +
>>> +  if (!grub_strcmp (cmd->name, "xen_linux"))
>>> +    module->node_info.type = MODULE_IMAGE;
>>> +  else if (!grub_strcmp (cmd->name, "xen_initrd"))
>>> +    module->node_info.type = MODULE_INITRD;
>>> +  else if (!grub_strcmp (cmd->name, "xen_xsm"))
>>> +    module->node_info.type = MODULE_XSM;
>>> +  else if (!grub_strcmp (cmd->name, "xen_module"))
>>> +    module->node_info.type = MODULE_CUSTOM;
>>> +
>>> +  /* if there are some options we need to process. */
>>> +  if (module->node_info.type == MODULE_CUSTOM)
>>> +    {
>>> +      compat_string_temp_array =
>>> +     (char **) grub_zalloc (sizeof (char *) * argc);
>>> +      if (!compat_string_temp_array)
>>> +     return grub_errno;
>>> +      /* the module type is set by "--type"(MODULE_CUSTOM) */
>>> +      while (argc > 2 && !grub_strcmp (argv[0], "--type"))
>>> +     {
>>> +       module->node_info.type = MODULE_CUSTOM;
>>> +       ARG_SHIFT (argc, argv);
>>> +       total_size += grub_strlen (argv[0]) + 1;
>>> +       compat_string_temp_array[num_types++] = argv[0];
>>> +       ARG_SHIFT (argc, argv);
>>> +       (*file_name_index) += 2;
>>> +     }
>>> +
>>> +      if (total_size)
>>> +     {
>>> +       module->node_info.compat_string = temp =
>>> +         (char *) grub_zalloc (total_size);
>>> +       if (!temp)
>>> +         {
>>> +           grub_free (compat_string_temp_array);
>>> +           return grub_errno;
>>> +         }
>>> +
>>> +       module->node_info.compat_string_size = total_size;
>>> +       for (i = 0; num_types > 0; num_types--, i++, temp++)
>>> +         {
>>> +           grub_strcpy (temp, compat_string_temp_array[i]);
>>> +           temp += grub_strlen (compat_string_temp_array[i]);
>>> +         }
>>> +     }
>>> +      else
>>> +     {
>>> +       module->node_info.compat_string =
>>> +         default_compat_string[MODULE_CUSTOM].compat_string;
>>> +       module->node_info.compat_string_size =
>>> +         default_compat_string[MODULE_CUSTOM].size;
>>> +     }
>>> +
>>> +      grub_free (compat_string_temp_array);
>>> +    }
>>> +
>>> +  return GRUB_ERR_NONE;
>>> +}
>>> +
>>> +static grub_err_t
>>> +prepare_xen_hypervisor_params (void)
>>> +{
>>> +  int chosen_node = 0;
>>> +  int retval;
>>> +
>>> +  xen_boot_fdt = grub_linux_get_fdt ();
>>> +  if (!xen_boot_fdt)
>>> +    return grub_error (GRUB_ERR_IO, "failed to get FDT");
>>> +
>>> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
>>> +  if (chosen_node < 0)
>>> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
>>> +  if (chosen_node < 1)
>>> +    return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
>>> +
>>> +  grub_dprintf ("xen_loader",
>>> +             "Xen Hypervisor cmdline : %s @ %p size:%d\n",
>>> +             xen_hypervisor->cmdline, xen_hypervisor->cmdline,
>>> +             xen_hypervisor->cmdline_size);
>>> +
>>> +  retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
>>> +                           xen_hypervisor->cmdline,
>>> +                           xen_hypervisor->cmdline_size);
>>> +  if (retval)
>>> +    return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
>>> +
>>> +  return GRUB_ERR_NONE;
>>> +}
>>> +
>>> +static grub_err_t
>>> +prepare_xen_module_params (struct xen_boot_binary *module)
>>> +{
>>> +  int retval, chosen_node = 0, module_node = 0;
>>> +  char module_name[FDT_NODE_NAME_MAX_SIZE];
>>> +
>>> +  retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
>>> +                       xen_boot_address_align (module->start,
>>> +                                               module->align));
>>> +  grub_dprintf ("xen_loader", "Module node name %s \n", module_name);
>>> +
>>> +  if (retval < (int) sizeof ("module@"))
>>> +    return grub_error (GRUB_ERR_IO, N_("failed to get FDT"));
>>> +
>>> +  chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
>>> +  if (chosen_node < 0)
>>> +    chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
>>> +  if (chosen_node < 1)
>>> +    return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
>>> +
>>> +  module_node =
>>> +    grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
>>> +  if (module_node < 0)
>>> +    module_node =
>>> +      grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
>>> +
>>> +  retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
>>> +                           module->node_info.compat_string,
>>> +                           (grub_uint32_t) module->
>>> +                           node_info.compat_string_size);
>>> +  if (retval)
>>> +    return grub_error (GRUB_ERR_IO, N_("failed to update FDT"));
>>> +
>>> +  grub_dprintf ("xen_loader", "Module %s compatible = %s size = 0x%lx\n",
>>> +             module->name, module->node_info.compat_string,
>>> +             module->node_info.compat_string_size);
>>> +
>>> +  retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
>>> +                            xen_boot_address_align (module->start,
>>> +                                                    module->align),
>>> +                            module->size);
>>> +  if (retval)
>>> +    return grub_error (GRUB_ERR_IO, N_("failed to update FDT"));
>>> +
>>> +  if (module->cmdline && module->cmdline_size > 0)
>>> +    {
>>> +      grub_dprintf ("xen_loader",
>>> +                 "Module %s cmdline : %s @ %p size:%d\n", module->name,
>>> +                 module->cmdline, module->cmdline, module->cmdline_size);
>>> +
>>> +      retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
>>> +                               module->cmdline, module->cmdline_size + 1);
>>> +      if (retval)
>>> +     return grub_error (GRUB_ERR_IO, "failed to update FDT");
>>> +    }
>>> +  else
>>> +    {
>>> +      grub_dprintf ("xen_loader", "Module %s has not bootargs!\n",
>>> +                 module->name);
>>> +    }
>>> +
>>> +  return GRUB_ERR_NONE;
>>> +}
>>> +
>>> +static grub_err_t
>>> +install_all_params (void)
>>> +{
>>> +  grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
>>> +  grub_efi_boot_services_t *b;
>>> +  grub_efi_status_t status;
>>> +
>>> +  b = grub_efi_system_table->boot_services;
>>> +  status = b->install_configuration_table (&fdt_guid, xen_boot_fdt);
>>> +  if (status != GRUB_EFI_SUCCESS)
>>> +    return grub_error (GRUB_ERR_IO, "failed to install FDT");
>>> +
>>> +  grub_dprintf ("xen_loader",
>>> +             "Installed/updated FDT configuration table @ %p\n",
>>> +             xen_boot_fdt);
>>> +
>>> +  return GRUB_ERR_NONE;
>>> +}
>>> +
>>> +static grub_err_t
>>> +clean_all_params (void)
>>> +{
>>> +  if (xen_boot_fdt)
>>> +    {
>>> +      grub_efi_free_pages ((grub_efi_physical_address_t) xen_boot_fdt,
>>> +                        BYTES_TO_PAGES (grub_fdt_get_totalsize
>>> +                                        (xen_boot_fdt)));
>>> +      xen_boot_fdt = NULL;
>>> +    }
>>> +
>>> +  return GRUB_ERR_NONE;
>>> +}
>>> +
>>> +static grub_err_t
>>> +finalize_params_xen_boot (void)
>>> +{
>>> +  struct xen_boot_binary *module;
>>> +
>>> +  if (xen_hypervisor)
>>> +    {
>>> +      if (prepare_xen_hypervisor_params () != GRUB_ERR_NONE)
>>> +     goto fail;
>>> +    }
>>> +  else
>>> +    {
>>> +      grub_dprintf ("xen_loader", "Failed to get Xen Hypervisor info!\n");
>>> +      goto fail;
>>> +    }
>>> +
>>> +  /* Set module params info */
>>> +  FOR_LIST_ELEMENTS (module, module_head)
>>> +  {
>>> +    if (module->start && module->size > 0)
>>> +      {
>>> +     grub_dprintf ("xen_loader", "Module %s @ 0x%lx size:0x%lx\n",
>>> +                   module->name,
>>> +                   xen_boot_address_align (module->start, module->align),
>>> +                   module->size);
>>> +     if (prepare_xen_module_params (module) != GRUB_ERR_NONE)
>>> +       goto fail;
>>> +      }
>>> +    else
>>> +      {
>>> +     grub_dprintf ("xen_loader", "Module info error: %s!\n", module->name);
>>> +     goto fail;
>>> +      }
>>> +  }
>>> +
>>> +  if (install_all_params () == GRUB_ERR_NONE)
>>> +    return GRUB_ERR_NONE;
>>> +
>>> +fail:
>>> +  clean_all_params ();
>>> +
>>> +  return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
>>> +}
>>> +
>>> +
>>> +static grub_err_t
>>> +xen_boot (void)
>>> +{
>>> +  grub_err_t err = finalize_params_xen_boot ();
>>> +  if (err)
>>> +    return err;
>>> +
>>> +  return grub_arm64_uefi_boot_image (xen_hypervisor->start,
>>> +                                  xen_hypervisor->size,
>>> +                                  xen_hypervisor->cmdline);
>>> +}
>>> +
>>> +static void
>>> +single_binary_unload (struct xen_boot_binary *binary)
>>> +{
>>> +  if (!binary)
>>> +    return;
>>> +
>>> +  if (binary->start && binary->size > 0)
>>> +    {
>>> +      grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
>>> +                        BYTES_TO_PAGES (binary->size + binary->align));
>>> +    }
>>> +
>>> +  if (binary->cmdline && binary->cmdline_size > 0)
>>> +    {
>>> +      grub_free (binary->cmdline);
>>> +      grub_dprintf ("xen_loader",
>>> +                 "Module %s cmdline memory free @ %p size: %d\n",
>>> +                 binary->name, binary->cmdline, binary->cmdline_size);
>>> +    }
>>> +
>>> +  if (binary->node_info.type == MODULE_CUSTOM)
>>> +    grub_free ((void *) binary->node_info.compat_string);
>>> +
>>> +  if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
>>> +    grub_list_remove (GRUB_AS_LIST (binary));
>>> +
>>> +  grub_dprintf ("xen_loader",
>>> +             "Module %s struct memory free @ %p size: 0x%lx\n",
>>> +             binary->name, binary, sizeof (binary));
>>> +  grub_free (binary);
>>> +
>>> +  return;
>>> +}
>>> +
>>> +static void
>>> +all_binaries_unload (void)
>>> +{
>>> +  struct xen_boot_binary *binary;
>>> +
>>> +  FOR_LIST_ELEMENTS (binary, module_head)
>>> +  {
>>> +    single_binary_unload (binary);
>>> +  }
>>> +
>>> +  if (xen_hypervisor)
>>> +    single_binary_unload (xen_hypervisor);
>>> +
>>> +  return;
>>> +}
>>> +
>>> +static grub_err_t
>>> +xen_unload (void)
>>> +{
>>> +  grub_linux_set_loaded (0);
>>> +  all_binaries_unload ();
>>> +  clean_all_params ();
>>> +  grub_dl_unref (my_mod);
>>> +
>>> +  return GRUB_ERR_NONE;
>>> +}
>>> +
>>> +static void
>>> +xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
>>> +                   int argc, char *argv[])
>>> +{
>>> +  binary->size = grub_file_size (file);
>>> +  grub_dprintf ("xen_loader", "Xen_boot %s file size: 0x%lx\n",
>>> +             binary->name, binary->size);
>>> +
>>> +  binary->start = (grub_addr_t) grub_efi_allocate_pages (0,
>>> +                                                      (BYTES_TO_PAGES
>>> +                                                       (binary->size +
>>> +                                                        binary->align)));
>>> +  if (!binary->start)
>>> +    {
>>> +      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>>> +      return;
>>> +    }
>>> +
>>> +  grub_dprintf ("xen_loader", "Xen_boot %s numpages: 0x%lx\n",
>>> +             binary->name, BYTES_TO_PAGES (binary->size + binary->align));
>>> +
>>> +  if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
>>> +                                                          binary->align),
>>> +                   binary->size) != (grub_ssize_t) binary->size)
>>> +    {
>>> +      single_binary_unload (binary);
>>> +      grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
>>> +      return;
>>> +    }
>>> +
>>> +  if (argc > 1)
>>> +    {
>>> +      binary->cmdline_size = grub_loader_cmdline_size (argc - 1, argv + 1);
>>> +      binary->cmdline = grub_zalloc (binary->cmdline_size);
>>> +      if (!binary->cmdline)
>>> +     {
>>> +       single_binary_unload (binary);
>>> +       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
>>> +       return;
>>> +     }
>>> +      grub_create_loader_cmdline (argc - 1, argv + 1, binary->cmdline,
>>> +                               binary->cmdline_size);
>>> +      grub_dprintf ("xen_loader",
>>> +                 "Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
>>> +                 binary->cmdline, binary->cmdline, binary->cmdline_size);
>>> +    }
>>> +  else
>>> +    {
>>> +      binary->cmdline_size = 0;
>>> +      binary->cmdline = NULL;
>>> +    }
>>> +
>>> +  grub_errno = GRUB_ERR_NONE;
>>> +  return;
>>> +}
>>> +
>>> +static grub_err_t
>>> +grub_cmd_xen_module (grub_command_t cmd, int argc, char *argv[])
>>> +{
>>> +
>>> +  struct xen_boot_binary *module = NULL;
>>> +  int file_name_index = 0;
>>> +  grub_file_t file = 0;
>>> +
>>> +  if (!argc)
>>> +    {
>>> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
>>> +      goto fail;
>>> +    }
>>> +
>>> +  if (!grub_linux_get_loaded ())
>>> +    {
>>> +      grub_error (GRUB_ERR_BAD_ARGUMENT,
>>> +               N_("you need to load the Xen Hypervisor first"));
>>> +      goto fail;
>>> +    }
>>> +
>>> +  module =
>>> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
>>> +  if (!module)
>>> +    return grub_errno;
>>> +
>>> +  /* process all the options and get module type */
>>> +  if (set_module_type (cmd, module, argc, argv, &file_name_index) !=
>>> +      GRUB_ERR_NONE)
>>> +    goto fail;
>>> +  switch (module->node_info.type)
>>> +    {
>>> +    case MODULE_IMAGE:
>>> +    case MODULE_INITRD:
>>> +    case MODULE_XSM:
>>> +      module->node_info.compat_string =
>>> +     default_compat_string[module->node_info.type].compat_string;
>>> +      module->node_info.compat_string_size =
>>> +     default_compat_string[module->node_info.type].size;
>>> +      break;
>>> +
>>> +    case MODULE_CUSTOM:
>>> +      /* we have set the node_info in set_module_type */
>>> +      break;
>>> +
>>> +    default:
>>> +      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
>>> +    }
>>> +  module->name = module->node_info.compat_string;
>>> +  module->align = module_default_align[module->node_info.type];
>>> +
>>> +  grub_dprintf ("xen_loader", "Init %s module and node info:\n"
>>> +             "compatible %s\ncompat_string_size 0x%lx\n",
>>> +             module->name, module->node_info.compat_string,
>>> +             module->node_info.compat_string_size);
>>> +
>>> +  file = grub_file_open (argv[file_name_index]);
>>> +  if (!file)
>>> +    goto fail;
>>> +
>>> +  xen_boot_binary_load (module, file, argc - file_name_index,
>>> +                     argv + file_name_index);
>>> +  if (grub_errno == GRUB_ERR_NONE)
>>> +    grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
>>> +
>>> +fail:
>>> +  if (file)
>>> +    grub_file_close (file);
>>> +  if (grub_errno != GRUB_ERR_NONE)
>>> +    single_binary_unload (module);
>>> +
>>> +  return grub_errno;
>>> +}
>>> +
>>> +static grub_err_t
>>> +grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
>>> +                      int argc, char *argv[])
>>> +{
>>> +  struct xen_hypervisor_header sh;
>>> +  grub_file_t file = NULL;
>>> +
>>> +  grub_dl_ref (my_mod);
>>> +
>>> +  if (!argc)
>>> +    {
>>> +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
>>> +      goto fail;
>>> +    }
>>> +
>>> +  file = grub_file_open (argv[0]);
>>> +  if (!file)
>>> +    goto fail;
>>> +
>>> +  if (grub_file_read (file, &sh, sizeof (sh)) != (long) sizeof (sh))
>>> +    goto fail;
>>> +  if (grub_arm64_uefi_check_image
>>> +      ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
>>> +    goto fail;
>>> +  grub_file_seek (file, 0);
>>> +
>>> +  /* if another module has called grub_loader_set,
>>> +     we need to make sure that another module is unloaded properly */
>>> +  grub_loader_unset ();
>>> +
>>> +  xen_hypervisor =
>>> +    (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
>>> +  if (!xen_hypervisor)
>>> +    return grub_errno;
>>> +
>>> +  xen_hypervisor->name = XEN_HYPERVISOR_NAME;
>>> +  xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
>>> +
>>> +  xen_boot_binary_load (xen_hypervisor, file, argc, argv);
>>> +  if (grub_errno == GRUB_ERR_NONE)
>>> +    {
>>> +      grub_loader_set (xen_boot, xen_unload, 0);
>>> +      grub_linux_set_loaded (1);
>>> +    }
>>> +
>>> +fail:
>>> +  if (file)
>>> +    grub_file_close (file);
>>> +  if (grub_errno != GRUB_ERR_NONE)
>>> +    {
>>> +      grub_linux_set_loaded (0);
>>> +      all_binaries_unload ();
>>> +      grub_dl_unref (my_mod);
>>> +    }
>>> +
>>> +  return grub_errno;
>>> +}
>>> +
>>> +static grub_command_t cmd_xen_hypervisor, cmd_xen_module;
>>> +static grub_command_t cmd_xen_linux, cmd_xen_initrd, cmd_xen_xsm;
>>> +
>>> +GRUB_MOD_INIT (xen_boot)
>>> +{
>>> +  cmd_xen_hypervisor =
>>> +    grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
>>> +                        N_("Load a xen hypervisor."));
>>> +  cmd_xen_linux =
>>> +    grub_register_command ("xen_linux", grub_cmd_xen_module, 0,
>>> +                        N_("Load a xen linux kernel for dom0."));
>>> +  cmd_xen_initrd =
>>> +    grub_register_command ("xen_initrd", grub_cmd_xen_module, 0,
>>> +                        N_("Load a xen initrd for dom0."));
>>> +  cmd_xen_xsm =
>>> +    grub_register_command ("xen_xsm", grub_cmd_xen_module, 0,
>>> +                        N_("Load a xen security module."));
>>> +  cmd_xen_module =
>>> +    grub_register_command ("xen_module", grub_cmd_xen_module, 0,
>>> +                        N_("Load a xen module."));
>>> +  my_mod = mod;
>>> +}
>>> +
>>> +GRUB_MOD_FINI (xen_boot)
>>> +{
>>> +  grub_unregister_command (cmd_xen_hypervisor);
>>> +  grub_unregister_command (cmd_xen_linux);
>>> +  grub_unregister_command (cmd_xen_initrd);
>>> +  grub_unregister_command (cmd_xen_xsm);
>>> +  grub_unregister_command (cmd_xen_module);
>>> +}
>>>
>>
>>
>
>
>
> --
> 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


^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 2/4] arm64: Add xen_boot module file
  2015-11-03 14:57           ` Fu Wei
@ 2015-11-03 15:22             ` Ian Campbell
  -1 siblings, 0 replies; 550+ messages in thread
From: Ian Campbell @ 2015-11-03 15:22 UTC (permalink / raw)
  To: Fu Wei, Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: The development of GNU GRUB, xen-devel, Stefano Stabellini,
	Andrei Borzenkov, Jon Masters, Leif Lindholm, Ryan Harkin,
	Linaro UEFI Mailman List

On Tue, 2015-11-03 at 22:57 +0800, Fu Wei wrote:
> Hi Vladimir,
> 
> After discussing with Ian Campbell,   Since we already can load all
> the necessary binaries for Xen boot on arm64 for now,  we don't really
> need "xen_module" command now.
> But maybe someday , xen need a new type of binary in boot time, then
> we still need this support.

You mean support for "--type" passed to the xen_module command, right? I
thought the xen_module stuff had been applied. Or am I misunderstanding
which bits have been applied?

> So I will submit  a   "xen_module" command patch soon, in case we need
> it.

Just to clarify, my suggestion was to repost the bits which were omitted
from the prior patches just so that they are available in the ML archives
etc should anyone ever want to resurrect them in the future.

Ian.


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 2/4] arm64: Add xen_boot module file
@ 2015-11-03 15:22             ` Ian Campbell
  0 siblings, 0 replies; 550+ messages in thread
From: Ian Campbell @ 2015-11-03 15:22 UTC (permalink / raw)
  To: Fu Wei, Vladimir 'φ-coder/phcoder' Serbinenko
  Cc: The development of GNU GRUB, xen-devel, Stefano Stabellini,
	Andrei Borzenkov, Jon Masters, Leif Lindholm, Ryan Harkin,
	Linaro UEFI Mailman List

On Tue, 2015-11-03 at 22:57 +0800, Fu Wei wrote:
> Hi Vladimir,
> 
> After discussing with Ian Campbell,   Since we already can load all
> the necessary binaries for Xen boot on arm64 for now,  we don't really
> need "xen_module" command now.
> But maybe someday , xen need a new type of binary in boot time, then
> we still need this support.

You mean support for "--type" passed to the xen_module command, right? I
thought the xen_module stuff had been applied. Or am I misunderstanding
which bits have been applied?

> So I will submit  a   "xen_module" command patch soon, in case we need
> it.

Just to clarify, my suggestion was to repost the bits which were omitted
from the prior patches just so that they are available in the ML archives
etc should anyone ever want to resurrect them in the future.

Ian.



^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 2/4] arm64: Add xen_boot module file
  2015-11-03 15:22             ` Ian Campbell
  (?)
@ 2015-11-05  9:46             ` Fu Wei
  -1 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2015-11-05  9:46 UTC (permalink / raw)
  To: Ian Campbell
  Cc: The development of GNU GRUB, xen-devel, Stefano Stabellini,
	Andrei Borzenkov,
	Vladimir 'φ-coder/phcoder' Serbinenko,
	Leif Lindholm, Ryan Harkin, Linaro UEFI Mailman List,
	Jon Masters

Hi Ian,

On 3 November 2015 at 23:22, Ian Campbell <ian.campbell@citrix.com> wrote:
> On Tue, 2015-11-03 at 22:57 +0800, Fu Wei wrote:
>> Hi Vladimir,
>>
>> After discussing with Ian Campbell,   Since we already can load all
>> the necessary binaries for Xen boot on arm64 for now,  we don't really
>> need "xen_module" command now.
>> But maybe someday , xen need a new type of binary in boot time, then
>> we still need this support.
>
> You mean support for "--type" passed to the xen_module command, right? I
> thought the xen_module stuff had been applied. Or am I misunderstanding
> which bits have been applied?

Actually, I mean: xen-module command is for "--type" support. If we
don't need "--type" now, we can delete  xen-module code(which has been
deleted by Vladimir from my patch, so now, the upstream grub has not
--type support).
Vladimir has applied most of my patch, except xen-module command code.

>
>> So I will submit  a   "xen_module" command patch soon, in case we need
>> it.
>
> Just to clarify, my suggestion was to repost the bits which were omitted
> from the prior patches just so that they are available in the ML archives
> etc should anyone ever want to resurrect them in the future.

yes, that is what I am gonna do.

>
> Ian.
>



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
       [not found]               ` <CAA91j0XKvpgVVWuv79AEv6bguxrQrV4q+eG5Xtw+UBvMSmDF-w@mail.gmail.com>
@ 2015-11-12 10:43                 ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 0 replies; 550+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2015-11-12 10:43 UTC (permalink / raw)
  To: Andrei Borzenkov, The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 1132 bytes --]

On 10.11.2015 08:01, Andrei Borzenkov wrote:
> Not really, although this is a good observation. Actually I think that
> xen_initrd should indeed have behavior 1, because what it does is
> provide initrd image to Linux kernel, and - although not often used -
> initrd image may be constructed by concatenation.
> 
> But what I meant - initially it was intended to have xen_module with
> some options. As soon as we add option parsing we must have defined
> way to differentiate between opption for xen_module itself and option
> for module loaded by xen_module. I.e. it should be possible to
> 
> xen_module --type=XXX some-module --option1=FOO --option2=bar
Yes, everything before the filename would be an option to command
itself. We have a similar thing with multiboot command. Currently there
are no options to xen_*, so no code to handle them. But it's impossible
to get any confusion as if you currently specify any of such future
options you'll get an error of bad file, so we won't break any
compatibility. Do you see any reason to introduce flag-handling code
now? Would it be for better error message?


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH v2 0/2] acpi, apei: add BERT support
  2015-08-18 16:44 ` [PATCH v2 0/2] acpi, apei: add BERT support fu.wei
  2015-08-18 16:44   ` [PATCH v2 1/2] acpi, apei: add Boot Error Record Table (BERT) support fu.wei
  2015-08-18 16:44   ` [PATCH v2 2/2] acpi, apei, bert: Clear error status at the end of error handling fu.wei
@ 2015-12-15 16:39   ` Timur Tabi
  2016-01-06 18:24     ` Fu Wei
  2 siblings, 1 reply; 550+ messages in thread
From: Timur Tabi @ 2015-12-15 16:39 UTC (permalink / raw)
  To: Fu Wei
  Cc: Linaro ACPI Mailman List, lkml, Jonathan (Zhixiong) Zhang,
	tony.luck, gong.chen, ying.huang, Tomasz Nowicki,
	Rafael J. Wysocki, matt.fleming, Jon Masters, Will Deacon, bp,
	Catalin Marinas, Wei Fu, tbaicar, rruigrok

On Tue, Aug 18, 2015 at 11:44 AM,  <fu.wei@linaro.org> wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> ACPI/APEI is designed to verifiy/report H/W errors, like Corrected
> Error(CE) and Uncorrected Error(UC). It contains four tables: HEST,
> ERST, EINJ and BERT. The first three tables have been merged for
> a long time, but because of lacking BIOS support for BERT, the
> support for BERT is pending until now. Recently on ARM 64 platform
> it is has been supported. So here we come.
>
> The following log is a BERT record after system reboot because of
> hitting a fatal error.

Both patches:

Tested-by: Tyler Baicar <tbaicar@codeaurora.org>

on a 4.3 kernel.  We'd like to see these patches merged for 4.5.

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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 1/2] acpi, apei: add Boot Error Record Table (BERT) support
  2015-08-18 16:44   ` [PATCH v2 1/2] acpi, apei: add Boot Error Record Table (BERT) support fu.wei
@ 2015-12-16 10:29     ` Borislav Petkov
  2016-01-06 18:21       ` Fu Wei
  0 siblings, 1 reply; 550+ messages in thread
From: Borislav Petkov @ 2015-12-16 10:29 UTC (permalink / raw)
  To: fu.wei
  Cc: linaro-acpi, linux-kernel, zjzhang, tony.luck, gong.chen,
	ying.huang, tomasz.nowicki, tekkamanninja, graeme.gregory,
	al.stone, hanjun.guo, jcm, mark.rutland, catalin.marinas,
	will.deacon, rjw, matt.fleming, Chen, Gong

On Wed, Aug 19, 2015 at 12:44:16AM +0800, fu.wei@linaro.org wrote:
> From: Huang Ying <ying.huang@intel.com>
> 
> Under normal circumstances, when a hardware error occurs, kernel will
> be notified via NMI, MCE or some other method, then kernel will
> process the error condition, report it, and recover it if possible.
> But sometime, the situation is so bad, so that firmware may choose to
> reset directly without notifying Linux kernel.
> 
> Linux kernel can use the Boot Error Record Table (BERT) to get the
> un-notified hardware errors that occurred in a previous boot. In this
> patch, the error information is reported via printk.
> 
> For more information about BERT, please refer to ACPI Specification
> version 6.0, section 18.3.1:
>   http://www.uefi.org/sites/default/files/resources/ACPI_6.0.pdf
> 
> [Tony: Applied some cleanups suggested by Fu Wei]
> [Fu Wei: delete EXPORT_SYMBOL_GPL(bert_disable), and do some cleanups]
> 
> Signed-off-by: Huang Ying <ying.huang@intel.com>
> Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
> Signed-off-by: Chen, Gong <gong.chen@linux.intel.com>
> Tested-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
> Tested-by: Fu Wei <fu.wei@linaro.org>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  Documentation/kernel-parameters.txt |   3 +
>  drivers/acpi/apei/Makefile          |   2 +-
>  drivers/acpi/apei/bert.c            | 162 ++++++++++++++++++++++++++++++++++++
>  include/acpi/apei.h                 |   1 +
>  4 files changed, 167 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
> index 1d6f045..7c6402c 100644
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -554,6 +554,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
>  
>  	bootmem_debug	[KNL] Enable bootmem allocator debug messages.
>  
> +	bert_disable	[ACPI]
> +			Disable Boot Error Record Table (BERT) support.

Please document what that new parameter is good for.

> +
>  	bttv.card=	[HW,V4L] bttv (bt848 + bt878 based grabber cards)
>  	bttv.radio=	Most important insmod options are available as
>  			kernel args too.
> diff --git a/drivers/acpi/apei/Makefile b/drivers/acpi/apei/Makefile
> index 5d575a9..e50573d 100644
> --- a/drivers/acpi/apei/Makefile
> +++ b/drivers/acpi/apei/Makefile
> @@ -3,4 +3,4 @@ obj-$(CONFIG_ACPI_APEI_GHES)	+= ghes.o
>  obj-$(CONFIG_ACPI_APEI_EINJ)	+= einj.o
>  obj-$(CONFIG_ACPI_APEI_ERST_DEBUG) += erst-dbg.o
>  
> -apei-y := apei-base.o hest.o erst.o
> +apei-y := apei-base.o hest.o erst.o bert.o
> diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c
> new file mode 100644
> index 0000000..1426227
> --- /dev/null
> +++ b/drivers/acpi/apei/bert.c
> @@ -0,0 +1,162 @@
> +/*
> + * APEI Boot Error Record Table (BERT) support
> + *
> + * Copyright 2011 Intel Corp.
> + *   Author: Huang Ying <ying.huang@intel.com>
> + *
> + * Under normal circumstances, when a hardware error occurs, kernel
> + * will be notified via NMI, MCE or some other method, then kernel
> + * will process the error condition, report it, and recover it if
> + * possible. But sometime, the situation is so bad, so that firmware
> + * may choose to reset directly without notifying Linux kernel.
> + *
> + * Linux kernel can use the Boot Error Record Table (BERT) to get the
> + * un-notified hardware errors that occurred in a previous boot.
> + *
> + * For more information about BERT, please refer to ACPI Specification
> + * version 4.0, section 17.3.1
> + *
> + * This file is licensed under GPLv2.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/acpi.h>
> +#include <linux/io.h>
> +
> +#include "apei-internal.h"
> +
> +#define BERT_PFX "BERT: "

This is done with pr_fmt

> +static int bert_disable;
> +
> +static void __init bert_print_all(struct acpi_hest_generic_status *region,
> +				  unsigned int region_len)
> +{
> +	struct acpi_hest_generic_status *estatus = region;
> +	int remain = region_len;
> +	u32 estatus_len;
> +	int first = 1;

	if (!estatus->block_status)
		return;

> +	while (remain > sizeof(struct acpi_hest_generic_status)) {
> +		/* No more error record */

			     ... records */

> +		if (!estatus->block_status)
> +			break;

This test should happen when you enter the function (see above) and when
you assign to estatus, i.e. below, at the end of the while loop body:

		estatus = (void *)estatus + estatus_len;
		if (!estatus->block_status)
			break;

> +
> +		estatus_len = cper_estatus_len(estatus);
> +		if (estatus_len < sizeof(struct acpi_hest_generic_status) ||
> +		    remain < estatus_len) {
> +			pr_err(FW_BUG BERT_PFX
> +			       "Invalid error status block with length %u\n",

				"Invalid status block length (%u)"

> +			       estatus_len);
> +			return;
> +		}
> +
> +		if (cper_estatus_check(estatus)) {
> +			pr_err(FW_BUG BERT_PFX "Invalid error status block\n");

						"Invalid error record."
> +			goto next;
> +		}
> +
> +		if (first) {
> +			pr_info(HW_ERR "Error record from previous boot:\n");

					Error records<--- plural.

> +			first = 0;
> +		}

We have pr_info_once() for this.

> +
> +		cper_estatus_print(KERN_INFO HW_ERR, estatus);
> +next:
> +		estatus = (void *)estatus + estatus_len;
> +		remain -= estatus_len;
> +	}
> +}
> +
> +static int __init setup_bert_disable(char *str)
> +{
> +	bert_disable = 1;
> +
> +	return 0;
> +}
> +__setup("bert_disable", setup_bert_disable);
> +
> +static int __init bert_check_table(struct acpi_table_bert *bert_tab)
> +{
> +	if (bert_tab->header.length < sizeof(struct acpi_table_bert))
> +		return -EINVAL;

\n here

> +	if (bert_tab->region_length &&

This test looks redundant if you're going to compare it to the size of
the BERT region struct below.

> +	    bert_tab->region_length < sizeof(struct acpi_bert_region))
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int __init bert_init(void)
> +{
> +	struct acpi_hest_generic_status *bert_region;
> +	struct acpi_table_bert *bert_tab;
> +	unsigned int region_len;
> +	acpi_status status;
> +	struct resource *r;
> +	int rc = -EINVAL;
> +
> +	if (acpi_disabled)
> +		goto out;
> +
> +	if (bert_disable) {
> +		pr_info(BERT_PFX "Boot Error Record Table (BERT) support is disabled.\n");
> +		goto out;
> +	}
> +
> +	status = acpi_get_table(ACPI_SIG_BERT, 0,
> +				(struct acpi_table_header **)&bert_tab);

No need to break that line, just leave it stick out.

> +	if (status == AE_NOT_FOUND) {
> +		pr_err(BERT_PFX "Table is not found!\n");

This will get issued on *all* machines which don't have BERT - which
is the majority now, I'm afraid - and that information is useless to
people. It's not like they can do anything about it short of overriding
their own firmware.

So please remove that printk.

> +		goto out;
> +	} else if (ACPI_FAILURE(status)) {
> +		const char *msg = acpi_format_exception(status);
> +
> +		pr_err(BERT_PFX "Failed to get table, %s\n", msg);
> +		goto out;
> +	}
> +
> +	rc = bert_check_table(bert_tab);
> +	if (rc) {
> +		pr_err(FW_BUG BERT_PFX "BERT table is invalid\n");

Prefix already has "BERT". Either write it out:

	"BERT: Boot Error Record Table invalid"

or make it shorter:

	"BERT: table invalid."

> +		goto out;
> +	}
> +
> +	region_len = bert_tab->region_length;
> +	if (!region_len) {
> +		rc = 0;
> +		goto out;
> +	}

Huh, we just checked ->region_length in bert_check_table(). This test is
redundant.

> +
> +	r = request_mem_region(bert_tab->address, region_len, "APEI BERT");
> +	if (!r) {
> +		pr_err(BERT_PFX "Can't request iomem region <%016llx-%016llx>\n",
> +		       (unsigned long long)bert_tab->address,
> +		       (unsigned long long)bert_tab->address + region_len - 1);
> +		rc = -EIO;
> +		goto out;
> +	}
> +
> +	bert_region = ioremap_cache(bert_tab->address, region_len);
> +	if (!bert_region) {
> +		rc = -ENOMEM;
> +		goto out_release;
> +	}
> +
> +	bert_print_all(bert_region, region_len);
> +
> +	iounmap(bert_region);
> +
> +out_release:
> +	release_mem_region(bert_tab->address, region_len);
> +out:
> +	if (rc)
> +		bert_disable = 1;

This assignment is redundant. We're not testing it anywhere else after
bert_init() has run.

> +
> +	return rc;
> +}
> +
> +late_initcall(bert_init);
> diff --git a/include/acpi/apei.h b/include/acpi/apei.h
> index 76284bb..284801a 100644
> --- a/include/acpi/apei.h
> +++ b/include/acpi/apei.h
> @@ -23,6 +23,7 @@ extern bool ghes_disable;
>  #else
>  #define ghes_disable 1
>  #endif
> +extern int bert_disable;
>  
>  #ifdef CONFIG_ACPI_APEI
>  void __init acpi_hest_init(void);
> -- 
> 2.4.3
> 
> 

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 2/2] acpi, apei, bert: Clear error status at the end of error handling
  2015-08-18 16:44   ` [PATCH v2 2/2] acpi, apei, bert: Clear error status at the end of error handling fu.wei
@ 2015-12-16 10:30     ` Borislav Petkov
  0 siblings, 0 replies; 550+ messages in thread
From: Borislav Petkov @ 2015-12-16 10:30 UTC (permalink / raw)
  To: fu.wei
  Cc: linaro-acpi, linux-kernel, zjzhang, tony.luck, gong.chen,
	ying.huang, tomasz.nowicki, tekkamanninja, graeme.gregory,
	al.stone, hanjun.guo, jcm, mark.rutland, catalin.marinas,
	will.deacon, rjw, matt.fleming, Chen, Gong

On Wed, Aug 19, 2015 at 12:44:17AM +0800, fu.wei@linaro.org wrote:
> From: Tomasz Nowicki <tomasz.nowicki@linaro.org>
> 
> Once error log is printed out clear error status so it would not be
> print during next boot again.
> 
> Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
> Signed-off-by: Chen, Gong <gong.chen@linux.intel.com>
> Tested-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> ---
>  drivers/acpi/apei/bert.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c
> index 1426227..dc2b79f 100644
> --- a/drivers/acpi/apei/bert.c
> +++ b/drivers/acpi/apei/bert.c
> @@ -65,6 +65,9 @@ static void __init bert_print_all(struct acpi_hest_generic_status *region,
>  		}
>  
>  		cper_estatus_print(KERN_INFO HW_ERR, estatus);
> +
> +		/* Clear error status */
> +		estatus->block_status = 0;
>  next:
>  		estatus = (void *)estatus + estatus_len;
>  		remain -= estatus_len;
> -- 

This one should be merged with the previous patch.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 1/2] acpi, apei: add Boot Error Record Table (BERT) support
  2015-12-16 10:29     ` Borislav Petkov
@ 2016-01-06 18:21       ` Fu Wei
  2016-01-06 18:31         ` Borislav Petkov
  0 siblings, 1 reply; 550+ messages in thread
From: Fu Wei @ 2016-01-06 18:21 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Linaro ACPI Mailman List, LKML, Zhang, Jonathan Zhixiong,
	Tony Luck, Chen, Gong, Huang Ying, Tomasz Nowicki, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Jon Masters, Mark Rutland,
	Catalin Marinas, Will Deacon, Rafael Wysocki, matt.fleming, Chen,
	Gong

Hi Borislav,

Thanks for your review.
I totally agree all your comment
I have made a new patch, and that is in testing, I will post it ASAP

On 16 December 2015 at 18:29, Borislav Petkov <bp@alien8.de> wrote:
> On Wed, Aug 19, 2015 at 12:44:16AM +0800, fu.wei@linaro.org wrote:
>> From: Huang Ying <ying.huang@intel.com>
>>
>> Under normal circumstances, when a hardware error occurs, kernel will
>> be notified via NMI, MCE or some other method, then kernel will
>> process the error condition, report it, and recover it if possible.
>> But sometime, the situation is so bad, so that firmware may choose to
>> reset directly without notifying Linux kernel.
>>
>> Linux kernel can use the Boot Error Record Table (BERT) to get the
>> un-notified hardware errors that occurred in a previous boot. In this
>> patch, the error information is reported via printk.
>>
>> For more information about BERT, please refer to ACPI Specification
>> version 6.0, section 18.3.1:
>>   http://www.uefi.org/sites/default/files/resources/ACPI_6.0.pdf
>>
>> [Tony: Applied some cleanups suggested by Fu Wei]
>> [Fu Wei: delete EXPORT_SYMBOL_GPL(bert_disable), and do some cleanups]
>>
>> Signed-off-by: Huang Ying <ying.huang@intel.com>
>> Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
>> Signed-off-by: Chen, Gong <gong.chen@linux.intel.com>
>> Tested-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
>> Tested-by: Fu Wei <fu.wei@linaro.org>
>> Signed-off-by: Tony Luck <tony.luck@intel.com>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  Documentation/kernel-parameters.txt |   3 +
>>  drivers/acpi/apei/Makefile          |   2 +-
>>  drivers/acpi/apei/bert.c            | 162 ++++++++++++++++++++++++++++++++++++
>>  include/acpi/apei.h                 |   1 +
>>  4 files changed, 167 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
>> index 1d6f045..7c6402c 100644
>> --- a/Documentation/kernel-parameters.txt
>> +++ b/Documentation/kernel-parameters.txt
>> @@ -554,6 +554,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
>>
>>       bootmem_debug   [KNL] Enable bootmem allocator debug messages.
>>
>> +     bert_disable    [ACPI]
>> +                     Disable Boot Error Record Table (BERT) support.
>
> Please document what that new parameter is good for.
>
>> +
>>       bttv.card=      [HW,V4L] bttv (bt848 + bt878 based grabber cards)
>>       bttv.radio=     Most important insmod options are available as
>>                       kernel args too.
>> diff --git a/drivers/acpi/apei/Makefile b/drivers/acpi/apei/Makefile
>> index 5d575a9..e50573d 100644
>> --- a/drivers/acpi/apei/Makefile
>> +++ b/drivers/acpi/apei/Makefile
>> @@ -3,4 +3,4 @@ obj-$(CONFIG_ACPI_APEI_GHES)  += ghes.o
>>  obj-$(CONFIG_ACPI_APEI_EINJ) += einj.o
>>  obj-$(CONFIG_ACPI_APEI_ERST_DEBUG) += erst-dbg.o
>>
>> -apei-y := apei-base.o hest.o erst.o
>> +apei-y := apei-base.o hest.o erst.o bert.o
>> diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c
>> new file mode 100644
>> index 0000000..1426227
>> --- /dev/null
>> +++ b/drivers/acpi/apei/bert.c
>> @@ -0,0 +1,162 @@
>> +/*
>> + * APEI Boot Error Record Table (BERT) support
>> + *
>> + * Copyright 2011 Intel Corp.
>> + *   Author: Huang Ying <ying.huang@intel.com>
>> + *
>> + * Under normal circumstances, when a hardware error occurs, kernel
>> + * will be notified via NMI, MCE or some other method, then kernel
>> + * will process the error condition, report it, and recover it if
>> + * possible. But sometime, the situation is so bad, so that firmware
>> + * may choose to reset directly without notifying Linux kernel.
>> + *
>> + * Linux kernel can use the Boot Error Record Table (BERT) to get the
>> + * un-notified hardware errors that occurred in a previous boot.
>> + *
>> + * For more information about BERT, please refer to ACPI Specification
>> + * version 4.0, section 17.3.1
>> + *
>> + * This file is licensed under GPLv2.
>> + *
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/init.h>
>> +#include <linux/acpi.h>
>> +#include <linux/io.h>
>> +
>> +#include "apei-internal.h"
>> +
>> +#define BERT_PFX "BERT: "
>
> This is done with pr_fmt
>
>> +static int bert_disable;
>> +
>> +static void __init bert_print_all(struct acpi_hest_generic_status *region,
>> +                               unsigned int region_len)
>> +{
>> +     struct acpi_hest_generic_status *estatus = region;
>> +     int remain = region_len;
>> +     u32 estatus_len;
>> +     int first = 1;
>
>         if (!estatus->block_status)
>                 return;
>
>> +     while (remain > sizeof(struct acpi_hest_generic_status)) {
>> +             /* No more error record */
>
>                              ... records */
>
>> +             if (!estatus->block_status)
>> +                     break;
>
> This test should happen when you enter the function (see above) and when
> you assign to estatus, i.e. below, at the end of the while loop body:
>
>                 estatus = (void *)estatus + estatus_len;
>                 if (!estatus->block_status)
>                         break;
>
>> +
>> +             estatus_len = cper_estatus_len(estatus);
>> +             if (estatus_len < sizeof(struct acpi_hest_generic_status) ||
>> +                 remain < estatus_len) {
>> +                     pr_err(FW_BUG BERT_PFX
>> +                            "Invalid error status block with length %u\n",
>
>                                 "Invalid status block length (%u)"
>
>> +                            estatus_len);
>> +                     return;
>> +             }
>> +
>> +             if (cper_estatus_check(estatus)) {
>> +                     pr_err(FW_BUG BERT_PFX "Invalid error status block\n");
>
>                                                 "Invalid error record."
>> +                     goto next;
>> +             }
>> +
>> +             if (first) {
>> +                     pr_info(HW_ERR "Error record from previous boot:\n");
>
>                                         Error records<--- plural.
>
>> +                     first = 0;
>> +             }
>
> We have pr_info_once() for this.
>
>> +
>> +             cper_estatus_print(KERN_INFO HW_ERR, estatus);
>> +next:
>> +             estatus = (void *)estatus + estatus_len;
>> +             remain -= estatus_len;
>> +     }
>> +}
>> +
>> +static int __init setup_bert_disable(char *str)
>> +{
>> +     bert_disable = 1;
>> +
>> +     return 0;
>> +}
>> +__setup("bert_disable", setup_bert_disable);
>> +
>> +static int __init bert_check_table(struct acpi_table_bert *bert_tab)
>> +{
>> +     if (bert_tab->header.length < sizeof(struct acpi_table_bert))
>> +             return -EINVAL;
>
> \n here
>
>> +     if (bert_tab->region_length &&
>
> This test looks redundant if you're going to compare it to the size of
> the BERT region struct below.
>
>> +         bert_tab->region_length < sizeof(struct acpi_bert_region))
>> +             return -EINVAL;
>> +
>> +     return 0;
>> +}
>> +
>> +static int __init bert_init(void)
>> +{
>> +     struct acpi_hest_generic_status *bert_region;
>> +     struct acpi_table_bert *bert_tab;
>> +     unsigned int region_len;
>> +     acpi_status status;
>> +     struct resource *r;
>> +     int rc = -EINVAL;
>> +
>> +     if (acpi_disabled)
>> +             goto out;
>> +
>> +     if (bert_disable) {
>> +             pr_info(BERT_PFX "Boot Error Record Table (BERT) support is disabled.\n");
>> +             goto out;
>> +     }
>> +
>> +     status = acpi_get_table(ACPI_SIG_BERT, 0,
>> +                             (struct acpi_table_header **)&bert_tab);
>
> No need to break that line, just leave it stick out.
>
>> +     if (status == AE_NOT_FOUND) {
>> +             pr_err(BERT_PFX "Table is not found!\n");
>
> This will get issued on *all* machines which don't have BERT - which
> is the majority now, I'm afraid - and that information is useless to
> people. It's not like they can do anything about it short of overriding
> their own firmware.
>
> So please remove that printk.
>
>> +             goto out;
>> +     } else if (ACPI_FAILURE(status)) {
>> +             const char *msg = acpi_format_exception(status);
>> +
>> +             pr_err(BERT_PFX "Failed to get table, %s\n", msg);
>> +             goto out;
>> +     }
>> +
>> +     rc = bert_check_table(bert_tab);
>> +     if (rc) {
>> +             pr_err(FW_BUG BERT_PFX "BERT table is invalid\n");
>
> Prefix already has "BERT". Either write it out:
>
>         "BERT: Boot Error Record Table invalid"
>
> or make it shorter:
>
>         "BERT: table invalid."
>
>> +             goto out;
>> +     }
>> +
>> +     region_len = bert_tab->region_length;
>> +     if (!region_len) {
>> +             rc = 0;
>> +             goto out;
>> +     }
>
> Huh, we just checked ->region_length in bert_check_table(). This test is
> redundant.
>
>> +
>> +     r = request_mem_region(bert_tab->address, region_len, "APEI BERT");
>> +     if (!r) {
>> +             pr_err(BERT_PFX "Can't request iomem region <%016llx-%016llx>\n",
>> +                    (unsigned long long)bert_tab->address,
>> +                    (unsigned long long)bert_tab->address + region_len - 1);
>> +             rc = -EIO;
>> +             goto out;
>> +     }
>> +
>> +     bert_region = ioremap_cache(bert_tab->address, region_len);
>> +     if (!bert_region) {
>> +             rc = -ENOMEM;
>> +             goto out_release;
>> +     }
>> +
>> +     bert_print_all(bert_region, region_len);
>> +
>> +     iounmap(bert_region);
>> +
>> +out_release:
>> +     release_mem_region(bert_tab->address, region_len);
>> +out:
>> +     if (rc)
>> +             bert_disable = 1;
>
> This assignment is redundant. We're not testing it anywhere else after
> bert_init() has run.
>
>> +
>> +     return rc;
>> +}
>> +
>> +late_initcall(bert_init);
>> diff --git a/include/acpi/apei.h b/include/acpi/apei.h
>> index 76284bb..284801a 100644
>> --- a/include/acpi/apei.h
>> +++ b/include/acpi/apei.h
>> @@ -23,6 +23,7 @@ extern bool ghes_disable;
>>  #else
>>  #define ghes_disable 1
>>  #endif
>> +extern int bert_disable;
>>
>>  #ifdef CONFIG_ACPI_APEI
>>  void __init acpi_hest_init(void);
>> --
>> 2.4.3
>>
>>
>
> --
> Regards/Gruss,
>     Boris.
>
> ECO tip #101: Trim your mails when you reply.



-- 
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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [Linaro-acpi] [PATCH v2 0/2] acpi, apei: add BERT support
  2015-12-15 16:39   ` [Linaro-acpi] [PATCH v2 0/2] acpi, apei: add BERT support Timur Tabi
@ 2016-01-06 18:24     ` Fu Wei
  0 siblings, 0 replies; 550+ messages in thread
From: Fu Wei @ 2016-01-06 18:24 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Linaro ACPI Mailman List, lkml, Jonathan (Zhixiong) Zhang,
	Tony Luck, Chen, Gong, Huang Ying, Tomasz Nowicki,
	Rafael J. Wysocki, matt.fleming, Jon Masters, Will Deacon, bp,
	Catalin Marinas, Wei Fu, tbaicar, rruigrok

Hi Tyler,

Great thanks for your testing,
But I just made a new one according to Borislav's suggestion.
Please help us again, if you get some time.  :-)

Thanks

On 16 December 2015 at 00:39, Timur Tabi <timur@codeaurora.org> wrote:
> On Tue, Aug 18, 2015 at 11:44 AM,  <fu.wei@linaro.org> wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> ACPI/APEI is designed to verifiy/report H/W errors, like Corrected
>> Error(CE) and Uncorrected Error(UC). It contains four tables: HEST,
>> ERST, EINJ and BERT. The first three tables have been merged for
>> a long time, but because of lacking BIOS support for BERT, the
>> support for BERT is pending until now. Recently on ARM 64 platform
>> it is has been supported. So here we come.
>>
>> The following log is a BERT record after system reboot because of
>> hitting a fatal error.
>
> Both patches:
>
> Tested-by: Tyler Baicar <tbaicar@codeaurora.org>
>
> on a 4.3 kernel.  We'd like to see these patches merged for 4.5.
>
> --
> 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

^ permalink raw reply	[flat|nested] 550+ messages in thread

* Re: [PATCH v2 1/2] acpi, apei: add Boot Error Record Table (BERT) support
  2016-01-06 18:21       ` Fu Wei
@ 2016-01-06 18:31         ` Borislav Petkov
  0 siblings, 0 replies; 550+ messages in thread
From: Borislav Petkov @ 2016-01-06 18:31 UTC (permalink / raw)
  To: Fu Wei
  Cc: Linaro ACPI Mailman List, LKML, Zhang, Jonathan Zhixiong,
	Tony Luck, Chen, Gong, Huang Ying, Tomasz Nowicki, Wei Fu,
	G Gregory, Al Stone, Hanjun Guo, Jon Masters, Mark Rutland,
	Catalin Marinas, Will Deacon, Rafael Wysocki, matt.fleming, Chen,
	Gong

On Thu, Jan 07, 2016 at 02:21:31AM +0800, Fu Wei wrote:
> Hi Borislav,
> 
> Thanks for your review.
> I totally agree all your comment
> I have made a new patch, and that is in testing, I will post it ASAP

Ok, but please do not top-post.

A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 550+ messages in thread

* [PATCH v2 0/4] arm64,xen: add xen_boot support into grup-mkconfig
       [not found] <=fu.wei@linaro.org>
                   ` (13 preceding siblings ...)
  2015-08-24 17:01 ` [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
@ 2016-02-25  6:50 ` fu.wei
  14 siblings, 0 replies; 550+ messages in thread
From: fu.wei @ 2016-02-25  6:50 UTC (permalink / raw)
  To: grub-devel, arvidjaar, phcoder
  Cc: xen-devel, Ian.Campbell, jcm, julien.grall, leif.lindholm,
	linaro-uefi, Fu Wei

From: Fu Wei <fu.wei@linaro.org>

This patchset add xen_boot support into grup-mkconfig for
generating xen boot entrances automatically

Also update the docs/grub.texi for new xen_boot commands.

This patchset has been tested on Foudation model with a bug fix:
http://lists.gnu.org/archive/html/grub-devel/2016-02/msg00205.html

ChangeLog:
v2: add "--nounzip" option support in xen_module
    use "feature_xen_boot" instead of "grub_xen_boot"
    update the introduction of xen boot commands in docs/grub.texi

v1 :first upstream patchset:
    http://lists.gnu.org/archive/html/grub-devel/2016-02/msg00264.html

Fu Wei (4):
  arm64: add "--nounzip" option support in xen_module command
  * util/grub.d/20_linux_xen.in: Add xen_boot command support
  i386,xen: Add xen_hypervisor and xen_module aliases for i386
  arm64: update the introduction of xen boot commands in     
    docs/grub.texi

 docs/grub.texi                    | 32 +++++++++-----------------------
 grub-core/loader/arm64/xen_boot.c | 17 +++++++++++++++++
 grub-core/loader/i386/xen.c       |  7 +++++++
 grub-core/normal/main.c           |  2 +-
 util/grub.d/20_linux_xen.in       | 13 ++++++++++---
 5 files changed, 44 insertions(+), 27 deletions(-)

-- 
2.5.0

^ permalink raw reply	[flat|nested] 550+ messages in thread

end of thread, other threads:[~2016-02-25  6:50 UTC | newest]

Thread overview: 550+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <=fu.wei@linaro.org>
2015-05-15 11:08 ` [PATCH 0/6] Watchdog: introdouce ARM SBSA watchdog driver fu.wei
2015-05-15 11:08   ` [PATCH 1/6] Documentation: add sbsa-gwdt.txt documentation fu.wei
2015-05-15 14:06     ` Arnd Bergmann
2015-05-15 14:06       ` Arnd Bergmann
2015-05-15 14:14       ` Fu Wei
2015-05-15 14:14         ` Fu Wei
2015-05-16 10:29       ` Fu Wei
2015-05-16 10:29         ` Fu Wei
2015-05-15 11:08   ` [PATCH 2/6] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts fu.wei
2015-05-15 11:08   ` [PATCH 3/6] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi fu.wei
2015-05-15 11:08     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-05-15 14:07   ` [Linaro-acpi] [PATCH 0/6] Watchdog: introdouce ARM SBSA watchdog driver Arnd Bergmann
2015-05-15 14:07     ` Arnd Bergmann
2015-05-16 10:33     ` Fu Wei
2015-05-16 10:33       ` Fu Wei
2015-05-15 11:24 ` [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework fu.wei
2015-05-15 11:24   ` [PATCH 5/6] Watchdog: introdouce ARM SBSA watchdog driver fu.wei
2015-05-15 13:57     ` Arnd Bergmann
2015-05-16 12:01       ` Fu Wei
2015-05-16 12:01         ` Fu Wei
2015-05-16 12:26         ` Timur Tabi
2015-05-15 22:57     ` Guenter Roeck
2015-05-15 22:57       ` Guenter Roeck
2015-05-18 17:38       ` Fu Wei
2015-05-18 17:38         ` Fu Wei
2015-05-15 11:24   ` [PATCH 6/6] ACPI: import watchdog info of GTDT into platform device fu.wei
2015-05-15 13:33   ` [PATCH 4/6] Watchdog: introdouce "pretimeout" into framework Guenter Roeck
2015-05-15 13:49     ` Fu Wei
2015-05-15 13:55       ` Timur Tabi
2015-05-15 13:55         ` Timur Tabi
2015-05-15 17:59         ` Guenter Roeck
2015-05-15 18:01       ` Guenter Roeck
2015-05-15 18:01         ` Guenter Roeck
2015-05-18 17:22         ` Fu Wei
2015-05-18 17:22           ` Fu Wei
2015-05-15 14:04   ` Arnd Bergmann
2015-05-18 17:19     ` Fu Wei
2015-05-18 17:19       ` Fu Wei
2015-05-18 17:23       ` Guenter Roeck
2015-05-18 17:39         ` Fu Wei
2015-05-18 20:03         ` Arnd Bergmann
2015-05-18 20:14           ` Guenter Roeck
2015-05-18 20:14             ` Guenter Roeck
2015-05-19  1:12             ` Fu Wei
2015-05-19  1:12               ` Fu Wei
2015-05-21  8:32 ` [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver fu.wei
2015-05-21  8:32   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-05-21  8:32   ` [PATCH v2 1/7] clocksource: export "arch_timer_get_rate" for the other drivers fu.wei
2015-05-21  8:32     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-05-22 14:02     ` Hanjun Guo
2015-05-22 14:09     ` Timur Tabi
2015-05-22 15:16       ` Guenter Roeck
2015-05-22 16:22         ` Timur Tabi
2015-05-21  8:32   ` [PATCH v2 2/7] Documentation: add sbsa-gwdt.txt documentation fu.wei
2015-05-21  8:32   ` [PATCH v2 3/7] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts fu.wei
2015-05-21  8:45     ` Arnd Bergmann
2015-05-21  8:49       ` Fu Wei
2015-05-21  8:49         ` Fu Wei
2015-05-21  8:32   ` [PATCH v2 4/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi fu.wei
2015-05-21 20:33     ` Suravee Suthikulpanit
2015-05-21 20:33       ` Suravee Suthikulpanit
2015-05-21  8:32   ` [PATCH v2 5/7] Watchdog: introduce "pretimeout" into framework fu.wei
2015-05-21  9:04     ` Guenter Roeck
2015-05-21 10:05       ` Fu Wei
2015-05-21 10:05         ` Fu Wei
2015-05-21 10:17         ` Guenter Roeck
2015-05-21 10:50           ` Fu Wei
2015-05-21 10:50             ` Fu Wei
2015-05-21 13:28             ` Guenter Roeck
2015-05-21 10:11     ` Guenter Roeck
2015-05-21 15:32     ` Guenter Roeck
2015-05-21 15:32       ` Guenter Roeck
2015-05-22  5:17       ` Fu Wei
2015-05-25  3:09       ` Fu Wei
2015-05-25  3:09         ` Fu Wei
2015-05-22  6:30     ` Timo Kokkonen
2015-05-22  8:23       ` Fu Wei
2015-05-22  8:59         ` Timo Kokkonen
2015-05-22 10:46           ` Fu Wei
2015-05-22 10:46             ` Fu Wei
2015-05-22 12:14             ` Timo Kokkonen
2015-05-22 13:37               ` Guenter Roeck
2015-05-22 13:23             ` Guenter Roeck
2015-05-22 14:38               ` Fu Wei
2015-05-22 14:38                 ` Fu Wei
2015-05-22 15:05                 ` Guenter Roeck
2015-05-24 16:17                   ` Fu Wei
2015-05-21  8:32   ` [PATCH v2 6/7] Watchdog: introduce ARM SBSA watchdog driver fu.wei
2015-05-21  8:32     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-05-21 10:34     ` Guenter Roeck
2015-05-21 10:34       ` Guenter Roeck
2015-05-21 11:08       ` Fu Wei
2015-05-21 15:18         ` Guenter Roeck
2015-05-21 15:18           ` Guenter Roeck
2015-05-21 15:46           ` Fu Wei
2015-05-21 15:59             ` Guenter Roeck
2015-05-21 16:12               ` Fu Wei
2015-05-21 16:12                 ` Fu Wei
2015-05-21 16:33                 ` Timur Tabi
2015-05-21 16:33                   ` Timur Tabi
2015-05-22  5:05                   ` Fu Wei
2015-05-22  5:05                     ` Fu Wei
2015-05-21 13:09       ` Timur Tabi
2015-05-21 15:28         ` Guenter Roeck
2015-05-21 15:28           ` Guenter Roeck
2015-05-25  3:43           ` Fu Wei
2015-05-25  3:43             ` Fu Wei
2015-05-25  3:46             ` Timur Tabi
2015-05-25  3:46               ` Timur Tabi
2015-05-25  4:11               ` Fu Wei
2015-05-25  4:11                 ` Fu Wei
2015-05-21 15:42     ` Timur Tabi
2015-05-21 15:42       ` Timur Tabi
2015-05-23 16:28       ` Fu Wei
2015-05-23 16:50         ` Fu Wei
2015-05-23 19:40         ` Timur Tabi
2015-05-23 19:40           ` Timur Tabi
2015-05-23 20:01           ` Guenter Roeck
2015-05-23 20:01             ` Guenter Roeck
2015-05-23 20:27             ` Timur Tabi
2015-05-23 20:27               ` Timur Tabi
2015-05-23 20:44               ` Guenter Roeck
2015-05-24 10:50                 ` Fu Wei
2015-05-24 10:15             ` Fu Wei
2015-05-24 14:15               ` Guenter Roeck
2015-05-24 14:15                 ` Guenter Roeck
2015-05-24 15:50                 ` Fu Wei
2015-05-24 15:50                   ` Fu Wei
2015-05-24 16:23                   ` Guenter Roeck
2015-05-24 16:47                     ` Fu Wei
2015-05-24 16:58                       ` Guenter Roeck
2015-05-24 16:58                         ` Guenter Roeck
2015-05-24 17:04                         ` Fu Wei
2015-05-24 17:04                           ` Fu Wei
2015-05-24 15:02               ` Timur Tabi
2015-05-24 16:04                 ` Fu Wei
2015-05-24 16:04                   ` Fu Wei
2015-05-24 16:13                   ` Timur Tabi
2015-05-24 16:13                     ` Timur Tabi
2015-05-24 16:29                     ` Guenter Roeck
2015-05-24 16:29                       ` Guenter Roeck
2015-05-24 16:33                       ` Fu Wei
2015-05-24 16:44                       ` Timur Tabi
2015-05-24 16:50                         ` Guenter Roeck
2015-05-24 16:52                         ` Fu Wei
2015-05-24 17:19                           ` Timur Tabi
2015-05-24 17:19                             ` Timur Tabi
2015-05-24 17:23                             ` Fu Wei
2015-05-24 17:32                             ` Guenter Roeck
2015-05-24 17:32                               ` Guenter Roeck
2015-05-24 17:47                               ` Timur Tabi
2015-05-25  2:03                                 ` Fu Wei
2015-05-25  2:00                               ` Fu Wei
2015-05-24 16:29                     ` Fu Wei
2015-05-22 14:50     ` Hanjun Guo
2015-05-22 14:50       ` Hanjun Guo
2015-05-22 14:55       ` Arnd Bergmann
2015-05-22 15:01         ` Guenter Roeck
2015-05-22 15:01           ` Guenter Roeck
2015-05-22 15:18           ` Hanjun Guo
2015-05-22 15:18             ` Hanjun Guo
2015-05-22 15:24             ` [Linaro-acpi] " Arnd Bergmann
2015-05-22 15:24               ` Arnd Bergmann
2015-05-22 16:19               ` Timur Tabi
2015-05-22 20:13                 ` Arnd Bergmann
2015-05-22 20:17                   ` Timur Tabi
2015-05-23  7:25               ` Fu Wei
2015-05-23  7:25                 ` Fu Wei
2015-05-22 16:19           ` Timur Tabi
2015-05-23 14:47           ` Fu Wei
2015-05-22 16:18         ` Timur Tabi
2015-05-23 15:08         ` Timur Tabi
2015-05-23 15:08           ` Timur Tabi
2015-05-23 17:26           ` Fu Wei
2015-05-23 18:35             ` Guenter Roeck
2015-05-23 18:37               ` Timur Tabi
2015-05-23 19:03                 ` Fu Wei
2015-05-23 19:51                 ` Guenter Roeck
2015-05-24  9:58                   ` Fu Wei
2015-05-24 14:06                     ` Guenter Roeck
2015-05-24 14:06                       ` Guenter Roeck
2015-05-24 15:06                       ` Timur Tabi
2015-05-24 15:06                         ` Timur Tabi
2015-05-24 15:37                       ` Fu Wei
2015-05-24 15:37                         ` Fu Wei
2015-05-23 18:40             ` Timur Tabi
2015-05-23 19:14               ` Fu Wei
2015-05-23 19:14                 ` Fu Wei
2015-05-23 19:21                 ` Timur Tabi
2015-05-21  8:32   ` [PATCH v2 7/7] ACPI: import watchdog info of GTDT into platform device fu.wei
2015-05-22 15:38     ` Hanjun Guo
2015-05-22 15:38       ` Hanjun Guo
2015-05-23 19:46     ` Timur Tabi
2015-05-23 19:46       ` Timur Tabi
2015-05-21  8:46   ` [Linaro-acpi] [PATCH v2 0/7] Watchdog: introduce ARM SBSA watchdog driver Arnd Bergmann
2015-05-21  8:46     ` Arnd Bergmann
2015-05-21  9:01     ` Fu Wei
2015-05-21  9:01       ` Fu Wei
2015-05-21 20:36   ` Suravee Suthikulpanit
2015-05-21 20:36     ` Suravee Suthikulpanit
2015-05-22  5:08     ` Fu Wei
2015-05-25 10:03 ` [PATCH v3 0/6] " fu.wei
2015-05-25 10:03   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-05-25 10:03   ` [PATCH v3 1/6] Documentation: add sbsa-gwdt.txt documentation fu.wei
2015-05-25 10:03     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-05-25 10:03   ` [PATCH v3 2/6] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts fu.wei
2015-05-25 10:03   ` [PATCH v3 3/6] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi fu.wei
2015-05-25 10:03   ` [PATCH v3 4/6] Watchdog: introdouce "pretimeout" into framework fu.wei
2015-05-25 19:28     ` Guenter Roeck
2015-05-25 19:28       ` Guenter Roeck
2015-05-25 10:03   ` [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver fu.wei
2015-05-25 19:39     ` Guenter Roeck
2015-05-25 19:39       ` Guenter Roeck
2015-05-29  9:11       ` Fu Wei
2015-05-29  9:11         ` Fu Wei
2015-05-29 14:54         ` Guenter Roeck
2015-05-29 15:05           ` Fu Wei
2015-05-26 16:50     ` Timur Tabi
2015-05-29 10:17       ` Fu Wei
2015-05-29 10:17         ` Fu Wei
2015-05-29 13:28         ` Timur Tabi
2015-05-29 13:28           ` Timur Tabi
2015-05-29 14:32           ` Fu Wei
2015-05-29 14:32             ` Fu Wei
2015-05-29 15:46             ` Timur Tabi
2015-05-29 15:46               ` Timur Tabi
2015-05-29 17:53               ` Fu Wei
2015-05-29 18:27                 ` Timur Tabi
2015-05-29 18:27                   ` Timur Tabi
2015-05-29 22:10               ` Guenter Roeck
2015-05-29 22:10                 ` Guenter Roeck
2015-06-01  7:50                 ` Fu Wei
2015-05-25 10:03   ` [PATCH v3 6/6] ACPI: import watchdog info of GTDT into platform device fu.wei
2015-05-26  8:28     ` Hanjun Guo
2015-05-26 16:35       ` Timur Tabi
2015-05-26 18:24         ` Guenter Roeck
2015-05-26 18:24           ` Guenter Roeck
2015-05-27  3:01         ` Hanjun Guo
2015-05-27  3:08           ` Timur Tabi
2015-05-27  3:08             ` Timur Tabi
2015-05-26 12:28     ` Will Deacon
2015-05-26 12:28       ` Will Deacon
2015-05-26 15:02       ` Ashwin Chaugule
2015-05-26 15:02         ` Ashwin Chaugule
2015-05-26 15:18         ` Will Deacon
2015-05-26 15:18           ` Will Deacon
2015-05-26 15:35           ` Ashwin Chaugule
2015-05-26 15:35             ` Ashwin Chaugule
2015-05-26 15:35             ` Ashwin Chaugule
2015-05-26 15:36           ` Guenter Roeck
2015-05-26 15:36             ` Guenter Roeck
2015-05-26 16:27             ` Fu Wei
2015-05-26 16:27               ` Fu Wei
2015-05-27 10:44               ` Will Deacon
2015-05-27 10:44                 ` Will Deacon
2015-05-29 11:13                 ` Fu Wei
2015-05-29 11:13                   ` Fu Wei
2015-06-02  4:05 ` [PATCH v4 0/7] Watchdog: introduce ARM SBSA watchdog driver fu.wei
2015-06-02  4:05   ` [PATCH v4 1/7] Documentation: add sbsa-gwdt.txt documentation fu.wei
2015-06-02  4:05   ` [PATCH v4 2/7] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts fu.wei
2015-06-02  4:05   ` [PATCH v4 3/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi fu.wei
2015-06-02  4:05     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-02  4:05   ` [PATCH v4 4/7] Watchdog: introdouce "pretimeout" into framework fu.wei
2015-06-02  4:05     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-02 16:12     ` Guenter Roeck
2015-06-02 16:12       ` Guenter Roeck
2015-06-08 16:44       ` Fu Wei
2015-06-02  4:05   ` [PATCH v4 5/7] Watchdog: introduce ARM SBSA watchdog driver fu.wei
2015-06-02  4:05     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-02 15:32     ` Timur Tabi
2015-06-02 15:32       ` Timur Tabi
2015-06-02 15:37       ` Guenter Roeck
2015-06-02 15:37         ` Guenter Roeck
2015-06-02 16:55       ` Fu Wei
2015-06-02 16:55         ` Fu Wei
2015-06-02 17:07         ` Guenter Roeck
2015-06-02 17:07           ` Guenter Roeck
2015-06-08 16:05           ` Fu Wei
2015-06-08 16:05             ` Fu Wei
2015-06-08 18:26             ` Guenter Roeck
2015-06-08 18:26               ` Guenter Roeck
2015-06-09  3:59               ` Fu Wei
2015-06-09  4:37                 ` Guenter Roeck
2015-06-09  4:37                   ` Guenter Roeck
2015-06-09  6:37                   ` Fu Wei
2015-06-09  6:37                     ` Fu Wei
2015-06-09  8:04                     ` Guenter Roeck
2015-06-09  8:04                       ` Guenter Roeck
2015-06-09 10:46                       ` Fu Wei
2015-06-09 16:22                         ` Guenter Roeck
2015-06-09 16:29                           ` Timur Tabi
2015-06-09 16:29                             ` Timur Tabi
2015-06-09 16:45                             ` Guenter Roeck
2015-06-09 16:53                               ` Timur Tabi
2015-06-09 16:53                                 ` Timur Tabi
2015-06-10  3:41                               ` Fu Wei
2015-06-10  3:41                                 ` Fu Wei
2015-06-10  4:20                                 ` Fu Wei
2015-06-10 14:22                                   ` Timur Tabi
2015-06-10 14:22                                     ` Timur Tabi
2015-06-10 14:36                                     ` Fu Wei
2015-06-10 14:36                                       ` Fu Wei
2015-06-10 14:41                                       ` Fu Wei
2015-06-10 14:41                                         ` Fu Wei
2015-06-10 14:41                                         ` Fu Wei
2015-06-10 15:38                                 ` Fu Wei
2015-06-10 15:38                                   ` Fu Wei
2015-06-10 17:54                                   ` Fu Wei
2015-06-10 17:54                                     ` Fu Wei
2015-06-11  0:22                                 ` Timur Tabi
2015-06-11  0:22                                   ` Timur Tabi
2015-06-11  3:00                                   ` Fu Wei
2015-06-11  3:45                                     ` Timur Tabi
2015-06-11  3:45                                       ` Timur Tabi
2015-06-11  5:13                                       ` Guenter Roeck
2015-06-11  5:13                                         ` Guenter Roeck
2015-06-11  5:33                                         ` Fu Wei
2015-06-11  5:32                                       ` Fu Wei
2015-06-11  5:32                                         ` Fu Wei
2015-06-02 17:21         ` Timur Tabi
2015-06-02 17:21           ` Timur Tabi
2015-06-03 18:16     ` Timur Tabi
2015-06-03 18:16       ` Timur Tabi
2015-06-03 18:25       ` Guenter Roeck
2015-06-03 18:25         ` Guenter Roeck
2015-06-03 18:53         ` Timur Tabi
2015-06-03 18:53           ` Timur Tabi
2015-06-03 19:29           ` Arnd Bergmann
2015-09-10 22:45           ` Jon Masters
2015-09-14  4:21             ` Pratyush Anand
2015-09-14 15:27               ` Fu Wei
2015-09-14 15:27                 ` Fu Wei
2015-09-14  8:51             ` Catalin Marinas
2015-09-15  3:16             ` Fu Wei
2015-09-15  3:16               ` Fu Wei
2015-06-08 16:10         ` Fu Wei
2015-06-02  4:05   ` [PATCH v4 6/7] ACPI: add GTDT table parse driver into ACPI driver fu.wei
2015-06-02  4:05   ` [PATCH v4 7/7] clocksource: simplify ACPI code in arm_arch_timer.c fu.wei
2015-06-10 13:41 ` [PATCH v5 0/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
2015-06-10 13:41   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-10 13:41   ` [PATCH v5 1/8] Documentation: add sbsa-gwdt.txt documentation fu.wei
2015-06-10 13:41   ` [PATCH v5 2/8] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts fu.wei
2015-06-10 13:41     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-10 13:41   ` [PATCH v5 3/8] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi fu.wei
2015-06-10 13:41     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-10 13:41   ` [PATCH v5 4/8] Watchdog: introdouce "pretimeout" into framework fu.wei
2015-06-10 16:21     ` Guenter Roeck
2015-06-10 16:21       ` Guenter Roeck
2015-06-11 11:22       ` Fu Wei
2015-06-11 16:38         ` Guenter Roeck
2015-06-11 16:38           ` Guenter Roeck
2015-06-10 13:41   ` [PATCH v5 5/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
2015-06-10 13:41     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-10 13:41   ` [PATCH v5 6/8] ACPI: add GTDT table parse driver into ACPI driver fu.wei
2015-06-10 13:41     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-10 13:41   ` [PATCH v5 7/8] Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver fu.wei
2015-06-10 13:41     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-10 13:41   ` [PATCH v5 8/8] clocksource: simplify ACPI code in arm_arch_timer.c fu.wei
2015-06-10 17:47 ` [PATCH non-pretimeout 0/7] Watchdog: introduce ARM SBSA watchdog driver fu.wei
2015-06-10 17:47   ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-10 17:47   ` [PATCH non-pretimeout 1/7] Documentation: add sbsa-gwdt.txt documentation fu.wei
2015-06-10 17:47     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-10 17:47   ` [PATCH non-pretimeout 2/7] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts fu.wei
2015-06-10 17:47   ` [PATCH non-pretimeout 3/7] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi fu.wei
2015-06-10 17:47     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-12 20:54     ` Timur Tabi
2015-06-12 20:54       ` Timur Tabi
2015-06-14 10:05       ` Fu Wei
2015-06-14 13:17         ` Timur Tabi
2015-06-14 13:17           ` Timur Tabi
2015-06-14 13:57         ` Guenter Roeck
2015-06-15 11:00           ` Fu Wei
2015-06-10 17:47   ` [PATCH non-pretimeout 4/7] Watchdog: introduce ARM SBSA watchdog driver fu.wei
2015-06-11  5:33     ` Guenter Roeck
2015-06-11  5:33       ` Guenter Roeck
2015-06-11  5:44       ` Fu Wei
2015-06-11  5:49         ` Guenter Roeck
2015-06-11  5:59           ` Fu Wei
2015-06-11  5:59             ` Fu Wei
2015-06-11 16:28     ` [non-pretimeout,4/7] " Guenter Roeck
2015-06-23 13:26       ` Fu Wei
2015-06-23 15:21         ` Guenter Roeck
2015-06-23 15:21           ` Guenter Roeck
2015-06-23 16:17           ` Fu Wei
2015-06-23 16:43             ` Guenter Roeck
2015-06-23 17:01               ` Fu Wei
2015-06-23 17:01                 ` Fu Wei
2015-06-12  3:57     ` [PATCH non-pretimeout 4/7] " Timur Tabi
2015-06-12  3:57       ` Timur Tabi
2015-06-14 10:15       ` Fu Wei
2015-06-14 10:15         ` Fu Wei
2015-06-10 17:47   ` [PATCH non-pretimeout 5/7] ACPI: add GTDT table parse driver into ACPI driver fu.wei
2015-06-11 11:14     ` Hanjun Guo
2015-06-10 17:47   ` [PATCH non-pretimeout 6/7] Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver fu.wei
2015-06-10 17:47     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-12 13:16     ` Timur Tabi
2015-06-10 17:47   ` [PATCH non-pretimeout 7/7] clocksource: simplify ACPI code in arm_arch_timer.c fu.wei
2015-06-10 17:47     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-23 14:16 ` [PATCH v6 0/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
2015-06-23 14:16   ` [PATCH v6 1/8] Documentation: add sbsa-gwdt.txt documentation fu.wei
2015-06-23 14:16     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-07-14 14:49     ` Rob Herring
2015-07-14 14:49       ` Rob Herring
2015-07-14 15:48       ` Fu Wei
2015-07-14 15:48         ` Fu Wei
2015-07-15 12:52         ` Fu Wei
2015-07-15 12:52           ` Fu Wei
2015-06-23 14:16   ` [PATCH v6 2/8] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts fu.wei
2015-06-23 14:16     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-23 14:16   ` [PATCH v6 3/8] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi fu.wei
2015-06-23 14:16   ` [PATCH v6 4/8] Watchdog: introdouce "pretimeout" into framework fu.wei
2015-06-23 14:16     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-29 16:53   ` [PATCH v6 0/8] Watchdog: introduce ARM SBSA watchdog driver Fu Wei
2015-06-29 16:53     ` Fu Wei
2015-06-29 19:16     ` Guenter Roeck
2015-06-30 23:47       ` Fu Wei
2015-07-13  9:09       ` Fu Wei
2015-07-13  9:09         ` Fu Wei
2015-07-13 15:34         ` Guenter Roeck
2015-07-14  0:42           ` Fu Wei
2015-07-14  0:42             ` Fu Wei
2015-06-23 15:59 ` [PATCH v6 5/8] " fu.wei
2015-06-23 15:59   ` [PATCH v6 6/8] ACPI: add GTDT table parse driver into ACPI driver fu.wei
2015-06-23 15:59     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-07-23  8:32     ` Fu Wei
2015-07-23  8:32       ` Fu Wei
2015-07-23  8:32       ` Fu Wei
2015-06-23 15:59   ` [PATCH v6 7/8] Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver fu.wei
2015-06-23 15:59     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-06-23 15:59   ` [PATCH v6 8/8] clocksource: simplify ACPI code in arm_arch_timer.c fu.wei
2015-06-23 15:59     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-07-13  8:53 ` [PATCH v2 0/3] arm64: Add multiboot support (via fdt) for Xen boot fu.wei
2015-07-13  8:53   ` [PATCH v2 1/3] arm64: Add Xen boot support file fu.wei
2015-07-15 16:18     ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-07-15 16:18       ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-07-16 16:46       ` Ian Campbell
2015-07-16 16:46         ` Ian Campbell
2015-07-23 10:16       ` Fu Wei
2015-07-23 10:16         ` Fu Wei
2015-07-13  8:53   ` [PATCH v2 2/3] util/grub.d/20_linux_xen.in: Add arm64 support fu.wei
2015-07-14  3:53     ` Andrei Borzenkov
2015-07-14  3:53       ` Andrei Borzenkov
2015-07-14  9:41       ` Ian Campbell
2015-07-14 15:23         ` [Xen-devel] " Konrad Rzeszutek Wilk
2015-07-14 13:09       ` Fu Wei
2015-07-14 13:09         ` Fu Wei
2015-07-15 16:24         ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-07-15 16:24           ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-07-13  8:54   ` [PATCH v2 3/3] arm64: Add the introduction of Xen boot command fu.wei
2015-07-14  9:29   ` [Xen-devel] [PATCH v2 0/3] arm64: Add multiboot support (via fdt) for Xen boot Ian Campbell
2015-07-14  9:29     ` Ian Campbell
2015-07-14 11:56     ` Fu Wei
2015-07-15 15:56   ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-07-15 15:56     ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-07-23  5:16 ` [PATCH v3 0/4] arm64: Add Xen boot support (via fdt) fu.wei
2015-07-23  5:16   ` [PATCH v3 1/4] arm64: Add and export some accessor functions for xen boot fu.wei
2015-10-29 12:03     ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-10-29 12:03       ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-10-30  7:11       ` Fu Wei
2015-10-30  7:11         ` Fu Wei
2015-07-23  5:16   ` [PATCH v3 2/4] arm64: Add xen_boot module file fu.wei
2015-10-29 14:27     ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-10-29 14:27       ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-10-30  8:08       ` Fu Wei
2015-10-30  8:08         ` Fu Wei
2015-11-03 14:57         ` Fu Wei
2015-11-03 14:57           ` Fu Wei
2015-11-03 15:22           ` Ian Campbell
2015-11-03 15:22             ` Ian Campbell
2015-11-05  9:46             ` Fu Wei
2015-07-23  5:16   ` [PATCH v3 3/4] * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64 fu.wei
2015-10-29 15:25     ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-10-29 15:25       ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-10-29 19:53       ` Andrei Borzenkov
2015-10-29 19:53         ` Andrei Borzenkov
2015-10-30  8:44       ` Fu Wei
2015-10-30  8:44         ` Fu Wei
2015-10-30  9:50         ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-10-30  9:50           ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-10-30 10:07           ` Andrei Borzenkov
2015-10-30 10:07             ` Andrei Borzenkov
     [not found]             ` <CAEaD8JOHR9QXa=ySc36a-ECF-7MUBgvaSVFw_BZxrXrvZA5u_A@mail.gmail.com>
     [not found]               ` <CAA91j0XKvpgVVWuv79AEv6bguxrQrV4q+eG5Xtw+UBvMSmDF-w@mail.gmail.com>
2015-11-12 10:43                 ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-07-23  5:16   ` [PATCH v3 4/4] arm64: Add the introduction of xen boot commands in docs/grub.texi fu.wei
2015-08-04  8:34   ` [PATCH v3 0/4] arm64: Add Xen boot support (via fdt) Fu Wei
2015-09-08  3:38     ` Fu Wei
2015-09-30 16:00       ` Stefano Stabellini
2015-10-01 16:19         ` Stefano Stabellini
2015-10-29  2:43           ` Fu Wei
2015-10-29  6:06         ` Fu Wei
2015-10-29 11:00           ` Stefano Stabellini
2015-08-14 12:35 ` [PATCH] acpi, apei, arm64: APEI initial support for aarch64 fu.wei
2015-08-14 12:39   ` Fu Wei
2015-08-14 18:27     ` Zhang, Jonathan Zhixiong
2015-08-15  6:45       ` Fu Wei
2015-08-17 10:01   ` Will Deacon
2015-08-17 23:19     ` Zhang, Jonathan Zhixiong
2015-08-18  8:31       ` Will Deacon
2015-08-18  9:26         ` Fu Wei
2015-08-18 16:44 ` [PATCH v2 0/2] acpi, apei: add BERT support fu.wei
2015-08-18 16:44   ` [PATCH v2 1/2] acpi, apei: add Boot Error Record Table (BERT) support fu.wei
2015-12-16 10:29     ` Borislav Petkov
2016-01-06 18:21       ` Fu Wei
2016-01-06 18:31         ` Borislav Petkov
2015-08-18 16:44   ` [PATCH v2 2/2] acpi, apei, bert: Clear error status at the end of error handling fu.wei
2015-12-16 10:30     ` Borislav Petkov
2015-12-15 16:39   ` [Linaro-acpi] [PATCH v2 0/2] acpi, apei: add BERT support Timur Tabi
2016-01-06 18:24     ` Fu Wei
2015-08-24 17:01 ` [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
2015-08-24 17:01   ` [PATCH v7 1/8] Documentation: add sbsa-gwdt.txt documentation fu.wei
2015-08-24 17:01   ` [PATCH v7 2/8] ARM64: add SBSA Generic Watchdog device node in foundation-v8.dts fu.wei
2015-09-15  8:43     ` Dave Young
2015-09-15  8:43       ` Dave Young
2015-09-15  9:44       ` Pratyush Anand
2015-09-15 10:23         ` Fu Wei
2015-09-15 10:15       ` Fu Wei
2015-08-24 17:01   ` [PATCH v7 3/8] ARM64: add SBSA Generic Watchdog device node in amd-seattle-soc.dtsi fu.wei
2015-08-24 17:01   ` [PATCH v7 4/8] Watchdog: introdouce "pretimeout" into framework fu.wei
2015-08-24 17:01   ` [PATCH v7 5/8] Watchdog: introduce ARM SBSA watchdog driver fu.wei
2015-09-10 22:29     ` Jon Masters
2015-09-11  2:05       ` Guenter Roeck
2015-09-11  2:50       ` Guenter Roeck
2015-09-11  2:50         ` Guenter Roeck
2015-09-14 17:11         ` Fu Wei
2015-09-15  8:38     ` Dave Young
2015-09-15 10:07       ` Fu Wei
2015-09-16  1:57         ` Dave Young
2015-10-13  8:34           ` Fu Wei
2015-10-13  8:34             ` Fu Wei
2015-08-24 17:01   ` [PATCH v7 6/8] ACPI: add GTDT table parse driver into ACPI driver fu.wei
2015-08-24 17:01   ` [PATCH v7 7/8] Watchdog: enable ACPI GTDT support for ARM SBSA watchdog driver fu.wei
2015-08-24 17:01   ` [PATCH v7 8/8] clocksource: simplify ACPI code in arm_arch_timer.c fu.wei
2015-08-24 17:01     ` fu.wei-QSEj5FYQhm4dnm+yROfE0A
2015-08-24 17:50     ` Thomas Gleixner
2015-08-25 17:19       ` Fu Wei
2015-08-25 19:17         ` Thomas Gleixner
2015-08-25 19:17           ` Thomas Gleixner
2015-08-27 12:02           ` Hanjun Guo
2015-08-27 12:02             ` Hanjun Guo
2015-08-27 12:08             ` Thomas Gleixner
2015-08-27 12:28               ` Hanjun Guo
2015-08-27 12:28                 ` Hanjun Guo
2015-08-27 13:36                 ` Hanjun Guo
2015-08-27 13:40                   ` Thomas Gleixner
2015-08-27 13:40                     ` Thomas Gleixner
2015-08-27 13:51                     ` Fu Wei
2015-09-14 18:05                       ` Marc Zyngier
2015-09-14 18:05                         ` Marc Zyngier
2015-09-30 17:13   ` [PATCH v7 0/8] Watchdog: introduce ARM SBSA watchdog driver Pratyush Anand
2015-09-30 17:22     ` Fu Wei
2016-02-25  6:50 ` [PATCH v2 0/4] arm64,xen: add xen_boot support into grup-mkconfig fu.wei

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.