Skip to content

Commit

Permalink
Merge tag 'usb-4.17-rc6' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are some USB driver fixes fro 4.17-rc6.

  They resolve some reported bugs in the musb driver, the xhci driver,
  and a number of small fixes for the usbip driver.

  All of these have been in linux-next with no reported issues"

* tag 'usb-4.17-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usbip: usbip_host: fix bad unlock balance during stub_probe()
  usbip: usbip_host: fix NULL-ptr deref and use-after-free errors
  usbip: usbip_host: run rebind from exit when module is removed
  usbip: usbip_host: delete device from busid_table after rebind
  usbip: usbip_host: refine probe and disconnect debug msgs to be useful
  usb: musb: fix remote wakeup racing with suspend
  xhci: Fix USB3 NULL pointer dereference at logical disconnect.
  • Loading branch information
Linus Torvalds committed May 18, 2018
2 parents 61c2ad9 + c171654 commit 0e273f9
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 44 deletions.
2 changes: 1 addition & 1 deletion drivers/usb/host/xhci-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,

slot_id = 0;
for (i = 0; i < MAX_HC_SLOTS; i++) {
if (!xhci->devs[i])
if (!xhci->devs[i] || !xhci->devs[i]->udev)
continue;
speed = xhci->devs[i]->udev->speed;
if (((speed >= USB_SPEED_SUPER) == (hcd->speed >= HCD_USB3))
Expand Down
5 changes: 4 additions & 1 deletion drivers/usb/musb/musb_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -2524,8 +2524,11 @@ static int musb_bus_suspend(struct usb_hcd *hcd)
{
struct musb *musb = hcd_to_musb(hcd);
u8 devctl;
int ret;

musb_port_suspend(musb, true);
ret = musb_port_suspend(musb, true);
if (ret)
return ret;

if (!is_host_active(musb))
return 0;
Expand Down
7 changes: 5 additions & 2 deletions drivers/usb/musb/musb_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ extern void musb_host_rx(struct musb *, u8);
extern void musb_root_disconnect(struct musb *musb);
extern void musb_host_resume_root_hub(struct musb *musb);
extern void musb_host_poke_root_hub(struct musb *musb);
extern void musb_port_suspend(struct musb *musb, bool do_suspend);
extern int musb_port_suspend(struct musb *musb, bool do_suspend);
extern void musb_port_reset(struct musb *musb, bool do_reset);
extern void musb_host_finish_resume(struct work_struct *work);
#else
Expand Down Expand Up @@ -99,7 +99,10 @@ static inline void musb_root_disconnect(struct musb *musb) {}
static inline void musb_host_resume_root_hub(struct musb *musb) {}
static inline void musb_host_poll_rh_status(struct musb *musb) {}
static inline void musb_host_poke_root_hub(struct musb *musb) {}
static inline void musb_port_suspend(struct musb *musb, bool do_suspend) {}
static inline int musb_port_suspend(struct musb *musb, bool do_suspend)
{
return 0;
}
static inline void musb_port_reset(struct musb *musb, bool do_reset) {}
static inline void musb_host_finish_resume(struct work_struct *work) {}
#endif
Expand Down
25 changes: 15 additions & 10 deletions drivers/usb/musb/musb_virthub.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ void musb_host_finish_resume(struct work_struct *work)
spin_unlock_irqrestore(&musb->lock, flags);
}

void musb_port_suspend(struct musb *musb, bool do_suspend)
int musb_port_suspend(struct musb *musb, bool do_suspend)
{
struct usb_otg *otg = musb->xceiv->otg;
u8 power;
void __iomem *mbase = musb->mregs;

if (!is_host_active(musb))
return;
return 0;

/* NOTE: this doesn't necessarily put PHY into low power mode,
* turning off its clock; that's a function of PHY integration and
Expand All @@ -66,16 +66,20 @@ void musb_port_suspend(struct musb *musb, bool do_suspend)
if (do_suspend) {
int retries = 10000;

power &= ~MUSB_POWER_RESUME;
power |= MUSB_POWER_SUSPENDM;
musb_writeb(mbase, MUSB_POWER, power);
if (power & MUSB_POWER_RESUME)
return -EBUSY;

/* Needed for OPT A tests */
power = musb_readb(mbase, MUSB_POWER);
while (power & MUSB_POWER_SUSPENDM) {
if (!(power & MUSB_POWER_SUSPENDM)) {
power |= MUSB_POWER_SUSPENDM;
musb_writeb(mbase, MUSB_POWER, power);

/* Needed for OPT A tests */
power = musb_readb(mbase, MUSB_POWER);
if (retries-- < 1)
break;
while (power & MUSB_POWER_SUSPENDM) {
power = musb_readb(mbase, MUSB_POWER);
if (retries-- < 1)
break;
}
}

musb_dbg(musb, "Root port suspended, power %02x", power);
Expand Down Expand Up @@ -111,6 +115,7 @@ void musb_port_suspend(struct musb *musb, bool do_suspend)
schedule_delayed_work(&musb->finish_resume_work,
msecs_to_jiffies(USB_RESUME_TIMEOUT));
}
return 0;
}

void musb_port_reset(struct musb *musb, bool do_reset)
Expand Down
2 changes: 2 additions & 0 deletions drivers/usb/usbip/stub.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ struct bus_id_priv {
struct stub_device *sdev;
struct usb_device *udev;
char shutdown_busid;
spinlock_t busid_lock;
};

/* stub_priv is allocated from stub_priv_cache */
Expand All @@ -83,6 +84,7 @@ extern struct usb_device_driver stub_driver;

/* stub_main.c */
struct bus_id_priv *get_busid_priv(const char *busid);
void put_busid_priv(struct bus_id_priv *bid);
int del_match_busid(char *busid);
void stub_device_cleanup_urbs(struct stub_device *sdev);

Expand Down
43 changes: 26 additions & 17 deletions drivers/usb/usbip/stub_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,9 +300,9 @@ static int stub_probe(struct usb_device *udev)
struct stub_device *sdev = NULL;
const char *udev_busid = dev_name(&udev->dev);
struct bus_id_priv *busid_priv;
int rc;
int rc = 0;

dev_dbg(&udev->dev, "Enter\n");
dev_dbg(&udev->dev, "Enter probe\n");

/* check we should claim or not by busid_table */
busid_priv = get_busid_priv(udev_busid);
Expand All @@ -317,27 +317,32 @@ static int stub_probe(struct usb_device *udev)
* other matched drivers by the driver core.
* See driver_probe_device() in driver/base/dd.c
*/
return -ENODEV;
rc = -ENODEV;
goto call_put_busid_priv;
}

if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) {
dev_dbg(&udev->dev, "%s is a usb hub device... skip!\n",
udev_busid);
return -ENODEV;
rc = -ENODEV;
goto call_put_busid_priv;
}

