Skip to content

Commit

Permalink
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/tip/tip

Pull irq updates from Thomas Gleixner:
 "The irq departement delivers:

   - plug a potential race related to chained interrupt handlers

   - core updates which address the needs of the x86 irqdomain conversion

   - new irqchip callback to support affinity settings for VCPUs

   - the usual pile of updates to interrupt chip drivers

   - a few helper functions to allow further cleanups and
     simplifications

  I have a largish pile of coccinelle scripted/verified cleanups and
  simplifications pending on top of that, but I prefer to send that
  towards the end of the merge window when the arch/driver changes have
  hit your tree to avoid API change wreckage as far as possible"

* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (34 commits)
  genirq: Remove bogus restriction in irq_move_mask_irq()
  irqchip: atmel-aic5: Add sama5d2 support
  irq: spear-shirq: Fix race in installing chained IRQ handler
  irq: irq-keystone: Fix race in installing chained IRQ handler
  gpio: gpio-tegra: Fix race in installing chained IRQ handler
  gpio: gpio-mxs: Fix race in installing chained IRQ handler
  gpio: gpio-mxc: Fix race in installing chained IRQ handler
  ARM: gemini: Fix race in installing GPIO chained IRQ handler
  GPU: ipu: Fix race in installing IPU chained IRQ handler
  ARM: sa1100: convert SA11x0 related code to use new chained handler helper
  irq: Add irq_set_chained_handler_and_data()
  irqchip: exynos-combiner: Save IRQ enable set on suspend
  genirq: Introduce helper function irq_data_get_affinity_mask()
  genirq: Introduce helper function irq_data_get_node()
  genirq: Introduce struct irq_common_data to host shared irq data
  genirq: Prevent crash in irq_move_irq()
  genirq: Enhance irq_data_to_desc() to support hierarchy irqdomain
  irqchip: gic: Simplify gic_configure_irq by using IRQCHIP_SET_TYPE_MASKED
  irqchip: renesas: intc-irqpin: Improve binding documentation
  genirq: Set IRQCHIP_SKIP_SET_WAKE for no_irq_chip
  ...
  • Loading branch information
Linus Torvalds committed Jun 23, 2015
2 parents 3a95398 + f052186 commit 407a2c7
Show file tree
Hide file tree
Showing 49 changed files with 378 additions and 191 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Required properties:
- compatible: Should be "atmel,<chip>-aic"
<chip> can be "at91rm9200", "sama5d3" or "sama5d4"
<chip> can be "at91rm9200", "sama5d2", "sama5d3" or "sama5d4"
- interrupt-controller: Identifies the node as an interrupt controller.
- interrupt-parent: For single AIC system, it is an empty property.
- #interrupt-cells: The number of cells to define the interrupts. It should be 3.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ Required properties:
- reg: Base address and length of each register bank used by the external
IRQ pins driven by the interrupt controller hardware module. The base
addresses, length and number of required register banks varies with soctype.

- interrupt-controller: Identifies the node as an interrupt controller.
- #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in
interrupts.txt in this directory
interrupts.txt in this directory.
- interrupts: Must contain a list of interrupt specifiers. For each interrupt
provided by this irqpin controller instance, there must be one entry,
referring to the corresponding parent interrupt.

Optional properties:

Expand All @@ -25,3 +28,35 @@ Optional properties:
if different from the default 4 bits
- control-parent: disable and enable interrupts on the parent interrupt
controller, needed for some broken implementations
- clocks: Must contain a reference to the functional clock. This property is
mandatory if the hardware implements a controllable functional clock for
the irqpin controller instance.
- power-domains: Must contain a reference to the power domain. This property is
mandatory if the irqpin controller instance is part of a controllable power
domain.


Example
-------

