diff options
Diffstat (limited to 'kernel/irq/manage.c')
-rw-r--r-- | kernel/irq/manage.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 4e461438e48b..92be519eff26 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -137,16 +137,40 @@ EXPORT_SYMBOL(enable_irq); | |||
137 | * @irq: interrupt to control | 137 | * @irq: interrupt to control |
138 | * @on: enable/disable power management wakeup | 138 | * @on: enable/disable power management wakeup |
139 | * | 139 | * |
140 | * Enable/disable power management wakeup mode | 140 | * Enable/disable power management wakeup mode, which is |
141 | * disabled by default. Enables and disables must match, | ||
142 | * just as they match for non-wakeup mode support. | ||
143 | * | ||
144 | * Wakeup mode lets this IRQ wake the system from sleep | ||
145 | * states like "suspend to RAM". | ||
141 | */ | 146 | */ |
142 | int set_irq_wake(unsigned int irq, unsigned int on) | 147 | int set_irq_wake(unsigned int irq, unsigned int on) |
143 | { | 148 | { |
144 | struct irq_desc *desc = irq_desc + irq; | 149 | struct irq_desc *desc = irq_desc + irq; |
145 | unsigned long flags; | 150 | unsigned long flags; |
146 | int ret = -ENXIO; | 151 | int ret = -ENXIO; |
152 | int (*set_wake)(unsigned, unsigned) = desc->chip->set_wake; | ||
147 | 153 | ||
154 | /* wakeup-capable irqs can be shared between drivers that | ||
155 | * don't need to have the same sleep mode behaviors. | ||
156 | */ | ||
148 | spin_lock_irqsave(&desc->lock, flags); | 157 | spin_lock_irqsave(&desc->lock, flags); |
149 | if (desc->chip->set_wake) | 158 | if (on) { |
159 | if (desc->wake_depth++ == 0) | ||
160 | desc->status |= IRQ_WAKEUP; | ||
161 | else | ||
162 | set_wake = NULL; | ||
163 | } else { | ||
164 | if (desc->wake_depth == 0) { | ||
165 | printk(KERN_WARNING "Unbalanced IRQ %d " | ||
166 | "wake disable\n", irq); | ||
167 | WARN_ON(1); | ||
168 | } else if (--desc->wake_depth == 0) | ||
169 | desc->status &= ~IRQ_WAKEUP; | ||
170 | else | ||
171 | set_wake = NULL; | ||
172 | } | ||
173 | if (set_wake) | ||
150 | ret = desc->chip->set_wake(irq, on); | 174 | ret = desc->chip->set_wake(irq, on); |
151 | spin_unlock_irqrestore(&desc->lock, flags); | 175 | spin_unlock_irqrestore(&desc->lock, flags); |
152 | return ret; | 176 | return ret; |