if (!strcmp(udev->bus->bus_name, "vhci_hcd")) {
dev_dbg(&udev->dev,
"%s is attached on vhci_hcd... skip!\n",
udev_busid);

return -ENODEV;
rc = -ENODEV;
goto call_put_busid_priv;
}

/* ok, this is my device */
sdev = stub_device_alloc(udev);
if (!sdev)
return -ENOMEM;
if (!sdev) {
rc = -ENOMEM;
goto call_put_busid_priv;
}

dev_info(&udev->dev,
"usbip-host: register new device (bus %u dev %u)\n",
Expand Down Expand Up @@ -369,7 +374,9 @@ static int stub_probe(struct usb_device *udev)
}
busid_priv->status = STUB_BUSID_ALLOC;

return 0;
rc = 0;
goto call_put_busid_priv;

err_files:
usb_hub_release_port(udev->parent, udev->portnum,
(struct usb_dev_state *) udev);
Expand All @@ -379,6 +386,9 @@ static int stub_probe(struct usb_device *udev)

busid_priv->sdev = NULL;
stub_device_free(sdev);

call_put_busid_priv:
put_busid_priv(busid_priv);
return rc;
}

Expand All @@ -404,7 +414,7 @@ static void stub_disconnect(struct usb_device *udev)
struct bus_id_priv *busid_priv;
int rc;

dev_dbg(&udev->dev, "Enter\n");
dev_dbg(&udev->dev, "Enter disconnect\n");

busid_priv = get_busid_priv(udev_busid);
if (!busid_priv) {
Expand All @@ -417,7 +427,7 @@ static void stub_disconnect(struct usb_device *udev)
/* get stub_device */
if (!sdev) {
dev_err(&udev->dev, "could not get device");
return;
goto call_put_busid_priv;
}

dev_set_drvdata(&udev->dev, NULL);
Expand All @@ -432,12 +442,12 @@ static void stub_disconnect(struct usb_device *udev)
(struct usb_dev_state *) udev);
if (rc) {
dev_dbg(&udev->dev, "unable to release port\n");
return;
goto call_put_busid_priv;
}

/* If usb reset is called from event handler */
if (usbip_in_eh(current))
return;
goto call_put_busid_priv;

/* shutdown the current connection */
shutdown_busid(busid_priv);
Expand All @@ -448,12 +458,11 @@ static void stub_disconnect(struct usb_device *udev)
busid_priv->sdev = NULL;
stub_device_free(sdev);

if (busid_priv->status == STUB_BUSID_ALLOC) {
if (busid_priv->status == STUB_BUSID_ALLOC)
busid_priv->status = STUB_BUSID_ADDED;
} else {
busid_priv->status = STUB_BUSID_OTHER;
del_match_busid((char *)udev_busid);
}

call_put_busid_priv:
put_busid_priv(busid_priv);
}

#ifdef CONFIG_PM
Expand Down
Loading

0 comments on commit 0e273f9

Please sign in to comment.