Skip to content
Snippets Groups Projects
Commit e02b6f34 authored by Marc Zyngier's avatar Marc Zyngier Committed by Yang Yingliang
Browse files

ACPI: GTDT: Don't corrupt interrupt mappings on watchdow probe failure


stable inclusion
from linux-4.19.191
commit 7b2162db1498c71962a4bb2f776fa4e76d4d305b

--------------------------------

commit 1ecd5b129252249b9bc03d7645a7bda512747277 upstream.

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: default avatardann frazier <dann.frazier@canonical.com>
Fixes: ca9ae5ec ("acpi/arm64: Add SBSA Generic Watchdog support in GTDT driver")
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/YH87dtTfwYgavusz@xps13.dannf


Cc: <stable@vger.kernel.org>
Cc: Fu Wei <wefu@redhat.com>
Reviewed-by: default avatarSudeep Holla <sudeep.holla@arm.com>
Tested-by: default avatardann frazier <dann.frazier@canonical.com>
Tested-by: default avatarHanjun Guo <guohanjun@huawei.com>
Reviewed-by: default avatarHanjun Guo <guohanjun@huawei.com>
Reviewed-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Link: https://lore.kernel.org/r/20210421164317.1718831-2-maz@kernel.org


Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
parent ac9c4031
No related branches found
No related tags found
No related merge requests found
......@@ -332,7 +332,7 @@ static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
int index)
{
struct platform_device *pdev;
int irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
int irq;
/*
* According to SBSA specification the size of refresh and control
......@@ -341,7 +341,7 @@ static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
struct resource res[] = {
DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
DEFINE_RES_IRQ(irq),
{},
};
int nr_res = ARRAY_SIZE(res);
......@@ -351,10 +351,11 @@ static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
if (!(wd->refresh_frame_address && wd->control_frame_address)) {
pr_err(FW_BUG "failed to get the Watchdog base address.\n");
acpi_unregister_gsi(wd->timer_interrupt);
return -EINVAL;
}
irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
res[2] = (struct resource)DEFINE_RES_IRQ(irq);
if (irq <= 0) {
pr_warn("failed to map the Watchdog interrupt.\n");
nr_res--;
......@@ -367,7 +368,8 @@ static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
*/
pdev = platform_device_register_simple("sbsa-gwdt", index, res, nr_res);
if (IS_ERR(pdev)) {
acpi_unregister_gsi(wd->timer_interrupt);
if (irq > 0)
acpi_unregister_gsi(wd->timer_interrupt);
return PTR_ERR(pdev);
}
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment