[GIT PULL] IRQ fixes

From: Ingo Molnar
Date: Sun Jan 31 2016 - 04:02:01 EST


Linus,

Please pull the latest irq-urgent-for-linus git tree from:

git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq-urgent-for-linus

# HEAD: c5b635203032462603c503ecce91a7021c1ad44a irqchip/mxs: Add missing set_handle_irq()

Mostly driver fixes, but also an irq core crash fix and a build fix.

Thanks,

Ingo

------------------>
Arnd Bergmann (1):
irqchip/s3c24xx: Mark init_eint as __maybe_unused

Marc Zyngier (3):
irqdomain: Allow domain lookup with DOMAIN_BUS_WIRED token
of: MSI: Simplify irqdomain lookup
irqchip/gic-v3-its: Recompute the number of pages on page size change

Milo Kim (1):
irqchip/atmel-aic: Fix wrong bit operation for IRQ priority

Oleksij Rempel (1):
irqchip/mxs: Add missing set_handle_irq()

Richard Weinberger (1):
irqchip: Fix dependencies for archs w/o HAS_IOMEM

Thomas Gleixner (1):
genirq: Validate action before dereferencing it in handle_irq_event_percpu()

Thomas Petazzoni (1):
base: Export platform_msi_domain_[alloc,free]_irqs


drivers/base/platform-msi.c | 2 ++
drivers/irqchip/Kconfig | 1 +
drivers/irqchip/irq-atmel-aic-common.c | 2 +-
drivers/irqchip/irq-gic-v3-its.c | 8 ++++++--
drivers/irqchip/irq-mxs.c | 1 +
drivers/irqchip/irq-s3c24xx.c | 2 +-
drivers/of/irq.c | 18 +++---------------
include/linux/irqdomain.h | 1 +
kernel/irq/handle.c | 5 +++--
kernel/irq/irqdomain.c | 11 ++++++++---
10 files changed, 27 insertions(+), 24 deletions(-)

diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
index 47c43386786b..279e53989374 100644
--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -284,6 +284,7 @@ int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,

return err;
}
+EXPORT_SYMBOL_GPL(platform_msi_domain_alloc_irqs);

/**
* platform_msi_domain_free_irqs - Free MSI interrupts for @dev
@@ -301,6 +302,7 @@ void platform_msi_domain_free_irqs(struct device *dev)
msi_domain_free_irqs(dev->msi_domain, dev);
platform_msi_free_descs(dev, 0, MAX_DEV_MSIS);
}
+EXPORT_SYMBOL_GPL(platform_msi_domain_free_irqs);

/**
* platform_msi_get_host_data - Query the private data associated with
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 11fc2a27fa2e..90ab59107830 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -154,6 +154,7 @@ config TB10X_IRQC
config TS4800_IRQ
tristate "TS-4800 IRQ controller"
select IRQ_DOMAIN
+ depends on HAS_IOMEM
help
Support for the TS-4800 FPGA IRQ controller

diff --git a/drivers/irqchip/irq-atmel-aic-common.c b/drivers/irqchip/irq-atmel-aic-common.c
index b12a5d58546f..37199b9b2cfa 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -86,7 +86,7 @@ int aic_common_set_priority(int priority, unsigned *val)
priority > AT91_AIC_IRQ_MAX_PRIORITY)
return -EINVAL;

- *val &= AT91_AIC_PRIOR;
+ *val &= ~AT91_AIC_PRIOR;
*val |= priority;

return 0;
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index e23d1d18f9d6..3447549fcc93 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -875,6 +875,7 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
}

alloc_size = (1 << order) * PAGE_SIZE;
+retry_alloc_baser:
alloc_pages = (alloc_size / psz);
if (alloc_pages > GITS_BASER_PAGES_MAX) {
alloc_pages = GITS_BASER_PAGES_MAX;
@@ -938,13 +939,16 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
* size and retry. If we reach 4K, then
* something is horribly wrong...
*/
+ free_pages((unsigned long)base, order);
+ its->tables[i] = NULL;
+
switch (psz) {
case SZ_16K:
psz = SZ_4K;
- goto retry_baser;
+ goto retry_alloc_baser;
case SZ_64K:
psz = SZ_16K;
- goto retry_baser;
+ goto retry_alloc_baser;
}
}

diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
index c22e2d40cb30..efe50845939d 100644
--- a/drivers/irqchip/irq-mxs.c
+++ b/drivers/irqchip/irq-mxs.c
@@ -241,6 +241,7 @@ static int __init asm9260_of_init(struct device_node *np,
writel(0, icoll_priv.intr + i);

icoll_add_domain(np, ASM9260_NUM_IRQS);
+ set_handle_irq(icoll_handle_irq);

return 0;
}
diff --git a/drivers/irqchip/irq-s3c24xx.c b/drivers/irqchip/irq-s3c24xx.c
index c71914e8f596..5dc5a760c723 100644
--- a/drivers/irqchip/irq-s3c24xx.c
+++ b/drivers/irqchip/irq-s3c24xx.c
@@ -605,7 +605,7 @@ static struct s3c_irq_intc * __init s3c24xx_init_intc(struct device_node *np,
return ERR_PTR(ret);
}

-static struct s3c_irq_data init_eint[32] = {
+static struct s3c_irq_data __maybe_unused init_eint[32] = {
{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 4fa916dffc91..a9ea5525109b 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -680,18 +680,6 @@ u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in)
return __of_msi_map_rid(dev, &msi_np, rid_in);
}

-static struct irq_domain *__of_get_msi_domain(struct device_node *np,
- enum irq_domain_bus_token token)
-{
- struct irq_domain *d;
-
- d = irq_find_matching_host(np, token);
- if (!d)
- d = irq_find_host(np);
-
- return d;
-}
-
/**
* of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain
* @dev: device for which the mapping is to be done.
@@ -707,7 +695,7 @@ struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 rid)
struct device_node *np = NULL;

__of_msi_map_rid(dev, &np, rid);
- return __of_get_msi_domain(np, DOMAIN_BUS_PCI_MSI);
+ return irq_find_matching_host(np, DOMAIN_BUS_PCI_MSI);
}

/**
@@ -731,7 +719,7 @@ struct irq_domain *of_msi_get_domain(struct device *dev,
/* Check for a single msi-parent property */
msi_np = of_parse_phandle(np, "msi-parent", 0);
if (msi_np && !of_property_read_bool(msi_np, "#msi-cells")) {
- d = __of_get_msi_domain(msi_np, token);
+ d = irq_find_matching_host(msi_np, token);
if (!d)
of_node_put(msi_np);
return d;
@@ -745,7 +733,7 @@ struct irq_domain *of_msi_get_domain(struct device *dev,
while (!of_parse_phandle_with_args(np, "msi-parent",
"#msi-cells",
index, &args)) {
- d = __of_get_msi_domain(args.np, token);
+ d = irq_find_matching_host(args.np, token);
if (d)
return d;

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index f64622ad02c1..04579d9fbce4 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -70,6 +70,7 @@ struct irq_fwspec {
*/
enum irq_domain_bus_token {
DOMAIN_BUS_ANY = 0,
+ DOMAIN_BUS_WIRED,
DOMAIN_BUS_PCI_MSI,
DOMAIN_BUS_PLATFORM_MSI,
DOMAIN_BUS_NEXUS,
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index a302cf9a2126..57bff7857e87 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -138,7 +138,8 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
unsigned int flags = 0, irq = desc->irq_data.irq;
struct irqaction *action = desc->action;

- do {
+ /* action might have become NULL since we dropped the lock */
+ while (action) {
irqreturn_t res;

trace_irq_handler_entry(irq, action);
@@ -173,7 +174,7 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)

retval |= res;
action = action->next;
- } while (action);
+ }

add_interrupt_randomness(irq, flags);

diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 8cf95de1ab3f..d75179735a28 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -575,10 +575,15 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
unsigned int type = IRQ_TYPE_NONE;
int virq;

- if (fwspec->fwnode)
- domain = irq_find_matching_fwnode(fwspec->fwnode, DOMAIN_BUS_ANY);
- else
+ if (fwspec->fwnode) {
+ domain = irq_find_matching_fwnode(fwspec->fwnode,
+ DOMAIN_BUS_WIRED);
+ if (!domain)
+ domain = irq_find_matching_fwnode(fwspec->fwnode,
+ DOMAIN_BUS_ANY);
+ } else {
domain = irq_default_domain;
+ }

if (!domain) {
pr_warn("no irq domain found for %s !\n",