From bff52352e0ccc2481f2b6b0d612ff8ff56c50f3a Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra <enric.balletbo@collabora.com> Date: Mon, 18 Dec 2017 16:14:36 +0100 Subject: usb: dwc3: of-simple: fix oops by unbalanced clk disable call dwc3_of_simple_dev_pm_ops has never been used since commit a0d8c4cfdf31 ("usb: dwc3: of-simple: set dev_pm_ops"), but this commit has brought and oops when unbind the device due this sequence: dwc3_of_simple_remove -> clk_disable ... -> pm_runtime_put_sync -> dwc3_of_simple_runtime_suspend -> clk_disable (again) This double call to clk_core_disable causes a kernel oops like this: WARNING: CPU: 1 PID: 4022 at drivers/clk/clk.c:656 clk_core_disable+0x78/0x80 CPU: 1 PID: 4022 Comm: bash Not tainted 4.15.0-rc4+ #44 Hardware name: Google Kevin (DT) pstate: 80000085 (Nzcv daIf -PAN -UAO) pc : clk_core_disable+0x78/0x80 lr : clk_core_disable_lock+0x20/0x38 sp : ffff00000bbf3a90 ... Call trace: clk_core_disable+0x78/0x80 clk_disable+0x1c/0x30 dwc3_of_simple_runtime_suspend+0x30/0x50 pm_generic_runtime_suspend+0x28/0x40 This patch fixes the unbalanced clk disable call by setting the num_clocks variable to zero once the clocks were disabled. Fixes: a0d8c4cfdf31 ("usb: dwc3: of-simple: set dev_pm_ops") Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/dwc3/dwc3-of-simple.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c index 7ae0eef..e54c362 100644 --- a/drivers/usb/dwc3/dwc3-of-simple.c +++ b/drivers/usb/dwc3/dwc3-of-simple.c @@ -143,6 +143,7 @@ static int dwc3_of_simple_remove(struct platform_device *pdev) clk_disable_unprepare(simple->clks[i]); clk_put(simple->clks[i]); } + simple->num_clocks = 0; reset_control_assert(simple->resets); reset_control_put(simple->resets); -- cgit v1.1 From e3190868e5f52fb26544f16463593d54ce46ce61 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Date: Fri, 12 Jan 2018 20:00:56 +0900 Subject: usb: gadget: udc: renesas_usb3: fix oops in renesas_usb3_remove() This patch fixes an issue that the renesas_usb3_remove() causes NULL pointer dereference because the usb3_to_dev() macro will use the gadget instance and it will be deleted before. Fixes: cf06df3fae28 ("usb: gadget: udc: renesas_usb3: move pm_runtime_{en,dis}able()") Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/gadget/udc/renesas_usb3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 6e87af2..409cde4 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -2410,7 +2410,7 @@ static int renesas_usb3_remove(struct platform_device *pdev) __renesas_usb3_ep_free_request(usb3->ep0_req); if (usb3->phy) phy_put(usb3->phy); - pm_runtime_disable(usb3_to_dev(usb3)); + pm_runtime_disable(&pdev->dev); return 0; } -- cgit v1.1 From 6180026341e852a250e1f97ebdcf71684a3c81b9 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Date: Fri, 12 Jan 2018 18:18:05 -0800 Subject: usb: dwc3: gadget: Set maxpacket size for ep0 IN There are 2 control endpoint structures for DWC3. However, the driver only updates the OUT direction control endpoint structure during ConnectDone event. DWC3 driver needs to update the endpoint max packet size for control IN endpoint as well. If the max packet size is not properly set, then the driver will incorrectly calculate the data transfer size and fail to send ZLP for HS/FS 3-stage control read transfer. The fix is simply to update the max packet size for the ep0 IN direction during ConnectDone event. Cc: stable@vger.kernel.org Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver") Signed-off-by: Thinh Nguyen <thinhn@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/dwc3/gadget.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 616ef49..2bda4eb 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2745,6 +2745,8 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) break; } + dwc->eps[1]->endpoint.maxpacket = dwc->gadget.ep0->maxpacket; + /* Enable USB2 LPM Capability */ if ((dwc->revision > DWC3_REVISION_194A) && -- cgit v1.1 From f035d139ffece7b6a7b8bfb17bd0ba715ee57a04 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Date: Fri, 12 Jan 2018 18:18:27 -0800 Subject: usb: dwc3: ep0: Reset TRB counter for ep0 IN DWC3 tracks TRB counter for each ep0 direction separately. In control read transfer completion handler, the driver needs to reset the TRB enqueue counter for ep0 IN direction. Currently the driver only resets the TRB counter for control OUT endpoint. Check for the data direction and properly reset the TRB counter from correct control endpoint. Cc: stable@vger.kernel.org Fixes: c2da2ff00606 ("usb: dwc3: ep0: don't use ep0in for transfers") Signed-off-by: Thinh Nguyen <thinhn@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/dwc3/ep0.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 9c2e4a1..18be31d 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -854,7 +854,12 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, trb++; trb->ctrl &= ~DWC3_TRB_CTRL_HWO; trace_dwc3_complete_trb(ep0, trb); - ep0->trb_enqueue = 0; + + if (r->direction) + dwc->eps[1]->trb_enqueue = 0; + else + dwc->eps[0]->trb_enqueue = 0; + dwc->ep0_bounced = false; } -- cgit v1.1 From 8813a59ed892305b5ac1b5b901740b1ad4b5fefa Mon Sep 17 00:00:00 2001 From: John Keeping <john@metanate.com> Date: Fri, 12 Jan 2018 18:43:32 +0000 Subject: usb: gadget: f_uac2: fix bFirstInterface in composite gadget If there are multiple functions associated with a configuration, then the UAC2 interfaces may not start at zero. Set the correct first interface number in the association descriptor so that the audio interfaces are enumerated correctly in this case. Reviewed-by: Krzysztof Opasiak <k.opasiak@samsung.com> Signed-off-by: John Keeping <john@metanate.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/gadget/function/f_uac2.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 11fe788..d2dc1f0 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -524,6 +524,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); return ret; } + iad_desc.bFirstInterface = ret; + std_ac_if_desc.bInterfaceNumber = ret; uac2->ac_intf = ret; uac2->ac_alt = 0; -- cgit v1.1 From 00b42170c86f90ac9dea83a7dfcd3f0c38098fe2 Mon Sep 17 00:00:00 2001 From: Brian Norris <briannorris@chromium.org> Date: Wed, 17 Jan 2018 13:22:49 -0800 Subject: usb: dwc3: Undo PHY init if soft reset fails In this function, we init the USB2 and USB3 PHYs, but if soft reset times out, we don't unwind this. Noticed by inspection. Signed-off-by: Brian Norris <briannorris@chromium.org> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/dwc3/core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index ade2ab0..bc2467f 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -234,6 +234,9 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) udelay(1); } while (--retries); + phy_exit(dwc->usb3_generic_phy); + phy_exit(dwc->usb2_generic_phy); + return -ETIMEDOUT; } -- cgit v1.1 From c4a5153e87fdf6805f63ff57556260e2554155a5 Mon Sep 17 00:00:00 2001 From: Manu Gautam <mgautam@codeaurora.org> Date: Thu, 18 Jan 2018 16:54:30 +0530 Subject: usb: dwc3: core: Power-off core/PHYs on system_suspend in host mode Commit 689bf72c6e0d ("usb: dwc3: Don't reinitialize core during host bus-suspend/resume") updated suspend/resume routines to not power_off and reinit PHYs/core for host mode. It broke platforms that rely on DWC3 core to power_off PHYs to enter low power state on system suspend. Perform dwc3_core_exit/init only during host mode system_suspend/ resume to addresses power regression from above mentioned patch and also allow USB session to stay connected across runtime_suspend/resume in host mode. While at it also replace existing checks for HOST only dr_mode with current_dr_role to have similar core driver behavior for both Host-only and DRD+Host configurations. Fixes: 689bf72c6e0d ("usb: dwc3: Don't reinitialize core during host bus-suspend/resume") Reviewed-by: Roger Quadros <rogerq@ti.com> Signed-off-by: Manu Gautam <mgautam@codeaurora.org> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/dwc3/core.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index bc2467f..59511f2 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -100,6 +100,8 @@ static void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); reg |= DWC3_GCTL_PRTCAPDIR(mode); dwc3_writel(dwc->regs, DWC3_GCTL, reg); + + dwc->current_dr_role = mode; } static void __dwc3_set_mode(struct work_struct *work) @@ -133,8 +135,6 @@ static void __dwc3_set_mode(struct work_struct *work) dwc3_set_prtcap(dwc, dwc->desired_dr_role); - dwc->current_dr_role = dwc->desired_dr_role; - spin_unlock_irqrestore(&dwc->lock, flags); switch (dwc->desired_dr_role) { @@ -219,7 +219,7 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) * XHCI driver will reset the host block. If dwc3 was configured for * host-only mode, then we can return early. */ - if (dwc->dr_mode == USB_DR_MODE_HOST) + if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) return 0; reg = dwc3_readl(dwc->regs, DWC3_DCTL); @@ -919,7 +919,6 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) switch (dwc->dr_mode) { case USB_DR_MODE_PERIPHERAL: - dwc->current_dr_role = DWC3_GCTL_PRTCAP_DEVICE; dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); if (dwc->usb2_phy) @@ -935,7 +934,6 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) } break; case USB_DR_MODE_HOST: - dwc->current_dr_role = DWC3_GCTL_PRTCAP_HOST; dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); if (dwc->usb2_phy) @@ -1287,7 +1285,7 @@ static int dwc3_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -static int dwc3_suspend_common(struct dwc3 *dwc) +static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) { unsigned long flags; @@ -1299,6 +1297,10 @@ static int dwc3_suspend_common(struct dwc3 *dwc) dwc3_core_exit(dwc); break; case DWC3_GCTL_PRTCAP_HOST: + /* do nothing during host runtime_suspend */ + if (!PMSG_IS_AUTO(msg)) + dwc3_core_exit(dwc); + break; default: /* do nothing */ break; @@ -1307,7 +1309,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc) return 0; } -static int dwc3_resume_common(struct dwc3 *dwc) +static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) { unsigned long flags; int ret; @@ -1323,6 +1325,13 @@ static int dwc3_resume_common(struct dwc3 *dwc) spin_unlock_irqrestore(&dwc->lock, flags); break; case DWC3_GCTL_PRTCAP_HOST: + /* nothing to do on host runtime_resume */ + if (!PMSG_IS_AUTO(msg)) { + ret = dwc3_core_init(dwc); + if (ret) + return ret; + } + break; default: /* do nothing */ break; @@ -1334,12 +1343,11 @@ static int dwc3_resume_common(struct dwc3 *dwc) static int dwc3_runtime_checks(struct dwc3 *dwc) { switch (dwc->current_dr_role) { - case USB_DR_MODE_PERIPHERAL: - case USB_DR_MODE_OTG: + case DWC3_GCTL_PRTCAP_DEVICE: if (dwc->connected) return -EBUSY; break; - case USB_DR_MODE_HOST: + case DWC3_GCTL_PRTCAP_HOST: default: /* do nothing */ break; @@ -1356,7 +1364,7 @@ static int dwc3_runtime_suspend(struct device *dev) if (dwc3_runtime_checks(dwc)) return -EBUSY; - ret = dwc3_suspend_common(dwc); + ret = dwc3_suspend_common(dwc, PMSG_AUTO_SUSPEND); if (ret) return ret; @@ -1372,7 +1380,7 @@ static int dwc3_runtime_resume(struct device *dev) device_init_wakeup(dev, false); - ret = dwc3_resume_common(dwc); + ret = dwc3_resume_common(dwc, PMSG_AUTO_RESUME); if (ret) return ret; @@ -1419,7 +1427,7 @@ static int dwc3_suspend(struct device *dev) struct dwc3 *dwc = dev_get_drvdata(dev); int ret; - ret = dwc3_suspend_common(dwc); + ret = dwc3_suspend_common(dwc, PMSG_SUSPEND); if (ret) return ret; @@ -1435,7 +1443,7 @@ static int dwc3_resume(struct device *dev) pinctrl_pm_select_default_state(dev); - ret = dwc3_resume_common(dwc); + ret = dwc3_resume_common(dwc, PMSG_RESUME); if (ret) return ret; -- cgit v1.1 From 499350865387f8b8c40a9e9453a9a7eb3cec5dc4 Mon Sep 17 00:00:00 2001 From: Fabio Estevam <fabio.estevam@nxp.com> Date: Thu, 18 Jan 2018 00:22:45 -0200 Subject: usb: phy: mxs: Fix NULL pointer dereference on i.MX23/28 Commit e93650994a95 ("usb: phy: mxs: add usb charger type detection") causes the following kernel hang on i.MX28: [ 2.207973] usbcore: registered new interface driver usb-storage [ 2.235659] Unable to handle kernel NULL pointer dereference at virtual address 00000188 [ 2.244195] pgd = (ptrval) [ 2.246994] [00000188] *pgd=00000000 [ 2.250676] Internal error: Oops: 5 [#1] ARM [ 2.254979] Modules linked in: [ 2.258089] CPU: 0 PID: 1 Comm: swapper Not tainted 4.15.0-rc8-next-20180117-00002-g75d5f21 #7 [ 2.266724] Hardware name: Freescale MXS (Device Tree) [ 2.271921] PC is at regmap_read+0x0/0x5c [ 2.275977] LR is at mxs_phy_charger_detect+0x34/0x1dc mxs_phy_charger_detect() makes accesses to the anatop registers via regmap, however i.MX23/28 do not have such registers, which causes a NULL pointer dereference. Fix the issue by doing a NULL check on the 'regmap' pointer. Fixes: e93650994a95 ("usb: phy: mxs: add usb charger type detection") Cc: <stable@vger.kernel.org> # v4.15 Reviewed-by: Li Jun <jun.li@nxp.com> Acked-by: Peter Chen <peter.chen@nxp.com> Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/phy/phy-mxs-usb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index da031c4..fbec863 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -602,6 +602,9 @@ static enum usb_charger_type mxs_phy_charger_detect(struct usb_phy *phy) void __iomem *base = phy->io_priv; enum usb_charger_type chgr_type = UNKNOWN_TYPE; + if (!regmap) + return UNKNOWN_TYPE; + if (mxs_charger_data_contact_detect(mxs_phy)) return chgr_type; -- cgit v1.1 From 6cf439e0d37463e42784271179c8a308fd7493c6 Mon Sep 17 00:00:00 2001 From: Jack Pham <jackp@codeaurora.org> Date: Wed, 24 Jan 2018 00:11:53 -0800 Subject: usb: gadget: f_fs: Process all descriptors during bind During _ffs_func_bind(), the received descriptors are evaluated to prepare for binding with the gadget in order to allocate endpoints and optionally set up OS descriptors. However, the high- and super-speed descriptors are only parsed based on whether the gadget_is_dualspeed() and gadget_is_superspeed() calls are true, respectively. This is a problem in case a userspace program always provides all of the {full,high,super,OS} descriptors when configuring a function. Then, for example if a gadget device is not capable of SuperSpeed, the call to ffs_do_descs() for the SS descriptors is skipped, resulting in an incorrect offset calculation for the vla_ptr when moving on to the OS descriptors that follow. This causes ffs_do_os_descs() to fail as it is now looking at the SS descriptors' offset within the raw_descs buffer instead. _ffs_func_bind() should evaluate the descriptors unconditionally, so remove the checks for gadget speed. Fixes: f0175ab51993 ("usb: gadget: f_fs: OS descriptors support") Cc: stable@vger.kernel.org Co-Developed-by: Mayank Rana <mrana@codeaurora.org> Signed-off-by: Mayank Rana <mrana@codeaurora.org> Signed-off-by: Jack Pham <jackp@codeaurora.org> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/gadget/function/f_fs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 8f2cf3b..49fc589 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -2979,10 +2979,8 @@ static int _ffs_func_bind(struct usb_configuration *c, struct ffs_data *ffs = func->ffs; const int full = !!func->ffs->fs_descs_count; - const int high = gadget_is_dualspeed(func->gadget) && - func->ffs->hs_descs_count; - const int super = gadget_is_superspeed(func->gadget) && - func->ffs->ss_descs_count; + const int high = !!func->ffs->hs_descs_count; + const int super = !!func->ffs->ss_descs_count; int fs_len, hs_len, ss_len, ret, i; struct ffs_ep *eps_ptr; -- cgit v1.1 From 675272d092e4a5570bace92593776f7348daf4c5 Mon Sep 17 00:00:00 2001 From: Jack Pham <jackp@codeaurora.org> Date: Wed, 24 Jan 2018 23:58:20 -0800 Subject: usb: gadget: f_fs: Use config_ep_by_speed() In commit 2bfa0719ac2a ("usb: gadget: function: f_fs: pass companion descriptor along") there is a pointer arithmetic bug where the comp_desc is obtained as follows: comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds + USB_DT_ENDPOINT_SIZE); Since ds is a pointer to usb_endpoint_descriptor, adding 7 to it ends up going out of bounds (7 * sizeof(struct usb_endpoint_descriptor), which is actually 7*9 bytes) past the SS descriptor. As a result the maxburst value will be read incorrectly, and the UDC driver will also get a garbage comp_desc (assuming it uses it). Since Felipe wrote, "Eventually, f_fs.c should be converted to use config_ep_by_speed() like all other functions, though", let's finally do it. This allows the other usb_ep fields to be properly populated, such as maxpacket and mult. It also eliminates the awkward speed-based descriptor lookup since config_ep_by_speed() does that already using the ones found in struct usb_function. Fixes: 2bfa0719ac2a ("usb: gadget: function: f_fs: pass companion descriptor along") Cc: stable@vger.kernel.org Signed-off-by: Jack Pham <jackp@codeaurora.org> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/gadget/function/f_fs.c | 38 +++++++------------------------------- 1 file changed, 7 insertions(+), 31 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 49fc589..c2592d8 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1855,44 +1855,20 @@ static int ffs_func_eps_enable(struct ffs_function *func) spin_lock_irqsave(&func->ffs->eps_lock, flags); while(count--) { - struct usb_endpoint_descriptor *ds; - struct usb_ss_ep_comp_descriptor *comp_desc = NULL; - int needs_comp_desc = false; - int desc_idx; - - if (ffs->gadget->speed == USB_SPEED_SUPER) { - desc_idx = 2; - needs_comp_desc = true; - } else if (ffs->gadget->speed == USB_SPEED_HIGH) - desc_idx = 1; - else - desc_idx = 0; - - /* fall-back to lower speed if desc missing for current speed */ - do { - ds = ep->descs[desc_idx]; - } while (!ds && --desc_idx >= 0); - - if (!ds) { - ret = -EINVAL; - break; - } - ep->ep->driver_data = ep; - ep->ep->desc = ds; - if (needs_comp_desc) { - comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds + - USB_DT_ENDPOINT_SIZE); - ep->ep->maxburst = comp_desc->bMaxBurst + 1; - ep->ep->comp_desc = comp_desc; + ret = config_ep_by_speed(func->gadget, &func->function, ep->ep); + if (ret) { + pr_err("%s: config_ep_by_speed(%s) returned %d\n", + __func__, ep->ep->name, ret); + break; } ret = usb_ep_enable(ep->ep); if (likely(!ret)) { epfile->ep = ep; - epfile->in = usb_endpoint_dir_in(ds); - epfile->isoc = usb_endpoint_xfer_isoc(ds); + epfile->in = usb_endpoint_dir_in(ep->ep->desc); + epfile->isoc = usb_endpoint_xfer_isoc(ep->ep->desc); } else { break; } -- cgit v1.1 From c49f63055e252810e5d6c83a4943b18db16b3cd8 Mon Sep 17 00:00:00 2001 From: Roger Quadros <rogerq@ti.com> Date: Mon, 22 Jan 2018 15:01:42 +0200 Subject: usb: dwc3: omap: don't miss events during suspend/resume The USB cable state can change during suspend/resume so be sure to check and update the extcon state. Signed-off-by: Roger Quadros <rogerq@ti.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/dwc3/dwc3-omap.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index a4719e8..ed8b865 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -582,9 +582,25 @@ static int dwc3_omap_resume(struct device *dev) return 0; } +static void dwc3_omap_complete(struct device *dev) +{ + struct dwc3_omap *omap = dev_get_drvdata(dev); + + if (extcon_get_state(omap->edev, EXTCON_USB)) + dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); + else + dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF); + + if (extcon_get_state(omap->edev, EXTCON_USB_HOST)) + dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); + else + dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT); +} + static const struct dev_pm_ops dwc3_omap_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume) + .complete = dwc3_omap_complete, }; #define DEV_PM_OPS (&dwc3_omap_dev_pm_ops) -- cgit v1.1 From e74bd4d358e5455233f1dcc3975425905b270b91 Mon Sep 17 00:00:00 2001 From: Manu Gautam <mgautam@codeaurora.org> Date: Thu, 21 Dec 2017 09:54:25 +0530 Subject: usb: gadget: core: Fix use-after-free of usb_request Driver is tracing usb_request after freeing it. Fix it by changing the order. Signed-off-by: Manu Gautam <mgautam@codeaurora.org> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/gadget/udc/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 859d5b1..1f8b19d 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -180,8 +180,8 @@ EXPORT_SYMBOL_GPL(usb_ep_alloc_request); void usb_ep_free_request(struct usb_ep *ep, struct usb_request *req) { - ep->ops->free_request(ep, req); trace_usb_ep_free_request(ep, req, 0); + ep->ops->free_request(ep, req); } EXPORT_SYMBOL_GPL(usb_ep_free_request); -- cgit v1.1 From b16ea8b9492e99e03b1269fe93ebdbf8e4eabf8a Mon Sep 17 00:00:00 2001 From: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Date: Fri, 2 Feb 2018 13:21:35 -0800 Subject: usb: dwc3: Fix GDBGFIFOSPACE_TYPE values The FIFO/Queue type values are incorrect. Correct them according to DWC_usb3 programming guide section 1.2.27 (or DWC_usb31 section 1.2.25). Additionally, this patch includes ProtocolStatusQ and AuxEventQ types. Fixes: cf6d867d3b57 ("usb: dwc3: core: add fifo space helper") Signed-off-by: Thinh Nguyen <thinhn@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/dwc3/core.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 03c7aaa..185b960 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -158,13 +158,15 @@ #define DWC3_GDBGFIFOSPACE_TYPE(n) (((n) << 5) & 0x1e0) #define DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(n) (((n) >> 16) & 0xffff) -#define DWC3_TXFIFOQ 1 -#define DWC3_RXFIFOQ 3 -#define DWC3_TXREQQ 5 -#define DWC3_RXREQQ 7 -#define DWC3_RXINFOQ 9 -#define DWC3_DESCFETCHQ 13 -#define DWC3_EVENTQ 15 +#define DWC3_TXFIFOQ 0 +#define DWC3_RXFIFOQ 1 +#define DWC3_TXREQQ 2 +#define DWC3_RXREQQ 3 +#define DWC3_RXINFOQ 4 +#define DWC3_PSTATQ 5 +#define DWC3_DESCFETCHQ 6 +#define DWC3_EVENTQ 7 +#define DWC3_AUXEVENTQ 8 /* Global RX Threshold Configuration Register */ #define DWC3_GRXTHRCFG_MAXRXBURSTSIZE(n) (((n) & 0x1f) << 19) -- cgit v1.1 From 20bf410ecf9e9c045f4b0548d516dd3de8691074 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson <ulfalizer@gmail.com> Date: Mon, 5 Feb 2018 02:21:23 +0100 Subject: usb: gadget: udc: Remove USB_GADGET_DUALSPEED select USB_GADGET_DUALSPEED was removed by commit 85b8614d7223 ("usb: gadget: get rid of USB_GADGET_{DUAL,SUPER}SPEED"), but the USB_SNP_UDC_PLAT symbol still selects it. Remove the USB_GADGET_DUALSPEED select from USB_SNP_UDC_PLAT. Discovered with the https://github.com/ulfalizer/Kconfiglib/blob/master/examples/list_undefined.py script. Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/gadget/udc/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index 1e95670..0875d38 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -274,7 +274,6 @@ config USB_SNP_UDC_PLAT tristate "Synopsys USB 2.0 Device controller" depends on USB_GADGET && OF && HAS_DMA depends on EXTCON || EXTCON=n - select USB_GADGET_DUALSPEED select USB_SNP_CORE default ARCH_BCM_IPROC help -- cgit v1.1 From 17aa31f13cad25daa19d3f923323f552e87bc874 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Date: Mon, 5 Feb 2018 17:12:35 +0900 Subject: usb: renesas_usbhs: missed the "running" flag in usb_dmac with rx path This fixes an issue that a gadget driver (usb_f_fs) is possible to stop rx transactions after the usb-dmac is used because the following functions missed to set/check the "running" flag. - usbhsf_dma_prepare_pop_with_usb_dmac() - usbhsf_dma_pop_done_with_usb_dmac() So, if next transaction uses pio, the usbhsf_prepare_pop() can not start the transaction because the "running" flag is 0. Fixes: 8355b2b3082d ("usb: renesas_usbhs: fix the behavior of some usbhs_pkt_handle") Cc: <stable@vger.kernel.org> # v3.19+ Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/renesas_usbhs/fifo.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 5925d11..39fa2fc 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -982,6 +982,10 @@ static int usbhsf_dma_prepare_pop_with_usb_dmac(struct usbhs_pkt *pkt, if ((uintptr_t)pkt->buf & (USBHS_USB_DMAC_XFER_SIZE - 1)) goto usbhsf_pio_prepare_pop; + /* return at this time if the pipe is running */ + if (usbhs_pipe_is_running(pipe)) + return 0; + usbhs_pipe_config_change_bfre(pipe, 1); ret = usbhsf_fifo_select(pipe, fifo, 0); @@ -1172,6 +1176,7 @@ static int usbhsf_dma_pop_done_with_usb_dmac(struct usbhs_pkt *pkt, usbhsf_fifo_clear(pipe, fifo); pkt->actual = usbhs_dma_calc_received_size(pkt, chan, rcv_len); + usbhs_pipe_running(pipe, 0); usbhsf_dma_stop(pipe, fifo); usbhsf_dma_unmap(pkt); usbhsf_fifo_unselect(pipe, pipe->fifo); -- cgit v1.1 From 20c63f4089cceab803438c383631963e34c4d8e5 Mon Sep 17 00:00:00 2001 From: Stefan Agner <stefan@agner.ch> Date: Mon, 12 Feb 2018 00:14:42 +0100 Subject: usb: gadget: fsl_udc_core: fix ep valid checks Clang reports the following warning: drivers/usb/gadget/udc/fsl_udc_core.c:1312:10: warning: address of array 'ep->name' will always evaluate to 'true' [-Wpointer-bool-conversion] if (ep->name) ~~ ~~~~^~~~ It seems that the authors intention was to check if the ep has been configured through struct_ep_setup. Check whether struct usb_ep name pointer has been set instead. Signed-off-by: Stefan Agner <stefan@agner.ch> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/gadget/udc/fsl_udc_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index e5b4ee9..56b517a 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c @@ -1305,7 +1305,7 @@ static void udc_reset_ep_queue(struct fsl_udc *udc, u8 pipe) { struct fsl_ep *ep = get_ep_by_pipe(udc, pipe); - if (ep->name) + if (ep->ep.name) nuke(ep, -ESHUTDOWN); } @@ -1693,7 +1693,7 @@ static void dtd_complete_irq(struct fsl_udc *udc) curr_ep = get_ep_by_pipe(udc, i); /* If the ep is configured */ - if (curr_ep->name == NULL) { + if (!curr_ep->ep.name) { WARNING("Invalid EP?"); continue; } -- cgit v1.1 From 201ec568c57a43dbc73c7ac00e73c3c2d39559fc Mon Sep 17 00:00:00 2001 From: Minas Harutyunyan <hminas@synopsys.com> Date: Tue, 16 Jan 2018 16:03:32 +0400 Subject: usb: dwc2: Add safety check in setting of descriptor chain pointers In some cases device sending ZLP IN on non EP0 which reassigning EP0 OUT descriptor pointer to that EP. Dedicated for EP0 OUT descriptor multiple time re-used by other EP while that descriptor already in use by EP0 OUT for SETUP transaction. As result when SETUP packet received BNA interrupt asserting. In dwc2_hsotg_program_zlp() function dwc2_gadget_set_ep0_desc_chain() must be called only for EP0. Acked-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Minas Harutyunyan <hminas@synopsys.com> Signed-off-by: Grigor Tovmasyan <tovmasya@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/dwc2/gadget.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index e4c3ce0..57c7400 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -1917,7 +1917,9 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg, /* Not specific buffer needed for ep0 ZLP */ dma_addr_t dma = hs_ep->desc_list_dma; - dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep); + if (!index) + dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep); + dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, dma, 0); } else { dwc2_writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) | -- cgit v1.1 From 9e95a66cce7250c358d496e1c3b62e29ce79ef40 Mon Sep 17 00:00:00 2001 From: Minas Harutyunyan <hminas@synopsys.com> Date: Tue, 16 Jan 2018 16:03:58 +0400 Subject: usb: dwc2: Add safety check for STSPHSERCVD intr STSPHSERCVD (status phase received) interrupt should be handled when EP0 is in DWC2_EP0_DATA_OUT state. Sometimes STSPHSERCVD interrupt asserted , when EP0 is not in DATA_OUT state. Spurios interrupt. Acked-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Minas Harutyunyan <hminas@synopsys.com> Signed-off-by: Grigor Tovmasyan <tovmasya@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/dwc2/gadget.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 57c7400..d6222e9 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -2976,9 +2976,13 @@ static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx, if (ints & DXEPINT_STSPHSERCVD) { dev_dbg(hsotg->dev, "%s: StsPhseRcvd\n", __func__); - /* Move to STATUS IN for DDMA */ - if (using_desc_dma(hsotg)) - dwc2_hsotg_ep0_zlp(hsotg, true); + /* Safety check EP0 state when STSPHSERCVD asserted */ + if (hsotg->ep0_state == DWC2_EP0_DATA_OUT) { + /* Move to STATUS IN for DDMA */ + if (using_desc_dma(hsotg)) + dwc2_hsotg_ep0_zlp(hsotg, true); + } + } if (ints & DXEPINT_BACK2BACKSETUP) -- cgit v1.1 From 755d739534f998d92e348fba8ffb0478416576e7 Mon Sep 17 00:00:00 2001 From: Vardan Mikayelyan <mvardan@synopsys.com> Date: Tue, 16 Jan 2018 16:04:24 +0400 Subject: usb: dwc2: Fix dwc2_hsotg_core_init_disconnected() We should call dwc2_hsotg_enqueue_setup() after properly setting lx_state. Because it may cause error-out from dwc2_hsotg_enqueue_setup() due to wrong value in lx_state. Issue can be reproduced by loading driver while connected A-Connector (start in A-HOST mode) then disconnect A-Connector to switch to B-DEVICE. Acked-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Vardan Mikayelyan <mvardan@synopsys.com> Signed-off-by: Grigor Tovmasyan <tovmasya@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/dwc2/gadget.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index d6222e9..5bcad1d 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -3381,12 +3381,6 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, dwc2_writel(dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) | DXEPCTL_USBACTEP, hsotg->regs + DIEPCTL0); - dwc2_hsotg_enqueue_setup(hsotg); - - dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", - dwc2_readl(hsotg->regs + DIEPCTL0), - dwc2_readl(hsotg->regs + DOEPCTL0)); - /* clear global NAKs */ val = DCTL_CGOUTNAK | DCTL_CGNPINNAK; if (!is_usb_reset) @@ -3397,6 +3391,12 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, mdelay(3); hsotg->lx_state = DWC2_L0; + + dwc2_hsotg_enqueue_setup(hsotg); + + dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", + dwc2_readl(hsotg->regs + DIEPCTL0), + dwc2_readl(hsotg->regs + DOEPCTL0)); } static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg) -- cgit v1.1 From 8874ae5f15f3feef3b4a415b9aed51edcf449aa1 Mon Sep 17 00:00:00 2001 From: Wei Yongjun <weiyongjun1@huawei.com> Date: Tue, 23 Jan 2018 09:35:14 +0000 Subject: USB: gadget: udc: Add missing platform_device_put() on error in bdc_pci_probe() Add the missing platform_device_put() before return from bdc_pci_probe() in the platform_device_add_resources() error handling case. Fixes: efed421a94e6 ("usb: gadget: Add UDC driver for Broadcom USB3.0 device controller IP BDC") Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/gadget/udc/bdc/bdc_pci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/bdc/bdc_pci.c b/drivers/usb/gadget/udc/bdc/bdc_pci.c index 1e940f0..6dbc489 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_pci.c +++ b/drivers/usb/gadget/udc/bdc/bdc_pci.c @@ -77,6 +77,7 @@ static int bdc_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) if (ret) { dev_err(&pci->dev, "couldn't add resources to bdc device\n"); + platform_device_put(bdc); return ret; } -- cgit v1.1 From 98112041bcca164676367e261c8c1073ef70cb51 Mon Sep 17 00:00:00 2001 From: Roger Quadros <rogerq@ti.com> Date: Mon, 12 Feb 2018 15:30:08 +0200 Subject: usb: dwc3: core: Fix ULPI PHYs and prevent phy_get/ulpi_init during suspend/resume In order for ULPI PHYs to work, dwc3_phy_setup() and dwc3_ulpi_init() must be doene before dwc3_core_get_phy(). commit 541768b08a40 ("usb: dwc3: core: Call dwc3_core_get_phy() before initializing phys") broke this. The other issue is that dwc3_core_get_phy() and dwc3_ulpi_init() should be called only once during the life cycle of the driver. However, as dwc3_core_init() is called during system suspend/resume it will result in multiple calls to dwc3_core_get_phy() and dwc3_ulpi_init() which is wrong. Fix this by moving dwc3_ulpi_init() out of dwc3_phy_setup() into dwc3_core_ulpi_init(). Use a flag 'ulpi_ready' to ensure that dwc3_core_ulpi_init() is called only once from dwc3_core_init(). Use another flag 'phys_ready' to call dwc3_core_get_phy() only once from dwc3_core_init(). Fixes: 541768b08a40 ("usb: dwc3: core: Call dwc3_core_get_phy() before initializing phys") Fixes: f54edb539c11 ("usb: dwc3: core: initialize ULPI before trying to get the PHY") Cc: linux-stable <stable@vger.kernel.org> # >= v4.13 Signed-off-by: Roger Quadros <rogerq@ti.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/dwc3/core.c | 47 ++++++++++++++++++++++++++++++++++++----------- drivers/usb/dwc3/core.h | 5 +++++ 2 files changed, 41 insertions(+), 11 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 59511f2..f1d838a 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -486,6 +486,22 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc) parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); } +static int dwc3_core_ulpi_init(struct dwc3 *dwc) +{ + int intf; + int ret = 0; + + intf = DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3); + + if (intf == DWC3_GHWPARAMS3_HSPHY_IFC_ULPI || + (intf == DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI && + dwc->hsphy_interface && + !strncmp(dwc->hsphy_interface, "ulpi", 4))) + ret = dwc3_ulpi_init(dwc); + + return ret; +} + /** * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core * @dwc: Pointer to our controller context structure @@ -497,7 +513,6 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc) static int dwc3_phy_setup(struct dwc3 *dwc) { u32 reg; - int ret; reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); @@ -568,9 +583,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc) } /* FALLTHROUGH */ case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: - ret = dwc3_ulpi_init(dwc); - if (ret) - return ret; /* FALLTHROUGH */ default: break; @@ -727,6 +739,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc) } static int dwc3_core_get_phy(struct dwc3 *dwc); +static int dwc3_core_ulpi_init(struct dwc3 *dwc); /** * dwc3_core_init - Low-level initialization of DWC3 Core @@ -758,17 +771,27 @@ static int dwc3_core_init(struct dwc3 *dwc) dwc->maximum_speed = USB_SPEED_HIGH; } - ret = dwc3_core_get_phy(dwc); + ret = dwc3_phy_setup(dwc); if (ret) goto err0; - ret = dwc3_core_soft_reset(dwc); - if (ret) - goto err0; + if (!dwc->ulpi_ready) { + ret = dwc3_core_ulpi_init(dwc); + if (ret) + goto err0; + dwc->ulpi_ready = true; + } - ret = dwc3_phy_setup(dwc); + if (!dwc->phys_ready) { + ret = dwc3_core_get_phy(dwc); + if (ret) + goto err0a; + dwc->phys_ready = true; + } + + ret = dwc3_core_soft_reset(dwc); if (ret) - goto err0; + goto err0a; dwc3_core_setup_global_control(dwc); dwc3_core_num_eps(dwc); @@ -841,6 +864,9 @@ err1: phy_exit(dwc->usb2_generic_phy); phy_exit(dwc->usb3_generic_phy); +err0a: + dwc3_ulpi_exit(dwc); + err0: return ret; } @@ -1235,7 +1261,6 @@ err4: err3: dwc3_free_event_buffers(dwc); - dwc3_ulpi_exit(dwc); err2: pm_runtime_allow(&pdev->dev); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 185b960..860d2bc 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -797,7 +797,9 @@ struct dwc3_scratchpad_array { * @usb3_phy: pointer to USB3 PHY * @usb2_generic_phy: pointer to USB2 PHY * @usb3_generic_phy: pointer to USB3 PHY + * @phys_ready: flag to indicate that PHYs are ready * @ulpi: pointer to ulpi interface + * @ulpi_ready: flag to indicate that ULPI is initialized * @u2sel: parameter from Set SEL request. * @u2pel: parameter from Set SEL request. * @u1sel: parameter from Set SEL request. @@ -895,7 +897,10 @@ struct dwc3 { struct phy *usb2_generic_phy; struct phy *usb3_generic_phy; + bool phys_ready; + struct ulpi *ulpi; + bool ulpi_ready; void __iomem *regs; size_t regs_size; -- cgit v1.1 From bde0716d1f076e4c913c7946bcc858f71243c7a0 Mon Sep 17 00:00:00 2001 From: Joe Lee <asmt.swfae@gmail.com> Date: Mon, 12 Feb 2018 14:24:46 +0200 Subject: xhci: workaround for AMD Promontory disabled ports wakeup For AMD Promontory xHCI host, although you can disable USB ports in BIOS settings, those ports will be enabled anyway after you remove a device on that port and re-plug it in again. It's a known limitation of the chip. As a workaround we can clear the PORT_WAKE_BITS. [commit and code comment rephrasing -Mathias] Signed-off-by: Joe Lee <asmt.swfae@gmail.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/pci-quirks.c | 109 ++++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/pci-quirks.h | 5 ++ drivers/usb/host/xhci-hub.c | 7 +++ drivers/usb/host/xhci-pci.c | 11 +++++ drivers/usb/host/xhci.h | 2 +- 5 files changed, 133 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 1615367..67ad4bb 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -66,6 +66,23 @@ #define AX_INDXC 0x30 #define AX_DATAC 0x34 +#define PT_ADDR_INDX 0xE8 +#define PT_READ_INDX 0xE4 +#define PT_SIG_1_ADDR 0xA520 +#define PT_SIG_2_ADDR 0xA521 +#define PT_SIG_3_ADDR 0xA522 +#define PT_SIG_4_ADDR 0xA523 +#define PT_SIG_1_DATA 0x78 +#define PT_SIG_2_DATA 0x56 +#define PT_SIG_3_DATA 0x34 +#define PT_SIG_4_DATA 0x12 +#define PT4_P1_REG 0xB521 +#define PT4_P2_REG 0xB522 +#define PT2_P1_REG 0xD520 +#define PT2_P2_REG 0xD521 +#define PT1_P1_REG 0xD522 +#define PT1_P2_REG 0xD523 + #define NB_PCIE_INDX_ADDR 0xe0 #define NB_PCIE_INDX_DATA 0xe4 #define PCIE_P_CNTL 0x10040 @@ -513,6 +530,98 @@ void usb_amd_dev_put(void) EXPORT_SYMBOL_GPL(usb_amd_dev_put); /* + * Check if port is disabled in BIOS on AMD Promontory host. + * BIOS Disabled ports may wake on connect/disconnect and need + * driver workaround to keep them disabled. + * Returns true if port is marked disabled. + */ +bool usb_amd_pt_check_port(struct device *device, int port) +{ + unsigned char value, port_shift; + struct pci_dev *pdev; + u16 reg; + + pdev = to_pci_dev(device); + pci_write_config_word(pdev, PT_ADDR_INDX, PT_SIG_1_ADDR); + + pci_read_config_byte(pdev, PT_READ_INDX, &value); + if (value != PT_SIG_1_DATA) + return false; + + pci_write_config_word(pdev, PT_ADDR_INDX, PT_SIG_2_ADDR); + + pci_read_config_byte(pdev, PT_READ_INDX, &value); + if (value != PT_SIG_2_DATA) + return false; + + pci_write_config_word(pdev, PT_ADDR_INDX, PT_SIG_3_ADDR); + + pci_read_config_byte(pdev, PT_READ_INDX, &value); + if (value != PT_SIG_3_DATA) + return false; + + pci_write_config_word(pdev, PT_ADDR_INDX, PT_SIG_4_ADDR); + + pci_read_config_byte(pdev, PT_READ_INDX, &value); + if (value != PT_SIG_4_DATA) + return false; + + /* Check disabled port setting, if bit is set port is enabled */ + switch (pdev->device) { + case 0x43b9: + case 0x43ba: + /* + * device is AMD_PROMONTORYA_4(0x43b9) or PROMONTORYA_3(0x43ba) + * PT4_P1_REG bits[7..1] represents USB2.0 ports 6 to 0 + * PT4_P2_REG bits[6..0] represents ports 13 to 7 + */ + if (port > 6) { + reg = PT4_P2_REG; + port_shift = port - 7; + } else { + reg = PT4_P1_REG; + port_shift = port + 1; + } + break; + case 0x43bb: + /* + * device is AMD_PROMONTORYA_2(0x43bb) + * PT2_P1_REG bits[7..5] represents USB2.0 ports 2 to 0 + * PT2_P2_REG bits[5..0] represents ports 9 to 3 + */ + if (port > 2) { + reg = PT2_P2_REG; + port_shift = port - 3; + } else { + reg = PT2_P1_REG; + port_shift = port + 5; + } + break; + case 0x43bc: + /* + * device is AMD_PROMONTORYA_1(0x43bc) + * PT1_P1_REG[7..4] represents USB2.0 ports 3 to 0 + * PT1_P2_REG[5..0] represents ports 9 to 4 + */ + if (port > 3) { + reg = PT1_P2_REG; + port_shift = port - 4; + } else { + reg = PT1_P1_REG; + port_shift = port + 4; + } + break; + default: + return false; + } + pci_write_config_word(pdev, PT_ADDR_INDX, reg); + pci_read_config_byte(pdev, PT_READ_INDX, &value); + + return !(value & BIT(port_shift)); +} +EXPORT_SYMBOL_GPL(usb_amd_pt_check_port); + +/* * Make sure the controller is completely inactive, unable to * generate interrupts or do DMA. */ diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index b68dcb5..4ca0d9b 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -17,6 +17,7 @@ void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev); void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); void sb800_prefetch(struct device *dev, int on); bool usb_xhci_needs_pci_reset(struct pci_dev *pdev); +bool usb_amd_pt_check_port(struct device *device, int port); #else struct pci_dev; static inline void usb_amd_quirk_pll_disable(void) {} @@ -25,6 +26,10 @@ static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {} static inline void usb_amd_dev_put(void) {} static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {} static inline void sb800_prefetch(struct device *dev, int on) {} +static inline bool usb_amd_pt_check_port(struct device *device, int port) +{ + return false; +} #endif /* CONFIG_USB_PCI */ #endif /* __LINUX_USB_PCI_QUIRKS_H */ diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 46d5e08..1df0c36 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1522,6 +1522,13 @@ int xhci_bus_suspend(struct usb_hcd *hcd) t2 |= PORT_WKOC_E | PORT_WKCONN_E; t2 &= ~PORT_WKDISC_E; } + + if ((xhci->quirks & XHCI_U2_DISABLE_WAKE) && + (hcd->speed < HCD_USB3)) { + if (usb_amd_pt_check_port(hcd->self.controller, + port_index)) + t2 &= ~PORT_WAKE_BITS; + } } else t2 &= ~PORT_WAKE_BITS; diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 6c79037..5262fa5 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -42,6 +42,10 @@ #define PCI_DEVICE_ID_INTEL_APL_XHCI 0x5aa8 #define PCI_DEVICE_ID_INTEL_DNV_XHCI 0x19d0 +#define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9 +#define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba +#define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb +#define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142 static const char hcd_name[] = "xhci_hcd"; @@ -125,6 +129,13 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) if (pdev->vendor == PCI_VENDOR_ID_AMD) xhci->quirks |= XHCI_TRUST_TX_LENGTH; + if ((pdev->vendor == PCI_VENDOR_ID_AMD) && + ((pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4) || + (pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_3) || + (pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_2) || + (pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_1))) + xhci->quirks |= XHCI_U2_DISABLE_WAKE; + if (pdev->vendor == PCI_VENDOR_ID_INTEL) { xhci->quirks |= XHCI_LPM_SUPPORT; xhci->quirks |= XHCI_INTEL_HOST; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 96099a2..e4d7d3d 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1822,7 +1822,7 @@ struct xhci_hcd { /* For controller with a broken Port Disable implementation */ #define XHCI_BROKEN_PORT_PED (1 << 25) #define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26) -/* Reserved. It was XHCI_U2_DISABLE_WAKE */ +#define XHCI_U2_DISABLE_WAKE (1 << 27) #define XHCI_ASMEDIA_MODIFY_FLOWCONTROL (1 << 28) #define XHCI_HW_LPM_DISABLE (1 << 29) -- cgit v1.1 From 1208d8a84fdcae6b395c57911cdf907450d30e70 Mon Sep 17 00:00:00 2001 From: Mathias Nyman <mathias.nyman@linux.intel.com> Date: Mon, 12 Feb 2018 14:24:47 +0200 Subject: xhci: Don't print a warning when setting link state for disabled ports When disabling a USB3 port the hub driver will set the port link state to U3 to prevent "ejected" or "safely removed" devices that are still physically connected from immediately re-enumerating. If the device was really unplugged, then error messages were printed as the hub tries to set the U3 link state for a port that is no longer enabled. xhci-hcd ee000000.usb: Cannot set link state. usb usb8-port1: cannot disable (err = -32) Don't print error message in xhci-hub if hub tries to set port link state for a disabled port. Return -ENODEV instead which also silences hub driver. Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/xhci-hub.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 1df0c36..72ebbc9 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1224,17 +1224,17 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = readl(port_array[wIndex]); break; } - - /* Software should not attempt to set - * port link state above '3' (U3) and the port - * must be enabled. - */ - if ((temp & PORT_PE) == 0 || - (link_state > USB_SS_PORT_LS_U3)) { - xhci_warn(xhci, "Cannot set link state.\n"); + /* Port must be enabled */ + if (!(temp & PORT_PE)) { + retval = -ENODEV; + break; + } + /* Can't set port link state above '3' (U3) */ + if (link_state > USB_SS_PORT_LS_U3) { + xhci_warn(xhci, "Cannot set port %d link state %d\n", + wIndex, link_state); goto error; } - if (link_state == USB_SS_PORT_LS_U3) { slot_id = xhci_find_slot_id_by_port(hcd, xhci, wIndex + 1); -- cgit v1.1 From fa2dfd0ec22e0069c84dfae162972cbbc7c75488 Mon Sep 17 00:00:00 2001 From: Zhengjun Xing <zhengjun.xing@linux.intel.com> Date: Mon, 12 Feb 2018 14:24:48 +0200 Subject: xhci: Fix NULL pointer in xhci debugfs Commit dde634057da7 ("xhci: Fix use-after-free in xhci debugfs") causes a null pointer dereference while fixing xhci-debugfs usage of ring pointers that were freed during hibernate. The fix passed addresses to ring pointers instead, but forgot to do this change for the xhci_ring_trb_show function. The address of the ring pointer passed to xhci-debugfs was of a temporary ring pointer "new_ring" instead of the actual ring "ring" pointer. The temporary new_ring pointer will be set to NULL later causing the NULL pointer dereference. This issue was seen when reading xhci related files in debugfs: cat /sys/kernel/debug/usb/xhci/*/devices/*/ep*/trbs [ 184.604861] BUG: unable to handle kernel NULL pointer dereference at (null) [ 184.613776] IP: xhci_ring_trb_show+0x3a/0x890 [ 184.618733] PGD 264193067 P4D 264193067 PUD 263238067 PMD 0 [ 184.625184] Oops: 0000 [#1] SMP [ 184.726410] RIP: 0010:xhci_ring_trb_show+0x3a/0x890 [ 184.731944] RSP: 0018:ffffba8243c0fd90 EFLAGS: 00010246 [ 184.737880] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 00000000000295d6 [ 184.746020] RDX: 00000000000295d5 RSI: 0000000000000001 RDI: ffff971a6418d400 [ 184.754121] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 [ 184.762222] R10: ffff971a64c98a80 R11: ffff971a62a00e40 R12: ffff971a62a85500 [ 184.770325] R13: 0000000000020000 R14: ffff971a6418d400 R15: ffff971a6418d400 [ 184.778448] FS: 00007fe725a79700(0000) GS:ffff971a6ec00000(0000) knlGS:0000000000000000 [ 184.787644] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 184.794168] CR2: 0000000000000000 CR3: 000000025f365005 CR4: 00000000003606f0 [ 184.802318] Call Trace: [ 184.805094] ? seq_read+0x281/0x3b0 [ 184.809068] seq_read+0xeb/0x3b0 [ 184.812735] full_proxy_read+0x4d/0x70 [ 184.817007] __vfs_read+0x23/0x120 [ 184.820870] vfs_read+0x91/0x130 [ 184.824538] SyS_read+0x42/0x90 [ 184.828106] entry_SYSCALL_64_fastpath+0x1a/0x7d Fixes: dde634057da7 ("xhci: Fix use-after-free in xhci debugfs") Cc: <stable@vger.kernel.org> # v4.15 Signed-off-by: Zhengjun Xing <zhengjun.xing@linux.intel.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/xhci-debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c index e26e685..5851052 100644 --- a/drivers/usb/host/xhci-debugfs.c +++ b/drivers/usb/host/xhci-debugfs.c @@ -211,7 +211,7 @@ static void xhci_ring_dump_segment(struct seq_file *s, static int xhci_ring_trb_show(struct seq_file *s, void *unused) { int i; - struct xhci_ring *ring = s->private; + struct xhci_ring *ring = *(struct xhci_ring **)s->private; struct xhci_segment *seg = ring->first_seg; for (i = 0; i < ring->num_segs; i++) { @@ -387,7 +387,7 @@ void xhci_debugfs_create_endpoint(struct xhci_hcd *xhci, snprintf(epriv->name, sizeof(epriv->name), "ep%02d", ep_index); epriv->root = xhci_debugfs_create_ring_dir(xhci, - &dev->eps[ep_index].new_ring, + &dev->eps[ep_index].ring, epriv->name, spriv->root); spriv->eps[ep_index] = epriv; -- cgit v1.1 From d91676717261578f429d3577dbe9154b26e8abf7 Mon Sep 17 00:00:00 2001 From: Zhengjun Xing <zhengjun.xing@linux.intel.com> Date: Mon, 12 Feb 2018 14:24:49 +0200 Subject: xhci: Fix xhci debugfs devices node disappearance after hibernation During system resume from hibernation, xhci host is reset, all the nodes in devices folder are removed in xhci_mem_cleanup function. Later nodes in /sys/kernel/debug/usb/xhci/* are created again in function xhci_run, but the nodes already exist, so the nodes still keep the old ones, finally device nodes in xhci debugfs folder /sys/kernel/debug/usb/xhci/*/devices/* are disappeared. This fix removed xhci debugfs nodes before the nodes are re-created, so all the nodes in xhci debugfs can be re-created successfully. Fixes: 02b6fdc2a153 ("usb: xhci: Add debugfs interface for xHCI driver") Cc: <stable@vger.kernel.org> # v4.15 Signed-off-by: Zhengjun Xing <zhengjun.xing@linux.intel.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/xhci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 1eeb339..b01bd64 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1014,6 +1014,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) xhci_dbg(xhci, "cleaning up memory\n"); xhci_mem_cleanup(xhci); + xhci_debugfs_exit(xhci); xhci_dbg(xhci, "xhci_stop completed - status = %x\n", readl(&xhci->op_regs->status)); -- cgit v1.1 From 8c5a93ebf7ac56d47f879b3c7c2f8c83b40c2cdb Mon Sep 17 00:00:00 2001 From: Zhengjun Xing <zhengjun.xing@linux.intel.com> Date: Mon, 12 Feb 2018 14:24:50 +0200 Subject: xhci: xhci debugfs device nodes weren't removed after device plugged out There is a bug after plugged out USB device, the device and its ep00 nodes are still kept, we need to remove the nodes in xhci_free_dev when USB device is plugged out. Fixes: 052f71e25a7e ("xhci: Fix xhci debugfs NULL pointer dereference in resume from hibernate") Cc: <stable@vger.kernel.org> # v4.15 Signed-off-by: Zhengjun Xing <zhengjun.xing@linux.intel.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/xhci.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index b01bd64..4adb6da 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3545,12 +3545,10 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) virt_dev->eps[i].ep_state &= ~EP_STOP_CMD_PENDING; del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); } - + xhci_debugfs_remove_slot(xhci, udev->slot_id); ret = xhci_disable_slot(xhci, udev->slot_id); - if (ret) { - xhci_debugfs_remove_slot(xhci, udev->slot_id); + if (ret) xhci_free_virt_device(xhci, udev->slot_id); - } } int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) -- cgit v1.1 From 11cd764dc9a030991880ad4d51db93918afa5822 Mon Sep 17 00:00:00 2001 From: Zhengjun Xing <zhengjun.xing@linux.intel.com> Date: Mon, 12 Feb 2018 14:24:51 +0200 Subject: xhci: fix xhci debugfs errors in xhci_stop In function xhci_stop, xhci_debugfs_exit called before xhci_mem_cleanup. xhci_debugfs_exit removed the xhci debugfs root nodes, xhci_mem_cleanup called function xhci_free_virt_devices_depth_first which in turn called function xhci_debugfs_remove_slot. Function xhci_debugfs_remove_slot removed the nodes for devices, the nodes folders are sub folder of xhci debugfs. It is unreasonable to remove xhci debugfs root folder before xhci debugfs sub folder. Function xhci_mem_cleanup should be called before function xhci_debugfs_exit. Fixes: 02b6fdc2a153 ("usb: xhci: Add debugfs interface for xHCI driver") Cc: <stable@vger.kernel.org> # v4.15 Signed-off-by: Zhengjun Xing <zhengjun.xing@linux.intel.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/xhci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 4adb6da..25d4b748 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -646,8 +646,6 @@ static void xhci_stop(struct usb_hcd *hcd) return; } - xhci_debugfs_exit(xhci); - xhci_dbc_exit(xhci); spin_lock_irq(&xhci->lock); @@ -680,6 +678,7 @@ static void xhci_stop(struct usb_hcd *hcd) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "cleaning up memory"); xhci_mem_cleanup(xhci); + xhci_debugfs_exit(xhci); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "xhci_stop completed - status = %x", readl(&xhci->op_regs->status)); -- cgit v1.1 From 71a0483d56e784b1e11f38f10d7e22d265dbe244 Mon Sep 17 00:00:00 2001 From: Kristian Evensen <kristian.evensen@gmail.com> Date: Thu, 1 Feb 2018 10:32:32 +0100 Subject: USB: serial: option: Add support for Quectel EP06 The Quectel EP06 is a Cat. 6 LTE modem, and the interface mapping is as follows: 0: Diag 1: NMEA 2: AT 3: Modem Interface 4 is QMI and interface 5 is ADB, so they are blacklisted. This patch should also be considered for -stable. The QMI-patch for this modem is already in the -stable-queue. v1->v2: * Updated commit prefix (thanks Johan Hovold) * Updated commit message slightly. Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com> Acked-by: Johan Hovold <johan@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/serial/option.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5db8ed5..2d8d915 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -241,6 +241,7 @@ static void option_instat_callback(struct urb *urb); #define QUECTEL_PRODUCT_EC21 0x0121 #define QUECTEL_PRODUCT_EC25 0x0125 #define QUECTEL_PRODUCT_BG96 0x0296 +#define QUECTEL_PRODUCT_EP06 0x0306 #define CMOTECH_VENDOR_ID 0x16d8 #define CMOTECH_PRODUCT_6001 0x6001 @@ -689,6 +690,10 @@ static const struct option_blacklist_info yuga_clm920_nc5_blacklist = { .reserved = BIT(1) | BIT(4), }; +static const struct option_blacklist_info quectel_ep06_blacklist = { + .reserved = BIT(4) | BIT(5), +}; + static const struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -1203,6 +1208,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06), + .driver_info = (kernel_ulong_t)&quectel_ep06_blacklist }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003), -- cgit v1.1 From b2685bdacdaab065c172b97b55ab46c6be77a037 Mon Sep 17 00:00:00 2001 From: Shigeru Yoshida <shigeru.yoshida@windriver.com> Date: Fri, 2 Feb 2018 13:51:39 +0800 Subject: ohci-hcd: Fix race condition caused by ohci_urb_enqueue() and io_watchdog_func() Running io_watchdog_func() while ohci_urb_enqueue() is running can cause a race condition where ohci->prev_frame_no is corrupted and the watchdog can mis-detect following error: ohci-platform 664a0800.usb: frame counter not updating; disabled ohci-platform 664a0800.usb: HC died; cleaning up Specifically, following scenario causes a race condition: 1. ohci_urb_enqueue() calls spin_lock_irqsave(&ohci->lock, flags) and enters the critical section 2. ohci_urb_enqueue() calls timer_pending(&ohci->io_watchdog) and it returns false 3. ohci_urb_enqueue() sets ohci->prev_frame_no to a frame number read by ohci_frame_no(ohci) 4. ohci_urb_enqueue() schedules io_watchdog_func() with mod_timer() 5. ohci_urb_enqueue() calls spin_unlock_irqrestore(&ohci->lock, flags) and exits the critical section 6. Later, ohci_urb_enqueue() is called 7. ohci_urb_enqueue() calls spin_lock_irqsave(&ohci->lock, flags) and enters the critical section 8. The timer scheduled on step 4 expires and io_watchdog_func() runs 9. io_watchdog_func() calls spin_lock_irqsave(&ohci->lock, flags) and waits on it because ohci_urb_enqueue() is already in the critical section on step 7 10. ohci_urb_enqueue() calls timer_pending(&ohci->io_watchdog) and it returns false 11. ohci_urb_enqueue() sets ohci->prev_frame_no to new frame number read by ohci_frame_no(ohci) because the frame number proceeded between step 3 and 6 12. ohci_urb_enqueue() schedules io_watchdog_func() with mod_timer() 13. ohci_urb_enqueue() calls spin_unlock_irqrestore(&ohci->lock, flags) and exits the critical section, then wake up io_watchdog_func() which is waiting on step 9 14. io_watchdog_func() enters the critical section 15. io_watchdog_func() calls ohci_frame_no(ohci) and set frame_no variable to the frame number 16. io_watchdog_func() compares frame_no and ohci->prev_frame_no On step 16, because this calling of io_watchdog_func() is scheduled on step 4, the frame number set in ohci->prev_frame_no is expected to the number set on step 3. However, ohci->prev_frame_no is overwritten on step 11. Because step 16 is executed soon after step 11, the frame number might not proceed, so ohci->prev_frame_no must equals to frame_no. To address above scenario, this patch introduces a special sentinel value IO_WATCHDOG_OFF and set this value to ohci->prev_frame_no when the watchdog is not pending or running. When ohci_urb_enqueue() schedules the watchdog (step 4 and 12 above), it compares ohci->prev_frame_no to IO_WATCHDOG_OFF so that ohci->prev_frame_no is not overwritten while io_watchdog_func() is running. Signed-off-by: Shigeru Yoshida <Shigeru.Yoshida@windriver.com> Signed-off-by: Haiqing Bai <Haiqing.Bai@windriver.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/ohci-hcd.c | 10 +++++++--- drivers/usb/host/ohci-hub.c | 4 +++- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index ee96763..84f88fa 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -74,6 +74,7 @@ static const char hcd_name [] = "ohci_hcd"; #define STATECHANGE_DELAY msecs_to_jiffies(300) #define IO_WATCHDOG_DELAY msecs_to_jiffies(275) +#define IO_WATCHDOG_OFF 0xffffff00 #include "ohci.h" #include "pci-quirks.h" @@ -231,7 +232,7 @@ static int ohci_urb_enqueue ( } /* Start up the I/O watchdog timer, if it's not running */ - if (!timer_pending(&ohci->io_watchdog) && + if (ohci->prev_frame_no == IO_WATCHDOG_OFF && list_empty(&ohci->eds_in_use) && !(ohci->flags & OHCI_QUIRK_QEMU)) { ohci->prev_frame_no = ohci_frame_no(ohci); @@ -501,6 +502,7 @@ static int ohci_init (struct ohci_hcd *ohci) return 0; timer_setup(&ohci->io_watchdog, io_watchdog_func, 0); + ohci->prev_frame_no = IO_WATCHDOG_OFF; ohci->hcca = dma_alloc_coherent (hcd->self.controller, sizeof(*ohci->hcca), &ohci->hcca_dma, GFP_KERNEL); @@ -730,7 +732,7 @@ static void io_watchdog_func(struct timer_list *t) u32 head; struct ed *ed; struct td *td, *td_start, *td_next; - unsigned frame_no; + unsigned frame_no, prev_frame_no = IO_WATCHDOG_OFF; unsigned long flags; spin_lock_irqsave(&ohci->lock, flags); @@ -835,7 +837,7 @@ static void io_watchdog_func(struct timer_list *t) } } if (!list_empty(&ohci->eds_in_use)) { - ohci->prev_frame_no = frame_no; + prev_frame_no = frame_no; ohci->prev_wdh_cnt = ohci->wdh_cnt; ohci->prev_donehead = ohci_readl(ohci, &ohci->regs->donehead); @@ -845,6 +847,7 @@ static void io_watchdog_func(struct timer_list *t) } done: + ohci->prev_frame_no = prev_frame_no; spin_unlock_irqrestore(&ohci->lock, flags); } @@ -973,6 +976,7 @@ static void ohci_stop (struct usb_hcd *hcd) if (quirk_nec(ohci)) flush_work(&ohci->nec_work); del_timer_sync(&ohci->io_watchdog); + ohci->prev_frame_no = IO_WATCHDOG_OFF; ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); ohci_usb_reset(ohci); diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index fb7aaa3..634f3c7 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -311,8 +311,10 @@ static int ohci_bus_suspend (struct usb_hcd *hcd) rc = ohci_rh_suspend (ohci, 0); spin_unlock_irq (&ohci->lock); - if (rc == 0) + if (rc == 0) { del_timer_sync(&ohci->io_watchdog); + ohci->prev_frame_no = IO_WATCHDOG_OFF; + } return rc; } -- cgit v1.1 From 009f41aed4b3e11e6dc1e3c07377a10c20f1a5ed Mon Sep 17 00:00:00 2001 From: Shuah Khan <shuahkh@osg.samsung.com> Date: Fri, 26 Jan 2018 11:56:50 -0700 Subject: usbip: keep usbip_device sockfd state in sync with tcp_socket Keep usbip_device sockfd state in sync with tcp_socket. When tcp_socket is reset to null, reset sockfd to -1 to keep it in sync. Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com> Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/usbip/stub_dev.c | 3 +++ drivers/usb/usbip/vhci_hcd.c | 2 ++ 2 files changed, 5 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c index 49e5524..dd8ef36 100644 --- a/drivers/usb/usbip/stub_dev.c +++ b/drivers/usb/usbip/stub_dev.c @@ -73,6 +73,7 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a goto err; sdev->ud.tcp_socket = socket; + sdev->ud.sockfd = sockfd; spin_unlock_irq(&sdev->ud.lock); @@ -172,6 +173,7 @@ static void stub_shutdown_connection(struct usbip_device *ud) if (ud->tcp_socket) { sockfd_put(ud->tcp_socket); ud->tcp_socket = NULL; + ud->sockfd = -1; } /* 3. free used data */ @@ -266,6 +268,7 @@ static struct stub_device *stub_device_alloc(struct usb_device *udev) sdev->ud.status = SDEV_ST_AVAILABLE; spin_lock_init(&sdev->ud.lock); sdev->ud.tcp_socket = NULL; + sdev->ud.sockfd = -1; INIT_LIST_HEAD(&sdev->priv_init); INIT_LIST_HEAD(&sdev->priv_tx); diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index c3e1008..20e3d46 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c @@ -984,6 +984,7 @@ static void vhci_shutdown_connection(struct usbip_device *ud) if (vdev->ud.tcp_socket) { sockfd_put(vdev->ud.tcp_socket); vdev->ud.tcp_socket = NULL; + vdev->ud.sockfd = -1; } pr_info("release socket\n"); @@ -1030,6 +1031,7 @@ static void vhci_device_reset(struct usbip_device *ud) if (ud->tcp_socket) { sockfd_put(ud->tcp_socket); ud->tcp_socket = NULL; + ud->sockfd = -1; } ud->status = VDEV_ST_NULL; -- cgit v1.1 From 02a10f061a3f8bca1b37332672f50a107198adbe Mon Sep 17 00:00:00 2001 From: Peter Chen <hzpeterchen@gmail.com> Date: Thu, 1 Feb 2018 12:26:43 +0800 Subject: usb: host: ehci: use correct device pointer for dma ops commit a8c06e407ef9 ("usb: separate out sysdev pointer from usb_bus") converted to use hcd->self.sysdev for DMA operations instead of hcd->self.controller, but forgot to do it for hcd test mode. Replace the correct one in this commit. Fixes: a8c06e407ef9 ("usb: separate out sysdev pointer from usb_bus") Signed-off-by: Peter Chen <peter.chen@nxp.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/ehci-hub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index facafdf..d7641cb 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -774,12 +774,12 @@ static struct urb *request_single_step_set_feature_urb( atomic_inc(&urb->use_count); atomic_inc(&urb->dev->urbnum); urb->setup_dma = dma_map_single( - hcd->self.controller, + hcd->self.sysdev, urb->setup_packet, sizeof(struct usb_ctrlrequest), DMA_TO_DEVICE); urb->transfer_dma = dma_map_single( - hcd->self.controller, + hcd->self.sysdev, urb->transfer_buffer, urb->transfer_buffer_length, DMA_FROM_DEVICE); -- cgit v1.1 From d6efa938ac366fe8cb92d6157f74d43cc35f1c67 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Date: Mon, 5 Feb 2018 17:12:35 +0900 Subject: usb: renesas_usbhs: missed the "running" flag in usb_dmac with rx path This fixes an issue that a gadget driver (usb_f_fs) is possible to stop rx transactions after the usb-dmac is used because the following functions missed to set/check the "running" flag. - usbhsf_dma_prepare_pop_with_usb_dmac() - usbhsf_dma_pop_done_with_usb_dmac() So, if next transaction uses pio, the usbhsf_prepare_pop() can not start the transaction because the "running" flag is 0. Fixes: 8355b2b3082d ("usb: renesas_usbhs: fix the behavior of some usbhs_pkt_handle") Cc: <stable@vger.kernel.org> # v3.19+ Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/renesas_usbhs/fifo.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 5925d11..39fa2fc 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -982,6 +982,10 @@ static int usbhsf_dma_prepare_pop_with_usb_dmac(struct usbhs_pkt *pkt, if ((uintptr_t)pkt->buf & (USBHS_USB_DMAC_XFER_SIZE - 1)) goto usbhsf_pio_prepare_pop; + /* return at this time if the pipe is running */ + if (usbhs_pipe_is_running(pipe)) + return 0; + usbhs_pipe_config_change_bfre(pipe, 1); ret = usbhsf_fifo_select(pipe, fifo, 0); @@ -1172,6 +1176,7 @@ static int usbhsf_dma_pop_done_with_usb_dmac(struct usbhs_pkt *pkt, usbhsf_fifo_clear(pipe, fifo); pkt->actual = usbhs_dma_calc_received_size(pkt, chan, rcv_len); + usbhs_pipe_running(pipe, 0); usbhsf_dma_stop(pipe, fifo); usbhsf_dma_unmap(pkt); usbhsf_fifo_unselect(pipe, pipe->fifo); -- cgit v1.1 From 52ad2bd8918158266fc88a05f95429b56b6a33c5 Mon Sep 17 00:00:00 2001 From: Karsten Koop <kkoop@ld-didactic.de> Date: Fri, 9 Feb 2018 09:12:06 +0000 Subject: usb: ldusb: add PIDs for new CASSY devices supported by this driver This patch adds support for new CASSY devices to the ldusb driver. The PIDs are also added to the ignore list in hid-quirks. Signed-off-by: Karsten Koop <kkoop@ld-didactic.de> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/misc/ldusb.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 63b9e85..236a60f 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -42,6 +42,9 @@ #define USB_DEVICE_ID_LD_MICROCASSYTIME 0x1033 /* USB Product ID of Micro-CASSY Time (reserved) */ #define USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE 0x1035 /* USB Product ID of Micro-CASSY Temperature */ #define USB_DEVICE_ID_LD_MICROCASSYPH 0x1038 /* USB Product ID of Micro-CASSY pH */ +#define USB_DEVICE_ID_LD_POWERANALYSERCASSY 0x1040 /* USB Product ID of Power Analyser CASSY */ +#define USB_DEVICE_ID_LD_CONVERTERCONTROLLERCASSY 0x1042 /* USB Product ID of Converter Controller CASSY */ +#define USB_DEVICE_ID_LD_MACHINETESTCASSY 0x1043 /* USB Product ID of Machine Test CASSY */ #define USB_DEVICE_ID_LD_JWM 0x1080 /* USB Product ID of Joule and Wattmeter */ #define USB_DEVICE_ID_LD_DMMP 0x1081 /* USB Product ID of Digital Multimeter P (reserved) */ #define USB_DEVICE_ID_LD_UMIP 0x1090 /* USB Product ID of UMI P */ @@ -84,6 +87,9 @@ static const struct usb_device_id ld_usb_table[] = { { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTIME) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYPH) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERANALYSERCASSY) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CONVERTERCONTROLLERCASSY) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETESTCASSY) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) }, -- cgit v1.1 From 91b119359c1c3033a6621909d3c5dbbdf201d6b4 Mon Sep 17 00:00:00 2001 From: Peter Chen <hzpeterchen@gmail.com> Date: Mon, 5 Feb 2018 11:50:56 +0800 Subject: usb: host: ehci: always enable interrupt for qtd completion at test mode At former code, the SETUP stage does not enable interrupt for qtd completion, it relies on IAA watchdog to complete interrupt, then the transcation would be considered timeout if the flag need_io_watchdog is cleared by platform code. In this commit, we always add enable interrupt for qtd completion, then the qtd completion can be notified by hardware interrupt. Signed-off-by: Peter Chen <peter.chen@nxp.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/ehci-q.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 8815832..3276304 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1188,10 +1188,10 @@ static int submit_single_step_set_feature( * 15 secs after the setup */ if (is_setup) { - /* SETUP pid */ + /* SETUP pid, and interrupt after SETUP completion */ qtd_fill(ehci, qtd, urb->setup_dma, sizeof(struct usb_ctrlrequest), - token | (2 /* "setup" */ << 8), 8); + QTD_IOC | token | (2 /* "setup" */ << 8), 8); submit_async(ehci, urb, &qtd_list, GFP_ATOMIC); return 0; /*Return now; we shall come back after 15 seconds*/ @@ -1228,12 +1228,8 @@ static int submit_single_step_set_feature( qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma); list_add_tail(&qtd->qtd_list, head); - /* dont fill any data in such packets */ - qtd_fill(ehci, qtd, 0, 0, token, 0); - - /* by default, enable interrupt on urb completion */ - if (likely(!(urb->transfer_flags & URB_NO_INTERRUPT))) - qtd->hw_token |= cpu_to_hc32(ehci, QTD_IOC); + /* Interrupt after STATUS completion */ + qtd_fill(ehci, qtd, 0, 0, token | QTD_IOC, 0); submit_async(ehci, urb, &qtd_list, GFP_KERNEL); -- cgit v1.1 From 46408ea558df13b110e0866b99624384a33bdeba Mon Sep 17 00:00:00 2001 From: AMAN DEEP <aman.deep@samsung.com> Date: Thu, 8 Feb 2018 11:55:01 +0800 Subject: usb: ohci: Proper handling of ed_rm_list to handle race condition between usb_kill_urb() and finish_unlinks() There is a race condition between finish_unlinks->finish_urb() function and usb_kill_urb() in ohci controller case. The finish_urb calls spin_unlock(&ohci->lock) before usb_hcd_giveback_urb() function call, then if during this time, usb_kill_urb is called for another endpoint, then new ed will be added to ed_rm_list at beginning for unlink, and ed_rm_list will point to newly added. When finish_urb() is completed in finish_unlinks() and ed->td_list becomes empty as in below code (in finish_unlinks() function): if (list_empty(&ed->td_list)) { *last = ed->ed_next; ed->ed_next = NULL; } else if (ohci->rh_state == OHCI_RH_RUNNING) { *last = ed->ed_next; ed->ed_next = NULL; ed_schedule(ohci, ed); } The *last = ed->ed_next will make ed_rm_list to point to ed->ed_next and previously added ed by usb_kill_urb will be left unreferenced by ed_rm_list. This causes usb_kill_urb() hang forever waiting for finish_unlink to remove added ed from ed_rm_list. The main reason for hang in this race condtion is addition and removal of ed from ed_rm_list in the beginning during usb_kill_urb and later last* is modified in finish_unlinks(). As suggested by Alan Stern, the solution for proper handling of ohci->ed_rm_list is to remove ed from the ed_rm_list before finishing any URBs. Then at the end, we can add ed back to the list if necessary. This properly handle the updated ohci->ed_rm_list in usb_kill_urb(). Fixes: 977dcfdc6031 ("USB: OHCI: don't lose track of EDs when a controller dies") Acked-by: Alan Stern <stern@rowland.harvard.edu> CC: <stable@vger.kernel.org> Signed-off-by: Aman Deep <aman.deep@samsung.com> Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/ohci-q.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index b2ec8c3..4ccb85a 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -1019,6 +1019,8 @@ skip_ed: * have modified this list. normally it's just prepending * entries (which we'd ignore), but paranoia won't hurt. */ + *last = ed->ed_next; + ed->ed_next = NULL; modified = 0; /* unlink urbs as requested, but rescan the list after @@ -1077,21 +1079,22 @@ rescan_this: goto rescan_this; /* - * If no TDs are queued, take ED off the ed_rm_list. + * If no TDs are queued, ED is now idle. * Otherwise, if the HC is running, reschedule. - * If not, leave it on the list for further dequeues. + * If the HC isn't running, add ED back to the + * start of the list for later processing. */ if (list_empty(&ed->td_list)) { - *last = ed->ed_next; - ed->ed_next = NULL; ed->state = ED_IDLE; list_del(&ed->in_use_list); } else if (ohci->rh_state == OHCI_RH_RUNNING) { - *last = ed->ed_next; - ed->ed_next = NULL; ed_schedule(ohci, ed); } else { - last = &ed->ed_next; + ed->ed_next = ohci->ed_rm_list; + ohci->ed_rm_list = ed; + /* Don't loop on the same ED */ + if (last == &ohci->ed_rm_list) + last = &ed->ed_next; } if (modified) -- cgit v1.1 From 7a1646d922577b5b48c0d222e03831141664bb59 Mon Sep 17 00:00:00 2001 From: Jack Stocker <jackstocker.93@gmail.com> Date: Thu, 15 Feb 2018 18:24:10 +0000 Subject: Add delay-init quirk for Corsair K70 RGB keyboards Following on from this patch: https://lkml.org/lkml/2017/11/3/516, Corsair K70 RGB keyboards also require the DELAY_INIT quirk to start correctly at boot. Device ids found here: usb 3-3: New USB device found, idVendor=1b1c, idProduct=1b13 usb 3-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3 usb 3-3: Product: Corsair K70 RGB Gaming Keyboard Signed-off-by: Jack Stocker <jackstocker.93@gmail.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/core/quirks.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 4024926..f4a5484 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -226,6 +226,9 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x1a0a, 0x0200), .driver_info = USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL }, + /* Corsair K70 RGB */ + { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT }, + /* Corsair Strafe RGB */ { USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT }, -- cgit v1.1 From b86b8eb6fecb5a4bac1ed0ca925c4082a61ea6e9 Mon Sep 17 00:00:00 2001 From: Dominik Bozek <dominikx.bozek@intel.com> Date: Thu, 15 Feb 2018 21:27:48 -0800 Subject: usb: cdc_acm: prevent race at write to acm while system resumes ACM driver may accept data to transmit while system is not fully resumed. In this case ACM driver buffers data and prepare URBs on usb anchor list. There is a little chance that two tasks put a char and initiate acm_tty_flush_chars(). In such a case, driver will put one URB twice on usb anchor list. This patch also reset length of data before resue of a buffer. This not only prevent sending rubbish, but also lower risc of race. Without this patch we hit following kernel panic in one of our stabilty/stress tests. [ 46.884442] *list_add double add*: new=ffff9b2ab7289330, prev=ffff9b2ab7289330, next=ffff9b2ab81e28e0. [ 46.884476] Modules linked in: hci_uart btbcm bluetooth rfkill_gpio igb_avb(O) cfg80211 snd_soc_sst_bxt_tdf8532 snd_soc_skl snd_soc_skl_ipc snd_soc_sst_ipc snd_soc_sst_dsp snd_soc_sst_acpi snd_soc_sst_match snd_hda_ext_core snd_hda_core trusty_timer trusty_wall trusty_log trusty_virtio trusty_ipc trusty_mem trusty_irq trusty virtio_ring virtio intel_ipu4_mmu_bxtB0 lib2600_mod_bxtB0 intel_ipu4_isys_mod_bxtB0 lib2600psys_mod_bxtB0 intel_ipu4_psys_mod_bxtB0 intel_ipu4_mod_bxtB0 intel_ipu4_wrapper_bxtB0 intel_ipu4_acpi videobuf2_dma_contig as3638 dw9714 lm3643 crlmodule smiapp smiapp_pll [ 46.884480] CPU: 1 PID: 33 Comm: kworker/u8:1 Tainted: G U W O 4.9.56-quilt-2e5dc0ac-g618ed69ced6e-dirty #4 [ 46.884489] Workqueue: events_unbound flush_to_ldisc [ 46.884494] ffffb98ac012bb08 ffffffffad3e82e5 ffffb98ac012bb58 0000000000000000 [ 46.884497] ffffb98ac012bb48 ffffffffad0a23d1 00000024ad6374dd ffff9b2ab7289330 [ 46.884500] ffff9b2ab81e28e0 ffff9b2ab7289330 0000000000000002 0000000000000000 [ 46.884501] Call Trace: [ 46.884507] [<ffffffffad3e82e5>] dump_stack+0x67/0x92 [ 46.884511] [<ffffffffad0a23d1>] __warn+0xd1/0xf0 [ 46.884513] [<ffffffffad0a244f>] warn_slowpath_fmt+0x5f/0x80 [ 46.884516] [<ffffffffad407443>] __list_add+0xb3/0xc0 [ 46.884521] [<ffffffffad71133c>] *usb_anchor_urb*+0x4c/0xa0 [ 46.884524] [<ffffffffad782c6f>] *acm_tty_flush_chars*+0x8f/0xb0 [ 46.884527] [<ffffffffad782cd1>] *acm_tty_put_char*+0x41/0x100 [ 46.884530] [<ffffffffad4ced34>] tty_put_char+0x24/0x40 [ 46.884533] [<ffffffffad4d3bf5>] do_output_char+0xa5/0x200 [ 46.884535] [<ffffffffad4d3e98>] __process_echoes+0x148/0x290 [ 46.884538] [<ffffffffad4d654c>] n_tty_receive_buf_common+0x57c/0xb00 [ 46.884541] [<ffffffffad4d6ae4>] n_tty_receive_buf2+0x14/0x20 [ 46.884543] [<ffffffffad4d9662>] tty_ldisc_receive_buf+0x22/0x50 [ 46.884545] [<ffffffffad4d9c05>] flush_to_ldisc+0xc5/0xe0 [ 46.884549] [<ffffffffad0bcfe8>] process_one_work+0x148/0x440 [ 46.884551] [<ffffffffad0bdc19>] worker_thread+0x69/0x4a0 [ 46.884554] [<ffffffffad0bdbb0>] ? max_active_store+0x80/0x80 [ 46.884556] [<ffffffffad0c2e10>] kthread+0x110/0x130 [ 46.884559] [<ffffffffad0c2d00>] ? kthread_park+0x60/0x60 [ 46.884563] [<ffffffffadad9917>] ret_from_fork+0x27/0x40 [ 46.884566] ---[ end trace 3bd599058b8a9eb3 ]--- Signed-off-by: Dominik Bozek <dominikx.bozek@intel.com> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Acked-by: Oliver Neukum <oneukum@suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/class/cdc-acm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 06b3b54..7b366a6 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -174,6 +174,7 @@ static int acm_wb_alloc(struct acm *acm) wb = &acm->wb[wbn]; if (!wb->use) { wb->use = 1; + wb->len = 0; return wbn; } wbn = (wbn + 1) % ACM_NW; @@ -805,16 +806,18 @@ static int acm_tty_write(struct tty_struct *tty, static void acm_tty_flush_chars(struct tty_struct *tty) { struct acm *acm = tty->driver_data; - struct acm_wb *cur = acm->putbuffer; + struct acm_wb *cur; int err; unsigned long flags; + spin_lock_irqsave(&acm->write_lock, flags); + + cur = acm->putbuffer; if (!cur) /* nothing to do */ - return; + goto out; acm->putbuffer = NULL; err = usb_autopm_get_interface_async(acm->control); - spin_lock_irqsave(&acm->write_lock, flags); if (err < 0) { cur->use = 0; acm->putbuffer = cur; -- cgit v1.1 From 17539f2f4f0b7fa906b508765c8ada07a1e45f52 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade <andreas@kemnade.info> Date: Tue, 20 Feb 2018 07:30:10 -0600 Subject: usb: musb: fix enumeration after resume On dm3730 there are enumeration problems after resume. Investigation led to the cause that the MUSB_POWER_SOFTCONN bit is not set. If it was set before suspend (because it was enabled via musb_pullup()), it is set in musb_restore_context() so the pullup is enabled. But then musb_start() is called which overwrites MUSB_POWER and therefore disables MUSB_POWER_SOFTCONN, so no pullup is enabled and the device is not enumerated. So let's do a subset of what musb_start() does in the same way as musb_suspend() does it. Platform-specific stuff it still called as there might be some phy-related stuff which needs to be enabled. Also interrupts are enabled, as it was the original idea of calling musb_start() in musb_resume() according to Commit 6fc6f4b87cb3 ("usb: musb: Disable interrupts on suspend, enable them on resume") Signed-off-by: Andreas Kemnade <andreas@kemnade.info> Tested-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Bin Liu <b-liu@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/musb/musb_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 968bf1e..eef4ad5 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2708,7 +2708,8 @@ static int musb_resume(struct device *dev) if ((devctl & mask) != (musb->context.devctl & mask)) musb->port1_status = 0; - musb_start(musb); + musb_enable_interrupts(musb); + musb_platform_enable(musb); spin_lock_irqsave(&musb->lock, flags); error = musb_run_resume_work(musb); -- cgit v1.1 From 44eb5e12b845cc8a0634f21b70ef07d774eb4b25 Mon Sep 17 00:00:00 2001 From: Bin Liu <b-liu@ti.com> Date: Tue, 20 Feb 2018 07:31:35 -0600 Subject: Revert "usb: musb: host: don't start next rx urb if current one failed" This reverts commit dbac5d07d13e330e6706813c9fde477140fb5d80. commit dbac5d07d13e ("usb: musb: host: don't start next rx urb if current one failed") along with commit b5801212229f ("usb: musb: host: clear rxcsr error bit if set") try to solve the issue described in [1], but the latter alone is sufficient, and the former causes the issue as in [2], so now revert it. [1] https://marc.info/?l=linux-usb&m=146173995117456&w=2 [2] https://marc.info/?l=linux-usb&m=151689238420622&w=2 Cc: stable@vger.kernel.org # v4.7+ Signed-off-by: Bin Liu <b-liu@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/musb/musb_host.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 394b4ac..45ed32c 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -391,13 +391,7 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb, } } - /* - * The pipe must be broken if current urb->status is set, so don't - * start next urb. - * TODO: to minimize the risk of regression, only check urb->status - * for RX, until we have a test case to understand the behavior of TX. - */ - if ((!status || !is_in) && qh && qh->is_ready) { + if (qh != NULL && qh->is_ready) { musb_dbg(musb, "... next ep%d %cX urb %p", hw_ep->epnum, is_in ? 'R' : 'T', next_urb(qh)); musb_start_urb(musb, is_in, qh); -- cgit v1.1 From 084a804e01205bcd74cd0849bc72cb5c88f8e648 Mon Sep 17 00:00:00 2001 From: Roger Quadros <rogerq@ti.com> Date: Tue, 27 Feb 2018 12:41:41 +0200 Subject: usb: dwc3: Fix lock-up on ID change during system suspend/resume To reproduce the lock up do the following - connect otg host adapter and a USB device to the dual-role port so that it is in host mode. - suspend to mem. - disconnect otg adapter. - resume the system. If we call dwc3_host_exit() before tasks are thawed xhci_plat_remove() seems to lock up at the second usb_remove_hcd() call. To work around this we queue the _dwc3_set_mode() work on the system_freezable_wq. Fixes: 41ce1456e1db ("usb: dwc3: core: make dwc3_set_mode() work properly") Cc: <stable@vger.kernel.org> # v4.12+ Suggested-by: Manu Gautam <mgautam@codeaurora.org> Signed-off-by: Roger Quadros <rogerq@ti.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/dwc3/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index f1d838a..e94bf91 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -175,7 +175,7 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode) dwc->desired_dr_role = mode; spin_unlock_irqrestore(&dwc->lock, flags); - queue_work(system_power_efficient_wq, &dwc->drd_work); + queue_work(system_freezable_wq, &dwc->drd_work); } u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) -- cgit v1.1 From 1a087f032111a88e826877449dfb93ceb22b78b9 Mon Sep 17 00:00:00 2001 From: Xinyong <xinyong.fang@linux.alibaba.com> Date: Fri, 2 Mar 2018 19:20:07 +0800 Subject: usb: gadget: f_fs: Fix use-after-free in ffs_fs_kill_sb() When I debug a kernel crash issue in funcitonfs, found ffs_data.ref overflowed, While functionfs is unmounting, ffs_data is put twice. Commit 43938613c6fd ("drivers, usb: convert ffs_data.ref from atomic_t to refcount_t") can avoid refcount overflow, but that is risk some situations. So no need put ffs data in ffs_fs_kill_sb, already put in ffs_data_closed. The issue can be reproduced in Mediatek mt6763 SoC, ffs for ADB device. KASAN enabled configuration reports use-after-free errro. BUG: KASAN: use-after-free in refcount_dec_and_test+0x14/0xe0 at addr ffffffc0579386a0 Read of size 4 by task umount/4650 ==================================================== BUG kmalloc-512 (Tainted: P W O ): kasan: bad access detected ----------------------------------------------------------------------------- INFO: Allocated in ffs_fs_mount+0x194/0x844 age=22856 cpu=2 pid=566 alloc_debug_processing+0x1ac/0x1e8 ___slab_alloc.constprop.63+0x640/0x648 __slab_alloc.isra.57.constprop.62+0x24/0x34 kmem_cache_alloc_trace+0x1a8/0x2bc ffs_fs_mount+0x194/0x844 mount_fs+0x6c/0x1d0 vfs_kern_mount+0x50/0x1b4 do_mount+0x258/0x1034 INFO: Freed in ffs_data_put+0x25c/0x320 age=0 cpu=3 pid=4650 free_debug_processing+0x22c/0x434 __slab_free+0x2d8/0x3a0 kfree+0x254/0x264 ffs_data_put+0x25c/0x320 ffs_data_closed+0x124/0x15c ffs_fs_kill_sb+0xb8/0x110 deactivate_locked_super+0x6c/0x98 deactivate_super+0xb0/0xbc INFO: Object 0xffffffc057938600 @offset=1536 fp=0x (null) ...... Call trace: [<ffffff900808cf5c>] dump_backtrace+0x0/0x250 [<ffffff900808d3a0>] show_stack+0x14/0x1c [<ffffff90084a8c04>] dump_stack+0xa0/0xc8 [<ffffff900826c2b4>] print_trailer+0x158/0x260 [<ffffff900826d9d8>] object_err+0x3c/0x40 [<ffffff90082745f0>] kasan_report_error+0x2a8/0x754 [<ffffff9008274f84>] kasan_report+0x5c/0x60 [<ffffff9008273208>] __asan_load4+0x70/0x88 [<ffffff90084cd81c>] refcount_dec_and_test+0x14/0xe0 [<ffffff9008d98f9c>] ffs_data_put+0x80/0x320 [<ffffff9008d9d904>] ffs_fs_kill_sb+0xc8/0x110 [<ffffff90082852a0>] deactivate_locked_super+0x6c/0x98 [<ffffff900828537c>] deactivate_super+0xb0/0xbc [<ffffff90082af0c0>] cleanup_mnt+0x64/0xec [<ffffff90082af1b0>] __cleanup_mnt+0x10/0x18 [<ffffff90080d9e68>] task_work_run+0xcc/0x124 [<ffffff900808c8c0>] do_notify_resume+0x60/0x70 [<ffffff90080866e4>] work_pending+0x10/0x14 Cc: stable@vger.kernel.org Signed-off-by: Xinyong <xinyong.fang@linux.alibaba.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/gadget/function/f_fs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index c2592d8..d2428a9 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1538,7 +1538,6 @@ ffs_fs_kill_sb(struct super_block *sb) if (sb->s_fs_info) { ffs_release_dev(sb->s_fs_info); ffs_data_closed(sb->s_fs_info); - ffs_data_put(sb->s_fs_info); } } -- cgit v1.1 From 1a149e3554e0324a3d551dfb327bdb67b150a320 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay <amelie.delaunay@st.com> Date: Thu, 1 Mar 2018 11:05:35 +0100 Subject: usb: dwc2: fix STM32F7 USB OTG HS compatible This patch fixes compatible for STM32F7 USB OTG HS and consistently rename dw2_set_params function. The v2 former patch [1] had been acked by Paul Young, but v1 was merged. [1] https://patchwork.kernel.org/patch/9925573/ Fixes: d8fae8b93682 ("usb: dwc2: add support for STM32F7xx USB OTG HS") Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/dwc2/params.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 03fd20f..c4a4749 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -137,7 +137,7 @@ static void dwc2_set_stm32f4x9_fsotg_params(struct dwc2_hsotg *hsotg) p->activate_stm_fs_transceiver = true; } -static void dwc2_set_stm32f7xx_hsotg_params(struct dwc2_hsotg *hsotg) +static void dwc2_set_stm32f7_hsotg_params(struct dwc2_hsotg *hsotg) { struct dwc2_core_params *p = &hsotg->params; @@ -164,8 +164,8 @@ const struct of_device_id dwc2_of_match_table[] = { { .compatible = "st,stm32f4x9-fsotg", .data = dwc2_set_stm32f4x9_fsotg_params }, { .compatible = "st,stm32f4x9-hsotg" }, - { .compatible = "st,stm32f7xx-hsotg", - .data = dwc2_set_stm32f7xx_hsotg_params }, + { .compatible = "st,stm32f7-hsotg", + .data = dwc2_set_stm32f7_hsotg_params }, {}, }; MODULE_DEVICE_TABLE(of, dwc2_of_match_table); -- cgit v1.1 From 9a513c905bb95bef79d96feb08621c1ec8d8c4bb Mon Sep 17 00:00:00 2001 From: Oliver Neukum <oneukum@suse.com> Date: Tue, 6 Mar 2018 15:04:24 +0100 Subject: uas: fix comparison for error code A typo broke the comparison. Fixes: cbeef22fd611 ("usb: uas: unconditionally bring back host after reset") Signed-off-by: Oliver Neukum <oneukum@suse.com> CC: stable@kernel.org Acked-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/storage/uas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 3b1b969..6034c39 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -1076,7 +1076,7 @@ static int uas_post_reset(struct usb_interface *intf) return 0; err = uas_configure_endpoints(devinfo); - if (err && err != ENODEV) + if (err && err != -ENODEV) shost_printk(KERN_ERR, shost, "%s: alloc streams error %d after reset", __func__, err); -- cgit v1.1 From cb88a0588717ba6c756cb5972d75766b273a6817 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <danilokrummrich@dk-develop.de> Date: Tue, 6 Mar 2018 09:38:49 +0100 Subject: usb: quirks: add control message delay for 1b1c:1b20 Corsair Strafe RGB keyboard does not respond to usb control messages sometimes and hence generates timeouts. Commit de3af5bf259d ("usb: quirks: add delay init quirk for Corsair Strafe RGB keyboard") tried to fix those timeouts by adding USB_QUIRK_DELAY_INIT. Unfortunately, even with this quirk timeouts of usb_control_msg() can still be seen, but with a lower frequency (approx. 1 out of 15): [ 29.103520] usb 1-8: string descriptor 0 read error: -110 [ 34.363097] usb 1-8: can't set config #1, error -110 Adding further delays to different locations where usb control messages are issued just moves the timeouts to other locations, e.g.: [ 35.400533] usbhid 1-8:1.0: can't add hid device: -110 [ 35.401014] usbhid: probe of 1-8:1.0 failed with error -110 The only way to reliably avoid those issues is having a pause after each usb control message. In approx. 200 boot cycles no more timeouts were seen. Addionaly, keep USB_QUIRK_DELAY_INIT as it turned out to be necessary to have the delay in hub_port_connect() after hub_port_init(). The overall boot time seems not to be influenced by these additional delays, even on fast machines and lightweight distributions. Fixes: de3af5bf259d ("usb: quirks: add delay init quirk for Corsair Strafe RGB keyboard") Cc: stable@vger.kernel.org Signed-off-by: Danilo Krummrich <danilokrummrich@dk-develop.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/core/message.c | 4 ++++ drivers/usb/core/quirks.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index c64cf6c..0c11d40 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -151,6 +151,10 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout); + /* Linger a bit, prior to the next control message. */ + if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG) + msleep(200); + kfree(dr); return ret; diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index f4a5484..54b019e 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -230,7 +230,8 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT }, /* Corsair Strafe RGB */ - { USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT }, + { USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT | + USB_QUIRK_DELAY_CTRL_MSG }, /* Corsair K70 LUX */ { USB_DEVICE(0x1b1c, 0x1b36), .driver_info = USB_QUIRK_DELAY_INIT }, -- cgit v1.1 From df6b074dbe248d8c43a82131e8fd429e401841a5 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer <merlijn@wizzup.org> Date: Mon, 5 Mar 2018 11:35:10 -0600 Subject: usb: musb: call pm_runtime_{get,put}_sync before reading vbus registers Without pm_runtime_{get,put}_sync calls in place, reading vbus status via /sys causes the following error: Unhandled fault: external abort on non-linefetch (0x1028) at 0xfa0ab060 pgd = b333e822 [fa0ab060] *pgd=48011452(bad) [<c05261b0>] (musb_default_readb) from [<c0525bd0>] (musb_vbus_show+0x58/0xe4) [<c0525bd0>] (musb_vbus_show) from [<c04c0148>] (dev_attr_show+0x20/0x44) [<c04c0148>] (dev_attr_show) from [<c0259f74>] (sysfs_kf_seq_show+0x80/0xdc) [<c0259f74>] (sysfs_kf_seq_show) from [<c0210bac>] (seq_read+0x250/0x448) [<c0210bac>] (seq_read) from [<c01edb40>] (__vfs_read+0x1c/0x118) [<c01edb40>] (__vfs_read) from [<c01edccc>] (vfs_read+0x90/0x144) [<c01edccc>] (vfs_read) from [<c01ee1d0>] (SyS_read+0x3c/0x74) [<c01ee1d0>] (SyS_read) from [<c0106fe0>] (ret_fast_syscall+0x0/0x54) Solution was suggested by Tony Lindgren <tony@atomide.com>. Signed-off-by: Merlijn Wajer <merlijn@wizzup.org> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Bin Liu <b-liu@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/musb/musb_core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index eef4ad5..c344ef4 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1756,6 +1756,7 @@ vbus_show(struct device *dev, struct device_attribute *attr, char *buf) int vbus; u8 devctl; + pm_runtime_get_sync(dev); spin_lock_irqsave(&musb->lock, flags); val = musb->a_wait_bcon; vbus = musb_platform_get_vbus_status(musb); @@ -1769,6 +1770,7 @@ vbus_show(struct device *dev, struct device_attribute *attr, char *buf) vbus = 0; } spin_unlock_irqrestore(&musb->lock, flags); + pm_runtime_put_sync(dev); return sprintf(buf, "Vbus %s, timeout %lu msec\n", vbus ? "on" : "off", val); -- cgit v1.1 From 6f566af3462897fc743e3af6ea8cc790a13148ba Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Tue, 6 Mar 2018 10:50:05 +0100 Subject: Revert "typec: tcpm: Only request matching pdos" Commit 57e6f0d7b804 ("typec: tcpm: Only request matching pdos") is causing a regression, before this commit e.g. the GPD win and GPD pocket devices were charging at 9V 3A with a PD charger, now they are instead slowly discharging at 5V 0.4A, as this commit causes the ports max_snk_mv/ma/mw settings to be completely ignored. Arguably the way to fix this would be to add a PDO_VAR() describing the voltage range to the snk_caps of boards which can handle any voltage in their range, but the "typec: tcpm: Only request matching pdos" commit looks at the type of PDO advertised by the source/charger and if that is fixed (as it typically is) only compairs against PDO_FIXED entries in the snk_caps so supporting a range of voltage would require adding a PDO_FIXED entry for *every possible* voltage to snk_caps. AFAICT there is no reason why a fixed source_cap cannot be matched against a variable snk_cap, so at a minimum the commit should be rewritten to support that. For now lets revert the "typec: tcpm: Only request matching pdos" commit, fixing the regression. Fixes: 57e6f0d7b804 ("typec: tcpm: Only request matching pdos") Cc: Badhri Jagan Sridharan <badhri@google.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Acked-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/typec/tcpm.c | 163 ++++++++++++----------------------------------- 1 file changed, 42 insertions(+), 121 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index f4d563e..8b637a4 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -252,9 +252,6 @@ struct tcpm_port { unsigned int nr_src_pdo; u32 snk_pdo[PDO_MAX_OBJECTS]; unsigned int nr_snk_pdo; - unsigned int nr_fixed; /* number of fixed sink PDOs */ - unsigned int nr_var; /* number of variable sink PDOs */ - unsigned int nr_batt; /* number of battery sink PDOs */ u32 snk_vdo[VDO_MAX_OBJECTS]; unsigned int nr_snk_vdo; @@ -1770,90 +1767,39 @@ static int tcpm_pd_check_request(struct tcpm_port *port) return 0; } -#define min_power(x, y) min(pdo_max_power(x), pdo_max_power(y)) -#define min_current(x, y) min(pdo_max_current(x), pdo_max_current(y)) - -static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo, - int *src_pdo) +static int tcpm_pd_select_pdo(struct tcpm_port *port) { - unsigned int i, j, max_mw = 0, max_mv = 0, mw = 0, mv = 0, ma = 0; + unsigned int i, max_mw = 0, max_mv = 0; int ret = -EINVAL; /* - * Select the source PDO providing the most power which has a - * matchig sink cap. + * Select the source PDO providing the most power while staying within + * the board's voltage limits. Prefer PDO providing exp */ for (i = 0; i < port->nr_source_caps; i++) { u32 pdo = port->source_caps[i]; enum pd_pdo_type type = pdo_type(pdo); + unsigned int mv, ma, mw; - if (type == PDO_TYPE_FIXED) { - for (j = 0; j < port->nr_fixed; j++) { - if (pdo_fixed_voltage(pdo) == - pdo_fixed_voltage(port->snk_pdo[j])) { - ma = min_current(pdo, port->snk_pdo[j]); - mv = pdo_fixed_voltage(pdo); - mw = ma * mv / 1000; - if (mw > max_mw || - (mw == max_mw && mv > max_mv)) { - ret = 0; - *src_pdo = i; - *sink_pdo = j; - max_mw = mw; - max_mv = mv; - } - /* There could only be one fixed pdo - * at a specific voltage level. - * So breaking here. - */ - break; - } - } - } else if (type == PDO_TYPE_BATT) { - for (j = port->nr_fixed; - j < port->nr_fixed + - port->nr_batt; - j++) { - if (pdo_min_voltage(pdo) >= - pdo_min_voltage(port->snk_pdo[j]) && - pdo_max_voltage(pdo) <= - pdo_max_voltage(port->snk_pdo[j])) { - mw = min_power(pdo, port->snk_pdo[j]); - mv = pdo_min_voltage(pdo); - if (mw > max_mw || - (mw == max_mw && mv > max_mv)) { - ret = 0; - *src_pdo = i; - *sink_pdo = j; - max_mw = mw; - max_mv = mv; - } - } - } - } else if (type == PDO_TYPE_VAR) { - for (j = port->nr_fixed + - port->nr_batt; - j < port->nr_fixed + - port->nr_batt + - port->nr_var; - j++) { - if (pdo_min_voltage(pdo) >= - pdo_min_voltage(port->snk_pdo[j]) && - pdo_max_voltage(pdo) <= - pdo_max_voltage(port->snk_pdo[j])) { - ma = min_current(pdo, port->snk_pdo[j]); - mv = pdo_min_voltage(pdo); - mw = ma * mv / 1000; - if (mw > max_mw || - (mw == max_mw && mv > max_mv)) { - ret = 0; - *src_pdo = i; - *sink_pdo = j; - max_mw = mw; - max_mv = mv; - } - } - } + if (type == PDO_TYPE_FIXED) + mv = pdo_fixed_voltage(pdo); + else + mv = pdo_min_voltage(pdo); + + if (type == PDO_TYPE_BATT) { + mw = pdo_max_power(pdo); + } else { + ma = min(pdo_max_current(pdo), + port->max_snk_ma); + mw = ma * mv / 1000; + } + + /* Perfer higher voltages if available */ + if ((mw > max_mw || (mw == max_mw && mv > max_mv)) && + mv <= port->max_snk_mv) { + ret = i; + max_mw = mw; + max_mv = mv; } } @@ -1865,14 +1811,13 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo) unsigned int mv, ma, mw, flags; unsigned int max_ma, max_mw; enum pd_pdo_type type; - int src_pdo_index, snk_pdo_index; - u32 pdo, matching_snk_pdo; + int index; + u32 pdo; - if (tcpm_pd_select_pdo(port, &snk_pdo_index, &src_pdo_index) < 0) + index = tcpm_pd_select_pdo(port); + if (index < 0) return -EINVAL; - - pdo = port->source_caps[src_pdo_index]; - matching_snk_pdo = port->snk_pdo[snk_pdo_index]; + pdo = port->source_caps[index]; type = pdo_type(pdo); if (type == PDO_TYPE_FIXED) @@ -1880,28 +1825,26 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo) else mv = pdo_min_voltage(pdo); - /* Select maximum available current within the sink pdo's limit */ + /* Select maximum available current within the board's power limit */ if (type == PDO_TYPE_BATT) { - mw = min_power(pdo, matching_snk_pdo); - ma = 1000 * mw / mv; + mw = pdo_max_power(pdo); + ma = 1000 * min(mw, port->max_snk_mw) / mv; } else { - ma = min_current(pdo, matching_snk_pdo); - mw = ma * mv / 1000; + ma = min(pdo_max_current(pdo), + 1000 * port->max_snk_mw / mv); } + ma = min(ma, port->max_snk_ma); flags = RDO_USB_COMM | RDO_NO_SUSPEND; /* Set mismatch bit if offered power is less than operating power */ + mw = ma * mv / 1000; max_ma = ma; max_mw = mw; if (mw < port->operating_snk_mw) { flags |= RDO_CAP_MISMATCH; - if (type == PDO_TYPE_BATT && - (pdo_max_power(matching_snk_pdo) > pdo_max_power(pdo))) - max_mw = pdo_max_power(matching_snk_pdo); - else if (pdo_max_current(matching_snk_pdo) > - pdo_max_current(pdo)) - max_ma = pdo_max_current(matching_snk_pdo); + max_mw = port->operating_snk_mw; + max_ma = max_mw * 1000 / mv; } tcpm_log(port, "cc=%d cc1=%d cc2=%d vbus=%d vconn=%s polarity=%d", @@ -1910,16 +1853,16 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo) port->polarity); if (type == PDO_TYPE_BATT) { - *rdo = RDO_BATT(src_pdo_index + 1, mw, max_mw, flags); + *rdo = RDO_BATT(index + 1, mw, max_mw, flags); tcpm_log(port, "Requesting PDO %d: %u mV, %u mW%s", - src_pdo_index, mv, mw, + index, mv, mw, flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); } else { - *rdo = RDO_FIXED(src_pdo_index + 1, ma, max_ma, flags); + *rdo = RDO_FIXED(index + 1, ma, max_ma, flags); tcpm_log(port, "Requesting PDO %d: %u mV, %u mA%s", - src_pdo_index, mv, ma, + index, mv, ma, flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); } @@ -3650,19 +3593,6 @@ int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, } EXPORT_SYMBOL_GPL(tcpm_update_sink_capabilities); -static int nr_type_pdos(const u32 *pdo, unsigned int nr_pdo, - enum pd_pdo_type type) -{ - int count = 0; - int i; - - for (i = 0; i < nr_pdo; i++) { - if (pdo_type(pdo[i]) == type) - count++; - } - return count; -} - struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) { struct tcpm_port *port; @@ -3708,15 +3638,6 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) tcpc->config->nr_src_pdo); port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, tcpc->config->snk_pdo, tcpc->config->nr_snk_pdo); - port->nr_fixed = nr_type_pdos(port->snk_pdo, - port->nr_snk_pdo, - PDO_TYPE_FIXED); - port->nr_var = nr_type_pdos(port->snk_pdo, - port->nr_snk_pdo, - PDO_TYPE_VAR); - port->nr_batt = nr_type_pdos(port->snk_pdo, - port->nr_snk_pdo, - PDO_TYPE_BATT); port->nr_snk_vdo = tcpm_copy_vdos(port->snk_vdo, tcpc->config->snk_vdo, tcpc->config->nr_snk_vdo); -- cgit v1.1 From 97ef0faf575e03b352553f92c9430cb4c0431436 Mon Sep 17 00:00:00 2001 From: Mathias Nyman <mathias.nyman@linux.intel.com> Date: Thu, 8 Mar 2018 17:17:14 +0200 Subject: xhci: fix endpoint context tracer output Fix incorrent values showed for max Primary stream and Linear stream array (LSA) values in the endpoint context decoder. Fixes: 19a7d0d65c4a ("usb: host: xhci: add Slot and EP Context tracers") Cc: <stable@vger.kernel.org> # v4.12+ Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/xhci.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index e4d7d3d..d20e57b 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -718,11 +718,12 @@ struct xhci_ep_ctx { /* bits 10:14 are Max Primary Streams */ /* bit 15 is Linear Stream Array */ /* Interval - period between requests to an endpoint - 125u increments. */ -#define EP_INTERVAL(p) (((p) & 0xff) << 16) -#define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff)) -#define CTX_TO_EP_INTERVAL(p) (((p) >> 16) & 0xff) -#define EP_MAXPSTREAMS_MASK (0x1f << 10) -#define EP_MAXPSTREAMS(p) (((p) << 10) & EP_MAXPSTREAMS_MASK) +#define EP_INTERVAL(p) (((p) & 0xff) << 16) +#define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff)) +#define CTX_TO_EP_INTERVAL(p) (((p) >> 16) & 0xff) +#define EP_MAXPSTREAMS_MASK (0x1f << 10) +#define EP_MAXPSTREAMS(p) (((p) << 10) & EP_MAXPSTREAMS_MASK) +#define CTX_TO_EP_MAXPSTREAMS(p) (((p) & EP_MAXPSTREAMS_MASK) >> 10) /* Endpoint is set up with a Linear Stream Array (vs. Secondary Stream Array) */ #define EP_HAS_LSA (1 << 15) /* hosts with LEC=1 use bits 31:24 as ESIT high bits. */ @@ -2549,21 +2550,22 @@ static inline const char *xhci_decode_ep_context(u32 info, u32 info2, u64 deq, u8 burst; u8 cerr; u8 mult; - u8 lsa; - u8 hid; + + bool lsa; + bool hid; esit = CTX_TO_MAX_ESIT_PAYLOAD_HI(info) << 16 | CTX_TO_MAX_ESIT_PAYLOAD(tx_info); ep_state = info & EP_STATE_MASK; - max_pstr = info & EP_MAXPSTREAMS_MASK; + max_pstr = CTX_TO_EP_MAXPSTREAMS(info); interval = CTX_TO_EP_INTERVAL(info); mult = CTX_TO_EP_MULT(info) + 1; - lsa = info & EP_HAS_LSA; + lsa = !!(info & EP_HAS_LSA); cerr = (info2 & (3 << 1)) >> 1; ep_type = CTX_TO_EP_TYPE(info2); - hid = info2 & (1 << 7); + hid = !!(info2 & (1 << 7)); burst = CTX_TO_MAX_BURST(info2); maxp = MAX_PACKET_DECODED(info2); -- cgit v1.1 From a098dc8b03d1c7284ed98d921224fffa15b13ece Mon Sep 17 00:00:00 2001 From: Lu Baolu <baolu.lu@linux.intel.com> Date: Thu, 8 Mar 2018 17:17:15 +0200 Subject: usb: xhci: dbc: Fix lockdep warning The xHCI DbC implementation might enter a deadlock situation because there is no sufficient protection against the shared data between process and softirq contexts. This can lead to the following lockdep warnings. This patch changes to use spin_{,un}lock_irq{save,restore} to avoid potential deadlock. [ 528.248084] ================================ [ 528.252914] WARNING: inconsistent lock state [ 528.257756] 4.15.0-rc1+ #1630 Not tainted [ 528.262305] -------------------------------- [ 528.267145] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. [ 528.273953] ksoftirqd/1/17 [HC0[0]:SC1[1]:HE0:SE0] takes: [ 528.280075] (&(&port->port_lock)->rlock){+.?.}, at: [<ffffffff815396a8>] dbc_rx_push+0x38/0x1c0 [ 528.290043] {SOFTIRQ-ON-W} state was registered at: [ 528.295570] _raw_spin_lock+0x2f/0x40 [ 528.299818] dbc_write_complete+0x27/0xa0 [ 528.304458] xhci_dbc_giveback+0xd1/0x200 [ 528.309098] xhci_dbc_flush_endpoint_requests+0x50/0x70 [ 528.315116] xhci_dbc_handle_events+0x696/0x7b0 [ 528.320349] process_one_work+0x1ee/0x6e0 [ 528.324988] worker_thread+0x4a/0x430 [ 528.329236] kthread+0x13e/0x170 [ 528.332992] ret_from_fork+0x24/0x30 [ 528.337141] irq event stamp: 2861 [ 528.340897] hardirqs last enabled at (2860): [<ffffffff810674ea>] tasklet_action+0x6a/0x250 [ 528.350460] hardirqs last disabled at (2861): [<ffffffff817dc1ef>] _raw_spin_lock_irq+0xf/0x40 [ 528.360219] softirqs last enabled at (2852): [<ffffffff817e0e8c>] __do_softirq+0x3dc/0x4f9 [ 528.369683] softirqs last disabled at (2857): [<ffffffff8106805b>] run_ksoftirqd+0x1b/0x60 [ 528.379048] [ 528.379048] other info that might help us debug this: [ 528.386443] Possible unsafe locking scenario: [ 528.386443] [ 528.393150] CPU0 [ 528.395917] ---- [ 528.398687] lock(&(&port->port_lock)->rlock); [ 528.403821] <Interrupt> [ 528.406786] lock(&(&port->port_lock)->rlock); [ 528.412116] [ 528.412116] *** DEADLOCK *** [ 528.412116] [ 528.418825] no locks held by ksoftirqd/1/17. [ 528.423662] [ 528.423662] stack backtrace: [ 528.428598] CPU: 1 PID: 17 Comm: ksoftirqd/1 Not tainted 4.15.0-rc1+ #1630 [ 528.436387] Call Trace: [ 528.439158] dump_stack+0x5e/0x8e [ 528.442914] print_usage_bug+0x1fc/0x220 [ 528.447357] mark_lock+0x4db/0x5a0 [ 528.451210] __lock_acquire+0x726/0x1130 [ 528.455655] ? __lock_acquire+0x557/0x1130 [ 528.460296] lock_acquire+0xa2/0x200 [ 528.464347] ? dbc_rx_push+0x38/0x1c0 [ 528.468496] _raw_spin_lock_irq+0x35/0x40 [ 528.473038] ? dbc_rx_push+0x38/0x1c0 [ 528.477186] dbc_rx_push+0x38/0x1c0 [ 528.481139] tasklet_action+0x1d2/0x250 [ 528.485483] __do_softirq+0x1dc/0x4f9 [ 528.489630] run_ksoftirqd+0x1b/0x60 [ 528.493682] smpboot_thread_fn+0x179/0x270 [ 528.498324] kthread+0x13e/0x170 [ 528.501981] ? sort_range+0x20/0x20 [ 528.505933] ? kthread_delayed_work_timer_fn+0x80/0x80 [ 528.511755] ret_from_fork+0x24/0x30 Fixes: dfba2174dc42 ("usb: xhci: Add DbC support in xHCI driver") Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/xhci-dbgcap.c | 20 ++++++++++++-------- drivers/usb/host/xhci-dbgtty.c | 20 ++++++++++++-------- 2 files changed, 24 insertions(+), 16 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c index a1ab8ac..c359bae 100644 --- a/drivers/usb/host/xhci-dbgcap.c +++ b/drivers/usb/host/xhci-dbgcap.c @@ -328,13 +328,14 @@ dbc_ep_do_queue(struct dbc_ep *dep, struct dbc_request *req) int dbc_ep_queue(struct dbc_ep *dep, struct dbc_request *req, gfp_t gfp_flags) { + unsigned long flags; struct xhci_dbc *dbc = dep->dbc; int ret = -ESHUTDOWN; - spin_lock(&dbc->lock); + spin_lock_irqsave(&dbc->lock, flags); if (dbc->state == DS_CONFIGURED) ret = dbc_ep_do_queue(dep, req); - spin_unlock(&dbc->lock); + spin_unlock_irqrestore(&dbc->lock, flags); mod_delayed_work(system_wq, &dbc->event_work, 0); @@ -521,15 +522,16 @@ static void xhci_do_dbc_stop(struct xhci_hcd *xhci) static int xhci_dbc_start(struct xhci_hcd *xhci) { int ret; + unsigned long flags; struct xhci_dbc *dbc = xhci->dbc; WARN_ON(!dbc); pm_runtime_get_sync(xhci_to_hcd(xhci)->self.controller); - spin_lock(&dbc->lock); + spin_lock_irqsave(&dbc->lock, flags); ret = xhci_do_dbc_start(xhci); - spin_unlock(&dbc->lock); + spin_unlock_irqrestore(&dbc->lock, flags); if (ret) { pm_runtime_put(xhci_to_hcd(xhci)->self.controller); @@ -541,6 +543,7 @@ static int xhci_dbc_start(struct xhci_hcd *xhci) static void xhci_dbc_stop(struct xhci_hcd *xhci) { + unsigned long flags; struct xhci_dbc *dbc = xhci->dbc; struct dbc_port *port = &dbc->port; @@ -551,9 +554,9 @@ static void xhci_dbc_stop(struct xhci_hcd *xhci) if (port->registered) xhci_dbc_tty_unregister_device(xhci); - spin_lock(&dbc->lock); + spin_lock_irqsave(&dbc->lock, flags); xhci_do_dbc_stop(xhci); - spin_unlock(&dbc->lock); + spin_unlock_irqrestore(&dbc->lock, flags); pm_runtime_put_sync(xhci_to_hcd(xhci)->self.controller); } @@ -779,14 +782,15 @@ static void xhci_dbc_handle_events(struct work_struct *work) int ret; enum evtreturn evtr; struct xhci_dbc *dbc; + unsigned long flags; struct xhci_hcd *xhci; dbc = container_of(to_delayed_work(work), struct xhci_dbc, event_work); xhci = dbc->xhci; - spin_lock(&dbc->lock); + spin_lock_irqsave(&dbc->lock, flags); evtr = xhci_dbc_do_handle_events(dbc); - spin_unlock(&dbc->lock); + spin_unlock_irqrestore(&dbc->lock, flags); switch (evtr) { case EVT_GSER: diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c index 8d47b6f..75f0b92 100644 --- a/drivers/usb/host/xhci-dbgtty.c +++ b/drivers/usb/host/xhci-dbgtty.c @@ -92,21 +92,23 @@ static void dbc_start_rx(struct dbc_port *port) static void dbc_read_complete(struct xhci_hcd *xhci, struct dbc_request *req) { + unsigned long flags; struct xhci_dbc *dbc = xhci->dbc; struct dbc_port *port = &dbc->port; - spin_lock(&port->port_lock); + spin_lock_irqsave(&port->port_lock, flags); list_add_tail(&req->list_pool, &port->read_queue); tasklet_schedule(&port->push); - spin_unlock(&port->port_lock); + spin_unlock_irqrestore(&port->port_lock, flags); } static void dbc_write_complete(struct xhci_hcd *xhci, struct dbc_request *req) { + unsigned long flags; struct xhci_dbc *dbc = xhci->dbc; struct dbc_port *port = &dbc->port; - spin_lock(&port->port_lock); + spin_lock_irqsave(&port->port_lock, flags); list_add(&req->list_pool, &port->write_pool); switch (req->status) { case 0: @@ -119,7 +121,7 @@ static void dbc_write_complete(struct xhci_hcd *xhci, struct dbc_request *req) req->status); break; } - spin_unlock(&port->port_lock); + spin_unlock_irqrestore(&port->port_lock, flags); } static void xhci_dbc_free_req(struct dbc_ep *dep, struct dbc_request *req) @@ -327,12 +329,13 @@ static void dbc_rx_push(unsigned long _port) { struct dbc_request *req; struct tty_struct *tty; + unsigned long flags; bool do_push = false; bool disconnect = false; struct dbc_port *port = (void *)_port; struct list_head *queue = &port->read_queue; - spin_lock_irq(&port->port_lock); + spin_lock_irqsave(&port->port_lock, flags); tty = port->port.tty; while (!list_empty(queue)) { req = list_first_entry(queue, struct dbc_request, list_pool); @@ -392,16 +395,17 @@ static void dbc_rx_push(unsigned long _port) if (!disconnect) dbc_start_rx(port); - spin_unlock_irq(&port->port_lock); + spin_unlock_irqrestore(&port->port_lock, flags); } static int dbc_port_activate(struct tty_port *_port, struct tty_struct *tty) { + unsigned long flags; struct dbc_port *port = container_of(_port, struct dbc_port, port); - spin_lock_irq(&port->port_lock); + spin_lock_irqsave(&port->port_lock, flags); dbc_start_rx(port); - spin_unlock_irq(&port->port_lock); + spin_unlock_irqrestore(&port->port_lock, flags); return 0; } -- cgit v1.1 From 5126a504b63d82785eaece3a9c30c660b313785a Mon Sep 17 00:00:00 2001 From: Teijo Kinnunen <teijo.kinnunen@code-q.fi> Date: Thu, 1 Mar 2018 19:34:29 +0200 Subject: USB: storage: Add JMicron bridge 152d:2567 to unusual_devs.h This USB-SATA controller seems to be similar with JMicron bridge 152d:2566 already on the list. Adding it here fixes "Invalid field in cdb" errors. Signed-off-by: Teijo Kinnunen <teijo.kinnunen@code-q.fi> Cc: stable@vger.kernel.org Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 264af19..747d3a9 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -2118,6 +2118,13 @@ UNUSUAL_DEV( 0x152d, 0x2566, 0x0114, 0x0114, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BROKEN_FUA ), +/* Reported by Teijo Kinnunen <teijo.kinnunen@code-q.fi> */ +UNUSUAL_DEV( 0x152d, 0x2567, 0x0117, 0x0117, + "JMicron", + "USB to ATA/ATAPI Bridge", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_BROKEN_FUA ), + /* Reported-by George Cherian <george.cherian@cavium.com> */ UNUSUAL_DEV(0x152d, 0x9561, 0x0000, 0x9999, "JMicron", -- cgit v1.1 From 015dbeb2282030bf56762e21d25f09422edfd750 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Date: Tue, 27 Feb 2018 17:15:20 +0900 Subject: usb: host: xhci-rcar: add support for r8a77965 This patch adds support for r8a77965 (R-Car M3-N). Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Reviewed-by: Simon Horman <horms+renesas@verge.net.au> Reviewed-by: Rob Herring <robh@kernel.org> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/xhci-rcar.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c index f0b5596..f33ffc2 100644 --- a/drivers/usb/host/xhci-rcar.c +++ b/drivers/usb/host/xhci-rcar.c @@ -83,6 +83,10 @@ static const struct soc_device_attribute rcar_quirks_match[] = { .soc_id = "r8a7796", .data = (void *)RCAR_XHCI_FIRMWARE_V3, }, + { + .soc_id = "r8a77965", + .data = (void *)RCAR_XHCI_FIRMWARE_V3, + }, { /* sentinel */ }, }; -- cgit v1.1 From a5f596830e27e15f7a0ecd6be55e433d776986d8 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev <zaitcev@kotori.zaitcev.us> Date: Fri, 9 Mar 2018 00:21:14 -0600 Subject: usb: usbmon: Read text within supplied buffer size This change fixes buffer overflows and silent data corruption with the usbmon device driver text file read operations. Signed-off-by: Fredrik Noring <noring@nocrew.org> Signed-off-by: Pete Zaitcev <zaitcev@redhat.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/mon/mon_text.c | 126 ++++++++++++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 48 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index f5e1bb5..984f7e1 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c @@ -85,6 +85,8 @@ struct mon_reader_text { wait_queue_head_t wait; int printf_size; + size_t printf_offset; + size_t printf_togo; char *printf_buf; struct mutex printf_lock; @@ -376,75 +378,103 @@ err_alloc: return rc; } -/* - * For simplicity, we read one record in one system call and throw out - * what does not fit. This means that the following does not work: - * dd if=/dbg/usbmon/0t bs=10 - * Also, we do not allow seeks and do not bother advancing the offset. - */ +static ssize_t mon_text_copy_to_user(struct mon_reader_text *rp, + char __user * const buf, const size_t nbytes) +{ + const size_t togo = min(nbytes, rp->printf_togo); + + if (copy_to_user(buf, &rp->printf_buf[rp->printf_offset], togo)) + return -EFAULT; + rp->printf_togo -= togo; + rp->printf_offset += togo; + return togo; +} + +/* ppos is not advanced since the llseek operation is not permitted. */ static ssize_t mon_text_read_t(struct file *file, char __user *buf, - size_t nbytes, loff_t *ppos) + size_t nbytes, loff_t *ppos) { struct mon_reader_text *rp = file->private_data; struct mon_event_text *ep; struct mon_text_ptr ptr; + ssize_t ret; - ep = mon_text_read_wait(rp, file); - if (IS_ERR(ep)) - return PTR_ERR(ep); mutex_lock(&rp->printf_lock); - ptr.cnt = 0; - ptr.pbuf = rp->printf_buf; - ptr.limit = rp->printf_size; - - mon_text_read_head_t(rp, &ptr, ep); - mon_text_read_statset(rp, &ptr, ep); - ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, - " %d", ep->length); - mon_text_read_data(rp, &ptr, ep); - - if (copy_to_user(buf, rp->printf_buf, ptr.cnt)) - ptr.cnt = -EFAULT; + + if (rp->printf_togo == 0) { + + ep = mon_text_read_wait(rp, file); + if (IS_ERR(ep)) { + mutex_unlock(&rp->printf_lock); + return PTR_ERR(ep); + } + ptr.cnt = 0; + ptr.pbuf = rp->printf_buf; + ptr.limit = rp->printf_size; + + mon_text_read_head_t(rp, &ptr, ep); + mon_text_read_statset(rp, &ptr, ep); + ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, + " %d", ep->length); + mon_text_read_data(rp, &ptr, ep); + + rp->printf_togo = ptr.cnt; + rp->printf_offset = 0; + + kmem_cache_free(rp->e_slab, ep); + } + + ret = mon_text_copy_to_user(rp, buf, nbytes); mutex_unlock(&rp->printf_lock); - kmem_cache_free(rp->e_slab, ep); - return ptr.cnt; + return ret; } +/* ppos is not advanced since the llseek operation is not permitted. */ static ssize_t mon_text_read_u(struct file *file, char __user *buf, - size_t nbytes, loff_t *ppos) + size_t nbytes, loff_t *ppos) { struct mon_reader_text *rp = file->private_data; struct mon_event_text *ep; struct mon_text_ptr ptr; + ssize_t ret; - ep = mon_text_read_wait(rp, file); - if (IS_ERR(ep)) - return PTR_ERR(ep); mutex_lock(&rp->printf_lock); - ptr.cnt = 0; - ptr.pbuf = rp->printf_buf; - ptr.limit = rp->printf_size; - mon_text_read_head_u(rp, &ptr, ep); - if (ep->type == 'E') { - mon_text_read_statset(rp, &ptr, ep); - } else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) { - mon_text_read_isostat(rp, &ptr, ep); - mon_text_read_isodesc(rp, &ptr, ep); - } else if (ep->xfertype == USB_ENDPOINT_XFER_INT) { - mon_text_read_intstat(rp, &ptr, ep); - } else { - mon_text_read_statset(rp, &ptr, ep); + if (rp->printf_togo == 0) { + + ep = mon_text_read_wait(rp, file); + if (IS_ERR(ep)) { + mutex_unlock(&rp->printf_lock); + return PTR_ERR(ep); + } + ptr.cnt = 0; + ptr.pbuf = rp->printf_buf; + ptr.limit = rp->printf_size; + + mon_text_read_head_u(rp, &ptr, ep); + if (ep->type == 'E') { + mon_text_read_statset(rp, &ptr, ep); + } else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) { + mon_text_read_isostat(rp, &ptr, ep); + mon_text_read_isodesc(rp, &ptr, ep); + } else if (ep->xfertype == USB_ENDPOINT_XFER_INT) { + mon_text_read_intstat(rp, &ptr, ep); + } else { + mon_text_read_statset(rp, &ptr, ep); + } + ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, + " %d", ep->length); + mon_text_read_data(rp, &ptr, ep); + + rp->printf_togo = ptr.cnt; + rp->printf_offset = 0; + + kmem_cache_free(rp->e_slab, ep); } - ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, - " %d", ep->length); - mon_text_read_data(rp, &ptr, ep); - if (copy_to_user(buf, rp->printf_buf, ptr.cnt)) - ptr.cnt = -EFAULT; + ret = mon_text_copy_to_user(rp, buf, nbytes); mutex_unlock(&rp->printf_lock); - kmem_cache_free(rp->e_slab, ep); - return ptr.cnt; + return ret; } static struct mon_event_text *mon_text_read_wait(struct mon_reader_text *rp, -- cgit v1.1 From d56e57ca030c8b4296944a2ae61ac167bf979c07 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Date: Thu, 8 Mar 2018 17:17:16 +0200 Subject: usb: host: xhci-plat: revert "usb: host: xhci-plat: enable clk in resume timing" This patch reverts the commit 835e4241e714 ("usb: host: xhci-plat: enable clk in resume timing") because this driver also has runtime PM and the commit 560869100b99 ("clk: renesas: cpg-mssr: Restore module clocks during resume") will restore the clock on R-Car H3 environment. If the xhci_plat_suspend() disables the clk, the system cannot enable the clk in resume like the following behavior: < In resume > - genpd_resume_noirq() runs and enable the clk (enable_count = 1) - cpg_mssr_resume_noirq() restores the clk register. -- Since the clk was disabled in suspend, cpg_mssr_resume_noirq() will disable the clk and keep the enable_count. - Even if xhci_plat_resume() calls clk_prepare_enable(), since the enable_count is 1, the clk will be not enabled. After this patch is applied, the cpg-mssr driver will save the clk as enable, so the clk will be enabled in resume. Fixes: 835e4241e714 ("usb: host: xhci-plat: enable clk in resume timing") Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/xhci-plat.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 6f03830..6652e2d 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -360,7 +360,6 @@ static int __maybe_unused xhci_plat_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); - int ret; /* * xhci_suspend() needs `do_wakeup` to know whether host is allowed @@ -370,12 +369,7 @@ static int __maybe_unused xhci_plat_suspend(struct device *dev) * reconsider this when xhci_plat_suspend enlarges its scope, e.g., * also applies to runtime suspend. */ - ret = xhci_suspend(xhci, device_may_wakeup(dev)); - - if (!device_may_wakeup(dev) && !IS_ERR(xhci->clk)) - clk_disable_unprepare(xhci->clk); - - return ret; + return xhci_suspend(xhci, device_may_wakeup(dev)); } static int __maybe_unused xhci_plat_resume(struct device *dev) @@ -384,9 +378,6 @@ static int __maybe_unused xhci_plat_resume(struct device *dev) struct xhci_hcd *xhci = hcd_to_xhci(hcd); int ret; - if (!device_may_wakeup(dev) && !IS_ERR(xhci->clk)) - clk_prepare_enable(xhci->clk); - ret = xhci_priv_resume_quirk(hcd); if (ret) return ret; -- cgit v1.1 From 191edc5e2e515aab1075a3f0ef23599e80be5f59 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng <kai.heng.feng@canonical.com> Date: Thu, 8 Mar 2018 17:17:17 +0200 Subject: xhci: Fix front USB ports on ASUS PRIME B350M-A When a USB device gets plugged on ASUS PRIME B350M-A's front ports, the xHC stops working: [ 549.114587] xhci_hcd 0000:02:00.0: WARN: xHC CMD_RUN timeout [ 549.114608] suspend_common(): xhci_pci_suspend+0x0/0xc0 returns -110 [ 549.114638] xhci_hcd 0000:02:00.0: can't suspend (hcd_pci_runtime_suspend returned -110) Delay before running xHC command CMD_RUN can workaround the issue. Use a new quirk to make the delay only targets to the affected xHC. Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/xhci-pci.c | 3 +++ drivers/usb/host/xhci.c | 3 +++ drivers/usb/host/xhci.h | 1 + 3 files changed, 7 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 5262fa5..d9f831b 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -126,6 +126,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info()) xhci->quirks |= XHCI_AMD_PLL_FIX; + if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x43bb) + xhci->quirks |= XHCI_SUSPEND_DELAY; + if (pdev->vendor == PCI_VENDOR_ID_AMD) xhci->quirks |= XHCI_TRUST_TX_LENGTH; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 25d4b748..5d37700 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -877,6 +877,9 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); del_timer_sync(&xhci->shared_hcd->rh_timer); + if (xhci->quirks & XHCI_SUSPEND_DELAY) + usleep_range(1000, 1500); + spin_lock_irq(&xhci->lock); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index d20e57b..866e141 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1826,6 +1826,7 @@ struct xhci_hcd { #define XHCI_U2_DISABLE_WAKE (1 << 27) #define XHCI_ASMEDIA_MODIFY_FLOWCONTROL (1 << 28) #define XHCI_HW_LPM_DISABLE (1 << 29) +#define XHCI_SUSPEND_DELAY (1 << 30) unsigned int num_active_eps; unsigned int limit_active_eps; -- cgit v1.1 From df3334c223a033f562645712e832ca4cbb326bbf Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Thu, 22 Feb 2018 17:39:17 +0000 Subject: usbip: vudc: fix null pointer dereference on udc->lock Currently the driver attempts to spin lock on udc->lock before a NULL pointer check is performed on udc, hence there is a potential null pointer dereference on udc->lock. Fix this by moving the null check on udc before the lock occurs. Fixes: ea6873a45a22 ("usbip: vudc: Add SysFS infrastructure for VUDC") Signed-off-by: Colin Ian King <colin.king@canonical.com> Acked-by: Shuah Khan <shuahkh@osg.samsung.com> Reviewed-by: Krzysztof Opasiak <k.opasiak@samsung.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/usbip/vudc_sysfs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/usbip/vudc_sysfs.c b/drivers/usb/usbip/vudc_sysfs.c index d86f72b..6dcd3ff 100644 --- a/drivers/usb/usbip/vudc_sysfs.c +++ b/drivers/usb/usbip/vudc_sysfs.c @@ -105,10 +105,14 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a if (rv != 0) return -EINVAL; + if (!udc) { + dev_err(dev, "no device"); + return -ENODEV; + } spin_lock_irqsave(&udc->lock, flags); /* Don't export what we don't have */ - if (!udc || !udc->driver || !udc->pullup) { - dev_err(dev, "no device or gadget not bound"); + if (!udc->driver || !udc->pullup) { + dev_err(dev, "gadget not bound"); ret = -ENODEV; goto unlock; } -- cgit v1.1 From d6c931ea32dc08ac2665bb5f009f9c40ad1bbdb3 Mon Sep 17 00:00:00 2001 From: Fredrik Noring <noring@nocrew.org> Date: Fri, 9 Mar 2018 18:34:34 +0100 Subject: USB: OHCI: Fix NULL dereference in HCDs using HCD_LOCAL_MEM Scatter-gather needs to be disabled when using dma_declare_coherent_memory and HCD_LOCAL_MEM. Andrea Righi made the equivalent fix for EHCI drivers in commit 4307a28eb01284 "USB: EHCI: fix NULL pointer dererence in HCDs that use HCD_LOCAL_MEM". The following NULL pointer WARN_ON_ONCE triggered with OHCI drivers: ------------[ cut here ]------------ WARNING: CPU: 0 PID: 49 at drivers/usb/core/hcd.c:1379 hcd_alloc_coherent+0x4c/0xc8 Modules linked in: CPU: 0 PID: 49 Comm: usb-storage Not tainted 4.15.0+ #1014 Stack : 00000000 00000000 805a78d2 0000003a 81f5c2cc 8053d367 804d77fc 00000031 805a3a08 00000563 81ee9400 805a0000 00000000 10058c00 81f61b10 805c0000 00000000 00000000 805a0000 00d9038e 00000004 803ee818 00000006 312e3420 805c0000 00000000 00000073 81f61958 00000000 00000000 802eb380 804fd538 00000009 00000563 81ee9400 805a0000 00000002 80056148 00000000 805a0000 ... Call Trace: [<578af360>] show_stack+0x74/0x104 [<2f3702c6>] __warn+0x118/0x120 [<ae93fc9e>] warn_slowpath_null+0x44/0x58 [<a891a517>] hcd_alloc_coherent+0x4c/0xc8 [<3578fa36>] usb_hcd_map_urb_for_dma+0x4d8/0x534 [<110bc94c>] usb_hcd_submit_urb+0x82c/0x834 [<02eb5baf>] usb_sg_wait+0x14c/0x1a0 [<ccd09e85>] usb_stor_bulk_transfer_sglist.part.1+0xac/0x124 [<87a5c34c>] usb_stor_bulk_srb+0x40/0x60 [<ff1792ac>] usb_stor_Bulk_transport+0x160/0x37c [<b9e2709c>] usb_stor_invoke_transport+0x3c/0x500 [<004754f4>] usb_stor_control_thread+0x258/0x28c [<22edf42e>] kthread+0x134/0x13c [<a419ffd0>] ret_from_kernel_thread+0x14/0x1c ---[ end trace bcdb825805eefdcc ]--- Signed-off-by: Fredrik Noring <noring@nocrew.org> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/host/ohci-hcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 84f88fa..d088c34 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -447,7 +447,8 @@ static int ohci_init (struct ohci_hcd *ohci) struct usb_hcd *hcd = ohci_to_hcd(ohci); /* Accept arbitrarily long scatter-gather lists */ - hcd->self.sg_tablesize = ~0; + if (!(hcd->driver->flags & HCD_LOCAL_MEM)) + hcd->self.sg_tablesize = ~0; if (distrust_firmware) ohci->flags |= OHCI_QUIRK_HUB_POWER; -- cgit v1.1 From 7832f6d12fa25cd4cfc18eaae67eb5e2dbaa2c34 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Sun, 25 Feb 2018 16:20:01 +0100 Subject: usb: typec: tcpm: fusb302: Do not log an error on -EPROBE_DEFER Do not log an error if tcpm_register_port() fails with -EPROBE_DEFER. Fixes: cf140a356971 ("typec: fusb302: Use dev_err during probe") Signed-off-by: Hans de Goede <hdegoede@redhat.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/typec/fusb302/fusb302.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c index 9ce4756..dcd8ef0 100644 --- a/drivers/usb/typec/fusb302/fusb302.c +++ b/drivers/usb/typec/fusb302/fusb302.c @@ -1857,7 +1857,8 @@ static int fusb302_probe(struct i2c_client *client, chip->tcpm_port = tcpm_register_port(&client->dev, &chip->tcpc_dev); if (IS_ERR(chip->tcpm_port)) { ret = PTR_ERR(chip->tcpm_port); - dev_err(dev, "cannot register tcpm port, ret=%d", ret); + if (ret != -EPROBE_DEFER) + dev_err(dev, "cannot register tcpm port, ret=%d", ret); goto destroy_workqueue; } -- cgit v1.1 From 94e46a4f2d5eb14059e42f313c098d4854847376 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer <merlijn@wizzup.org> Date: Tue, 13 Mar 2018 09:48:40 -0500 Subject: usb: musb: Fix external abort in musb_remove on omap2430 This fixes an oops on unbind / module unload (on the musb omap2430 platform). musb_remove function now calls musb_platform_exit before disabling runtime pm. Signed-off-by: Merlijn Wajer <merlijn@wizzup.org> Signed-off-by: Bin Liu <b-liu@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/usb/musb/musb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index c344ef4..4d72307 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2473,11 +2473,11 @@ static int musb_remove(struct platform_device *pdev) musb_disable_interrupts(musb); musb_writeb(musb->mregs, MUSB_DEVCTL, 0); spin_unlock_irqrestore(&musb->lock, flags); + musb_platform_exit(musb); pm_runtime_dont_use_autosuspend(musb->controller); pm_runtime_put_sync(musb->controller); pm_runtime_disable(musb->controller); - musb_platform_exit(musb); musb_phy_callback = NULL; if (musb->dma_controller) musb_dma_controller_destroy(musb->dma_controller); -- cgit v1.1