Skip to content

Commit

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

Pull irq fixes from Thomas Gleixner:
 "This contains:

   - a series of fixes for interrupt drivers to prevent a potential race
     when installing a chained interrupt handler

   - a fix for cpumask pointer misuse

   - a fix for using the wrong interrupt number from struct irq_data

   - removal of unused code and outdated comments

   - a few new helper functions which allow us to cleanup the interrupt
     handling code further in 4.3

   I decided against doing the cleanup at the end of this merge window
   and rather do the preparatory steps for 4.3, so we can run the final
   ABI change at the end of the 4.3 merge window with less risk"

* 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (26 commits)
  ARM/LPC32xx: Use irq not hwirq for __irq_set_handler_locked()
  genirq: Implement irq_set_handler_locked()/irq_set_chip_handler_name_locked()
  genirq: Introduce helper irq_desc_get_irq()
  genirq: Remove irq_node()
  genirq: Clean up outdated comments related to include/linux/irqdesc.h
  mn10300: Fix incorrect use of irq_data->affinity
  MIPS/ralink: Fix race in installing chained IRQ handler
  MIPS/pci: Fix race in installing chained IRQ handler
  MIPS/ath25: Fix race in installing chained IRQ handler
  MIPS/ath25: Fix race in installing chained IRQ handler
  m68k/psc: Fix race in installing chained IRQ handler
  avr32/at32ap: Fix race in installing chained IRQ handler
  sh/intc: Fix race in installing chained IRQ handler
  sh/intc: Fix potential race in installing chained IRQ handler
  pinctrl/sun4i: Fix race in installing chained IRQ handler
  pinctrl/samsung: Fix race in installing chained IRQ handler
  pinctrl/samsung: Fix race in installing chained IRQ handler
  pinctrl/exynos: Fix race in installing chained IRQ handler
  pinctrl/st: Fix race in installing chained IRQ handler
  pinctrl/adi2: Fix race in installing chained IRQ handler
  ...
  • Loading branch information
torvalds committed Jul 1, 2015
2 parents 8fff775 + 93b6eb7 commit d5fb821
Show file tree
Hide file tree
Showing 25 changed files with 95 additions and 67 deletions.
8 changes: 4 additions & 4 deletions arch/arm/mach-lpc32xx/irq.c
Expand Up @@ -283,25 +283,25 @@ static int lpc32xx_set_irq_type(struct irq_data *d, unsigned int type)
case IRQ_TYPE_EDGE_RISING:
/* Rising edge sensitive */
__lpc32xx_set_irq_type(d->hwirq, 1, 1);
__irq_set_handler_locked(d->hwirq, handle_edge_irq);
__irq_set_handler_locked(d->irq, handle_edge_irq);
break;

case IRQ_TYPE_EDGE_FALLING:
/* Falling edge sensitive */
__lpc32xx_set_irq_type(d->hwirq, 0, 1);
__irq_set_handler_locked(d->hwirq, handle_edge_irq);
__irq_set_handler_locked(d->irq, handle_edge_irq);
break;

case IRQ_TYPE_LEVEL_LOW:
/* Low level sensitive */
__lpc32xx_set_irq_type(d->hwirq, 0, 0);
__irq_set_handler_locked(d->hwirq, handle_level_irq);
__irq_set_handler_locked(d->irq, handle_level_irq);
break;

case IRQ_TYPE_LEVEL_HIGH:
/* High level sensitive */
__lpc32xx_set_irq_type(d->hwirq, 1, 0);
__irq_set_handler_locked(d->hwirq, handle_level_irq);
__irq_set_handler_locked(d->irq, handle_level_irq);
break;

/* Other modes are not supported */
Expand Down
3 changes: 1 addition & 2 deletions arch/avr32/mach-at32ap/extint.c
Expand Up @@ -231,8 +231,7 @@ static int __init eic_probe(struct platform_device *pdev)
irq_set_chip_data(eic->first_irq + i, eic);
}

irq_set_chained_handler(int_irq, demux_eic_irq);
irq_set_handler_data(int_irq, eic);
irq_set_chained_handler_and_data(int_irq, demux_eic_irq, eic);

