Skip to content

Commit

Permalink
HID: i2c-hid: Only disable irq wake if it was successfully enabled du…
Browse files Browse the repository at this point in the history
…ring 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 <aduggan@synaptics.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
  • Loading branch information
Andrew Duggan authored and Jiri Kosina committed Aug 18, 2015
1 parent af4739c commit d1c4803
Showing 1 changed file with 20 additions and 4 deletions.
24 changes: 20 additions & 4 deletions drivers/hid/i2c-hid/i2c-hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit d1c4803

Please sign in to comment.