From 36464580e658019ac7be26a08c4679bee0454d2c Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Mon, 11 Dec 2017 21:39:10 +0100 Subject: [PATCH 1/9] dt-bindings/bcm2836-l1-intc: Add interrupt polarity support This increases the interrupt cells for the 1st level interrupt controller binding in order to describe the polarity like on the other ARM platforms. Reviewed-by: Rob Herring Signed-off-by: Stefan Wahren Signed-off-by: Marc Zyngier --- .../bindings/interrupt-controller/brcm,bcm2836-l1-intc.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2836-l1-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2836-l1-intc.txt index f320dcd6e69b..8ced1696c325 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2836-l1-intc.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2836-l1-intc.txt @@ -12,7 +12,7 @@ Required properties: registers - interrupt-controller: Identifies the node as an interrupt controller - #interrupt-cells: Specifies the number of cells needed to encode an - interrupt source. The value shall be 1 + interrupt source. The value shall be 2 Please refer to interrupts.txt in this directory for details of the common Interrupt Controllers bindings used by client devices. @@ -32,6 +32,6 @@ local_intc: local_intc { compatible = "brcm,bcm2836-l1-intc"; reg = <0x40000000 0x100>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; interrupt-parent = <&local_intc>; }; From ad83c7cb2f37fad01f53a8748c6f8067acb2968d Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Mon, 11 Dec 2017 21:39:11 +0100 Subject: [PATCH 2/9] irqchip/irq-bcm2836: Add support for DT interrupt polarity In order to properly define the polarity of the per-cpu interrupts, we need to support for a second property cell. But this must be optional to keep backward compatibility with old DT blobs. Suggested-by: Marc Zyngier Signed-off-by: Stefan Wahren Signed-off-by: Marc Zyngier --- drivers/irqchip/irq-bcm2836.c | 44 +++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c index 667b9e14b032..dfe4a460340b 100644 --- a/drivers/irqchip/irq-bcm2836.c +++ b/drivers/irqchip/irq-bcm2836.c @@ -98,13 +98,35 @@ static struct irq_chip bcm2836_arm_irqchip_gpu = { .irq_unmask = bcm2836_arm_irqchip_unmask_gpu_irq, }; -static void bcm2836_arm_irqchip_register_irq(int hwirq, struct irq_chip *chip) +static int bcm2836_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) { - int irq = irq_create_mapping(intc.domain, hwirq); + struct irq_chip *chip; + + switch (hw) { + case LOCAL_IRQ_CNTPSIRQ: + case LOCAL_IRQ_CNTPNSIRQ: + case LOCAL_IRQ_CNTHPIRQ: + case LOCAL_IRQ_CNTVIRQ: + chip = &bcm2836_arm_irqchip_timer; + break; + case LOCAL_IRQ_GPU_FAST: + chip = &bcm2836_arm_irqchip_gpu; + break; + case LOCAL_IRQ_PMU_FAST: + chip = &bcm2836_arm_irqchip_pmu; + break; + default: + pr_warn_once("Unexpected hw irq: %lu\n", hw); + return -EINVAL; + } irq_set_percpu_devid(irq); - irq_set_chip_and_handler(irq, chip, handle_percpu_devid_irq); + irq_domain_set_info(d, irq, hw, chip, d->host_data, + handle_percpu_devid_irq, NULL, NULL); irq_set_status_flags(irq, IRQ_NOAUTOEN); + + return 0; } static void @@ -165,7 +187,8 @@ static int bcm2836_cpu_dying(unsigned int cpu) #endif static const struct irq_domain_ops bcm2836_arm_irqchip_intc_ops = { - .xlate = irq_domain_xlate_onecell + .xlate = irq_domain_xlate_onetwocell, + .map = bcm2836_map, }; static void @@ -218,19 +241,6 @@ static int __init bcm2836_arm_irqchip_l1_intc_of_init(struct device_node *node, if (!intc.domain) panic("%pOF: unable to create IRQ domain\n", node); - bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTPSIRQ, - &bcm2836_arm_irqchip_timer); - bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTPNSIRQ, - &bcm2836_arm_irqchip_timer); - bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTHPIRQ, - &bcm2836_arm_irqchip_timer); - bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTVIRQ, - &bcm2836_arm_irqchip_timer); - bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_GPU_FAST, - &bcm2836_arm_irqchip_gpu); - bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_PMU_FAST, - &bcm2836_arm_irqchip_pmu); - bcm2836_arm_irqchip_smp_init(); set_handle_irq(bcm2836_arm_irqchip_handle_irq); From b12f5d0ffcdcd1dc9c732a5be72afdc6a7d627cf Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Mon, 11 Dec 2017 21:39:12 +0100 Subject: [PATCH 3/9] dt-bindings/bcm283x: Define polarity of per-cpu interrupts This patch define the polarity of the per-cpu interrupts on BCM2836 and BCM2837 in order to avoid the warnings from ARM arch timer code: arch_timer: WARNING: Invalid trigger for IRQ19, assuming level low arch_timer: WARNING: Please fix your firmware arch_timer: cp15 timer(s) running at 19.20MHz (virt). Signed-off-by: Stefan Wahren Signed-off-by: Marc Zyngier --- arch/arm/boot/dts/bcm2836.dtsi | 14 +++++++------- arch/arm/boot/dts/bcm2837.dtsi | 12 ++++++------ arch/arm/boot/dts/bcm283x.dtsi | 1 + 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/arch/arm/boot/dts/bcm2836.dtsi b/arch/arm/boot/dts/bcm2836.dtsi index 61e158003509..1dfd76442777 100644 --- a/arch/arm/boot/dts/bcm2836.dtsi +++ b/arch/arm/boot/dts/bcm2836.dtsi @@ -13,24 +13,24 @@ compatible = "brcm,bcm2836-l1-intc"; reg = <0x40000000 0x100>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; interrupt-parent = <&local_intc>; }; arm-pmu { compatible = "arm,cortex-a7-pmu"; interrupt-parent = <&local_intc>; - interrupts = <9>; + interrupts = <9 IRQ_TYPE_LEVEL_HIGH>; }; }; timer { compatible = "arm,armv7-timer"; interrupt-parent = <&local_intc>; - interrupts = <0>, // PHYS_SECURE_PPI - <1>, // PHYS_NONSECURE_PPI - <3>, // VIRT_PPI - <2>; // HYP_PPI + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>, // PHYS_SECURE_PPI + <1 IRQ_TYPE_LEVEL_HIGH>, // PHYS_NONSECURE_PPI + <3 IRQ_TYPE_LEVEL_HIGH>, // VIRT_PPI + <2 IRQ_TYPE_LEVEL_HIGH>; // HYP_PPI always-on; }; @@ -76,7 +76,7 @@ compatible = "brcm,bcm2836-armctrl-ic"; reg = <0x7e00b200 0x200>; interrupt-parent = <&local_intc>; - interrupts = <8>; + interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; }; &cpu_thermal { diff --git a/arch/arm/boot/dts/bcm2837.dtsi b/arch/arm/boot/dts/bcm2837.dtsi index bc1cca5cf43c..efa7d3387ab2 100644 --- a/arch/arm/boot/dts/bcm2837.dtsi +++ b/arch/arm/boot/dts/bcm2837.dtsi @@ -12,7 +12,7 @@ compatible = "brcm,bcm2836-l1-intc"; reg = <0x40000000 0x100>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; interrupt-parent = <&local_intc>; }; }; @@ -20,10 +20,10 @@ timer { compatible = "arm,armv7-timer"; interrupt-parent = <&local_intc>; - interrupts = <0>, // PHYS_SECURE_PPI - <1>, // PHYS_NONSECURE_PPI - <3>, // VIRT_PPI - <2>; // HYP_PPI + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>, // PHYS_SECURE_PPI + <1 IRQ_TYPE_LEVEL_HIGH>, // PHYS_NONSECURE_PPI + <3 IRQ_TYPE_LEVEL_HIGH>, // VIRT_PPI + <2 IRQ_TYPE_LEVEL_HIGH>; // HYP_PPI always-on; }; @@ -73,7 +73,7 @@ compatible = "brcm,bcm2836-armctrl-ic"; reg = <0x7e00b200 0x200>; interrupt-parent = <&local_intc>; - interrupts = <8>; + interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; }; &cpu_thermal { diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi index dcde93c85c2d..18db25a5a66e 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi @@ -2,6 +2,7 @@ #include #include #include +#include /* firmware-provided startup stubs live here, where the secondary CPUs are * spinning. From 404e6bea10662f0e142748353169d25378271e49 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 2 Jan 2018 11:47:19 +0000 Subject: [PATCH 4/9] irqchip/ompic: fix return value check in ompic_of_init() In case of error, the function ioremap() returns NULL pointer not ERR_PTR(). The IS_ERR() test in the return value check should be replaced with NULL test. Fixes: 9b54470afd83 ("irqchip: add initial support for ompic") Acked-by: Stafford Horne Signed-off-by: Wei Yongjun Signed-off-by: Marc Zyngier --- drivers/irqchip/irq-ompic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/irq-ompic.c b/drivers/irqchip/irq-ompic.c index cf6d0c455518..e66ef4373b1e 100644 --- a/drivers/irqchip/irq-ompic.c +++ b/drivers/irqchip/irq-ompic.c @@ -171,9 +171,9 @@ static int __init ompic_of_init(struct device_node *node, /* Setup the device */ ompic_base = ioremap(res.start, resource_size(&res)); - if (IS_ERR(ompic_base)) { + if (!ompic_base) { pr_err("ompic: unable to map registers"); - return PTR_ERR(ompic_base); + return -ENOMEM; } irq = irq_of_parse_and_map(node, 0); From c2ba80af4805543ace4928191d877ffe706087e1 Mon Sep 17 00:00:00 2001 From: Miodrag Dinic Date: Fri, 29 Dec 2017 16:41:45 +0100 Subject: [PATCH 5/9] dt-bindings/goldfish-pic: Add device tree binding for Goldfish PIC driver Add documentation for DT binding of Goldfish PIC driver. The compatible string used by OS for binding the driver is "google,goldfish-pic". Acked-by: Rob Herring Signed-off-by: Miodrag Dinic Signed-off-by: Goran Ferenc Signed-off-by: Aleksandar Markovic Signed-off-by: Marc Zyngier --- .../google,goldfish-pic.txt | 30 +++++++++++++++++++ MAINTAINERS | 5 ++++ 2 files changed, 35 insertions(+) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt diff --git a/Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt b/Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt new file mode 100644 index 000000000000..35f752706e7d --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt @@ -0,0 +1,30 @@ +Android Goldfish PIC + +Android Goldfish programmable interrupt device used by Android +emulator. + +Required properties: + +- compatible : should contain "google,goldfish-pic" +- reg : +- interrupts : + +Example for mips when used in cascade mode: + + cpuintc { + #interrupt-cells = <0x1>; + #address-cells = <0>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + interrupt-controller@1f000000 { + compatible = "google,goldfish-pic"; + reg = <0x1f000000 0x1000>; + + interrupt-controller; + #interrupt-cells = <0x1>; + + interrupt-parent = <&cpuintc>; + interrupts = <0x2>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index b46c9cea5ae5..fe9a60ac81d8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -867,6 +867,11 @@ S: Supported F: drivers/android/ F: drivers/staging/android/ +ANDROID GOLDFISH PIC DRIVER +M: Miodrag Dinic +S: Supported +F: Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt + ANDROID GOLDFISH RTC DRIVER M: Miodrag Dinic S: Supported From 4235ff50cf98dd42ba15175687570f9f03e124a1 Mon Sep 17 00:00:00 2001 From: Miodrag Dinic Date: Fri, 29 Dec 2017 16:41:46 +0100 Subject: [PATCH 6/9] irqchip/irq-goldfish-pic: Add Goldfish PIC driver Add device driver for a virtual programmable interrupt controller The virtual PIC is designed as a device tree-based interrupt controller. The compatible string used by OS for binding the driver is "google,goldfish-pic". Signed-off-by: Miodrag Dinic Signed-off-by: Goran Ferenc Signed-off-by: Aleksandar Markovic Signed-off-by: Marc Zyngier --- MAINTAINERS | 1 + drivers/irqchip/Kconfig | 8 ++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-goldfish-pic.c | 139 +++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+) create mode 100644 drivers/irqchip/irq-goldfish-pic.c diff --git a/MAINTAINERS b/MAINTAINERS index fe9a60ac81d8..f3b9b8775e41 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -871,6 +871,7 @@ ANDROID GOLDFISH PIC DRIVER M: Miodrag Dinic S: Supported F: Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt +F: drivers/irqchip/irq-goldfish-pic.c ANDROID GOLDFISH RTC DRIVER M: Miodrag Dinic diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index c70476b34a53..d913aec85109 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -343,4 +343,12 @@ config MESON_IRQ_GPIO help Support Meson SoC Family GPIO Interrupt Multiplexer +config GOLDFISH_PIC + bool "Goldfish programmable interrupt controller" + depends on MIPS && (GOLDFISH || COMPILE_TEST) + select IRQ_DOMAIN + help + Say yes here to enable Goldfish interrupt controller driver used + for Goldfish based virtual platforms. + endmenu diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index d2df34a54d38..d27e3e3619e0 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -84,3 +84,4 @@ obj-$(CONFIG_QCOM_IRQ_COMBINER) += qcom-irq-combiner.o obj-$(CONFIG_IRQ_UNIPHIER_AIDET) += irq-uniphier-aidet.o obj-$(CONFIG_ARCH_SYNQUACER) += irq-sni-exiu.o obj-$(CONFIG_MESON_IRQ_GPIO) += irq-meson-gpio.o +obj-$(CONFIG_GOLDFISH_PIC) += irq-goldfish-pic.o diff --git a/drivers/irqchip/irq-goldfish-pic.c b/drivers/irqchip/irq-goldfish-pic.c new file mode 100644 index 000000000000..2a92f03c73e4 --- /dev/null +++ b/drivers/irqchip/irq-goldfish-pic.c @@ -0,0 +1,139 @@ +/* + * Driver for MIPS Goldfish Programmable Interrupt Controller. + * + * Author: Miodrag Dinic + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include + +#define GFPIC_NR_IRQS 32 + +/* 8..39 Cascaded Goldfish PIC interrupts */ +#define GFPIC_IRQ_BASE 8 + +#define GFPIC_REG_IRQ_PENDING 0x04 +#define GFPIC_REG_IRQ_DISABLE_ALL 0x08 +#define GFPIC_REG_IRQ_DISABLE 0x0c +#define GFPIC_REG_IRQ_ENABLE 0x10 + +struct goldfish_pic_data { + void __iomem *base; + struct irq_domain *irq_domain; +}; + +static void goldfish_pic_cascade(struct irq_desc *desc) +{ + struct goldfish_pic_data *gfpic = irq_desc_get_handler_data(desc); + struct irq_chip *host_chip = irq_desc_get_chip(desc); + u32 pending, hwirq, virq; + + chained_irq_enter(host_chip, desc); + + pending = readl(gfpic->base + GFPIC_REG_IRQ_PENDING); + while (pending) { + hwirq = __fls(pending); + virq = irq_linear_revmap(gfpic->irq_domain, hwirq); + generic_handle_irq(virq); + pending &= ~(1 << hwirq); + } + + chained_irq_exit(host_chip, desc); +} + +static const struct irq_domain_ops goldfish_irq_domain_ops = { + .xlate = irq_domain_xlate_onecell, +}; + +static int __init goldfish_pic_of_init(struct device_node *of_node, + struct device_node *parent) +{ + struct goldfish_pic_data *gfpic; + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + unsigned int parent_irq; + int ret = 0; + + gfpic = kzalloc(sizeof(*gfpic), GFP_KERNEL); + if (!gfpic) { + ret = -ENOMEM; + goto out_err; + } + + parent_irq = irq_of_parse_and_map(of_node, 0); + if (!parent_irq) { + pr_err("Failed to map parent IRQ!\n"); + ret = -EINVAL; + goto out_free; + } + + gfpic->base = of_iomap(of_node, 0); + if (!gfpic->base) { + pr_err("Failed to map base address!\n"); + ret = -ENOMEM; + goto out_unmap_irq; + } + + /* Mask interrupts. */ + writel(1, gfpic->base + GFPIC_REG_IRQ_DISABLE_ALL); + + gc = irq_alloc_generic_chip("GFPIC", 1, GFPIC_IRQ_BASE, gfpic->base, + handle_level_irq); + if (!gc) { + pr_err("Failed to allocate chip structures!\n"); + ret = -ENOMEM; + goto out_iounmap; + } + + ct = gc->chip_types; + ct->regs.enable = GFPIC_REG_IRQ_ENABLE; + ct->regs.disable = GFPIC_REG_IRQ_DISABLE; + ct->chip.irq_unmask = irq_gc_unmask_enable_reg; + ct->chip.irq_mask = irq_gc_mask_disable_reg; + + irq_setup_generic_chip(gc, IRQ_MSK(GFPIC_NR_IRQS), 0, + IRQ_NOPROBE | IRQ_LEVEL, 0); + + gfpic->irq_domain = irq_domain_add_legacy(of_node, GFPIC_NR_IRQS, + GFPIC_IRQ_BASE, 0, + &goldfish_irq_domain_ops, + NULL); + if (!gfpic->irq_domain) { + pr_err("Failed to add irqdomain!\n"); + ret = -ENOMEM; + goto out_destroy_generic_chip; + } + + irq_set_chained_handler_and_data(parent_irq, + goldfish_pic_cascade, gfpic); + + pr_info("Successfully registered.\n"); + return 0; + +out_destroy_generic_chip: + irq_destroy_generic_chip(gc, IRQ_MSK(GFPIC_NR_IRQS), + IRQ_NOPROBE | IRQ_LEVEL, 0); +out_iounmap: + iounmap(gfpic->base); +out_unmap_irq: + irq_dispose_mapping(parent_irq); +out_free: + kfree(gfpic); +out_err: + pr_err("Failed to initialize! (errno = %d)\n", ret); + return ret; +} + +IRQCHIP_DECLARE(google_gf_pic, "google,goldfish-pic", goldfish_pic_of_init); From ebe2f8718007d5a1238bb3cb8141b5bb2b4d5773 Mon Sep 17 00:00:00 2001 From: Shanker Donthineni Date: Tue, 5 Dec 2017 13:16:21 -0600 Subject: [PATCH 7/9] 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 [] dump_backtrace+0x0/0x218 [] show_stack+0x14/0x20 [] dump_stack+0x98/0xb8 [] panic+0x118/0x26c [] init_IRQ+0x24/0x2c [] start_kernel+0x230/0x394 [] __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 Signed-off-by: Marc Zyngier --- drivers/irqchip/irq-gic-v3.c | 11 +++++++++++ 1 file changed, 11 insertions(+) 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, 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; @@ -1380,6 +1384,13 @@ static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header, 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; } From 6baf9e67c9c5d738188b8490893c7e079d3deb7e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 5 Jan 2018 05:19:56 +0100 Subject: [PATCH 8/9] irq/work: Improve the flag definitions IRQ_WORK_FLAGS is defined simply to 3UL. This is confusing as it says nothing about its purpose. Define IRQ_WORK_FLAGS as a bitwise OR of IRQ_WORK_PENDING and IRQ_WORK_BUSY and change its name to IRQ_WORK_CLAIMED. While we're at it: use the BIT() macro for all flags. Signed-off-by: Bartosz Golaszewski Signed-off-by: Frederic Weisbecker Reviewed-by: Andy Shevchenko Cc: Linus Torvalds Cc: Marc Zyngier Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1515125996-21564-1-git-send-email-frederic@kernel.org Signed-off-by: Ingo Molnar --- include/linux/irq_work.h | 11 +++++++---- kernel/irq_work.c | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/linux/irq_work.h b/include/linux/irq_work.h index 0e81035b678f..b11fcdfd0770 100644 --- a/include/linux/irq_work.h +++ b/include/linux/irq_work.h @@ -13,10 +13,13 @@ * busy NULL, 2 -> {free, claimed} : callback in progress, can be claimed */ -#define IRQ_WORK_PENDING 1UL -#define IRQ_WORK_BUSY 2UL -#define IRQ_WORK_FLAGS 3UL -#define IRQ_WORK_LAZY 4UL /* Doesn't want IPI, wait for tick */ +#define IRQ_WORK_PENDING BIT(0) +#define IRQ_WORK_BUSY BIT(1) + +/* Doesn't want IPI, wait for tick: */ +#define IRQ_WORK_LAZY BIT(2) + +#define IRQ_WORK_CLAIMED (IRQ_WORK_PENDING | IRQ_WORK_BUSY) struct irq_work { unsigned long flags; diff --git a/kernel/irq_work.c b/kernel/irq_work.c index 40e9d739c169..6b7cdf17ccf8 100644 --- a/kernel/irq_work.c +++ b/kernel/irq_work.c @@ -36,7 +36,7 @@ static bool irq_work_claim(struct irq_work *work) */ flags = work->flags & ~IRQ_WORK_PENDING; for (;;) { - nflags = flags | IRQ_WORK_FLAGS; + nflags = flags | IRQ_WORK_CLAIMED; oflags = cmpxchg(&work->flags, flags, nflags); if (oflags == flags) break; From c5baa1be8f559d5f33c412d00cc1c86762a8bbbf Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 17 Jan 2018 14:26:47 +0000 Subject: [PATCH 9/9] irqdomain: Kill CONFIG_IRQ_DOMAIN_DEBUG CONFIG_IRQ_DOMAIN_DEBUG is similar to CONFIG_GENERIC_IRQ_DEBUGFS, just with less information. Spring cleanup time. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Yang Shunyong Link: https://lkml.kernel.org/r/20180117142647.23622-1-marc.zyngier@arm.com --- Documentation/IRQ-domain.txt | 36 +----- arch/arm/configs/aspeed_g4_defconfig | 1 - arch/arm/configs/aspeed_g5_defconfig | 1 - arch/arm/configs/hisi_defconfig | 1 - arch/arm/configs/multi_v7_defconfig | 1 - arch/arm/configs/mvebu_v7_defconfig | 1 - arch/arm/configs/pxa_defconfig | 1 - arch/arm/configs/sama5_defconfig | 1 - arch/arm/configs/tegra_defconfig | 1 - arch/arm/configs/vt8500_v6_v7_defconfig | 1 - arch/powerpc/configs/fsl-emb-nonhw.config | 1 - arch/powerpc/configs/powernv_defconfig | 1 - arch/powerpc/configs/ppc64_defconfig | 1 - arch/powerpc/configs/pseries_defconfig | 1 - arch/xtensa/configs/audio_kc705_defconfig | 1 - arch/xtensa/configs/cadence_csp_defconfig | 1 - arch/xtensa/configs/generic_kc705_defconfig | 1 - arch/xtensa/configs/nommu_kc705_defconfig | 1 - arch/xtensa/configs/smp_lx200_defconfig | 1 - kernel/irq/Kconfig | 10 -- kernel/irq/irqdomain.c | 118 -------------------- 21 files changed, 2 insertions(+), 180 deletions(-) diff --git a/Documentation/IRQ-domain.txt b/Documentation/IRQ-domain.txt index 4a1cd7645d85..507775cce753 100644 --- a/Documentation/IRQ-domain.txt +++ b/Documentation/IRQ-domain.txt @@ -265,37 +265,5 @@ support other architectures, such as ARM, ARM64 etc. === Debugging === -If you switch on CONFIG_IRQ_DOMAIN_DEBUG (which depends on -CONFIG_IRQ_DOMAIN and CONFIG_DEBUG_FS), you will find a new file in -your debugfs mount point, called irq_domain_mapping. This file -contains a live snapshot of all the IRQ domains in the system: - - name mapped linear-max direct-max devtree-node - pl061 8 8 0 /smb/gpio@e0080000 - pl061 8 8 0 /smb/gpio@e1050000 - pMSI 0 0 0 /interrupt-controller@e1101000/v2m@e0080000 - MSI 37 0 0 /interrupt-controller@e1101000/v2m@e0080000 - GICv2m 37 0 0 /interrupt-controller@e1101000/v2m@e0080000 - GICv2 448 448 0 /interrupt-controller@e1101000 - -it also iterates over the interrupts to display their mapping in the -domains, and makes the domain stacking visible: - - -irq hwirq chip name chip data active type domain - 1 0x00019 GICv2 0xffff00000916bfd8 * LINEAR GICv2 - 2 0x0001d GICv2 0xffff00000916bfd8 LINEAR GICv2 - 3 0x0001e GICv2 0xffff00000916bfd8 * LINEAR GICv2 - 4 0x0001b GICv2 0xffff00000916bfd8 * LINEAR GICv2 - 5 0x0001a GICv2 0xffff00000916bfd8 LINEAR GICv2 -[...] - 96 0x81808 MSI 0x (null) RADIX MSI - 96+ 0x00063 GICv2m 0xffff8003ee116980 RADIX GICv2m - 96+ 0x00063 GICv2 0xffff00000916bfd8 LINEAR GICv2 - 97 0x08800 MSI 0x (null) * RADIX MSI - 97+ 0x00064 GICv2m 0xffff8003ee116980 * RADIX GICv2m - 97+ 0x00064 GICv2 0xffff00000916bfd8 * LINEAR GICv2 - -Here, interrupts 1-5 are only using a single domain, while 96 and 97 -are build out of a stack of three domain, each level performing a -particular function. +Most of the internals of the IRQ subsystem are exposed in debugfs by +turning CONFIG_GENERIC_IRQ_DEBUGFS on. diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/aspeed_g4_defconfig index d23b9d56a88b..95946dee9c77 100644 --- a/arch/arm/configs/aspeed_g4_defconfig +++ b/arch/arm/configs/aspeed_g4_defconfig @@ -1,7 +1,6 @@ CONFIG_KERNEL_XZ=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y CONFIG_LOG_BUF_SHIFT=14 diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig index c0ad7b82086b..8c7ea033cdc2 100644 --- a/arch/arm/configs/aspeed_g5_defconfig +++ b/arch/arm/configs/aspeed_g5_defconfig @@ -1,7 +1,6 @@ CONFIG_KERNEL_XZ=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y CONFIG_LOG_BUF_SHIFT=14 diff --git a/arch/arm/configs/hisi_defconfig b/arch/arm/configs/hisi_defconfig index b2e340b272ee..74d611e41e02 100644 --- a/arch/arm/configs/hisi_defconfig +++ b/arch/arm/configs/hisi_defconfig @@ -1,4 +1,3 @@ -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_BLK_DEV_INITRD=y diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 61509c4b769f..b659244902cd 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -1,6 +1,5 @@ CONFIG_SYSVIPC=y CONFIG_FHANDLE=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_CGROUPS=y diff --git a/arch/arm/configs/mvebu_v7_defconfig b/arch/arm/configs/mvebu_v7_defconfig index 69553704f2dc..ee61be093633 100644 --- a/arch/arm/configs/mvebu_v7_defconfig +++ b/arch/arm/configs/mvebu_v7_defconfig @@ -1,6 +1,5 @@ CONFIG_SYSVIPC=y CONFIG_FHANDLE=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_HIGH_RES_TIMERS=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y diff --git a/arch/arm/configs/pxa_defconfig b/arch/arm/configs/pxa_defconfig index 830e817a028a..837d0c9c8b0e 100644 --- a/arch/arm/configs/pxa_defconfig +++ b/arch/arm/configs/pxa_defconfig @@ -1,7 +1,6 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_FHANDLE=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_BSD_PROCESS_ACCT=y diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig index 6529cb43e0fd..2080025556b5 100644 --- a/arch/arm/configs/sama5_defconfig +++ b/arch/arm/configs/sama5_defconfig @@ -2,7 +2,6 @@ # CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_FHANDLE=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y CONFIG_LOG_BUF_SHIFT=14 diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig index 6678f2929356..c819be04187e 100644 --- a/arch/arm/configs/tegra_defconfig +++ b/arch/arm/configs/tegra_defconfig @@ -1,5 +1,4 @@ CONFIG_SYSVIPC=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_IKCONFIG=y diff --git a/arch/arm/configs/vt8500_v6_v7_defconfig b/arch/arm/configs/vt8500_v6_v7_defconfig index 1bfaa7bfc392..9b85326ba287 100644 --- a/arch/arm/configs/vt8500_v6_v7_defconfig +++ b/arch/arm/configs/vt8500_v6_v7_defconfig @@ -1,4 +1,3 @@ -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_BLK_DEV_INITRD=y diff --git a/arch/powerpc/configs/fsl-emb-nonhw.config b/arch/powerpc/configs/fsl-emb-nonhw.config index cc49c95494da..e0567dc41968 100644 --- a/arch/powerpc/configs/fsl-emb-nonhw.config +++ b/arch/powerpc/configs/fsl-emb-nonhw.config @@ -71,7 +71,6 @@ CONFIG_IP_ROUTE_MULTIPATH=y CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_SCTP=m CONFIG_IPV6=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_ISO9660_FS=m CONFIG_JFFS2_FS_DEBUG=1 CONFIG_JFFS2_FS=y diff --git a/arch/powerpc/configs/powernv_defconfig b/arch/powerpc/configs/powernv_defconfig index 4891bbed6258..73dab7a37386 100644 --- a/arch/powerpc/configs/powernv_defconfig +++ b/arch/powerpc/configs/powernv_defconfig @@ -4,7 +4,6 @@ CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_AUDIT=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_TASKSTATS=y diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 6ddca80c52c3..5033e630afea 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -1,7 +1,6 @@ CONFIG_PPC64=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_TASKSTATS=y diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index bde2cd1005a2..0dd5cf7b566d 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig @@ -3,7 +3,6 @@ CONFIG_NR_CPUS=2048 CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_AUDIT=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_TASKSTATS=y diff --git a/arch/xtensa/configs/audio_kc705_defconfig b/arch/xtensa/configs/audio_kc705_defconfig index 8d16925765cb..2bf964df37ba 100644 --- a/arch/xtensa/configs/audio_kc705_defconfig +++ b/arch/xtensa/configs/audio_kc705_defconfig @@ -1,7 +1,6 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_FHANDLE=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y CONFIG_IRQ_TIME_ACCOUNTING=y diff --git a/arch/xtensa/configs/cadence_csp_defconfig b/arch/xtensa/configs/cadence_csp_defconfig index f2d3094aa1d1..3221b7053fa3 100644 --- a/arch/xtensa/configs/cadence_csp_defconfig +++ b/arch/xtensa/configs/cadence_csp_defconfig @@ -1,7 +1,6 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_USELIB=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y CONFIG_IRQ_TIME_ACCOUNTING=y diff --git a/arch/xtensa/configs/generic_kc705_defconfig b/arch/xtensa/configs/generic_kc705_defconfig index 744adeaf2945..985fa8546e4e 100644 --- a/arch/xtensa/configs/generic_kc705_defconfig +++ b/arch/xtensa/configs/generic_kc705_defconfig @@ -1,7 +1,6 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_FHANDLE=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y CONFIG_IRQ_TIME_ACCOUNTING=y diff --git a/arch/xtensa/configs/nommu_kc705_defconfig b/arch/xtensa/configs/nommu_kc705_defconfig index 78c2529d0459..624f9b3a3878 100644 --- a/arch/xtensa/configs/nommu_kc705_defconfig +++ b/arch/xtensa/configs/nommu_kc705_defconfig @@ -1,7 +1,6 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_FHANDLE=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y CONFIG_IRQ_TIME_ACCOUNTING=y diff --git a/arch/xtensa/configs/smp_lx200_defconfig b/arch/xtensa/configs/smp_lx200_defconfig index 14e3ca353ac8..11fed6c06a7c 100644 --- a/arch/xtensa/configs/smp_lx200_defconfig +++ b/arch/xtensa/configs/smp_lx200_defconfig @@ -1,7 +1,6 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_FHANDLE=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y CONFIG_IRQ_TIME_ACCOUNTING=y diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig index 89e355866450..6fc87ccda1d7 100644 --- a/kernel/irq/Kconfig +++ b/kernel/irq/Kconfig @@ -103,16 +103,6 @@ config GENERIC_IRQ_MATRIX_ALLOCATOR config GENERIC_IRQ_RESERVATION_MODE bool -config IRQ_DOMAIN_DEBUG - bool "Expose hardware/virtual IRQ mapping via debugfs" - depends on IRQ_DOMAIN && DEBUG_FS - help - This option will show the mapping relationship between hardware irq - numbers and Linux irq numbers. The mapping is exposed via debugfs - in the file "irq_domain_mapping". - - If you don't know what this means you don't need it. - # Support forced irq threading config IRQ_FORCED_THREADING bool diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 62068ad46930..e6a9c36470ee 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -897,124 +897,6 @@ unsigned int irq_find_mapping(struct irq_domain *domain, } EXPORT_SYMBOL_GPL(irq_find_mapping); -#ifdef CONFIG_IRQ_DOMAIN_DEBUG -static void virq_debug_show_one(struct seq_file *m, struct irq_desc *desc) -{ - struct irq_domain *domain; - struct irq_data *data; - - domain = desc->irq_data.domain; - data = &desc->irq_data; - - while (domain) { - unsigned int irq = data->irq; - unsigned long hwirq = data->hwirq; - struct irq_chip *chip; - bool direct; - - if (data == &desc->irq_data) - seq_printf(m, "%5d ", irq); - else - seq_printf(m, "%5d+ ", irq); - seq_printf(m, "0x%05lx ", hwirq); - - chip = irq_data_get_irq_chip(data); - seq_printf(m, "%-15s ", (chip && chip->name) ? chip->name : "none"); - - seq_printf(m, "0x%p ", irq_data_get_irq_chip_data(data)); - - seq_printf(m, " %c ", (desc->action && desc->action->handler) ? '*' : ' '); - direct = (irq == hwirq) && (irq < domain->revmap_direct_max_irq); - seq_printf(m, "%6s%-8s ", - (hwirq < domain->revmap_size) ? "LINEAR" : "RADIX", - direct ? "(DIRECT)" : ""); - seq_printf(m, "%s\n", domain->name); -#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY - domain = domain->parent; - data = data->parent_data; -#else - domain = NULL; -#endif - } -} - -static int virq_debug_show(struct seq_file *m, void *private) -{ - unsigned long flags; - struct irq_desc *desc; - struct irq_domain *domain; - struct radix_tree_iter iter; - void __rcu **slot; - int i; - - seq_printf(m, " %-16s %-6s %-10s %-10s %s\n", - "name", "mapped", "linear-max", "direct-max", "devtree-node"); - mutex_lock(&irq_domain_mutex); - list_for_each_entry(domain, &irq_domain_list, link) { - struct device_node *of_node; - const char *name; - - int count = 0; - - of_node = irq_domain_get_of_node(domain); - if (of_node) - name = of_node_full_name(of_node); - else if (is_fwnode_irqchip(domain->fwnode)) - name = container_of(domain->fwnode, struct irqchip_fwid, - fwnode)->name; - else - name = ""; - - radix_tree_for_each_slot(slot, &domain->revmap_tree, &iter, 0) - count++; - seq_printf(m, "%c%-16s %6u %10u %10u %s\n", - domain == irq_default_domain ? '*' : ' ', domain->name, - domain->revmap_size + count, domain->revmap_size, - domain->revmap_direct_max_irq, - name); - } - mutex_unlock(&irq_domain_mutex); - - seq_printf(m, "%-5s %-7s %-15s %-*s %6s %-14s %s\n", "irq", "hwirq", - "chip name", (int)(2 * sizeof(void *) + 2), "chip data", - "active", "type", "domain"); - - for (i = 1; i < nr_irqs; i++) { - desc = irq_to_desc(i); - if (!desc) - continue; - - raw_spin_lock_irqsave(&desc->lock, flags); - virq_debug_show_one(m, desc); - raw_spin_unlock_irqrestore(&desc->lock, flags); - } - - return 0; -} - -static int virq_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, virq_debug_show, inode->i_private); -} - -static const struct file_operations virq_debug_fops = { - .open = virq_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init irq_debugfs_init(void) -{ - if (debugfs_create_file("irq_domain_mapping", S_IRUGO, NULL, - NULL, &virq_debug_fops) == NULL) - return -ENOMEM; - - return 0; -} -__initcall(irq_debugfs_init); -#endif /* CONFIG_IRQ_DOMAIN_DEBUG */ - /** * irq_domain_xlate_onecell() - Generic xlate for direct one cell bindings *