aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq')
-rw-r--r--kernel/irq/Kconfig3
-rw-r--r--kernel/irq/chip.c86
-rw-r--r--kernel/irq/devres.c2
-rw-r--r--kernel/irq/internals.h16
-rw-r--r--kernel/irq/irqdesc.c42
-rw-r--r--kernel/irq/manage.c32
-rw-r--r--kernel/irq/pm.c159
7 files changed, 242 insertions, 98 deletions
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index d269cecdfbf0..225086b2652e 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -55,6 +55,9 @@ config GENERIC_IRQ_CHIP
55config IRQ_DOMAIN 55config IRQ_DOMAIN
56 bool 56 bool
57 57
58config HANDLE_DOMAIN_IRQ
59 bool
60
58config IRQ_DOMAIN_DEBUG 61config IRQ_DOMAIN_DEBUG
59 bool "Expose hardware/virtual IRQ mapping via debugfs" 62 bool "Expose hardware/virtual IRQ mapping via debugfs"
60 depends on IRQ_DOMAIN && DEBUG_FS 63 depends on IRQ_DOMAIN && DEBUG_FS
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index cca7292fc61e..e5202f00cabc 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -342,6 +342,31 @@ static bool irq_check_poll(struct irq_desc *desc)
342 return irq_wait_for_poll(desc); 342 return irq_wait_for_poll(desc);
343} 343}
344 344
345static bool irq_may_run(struct irq_desc *desc)
346{
347 unsigned int mask = IRQD_IRQ_INPROGRESS | IRQD_WAKEUP_ARMED;
348
349 /*
350 * If the interrupt is not in progress and is not an armed
351 * wakeup interrupt, proceed.
352 */
353 if (!irqd_has_set(&desc->irq_data, mask))
354 return true;
355
356 /*
357 * If the interrupt is an armed wakeup source, mark it pending
358 * and suspended, disable it and notify the pm core about the
359 * event.
360 */
361 if (irq_pm_check_wakeup(desc))
362 return false;
363
364 /*
365 * Handle a potential concurrent poll on a different core.
366 */
367 return irq_check_poll(desc);
368}
369
345/** 370/**
346 * handle_simple_irq - Simple and software-decoded IRQs. 371 * handle_simple_irq - Simple and software-decoded IRQs.
347 * @irq: the interrupt number 372 * @irq: the interrupt number
@@ -359,9 +384,8 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc)
359{ 384{
360 raw_spin_lock(&desc->lock); 385 raw_spin_lock(&desc->lock);
361 386
362 if (unlikely(irqd_irq_inprogress(&desc->irq_data))) 387 if (!irq_may_run(desc))
363 if (!irq_check_poll(desc)) 388 goto out_unlock;
364 goto out_unlock;
365 389
366 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); 390 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
367 kstat_incr_irqs_this_cpu(irq, desc); 391 kstat_incr_irqs_this_cpu(irq, desc);
@@ -412,9 +436,8 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
412 raw_spin_lock(&desc->lock); 436 raw_spin_lock(&desc->lock);
413 mask_ack_irq(desc); 437 mask_ack_irq(desc);
414 438
415 if (unlikely(irqd_irq_inprogress(&desc->irq_data))) 439 if (!irq_may_run(desc))
416 if (!irq_check_poll(desc)) 440 goto out_unlock;
417 goto out_unlock;
418 441
419 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); 442 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
420 kstat_incr_irqs_this_cpu(irq, desc); 443 kstat_incr_irqs_this_cpu(irq, desc);
@@ -485,9 +508,8 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
485 508
486 raw_spin_lock(&desc->lock); 509 raw_spin_lock(&desc->lock);
487 510
488 if (unlikely(irqd_irq_inprogress(&desc->irq_data))) 511 if (!irq_may_run(desc))
489 if (!irq_check_poll(desc)) 512 goto out;
490 goto out;
491 513
492 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); 514 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
493 kstat_incr_irqs_this_cpu(irq, desc); 515 kstat_incr_irqs_this_cpu(irq, desc);
@@ -517,6 +539,7 @@ out:
517 chip->irq_eoi(&desc->irq_data); 539 chip->irq_eoi(&desc->irq_data);
518 raw_spin_unlock(&desc->lock); 540 raw_spin_unlock(&desc->lock);
519} 541}
542EXPORT_SYMBOL_GPL(handle_fasteoi_irq);
520 543
521/** 544/**
522 * handle_edge_irq - edge type IRQ handler 545 * handle_edge_irq - edge type IRQ handler
@@ -540,19 +563,23 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
540 raw_spin_lock(&desc->lock); 563 raw_spin_lock(&desc->lock);
541 564
542 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); 565 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
566
567 if (!irq_may_run(desc)) {
568 desc->istate |= IRQS_PENDING;
569 mask_ack_irq(desc);
570 goto out_unlock;
571 }
572
543 /* 573 /*
544 * If we're currently running this IRQ, or its disabled, 574 * If its disabled or no action available then mask it and get
545 * we shouldn't process the IRQ. Mark it pending, handle 575 * out of here.
546 * the necessary masking and go out
547 */ 576 */
548 if (unlikely(irqd_irq_disabled(&desc->irq_data) || 577 if (irqd_irq_disabled(&desc->irq_data) || !desc->action) {
549 irqd_irq_inprogress(&desc->irq_data) || !desc->action)) { 578 desc->istate |= IRQS_PENDING;
550 if (!irq_check_poll(desc)) { 579 mask_ack_irq(desc);
551 desc->istate |= IRQS_PENDING; 580 goto out_unlock;
552 mask_ack_irq(desc);
553 goto out_unlock;
554 }
555 } 581 }
582
556 kstat_incr_irqs_this_cpu(irq, desc); 583 kstat_incr_irqs_this_cpu(irq, desc);
557 584
558 /* Start handling the irq */ 585 /* Start handling the irq */
@@ -601,18 +628,21 @@ void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc)
601 raw_spin_lock(&desc->lock); 628 raw_spin_lock(&desc->lock);
602 629
603 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); 630 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
631
632 if (!irq_may_run(desc)) {
633 desc->istate |= IRQS_PENDING;
634 goto out_eoi;
635 }
636
604 /* 637 /*
605 * If we're currently running this IRQ, or its disabled, 638 * If its disabled or no action available then mask it and get
606 * we shouldn't process the IRQ. Mark it pending, handle 639 * out of here.
607 * the necessary masking and go out
608 */ 640 */
609 if (unlikely(irqd_irq_disabled(&desc->irq_data) || 641 if (irqd_irq_disabled(&desc->irq_data) || !desc->action) {
610 irqd_irq_inprogress(&desc->irq_data) || !desc->action)) { 642 desc->istate |= IRQS_PENDING;
611 if (!irq_check_poll(desc)) { 643 goto out_eoi;
612 desc->istate |= IRQS_PENDING;
613 goto out_eoi;
614 }
615 } 644 }
645
616 kstat_incr_irqs_this_cpu(irq, desc); 646 kstat_incr_irqs_this_cpu(irq, desc);
617 647
618 do { 648 do {
diff --git a/kernel/irq/devres.c b/kernel/irq/devres.c
index 1ef0606797c9..d5d0f7345c54 100644
--- a/kernel/irq/devres.c
+++ b/kernel/irq/devres.c
@@ -38,7 +38,7 @@ static int devm_irq_match(struct device *dev, void *res, void *data)
38 * 38 *
39 * Except for the extra @dev argument, this function takes the 39 * Except for the extra @dev argument, this function takes the
40 * same arguments and performs the same function as 40 * same arguments and performs the same function as
41 * request_irq(). IRQs requested with this function will be 41 * request_threaded_irq(). IRQs requested with this function will be
42 * automatically freed on driver detach. 42 * automatically freed on driver detach.
43 * 43 *
44 * If an IRQ allocated with this function needs to be freed 44 * If an IRQ allocated with this function needs to be freed
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 099ea2e0eb88..4332d766619d 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -63,8 +63,8 @@ enum {
63 63
64extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, 64extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
65 unsigned long flags); 65 unsigned long flags);
66extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp); 66extern void __disable_irq(struct irq_desc *desc, unsigned int irq);
67extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume); 67extern void __enable_irq(struct irq_desc *desc, unsigned int irq);
68 68
69extern int irq_startup(struct irq_desc *desc, bool resend); 69extern int irq_startup(struct irq_desc *desc, bool resend);
70extern void irq_shutdown(struct irq_desc *desc); 70extern void irq_shutdown(struct irq_desc *desc);
@@ -194,3 +194,15 @@ static inline void kstat_incr_irqs_this_cpu(unsigned int irq, struct irq_desc *d
194 __this_cpu_inc(*desc->kstat_irqs); 194 __this_cpu_inc(*desc->kstat_irqs);
195 __this_cpu_inc(kstat.irqs_sum); 195 __this_cpu_inc(kstat.irqs_sum);
196} 196}
197
198#ifdef CONFIG_PM_SLEEP
199bool irq_pm_check_wakeup(struct irq_desc *desc);
200void irq_pm_install_action(struct irq_desc *desc, struct irqaction *action);
201void irq_pm_remove_action(struct irq_desc *desc, struct irqaction *action);
202#else
203static inline bool irq_pm_check_wakeup(struct irq_desc *desc) { return false; }
204static inline void
205irq_pm_install_action(struct irq_desc *desc, struct irqaction *action) { }
206static inline void
207irq_pm_remove_action(struct irq_desc *desc, struct irqaction *action) { }
208#endif
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 1487a123db5c..a1782f88f0af 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -14,6 +14,7 @@
14#include <linux/kernel_stat.h> 14#include <linux/kernel_stat.h>
15#include <linux/radix-tree.h> 15#include <linux/radix-tree.h>
16#include <linux/bitmap.h> 16#include <linux/bitmap.h>
17#include <linux/irqdomain.h>
17 18
18#include "internals.h" 19#include "internals.h"
19 20
@@ -336,6 +337,47 @@ int generic_handle_irq(unsigned int irq)
336} 337}
337EXPORT_SYMBOL_GPL(generic_handle_irq); 338EXPORT_SYMBOL_GPL(generic_handle_irq);
338 339
340#ifdef CONFIG_HANDLE_DOMAIN_IRQ
341/**
342 * __handle_domain_irq - Invoke the handler for a HW irq belonging to a domain
343 * @domain: The domain where to perform the lookup
344 * @hwirq: The HW irq number to convert to a logical one
345 * @lookup: Whether to perform the domain lookup or not
346 * @regs: Register file coming from the low-level handling code
347 *
348 * Returns: 0 on success, or -EINVAL if conversion has failed
349 */
350int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,
351 bool lookup, struct pt_regs *regs)
352{
353 struct pt_regs *old_regs = set_irq_regs(regs);
354 unsigned int irq = hwirq;
355 int ret = 0;
356
357 irq_enter();
358
359#ifdef CONFIG_IRQ_DOMAIN
360 if (lookup)
361 irq = irq_find_mapping(domain, hwirq);
362#endif
363
364 /*
365 * Some hardware gives randomly wrong interrupts. Rather
366 * than crashing, do something sensible.
367 */
368 if (unlikely(!irq || irq >= nr_irqs)) {
369 ack_bad_irq(irq);
370 ret = -EINVAL;
371 } else {
372 generic_handle_irq(irq);
373 }
374
375 irq_exit();
376 set_irq_regs(old_regs);
377 return ret;
378}
379#endif
380
339/* Dynamic interrupt handling */ 381/* Dynamic interrupt handling */
340 382
341/** 383/**
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 3dc6a61bf06a..0a9104b4608b 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -382,14 +382,8 @@ setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask)
382} 382}
383#endif 383#endif
384 384
385void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend) 385void __disable_irq(struct irq_desc *desc, unsigned int irq)
386{ 386{
387 if (suspend) {
388 if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
389 return;
390 desc->istate |= IRQS_SUSPENDED;
391 }
392
393 if (!desc->depth++) 387 if (!desc->depth++)
394 irq_disable(desc); 388 irq_disable(desc);
395} 389}
@@ -401,7 +395,7 @@ static int __disable_irq_nosync(unsigned int irq)
401 395
402 if (!desc) 396 if (!desc)
403 return -EINVAL; 397 return -EINVAL;
404 __disable_irq(desc, irq, false); 398 __disable_irq(desc, irq);
405 irq_put_desc_busunlock(desc, flags); 399 irq_put_desc_busunlock(desc, flags);
406 return 0; 400 return 0;
407} 401}
@@ -442,20 +436,8 @@ void disable_irq(unsigned int irq)
442} 436}
443EXPORT_SYMBOL(disable_irq); 437EXPORT_SYMBOL(disable_irq);
444 438
445void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume) 439void __enable_irq(struct irq_desc *desc, unsigned int irq)
446{ 440{
447 if (resume) {
448 if (!(desc->istate & IRQS_SUSPENDED)) {
449 if (!desc->action)
450 return;
451 if (!(desc->action->flags & IRQF_FORCE_RESUME))
452 return;
453 /* Pretend that it got disabled ! */
454 desc->depth++;
455 }
456 desc->istate &= ~IRQS_SUSPENDED;
457 }
458
459 switch (desc->depth) { 441 switch (desc->depth) {
460 case 0: 442 case 0:
461 err_out: 443 err_out:
@@ -497,7 +479,7 @@ void enable_irq(unsigned int irq)
497 KERN_ERR "enable_irq before setup/request_irq: irq %u\n", irq)) 479 KERN_ERR "enable_irq before setup/request_irq: irq %u\n", irq))
498 goto out; 480 goto out;
499 481
500 __enable_irq(desc, irq, false); 482 __enable_irq(desc, irq);
501out: 483out:
502 irq_put_desc_busunlock(desc, flags); 484 irq_put_desc_busunlock(desc, flags);
503} 485}
@@ -1218,6 +1200,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
1218 new->irq = irq; 1200 new->irq = irq;
1219 *old_ptr = new; 1201 *old_ptr = new;
1220 1202
1203 irq_pm_install_action(desc, new);
1204
1221 /* Reset broken irq detection when installing new handler */ 1205 /* Reset broken irq detection when installing new handler */
1222 desc->irq_count = 0; 1206 desc->irq_count = 0;
1223 desc->irqs_unhandled = 0; 1207 desc->irqs_unhandled = 0;
@@ -1228,7 +1212,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
1228 */ 1212 */
1229 if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED)) { 1213 if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED)) {
1230 desc->istate &= ~IRQS_SPURIOUS_DISABLED; 1214 desc->istate &= ~IRQS_SPURIOUS_DISABLED;
1231 __enable_irq(desc, irq, false); 1215 __enable_irq(desc, irq);
1232 } 1216 }
1233 1217
1234 raw_spin_unlock_irqrestore(&desc->lock, flags); 1218 raw_spin_unlock_irqrestore(&desc->lock, flags);
@@ -1336,6 +1320,8 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
1336 /* Found it - now remove it from the list of entries: */ 1320 /* Found it - now remove it from the list of entries: */
1337 *action_ptr = action->next; 1321 *action_ptr = action->next;
1338 1322
1323 irq_pm_remove_action(desc, action);
1324
1339 /* If this was the last handler, shut down the IRQ line: */ 1325 /* If this was the last handler, shut down the IRQ line: */
1340 if (!desc->action) { 1326 if (!desc->action) {
1341 irq_shutdown(desc); 1327 irq_shutdown(desc);
diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c
index abcd6ca86cb7..3ca532592704 100644
--- a/kernel/irq/pm.c
+++ b/kernel/irq/pm.c
@@ -9,17 +9,105 @@
9#include <linux/irq.h> 9#include <linux/irq.h>
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/interrupt.h> 11#include <linux/interrupt.h>
12#include <linux/suspend.h>
12#include <linux/syscore_ops.h> 13#include <linux/syscore_ops.h>
13 14
14#include "internals.h" 15#include "internals.h"
15 16
17bool irq_pm_check_wakeup(struct irq_desc *desc)
18{
19 if (irqd_is_wakeup_armed(&desc->irq_data)) {
20 irqd_clear(&desc->irq_data, IRQD_WAKEUP_ARMED);
21 desc->istate |= IRQS_SUSPENDED | IRQS_PENDING;
22 desc->depth++;
23 irq_disable(desc);
24 pm_system_wakeup();
25 return true;
26 }
27 return false;
28}
29
30/*
31 * Called from __setup_irq() with desc->lock held after @action has
32 * been installed in the action chain.
33 */
34void irq_pm_install_action(struct irq_desc *desc, struct irqaction *action)
35{
36 desc->nr_actions++;
37
38 if (action->flags & IRQF_FORCE_RESUME)
39 desc->force_resume_depth++;
40
41 WARN_ON_ONCE(desc->force_resume_depth &&
42 desc->force_resume_depth != desc->nr_actions);
43
44 if (action->flags & IRQF_NO_SUSPEND)
45 desc->no_suspend_depth++;
46
47 WARN_ON_ONCE(desc->no_suspend_depth &&
48 desc->no_suspend_depth != desc->nr_actions);
49}
50
51/*
52 * Called from __free_irq() with desc->lock held after @action has
53 * been removed from the action chain.
54 */
55void irq_pm_remove_action(struct irq_desc *desc, struct irqaction *action)
56{
57 desc->nr_actions--;
58
59 if (action->flags & IRQF_FORCE_RESUME)
60 desc->force_resume_depth--;
61
62 if (action->flags & IRQF_NO_SUSPEND)
63 desc->no_suspend_depth--;
64}
65
66static bool suspend_device_irq(struct irq_desc *desc, int irq)
67{
68 if (!desc->action || desc->no_suspend_depth)
69 return false;
70
71 if (irqd_is_wakeup_set(&desc->irq_data)) {
72 irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);
73 /*
74 * We return true here to force the caller to issue
75 * synchronize_irq(). We need to make sure that the
76 * IRQD_WAKEUP_ARMED is visible before we return from
77 * suspend_device_irqs().
78 */
79 return true;
80 }
81
82 desc->istate |= IRQS_SUSPENDED;
83 __disable_irq(desc, irq);
84
85 /*
86 * Hardware which has no wakeup source configuration facility
87 * requires that the non wakeup interrupts are masked at the
88 * chip level. The chip implementation indicates that with
89 * IRQCHIP_MASK_ON_SUSPEND.
90 */
91 if (irq_desc_get_chip(desc)->flags & IRQCHIP_MASK_ON_SUSPEND)
92 mask_irq(desc);
93 return true;
94}
95
16/** 96/**
17 * suspend_device_irqs - disable all currently enabled interrupt lines 97 * suspend_device_irqs - disable all currently enabled interrupt lines
18 * 98 *
19 * During system-wide suspend or hibernation device drivers need to be prevented 99 * During system-wide suspend or hibernation device drivers need to be
20 * from receiving interrupts and this function is provided for this purpose. 100 * prevented from receiving interrupts and this function is provided
21 * It marks all interrupt lines in use, except for the timer ones, as disabled 101 * for this purpose.
22 * and sets the IRQS_SUSPENDED flag for each of them. 102 *
103 * So we disable all interrupts and mark them IRQS_SUSPENDED except
104 * for those which are unused, those which are marked as not
105 * suspendable via an interrupt request with the flag IRQF_NO_SUSPEND
106 * set and those which are marked as active wakeup sources.
107 *
108 * The active wakeup sources are handled by the flow handler entry
109 * code which checks for the IRQD_WAKEUP_ARMED flag, suspends the
110 * interrupt and notifies the pm core about the wakeup.
23 */ 111 */
24void suspend_device_irqs(void) 112void suspend_device_irqs(void)
25{ 113{
@@ -28,18 +116,36 @@ void suspend_device_irqs(void)
28 116
29 for_each_irq_desc(irq, desc) { 117 for_each_irq_desc(irq, desc) {
30 unsigned long flags; 118 unsigned long flags;
119 bool sync;
31 120
32 raw_spin_lock_irqsave(&desc->lock, flags); 121 raw_spin_lock_irqsave(&desc->lock, flags);
33 __disable_irq(desc, irq, true); 122 sync = suspend_device_irq(desc, irq);
34 raw_spin_unlock_irqrestore(&desc->lock, flags); 123 raw_spin_unlock_irqrestore(&desc->lock, flags);
35 }
36 124
37 for_each_irq_desc(irq, desc) 125 if (sync)
38 if (desc->istate & IRQS_SUSPENDED)
39 synchronize_irq(irq); 126 synchronize_irq(irq);
127 }
40} 128}
41EXPORT_SYMBOL_GPL(suspend_device_irqs); 129EXPORT_SYMBOL_GPL(suspend_device_irqs);
42 130
131static void resume_irq(struct irq_desc *desc, int irq)
132{
133 irqd_clear(&desc->irq_data, IRQD_WAKEUP_ARMED);
134
135 if (desc->istate & IRQS_SUSPENDED)
136 goto resume;
137
138 /* Force resume the interrupt? */
139 if (!desc->force_resume_depth)
140 return;
141
142 /* Pretend that it got disabled ! */
143 desc->depth++;
144resume:
145 desc->istate &= ~IRQS_SUSPENDED;
146 __enable_irq(desc, irq);
147}
148
43static void resume_irqs(bool want_early) 149static void resume_irqs(bool want_early)
44{ 150{
45 struct irq_desc *desc; 151 struct irq_desc *desc;
@@ -54,7 +160,7 @@ static void resume_irqs(bool want_early)
54 continue; 160 continue;
55 161
56 raw_spin_lock_irqsave(&desc->lock, flags); 162 raw_spin_lock_irqsave(&desc->lock, flags);
57 __enable_irq(desc, irq, true); 163 resume_irq(desc, irq);
58 raw_spin_unlock_irqrestore(&desc->lock, flags); 164 raw_spin_unlock_irqrestore(&desc->lock, flags);
59 } 165 }
60} 166}
@@ -93,38 +199,3 @@ void resume_device_irqs(void)
93 resume_irqs(false); 199 resume_irqs(false);
94} 200}
95EXPORT_SYMBOL_GPL(resume_device_irqs); 201EXPORT_SYMBOL_GPL(resume_device_irqs);
96
97/**
98 * check_wakeup_irqs - check if any wake-up interrupts are pending
99 */
100int check_wakeup_irqs(void)
101{
102 struct irq_desc *desc;
103 int irq;
104
105 for_each_irq_desc(irq, desc) {
106 /*
107 * Only interrupts which are marked as wakeup source
108 * and have not been disabled before the suspend check
109 * can abort suspend.
110 */
111 if (irqd_is_wakeup_set(&desc->irq_data)) {
112 if (desc->depth == 1 && desc->istate & IRQS_PENDING)
113 return -EBUSY;
114 continue;
115 }
116 /*
117 * Check the non wakeup interrupts whether they need
118 * to be masked before finally going into suspend
119 * state. That's for hardware which has no wakeup
120 * source configuration facility. The chip
121 * implementation indicates that with
122 * IRQCHIP_MASK_ON_SUSPEND.
123 */
124 if (desc->istate & IRQS_SUSPENDED &&
125 irq_desc_get_chip(desc)->flags & IRQCHIP_MASK_ON_SUSPEND)
126 mask_irq(desc);
127 }
128
129 return 0;
130}