if (pdev->id == 0) {
nmi_eic = eic;
Expand Down
12 changes: 4 additions & 8 deletions arch/m68k/mac/psc.c
Expand Up @@ -148,14 +148,10 @@ static void psc_irq(unsigned int irq, struct irq_desc *desc)

void __init psc_register_interrupts(void)
{
irq_set_chained_handler(IRQ_AUTO_3, psc_irq);
irq_set_handler_data(IRQ_AUTO_3, (void *)0x30);
irq_set_chained_handler(IRQ_AUTO_4, psc_irq);
irq_set_handler_data(IRQ_AUTO_4, (void *)0x40);
irq_set_chained_handler(IRQ_AUTO_5, psc_irq);
irq_set_handler_data(IRQ_AUTO_5, (void *)0x50);
irq_set_chained_handler(IRQ_AUTO_6, psc_irq);
irq_set_handler_data(IRQ_AUTO_6, (void *)0x60);
irq_set_chained_handler_and_data(IRQ_AUTO_3, psc_irq, (void *)0x30);
irq_set_chained_handler_and_data(IRQ_AUTO_4, psc_irq, (void *)0x40);
irq_set_chained_handler_and_data(IRQ_AUTO_5, psc_irq, (void *)0x50);
irq_set_chained_handler_and_data(IRQ_AUTO_6, psc_irq, (void *)0x60);
}

void psc_irq_enable(int irq) {
Expand Down
4 changes: 2 additions & 2 deletions arch/mips/ath25/ar2315.c
Expand Up @@ -161,8 +161,8 @@ void __init ar2315_arch_init_irq(void)
irq = irq_create_mapping(domain, AR2315_MISC_IRQ_AHB);
setup_irq(irq, &ar2315_ahb_err_interrupt);

irq_set_chained_handler(AR2315_IRQ_MISC, ar2315_misc_irq_handler);
irq_set_handler_data(AR2315_IRQ_MISC, domain);
irq_set_chained_handler_and_data(AR2315_IRQ_MISC,
ar2315_misc_irq_handler, domain);

ar2315_misc_irq_domain = domain;
}
Expand Down
4 changes: 2 additions & 2 deletions arch/mips/ath25/ar5312.c
Expand Up @@ -156,8 +156,8 @@ void __init ar5312_arch_init_irq(void)
irq = irq_create_mapping(domain, AR5312_MISC_IRQ_AHB_PROC);
setup_irq(irq, &ar5312_ahb_err_interrupt);

irq_set_chained_handler(AR5312_IRQ_MISC, ar5312_misc_irq_handler);
irq_set_handler_data(AR5312_IRQ_MISC, domain);
irq_set_chained_handler_and_data(AR5312_IRQ_MISC,
ar5312_misc_irq_handler, domain);

ar5312_misc_irq_domain = domain;
}
Expand Down
4 changes: 2 additions & 2 deletions arch/mips/pci/pci-ar2315.c
Expand Up @@ -384,8 +384,8 @@ static void ar2315_pci_irq_init(struct ar2315_pci_ctrl *apc)

apc->irq_ext = irq_create_mapping(apc->domain, AR2315_PCI_IRQ_EXT);

irq_set_chained_handler(apc->irq, ar2315_pci_irq_handler);
irq_set_handler_data(apc->irq, apc);
irq_set_chained_handler_and_data(apc->irq, ar2315_pci_irq_handler,
apc);

