mirror of
https://github.com/t2linux/kernel.git
synced 2026-04-30 13:48:59 -07:00
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:
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user