From: "Jordan Crouse" <jordan.crouse@amd.com>
To: "Arnd Hannemann" <hannemann@i4.informatik.rwth-aachen.de>
Cc: "Andres Salomon" <dilinger@queued.net>,
marc.jones@amd.com,
"Linux Kernel Mailing List" <linux-kernel@vger.kernel.org>,
wim@iguana.be
Subject: [GEODE] Geode GX/LX watchdog timer (was 2.6.24-rc8 hangs at mfgpt-timer)
Date: Fri, 18 Jan 2008 18:06:24 -0700 [thread overview]
Message-ID: <20080119010624.GA25328@cosmic.amd.com> (raw)
In-Reply-To: <478FDC12.6020505@i4.informatik.rwth-aachen.de>
[-- Attachment #1: Type: text/plain, Size: 1666 bytes --]
On 17/01/08 23:52 +0100, Arnd Hannemann wrote:
> >> Watchdog for the new API would be great :-)
> >
> > Coming soon.
As promised, a watchdog driver for the Geode GX/LX processors is attached.
I basically just ported the previous patch forward to 2.6.24.
I also have good news or bad news depending on your perspective. I wanted
to test this against 2.6.24, and OLPC is stuck at an older kernel version,
so I had to test this with coreboot (LinuxBIOS) on another Geode
platform. Like all BIOSen execpt for the OLPC firmware, coreboot uses
VSA (SMM handler) which consumes all the timers.
So I used the magical MSR and surprise! - the timer tick hung.
I compiled out the timer tick, and tested the watchdog timer instead,
and it worked fine on timer 0. So I don't think the MFGPTs themselves
have anything to do with this problem, but I do think it might be
related to VSA and possibly interrupts too. I'm going to invoke the
strong BIOS fu of our LinuxBIOS / BIOS expert Marc Jones, and see what
he comes up with.
I don't know how much of a hassle it would be for Andres to get a 2.6.24
kernel running on the OLPC to make sure that this isn't a regression
in the timer tick code (I suspect it isn't a regression, but you never
know). I also think that it would probably be in our best interest to
default CONFIG_GEODE_MFGPT_TIMER to 'n' until we get this figured
out. Since most BIOSen don't have timers available, that shouldn't affect
too many people.
So, anyway, enjoy the watchdog timer - I hope it meets everybody's
expectations for the 2.6.25 kernel.
Jordan
--
Jordan Crouse
Systems Software Development Engineer
Advanced Micro Devices, Inc.
[-- Attachment #2: geode-watchdog.patch --]
[-- Type: text/plain, Size: 9937 bytes --]
[GEODE] Add a watchdog driver based on the CS5535/CS5536 MFGPT timers
From: Jordan Crouse <jordan.crouse@amd.com>
Add a watchdog timer based on the MFGPT timers in the CS5535/CS5536
companion chips to the AMD Geode GX and LX processors. Only caveat
is that the BIOS must provide at least a one free timer, and most
do not.
Signed-off-by: Jordan Crouse <jordan.crouse@amd.com>
---
drivers/watchdog/Kconfig | 13 ++
drivers/watchdog/Makefile | 1
drivers/watchdog/geodewdt.c | 321 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 335 insertions(+), 0 deletions(-)
Index: git/drivers/watchdog/Kconfig
===================================================================
--- git.orig/drivers/watchdog/Kconfig 2008-01-18 15:06:44.000000000 -0700
+++ git/drivers/watchdog/Kconfig 2008-01-18 17:50:25.000000000 -0700
@@ -295,6 +295,20 @@
Most people will say N.
+config GEODE_WDT
+ tristate "AMD Geode CS5535/CS5536 Watchdog"
+ depends on MGEODE_LX
+ default n
+ help
+ This driver enables a watchdog capability built into the
+ CS5535/CS5536 companion chips for the AMD Geode GX and LX
+ processors. This watchdog watches your kernel to make sure
+ it doesn't freeze, and if it does, it reboots your computer after
+ a certain amount of time.
+
+ You can compile this driver directly into the kernel, or use
+ it as a module. The module will be called geodewdt.
+
config SC520_WDT
tristate "AMD Elan SC520 processor Watchdog"
depends on X86
Index: git/drivers/watchdog/Makefile
===================================================================
--- git.orig/drivers/watchdog/Makefile 2008-01-18 15:06:44.000000000 -0700
+++ git/drivers/watchdog/Makefile 2008-01-18 16:32:15.000000000 -0700
@@ -59,6 +59,7 @@
obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o
obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
+obj-$(CONFIG_GEODE_WDT) += geodewdt.o
obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
obj-$(CONFIG_IB700_WDT) += ib700wdt.o
Index: git/drivers/watchdog/geodewdt.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ git/drivers/watchdog/geodewdt.c 2008-01-18 17:47:39.000000000 -0700
@@ -0,0 +1,308 @@
+/* Watchdog timer for the Geode GX/LX with the CS5535/CS5536 companion chip
+ *
+ * Copyright (C) 2006-2007, Advanced Micro Devices, Inc.
+ *
+ * This program 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
+ * 2 of the License, or (at your option) any later version.
+ */
+
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+
+#include <asm/uaccess.h>
+#include <asm/geode.h>
+
+#define GEODEWDT_HZ 500
+#define GEODEWDT_SCALE 6
+#define GEODEWDT_MAX_SECONDS 131
+
+#define WDT_FLAGS_OPEN 1
+#define WDT_FLAGS_ORPHAN 2
+
+#define DRV_NAME "geodewdt"
+#define WATCHDOG_NAME "Geode GX/LX WDT"
+#define WATCHDOG_TIMEOUT 60
+
+static int timeout = WATCHDOG_TIMEOUT;
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=131, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static struct platform_device *geodewdt_platform_device;
+static unsigned long wdt_flags;
+static int wdt_timer;
+static int safe_close;
+
+static void geodewdt_ping(void)
+{
+ /* Stop the counter */
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);
+
+ /* Reset the counter */
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);
+
+ /* Enable the counter */
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN);
+}
+
+static void geodewdt_disable(void)
+{
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);
+}
+
+static int geodewdt_set_heartbeat(int val)
+{
+ if (val < 1 || val > GEODEWDT_MAX_SECONDS)
+ return -EINVAL;
+
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_CMP2, val * GEODEWDT_HZ);
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN);
+
+ timeout = val;
+ return 0;
+}
+
+static int
+geodewdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags))
+ return -EBUSY;
+
+ if (!test_and_clear_bit(WDT_FLAGS_ORPHAN, &wdt_flags))
+ __module_get(THIS_MODULE);
+
+ geodewdt_ping();
+ return nonseekable_open(inode, file);
+}
+
+static int
+geodewdt_release(struct inode *inode, struct file *file)
+{
+ if (safe_close) {
+ geodewdt_disable();
+ module_put(THIS_MODULE);
+ }
+ else {
+ printk(KERN_CRIT "Unexpected close - watchdog is not stopping.\n");
+ geodewdt_ping();
+
+ set_bit(WDT_FLAGS_ORPHAN, &wdt_flags);
+ }
+
+ clear_bit(WDT_FLAGS_OPEN, &wdt_flags);
+ safe_close = 0;
+ return 0;
+}
+
+static ssize_t
+geodewdt_write(struct file *file, const char __user *data, size_t len,
+ loff_t *ppos)
+{
+ if(len) {
+ if (!nowayout) {
+ size_t i;
+ safe_close = 0;
+
+ for (i = 0; i != len; i++) {
+ char c;
+
+ if (get_user(c, data + i))
+ return -EFAULT;
+
+ if (c == 'V')
+ safe_close = 1;
+ }
+ }
+
+ geodewdt_ping();
+ }
+ return len;
+}
+
+static int
+geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ int interval;
+
+ static struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING
+ | WDIOF_MAGICCLOSE,
+ .firmware_version = 1,
+ .identity = WATCHDOG_NAME,
+ };
+
+ switch(cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ident,
+ sizeof(ident)) ? -EFAULT : 0;
+ break;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, p);
+
+ case WDIOC_KEEPALIVE:
+ geodewdt_ping();
+ return 0;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(interval, p))
+ return -EFAULT;
+
+ if (geodewdt_set_heartbeat(interval))
+ return -EINVAL;
+
+/* Fall through */
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(timeout, p);
+
+ case WDIOC_SETOPTIONS:
+ {
+ int options, ret = -EINVAL;
+
+ if (get_user(options, p))
+ return -EFAULT;
+
+ if (options & WDIOS_DISABLECARD) {
+ geodewdt_disable();
+ ret = 0;
+ }
+
+ if (options & WDIOS_ENABLECARD) {
+ geodewdt_ping();
+ ret = 0;
+ }
+
+ return ret;
+ }
+ default:
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+static const struct file_operations geodewdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = geodewdt_write,
+ .ioctl = geodewdt_ioctl,
+ .open = geodewdt_open,
+ .release = geodewdt_release,
+};
+
+static struct miscdevice geodewdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "geode-watchdog",
+ .fops = &geodewdt_fops
+};
+
+static int __devinit
+geodewdt_probe(struct platform_device *dev)
+{
+ int ret, timer;
+
+ timer = geode_mfgpt_alloc_timer(MFGPT_TIMER_ANY,
+ MFGPT_DOMAIN_WORKING, THIS_MODULE);
+
+ if (timer == -1) {
+ printk(KERN_ERR "geodewdt: No timers were available\n");
+ return -ENODEV;
+ }
+
+ wdt_timer = timer;
+
+ /* Set up the timer */
+
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP,
+ GEODEWDT_SCALE | (3 << 8));
+
+ /* Set up comparator 2 to reset when the event fires */
+ geode_mfgpt_toggle_event(wdt_timer, MFGPT_CMP2, MFGPT_EVENT_RESET, 1);
+
+ /* Set up the initial timeout */
+
+ geode_mfgpt_write(wdt_timer, MFGPT_REG_CMP2,
+ timeout * GEODEWDT_HZ);
+
+ ret = misc_register(&geodewdt_miscdev);
+
+ return ret;
+}
+
+static int __devexit
+geodewdt_remove(struct platform_device *dev)
+{
+ misc_deregister(&geodewdt_miscdev);
+}
+
+static void
+geodewdt_shutdown(struct platform_device *dev)
+{
+ geodewdt_disable();
+}
+
+static struct platform_driver geodewdt_driver = {
+ .probe = geodewdt_probe,
+ .remove = __devexit_p(geodewdt_remove),
+ .shutdown = geodewdt_shutdown,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ },
+};
+
+static int __init
+geodewdt_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&geodewdt_driver);
+ if (ret)
+ return ret;
+
+ geodewdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
+ if (IS_ERR(geodewdt_platform_device)) {
+ ret = PTR_ERR(geodewdt_platform_device);
+ goto err;
+ }
+
+ return 0;
+err:
+ platform_driver_unregister(&geodewdt_driver);
+ return ret;
+}
+
+static void __exit
+geodewdt_exit(void)
+{
+ platform_device_unregister(geodewdt_platform_device);
+ platform_driver_unregister(&geodewdt_driver);
+}
+
+module_init(geodewdt_init);
+module_exit(geodewdt_exit);
+
+MODULE_AUTHOR("Advanced Micro Devices, Inc");
+MODULE_DESCRIPTION("Geode GX/LX Watchdog Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
Index: git/arch/x86/kernel/mfgpt_32.c
===================================================================
--- git.orig/arch/x86/kernel/mfgpt_32.c 2008-01-18 16:57:50.000000000 -0700
+++ git/arch/x86/kernel/mfgpt_32.c 2008-01-18 17:48:22.000000000 -0700
@@ -142,6 +142,8 @@
return 0;
}
+EXPORT_SYMBOL_GPL(geode_mfgpt_toggle_event);
+
int geode_mfgpt_set_irq(int timer, int cmp, int irq, int enable)
{
u32 val, dummy;
@@ -204,6 +206,7 @@
return -1;
}
+EXPORT_SYMBOL_GPL(geode_mfgpt_alloc_timer);
#ifdef CONFIG_GEODE_MFGPT_TIMER
next prev parent reply other threads:[~2008-01-19 1:15 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-16 17:44 2.6.24-rc8 hangs at mfgpt-timer Arnd Hannemann
2008-01-16 21:19 ` Andres Salomon
2008-01-16 21:56 ` Andres Salomon
2008-01-17 9:54 ` Arnd Hannemann
2008-01-17 18:40 ` Andres Salomon
2008-01-17 19:53 ` Arnd Hannemann
2008-01-17 20:42 ` Andres Salomon
2008-01-17 21:19 ` Jordan Crouse
2008-01-17 21:50 ` Arnd Hannemann
2008-01-17 22:36 ` Jordan Crouse
2008-01-17 22:52 ` Arnd Hannemann
2008-01-17 22:57 ` Jordan Crouse
2008-01-17 23:39 ` Arnd Hannemann
2008-01-18 0:40 ` Jordan Crouse
2008-01-21 23:27 ` Jordan Crouse
2008-01-21 23:32 ` Willy Tarreau
2008-01-22 20:15 ` Willy Tarreau
2008-01-22 21:08 ` Jordan Crouse
2008-01-22 21:15 ` Willy Tarreau
2008-01-23 16:36 ` Jordan Crouse
2008-01-23 16:10 ` Willy Tarreau
2008-01-22 9:03 ` Arnd Hannemann
2008-01-22 10:11 ` Lars Heete
2008-01-22 11:18 ` Arnd Hannemann
2008-01-22 18:15 ` Jordan Crouse
2008-01-22 19:27 ` Jordan Crouse
2008-01-22 20:54 ` Arnd Hannemann
2008-01-22 21:10 ` Ingo Molnar
2008-01-22 21:20 ` Willy Tarreau
2008-01-22 21:53 ` [git pull] was: " Thomas Gleixner
2008-01-23 21:17 ` [PATCH 0/2] Was: " Willy Tarreau
2008-01-23 21:18 ` [PATCH 1/2] x86: GEODE fix MFGPT input clock value Willy Tarreau
2008-01-23 21:59 ` H. Peter Anvin
2008-01-23 22:11 ` Willy Tarreau
2008-01-23 22:22 ` H. Peter Anvin
2008-01-23 22:10 ` Willy Tarreau
2008-01-23 22:38 ` Jordan Crouse
2008-01-23 23:17 ` Arnd Hannemann
2008-01-23 21:19 ` [PATCH 2/2] x86: GEODE add the "mfgptfix" boot time option to fix MFGPT timers Willy Tarreau
2008-01-19 1:06 ` Jordan Crouse [this message]
2008-01-19 6:36 ` [GEODE] Geode GX/LX watchdog timer (was 2.6.24-rc8 hangs at mfgpt-timer) Willy Tarreau
2008-01-20 13:22 ` Arnd Hannemann
2008-01-20 16:34 ` Jordan Crouse
2008-01-21 17:07 ` Geode GX/LX watchdog timer (RESEND) Jordan Crouse
2008-01-21 18:37 ` Arnd Hannemann
2008-02-17 14:14 ` Iain Paton
2008-02-17 14:46 ` Arnd Hannemann
2008-02-17 14:54 ` Adrian Bunk
2008-02-17 16:10 ` Iain Paton
2008-02-17 17:32 ` Andres Salomon
2008-02-17 19:46 ` Arnd Hannemann
2008-01-20 20:16 ` [GEODE] Geode GX/LX watchdog timer (was 2.6.24-rc8 hangs at mfgpt-timer) Lennart Sorensen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080119010624.GA25328@cosmic.amd.com \
--to=jordan.crouse@amd.com \
--cc=dilinger@queued.net \
--cc=hannemann@i4.informatik.rwth-aachen.de \
--cc=linux-kernel@vger.kernel.org \
--cc=marc.jones@amd.com \
--cc=wim@iguana.be \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.