usb: dwc3: Fixes and improvements for DWC3 driver
Subsystems (2)
cover usb: dwc3: Fixes and improvements for DWC3 driver
Those patches should be applied on top of Kishon Vijay Abraham I work (v1) [40 patches]:
https://patchwork.ozlabs.org/patch/442467/
"dra7xx: am43xx: add dwc3 gadget driver support and enable dfu"
Those changes fixes composite, DFU and UMS gadgets - as a result relevant tests (available at test/{dfu|ums} pass.
Test HW: Odroid XU3 - Exynos5422
There is one important thing to note:
Since on our setup Data and Instruction Caches seems to be broken (or at least don't behave as expected) the comments regarding cache management in DWC3 still applies.
I will look on them at v2 of this patch set. This code should be also easily applicable on top of v2.
Inha Song (1):
usb: dwc3: Add BIT() macro
Joonyoung Shim (1):
usb: dwc3: make dwc3_set_mode to static
Marek Szyprowski (3):
usb: dwc3: add a workaround for too small OUT requests
usb: dwc3: gadget: add common endpoint configuration for dwc3 udc
driver
usb: dwc3: optimize interrupt loop
?ukasz Majewski (6):
usb: composite: Add .reset callback to usb_gadget_driver structure
usb: dwc3: linux-compat: Fix: Adding missing include files
usb: dwc3: Set usbdrd phy ctrl and mode in dwc3 core
usb: dwc3: gadget: Set all ctrl fields of Transfer Control Blocks
(TRB) to be LST
usb: dwc3: gadget: Set non EP0 max packet limit to 512B
usb: dwc3: Correct clean up code for requests
drivers/usb/dwc3/core.c | 86 +++++++++++++++++++++++++++++++++++---- drivers/usb/dwc3/core.h | 3 +- drivers/usb/dwc3/gadget.c | 76 ++++++++++++++++------------------ drivers/usb/dwc3/linux-compat.h | 3 ++ drivers/usb/gadget/composite.c | 1 + drivers/usb/gadget/epautoconf.c | 21 +++++++++- drivers/usb/gadget/gadget_chips.h | 8 ++++ include/dwc3-uboot.h | 2 + 8 files changed, 149 insertions(+), 51 deletions(-)
Signature · 1 line
2.0.0.rc2
PATCH 1/11 usb: composite: Add .reset callback to usb_gadget_driver structure
DWC3 UDC driver requires presence of .reset callback in a composite driver. This setting is similar to the one nowadays present in linux kernel.
--- drivers/usb/gadget/composite.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/gadget/composite.c +1 -0
@@ -1052,6 +1052,7 @@ static struct usb_gadget_driver composite_driver = { .unbind = composite_unbind, .setup = composite_setup, + .reset = composite_disconnect, .disconnect = composite_disconnect, .suspend = composite_suspend,
Signature · 1 line
2.0.0.rc2
PATCH 2/11 usb: dwc3: linux-compat: Fix: Adding missing include files
In reply to Lukasz MajewskiAdded #includes are necessary to allow dwc3 to compile and run on u-boot for Odroid XU3.
--- drivers/usb/dwc3/linux-compat.h | 3 +++ 1 file changed, 3 insertions(+)
drivers/usb/dwc3/linux-compat.h +3 -0
@@ -12,6 +12,9 @@#ifndef __DWC3_LINUX_COMPAT__#define __DWC3_LINUX_COMPAT__ +#include <common.h> +#include <linux/compat.h> +#define pr_debug (format) debug(format) #define WARN(val, format, arg...) debug(format, ##arg) #define dev_WARN(dev, format, arg...) debug(format, ##arg)
Signature · 1 line
2.0.0.rc2
PATCH 2/11 usb: dwc3: linux-compat: Fix: Adding missing include files
Hi,
Quoted 2 lines · Lukasz Majewski
Added #includes are necessary to allow dwc3 to compile and run on u-boot for Odroid XU3.
I think you should also add the files for Odroid XU3.
Quoted 11 lines
Signed-off-by Lukasz Majewski <[email protected]>--- drivers/usb/dwc3/linux-compat.h | 3 +++ 1 file changed, 3 insertions(+)drivers/usb/dwc3/linux-compat.h +0
-0
drivers/usb/dwc3/linux-compat.h line 16
Quoted 5 lines
drivers/usb/dwc3/linux-compat.h +2
-0@@ -12,6 +12,9 @@#ifndef __DWC3_LINUX_COMPAT__#define __DWC3_LINUX_COMPAT__ +#include <common.h> +#include <linux/compat.h>
These are not needed for dwc3 core driver. So I'd assume it is required only for Odroid XU3 file? For other files it is redundant.
Thanks
Kishon
PATCH 3/11 usb: dwc3: Add BIT() macro
In reply to Lukasz MajewskiFrom: Inha Song <[email protected]>
--- drivers/usb/dwc3/core.h | 1 + 1 file changed, 1 insertion(+)
drivers/usb/dwc3/core.h +1 -0
@@ -392,6 +392,7 @@ struct dwc3_event_buffer {unsigned int count;unsigned int flags; +#define BIT (x) (1 << x)#define DWC3_EVENT_PENDING BIT(0)dma_addr_t dma;
Signature · 1 line
2.0.0.rc2
PATCH 3/11 usb: dwc3: Add BIT() macro
Quoted 3 lines · Lukasz Majewski
From: Inha Song <[email protected]>
Signed-off-by Inha Song <[email protected]>
Is such confusing macro really necessary please ?
Moreover, the #define BIT(x) (1 << x) should really be #define BIT(x) (1 << (x)) (with (x) in round brackets).
Best regards,
Marek Vasut
PATCH 4/11 usb: dwc3: make dwc3_set_mode to static
In reply to Lukasz MajewskiFrom: Joonyoung Shim <[email protected]>
--- drivers/usb/dwc3/core.c | 2 +- drivers/usb/dwc3/core.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-)
drivers/usb/dwc3/core.c +1 -1
@@ -32,7 +32,7 @@static LIST_HEAD (dwc3_list);/* -------------------------------------------------------------------------- */ -void dwc3_set_mode (struct dwc3 *dwc,u32 mode) +static void dwc3_set_mode (struct dwc3 *dwc,u32 mode) {u32 reg;
drivers/usb/dwc3/core.h +0 -1
@@ -988,7 +988,6 @@ struct dwc3_gadget_ep_cmd_params {#define DWC3_HAS_OTG BIT(3)/* prototypes */ -void dwc3_set_mode (struct dwc3 *dwc,u32 mode);int dwc3_gadget_resize_tx_fifos (struct dwc3 *dwc);#ifdef CONFIG_USB_DWC3_HOST
Signature · 1 line
2.0.0.rc2
PATCH 4/11 usb: dwc3: make dwc3_set_mode to static
Hi,
Quoted 1 line · Lukasz Majewski
From: Joonyoung Shim <[email protected]>
commit message please.
-Kishon
Quoted 33 lines
Signed-off-by Joonyoung Shim <[email protected]>--- drivers/usb/dwc3/core.c | 2 +- drivers/usb/dwc3/core.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-)drivers/usb/dwc3/core.c +1
-1@@ -32,7 +32,7 @@static LIST_HEAD (dwc3_list);/* -------------------------------------------------------------------------- */ -void dwc3_set_mode (struct dwc3 *dwc,u32 mode) +static void dwc3_set_mode (struct dwc3 *dwc,u32 mode) {u32 reg;drivers/usb/dwc3/core.h +0
-1@@ -988,7 +988,6 @@ struct dwc3_gadget_ep_cmd_params {#define DWC3_HAS_OTG BIT(3)/* prototypes */ -void dwc3_set_mode (struct dwc3 *dwc,u32 mode);int dwc3_gadget_resize_tx_fifos (struct dwc3 *dwc);#ifdef CONFIG_USB_DWC3_HOST
PATCH 5/11 usb: dwc3: Set usbdrd phy ctrl and mode in dwc3 core
In reply to Lukasz Majewski--- drivers/usb/dwc3/core.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++- drivers/usb/dwc3/core.h | 1 + include/dwc3-uboot.h | 2 ++ 3 files changed, 79 insertions(+), 1 deletion(-)
drivers/usb/dwc3/core.c +76 -1
@@ -14,7 +14,12 @@* SPDX-License-Identifier: GPL-2.0 */ +#include "linux-compat.h" +#include <common.h> +#include <asm/arch/power.h> +#include <asm/arch/xhci-exynos.h> +#include <asm/cache.h> #include <malloc.h> #include <dwc3-uboot.h> #include <asm/dma-mapping.h>
@@ -42,6 +47,71 @@ static void dwc3_set_mode(struct dwc3 *dwc, u32 mode)dwc3_writel (dwc->regs,DWC3_GCTL , reg); } +static void exynos5_usb3_phy_init (struct exynos_usb3_phy *phy) +{ +u32 reg; + +/* Reset USB 3.0 PHY */ +writel (0x0 , &phy->phy_reg0); + +clrbits_le32 (&phy->phy_param0, +/* Select PHY CLK source */ +PHYPARAM0_REF_USE_PAD | +/* Set Loss-of-Signal Detector sensitivity */ +PHYPARAM0_REF_LOSLEVEL_MASK ); +setbits_le32 (&phy->phy_param0,PHYPARAM0_REF_LOSLEVEL ); + + +writel (0x0 , &phy->phy_resume); + +/* +* Setting the Frame length Adj value[6:1] to default 0x20 +* See xHCI 1.0 spec, 5.2.4 +*/ +setbits_le32 (&phy->link_system, +LINKSYSTEM_XHCI_VERSION_CONTROL | +LINKSYSTEM_FLADJ (0x20 )); + +/* Set Tx De-Emphasis level */ +clrbits_le32 (&phy->phy_param1,PHYPARAM1_PCS_TXDEEMPH_MASK ); +setbits_le32 (&phy->phy_param1,PHYPARAM1_PCS_TXDEEMPH ); + +setbits_le32 (&phy->phy_batchg,PHYBATCHG_UTMI_CLKSEL ); + +/* PHYTEST POWERDOWN Control */ +clrbits_le32 (&phy->phy_test, +PHYTEST_POWERDOWN_SSP | +PHYTEST_POWERDOWN_HSP ); + +/* UTMI Power Control */ +writel (PHYUTMI_OTGDISABLE , &phy->phy_utmi); + +/* Use core clock from main PLL */ + reg =PHYCLKRST_REFCLKSEL_EXT_REFCLK | +/* Default 24Mhz crystal clock */ +PHYCLKRST_FSEL (FSEL_CLKSEL_24M ) | +PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF | +PHYCLKRST_SSC_REFCLKSEL (0 ) | +/* Force PortReset of PHY */ +PHYCLKRST_PORTRESET | +/* Digital power supply in normal operating mode */ +PHYCLKRST_RETENABLEN | +/* Enable ref clock for SS function */ +PHYCLKRST_REF_SSP_EN | +/* Enable spread spectrum */ +PHYCLKRST_SSC_EN | +/* Power down HS Bias and PLL blocks in suspend mode */ +PHYCLKRST_COMMONONN ; + +writel (reg, &phy->phy_clk_rst); + +/* giving time to Phy clock to settle before resetting */ +udelay (10 ); + + reg &= ~PHYCLKRST_PORTRESET ; +writel (reg, &phy->phy_clk_rst); +} +/** * dwc3_core_soft_reset - Issues core soft reset and PHY reset * @dwc: pointer to our context structure
@@ -66,6 +136,7 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)dwc3_writel (dwc->regs,DWC3_GUSB2PHYCFG (0 ), reg);mdelay (100 ); +exynos5_usb3_phy_init ((struct exynos_usb3_phy *)dwc->phy_regs);/* Clear USB3 PHY reset */ reg =dwc3_readl (dwc->regs,DWC3_GUSB3PIPECTL (0 ));
@@ -599,6 +670,7 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)#define DWC3_ALIGN_MASK (16 - 1) +void set_usbdrd_phy_ctrl (unsigned int enable);/** * dwc3_uboot_init - dwc3 core uboot initialization code * @dwc3_dev: struct dwc3_device containing initialization data
@@ -629,7 +701,8 @@ int dwc3_uboot_init(struct dwc3_device *dwc3_dev) dwc =PTR_ALIGN (mem,DWC3_ALIGN_MASK +1 ); dwc->mem = mem; - dwc->regs = (int *)(dwc3_dev->base +DWC3_GLOBALS_REGS_START ); + dwc->regs = (int *)(dwc3_dev->base +DWC3_GLOBALS_REGS_START ); + dwc->phy_regs = (int *)(dwc3_dev->phy_base);/* default to highest possible threshold */ lpm_nyet_threshold =0xff ;
@@ -697,6 +770,8 @@ int dwc3_uboot_init(struct dwc3_device *dwc3_dev)if (dwc->dr_mode ==USB_DR_MODE_UNKNOWN ) dwc->dr_mode =USB_DR_MODE_OTG ; +set_usbdrd_phy_ctrl (POWER_USB_DRD_PHY_CTRL_EN ); + ret =dwc3_core_init (dwc);if (ret) {dev_err (dev,"failed to initialize core\n" );
drivers/usb/dwc3/core.h +1 -0
@@ -727,6 +727,7 @@ struct dwc3 {void __iomem *regs;size_t regs_size; +void __iomem *phy_regs;enum usb_dr_mode dr_mode;
include/dwc3-uboot.h +2 -0
@@ -14,6 +14,8 @@struct dwc3_device {int base; +int phy_base; +unsigned needs_fifo_resize:1 ;enum usb_dr_mode dr_mode;u32 maximum_speed;unsigned tx_fifo_resize:1 ;
Signature · 1 line
2.0.0.rc2
PATCH 5/11 usb: dwc3: Set usbdrd phy ctrl and mode in dwc3 core
Hi,
On Monday 23 February 2015 07:32 PM, Lukasz Majewski wrote:
commit message here again.
Quoted 14 lines
Signed-off-by Joonyoung Shim <[email protected]>Signed-off-by Lukasz Majewski <[email protected]>[The code has been rebased on v2 dwc3 support provided by Kishon Vijay Abraham I]--- drivers/usb/dwc3/core.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++- drivers/usb/dwc3/core.h | 1 + include/dwc3-uboot.h | 2 ++ 3 files changed, 79 insertions(+), 1 deletion(-)drivers/usb/dwc3/core.c +0
-0
drivers/usb/dwc3/core.c line 17
Quoted 4 lines
drivers/usb/dwc3/core.c +1
-0@@ -14,7 +14,12 @@* SPDX-License-Identifier: GPL-2.0 */ +#include "linux-compat.h"
This is already included.
drivers/usb/dwc3/core.c line 21
Quoted 4 lines
drivers/usb/dwc3/core.c +3
-0+#include <common.h> +#include <asm/arch/power.h> +#include <asm/arch/xhci-exynos.h>
Don't do platform specific stuff in DWC3 core files and break other platforms.
Quoted 62 lines
drivers/usb/dwc3/core.c +55
-0+#include <asm/cache.h> #include <malloc.h> #include <dwc3-uboot.h> #include <asm/dma-mapping.h> @@ -42,6 +47,71 @@ static void dwc3_set_mode(struct dwc3 *dwc, u32 mode)dwc3_writel (dwc->regs,DWC3_GCTL , reg); } +static void exynos5_usb3_phy_init (struct exynos_usb3_phy *phy) +{ +u32 reg; + +/* Reset USB 3.0 PHY */ +writel (0x0 , &phy->phy_reg0); + +clrbits_le32 (&phy->phy_param0, +/* Select PHY CLK source */ +PHYPARAM0_REF_USE_PAD | +/* Set Loss-of-Signal Detector sensitivity */ +PHYPARAM0_REF_LOSLEVEL_MASK ); +setbits_le32 (&phy->phy_param0,PHYPARAM0_REF_LOSLEVEL ); + + +writel (0x0 , &phy->phy_resume); + +/* +* Setting the Frame length Adj value[6:1] to default 0x20 +* See xHCI 1.0 spec, 5.2.4 +*/ +setbits_le32 (&phy->link_system, +LINKSYSTEM_XHCI_VERSION_CONTROL | +LINKSYSTEM_FLADJ (0x20 )); + +/* Set Tx De-Emphasis level */ +clrbits_le32 (&phy->phy_param1,PHYPARAM1_PCS_TXDEEMPH_MASK ); +setbits_le32 (&phy->phy_param1,PHYPARAM1_PCS_TXDEEMPH ); + +setbits_le32 (&phy->phy_batchg,PHYBATCHG_UTMI_CLKSEL ); + +/* PHYTEST POWERDOWN Control */ +clrbits_le32 (&phy->phy_test, +PHYTEST_POWERDOWN_SSP | +PHYTEST_POWERDOWN_HSP ); + +/* UTMI Power Control */ +writel (PHYUTMI_OTGDISABLE , &phy->phy_utmi); + +/* Use core clock from main PLL */ + reg =PHYCLKRST_REFCLKSEL_EXT_REFCLK | +/* Default 24Mhz crystal clock */ +PHYCLKRST_FSEL (FSEL_CLKSEL_24M ) | +PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF | +PHYCLKRST_SSC_REFCLKSEL (0 ) | +/* Force PortReset of PHY */ +PHYCLKRST_PORTRESET | +/* Digital power supply in normal operating mode */ +PHYCLKRST_RETENABLEN | +/* Enable ref clock for SS function */ +PHYCLKRST_REF_SSP_EN | +/* Enable spread spectrum */ + PHYCLKRST_SSC_EN | +/* Power down HS Bias and PLL blocks in suspend mode */
drivers/usb/dwc3/core.c static void dwc3_set_mode(struct dwc3 *dwc, u32 mode) · line 113
Quoted 10 lines
drivers/usb/dwc3/core.c +10
-0+PHYCLKRST_COMMONONN ; + +writel (reg, &phy->phy_clk_rst); + +/* giving time to Phy clock to settle before resetting */ +udelay (10 ); + + reg &= ~PHYCLKRST_PORTRESET ; +writel (reg, &phy->phy_clk_rst); +}
This function shouldn't be here at all.
Quoted 56 lines
drivers/usb/dwc3/core.c +7
-1+/** * dwc3_core_soft_reset - Issues core soft reset and PHY reset * @dwc: pointer to our context structure @@ -66,6 +136,7 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)dwc3_writel (dwc->regs,DWC3_GUSB2PHYCFG (0 ), reg);mdelay (100 ); +exynos5_usb3_phy_init ((struct exynos_usb3_phy *)dwc->phy_regs);/* Clear USB3 PHY reset */ reg =dwc3_readl (dwc->regs,DWC3_GUSB3PIPECTL (0 ));@@ -599,6 +670,7 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)#define DWC3_ALIGN_MASK (16 - 1) +void set_usbdrd_phy_ctrl (unsigned int enable);/** * dwc3_uboot_init - dwc3 core uboot initialization code * @dwc3_dev: struct dwc3_device containing initialization data @@ -629,7 +701,8 @@ int dwc3_uboot_init(struct dwc3_device *dwc3_dev) dwc =PTR_ALIGN (mem,DWC3_ALIGN_MASK +1 ); dwc->mem = mem; - dwc->regs = (int *)(dwc3_dev->base +DWC3_GLOBALS_REGS_START ); + dwc->regs = (int *)(dwc3_dev->base +DWC3_GLOBALS_REGS_START ); + dwc->phy_regs = (int *)(dwc3_dev->phy_base);/* default to highest possible threshold */ lpm_nyet_threshold =0xff ;@@ -697,6 +770,8 @@ int dwc3_uboot_init(struct dwc3_device *dwc3_dev)if (dwc->dr_mode ==USB_DR_MODE_UNKNOWN ) dwc->dr_mode =USB_DR_MODE_OTG ; +set_usbdrd_phy_ctrl (POWER_USB_DRD_PHY_CTRL_EN ); + ret =dwc3_core_init (dwc);if (ret) {dev_err (dev,"failed to initialize core\n" );drivers/usb/dwc3/core.h +1
-0@@ -727,6 +727,7 @@ struct dwc3 {void __iomem *regs;size_t regs_size; +void __iomem *phy_regs;enum usb_dr_mode dr_mode;include/dwc3-uboot.h +0
-0
include/dwc3-uboot.h line 18
Quoted 5 lines
include/dwc3-uboot.h +2
-0@@ -14,6 +14,8 @@struct dwc3_device {int base; +int phy_base; +unsigned needs_fifo_resize:1 ;
tx_fifo_resize is already part of this structure.
Thanks
Kishon
PATCH 6/11 usb: dwc3: add a workaround for too small OUT requests
In reply to Lukasz MajewskiFrom: Marek Szyprowski <[email protected]>
DWC3 hangs on OUT requests smaller than maxpacket size, so HACK the request length to be at least equal to maxpacket size.
--- drivers/usb/dwc3/gadget.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/usb/dwc3/gadget.c +6 -0
@@ -974,6 +974,12 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) req->direction = dep->direction; req->epnum = dep->number; +/* DWC3 hangs on OUT requests smaller than maxpacket size, +so HACK the request length */ +if (dep->direction ==0 && + req->request.length < dep->endpoint.maxpacket) + req->request.length = dep->endpoint.maxpacket; +/* * We only add to our list of requests now and * start consuming the list once we get XferNotReady
Signature · 1 line
2.0.0.rc2
PATCH 6/11 usb: dwc3: add a workaround for too small OUT requests
Hi,
Quoted 4 lines · Lukasz Majewski
From: Marek Szyprowski <[email protected]>
DWC3 hangs on OUT requests smaller than maxpacket size, so HACK the request length to be at least equal to maxpacket size.
Curious to know using which gadget this issue was seen.
Thanks
Kishon
Quoted 24 lines
Signed-off-by Marek Szyprowski <[email protected]>--- drivers/usb/dwc3/gadget.c | 6 ++++++ 1 file changed, 6 insertions(+)drivers/usb/dwc3/gadget.c +6
-0@@ -974,6 +974,12 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) req->direction = dep->direction; req->epnum = dep->number; +/* DWC3 hangs on OUT requests smaller than maxpacket size, +so HACK the request length */ +if (dep->direction ==0 && + req->request.length < dep->endpoint.maxpacket) + req->request.length = dep->endpoint.maxpacket; +/* * We only add to our list of requests now and * start consuming the list once we get XferNotReady
PATCH 6/11 usb: dwc3: add a workaround for too small OUT requests
Hi Kishon,
Quoted 9 lines
Hi,
Quoted 4 lines · Lukasz Majewski
From: Marek Szyprowski <[email protected]>
DWC3 hangs on OUT requests smaller than maxpacket size, so HACK the request length to be at least equal to maxpacket size.
Curious to know using which gadget this issue was seen.
We have been testing this code with USB Mass Storage, Thor and DFU gadgets.
In the v2 commit letter you have stated that this code was tested with DFU MMC:
Quoted 2 lines
Quoted 2 lines
Testing:
*) tested DFU RAM and DFU MMC in dra7xx and am43xx
Have you tried to run test at ./test/dfu directory?
Quoted 29 lines
Thanks
KishonQuoted 25 lines
Signed-off-by Marek Szyprowski <[email protected]>--- drivers/usb/dwc3/gadget.c | 6 ++++++ 1 file changed, 6 insertions(+)drivers/usb/dwc3/gadget.c +6
-0@@ -974,6 +974,12 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) req->direction = dep->direction; req->epnum = dep->number; +/* DWC3 hangs on OUT requests smaller than maxpacket size, +so HACK the request length */ +if (dep->direction ==0 && + req->request.length < dep->endpoint.maxpacket) + req->request.length = dep->endpoint.maxpacket; +/* * We only add to our list of requests now and * start consuming the list once we get XferNotReady
Signature · 5 lines
Best regards, Lukasz Majewski Samsung R&D Institute Poland (SRPOL) | Linux Platform Group
PATCH 6/11 usb: dwc3: add a workaround for too small OUT requests
Hi,
Quoted 7 lines · Lukasz Majewski
Hi Kishon,
Quoted 5 lines
Hi,
Quoted 2 lines · Lukasz Majewski
From: Marek Szyprowski <[email protected]>
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
DWC3 hangs on OUT requests smaller than maxpacket size, so HACK the request length to be at least equal to maxpacket size.
Curious to know using which gadget this issue was seen.
We have been testing this code with USB Mass Storage, Thor and DFU gadgets.
nice!
Quoted 8 lines
In the v2 commit letter you have stated that this code was tested with DFU MMC:
Quoted 2 lines
Quoted 2 lines
Testing:
*) tested DFU RAM and DFU MMC in dra7xx and am43xxHave you tried to run test at ./test/dfu directory?
Haven't seen that before. I download images MLO, u-boot.img, uImage, fdt etc using dfu and do a boot test using the downloaded images.
Will try using the ./test/dfu directory.
Thanks
Kishon
PATCH 7/11 usb: dwc3: gadget: add common endpoint configuration for dwc3 udc driver
In reply to Lukasz MajewskiFrom: Marek Szyprowski <[email protected]>
This patch adds code to select standard, commonly used usb endpoint configuration (ep1in-bulk, ep2out-bulk, ep3in-int) to dwc3 driver. This ensures compatibility with old userspace and windows drivers, which expects hardcoded endpoint numbers.
--- drivers/usb/gadget/epautoconf.c | 21 ++++++++++++++++++++- drivers/usb/gadget/gadget_chips.h | 8 ++++++++ 2 files changed, 28 insertions(+), 1 deletion(-)
drivers/usb/gadget/epautoconf.c +20 -1
@@ -220,7 +220,7 @@ struct usb_ep *usb_ep_autoconfig(struct usb_endpoint_descriptor *desc ) { -struct usb_ep *ep; +struct usb_ep *ep =NULL ;u8 type; type = desc->bmAttributes &USB_ENDPOINT_XFERTYPE_MASK ;
@@ -261,6 +261,25 @@ struct usb_ep *usb_ep_autoconfig( ep =find_ep (gadget,"ep1-bulk" );if (ep &&ep_matches (gadget, ep, desc))return ep; + }else if (gadget_is_dwc3 (gadget)) { +const char *name =NULL ; +/* +First try standard, common configuration: ep1in-bulk, +ep2out-bulk, ep3in-int to match other udc drivers to avoid confusion +in already deployed software (endpoint numbers hardcoded in userspace +software/drivers) +*/ +if ((desc->bEndpointAddress &USB_DIR_IN ) && type ==USB_ENDPOINT_XFER_BULK ) + name ="ep1in" ; +else if ((desc->bEndpointAddress &USB_DIR_IN ) ==0 && type ==USB_ENDPOINT_XFER_BULK ) + name ="ep2out" ; +else if ((desc->bEndpointAddress &USB_DIR_IN ) && type ==USB_ENDPOINT_XFER_INT ) + name ="ep3in" ; + +if (name) + ep =find_ep (gadget, name); +if (ep &&ep_matches (gadget, ep, desc)) +return ep; }/* Second, look at endpoints until an unclaimed one looks usable */
drivers/usb/gadget/gadget_chips.h +8 -0
@@ -156,6 +156,14 @@#define gadget_is_fotg210 (g) 0#endif +#ifdef CONFIG_USB_DWC3_GADGET +#define gadget_is_dwc3 (g) (!strcmp("dwc3-gadget", (g)->name)) +#else +#define gadget_is_dwc3 (g) 0 +#endif + + +/* * CONFIG_USB_GADGET_SX2 * CONFIG_USB_GADGET_AU1X00
Signature · 1 line
2.0.0.rc2
PATCH 8/11 usb: dwc3: optimize interrupt loop
In reply to Lukasz MajewskiFrom: Marek Szyprowski <[email protected]>
There is no point in calling dwc3_thread_interrupt() if no event is pending. There is also no point in flushing event cache in EVERY loop iteration.
--- drivers/usb/dwc3/core.c | 7 ------- drivers/usb/dwc3/gadget.c | 15 +++++++++++++-- 2 files changed, 13 insertions(+), 9 deletions(-)
drivers/usb/dwc3/core.c +0 -7
@@ -844,18 +844,11 @@ void dwc3_uboot_exit(int index)void dwc3_uboot_handle_interrupt (int index) {struct dwc3 *dwc =NULL ; -int i; -struct dwc3_event_buffer *evt;list_for_each_entry (dwc, &dwc3_list, list) {if (dwc->index != index)continue ; -for (i =0 ; i < dwc->num_event_buffers; i++) { - evt = dwc->ev_buffs[i]; -dwc3_flush_cache ((int )evt->buf, evt->length); - } -dwc3_gadget_uboot_handle_interrupt (dwc);break ; }
drivers/usb/dwc3/gadget.c +13 -2
@@ -2680,6 +2680,17 @@ void dwc3_gadget_exit(struct dwc3 *dwc)*/ void dwc3_gadget_uboot_handle_interrupt (struct dwc3 *dwc) { -dwc3_interrupt (0 , dwc); -dwc3_thread_interrupt (0 , dwc); +int ret =dwc3_interrupt (0 , dwc); + +if (ret ==IRQ_WAKE_THREAD ) { +int i; +struct dwc3_event_buffer *evt; + +for (i =0 ; i < dwc->num_event_buffers; i++) { + evt = dwc->ev_buffs[i]; +dwc3_flush_cache ((int )evt->buf, evt->length); + } + +dwc3_thread_interrupt (0 , dwc); + } }
Signature · 1 line
2.0.0.rc2
PATCH 9/11 usb: dwc3: gadget: Set all ctrl fields of Transfer Control Blocks (TRB) to be LST
In reply to Lukasz MajewskiIt turned out that current dwc3 gadget code is preparing multiple TRBs for a transfer. Unfortunately, when multiple requests are in the same queue, only for the last one the LST (last) ctrl bit is set.
Due to that dwc3 HW executes all TRBs up till the one marked as last. Unfortunately, UMS requires call of ->complete callback after any send TRB. This is the reason for "hangs" in executing UMS.
This code simplifies this situation and set each TRB's ctrl field bit to be last (LST bit).
--- drivers/usb/dwc3/gadget.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-)
drivers/usb/dwc3/gadget.c +2 -13
@@ -789,7 +789,6 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)struct dwc3_request *req, *n;u32 trbs_left;u32 max; -unsigned int last_one =0 ;BUILD_BUG_ON_NOT_POWER_OF_2 (DWC3_TRB_NUM );
@@ -839,24 +838,14 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)list_for_each_entry_safe (req, n, &dep->request_list, list) {unsigned length;dma_addr_t dma; - last_one = false; dma = req->request.dma; length = req->request.length; - trbs_left--; - -if (!trbs_left) - last_one =1 ; - -/* Is this the last request? */ -if (list_is_last (&req->list, &dep->request_list)) - last_one =1 ;dwc3_prepare_one_trb (dep, req, dma, length, - last_one, false,0 ); + true, false,0 ); -if (last_one) -break ; +break ; } }
Signature · 1 line
2.0.0.rc2
PATCH 10/11 usb: dwc3: gadget: Set non EP0 max packet limit to 512B
In reply to Lukasz MajewskiCommit "drivers/dwc3: add a workaround for too small OUT requests" sets max packet for OUT requests when transfer is smaller.
Until this change the default maxpacket for non EP0 EPs was 1024. This is too much, since UMS LBA size is 512B
--- drivers/usb/dwc3/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/dwc3/gadget.c +1 -1
@@ -1603,7 +1603,7 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, }else {int ret; -usb_ep_set_maxpacket_limit (&dep->endpoint,1024 ); +usb_ep_set_maxpacket_limit (&dep->endpoint,512 ); dep->endpoint.max_streams =15 ; dep->endpoint.ops = &dwc3_gadget_ep_ops; list_add_tail(&dep->endpoint.ep_list,
Signature · 1 line
2.0.0.rc2
PATCH 11/11 usb: dwc3: Correct clean up code for requests
In reply to Lukasz MajewskiFor u-boot dwc3 driver the scatter gather list support has been removed from original linux code. It is correct, since we try to send one request at a time.
However, the cleanup left spurious break, which caused early exit from loop at dwc3_cleanup_done_reqs() function. As a result the dwc3_gadget_giveback() wasn't called and caused USB Mass Storage to hang.
This commit removes this problem and refactor the code to remove superfluous do { } while(1) loop.
Test HW: Odroid XU3 (with ./test/ums/ums_gadget_test.sh)
--- drivers/usb/dwc3/gadget.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-)
drivers/usb/dwc3/gadget.c +14 -24
@@ -1753,33 +1753,23 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,struct dwc3_request *req;struct dwc3_trb *trb;unsigned int slot; -int ret; - -do { - req =next_request (&dep->req_queued); -if (!req) { -WARN_ON_ONCE (1 ); -return 1 ; - } - - slot = req->start_slot; -if ((slot ==DWC3_TRB_NUM -1 ) && -usb_endpoint_xfer_isoc (dep->endpoint.desc)) - slot++; - slot %=DWC3_TRB_NUM ; - trb = &dep->trb_pool[slot]; -dwc3_flush_cache ((int )trb,sizeof (*trb)); - ret =__dwc3_cleanup_done_trbs (dwc, dep, req, trb, - event, status); -if (ret) -break ; + req =next_request (&dep->req_queued); +if (!req) { +WARN_ON_ONCE (1 ); +return 1 ; + } -dwc3_gadget_giveback (dep, req, status); + slot = req->start_slot; +if ((slot ==DWC3_TRB_NUM -1 ) && +usb_endpoint_xfer_isoc (dep->endpoint.desc)) + slot++; + slot %=DWC3_TRB_NUM ; + trb = &dep->trb_pool[slot]; -if (ret) -break ; - }while (1 ); +dwc3_flush_cache ((int )trb,sizeof (*trb)); +__dwc3_cleanup_done_trbs (dwc, dep, req, trb, event, status); +dwc3_gadget_giveback (dep, req, status);if (usb_endpoint_xfer_isoc (dep->endpoint.desc) &&list_empty (&dep->req_queued)) {
Signature · 1 line
2.0.0.rc2
cover usb: dwc3: Fixes and improvements for DWC3 driver
In reply to Lukasz MajewskiThis patch set should be applied on top of recent Kishon Vijay Abraham I work (v2) regarding providing dwc3 support to u-boot as well as clean up of the linux-compat header file.
For the whole patch set please refer to -dfu u-boot repo, branch (devel/dwc3_gadget):
http://git.denx.de/?p=u-boot/u-boot-dfu.git;a=shortlog;h=refs/heads/devel/dwc3_gadget
This patch set fixes things, so all Samsung boards compile after applying DWC3 support.
Tests and comments are welcome.
Inha Song (2):
usb: gadget: UMS: Invoke board specific USB cleanup interface
usb: gadget: thor: Invoke board specific USB cleanup interface
Joonyoung Shim (1):
usb: dwc3: make dwc3_set_mode to static
Marek Szyprowski (4):
usb: dwc3: add a workaround for too small OUT requests
usb: dwc3: gadget: add common endpoint configuration for dwc3 udc
driver
usb: dwc3: optimize interrupt loop
usb: gadget: thor: Claim EP after allocating it in thor gadget
?ukasz Majewski (7):
usb: board: samsung: Add default board_usb_cleanup() definition for
Exynos SoCs
usb: board: goni: Add default board_usb_cleanup() definition for Goni
board
usb: composite: Add .reset callback to usb_gadget_driver structure
usb: dwc3: Remove BIT(x) macro from DWC3's gadget code
usb: dwc3: gadget: Set all ctrl fields of Transfer Control Blocks
(TRB) to be LST
usb: dwc3: gadget: Set non EP0 max packet limit to 512B
usb: dwc3: Correct clean up code for requests
board/samsung/common/board.c | 6 +++ board/samsung/goni/goni.c | 5 +++ common/cmd_thordown.c | 1 + common/cmd_usb_mass_storage.c | 1 + drivers/usb/dwc3/core.c | 9 +---- drivers/usb/dwc3/core.h | 3 +- drivers/usb/dwc3/gadget.c | 80 +++++++++++++++++++-------------------- drivers/usb/gadget/composite.c | 1 + drivers/usb/gadget/epautoconf.c | 24 +++++++++++- drivers/usb/gadget/f_thor.c | 3 ++ drivers/usb/gadget/gadget_chips.h | 8 ++++ 11 files changed, 89 insertions(+), 52 deletions(-)
Signature · 1 line
2.0.0.rc2
PATCH 1/14 usb: board: samsung: Add default board_usb_cleanup() definition for Exynos SoCs
This definition is necessary for Exynos based boards to work properly.
--- board/samsung/common/board.c | 6 ++++++ 1 file changed, 6 insertions(+)
board/samsung/common/board.c +6 -0
@@ -25,6 +25,7 @@#include <asm/arch/sromc.h> #include <lcd.h> #include <samsung/misc.h> +#include <usb.h> DECLARE_GLOBAL_DATA_PTR ;
@@ -380,3 +381,8 @@ void reset_misc(void)dm_gpio_set_value (&gpio,1 ); } } + +int board_usb_cleanup (int index,enum usb_init_type init) +{ +return 0 ; +}
Signature · 1 line
2.0.0.rc2
PATCH 2/14 usb: board: goni: Add default board_usb_cleanup() definition for Goni board
In reply to Lukasz MajewskiThis definition is necessary for S5PC110 based GONI board to work properly.
--- board/samsung/goni/goni.c | 5 +++++ 1 file changed, 5 insertions(+)
board/samsung/goni/goni.c +5 -0
@@ -206,3 +206,8 @@ int misc_init_r(void) return 0; }#endif + +int board_usb_cleanup (int index,enum usb_init_type init) +{ +return 0 ; +}
Signature · 1 line
2.0.0.rc2
PATCH 3/14 usb: gadget: UMS: Invoke board specific USB cleanup interface
In reply to Lukasz MajewskiFrom: Inha Song <[email protected]>
This patch invokes board-specific USB cleanup (board_usb_cleanup) function in the mass storage gadget
--- common/cmd_usb_mass_storage.c | 1 + 1 file changed, 1 insertion(+)
common/cmd_usb_mass_storage.c +1 -0
@@ -154,6 +154,7 @@ int do_usb_mass_storage(cmd_tbl_t *cmdtp, int flag, } exit:g_dnl_unregister (); +board_usb_cleanup (controller_index,USB_INIT_DEVICE );return CMD_RET_SUCCESS ; }
Signature · 1 line
2.0.0.rc2
PATCH 4/14 usb: gadget: thor: Invoke board specific USB cleanup interface
In reply to Lukasz MajewskiFrom: Inha Song <[email protected]>
This patch invokes board-specific USB cleanup (board_usb_cleanup) function in the thor gadget.
--- common/cmd_thordown.c | 1 + 1 file changed, 1 insertion(+)
common/cmd_thordown.c +1 -0
@@ -56,6 +56,7 @@ int do_thor_down(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) exit:g_dnl_unregister (); +board_usb_cleanup (controller_index,USB_INIT_DEVICE ); done:dfu_free_entities ();
Signature · 1 line
2.0.0.rc2
PATCH 5/14 usb: composite: Add .reset callback to usb_gadget_driver structure
In reply to Lukasz MajewskiDWC3 UDC driver requires presence of .reset callback in a composite driver. This setting is similar to the one nowadays present in linux kernel.
--- drivers/usb/gadget/composite.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/gadget/composite.c +1 -0
@@ -1052,6 +1052,7 @@ static struct usb_gadget_driver composite_driver = { .unbind = composite_unbind, .setup = composite_setup, + .reset = composite_disconnect, .disconnect = composite_disconnect, .suspend = composite_suspend,
Signature · 1 line
2.0.0.rc2
PATCH 6/14 usb: dwc3: Remove BIT(x) macro from DWC3's gadget code
In reply to Lukasz MajewskiThe BIT() macro is used only in those places, so it is reasonable to replace it by a constant value.
--- drivers/usb/dwc3/core.h | 2 +- drivers/usb/dwc3/gadget.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/usb/dwc3/core.h +1 -1
@@ -392,7 +392,7 @@ struct dwc3_event_buffer {unsigned int count;unsigned int flags; -#define DWC3_EVENT_PENDING BIT(0) +#define DWC3_EVENT_PENDING (1UL << 0)dma_addr_t dma;
drivers/usb/dwc3/gadget.c +1 -1
@@ -2365,7 +2365,7 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,static void dwc3_gadget_hibernation_interrupt (struct dwc3 *dwc,unsigned int evtinfo) { -unsigned int is_ss = evtinfo &BIT (4 ); +unsigned int is_ss = evtinfo & (1UL <<4 );/** * WORKAROUND: DWC3 revison 2.20a with hibernation support
Signature · 1 line
2.0.0.rc2
PATCH 7/14 usb: dwc3: make dwc3_set_mode to static
In reply to Lukasz MajewskiFrom: Joonyoung Shim <[email protected]>
This commit makes the dwc3_set_mode() as static, to prevent collisions.
--- drivers/usb/dwc3/core.c | 2 +- drivers/usb/dwc3/core.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-)
drivers/usb/dwc3/core.c +1 -1
@@ -30,7 +30,7 @@static LIST_HEAD (dwc3_list);/* -------------------------------------------------------------------------- */ -void dwc3_set_mode (struct dwc3 *dwc,u32 mode) +static void dwc3_set_mode (struct dwc3 *dwc,u32 mode) {u32 reg;
drivers/usb/dwc3/core.h +0 -1
@@ -987,7 +987,6 @@ struct dwc3_gadget_ep_cmd_params {#define DWC3_HAS_OTG BIT(3)/* prototypes */ -void dwc3_set_mode (struct dwc3 *dwc,u32 mode);int dwc3_gadget_resize_tx_fifos (struct dwc3 *dwc);#ifdef CONFIG_USB_DWC3_HOST
Signature · 1 line
2.0.0.rc2
PATCH 8/14 usb: dwc3: add a workaround for too small OUT requests
In reply to Lukasz MajewskiFrom: Marek Szyprowski <[email protected]>
DWC3 hangs on OUT requests smaller than maxpacket size, so HACK the request length to be at least equal to maxpacket size.
--- drivers/usb/dwc3/gadget.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/usb/dwc3/gadget.c +8 -0
@@ -973,6 +973,14 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) req->epnum = dep->number;/* +* DWC3 hangs on OUT requests smaller than maxpacket size, +* so HACK the request length +*/ +if (dep->direction ==0 && + req->request.length < dep->endpoint.maxpacket) + req->request.length = dep->endpoint.maxpacket; + +/* * We only add to our list of requests now and * start consuming the list once we get XferNotReady * IRQ.
Signature · 1 line
2.0.0.rc2
PATCH 9/14 usb: dwc3: gadget: add common endpoint configuration for dwc3 udc driver
In reply to Lukasz MajewskiFrom: Marek Szyprowski <[email protected]>
This patch adds code to select standard, commonly used usb endpoint configuration (ep1in-bulk, ep2out-bulk, ep3in-int) to dwc3 driver. This ensures compatibility with old userspace and windows drivers, which expects hardcoded endpoint numbers.
--- drivers/usb/gadget/epautoconf.c | 24 +++++++++++++++++++++++- drivers/usb/gadget/gadget_chips.h | 8 ++++++++ 2 files changed, 31 insertions(+), 1 deletion(-)
drivers/usb/gadget/epautoconf.c +23 -1
@@ -220,7 +220,7 @@ struct usb_ep *usb_ep_autoconfig(struct usb_endpoint_descriptor *desc ) { -struct usb_ep *ep; +struct usb_ep *ep =NULL ;u8 type; type = desc->bmAttributes &USB_ENDPOINT_XFERTYPE_MASK ;
@@ -261,6 +261,28 @@ struct usb_ep *usb_ep_autoconfig( ep =find_ep (gadget,"ep1-bulk" );if (ep &&ep_matches (gadget, ep, desc))return ep; + }else if (gadget_is_dwc3 (gadget)) { +const char *name =NULL ; +/* +* First try standard, common configuration: ep1in-bulk, +* ep2out-bulk, ep3in-int to match other udc drivers to avoid +* confusion in already deployed software (endpoint numbers +* hardcoded in userspace software/drivers) +*/ +if ((desc->bEndpointAddress &USB_DIR_IN ) && + type ==USB_ENDPOINT_XFER_BULK ) + name ="ep1in" ; +else if ((desc->bEndpointAddress &USB_DIR_IN ) ==0 && + type ==USB_ENDPOINT_XFER_BULK ) + name ="ep2out" ; +else if ((desc->bEndpointAddress &USB_DIR_IN ) && + type ==USB_ENDPOINT_XFER_INT ) + name ="ep3in" ; + +if (name) + ep =find_ep (gadget, name); +if (ep &&ep_matches (gadget, ep, desc)) +return ep; }/* Second, look at endpoints until an unclaimed one looks usable */
drivers/usb/gadget/gadget_chips.h +8 -0
@@ -156,6 +156,14 @@#define gadget_is_fotg210 (g) 0#endif +#ifdef CONFIG_USB_DWC3_GADGET +#define gadget_is_dwc3 (g) (!strcmp("dwc3-gadget", (g)->name)) +#else +#define gadget_is_dwc3 (g) 0 +#endif + + +/* * CONFIG_USB_GADGET_SX2 * CONFIG_USB_GADGET_AU1X00
Signature · 1 line
2.0.0.rc2
PATCH 10/14 usb: dwc3: optimize interrupt loop
In reply to Lukasz MajewskiFrom: Marek Szyprowski <[email protected]>
There is no point in calling dwc3_thread_interrupt() if no event is pending. There is also no point in flushing event cache in EVERY loop iteration.
--- drivers/usb/dwc3/core.c | 7 ------- drivers/usb/dwc3/gadget.c | 15 +++++++++++++-- 2 files changed, 13 insertions(+), 9 deletions(-)
drivers/usb/dwc3/core.c +0 -7
@@ -766,18 +766,11 @@ void dwc3_uboot_exit(int index)void dwc3_uboot_handle_interrupt (int index) {struct dwc3 *dwc =NULL ; -int i; -struct dwc3_event_buffer *evt;list_for_each_entry (dwc, &dwc3_list, list) {if (dwc->index != index)continue ; -for (i =0 ; i < dwc->num_event_buffers; i++) { - evt = dwc->ev_buffs[i]; -dwc3_flush_cache ((int )evt->buf, evt->length); - } -dwc3_gadget_uboot_handle_interrupt (dwc);break ; }
drivers/usb/dwc3/gadget.c +13 -2
@@ -2681,6 +2681,17 @@ void dwc3_gadget_exit(struct dwc3 *dwc)*/ void dwc3_gadget_uboot_handle_interrupt (struct dwc3 *dwc) { -dwc3_interrupt (0 , dwc); -dwc3_thread_interrupt (0 , dwc); +int ret =dwc3_interrupt (0 , dwc); + +if (ret ==IRQ_WAKE_THREAD ) { +int i; +struct dwc3_event_buffer *evt; + +for (i =0 ; i < dwc->num_event_buffers; i++) { + evt = dwc->ev_buffs[i]; +dwc3_flush_cache ((int )evt->buf, evt->length); + } + +dwc3_thread_interrupt (0 , dwc); + } }
Signature · 1 line
2.0.0.rc2
PATCH 11/14 usb: dwc3: gadget: Set all ctrl fields of Transfer Control Blocks (TRB) to be LST
In reply to Lukasz MajewskiIt turned out that current dwc3 gadget code is preparing multiple TRBs for a transfer. Unfortunately, when multiple requests are in the same queue, only for the last one the LST (last) ctrl bit is set.
Due to that dwc3 HW executes all TRBs up till the one marked as last. Unfortunately, UMS requires call of ->complete callback after any send TRB. This is the reason for "hangs" in executing UMS.
This code simplifies this situation and set each TRB's ctrl field bit to be last (LST bit).
--- drivers/usb/dwc3/gadget.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-)
drivers/usb/dwc3/gadget.c +2 -13
@@ -787,7 +787,6 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)struct dwc3_request *req, *n;u32 trbs_left;u32 max; -unsigned int last_one =0 ;BUILD_BUG_ON_NOT_POWER_OF_2 (DWC3_TRB_NUM );
@@ -837,24 +836,14 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)list_for_each_entry_safe (req, n, &dep->request_list, list) {unsigned length;dma_addr_t dma; - last_one = false; dma = req->request.dma; length = req->request.length; - trbs_left--; - -if (!trbs_left) - last_one =1 ; - -/* Is this the last request? */ -if (list_is_last (&req->list, &dep->request_list)) - last_one =1 ;dwc3_prepare_one_trb (dep, req, dma, length, - last_one, false,0 ); + true, false,0 ); -if (last_one) -break ; +break ; } }
Signature · 1 line
2.0.0.rc2
PATCH 12/14 usb: dwc3: gadget: Set non EP0 max packet limit to 512B
In reply to Lukasz MajewskiCommit "drivers/dwc3: add a workaround for too small OUT requests" sets max packet for OUT requests when transfer is smaller.
Until this change the default maxpacket for non EP0 EPs was 1024. This is too much, since UMS LBA size is 512B
--- drivers/usb/dwc3/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/dwc3/gadget.c +1 -1
@@ -1603,7 +1603,7 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, }else {int ret; -usb_ep_set_maxpacket_limit (&dep->endpoint,1024 ); +usb_ep_set_maxpacket_limit (&dep->endpoint,512 ); dep->endpoint.max_streams =15 ; dep->endpoint.ops = &dwc3_gadget_ep_ops; list_add_tail(&dep->endpoint.ep_list,
Signature · 1 line
2.0.0.rc2
PATCH 13/14 usb: dwc3: Correct clean up code for requests
In reply to Lukasz MajewskiFor u-boot dwc3 driver the scatter gather list support has been removed from original linux code. It is correct, since we try to send one request at a time.
However, the cleanup left spurious break, which caused early exit from loop at dwc3_cleanup_done_reqs() function. As a result the dwc3_gadget_giveback() wasn't called and caused USB Mass Storage to hang.
This commit removes this problem and refactor the code to remove superfluous do { } while(1) loop.
Test HW: Odroid XU3 (with ./test/ums/ums_gadget_test.sh)
--- drivers/usb/dwc3/gadget.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-)
drivers/usb/dwc3/gadget.c +14 -24
@@ -1753,33 +1753,23 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,struct dwc3_request *req;struct dwc3_trb *trb;unsigned int slot; -int ret; - -do { - req =next_request (&dep->req_queued); -if (!req) { -WARN_ON_ONCE (1 ); -return 1 ; - } - - slot = req->start_slot; -if ((slot ==DWC3_TRB_NUM -1 ) && -usb_endpoint_xfer_isoc (dep->endpoint.desc)) - slot++; - slot %=DWC3_TRB_NUM ; - trb = &dep->trb_pool[slot]; -dwc3_flush_cache ((int )trb,sizeof (*trb)); - ret =__dwc3_cleanup_done_trbs (dwc, dep, req, trb, - event, status); -if (ret) -break ; + req =next_request (&dep->req_queued); +if (!req) { +WARN_ON_ONCE (1 ); +return 1 ; + } -dwc3_gadget_giveback (dep, req, status); + slot = req->start_slot; +if ((slot ==DWC3_TRB_NUM -1 ) && +usb_endpoint_xfer_isoc (dep->endpoint.desc)) + slot++; + slot %=DWC3_TRB_NUM ; + trb = &dep->trb_pool[slot]; -if (ret) -break ; - }while (1 ); +dwc3_flush_cache ((int )trb,sizeof (*trb)); +__dwc3_cleanup_done_trbs (dwc, dep, req, trb, event, status); +dwc3_gadget_giveback (dep, req, status);if (usb_endpoint_xfer_isoc (dep->endpoint.desc) &&list_empty (&dep->req_queued)) {
Signature · 1 line
2.0.0.rc2
PATCH 14/14 usb: gadget: thor: Claim EP after allocating it in thor gadget
In reply to Lukasz MajewskiFrom: Marek Szyprowski <[email protected]>
Storing thor device struct as an EP private data. It is necessary for DWC3 operation.
--- drivers/usb/gadget/f_thor.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/usb/gadget/f_thor.c +3 -0
@@ -806,6 +806,7 @@ static int thor_func_bind(struct usb_configuration *c, struct usb_function *f) } dev->in_ep = ep;/* Store IN EP for enabling @ setup */ + ep->driver_data = dev; ep =usb_ep_autoconfig (gadget, &fs_out_desc);if (!ep) {
@@ -818,6 +819,7 @@ static int thor_func_bind(struct usb_configuration *c, struct usb_function *f) fs_out_desc.bEndpointAddress; dev->out_ep = ep;/* Store OUT EP for enabling @ setup */ + ep->driver_data = dev; ep =usb_ep_autoconfig (gadget, &fs_int_desc);if (!ep) {
@@ -826,6 +828,7 @@ static int thor_func_bind(struct usb_configuration *c, struct usb_function *f) } dev->int_ep = ep; + ep->driver_data = dev;if (gadget_is_dualspeed (gadget)) { hs_int_desc.bEndpointAddress =
Signature · 1 line
2.0.0.rc2
cover usb: dwc3: Fixes and improvements for DWC3 driver
In reply to Lukasz MajewskiQuoted 11 lines · Lukasz Majewski
This patch set should be applied on top of recent Kishon Vijay Abraham I work (v2) regarding providing dwc3 support to u-boot as well as clean up of the linux-compat header file.
For the whole patch set please refer to -dfu u-boot repo, branch (devel/dwc3_gadget):
http://git.denx.de/?p=u-boot/u-boot-dfu.git;a=shortlog;h=refs/heads/devel/dwc3_gadgetThis patch set fixes things, so all Samsung boards compile after applying DWC3 support.
I picked this all into the topic/dwc3 branch and replaced the old patches. Please let me know if there's something broken.
Thanks!
Best regards,
Marek Vasut