Merge branch 'linus' into irq/threaded
Conflicts: include/linux/irq.h kernel/irq/handle.c
This commit is contained in:
@@ -4,3 +4,4 @@ obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
|
||||
obj-$(CONFIG_PROC_FS) += proc.o
|
||||
obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
|
||||
obj-$(CONFIG_NUMA_MIGRATE_IRQ_DESC) += numa_migrate.o
|
||||
obj-$(CONFIG_PM_SLEEP) += pm.o
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/rculist.h>
|
||||
#include <linux/hash.h>
|
||||
#include <trace/irq.h>
|
||||
#include <linux/bootmem.h>
|
||||
|
||||
#include "internals.h"
|
||||
@@ -347,6 +348,9 @@ static void warn_no_thread(unsigned int irq, struct irqaction *action)
|
||||
"but no thread function available.", irq, action->name);
|
||||
}
|
||||
|
||||
DEFINE_TRACE(irq_handler_entry);
|
||||
DEFINE_TRACE(irq_handler_exit);
|
||||
|
||||
/**
|
||||
* handle_IRQ_event - irq action chain handler
|
||||
* @irq: the interrupt number
|
||||
@@ -365,7 +369,9 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
|
||||
local_irq_enable_in_hardirq();
|
||||
|
||||
do {
|
||||
trace_irq_handler_entry(irq, action);
|
||||
ret = action->handler(irq, action->dev_id);
|
||||
trace_irq_handler_exit(irq, action, ret);
|
||||
|
||||
switch (ret) {
|
||||
case IRQ_WAKE_THREAD:
|
||||
|
||||
@@ -12,6 +12,8 @@ extern void compat_irq_chip_set_default_handler(struct irq_desc *desc);
|
||||
|
||||
extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
|
||||
unsigned long flags);
|
||||
extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
|
||||
extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
|
||||
|
||||
extern struct lock_class_key irq_desc_lock_class;
|
||||
extern void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr);
|
||||
|
||||
+24
-7
@@ -185,6 +185,20 @@ static inline int setup_affinity(unsigned int irq, struct irq_desc *desc)
|
||||
}
|
||||
#endif
|
||||
|
||||
void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
|
||||
{
|
||||
if (suspend) {
|
||||
if (!desc->action || (desc->action->flags & IRQF_TIMER))
|
||||
return;
|
||||
desc->status |= IRQ_SUSPENDED;
|
||||
}
|
||||
|
||||
if (!desc->depth++) {
|
||||
desc->status |= IRQ_DISABLED;
|
||||
desc->chip->disable(irq);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* disable_irq_nosync - disable an irq without waiting
|
||||
* @irq: Interrupt to disable
|
||||
@@ -205,10 +219,7 @@ void disable_irq_nosync(unsigned int irq)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
if (!desc->depth++) {
|
||||
desc->status |= IRQ_DISABLED;
|
||||
desc->chip->disable(irq);
|
||||
}
|
||||
__disable_irq(desc, irq, false);
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(disable_irq_nosync);
|
||||
@@ -238,15 +249,21 @@ void disable_irq(unsigned int irq)
|
||||
}
|
||||
EXPORT_SYMBOL(disable_irq);
|
||||
|
||||
static void __enable_irq(struct irq_desc *desc, unsigned int irq)
|
||||
void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume)
|
||||
{
|
||||
if (resume)
|
||||
desc->status &= ~IRQ_SUSPENDED;
|
||||
|
||||
switch (desc->depth) {
|
||||
case 0:
|
||||
err_out:
|
||||
WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
|
||||
break;
|
||||
case 1: {
|
||||
unsigned int status = desc->status & ~IRQ_DISABLED;
|
||||
|
||||
if (desc->status & IRQ_SUSPENDED)
|
||||
goto err_out;
|
||||
/* Prevent probing on this irq: */
|
||||
desc->status = status | IRQ_NOPROBE;
|
||||
check_irq_resend(desc, irq);
|
||||
@@ -276,7 +293,7 @@ void enable_irq(unsigned int irq)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
__enable_irq(desc, irq);
|
||||
__enable_irq(desc, irq, false);
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(enable_irq);
|
||||
@@ -638,7 +655,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
|
||||
*/
|
||||
if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) {
|
||||
desc->status &= ~IRQ_SPURIOUS_DISABLED;
|
||||
__enable_irq(desc, irq);
|
||||
__enable_irq(desc, irq, false);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* linux/kernel/irq/pm.c
|
||||
*
|
||||
* Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
|
||||
*
|
||||
* This file contains power management functions related to interrupts.
|
||||
*/
|
||||
|
||||
#include <linux/irq.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "internals.h"
|
||||
|
||||
/**
|
||||
* suspend_device_irqs - disable all currently enabled interrupt lines
|
||||
*
|
||||
* During system-wide suspend or hibernation device interrupts need to be
|
||||
* disabled at the chip level and this function is provided for this purpose.
|
||||
* It disables all interrupt lines that are enabled at the moment and sets the
|
||||
* IRQ_SUSPENDED flag for them.
|
||||
*/
|
||||
void suspend_device_irqs(void)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
int irq;
|
||||
|
||||
for_each_irq_desc(irq, desc) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
__disable_irq(desc, irq, true);
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
|
||||
for_each_irq_desc(irq, desc)
|
||||
if (desc->status & IRQ_SUSPENDED)
|
||||
synchronize_irq(irq);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(suspend_device_irqs);
|
||||
|
||||
/**
|
||||
* resume_device_irqs - enable interrupt lines disabled by suspend_device_irqs()
|
||||
*
|
||||
* Enable all interrupt lines previously disabled by suspend_device_irqs() that
|
||||
* have the IRQ_SUSPENDED flag set.
|
||||
*/
|
||||
void resume_device_irqs(void)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
int irq;
|
||||
|
||||
for_each_irq_desc(irq, desc) {
|
||||
unsigned long flags;
|
||||
|
||||
if (!(desc->status & IRQ_SUSPENDED))
|
||||
continue;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
__enable_irq(desc, irq, true);
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(resume_device_irqs);
|
||||
|
||||
/**
|
||||
* check_wakeup_irqs - check if any wake-up interrupts are pending
|
||||
*/
|
||||
int check_wakeup_irqs(void)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
int irq;
|
||||
|
||||
for_each_irq_desc(irq, desc)
|
||||
if ((desc->status & IRQ_WAKEUP) && (desc->status & IRQ_PENDING))
|
||||
return -EBUSY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user