aboutsummaryrefslogtreecommitdiff
path: root/drivers/hid/hid-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hid-core.c')
-rw-r--r--drivers/hid/hid-core.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index bb6f334f05bd..e9b5f44683fd 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2027,7 +2027,8 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event);
static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
- u8 *data, u32 size, int interrupt, u64 source)
+ u8 *data, u32 size, int interrupt, u64 source,
+ bool lock_already_taken)
{
struct hid_report_enum *report_enum;
struct hid_driver *hdrv;
@@ -2037,8 +2038,13 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
if (!hid)
return -ENODEV;
- if (down_trylock(&hid->driver_input_lock))
+ ret = down_trylock(&hid->driver_input_lock);
+ if (lock_already_taken && !ret) {
+ up(&hid->driver_input_lock);
+ return -EINVAL;
+ } else if (!lock_already_taken && ret) {
return -EBUSY;
+ }
if (!hid->driver) {
ret = -ENODEV;
@@ -2079,7 +2085,8 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
ret = hid_report_raw_event(hid, type, data, size, interrupt);
unlock:
- up(&hid->driver_input_lock);
+ if (!lock_already_taken)
+ up(&hid->driver_input_lock);
return ret;
}
@@ -2097,7 +2104,8 @@ unlock:
int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
int interrupt)
{
- return __hid_input_report(hid, type, data, size, interrupt, 0);
+ return __hid_input_report(hid, type, data, size, interrupt, 0,
+ false /* lock_already_taken */);
}
EXPORT_SYMBOL_GPL(hid_input_report);