aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcus Folkesson <marcus.folkesson@gmail.com>2018-03-17 13:49:46 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2018-03-17 14:05:18 -0400
commitb8a7cc4b5e5a0681fdeffe92b613e3e4eb769801 (patch)
tree64fa737a3a633e60a11682413d9ed1d8d33c36dd
parentba521f1bd202237d2c1dea95e4213169b8c6ba01 (diff)
Input: synaptics_usb - fix deadlock in autosuspend
usb_autopm_get_interface() that is called in synusb_open() does an autoresume if the device is suspended. input_dev->mutex used in synusb_resume() is in this case already taken by the input subsystem and will cause a deadlock. Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/mouse/synaptics_usb.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/drivers/input/mouse/synaptics_usb.c b/drivers/input/mouse/synaptics_usb.c
index cb7d15d826d0..2c66913cf5a2 100644
--- a/drivers/input/mouse/synaptics_usb.c
+++ b/drivers/input/mouse/synaptics_usb.c
@@ -82,6 +82,9 @@ struct synusb {
82 struct urb *urb; 82 struct urb *urb;
83 unsigned char *data; 83 unsigned char *data;
84 84
85 /* serialize access to open/suspend */
86 struct mutex pm_mutex;
87
85 /* input device related data structures */ 88 /* input device related data structures */
86 struct input_dev *input; 89 struct input_dev *input;
87 char name[128]; 90 char name[128];
@@ -252,6 +255,7 @@ static int synusb_open(struct input_dev *dev)
252 return retval; 255 return retval;
253 } 256 }
254 257
258 mutex_lock(&synusb->pm_mutex);
255 retval = usb_submit_urb(synusb->urb, GFP_KERNEL); 259 retval = usb_submit_urb(synusb->urb, GFP_KERNEL);
256 if (retval) { 260 if (retval) {
257 dev_err(&synusb->intf->dev, 261 dev_err(&synusb->intf->dev,
@@ -264,6 +268,7 @@ static int synusb_open(struct input_dev *dev)
264 synusb->intf->needs_remote_wakeup = 1; 268 synusb->intf->needs_remote_wakeup = 1;
265 269
266out: 270out:
271 mutex_unlock(&synusb->pm_mutex);
267 usb_autopm_put_interface(synusb->intf); 272 usb_autopm_put_interface(synusb->intf);
268 return retval; 273 return retval;
269} 274}
@@ -275,8 +280,10 @@ static void synusb_close(struct input_dev *dev)
275 280
276 autopm_error = usb_autopm_get_interface(synusb->intf); 281 autopm_error = usb_autopm_get_interface(synusb->intf);
277 282
283 mutex_lock(&synusb->pm_mutex);
278 usb_kill_urb(synusb->urb); 284 usb_kill_urb(synusb->urb);
279 synusb->intf->needs_remote_wakeup = 0; 285 synusb->intf->needs_remote_wakeup = 0;
286 mutex_unlock(&synusb->pm_mutex);
280 287
281 if (!autopm_error) 288 if (!autopm_error)
282 usb_autopm_put_interface(synusb->intf); 289 usb_autopm_put_interface(synusb->intf);
@@ -315,6 +322,7 @@ static int synusb_probe(struct usb_interface *intf,
315 synusb->udev = udev; 322 synusb->udev = udev;
316 synusb->intf = intf; 323 synusb->intf = intf;
317 synusb->input = input_dev; 324 synusb->input = input_dev;
325 mutex_init(&synusb->pm_mutex);
318 326
319 synusb->flags = id->driver_info; 327 synusb->flags = id->driver_info;
320 if (synusb->flags & SYNUSB_COMBO) { 328 if (synusb->flags & SYNUSB_COMBO) {
@@ -466,11 +474,10 @@ static void synusb_disconnect(struct usb_interface *intf)
466static int synusb_suspend(struct usb_interface *intf, pm_message_t message) 474static int synusb_suspend(struct usb_interface *intf, pm_message_t message)
467{ 475{
468 struct synusb *synusb = usb_get_intfdata(intf); 476 struct synusb *synusb = usb_get_intfdata(intf);
469 struct input_dev *input_dev = synusb->input;
470 477
471 mutex_lock(&input_dev->mutex); 478 mutex_lock(&synusb->pm_mutex);
472 usb_kill_urb(synusb->urb); 479 usb_kill_urb(synusb->urb);
473 mutex_unlock(&input_dev->mutex); 480 mutex_unlock(&synusb->pm_mutex);
474 481
475 return 0; 482 return 0;
476} 483}
@@ -481,14 +488,14 @@ static int synusb_resume(struct usb_interface *intf)
481 struct input_dev *input_dev = synusb->input; 488 struct input_dev *input_dev = synusb->input;
482 int retval = 0; 489 int retval = 0;
483 490
484 mutex_lock(&input_dev->mutex); 491 mutex_lock(&synusb->pm_mutex);
485 492
486 if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) && 493 if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) &&
487 usb_submit_urb(synusb->urb, GFP_NOIO) < 0) { 494 usb_submit_urb(synusb->urb, GFP_NOIO) < 0) {
488 retval = -EIO; 495 retval = -EIO;
489 } 496 }
490 497
491 mutex_unlock(&input_dev->mutex); 498 mutex_unlock(&synusb->pm_mutex);
492 499
493 return retval; 500 return retval;
494} 501}
@@ -496,9 +503,8 @@ static int synusb_resume(struct usb_interface *intf)
496static int synusb_pre_reset(struct usb_interface *intf) 503static int synusb_pre_reset(struct usb_interface *intf)
497{ 504{
498 struct synusb *synusb = usb_get_intfdata(intf); 505 struct synusb *synusb = usb_get_intfdata(intf);
499 struct input_dev *input_dev = synusb->input;
500 506
501 mutex_lock(&input_dev->mutex); 507 mutex_lock(&synusb->pm_mutex);
502 usb_kill_urb(synusb->urb); 508 usb_kill_urb(synusb->urb);
503 509
504 return 0; 510 return 0;
@@ -515,7 +521,7 @@ static int synusb_post_reset(struct usb_interface *intf)
515 retval = -EIO; 521 retval = -EIO;
516 } 522 }
517 523
518 mutex_unlock(&input_dev->mutex); 524 mutex_unlock(&synusb->pm_mutex);
519 525
520 return retval; 526 return retval;
521} 527}