From 5aac2d3368210f15c2fc73f158e2110a0bb611ca Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 14 Sep 2015 10:11:26 +0200 Subject: powerpc/mpc5121_ads_cpld: Prepare irq handler for irq argument removal The irq argument of most interrupt flow handlers is unused or merily used instead of a local variable. The handlers which need the irq argument can retrieve the irq number from the irq descriptor. Search and update was done with coccinelle and the invaluable help of Julia Lawall. Signed-off-by: Thomas Gleixner Cc: Julia Lawall Cc: Jiang Liu Cc: Anatolij Gustschin Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c index 11090ab4bf59..cf8287487157 100644 --- a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c +++ b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c @@ -105,8 +105,10 @@ cpld_pic_get_irq(int offset, u8 ignore, u8 __iomem *statusp, } static void -cpld_pic_cascade(unsigned int irq, struct irq_desc *desc) +cpld_pic_cascade(unsigned int __irq, struct irq_desc *desc) { + unsigned int irq; + irq = cpld_pic_get_irq(0, PCI_IGNORE, &cpld_regs->pci_status, &cpld_regs->pci_mask); if (irq != NO_IRQ) { -- cgit v1.2.3 From 0a0dbd92584061549d9775030269365dc16ad289 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 14 Sep 2015 10:13:42 +0200 Subject: powerpc/85xx: Prepare irq handlers for irq argument removal The irq argument of most interrupt flow handlers is unused or merily used instead of a local variable. The handlers which need the irq argument can retrieve the irq number from the irq descriptor. Search and update was done with coccinelle and the invaluable help of Julia Lawall. Signed-off-by: Thomas Gleixner Cc: Julia Lawall Cc: Jiang Liu Cc: Scott Wood Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/platforms/85xx/mpc85xx_cds.c | 3 ++- arch/powerpc/platforms/85xx/socrates_fpga_pic.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c index b0753e222086..13a8d1a3d55c 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c @@ -192,9 +192,10 @@ void mpc85xx_cds_fixup_bus(struct pci_bus *bus) } #ifdef CONFIG_PPC_I8259 -static void mpc85xx_8259_cascade_handler(unsigned int irq, +static void mpc85xx_8259_cascade_handler(unsigned int __irq, struct irq_desc *desc) { + unsigned int irq = irq_desc_get_irq(desc); unsigned int cascade_irq = i8259_irq(); if (cascade_irq != NO_IRQ) diff --git a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c index 55a9682b9529..d78fda892e8b 100644 --- a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c +++ b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c @@ -91,9 +91,10 @@ static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq) (irq_hw_number_t)i); } -void socrates_fpga_pic_cascade(unsigned int irq, struct irq_desc *desc) +void socrates_fpga_pic_cascade(unsigned int __irq, struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); + unsigned int irq = irq_desc_get_irq(desc); unsigned int cascade_irq; /* -- cgit v1.2.3 From 391de7f9ef9e6a500343d977ccd037b70e62aa45 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 14 Sep 2015 10:17:00 +0200 Subject: powerpc/cell: Prepare irq handler for irq argument removal The irq argument of most interrupt flow handlers is unused or merily used instead of a local variable. The handlers which need the irq argument can retrieve the irq number from the irq descriptor. Search and update was done with coccinelle and the invaluable help of Julia Lawall. Signed-off-by: Thomas Gleixner Cc: Julia Lawall Cc: Jiang Liu Cc: Arnd Bergmann Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/platforms/cell/interrupt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index a15f1efc295f..6558e7e8ee50 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -99,11 +99,12 @@ static void iic_ioexc_eoi(struct irq_data *d) { } -static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc) +static void iic_ioexc_cascade(unsigned int __irq, struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); struct cbe_iic_regs __iomem *node_iic = (void __iomem *)irq_desc_get_handler_data(desc); + unsigned int irq = irq_desc_get_irq(desc); unsigned int base = (irq & 0xffffff00) | IIC_IRQ_TYPE_IOEXC; unsigned long bits, ack; int cascade; -- cgit v1.2.3 From 5230347ea70a811f0a526e8e4f0f529ac31b7d18 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 14 Sep 2015 10:27:13 +0200 Subject: soc: dove: Use irq_desc_get_xxx() to avoid redundant lookup of irq_desc Search and replace done with coccinelle Signed-off-by: Thomas Gleixner Cc: Julia Lawall Cc: Jiang Liu --- drivers/soc/dove/pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/dove/pmu.c b/drivers/soc/dove/pmu.c index 6792aae9e2e5..4decb26e8116 100644 --- a/drivers/soc/dove/pmu.c +++ b/drivers/soc/dove/pmu.c @@ -224,7 +224,7 @@ static void __pmu_domain_register(struct pmu_domain *domain, /* PMU IRQ controller */ static void pmu_irq_handler(unsigned int irq, struct irq_desc *desc) { - struct pmu_data *pmu = irq_get_handler_data(irq); + struct pmu_data *pmu = irq_desc_get_handler_data(desc); struct irq_chip_generic *gc = pmu->irq_gc; struct irq_domain *domain = pmu->irq_domain; void __iomem *base = gc->reg_base; -- cgit v1.2.3 From b838c950b397ebed94eb11b473f1f17428a1443d Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 14 Sep 2015 10:20:25 +0200 Subject: soc: dove: Prepare irq handler for irq argument removal The irq argument of most interrupt flow handlers is unused or merily used instead of a local variable. The handlers which need the irq argument can retrieve the irq number from the irq descriptor. Search and update was done with coccinelle and the invaluable help of Julia Lawall. Signed-off-by: Thomas Gleixner Cc: Julia Lawall Cc: Jiang Liu Cc: Gregory CLEMENT --- drivers/soc/dove/pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/dove/pmu.c b/drivers/soc/dove/pmu.c index 4decb26e8116..6bc13f99489a 100644 --- a/drivers/soc/dove/pmu.c +++ b/drivers/soc/dove/pmu.c @@ -232,7 +232,7 @@ static void pmu_irq_handler(unsigned int irq, struct irq_desc *desc) u32 done = ~0; if (stat == 0) { - handle_bad_irq(irq, desc); + handle_bad_irq(irq_desc_get_irq(desc), desc); return; } -- cgit v1.2.3 From da92b4eb7e2ec9866f14a0c8f453788e8052dee7 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 1 Jun 2015 16:05:33 +0800 Subject: powerpc, irq: Use access helper irq_data_get_affinity_mask() Use access helper irq_data_get_affinity_mask() so we can move the affinity mask to irq_common_data. Signed-off-by: Jiang Liu Cc: Benjamin Herrenschmidt Cc: Michael Ellerman Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/1433145945-789-25-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/powerpc/kernel/irq.c | 2 +- arch/powerpc/sysdev/xics/ics-opal.c | 2 +- arch/powerpc/sysdev/xics/ics-rtas.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 45096033d37b..290559df1e8b 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -441,7 +441,7 @@ void migrate_irqs(void) chip = irq_data_get_irq_chip(data); - cpumask_and(mask, data->affinity, map); + cpumask_and(mask, irq_data_get_affinity_mask(data), map); if (cpumask_any(mask) >= nr_cpu_ids) { pr_warn("Breaking affinity for irq %i\n", irq); cpumask_copy(mask, map); diff --git a/arch/powerpc/sysdev/xics/ics-opal.c b/arch/powerpc/sysdev/xics/ics-opal.c index 11ac964d5175..27c936c080a6 100644 --- a/arch/powerpc/sysdev/xics/ics-opal.c +++ b/arch/powerpc/sysdev/xics/ics-opal.c @@ -54,7 +54,7 @@ static void ics_opal_unmask_irq(struct irq_data *d) if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS) return; - server = xics_get_irq_server(d->irq, d->affinity, 0); + server = xics_get_irq_server(d->irq, irq_data_get_affinity_mask(d), 0); server = ics_opal_mangle_server(server); rc = opal_set_xive(hw_irq, server, DEFAULT_PRIORITY); diff --git a/arch/powerpc/sysdev/xics/ics-rtas.c b/arch/powerpc/sysdev/xics/ics-rtas.c index d1c625c4cc5a..3854dd41558d 100644 --- a/arch/powerpc/sysdev/xics/ics-rtas.c +++ b/arch/powerpc/sysdev/xics/ics-rtas.c @@ -47,7 +47,7 @@ static void ics_rtas_unmask_irq(struct irq_data *d) if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS) return; - server = xics_get_irq_server(d->irq, d->affinity, 0); + server = xics_get_irq_server(d->irq, irq_data_get_affinity_mask(d), 0); call_status = rtas_call(ibm_set_xive, 3, 1, NULL, hw_irq, server, DEFAULT_PRIORITY); -- cgit v1.2.3 From dc2ec62f75fd9be78d07b3b453aeb0d201ead419 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 15 Sep 2015 13:34:05 +0200 Subject: net/mlx4_en: Use access helper irq_data_get_affinity_mask() This is a preparatory patch for moving irq_data struct members. Search and replace was done with coccinelle Signed-off-by: Thomas Gleixner Cc: Julia Lawall Cc: Jiang Liu Cc: Amir Vadai --- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 4402a1e48c9b..4c7de8c44659 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -1047,13 +1047,15 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget) /* If we used up all the quota - we're probably not done yet... */ if (done == budget) { - int cpu_curr; const struct cpumask *aff; + struct irq_data *idata; + int cpu_curr; INC_PERF_COUNTER(priv->pstats.napi_quota); cpu_curr = smp_processor_id(); - aff = irq_desc_get_irq_data(cq->irq_desc)->affinity; + idata = irq_desc_get_irq_data(cq->irq_desc); + aff = irq_data_get_affinity_mask(idata); if (likely(cpumask_test_cpu(cpu_curr, aff))) return budget; -- cgit v1.2.3 From e4084a16bbe07957811c75dfb7c9bf25c5862ba0 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Sun, 13 Sep 2015 13:37:03 +0100 Subject: platform-msi: Do not cache msi_desc in handler_data The current implementation of platform MSI caches the msi_desc pointer in irq_data::handler_data. This is a bit silly, as we also have irq_data::msi_desc, which is perfectly valid. Remove the useless assignment and simplify the whole flow. Reported-by: Ma Jun Signed-off-by: Marc Zyngier Reviewed-by: Jiang Liu Link: http://lkml.kernel.org/r/1442147824-20971-1-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- drivers/base/platform-msi.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c index 1857a5dd0816..134483daac25 100644 --- a/drivers/base/platform-msi.c +++ b/drivers/base/platform-msi.c @@ -63,20 +63,8 @@ static int platform_msi_init(struct irq_domain *domain, unsigned int virq, irq_hw_number_t hwirq, msi_alloc_info_t *arg) { - struct irq_data *data; - - irq_domain_set_hwirq_and_chip(domain, virq, hwirq, - info->chip, info->chip_data); - - /* - * Save the MSI descriptor in handler_data so that the - * irq_write_msi_msg callback can retrieve it (and the - * associated device). - */ - data = irq_domain_get_irq_data(domain, virq); - data->handler_data = arg->desc; - - return 0; + return irq_domain_set_hwirq_and_chip(domain, virq, hwirq, + info->chip, info->chip_data); } #else #define platform_msi_set_desc NULL @@ -97,7 +85,7 @@ static void platform_msi_update_dom_ops(struct msi_domain_info *info) static void platform_msi_write_msg(struct irq_data *data, struct msi_msg *msg) { - struct msi_desc *desc = irq_data_get_irq_handler_data(data); + struct msi_desc *desc = irq_data_get_msi_desc(data); struct platform_msi_priv_data *priv_data; priv_data = desc->platform.msi_priv_data; -- cgit v1.2.3 From 12e14066f4835f5ee1ca795f0309415b54c067a9 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Sun, 13 Sep 2015 12:14:31 +0100 Subject: irqchip/GIC: Add workaround for aliased GIC400 The GICv2 architecture mandates that the two 4kB GIC regions are contiguous, and on two separate physical pages (so that access to the second page can be trapped by a hypervisor). This doesn't work very well when PAGE_SIZE is 64kB. A relatively common hack^Wway to work around this is to alias each 4kB region over its own 64kB page. Of course in this case, the base address you want to use is not really the begining of the region, but base + 60kB (so that you get a contiguous 8kB region over two distinct pages). Normally, this would be described in DT with a new property, but some HW is already out there, and the firmware makes sure that it will override whatever you put in the GIC node. Duh. And of course, said firmware source code is not available, despite being based on u-boot. The workaround is to detect the case where the CPU interface size is set to 128kB, and verify the aliasing by checking that the ID register for GIC400 (which is the only GIC wired this way so far) is the same at base and base + 0xF000. In this case, we update the GIC base address and let it roll. And if you feel slightly sick by looking at this, rest assured that I do too... Reported-by: Julien Grall Signed-off-by: Marc Zyngier Cc: linux-arm-kernel@lists.infradead.org Cc: Stuart Yoder Cc: Pavel Fedin Cc: Jason Cooper Link: http://lkml.kernel.org/r/1442142873-20213-2-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-gic.c | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index e6b7ed537952..a9470574c031 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -1119,12 +1119,49 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, #ifdef CONFIG_OF static int gic_cnt __initdata; +static bool gic_check_eoimode(struct device_node *node, void __iomem **base) +{ + struct resource cpuif_res; + + of_address_to_resource(node, 1, &cpuif_res); + + if (!is_hyp_mode_available()) + return false; + if (resource_size(&cpuif_res) < SZ_8K) + return false; + if (resource_size(&cpuif_res) == SZ_128K) { + u32 val_low, val_high; + + /* + * Verify that we have the first 4kB of a GIC400 + * aliased over the first 64kB by checking the + * GICC_IIDR register on both ends. + */ + val_low = readl_relaxed(*base + GIC_CPU_IDENT); + val_high = readl_relaxed(*base + GIC_CPU_IDENT + 0xf000); + if ((val_low & 0xffff0fff) != 0x0202043B || + val_low != val_high) + return false; + + /* + * Move the base up by 60kB, so that we have a 8kB + * contiguous region, which allows us to use GICC_DIR + * at its normal offset. Please pass me that bucket. + */ + *base += 0xf000; + cpuif_res.start += 0xf000; + pr_warn("GIC: Adjusting CPU interface base to %pa", + &cpuif_res.start); + } + + return true; +} + static int __init gic_of_init(struct device_node *node, struct device_node *parent) { void __iomem *cpu_base; void __iomem *dist_base; - struct resource cpu_res; u32 percpu_offset; int irq; @@ -1137,14 +1174,11 @@ gic_of_init(struct device_node *node, struct device_node *parent) cpu_base = of_iomap(node, 1); WARN(!cpu_base, "unable to map gic cpu registers\n"); - of_address_to_resource(node, 1, &cpu_res); - /* * Disable split EOI/Deactivate if either HYP is not available * or the CPU interface is too small. */ - if (gic_cnt == 0 && (!is_hyp_mode_available() || - resource_size(&cpu_res) < SZ_8K)) + if (gic_cnt == 0 && !gic_check_eoimode(node, &cpu_base)) static_key_slow_dec(&supports_deactivate); if (of_property_read_u32(node, "cpu-offset", &percpu_offset)) -- cgit v1.2.3 From 5a9a8915c8888b615521b17d70a4342187eae60b Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Sun, 13 Sep 2015 12:14:32 +0100 Subject: irqchip/gic-v3-its: Add missing cache flushes When the ITS is configured for non-cacheable transactions, make sure that the allocated, zeroed memory is flushed to the Point of Coherency, allowing the ITS to observe the zeros instead of random garbage (or even get its own data overwritten by zeros being evicted from the cache...). Fixes: 241a386c7dbb "irqchip: gicv3-its: Use non-cacheable accesses when no shareability" Reported-and-tested-by: Stuart Yoder Signed-off-by: Marc Zyngier Cc: linux-arm-kernel@lists.infradead.org Cc: Pavel Fedin Cc: Jason Cooper Link: http://lkml.kernel.org/r/1442142873-20213-3-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-gic-v3-its.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 26b55c53755f..ac7ae2b3cb83 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -898,8 +898,10 @@ retry_baser: * non-cacheable as well. */ shr = tmp & GITS_BASER_SHAREABILITY_MASK; - if (!shr) + if (!shr) { cache = GITS_BASER_nC; + __flush_dcache_area(base, alloc_size); + } goto retry_baser; } @@ -1140,6 +1142,8 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, return NULL; } + __flush_dcache_area(itt, sz); + dev->its = its; dev->itt = itt; dev->nr_ites = nr_ites; -- cgit v1.2.3 From 157add60cb35913b8a848a3d7e6456b8ed134796 Mon Sep 17 00:00:00 2001 From: Pavel Fedin Date: Sun, 13 Sep 2015 12:14:33 +0100 Subject: irqchip/GICv2m: Fix GICv2m build warning on 32 bits After GICv2m was enabled for 32-bit ARM kernel, a warning popped up: drivers/irqchip/irq-gic-v2m.c: In function gicv2m_compose_msi_msg: drivers/irqchip/irq-gic-v2m.c:100:2: warning: right shift count >= width of type [enabled by default] msg->address_hi = (u32) (addr >> 32); ^ This patch fixes it by using proper macros for splitting up the value. Signed-off-by: Pavel Fedin Reviewed-by: Marc Zyngier Signed-off-by: Marc Zyngier Cc: linux-arm-kernel@lists.infradead.org Cc: Stuart Yoder Cc: Jason Cooper Link: http://lkml.kernel.org/r/1442142873-20213-4-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-gic-v2m.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c index db04fc1f56b2..12985daa66ab 100644 --- a/drivers/irqchip/irq-gic-v2m.c +++ b/drivers/irqchip/irq-gic-v2m.c @@ -95,8 +95,8 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) struct v2m_data *v2m = irq_data_get_irq_chip_data(data); phys_addr_t addr = v2m->res.start + V2M_MSI_SETSPI_NS; - msg->address_hi = (u32) (addr >> 32); - msg->address_lo = (u32) (addr); + msg->address_hi = upper_32_bits(addr); + msg->address_lo = lower_32_bits(addr); msg->data = data->hwirq; } -- cgit v1.2.3 From b1370658804510f6a1c0517a8ff1c9534d371edd Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 9 Sep 2015 13:42:53 +0200 Subject: irqchip/renesas-irqc: Use a separate lockdep class The renesas-irqc interrupt controller is cascaded to the GIC. Hence when propagating wake-up settings to its parent interrupt controller, the following lockdep warning is printed: ============================================= [ INFO: possible recursive locking detected ] 4.2.0-ape6evm-10725-g50fcd7643c034198 #280 Not tainted --------------------------------------------- s2ram/1072 is trying to acquire lock: (&irq_desc_lock_class){-.-...}, at: [] __irq_get_desc_lock+0x58/0x98 but task is already holding lock: (&irq_desc_lock_class){-.-...}, at: [] __irq_get_desc_lock+0x58/0x98 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&irq_desc_lock_class); lock(&irq_desc_lock_class); *** DEADLOCK *** May be due to missing lock nesting notation 6 locks held by s2ram/1072: #0: (sb_writers#7){.+.+.+}, at: [] __sb_start_write+0xa0/0xa8 #1: (&of->mutex){+.+.+.}, at: [] kernfs_fop_write+0x4c/0x1bc #2: (s_active#24){.+.+.+}, at: [] kernfs_fop_write+0x54/0x1bc #3: (pm_mutex){+.+.+.}, at: [] pm_suspend+0x10c/0x510 #4: (&dev->mutex){......}, at: [] __device_suspend+0xdc/0x2cc #5: (&irq_desc_lock_class){-.-...}, at: [] __irq_get_desc_lock+0x58/0x98 stack backtrace: CPU: 0 PID: 1072 Comm: s2ram Not tainted 4.2.0-ape6evm-10725-g50fcd7643c034198 #280 Hardware name: Generic R8A73A4 (Flattened Device Tree) [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0x88/0x98) [] (dump_stack) from [] (__lock_acquire+0x15cc/0x20e4) [] (__lock_acquire) from [] (lock_acquire+0xac/0x12c) [] (lock_acquire) from [] (_raw_spin_lock_irqsave+0x40/0x54) [] (_raw_spin_lock_irqsave) from [] (__irq_get_desc_lock+0x58/0x98) [] (__irq_get_desc_lock) from [] (irq_set_irq_wake+0x20/0xf8) [] (irq_set_irq_wake) from [] (irqc_irq_set_wake+0x20/0x4c) [] (irqc_irq_set_wake) from [] (irq_set_irq_wake+0x8c/0xf8) [] (irq_set_irq_wake) from [] (gpio_keys_suspend+0x74/0xc0) [] (gpio_keys_suspend) from [] (dpm_run_callback+0x54/0x124) Avoid this false positive by using a separate lockdep class for IRQC interrupts. Signed-off-by: Geert Uytterhoeven Cc: Grygorii Strashko Cc: Magnus Damm Cc: Jason Cooper Link: http://lkml.kernel.org/r/1441798974-25716-2-git-send-email-geert%2Brenesas@glider.be Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-renesas-irqc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c index 2aa3add711a6..4652cc385d39 100644 --- a/drivers/irqchip/irq-renesas-irqc.c +++ b/drivers/irqchip/irq-renesas-irqc.c @@ -150,6 +150,12 @@ static irqreturn_t irqc_irq_handler(int irq, void *dev_id) return IRQ_NONE; } +/* + * This lock class tells lockdep that IRQC irqs are in a different + * category than their parents, so it won't report false recursion. + */ +static struct lock_class_key irqc_irq_lock_class; + static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq, irq_hw_number_t hw) { @@ -157,6 +163,7 @@ static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq, irqc_dbg(&p->irq[hw], "map"); irq_set_chip_data(virq, h->host_data); + irq_set_lockdep_class(virq, &irqc_irq_lock_class); irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq); return 0; } -- cgit v1.2.3 From 769b5cf78e6c653c2f513649ee6c4e7a06723872 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 9 Sep 2015 13:42:54 +0200 Subject: irqchip/renesas-intc-irqpin: Use a separate lockdep class The renesas-intc-irqpin interrupt controller is cascaded to the GIC. Hence when propagating wake-up settings to its parent interrupt controller, the following lockdep warning is printed: ============================================= [ INFO: possible recursive locking detected ] 4.2.0-armadillo-10725-g50fcd7643c034198 #781 Not tainted --------------------------------------------- s2ram/1179 is trying to acquire lock: (&irq_desc_lock_class){-.-...}, at: [] __irq_get_desc_lock+0x78/0x94 but task is already holding lock: (&irq_desc_lock_class){-.-...}, at: [] __irq_get_desc_lock+0x78/0x94 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&irq_desc_lock_class); lock(&irq_desc_lock_class); *** DEADLOCK *** May be due to missing lock nesting notation 7 locks held by s2ram/1179: #0: (sb_writers#7){.+.+.+}, at: [] __sb_start_write+0x64/0xb8 #1: (&of->mutex){+.+.+.}, at: [] kernfs_fop_write+0x78/0x1a0 #2: (s_active#23){.+.+.+}, at: [] kernfs_fop_write+0x80/0x1a0 #3: (autosleep_lock){+.+.+.}, at: [] pm_autosleep_lock+0x18/0x20 #4: (pm_mutex){+.+.+.}, at: [] pm_suspend+0x54/0x248 #5: (&dev->mutex){......}, at: [] __device_suspend+0xdc/0x240 #6: (&irq_desc_lock_class){-.-...}, at: [] __irq_get_desc_lock+0x78/0x94 stack backtrace: CPU: 0 PID: 1179 Comm: s2ram Not tainted 4.2.0-armadillo-10725-g50fcd7643c034198 Hardware name: Generic R8A7740 (Flattened Device Tree) [] (dump_backtrace) from [] (show_stack+0x18/0x1c) [] (show_stack) from [] (dump_stack+0x20/0x28) [] (dump_stack) from [] (__lock_acquire+0x67c/0x1b88) [] (__lock_acquire) from [] (lock_acquire+0x9c/0xbc) [] (lock_acquire) from [] (_raw_spin_lock_irqsave+0x44/0x58) [] (_raw_spin_lock_irqsave) from [] (__irq_get_desc_lock+0x78/0x94 [] (__irq_get_desc_lock) from [] (irq_set_irq_wake+0x28/0x100) [] (irq_set_irq_wake) from [] (intc_irqpin_irq_set_wake+0x24/0x4c) [] (intc_irqpin_irq_set_wake) from [] (set_irq_wake_real+0x3c/0x50 [] (set_irq_wake_real) from [] (irq_set_irq_wake+0x64/0x100) [] (irq_set_irq_wake) from [] (gpio_keys_suspend+0x60/0xa0) [] (gpio_keys_suspend) from [] (platform_pm_suspend+0x3c/0x5c) Avoid this false positive by using a separate lockdep class for INTC External IRQ Pin interrupts. Signed-off-by: Geert Uytterhoeven Cc: Grygorii Strashko Cc: Magnus Damm Cc: Jason Cooper Link: http://lkml.kernel.org/r/1441798974-25716-3-git-send-email-geert%2Brenesas@glider.be Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-renesas-intc-irqpin.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c index 0670ab4e3897..67797eebbd5e 100644 --- a/drivers/irqchip/irq-renesas-intc-irqpin.c +++ b/drivers/irqchip/irq-renesas-intc-irqpin.c @@ -332,6 +332,12 @@ static irqreturn_t intc_irqpin_shared_irq_handler(int irq, void *dev_id) return status; } +/* + * This lock class tells lockdep that INTC External IRQ Pin irqs are in a + * different category than their parents, so it won't report false recursion. + */ +static struct lock_class_key intc_irqpin_irq_lock_class; + static int intc_irqpin_irq_domain_map(struct irq_domain *h, unsigned int virq, irq_hw_number_t hw) { @@ -342,6 +348,7 @@ static int intc_irqpin_irq_domain_map(struct irq_domain *h, unsigned int virq, intc_irqpin_dbg(&p->irq[hw], "map"); irq_set_chip_data(virq, h->host_data); + irq_set_lockdep_class(virq, &intc_irqpin_irq_lock_class); irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq); set_irq_flags(virq, IRQF_VALID); /* kill me now */ return 0; -- cgit v1.2.3 From f4e209cdc7a00f934007f40cf885471799073b0d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 8 Sep 2015 19:00:35 +0200 Subject: irqchip/renesas-intc-irqpin: Propagate wake-up settings to parent The renesas-intc-irqpin interrupt controller is cascaded to the GIC, but its driver doesn't propagate wake-up settings to the parent interrupt controller. Since commit aec89ef72ba6c944 ("irqchip/gic: Enable SKIP_SET_WAKE and MASK_ON_SUSPEND"), the GIC driver masks interrupts during suspend, and wake-up through gpio-keys now fails on r8a7740/armadillo and sh73a0/kzm9g. Fix this by propagating wake-up settings to the parent interrupt controller. There's no need to handle irq_set_irq_wake() failures, as the renesas-intc-irqpin interrupt controller is always cascaded to a GIC, and the GIC driver always sets SKIP_SET_WAKE since the aforementioned commit. Signed-off-by: Geert Uytterhoeven Cc: Sudeep Holla Cc: Magnus Damm Cc: Jason Cooper Cc: Marc Zyngier Link: http://lkml.kernel.org/r/1441731636-17610-2-git-send-email-geert%2Brenesas@glider.be Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-renesas-intc-irqpin.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c index 67797eebbd5e..d3546a6f4978 100644 --- a/drivers/irqchip/irq-renesas-intc-irqpin.c +++ b/drivers/irqchip/irq-renesas-intc-irqpin.c @@ -283,6 +283,9 @@ static int intc_irqpin_irq_set_type(struct irq_data *d, unsigned int type) static int intc_irqpin_irq_set_wake(struct irq_data *d, unsigned int on) { struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d); + int hw_irq = irqd_to_hwirq(d); + + irq_set_irq_wake(p->irq[hw_irq].requested_irq, on); if (!p->clk) return 0; -- cgit v1.2.3 From 4cd7863ecb90010533c178fba6ecc84d5529b402 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 8 Sep 2015 19:00:36 +0200 Subject: irqchip/renesas-irqc: Propagate wake-up settings to parent The renesas-irqc interrupt controller is cascaded to the GIC, but its driver doesn't propagate wake-up settings to the parent interrupt controller. Since commit aec89ef72ba6c944 ("irqchip/gic: Enable SKIP_SET_WAKE and MASK_ON_SUSPEND"), the GIC driver masks interrupts during suspend, and wake-up through gpio-keys now fails on r8a73a4/ape6evm. Fix this by propagating wake-up settings to the parent interrupt controller. There's no need to handle irq_set_irq_wake() failures, as the renesas-irqc interrupt controller is always cascaded to a GIC, and the GIC driver always sets SKIP_SET_WAKE since the aforementioned commit. Signed-off-by: Geert Uytterhoeven Cc: Sudeep Holla Cc: Magnus Damm Cc: Jason Cooper Cc: Marc Zyngier Link: http://lkml.kernel.org/r/1441731636-17610-3-git-send-email-geert%2Brenesas@glider.be Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-renesas-irqc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c index 4652cc385d39..35bf97ba4a3d 100644 --- a/drivers/irqchip/irq-renesas-irqc.c +++ b/drivers/irqchip/irq-renesas-irqc.c @@ -121,6 +121,9 @@ static int irqc_irq_set_type(struct irq_data *d, unsigned int type) static int irqc_irq_set_wake(struct irq_data *d, unsigned int on) { struct irqc_priv *p = irq_data_get_irq_chip_data(d); + int hw_irq = irqd_to_hwirq(d); + + irq_set_irq_wake(p->irq[hw_irq].requested_irq, on); if (!p->clk) return 0; -- cgit v1.2.3 From 3829c664b1eec243f2a355829efa40f0f414de8d Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 15 Sep 2015 13:47:24 +0200 Subject: genirq: Remove stale comment Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index 6f8b34066442..72a6b2feb7bf 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -151,10 +151,6 @@ struct irq_common_data { * methods, to allow shared chip implementations * @msi_desc: MSI descriptor * @affinity: IRQ affinity on SMP - * - * The fields here need to overlay the ones in irq_desc until we - * cleaned up the direct references and switched everything over to - * irq_data. */ struct irq_data { u32 mask; -- cgit v1.2.3 From 6584d84c3e504c76ad291cc2e381bbeed59798ab Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Tue, 1 Sep 2015 10:35:50 +0800 Subject: genirq: Update the comment for generic_handle_irq_desc __do_IRQ() was removed by commit 1c77ff2 "genirq: Remove __do_IRQ", but the comment referring to __do_IRQ() was left. Update the comment for generic_handle_irq_desc(). Signed-off-by: Huang Shijie Cc: jiang.liu@linux.intel.com Cc: peterz@infradead.org Cc: rafael.j.wysocki@intel.com Cc: jason@lakedaemon.net Cc: marc.zyngier@arm.com Link: http://lkml.kernel.org/r/1441074950-3893-1-git-send-email-shijie.huang@arm.com Signed-off-by: Thomas Gleixner --- include/linux/irqdesc.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index 5acfa26602e1..0593c691d091 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h @@ -137,9 +137,7 @@ static inline struct msi_desc *irq_desc_get_msi_desc(struct irq_desc *desc) /* * Architectures call this to let the generic IRQ layer - * handle an interrupt. If the descriptor is attached to an - * irqchip-style controller then we call the ->handle_irq() handler, - * and it calls __do_IRQ() if it's attached to an irqtype-style controller. + * handle an interrupt. */ static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *desc) { -- cgit v1.2.3 From b9a5ec33e32069a2f8af09d46266091602902bf4 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 16 Sep 2015 12:32:40 +0200 Subject: pinctrl: sunxi: Use irq_set_chip_handler_name_locked() __irq_set_chip_handler_name_locked() is about to be replaced. Use irq_set_chip_handler_name_locked() instead. Signed-off-by: Thomas Gleixner Cc: Linus Walleij Cc: linux-gpio@vger.kernel.org --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index fb4669c0ce0e..31af97d89272 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -617,13 +617,11 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type) spin_lock_irqsave(&pctl->lock, flags); if (type & IRQ_TYPE_LEVEL_MASK) - __irq_set_chip_handler_name_locked(d->irq, - &sunxi_pinctrl_level_irq_chip, - handle_fasteoi_irq, NULL); + irq_set_chip_handler_name_locked(d, &sunxi_pinctrl_level_irq_chip, + handle_fasteoi_irq, NULL); else - __irq_set_chip_handler_name_locked(d->irq, - &sunxi_pinctrl_edge_irq_chip, - handle_edge_irq, NULL); + irq_set_chip_handler_name_locked(d, &sunxi_pinctrl_edge_irq_chip, + handle_edge_irq, NULL); regval = readl(pctl->membase + reg); regval &= ~(IRQ_CFG_IRQ_MASK << index); -- cgit v1.2.3 From e902e14549e04c040fb6e15785efd35f810a223a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 16 Sep 2015 12:36:04 +0200 Subject: genirq: Remove __irq_set_chip_handler_name_locked() All users converted to irq_set_chip_handler_name_locked() Signed-off-by: Thomas Gleixner --- include/linux/irqdesc.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index 0593c691d091..29741382593c 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h @@ -184,19 +184,6 @@ static inline void __irq_set_handler_locked(unsigned int irq, desc->handle_irq = handler; } -/* caller has locked the irq_desc and both params are valid */ -static inline void -__irq_set_chip_handler_name_locked(unsigned int irq, struct irq_chip *chip, - irq_flow_handler_t handler, const char *name) -{ - struct irq_desc *desc; - - desc = irq_to_desc(irq); - irq_desc_get_irq_data(desc)->chip = chip; - desc->handle_irq = handler; - desc->name = name; -} - /** * irq_set_handler_locked - Set irq handler from a locked region * @data: Pointer to the irq_data structure which identifies the irq -- cgit v1.2.3 From 6b83bd941479e99f6890ed4b5c54cb1f43c7146f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 23 Jun 2015 15:52:31 +0200 Subject: powerpc/mpc52xx: Use irq_set_handler_locked() Use irq_set_handler_locked() as it avoids a redundant lookup of the irq descriptor. Search and replacement was done with coccinelle: @@ struct irq_data *d; expression E1; @@ -__irq_set_handler_locked(d->irq, E1); +irq_set_handler_locked(d, E1); Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Julia Lawall Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/platforms/52xx/mpc52xx_pic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index 2944bc84b9d6..4fe2074c88cb 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c @@ -196,7 +196,7 @@ static int mpc52xx_extirq_set_type(struct irq_data *d, unsigned int flow_type) ctrl_reg |= (type << (22 - (l2irq * 2))); out_be32(&intr->ctrl, ctrl_reg); - __irq_set_handler_locked(d->irq, handler); + irq_set_handler_locked(d, handler); return 0; } -- cgit v1.2.3 From e9e879a3d6cecc4258294c674627045da648fab0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 23 Jun 2015 15:52:32 +0200 Subject: powerpc/cpm2: Use irq_set_handler_locked() Use irq_set_handler_locked() as it avoids a redundant lookup of the irq descriptor. Search and replacement was done with coccinelle: @@ struct irq_data *d; expression E1; @@ -__irq_set_handler_locked(d->irq, E1); +irq_set_handler_locked(d, E1); Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Julia Lawall Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/sysdev/cpm2_pic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c index a11bd1d433ad..9e86074719a9 100644 --- a/arch/powerpc/sysdev/cpm2_pic.c +++ b/arch/powerpc/sysdev/cpm2_pic.c @@ -155,9 +155,9 @@ static int cpm2_set_irq_type(struct irq_data *d, unsigned int flow_type) irqd_set_trigger_type(d, flow_type); if (flow_type & IRQ_TYPE_LEVEL_LOW) - __irq_set_handler_locked(d->irq, handle_level_irq); + irq_set_handler_locked(d, handle_level_irq); else - __irq_set_handler_locked(d->irq, handle_edge_irq); + irq_set_handler_locked(d, handle_edge_irq); /* internal IRQ senses are LEVEL_LOW * EXT IRQ and Port C IRQ senses are programmable -- cgit v1.2.3 From 9758a7b0e5fdd5a08bcc73540bb3b98d59295a6d Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 23 Jun 2015 15:52:34 +0200 Subject: powerpc/ipic: Use irq_set_handler_locked() Use irq_set_handler_locked() as it avoids a redundant lookup of the irq descriptor. Search and replacement was done with coccinelle: @@ struct irq_data *d; expression E1; @@ -__irq_set_handler_locked(d->irq, E1); +irq_set_handler_locked(d, E1); Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Julia Lawall Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Anton Blanchard Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/sysdev/ipic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index 6b2b68914810..b1297ab1599b 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c @@ -624,10 +624,10 @@ static int ipic_set_irq_type(struct irq_data *d, unsigned int flow_type) irqd_set_trigger_type(d, flow_type); if (flow_type & IRQ_TYPE_LEVEL_LOW) { - __irq_set_handler_locked(d->irq, handle_level_irq); + irq_set_handler_locked(d, handle_level_irq); d->chip = &ipic_level_irq_chip; } else { - __irq_set_handler_locked(d->irq, handle_edge_irq); + irq_set_handler_locked(d, handle_edge_irq); d->chip = &ipic_edge_irq_chip; } -- cgit v1.2.3 From 9ca86b204b3c874e6ada28309f607e3aa74d60a9 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 23 Jun 2015 15:52:36 +0200 Subject: powerpc/mpc8xx: Use irq_set_handler_locked() Use irq_set_handler_locked() as it avoids a redundant lookup of the irq descriptor. Search and replacement was done with coccinelle: @@ struct irq_data *d; expression E1; @@ -__irq_set_handler_locked(d->irq, E1); +irq_set_handler_locked(d, E1); Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Julia Lawall Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/sysdev/mpc8xx_pic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c index d93a78be4346..9a423975853a 100644 --- a/arch/powerpc/sysdev/mpc8xx_pic.c +++ b/arch/powerpc/sysdev/mpc8xx_pic.c @@ -55,7 +55,7 @@ static int mpc8xx_set_irq_type(struct irq_data *d, unsigned int flow_type) unsigned int siel = in_be32(&siu_reg->sc_siel); siel |= mpc8xx_irqd_to_bit(d); out_be32(&siu_reg->sc_siel, siel); - __irq_set_handler_locked(d->irq, handle_edge_irq); + irq_set_handler_locked(d, handle_edge_irq); } return 0; } -- cgit v1.2.3 From a7147db0f5184954687546d430aed65cce483ffa Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 16 Sep 2015 12:51:00 +0200 Subject: gpio: vf610: Use irq_set_handler_locked Use irq_set_handler_locked() as it avoids a redundant lookup of the irq descriptor. Search and replacement was done with coccinelle: Signed-off-by: Thomas Gleixner Cc: Julia Lawall Cc: Linus Walleij Cc: linux-gpio@vger.kernel.org --- drivers/gpio/gpio-vf610.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 3d5714d4f405..7a6640b51911 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -176,9 +176,9 @@ static int vf610_gpio_irq_set_type(struct irq_data *d, u32 type) port->irqc[d->hwirq] = irqc; if (type & IRQ_TYPE_LEVEL_MASK) - __irq_set_handler_locked(d->irq, handle_level_irq); + irq_set_handler_locked(d, handle_level_irq); else - __irq_set_handler_locked(d->irq, handle_edge_irq); + irq_set_handler_locked(d, handle_edge_irq); return 0; } -- cgit v1.2.3 From 7c51173adde2ec520348812214704313f5b36f75 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 16 Sep 2015 12:52:53 +0200 Subject: pinctrl/pistachio: Use irq_set_handler_locked Use irq_set_handler_locked() as it avoids a redundant lookup of the irq descriptor. Search and replacement was done with coccinelle: Signed-off-by: Thomas Gleixner Cc: Julia Lawall Cc: Linus Walleij Cc: linux-gpio@vger.kernel.org --- drivers/pinctrl/pinctrl-pistachio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/pinctrl-pistachio.c b/drivers/pinctrl/pinctrl-pistachio.c index 3dc2ae15f3a1..f22d585d9300 100644 --- a/drivers/pinctrl/pinctrl-pistachio.c +++ b/drivers/pinctrl/pinctrl-pistachio.c @@ -1303,9 +1303,9 @@ static int pistachio_gpio_irq_set_type(struct irq_data *data, unsigned int type) } if (type & IRQ_TYPE_LEVEL_MASK) - __irq_set_handler_locked(data->irq, handle_level_irq); + irq_set_handler_locked(data, handle_level_irq); else - __irq_set_handler_locked(data->irq, handle_edge_irq); + irq_set_handler_locked(data, handle_edge_irq); return 0; } -- cgit v1.2.3 From 123236ccacc933daac3b39c5eb1f0011c70d41d8 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 16 Sep 2015 12:54:23 +0200 Subject: genirq: Remove __irq_set_handler_locked() All users converted to irq_set_handler_locked() Signed-off-by: Thomas Gleixner --- include/linux/irqdesc.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index 29741382593c..dce395cd67de 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h @@ -174,16 +174,6 @@ static inline int irq_has_action(unsigned int irq) return irq_desc_has_action(irq_to_desc(irq)); } -/* caller has locked the irq_desc and both params are valid */ -static inline void __irq_set_handler_locked(unsigned int irq, - irq_flow_handler_t handler) -{ - struct irq_desc *desc; - - desc = irq_to_desc(irq); - desc->handle_irq = handler; -} - /** * irq_set_handler_locked - Set irq handler from a locked region * @data: Pointer to the irq_data structure which identifies the irq -- cgit v1.2.3 From 755d119a6204974b2005a98549a48a75a7f5010b Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 16 Sep 2015 14:37:12 +0200 Subject: genirq: Simplify irq_data_to_desc() Avoid the lookup of irq_desc and use the same mechanism for hierarchical and flat irqdomains. Based-on-a-patch-from: Jiang Liu Signed-off-by: Thomas Gleixner --- include/linux/irqdesc.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index dce395cd67de..1fc5304641a1 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h @@ -98,11 +98,7 @@ extern struct irq_desc irq_desc[NR_IRQS]; static inline struct irq_desc *irq_data_to_desc(struct irq_data *data) { -#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY - return irq_to_desc(data->irq); -#else - return container_of(data, struct irq_desc, irq_data); -#endif + return container_of(data->common, struct irq_desc, irq_common_data); } static inline unsigned int irq_desc_get_irq(struct irq_desc *desc) -- cgit v1.2.3 From fc5697126aa074c289df5e8baae28e115963023f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 15 Sep 2015 12:33:42 +0200 Subject: genirq: Provide IRQD_FORWARDED_TO_VCPU status flag Provide a irq data flag to mark an irq forwarded to a VCPU along with the accessor functions. Signed-off-by: Thomas Gleixner Acked-by: Marc Zyngier --- include/linux/irq.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/linux/irq.h b/include/linux/irq.h index 72a6b2feb7bf..e54ae8295460 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -186,6 +186,7 @@ struct irq_data { * IRQD_IRQ_MASKED - Masked state of the interrupt * IRQD_IRQ_INPROGRESS - In progress state of the interrupt * IRQD_WAKEUP_ARMED - Wakeup mode armed + * IRQD_FORWARDED_TO_VCPU - The interrupt is forwarded to a VCPU */ enum { IRQD_TRIGGER_MASK = 0xf, @@ -200,6 +201,7 @@ enum { IRQD_IRQ_MASKED = (1 << 17), IRQD_IRQ_INPROGRESS = (1 << 18), IRQD_WAKEUP_ARMED = (1 << 19), + IRQD_FORWARDED_TO_VCPU = (1 << 20), }; #define __irqd_to_state(d) ((d)->common->state_use_accessors) @@ -278,6 +280,20 @@ static inline bool irqd_is_wakeup_armed(struct irq_data *d) return __irqd_to_state(d) & IRQD_WAKEUP_ARMED; } +static inline bool irqd_is_forwarded_to_vcpu(struct irq_data *d) +{ + return __irqd_to_state(d) & IRQD_FORWARDED_TO_VCPU; +} + +static inline void irqd_set_forwarded_to_vcpu(struct irq_data *d) +{ + __irqd_to_state(d) |= IRQD_FORWARDED_TO_VCPU; +} + +static inline void irqd_clr_forwarded_to_vcpu(struct irq_data *d) +{ + __irqd_to_state(d) &= ~IRQD_FORWARDED_TO_VCPU; +} /* * Functions for chained handlers which can be enabled/disabled by the -- cgit v1.2.3 From 714665351cc718e01f0ce34ef5325932d56d8b4e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 15 Sep 2015 12:37:36 +0200 Subject: irqchip/gic: Use IRQD_FORWARDED_TO_VCPU flag Get rid of the handler_data abuse. Signed-off-by: Thomas Gleixner Acked-by: Marc Zyngier --- drivers/irqchip/irq-gic.c | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index a9470574c031..9bccdd295769 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -145,29 +145,10 @@ static inline bool cascading_gic_irq(struct irq_data *d) void *data = irq_data_get_irq_handler_data(d); /* - * If handler_data pointing to one of the secondary GICs, then - * this is a cascading interrupt, and it cannot possibly be - * forwarded. + * If handler_data is set, this is a cascading interrupt, and + * it cannot possibly be forwarded. */ - if (data >= (void *)(gic_data + 1) && - data < (void *)(gic_data + MAX_GIC_NR)) - return true; - - return false; -} - -static inline bool forwarded_irq(struct irq_data *d) -{ - /* - * A forwarded interrupt: - * - is on the primary GIC - * - has its handler_data set to a value - * - that isn't a secondary GIC - */ - if (d->handler_data && !cascading_gic_irq(d)) - return true; - - return false; + return data != NULL; } /* @@ -201,7 +182,7 @@ static void gic_eoimode1_mask_irq(struct irq_data *d) * disabled/masked will not get "stuck", because there is * noone to deactivate it (guest is being terminated). */ - if (forwarded_irq(d)) + if (irqd_is_forwarded_to_vcpu(d)) gic_poke_irq(d, GIC_DIST_ACTIVE_CLEAR); } @@ -218,7 +199,7 @@ static void gic_eoi_irq(struct irq_data *d) static void gic_eoimode1_eoi_irq(struct irq_data *d) { /* Do not deactivate an IRQ forwarded to a vcpu. */ - if (forwarded_irq(d)) + if (irqd_is_forwarded_to_vcpu(d)) return; writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_DEACTIVATE); @@ -296,7 +277,10 @@ static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu) if (cascading_gic_irq(d)) return -EINVAL; - d->handler_data = vcpu; + if (vcpu) + irqd_set_forwarded_to_vcpu(d); + else + irqd_clr_forwarded_to_vcpu(d); return 0; } -- cgit v1.2.3 From 4df7f54d16ebe9c37631182de84c4347f0e44db3 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 15 Sep 2015 13:19:16 +0200 Subject: irqchip/gic-v3: Use IRQD_FORWARDED_TO_VCPU flag Get rid of the handler_data abuse. Signed-off-by: Thomas Gleixner Acked-by: Marc Zyngier --- drivers/irqchip/irq-gic-v3.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 7deed6ef54c2..b5418f57ddc2 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -70,11 +70,6 @@ static inline int gic_irq_in_rdist(struct irq_data *d) return gic_irq(d) < 32; } -static inline bool forwarded_irq(struct irq_data *d) -{ - return d->handler_data != NULL; -} - static inline void __iomem *gic_dist_base(struct irq_data *d) { if (gic_irq_in_rdist(d)) /* SGI+PPI -> SGI_base for this CPU */ @@ -249,7 +244,7 @@ static void gic_eoimode1_mask_irq(struct irq_data *d) * disabled/masked will not get "stuck", because there is * noone to deactivate it (guest is being terminated). */ - if (forwarded_irq(d)) + if (irqd_is_forwarded_to_vcpu(d)) gic_poke_irq(d, GICD_ICACTIVER); } @@ -324,7 +319,7 @@ static void gic_eoimode1_eoi_irq(struct irq_data *d) * No need to deactivate an LPI, or an interrupt that * is is getting forwarded to a vcpu. */ - if (gic_irq(d) >= 8192 || forwarded_irq(d)) + if (gic_irq(d) >= 8192 || irqd_is_forwarded_to_vcpu(d)) return; gic_write_dir(gic_irq(d)); } @@ -357,7 +352,10 @@ static int gic_set_type(struct irq_data *d, unsigned int type) static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu) { - d->handler_data = vcpu; + if (vcpu) + irqd_set_forwarded_to_vcpu(d); + else + irqd_clr_forwarded_to_vcpu(d); return 0; } -- cgit v1.2.3 From 449e9cae58b06be1293858ec8e5d8cb728238baa Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 1 Jun 2015 16:05:16 +0800 Subject: genirq: Move field 'node' from irq_data into irq_common_data NUMA node information is per-irq instead of per-irqchip, so move it into struct irq_common_data. Also use CONFIG_NUMA to guard irq_common_data.node. Signed-off-by: Jiang Liu Cc: Konrad Rzeszutek Wilk Cc: Tony Luck Cc: Bjorn Helgaas Cc: Benjamin Herrenschmidt Cc: Randy Dunlap Cc: Yinghai Lu Cc: Borislav Petkov Cc: Jason Cooper Cc: Kevin Cernekee Cc: Arnd Bergmann Link: http://lkml.kernel.org/r/1433145945-789-8-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 17 ++++++++++++++--- kernel/irq/internals.h | 2 +- kernel/irq/irqdesc.c | 4 +++- kernel/irq/irqdomain.c | 1 - 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index e54ae8295460..ebcc5c6745eb 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -129,9 +129,13 @@ struct irq_domain; * struct irq_common_data - per irq data shared by all irqchips * @state_use_accessors: status information for irq chip functions. * Use accessor functions to deal with it + * @node: node index useful for balancing */ struct irq_common_data { unsigned int state_use_accessors; +#ifdef CONFIG_NUMA + unsigned int node; +#endif }; /** @@ -139,7 +143,6 @@ struct irq_common_data { * @mask: precomputed bitmask for accessing the chip registers * @irq: interrupt number * @hwirq: hardware interrupt number, local to the interrupt domain - * @node: node index useful for balancing * @common: point to data shared by all irqchips * @chip: low level interrupt hardware access * @domain: Interrupt translation domain; responsible for mapping @@ -156,7 +159,6 @@ struct irq_data { u32 mask; unsigned int irq; unsigned long hwirq; - unsigned int node; struct irq_common_data *common; struct irq_chip *chip; struct irq_domain *domain; @@ -664,9 +666,18 @@ static inline u32 irq_get_trigger_type(unsigned int irq) return d ? irqd_get_trigger_type(d) : 0; } -static inline int irq_data_get_node(struct irq_data *d) +static inline int irq_common_data_get_node(struct irq_common_data *d) { +#ifdef CONFIG_NUMA return d->node; +#else + return 0; +#endif +} + +static inline int irq_data_get_node(struct irq_data *d) +{ + return irq_common_data_get_node(d->common); } static inline struct cpumask *irq_get_affinity_mask(int irq) diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index eee4b385cffb..5ef0c2dbe930 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h @@ -194,7 +194,7 @@ static inline void kstat_incr_irqs_this_cpu(struct irq_desc *desc) static inline int irq_desc_get_node(struct irq_desc *desc) { - return irq_data_get_node(&desc->irq_data); + return irq_common_data_get_node(&desc->irq_common_data); } #ifdef CONFIG_PM_SLEEP diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 0a2a4b697bcb..7f3e9faa6e4d 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -52,11 +52,13 @@ static int alloc_masks(struct irq_desc *desc, gfp_t gfp, int node) static void desc_smp_init(struct irq_desc *desc, int node) { - desc->irq_data.node = node; cpumask_copy(desc->irq_data.affinity, irq_default_affinity); #ifdef CONFIG_GENERIC_PENDING_IRQ cpumask_clear(desc->pending_mask); #endif +#ifdef CONFIG_NUMA + desc->irq_common_data.node = node; +#endif } #else diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 79baaf8a7813..dc9d27c0c158 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -844,7 +844,6 @@ static struct irq_data *irq_domain_insert_irq_data(struct irq_domain *domain, child->parent_data = irq_data; irq_data->irq = child->irq; irq_data->common = child->common; - irq_data->node = child->node; irq_data->domain = domain; } -- cgit v1.2.3 From af7080e040d223b5e7d0a8de28f7cea24ef017c4 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 1 Jun 2015 16:05:21 +0800 Subject: genirq: Move field 'handler_data' from irq_data into irq_common_data Handler data (handler_data) is per-irq instead of per irqchip, so move it into struct irq_common_data. Signed-off-by: Jiang Liu Cc: Konrad Rzeszutek Wilk Cc: Tony Luck Cc: Bjorn Helgaas Cc: Benjamin Herrenschmidt Cc: Randy Dunlap Cc: Yinghai Lu Cc: Borislav Petkov Cc: Jason Cooper Cc: Kevin Cernekee Cc: Arnd Bergmann Cc: Marc Zyngier Link: http://lkml.kernel.org/r/1433145945-789-13-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 8 ++++---- include/linux/irqdesc.h | 2 +- kernel/irq/chip.c | 4 ++-- kernel/irq/irqdesc.c | 3 ++- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index ebcc5c6745eb..516aadbfc072 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -130,12 +130,14 @@ struct irq_domain; * @state_use_accessors: status information for irq chip functions. * Use accessor functions to deal with it * @node: node index useful for balancing + * @handler_data: per-IRQ data for the irq_chip methods */ struct irq_common_data { unsigned int state_use_accessors; #ifdef CONFIG_NUMA unsigned int node; #endif + void *handler_data; }; /** @@ -149,7 +151,6 @@ struct irq_common_data { * between hwirq number and linux irq number. * @parent_data: pointer to parent struct irq_data to support hierarchy * irq_domain - * @handler_data: per-IRQ data for the irq_chip methods * @chip_data: platform-specific per-chip private data for the chip * methods, to allow shared chip implementations * @msi_desc: MSI descriptor @@ -165,7 +166,6 @@ struct irq_data { #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY struct irq_data *parent_data; #endif - void *handler_data; void *chip_data; struct msi_desc *msi_desc; cpumask_var_t affinity; @@ -641,12 +641,12 @@ static inline void *irq_data_get_irq_chip_data(struct irq_data *d) static inline void *irq_get_handler_data(unsigned int irq) { struct irq_data *d = irq_get_irq_data(irq); - return d ? d->handler_data : NULL; + return d ? d->common->handler_data : NULL; } static inline void *irq_data_get_irq_handler_data(struct irq_data *d) { - return d->handler_data; + return d->common->handler_data; } static inline struct msi_desc *irq_get_msi_desc(unsigned int irq) diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index 1fc5304641a1..c7b3e1cc6d59 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h @@ -123,7 +123,7 @@ static inline void *irq_desc_get_chip_data(struct irq_desc *desc) static inline void *irq_desc_get_handler_data(struct irq_desc *desc) { - return desc->irq_data.handler_data; + return desc->irq_common_data.handler_data; } static inline struct msi_desc *irq_desc_get_msi_desc(struct irq_desc *desc) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 6e40a9539763..a48e00e345d7 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -83,7 +83,7 @@ int irq_set_handler_data(unsigned int irq, void *data) if (!desc) return -EINVAL; - desc->irq_data.handler_data = data; + desc->irq_common_data.handler_data = data; irq_put_desc_unlock(desc, flags); return 0; } @@ -796,7 +796,7 @@ irq_set_chained_handler_and_data(unsigned int irq, irq_flow_handler_t handle, return; __irq_do_set_handler(desc, handle, 1, NULL); - desc->irq_data.handler_data = data; + desc->irq_common_data.handler_data = data; irq_put_desc_busunlock(desc, flags); } diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 7f3e9faa6e4d..594b3e349aac 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -72,11 +72,12 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node, { int cpu; + desc->irq_common_data.handler_data = NULL; + desc->irq_data.common = &desc->irq_common_data; desc->irq_data.irq = irq; desc->irq_data.chip = &no_irq_chip; desc->irq_data.chip_data = NULL; - desc->irq_data.handler_data = NULL; desc->irq_data.msi_desc = NULL; irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS); irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED); -- cgit v1.2.3 From 9df872faa7e1619e9278bec00ceaed2236533530 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 3 Jun 2015 11:47:50 +0800 Subject: genirq: Move field 'affinity' from irq_data into irq_common_data Irq affinity mask is per-irq instead of per irqchip, so move it into struct irq_common_data. Signed-off-by: Jiang Liu Cc: Konrad Rzeszutek Wilk Cc: Tony Luck Cc: Bjorn Helgaas Cc: Benjamin Herrenschmidt Cc: Randy Dunlap Cc: Yinghai Lu Cc: Borislav Petkov Cc: Jason Cooper Cc: Kevin Cernekee Cc: Arnd Bergmann Link: http://lkml.kernel.org/r/1433303281-27688-1-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/vector.c | 4 +--- include/linux/irq.h | 12 ++++++------ kernel/irq/irqdesc.c | 9 +++++---- kernel/irq/manage.c | 12 ++++++------ kernel/irq/proc.c | 2 +- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 1bbd0fe2c806..836d11b92811 100644 --- a/ar