/* Clear any pending Abort or external Interrupts
* and enable interrupt processing */
Expand Down
3 changes: 1 addition & 2 deletions arch/mips/ralink/irq.c
Expand Up @@ -184,8 +184,7 @@ static int __init intc_of_init(struct device_node *node,

rt_intc_w32(INTC_INT_GLOBAL, INTC_REG_ENABLE);

irq_set_chained_handler(irq, ralink_intc_irq_handler);
irq_set_handler_data(irq, domain);
irq_set_chained_handler_and_data(irq, ralink_intc_irq_handler, domain);

/* tell the kernel which irq is used for performance monitoring */
rt_perfcount_irq = irq_create_mapping(domain, 9);
Expand Down
6 changes: 3 additions & 3 deletions arch/mn10300/kernel/irq.c
Expand Up @@ -320,11 +320,11 @@ void migrate_irqs(void)
if (irqd_is_per_cpu(data))
continue;

if (cpumask_test_cpu(self, &data->affinity) &&
if (cpumask_test_cpu(self, data->affinity) &&
!cpumask_intersects(&irq_affinity[irq], cpu_online_mask)) {
int cpu_id;
cpu_id = cpumask_first(cpu_online_mask);
cpumask_set_cpu(cpu_id, &data->affinity);
cpumask_set_cpu(cpu_id, data->affinity);
}
/* We need to operate irq_affinity_online atomically. */
arch_local_cli_save(flags);
Expand All @@ -335,7 +335,7 @@ void migrate_irqs(void)
GxICR(irq) = x & GxICR_LEVEL;
tmp = GxICR(irq);

new = cpumask_any_and(&data->affinity,
new = cpumask_any_and(data->affinity,
cpu_online_mask);
irq_affinity_online[irq] = new;

Expand Down
5 changes: 3 additions & 2 deletions drivers/gpio/gpio-bcm-kona.c
Expand Up @@ -657,8 +657,9 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev)
}
for (i = 0; i < kona_gpio->num_bank; i++) {
bank = &kona_gpio->banks[i];
irq_set_chained_handler(bank->irq, bcm_kona_gpio_irq_handler);
irq_set_handler_data(bank->irq, bank);
irq_set_chained_handler_and_data(bank->irq,
bcm_kona_gpio_irq_handler,
bank);
}

spin_lock_init(&kona_gpio->lock);
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpio/gpio-dwapb.c
Expand Up @@ -348,8 +348,8 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
irq_gc->chip_types[1].handler = handle_edge_irq;

if (!pp->irq_shared) {
irq_set_chained_handler(pp->irq, dwapb_irq_handler);
irq_set_handler_data(pp->irq, gpio);
irq_set_chained_handler_and_data(pp->irq, dwapb_irq_handler,
gpio);
} else {
/*
* Request a shared IRQ since where MFD would have devices
Expand Down
3 changes: 1 addition & 2 deletions drivers/gpio/gpio-msic.c
Expand Up @@ -309,8 +309,7 @@ static int platform_msic_gpio_probe(struct platform_device *pdev)
&msic_irqchip,
handle_simple_irq);
}
irq_set_chained_handler(mg->irq, msic_gpio_irq_handler);
irq_set_handler_data(mg->irq, mg);
irq_set_chained_handler_and_data(mg->irq, msic_gpio_irq_handler, mg);

return 0;
err:
Expand Down
3 changes: 1 addition & 2 deletions drivers/mfd/asic3.c
Expand Up @@ -417,9 +417,8 @@ static int __init asic3_irq_probe(struct platform_device *pdev)
asic3_write_register(asic, ASIC3_OFFSET(INTR, INT_MASK),
ASIC3_INTMASK_GINTMASK);

irq_set_chained_handler(asic->irq_nr, asic3_irq_demux);
irq_set_chained_handler_and_data(asic->irq_nr, asic3_irq_demux, asic);
irq_set_irq_type(asic->irq_nr, IRQ_TYPE_EDGE_RISING);
irq_set_handler_data(asic->irq_nr, asic);

return 0;
}
Expand Down
7 changes: 3 additions & 4 deletions drivers/pci/host/pci-keystone.c
Expand Up @@ -221,10 +221,9 @@ static void ks_pcie_setup_interrupts(struct keystone_pcie *ks_pcie)
/* MSI IRQ */
if (IS_ENABLED(CONFIG_PCI_MSI)) {
for (i = 0; i < ks_pcie->num_msi_host_irqs; i++) {
irq_set_chained_handler(ks_pcie->msi_host_irqs[i],
ks_pcie_msi_irq_handler);
irq_set_handler_data(ks_pcie->msi_host_irqs[i],
ks_pcie);
irq_set_chained_handler_and_data(ks_pcie->msi_host_irqs[i],
ks_pcie_msi_irq_handler,
ks_pcie);
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions drivers/pinctrl/mediatek/pinctrl-mtk-common.c
Expand Up @@ -1351,8 +1351,7 @@ int mtk_pctrl_init(struct platform_device *pdev,
set_irq_flags(virq, IRQF_VALID);
};

irq_set_chained_handler(irq, mtk_eint_irq_handler);
irq_set_handler_data(irq, pctl);
irq_set_chained_handler_and_data(irq, mtk_eint_irq_handler, pctl);
set_irq_flags(irq, IRQF_VALID);
return 0;

Expand Down
4 changes: 2 additions & 2 deletions drivers/pinctrl/pinctrl-adi2.c
Expand Up @@ -865,8 +865,8 @@ static int adi_gpio_pint_probe(struct platform_device *pdev)
pint->pint_map_port = adi_pint_map_port;
platform_set_drvdata(pdev, pint);

irq_set_chained_handler(pint->irq, adi_gpio_handle_pint_irq);
irq_set_handler_data(pint->irq, pint);
irq_set_chained_handler_and_data(pint->irq, adi_gpio_handle_pint_irq,
pint);

list_add_tail(&pint->node, &adi_pint_list);

Expand Down
4 changes: 2 additions & 2 deletions drivers/pinctrl/pinctrl-st.c
Expand Up @@ -1661,8 +1661,8 @@ static int st_pctl_probe_dt(struct platform_device *pdev,
if (IS_ERR(info->irqmux_base))
return PTR_ERR(info->irqmux_base);

irq_set_chained_handler(irq, st_gpio_irqmux_handler);
irq_set_handler_data(irq, info);
irq_set_chained_handler_and_data(irq, st_gpio_irqmux_handler,
info);

}

Expand Down
4 changes: 2 additions & 2 deletions drivers/pinctrl/samsung/pinctrl-exynos.c
Expand Up @@ -563,8 +563,8 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
return -ENOMEM;
}

irq_set_chained_handler(irq, exynos_irq_demux_eint16_31);
irq_set_handler_data(irq, muxed_data);
irq_set_chained_handler_and_data(irq, exynos_irq_demux_eint16_31,
muxed_data);

bank = d->pin_banks;
idx = 0;
Expand Down
3 changes: 1 addition & 2 deletions drivers/pinctrl/samsung/pinctrl-s3c24xx.c
Expand Up @@ -514,8 +514,7 @@ static int s3c24xx_eint_init(struct samsung_pinctrl_drv_data *d)
}

eint_data->parents[i] = irq;
irq_set_chained_handler(irq, handlers[i]);
irq_set_handler_data(irq, eint_data);
irq_set_chained_handler_and_data(irq, handlers[i], eint_data);
}

bank = d->pin_banks;
Expand Down
8 changes: 4 additions & 4 deletions drivers/pinctrl/samsung/pinctrl-s3c64xx.c
Expand Up @@ -506,8 +506,7 @@ static int s3c64xx_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
data->domains[nr_domains++] = bank->irq_domain;
}

