The leg-kernel release has been made and tagged as leg-20150519.0
This is based on mainline kernel v4.1-rc4
Repository : http://git.linaro.org/leg/acpi/leg-kernel.git
Direct Link:
http://git.linaro.org/leg/acpi/leg-kernel.git/commit/6fad3ac6a73d6ec7f1c664…
Notes :-
1) Contains first draft of exporting RSDP, RSDT, XSDT tables patch for
the no /dev/mem project
2) Contains V4 of the SBSA Watchdog driver patches.
3) Kludge/fix for Redhat OS login issues.
4) Support for booting on qemu virt machine type.
From: Fu Wei <fu.wei(a)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(a)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
Hi Graeme,
Are you saying :
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,
};
.name = "sbsa-gwdt", ???
I am not sure if that can do the auto-insmod part, maybe I miss some
knowledge of platform_driver , But AFAIK, the platform mechanism uses
that name to match the driver and device, ONCE the driver or device is
registered into system. that means when the driver is insmod'ed , then
the "name" will take effect.
But MODULE_DEVICE_TABLE creates an alias string in the .ok so depmod
can find device table.
please correct me , If I misunderstand this part .
On 18 May 2015 at 17:11, Hanjun Guo <hanjun.guo(a)linaro.org> wrote:
> On 2015年05月18日 17:05, G Gregory wrote:
>>
>> Shouldn't the standard platform_device matching kick in?
>>
>> It should match the driver to the name!
>
>
> Hmm, I missed this part, I'm not familiar with
> the mechanism, Fuwei, could you please try this
> direction?
>
>
>>
>> Graeme
>>
>> On 18 May 2015 at 10:04, Hanjun Guo <hanjun.guo(a)linaro.org> wrote:
>>>
>>> On 2015年05月18日 16:48, Fu Wei wrote:
>>>>
>>>>
>>>> Hi Suravee,
>>>>
>>>> Hanjun and me have figured out the problem of auto-insmod SBSA
>>>> watchdog module, when boot with ACPI:
>>>>
>>>> For now , we can not insmod SBSA watchdog driver automatically, because
>>>> :
>>>>
>>>> For booting with dtb , in the driver module, we already have :
>>>> ---------------------
>>>> static const struct of_device_id sbsa_gwdt_of_match[] = {
>>>> { .compatible = "arm,sbsa-gwdt", },
>>>> {},
>>>> };
>>>> MODULE_DEVICE_TABLE(of, sbsa_gwdt_of_match);
>>>> ---------------------
>>>>
>>>> For booting with acpi , we should have sometime like :
>>>> ---------------------
>>>> static const struct acpi_device_id sbsa_gwdt_ids[] __used = {
>>>> {ACPI_GTDT_SBSA_GWDT_HID, 0},
>>>> {"", 0}
>>>> };
>>>> MODULE_DEVICE_TABLE(acpi, sbsa_gwdt_ids);
>>>> ---------------------
>>>>
>>>> Unfortunately, for now , in ACPI spec, it seems we don't have
>>>> ACPI_GTDT_SBSA_GWDT_HID, and in Linux kernel, there is not a
>>>> mechanism to register the Wakeup-timer and Watchdog in GTDT with
>>>> ACPI_GTDT_*_HID.
>>>>
>>>> Maybe, ACPI team of LEG can discuss about that and rise a request of
>>>> adding ACPI_GTDT_*_HID to ACPI spec for GTDT table
>>>>
>>>> @Hanjun, Al
>>>> Please correct me if I misunderstand something :-)
>>>> Great thanks!
>>>
>>>
>>>
>>> You are right, more specifically, there is no mechanism to auto
>>> match/register modules for ACPI static tables (MADT/gtdt..), I think
>>> we can post a question on ACPI maillist to see if any good inputs.
>>>
>>> Thanks
>>> Hanjun
--
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
From: Fu Wei <fu.wei(a)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
Introduce invalid_phys_cpuid() to identify cpu with invalid
physical ID, then used it as replacement of the direct comparisons
with PHYS_CPUID_INVALID.
Signed-off-by: Hanjun Guo <hanjun.guo(a)linaro.org>
---
Hi Rafael,
This is replacement of patch 7/7 of patch set
"[PATCH v3 0/7] minor cleanups for ACPI processor driver",
which suggested by Sudeep and Lorenzo to replace
"(int)phys_id" < 0 with "phys_id == PHYS_CPUID_INVALID" in
invalid_phys_cpuid().
Thanks
Hanjun
drivers/acpi/acpi_processor.c | 4 ++--
drivers/acpi/processor_core.c | 4 ++--
include/linux/acpi.h | 5 +++++
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index 62c846b..92a5f73 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -170,7 +170,7 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr)
acpi_status status;
int ret;
- if (pr->phys_id == PHYS_CPUID_INVALID)
+ if (invalid_phys_cpuid(pr->phys_id))
return -ENODEV;
status = acpi_evaluate_integer(pr->handle, "_STA", NULL, &sta);
@@ -264,7 +264,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
pr->phys_id = acpi_get_phys_id(pr->handle, device_declaration,
pr->acpi_id);
- if (pr->phys_id == PHYS_CPUID_INVALID)
+ if (invalid_phys_cpuid(pr->phys_id))
acpi_handle_debug(pr->handle, "failed to get CPU physical ID.\n");
pr->id = acpi_map_cpuid(pr->phys_id, pr->acpi_id);
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index fd4140d..33a38d6 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -184,7 +184,7 @@ phys_cpuid_t acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id)
phys_cpuid_t phys_id;
phys_id = map_mat_entry(handle, type, acpi_id);
- if (phys_id == PHYS_CPUID_INVALID)
+ if (invalid_phys_cpuid(phys_id))
phys_id = map_madt_entry(type, acpi_id);
return phys_id;
@@ -196,7 +196,7 @@ int acpi_map_cpuid(phys_cpuid_t phys_id, u32 acpi_id)
int i;
#endif
- if (phys_id == PHYS_CPUID_INVALID) {
+ if (invalid_phys_cpuid(phys_id)) {
/*
* On UP processor, there is no _MAT or MADT table.
* So above phys_id is always set to PHYS_CPUID_INVALID.
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 913b49f..90e4ed1e 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -163,6 +163,11 @@ static inline bool invalid_logical_cpuid(u32 cpuid)
return (int)cpuid < 0;
}
+static inline bool invalid_phys_cpuid(phys_cpuid_t phys_id)
+{
+ return phys_id == PHYS_CPUID_INVALID;
+}
+
#ifdef CONFIG_ACPI_HOTPLUG_CPU
/* Arch dependent functions for cpu hotplug support */
int acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, int *pcpu);
--
1.9.1
This patch set are some minor cleanups for ACPI processor driver
to address the comments which raised by Rafael in ARM64 ACPI core
patches. I rebased this patch set on top of current Linus's tree.
v2:
- rebased on top of 4.1-rc2
Hanjun Guo (7):
ACPI / processor: remove cpu_index in acpi_processor_get_info()
ACPI / processor: remove phys_id in acpi_processor_get_info()
ACPI / processor: Introduce invalid_logical_cpuid()
Xen / ACPI / processor: use invalid_logical_cpuid()
Xen / ACPI / processor: Remove unneeded NULL check in
xen_acpi_processor_enable()
ACPI / processor: return specific error instead of -1
ACPI / processor: Introduce invalid_phys_cpuid()
drivers/acpi/acpi_processor.c | 20 +++++++++-----------
drivers/acpi/processor_core.c | 10 +++++-----
drivers/acpi/processor_pdc.c | 5 +----
drivers/xen/xen-acpi-cpuhotplug.c | 12 +++---------
include/linux/acpi.h | 10 ++++++++++
5 files changed, 28 insertions(+), 29 deletions(-)
--
1.9.1