浏览代码

HID: remove setup mutex, fix possible deadlock

It causes recursive locking warning and is unneeded after
introduction of STARTED flag.

* Resume vs. stop is effectively solved by DISCONNECT flag.
* No problem in suspend vs. start -- urb is submitted even after open
  which is possible after connect which is called after start.
* Resume vs. start solved by STARTED flag.
* Suspend vs. stop -- no problem in killing urb and timer twice.

Reported-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Jiri Slaby 16 年之前
父节点
当前提交
fde5be353e
共有 2 个文件被更改,包括 2 次插入17 次删除
  1. 2 16
      drivers/hid/usbhid/hid-core.c
  2. 0 1
      drivers/hid/usbhid/usbhid.h

+ 2 - 16
drivers/hid/usbhid/hid-core.c

@@ -796,7 +796,6 @@ static int usbhid_start(struct hid_device *hid)
 	if (insize > HID_MAX_BUFFER_SIZE)
 	if (insize > HID_MAX_BUFFER_SIZE)
 		insize = HID_MAX_BUFFER_SIZE;
 		insize = HID_MAX_BUFFER_SIZE;
 
 
-	mutex_lock(&usbhid->setup);
 	if (hid_alloc_buffers(dev, hid)) {
 	if (hid_alloc_buffers(dev, hid)) {
 		ret = -ENOMEM;
 		ret = -ENOMEM;
 		goto fail;
 		goto fail;
@@ -876,7 +875,6 @@ static int usbhid_start(struct hid_device *hid)
 	hid_dump_device(hid);
 	hid_dump_device(hid);
 
 
 	set_bit(HID_STARTED, &usbhid->iofl);
 	set_bit(HID_STARTED, &usbhid->iofl);
-	mutex_unlock(&usbhid->setup);
 
 
 	return 0;
 	return 0;
 
 
@@ -888,7 +886,6 @@ fail:
 	usbhid->urbout = NULL;
 	usbhid->urbout = NULL;
 	usbhid->urbctrl = NULL;
 	usbhid->urbctrl = NULL;
 	hid_free_buffers(dev, hid);
 	hid_free_buffers(dev, hid);
-	mutex_unlock(&usbhid->setup);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -899,7 +896,6 @@ static void usbhid_stop(struct hid_device *hid)
 	if (WARN_ON(!usbhid))
 	if (WARN_ON(!usbhid))
 		return;
 		return;
 
 
-	mutex_lock(&usbhid->setup);
 	clear_bit(HID_STARTED, &usbhid->iofl);
 	clear_bit(HID_STARTED, &usbhid->iofl);
 	spin_lock_irq(&usbhid->inlock);	/* Sync with error handler */
 	spin_lock_irq(&usbhid->inlock);	/* Sync with error handler */
 	set_bit(HID_DISCONNECTED, &usbhid->iofl);
 	set_bit(HID_DISCONNECTED, &usbhid->iofl);
@@ -928,7 +924,6 @@ static void usbhid_stop(struct hid_device *hid)
 	usbhid->urbout = NULL;
 	usbhid->urbout = NULL;
 
 
 	hid_free_buffers(hid_to_usb_dev(hid), hid);
 	hid_free_buffers(hid_to_usb_dev(hid), hid);
-	mutex_unlock(&usbhid->setup);
 }
 }
 
 
 static struct hid_ll_driver usb_hid_driver = {
 static struct hid_ll_driver usb_hid_driver = {
@@ -1016,7 +1011,6 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
 
 
 	hid->driver_data = usbhid;
 	hid->driver_data = usbhid;
 	usbhid->hid = hid;
 	usbhid->hid = hid;
-	mutex_init(&usbhid->setup); /* needed on suspend/resume */
 
 
 	ret = hid_add_device(hid);
 	ret = hid_add_device(hid);
 	if (ret) {
 	if (ret) {
@@ -1051,18 +1045,14 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
 	struct hid_device *hid = usb_get_intfdata (intf);
 	struct hid_device *hid = usb_get_intfdata (intf);
 	struct usbhid_device *usbhid = hid->driver_data;
 	struct usbhid_device *usbhid = hid->driver_data;
 
 
-	mutex_lock(&usbhid->setup);
-	if (!test_bit(HID_STARTED, &usbhid->iofl)) {
-		mutex_unlock(&usbhid->setup);
+	if (!test_bit(HID_STARTED, &usbhid->iofl))
 		return 0;
 		return 0;
-	}
 
 
 	spin_lock_irq(&usbhid->inlock);	/* Sync with error handler */
 	spin_lock_irq(&usbhid->inlock);	/* Sync with error handler */
 	set_bit(HID_SUSPENDED, &usbhid->iofl);
 	set_bit(HID_SUSPENDED, &usbhid->iofl);
 	spin_unlock_irq(&usbhid->inlock);
 	spin_unlock_irq(&usbhid->inlock);
 	del_timer_sync(&usbhid->io_retry);
 	del_timer_sync(&usbhid->io_retry);
 	usb_kill_urb(usbhid->urbin);
 	usb_kill_urb(usbhid->urbin);
-	mutex_unlock(&usbhid->setup);
 	dev_dbg(&intf->dev, "suspend\n");
 	dev_dbg(&intf->dev, "suspend\n");
 	return 0;
 	return 0;
 }
 }
@@ -1073,16 +1063,12 @@ static int hid_resume(struct usb_interface *intf)
 	struct usbhid_device *usbhid = hid->driver_data;
 	struct usbhid_device *usbhid = hid->driver_data;
 	int status;
 	int status;
 
 
-	mutex_lock(&usbhid->setup);
-	if (!test_bit(HID_STARTED, &usbhid->iofl)) {
-		mutex_unlock(&usbhid->setup);
+	if (!test_bit(HID_STARTED, &usbhid->iofl))
 		return 0;
 		return 0;
-	}
 
 
 	clear_bit(HID_SUSPENDED, &usbhid->iofl);
 	clear_bit(HID_SUSPENDED, &usbhid->iofl);
 	usbhid->retry_delay = 0;
 	usbhid->retry_delay = 0;
 	status = hid_start_in(hid);
 	status = hid_start_in(hid);
-	mutex_unlock(&usbhid->setup);
 	dev_dbg(&intf->dev, "resume status %d\n", status);
 	dev_dbg(&intf->dev, "resume status %d\n", status);
 	return status;
 	return status;
 }
 }

+ 0 - 1
drivers/hid/usbhid/usbhid.h

@@ -74,7 +74,6 @@ struct usbhid_device {
 	dma_addr_t outbuf_dma;                                          /* Output buffer dma */
 	dma_addr_t outbuf_dma;                                          /* Output buffer dma */
 	spinlock_t outlock;                                             /* Output fifo spinlock */
 	spinlock_t outlock;                                             /* Output fifo spinlock */
 
 
-	struct mutex setup;
 	unsigned long iofl;                                             /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
 	unsigned long iofl;                                             /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
 	struct timer_list io_retry;                                     /* Retry timer */
 	struct timer_list io_retry;                                     /* Retry timer */
 	unsigned long stop_retry;                                       /* Time to give up, in jiffies */
 	unsigned long stop_retry;                                       /* Time to give up, in jiffies */