diff options
-rw-r--r-- | include/linux/irq.h | 8 | ||||
-rw-r--r-- | kernel/irq/chip.c | 58 |
2 files changed, 66 insertions, 0 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h index 8649b0fb9daf..c2a0c1929690 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -279,6 +279,8 @@ static inline bool irqd_irq_disabled(struct irq_data *d) | |||
279 | * @irq_set_wake: enable/disable power-management wake-on of an IRQ | 279 | * @irq_set_wake: enable/disable power-management wake-on of an IRQ |
280 | * @irq_bus_lock: function to lock access to slow bus (i2c) chips | 280 | * @irq_bus_lock: function to lock access to slow bus (i2c) chips |
281 | * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips | 281 | * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips |
282 | * @irq_cpu_online: configure an interrupt source for a secondary CPU | ||
283 | * @irq_cpu_offline: un-configure an interrupt source for a secondary CPU | ||
282 | * @irq_print_chip: optional to print special chip info in show_interrupts | 284 | * @irq_print_chip: optional to print special chip info in show_interrupts |
283 | * @flags: chip specific flags | 285 | * @flags: chip specific flags |
284 | * | 286 | * |
@@ -327,6 +329,9 @@ struct irq_chip { | |||
327 | void (*irq_bus_lock)(struct irq_data *data); | 329 | void (*irq_bus_lock)(struct irq_data *data); |
328 | void (*irq_bus_sync_unlock)(struct irq_data *data); | 330 | void (*irq_bus_sync_unlock)(struct irq_data *data); |
329 | 331 | ||
332 | void (*irq_cpu_online)(struct irq_data *data); | ||
333 | void (*irq_cpu_offline)(struct irq_data *data); | ||
334 | |||
330 | void (*irq_print_chip)(struct irq_data *data, struct seq_file *p); | 335 | void (*irq_print_chip)(struct irq_data *data, struct seq_file *p); |
331 | 336 | ||
332 | unsigned long flags; | 337 | unsigned long flags; |
@@ -372,6 +377,9 @@ struct irqaction; | |||
372 | extern int setup_irq(unsigned int irq, struct irqaction *new); | 377 | extern int setup_irq(unsigned int irq, struct irqaction *new); |
373 | extern void remove_irq(unsigned int irq, struct irqaction *act); | 378 | extern void remove_irq(unsigned int irq, struct irqaction *act); |
374 | 379 | ||
380 | extern void irq_cpu_online(void); | ||
381 | extern void irq_cpu_offline(void); | ||
382 | |||
375 | #ifdef CONFIG_GENERIC_HARDIRQS | 383 | #ifdef CONFIG_GENERIC_HARDIRQS |
376 | 384 | ||
377 | #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ) | 385 | #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ) |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 0a890bdd9c63..44b16a1ecd9a 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -696,3 +696,61 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) | |||
696 | 696 | ||
697 | irq_put_desc_unlock(desc, flags); | 697 | irq_put_desc_unlock(desc, flags); |
698 | } | 698 | } |
699 | |||
700 | /** | ||
701 | * irq_cpu_online - Invoke all irq_cpu_online functions. | ||
702 | * | ||
703 | * Iterate through all irqs and invoke the chip.irq_cpu_online() | ||
704 | * for each. | ||
705 | */ | ||
706 | void irq_cpu_online(void) | ||
707 | { | ||
708 | struct irq_desc *desc; | ||
709 | struct irq_chip *chip; | ||
710 | unsigned long flags; | ||
711 | unsigned int irq; | ||
712 | |||
713 | for_each_active_irq(irq) { | ||
714 | desc = irq_to_desc(irq); | ||
715 | if (!desc) | ||
716 | continue; | ||
717 | |||
718 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
719 | |||
720 | chip = irq_data_get_irq_chip(&desc->irq_data); | ||
721 | |||
722 | if (chip && chip->irq_cpu_online) | ||
723 | chip->irq_cpu_online(&desc->irq_data); | ||
724 | |||
725 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
726 | } | ||
727 | } | ||
728 | |||
729 | /** | ||
730 | * irq_cpu_offline - Invoke all irq_cpu_offline functions. | ||
731 | * | ||
732 | * Iterate through all irqs and invoke the chip.irq_cpu_offline() | ||
733 | * for each. | ||
734 | */ | ||
735 | void irq_cpu_offline(void) | ||
736 | { | ||
737 | struct irq_desc *desc; | ||
738 | struct irq_chip *chip; | ||
739 | unsigned long flags; | ||
740 | unsigned int irq; | ||
741 | |||
742 | for_each_active_irq(irq) { | ||
743 | desc = irq_to_desc(irq); | ||
744 | if (!desc) | ||
745 | continue; | ||
746 | |||
747 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
748 | |||
749 | chip = irq_data_get_irq_chip(&desc->irq_data); | ||
750 | |||
751 | if (chip && chip->irq_cpu_offline) | ||
752 | chip->irq_cpu_offline(&desc->irq_data); | ||
753 | |||
754 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
755 | } | ||
756 | } | ||