irq_set_chained_handler(d->irq, s3c64xx_eint_gpio_irq);
irq_set_handler_data(d->irq, data);
irq_set_chained_handler_and_data(d->irq, s3c64xx_eint_gpio_irq, data);

return 0;
}
Expand Down Expand Up @@ -731,8 +730,9 @@ static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d)
return -ENXIO;
}

irq_set_chained_handler(irq, s3c64xx_eint0_handlers[i]);
irq_set_handler_data(irq, data);
irq_set_chained_handler_and_data(irq,
s3c64xx_eint0_handlers[i],
data);
}

bank = d->pin_banks;
Expand Down
6 changes: 3 additions & 3 deletions drivers/pinctrl/sunxi/pinctrl-sunxi.c
Expand Up @@ -1005,9 +1005,9 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
writel(0xffffffff,
pctl->membase + sunxi_irq_status_reg_from_bank(i));

irq_set_chained_handler(pctl->irq[i],
sunxi_pinctrl_irq_handler);
irq_set_handler_data(pctl->irq[i], pctl);
irq_set_chained_handler_and_data(pctl->irq[i],
sunxi_pinctrl_irq_handler,
pctl);
}

dev_info(&pdev->dev, "initialized sunXi PIO driver\n");
Expand Down
5 changes: 3 additions & 2 deletions drivers/sh/intc/core.c
Expand Up @@ -366,8 +366,9 @@ int __init register_intc_controller(struct intc_desc *desc)

