From bd84f4ae9986ac9acd278566ccb39c60bc961abb Mon Sep 17 00:00:00 2001 From: John Youn Date: Mon, 15 Feb 2016 15:30:20 -0800 Subject: usb: dwc2: Add extra delay when forcing dr_mode Fixes an issue found on rockchip rk3036 and rk3188 SOC platforms. For some reason, the existing msleep(25) is not enough after the force mode. The following patch was reported to fix the issue. This does increase the probe delay again slightly, but not up to the level it was before the original series of patches that this fixes. It does not cause any other issues when tested on Synopsys HAPS and Altera socfpga platforms. Need to revisit this series next release to see if we can address these issues without having an unconditional delay. Fixes: 09c96980dc72 ("usb: dwc2: Add functions to set and clear force mode") Reported-by: Caesar Wang Reported-by: Michael Niewoehner Tested-by: Heiko Stuebner Tested-by: Caesar Wang Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/core.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index e991d55914db..46c4ba75dc2a 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -619,6 +619,12 @@ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg) __func__, hsotg->dr_mode); break; } + + /* + * NOTE: This is required for some rockchip soc based + * platforms. + */ + msleep(50); } /* -- cgit v1.2.3 From c450960187f45d4260db87c7dd4fc0bceb5565d8 Mon Sep 17 00:00:00 2001 From: John Youn Date: Tue, 16 Feb 2016 20:10:53 -0800 Subject: usb: dwc3: Fix assignment of EP transfer resources The assignement of EP transfer resources was not handled properly in the dwc3 driver. Commit aebda6187181 ("usb: dwc3: Reset the transfer resource index on SET_INTERFACE") previously fixed one aspect of this where resources may be exhausted with multiple calls to SET_INTERFACE. However, it introduced an issue where composite devices with multiple interfaces can be assigned the same transfer resources for different endpoints. This patch solves both issues. The assignment of transfer resources cannot perfectly follow the data book due to the fact that the controller driver does not have all knowledge of the configuration in advance. It is given this information piecemeal by the composite gadget framework after every SET_CONFIGURATION and SET_INTERFACE. Trying to follow the databook programming model in this scenario can cause errors. For two reasons: 1) The databook says to do DEPSTARTCFG for every SET_CONFIGURATION and SET_INTERFACE (8.1.5). This is incorrect in the scenario of multiple interfaces. 2) The databook does not mention doing more DEPXFERCFG for new endpoint on alt setting (8.1.6). The following simplified method is used instead: All hardware endpoints can be assigned a transfer resource and this setting will stay persistent until either a core reset or hibernation. So whenever we do a DEPSTARTCFG(0) we can go ahead and do DEPXFERCFG for every hardware endpoint as well. We are guaranteed that there are as many transfer resources as endpoints. This patch triggers off of the calling dwc3_gadget_start_config() for EP0-out, which always happens first, and which should only happen in one of the above conditions. Fixes: aebda6187181 ("usb: dwc3: Reset the transfer resource index on SET_INTERFACE") Cc: # v3.2+ Reported-by: Ravi Babu Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 1 - drivers/usb/dwc3/ep0.c | 5 ---- drivers/usb/dwc3/gadget.c | 70 +++++++++++++++++++++++++++++++++++------------ 3 files changed, 52 insertions(+), 24 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 29130682e547..e4f8b90d9627 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -856,7 +856,6 @@ struct dwc3 { unsigned pullups_connected:1; unsigned resize_fifos:1; unsigned setup_packet_pending:1; - unsigned start_config_issued:1; unsigned three_stage_setup:1; unsigned usb3_lpm_capable:1; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 3a9354abcb68..8d6b75c2f53b 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -555,7 +555,6 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) int ret; u32 reg; - dwc->start_config_issued = false; cfg = le16_to_cpu(ctrl->wValue); switch (state) { @@ -737,10 +736,6 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY"); ret = dwc3_ep0_set_isoch_delay(dwc, ctrl); break; - case USB_REQ_SET_INTERFACE: - dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_INTERFACE"); - dwc->start_config_issued = false; - /* Fall through */ default: dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver"); ret = dwc3_ep0_delegate_req(dwc, ctrl); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 7d1dd82a95ac..2363bad45af8 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -385,24 +385,66 @@ static void dwc3_free_trb_pool(struct dwc3_ep *dep) dep->trb_pool_dma = 0; } +static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep); + +/** + * dwc3_gadget_start_config - Configure EP resources + * @dwc: pointer to our controller context structure + * @dep: endpoint that is being enabled + * + * The assignment of transfer resources cannot perfectly follow the + * data book due to the fact that the controller driver does not have + * all knowledge of the configuration in advance. It is given this + * information piecemeal by the composite gadget framework after every + * SET_CONFIGURATION and SET_INTERFACE. Trying to follow the databook + * programming model in this scenario can cause errors. For two + * reasons: + * + * 1) The databook says to do DEPSTARTCFG for every SET_CONFIGURATION + * and SET_INTERFACE (8.1.5). This is incorrect in the scenario of + * multiple interfaces. + * + * 2) The databook does not mention doing more DEPXFERCFG for new + * endpoint on alt setting (8.1.6). + * + * The following simplified method is used instead: + * + * All hardware endpoints can be assigned a transfer resource and this + * setting will stay persistent until either a core reset or + * hibernation. So whenever we do a DEPSTARTCFG(0) we can go ahead and + * do DEPXFERCFG for every hardware endpoint as well. We are + * guaranteed that there are as many transfer resources as endpoints. + * + * This function is called for each endpoint when it is being enabled + * but is triggered only when called for EP0-out, which always happens + * first, and which should only happen in one of the above conditions. + */ static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep) { struct dwc3_gadget_ep_cmd_params params; u32 cmd; + int i; + int ret; + + if (dep->number) + return 0; memset(¶ms, 0x00, sizeof(params)); + cmd = DWC3_DEPCMD_DEPSTARTCFG; - if (dep->number != 1) { - cmd = DWC3_DEPCMD_DEPSTARTCFG; - /* XferRscIdx == 0 for ep0 and 2 for the remaining */ - if (dep->number > 1) { - if (dwc->start_config_issued) - return 0; - dwc->start_config_issued = true; - cmd |= DWC3_DEPCMD_PARAM(2); - } + ret = dwc3_send_gadget_ep_cmd(dwc, 0, cmd, ¶ms); + if (ret) + return ret; - return dwc3_send_gadget_ep_cmd(dwc, 0, cmd, ¶ms); + for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) { + struct dwc3_ep *dep = dwc->eps[i]; + + if (!dep) + continue; + + ret = dwc3_gadget_set_xfer_resource(dwc, dep); + if (ret) + return ret; } return 0; @@ -516,10 +558,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, struct dwc3_trb *trb_st_hw; struct dwc3_trb *trb_link; - ret = dwc3_gadget_set_xfer_resource(dwc, dep); - if (ret) - return ret; - dep->endpoint.desc = desc; dep->comp_desc = comp_desc; dep->type = usb_endpoint_type(desc); @@ -1636,8 +1674,6 @@ static int dwc3_gadget_start(struct usb_gadget *g, } dwc3_writel(dwc->regs, DWC3_DCFG, reg); - dwc->start_config_issued = false; - /* Start with SuperSpeed Default */ dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); @@ -2237,7 +2273,6 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_DCTL, reg); dwc3_disconnect_gadget(dwc); - dwc->start_config_issued = false; dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->setup_packet_pending = false; @@ -2288,7 +2323,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) dwc3_stop_active_transfers(dwc); dwc3_clear_stall_all_ep(dwc); - dwc->start_config_issued = false; /* Reset device address to zero */ reg = dwc3_readl(dwc->regs, DWC3_DCFG); -- cgit v1.2.3 From 3142a16b9816c24501103a92010a283eb6e2766c Mon Sep 17 00:00:00 2001 From: Vardan Mikayelyan Date: Tue, 16 Feb 2016 15:01:53 -0800 Subject: usb: dwc2: host: fix logical omissions in dwc2_process_non_isoc_desc Fixes memory manipulation issues and makes Host DDMA bulk transfers work. dwc2_process_non_isoc_desc() must return non zero value ONLY when failure happens in one of the queued descriptors. After receiving non zero value the caller must stop processing of remaining QTDs and their descriptors from chain. Commit 26a19ea699060fde ("usb: dwc2: host: fix use of qtd after free in desc dma mode") breaks non_isoc transaction completion logic in Host DDMA mode. There were bugs before that, but after this patch dwc2_process_non_isoc_desc() returns fail status even if descriptor was processed normally. This causes break from loop which is processing remaining descriptors assigned to QTD, which is not correct for QTDs containing more than one descriptor. Current dwc2 driver gathers queued BULK URBs until receiving URB without URB_NO_INTERRUPT flag. Once getting it, SW creates descriptor chain, stores it in qh structure and passes start address to HW. Multiple URB data is contained in that chain. Hence on getting error on descriptor after its processing by HW, SW should go out of both loops(qh->qtd, qtd->descs) and report the failure. Fixes: 26a19ea699060fde ("usb: dwc2: host: fix use of qtd after free in desc dma mode") Cc: Gregory Herrero Signed-off-by: Vardan Mikayelyan Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/hcd_ddma.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc2/hcd_ddma.c b/drivers/usb/dwc2/hcd_ddma.c index 36606fc33c0d..89db47a1ffed 100644 --- a/drivers/usb/dwc2/hcd_ddma.c +++ b/drivers/usb/dwc2/hcd_ddma.c @@ -1174,14 +1174,11 @@ static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg, failed = dwc2_update_non_isoc_urb_state_ddma(hsotg, chan, qtd, dma_desc, halt_status, n_bytes, xfer_done); - if (*xfer_done && urb->status != -EINPROGRESS) - failed = 1; - - if (failed) { + if (failed || (*xfer_done && urb->status != -EINPROGRESS)) { dwc2_host_complete(hsotg, qtd, urb->status); dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); - dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x status=%08x\n", - failed, *xfer_done, urb->status); + dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x\n", + failed, *xfer_done); return failed; } @@ -1236,21 +1233,23 @@ static void dwc2_complete_non_isoc_xfer_ddma(struct dwc2_hsotg *hsotg, list_for_each_safe(qtd_item, qtd_tmp, &qh->qtd_list) { int i; + int qtd_desc_count; qtd = list_entry(qtd_item, struct dwc2_qtd, qtd_list_entry); xfer_done = 0; + qtd_desc_count = qtd->n_desc; - for (i = 0; i < qtd->n_desc; i++) { + for (i = 0; i < qtd_desc_count; i++) { if (dwc2_process_non_isoc_desc(hsotg, chan, chnum, qtd, desc_num, halt_status, - &xfer_done)) { - qtd = NULL; - break; - } + &xfer_done)) + goto stop_scan; + desc_num++; } } +stop_scan: if (qh->ep_type != USB_ENDPOINT_XFER_CONTROL) { /* * Resetting the data toggle for bulk and interrupt endpoints -- cgit v1.2.3 From 62943b7dfa35887a40f71f698deec4488bf73036 Mon Sep 17 00:00:00 2001 From: "Tang, Jianqiang" Date: Tue, 16 Feb 2016 15:02:07 -0800 Subject: usb: dwc2: host: fix the data toggle error in full speed descriptor dma There will be data toggle error happen for full speed buld-out transfer. The data toggle bit is saved in qh for non-control transfers, it is wrong to check the qtd for that case. Also fix one static analysis tool issue after fix the data toggle error. John Youn: * Added WARN() to warn on improper usage of the dwc2_hcd_save_data_toggle() function. Signed-off-by: Dyson Lee Signed-off-by: Tang, Jianqiang Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/hcd_ddma.c | 2 +- drivers/usb/dwc2/hcd_intr.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc2/hcd_ddma.c b/drivers/usb/dwc2/hcd_ddma.c index 89db47a1ffed..a41274aa52ad 100644 --- a/drivers/usb/dwc2/hcd_ddma.c +++ b/drivers/usb/dwc2/hcd_ddma.c @@ -1257,7 +1257,7 @@ stop_scan: */ if (halt_status == DWC2_HC_XFER_STALL) qh->data_toggle = DWC2_HC_PID_DATA0; - else if (qtd) + else dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd); } diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index f8253803a050..cadba8b13c48 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c @@ -525,11 +525,19 @@ void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg, u32 pid = (hctsiz & TSIZ_SC_MC_PID_MASK) >> TSIZ_SC_MC_PID_SHIFT; if (chan->ep_type != USB_ENDPOINT_XFER_CONTROL) { + if (WARN(!chan || !chan->qh, + "chan->qh must be specified for non-control eps\n")) + return; + if (pid == TSIZ_SC_MC_PID_DATA0) chan->qh->data_toggle = DWC2_HC_PID_DATA0; else chan->qh->data_toggle = DWC2_HC_PID_DATA1; } else { + if (WARN(!qtd, + "qtd must be specified for control eps\n")) + return; + if (pid == TSIZ_SC_MC_PID_DATA0) qtd->data_toggle = DWC2_HC_PID_DATA0; else -- cgit v1.2.3 From ee89b641a9ddca5f2d1e38d205473c4b0d26c670 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 16 Feb 2016 16:10:59 +0100 Subject: usb: dwc2: USB_DWC2 should depend on HAS_DMA If NO_DMA=y: ERROR: "usb_gadget_map_request" [drivers/usb/dwc2/dwc2.ko] undefined! ERROR: "usb_gadget_unmap_request" [drivers/usb/dwc2/dwc2.ko] undefined! ERROR: "bad_dma_ops" [drivers/usb/dwc2/dwc2.ko] undefined! Add a dependency on HAS_DMA to fix this. Signed-off-by: Geert Uytterhoeven Acked-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig index fd95ba6ec317..f0decc0d69b5 100644 --- a/drivers/usb/dwc2/Kconfig +++ b/drivers/usb/dwc2/Kconfig @@ -1,5 +1,6 @@ config USB_DWC2 tristate "DesignWare USB2 DRD Core Support" + depends on HAS_DMA depends on USB || USB_GADGET help Say Y here if your system has a Dual Role Hi-Speed USB -- cgit v1.2.3 From 96c7de4ff41c2ed6da43141a4deb922de09617d0 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 15 Feb 2016 15:35:25 +0100 Subject: usb: gadget: fsl_qe_udc: fix IS_ERR_VALUE usage IS_ERR_VALUE macro should be used only with unsigned long type. Otherwise it can work incorrectly. The patch follows conclusion from discussion on LKML [1][2]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2120927 [2]: http://permalink.gmane.org/gmane.linux.kernel/2150581 Signed-off-by: Andrzej Hajda Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/fsl_qe_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c index 53c0692f1b09..93d28cb00b76 100644 --- a/drivers/usb/gadget/udc/fsl_qe_udc.c +++ b/drivers/usb/gadget/udc/fsl_qe_udc.c @@ -2340,7 +2340,7 @@ static struct qe_udc *qe_udc_config(struct platform_device *ofdev) { struct qe_udc *udc; struct device_node *np = ofdev->dev.of_node; - unsigned int tmp_addr = 0; + unsigned long tmp_addr = 0; struct usb_device_para __iomem *usbpram; unsigned int i; u64 size; -- cgit v1.2.3 From bba40e6948b94cba71965285fbac31bd078c024a Mon Sep 17 00:00:00 2001 From: Cristian Birsan Date: Thu, 11 Feb 2016 08:58:17 -0700 Subject: usb: musb: Fix DMA desired mode for Mentor DMA engine Commit 754fe4a92c07 ("usb: musb: Remove ifdefs for TX DMA for musb_host.c") introduces a problem setting the desired channel mode for the Mentor DMA engine. There is a case where an address is incorrectly assigned to the DMA channel desired mode when it should instead be assigned the actual mode value. This results in the value of channel->desired_mode not being correct. Acked-by: Sergei Shtylyov Signed-off-by: Cristian Birsan Signed-off-by: Joshua Henderson Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 795a45b1b25b..79d081883628 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -662,7 +662,7 @@ static int musb_tx_dma_set_mode_mentor(struct dma_controller *dma, csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE); csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */ } - channel->desired_mode = mode; + channel->desired_mode = *mode; musb_writew(epio, MUSB_TXCSR, csr); return 0; -- cgit v1.2.3 From 31b994a4986dcdd664c597afcef2c0918763019a Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 8 Feb 2016 13:42:14 +0100 Subject: usb: gadget: remove driver from pending list on probe error Retry gadget probe only if the probe result is -EPROBE_DEFER, not on every probe error. Signed-off-by: Marek Szyprowski Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/udc-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index fd73a3ea07c2..b86a6f03592e 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -413,9 +413,10 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, if (!driver->udc_name || strcmp(driver->udc_name, dev_name(&udc->dev)) == 0) { ret = udc_bind_to_driver(udc, driver); + if (ret != -EPROBE_DEFER) + list_del(&driver->pending); if (ret) goto err4; - list_del(&driver->pending); break; } } -- cgit v1.2.3 From 7b0a271d5cadf5fbb5a9c7cb868776af2a2c248c Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 18 Feb 2016 08:59:26 +0100 Subject: usb: gadget: gadgetfs: unregister gadget only if it got successfully registered Gadgetfs driver called usb_gadget_unregister_driver unconditionally, even if it didn't register it earlier due to other failures. This patch fixes this. Reported-by: Vegard Nossum Signed-off-by: Marek Szyprowski Tested-by: Vegard Nossum Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/inode.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 7e179f81d05c..87fb0fd6aaab 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -130,7 +130,8 @@ struct dev_data { setup_can_stall : 1, setup_out_ready : 1, setup_out_error : 1, - setup_abort : 1; + setup_abort : 1, + gadget_registered : 1; unsigned setup_wLength; /* the rest is basically write-once */ @@ -1179,7 +1180,8 @@ dev_release (struct inode *inode, struct file *fd) /* closing ep0 === shutdown all */ - usb_gadget_unregister_driver (&gadgetfs_driver); + if (dev->gadget_registered) + usb_gadget_unregister_driver (&gadgetfs_driver); /* at this point "good" hardware has disconnected the * device from USB; the host won't see it any more. @@ -1847,6 +1849,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) * kick in after the ep0 descriptor is closed. */ value = len; + dev->gadget_registered = true; } return value; -- cgit v1.2.3 From ca1c11894274c1687417945c034d6b8aee49f625 Mon Sep 17 00:00:00 2001 From: Simon Appleby Date: Tue, 9 Feb 2016 09:19:46 +0000 Subject: usb: gadget: net2280: fix endpoint max packet for super speed connections This patch fixes the register offset used for super-speed connection's max packet size. Without it using the 338x series of devices in enhanced mode will only allow full or high speed operation to function correctly. Signed-off-by: Simon Appleby Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/net2280.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/net2280.h b/drivers/usb/gadget/udc/net2280.h index 4dff60d34f73..0d32052bf16f 100644 --- a/drivers/usb/gadget/udc/net2280.h +++ b/drivers/usb/gadget/udc/net2280.h @@ -369,9 +369,20 @@ static inline void set_max_speed(struct net2280_ep *ep, u32 max) static const u32 ep_enhanced[9] = { 0x10, 0x60, 0x30, 0x80, 0x50, 0x20, 0x70, 0x40, 0x90 }; - if (ep->dev->enhanced_mode) + if (ep->dev->enhanced_mode) { reg = ep_enhanced[ep->num]; - else{ + switch (ep->dev->gadget.speed) { + case USB_SPEED_SUPER: + reg += 2; + break; + case USB_SPEED_FULL: + reg += 1; + break; + case USB_SPEED_HIGH: + default: + break; + } + } else { reg = (ep->num + 1) * 0x10; if (ep->dev->gadget.speed != USB_SPEED_HIGH) reg += 1; -- cgit v1.2.3 From 8de4b3a3fcbc18e0aa62e9defe5c08821351be12 Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Fri, 5 Feb 2016 19:17:09 +0000 Subject: usb: phy: msm: Trigger USB state detection work in DRD mode When working in Dual Role Device mode, USB state machine is not kicked, when host or gadget drivers are loaded. Fix this be explicitly triggering state detection on client driver load. Issue is that if the board is booted without micro usb cable and usb device attached, kernel fails to populate the usb host and device. The reason for this is that the state machine worker logic only checks for USB_DR_MODE_PERIPHERAL and USB_DR_MODE_HOST modes to run worker thread. However if the phy is configured in OTG mode it would fail to run the state machine, resulting in failure to detect for very first time. This patch fixes the issue by removing the explicit checks. Issue is noticed on Qualcomm Dragon board DB410C. [srinivas.kandagatla@linaro.org: Added more details to log] Signed-off-by: Ivan T. Ivanov Signed-off-by: Srinivas Kandagatla Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-msm-usb.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 970a30e155cb..72b387d592c2 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -757,14 +757,8 @@ static int msm_otg_set_host(struct usb_otg *otg, struct usb_bus *host) otg->host = host; dev_dbg(otg->usb_phy->dev, "host driver registered w/ tranceiver\n"); - /* - * Kick the state machine work, if peripheral is not supported - * or peripheral is already registered with us. - */ - if (motg->pdata->mode == USB_DR_MODE_HOST || otg->gadget) { - pm_runtime_get_sync(otg->usb_phy->dev); - schedule_work(&motg->sm_work); - } + pm_runtime_get_sync(otg->usb_phy->dev); + schedule_work(&motg->sm_work); return 0; } @@ -827,14 +821,8 @@ static int msm_otg_set_peripheral(struct usb_otg *otg, dev_dbg(otg->usb_phy->dev, "peripheral driver registered w/ tranceiver\n"); - /* - * Kick the state machine work, if host is not supported - * or host is already registered with us. - */ - if (motg->pdata->mode == USB_DR_MODE_PERIPHERAL || otg->host) { - pm_runtime_get_sync(otg->usb_phy->dev); - schedule_work(&motg->sm_work); - } + pm_runtime_get_sync(otg->usb_phy->dev); + schedule_work(&motg->sm_work); return 0; } -- cgit v1.2.3 From 4c2ba0c67394514f3f75c660c9f5d02e66a7efd4 Mon Sep 17 00:00:00 2001 From: Cristian Birsan Date: Fri, 19 Feb 2016 10:11:56 +0200 Subject: usb: musb: fix DMA for host mode Commit ac33cdb16681 ("usb: musb: Remove ifdefs for musb_host_rx in musb_host.c part5") introduces a problem setting DMA host mode. The musb_advance_schedule() is called immediately after receiving an endpoint RX interrupt without waiting for the DMA transfer to complete. As a consequence when the dma complete interrupt arrives the in_qh member of hw_ep is already null an the musb_host_rx() exits on !urb error case. Fix the done condition that advances the musb schedule. Signed-off-by: Cristian Birsan Signed-off-by: Joshua Henderson Tested-by: Ladislav Michl Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_host.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 79d081883628..58487a473521 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2003,10 +2003,8 @@ void musb_host_rx(struct musb *musb, u8 epnum) qh->offset, urb->transfer_buffer_length); - done = musb_rx_dma_in_inventra_cppi41(c, hw_ep, qh, - urb, xfer_len, - iso_err); - if (done) + if (musb_rx_dma_in_inventra_cppi41(c, hw_ep, qh, urb, + xfer_len, iso_err)) goto finish; else dev_err(musb->controller, "error: rx_dma failed\n"); -- cgit v1.2.3