Merge tag 'irqchip-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/core

Pull irqchip updates from Marc Zyngier:

- API updates:

  - Treewide conversion to generic_handle_domain_irq() for anything
    that looks like a chained interrupt controller

  - Update the irqdomain documentation

  - Use of bitmap_zalloc() throughout the tree

- New functionalities:

  - Support for GICv3 EPPI partitions

- Fixes:

  - Qualcomm PDC hierarchy fixes

  - Yet another priority decoding fix for the GICv3 pseudo-NMIs

  - Fix the apple-aic driver irq_eoi() callback to always unmask
    the interrupt

  - Properly handle edge interrupts on loongson-pch-pic

  - Let the mtk-sysirq driver advertise IRQCHIP_SKIP_SET_WAKE

Link: https://lore.kernel.org/r/20210828121013.2647964-1-maz@kernel.org
This commit is contained in:
Thomas Gleixner
2021-08-29 21:19:50 +02:00
128 changed files with 1488 additions and 1405 deletions
+25 -3
View File
@@ -55,8 +55,24 @@ exist then it will allocate a new Linux irq_desc, associate it with
the hwirq, and call the .map() callback so the driver can perform any
required hardware setup.
When an interrupt is received, irq_find_mapping() function should
be used to find the Linux IRQ number from the hwirq number.
Once a mapping has been established, it can be retrieved or used via a
variety of methods:
- irq_resolve_mapping() returns a pointer to the irq_desc structure
for a given domain and hwirq number, and NULL if there was no
mapping.
- irq_find_mapping() returns a Linux IRQ number for a given domain and
hwirq number, and 0 if there was no mapping
- irq_linear_revmap() is now identical to irq_find_mapping(), and is
deprecated
- generic_handle_domain_irq() handles an interrupt described by a
domain and a hwirq number
- handle_domain_irq() does the same thing for root interrupt
controllers and deals with the set_irq_reg()/irq_enter() sequences
that most architecture requires
Note that irq domain lookups must happen in contexts that are
compatible with a RCU read-side critical section.
The irq_create_mapping() function must be called *atleast once*
before any call to irq_find_mapping(), lest the descriptor will not
@@ -137,7 +153,9 @@ required. Calling irq_create_direct_mapping() will allocate a Linux
IRQ number and call the .map() callback so that driver can program the
Linux IRQ number into the hardware.
Most drivers cannot use this mapping.
Most drivers cannot use this mapping, and it is now gated on the
CONFIG_IRQ_DOMAIN_NOMAP option. Please refrain from introducing new
users of this API.
Legacy
------
@@ -157,6 +175,10 @@ for IRQ numbers that are passed to struct device registrations. In that
case the Linux IRQ numbers cannot be dynamically assigned and the legacy
mapping should be used.
As the name implies, the *_legacy() functions are deprecated and only
exist to ease the support of ancient platforms. No new users should be
added.
The legacy map assumes a contiguous range of IRQ numbers has already
been allocated for the controller and that the IRQ number can be
calculated by adding a fixed offset to the hwirq number, and
@@ -22,7 +22,10 @@ properties:
maxItems: 1
clocks:
maxItems: 1
minItems: 1
items:
- description: APB interface clock source
- description: GPIO debounce reference clock source
gpio-controller: true
+1 -1
View File
@@ -352,7 +352,7 @@ static void idu_cascade_isr(struct irq_desc *desc)
irq_hw_number_t idu_hwirq = core_hwirq - FIRST_EXT_IRQ;
chained_irq_enter(core_chip, desc);
generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
generic_handle_domain_irq(idu_domain, idu_hwirq);
chained_irq_exit(core_chip, desc);
}
+2 -10
View File
@@ -196,14 +196,6 @@ static int sa1111_map_irq(struct sa1111 *sachip, irq_hw_number_t hwirq)
return irq_create_mapping(sachip->irqdomain, hwirq);
}
static void sa1111_handle_irqdomain(struct irq_domain *irqdomain, int irq)
{
struct irq_desc *d = irq_to_desc(irq_linear_revmap(irqdomain, irq));
if (d)
generic_handle_irq_desc(d);
}
/*
* SA1111 interrupt support. Since clearing an IRQ while there are
* active IRQs causes the interrupt output to pulse, the upper levels
@@ -234,11 +226,11 @@ static void sa1111_irq_handler(struct irq_desc *desc)
for (i = 0; stat0; i++, stat0 >>= 1)
if (stat0 & 1)
sa1111_handle_irqdomain(irqdomain, i);
generic_handle_domain_irq(irqdomain, i);
for (i = 32; stat1; i++, stat1 >>= 1)
if (stat1 & 1)
sa1111_handle_irqdomain(irqdomain, i);
generic_handle_domain_irq(irqdomain, i);
/* For level-based interrupts */
desc->irq_data.chip->irq_unmask(&desc->irq_data);
+2 -4
View File
@@ -39,10 +39,8 @@ static irqreturn_t cplds_irq_handler(int in_irq, void *d)
do {
pending = readl(fpga->base + FPGA_IRQ_SET_CLR) & fpga->irq_mask;
for_each_set_bit(bit, &pending, CPLDS_NB_IRQ) {
generic_handle_irq(irq_find_mapping(fpga->irqdomain,
bit));
}
for_each_set_bit(bit, &pending, CPLDS_NB_IRQ)
generic_handle_domain_irq(fpga->irqdomain, bit);
} while (pending);
return IRQ_HANDLED;
+2 -3
View File
@@ -298,7 +298,7 @@ static void s3c_irq_demux(struct irq_desc *desc)
struct s3c_irq_data *irq_data = irq_desc_get_chip_data(desc);
struct s3c_irq_intc *intc = irq_data->intc;
struct s3c_irq_intc *sub_intc = irq_data->sub_intc;
unsigned int n, offset, irq;
unsigned int n, offset;
unsigned long src, msk;
/* we're using individual domains for the non-dt case
@@ -318,8 +318,7 @@ static void s3c_irq_demux(struct irq_desc *desc)
while (src) {
n = __ffs(src);
src &= ~(1 << n);
irq = irq_find_mapping(sub_intc->domain, offset + n);
generic_handle_irq(irq);
generic_handle_domain_irq(sub_intc->domain, offset + n);
}
chained_irq_exit(chip, desc);
+7 -7
View File
@@ -69,24 +69,24 @@ static void ar2315_misc_irq_handler(struct irq_desc *desc)
{
u32 pending = ar2315_rst_reg_read(AR2315_ISR) &
ar2315_rst_reg_read(AR2315_IMR);
unsigned nr, misc_irq = 0;
unsigned nr;
int ret = 0;
if (pending) {
struct irq_domain *domain = irq_desc_get_handler_data(desc);
nr = __ffs(pending);
misc_irq = irq_find_mapping(domain, nr);
}
if (misc_irq) {
if (nr == AR2315_MISC_IRQ_GPIO)
ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_GPIO);
else if (nr == AR2315_MISC_IRQ_WATCHDOG)
ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_WD);
generic_handle_irq(misc_irq);
} else {
spurious_interrupt();
ret = generic_handle_domain_irq(domain, nr);
}
if (!pending || ret)
spurious_interrupt();
}
static void ar2315_misc_irq_unmask(struct irq_data *d)
+6 -7
View File
@@ -73,22 +73,21 @@ static void ar5312_misc_irq_handler(struct irq_desc *desc)
{
u32 pending = ar5312_rst_reg_read(AR5312_ISR) &
ar5312_rst_reg_read(AR5312_IMR);
unsigned nr, misc_irq = 0;
unsigned nr;
int ret = 0;
if (pending) {
struct irq_domain *domain = irq_desc_get_handler_data(desc);
nr = __ffs(pending);
misc_irq = irq_find_mapping(domain, nr);
}
if (misc_irq) {
generic_handle_irq(misc_irq);
ret = generic_handle_domain_irq(domain, nr);
if (nr == AR5312_MISC_IRQ_TIMER)
ar5312_rst_reg_read(AR5312_TIMER);
} else {
spurious_interrupt();
}
if (!pending || ret)
spurious_interrupt();
}
/* Enable the specified AR5312_MISC_IRQ interrupt */
+1 -1
View File
@@ -300,7 +300,7 @@ static void ltq_hw_irq_handler(struct irq_desc *desc)
*/
irq = __fls(irq);
hwirq = irq + MIPS_CPU_IRQ_CASCADE + (INT_NUM_IM_OFFSET * module);
generic_handle_irq(irq_linear_revmap(ltq_domain, hwirq));
generic_handle_domain_irq(ltq_domain, hwirq);
/* if this is a EBU irq, we need to ack it or get a deadlock */
if (irq == LTQ_ICU_EBU_IRQ && !module && LTQ_EBU_PCC_ISTAT != 0)
+3 -5
View File
@@ -337,14 +337,12 @@ static void ar2315_pci_irq_handler(struct irq_desc *desc)
struct ar2315_pci_ctrl *apc = irq_desc_get_handler_data(desc);
u32 pending = ar2315_pci_reg_read(apc, AR2315_PCI_ISR) &
ar2315_pci_reg_read(apc, AR2315_PCI_IMR);
unsigned pci_irq = 0;
int ret = 0;
if (pending)
pci_irq = irq_find_mapping(apc->domain, __ffs(pending));
ret = generic_handle_domain_irq(apc->domain, __ffs(pending));
if (pci_irq)
generic_handle_irq(pci_irq);
else
if (!pending || ret)
spurious_interrupt();
}
+2 -3
View File
@@ -140,10 +140,9 @@ static void rt3883_pci_irq_handler(struct irq_desc *desc)
}
while (pending) {
unsigned irq, bit = __ffs(pending);
unsigned bit = __ffs(pending);
irq = irq_find_mapping(rpc->irq_domain, bit);
generic_handle_irq(irq);
generic_handle_domain_irq(rpc->irq_domain, bit);
pending &= ~BIT(bit);
}
+1 -1
View File
@@ -100,7 +100,7 @@ static void ralink_intc_irq_handler(struct irq_desc *desc)
if (pending) {
struct irq_domain *domain = irq_desc_get_handler_data(desc);
generic_handle_irq(irq_find_mapping(domain, __ffs(pending)));
generic_handle_domain_irq(domain, __ffs(pending));
} else {
spurious_interrupt();
}
+6 -10
View File
@@ -190,7 +190,7 @@ static void ip27_do_irq_mask0(struct irq_desc *desc)
unsigned long *mask = per_cpu(irq_enable_mask, cpu);
struct irq_domain *domain;
u64 pend0;
int irq;
int ret;
/* copied from Irix intpend0() */
pend0 = LOCAL_HUB_L(PI_INT_PEND0);
@@ -216,10 +216,8 @@ static void ip27_do_irq_mask0(struct irq_desc *desc)
#endif
{
domain = irq_desc_get_handler_data(desc);
irq = irq_linear_revmap(domain, __ffs(pend0));
if (irq)
generic_handle_irq(irq);
else
ret = generic_handle_domain_irq(domain, __ffs(pend0));
if (ret)
spurious_interrupt();
}
@@ -232,7 +230,7 @@ static void ip27_do_irq_mask1(struct irq_desc *desc)
unsigned long *mask = per_cpu(irq_enable_mask, cpu);
struct irq_domain *domain;
u64 pend1;
int irq;
int ret;
/* copied from Irix intpend0() */
pend1 = LOCAL_HUB_L(PI_INT_PEND1);
@@ -242,10 +240,8 @@ static void ip27_do_irq_mask1(struct irq_desc *desc)
return;
domain = irq_desc_get_handler_data(desc);
irq = irq_linear_revmap(domain, __ffs(pend1) + 64);
if (irq)
generic_handle_irq(irq);
else
ret = generic_handle_domain_irq(domain, __ffs(pend1) + 64);
if (ret)
spurious_interrupt();
LOCAL_HUB_L(PI_INT_PEND1);
+3 -5
View File
@@ -99,7 +99,7 @@ static void ip30_normal_irq(struct irq_desc *desc)
int cpu = smp_processor_id();
struct irq_domain *domain;
u64 pend, mask;
int irq;
int ret;
pend = heart_read(&heart_regs->isr);
mask = (heart_read(&heart_regs->imr[cpu]) &
@@ -130,10 +130,8 @@ static void ip30_normal_irq(struct irq_desc *desc)
#endif
{
domain = irq_desc_get_handler_data(desc);
irq = irq_linear_revmap(domain, __ffs(pend));
if (irq)
generic_handle_irq(irq);
else
ret = generic_handle_domain_irq(domain, __ffs(pend));
if (ret)
spurious_interrupt();
}
}
+1 -3
View File
@@ -19,11 +19,9 @@ static u32 ienable;
asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
{
struct pt_regs *oldregs = set_irq_regs(regs);
int irq;
irq_enter();
irq = irq_find_mapping(NULL, hwirq);
generic_handle_irq(irq);
generic_handle_domain_irq(NULL, hwirq);
irq_exit();
set_irq_regs(oldregs);
+1 -3
View File
@@ -198,7 +198,6 @@ static void uic_irq_cascade(struct irq_desc *desc)
struct uic *uic = irq_desc_get_handler_data(desc);
u32 msr;
int src;
int subvirq;
raw_spin_lock(&desc->lock);
if (irqd_is_level_type(idata))
@@ -213,8 +212,7 @@ static void uic_irq_cascade(struct irq_desc *desc)
src = 32 - ffs(msr);
subvirq = irq_linear_revmap(uic->irqhost, src);
generic_handle_irq(subvirq);
generic_handle_domain_irq(uic->irqhost, src);
uic_irq_ret:
raw_spin_lock(&desc->lock);
+10 -13
View File
@@ -81,11 +81,10 @@ static struct irq_chip cpld_pic = {
.irq_unmask = cpld_unmask_irq,
};
static int
static unsigned int
cpld_pic_get_irq(int offset, u8 ignore, u8 __iomem *statusp,
u8 __iomem *maskp)
{
int cpld_irq;
u8 status = in_8(statusp);
u8 mask = in_8(maskp);
@@ -93,28 +92,26 @@ cpld_pic_get_irq(int offset, u8 ignore, u8 __iomem *statusp,
status |= (ignore | mask);
if (status == 0xff)
return 0;
return ~0;
cpld_irq = ffz(status) + offset;
return irq_linear_revmap(cpld_pic_host, cpld_irq);
return ffz(status) + offset;
}
static void cpld_pic_cascade(struct irq_desc *desc)
{
unsigned int irq;
unsigned int hwirq;
irq = cpld_pic_get_irq(0, PCI_IGNORE, &cpld_regs->pci_status,
hwirq = cpld_pic_get_irq(0, PCI_IGNORE, &cpld_regs->pci_status,
&cpld_regs->pci_mask);
if (irq) {
generic_handle_irq(irq);
if (hwirq != ~0) {
generic_handle_domain_irq(cpld_pic_host, hwirq);
return;
}
irq = cpld_pic_get_irq(8, MISC_IGNORE, &cpld_regs->misc_status,
hwirq = cpld_pic_get_irq(8, MISC_IGNORE, &cpld_regs->misc_status,
&cpld_regs->misc_mask);
if (irq) {
generic_handle_irq(irq);
if (hwirq != ~0) {
generic_handle_domain_irq(cpld_pic_host, hwirq);
return;
}
}
+4 -5
View File
@@ -78,7 +78,7 @@ static struct irq_chip media5200_irq_chip = {
static void media5200_irq_cascade(struct irq_desc *desc)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
int sub_virq, val;
int val;
u32 status, enable;
/* Mask off the cascaded IRQ */
@@ -92,11 +92,10 @@ static void media5200_irq_cascade(struct irq_desc *desc)
enable = in_be32(media5200_irq.regs + MEDIA5200_IRQ_STATUS);
val = ffs((status & enable) >> MEDIA5200_IRQ_SHIFT);
if (val) {
sub_virq = irq_linear_revmap(media5200_irq.irqhost, val - 1);
/* pr_debug("%s: virq=%i s=%.8x e=%.8x hwirq=%i subvirq=%i\n",
* __func__, virq, status, enable, val - 1, sub_virq);
generic_handle_domain_irq(media5200_irq.irqhost, val - 1);
/* pr_debug("%s: virq=%i s=%.8x e=%.8x hwirq=%i\n",
* __func__, virq, status, enable, val - 1);
*/
generic_handle_irq(sub_virq);
}
/* Processing done; can reenable the cascade now */
+2 -5
View File
@@ -190,14 +190,11 @@ static struct irq_chip mpc52xx_gpt_irq_chip = {
static void mpc52xx_gpt_irq_cascade(struct irq_desc *desc)
{
struct mpc52xx_gpt_priv *gpt = irq_desc_get_handler_data(desc);
int sub_virq;
u32 status;
status = in_be32(&gpt->regs->status) & MPC52xx_GPT_STATUS_IRQMASK;
if (status) {
sub_virq = irq_linear_revmap(gpt->irqhost, 0);
generic_handle_irq(sub_virq);
}
if (status)
generic_handle_domain_irq(gpt->irqhost, 0);
}
static int mpc52xx_gpt_irq_map(struct irq_domain *h, unsigned int virq,
+2 -4
View File
@@ -91,10 +91,8 @@ static void pq2ads_pci_irq_demux(struct irq_desc *desc)
break;
for (bit = 0; pend != 0; ++bit, pend <<= 1) {
if (pend & 0x80000000) {
int virq = irq_linear_revmap(priv->host, bit);
generic_handle_irq(virq);
}
if (pend & 0x80000000)
generic_handle_domain_irq(priv->host, bit);
}
}
}

Some files were not shown because too many files have changed in this diff Show More