On Thu, 18 Apr 2019, Alan Stern wrote: > On Wed, 17 Apr 2019, Alan Stern wrote: > > > I'm still having trouble understanding this. Here's some more > > debugging. > > Let's try this again. The patch format was wrong. One more try, this time with the syz command line. Incidentally, the console log from the last test had a very troubling entry showing the runtime PM usage counter for the hub interface was set to -4! Whatever caused the counter to go negative is probably also the reason for this bug. Alan Stern #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git e12e00e388de --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1016,6 +1016,9 @@ static void hub_activate(struct usb_hub bool need_debounce_delay = false; unsigned delay; + dev_info(hub->intfdev, "%p %s type %d discon %d\n", + hub, __func__, type, hub->disconnected); + /* Continue a partial initialization */ if (type == HUB_INIT2 || type == HUB_INIT3) { device_lock(&hdev->dev); @@ -1299,6 +1302,8 @@ static void hub_quiesce(struct usb_hub * unsigned long flags; int i; + dev_info(hub->intfdev, "%p %s type %d\n", hub, __func__, type); + /* hub_wq and related activity won't re-trigger */ spin_lock_irqsave(&hub->irq_urb_lock, flags); hub->quiescing = 1; @@ -3711,7 +3716,9 @@ static int hub_suspend(struct usb_interf } } - dev_dbg(&intf->dev, "%s\n", __func__); + dev_info(&intf->dev, "%p %s usage %d\n", + hub, __func__, + atomic_read(&intf->dev.power.usage_count)); /* stop hub_wq and related activity */ hub_quiesce(hub, HUB_SUSPEND); @@ -3756,7 +3763,7 @@ static int hub_resume(struct usb_interfa { struct usb_hub *hub = usb_get_intfdata(intf); - dev_dbg(&intf->dev, "%s\n", __func__); + dev_info(&intf->dev, "%p %s\n", hub, __func__); hub_activate(hub, HUB_RESUME); /* --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -358,7 +358,11 @@ static int usb_probe_interface(struct de intf->needs_altsetting0 = 0; } + dev_info(dev, "pre-probe usage %d\n", + atomic_read(&intf->dev.power.usage_count)); error = driver->probe(intf, id); + dev_info(dev, "post-probe usage %d\n", + atomic_read(&intf->dev.power.usage_count)); if (error) goto err; @@ -420,7 +424,11 @@ static int usb_unbind_interface(struct d if (!driver->soft_unbind || udev->state == USB_STATE_NOTATTACHED) usb_disable_interface(udev, intf, false); + dev_info(dev, "pre-discon usage %d\n", + atomic_read(&intf->dev.power.usage_count)); driver->disconnect(intf); + dev_info(dev, "post-discon usage %d\n", + atomic_read(&intf->dev.power.usage_count)); /* Free streams */ for (i = 0, j = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {