--- x/drivers/usb/class/cdc-wdm.c +++ y/drivers/usb/class/cdc-wdm.c @@ -262,6 +262,10 @@ static void wdm_int_callback(struct urb case -ECONNRESET: return; /* unplug */ case -EPIPE: + if (test_bit(WDM_INT_STALL, &desc->flags)) { + clear_bit(WDM_INT_STALL, &desc->flags); + return; + } set_bit(WDM_INT_STALL, &desc->flags); dev_err(&desc->intf->dev, "Stall on int endpoint\n"); goto sw; /* halt is cleared in work */ @@ -272,6 +276,9 @@ static void wdm_int_callback(struct urb } } + if (test_bit(WDM_INT_STALL, &desc->flags)) + clear_bit(WDM_INT_STALL, &desc->flags); + if (urb->actual_length < sizeof(struct usb_cdc_notification)) { dev_err(&desc->intf->dev, "wdm_int_callback - %d bytes\n", urb->actual_length); @@ -311,11 +318,12 @@ static void wdm_int_callback(struct urb && !test_bit(WDM_DISCONNECTING, &desc->flags) && !test_bit(WDM_SUSPENDING, &desc->flags)) { rv = usb_submit_urb(desc->response, GFP_ATOMIC); + if (rv) + clear_bit(WDM_RESPONDING, &desc->flags); dev_dbg(&desc->intf->dev, "submit response URB %d\n", rv); } spin_unlock_irqrestore(&desc->iuspin, flags); if (rv < 0) { - clear_bit(WDM_RESPONDING, &desc->flags); if (rv == -EPERM) return; if (rv == -ENOMEM) {