Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f6cd3783 authored by Dmitry Torokhov's avatar Dmitry Torokhov
Browse files

Input: wacom - fix runtime PM related deadlock



When runtime PM is enabled by default for input devices, X hangs in
wacom open:
[<ffffffff814a00ea>] mutex_lock+0x1a/0x40
[<ffffffffa02bc94b>] wacom_resume+0x3b/0x90 [wacom]
[<ffffffff81327a32>] usb_resume_interface+0xd2/0x190
[<ffffffff81327b5d>] usb_resume_both+0x6d/0x110
[<ffffffff81327c24>] usb_runtime_resume+0x24/0x40
[<ffffffff8130a2cf>] __pm_runtime_resume+0x26f/0x450
[<ffffffff8130a23a>] __pm_runtime_resume+0x1da/0x450
[<ffffffff8130a53a>] pm_runtime_resume+0x2a/0x50
[<ffffffff81328176>] usb_autopm_get_interface+0x26/0x60
[<ffffffffa02bc626>] wacom_open+0x36/0x90 [wacom]

wacom_open() takes wacom->lock and calls usb_autopm_get_interface(),
which in turn calls wacom_resume() which tries to acquire the lock
again.

The fix is to call usb_autopm_get_interface() first, before we take
the lock.

Since we do not do usb_autopm_put_interface() until wacom_close()
is called runtime PM is effectively disabled for the driver, however
changing it now would risk regressions so the complete fix will
have to wait till the next merge window.

Reported-by: default avatarJiri Slaby <jslaby@suse.cz>
Acked-by: default avatarOliver Neukum <oneukum@suse.de>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent d2520a42
Loading
Loading
Loading
Loading
+12 −11
Original line number Diff line number Diff line
@@ -103,27 +103,26 @@ static void wacom_sys_irq(struct urb *urb)
static int wacom_open(struct input_dev *dev)
{
	struct wacom *wacom = input_get_drvdata(dev);
	int retval = 0;

	mutex_lock(&wacom->lock);

	wacom->irq->dev = wacom->usbdev;

	if (usb_autopm_get_interface(wacom->intf) < 0) {
		mutex_unlock(&wacom->lock);
	if (usb_autopm_get_interface(wacom->intf) < 0)
		return -EIO;
	}

	mutex_lock(&wacom->lock);

	if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
		usb_autopm_put_interface(wacom->intf);
		mutex_unlock(&wacom->lock);
		return -EIO;
		retval = -EIO;
		goto out;
	}

	wacom->open = true;
	wacom->intf->needs_remote_wakeup = 1;

out:
	mutex_unlock(&wacom->lock);
	return 0;
	if (retval)
		usb_autopm_put_interface(wacom->intf);
	return retval;
}

static void wacom_close(struct input_dev *dev)
@@ -135,6 +134,8 @@ static void wacom_close(struct input_dev *dev)
	wacom->open = false;
	wacom->intf->needs_remote_wakeup = 0;
	mutex_unlock(&wacom->lock);

	usb_autopm_put_interface(wacom->intf);
}

static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc,