ChangeSet 1.811.2.1, 2002/12/16 11:18:15-08:00, arjanv@redhat.com

[PATCH] USB pwc deadlock fixes


diff -Nru a/drivers/usb/pwc-if.c b/drivers/usb/pwc-if.c
--- a/drivers/usb/pwc-if.c	Mon Dec 16 16:33:57 2002
+++ b/drivers/usb/pwc-if.c	Mon Dec 16 16:33:57 2002
@@ -1131,6 +1131,7 @@
 	if (pdev->image_read_pos == 0) {
 		/* Do wait queueing according to the (doc)book */
 		add_wait_queue(&pdev->frameq, &wait);
+	        set_current_state(TASK_INTERRUPTIBLE);
 		while (pdev->full_frames == NULL) {
 	                if (noblock) {
 	                	remove_wait_queue(&pdev->frameq, &wait);
@@ -1483,6 +1484,7 @@
 			            frameq is safe now.
 			 */
 			add_wait_queue(&pdev->frameq, &wait);
+		        set_current_state(TASK_INTERRUPTIBLE);
 			while (pdev->full_frames == NULL) {
 				if (pdev->unplugged) {
 					remove_wait_queue(&pdev->frameq, &wait);
@@ -1868,6 +1870,8 @@
 	
 	pdev->unplugged = 1;
 	if (pdev->vdev != NULL) {
+		add_wait_queue(&pdev->remove_ok, &wait);
+		set_current_state(TASK_UNINTERRUPTIBLE);
 		if (pdev->vopen) {
 			Info("Disconnected while device/video is open!\n");
 			
@@ -1883,12 +1887,8 @@
 			 */
 			   
 			Trace(TRACE_PROBE, "Sleeping on remove_ok.\n");
-			add_wait_queue(&pdev->remove_ok, &wait);
-			set_current_state(TASK_UNINTERRUPTIBLE);
 			/* ... wait ... */
 			schedule();
-			remove_wait_queue(&pdev->remove_ok, &wait);
-			set_current_state(TASK_RUNNING);
 			Trace(TRACE_PROBE, "Done sleeping.\n");
 			set_mem_leak(pdev->vdev);
 			pdev->vdev = NULL;
@@ -1900,6 +1900,8 @@
 			kfree(pdev->vdev);
 			pdev->vdev = NULL;
 		}
+		remove_wait_queue(&pdev->remove_ok, &wait);
+		set_current_state(TASK_RUNNING);
 	}
 
 	/* search device_hint[] table if we occupy a slot, by any chance */
