genirq: Add sanity checks for PM options on shared interrupt lines
Account the IRQF_NO_SUSPEND and IRQF_RESUME_EARLY actions on shared interrupt lines and yell loudly if there is a mismatch. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Родитель
8df2e02c5c
Коммит
cab303be91
|
@ -36,6 +36,11 @@ struct irq_desc;
|
|||
* @threads_oneshot: bitfield to handle shared oneshot threads
|
||||
* @threads_active: number of irqaction threads currently running
|
||||
* @wait_for_threads: wait queue for sync_irq to wait for threaded handlers
|
||||
* @nr_actions: number of installed actions on this descriptor
|
||||
* @no_suspend_depth: number of irqactions on a irq descriptor with
|
||||
* IRQF_NO_SUSPEND set
|
||||
* @force_resume_depth: number of irqactions on a irq descriptor with
|
||||
* IRQF_FORCE_RESUME set
|
||||
* @dir: /proc/irq/ procfs entry
|
||||
* @name: flow handler name for /proc/interrupts output
|
||||
*/
|
||||
|
@ -68,6 +73,11 @@ struct irq_desc {
|
|||
unsigned long threads_oneshot;
|
||||
atomic_t threads_active;
|
||||
wait_queue_head_t wait_for_threads;
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
unsigned int nr_actions;
|
||||
unsigned int no_suspend_depth;
|
||||
unsigned int force_resume_depth;
|
||||
#endif
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_dir_entry *dir;
|
||||
#endif
|
||||
|
|
|
@ -194,3 +194,13 @@ static inline void kstat_incr_irqs_this_cpu(unsigned int irq, struct irq_desc *d
|
|||
__this_cpu_inc(*desc->kstat_irqs);
|
||||
__this_cpu_inc(kstat.irqs_sum);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
void irq_pm_install_action(struct irq_desc *desc, struct irqaction *action);
|
||||
void irq_pm_remove_action(struct irq_desc *desc, struct irqaction *action);
|
||||
#else
|
||||
static inline void
|
||||
irq_pm_install_action(struct irq_desc *desc, struct irqaction *action) { }
|
||||
static inline void
|
||||
irq_pm_remove_action(struct irq_desc *desc, struct irqaction *action) { }
|
||||
#endif
|
||||
|
|
|
@ -1200,6 +1200,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
|
|||
new->irq = irq;
|
||||
*old_ptr = new;
|
||||
|
||||
irq_pm_install_action(desc, new);
|
||||
|
||||
/* Reset broken irq detection when installing new handler */
|
||||
desc->irq_count = 0;
|
||||
desc->irqs_unhandled = 0;
|
||||
|
@ -1318,6 +1320,8 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
|
|||
/* Found it - now remove it from the list of entries: */
|
||||
*action_ptr = action->next;
|
||||
|
||||
irq_pm_remove_action(desc, action);
|
||||
|
||||
/* If this was the last handler, shut down the IRQ line: */
|
||||
if (!desc->action) {
|
||||
irq_shutdown(desc);
|
||||
|
|
|
@ -13,6 +13,42 @@
|
|||
|
||||
#include "internals.h"
|
||||
|
||||
/*
|
||||
* Called from __setup_irq() with desc->lock held after @action has
|
||||
* been installed in the action chain.
|
||||
*/
|
||||
void irq_pm_install_action(struct irq_desc *desc, struct irqaction *action)
|
||||
{
|
||||
desc->nr_actions++;
|
||||
|
||||
if (action->flags & IRQF_FORCE_RESUME)
|
||||
desc->force_resume_depth++;
|
||||
|
||||
WARN_ON_ONCE(desc->force_resume_depth &&
|
||||
desc->force_resume_depth != desc->nr_actions);
|
||||
|
||||
if (action->flags & IRQF_NO_SUSPEND)
|
||||
desc->no_suspend_depth++;
|
||||
|
||||
WARN_ON_ONCE(desc->no_suspend_depth &&
|
||||
desc->no_suspend_depth != desc->nr_actions);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called from __free_irq() with desc->lock held after @action has
|
||||
* been removed from the action chain.
|
||||
*/
|
||||
void irq_pm_remove_action(struct irq_desc *desc, struct irqaction *action)
|
||||
{
|
||||
desc->nr_actions--;
|
||||
|
||||
if (action->flags & IRQF_FORCE_RESUME)
|
||||
desc->force_resume_depth--;
|
||||
|
||||
if (action->flags & IRQF_NO_SUSPEND)
|
||||
desc->no_suspend_depth--;
|
||||
}
|
||||
|
||||
static void suspend_device_irq(struct irq_desc *desc, int irq)
|
||||
{
|
||||
if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
|
||||
|
|
Загрузка…
Ссылка в новой задаче