The ACPI processor driver is currently tied too closely
to the ACPI C-states (CST), P-states (PSS) and other related
constructs for controlling CPU idle and CPU performance.
The newer ACPI specification (v5.1 onwards) introduces
alternative methods to CST and PSS. These new mechanisms
are described within each ACPI Processor object and so they
need to be scanned whenever a new Processor object is detected.
This patch introduces two new Kconfig symbols to allow for
finer configurability among the various options for controlling
CPU idle and performance states. There is no change in functionality
and these options are defaulted to enabled to maintain previous
behaviour.
The following patchwork introduces CPPC: A newer method of
controlling CPU performance. The OS is not expected to support CPPC
and PSS at runtime. So the kconfig option lets us make these two
mutually exclusive at compile time.
Signed-off-by: Ashwin Chaugule <ashwin.chaugule(a)linaro.org>
---
drivers/acpi/Kconfig | 41 +++++++++++----
drivers/acpi/Makefile | 7 +--
drivers/acpi/processor_driver.c | 85 ++++++++++++++++++++-----------
drivers/cpufreq/Kconfig | 2 +-
drivers/cpufreq/Kconfig.x86 | 2 +
include/acpi/processor.h | 109 ++++++++++++++++++++++++++++++++++------
6 files changed, 187 insertions(+), 59 deletions(-)
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index ab2cbb5..d98d304 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -163,23 +163,42 @@ config ACPI_FAN
config ACPI_DOCK
bool "Dock"
help
- This driver supports ACPI-controlled docking stations and removable
- drive bays such as the IBM Ultrabay and the Dell Module Bay.
+ This driver supports ACPI-controlled docking stations and removable
+ drive bays such as the IBM Ultrabay and the Dell Module Bay.
+
+config ACPI_CST
+ bool "ACPI C states (CST) driver"
+ depends on ACPI_PROCESSOR
+ select CPU_IDLE
+ default y
+ help
+ This driver installs ACPI as the idle handler for Linux and uses
+ ACPI C2 and C3 processor states to save power on systems that
+ support it.
+
+config ACPI_PSS
+ bool "ACPI P States (PSS) driver"
+ depends on ACPI_PROCESSOR
+ select THERMAL
+ default y
+ help
+ This driver implements ACPI methods for controlling CPU performance
+ using PSS methods as described in the ACPI spec. It also enables support
+ for ACPI based performance throttling (TSS) and ACPI based thermal
+ monitoring. It is required by several flavors of cpufreq
+ performance-state drivers.
config ACPI_PROCESSOR
tristate "Processor"
- select THERMAL
- select CPU_IDLE
- depends on X86 || IA64
+ depends on X86 || IA64 || ARM64
default y
help
- This driver installs ACPI as the idle handler for Linux and uses
- ACPI C2 and C3 processor states to save power on systems that
- support it. It is required by several flavors of cpufreq
- performance-state drivers.
+ This driver adds support for the ACPI Processor package. It is required
+ by several flavors of cpufreq performance-state, thermal, throttling and
+ idle drivers.
- To compile this driver as a module, choose M here:
- the module will be called processor.
+ To compile this driver as a module, choose M here:
+ the module will be called processor.
config ACPI_IPMI
tristate "IPMI"
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 8a063e2..30b2bfc 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -82,9 +82,10 @@ obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
obj-$(CONFIG_ACPI_BGRT) += bgrt.o
# processor has its own "processor." module_param namespace
-processor-y := processor_driver.o processor_throttling.o
-processor-y += processor_idle.o processor_thermal.o
-processor-$(CONFIG_CPU_FREQ) += processor_perflib.o
+processor-y := processor_driver.o
+processor-$(CONFIG_ACPI_CST) += processor_idle.o
+processor-$(CONFIG_ACPI_PSS) += processor_perflib.o \
+ processor_throttling.o processor_thermal.o
obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index d9f7158..f61c09b 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -163,34 +163,23 @@ static struct notifier_block __refdata acpi_cpu_notifier = {
.notifier_call = acpi_cpu_soft_notify,
};
-static int __acpi_processor_start(struct acpi_device *device)
+#ifdef CONFIG_ACPI_PSS
+static int acpi_pss_init(struct acpi_processor *pr, struct acpi_device *device)
{
- struct acpi_processor *pr = acpi_driver_data(device);
- acpi_status status;
int result = 0;
- if (!pr)
- return -ENODEV;
-
- if (pr->flags.need_hotplug_init)
- return 0;
-
-#ifdef CONFIG_CPU_FREQ
acpi_processor_ppc_has_changed(pr, 0);
-#endif
+
acpi_processor_get_throttling_info(pr);
if (pr->flags.throttling)
pr->flags.limit = 1;
- if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
- acpi_processor_power_init(pr);
-
pr->cdev = thermal_cooling_device_register("Processor", device,
&processor_cooling_ops);
if (IS_ERR(pr->cdev)) {
result = PTR_ERR(pr->cdev);
- goto err_power_exit;
+ return result;
}
dev_dbg(&device->dev, "registered as cooling_device%d\n",
@@ -204,6 +193,7 @@ static int __acpi_processor_start(struct acpi_device *device)
"Failed to create sysfs link 'thermal_cooling'\n");
goto err_thermal_unregister;
}
+
result = sysfs_create_link(&pr->cdev->device.kobj,
&device->dev.kobj,
"device");
@@ -213,17 +203,61 @@ static int __acpi_processor_start(struct acpi_device *device)
goto err_remove_sysfs_thermal;
}
- status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
- acpi_processor_notify, device);
- if (ACPI_SUCCESS(status))
- return 0;
-
sysfs_remove_link(&pr->cdev->device.kobj, "device");
err_remove_sysfs_thermal:
sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
err_thermal_unregister:
thermal_cooling_device_unregister(pr->cdev);
- err_power_exit:
+
+ return result;
+}
+
+static void acpi_pss_exit(struct acpi_processor *pr,
+ struct acpi_device *device)
+{
+ if (pr->cdev) {
+ sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
+ sysfs_remove_link(&pr->cdev->device.kobj, "device");
+ thermal_cooling_device_unregister(pr->cdev);
+ pr->cdev = NULL;
+ }
+}
+#else
+static inline int acpi_pss_init(struct acpi_processor *pr,
+ struct acpi_device *device)
+{
+ return 0;
+}
+
+static inline void acpi_pss_exit(struct acpi_processor *pr,
+ struct acpi_device *device) {}
+#endif /* CONFIG_ACPI_PSS */
+
+static int __acpi_processor_start(struct acpi_device *device)
+{
+ struct acpi_processor *pr = acpi_driver_data(device);
+ acpi_status status;
+ int result = 0;
+
+ if (!pr)
+ return -ENODEV;
+
+ if (pr->flags.need_hotplug_init)
+ return 0;
+
+ if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
+ acpi_processor_power_init(pr);
+
+ result = acpi_pss_init(pr, device);
+ if (result)
+ goto err_power_exit;
+
+ status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
+ acpi_processor_notify, device);
+ if (ACPI_SUCCESS(status))
+ return 0;
+
+err_power_exit:
acpi_processor_power_exit(pr);
return result;
}
@@ -252,15 +286,10 @@ static int acpi_processor_stop(struct device *dev)
pr = acpi_driver_data(device);
if (!pr)
return 0;
-
acpi_processor_power_exit(pr);
- if (pr->cdev) {
- sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
- sysfs_remove_link(&pr->cdev->device.kobj, "device");
- thermal_cooling_device_unregister(pr->cdev);
- pr->cdev = NULL;
- }
+ acpi_pss_exit(pr, device);
+
return 0;
}
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 659879a..2f36e2a 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -223,7 +223,7 @@ endif
if IA64
config IA64_ACPI_CPUFREQ
tristate "ACPI Processor P-States driver"
- depends on ACPI_PROCESSOR
+ depends on ACPI_PROCESSOR && ACPI_PSS && ACPI_CST
help
This driver adds a CPUFreq driver which utilizes the ACPI
Processor Performance States.
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
index c59bdcb..ee285a8 100644
--- a/drivers/cpufreq/Kconfig.x86
+++ b/drivers/cpufreq/Kconfig.x86
@@ -18,6 +18,7 @@ config X86_INTEL_PSTATE
config X86_PCC_CPUFREQ
tristate "Processor Clocking Control interface driver"
depends on ACPI && ACPI_PROCESSOR
+ depends on ACPI_PSS && ACPI_CST
help
This driver adds support for the PCC interface.
@@ -32,6 +33,7 @@ config X86_PCC_CPUFREQ
config X86_ACPI_CPUFREQ
tristate "ACPI Processor P-States driver"
depends on ACPI_PROCESSOR
+ depends on ACPI_PSS && ACPI_CST
help
This driver adds a CPUFreq driver which utilizes the ACPI
Processor Performance States.
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 4188a4d..659edd6 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -222,16 +222,6 @@ struct acpi_processor_errata {
} piix4;
};
-extern int acpi_processor_preregister_performance(struct
- acpi_processor_performance
- __percpu *performance);
-
-extern int acpi_processor_register_performance(struct acpi_processor_performance
- *performance, unsigned int cpu);
-extern void acpi_processor_unregister_performance(struct
- acpi_processor_performance
- *performance,
- unsigned int cpu);
/* note: this locks both the calling module and the processor module
if a _PPC object exists, rmmod is disallowed then */
@@ -275,20 +265,55 @@ static inline void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx
/* in processor_perflib.c */
-#ifdef CONFIG_CPU_FREQ
+#ifdef CONFIG_ACPI_PSS
+extern int acpi_processor_preregister_performance(struct
+ acpi_processor_performance
+ __percpu *performance);
+
+extern int acpi_processor_register_performance(struct acpi_processor_performance
+ *performance, unsigned int cpu);
+extern void acpi_processor_unregister_performance(struct
+ acpi_processor_performance
+ *performance,
+ unsigned int cpu);
void acpi_processor_ppc_init(void);
void acpi_processor_ppc_exit(void);
int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag);
extern int acpi_processor_get_bios_limit(int cpu, unsigned int *limit);
#else
+static inline int acpi_processor_preregister_performance(struct
+ acpi_processor_performance
+ __percpu *performance)
+{
+ return -ENODEV;
+
+}
+
+static inline int acpi_processor_register_performance(struct acpi_processor_performance
+ *performance, unsigned int cpu)
+{
+ return -ENODEV;
+
+}
+
+static inline void acpi_processor_unregister_performance(struct
+ acpi_processor_performance
+ *performance,
+ unsigned int cpu)
+{
+ return;
+}
+
static inline void acpi_processor_ppc_init(void)
{
return;
}
+
static inline void acpi_processor_ppc_exit(void)
{
return;
}
+
static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr,
int event_flag)
{
@@ -302,12 +327,12 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr,
}
return 0;
}
+
static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
{
return -ENODEV;
}
-
-#endif /* CONFIG_CPU_FREQ */
+#endif /* CONFIG_ACPI_PSS */
/* in processor_core.c */
phys_cpuid_t acpi_get_phys_id(acpi_handle, int type, u32 acpi_id);
@@ -318,6 +343,7 @@ int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id);
void acpi_processor_set_pdc(acpi_handle handle);
/* in processor_throttling.c */
+#ifdef CONFIG_ACPI_PSS
int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
int acpi_processor_get_throttling_info(struct acpi_processor *pr);
extern int acpi_processor_set_throttling(struct acpi_processor *pr,
@@ -330,12 +356,63 @@ extern void acpi_processor_reevaluate_tstate(struct acpi_processor *pr,
unsigned long action);
extern const struct file_operations acpi_processor_throttling_fops;
extern void acpi_processor_throttling_init(void);
+#else
+static inline int acpi_processor_tstate_has_changed(struct acpi_processor *pr)
+{
+ return 0;
+}
+
+static inline int acpi_processor_get_throttling_info(struct acpi_processor *pr)
+{
+ return -ENODEV;
+}
+
+static inline int acpi_processor_set_throttling(struct acpi_processor *pr,
+ int state, bool force)
+{
+ return -ENODEV;
+}
+
+static inline void acpi_processor_reevaluate_tstate(struct acpi_processor *pr,
+ unsigned long action)
+{
+ return;
+}
+
+static inline void acpi_processor_throttling_init(void)
+{
+ return;
+}
+#endif /* CONFIG_ACPI_PSS */
+
/* in processor_idle.c */
+extern struct cpuidle_driver acpi_idle_driver;
+#ifdef CONFIG_ACPI_CST
int acpi_processor_power_init(struct acpi_processor *pr);
int acpi_processor_power_exit(struct acpi_processor *pr);
int acpi_processor_cst_has_changed(struct acpi_processor *pr);
int acpi_processor_hotplug(struct acpi_processor *pr);
-extern struct cpuidle_driver acpi_idle_driver;
+#else
+static inline int acpi_processor_power_init(struct acpi_processor *pr)
+{
+ return -ENODEV;
+}
+
+static inline int acpi_processor_power_exit(struct acpi_processor *pr)
+{
+ return -ENODEV;
+}
+
+static inline int acpi_processor_cst_has_changed(struct acpi_processor *pr)
+{
+ return -ENODEV;
+}
+
+static inline int acpi_processor_hotplug(struct acpi_processor *pr)
+{
+ return -ENODEV;
+}
+#endif /* CONFIG_ACPI_CST */
#ifdef CONFIG_PM_SLEEP
void acpi_processor_syscore_init(void);
@@ -347,8 +424,8 @@ static inline void acpi_processor_syscore_exit(void) {}
/* in processor_thermal.c */
int acpi_processor_get_limit_info(struct acpi_processor *pr);
+#ifdef CONFIG_ACPI_PSS
extern const struct thermal_cooling_device_ops processor_cooling_ops;
-#ifdef CONFIG_CPU_FREQ
void acpi_thermal_cpufreq_init(void);
void acpi_thermal_cpufreq_exit(void);
#else
@@ -360,6 +437,6 @@ static inline void acpi_thermal_cpufreq_exit(void)
{
return;
}
-#endif
+#endif /* CONFIG_ACPI_PSS */
#endif
--
1.9.1
From: "Jonathan (Zhixiong) Zhang" <zjzhang(a)codeaurora.org>
On a platform with APEI (ACPI Platform Error Interface) enabled, firmware
updates a memory region with hardware error record using nocache
attribute. When OS reads the region, since it maps the region with
cacahed attribute even though EFI memory map defines this region as
uncached, OS gets stale data and errorneously reports there is no new
HW error.
When ghes driver maps the memory region, it uses the cache attribute
according to EFI memory map, if EFI memory map feature is enabled
at runtime.
Since both arch/x86 and arch/ia64 implemented architecture agnostic EFI
memory map attribue lookup function efi_memattributes(), the code is
moved from arch/x86 into EFI subsystem and is declared as __weak; archs
other than ia64 should not override the default implementation.
V4:
1. Introduced arch_apei_get_mem_attributes() to allow arch specific
implementation of getting pgprot_t appropriate for a physical
address.
2. Implemented arch_apei_get_mem_attributes() for x86 and for arm64.
V3:
1. Rebased to v4.1-rc7.
2. Moved efi_mem_attributes() from arch/x86 to drivers/firmware/efi
and declared it as __weak.
3. Introduced ARCH_APEI_PAGE_KERNEL_UC to allow arch specific page
protection type for UC.
4. Removed efi_ioremap(). It can not be used for GHES memory region
mapping purpose since ioremap can not be used in atomic context.
V2:
1. Rebased to v4.1-rc5.
2. Split removal of efi_mem_attributes() and creation of efi_ioremap()
into two patches.
Jonathan (Zhixiong) Zhang (4):
efi: x86: rearrange efi_mem_attributes()
x86: acpi: add arch_apei_get_mem_attributes()
arm64: apei: implement arch_apei_get_mem_attributes()
acpi, apei: use appropriate pgprot_t to map GHES memory
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/apei.c | 27 +++++++++++++++++++++++++++
arch/x86/kernel/acpi/apei.c | 10 ++++++++++
arch/x86/platform/efi/efi.c | 18 ------------------
drivers/acpi/apei/ghes.c | 6 ++++--
drivers/firmware/efi/efi.c | 18 ++++++++++++++++++
include/acpi/apei.h | 1 +
7 files changed, 61 insertions(+), 20 deletions(-)
create mode 100644 arch/arm64/kernel/apei.c
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
From: Al Stone <al.stone(a)linaro.org>
In the ACPI 5.1 version of the spec, the struct for the GICC subtable (struct
acpi_madt_generic_interrupt) of the MADT is 76 bytes long; in ACPI 6.0, the
struct is 80 bytes long. But, there is only one definition in ACPICA for
this struct -- and that is the 6.0 version. Hence, when BAD_MADT_ENTRY()
compares the struct size to the length in the GICC subtable, it fails if 5.1
structs are in use, and there are systems in the wild that have them.
Note that this was found in linux-next and these patches apply against that
tree and the arm64 kernel tree; 4.1-rc7 does not appear to have this problem
since it has the 5.1 struct definition.
This patch set first adds macros for easily using the ACPI spec version, and
then adds the BAD_MADT_GICC_ENTRY() macro that uses them to check the GICC
subtable only, accounting for the difference in specification versions that
are possible. The final patch adds in usage of the BAD_MADT_GICC_ENTRY
macro. The BAD_MADT_ENTRY() will continue to work as is for all other
MADT subtables.
If these patches are acceptable, a cleanup effort will follow to simplify
the use of ACPI spec version numbers elsewhere.
These were tested and known to work on an APM Mustang system, where the
problem was originally uncovered.
Al Stone (3):
ACPI: introduce macros for using the ACPI specification version
ACPI: add BAD_MADT_GICC_ENTRY() macro
ACPI / ARM64: use the new BAD_MADT_GICC_ENTRY macro
arch/arm64/kernel/smp.c | 2 +-
drivers/irqchip/irq-gic.c | 2 +-
include/linux/acpi.h | 12 ++++++++++++
3 files changed, 14 insertions(+), 2 deletions(-)
--
2.1.0
From: "Jonathan (Zhixiong) Zhang" <zjzhang(a)codeaurora.org>
On a platform with APEI (ACPI Platform Error Interface) enabled, firmware
updates a memory region with hardware error record using nocache
attribute. When OS reads the region, since it maps the region with
cacahed attribute even though EFI memory map defines this region as
uncached, OS gets stale data and errorneously reports there is no new
HW error.
When ghes driver maps the memory region, it uses the cache attribute
according to EFI memory map, if EFI memory map feature is enabled
at runtime.
Since both arch/x86 and arch/ia64 implemented architecture agnostic EFI
memory map attribue lookup function efi_memattributes(), the code is
moved from arch/x86 into EFI subsystem and is declared as __weak; archs
other than ia64 should not override the default implementation.
V3:
1. Rebased to v4.1-rc7.
2. Moved efi_mem_attributes() from arch/x86 to drivers/firmware/efi
and declared it as __weak.
3. Introduced ARCH_APEI_PAGE_KERNEL_UC to allow arch specific page
protection type for UC.
4. Removed efi_ioremap(). It can not be used for GHES memory region
mapping purpose since ioremap can not be used in atomic context.
V2:
1. Rebased to v4.1-rc5.
2. Split removal of efi_mem_attributes() and creation of efi_ioremap()
into two patches.
Jonathan (Zhixiong) Zhang (4):
x86: acpi: define uncached page flag
arm64: acpi: define uncached page flag
efi: x86: rearrange efi_mem_attributes()
acpi, apei: use EFI memmap to map GHES memory
arch/arm64/include/asm/acpi.h | 4 ++++
arch/x86/include/asm/acpi.h | 4 ++++
arch/x86/platform/efi/efi.c | 18 ------------------
drivers/acpi/apei/ghes.c | 9 ++++++++-
drivers/firmware/efi/efi.c | 18 ++++++++++++++++++
5 files changed, 34 insertions(+), 19 deletions(-)
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
From: Al Stone <al.stone(a)linaro.org>
In the ACPI 5.1 version of the spec, the struct for the GICC subtable (struct
acpi_madt_generic_interrupt) of the MADT is 76 bytes long; in ACPI 6.0, the
struct is 80 bytes long. But, there is only one definition in ACPICA for
this struct -- and that is the 6.0 version. Hence, when BAD_MADT_ENTRY()
compares the struct size to the length in the GICC subtable, it fails if 5.1
structs are in use, and there are systems in the wild that have them.
This patch set first adds macros for easily using the ACPI spec version, and
then adds the BAD_MADT_GICC_ENTRY() macro that uses them to check the GICC
subtable only, accounting for the difference in specification versions that
are possible. The final patch adds in usage of the BAD_MADT_GICC_ENTRY
macro. The BAD_MADT_ENTRY() will continue to work as is for all other
MADT subtables.
If these patches are acceptable, a cleanup effort will follow to simplify
the use of ACPI spec version numbers elsewhere.
Al Stone (3):
ACPI: introduce macros for using the ACPI specification version
ACPI: add BAD_MADT_GICC_ENTRY() macro
ACPI / ARM64: use the new BAD_MADT_GICC_ENTRY macro
arch/arm64/kernel/smp.c | 2 +-
drivers/irqchip/irq-gic.c | 2 +-
include/linux/acpi.h | 12 ++++++++++++
3 files changed, 14 insertions(+), 2 deletions(-)
--
2.1.0
From: Fu Wei <fu.wei(a)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
So, in ACPI 5.1, the GICC subtable of the MADT is 76 bytes long. In the
6.0 version of the spec, the GICC subtable is 80 bytes long. This causes
a problem in the code in linux-next, specifically on the APM Mustang. The
same problem could exist for any other ACPI tables on arm64 that are 5.1
tables that we are trying to read.
What happens is that the BAD_MADT_ENTRY() macro will fail in these cases,
even though the GICC subtable entry is perfectly valid according to the spec.
The macro fail because it compares the subtable length contained in the subtable
to the length of the struct in ACPICA. Unfortunately, that causes any 5.1
GICC items to be seen as invalid.
Whilst we try to straighten this out in the spec (this seems like something
pretty dumb that should not have happened), I've put together two alternative
solutions:
-- per Graeme's suggestion, we change it so that we only use ACPI >= 6.0
on arm64; my only objection to this is that it breaks APM Mustangs
that are already in use -- on the positive side, it's the simpler of
the two patches.
-- or, replace the use of BAD_MADT_ENTRY with a specific function that
works around the spec problem, at least until we straighten out what
the spec _should_ do; the downside here is that this may be a short
term fix, but on the positive side it keeps the change to the only
arch that's affected.
I've attached both patches. Opinions on which one to send upstream?
--
ciao,
al
-----------------------------------
Al Stone
Software Engineer
Linaro Enterprise Group
al.stone(a)linaro.org
-----------------------------------
On Tue, Jun 09, 2015 at 07:09:47PM +0100, Build bot for Mark Brown wrote:
> arm64-allmodconfig
> ERROR: "acpi_gpiochip_request_interrupts" [drivers/gpio/gpio-xgene-sb.ko] undefined!
> ERROR: "acpi_gpiochip_free_interrupts" [drivers/gpio/gpio-xgene-sb.ko] undefined!
Today's -next fails to build an arm64 allmodconfig due to commit
733cf014f02040b3ad (gpio: xgene: add ACPI support for APM X-Gene GPIO
standby driver) which adds ACPI support to the X-Gene standby driver
without either adding a dependency on ACPI or there being stubs in the
ACPI headers for the above functions in !ACPI configurations. My
instinct is that the stubs are going to be nicer since it'll save on
ifdefs in drivers which seems nicer.