PM / wakeirq: Avoid setting power.wakeirq too hastily
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 7 Jul 2015 11:08:39 +0000 (13:08 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 7 Jul 2015 11:08:39 +0000 (13:08 +0200)
If dev_pm_attach_wake_irq() fails, the device's power.wakeirq field
should not be set to point to the struct wake_irq passed to that
function, as that object will be freed going forward.

For this reason, make dev_pm_attach_wake_irq() first call
device_wakeup_attach_irq() and only set the device's power.wakeirq
field if that's successful.

That requires device_wakeup_attach_irq() to be called under the
device's power.lock lock, but since dev_pm_attach_wake_irq() is
the only caller of it, the requisite changes are easy to make.

Fixes: 4990d4fe327b (PM / Wakeirq: Add automated device wake IRQ handling)
Reported-by: Felipe Balbi <balbi@ti.com>
Tested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/base/power/wakeirq.c
drivers/base/power/wakeup.c

index 7470004..eb6e674 100644 (file)
@@ -45,14 +45,12 @@ static int dev_pm_attach_wake_irq(struct device *dev, int irq,
                return -EEXIST;
        }
 
-       dev->power.wakeirq = wirq;
-       spin_unlock_irqrestore(&dev->power.lock, flags);
-
        err = device_wakeup_attach_irq(dev, wirq);
-       if (err)
-               return err;
+       if (!err)
+               dev->power.wakeirq = wirq;
 
-       return 0;
+       spin_unlock_irqrestore(&dev->power.lock, flags);
+       return err;
 }
 
 /**
@@ -105,10 +103,10 @@ void dev_pm_clear_wake_irq(struct device *dev)
                return;
 
        spin_lock_irqsave(&dev->power.lock, flags);
+       device_wakeup_detach_irq(dev);
        dev->power.wakeirq = NULL;
        spin_unlock_irqrestore(&dev->power.lock, flags);
 
-       device_wakeup_detach_irq(dev);
        if (wirq->dedicated_irq)
                free_irq(wirq->irq, wirq);
        kfree(wirq);
Simple merge