From bff52352e0ccc2481f2b6b0d612ff8ff56c50f3a Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Mon, 18 Dec 2017 16:14:36 +0100 Subject: [PATCH 01/21] 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 Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-of-simple.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c index 7ae0eefc7cc7..e54c3622eb28 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); From e3190868e5f52fb26544f16463593d54ce46ce61 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Fri, 12 Jan 2018 20:00:56 +0900 Subject: [PATCH 02/21] 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 Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/renesas_usb3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 6e87af248367..409cde4e6a51 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; } From 6180026341e852a250e1f97ebdcf71684a3c81b9 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Fri, 12 Jan 2018 18:18:05 -0800 Subject: [PATCH 03/21] 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 Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 616ef49ccb49..2bda4eb1e9ac 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) && From f035d139ffece7b6a7b8bfb17bd0ba715ee57a04 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Fri, 12 Jan 2018 18:18:27 -0800 Subject: [PATCH 04/21] 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 Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 9c2e4a17918e..18be31d5743a 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; } From 8813a59ed892305b5ac1b5b901740b1ad4b5fefa Mon Sep 17 00:00:00 2001 From: John Keeping Date: Fri, 12 Jan 2018 18:43:32 +0000 Subject: [PATCH 05/21] 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 Signed-off-by: John Keeping Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_uac2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 11fe788b4308..d2dc1f00180b 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; From 00b42170c86f90ac9dea83a7dfcd3f0c38098fe2 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 17 Jan 2018 13:22:49 -0800 Subject: [PATCH 06/21] 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 Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index ade2ab00d37a..bc2467f0e6a7 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; } From c4a5153e87fdf6805f63ff57556260e2554155a5 Mon Sep 17 00:00:00 2001 From: Manu Gautam Date: Thu, 18 Jan 2018 16:54:30 +0530 Subject: [PATCH 07/21] 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 Signed-off-by: Manu Gautam Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index bc2467f0e6a7..59511f2cd3ac 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; From 499350865387f8b8c40a9e9453a9a7eb3cec5dc4 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 18 Jan 2018 00:22:45 -0200 Subject: [PATCH 08/21] 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: # v4.15 Reviewed-by: Li Jun Acked-by: Peter Chen Signed-off-by: Fabio Estevam Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-mxs-usb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index da031c45395a..fbec863350f6 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; From 6cf439e0d37463e42784271179c8a308fd7493c6 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Wed, 24 Jan 2018 00:11:53 -0800 Subject: [PATCH 09/21] 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 Signed-off-by: Mayank Rana Signed-off-by: Jack Pham Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_fs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 8f2cf3baa19c..49fc589fbf58 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; From 675272d092e4a5570bace92593776f7348daf4c5 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Wed, 24 Jan 2018 23:58:20 -0800 Subject: [PATCH 10/21] 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 Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_fs.c | 38 ++++++------------------------ 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 49fc589fbf58..c2592d883f67 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; } From c49f63055e252810e5d6c83a4943b18db16b3cd8 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Mon, 22 Jan 2018 15:01:42 +0200 Subject: [PATCH 11/21] 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 Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index a4719e853b85..ed8b86517675 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) From e74bd4d358e5455233f1dcc3975425905b270b91 Mon Sep 17 00:00:00 2001 From: Manu Gautam Date: Thu, 21 Dec 2017 09:54:25 +0530 Subject: [PATCH 12/21] 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 Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 859d5b11ba4c..1f8b19d9cf97 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); From b16ea8b9492e99e03b1269fe93ebdbf8e4eabf8a Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Fri, 2 Feb 2018 13:21:35 -0800 Subject: [PATCH 13/21] 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 Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 03c7aaaac926..185b9603fd98 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) From 20bf410ecf9e9c045f4b0548d516dd3de8691074 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Mon, 5 Feb 2018 02:21:23 +0100 Subject: [PATCH 14/21] 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 Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index 1e9567091d86..0875d38476ee 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 From 17aa31f13cad25daa19d3f923323f552e87bc874 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 5 Feb 2018 17:12:35 +0900 Subject: [PATCH 15/21] 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: # v3.19+ Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 5925d111bd47..39fa2fc1b8b7 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); From 20c63f4089cceab803438c383631963e34c4d8e5 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Mon, 12 Feb 2018 00:14:42 +0100 Subject: [PATCH 16/21] 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 Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/fsl_udc_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index e5b4ee96c4bf..56b517a38865 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; } From 201ec568c57a43dbc73c7ac00e73c3c2d39559fc Mon Sep 17 00:00:00 2001 From: Minas Harutyunyan Date: Tue, 16 Jan 2018 16:03:32 +0400 Subject: [PATCH 17/21] 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 Signed-off-by: Minas Harutyunyan Signed-off-by: Grigor Tovmasyan Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index e4c3ce0de5de..57c7400057fa 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) | From 9e95a66cce7250c358d496e1c3b62e29ce79ef40 Mon Sep 17 00:00:00 2001 From: Minas Harutyunyan Date: Tue, 16 Jan 2018 16:03:58 +0400 Subject: [PATCH 18/21] 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 Signed-off-by: Minas Harutyunyan Signed-off-by: Grigor Tovmasyan Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 57c7400057fa..d6222e946463 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) From 755d739534f998d92e348fba8ffb0478416576e7 Mon Sep 17 00:00:00 2001 From: Vardan Mikayelyan Date: Tue, 16 Jan 2018 16:04:24 +0400 Subject: [PATCH 19/21] 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 Signed-off-by: Vardan Mikayelyan Signed-off-by: Grigor Tovmasyan Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index d6222e946463..5bcad1d869b5 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) From 8874ae5f15f3feef3b4a415b9aed51edcf449aa1 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 23 Jan 2018 09:35:14 +0000 Subject: [PATCH 20/21] 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 Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/bdc/bdc_pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/udc/bdc/bdc_pci.c b/drivers/usb/gadget/udc/bdc/bdc_pci.c index 1e940f054cb8..6dbc489513cd 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; } From 98112041bcca164676367e261c8c1073ef70cb51 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Mon, 12 Feb 2018 15:30:08 +0200 Subject: [PATCH 21/21] 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 # >= v4.13 Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 51 ++++++++++++++++++++++++++++++----------- drivers/usb/dwc3/core.h | 5 ++++ 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 59511f2cd3ac..f1d838a4acd6 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,18 +771,28 @@ static int dwc3_core_init(struct dwc3 *dwc) dwc->maximum_speed = USB_SPEED_HIGH; } - ret = dwc3_core_get_phy(dwc); - if (ret) - goto err0; - - ret = dwc3_core_soft_reset(dwc); - if (ret) - goto err0; - ret = dwc3_phy_setup(dwc); if (ret) goto err0; + if (!dwc->ulpi_ready) { + ret = dwc3_core_ulpi_init(dwc); + if (ret) + goto err0; + dwc->ulpi_ready = true; + } + + 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 err0a; + dwc3_core_setup_global_control(dwc); dwc3_core_num_eps(dwc); @@ -841,6 +864,9 @@ static int dwc3_core_init(struct dwc3 *dwc) phy_exit(dwc->usb2_generic_phy); phy_exit(dwc->usb3_generic_phy); +err0a: + dwc3_ulpi_exit(dwc); + err0: return ret; } @@ -1235,7 +1261,6 @@ static int dwc3_probe(struct platform_device *pdev) 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 185b9603fd98..860d2bc184d1 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;