--- x/drivers/usb/core/hcd.c +++ y/drivers/usb/core/hcd.c @@ -1667,6 +1667,8 @@ static void __usb_hcd_giveback_urb(struc atomic_dec(&urb->use_count); if (unlikely(atomic_read(&urb->reject))) wake_up(&usb_kill_urb_queue); + else if (urb->debug_complete != NULL) + complete(urb->debug_complete); usb_put_urb(urb); } --- x/drivers/usb/core/message.c +++ y/drivers/usb/core/message.c @@ -49,19 +49,23 @@ static void usb_api_blocking_completion( static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) { struct api_context ctx; + struct completion compl; unsigned long expire; int retval; init_completion(&ctx.done); urb->context = &ctx; urb->actual_length = 0; + urb->debug_complete = &compl; + init_completion(urb->debug_complete); retval = usb_submit_urb(urb, GFP_NOIO); if (unlikely(retval)) goto out; expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT; if (!wait_for_completion_timeout(&ctx.done, expire)) { - usb_kill_urb(urb); + dev_dbg(&urb->dev->dev, "%s timeout %lu\n", __func__, expire); + wait_for_completion(urb->debug_complete); retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status); dev_dbg(&urb->dev->dev, --- x/include/linux/usb.h +++ y/include/linux/usb.h @@ -1560,6 +1560,7 @@ struct urb { void *hcpriv; /* private data for host controller */ atomic_t use_count; /* concurrent submissions counter */ atomic_t reject; /* submissions will fail */ + struct completion *debug_complete; /* public: documented fields in the urb that can be used by drivers */ struct list_head urb_list; /* list head for use by the urb's