aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiner Kallweit <hkallweit1@gmail.com>2016-03-01 14:49:54 -0500
committerJiri Kosina <jkosina@suse.cz>2016-03-02 04:20:31 -0500
commit43a4a04d4ddb268373d5857c7a7bcbe3658e5b48 (patch)
tree7bcaa4f2b7774bdfddb465b903c79e9fd05ff83e
parentc46fab28703bf12772b3bdbeabcf90df9cd20d58 (diff)
HID: thingm: improve locking
Reading from the device consists of two operations: sending the read command and the actual read from the device. If the device is accessed in between we might read wrong data. Therefore protect the full sequence of both operations with a mutex. Also change the semantics of thingm_recv to include both operations. Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-thingm.c33
1 files changed, 22 insertions, 11 deletions
diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c
index 5e35ec1b6d8a..f4196ac25a64 100644
--- a/drivers/hid/hid-thingm.c
+++ b/drivers/hid/hid-thingm.c
@@ -77,9 +77,13 @@ static int thingm_send(struct thingm_device *tdev, u8 buf[REPORT_SIZE])
77 buf[0], buf[1], buf[2], buf[3], buf[4], 77 buf[0], buf[1], buf[2], buf[3], buf[4],
78 buf[5], buf[6], buf[7], buf[8]); 78 buf[5], buf[6], buf[7], buf[8]);
79 79
80 mutex_lock(&tdev->lock);
81
80 ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE, 82 ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
81 HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 83 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
82 84
85 mutex_unlock(&tdev->lock);
86
83 return ret < 0 ? ret : 0; 87 return ret < 0 ? ret : 0;
84} 88}
85 89
@@ -87,16 +91,31 @@ static int thingm_recv(struct thingm_device *tdev, u8 buf[REPORT_SIZE])
87{ 91{
88 int ret; 92 int ret;
89 93
94 /*
95 * A read consists of two operations: sending the read command
96 * and the actual read from the device. Use the mutex to protect
97 * the full sequence of both operations.
98 */
99 mutex_lock(&tdev->lock);
100
101 ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
102 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
103 if (ret < 0)
104 goto err;
105
90 ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE, 106 ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
91 HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 107 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
92 if (ret < 0) 108 if (ret < 0)
93 return ret; 109 goto err;
110
111 ret = 0;
94 112
95 hid_dbg(tdev->hdev, "<- %d %c %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n", 113 hid_dbg(tdev->hdev, "<- %d %c %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n",
96 buf[0], buf[1], buf[2], buf[3], buf[4], 114 buf[0], buf[1], buf[2], buf[3], buf[4],
97 buf[5], buf[6], buf[7], buf[8]); 115 buf[5], buf[6], buf[7], buf[8]);
98 116err:
99 return 0; 117 mutex_unlock(&tdev->lock);
118 return ret;
100} 119}
101 120
102static int thingm_version(struct thingm_device *tdev) 121static int thingm_version(struct thingm_device *tdev)
@@ -104,10 +123,6 @@ static int thingm_version(struct thingm_device *tdev)
104 u8 buf[REPORT_SIZE] = { REPORT_ID, 'v', 0, 0, 0, 0, 0, 0, 0 }; 123 u8 buf[REPORT_SIZE] = { REPORT_ID, 'v', 0, 0, 0, 0, 0, 0, 0 };
105 int err; 124 int err;
106 125
107 err = thingm_send(tdev, buf);
108 if (err)
109 return err;
110
111 err = thingm_recv(tdev, buf); 126 err = thingm_recv(tdev, buf);
112 if (err) 127 if (err)
113 return err; 128 return err;
@@ -135,14 +150,10 @@ static int thingm_led_set(struct led_classdev *ldev,
135 struct thingm_led *led = container_of(ldev, struct thingm_led, ldev); 150 struct thingm_led *led = container_of(ldev, struct thingm_led, ldev);
136 int ret; 151 int ret;
137 152
138 mutex_lock(&led->rgb->tdev->lock);
139
140 ret = thingm_write_color(led->rgb); 153 ret = thingm_write_color(led->rgb);
141 if (ret) 154 if (ret)
142 hid_err(led->rgb->tdev->hdev, "failed to write color\n"); 155 hid_err(led->rgb->tdev->hdev, "failed to write color\n");
143 156
144 mutex_unlock(&led->rgb->tdev->lock);
145
146 return ret; 157 return ret;
147} 158}
148 159