aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorRodrigo Rivas Costa <rodrigorivascosta@gmail.com>2019-03-15 15:09:10 -0400
committerJiri Kosina <jkosina@suse.cz>2019-03-18 09:44:20 -0400
commit6b538cc21334b83f09b25dec4aa2d2726bf07ed0 (patch)
tree85cbcab21717ac86e29150b177fabf499e7678fc /drivers/hid
parent1cbbd85fbcdce186649ce778ff1e08e3df35d285 (diff)
HID: steam: fix deadlock with input devices.
When using this driver with the wireless dongle and some usermode program that monitors every input device (acpid, for example), while another usermode client opens and closes the low-level device repeadedly, the system eventually deadlocks. The reason is that steam_input_register_device() must not be called with the mutex held, because the input subsystem has its own synchronization that clashes with this one: it is possible that steam_input_open() is called before input_register_device() returns, and since steam_input_open() needs to lock the mutex, it deadlocks. However we must hold the mutex when calling any function that sends commands to the controller. If not, random commands end up falling fail. Reported-by: Simon Gene Gottlieb <simon@gottliebtfreitag.de> Signed-off-by: Rodrigo Rivas Costa <rodrigorivascosta@gmail.com> Tested-by: Simon Gene Gottlieb <simon@gottliebtfreitag.de> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-steam.c26
1 files changed, 19 insertions, 7 deletions
diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
index 8141cadfca0e..8dae0f9b819e 100644
--- a/drivers/hid/hid-steam.c
+++ b/drivers/hid/hid-steam.c
@@ -499,6 +499,7 @@ static void steam_battery_unregister(struct steam_device *steam)
499static int steam_register(struct steam_device *steam) 499static int steam_register(struct steam_device *steam)
500{ 500{
501 int ret; 501 int ret;
502 bool client_opened;
502 503
503 /* 504 /*
504 * This function can be called several times in a row with the 505 * This function can be called several times in a row with the
@@ -511,9 +512,11 @@ static int steam_register(struct steam_device *steam)
511 * Unlikely, but getting the serial could fail, and it is not so 512 * Unlikely, but getting the serial could fail, and it is not so
512 * important, so make up a serial number and go on. 513 * important, so make up a serial number and go on.
513 */ 514 */
515 mutex_lock(&steam->mutex);
514 if (steam_get_serial(steam) < 0) 516 if (steam_get_serial(steam) < 0)
515 strlcpy(steam->serial_no, "XXXXXXXXXX", 517 strlcpy(steam->serial_no, "XXXXXXXXXX",
516 sizeof(steam->serial_no)); 518 sizeof(steam->serial_no));
519 mutex_unlock(&steam->mutex);
517 520
518 hid_info(steam->hdev, "Steam Controller '%s' connected", 521 hid_info(steam->hdev, "Steam Controller '%s' connected",
519 steam->serial_no); 522 steam->serial_no);
@@ -528,13 +531,15 @@ static int steam_register(struct steam_device *steam)
528 } 531 }
529 532
530 mutex_lock(&steam->mutex); 533 mutex_lock(&steam->mutex);
531 if (!steam->client_opened) { 534 client_opened = steam->client_opened;
535 if (!client_opened)
532 steam_set_lizard_mode(steam, lizard_mode); 536 steam_set_lizard_mode(steam, lizard_mode);
537 mutex_unlock(&steam->mutex);
538
539 if (!client_opened)
533 ret = steam_input_register(steam); 540 ret = steam_input_register(steam);
534 } else { 541 else
535 ret = 0; 542 ret = 0;
536 }
537 mutex_unlock(&steam->mutex);
538 543
539 return ret; 544 return ret;
540} 545}
@@ -630,14 +635,21 @@ static void steam_client_ll_close(struct hid_device *hdev)
630{ 635{
631 struct steam_device *steam = hdev->driver_data; 636 struct steam_device *steam = hdev->driver_data;
632 637
638 unsigned long flags;
639 bool connected;
640
641 spin_lock_irqsave(&steam->lock, flags);
642 connected = steam->connected;
643 spin_unlock_irqrestore(&steam->lock, flags);
644
633 mutex_lock(&steam->mutex); 645 mutex_lock(&steam->mutex);
634 steam->client_opened = false; 646 steam->client_opened = false;
647 if (connected)
648 steam_set_lizard_mode(steam, lizard_mode);
635 mutex_unlock(&steam->mutex); 649 mutex_unlock(&steam->mutex);
636 650
637 if (steam->connected) { 651 if (connected)
638 steam_set_lizard_mode(steam, lizard_mode);
639 steam_input_register(steam); 652 steam_input_register(steam);
640 }
641} 653}
642 654
643static int steam_client_ll_raw_request(struct hid_device *hdev, 655static int steam_client_ll_raw_request(struct hid_device *hdev,