Good morning Alan, The most recent patch you provided resolved the lockup issue I have been encountering. I will carry out full release testing shortly to further validate it. Would this be something that could be proposed for inclusion in the kernel, pending cosmetic changes (ie: `alantest', etc)? Thank you. ================================================================================ On Fri, 15 Apr 2016, Matthew Giassa wrote: > Good afternoon Alan, > > Attached is the requested usbmon output. I started the camera, had a lot > of config read/write calls complete, and was able to eventually get one > frame of image data to be saved and rendered. Obviously something is going on that I don't understand. Try this patch, which has extra debugging output added, in place of the earler one. I won't need to see any usbmon output, just the dmesg log. (And you don't have to post the entire thing, with hundreds of repetitions of the same information over and over again. Two or three iterations will be fine.) Alan Stern Index: usb-4.4/include/linux/usb.h =================================================================== --- usb-4.4.orig/include/linux/usb.h +++ usb-4.4/include/linux/usb.h @@ -1076,7 +1076,7 @@ struct usbdrv_wrap { * for interfaces bound to this driver. * @soft_unbind: if set to 1, the USB core will not kill URBs and disable * endpoints before calling the driver's disconnect method. - * @disable_hub_initiated_lpm: if set to 0, the USB core will not allow hubs + * @disable_hub_initiated_lpm: if set to 1, the USB core will not allow hubs * to initiate lower power link state transitions when an idle timeout * occurs. Device-initiated USB 3.0 link PM will still be allowed. * Index: usb-4.4/drivers/usb/core/driver.c =================================================================== --- usb-4.4.orig/drivers/usb/core/driver.c +++ usb-4.4/drivers/usb/core/driver.c @@ -284,7 +284,7 @@ static int usb_probe_interface(struct de struct usb_device *udev = interface_to_usbdev(intf); const struct usb_device_id *id; int error = -ENODEV; - int lpm_disable_error; + int lpm_disable_error = -ENODEV; dev_dbg(dev, "%s\n", __func__); @@ -336,12 +336,14 @@ static int usb_probe_interface(struct de * setting during probe, that should also be fine. usb_set_interface() * will attempt to disable LPM, and fail if it can't disable it. */ - lpm_disable_error = usb_unlocked_disable_lpm(udev); - if (lpm_disable_error && driver->disable_hub_initiated_lpm) { - dev_err(&intf->dev, "%s Failed to disable LPM for driver %s\n.", - __func__, driver->name); - error = lpm_disable_error; - goto err; + if (driver->disable_hub_initiated_lpm) { + lpm_disable_error = usb_unlocked_disable_lpm(udev); + if (lpm_disable_error) { + dev_err(&intf->dev, "%s Failed to disable LPM for driver %s\n.", + __func__, driver->name); + error = lpm_disable_error; + goto err; + } } /* Carry out a deferred switch to altsetting 0 */ @@ -391,7 +393,8 @@ static int usb_unbind_interface(struct d struct usb_interface *intf = to_usb_interface(dev); struct usb_host_endpoint *ep, **eps = NULL; struct usb_device *udev; - int i, j, error, r, lpm_disable_error; + int i, j, error, r; + int lpm_disable_error = -ENODEV; intf->condition = USB_INTERFACE_UNBINDING; @@ -399,12 +402,13 @@ static int usb_unbind_interface(struct d udev = interface_to_usbdev(intf); error = usb_autoresume_device(udev); - /* Hub-initiated LPM policy may change, so attempt to disable LPM until + /* If hub-initiated LPM policy may change, attempt to disable LPM until * the driver is unbound. If LPM isn't disabled, that's fine because it * wouldn't be enabled unless all the bound interfaces supported * hub-initiated LPM. */ - lpm_disable_error = usb_unlocked_disable_lpm(udev); + if (driver->disable_hub_initiated_lpm) + lpm_disable_error = usb_unlocked_disable_lpm(udev); /* * Terminate all URBs for this interface unless the driver Index: usb-4.4/drivers/usb/core/devio.c =================================================================== --- usb-4.4.orig/drivers/usb/core/devio.c +++ usb-4.4/drivers/usb/core/devio.c @@ -612,6 +612,8 @@ struct usb_driver usbfs_driver = { .resume = driver_resume, }; +int alantest; + static int claimintf(struct usb_dev_state *ps, unsigned int ifnum) { struct usb_device *dev = ps->dev; @@ -627,8 +629,11 @@ static int claimintf(struct usb_dev_stat intf = usb_ifnum_to_if(dev, ifnum); if (!intf) err = -ENOENT; - else + else { + alantest = 1; err = usb_driver_claim_interface(&usbfs_driver, intf, ps); + alantest = 0; + } if (err == 0) set_bit(ifnum, &ps->ifclaimed); return err; @@ -648,7 +653,9 @@ static int releaseintf(struct usb_dev_st if (!intf) err = -ENOENT; else if (test_and_clear_bit(ifnum, &ps->ifclaimed)) { + alantest = 1; usb_driver_release_interface(&usbfs_driver, intf); + alantest = 0; err = 0; } return err; Index: usb-4.4/drivers/usb/core/hub.c =================================================================== --- usb-4.4.orig/drivers/usb/core/hub.c +++ usb-4.4/drivers/usb/core/hub.c @@ -33,6 +33,8 @@ #include "hub.h" #include "otg_whitelist.h" +extern int alantest; + #define USB_VENDOR_GENESYS_LOGIC 0x05e3 #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01 @@ -4002,6 +4004,11 @@ int usb_disable_lpm(struct usb_device *u if ((udev->u1_params.timeout == 0 && udev->u2_params.timeout == 0)) return 0; + if (alantest) { + pr_info("disable LPM\n"); + dump_stack(); + } + /* If LPM is enabled, attempt to disable it. */ if (usb_disable_link_state(hcd, udev, USB3_LPM_U1)) goto enable_lpm; @@ -4069,6 +4076,11 @@ void usb_enable_lpm(struct usb_device *u if (!hub) return; + if (alantest) { + pr_info("enable LPM\n"); + dump_stack(); + } + port_dev = hub->ports[udev->portnum - 1]; if (port_dev->usb3_lpm_u1_permit) ============================================================ Matthew Giassa, MASc, BASc, EIT Security and Embedded Systems Specialist linkedin: https://ca.linkedin.com/in/giassa e-mail: matthew@xxxxxxxxxx website: www.giassa.net -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html