All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kyle Roeschley <kyle.roeschley@ni.com>
To: wim@iguana.be
Cc: linux-watchdog@vger.kernel.org, joshc@ni.com
Subject: [RFC 2/4] watchdog: ni9x3x_wdt: Add counter sysfs attribute
Date: Thu, 4 Feb 2016 19:28:01 -0600	[thread overview]
Message-ID: <1454635683-13668-2-git-send-email-kyle.roeschley@ni.com> (raw)
In-Reply-To: <1454635683-13668-1-git-send-email-kyle.roeschley@ni.com>

The NI 9x3x watchdog timer has 30.72 µs resolution, so expose this
by allowing the user to set the timeout counter directly via a sysfs
attribute.

RFC because we can't use the watchdog core lock inside the _show and
_store functions, so we're left without any protection on setting or
reading the control register. The options right now are either add our
own lock and double lock everything or force access to the watchdog core
lock. We don't want to do either, so for now we do nothing.

Signed-off-by: Kyle Roeschley <kyle.roeschley@ni.com>
---
 drivers/watchdog/ni9x3x_wdt.c | 73 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 58 insertions(+), 15 deletions(-)

diff --git a/drivers/watchdog/ni9x3x_wdt.c b/drivers/watchdog/ni9x3x_wdt.c
index 2cb5627..13f5c10 100644
--- a/drivers/watchdog/ni9x3x_wdt.c
+++ b/drivers/watchdog/ni9x3x_wdt.c
@@ -60,37 +60,45 @@ static void ni9x3x_wdt_start(struct ni9x3x_wdt *wdt)
 	outb(control | NIWD_CONTROL_PET, wdt->io_base + NIWD_CONTROL);
 }
 
-static int ni9x3x_wdt_wdd_set_timeout(struct watchdog_device *wdd,
-				      unsigned int timeout)
+static void ni9x3x_wdt_counter_set(struct ni9x3x_wdt *wdt, u32 counter)
 {
-	struct ni9x3x_wdt *wdt = to_ni9x3x_wdt(wdd);
-	u32 counter = timeout * (1000000000 / NIWD_PERIOD_NS);
-
 	outb(((0x00FF0000 & counter) >> 16), wdt->io_base + NIWD_SEED2);
 	outb(((0x0000FF00 & counter) >> 8), wdt->io_base + NIWD_SEED1);
 	outb((0x000000FF & counter), wdt->io_base + NIWD_SEED0);
-
-	return 0;
 }
 
-static unsigned int ni9x3x_wdt_wdd_get_timeleft(struct watchdog_device *wdd)
+static unsigned int ni9x3x_wdt_counter_get(struct ni9x3x_wdt *wdt)
 {
-	struct ni9x3x_wdt *wdt = to_ni9x3x_wdt(wdd);
 	u8 control, counter0, counter1, counter2;
-	u32 counter;
 
 	control = inb(wdt->io_base + NIWD_CONTROL);
-	control |= NIWD_CONTROL_CAPTURECOUNTER;
-	outb(control, wdt->io_base + NIWD_CONTROL);
+	outb(control | NIWD_CONTROL_CAPTURECOUNTER,
+	     wdt->io_base + NIWD_CONTROL);
 
 	counter2 = inb(wdt->io_base + NIWD_COUNTER2);
 	counter1 = inb(wdt->io_base + NIWD_COUNTER1);
 	counter0 = inb(wdt->io_base + NIWD_COUNTER0);
 
-	counter = (counter2 << 16) | (counter1 << 8) | counter0;
-	counter = (counter * (u64)NIWD_PERIOD_NS) / 1000000000;
+	return (counter2 << 16) | (counter1 << 8) | counter0;
+}
+
+static int ni9x3x_wdt_wdd_set_timeout(struct watchdog_device *wdd,
+				      unsigned int timeout)
+{
+	struct ni9x3x_wdt *wdt = to_ni9x3x_wdt(wdd);
+	u32 counter = timeout * (1000000000 / NIWD_PERIOD_NS);
+
+	ni9x3x_wdt_counter_set(wdt, counter);
+
+	return 0;
+}
+
+static unsigned int ni9x3x_wdt_wdd_get_timeleft(struct watchdog_device *wdd)
+{
+	struct ni9x3x_wdt *wdt = to_ni9x3x_wdt(wdd);
+	u32 counter = ni9x3x_wdt_counter_get(wdt);
 
-	return (unsigned int)counter;
+	return (unsigned int)((counter * (u64)NIWD_PERIOD_NS) / 1000000000);
 }
 
 static int ni9x3x_wdt_wdd_start(struct watchdog_device *wdd)
