From 2a1d3ab8986d1b2f598ffc42351d94166fa0f022 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 21 Sep 2015 11:01:10 +0200 Subject: genirq: Handle force threading of irqs with primary and thread handler Force threading of interrupts does not really deal with interrupts which are requested with a primary and a threaded handler. The current policy is to leave them alone and let the primary handler run in interrupt context, but we set the ONESHOT flag for those interrupts as well. Kohji Okuno debugged a problem with the SDHCI driver where the interrupt thread waits for a hardware interrupt to trigger, which can't work well because the hardware interrupt is masked due to the ONESHOT flag being set. He proposed to set the ONESHOT flag only if the interrupt does not provide a thread handler. Though that does not work either because these interrupts can be shared. So the other interrupt would rightfully get the ONESHOT flag set and therefor the same situation would happen again. To deal with this proper, we need to force thread the primary handler of such interrupts as well. That means that the primary interrupt handler is treated as any other primary interrupt handler which is not marked IRQF_NO_THREAD. The threaded handler becomes a separate thread so the SDHCI flow logic can be handled gracefully. The same issue was reported against 4.1-rt. Reported-and-tested-by: Kohji Okuno Reported-By: Michal Smucr Reported-and-tested-by: Nathan Sullivan Signed-off-by: Thomas Gleixner Cc: Sebastian Andrzej Siewior Link: http://lkml.kernel.org/r/alpine.DEB.2.11.1509211058080.5606@nanos Signed-off-by: Thomas Gleixner --- include/linux/interrupt.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index be7e75c945e9..ad16809c8596 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -102,6 +102,7 @@ typedef irqreturn_t (*irq_handler_t)(int, void *); * @flags: flags (see IRQF_* above) * @thread_fn: interrupt handler function for threaded interrupts * @thread: thread pointer for threaded interrupts + * @secondary: pointer to secondary irqaction (force threading) * @thread_flags: flags related to @thread * @thread_mask: bitmask for keeping track of @thread activity * @dir: pointer to the proc/irq/NN/name entry @@ -113,6 +114,7 @@ struct irqaction { struct irqaction *next; irq_handler_t thread_fn; struct task_struct *thread; + struct irqaction *secondary; unsigned int irq; unsigned int flags; unsigned long thread_flags; -- cgit v1.2.3 From 30f2136346cab91e1ffd9ee6370d76809f20487a Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 21 Sep 2015 22:58:34 +0200 Subject: irqchip/gicv3-its: Add range check for number of allocated pages The number of pages for the its table may exceed the maximum of 256. Adding a range check and limitting the number to its maximum. Based on a patch from Tirumalesh Chalamarla . Signed-off-by: Tirumalesh Chalamarla Signed-off-by: Robert Richter Reviewed-by: Marc Zyngier Acked-by: Catalin Marinas Cc: linux-arm-kernel@lists.infradead.org Cc: Jason Cooper Link: http://lkml.kernel.org/r/1442869119-1814-2-git-send-email-rric@kernel.org Signed-off-by: Thomas Gleixner --- include/linux/irqchip/arm-gic-v3.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index 9eeeb9589acf..c0c8a2ef9d90 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -231,6 +231,7 @@ #define GITS_BASER_PAGE_SIZE_16K (1UL << GITS_BASER_PAGE_SIZE_SHIFT) #define GITS_BASER_PAGE_SIZE_64K (2UL << GITS_BASER_PAGE_SIZE_SHIFT) #define GITS_BASER_PAGE_SIZE_MASK (3UL << GITS_BASER_PAGE_SIZE_SHIFT) +#define GITS_BASER_PAGES_MAX 256 #define GITS_BASER_TYPE_NONE 0 #define GITS_BASER_TYPE_DEVICE 1 -- cgit v1.2.3 From f1e0bb0ad473a32d1b7e6d285ae9f7e47710bb5e Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Thu, 24 Sep 2015 17:32:13 +0800 Subject: genirq: Introduce generic irq migration for cpu hotunplug ARM and ARM64 have almost identical code for migrating interrupts on cpu hotunplug. Provide a generic version which can be used by both. The new code addresses a shortcoming in the ARM[64] variants which fails to update the affinity change in some cases. The solution for this is to use the core function irq_do_set_affinity() instead of open coding it. [ tglx: Added copyright notice and license boilerplate. Rewrote subject and changelog. ] Signed-off-by: Yang Yingliang Acked-by: Russell King - ARM Linux Cc: Jiang Liu Cc: Marc Zyngier Cc: Mark Rutland Cc: Will Deacon Cc: Hanjun Guo Cc: Link: http://lkml.kernel.org/r/1443087135-17044-2-git-send-email-yangyingliang@huawei.com Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/irq.h b/include/linux/irq.h index 11bf09288ddb..45cc7299bb61 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -452,6 +452,8 @@ extern int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *cpumask, bool force); extern int irq_set_vcpu_affinity(unsigned int irq, void *vcpu_info); +extern void irq_migrate_all_off_this_cpu(void); + #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ) void irq_move_irq(struct irq_data *data); void irq_move_masked_irq(struct irq_data *data); -- cgit v1.2.3 From 92068d17c20b218bf1e24505a3e08495476b0ebf Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 1 Oct 2015 15:54:52 +0300 Subject: genirq: Fix typo in documentation of enumeration field name It should say IRQ_NESTED_THREAD instead of IRQ_NESTED_TRHEAD. Signed-off-by: Mika Westerberg Cc: Jiang Liu Link: http://lkml.kernel.org/r/1443704093-36837-1-git-send-email-mika.westerberg@linux.intel.com Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/irq.h b/include/linux/irq.h index 45cc7299bb61..7038f38a63c7 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -67,7 +67,7 @@ enum irqchip_irq_state; * request/setup_irq() * IRQ_NO_BALANCING - Interrupt cannot be balanced (affinity set) * IRQ_MOVE_PCNTXT - Interrupt can be migrated from process context - * IRQ_NESTED_TRHEAD - Interrupt nests into another thread + * IRQ_NESTED_THREAD - Interrupt nests into another thread * IRQ_PER_CPU_DEVID - Dev_id is a per-cpu variable * IRQ_IS_POLLED - Always polled by another interrupt. Exclude * it from the spurious interrupt detection -- cgit v1.2.3 From 9e7e2b0a6a005941a6854cdabae19c3d9e069dbe Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 1 Oct 2015 15:54:53 +0300 Subject: genirq: Remove unused functions irqd_[set|clr]_chained_irq_inprogress() These two functions are not used anywhere in the kernel source tree so remove them. Signed-off-by: Mika Westerberg Cc: Jiang Liu Link: http://lkml.kernel.org/r/1443704093-36837-2-git-send-email-mika.westerberg@linux.intel.com Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'include/linux') diff --git a/include/linux/irq.h b/include/linux/irq.h index 7038f38a63c7..ba72b60b57b1 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -297,21 +297,6 @@ 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 - * standard disable_irq/enable_irq calls. Must be called with - * irq_desc->lock held. - */ -static inline void irqd_set_chained_irq_inprogress(struct irq_data *d) -{ - __irqd_to_state(d) |= IRQD_IRQ_INPROGRESS; -} - -static inline void irqd_clr_chained_irq_inprogress(struct irq_data *d) -{ - __irqd_to_state(d) &= ~IRQD_IRQ_INPROGRESS; -} - static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d) { return d->hwirq; -- cgit v1.2.3 From 7cabd0086acd8f204d9b11a9b0aca90d6a9fcc5b Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 30 Sep 2015 11:48:01 +0100 Subject: irqchip/gic-v3: Make gic_enable_sre an inline function In order for gic_enable_sre to be used by the arm64 core code, move it to arm-gic-v3.h. As a bonus, we now also check if system registers have been already enabled, and return early if they have. In all cases, the function now returns a boolean indicating if the enabling has been successful. Reviewed-by: Catalin Marinas Signed-off-by: Marc Zyngier --- include/linux/irqchip/arm-gic-v3.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'include/linux') diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index c0c8a2ef9d90..9001b0bbe878 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -398,6 +398,22 @@ static inline void gic_write_dir(u64 irq) isb(); } +static inline bool gic_enable_sre(void) +{ + u64 val; + + asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val)); + if (val & ICC_SRE_EL1_SRE) + return true; + + val |= ICC_SRE_EL1_SRE; + asm volatile("msr_s " __stringify(ICC_SRE_EL1) ", %0" : : "r" (val)); + isb(); + asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val)); + + return !!(val & ICC_SRE_EL1_SRE); +} + struct irq_domain; int its_cpu_init(void); int its_init(struct device_node *node, struct rdists *rdists, -- cgit v1.2.3 From 7936e914f7b0827c2dcfe63fbefdc21de2d61dcb Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Thu, 1 Oct 2015 13:47:14 +0100 Subject: irqchip/gic-v3: Refactor the arm64 specific parts This patch moves the GICv3 system register access helpers to arch/arm64/. Their 32bit counterparts will need to use mrc/mcr accesses instead of mrs_s/msr_s. [maz: fixed conflict with Cavium erratum handling] Reviewed-by: Marc Zyngier Signed-off-by: Jean-Philippe Brucker Signed-off-by: Marc Zyngier --- include/linux/irqchip/arm-gic-v3.h | 88 ++++---------------------------------- 1 file changed, 9 insertions(+), 79 deletions(-) (limited to 'include/linux') diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index 9001b0bbe878..b4ee60076ff8 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -18,8 +18,6 @@ #ifndef __LINUX_IRQCHIP_ARM_GIC_V3_H #define __LINUX_IRQCHIP_ARM_GIC_V3_H -#include - /* * Distributor registers. We assume we're running non-secure, with ARE * being set. Secure-only and non-ARE registers are not described. @@ -293,19 +291,8 @@ #define ICH_VMCR_PMR_SHIFT 24 #define ICH_VMCR_PMR_MASK (0xffUL << ICH_VMCR_PMR_SHIFT) -#define ICC_EOIR1_EL1 sys_reg(3, 0, 12, 12, 1) -#define ICC_DIR_EL1 sys_reg(3, 0, 12, 11, 1) -#define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0) -#define ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5) -#define ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0) -#define ICC_CTLR_EL1 sys_reg(3, 0, 12, 12, 4) -#define ICC_SRE_EL1 sys_reg(3, 0, 12, 12, 5) -#define ICC_GRPEN1_EL1 sys_reg(3, 0, 12, 12, 7) - #define ICC_IAR1_EL1_SPURIOUS 0x3ff -#define ICC_SRE_EL2 sys_reg(3, 4, 12, 9, 5) - #define ICC_SRE_EL2_SRE (1 << 0) #define ICC_SRE_EL2_ENABLE (1 << 3) @@ -321,54 +308,10 @@ #define ICC_SGI1R_AFFINITY_3_SHIFT 48 #define ICC_SGI1R_AFFINITY_3_MASK (0xffULL << ICC_SGI1R_AFFINITY_1_SHIFT) -/* - * System register definitions - */ -#define ICH_VSEIR_EL2 sys_reg(3, 4, 12, 9, 4) -#define ICH_HCR_EL2 sys_reg(3, 4, 12, 11, 0) -#define ICH_VTR_EL2 sys_reg(3, 4, 12, 11, 1) -#define ICH_MISR_EL2 sys_reg(3, 4, 12, 11, 2) -#define ICH_EISR_EL2 sys_reg(3, 4, 12, 11, 3) -#define ICH_ELSR_EL2 sys_reg(3, 4, 12, 11, 5) -#define ICH_VMCR_EL2 sys_reg(3, 4, 12, 11, 7) - -#define __LR0_EL2(x) sys_reg(3, 4, 12, 12, x) -#define __LR8_EL2(x) sys_reg(3, 4, 12, 13, x) - -#define ICH_LR0_EL2 __LR0_EL2(0) -#define ICH_LR1_EL2 __LR0_EL2(1) -#define ICH_LR2_EL2 __LR0_EL2(2) -#define ICH_LR3_EL2 __LR0_EL2(3) -#define ICH_LR4_EL2 __LR0_EL2(4) -#define ICH_LR5_EL2 __LR0_EL2(5) -#define ICH_LR6_EL2 __LR0_EL2(6) -#define ICH_LR7_EL2 __LR0_EL2(7) -#define ICH_LR8_EL2 __LR8_EL2(0) -#define ICH_LR9_EL2 __LR8_EL2(1) -#define ICH_LR10_EL2 __LR8_EL2(2) -#define ICH_LR11_EL2 __LR8_EL2(3) -#define ICH_LR12_EL2 __LR8_EL2(4) -#define ICH_LR13_EL2 __LR8_EL2(5) -#define ICH_LR14_EL2 __LR8_EL2(6) -#define ICH_LR15_EL2 __LR8_EL2(7) - -#define __AP0Rx_EL2(x) sys_reg(3, 4, 12, 8, x) -#define ICH_AP0R0_EL2 __AP0Rx_EL2(0) -#define ICH_AP0R1_EL2 __AP0Rx_EL2(1) -#define ICH_AP0R2_EL2 __AP0Rx_EL2(2) -#define ICH_AP0R3_EL2 __AP0Rx_EL2(3) - -#define __AP1Rx_EL2(x) sys_reg(3, 4, 12, 9, x) -#define ICH_AP1R0_EL2 __AP1Rx_EL2(0) -#define ICH_AP1R1_EL2 __AP1Rx_EL2(1) -#define ICH_AP1R2_EL2 __AP1Rx_EL2(2) -#define ICH_AP1R3_EL2 __AP1Rx_EL2(3) +#include #ifndef __ASSEMBLY__ -#include -#include - /* * We need a value to serve as a irq-type for LPIs. Choose one that will * hopefully pique the interest of the reviewer. @@ -386,39 +329,26 @@ struct rdists { u64 flags; }; -static inline void gic_write_eoir(u64 irq) -{ - asm volatile("msr_s " __stringify(ICC_EOIR1_EL1) ", %0" : : "r" (irq)); - isb(); -} - -static inline void gic_write_dir(u64 irq) -{ - asm volatile("msr_s " __stringify(ICC_DIR_EL1) ", %0" : : "r" (irq)); - isb(); -} +struct irq_domain; +int its_cpu_init(void); +int its_init(struct device_node *node, struct rdists *rdists, + struct irq_domain *domain); static inline bool gic_enable_sre(void) { - u64 val; + u32 val; - asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val)); + val = gic_read_sre(); if (val & ICC_SRE_EL1_SRE) return true; val |= ICC_SRE_EL1_SRE; - asm volatile("msr_s " __stringify(ICC_SRE_EL1) ", %0" : : "r" (val)); - isb(); - asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val)); + gic_write_sre(val); + val = gic_read_sre(); return !!(val & ICC_SRE_EL1_SRE); } -struct irq_domain; -int its_cpu_init(void); -int its_init(struct device_node *node, struct rdists *rdists, - struct irq_domain *domain); - #endif #endif -- cgit v1.2.3 From f6c86a41e1dc2214363b00cc0eadb8a5401c892d Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Thu, 1 Oct 2015 13:47:15 +0100 Subject: irqchip/gic-v3: Change unsigned types for AArch32 compatibility This patch does a few simple compatibility-related changes: - change the system register access prototypes to their actual size, - homogenise mpidr accesses with unsigned long, - force the 64bit register values to unsigned long long. Note: the list registers are 64bit on GICv3, but the AArch32 vGIC driver will need to split their values into two 32bit registers: LRn and LRCn. Reviewed-by: Marc Zyngier Signed-off-by: Jean-Philippe Brucker Signed-off-by: Marc Zyngier --- include/linux/irqchip/arm-gic-v3.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'include/linux') diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index b4ee60076ff8..c9ae0c6ec050 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -265,16 +265,16 @@ /* * Hypervisor interface registers (SRE only) */ -#define ICH_LR_VIRTUAL_ID_MASK ((1UL << 32) - 1) - -#define ICH_LR_EOI (1UL << 41) -#define ICH_LR_GROUP (1UL << 60) -#define ICH_LR_HW (1UL << 61) -#define ICH_LR_STATE (3UL << 62) -#define ICH_LR_PENDING_BIT (1UL << 62) -#define ICH_LR_ACTIVE_BIT (1UL << 63) +#define ICH_LR_VIRTUAL_ID_MASK ((1ULL << 32) - 1) + +#define ICH_LR_EOI (1ULL << 41) +#define ICH_LR_GROUP (1ULL << 60) +#define ICH_LR_HW (1ULL << 61) +#define ICH_LR_STATE (3ULL << 62) +#define ICH_LR_PENDING_BIT (1ULL << 62) +#define ICH_LR_ACTIVE_BIT (1ULL << 63) #define ICH_LR_PHYS_ID_SHIFT 32 -#define ICH_LR_PHYS_ID_MASK (0x3ffUL << ICH_LR_PHYS_ID_SHIFT) +#define ICH_LR_PHYS_ID_MASK (0x3ffULL << ICH_LR_PHYS_ID_SHIFT) #define ICH_MISR_EOI (1 << 0) #define ICH_MISR_U (1 << 1) -- cgit v1.2.3 From e9849777d0e27cdd2902805be51da73e7c79578c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 9 Oct 2015 23:28:58 +0200 Subject: genirq: Add flag to force mask in disable_irq[_nosync]() If an irq chip does not implement the irq_disable callback, then we use a lazy approach for disabling the interrupt. That means that the interrupt is marked disabled, but the interrupt line is not immediately masked in the interrupt chip. It only becomes masked if the interrupt is raised while it's marked disabled. We use this to avoid possibly expensive mask/unmask operations for common case operations. Unfortunately there are devices which do not allow the interrupt to be disabled easily at the device level. They are forced to use disable_irq_nosync(). This can result in taking each interrupt twice. Instead of enforcing the non lazy mode on all interrupts of a irq chip, provide a settings flag, which can be set by the driver for that particular interrupt line. Reported-and-tested-by: Duc Dang Signed-off-by: Thomas Gleixner Cc: Marc Zyngier Cc: Jason Cooper Link: http://lkml.kernel.org/r/alpine.DEB.2.11.1510092348370.6097@nanos --- include/linux/irq.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/irq.h b/include/linux/irq.h index ba72b60b57b1..3c1c96786248 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -72,6 +72,7 @@ enum irqchip_irq_state; * IRQ_IS_POLLED - Always polled by another interrupt. Exclude * it from the spurious interrupt detection * mechanism and from core side polling. + * IRQ_DISABLE_UNLAZY - Disable lazy irq disable */ enum { IRQ_TYPE_NONE = 0x00000000, @@ -97,13 +98,14 @@ enum { IRQ_NOTHREAD = (1 << 16), IRQ_PER_CPU_DEVID = (1 << 17), IRQ_IS_POLLED = (1 << 18), + IRQ_DISABLE_UNLAZY = (1 << 19), }; #define IRQF_MODIFY_MASK \ (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \ IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \ IRQ_PER_CPU | IRQ_NESTED_THREAD | IRQ_NOTHREAD | IRQ_PER_CPU_DEVID | \ - IRQ_IS_POLLED) + IRQ_IS_POLLED | IRQ_DISABLE_UNLAZY) #define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING) -- cgit v1.2.3 From f110711a6053f08731858aa91420104094188973 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 13 Oct 2015 12:51:30 +0100 Subject: irqdomain: Convert irqdomain-%3Eof_node to fwnode Now that we have everyone accessing the of_node field via the irq_domain_get_of_node accessor, it is pretty easy to swap it for a pointer to a fwnode_handle. This translates into a few limited changes in __irq_domain_add, and an updated irq_domain_get_of_node. Signed-off-by: Marc Zyngier Reviewed-and-tested-by: Hanjun Guo Tested-by: Lorenzo Pieralisi Cc: Cc: Tomasz Nowicki Cc: Suravee Suthikulpanit Cc: Graeme Gregory Cc: Jake Oshins Cc: Jiang Liu Cc: Jason Cooper Cc: Rafael J. Wysocki Link: http://lkml.kernel.org/r/1444737105-31573-3-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- include/linux/irqdomain.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index f644fdb06dd6..2f508f4ac2ea 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -34,6 +34,7 @@ #include #include +#include #include struct device_node; @@ -130,7 +131,7 @@ struct irq_domain { unsigned int flags; /* Optional data */ - struct device_node *of_node; + struct fwnode_handle *fwnode; enum irq_domain_bus_token bus_token; struct irq_domain_chip_generic *gc; #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY @@ -163,7 +164,7 @@ enum { static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d) { - return d->of_node; + return to_of_node(d->fwnode); } #ifdef CONFIG_IRQ_DOMAIN -- cgit v1.2.3 From 130b8c6c8d86075304952241bf2365cea6489df1 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 13 Oct 2015 12:51:31 +0100 Subject: irqdomain: Allow irq domain lookup by fwnode So far, our irq domains are still looked up by device node. Let's change this and allow a domain to be looked up using a fwnode_handle pointer. The existing interfaces are preserved with a couple of helpers. Signed-off-by: Marc Zyngier Reviewed-and-tested-by: Hanjun Guo Tested-by: Lorenzo Pieralisi Cc: Cc: Tomasz Nowicki Cc: Suravee Suthikulpanit Cc: Graeme Gregory Cc: Jake Oshins Cc: Jiang Liu Cc: Jason Cooper Cc: Rafael J. Wysocki Link: http://lkml.kernel.org/r/1444737105-31573-4-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- include/linux/irqdomain.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 2f508f4ac2ea..607c1856cc01 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -183,10 +183,17 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, irq_hw_number_t first_hwirq, const struct irq_domain_ops *ops, void *host_data); -extern struct irq_domain *irq_find_matching_host(struct device_node *node, - enum irq_domain_bus_token bus_token); +extern struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode, + enum irq_domain_bus_token bus_token); extern void irq_set_default_host(struct irq_domain *host); +static inline struct irq_domain *irq_find_matching_host(struct device_node *node, + enum irq_domain_bus_token bus_token) +{ + return irq_find_matching_fwnode(node ? &node->fwnode : NULL, + bus_token); +} + static inline struct irq_domain *irq_find_host(struct device_node *node) { return irq_find_matching_host(node, DOMAIN_BUS_ANY); -- cgit v1.2.3 From 11e4438ee330fab0f216ee7cc1b651cb2ddceb5d Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 13 Oct 2015 12:51:32 +0100 Subject: irqdomain: Introduce a firmware-specific IRQ specifier structure So far the closest thing to a generic IRQ specifier structure is of_phandle_args, which happens to be pretty OF specific (the of_node pointer in there is quite annoying). Let's introduce 'struct irq_fwspec' that can be used in place of of_phandle_args for OF, but also for other firmware implementations (that'd be ACPI). This is used together with a new 'translate' method that is the pendent of 'xlate'. We convert irq_create_of_mapping to use this new structure (with a small hack that will be removed later). Signed-off-by: Marc Zyngier Reviewed-and-tested-by: Hanjun Guo Tested-by: Lorenzo Pieralisi Cc: Cc: Tomasz Nowicki Cc: Suravee Suthikulpanit Cc: Graeme Gregory Cc: Jake Oshins Cc: Jiang Liu Cc: Jason Cooper Cc: Rafael J. Wysocki Link: http://lkml.kernel.org/r/1444737105-31573-5-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- include/linux/irqdomain.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'include/linux') diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 607c1856cc01..533c974b9d94 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -46,6 +46,24 @@ struct irq_data; /* Number of irqs reserved for a legacy isa controller */ #define NUM_ISA_INTERRUPTS 16 +#define IRQ_DOMAIN_IRQ_SPEC_PARAMS 16 + +/** + * struct irq_fwspec - generic IRQ specifier structure + * + * @fwnode: Pointer to a firmware-specific descriptor + * @param_count: Number of device-specific parameters + * @param: Device-specific parameters + * + * This structure, directly modeled after of_phandle_args, is used to + * pass a device-specific description of an interrupt. + */ +struct irq_fwspec { + struct fwnode_handle *fwnode; + int param_count; + u32 param[IRQ_DOMAIN_IRQ_SPEC_PARAMS]; +}; + /* * Should several domains have the same device node, but serve * different purposes (for example one domain is for PCI/MSI, and the @@ -92,6 +110,8 @@ struct irq_domain_ops { unsigned int nr_irqs); void (*activate)(struct irq_domain *d, struct irq_data *irq_data); void (*deactivate)(struct irq_domain *d, struct irq_data *irq_data); + int (*translate)(struct irq_domain *d, struct irq_fwspec *fwspec, + unsigned long *out_hwirq, unsigned int *out_type); #endif }; -- cgit v1.2.3 From c0131f09de8c2d301814cac86d78f643b8ee0574 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 13 Oct 2015 12:51:34 +0100 Subject: irqdomain: Introduce irq_create_fwspec_mapping Just like we have irq_create_of_mapping, irq_create_fwspec_mapping creates a IRQ domain mapping for an interrupt described in a struct irq_fwspec. irq_create_of_mapping gets rewritten in terms of the new function, and the hack we introduced before gets removed (now that no stacked irqchip uses of_phandle_args anymore). Signed-off-by: Marc Zyngier Reviewed-and-tested-by: Hanjun Guo Tested-by: Lorenzo Pieralisi Cc: Cc: Tomasz Nowicki Cc: Suravee Suthikulpanit Cc: Graeme Gregory Cc: Jake Oshins Cc: Jiang Liu Cc: Jason Cooper Cc: Rafael J. Wysocki Link: http://lkml.kernel.org/r/1444737105-31573-7-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- include/linux/irqdomain.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 533c974b9d94..7e7842e90d40 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -267,6 +267,7 @@ extern void irq_domain_disassociate(struct irq_domain *domain, extern unsigned int irq_create_mapping(struct irq_domain *host, irq_hw_number_t hwirq); +extern unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec); extern void irq_dispose_mapping(unsigned int virq); /** -- cgit v1.2.3 From 1bf4ddc46c5d6123897a54cea4ffe3e90f30600b Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 13 Oct 2015 12:51:35 +0100 Subject: irqdomain: Introduce irq_domain_create_{linear, tree} Just like we have irq_domain_add_{linear,tree} to create a irq domain identified by an of_node, introduce irq_domain_create_{linear,tree} that do the same thing, except that they take a struct fwnode_handle. Existing functions get rewritten in terms of the new ones so that everything keeps working as before (and __irq_domain_add is now fwnode_handle based as well). Signed-off-by: Marc Zyngier Reviewed-and-tested-by: Hanjun Guo Tested-by: Lorenzo Pieralisi Cc: Cc: Tomasz Nowicki Cc: Suravee Suthikulpanit Cc: Graeme Gregory Cc: Jake Oshins Cc: Jiang Liu Cc: Jason Cooper Cc: Rafael J. Wysocki Link: http://lkml.kernel.org/r/1444737105-31573-8-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- include/linux/irqdomain.h | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 7e7842e90d40..995d4c5100d3 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -188,7 +188,7 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d) } #ifdef CONFIG_IRQ_DOMAIN -struct irq_domain *__irq_domain_add(struct device_node *of_node, int size, +struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size, irq_hw_number_t hwirq_max, int direct_max, const struct irq_domain_ops *ops, void *host_data); @@ -207,11 +207,15 @@ extern struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode, enum irq_domain_bus_token bus_token); extern void irq_set_default_host(struct irq_domain *host); +static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node) +{ + return node ? &node->fwnode : NULL; +} + static inline struct irq_domain *irq_find_matching_host(struct device_node *node, enum irq_domain_bus_token bus_token) { - return irq_find_matching_fwnode(node ? &node->fwnode : NULL, - bus_token); + return irq_find_matching_fwnode(of_node_to_fwnode(node), bus_token); } static inline struct irq_domain *irq_find_host(struct device_node *node) @@ -231,14 +235,14 @@ static inline struct irq_domain *irq_domain_add_linear(struct device_node *of_no const struct irq_domain_ops *ops, void *host_data) { - return __irq_domain_add(of_node, size, size, 0, ops, host_data); + return __irq_domain_add(of_node_to_fwnode(of_node), size, size, 0, ops, host_data); } static inline struct irq_domain *irq_domain_add_nomap(struct device_node *of_node, unsigned int max_irq, const struct irq_domain_ops *ops, void *host_data) { - return __irq_domain_add(of_node, 0, max_irq, max_irq, ops, host_data); + return __irq_domain_add(of_node_to_fwnode(of_node), 0, max_irq, max_irq, ops, host_data); } static inline struct irq_domain *irq_domain_add_legacy_isa( struct device_node *of_node, @@ -252,7 +256,22 @@ static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node const struct irq_domain_ops *ops, void *host_data) { - return __irq_domain_add(of_node, 0, ~0, 0, ops, host_data); + return __irq_domain_add(of_node_to_fwnode(of_node), 0, ~0, 0, ops, host_data); +} + +static inline struct irq_domain *irq_domain_create_linear(struct fwnode_handle *fwnode, + unsigned int size, + const struct irq_domain_ops *ops, + void *host_data) +{ + return __irq_domain_add(fwnode, size, size, 0, ops, host_data); +} + +static inline struct irq_domain *irq_domain_create_tree(struct fwnode_handle *fwnode, + const struct irq_domain_ops *ops, + void *host_data) +{ + return __irq_domain_add(fwnode, 0, ~0, 0, ops, host_data); } extern void irq_domain_remove(struct irq_domain *host); -- cgit v1.2.3 From b145dcc45a6af0abfcf9b4de8006d40559c50fc6 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 13 Oct 2015 12:51:36 +0100 Subject: irqdomain: Add a fwnode_handle allocator In order to be able to reference an irqdomain from ACPI, we need to be able to create an identifier, which is usually a struct device_node. This device node does't really fit the ACPI infrastructure, so we cunningly allocate a new structure containing a fwnode_handle, and return that. This structure doesn't really point to a device (interrupt controllers are not "real" devices in Linux), but as we cannot really deny that they exist, we create them with a new fwnode_type (FWNODE_IRQCHIP). Signed-off-by: Marc Zyngier Acked-by: Rafael J. Wysocki Reviewed-and-tested-by: Hanjun Guo Tested-by: Lorenzo Pieralisi Cc: Cc: Tomasz Nowicki Cc: Suravee Suthikulpanit Cc: Graeme Gregory Cc: Jake Oshins Cc: Jiang Liu Cc: Jason Cooper Cc: Rafael J. Wysocki Link: http://lkml.kernel.org/r/1444737105-31573-9-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- include/linux/fwnode.h | 1 + include/linux/irqdomain.h | 2 ++ 2 files changed, 3 insertions(+) (limited to 'include/linux') diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h index 0408545bce42..37ec668546ab 100644 --- a/include/linux/fwnode.h +++ b/include/linux/fwnode.h @@ -17,6 +17,7 @@ enum fwnode_type { FWNODE_OF, FWNODE_ACPI, FWNODE_PDATA, + FWNODE_IRQCHIP, }; struct fwnode_handle { diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 995d4c5100d3..949caa728758 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -188,6 +188,8 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d) } #ifdef CONFIG_IRQ_DOMAIN +struct fwnode_handle *irq_domain_alloc_fwnode(void *data); +void irq_domain_free_fwnode(struct fwnode_handle *fwnode); struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size, irq_hw_number_t hwirq_max, int direct_max, const struct irq_domain_ops *ops, -- cgit v1.2.3 From 2bc6eba4a322e70eac8cde76442c4ac90699fb39 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 13 Oct 2015 12:51:38 +0100 Subject: acpi/gsi: Add acpi_set_irq_model to initialize the GSI layer In order to start embrassing irqdomains at the GSI level, introduce a new initializer: void acpi_set_irq_model(enum acpi_irq_model_id model, struct fwnode_handle *fwnode); where: - model is the value assigned to acpi_irq_model - fwnode is the identifier for the irqdomain mapping GSI interrupts As nobody calls this code yet, the current code is (mostly) left in place. Signed-off-by: Marc Zyngier Acked-by: Rafael J. Wysocki Reviewed-and-tested-by: Hanjun Guo Tested-by: Lorenzo Pieralisi Cc: Cc: Tomasz Nowicki Cc: Suravee Suthikulpanit Cc: Graeme Gregory Cc: Jake Oshins Cc: Jiang Liu Cc: Jason Cooper Cc: Rafael J. Wysocki Link: http://lkml.kernel.org/r/1444737105-31573-11-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- include/linux/acpi.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/linux') diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 43856d19cf4d..d863e12bbead 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -201,6 +201,9 @@ int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi); +void acpi_set_irq_model(enum acpi_irq_model_id model, + struct fwnode_handle *fwnode); + #ifdef CONFIG_X86_IO_APIC extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity); #else -- cgit v1.2.3 From e81a7cd96bd55bb57d92486c514b7b8f8c8cd8ce Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 13 Oct 2015 12:51:39 +0100 Subject: irqchip/gic: Get rid of gic_init_bases() Since nobody is using gic_init_bases anymore outside of the GIC driver itself, let's do a bit of housekeeping and remove the now useless entry point. Only gic_init() is now exposed to the rest of the kernel for the benefit of legacy systems. Signed-off-by: Marc Zyngier Reviewed-and-tested-by: Hanjun Guo Tested-by: Lorenzo Pieralisi Cc: Cc: Tomasz Nowicki Cc: Suravee Suthikulpanit Cc: Graeme Gregory Cc: Jake Oshins Cc: Jiang Liu Cc: Jason Cooper Cc: Rafael J. Wysocki Link: http://lkml.kernel.org/r/1444737105-31573-12-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- include/linux/irqchip/arm-gic.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index b8901dfd9e95..bae69e5d693c 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -100,16 +100,11 @@ struct device_node; -void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *, - u32 offset, struct device_node *); void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); int gic_cpu_if_down(unsigned int gic_nr); -static inline void gic_init(unsigned int nr, int start, - void __iomem *dist , void __iomem *cpu) -{ - gic_init_bases(nr, start, dist, cpu, 0, NULL); -} +void gic_init(unsigned int nr, int start, + void __iomem *dist , void __iomem *cpu); int gicv2m_of_init(struct device_node *node, struct irq_domain *parent); -- cgit v1.2.3 From 2a5e9a072da6469a37d1f0b1577416f51223c280 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 13 Oct 2015 12:51:43 +0100 Subject: irqdomain: Introduce irq_domain_create_hierarchy As we're about to start converting the various MSI layers to use fwnode_handle instead of device_node, add irq_domain_create_hierarchy as a directly equivalent of irq_domain_add_hierarchy (which still exists as a compatibility interface). Signed-off-by: Marc Zyngier Tested-by: Hanjun Guo Tested-by: Lorenzo Pieralisi Cc: Cc: Tomasz Nowicki Cc: Suravee Suthikulpanit Cc: Graeme Gregory Cc: Jake Oshins Cc: Jiang Liu Cc: Jason Cooper Cc: Rafael J. Wysocki Link: http://lkml.kernel.org/r/1444737105-31573-16-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- include/linux/irqdomain.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 949caa728758..2b3340ae915d 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -340,10 +340,23 @@ extern void irq_domain_set_info(struct irq_domain *domain, unsigned int virq, void *chip_data, irq_flow_handler_t handler, void *handler_data, const char *handler_name); #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY -extern struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent, +extern struct irq_domain *irq_domain_create_hierarchy(struct irq_domain *parent, unsigned int flags, unsigned int size, - struct device_node *node, + struct fwnode_handle *fwnode, const struct irq_domain_ops *ops, void *host_data); + +static inline struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent, + unsigned int flags, + unsigned int size, + struct device_node *node, + const struct irq_domain_ops *ops, + void *host_data) +{ + return irq_domain_create_hierarchy(parent, flags, size, + of_node_to_fwnode(node), + ops, host_data); +} + extern int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base, unsigned int nr_irqs, int node, void *arg, bool realloc); -- cgit v1.2.3 From be5436c83ac8921f33fe07323fab03c6644ce52e Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 13 Oct 2015 12:51:44 +0100 Subject: irqdomain/msi: Use fwnode instead of of_node As we continue to push of_node towards the outskirts of irq domains, let's start tackling the case of msi_create_irq_domain and its little friends. This has limited impact in both PCI/MSI, platform MSI, and a few drivers. Signed-off-by: Marc Zyngier Tested-by: Hanjun Guo Tested-by: Lorenzo Pieralisi Cc: Cc: Tomasz Nowicki Cc: Suravee Suthikulpanit Cc: Graeme Gregory Cc: Jake Oshins Cc: Jiang Liu Cc: Jason Cooper Cc: Rafael J. Wysocki Link: http://lkml.kernel.org/r/1444737105-31573-17-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- include/linux/msi.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/msi.h b/include/linux/msi.h index ad939d0ba816..32a24b9a9556 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -174,6 +174,7 @@ struct msi_controller { struct irq_domain; struct irq_chip; struct device_node; +struct fwnode_handle; struct msi_domain_info; /** @@ -262,7 +263,7 @@ enum { int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force); -struct irq_domain *msi_create_irq_domain(struct device_node *of_node, +struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode, struct msi_domain_info *info, struct irq_domain *parent); int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, @@ -270,7 +271,7 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev); struct msi_domain_info *msi_get_domain_info(struct irq_domain *domain); -struct irq_domain *platform_msi_create_irq_domain(struct device_node *np, +struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode, struct msi_domain_info *info, struct irq_domain *parent); int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec, @@ -280,13 +281,13 @@ void platform_msi_domain_free_irqs(struct device *dev); #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN void pci_msi_domain_write_msg(struct irq_data *irq_data, struct msi_msg *msg); -struct irq_domain *pci_msi_create_irq_domain(struct device_node *node, +struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode, struct msi_domain_info *info, struct irq_domain *parent); int pci_msi_domain_alloc_irqs(struct irq_domain *domain, struct pci_dev *dev, int nvec, int type); void pci_msi_domain_free_irqs(struct irq_domain *domain, struct pci_dev *dev); -struct irq_domain *pci_msi_create_default_irq_domain(struct device_node *node, +struct irq_domain *pci_msi_create_default_irq_domain(struct fwnode_handle *fwnode, struct msi_domain_info *info, struct irq_domain *parent); irq_hw_number_t pci_msi_domain_calc_hwirq(struct pci_dev *dev, -- cgit v1.2.3 From e7a46c818564329f977f8fa157b5e9e1d0d83012 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 13 Oct 2015 12:51:45 +0100 Subject: irqdomain: Documentation updates Update the IRQ domain documentation to reflect the changes made while divorcing the domain infrastructure from Device Tree. Signed-off-by: Marc Zyngier Tested-by: Hanjun Guo Tested-by: Lorenzo Pieralisi Cc: Cc: Tomasz Nowicki Cc: Suravee Suthikulpanit Cc: Graeme Gregory Cc: Jake Oshins Cc: Jiang Liu Cc: Jason Cooper Cc: Rafael J. Wysocki Link: http://lkml.kernel.org/r/1444737105-31573-18-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- include/linux/irqdomain.h | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'include/linux') diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 2b3340ae915d..d5e5c5bef28c 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -5,9 +5,10 @@ * helpful for interrupt controllers to implement mapping between hardware * irq numbers and the Linux irq number space. * - * irq_domains also have a hook for translating device tree interrupt - * representation into a hardware irq number that can be mapped back to a - * Linux irq number without any extra platform support code. + * irq_domains also have hooks for translating device tree or other + * firmware interrupt representations into a hardware irq number that + * can be mapped back to a Linux irq number without any extra platform + * support code. * * Interrupt controller "domain" data structure. This could be defined as a * irq domain controller. That is, it handles the mapping between hardware @@ -17,16 +18,12 @@ * model). It's the domain callbacks that are responsible for setting the * irq_chip on a given irq_desc after it's been mapped. * - * The host code and data structures are agnostic to whether or not - * we use an open firmware device-tree. We do have references to struct - * device_node in two places: in irq_find_host() to find the host matching - * a given interrupt controller node, and of course as an argument to its - * counterpart domain->ops->match() callback. However, those are treated as - * generic pointers by the core and the fact that it's actually a device-node - * pointer is purely a convention between callers and implementation. This - * code could thus be used on other architectures by replacing those two - * by some sort of arch-specific void * "token" used to identify interrupt - * controllers. + * The host code and data structures use a fwnode_handle pointer to + * identify the domain. In some cases, and in order to preserve source + * code compatibility, this fwnode pointer is "upgraded" to a DT + * device_node. For those firmware infrastructures that do not provide + * a unique identifier for an interrupt controller, the irq_domain + * code offers a fwnode allocator. */ #ifndef _LINUX_IRQDOMAIN_H -- cgit v1.2.3 From 8db02d8b4089fa8098a170738e8ae7939aa8ae7a Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 8 Oct 2015 15:10:48 -0700 Subject: of/irq: Add new function of_msi_map_rid() The device tree property "msi-map" specifies how to create the PCI requester id used in some MSI controllers. Add a new function of_msi_map_rid() that finds the msi-map property and applies its translation to a given requester id. Reviewed-by: Marc Zyngier Acked-by: Rob Herring Signed-off-by: David Daney Signed-off-by: Marc Zyngier --- include/linux/of_irq.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux') diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h index 4bcbd586a672..8cd9334e5731 100644 --- a/include/linux/of_irq.h +++ b/include/linux/of_irq.h @@ -75,6 +75,7 @@ static inline int of_irq_to_resource_table(struct device_node *dev, extern unsigned int irq_of_parse_and_map(struct device_node *node, int index); extern struct device_node *of_irq_find_parent(struct device_node *child); extern void of_msi_configure(struct device *dev, struct device_node *np); +u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in); #else /* !CONFIG_OF */ static inline unsigned int irq_of_parse_and_map(struct device_node *dev, @@ -87,6 +88,12 @@ static inline void *of_irq_find_parent(struct device_node *child) { return NULL; } + +static inline u32 of_msi_map_rid(struct device *dev, + struct device_node *msi_np, u32 rid_in) +{ + return rid_in; +} #endif /* !CONFIG_OF */ #endif /* __OF_IRQ_H */ -- cgit v1.2.3 From b6eec9b717d4dcb39ef024b8a3b619a32468b01e Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 8 Oct 2015 15:10:49 -0700 Subject: PCI/MSI: Add helper function pci_msi_domain_get_msi_rid(). Add pci_msi_domain_get_msi_rid() to return the MSI requester id (RID). Initially needed by gic-v3 based systems. It will be used by follow on patch to drivers/irqchip/irq-gic-v3-its-pci-msi.c Initially supports mapping the RID via OF device tree. In the future, this could be extended to use ACPI _IORT tables as well. Reviewed-by: Marc Zyngier Acked-by: Bjorn Helgaas Signed-off-by: David Daney Signed-off-by: Marc Zyngier --- include/linux/msi.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/msi.h b/include/linux/msi.h index 32a24b9a9556..87723751054d 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -294,6 +294,7 @@ irq_hw_number_t pci_msi_domain_calc_hwirq(struct pci_dev *dev, struct msi_desc *desc); int pci_msi_domain_check_cap(struct irq_domain *domain, struct msi_domain_info *info, struct device *dev); +u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev); #endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */ #endif /* LINUX_MSI_H */ -- cgit v1.2.3 From 48ae34fb39b0c0cfc76275e844fba5b0b04fa49e Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 18 Sep 2015 14:07:40 +0100 Subject: of/irq: Add support code for multi-parent version of "msi-parent" Since 126b16e2ad98 ("Docs: dt: add generic MSI bindings"), the definition of "msi-parent" has evolved, while maintaining some degree of compatibility. It can now express multiple MSI controllers as parents, as well as some sideband data being communicated to the controller. This patch adds the parsing of the property, iterating over the multiple parents until a suitable irqdomain is found. It can also fallback to the original parsing if the old binding is detected. This support code gets used in the subsequent patches. Suggested-by: Robin Murphy Acked-by: Rob Herring Signed-off-by: Marc Zyngier --- include/linux/of_irq.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include/linux') diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h index 8cd9334e5731..62ae6edecfd5 100644 --- a/include/linux/of_irq.h +++ b/include/linux/of_irq.h @@ -46,6 +46,9 @@ extern int of_irq_get(struct device_node *dev, int index); extern int of_irq_get_byname(struct device_node *dev, const char *name); extern int of_irq_to_resource_table(struct device_node *dev, struct resource *res, int nr_irqs); +extern struct irq_domain *of_msi_get_domain(struct device *dev, + struct device_node *np, + enum irq_domain_bus_token token); #else static inline int of_irq_count(struct device_node *dev) { @@ -64,6 +67,12 @@ static inline int of_irq_to_resource_table(struct device_node *dev, { return 0; } +static inline struct irq_domain *of_msi_get_domain(struct device *dev, + struct device_node *np, + enum irq_domain_bus_token token) +{ + return NULL; +} #endif #if defined(CONFIG_OF) -- cgit v1.2.3 From 82b9b4243c6d99d9e38087fa89183aa7479185e9 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 2 Oct 2015 14:38:55 +0100 Subject: of/irq: Use the msi-map property to provide device-specific MSI domain While msi-parent is used to point to the MSI controller that works for all the devices behind a root complex, it doesn't allow configurations where each individual device can be routed to a separate MSI controller. The msi-map property provides this flexibility (and much more), so let's add a utility function that parses it, and return the corresponding MSI domain. Acked-by: Rob Herring Signed-off-by: Marc Zyngier --- include/linux/of_irq.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux') diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h index 62ae6edecfd5..65d969246a4d 100644 --- a/include/linux/of_irq.h +++ b/include/linux/of_irq.h @@ -49,6 +49,8 @@ extern int of_irq_to_resource_table(struct device_node *dev, extern struct irq_domain *of_msi_get_domain(struct device *dev, struct device_node *np, enum irq_domain_bus_token token); +extern struct irq_domain *of_msi_map_get_device_domain(struct device *dev, + u32 rid); #else static inline int of_irq_count(struct device_node *dev) { @@ -73,6 +75,11 @@ static inline struct irq_domain *of_msi_get_domain(struct device *dev, { return NULL; } +static inline struct irq_domain *of_msi_map_get_device_domain(struct device *dev, + u32 rid) +{ + return NULL; +} #endif #if defined(CONFIG_OF) -- cgit v1.2.3 From 54fa97eeb9e22b47d68b67ee00987afa7fbc2178 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 2 Oct 2015 14:43:06 +0100 Subject: PCI/MSI: Allow the MSI domain to be device-specific So far, we've always considered that for a given PCI device, its MSI controller was either set by the architecture-specific pcibios hook, or simply inherited from the host bridge. This doesn't cover things like firmware-defined topologies like msi-map (DT) or IORT (ACPI), which can provide information about which MSI controller to use on a per-device basis. This patch adds the necessary hook into the MSI code to allow this feature, and provides the msi-map functionnality as a first implementation. Acked-by: Rob Herring Acked-by: Bjorn Helgaas Signed-off-by: Marc Zyngier --- include/linux/msi.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux') diff --git a/include/linux/msi.h b/include/linux/msi.h index 87723751054d..0b4460374020 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -295,6 +295,12 @@ irq_hw_number_t pci_msi_domain_calc_hwirq(struct pci_dev *dev, int pci_msi_domain_check_cap(struct irq_domain *domain, struct msi_domain_info *info, struct device *dev); u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev); +struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev); +#else +static inline struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev) +{ + return NULL; +} #endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */ #endif /* LINUX_MSI_H */ -- cgit v1.2.3 From d9e4ad5badf4ccbfddee208c898fb8fd0c8836b1 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 28 Oct 2015 16:14:31 +0900 Subject: Document that IRQ_NONE should be returned when IRQ not actually handled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our IRQ storm detection works when an interrupt handler returns IRQ_NONE for thousands of consecutive interrupts in a second. It doesn't hurt to occasionally return IRQ_NONE when the interrupt is actually genuine. Drivers should only be returning IRQ_HANDLED if they have actually *done* something to stop an interrupt from happening — it doesn't just mean "this really *was* my device". Signed-off-by: David Woodhouse Cc: davem@davemloft.net Link: http://lkml.kernel.org/r/1446016471.3405.201.camel@infradead.org Signed-off-by: Thomas Gleixner --- include/linux/irqreturn.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/irqreturn.h b/include/linux/irqreturn.h index e374e369fb2f..eb1bdcf95f2e 100644 --- a/include/linux/irqreturn.h +++ b/include/linux/irqreturn.h @@ -3,7 +3,7 @@ /** * enum irqreturn - * @IRQ_NONE interrupt was not from this device + * @IRQ_NONE interrupt was not from this device or was not handled * @IRQ_HANDLED interrupt was handled by this device * @IRQ_WAKE_THREAD handler requests to wake the handler thread */ -- cgit v1.2.3