diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-22 19:42:56 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-22 19:42:56 -0700 | 
| commit | 407a2c720556e8e340e06f6a7174f5d6d80cf9ea (patch) | |
| tree | b78ba543dbef195909611448ca833348581b63a6 /kernel/irq/chip.c | |
| parent | 3a95398f54cbd664c749fe9f1bfc7e7dbace92d0 (diff) | |
| parent | f05218651be1ac6a6088e226bd7350fb6c154414 (diff) | |
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/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
  ...
Diffstat (limited to 'kernel/irq/chip.c')
| -rw-r--r-- | kernel/irq/chip.c | 73 | 
1 files changed, 62 insertions, 11 deletions
| diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 55016b2151f3..27f4332c7f84 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -719,15 +719,9 @@ void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc)  }  void -__irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, -		  const char *name) +__irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, +		     int is_chained, const char *name)  { -	unsigned long flags; -	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0); - -	if (!desc) -		return; -  	if (!handle) {  		handle = handle_bad_irq;  	} else { @@ -749,13 +743,13 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,  			 * right away.  			 */  			if (WARN_ON(is_chained)) -				goto out; +				return;  			/* Try the parent */  			irq_data = irq_data->parent_data;  		}  #endif  		if (WARN_ON(!irq_data || irq_data->chip == &no_irq_chip)) -			goto out; +			return;  	}  	/* Uninstall? */ @@ -774,12 +768,41 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,  		irq_settings_set_nothread(desc);  		irq_startup(desc, true);  	} -out: +} + +void +__irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, +		  const char *name) +{ +	unsigned long flags; +	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0); + +	if (!desc) +		return; + +	__irq_do_set_handler(desc, handle, is_chained, name);  	irq_put_desc_busunlock(desc, flags);  }  EXPORT_SYMBOL_GPL(__irq_set_handler);  void +irq_set_chained_handler_and_data(unsigned int irq, irq_flow_handler_t handle, +				 void *data) +{ +	unsigned long flags; +	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0); + +	if (!desc) +		return; + +	__irq_do_set_handler(desc, handle, 1, NULL); +	desc->irq_data.handler_data = data; + +	irq_put_desc_busunlock(desc, flags); +} +EXPORT_SYMBOL_GPL(irq_set_chained_handler_and_data); + +void  irq_set_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,  			      irq_flow_handler_t handle, const char *name)  { @@ -876,6 +899,34 @@ void irq_cpu_offline(void)  #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY  /** + * irq_chip_enable_parent - Enable the parent interrupt (defaults to unmask if + * NULL) + * @data:	Pointer to interrupt specific data + */ +void irq_chip_enable_parent(struct irq_data *data) +{ +	data = data->parent_data; +	if (data->chip->irq_enable) +		data->chip->irq_enable(data); +	else +		data->chip->irq_unmask(data); +} + +/** + * irq_chip_disable_parent - Disable the parent interrupt (defaults to mask if + * NULL) + * @data:	Pointer to interrupt specific data + */ +void irq_chip_disable_parent(struct irq_data *data) +{ +	data = data->parent_data; +	if (data->chip->irq_disable) +		data->chip->irq_disable(data); +	else +		data->chip->irq_mask(data); +} + +/**   * irq_chip_ack_parent - Acknowledge the parent interrupt   * @data:	Pointer to interrupt specific data   */ | 
