1 /* 2 * linux/kernel/irq/pm.c 3 * 4 * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. 5 * 6 * This file contains power management functions related to interrupts. 7 */ 8 9 #include <linux/irq.h> 10 #include <linux/module.h> 11 #include <linux/interrupt.h> 12 13 #include "internals.h" 14 15 /** 16 * suspend_device_irqs - disable all currently enabled interrupt lines 17 * 18 * During system-wide suspend or hibernation device drivers need to be prevented 19 * from receiving interrupts and this function is provided for this purpose. 20 * It marks all interrupt lines in use, except for the timer ones, as disabled 21 * and sets the IRQS_SUSPENDED flag for each of them. 22 */ 23 void suspend_device_irqs(void) 24 { 25 struct irq_desc *desc; 26 int irq; 27 28 for_each_irq_desc(irq, desc) { 29 unsigned long flags; 30 31 raw_spin_lock_irqsave(&desc->lock, flags); 32 __disable_irq(desc, irq, true); 33 raw_spin_unlock_irqrestore(&desc->lock, flags); 34 } 35 36 for_each_irq_desc(irq, desc) 37 if (desc->istate & IRQS_SUSPENDED) 38 synchronize_irq(irq); 39 } 40 EXPORT_SYMBOL_GPL(suspend_device_irqs); 41 42 /** 43 * resume_device_irqs - enable interrupt lines disabled by suspend_device_irqs() 44 * 45 * Enable all interrupt lines previously disabled by suspend_device_irqs() that 46 * have the IRQS_SUSPENDED flag set. 47 */ 48 void resume_device_irqs(void) 49 { 50 struct irq_desc *desc; 51 int irq; 52 53 for_each_irq_desc(irq, desc) { 54 unsigned long flags; 55 56 raw_spin_lock_irqsave(&desc->lock, flags); 57 __enable_irq(desc, irq, true); 58 raw_spin_unlock_irqrestore(&desc->lock, flags); 59 } 60 } 61 EXPORT_SYMBOL_GPL(resume_device_irqs); 62 63 /** 64 * check_wakeup_irqs - check if any wake-up interrupts are pending 65 */ 66 int check_wakeup_irqs(void) 67 { 68 struct irq_desc *desc; 69 int irq; 70 71 for_each_irq_desc(irq, desc) { 72 if (irqd_is_wakeup_set(&desc->irq_data)) { 73 if (desc->istate & IRQS_PENDING) 74 return -EBUSY; 75 continue; 76 } 77 /* 78 * Check the non wakeup interrupts whether they need 79 * to be masked before finally going into suspend 80 * state. That's for hardware which has no wakeup 81 * source configuration facility. The chip 82 * implementation indicates that with 83 * IRQCHIP_MASK_ON_SUSPEND. 84 */ 85 if (desc->istate & IRQS_SUSPENDED && 86 irq_desc_get_chip(desc)->flags & IRQCHIP_MASK_ON_SUSPEND) 87 mask_irq(desc); 88 } 89 90 return 0; 91 } 92