diff options
author | Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> | 2014-03-24 16:25:04 -0700 |
---|---|---|
committer | Jiri Slaby <jslaby@suse.cz> | 2015-07-30 14:10:56 +0200 |
commit | ae432ba6bc105f7279ed729ae47a8c9e42ac6c22 (patch) | |
tree | 6240236884b978d709b9299dc8b827d161a90621 /drivers | |
parent | 13ae2b524788cb3b279cdb2529edd4b418e51251 (diff) |
HID: hid-sensor-hub: fix sleeping function called from invalid context
commit f74346a04b79c9a5e50a2ee5e923b94195975d17 upstream.
Fix issue with the sleeping calling hid_hw_request under spinlock.
When i2c is used as HID transport, this is calling kmalloc, which
can sleep. So remove call to this function while under spinlock.
[ 1067.021961] Call Trace:
[ 1067.021970] [<ffffffff8192f5f2>] dump_stack+0x4d/0x6f
[ 1067.021976] [<ffffffff811109f2>] __might_sleep+0xd2/0xf0
[ 1067.021981] [<ffffffff811ea15b>] __kmalloc+0xeb/0x200
[ 1067.021989] [<ffffffff816e0cb3>] ? hid_alloc_report_buf+0x23/0x30
[ 1067.021993] [<ffffffff816e0cb3>] hid_alloc_report_buf+0x23/0x30
[ 1067.021997] [<ffffffff816f4cb7>] i2c_hid_request+0x57/0x110
[ 1067.022006] [<ffffffffa02bc61c>] sensor_hub_input_attr_get_raw_value+0xbc/0x100 [hid_sensor_hub]
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Cc: Oliver Neukum <ONeukum@suse.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hid/hid-sensor-hub.c | 7 |
1 files changed, 3 insertions, 4 deletions
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 9e4cdca549c0..fe8618c5b5c1 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -255,13 +255,12 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev, spin_lock_irqsave(&data->lock, flags); data->pending.status = true; + spin_unlock_irqrestore(&data->lock, flags); report = sensor_hub_report(report_id, hsdev->hdev, HID_INPUT_REPORT); - if (!report) { - spin_unlock_irqrestore(&data->lock, flags); + if (!report) goto err_free; - } + hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT); - spin_unlock_irqrestore(&data->lock, flags); wait_for_completion_interruptible_timeout(&data->pending.ready, HZ*5); switch (data->pending.raw_size) { case 1: |