aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>2015-02-19 18:31:25 -0500
committerJiri Kosina <jkosina@suse.cz>2015-02-23 09:11:38 -0500
commite651a1da442ae02a50081e38309dea5e89da2d41 (patch)
treed4871274ef43f665a473a2a076b4c43343b5465b /drivers/hid
parent870fd0f5df4e131467612cc46db46fc3b69fd706 (diff)
HID: hid-sensor-hub: Allow parallel synchronous reads
Current implementation only allows one outstanding synchronous read. This is a performance hit when user mode is requesting raw reads of sensor attributes on multiple sensors together. This change changes the mutex lock to per hid sensor hub device instead of global lock. Although request to hid sensor hub is serialized, there can be multiple outstanding read requests pending for responses via hid reports. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Acked-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-sensor-hub.c90
1 files changed, 41 insertions, 49 deletions
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index 6a58b6c723aa..62fadf8c86fc 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -29,29 +29,10 @@
29#define HID_SENSOR_HUB_ENUM_QUIRK 0x01 29#define HID_SENSOR_HUB_ENUM_QUIRK 0x01
30 30
31/** 31/**
32 * struct sensor_hub_pending - Synchronous read pending information
33 * @status: Pending status true/false.
34 * @ready: Completion synchronization data.
35 * @usage_id: Usage id for physical device, E.g. Gyro usage id.
36 * @attr_usage_id: Usage Id of a field, E.g. X-AXIS for a gyro.
37 * @raw_size: Response size for a read request.
38 * @raw_data: Place holder for received response.
39 */
40struct sensor_hub_pending {
41 bool status;
42 struct completion ready;
43 u32 usage_id;
44 u32 attr_usage_id;
45 int raw_size;
46 u8 *raw_data;
47};
48
49/**
50 * struct sensor_hub_data - Hold a instance data for a HID hub device 32 * struct sensor_hub_data - Hold a instance data for a HID hub device
51 * @hsdev: Stored hid instance for current hub device. 33 * @hsdev: Stored hid instance for current hub device.
52 * @mutex: Mutex to serialize synchronous request. 34 * @mutex: Mutex to serialize synchronous request.
53 * @lock: Spin lock to protect pending request structure. 35 * @lock: Spin lock to protect pending request structure.
54 * @pending: Holds information of pending sync read request.
55 * @dyn_callback_list: Holds callback function 36 * @dyn_callback_list: Holds callback function
56 * @dyn_callback_lock: spin lock to protect callback list 37 * @dyn_callback_lock: spin lock to protect callback list
57 * @hid_sensor_hub_client_devs: Stores all MFD cells for a hub instance. 38 * @hid_sensor_hub_client_devs: Stores all MFD cells for a hub instance.
@@ -61,7 +42,6 @@ struct sensor_hub_pending {
61struct sensor_hub_data { 42struct sensor_hub_data {
62 struct mutex mutex; 43 struct mutex mutex;
63 spinlock_t lock; 44 spinlock_t lock;
64 struct sensor_hub_pending pending;
65 struct list_head dyn_callback_list; 45 struct list_head dyn_callback_list;
66 spinlock_t dyn_callback_lock; 46 spinlock_t dyn_callback_lock;
67 struct mfd_cell *hid_sensor_hub_client_devs; 47 struct mfd_cell *hid_sensor_hub_client_devs;
@@ -264,40 +244,42 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
264 struct hid_report *report; 244 struct hid_report *report;
265 int ret_val = 0; 245 int ret_val = 0;
266 246
267 mutex_lock(&data->mutex); 247 mutex_lock(&hsdev->mutex);
268 memset(&data->pending, 0, sizeof(data->pending)); 248 memset(&hsdev->pending, 0, sizeof(hsdev->pending));
269 init_completion(&data->pending.ready); 249 init_completion(&hsdev->pending.ready);
270 data->pending.usage_id = usage_id; 250 hsdev->pending.usage_id = usage_id;
271 data->pending.attr_usage_id = attr_usage_id; 251 hsdev->pending.attr_usage_id = attr_usage_id;
272 data->pending.raw_size = 0; 252 hsdev->pending.raw_size = 0;
273 253
274 spin_lock_irqsave(&data->lock, flags); 254 spin_lock_irqsave(&data->lock, flags);
275 data->pending.status = true; 255 hsdev->pending.status = true;
276 spin_unlock_irqrestore(&data->lock, flags); 256 spin_unlock_irqrestore(&data->lock, flags);
277 report = sensor_hub_report(report_id, hsdev->hdev, HID_INPUT_REPORT); 257 report = sensor_hub_report(report_id, hsdev->hdev, HID_INPUT_REPORT);
278 if (!report) 258 if (!report)
279 goto err_free; 259 goto err_free;
280 260
261 mutex_lock(&data->mutex);
281 hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT); 262 hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);
282 wait_for_completion_interruptible_timeout(&data->pending.ready, HZ*5); 263 mutex_unlock(&data->mutex);
283 switch (data->pending.raw_size) { 264 wait_for_completion_interruptible_timeout(&hsdev->pending.ready, HZ*5);
265 switch (hsdev->pending.raw_size) {
284 case 1: 266 case 1:
285 ret_val = *(u8 *)data->pending.raw_data; 267 ret_val = *(u8 *)hsdev->pending.raw_data;
286 break; 268 break;
287 case 2: 269 case 2:
288 ret_val = *(u16 *)data->pending.raw_data; 270 ret_val = *(u16 *)hsdev->pending.raw_data;
289 break; 271 break;
290 case 4: 272 case 4:
291 ret_val = *(u32 *)data->pending.raw_data; 273 ret_val = *(u32 *)hsdev->pending.raw_data;
292 break; 274 break;
293 default: 275 default:
294 ret_val = 0; 276 ret_val = 0;
295 } 277 }
296 kfree(data->pending.raw_data); 278 kfree(hsdev->pending.raw_data);
297 279
298err_free: 280err_free:
299 data->pending.status = false; 281 hsdev->pending.status = false;
300 mutex_unlock(&data->mutex); 282 mutex_unlock(&hsdev->mutex);
301 283
302 return ret_val; 284 return ret_val;
303} 285}
@@ -453,16 +435,6 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
453 report->field[i]->report_count)/8); 435 report->field[i]->report_count)/8);
454 sz = (report->field[i]->report_size * 436 sz = (report->field[i]->report_size *
455 report->field[i]->report_count)/8; 437 report->field[i]->report_count)/8;
456 if (pdata->pending.status && pdata->pending.attr_usage_id ==
457 report->field[i]->usage->hid) {
458 hid_dbg(hdev, "data was pending ...\n");
459 pdata->pending.raw_data = kmemdup(ptr, sz, GFP_ATOMIC);
460 if (pdata->pending.raw_data)
461 pdata->pending.raw_size = sz;
462 else
463 pdata->pending.raw_size = 0;
464 complete(&pdata->pending.ready);
465 }
466 collection = &hdev->collection[ 438 collection = &hdev->collection[
467 report->field[i]->usage->collection_index]; 439 report->field[i]->usage->collection_index];
468 hid_dbg(hdev, "collection->usage %x\n", 440 hid_dbg(hdev, "collection->usage %x\n",
@@ -472,8 +444,21 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
472 report->field[i]->physical, 444 report->field[i]->physical,
473 report->field[i]->usage[0].collection_index, 445 report->field[i]->usage[0].collection_index,
474 &hsdev, &priv); 446 &hsdev, &priv);
475 447 if (!callback) {
476 if (callback && callback->capture_sample) { 448 ptr += sz;
449 continue;
450 }
451 if (hsdev->pending.status && hsdev->pending.attr_usage_id ==
452 report->field[i]->usage->hid) {
453 hid_dbg(hdev, "data was pending ...\n");
454 hsdev->pending.raw_data = kmemdup(ptr, sz, GFP_ATOMIC);
455 if (hsdev->pending.raw_data)
456 hsdev->pending.raw_size = sz;
457 else
458 hsdev->pending.raw_size = 0;
459 complete(&hsdev->pending.ready);
460 }
461 if (callback->capture_sample) {
477 if (report->field[i]->logical) 462 if (report->field[i]->logical)
478 callback->capture_sample(hsdev, 463 callback->capture_sample(hsdev,
479 report->field[i]->logical, sz, ptr, 464 report->field[i]->logical, sz, ptr,
@@ -628,6 +613,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
628 hsdev->hdev = hdev; 613 hsdev->hdev = hdev;
629 hsdev->vendor_id = hdev->vendor; 614 hsdev->vendor_id = hdev->vendor;
630 hsdev->product_id = hdev->product; 615 hsdev->product_id = hdev->product;
616 hsdev->usage = collection->usage;
617 mutex_init(&hsdev->mutex);
631 hsdev->start_collection_index = i; 618 hsdev->start_collection_index = i;
632 if (last_hsdev) 619 if (last_hsdev)
633 last_hsdev->end_collection_index = i; 620 last_hsdev->end_collection_index = i;
@@ -674,13 +661,18 @@ static void sensor_hub_remove(struct hid_device *hdev)
674{ 661{
675 struct sensor_hub_data *data = hid_get_drvdata(hdev); 662 struct sensor_hub_data *data = hid_get_drvdata(hdev);
676 unsigned long flags; 663 unsigned long flags;
664 int i;
677 665
678 hid_dbg(hdev, " hardware removed\n"); 666 hid_dbg(hdev, " hardware removed\n");
679 hid_hw_close(hdev); 667 hid_hw_close(hdev);
680 hid_hw_stop(hdev); 668 hid_hw_stop(hdev);
681 spin_lock_irqsave(&data->lock, flags); 669 spin_lock_irqsave(&data->lock, flags);
682 if (data->pending.status) 670 for (i = 0; i < data->hid_sensor_client_cnt; ++i) {
683 complete(&data->pending.ready); 671 struct hid_sensor_hub_device *hsdev =
672 data->hid_sensor_hub_client_devs[i].platform_data;
673 if (hsdev->pending.status)
674 complete(&hsdev->pending.ready);
675 }
684 spin_unlock_irqrestore(&data->lock, flags); 676 spin_unlock_irqrestore(&data->lock, flags);
685 mfd_remove_devices(&hdev->dev); 677 mfd_remove_devices(&hdev->dev);
686 hid_set_drvdata(hdev, NULL); 678 hid_set_drvdata(hdev, NULL);