From: Jeremy Figgins <kernel@xxxxxxxxxxxxxxxxx> commit d8c6edfa3f4ee0d45d7ce5ef18d1245b78774b9d upstream. Some devices, such as the Winbond Electronics Corp. Virtual Com Port (Vendor=0416, ProdId=5011), lockup when usb_set_interface() or usb_clear_halt() are called. This device has only a single altsetting, so it should not be necessary to call usb_set_interface(). Acked-by: Pete Zaitcev <zaitcev@xxxxxxxxxx> Signed-off-by: Jeremy Figgins <kernel@xxxxxxxxxxxxxxxxx> Link: https://lore.kernel.org/r/YAy9kJhM/rG8EQXC@watson Cc: stable <stable@xxxxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/usb/class/usblp.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1349,14 +1349,17 @@ static int usblp_set_protocol(struct usb if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL) return -EINVAL; - alts = usblp->protocol[protocol].alt_setting; - if (alts < 0) - return -EINVAL; - r = usb_set_interface(usblp->dev, usblp->ifnum, alts); - if (r < 0) { - printk(KERN_ERR "usblp: can't set desired altsetting %d on interface %d\n", - alts, usblp->ifnum); - return r; + /* Don't unnecessarily set the interface if there's a single alt. */ + if (usblp->intf->num_altsetting > 1) { + alts = usblp->protocol[protocol].alt_setting; + if (alts < 0) + return -EINVAL; + r = usb_set_interface(usblp->dev, usblp->ifnum, alts); + if (r < 0) { + printk(KERN_ERR "usblp: can't set desired altsetting %d on interface %d\n", + alts, usblp->ifnum); + return r; + } } usblp->bidir = (usblp->protocol[protocol].epread != NULL);