irqpin1: interrupt-controller@e6900004 {
compatible = "renesas,intc-irqpin-r8a7740",
"renesas,intc-irqpin";
#interrupt-cells = <2>;
interrupt-controller;
reg = <0xe6900004 4>,
<0xe6900014 4>,
<0xe6900024 1>,
<0xe6900044 1>,
<0xe6900064 1>;
interrupts = <0 149 IRQ_TYPE_LEVEL_HIGH
0 149 IRQ_TYPE_LEVEL_HIGH
0 149 IRQ_TYPE_LEVEL_HIGH
0 149 IRQ_TYPE_LEVEL_HIGH
0 149 IRQ_TYPE_LEVEL_HIGH
0 149 IRQ_TYPE_LEVEL_HIGH
0 149 IRQ_TYPE_LEVEL_HIGH
0 149 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp2_clks R8A7740_CLK_INTCA>;
power-domains = <&pd_a4s>;
};
7 changes: 3 additions & 4 deletions arch/arm/common/sa1111.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,8 +501,8 @@ static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base)
* Register SA1111 interrupt
*/
irq_set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING);
irq_set_handler_data(sachip->irq, sachip);
irq_set_chained_handler(sachip->irq, sa1111_irq_handler);
irq_set_chained_handler_and_data(sachip->irq, sa1111_irq_handler,
sachip);

dev_info(sachip->dev, "Providing IRQ%u-%u\n",
sachip->irq_base, sachip->irq_base + SA1111_IRQ_NR - 1);
Expand Down Expand Up @@ -836,8 +836,7 @@ static void __sa1111_remove(struct sa1111 *sachip)
clk_unprepare(sachip->clk);

if (sachip->irq != NO_IRQ) {
irq_set_chained_handler(sachip->irq, NULL);
irq_set_handler_data(sachip->irq, NULL);
irq_set_chained_handler_and_data(sachip->irq, NULL, NULL);
irq_free_descs(sachip->irq_base, SA1111_IRQ_NR);

release_mem_region(sachip->phys + SA1111_INTC, 512);
Expand Down
4 changes: 2 additions & 2 deletions arch/arm/mach-gemini/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,8 @@ void __init gemini_gpio_init(void)
set_irq_flags(j, IRQF_VALID);
}

irq_set_chained_handler(IRQ_GPIO(i), gpio_irq_handler);
irq_set_handler_data(IRQ_GPIO(i), (void *)i);
irq_set_chained_handler_and_data(IRQ_GPIO(i), gpio_irq_handler,
(void *)i);
}

BUG_ON(gpiochip_add(&gemini_gpio_chip));
Expand Down
3 changes: 1 addition & 2 deletions arch/arm/mach-sa1100/neponset.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,7 @@ static int neponset_probe(struct platform_device *dev)
irq_set_chip(d->irq_base + NEP_IRQ_SA1111, &nochip);

irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
irq_set_handler_data(irq, d);
irq_set_chained_handler(irq, neponset_irq_handler);
irq_set_chained_handler_and_data(irq, neponset_irq_handler, d);

/*
* We would set IRQ_GPIO25 to be a wake-up IRQ, but unfortunately
Expand Down
13 changes: 6 additions & 7 deletions drivers/gpio/gpio-mxc.c
Original file line number Diff line number Diff line change
Expand Up @@ -437,14 +437,13 @@ static int mxc_gpio_probe(struct platform_device *pdev)
irq_set_chained_handler(port->irq, mx2_gpio_irq_handler);
} else {
/* setup one handler for each entry */
irq_set_chained_handler(port->irq, mx3_gpio_irq_handler);
irq_set_handler_data(port->irq, port);
if (port->irq_high > 0) {
irq_set_chained_handler_and_data(port->irq,
mx3_gpio_irq_handler, port);
if (port->irq_high > 0)
/* setup handler for GPIO 16 to 31 */
irq_set_chained_handler(port->irq_high,
mx3_gpio_irq_handler);
irq_set_handler_data(port->irq_high, port);
}
irq_set_chained_handler_and_data(port->irq_high,
mx3_gpio_irq_handler,
port);
}

