genirq: Add runtime power management support for IRQ chips
[cascardo/linux.git] / kernel / irq / manage.c
index f78b084..00cfc85 100644 (file)
@@ -1416,10 +1416,18 @@ int setup_irq(unsigned int irq, struct irqaction *act)
 
        if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
                return -EINVAL;
+
+       retval = irq_chip_pm_get(&desc->irq_data);
+       if (retval < 0)
+               return retval;
+
        chip_bus_lock(desc);
        retval = __setup_irq(irq, desc, act);
        chip_bus_sync_unlock(desc);
 
+       if (retval)
+               irq_chip_pm_put(&desc->irq_data);
+
        return retval;
 }
 EXPORT_SYMBOL_GPL(setup_irq);
@@ -1513,6 +1521,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
                }
        }
 
+       irq_chip_pm_put(&desc->irq_data);
        module_put(desc->owner);
        kfree(action->secondary);
        return action;
@@ -1655,11 +1664,16 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler,
        action->name = devname;
        action->dev_id = dev_id;
 
+       retval = irq_chip_pm_get(&desc->irq_data);
+       if (retval < 0)
+               return retval;
+
        chip_bus_lock(desc);
        retval = __setup_irq(irq, desc, action);
        chip_bus_sync_unlock(desc);
 
        if (retval) {
+               irq_chip_pm_put(&desc->irq_data);
                kfree(action->secondary);
                kfree(action);
        }
@@ -1836,6 +1850,7 @@ static struct irqaction *__free_percpu_irq(unsigned int irq, void __percpu *dev_
 
        unregister_handler_proc(irq, action);
 
+       irq_chip_pm_put(&desc->irq_data);
        module_put(desc->owner);
        return action;
 
@@ -1898,10 +1913,18 @@ int setup_percpu_irq(unsigned int irq, struct irqaction *act)
 
        if (!desc || !irq_settings_is_per_cpu_devid(desc))
                return -EINVAL;
+
+       retval = irq_chip_pm_get(&desc->irq_data);
+       if (retval < 0)
+               return retval;
+
        chip_bus_lock(desc);
        retval = __setup_irq(irq, desc, act);
        chip_bus_sync_unlock(desc);
 
+       if (retval)
+               irq_chip_pm_put(&desc->irq_data);
+
        return retval;
 }
 
@@ -1945,12 +1968,18 @@ int request_percpu_irq(unsigned int irq, irq_handler_t handler,
        action->name = devname;
        action->percpu_dev_id = dev_id;
 
+       retval = irq_chip_pm_get(&desc->irq_data);
+       if (retval < 0)
+               return retval;
+
        chip_bus_lock(desc);
        retval = __setup_irq(irq, desc, action);
        chip_bus_sync_unlock(desc);
 
-       if (retval)
+       if (retval) {
+               irq_chip_pm_put(&desc->irq_data);
                kfree(action);
+       }
 
        return retval;
 }