aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-08-02 17:22:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-08-02 17:22:15 -0400
commitf9ed432c929f005110c23eb00702265fc4c08e66 (patch)
tree060e6787d0fe75c3a65827aaa9d51620cc3b6df7 /drivers/hid
parent940e84fc2681d5265a602a287e0204569ca215fa (diff)
parente6dfb04360bb265c2e931316369c877b3bb7159c (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID fixes from Jiri Kosina: - fix hid-sony PS3 sixaxxis breakage from Benjamin Tissories - fix hidraw race condition from Yonghua Zheng - fix/bandaid for rare device enumeration problems of Logitech Unifying receivers from Nestor Lopez Casado * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: HID: hidraw: fix improper mutex release HID: sony: fix HID mapping for PS3 sixaxis controller HID: hid-logitech-dj: querying_devices was never set HID: Revert "Revert "HID: Fix logitech-dj: missing Unifying device issue""
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-logitech-dj.c47
-rw-r--r--drivers/hid/hid-logitech-dj.h1
-rw-r--r--drivers/hid/hid-sony.c3
-rw-r--r--drivers/hid/hidraw.c2
4 files changed, 51 insertions, 2 deletions
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 5207591a598c..7a5764843bfb 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -192,6 +192,7 @@ static struct hid_ll_driver logi_dj_ll_driver;
192static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, 192static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
193 size_t count, 193 size_t count,
194 unsigned char report_type); 194 unsigned char report_type);
195static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev);
195 196
196static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, 197static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
197 struct dj_report *dj_report) 198 struct dj_report *dj_report)
@@ -232,6 +233,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
232 if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & 233 if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
233 SPFUNCTION_DEVICE_LIST_EMPTY) { 234 SPFUNCTION_DEVICE_LIST_EMPTY) {
234 dbg_hid("%s: device list is empty\n", __func__); 235 dbg_hid("%s: device list is empty\n", __func__);
236 djrcv_dev->querying_devices = false;
235 return; 237 return;
236 } 238 }
237 239
@@ -242,6 +244,12 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
242 return; 244 return;
243 } 245 }
244 246
247 if (djrcv_dev->paired_dj_devices[dj_report->device_index]) {
248 /* The device is already known. No need to reallocate it. */
249 dbg_hid("%s: device is already known\n", __func__);
250 return;
251 }
252
245 dj_hiddev = hid_allocate_device(); 253 dj_hiddev = hid_allocate_device();
246 if (IS_ERR(dj_hiddev)) { 254 if (IS_ERR(dj_hiddev)) {
247 dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", 255 dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n",
@@ -305,6 +313,7 @@ static void delayedwork_callback(struct work_struct *work)
305 struct dj_report dj_report; 313 struct dj_report dj_report;
306 unsigned long flags; 314 unsigned long flags;
307 int count; 315 int count;
316 int retval;
308 317
309 dbg_hid("%s\n", __func__); 318 dbg_hid("%s\n", __func__);
310 319
@@ -337,6 +346,25 @@ static void delayedwork_callback(struct work_struct *work)
337 logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); 346 logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
338 break; 347 break;
339 default: 348 default:
349 /* A normal report (i. e. not belonging to a pair/unpair notification)
350 * arriving here, means that the report arrived but we did not have a
351 * paired dj_device associated to the report's device_index, this
352 * means that the original "device paired" notification corresponding
353 * to this dj_device never arrived to this driver. The reason is that
354 * hid-core discards all packets coming from a device while probe() is
355 * executing. */
356 if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) {
357 /* ok, we don't know the device, just re-ask the
358 * receiver for the list of connected devices. */
359 retval = logi_dj_recv_query_paired_devices(djrcv_dev);
360 if (!retval) {
361 /* everything went fine, so just leave */
362 break;
363 }
364 dev_err(&djrcv_dev->hdev->dev,
365 "%s:logi_dj_recv_query_paired_devices "
366 "error:%d\n", __func__, retval);
367 }
340 dbg_hid("%s: unexpected report type\n", __func__); 368 dbg_hid("%s: unexpected report type\n", __func__);
341 } 369 }
342} 370}
@@ -367,6 +395,12 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev,
367 if (!djdev) { 395 if (!djdev) {
368 dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" 396 dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
369 " is NULL, index %d\n", dj_report->device_index); 397 " is NULL, index %d\n", dj_report->device_index);
398 kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
399
400 if (schedule_work(&djrcv_dev->work) == 0) {
401 dbg_hid("%s: did not schedule the work item, was already "
402 "queued\n", __func__);
403 }
370 return; 404 return;
371 } 405 }
372 406
@@ -397,6 +431,12 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev,
397 if (dj_device == NULL) { 431 if (dj_device == NULL) {
398 dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" 432 dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
399 " is NULL, index %d\n", dj_report->device_index); 433 " is NULL, index %d\n", dj_report->device_index);
434 kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
435
436 if (schedule_work(&djrcv_dev->work) == 0) {
437 dbg_hid("%s: did not schedule the work item, was already "
438 "queued\n", __func__);
439 }
400 return; 440 return;
401 } 441 }
402 442
@@ -444,6 +484,12 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
444 struct dj_report *dj_report; 484 struct dj_report *dj_report;
445 int retval; 485 int retval;
446 486
487 /* no need to protect djrcv_dev->querying_devices */
488 if (djrcv_dev->querying_devices)
489 return 0;
490
491 djrcv_dev->querying_devices = true;
492
447 dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); 493 dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
448 if (!dj_report) 494 if (!dj_report)
449 return -ENOMEM; 495 return -ENOMEM;
@@ -455,6 +501,7 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
455 return retval; 501 return retval;
456} 502}
457 503
504
458static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, 505static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
459 unsigned timeout) 506 unsigned timeout)
460{ 507{
diff --git a/drivers/hid/hid-logitech-dj.h b/drivers/hid/hid-logitech-dj.h
index fd28a5e0ca3b..4a4000340ce1 100644
--- a/drivers/hid/hid-logitech-dj.h
+++ b/drivers/hid/hid-logitech-dj.h
@@ -101,6 +101,7 @@ struct dj_receiver_dev {
101 struct work_struct work; 101 struct work_struct work;
102 struct kfifo notif_fifo; 102 struct kfifo notif_fifo;
103 spinlock_t lock; 103 spinlock_t lock;
104 bool querying_devices;
104}; 105};
105 106
106struct dj_device { 107struct dj_device {
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index ecbc74923d06..87fbe2924cfa 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -369,7 +369,8 @@ static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
369 if (sc->quirks & PS3REMOTE) 369 if (sc->quirks & PS3REMOTE)
370 return ps3remote_mapping(hdev, hi, field, usage, bit, max); 370 return ps3remote_mapping(hdev, hi, field, usage, bit, max);
371 371
372 return -1; 372 /* Let hid-core decide for the others */
373 return 0;
373} 374}
374 375
375/* 376/*
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index a7451632ceb4..6f1feb2c2e97 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -518,7 +518,6 @@ int hidraw_connect(struct hid_device *hid)
518 goto out; 518 goto out;
519 } 519 }
520 520
521 mutex_unlock(&minors_lock);
522 init_waitqueue_head(&dev->wait); 521 init_waitqueue_head(&dev->wait);
523 INIT_LIST_HEAD(&dev->list); 522 INIT_LIST_HEAD(&dev->list);
524 523
@@ -528,6 +527,7 @@ int hidraw_connect(struct hid_device *hid)
528 dev->exist = 1; 527 dev->exist = 1;
529 hid->hidraw = dev; 528 hid->hidraw = dev;
530 529
530 mutex_unlock(&minors_lock);
531out: 531out:
532 return result; 532 return result;
533 533