USB: usblp: don't call usb_set_interface if there's a single alt
authorJeremy Figgins <kernel@jeremyfiggins.com>
Sun, 24 Jan 2021 00:21:36 +0000 (18:21 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 26 Jan 2021 14:15:31 +0000 (15:15 +0100)
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@redhat.com>
Signed-off-by: Jeremy Figgins <kernel@jeremyfiggins.com>
Link: https://lore.kernel.org/r/YAy9kJhM/rG8EQXC@watson
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/class/usblp.c

index 134dc2005ce97de81ee1787510d4772395da8ef4..c9f6e975828852f09206ca11ed84c0fb6582e21c 100644 (file)
@@ -1329,14 +1329,17 @@ static int usblp_set_protocol(struct usblp *usblp, int protocol)
        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);