Loading drivers/hid/i2c-hid/i2c-hid.c +57 −11 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <linux/delay.h> #include <linux/slab.h> #include <linux/pm.h> #include <linux/pm_runtime.h> #include <linux/device.h> #include <linux/wait.h> #include <linux/err.h> Loading Loading @@ -454,10 +455,18 @@ static void i2c_hid_init_reports(struct hid_device *hid) return; } /* * The device must be powered on while we fetch initial reports * from it. */ pm_runtime_get_sync(&client->dev); list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) i2c_hid_init_report(report, inbuf, ihid->bufsize); pm_runtime_put(&client->dev); kfree(inbuf); } Loading Loading @@ -703,8 +712,8 @@ static int i2c_hid_open(struct hid_device *hid) mutex_lock(&i2c_hid_open_mut); if (!hid->open++) { ret = i2c_hid_set_power(client, I2C_HID_PWR_ON); if (ret) { ret = pm_runtime_get_sync(&client->dev); if (ret < 0) { hid->open--; goto done; } Loading @@ -712,7 +721,7 @@ static int i2c_hid_open(struct hid_device *hid) } done: mutex_unlock(&i2c_hid_open_mut); return ret; return ret < 0 ? ret : 0; } static void i2c_hid_close(struct hid_device *hid) Loading @@ -729,7 +738,7 @@ static void i2c_hid_close(struct hid_device *hid) clear_bit(I2C_HID_STARTED, &ihid->flags); /* Save some power */ i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); pm_runtime_put(&client->dev); } mutex_unlock(&i2c_hid_open_mut); } Loading @@ -738,19 +747,18 @@ static int i2c_hid_power(struct hid_device *hid, int lvl) { struct i2c_client *client = hid->driver_data; struct i2c_hid *ihid = i2c_get_clientdata(client); int ret = 0; i2c_hid_dbg(ihid, "%s lvl:%d\n", __func__, lvl); switch (lvl) { case PM_HINT_FULLON: ret = i2c_hid_set_power(client, I2C_HID_PWR_ON); pm_runtime_get_sync(&client->dev); break; case PM_HINT_NORMAL: ret = i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); pm_runtime_put(&client->dev); break; } return ret; return 0; } static struct hid_ll_driver i2c_hid_ll_driver = { Loading Loading @@ -987,13 +995,17 @@ static int i2c_hid_probe(struct i2c_client *client, if (ret < 0) goto err; pm_runtime_get_noresume(&client->dev); pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); ret = i2c_hid_fetch_hid_descriptor(ihid); if (ret < 0) goto err; goto err_pm; ret = i2c_hid_init_irq(client); if (ret < 0) goto err; goto err_pm; hid = hid_allocate_device(); if (IS_ERR(hid)) { Loading Loading @@ -1024,6 +1036,7 @@ static int i2c_hid_probe(struct i2c_client *client, goto err_mem_free; } pm_runtime_put(&client->dev); return 0; err_mem_free: Loading @@ -1032,6 +1045,10 @@ err_mem_free: err_irq: free_irq(client->irq, ihid); err_pm: pm_runtime_put_noidle(&client->dev); pm_runtime_disable(&client->dev); err: i2c_hid_free_buffers(ihid); kfree(ihid); Loading @@ -1043,6 +1060,11 @@ static int i2c_hid_remove(struct i2c_client *client) struct i2c_hid *ihid = i2c_get_clientdata(client); struct hid_device *hid; pm_runtime_get_sync(&client->dev); pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); pm_runtime_put_noidle(&client->dev); hid = ihid->hid; hid_destroy_device(hid); Loading Loading @@ -1088,7 +1110,31 @@ static int i2c_hid_resume(struct device *dev) } #endif static SIMPLE_DEV_PM_OPS(i2c_hid_pm, i2c_hid_suspend, i2c_hid_resume); #ifdef CONFIG_PM_RUNTIME static int i2c_hid_runtime_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); disable_irq(client->irq); return 0; } static int i2c_hid_runtime_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); enable_irq(client->irq); i2c_hid_set_power(client, I2C_HID_PWR_ON); return 0; } #endif static const struct dev_pm_ops i2c_hid_pm = { SET_SYSTEM_SLEEP_PM_OPS(i2c_hid_suspend, i2c_hid_resume) SET_RUNTIME_PM_OPS(i2c_hid_runtime_suspend, i2c_hid_runtime_resume, NULL) }; static const struct i2c_device_id i2c_hid_id_table[] = { { "hid", 0 }, Loading Loading
drivers/hid/i2c-hid/i2c-hid.c +57 −11 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <linux/delay.h> #include <linux/slab.h> #include <linux/pm.h> #include <linux/pm_runtime.h> #include <linux/device.h> #include <linux/wait.h> #include <linux/err.h> Loading Loading @@ -454,10 +455,18 @@ static void i2c_hid_init_reports(struct hid_device *hid) return; } /* * The device must be powered on while we fetch initial reports * from it. */ pm_runtime_get_sync(&client->dev); list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) i2c_hid_init_report(report, inbuf, ihid->bufsize); pm_runtime_put(&client->dev); kfree(inbuf); } Loading Loading @@ -703,8 +712,8 @@ static int i2c_hid_open(struct hid_device *hid) mutex_lock(&i2c_hid_open_mut); if (!hid->open++) { ret = i2c_hid_set_power(client, I2C_HID_PWR_ON); if (ret) { ret = pm_runtime_get_sync(&client->dev); if (ret < 0) { hid->open--; goto done; } Loading @@ -712,7 +721,7 @@ static int i2c_hid_open(struct hid_device *hid) } done: mutex_unlock(&i2c_hid_open_mut); return ret; return ret < 0 ? ret : 0; } static void i2c_hid_close(struct hid_device *hid) Loading @@ -729,7 +738,7 @@ static void i2c_hid_close(struct hid_device *hid) clear_bit(I2C_HID_STARTED, &ihid->flags); /* Save some power */ i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); pm_runtime_put(&client->dev); } mutex_unlock(&i2c_hid_open_mut); } Loading @@ -738,19 +747,18 @@ static int i2c_hid_power(struct hid_device *hid, int lvl) { struct i2c_client *client = hid->driver_data; struct i2c_hid *ihid = i2c_get_clientdata(client); int ret = 0; i2c_hid_dbg(ihid, "%s lvl:%d\n", __func__, lvl); switch (lvl) { case PM_HINT_FULLON: ret = i2c_hid_set_power(client, I2C_HID_PWR_ON); pm_runtime_get_sync(&client->dev); break; case PM_HINT_NORMAL: ret = i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); pm_runtime_put(&client->dev); break; } return ret; return 0; } static struct hid_ll_driver i2c_hid_ll_driver = { Loading Loading @@ -987,13 +995,17 @@ static int i2c_hid_probe(struct i2c_client *client, if (ret < 0) goto err; pm_runtime_get_noresume(&client->dev); pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); ret = i2c_hid_fetch_hid_descriptor(ihid); if (ret < 0) goto err; goto err_pm; ret = i2c_hid_init_irq(client); if (ret < 0) goto err; goto err_pm; hid = hid_allocate_device(); if (IS_ERR(hid)) { Loading Loading @@ -1024,6 +1036,7 @@ static int i2c_hid_probe(struct i2c_client *client, goto err_mem_free; } pm_runtime_put(&client->dev); return 0; err_mem_free: Loading @@ -1032,6 +1045,10 @@ err_mem_free: err_irq: free_irq(client->irq, ihid); err_pm: pm_runtime_put_noidle(&client->dev); pm_runtime_disable(&client->dev); err: i2c_hid_free_buffers(ihid); kfree(ihid); Loading @@ -1043,6 +1060,11 @@ static int i2c_hid_remove(struct i2c_client *client) struct i2c_hid *ihid = i2c_get_clientdata(client); struct hid_device *hid; pm_runtime_get_sync(&client->dev); pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); pm_runtime_put_noidle(&client->dev); hid = ihid->hid; hid_destroy_device(hid); Loading Loading @@ -1088,7 +1110,31 @@ static int i2c_hid_resume(struct device *dev) } #endif static SIMPLE_DEV_PM_OPS(i2c_hid_pm, i2c_hid_suspend, i2c_hid_resume); #ifdef CONFIG_PM_RUNTIME static int i2c_hid_runtime_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); disable_irq(client->irq); return 0; } static int i2c_hid_runtime_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); enable_irq(client->irq); i2c_hid_set_power(client, I2C_HID_PWR_ON); return 0; } #endif static const struct dev_pm_ops i2c_hid_pm = { SET_SYSTEM_SLEEP_PM_OPS(i2c_hid_suspend, i2c_hid_resume) SET_RUNTIME_PM_OPS(i2c_hid_runtime_suspend, i2c_hid_runtime_resume, NULL) }; static const struct i2c_device_id i2c_hid_id_table[] = { { "hid", 0 }, Loading