RE: [RFT PATCH 1/2] xhci: Fix leaking USB3 shared_hcd at xhci removal
> Ensure that the shared_hcd pointer is valid when calling usb_put_hcd() > > The shared_hcd is removed and freed in xhci by first calling > usb_remove_hcd(xhci- > >shared_hcd), and later > usb_put_hcd(xhci->shared_hcd) > > Afer commit fe190ed0d602 ("xhci: Do not halt the host until both HCD have > disconnected their devices.") the shared_hcd was never properly put as > xhci->shared_hcd was set to NULL before usb_put_hcd(xhci->shared_hcd) > xhci->was > called. > > shared_hcd (USB3) is removed before primary hcd (USB2). > While removing the primary hcd we might need to handle xhci interrupts to > cleanly > remove last USB2 devices, therefore we need to set > xhci->shared_hcd to NULL before removing the primary hcd to let xhci > interrupt handler know shared_hcd is no longer available. > > xhci-plat.c, xhci-histb.c and xhci-mtk first create both their hcd's before > adding them. > so to keep the correct reverse removal order use a temporary shared_hcd > variable > for them. > For more details see commit 4ac53087d6d4 ("usb: xhci: plat: Create both HCDs > before adding them") > > Fixes: fe190ed0d602 ("xhci: Do not halt the host until both HCD have > disconnected > their devices.") > Cc: Joel Stanley > Cc: Chunfeng Yun > Cc: Thierry Reding > Cc: Jianguo Sun > Cc: > Reported-by: Jack Pham > Signed-off-by: Mathias Nyman > --- > drivers/usb/host/xhci-histb.c | 6 -- > drivers/usb/host/xhci-mtk.c | 6 -- > drivers/usb/host/xhci-pci.c | 1 + > drivers/usb/host/xhci-plat.c | 6 -- drivers/usb/host/xhci-tegra.c | 1 + > drivers/usb/host/xhci.c | 2 -- > 6 files changed, 14 insertions(+), 8 deletions(-) > > diff --git a/drivers/usb/host/xhci-histb.c b/drivers/usb/host/xhci-histb.c > index > 27f0016..3c4abb5 100644 > --- a/drivers/usb/host/xhci-histb.c > +++ b/drivers/usb/host/xhci-histb.c > @@ -325,14 +325,16 @@ static int xhci_histb_remove(struct platform_device > *dev) > struct xhci_hcd_histb *histb = platform_get_drvdata(dev); > struct usb_hcd *hcd = histb->hcd; > struct xhci_hcd *xhci = hcd_to_xhci(hcd); > + struct usb_hcd *shared_hcd = xhci->shared_hcd; > > xhci->xhc_state |= XHCI_STATE_REMOVING; > > - usb_remove_hcd(xhci->shared_hcd); > + usb_remove_hcd(shared_hcd); > + xhci->shared_hcd = NULL; > device_wakeup_disable(>dev); > > usb_remove_hcd(hcd); > - usb_put_hcd(xhci->shared_hcd); > + usb_put_hcd(shared_hcd); > > xhci_histb_host_disable(histb); > usb_put_hcd(hcd); > diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index > 71d0d33..60987c7 100644 > --- a/drivers/usb/host/xhci-mtk.c > +++ b/drivers/usb/host/xhci-mtk.c > @@ -590,12 +590,14 @@ static int xhci_mtk_remove(struct platform_device *dev) > struct xhci_hcd_mtk *mtk = platform_get_drvdata(dev); > struct usb_hcd *hcd = mtk->hcd; > struct xhci_hcd *xhci = hcd_to_xhci(hcd); > + struct usb_hcd *shared_hcd = xhci->shared_hcd; > > - usb_remove_hcd(xhci->shared_hcd); > + usb_remove_hcd(shared_hcd); > + xhci->shared_hcd = NULL; > device_init_wakeup(>dev, false); > > usb_remove_hcd(hcd); > - usb_put_hcd(xhci->shared_hcd); > + usb_put_hcd(shared_hcd); > usb_put_hcd(hcd); > xhci_mtk_sch_exit(mtk); > xhci_mtk_clks_disable(mtk); > diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index > 51dd8e0..92fd6b6 100644 > --- a/drivers/usb/host/xhci-pci.c > +++ b/drivers/usb/host/xhci-pci.c > @@ -356,6 +356,7 @@ static void xhci_pci_remove(struct pci_dev *dev) > if (xhci->shared_hcd) { > usb_remove_hcd(xhci->shared_hcd); > usb_put_hcd(xhci->shared_hcd); > + xhci->shared_hcd = NULL; > } > > /* Workaround for spurious wakeups at shutdown with HSW */ diff --git > a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index > 94e9392..e5da8ce > 100644 > --- a/drivers/usb/host/xhci-plat.c > +++ b/drivers/usb/host/xhci-plat.c > @@ -359,14 +359,16 @@ static int xhci_plat_remove(struct platform_device *dev) > struct xhci_hcd *xhci = hcd_to_xhci(hcd); > struct clk *clk = xhci->clk; > struct clk *reg_clk = xhci->reg_clk; > + struct usb_hcd *shared_hcd = xhci->shared_hcd; > > xhci->xhc_state |= XHCI_STATE_REMOVING; > > - usb_remove_hcd(xhci->shared_hcd); > + usb_remove_hcd(shared_hcd); > + xhci->shared_hcd = NULL; > usb_phy_shutdown(hcd->usb_phy); > > usb_remove_hcd(hcd); > - usb_put_hcd(xhci->shared_hcd); > + usb_put_hcd(shared_hcd); > > clk_disable_unprepare(clk); > clk_disable_unprepare(reg_clk); > diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c > index > 4b463e5..b1cce98 100644 > --- a/drivers/usb/host/xhci-tegra.c > +++ b/drivers/usb/host/xhci-tegra.c > @@ -1240,6 +1240,7 @@ static int tegra_xusb_remove(struct platform_device > *pdev) > > usb_remove_hcd(xhci->shared_hcd);
RE: [RFT PATCH 2/2] xhci: handle port status events for removed USB3 hcd
> > Cc: > > Reported-by: Peter Chen > > Signed-off-by: Mathias Nyman > > --- > > drivers/usb/host/xhci-ring.c | 7 +++ > > 1 file changed, 7 insertions(+) > > > > diff --git a/drivers/usb/host/xhci-ring.c > > b/drivers/usb/host/xhci-ring.c index f0a99aa..3d314b8 100644 > > --- a/drivers/usb/host/xhci-ring.c > > +++ b/drivers/usb/host/xhci-ring.c > > @@ -1552,6 +1552,13 @@ static void handle_port_status(struct xhci_hcd *xhci, > > goto cleanup; > > } > > > > + /* We might get interrupts after shared_hcd is removed */ > > + if (port->rhub == >usb3_rhub && xhci->shared_hcd == NULL) { > > + xhci_dbg(xhci, "ignore port event for removed USB3 hcd\n"); > > + bogus_port_status = true; > > + goto cleanup; > > + } > > + > > hcd = port->rhub->hcd; > > bus_state = >bus_state[hcd_index(hcd)]; > > hcd_portnum = port->hcd_portnum; > > > > This probably only applies from 4.18 onwards, to test on older kernel try > something > like this instead: > > diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index > 6996235..7925da9 100644 > --- a/drivers/usb/host/xhci-ring.c > +++ b/drivers/usb/host/xhci-ring.c > @@ -1606,7 +1606,11 @@ static void handle_port_status(struct xhci_hcd *xhci, > hcd = xhci_to_hcd(xhci); > if ((major_revision == 0x03) != (hcd->speed >= HCD_USB3)) > hcd = xhci->shared_hcd; > - > + if (!hcd) { > + bogus_port_status = true; > + goto cleanup; > + } > if (major_revision == 0) { > xhci_warn(xhci, "Event for port %u not in " > "Extended Capabilities, ignoring.\n", > > > Jack, Peter, do these patches solve the remove issues you are seeing? At my two USB3 platforms, only apply the 1st patch can fix my problem. Maybe my USB3 port change interrupt occurs always before removing USB2 HCD. Peter
[PATCH] usb: dwc2: disable power_down on rockchip devices
>From 04fbf78e4e569bf872f1ffcb0a6f9b89569dc913 Mon Sep 17 00:00:00 2001 From: Hal Emmerich Date: Thu, 19 Jul 2018 21:48:08 -0500 Subject: [PATCH] usb: dwc2: disable power_down on rockchip devices The bug would let the usb controller enter partial power down, which was formally known as hibernate, upon boot if nothing was plugged in to the port. Partial power down couldn't be exited properly, so any usb devices plugged in after boot would not be usable. Before the name change, params.hibernation was false by default, so _dwc2_hcd_suspend() would skip entering hibernation. With the rename, _dwc2_hcd_suspend() was changed to use params.power_down to decide whether or not to enter partial power down. Since params.power_down is non-zero by default, it needs to be set to 0 for rockchip devices to restore functionality. This bug was reported in the linux-usb thread: REGRESSION: usb: dwc2: USB device not seen after boot The commit that caused this regression is: 6d23ee9caa6790aea047f9aca7f3c03cb8d96eb6 Signed-off-by: Hal Emmerich --- drivers/usb/dwc2/params.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index f03e41879224..492607adc506 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -82,6 +82,7 @@ static void dwc2_set_rk_params(struct dwc2_hsotg *hsotg) p->host_perio_tx_fifo_size = 256; p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << GAHBCFG_HBSTLEN_SHIFT; + p->power_down = 0; } static void dwc2_set_ltq_params(struct dwc2_hsotg *hsotg) -- 2.11.0
Re: [RFT PATCH 1/2] xhci: Fix leaking USB3 shared_hcd at xhci removal
On Thu, 2018-09-27 at 19:26 +0300, Mathias Nyman wrote: > Ensure that the shared_hcd pointer is valid when calling usb_put_hcd() > > The shared_hcd is removed and freed in xhci by first calling > usb_remove_hcd(xhci->shared_hcd), and later > usb_put_hcd(xhci->shared_hcd) > > Afer commit fe190ed0d602 ("xhci: Do not halt the host until both HCD have > disconnected their devices.") the shared_hcd was never properly put as > xhci->shared_hcd was set to NULL before usb_put_hcd(xhci->shared_hcd) was > called. > > shared_hcd (USB3) is removed before primary hcd (USB2). > While removing the primary hcd we might need to handle xhci interrupts > to cleanly remove last USB2 devices, therefore we need to set > xhci->shared_hcd to NULL before removing the primary hcd to let xhci > interrupt handler know shared_hcd is no longer available. > > xhci-plat.c, xhci-histb.c and xhci-mtk first create both their hcd's before > adding them. so to keep the correct reverse removal order use a temporary > shared_hcd variable for them. > For more details see commit 4ac53087d6d4 ("usb: xhci: plat: Create both > HCDs before adding them") > > Fixes: fe190ed0d602 ("xhci: Do not halt the host until both HCD have > disconnected their devices.") > Cc: Joel Stanley > Cc: Chunfeng Yun > Cc: Thierry Reding > Cc: Jianguo Sun > Cc: > Reported-by: Jack Pham > Signed-off-by: Mathias Nyman > --- > drivers/usb/host/xhci-histb.c | 6 -- > drivers/usb/host/xhci-mtk.c | 6 -- > drivers/usb/host/xhci-pci.c | 1 + > drivers/usb/host/xhci-plat.c | 6 -- > drivers/usb/host/xhci-tegra.c | 1 + > drivers/usb/host/xhci.c | 2 -- > 6 files changed, 14 insertions(+), 8 deletions(-) > > diff --git a/drivers/usb/host/xhci-histb.c b/drivers/usb/host/xhci-histb.c > index 27f0016..3c4abb5 100644 > --- a/drivers/usb/host/xhci-histb.c > +++ b/drivers/usb/host/xhci-histb.c > @@ -325,14 +325,16 @@ static int xhci_histb_remove(struct platform_device > *dev) > struct xhci_hcd_histb *histb = platform_get_drvdata(dev); > struct usb_hcd *hcd = histb->hcd; > struct xhci_hcd *xhci = hcd_to_xhci(hcd); > + struct usb_hcd *shared_hcd = xhci->shared_hcd; > > xhci->xhc_state |= XHCI_STATE_REMOVING; > > - usb_remove_hcd(xhci->shared_hcd); > + usb_remove_hcd(shared_hcd); > + xhci->shared_hcd = NULL; > device_wakeup_disable(>dev); > > usb_remove_hcd(hcd); > - usb_put_hcd(xhci->shared_hcd); > + usb_put_hcd(shared_hcd); > > xhci_histb_host_disable(histb); > usb_put_hcd(hcd); > diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c > index 71d0d33..60987c7 100644 > --- a/drivers/usb/host/xhci-mtk.c > +++ b/drivers/usb/host/xhci-mtk.c > @@ -590,12 +590,14 @@ static int xhci_mtk_remove(struct platform_device *dev) > struct xhci_hcd_mtk *mtk = platform_get_drvdata(dev); > struct usb_hcd *hcd = mtk->hcd; > struct xhci_hcd *xhci = hcd_to_xhci(hcd); > + struct usb_hcd *shared_hcd = xhci->shared_hcd; > > - usb_remove_hcd(xhci->shared_hcd); > + usb_remove_hcd(shared_hcd); > + xhci->shared_hcd = NULL; > device_init_wakeup(>dev, false); > > usb_remove_hcd(hcd); > - usb_put_hcd(xhci->shared_hcd); > + usb_put_hcd(shared_hcd); > usb_put_hcd(hcd); > xhci_mtk_sch_exit(mtk); > xhci_mtk_clks_disable(mtk); > diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c > index 51dd8e0..92fd6b6 100644 > --- a/drivers/usb/host/xhci-pci.c > +++ b/drivers/usb/host/xhci-pci.c > @@ -356,6 +356,7 @@ static void xhci_pci_remove(struct pci_dev *dev) > if (xhci->shared_hcd) { > usb_remove_hcd(xhci->shared_hcd); > usb_put_hcd(xhci->shared_hcd); > + xhci->shared_hcd = NULL; > } > > /* Workaround for spurious wakeups at shutdown with HSW */ > diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c > index 94e9392..e5da8ce 100644 > --- a/drivers/usb/host/xhci-plat.c > +++ b/drivers/usb/host/xhci-plat.c > @@ -359,14 +359,16 @@ static int xhci_plat_remove(struct platform_device *dev) > struct xhci_hcd *xhci = hcd_to_xhci(hcd); > struct clk *clk = xhci->clk; > struct clk *reg_clk = xhci->reg_clk; > + struct usb_hcd *shared_hcd = xhci->shared_hcd; > > xhci->xhc_state |= XHCI_STATE_REMOVING; > > - usb_remove_hcd(xhci->shared_hcd); > + usb_remove_hcd(shared_hcd); > + xhci->shared_hcd = NULL; > usb_phy_shutdown(hcd->usb_phy); > > usb_remove_hcd(hcd); > - usb_put_hcd(xhci->shared_hcd); > + usb_put_hcd(shared_hcd); > > clk_disable_unprepare(clk); > clk_disable_unprepare(reg_clk); > diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c > index 4b463e5..b1cce98 100644 > --- a/drivers/usb/host/xhci-tegra.c > +++ b/drivers/usb/host/xhci-tegra.c > @@ -1240,6 +1240,7 @@ static int tegra_xusb_remove(struct platform_device > *pdev) > >
[PATCH] usb: usbtmc: check size before allocating buffer and remove duplicated allocation
From: Colin Ian King Currently the allocation of a buffer is performed before a sanity check on the required buffer size and if the buffer size is too large the error exit return leaks the allocated buffer. Fix this by checking the size before allocating. Also, the same buffer is allocated again inside an if statement, causing the first allocation to be leaked. Fix this by removing this second redundant allocation. Detected by CoverityScan, CID#1473697 ("Resource leak") Fixes: 658f24f4523e ("usb: usbtmc: Add ioctl for generic requests on control") Signed-off-by: Colin Ian King --- drivers/usb/class/usbtmc.c | 10 +++--- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 0fcb81a1399b..c01edff190d2 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1895,18 +1895,14 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data, if (res) return -EFAULT; + if (request.req.wLength > USBTMC_BUFSIZE) + return -EMSGSIZE; + buffer = kmalloc(request.req.wLength, GFP_KERNEL); if (!buffer) return -ENOMEM; - if (request.req.wLength > USBTMC_BUFSIZE) - return -EMSGSIZE; - if (request.req.wLength) { - buffer = kmalloc(request.req.wLength, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - if ((request.req.bRequestType & USB_DIR_IN) == 0) { /* Send control data to device */ res = copy_from_user(buffer, request.data, -- 2.17.1
Re: [RFT PATCH 2/2] xhci: handle port status events for removed USB3 hcd
On 27.09.2018 19:26, Mathias Nyman wrote: At xhci removal the USB3 hcd (shared_hcd) is removed before the primary USB2 hcd. Interrupts for port status changes may still occur for USB3 ports after the shared_hcd is freed, causing NULL pointer dereference. Check if xhci->shared_hcd is still valid before handing USB3 port events Cc: Reported-by: Peter Chen Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-ring.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index f0a99aa..3d314b8 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1552,6 +1552,13 @@ static void handle_port_status(struct xhci_hcd *xhci, goto cleanup; } + /* We might get interrupts after shared_hcd is removed */ + if (port->rhub == >usb3_rhub && xhci->shared_hcd == NULL) { + xhci_dbg(xhci, "ignore port event for removed USB3 hcd\n"); + bogus_port_status = true; + goto cleanup; + } + hcd = port->rhub->hcd; bus_state = >bus_state[hcd_index(hcd)]; hcd_portnum = port->hcd_portnum; This probably only applies from 4.18 onwards, to test on older kernel try something like this instead: diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 6996235..7925da9 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1606,7 +1606,11 @@ static void handle_port_status(struct xhci_hcd *xhci, hcd = xhci_to_hcd(xhci); if ((major_revision == 0x03) != (hcd->speed >= HCD_USB3)) hcd = xhci->shared_hcd; - + if (!hcd) { + bogus_port_status = true; + goto cleanup; + } if (major_revision == 0) { xhci_warn(xhci, "Event for port %u not in " "Extended Capabilities, ignoring.\n", Jack, Peter, do these patches solve the remove issues you are seeing? Thanks -Mathias
[RFT PATCH 2/2] xhci: handle port status events for removed USB3 hcd
At xhci removal the USB3 hcd (shared_hcd) is removed before the primary USB2 hcd. Interrupts for port status changes may still occur for USB3 ports after the shared_hcd is freed, causing NULL pointer dereference. Check if xhci->shared_hcd is still valid before handing USB3 port events Cc: Reported-by: Peter Chen Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-ring.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index f0a99aa..3d314b8 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1552,6 +1552,13 @@ static void handle_port_status(struct xhci_hcd *xhci, goto cleanup; } + /* We might get interrupts after shared_hcd is removed */ + if (port->rhub == >usb3_rhub && xhci->shared_hcd == NULL) { + xhci_dbg(xhci, "ignore port event for removed USB3 hcd\n"); + bogus_port_status = true; + goto cleanup; + } + hcd = port->rhub->hcd; bus_state = >bus_state[hcd_index(hcd)]; hcd_portnum = port->hcd_portnum; -- 2.7.4
[RFT PATCH 1/2] xhci: Fix leaking USB3 shared_hcd at xhci removal
Ensure that the shared_hcd pointer is valid when calling usb_put_hcd() The shared_hcd is removed and freed in xhci by first calling usb_remove_hcd(xhci->shared_hcd), and later usb_put_hcd(xhci->shared_hcd) Afer commit fe190ed0d602 ("xhci: Do not halt the host until both HCD have disconnected their devices.") the shared_hcd was never properly put as xhci->shared_hcd was set to NULL before usb_put_hcd(xhci->shared_hcd) was called. shared_hcd (USB3) is removed before primary hcd (USB2). While removing the primary hcd we might need to handle xhci interrupts to cleanly remove last USB2 devices, therefore we need to set xhci->shared_hcd to NULL before removing the primary hcd to let xhci interrupt handler know shared_hcd is no longer available. xhci-plat.c, xhci-histb.c and xhci-mtk first create both their hcd's before adding them. so to keep the correct reverse removal order use a temporary shared_hcd variable for them. For more details see commit 4ac53087d6d4 ("usb: xhci: plat: Create both HCDs before adding them") Fixes: fe190ed0d602 ("xhci: Do not halt the host until both HCD have disconnected their devices.") Cc: Joel Stanley Cc: Chunfeng Yun Cc: Thierry Reding Cc: Jianguo Sun Cc: Reported-by: Jack Pham Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-histb.c | 6 -- drivers/usb/host/xhci-mtk.c | 6 -- drivers/usb/host/xhci-pci.c | 1 + drivers/usb/host/xhci-plat.c | 6 -- drivers/usb/host/xhci-tegra.c | 1 + drivers/usb/host/xhci.c | 2 -- 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/usb/host/xhci-histb.c b/drivers/usb/host/xhci-histb.c index 27f0016..3c4abb5 100644 --- a/drivers/usb/host/xhci-histb.c +++ b/drivers/usb/host/xhci-histb.c @@ -325,14 +325,16 @@ static int xhci_histb_remove(struct platform_device *dev) struct xhci_hcd_histb *histb = platform_get_drvdata(dev); struct usb_hcd *hcd = histb->hcd; struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct usb_hcd *shared_hcd = xhci->shared_hcd; xhci->xhc_state |= XHCI_STATE_REMOVING; - usb_remove_hcd(xhci->shared_hcd); + usb_remove_hcd(shared_hcd); + xhci->shared_hcd = NULL; device_wakeup_disable(>dev); usb_remove_hcd(hcd); - usb_put_hcd(xhci->shared_hcd); + usb_put_hcd(shared_hcd); xhci_histb_host_disable(histb); usb_put_hcd(hcd); diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 71d0d33..60987c7 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -590,12 +590,14 @@ static int xhci_mtk_remove(struct platform_device *dev) struct xhci_hcd_mtk *mtk = platform_get_drvdata(dev); struct usb_hcd *hcd = mtk->hcd; struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct usb_hcd *shared_hcd = xhci->shared_hcd; - usb_remove_hcd(xhci->shared_hcd); + usb_remove_hcd(shared_hcd); + xhci->shared_hcd = NULL; device_init_wakeup(>dev, false); usb_remove_hcd(hcd); - usb_put_hcd(xhci->shared_hcd); + usb_put_hcd(shared_hcd); usb_put_hcd(hcd); xhci_mtk_sch_exit(mtk); xhci_mtk_clks_disable(mtk); diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 51dd8e0..92fd6b6 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -356,6 +356,7 @@ static void xhci_pci_remove(struct pci_dev *dev) if (xhci->shared_hcd) { usb_remove_hcd(xhci->shared_hcd); usb_put_hcd(xhci->shared_hcd); + xhci->shared_hcd = NULL; } /* Workaround for spurious wakeups at shutdown with HSW */ diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 94e9392..e5da8ce 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -359,14 +359,16 @@ static int xhci_plat_remove(struct platform_device *dev) struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct clk *clk = xhci->clk; struct clk *reg_clk = xhci->reg_clk; + struct usb_hcd *shared_hcd = xhci->shared_hcd; xhci->xhc_state |= XHCI_STATE_REMOVING; - usb_remove_hcd(xhci->shared_hcd); + usb_remove_hcd(shared_hcd); + xhci->shared_hcd = NULL; usb_phy_shutdown(hcd->usb_phy); usb_remove_hcd(hcd); - usb_put_hcd(xhci->shared_hcd); + usb_put_hcd(shared_hcd); clk_disable_unprepare(clk); clk_disable_unprepare(reg_clk); diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index 4b463e5..b1cce98 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -1240,6 +1240,7 @@ static int tegra_xusb_remove(struct platform_device *pdev) usb_remove_hcd(xhci->shared_hcd); usb_put_hcd(xhci->shared_hcd); + xhci->shared_hcd = NULL; usb_remove_hcd(tegra->hcd); usb_put_hcd(tegra->hcd); diff --git a/drivers/usb/host/xhci.c