@@ -126,6 +134,40 @@ static int ni9x3x_wdt_wdd_ping(struct watchdog_device *wdd)
 	return 0;
 }
 
+static ssize_t counter_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+	struct ni9x3x_wdt *wdt = acpi_driver_data(acpi_dev);
+	u32 counter;
+
+	counter = ni9x3x_wdt_counter_get(wdt);
+
+	return sprintf(buf, "%u\n", counter);
+}
+
+static ssize_t counter_store(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+	struct ni9x3x_wdt *wdt = acpi_driver_data(acpi_dev);
+	u32 val;
+
+	if (kstrtouint(buf, 10, &val) || val > 0xFFFFFF)
+		return -EINVAL;
+
+	ni9x3x_wdt_counter_set(wdt, val);
+
+	return count;
+}
+static DEVICE_ATTR_RW(counter);
+
+static struct attribute *ni9x3x_wdt_attrs[] = {
+	&dev_attr_counter.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(ni9x3x_wdt);
+
 static acpi_status ni9x3x_wdt_resources(struct acpi_resource *res, void *data)
 {
 	struct ni9x3x_wdt *wdt = data;
@@ -214,6 +256,7 @@ static int ni9x3x_wdt_acpi_add(struct acpi_device *device)
 	wdt->wdog.max_timeout = NIWD_MAX_TIMEOUT;
 	wdt->wdog.timeout = NIWD_DEFAULT_TIMEOUT;
 	wdt->wdog.parent = &device->dev;
+	wdt->wdog.groups = ni9x3x_wdt_groups;
 
 	ret = watchdog_register_device(&wdt->wdog);
 	if (ret) {
-- 
2.7.0


  reply	other threads:[~2016-02-05  1:28 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-05  1:28 [RFC 1/4] watchdog: ni9x3x_wdt: Add NI 903x/913x watchdog driver Kyle Roeschley
2016-02-05  1:28 ` Kyle Roeschley [this message]
2016-02-05 19:53   ` [RFC 2/4] watchdog: ni9x3x_wdt: Add counter sysfs attribute Josh Cartwright
2016-02-06 16:35     ` Guenter Roeck
2016-02-05  1:28 ` [RFC 3/4] watchdog: ni9x3x_wdt: Add timeout_action " Kyle Roeschley
2016-02-05 20:08   ` Josh Cartwright
2016-02-05 21:13     ` Kyle Roeschley
2016-02-05 21:40       ` Josh Cartwright
2016-02-06  0:00       ` Guenter Roeck
2016-02-05  1:28 ` [RFC 4/4] watchdog: ni9x3x_wdt: Let user control watchdog mode Kyle Roeschley
2016-02-05 20:27   ` Josh Cartwright
2016-02-05 21:03     ` Kyle Roeschley
2016-02-05 21:34       ` Josh Cartwright
2016-02-06 16:42       ` Guenter Roeck
2016-02-05 19:49 ` [RFC 1/4] watchdog: ni9x3x_wdt: Add NI 903x/913x watchdog driver Josh Cartwright
2016-02-06 16:30 ` Guenter Roeck
2016-02-08 16:06   ` Kyle Roeschley
2016-02-06 16:33 ` Guenter Roeck

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=1454635683-13668-2-git-send-email-kyle.roeschley@ni.com \
    --to=kyle.roeschley@ni.com \
    --cc=joshc@ni.com \
    --cc=linux-watchdog@vger.kernel.org \
    --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.