err = bgpio_init(&port->bgc, &pdev->dev, 4,
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpio/gpio-mxs.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,8 +320,8 @@ static int mxs_gpio_probe(struct platform_device *pdev)
mxs_gpio_init_gc(port, irq_base);

/* setup one handler for each entry */
irq_set_chained_handler(port->irq, mxs_gpio_irq_handler);
irq_set_handler_data(port->irq, port);
irq_set_chained_handler_and_data(port->irq, mxs_gpio_irq_handler,
port);

err = bgpio_init(&port->bgc, &pdev->dev, 4,
port->base + PINCTRL_DIN(port),
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpio/gpio-tegra.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,8 +515,8 @@ static int tegra_gpio_probe(struct platform_device *pdev)
for (i = 0; i < tegra_gpio_bank_count; i++) {
bank = &tegra_gpio_banks[i];

irq_set_chained_handler(bank->irq, tegra_gpio_irq_handler);
irq_set_handler_data(bank->irq, bank);
irq_set_chained_handler_and_data(bank->irq,
tegra_gpio_irq_handler, bank);

for (j = 0; j < 4; j++)
spin_lock_init(&bank->lvl_lock[j]);
Expand Down
13 changes: 5 additions & 8 deletions drivers/gpu/ipu-v3/ipu-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1119,10 +1119,9 @@ static int ipu_irq_init(struct ipu_soc *ipu)
ct->regs.mask = IPU_INT_CTRL(i / 32);
}

irq_set_chained_handler(ipu->irq_sync, ipu_irq_handler);
irq_set_handler_data(ipu->irq_sync, ipu);
irq_set_chained_handler(ipu->irq_err, ipu_err_irq_handler);
irq_set_handler_data(ipu->irq_err, ipu);
irq_set_chained_handler_and_data(ipu->irq_sync, ipu_irq_handler, ipu);
irq_set_chained_handler_and_data(ipu->irq_err, ipu_err_irq_handler,
ipu);

return 0;
}
Expand All @@ -1131,10 +1130,8 @@ static void ipu_irq_exit(struct ipu_soc *ipu)
{
int i, irq;

irq_set_chained_handler(ipu->irq_err, NULL);
irq_set_handler_data(ipu->irq_err, NULL);
irq_set_chained_handler(ipu->irq_sync, NULL);
irq_set_handler_data(ipu->irq_sync, NULL);
irq_set_chained_handler_and_data(ipu->irq_err, NULL, NULL);
irq_set_chained_handler_and_data(ipu->irq_sync, NULL, NULL);

/* TODO: remove irq_domain_generic_chips */

Expand Down
1 change: 1 addition & 0 deletions drivers/irqchip/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ config ARM_GIC_V3_ITS
config ARM_NVIC
bool
select IRQ_DOMAIN
select IRQ_DOMAIN_HIERARCHY
select GENERIC_IRQ_CHIP

config ARM_VIC
Expand Down
66 changes: 60 additions & 6 deletions drivers/irqchip/exynos-combiner.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/syscore_ops.h>
#include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/interrupt.h>
Expand All @@ -34,9 +35,14 @@ struct combiner_chip_data {
unsigned int irq_mask;
void __iomem *base;
unsigned int parent_irq;
#ifdef CONFIG_PM
u32 pm_save;
#endif
};

static struct combiner_chip_data *combiner_data;
static struct irq_domain *combiner_irq_domain;
static unsigned int max_nr = 20;

static inline void __iomem *combiner_base(struct irq_data *data)
{
Expand Down Expand Up @@ -164,18 +170,16 @@ static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
return 0;
}

static struct irq_domain_ops combiner_irq_domain_ops = {
static const struct irq_domain_ops combiner_irq_domain_ops = {
.xlate = combiner_irq_domain_xlate,
.map = combiner_irq_domain_map,
};

static void __init combiner_init(void __iomem *combiner_base,
struct device_node *np,
unsigned int max_nr)
struct device_node *np)
{
int i, irq;
unsigned int nr_irq;
struct combiner_chip_data *combiner_data;

nr_irq = max_nr * IRQ_IN_COMBINER;

Expand All @@ -201,11 +205,59 @@ static void __init combiner_init(void __iomem *combiner_base,
}
}

#ifdef CONFIG_PM

/**
* combiner_suspend - save interrupt combiner state before suspend
*
* Save the interrupt enable set register for all combiner groups since
* the state is lost when the system enters into a sleep state.
*
*/
static int combiner_suspend(void)
{
int i;

for (i = 0; i < max_nr; i++)
combiner_data[i].pm_save =
__raw_readl(combiner_data[i].base + COMBINER_ENABLE_SET);

return 0;
}

/**
* combiner_resume - restore interrupt combiner state after resume
*
* Restore the interrupt enable set register for all combiner groups since
* the state is lost when the system enters into a sleep state on suspend.
*
*/
static void combiner_resume(void)
{
int i;

for (i = 0; i < max_nr; i++) {
__raw_writel(combiner_data[i].irq_mask,
combiner_data[i].base + COMBINER_ENABLE_CLEAR);
__raw_writel(combiner_data[i].pm_save,
combiner_data[i].base + COMBINER_ENABLE_SET);
}
}

#else
#define combiner_suspend NULL
#define combiner_resume NULL
#endif

static struct syscore_ops combiner_syscore_ops = {
.suspend = combiner_suspend,
.resume = combiner_resume,
};

static int __init combiner_of_init(struct device_node *np,
struct device_node *parent)
{
void __iomem *combiner_base;
unsigned int max_nr = 20;

combiner_base = of_iomap(np, 0);
if (!combiner_base) {
Expand All @@ -219,7 +271,9 @@ static int __init combiner_of_init(struct device_node *np,
__func__, max_nr);
}

combiner_init(combiner_base, np, max_nr);
combiner_init(combiner_base, np);

register_syscore_ops(&combiner_syscore_ops);

return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/irqchip/irq-armada-370-xp.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ static struct notifier_block mpic_cascaded_cpu_notifier = {
};
#endif /* CONFIG_SMP */

static struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
static const struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
.map = armada_370_xp_mpic_irq_map,
.xlate = irq_domain_xlate_onecell,
};
Expand Down
9 changes: 9 additions & 0 deletions drivers/irqchip/irq-atmel-aic5.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,15 @@ static int __init aic5_of_init(struct device_node *node,
return 0;
}

#define NR_SAMA5D2_IRQS 77

static int __init sama5d2_aic5_of_init(struct device_node *node,
struct device_node *parent)
{
return aic5_of_init(node, parent, NR_SAMA5D2_IRQS);
}
IRQCHIP_DECLARE(sama5d2_aic5, "atmel,sama5d2-aic", sama5d2_aic5_of_init);

#define NR_SAMA5D3_IRQS 48

static int __init sama5d3_aic5_of_init(struct device_node *node,
Expand Down
2 changes: 1 addition & 1 deletion drivers/irqchip/irq-bcm2835.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr,
return 0;
}

static struct irq_domain_ops armctrl_ops = {
static const struct irq_domain_ops armctrl_ops = {
.xlate = armctrl_xlate
};

Expand Down
17 changes: 0 additions & 17 deletions drivers/irqchip/irq-gic-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,8 @@
int gic_configure_irq(unsigned int irq, unsigned int type,
void __iomem *base, void (*sync_access)(void))
{
u32 enablemask = 1 << (irq % 32);
u32 enableoff = (irq / 32) * 4;
u32 confmask = 0x2 << ((irq % 16) * 2);
u32 confoff = (irq / 16) * 4;
bool enabled = false;
u32 val, oldval;
int ret = 0;

Expand All @@ -42,17 +39,6 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
else if (type & IRQ_TYPE_EDGE_BOTH)
val |= confmask;

/*
* As recommended by the spec, disable the interrupt before changing
* the configuration
*/
if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
if (sync_access)
sync_access();
enabled = true;
}

/*
* Write back the new configuration, and possibly re-enable
* the interrupt. If we tried to write a new configuration and failed,
Expand All @@ -62,9 +48,6 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
if (readl_relaxed(base + GIC_DIST_CONFIG + confoff) != val && val != oldval)
ret = -EINVAL;

if (enabled)
writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);

if (sync_access)
sync_access();

Expand Down
1 change: 1 addition & 0 deletions drivers/irqchip/irq-gic-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,7 @@ static struct irq_chip gic_chip = {
.irq_set_affinity = gic_set_affinity,
.irq_get_irqchip_state = gic_irq_get_irqchip_state,
.irq_set_irqchip_state = gic_irq_set_irqchip_state,
.flags = IRQCHIP_SET_TYPE_MASKED,
};

#define GIC_ID_NR (1U << gic_data.rdists.id_bits)
Expand Down
1 change: 1 addition & 0 deletions drivers/irqchip/irq-gic.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ static struct irq_chip gic_chip = {
#endif
.irq_get_irqchip_state = gic_irq_get_irqchip_state,
.irq_set_irqchip_state = gic_irq_set_irqchip_state,
.flags = IRQCHIP_SET_TYPE_MASKED,
};

void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
Expand Down
1 change: 1 addition & 0 deletions drivers/irqchip/irq-hip04.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ static struct irq_chip hip04_irq_chip = {
#ifdef CONFIG_SMP
.irq_set_affinity = hip04_irq_set_affinity,
#endif
.flags = IRQCHIP_SET_TYPE_MASKED,
};

static u16 hip04_get_cpumask(struct hip04_irq_data *intc)
Expand Down
Loading

0 comments on commit 407a2c7

Please sign in to comment.