Merge branch irq/generic_handle_domain_irq-core into irq/irqchip-next
Simplify the handling of interrupts that require an IRQ domain resolution: - domains now cache the irqdata instead of the irq number - consistent behaviour wrt RCU - single lookup for architectures using sparse IRQs - reduced boilerplate code in drivers. * irq/generic_handle_domain_irq-core: (26 commits) irqchip: Bulk conversion to generic_handle_domain_irq() genirq: Move non-irqdomain handle_domain_irq() handling into ARM's handle_IRQ() genirq: Add generic_handle_domain_irq() helper irqchip/nvic: Convert from handle_IRQ() to handle_domain_irq() irqdesc: Fix __handle_domain_irq() comment genirq: Use irq_resolve_mapping() to implement __handle_domain_irq() and co irqdomain: Introduce irq_resolve_mapping() irqdomain: Protect the linear revmap with RCU irqdomain: Cache irq_data instead of a virq number in the revmap irqdomain: Use struct_size() helper when allocating irqdomain irqdomain: Make normal and nomap irqdomains exclusive powerpc: Move the use of irq_domain_add_nomap() behind a config option irqdomain: Reimplement irq_linear_revmap() with irq_find_mapping() irqdomain: Kill irq_domain_add_legacy_isa powerpc: Drop dependency between asm/irq.h and linux/irqdomain.h powerpc: Convert irq_domain_add_legacy_isa use to irq_domain_add_legacy scsi/ibmvscsi: Directly include linux/{of.h,irqdomain.h} powerpc: Add missing linux/{of.h,irqdomain.h} include directives MIPS: Do not include linux/irqdomain.h from asm/irq.h MIPS: Add missing linux/irqdomain.h includes ...
This commit is contained in:
Коммит
c64638d509
|
@ -146,7 +146,6 @@ Legacy
|
|||
|
||||
irq_domain_add_simple()
|
||||
irq_domain_add_legacy()
|
||||
irq_domain_add_legacy_isa()
|
||||
irq_domain_create_simple()
|
||||
irq_domain_create_legacy()
|
||||
|
||||
|
|
|
@ -63,7 +63,27 @@ int arch_show_interrupts(struct seq_file *p, int prec)
|
|||
*/
|
||||
void handle_IRQ(unsigned int irq, struct pt_regs *regs)
|
||||
{
|
||||
__handle_domain_irq(NULL, irq, false, regs);
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
struct irq_desc *desc;
|
||||
|
||||
irq_enter();
|
||||
|
||||
/*
|
||||
* Some hardware gives randomly wrong interrupts. Rather
|
||||
* than crashing, do something sensible.
|
||||
*/
|
||||
if (unlikely(!irq || irq >= nr_irqs))
|
||||
desc = NULL;
|
||||
else
|
||||
desc = irq_to_desc(irq);
|
||||
|
||||
if (likely(desc))
|
||||
handle_irq_desc(desc);
|
||||
else
|
||||
ack_bad_irq(irq);
|
||||
|
||||
irq_exit();
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/irqdomain.h>
|
||||
|
||||
#include <asm/mipsmtregs.h>
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <lantiq_soc.h>
|
||||
#include <xway_dma.h>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_pci.h>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/platform_data/xtalk-bridge.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
#include <linux/crc16.h>
|
||||
#include <linux/irqdomain.h>
|
||||
|
||||
#include <asm/pci/bridge.h>
|
||||
#include <asm/paccess.h>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/bitops.h>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/tick.h>
|
||||
|
|
|
@ -10,6 +10,5 @@
|
|||
#define NIOS2_CPU_NR_IRQS 32
|
||||
|
||||
#include <asm-generic/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
static u32 ienable;
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
/*
|
||||
*/
|
||||
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/threads.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/radix-tree.h>
|
||||
|
@ -23,8 +22,8 @@ extern atomic_t ppc_n_lost_interrupts;
|
|||
/* Total number of virq in the platform */
|
||||
#define NR_IRQS CONFIG_NR_IRQS
|
||||
|
||||
/* Same thing, used by the generic IRQ code */
|
||||
#define NR_IRQS_LEGACY NUM_ISA_INTERRUPTS
|
||||
/* Number of irqs reserved for a legacy isa controller */
|
||||
#define NR_IRQS_LEGACY 16
|
||||
|
||||
extern irq_hw_number_t virq_to_hw(unsigned int virq);
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/extable.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/interrupt.h>
|
||||
#include <asm/machdep.h>
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
#include <linux/migrate.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/ksm.h>
|
||||
#include <linux/of.h>
|
||||
#include <asm/ultravisor.h>
|
||||
#include <asm/mman.h>
|
||||
#include <asm/kvm_ppc.h>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/percpu.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <asm/kvm_book3s.h>
|
||||
#include <asm/kvm_ppc.h>
|
||||
#include <asm/hvcall.h>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/kvm_book3s.h>
|
||||
#include <asm/kvm_ppc.h>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/sched/mm.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/hugetlb.h>
|
||||
|
|
|
@ -35,6 +35,7 @@ config PPC_IBM_CELL_BLADE
|
|||
config AXON_MSI
|
||||
bool
|
||||
depends on PPC_IBM_CELL_BLADE && PCI_MSI
|
||||
select IRQ_DOMAIN_NOMAP
|
||||
default y
|
||||
|
||||
menu "Cell Broadband Engine options"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/export.h>
|
||||
#include <asm/io.h>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <asm/io.h>
|
||||
|
|
|
@ -24,6 +24,7 @@ config PPC_PMAC32_PSURGE
|
|||
bool "Support for powersurge upgrade cards" if EXPERT
|
||||
depends on SMP && PPC32 && PPC_PMAC
|
||||
select PPC_SMP_MUXED_IPI
|
||||
select IRQ_DOMAIN_NOMAP
|
||||
default y
|
||||
help
|
||||
The powersurge cpu boards can be used in the generation
|
||||
|
|
|
@ -7,6 +7,7 @@ config PPC_PS3
|
|||
select USB_OHCI_BIG_ENDIAN_MMIO
|
||||
select USB_EHCI_BIG_ENDIAN_MMIO
|
||||
select HAVE_PCI
|
||||
select IRQ_DOMAIN_NOMAP
|
||||
help
|
||||
This option enables support for the Sony PS3 game console
|
||||
and other platforms using the PS3 hypervisor. Enabling this
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/udbg.h>
|
||||
|
@ -45,7 +46,7 @@
|
|||
* implementation equates HV plug value to Linux virq value, constrains each
|
||||
* interrupt to have a system wide unique plug number, and limits the range
|
||||
* of the plug values to map into the first dword of the bitmaps. This
|
||||
* gives a usable range of plug values of {NUM_ISA_INTERRUPTS..63}. Note
|
||||
* gives a usable range of plug values of {NR_IRQS_LEGACY..63}. Note
|
||||
* that there is no constraint on how many in this set an individual thread
|
||||
* can acquire.
|
||||
*
|
||||
|
@ -721,7 +722,7 @@ static unsigned int ps3_get_irq(void)
|
|||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
if (unlikely(plug < NUM_ISA_INTERRUPTS || plug > PS3_PLUG_MAX)) {
|
||||
if (unlikely(plug < NR_IRQS_LEGACY || plug > PS3_PLUG_MAX)) {
|
||||
dump_bmp(&per_cpu(ps3_private, 0));
|
||||
dump_bmp(&per_cpu(ps3_private, 1));
|
||||
BUG();
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <linux/kobject.h>
|
||||
#include <linux/dma-map-ops.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stat.h>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <linux/irq.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
|
|
@ -260,7 +260,8 @@ void i8259_init(struct device_node *node, unsigned long intack_addr)
|
|||
raw_spin_unlock_irqrestore(&i8259_lock, flags);
|
||||
|
||||
/* create a legacy host */
|
||||
i8259_host = irq_domain_add_legacy_isa(node, &i8259_host_ops, NULL);
|
||||
i8259_host = irq_domain_add_legacy(node, NR_IRQS_LEGACY, 0, 0,
|
||||
&i8259_host_ops, NULL);
|
||||
if (i8259_host == NULL) {
|
||||
printk(KERN_ERR "i8259: failed to allocate irq host !\n");
|
||||
return;
|
||||
|
|
|
@ -602,7 +602,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
|
|||
/* Find an mpic associated with a given linux interrupt */
|
||||
static struct mpic *mpic_find(unsigned int irq)
|
||||
{
|
||||
if (irq < NUM_ISA_INTERRUPTS)
|
||||
if (irq < NR_IRQS_LEGACY)
|
||||
return NULL;
|
||||
|
||||
return irq_get_chip_data(irq);
|
||||
|
|
|
@ -404,7 +404,8 @@ void __init tsi108_pci_int_init(struct device_node *node)
|
|||
{
|
||||
DBG("Tsi108_pci_int_init: initializing PCI interrupts\n");
|
||||
|
||||
pci_irq_host = irq_domain_add_legacy_isa(node, &pci_irq_domain_ops, NULL);
|
||||
pci_irq_host = irq_domain_add_legacy(node, NR_IRQS_LEGACY, 0, 0,
|
||||
&pci_irq_domain_ops, NULL);
|
||||
if (pci_irq_host == NULL) {
|
||||
printk(KERN_ERR "pci_irq_host: failed to allocate irq domain!\n");
|
||||
return;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/irq.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/irq.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ void xics_migrate_irqs_away(void)
|
|||
struct ics *ics;
|
||||
|
||||
/* We can't set affinity on ISA interrupts */
|
||||
if (virq < NUM_ISA_INTERRUPTS)
|
||||
if (virq < NR_IRQS_LEGACY)
|
||||
continue;
|
||||
/* We only need to migrate enabled IRQS */
|
||||
if (!desc->action)
|
||||
|
|
|
@ -3,6 +3,7 @@ config PPC_XIVE
|
|||
bool
|
||||
select PPC_SMP_MUXED_IPI
|
||||
select HARDIRQS_SW_RESEND
|
||||
select IRQ_DOMAIN_NOMAP
|
||||
|
||||
config PPC_XIVE_NATIVE
|
||||
bool
|
||||
|
|
|
@ -66,8 +66,9 @@ static void combiner_handle_cascade_irq(struct irq_desc *desc)
|
|||
{
|
||||
struct combiner_chip_data *chip_data = irq_desc_get_handler_data(desc);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
unsigned int cascade_irq, combiner_irq;
|
||||
unsigned int combiner_irq;
|
||||
unsigned long status;
|
||||
int ret;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
|
@ -80,12 +81,9 @@ static void combiner_handle_cascade_irq(struct irq_desc *desc)
|
|||
goto out;
|
||||
|
||||
combiner_irq = chip_data->hwirq_offset + __ffs(status);
|
||||
cascade_irq = irq_find_mapping(combiner_irq_domain, combiner_irq);
|
||||
|
||||
if (unlikely(!cascade_irq))
|
||||
ret = generic_handle_domain_irq(combiner_irq_domain, combiner_irq);
|
||||
if (unlikely(ret))
|
||||
handle_bad_irq(desc);
|
||||
else
|
||||
generic_handle_irq(cascade_irq);
|
||||
|
||||
out:
|
||||
chained_irq_exit(chip, desc);
|
||||
|
|
|
@ -111,7 +111,6 @@ static void al_fic_irq_handler(struct irq_desc *desc)
|
|||
struct irq_chip *irqchip = irq_desc_get_chip(desc);
|
||||
struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
|
||||
unsigned long pending;
|
||||
unsigned int irq;
|
||||
u32 hwirq;
|
||||
|
||||
chained_irq_enter(irqchip, desc);
|
||||
|
@ -119,10 +118,8 @@ static void al_fic_irq_handler(struct irq_desc *desc)
|
|||
pending = readl_relaxed(fic->base + AL_FIC_CAUSE);
|
||||
pending &= ~gc->mask_cache;
|
||||
|
||||
for_each_set_bit(hwirq, &pending, NR_FIC_IRQS) {
|
||||
irq = irq_find_mapping(domain, hwirq);
|
||||
generic_handle_irq(irq);
|
||||
}
|
||||
for_each_set_bit(hwirq, &pending, NR_FIC_IRQS)
|
||||
generic_handle_domain_irq(domain, hwirq);
|
||||
|
||||
chained_irq_exit(irqchip, desc);
|
||||
}
|
||||
|
|
|
@ -582,20 +582,19 @@ static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained)
|
|||
|
||||
for (msinr = PCI_MSI_DOORBELL_START;
|
||||
msinr < PCI_MSI_DOORBELL_END; msinr++) {
|
||||
int irq;
|
||||
unsigned int irq;
|
||||
|
||||
if (!(msimask & BIT(msinr)))
|
||||
continue;
|
||||
|
||||
if (is_chained) {
|
||||
irq = irq_find_mapping(armada_370_xp_msi_inner_domain,
|
||||
msinr - PCI_MSI_DOORBELL_START);
|
||||
generic_handle_irq(irq);
|
||||
} else {
|
||||
irq = msinr - PCI_MSI_DOORBELL_START;
|
||||
irq = msinr - PCI_MSI_DOORBELL_START;
|
||||
|
||||
if (is_chained)
|
||||
generic_handle_domain_irq(armada_370_xp_msi_inner_domain,
|
||||
irq);
|
||||
else
|
||||
handle_domain_irq(armada_370_xp_msi_inner_domain,
|
||||
irq, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -606,7 +605,6 @@ static void armada_370_xp_mpic_handle_cascade_irq(struct irq_desc *desc)
|
|||
{
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
unsigned long irqmap, irqn, irqsrc, cpuid;
|
||||
unsigned int cascade_irq;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
|
@ -628,8 +626,7 @@ static void armada_370_xp_mpic_handle_cascade_irq(struct irq_desc *desc)
|
|||
continue;
|
||||
}
|
||||
|
||||
cascade_irq = irq_find_mapping(armada_370_xp_mpic_domain, irqn);
|
||||
generic_handle_irq(cascade_irq);
|
||||
generic_handle_domain_irq(armada_370_xp_mpic_domain, irqn);
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
|
|
|
@ -34,14 +34,12 @@ static void aspeed_i2c_ic_irq_handler(struct irq_desc *desc)
|
|||
struct aspeed_i2c_ic *i2c_ic = irq_desc_get_handler_data(desc);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
unsigned long bit, status;
|
||||
unsigned int bus_irq;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
status = readl(i2c_ic->base);
|
||||
for_each_set_bit(bit, &status, ASPEED_I2C_IC_NUM_BUS) {
|
||||
bus_irq = irq_find_mapping(i2c_ic->irq_domain, bit);
|
||||
generic_handle_irq(bus_irq);
|
||||
}
|
||||
for_each_set_bit(bit, &status, ASPEED_I2C_IC_NUM_BUS)
|
||||
generic_handle_domain_irq(i2c_ic->irq_domain, bit);
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@ struct aspeed_scu_ic {
|
|||
|
||||
static void aspeed_scu_ic_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
unsigned int irq;
|
||||
unsigned int sts;
|
||||
unsigned long bit;
|
||||
unsigned long enabled;
|
||||
|
@ -74,9 +73,8 @@ static void aspeed_scu_ic_irq_handler(struct irq_desc *desc)
|
|||
max = scu_ic->num_irqs + bit;
|
||||
|
||||
for_each_set_bit_from(bit, &status, max) {
|
||||
irq = irq_find_mapping(scu_ic->irq_domain,
|
||||
bit - scu_ic->irq_shift);
|
||||
generic_handle_irq(irq);
|
||||
generic_handle_domain_irq(scu_ic->irq_domain,
|
||||
bit - scu_ic->irq_shift);
|
||||
|
||||
regmap_update_bits(scu_ic->scu, scu_ic->reg, mask,
|
||||
BIT(bit + ASPEED_SCU_IC_STATUS_SHIFT));
|
||||
|
|
|
@ -50,7 +50,7 @@ static void ath79_misc_irq_handler(struct irq_desc *desc)
|
|||
while (pending) {
|
||||
int bit = __ffs(pending);
|
||||
|
||||
generic_handle_irq(irq_linear_revmap(domain, bit));
|
||||
generic_handle_domain_irq(domain, bit);
|
||||
pending &= ~BIT(bit);
|
||||
}
|
||||
|
||||
|
|
|
@ -254,7 +254,7 @@ static void bcm2836_chained_handle_irq(struct irq_desc *desc)
|
|||
u32 hwirq;
|
||||
|
||||
while ((hwirq = get_next_armctrl_hwirq()) != ~0)
|
||||
generic_handle_irq(irq_linear_revmap(intc.domain, hwirq));
|
||||
generic_handle_domain_irq(intc.domain, hwirq);
|
||||
}
|
||||
|
||||
IRQCHIP_DECLARE(bcm2835_armctrl_ic, "brcm,bcm2835-armctrl-ic",
|
||||
|
|
|
@ -161,7 +161,7 @@ static void bcm2836_arm_irqchip_handle_ipi(struct irq_desc *desc)
|
|||
mbox_val = readl_relaxed(intc.base + LOCAL_MAILBOX0_CLR0 + 16 * cpu);
|
||||
if (mbox_val) {
|
||||
int hwirq = ffs(mbox_val) - 1;
|
||||
generic_handle_irq(irq_find_mapping(ipi_domain, hwirq));
|
||||
generic_handle_domain_irq(ipi_domain, hwirq);
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
|
|
|
@ -145,10 +145,8 @@ static void bcm7038_l1_irq_handle(struct irq_desc *desc)
|
|||
~cpu->mask_cache[idx];
|
||||
raw_spin_unlock_irqrestore(&intc->lock, flags);
|
||||
|
||||
for_each_set_bit(hwirq, &pending, IRQS_PER_WORD) {
|
||||
generic_handle_irq(irq_find_mapping(intc->domain,
|
||||
base + hwirq));
|
||||
}
|
||||
for_each_set_bit(hwirq, &pending, IRQS_PER_WORD)
|
||||
generic_handle_domain_irq(intc->domain, base + hwirq);
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
|
|
|
@ -74,10 +74,8 @@ static void bcm7120_l2_intc_irq_handle(struct irq_desc *desc)
|
|||
data->irq_map_mask[idx];
|
||||
irq_gc_unlock(gc);
|
||||
|
||||
for_each_set_bit(hwirq, &pending, IRQS_PER_WORD) {
|
||||
generic_handle_irq(irq_find_mapping(b->domain,
|
||||
base + hwirq));
|
||||
}
|
||||
for_each_set_bit(hwirq, &pending, IRQS_PER_WORD)
|
||||
generic_handle_domain_irq(b->domain, base + hwirq);
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
|
|
|
@ -110,7 +110,7 @@ static void brcmstb_l2_intc_irq_handle(struct irq_desc *desc)
|
|||
do {
|
||||
irq = ffs(status) - 1;
|
||||
status &= ~(1 << irq);
|
||||
generic_handle_irq(irq_linear_revmap(b->domain, irq));
|
||||
generic_handle_domain_irq(b->domain, irq);
|
||||
} while (status);
|
||||
out:
|
||||
chained_irq_exit(chip, desc);
|
||||
|
|
|
@ -62,9 +62,8 @@ static void dw_apb_ictl_handle_irq_cascaded(struct irq_desc *desc)
|
|||
|
||||
while (stat) {
|
||||
u32 hwirq = ffs(stat) - 1;
|
||||
u32 virq = irq_find_mapping(d, gc->irq_base + hwirq);
|
||||
generic_handle_domain_irq(d, gc->irq_base + hwirq);
|
||||
|
||||
generic_handle_irq(virq);
|
||||
stat &= ~BIT(hwirq);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -375,8 +375,9 @@ static void gic_handle_cascade_irq(struct irq_desc *desc)
|
|||
{
|
||||
struct gic_chip_data *chip_data = irq_desc_get_handler_data(desc);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
unsigned int cascade_irq, gic_irq;
|
||||
unsigned int gic_irq;
|
||||
unsigned long status;
|
||||
int ret;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
|
@ -386,14 +387,10 @@ static void gic_handle_cascade_irq(struct irq_desc *desc)
|
|||
if (gic_irq == GICC_INT_SPURIOUS)
|
||||
goto out;
|
||||
|
||||
cascade_irq = irq_find_mapping(chip_data->domain, gic_irq);
|
||||
if (unlikely(gic_irq < 32 || gic_irq > 1020)) {
|
||||
isb();
|
||||
ret = generic_handle_domain_irq(chip_data->domain, gic_irq);
|
||||
if (unlikely(ret))
|
||||
handle_bad_irq(desc);
|
||||
} else {
|
||||
isb();
|
||||
generic_handle_irq(cascade_irq);
|
||||
}
|
||||
|
||||
out:
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
|
|
@ -34,15 +34,14 @@ static void goldfish_pic_cascade(struct irq_desc *desc)
|
|||
{
|
||||
struct goldfish_pic_data *gfpic = irq_desc_get_handler_data(desc);
|
||||
struct irq_chip *host_chip = irq_desc_get_chip(desc);
|
||||
u32 pending, hwirq, virq;
|
||||
u32 pending, hwirq;
|
||||
|
||||
chained_irq_enter(host_chip, desc);
|
||||
|
||||
pending = readl(gfpic->base + GFPIC_REG_IRQ_PENDING);
|
||||
while (pending) {
|
||||
hwirq = __fls(pending);
|
||||
virq = irq_linear_revmap(gfpic->irq_domain, hwirq);
|
||||
generic_handle_irq(virq);
|
||||
generic_handle_domain_irq(gfpic->irq_domain, hwirq);
|
||||
pending &= ~(1 << hwirq);
|
||||
}
|
||||
|
||||
|
|
|
@ -333,13 +333,11 @@ static void i8259_irq_dispatch(struct irq_desc *desc)
|
|||
{
|
||||
struct irq_domain *domain = irq_desc_get_handler_data(desc);
|
||||
int hwirq = i8259_poll();
|
||||
unsigned int irq;
|
||||
|
||||
if (hwirq < 0)
|
||||
return;
|
||||
|
||||
irq = irq_linear_revmap(domain, hwirq);
|
||||
generic_handle_irq(irq);
|
||||
generic_handle_domain_irq(domain, hwirq);
|
||||
}
|
||||
|
||||
int __init i8259_of_init(struct device_node *node, struct device_node *parent)
|
||||
|
|
|
@ -28,7 +28,7 @@ static void idt_irq_dispatch(struct irq_desc *desc)
|
|||
{
|
||||
struct idt_pic_data *idtpic = irq_desc_get_handler_data(desc);
|
||||
struct irq_chip *host_chip = irq_desc_get_chip(desc);
|
||||
u32 pending, hwirq, virq;
|
||||
u32 pending, hwirq;
|
||||
|
||||
chained_irq_enter(host_chip, desc);
|
||||
|
||||
|
@ -36,9 +36,7 @@ static void idt_irq_dispatch(struct irq_desc *desc)
|
|||
pending &= ~idtpic->gc->mask_cache;
|
||||
while (pending) {
|
||||
hwirq = __fls(pending);
|
||||
virq = irq_linear_revmap(idtpic->irq_domain, hwirq);
|
||||
if (virq)
|
||||
generic_handle_irq(virq);
|
||||
generic_handle_domain_irq(idtpic->irq_domain, hwirq);
|
||||
pending &= ~(1 << hwirq);
|
||||
}
|
||||
|
||||
|
|
|
@ -223,7 +223,7 @@ static void pdc_intc_perip_isr(struct irq_desc *desc)
|
|||
{
|
||||
unsigned int irq = irq_desc_get_irq(desc);
|
||||
struct pdc_intc_priv *priv;
|
||||
unsigned int i, irq_no;
|
||||
unsigned int i;
|
||||
|
||||
priv = (struct pdc_intc_priv *)irq_desc_get_handler_data(desc);
|
||||
|
||||
|
@ -237,14 +237,13 @@ static void pdc_intc_perip_isr(struct irq_desc *desc)
|
|||
found:
|
||||
|
||||
/* pass on the interrupt */
|
||||
irq_no = irq_linear_revmap(priv->domain, i);
|
||||
generic_handle_irq(irq_no);
|
||||
generic_handle_domain_irq(priv->domain, i);
|
||||
}
|
||||
|
||||
static void pdc_intc_syswake_isr(struct irq_desc *desc)
|
||||
{
|
||||
struct pdc_intc_priv *priv;
|
||||
unsigned int syswake, irq_no;
|
||||
unsigned int syswake;
|
||||
unsigned int status;
|
||||
|
||||
priv = (struct pdc_intc_priv *)irq_desc_get_handler_data(desc);
|
||||
|
@ -258,9 +257,7 @@ static void pdc_intc_syswake_isr(struct irq_desc *desc)
|
|||
if (!(status & 1))
|
||||
continue;
|
||||
|
||||
irq_no = irq_linear_revmap(priv->domain,
|
||||
syswake_to_hwirq(syswake));
|
||||
generic_handle_irq(irq_no);
|
||||
generic_handle_domain_irq(priv->domain, syswake_to_hwirq(syswake));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -182,18 +182,15 @@ static void imx_intmux_irq_handler(struct irq_desc *desc)
|
|||
struct intmux_data *data = container_of(irqchip_data, struct intmux_data,
|
||||
irqchip_data[idx]);
|
||||
unsigned long irqstat;
|
||||
int pos, virq;
|
||||
int pos;
|
||||
|
||||
chained_irq_enter(irq_desc_get_chip(desc), desc);
|
||||
|
||||
/* read the interrupt source pending status of this channel */
|
||||
irqstat = readl_relaxed(data->regs + CHANIPR(idx));
|
||||
|
||||
for_each_set_bit(pos, &irqstat, 32) {
|
||||
virq = irq_find_mapping(irqchip_data->domain, pos);
|
||||
if (virq)
|
||||
generic_handle_irq(virq);
|
||||
}
|
||||
for_each_set_bit(pos, &irqstat, 32)
|
||||
generic_handle_domain_irq(irqchip_data->domain, pos);
|
||||
|
||||
chained_irq_exit(irq_desc_get_chip(desc), desc);
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ static void imx_irqsteer_irq_handler(struct irq_desc *desc)
|
|||
for (i = 0; i < 2; i++, hwirq += 32) {
|
||||
int idx = imx_irqsteer_get_reg_index(data, hwirq);
|
||||
unsigned long irqmap;
|
||||
int pos, virq;
|
||||
int pos;
|
||||
|
||||
if (hwirq >= data->reg_num * 32)
|
||||
break;
|
||||
|
@ -130,11 +130,8 @@ static void imx_irqsteer_irq_handler(struct irq_desc *desc)
|
|||
irqmap = readl_relaxed(data->regs +
|
||||
CHANSTATUS(idx, data->reg_num));
|
||||
|
||||
for_each_set_bit(pos, &irqmap, 32) {
|
||||
virq = irq_find_mapping(data->domain, pos + hwirq);
|
||||
if (virq)
|
||||
generic_handle_irq(virq);
|
||||
}
|
||||
for_each_set_bit(pos, &irqmap, 32)
|
||||
generic_handle_domain_irq(data->domain, pos + hwirq);
|
||||
}
|
||||
|
||||
chained_irq_exit(irq_desc_get_chip(desc), desc);
|
||||
|
|
|
@ -38,7 +38,7 @@ static void ingenic_tcu_intc_cascade(struct irq_desc *desc)
|
|||
irq_reg &= ~irq_mask;
|
||||
|
||||
for_each_set_bit(i, (unsigned long *)&irq_reg, 32)
|
||||
generic_handle_irq(irq_linear_revmap(domain, i));
|
||||
generic_handle_domain_irq(domain, i);
|
||||
|
||||
chained_irq_exit(irq_chip, desc);
|
||||
}
|
||||
|
|
|
@ -49,8 +49,7 @@ static irqreturn_t intc_cascade(int irq, void *data)
|
|||
while (pending) {
|
||||
int bit = __fls(pending);
|
||||
|
||||
irq = irq_linear_revmap(domain, bit + (i * 32));
|
||||
generic_handle_irq(irq);
|
||||
generic_handle_domain_irq(domain, bit + (i * 32));
|
||||
pending &= ~BIT(bit);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ static irqreturn_t keystone_irq_handler(int irq, void *keystone_irq)
|
|||
struct keystone_irq_device *kirq = keystone_irq;
|
||||
unsigned long wa_lock_flags;
|
||||
unsigned long pending;
|
||||
int src, virq;
|
||||
int src, err;
|
||||
|
||||
dev_dbg(kirq->dev, "start irq %d\n", irq);
|
||||
|
||||
|
@ -104,16 +104,14 @@ static irqreturn_t keystone_irq_handler(int irq, void *keystone_irq)
|
|||
|
||||
for (src = 0; src < KEYSTONE_N_IRQ; src++) {
|
||||
if (BIT(src) & pending) {
|
||||
virq = irq_find_mapping(kirq->irqd, src);
|
||||
dev_dbg(kirq->dev, "dispatch bit %d, virq %d\n",
|
||||
src, virq);
|
||||
if (!virq)
|
||||
dev_warn(kirq->dev, "spurious irq detected hwirq %d, virq %d\n",
|
||||
src, virq);
|
||||
raw_spin_lock_irqsave(&kirq->wa_lock, wa_lock_flags);
|
||||
generic_handle_irq(virq);
|
||||
err = generic_handle_domain_irq(kirq->irqd, src);
|
||||
raw_spin_unlock_irqrestore(&kirq->wa_lock,
|
||||
wa_lock_flags);
|
||||
|
||||
if (err)
|
||||
dev_warn_ratelimited(kirq->dev, "spurious irq detected hwirq %d\n",
|
||||
src);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ static void htpic_irq_dispatch(struct irq_desc *desc)
|
|||
break;
|
||||
}
|
||||
|
||||
generic_handle_irq(irq_linear_revmap(priv->domain, bit));
|
||||
generic_handle_domain_irq(priv->domain, bit);
|
||||
pending &= ~BIT(bit);
|
||||
}
|
||||
chained_irq_exit(chip, desc);
|
||||
|
|
|
@ -47,8 +47,8 @@ static void htvec_irq_dispatch(struct irq_desc *desc)
|
|||
while (pending) {
|
||||
int bit = __ffs(pending);
|
||||
|
||||
generic_handle_irq(irq_linear_revmap(priv->htvec_domain, bit +
|
||||
VEC_COUNT_PER_REG * i));
|
||||
generic_handle_domain_irq(priv->htvec_domain,
|
||||
bit + VEC_COUNT_PER_REG * i);
|
||||
pending &= ~BIT(bit);
|
||||
handled = true;
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ static void liointc_chained_handle_irq(struct irq_desc *desc)
|
|||
while (pending) {
|
||||
int bit = __ffs(pending);
|
||||
|
||||
generic_handle_irq(irq_find_mapping(gc->domain, bit));
|
||||
generic_handle_domain_irq(gc->domain, bit);
|
||||
pending &= ~BIT(bit);
|
||||
}
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ static void lpc32xx_sic_handler(struct irq_desc *desc)
|
|||
while (hwirq) {
|
||||
irq = __ffs(hwirq);
|
||||
hwirq &= ~BIT(irq);
|
||||
generic_handle_irq(irq_find_mapping(ic->domain, irq));
|
||||
generic_handle_domain_irq(ic->domain, irq);
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
|
|
|
@ -194,7 +194,7 @@ static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
|
|||
struct ls_scfg_msir *msir = irq_desc_get_handler_data(desc);
|
||||
struct ls_scfg_msi *msi_data = msir->msi_data;
|
||||
unsigned long val;
|
||||
int pos, size, virq, hwirq;
|
||||
int pos, size, hwirq;
|
||||
|
||||
chained_irq_enter(irq_desc_get_chip(desc), desc);
|
||||
|
||||
|
@ -206,9 +206,7 @@ static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
|
|||
for_each_set_bit_from(pos, &val, size) {
|
||||
hwirq = ((msir->bit_end - pos) << msi_data->cfg->ibs_shift) |
|
||||
msir->srs;
|
||||
virq = irq_find_mapping(msi_data->parent, hwirq);
|
||||
if (virq)
|
||||
generic_handle_irq(virq);
|
||||
generic_handle_domain_irq(msi_data->parent, hwirq);
|
||||
}
|
||||
|
||||
chained_irq_exit(irq_desc_get_chip(desc), desc);
|
||||
|
|
|
@ -50,7 +50,7 @@ static void ls1x_chained_handle_irq(struct irq_desc *desc)
|
|||
while (pending) {
|
||||
int bit = __ffs(pending);
|
||||
|
||||
generic_handle_irq(irq_find_mapping(priv->domain, bit));
|
||||
generic_handle_domain_irq(priv->domain, bit);
|
||||
pending &= ~BIT(bit);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/sched.h>
|
||||
|
@ -147,7 +148,7 @@ int gic_get_c0_fdc_int(void)
|
|||
|
||||
static void gic_handle_shared_int(bool chained)
|
||||
{
|
||||
unsigned int intr, virq;
|
||||
unsigned int intr;
|
||||
unsigned long *pcpu_mask;
|
||||
DECLARE_BITMAP(pending, GIC_MAX_INTRS);
|
||||
|
||||
|
@ -164,12 +165,12 @@ static void gic_handle_shared_int(bool chained)
|
|||
bitmap_and(pending, pending, pcpu_mask, gic_shared_intrs);
|
||||
|
||||
for_each_set_bit(intr, pending, gic_shared_intrs) {
|
||||
virq = irq_linear_revmap(gic_irq_domain,
|
||||
GIC_SHARED_TO_HWIRQ(intr));
|
||||
if (chained)
|
||||
generic_handle_irq(virq);
|
||||
generic_handle_domain_irq(gic_irq_domain,
|
||||
GIC_SHARED_TO_HWIRQ(intr));
|
||||
else
|
||||
do_IRQ(virq);
|
||||
do_IRQ(irq_find_mapping(gic_irq_domain,
|
||||
GIC_SHARED_TO_HWIRQ(intr)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,7 +308,7 @@ static struct irq_chip gic_edge_irq_controller = {
|
|||
static void gic_handle_local_int(bool chained)
|
||||
{
|
||||
unsigned long pending, masked;
|
||||
unsigned int intr, virq;
|
||||
unsigned int intr;
|
||||
|
||||
pending = read_gic_vl_pend();
|
||||
masked = read_gic_vl_mask();
|
||||
|
@ -315,12 +316,12 @@ static void gic_handle_local_int(bool chained)
|
|||
bitmap_and(&pending, &pending, &masked, GIC_NUM_LOCAL_INTRS);
|
||||
|
||||
for_each_set_bit(intr, &pending, GIC_NUM_LOCAL_INTRS) {
|
||||
virq = irq_linear_revmap(gic_irq_domain,
|
||||
GIC_LOCAL_TO_HWIRQ(intr));
|
||||
if (chained)
|
||||
generic_handle_irq(virq);
|
||||
generic_handle_domain_irq(gic_irq_domain,
|
||||
GIC_LOCAL_TO_HWIRQ(intr));
|
||||
else
|
||||
do_IRQ(virq);
|
||||
do_IRQ(irq_find_mapping(gic_irq_domain,
|
||||
GIC_LOCAL_TO_HWIRQ(intr)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ static void ocelot_irq_handler(struct irq_desc *desc)
|
|||
while (reg) {
|
||||
u32 hwirq = __fls(reg);
|
||||
|
||||
generic_handle_irq(irq_find_mapping(d, hwirq));
|
||||
generic_handle_domain_irq(d, hwirq);
|
||||
reg &= ~(BIT(hwirq));
|
||||
}
|
||||
|
||||
|
|
|
@ -91,15 +91,12 @@ static void mvebu_pic_handle_cascade_irq(struct irq_desc *desc)
|
|||
struct mvebu_pic *pic = irq_desc_get_handler_data(desc);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
unsigned long irqmap, irqn;
|
||||
unsigned int cascade_irq;
|
||||
|
||||
irqmap = readl_relaxed(pic->base + PIC_CAUSE);
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
for_each_set_bit(irqn, &irqmap, BITS_PER_LONG) {
|
||||
cascade_irq = irq_find_mapping(pic->domain, irqn);
|
||||
generic_handle_irq(cascade_irq);
|
||||
}
|
||||
for_each_set_bit(irqn, &irqmap, BITS_PER_LONG)
|
||||
generic_handle_domain_irq(pic->domain, irqn);
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
|
|
@ -337,17 +337,12 @@ static void mvebu_sei_handle_cascade_irq(struct irq_desc *desc)
|
|||
irqmap = readl_relaxed(sei->base + GICP_SECR(idx));
|
||||
for_each_set_bit(bit, &irqmap, SEI_IRQ_COUNT_PER_REG) {
|
||||
unsigned long hwirq;
|
||||
unsigned int virq;
|
||||
int err;
|
||||
|
||||
hwirq = idx * SEI_IRQ_COUNT_PER_REG + bit;
|
||||
virq = irq_find_mapping(sei->sei_domain, hwirq);
|
||||
if (likely(virq)) {
|
||||
generic_handle_irq(virq);
|
||||
continue;
|
||||
}
|
||||
|
||||
dev_warn(sei->dev,
|
||||
"Spurious IRQ detected (hwirq %lu)\n", hwirq);
|
||||
err = generic_handle_domain_irq(sei->sei_domain, hwirq);
|
||||
if (unlikely(err))
|
||||
dev_warn(sei->dev, "Spurious IRQ detected (hwirq %lu)\n", hwirq);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,9 +40,7 @@ static struct irq_domain *nvic_irq_domain;
|
|||
asmlinkage void __exception_irq_entry
|
||||
nvic_handle_irq(irq_hw_number_t hwirq, struct pt_regs *regs)
|
||||
{
|
||||
unsigned int irq = irq_linear_revmap(nvic_irq_domain, hwirq);
|
||||
|
||||
handle_IRQ(irq, regs);
|
||||
handle_domain_irq(nvic_irq_domain, hwirq, regs);
|
||||
}
|
||||
|
||||
static int nvic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
|
||||
|
|
|
@ -117,7 +117,7 @@ static void orion_bridge_irq_handler(struct irq_desc *desc)
|
|||
while (stat) {
|
||||
u32 hwirq = __fls(stat);
|
||||
|
||||
generic_handle_irq(irq_find_mapping(d, gc->irq_base + hwirq));
|
||||
generic_handle_domain_irq(d, gc->irq_base + hwirq);
|
||||
stat &= ~(1 << hwirq);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,13 +124,10 @@ static void partition_handle_irq(struct irq_desc *desc)
|
|||
break;
|
||||
}
|
||||
|
||||
if (unlikely(hwirq == part->nr_parts)) {
|
||||
if (unlikely(hwirq == part->nr_parts))
|
||||
handle_bad_irq(desc);
|
||||
} else {
|
||||
unsigned int irq;
|
||||
irq = irq_find_mapping(part->domain, hwirq);
|
||||
generic_handle_irq(irq);
|
||||
}
|
||||
else
|
||||
generic_handle_domain_irq(part->domain, hwirq);
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
|
|
@ -488,8 +488,7 @@ static void pruss_intc_irq_handler(struct irq_desc *desc)
|
|||
|
||||
while (true) {
|
||||
u32 hipir;
|
||||
unsigned int virq;
|
||||
int hwirq;
|
||||
int hwirq, err;
|
||||
|
||||
/* get highest priority pending PRUSS system event */
|
||||
hipir = pruss_intc_read_reg(intc, PRU_INTC_HIPIR(host_irq));
|
||||
|
@ -497,16 +496,14 @@ static void pruss_intc_irq_handler(struct irq_desc *desc)
|
|||
break;
|
||||
|
||||
hwirq = hipir & GENMASK(9, 0);
|
||||
virq = irq_find_mapping(intc->domain, hwirq);
|
||||
err = generic_handle_domain_irq(intc->domain, hwirq);
|
||||
|
||||
/*
|
||||
* NOTE: manually ACK any system events that do not have a
|
||||
* handler mapped yet
|
||||
*/
|
||||
if (WARN_ON_ONCE(!virq))
|
||||
if (WARN_ON_ONCE(err))
|
||||
pruss_intc_write_reg(intc, PRU_INTC_SICR, hwirq);
|
||||
else
|
||||
generic_handle_irq(virq);
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
|
|
|
@ -85,7 +85,7 @@ static void realtek_irq_dispatch(struct irq_desc *desc)
|
|||
goto out;
|
||||
}
|
||||
domain = irq_desc_get_handler_data(desc);
|
||||
generic_handle_irq(irq_find_mapping(domain, __ffs(pending)));
|
||||
generic_handle_domain_irq(domain, __ffs(pending));
|
||||
|
||||
out:
|
||||
chained_irq_exit(chip, desc);
|
||||
|
|
|
@ -115,7 +115,7 @@ static irqreturn_t irqc_irq_handler(int irq, void *dev_id)
|
|||
if (ioread32(p->iomem + DETECT_STATUS) & bit) {
|
||||
iowrite32(bit, p->iomem + DETECT_STATUS);
|
||||
irqc_dbg(i, "demux2");
|
||||
generic_handle_irq(irq_find_mapping(p->irq_domain, i->hw_irq));
|
||||
generic_handle_domain_irq(p->irq_domain, i->hw_irq);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
return IRQ_NONE;
|
||||
|
|
|
@ -233,13 +233,11 @@ static void plic_handle_irq(struct irq_desc *desc)
|
|||
chained_irq_enter(chip, desc);
|
||||
|
||||
while ((hwirq = readl(claim))) {
|
||||
int irq = irq_find_mapping(handler->priv->irqdomain, hwirq);
|
||||
|
||||
if (unlikely(irq <= 0))
|
||||
int err = generic_handle_domain_irq(handler->priv->irqdomain,
|
||||
hwirq);
|
||||
if (unlikely(err))
|
||||
pr_warn_ratelimited("can't find mapping for hwirq %lu\n",
|
||||
hwirq);
|
||||
else
|
||||
generic_handle_irq(irq);
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
|
|
|
@ -257,7 +257,7 @@ static void stm32_irq_handler(struct irq_desc *desc)
|
|||
{
|
||||
struct irq_domain *domain = irq_desc_get_handler_data(desc);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
unsigned int virq, nbanks = domain->gc->num_chips;
|
||||
unsigned int nbanks = domain->gc->num_chips;
|
||||
struct irq_chip_generic *gc;
|
||||
unsigned long pending;
|
||||
int n, i, irq_base = 0;
|
||||
|
@ -268,11 +268,9 @@ static void stm32_irq_handler(struct irq_desc *desc)
|
|||
gc = irq_get_domain_generic_chip(domain, irq_base);
|
||||
|
||||
while ((pending = stm32_exti_pending(gc))) {
|
||||
for_each_set_bit(n, &pending, IRQS_PER_BANK) {
|
||||
virq = irq_find_mapping(domain, irq_base + n);
|
||||
generic_handle_irq(virq);
|
||||
}
|
||||
}
|
||||
for_each_set_bit(n, &pending, IRQS_PER_BANK)
|
||||
generic_handle_domain_irq(domain, irq_base + n);
|
||||
}
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
|
|
|
@ -88,10 +88,9 @@ static void sunxi_sc_nmi_handle_irq(struct irq_desc *desc)
|
|||
{
|
||||
struct irq_domain *domain = irq_desc_get_handler_data(desc);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
unsigned int virq = irq_find_mapping(domain, 0);
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
generic_handle_irq(virq);
|
||||
generic_handle_domain_irq(domain, 0);
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ static void tb10x_irq_cascade(struct irq_desc *desc)
|
|||
struct irq_domain *domain = irq_desc_get_handler_data(desc);
|
||||
unsigned int irq = irq_desc_get_irq(desc);
|
||||
|
||||
generic_handle_irq(irq_find_mapping(domain, irq));
|
||||
generic_handle_domain_irq(domain, irq);
|
||||
}
|
||||
|
||||
static int __init of_tb10x_init_irq(struct device_node *ictl,
|
||||
|
|
|
@ -147,7 +147,7 @@ static void ti_sci_inta_irq_handler(struct irq_desc *desc)
|
|||
struct ti_sci_inta_vint_desc *vint_desc;
|
||||
struct ti_sci_inta_irq_domain *inta;
|
||||
struct irq_domain *domain;
|
||||
unsigned int virq, bit;
|
||||
unsigned int bit;
|
||||
unsigned long val;
|
||||
|
||||
vint_desc = irq_desc_get_handler_data(desc);
|
||||
|
@ -159,11 +159,8 @@ static void ti_sci_inta_irq_handler(struct irq_desc *desc)
|
|||
val = readq_relaxed(inta->base + vint_desc->vint_id * 0x1000 +
|
||||
VINT_STATUS_MASKED_OFFSET);
|
||||
|
||||
for_each_set_bit(bit, &val, MAX_EVENTS_PER_VINT) {
|
||||
virq = irq_find_mapping(domain, vint_desc->events[bit].hwirq);
|
||||
if (virq)
|
||||
generic_handle_irq(virq);
|
||||
}
|
||||
for_each_set_bit(bit, &val, MAX_EVENTS_PER_VINT)
|
||||
generic_handle_domain_irq(domain, vint_desc->events[bit].hwirq);
|
||||
|
||||
chained_irq_exit(irq_desc_get_chip(desc), desc);
|
||||
}
|
||||
|
|
|
@ -79,10 +79,9 @@ static void ts4800_ic_chained_handle_irq(struct irq_desc *desc)
|
|||
|
||||
do {
|
||||
unsigned int bit = __ffs(status);
|
||||
int irq = irq_find_mapping(data->domain, bit);
|
||||
|
||||
generic_handle_domain_irq(data->domain, bit);
|
||||
status &= ~(1 << bit);
|
||||
generic_handle_irq(irq);
|
||||
} while (status);
|
||||
|
||||
out:
|
||||
|
|
|
@ -85,7 +85,7 @@ static void fpga_irq_handle(struct irq_desc *desc)
|
|||
unsigned int irq = ffs(status) - 1;
|
||||
|
||||
status &= ~(1 << irq);
|
||||
generic_handle_irq(irq_find_mapping(f->domain, irq));
|
||||
generic_handle_domain_irq(f->domain, irq);
|
||||
} while (status);
|
||||
|
||||
out:
|
||||
|
|
|
@ -225,7 +225,7 @@ static void vic_handle_irq_cascaded(struct irq_desc *desc)
|
|||
|
||||
while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
|
||||
hwirq = ffs(stat) - 1;
|
||||
generic_handle_irq(irq_find_mapping(vic->domain, hwirq));
|
||||
generic_handle_domain_irq(vic->domain, hwirq);
|
||||
}
|
||||
|
||||
chained_irq_exit(host_chip, desc);
|
||||
|
|
|
@ -110,20 +110,6 @@ static struct irq_chip intc_dev = {
|
|||
.irq_mask_ack = intc_mask_ack,
|
||||
};
|
||||
|
||||
static unsigned int xintc_get_irq_local(struct xintc_irq_chip *irqc)
|
||||
{
|
||||
unsigned int irq = 0;
|
||||
u32 hwirq;
|
||||
|
||||
hwirq = xintc_read(irqc, IVR);
|
||||
if (hwirq != -1U)
|
||||
irq = irq_find_mapping(irqc->root_domain, hwirq);
|
||||
|
||||
pr_debug("irq-xilinx: hwirq=%d, irq=%d\n", hwirq, irq);
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
unsigned int xintc_get_irq(void)
|
||||
{
|
||||
unsigned int irq = -1;
|
||||
|
@ -164,15 +150,16 @@ static void xil_intc_irq_handler(struct irq_desc *desc)
|
|||
{
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct xintc_irq_chip *irqc;
|
||||
u32 pending;
|
||||
|
||||
irqc = irq_data_get_irq_handler_data(&desc->irq_data);
|
||||
chained_irq_enter(chip, desc);
|
||||
do {
|
||||
pending = xintc_get_irq_local(irqc);
|
||||
if (pending == 0)
|
||||
u32 hwirq = xintc_read(irqc, IVR);
|
||||
|
||||
if (hwirq == -1U)
|
||||
break;
|
||||
generic_handle_irq(pending);
|
||||
|
||||
generic_handle_domain_irq(irqc->root_domain, hwirq);
|
||||
} while (true);
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@ static void combiner_handle_irq(struct irq_desc *desc)
|
|||
chained_irq_enter(chip, desc);
|
||||
|
||||
for (reg = 0; reg < combiner->nregs; reg++) {
|
||||
int virq;
|
||||
int hwirq;
|
||||
u32 bit;
|
||||
u32 status;
|
||||
|
@ -70,10 +69,7 @@ static void combiner_handle_irq(struct irq_desc *desc)
|
|||
bit = __ffs(status);
|
||||
status &= ~(1 << bit);
|
||||
hwirq = irq_nr(reg, bit);
|
||||
virq = irq_find_mapping(combiner->domain, hwirq);
|
||||
if (virq > 0)
|
||||
generic_handle_irq(virq);
|
||||
|
||||
generic_handle_domain_irq(combiner->domain, hwirq);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/dmapool.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/list.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <target/target_core_base.h>
|
||||
#include <target/target_core_fabric.h>
|
||||
|
|
|
@ -50,8 +50,10 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/usb/hcd.h>
|
||||
#include <linux/prefetch.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/octeon/octeon.h>
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/uasm.h>
|
||||
|
|
|
@ -158,25 +158,21 @@ static inline void generic_handle_irq_desc(struct irq_desc *desc)
|
|||
desc->handle_irq(desc);
|
||||
}
|
||||
|
||||
int handle_irq_desc(struct irq_desc *desc);
|
||||
int generic_handle_irq(unsigned int irq);
|
||||
|
||||
#ifdef CONFIG_HANDLE_DOMAIN_IRQ
|
||||
#ifdef CONFIG_IRQ_DOMAIN
|
||||
/*
|
||||
* Convert a HW interrupt number to a logical one using a IRQ domain,
|
||||
* and handle the result interrupt number. Return -EINVAL if
|
||||
* conversion failed. Providing a NULL domain indicates that the
|
||||
* conversion has already been done.
|
||||
* conversion failed.
|
||||
*/
|
||||
int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,
|
||||
bool lookup, struct pt_regs *regs);
|
||||
int generic_handle_domain_irq(struct irq_domain *domain, unsigned int hwirq);
|
||||
|
||||
static inline int handle_domain_irq(struct irq_domain *domain,
|
||||
unsigned int hwirq, struct pt_regs *regs)
|
||||
{
|
||||
return __handle_domain_irq(domain, hwirq, true, regs);
|
||||
}
|
||||
#ifdef CONFIG_HANDLE_DOMAIN_IRQ
|
||||
int handle_domain_irq(struct irq_domain *domain,
|
||||
unsigned int hwirq, struct pt_regs *regs);
|
||||
|
||||
#ifdef CONFIG_IRQ_DOMAIN
|
||||
int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq,
|
||||
struct pt_regs *regs);
|
||||
#endif
|
||||
|
|
|
@ -41,13 +41,11 @@ struct fwnode_handle;
|
|||
struct irq_domain;
|
||||
struct irq_chip;
|
||||
struct irq_data;
|
||||
struct irq_desc;
|
||||
struct cpumask;
|
||||
struct seq_file;
|
||||
struct irq_affinity_desc;
|
||||
|
||||
/* Number of irqs reserved for a legacy isa controller */
|
||||
#define NUM_ISA_INTERRUPTS 16
|
||||
|
||||
#define IRQ_DOMAIN_IRQ_SPEC_PARAMS 16
|
||||
|
||||
/**
|
||||
|
@ -152,11 +150,10 @@ struct irq_domain_chip_generic;
|
|||
* @parent: Pointer to parent irq_domain to support hierarchy irq_domains
|
||||
*
|
||||
* Revmap data, used internally by irq_domain
|
||||
* @revmap_direct_max_irq: The largest hwirq that can be set for controllers that
|
||||
* support direct mapping
|
||||
* @revmap_size: Size of the linear map table @linear_revmap[]
|
||||
* @revmap_size: Size of the linear map table @revmap[]
|
||||
* @revmap_tree: Radix map tree for hwirqs that don't fit in the linear map
|
||||
* @linear_revmap: Linear table of hwirq->virq reverse mappings
|
||||
* @revmap_mutex: Lock for the revmap
|
||||
* @revmap: Linear table of irq_data pointers
|
||||
*/
|
||||
struct irq_domain {
|
||||
struct list_head link;
|
||||
|
@ -176,11 +173,10 @@ struct irq_domain {
|
|||
|
||||
/* reverse map data. The linear map gets appended to the irq_domain */
|
||||
irq_hw_number_t hwirq_max;
|
||||
unsigned int revmap_direct_max_irq;
|
||||
unsigned int revmap_size;
|
||||
struct radix_tree_root revmap_tree;
|
||||
struct mutex revmap_tree_mutex;
|
||||
unsigned int linear_revmap[];
|
||||
struct mutex revmap_mutex;
|
||||
struct irq_data __rcu *revmap[];
|
||||
};
|
||||
|
||||
/* Irq domain flags */
|
||||
|
@ -210,6 +206,9 @@ enum {
|
|||
*/
|
||||
IRQ_DOMAIN_MSI_NOMASK_QUIRK = (1 << 6),
|
||||
|
||||
/* Irq domain doesn't translate anything */
|
||||
IRQ_DOMAIN_FLAG_NO_MAP = (1 << 7),
|
||||
|
||||
/*
|
||||
* Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved
|
||||
* for implementation specific purposes and ignored by the
|
||||
|
@ -348,6 +347,8 @@ static inline struct irq_domain *irq_domain_add_linear(struct device_node *of_no
|
|||
{
|
||||
return __irq_domain_add(of_node_to_fwnode(of_node), size, size, 0, ops, host_data);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IRQ_DOMAIN_NOMAP
|
||||
static inline struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
|
||||
unsigned int max_irq,
|
||||
const struct irq_domain_ops *ops,
|
||||
|
@ -355,14 +356,10 @@ static inline struct irq_domain *irq_domain_add_nomap(struct device_node *of_nod
|
|||
{
|
||||
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,
|
||||
const struct irq_domain_ops *ops,
|
||||
void *host_data)
|
||||
{
|
||||
return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS, 0, 0, ops,
|
||||
host_data);
|
||||
}
|
||||
|
||||
extern unsigned int irq_create_direct_mapping(struct irq_domain *host);
|
||||
#endif
|
||||
|
||||
static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
|
||||
const struct irq_domain_ops *ops,
|
||||
void *host_data)
|
||||
|
@ -405,25 +402,37 @@ static inline unsigned int irq_create_mapping(struct irq_domain *host,
|
|||
return irq_create_mapping_affinity(host, hwirq, NULL);
|
||||
}
|
||||
|
||||
extern struct irq_desc *__irq_resolve_mapping(struct irq_domain *domain,
|
||||
irq_hw_number_t hwirq,
|
||||
unsigned int *irq);
|
||||
|
||||
static inline struct irq_desc *irq_resolve_mapping(struct irq_domain *domain,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
return __irq_resolve_mapping(domain, hwirq, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* irq_linear_revmap() - Find a linux irq from a hw irq number.
|
||||
* irq_find_mapping() - Find a linux irq from a hw irq number.
|
||||
* @domain: domain owning this hardware interrupt
|
||||
* @hwirq: hardware irq number in that domain space
|
||||
*
|
||||
* This is a fast path alternative to irq_find_mapping() that can be
|
||||
* called directly by irq controller code to save a handful of
|
||||
* instructions. It is always safe to call, but won't find irqs mapped
|
||||
* using the radix tree.
|
||||
*/
|
||||
static inline unsigned int irq_find_mapping(struct irq_domain *domain,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
unsigned int irq;
|
||||
|
||||
if (__irq_resolve_mapping(domain, hwirq, &irq))
|
||||
return irq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int irq_linear_revmap(struct irq_domain *domain,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
return hwirq < domain->revmap_size ? domain->linear_revmap[hwirq] : 0;
|
||||
return irq_find_mapping(domain, hwirq);
|
||||
}
|
||||
extern unsigned int irq_find_mapping(struct irq_domain *host,
|
||||
irq_hw_number_t hwirq);
|
||||
extern unsigned int irq_create_direct_mapping(struct irq_domain *host);
|
||||
|
||||
extern const struct irq_domain_ops irq_domain_simple_ops;
|
||||
|
||||
|
|
|
@ -70,6 +70,11 @@ config IRQ_DOMAIN_HIERARCHY
|
|||
bool
|
||||
select IRQ_DOMAIN
|
||||
|
||||
# Support for obsolete non-mapping irq domains
|
||||
config IRQ_DOMAIN_NOMAP
|
||||
bool
|
||||
select IRQ_DOMAIN
|
||||
|
||||
# Support for hierarchical fasteoi+edge and fasteoi+level handlers
|
||||
config IRQ_FASTEOI_HIERARCHY_HANDLERS
|
||||
bool
|
||||
|
|
|
@ -632,14 +632,8 @@ void irq_init_desc(unsigned int irq)
|
|||
|
||||
#endif /* !CONFIG_SPARSE_IRQ */
|
||||
|
||||
/**
|
||||
* generic_handle_irq - Invoke the handler for a particular irq
|
||||
* @irq: The irq number to handle
|
||||
*
|
||||
*/
|
||||
int generic_handle_irq(unsigned int irq)
|
||||
int handle_irq_desc(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
struct irq_data *data;
|
||||
|
||||
if (!desc)
|
||||
|
@ -652,11 +646,40 @@ int generic_handle_irq(unsigned int irq)
|
|||
generic_handle_irq_desc(desc);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(handle_irq_desc);
|
||||
|
||||
/**
|
||||
* generic_handle_irq - Invoke the handler for a particular irq
|
||||
* @irq: The irq number to handle
|
||||
*
|
||||
*/
|
||||
int generic_handle_irq(unsigned int irq)
|
||||
{
|
||||
return handle_irq_desc(irq_to_desc(irq));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(generic_handle_irq);
|
||||
|
||||
#ifdef CONFIG_IRQ_DOMAIN
|
||||
/**
|
||||
* generic_handle_domain_irq - Invoke the handler for a HW irq belonging
|
||||
* to a domain, usually for a non-root interrupt
|
||||
* controller
|
||||
* @domain: The domain where to perform the lookup
|
||||
* @hwirq: The HW irq number to convert to a logical one
|
||||
*
|
||||
* Returns: 0 on success, or -EINVAL if conversion has failed
|
||||
*
|
||||
*/
|
||||
int generic_handle_domain_irq(struct irq_domain *domain, unsigned int hwirq)
|
||||
{
|
||||
return handle_irq_desc(irq_resolve_mapping(domain, hwirq));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(generic_handle_domain_irq);
|
||||
|
||||
#ifdef CONFIG_HANDLE_DOMAIN_IRQ
|
||||
/**
|
||||
* __handle_domain_irq - Invoke the handler for a HW irq belonging to a domain
|
||||
* handle_domain_irq - Invoke the handler for a HW irq belonging to a domain,
|
||||
* usually for a root interrupt controller
|
||||
* @domain: The domain where to perform the lookup
|
||||
* @hwirq: The HW irq number to convert to a logical one
|
||||
* @lookup: Whether to perform the domain lookup or not
|
||||
|
@ -664,37 +687,27 @@ EXPORT_SYMBOL_GPL(generic_handle_irq);
|
|||
*
|
||||
* Returns: 0 on success, or -EINVAL if conversion has failed
|
||||
*/
|
||||
int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,
|
||||
bool lookup, struct pt_regs *regs)
|
||||
int handle_domain_irq(struct irq_domain *domain,
|
||||
unsigned int hwirq, struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
unsigned int irq = hwirq;
|
||||
struct irq_desc *desc;
|
||||
int ret = 0;
|
||||
|
||||
irq_enter();
|
||||
|
||||
#ifdef CONFIG_IRQ_DOMAIN
|
||||
if (lookup)
|
||||
irq = irq_find_mapping(domain, hwirq);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some hardware gives randomly wrong interrupts. Rather
|
||||
* than crashing, do something sensible.
|
||||
*/
|
||||
if (unlikely(!irq || irq >= nr_irqs)) {
|
||||
ack_bad_irq(irq);
|
||||
/* The irqdomain code provides boundary checks */
|
||||
desc = irq_resolve_mapping(domain, hwirq);
|
||||
if (likely(desc))
|
||||
handle_irq_desc(desc);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
generic_handle_irq(irq);
|
||||
}
|
||||
|
||||
irq_exit();
|
||||
set_irq_regs(old_regs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IRQ_DOMAIN
|
||||
/**
|
||||
* handle_domain_nmi - Invoke the handler for a HW irq belonging to a domain
|
||||
* @domain: The domain where to perform the lookup
|
||||
|
@ -709,7 +722,7 @@ int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq,
|
|||
struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
unsigned int irq;
|
||||
struct irq_desc *desc;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
|
@ -717,14 +730,14 @@ int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq,
|
|||
*/
|
||||
WARN_ON(!in_nmi());
|
||||
|
||||
irq = irq_find_mapping(domain, hwirq);
|
||||
desc = irq_resolve_mapping(domain, hwirq);
|
||||
|
||||
/*
|
||||
* ack_bad_irq is not NMI-safe, just report
|
||||
* an invalid interrupt.
|
||||
*/
|
||||
if (likely(irq))
|
||||
generic_handle_irq(irq);
|
||||
if (likely(desc))
|
||||
handle_irq_desc(desc);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
|
|
|
@ -146,7 +146,11 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
|
|||
|
||||
static atomic_t unknown_domains;
|
||||
|
||||
domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
|
||||
if (WARN_ON((size && direct_max) ||
|
||||
(!IS_ENABLED(CONFIG_IRQ_DOMAIN_NOMAP) && direct_max)))
|
||||
return NULL;
|
||||
|
||||
domain = kzalloc_node(struct_size(domain, revmap, size),
|
||||
GFP_KERNEL, of_node_to_nid(to_of_node(fwnode)));
|
||||
if (!domain)
|
||||
return NULL;
|
||||
|
@ -209,12 +213,18 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
|
|||
|
||||
/* Fill structure */
|
||||
INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL);
|
||||
mutex_init(&domain->revmap_tree_mutex);
|
||||
mutex_init(&domain->revmap_mutex);
|
||||
domain->ops = ops;
|
||||
domain->host_data = host_data;
|
||||
domain->hwirq_max = hwirq_max;
|
||||
|
||||
if (direct_max) {
|
||||
size = direct_max;
|
||||
domain->flags |= IRQ_DOMAIN_FLAG_NO_MAP;
|
||||
}
|
||||
|
||||
domain->revmap_size = size;
|
||||
domain->revmap_direct_max_irq = direct_max;
|
||||
|
||||
irq_domain_check_hierarchy(domain);
|
||||
|
||||
mutex_lock(&irq_domain_mutex);
|
||||
|
@ -482,29 +492,39 @@ struct irq_domain *irq_get_default_host(void)
|
|||
return irq_default_domain;
|
||||
}
|
||||
|
||||
static bool irq_domain_is_nomap(struct irq_domain *domain)
|
||||
{
|
||||
return IS_ENABLED(CONFIG_IRQ_DOMAIN_NOMAP) &&
|
||||
(domain->flags & IRQ_DOMAIN_FLAG_NO_MAP);
|
||||
}
|
||||
|
||||
static void irq_domain_clear_mapping(struct irq_domain *domain,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
if (hwirq < domain->revmap_size) {
|
||||
domain->linear_revmap[hwirq] = 0;
|
||||
} else {
|
||||
mutex_lock(&domain->revmap_tree_mutex);
|
||||
if (irq_domain_is_nomap(domain))
|
||||
return;
|
||||
|
||||
mutex_lock(&domain->revmap_mutex);
|
||||
if (hwirq < domain->revmap_size)
|
||||
rcu_assign_pointer(domain->revmap[hwirq], NULL);
|
||||
else
|
||||
radix_tree_delete(&domain->revmap_tree, hwirq);
|
||||
mutex_unlock(&domain->revmap_tree_mutex);
|
||||
}
|
||||
mutex_unlock(&domain->revmap_mutex);
|
||||
}
|
||||
|
||||
static void irq_domain_set_mapping(struct irq_domain *domain,
|
||||
irq_hw_number_t hwirq,
|
||||
struct irq_data *irq_data)
|
||||
{
|
||||
if (hwirq < domain->revmap_size) {
|
||||
domain->linear_revmap[hwirq] = irq_data->irq;
|
||||
} else {
|
||||
mutex_lock(&domain->revmap_tree_mutex);
|
||||
if (irq_domain_is_nomap(domain))
|
||||
return;
|
||||
|
||||
mutex_lock(&domain->revmap_mutex);
|
||||
if (hwirq < domain->revmap_size)
|
||||
rcu_assign_pointer(domain->revmap[hwirq], irq_data);
|
||||
else
|
||||
radix_tree_insert(&domain->revmap_tree, hwirq, irq_data);
|
||||
mutex_unlock(&domain->revmap_tree_mutex);
|
||||
}
|
||||
mutex_unlock(&domain->revmap_mutex);
|
||||
}
|
||||
|
||||
static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
|
||||
|
@ -604,6 +624,7 @@ void irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(irq_domain_associate_many);
|
||||
|
||||
#ifdef CONFIG_IRQ_DOMAIN_NOMAP
|
||||
/**
|
||||
* irq_create_direct_mapping() - Allocate an irq for direct mapping
|
||||
* @domain: domain to allocate the irq for or NULL for default domain
|
||||
|
@ -628,9 +649,9 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
|
|||
pr_debug("create_direct virq allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
if (virq >= domain->revmap_direct_max_irq) {
|
||||
if (virq >= domain->revmap_size) {
|
||||
pr_err("ERROR: no free irqs available below %i maximum\n",
|
||||
domain->revmap_direct_max_irq);
|
||||
domain->revmap_size);
|
||||
irq_free_desc(virq);
|
||||
return 0;
|
||||
}
|
||||
|
@ -644,6 +665,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
|
|||
return virq;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* irq_create_mapping_affinity() - Map a hardware interrupt into linux irq space
|
||||
|
@ -862,37 +884,53 @@ void irq_dispose_mapping(unsigned int virq)
|
|||
EXPORT_SYMBOL_GPL(irq_dispose_mapping);
|
||||
|
||||
/**
|
||||
* irq_find_mapping() - Find a linux irq from a hw irq number.
|
||||
* __irq_resolve_mapping() - Find a linux irq from a hw irq number.
|
||||
* @domain: domain owning this hardware interrupt
|
||||
* @hwirq: hardware irq number in that domain space
|
||||
* @irq: optional pointer to return the Linux irq if required
|
||||
*
|
||||
* Returns the interrupt descriptor.
|
||||
*/
|
||||
unsigned int irq_find_mapping(struct irq_domain *domain,
|
||||
irq_hw_number_t hwirq)
|
||||
struct irq_desc *__irq_resolve_mapping(struct irq_domain *domain,
|
||||
irq_hw_number_t hwirq,
|
||||
unsigned int *irq)
|
||||
{
|
||||
struct irq_desc *desc = NULL;
|
||||
struct irq_data *data;
|
||||
|
||||
/* Look for default domain if necessary */
|
||||
if (domain == NULL)
|
||||
domain = irq_default_domain;
|
||||
if (domain == NULL)
|
||||
return 0;
|
||||
return desc;
|
||||
|
||||
if (hwirq < domain->revmap_direct_max_irq) {
|
||||
data = irq_domain_get_irq_data(domain, hwirq);
|
||||
if (data && data->hwirq == hwirq)
|
||||
return hwirq;
|
||||
if (irq_domain_is_nomap(domain)) {
|
||||
if (hwirq < domain->revmap_size) {
|
||||
data = irq_domain_get_irq_data(domain, hwirq);
|
||||
if (data && data->hwirq == hwirq)
|
||||
desc = irq_data_to_desc(data);
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
/* Check if the hwirq is in the linear revmap. */
|
||||
if (hwirq < domain->revmap_size)
|
||||
return domain->linear_revmap[hwirq];
|
||||
data = rcu_dereference(domain->revmap[hwirq]);
|
||||
else
|
||||
data = radix_tree_lookup(&domain->revmap_tree, hwirq);
|
||||
|
||||
if (likely(data)) {
|
||||
desc = irq_data_to_desc(data);
|
||||
if (irq)
|
||||
*irq = data->irq;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
data = radix_tree_lookup(&domain->revmap_tree, hwirq);
|
||||
rcu_read_unlock();
|
||||
return data ? data->irq : 0;
|
||||
return desc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(irq_find_mapping);
|
||||
EXPORT_SYMBOL_GPL(__irq_resolve_mapping);
|
||||
|
||||
/**
|
||||
* irq_domain_xlate_onecell() - Generic xlate for direct one cell bindings
|
||||
|
@ -1468,15 +1506,20 @@ static void irq_domain_fix_revmap(struct irq_data *d)
|
|||
{
|
||||
void __rcu **slot;
|
||||
|
||||
if (d->hwirq < d->domain->revmap_size)
|
||||
return; /* Not using radix tree. */
|
||||
if (irq_domain_is_nomap(d->domain))
|
||||
return;
|
||||
|
||||
/* Fix up the revmap. */
|
||||
mutex_lock(&d->domain->revmap_tree_mutex);
|
||||
slot = radix_tree_lookup_slot(&d->domain->revmap_tree, d->hwirq);
|
||||
if (slot)
|
||||
radix_tree_replace_slot(&d->domain->revmap_tree, slot, d);
|
||||
mutex_unlock(&d->domain->revmap_tree_mutex);
|
||||
mutex_lock(&d->domain->revmap_mutex);
|
||||
if (d->hwirq < d->domain->revmap_size) {
|
||||
/* Not using radix tree */
|
||||
rcu_assign_pointer(d->domain->revmap[d->hwirq], d);
|
||||
} else {
|
||||
slot = radix_tree_lookup_slot(&d->domain->revmap_tree, d->hwirq);
|
||||
if (slot)
|
||||
radix_tree_replace_slot(&d->domain->revmap_tree, slot, d);
|
||||
}
|
||||
mutex_unlock(&d->domain->revmap_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1828,8 +1871,7 @@ static void
|
|||
irq_domain_debug_show_one(struct seq_file *m, struct irq_domain *d, int ind)
|
||||
{
|
||||
seq_printf(m, "%*sname: %s\n", ind, "", d->name);
|
||||
seq_printf(m, "%*ssize: %u\n", ind + 1, "",
|
||||
d->revmap_size + d->revmap_direct_max_irq);
|
||||
seq_printf(m, "%*ssize: %u\n", ind + 1, "", d->revmap_size);
|
||||
seq_printf(m, "%*smapped: %u\n", ind + 1, "", d->mapcount);
|
||||
seq_printf(m, "%*sflags: 0x%08x\n", ind +1 , "", d->flags);
|
||||
if (d->ops && d->ops->debug_show)
|
||||
|
|
Загрузка…
Ссылка в новой задаче