From d1c48038b849e9df0475621a52193a62424a4e87 Mon Sep 17 00:00:00 2001 From: Andrew Duggan Date: Thu, 30 Jul 2015 14:49:00 -0700 Subject: [PATCH] HID: i2c-hid: Only disable irq wake if it was successfully enabled during suspend Enabling irq wake could potentially fail and calling disable_irq_wake after a failed call to enable_irq_wake could result in an unbalanced irq warning. This patch warns if enable_irq_wake fails and avoids other potential issues caused by calling disable_irq_wake on resume after enable_irq_wake failed during suspend. Signed-off-by: Andrew Duggan Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 9ed69b5121f7..2871f3c81a4c 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -149,6 +149,8 @@ struct i2c_hid { int irq; struct i2c_hid_platform_data pdata; + + bool irq_wake_enabled; }; static int __i2c_hid_command(struct i2c_client *client, @@ -1091,13 +1093,20 @@ static int i2c_hid_suspend(struct device *dev) struct i2c_hid *ihid = i2c_get_clientdata(client); struct hid_device *hid = ihid->hid; int ret = 0; + int wake_status; if (hid->driver && hid->driver->suspend) ret = hid->driver->suspend(hid, PMSG_SUSPEND); disable_irq(ihid->irq); - if (device_may_wakeup(&client->dev)) - enable_irq_wake(ihid->irq); + if (device_may_wakeup(&client->dev)) { + wake_status = enable_irq_wake(ihid->irq); + if (!wake_status) + ihid->irq_wake_enabled = true; + else + hid_warn(hid, "Failed to enable irq wake: %d\n", + wake_status); + } /* Save some power */ i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); @@ -1111,14 +1120,21 @@ static int i2c_hid_resume(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct i2c_hid *ihid = i2c_get_clientdata(client); struct hid_device *hid = ihid->hid; + int wake_status; enable_irq(ihid->irq); ret = i2c_hid_hwreset(client); if (ret) return ret; - if (device_may_wakeup(&client->dev)) - disable_irq_wake(ihid->irq); + if (device_may_wakeup(&client->dev) && ihid->irq_wake_enabled) { + wake_status = disable_irq_wake(ihid->irq); + if (!wake_status) + ihid->irq_wake_enabled = false; + else + hid_warn(hid, "Failed to disable irq wake: %d\n", + wake_status); + } if (hid->driver && hid->driver->reset_resume) { ret = hid->driver->reset_resume(hid); -- 2.20.1