aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShanker Donthineni <shankerd@codeaurora.org>2017-12-05 14:16:21 -0500
committerMarc Zyngier <marc.zyngier@arm.com>2018-01-04 06:14:10 -0500
commitebe2f8718007d5a1238bb3cb8141b5bb2b4d5773 (patch)
treeff44262f9135403934612ed02d35d99f74383fd6
parent4235ff50cf98dd42ba15175687570f9f03e124a1 (diff)
irqchip/gic-v3: Fix the driver probe() fail due to disabled GICC entry
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>
-rw-r--r--drivers/irqchip/irq-gic-v3.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index b56c3e23f0af..a874777e9b9d 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -1331,6 +1331,10 @@ gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
1331 u32 size = reg == GIC_PIDR2_ARCH_GICv4 ? SZ_64K * 4 : SZ_64K * 2; 1331 u32 size = reg == GIC_PIDR2_ARCH_GICv4 ? SZ_64K * 4 : SZ_64K * 2;
1332 void __iomem *redist_base; 1332 void __iomem *redist_base;
1333 1333
1334 /* GICC entry which has !ACPI_MADT_ENABLED is not unusable so skip */
1335 if (!(gicc->flags & ACPI_MADT_ENABLED))
1336 return 0;
1337
1334 redist_base = ioremap(gicc->gicr_base_address, size); 1338 redist_base = ioremap(gicc->gicr_base_address, size);
1335 if (!redist_base) 1339 if (!redist_base)
1336 return -ENOMEM; 1340 return -ENOMEM;
@@ -1380,6 +1384,13 @@ static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header,
1380 if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address) 1384 if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address)
1381 return 0; 1385 return 0;
1382 1386
1387 /*
1388 * It's perfectly valid firmware can pass disabled GICC entry, driver
1389 * should not treat as errors, skip the entry instead of probe fail.
1390 */
1391 if (!(gicc->flags & ACPI_MADT_ENABLED))
1392 return 0;
1393
1383 return -ENODEV; 1394 return -ENODEV;
1384} 1395}
1385 1396