/* redirect this interrupts to the first one */
irq_set_chip(irq2, &dummy_irq_chip);
irq_set_chained_handler(irq2, intc_redirect_irq);
irq_set_handler_data(irq2, (void *)irq);
irq_set_chained_handler_and_data(irq2,
intc_redirect_irq,
(void *)irq);
}
}

Expand Down
3 changes: 2 additions & 1 deletion drivers/sh/intc/virq.c
Expand Up @@ -243,8 +243,9 @@ static void __init intc_subgroup_map(struct intc_desc_int *d)
*/
irq_set_nothread(irq);

irq_set_chained_handler(entry->pirq, intc_virq_handler);
/* Set handler data before installing the handler */
add_virq_to_pirq(entry->pirq, irq);
irq_set_chained_handler(entry->pirq, intc_virq_handler);

radix_tree_tag_clear(&d->tree, entry->enum_id,
INTC_TAG_VIRQ_NEEDS_ALLOC);
Expand Down
1 change: 0 additions & 1 deletion include/linux/irq.h
Expand Up @@ -407,7 +407,6 @@ enum {
IRQCHIP_EOI_THREADED = (1 << 6),
};

/* This include will go away once we isolated irq_desc usage to core code */
#include <linux/irqdesc.h>

/*
Expand Down
49 changes: 46 additions & 3 deletions include/linux/irqdesc.h
Expand Up @@ -3,9 +3,6 @@

/*
* Core internal functions to deal with irq descriptors
*
* This include will move to kernel/irq once we cleaned up the tree.
* For now it's included from <linux/irq.h>
*/

struct irq_affinity_notify;
Expand Down Expand Up @@ -103,6 +100,11 @@ static inline struct irq_desc *irq_data_to_desc(struct irq_data *data)
#endif
}

static inline unsigned int irq_desc_get_irq(struct irq_desc *desc)
{
return desc->irq_data.irq;
}

static inline struct irq_data *irq_desc_get_irq_data(struct irq_desc *desc)
{
return &desc->irq_data;
Expand Down Expand Up @@ -188,6 +190,47 @@ __irq_set_chip_handler_name_locked(unsigned int irq, struct irq_chip *chip,
desc->name = name;
}

/**
* irq_set_handler_locked - Set irq handler from a locked region
* @data: Pointer to the irq_data structure which identifies the irq
* @handler: Flow control handler function for this interrupt
*
* Sets the handler in the irq descriptor associated to @data.
*
* Must be called with irq_desc locked and valid parameters. Typical
* call site is the irq_set_type() callback.
*/
static inline void irq_set_handler_locked(struct irq_data *data,
irq_flow_handler_t handler)
{
struct irq_desc *desc = irq_data_to_desc(data);

desc->handle_irq = handler;
}

/**
* irq_set_chip_handler_name_locked - Set chip, handler and name from a locked region
* @data: Pointer to the irq_data structure for which the chip is set
* @chip: Pointer to the new irq chip
* @handler: Flow control handler function for this interrupt
* @name: Name of the interrupt
*
* Replace the irq chip at the proper hierarchy level in @data and
* sets the handler and name in the associated irq descriptor.
*
* Must be called with irq_desc locked and valid parameters.
*/
static inline void
irq_set_chip_handler_name_locked(struct irq_data *data, struct irq_chip *chip,
irq_flow_handler_t handler, const char *name)
{
struct irq_desc *desc = irq_data_to_desc(data);

desc->handle_irq = handler;
desc->name = name;
data->chip = chip;
}

static inline int irq_balancing_disabled(unsigned int irq)
{
struct irq_desc *desc;
Expand Down
6 changes: 0 additions & 6 deletions include/linux/irqnr.h
Expand Up @@ -23,12 +23,6 @@ unsigned int irq_get_next_irq(unsigned int offset);
; \
else

#ifdef CONFIG_SMP
#define irq_node(irq) (irq_get_irq_data(irq)->node)
#else
#define irq_node(irq) 0
#endif

# define for_each_active_irq(irq) \
for (irq = irq_get_next_irq(0); irq < nr_irqs; \
irq = irq_get_next_irq(irq + 1))
Expand Down

0 comments on commit d5fb821

Please sign in to comment.