| From foo@baz Mon Apr 9 17:09:24 CEST 2018 |
| From: Shanker Donthineni <shankerd@codeaurora.org> |
| Date: Tue, 5 Dec 2017 13:16:21 -0600 |
| Subject: irqchip/gic-v3: Fix the driver probe() fail due to disabled GICC entry |
| |
| From: Shanker Donthineni <shankerd@codeaurora.org> |
| |
| |
| [ Upstream commit ebe2f8718007d5a1238bb3cb8141b5bb2b4d5773 ] |
| |
| The ACPI specification says OS shouldn't attempt to use GICC configuration |
| parameters if the flag ACPI_MADT_ENABLED is cleared. The ARM64-SMP code |
| skips the disabled GICC entries but not causing any issue. However the |
| current GICv3 driver probe bails out causing kernel panic() instead of |
| skipping the disabled GICC interfaces. This issue happens on systems |
| where redistributor regions are not in the always-on power domain and |
| one of GICC interface marked with ACPI_MADT_ENABLED=0. |
| |
| This patch does the two things to fix the panic. |
| - Don't return an error in gic_acpi_match_gicc() for disabled GICC entry. |
| - No need to keep GICR region information for disabled GICC entry. |
| |
| Observed kernel crash on QDF2400 platform GICC entry is disabled. |
| Kernel crash traces: |
| Kernel panic - not syncing: No interrupt controller found. |
| CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.13.5 #26 |
| [<ffff000008087770>] dump_backtrace+0x0/0x218 |
| [<ffff0000080879dc>] show_stack+0x14/0x20 |
| [<ffff00000883b078>] dump_stack+0x98/0xb8 |
| [<ffff0000080c5c14>] panic+0x118/0x26c |
| [<ffff000008b62348>] init_IRQ+0x24/0x2c |
| [<ffff000008b609fc>] start_kernel+0x230/0x394 |
| [<ffff000008b601e4>] __primary_switched+0x64/0x6c |
| ---[ end Kernel panic - not syncing: No interrupt controller found. |
| |
| Disabled GICC subtable example: |
| Subtable Type : 0B [Generic Interrupt Controller] |
| Length : 50 |
| Reserved : 0000 |
| CPU Interface Number : 0000003D |
| Processor UID : 0000003D |
| Flags (decoded below) : 00000000 |
| Processor Enabled : 0 |
| Performance Interrupt Trig Mode : 0 |
| Virtual GIC Interrupt Trig Mode : 0 |
| Parking Protocol Version : 00000000 |
| Performance Interrupt : 00000017 |
| Parked Address : 0000000000000000 |
| Base Address : 0000000000000000 |
| Virtual GIC Base Address : 0000000000000000 |
| Hypervisor GIC Base Address : 0000000000000000 |
| Virtual GIC Interrupt : 00000019 |
| Redistributor Base Address : 0000FFFF88F40000 |
| ARM MPIDR : 000000000000000D |
| Efficiency Class : 00 |
| Reserved : 000000 |
| Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org> |
| Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> |
| |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/irqchip/irq-gic-v3.c | 11 +++++++++++ |
| 1 file changed, 11 insertions(+) |
| |
| --- a/drivers/irqchip/irq-gic-v3.c |
| +++ b/drivers/irqchip/irq-gic-v3.c |
| @@ -1250,6 +1250,10 @@ gic_acpi_parse_madt_gicc(struct acpi_sub |
| u32 size = reg == GIC_PIDR2_ARCH_GICv4 ? SZ_64K * 4 : SZ_64K * 2; |
| void __iomem *redist_base; |
| |
| + /* GICC entry which has !ACPI_MADT_ENABLED is not unusable so skip */ |
| + if (!(gicc->flags & ACPI_MADT_ENABLED)) |
| + return 0; |
| + |
| redist_base = ioremap(gicc->gicr_base_address, size); |
| if (!redist_base) |
| return -ENOMEM; |
| @@ -1299,6 +1303,13 @@ static int __init gic_acpi_match_gicc(st |
| if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address) |
| return 0; |
| |
| + /* |
| + * It's perfectly valid firmware can pass disabled GICC entry, driver |
| + * should not treat as errors, skip the entry instead of probe fail. |
| + */ |
| + if (!(gicc->flags & ACPI_MADT_ENABLED)) |
| + return 0; |
| + |
| return -ENODEV; |
| } |
| |