Skip to content

Commit c60c040

Browse files
committed
Merge tag 'acpi-5.6-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI fixes from Rafael Wysocki: "Fix a couple of configuration issues in the ACPI watchdog (WDAT) driver (Mika Westerberg) and make it possible to disable that driver at boot time in case it still does not work as expected (Jean Delvare)" * tag 'acpi-5.6-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI: watchdog: Set default timeout in probe ACPI: watchdog: Fix gas->access_width usage ACPICA: Introduce ACPI_ACCESS_BYTE_WIDTH() macro ACPI: watchdog: Allow disabling WDAT at boot
2 parents 3642859 + cabe17d commit c60c040

File tree

4 files changed

+42
-5
lines changed

4 files changed

+42
-5
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@
136136
dynamic table installation which will install SSDT
137137
tables to /sys/firmware/acpi/tables/dynamic.
138138

139+
acpi_no_watchdog [HW,ACPI,WDT]
140+
Ignore the ACPI-based watchdog interface (WDAT) and let
141+
a native driver control the watchdog device instead.
142+
139143
acpi_rsdp= [ACPI,EFI,KEXEC]
140144
Pass the RSDP address to the kernel, mostly used
141145
on machines running EFI runtime service to boot the

drivers/acpi/acpi_watchdog.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,14 @@ static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat)
5555
}
5656
#endif
5757

58+
static bool acpi_no_watchdog;
59+
5860
static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
5961
{
6062
const struct acpi_table_wdat *wdat = NULL;
6163
acpi_status status;
6264

63-
if (acpi_disabled)
65+
if (acpi_disabled || acpi_no_watchdog)
6466
return NULL;
6567

6668
status = acpi_get_table(ACPI_SIG_WDAT, 0,
@@ -88,6 +90,14 @@ bool acpi_has_watchdog(void)
8890
}
8991
EXPORT_SYMBOL_GPL(acpi_has_watchdog);
9092

93+
/* ACPI watchdog can be disabled on boot command line */
94+
static int __init disable_acpi_watchdog(char *str)
95+
{
96+
acpi_no_watchdog = true;
97+
return 1;
98+
}
99+
__setup("acpi_no_watchdog", disable_acpi_watchdog);
100+
91101
void __init acpi_watchdog_init(void)
92102
{
93103
const struct acpi_wdat_entry *entries;
@@ -126,12 +136,11 @@ void __init acpi_watchdog_init(void)
126136
gas = &entries[i].register_region;
127137

128138
res.start = gas->address;
139+
res.end = res.start + ACPI_ACCESS_BYTE_WIDTH(gas->access_width) - 1;
129140
if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
130141
res.flags = IORESOURCE_MEM;
131-
res.end = res.start + ALIGN(gas->access_width, 4) - 1;
132142
} else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
133143
res.flags = IORESOURCE_IO;
134-
res.end = res.start + gas->access_width - 1;
135144
} else {
136145
pr_warn("Unsupported address space: %u\n",
137146
gas->space_id);

drivers/watchdog/wdat_wdt.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ module_param(nowayout, bool, 0);
5454
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
5555
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
5656

57+
#define WDAT_DEFAULT_TIMEOUT 30
58+
59+
static int timeout = WDAT_DEFAULT_TIMEOUT;
60+
module_param(timeout, int, 0);
61+
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default="
62+
__MODULE_STRING(WDAT_DEFAULT_TIMEOUT) ")");
63+
5764
static int wdat_wdt_read(struct wdat_wdt *wdat,
5865
const struct wdat_instruction *instr, u32 *value)
5966
{
@@ -389,7 +396,7 @@ static int wdat_wdt_probe(struct platform_device *pdev)
389396

390397
memset(&r, 0, sizeof(r));
391398
r.start = gas->address;
392-
r.end = r.start + gas->access_width - 1;
399+
r.end = r.start + ACPI_ACCESS_BYTE_WIDTH(gas->access_width) - 1;
393400
if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
394401
r.flags = IORESOURCE_MEM;
395402
} else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
@@ -438,6 +445,22 @@ static int wdat_wdt_probe(struct platform_device *pdev)
438445

439446
platform_set_drvdata(pdev, wdat);
440447

448+
/*
449+
* Set initial timeout so that userspace has time to configure the
450+
* watchdog properly after it has opened the device. In some cases
451+
* the BIOS default is too short and causes immediate reboot.
452+
*/
453+
if (timeout * 1000 < wdat->wdd.min_hw_heartbeat_ms ||
454+
timeout * 1000 > wdat->wdd.max_hw_heartbeat_ms) {
455+
dev_warn(dev, "Invalid timeout %d given, using %d\n",
456+
timeout, WDAT_DEFAULT_TIMEOUT);
457+
timeout = WDAT_DEFAULT_TIMEOUT;
458+
}
459+
460+
ret = wdat_wdt_set_timeout(&wdat->wdd, timeout);
461+
if (ret)
462+
return ret;
463+
441464
watchdog_set_nowayout(&wdat->wdd, nowayout);
442465
return devm_watchdog_register_device(dev, &wdat->wdd);
443466
}

include/acpi/actypes.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,11 +532,12 @@ typedef u64 acpi_integer;
532532
strnlen (a, ACPI_NAMESEG_SIZE) == ACPI_NAMESEG_SIZE)
533533

534534
/*
535-
* Algorithm to obtain access bit width.
535+
* Algorithm to obtain access bit or byte width.
536536
* Can be used with access_width of struct acpi_generic_address and access_size of
537537
* struct acpi_resource_generic_register.
538538
*/
539539
#define ACPI_ACCESS_BIT_WIDTH(size) (1 << ((size) + 2))
540+
#define ACPI_ACCESS_BYTE_WIDTH(size) (1 << ((size) - 1))
540541

541542
/*******************************************************************************
542543
*

0 commit comments

Comments
 (0)