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 */