Skip to content

Commit 1ecd5b1

Browse files
Marc Zyngierctmarinas
authored andcommitted
ACPI: GTDT: Don't corrupt interrupt mappings on watchdow probe failure
When failing the driver probe because of invalid firmware properties, the GTDT driver unmaps the interrupt that it mapped earlier. However, it never checks whether the mapping of the interrupt actially succeeded. Even more, should the firmware report an illegal interrupt number that overlaps with the GIC SGI range, this can result in an IPI being unmapped, and subsequent fireworks (as reported by Dann Frazier). Rework the driver to have a slightly saner behaviour and actually check whether the interrupt has been mapped before unmapping things. Reported-by: dann frazier <[email protected]> Fixes: ca9ae5e ("acpi/arm64: Add SBSA Generic Watchdog support in GTDT driver") Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Cc: <[email protected]> Cc: Fu Wei <[email protected]> Reviewed-by: Sudeep Holla <[email protected]> Tested-by: dann frazier <[email protected]> Tested-by: Hanjun Guo <[email protected]> Reviewed-by: Hanjun Guo <[email protected]> Reviewed-by: Lorenzo Pieralisi <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent 0bca3ec commit 1ecd5b1

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

drivers/acpi/arm64/gtdt.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
329329
int index)
330330
{
331331
struct platform_device *pdev;
332-
int irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
332+
int irq;
333333

334334
/*
335335
* According to SBSA specification the size of refresh and control
@@ -338,7 +338,7 @@ static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
338338
struct resource res[] = {
339339
DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
340340
DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
341-
DEFINE_RES_IRQ(irq),
341+
{},
342342
};
343343
int nr_res = ARRAY_SIZE(res);
344344

@@ -348,10 +348,11 @@ static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
348348

349349
if (!(wd->refresh_frame_address && wd->control_frame_address)) {
350350
pr_err(FW_BUG "failed to get the Watchdog base address.\n");
351-
acpi_unregister_gsi(wd->timer_interrupt);
352351
return -EINVAL;
353352
}
354353

354+
irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
355+
res[2] = (struct resource)DEFINE_RES_IRQ(irq);
355356
if (irq <= 0) {
356357
pr_warn("failed to map the Watchdog interrupt.\n");
357358
nr_res--;
@@ -364,7 +365,8 @@ static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
364365
*/
365366
pdev = platform_device_register_simple("sbsa-gwdt", index, res, nr_res);
366367
if (IS_ERR(pdev)) {
367-
acpi_unregister_gsi(wd->timer_interrupt);
368+
if (irq > 0)
369+
acpi_unregister_gsi(wd->timer_interrupt);
368370
return PTR_ERR(pdev);
369371
}
370372

0 commit comments

Comments
 (0)