Re: [PATCH 5/7] usb: gadget: fsl_udc: postpone freeing current dTD
On Fri, 2012-10-19 at 13:44 +0300, Felipe Balbi wrote: I thought about this too but wasn't able to use chipidea with MXC_EHCI_INTERNAL_PHY as it's called in fsl_udc. that's a matter of writing the PHY driver, right ;-) It has nothing to do with chipidea, actually :-) Okay, I'll do. But then we should purge the old buggy fsl_udc. Thanks -- Christoph ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 0/7] update USB gadget driver fsl-usb2-udc
This series updates USB gadget driver fsl-usb2-udc. Christoph Fritz (7): usb: gadget: fsl_udc: simplify driver init usb: gadget: fsl_udc: protect fsl_pullup() with spin_lock usb: gadget: fsl_udc: convert to new ulc style usb: gadget: fsl_udc: drop ARCH dependency usb: gadget: fsl_udc: postpone freeing current dTD usb: gadget: fsl_udc: purge global pointer usb_sys_regs usb: gadget: fsl_udc: purge global pointer dr_regs drivers/usb/gadget/fsl_udc_core.c | 755 - drivers/usb/gadget/fsl_usb2_udc.h |4 + 2 files changed, 322 insertions(+), 437 deletions(-) -- 1.7.2.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/7] usb: gadget: fsl_udc: simplify driver init
To initialize this driver use 'module_platform_driver' instead of '__init' and '__exit'. Signed-off-by: Christoph Fritz chf.fr...@googlemail.com --- drivers/usb/gadget/fsl_udc_core.c | 37 +++-- 1 files changed, 11 insertions(+), 26 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 6ae70cb..340451d 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -49,13 +49,14 @@ #include fsl_usb2_udc.h +#defineDRIVER_NAME fsl-usb2-udc #defineDRIVER_DESC Freescale High-Speed USB SOC Device Controller driver #defineDRIVER_AUTHOR Li Yang/Jiang Bo #defineDRIVER_VERSION Apr 20, 2007 #defineDMA_ADDR_INVALID(~(dma_addr_t)0) -static const char driver_name[] = fsl-usb2-udc; +static const char driver_name[] = DRIVER_NAME; static const char driver_desc[] = DRIVER_DESC; static struct usb_dr_device *dr_regs; @@ -2761,35 +2762,19 @@ static int fsl_udc_otg_resume(struct device *dev) Register entry point for the peripheral controller driver --*/ -static struct platform_driver udc_driver = { - .remove = __exit_p(fsl_udc_remove), - /* these suspend and resume are not usb suspend and resume */ - .suspend = fsl_udc_suspend, - .resume = fsl_udc_resume, - .driver = { - .name = (char *)driver_name, - .owner = THIS_MODULE, - /* udc suspend/resume called from OTG driver */ +static struct platform_driver fsl_udc_driver = { + .probe = fsl_udc_probe, + .remove = __devexit_p(fsl_udc_remove), + .suspend= fsl_udc_suspend, + .resume = fsl_udc_resume, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, .suspend = fsl_udc_otg_suspend, .resume = fsl_udc_otg_resume, }, }; - -static int __init udc_init(void) -{ - printk(KERN_INFO %s (%s)\n, driver_desc, DRIVER_VERSION); - return platform_driver_probe(udc_driver, fsl_udc_probe); -} - -module_init(udc_init); - -static void __exit udc_exit(void) -{ - platform_driver_unregister(udc_driver); - printk(KERN_WARNING %s unregistered\n, driver_desc); -} - -module_exit(udc_exit); +module_platform_driver(fsl_udc_driver); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR(DRIVER_AUTHOR); -- 1.7.2.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 2/7] usb: gadget: fsl_udc: protect fsl_pullup() with spin_lock
This patch reworks fsl_pullup() against the background of switching over to udc_start()/udc_stop() style: Protect function fsl_pullup() with a spin_lock. Also set vbus_active as default to true. This prevents disabling USB controller if there is no driver support for an external transceiver (or GPIO) that detects a VBUS power session starting. Signed-off-by: Christoph Fritz chf.fr...@googlemail.com --- drivers/usb/gadget/fsl_udc_core.c |4 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 340451d..0a0d6a6 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1242,8 +1242,10 @@ static int fsl_vbus_draw(struct usb_gadget *gadget, unsigned mA) static int fsl_pullup(struct usb_gadget *gadget, int is_on) { struct fsl_udc *udc; + unsigned long flags; udc = container_of(gadget, struct fsl_udc, gadget); + spin_lock_irqsave(udc-lock, flags); udc-softconnect = (is_on != 0); if (can_pullup(udc)) fsl_writel((fsl_readl(dr_regs-usbcmd) | USB_CMD_RUN_STOP), @@ -1251,6 +1253,7 @@ static int fsl_pullup(struct usb_gadget *gadget, int is_on) else fsl_writel((fsl_readl(dr_regs-usbcmd) ~USB_CMD_RUN_STOP), dr_regs-usbcmd); + spin_unlock_irqrestore(udc-lock, flags); return 0; } @@ -2557,6 +2560,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) INIT_LIST_HEAD(udc_controller-gadget.ep_list); udc_controller-gadget.speed = USB_SPEED_UNKNOWN; udc_controller-gadget.name = driver_name; + udc-vbus_active = true; /* Setup gadget.dev and register with kernel */ dev_set_name(udc_controller-gadget.dev, gadget); -- 1.7.2.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 3/7] usb: gadget: fsl_udc: convert to new ulc style
Convert to new UDC style registration and remove global 'udc_controller' pointer. Signed-off-by: Christoph Fritz chf.fr...@googlemail.com --- drivers/usb/gadget/fsl_udc_core.c | 289 + 1 files changed, 131 insertions(+), 158 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 0a0d6a6..d113f39 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -63,9 +63,6 @@ static struct usb_dr_device *dr_regs; static struct usb_sys_interface *usb_sys_regs; -/* it is initialized in probe() */ -static struct fsl_udc *udc_controller = NULL; - static const struct usb_endpoint_descriptor fsl_ep0_desc = { .bLength = USB_DT_ENDPOINT_SIZE, @@ -783,12 +780,14 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) } /* Fill in the dTD structure + * @udc: driver private data * @req: request that the transfer belongs to * @length: return actually data length of the dTD * @dma: return dma address of the dTD * @is_last: return flag if it is the last dTD of the request * return: pointer to the built dTD */ -static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length, +static struct ep_td_struct *fsl_build_dtd(struct fsl_udc *udc, + struct fsl_req *req, unsigned *length, dma_addr_t *dma, int *is_last, gfp_t gfp_flags) { u32 swap_temp; @@ -798,7 +797,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length, *length = min(req-req.length - req-req.actual, (unsigned)EP_MAX_LENGTH_TRANSFER); - dtd = dma_pool_alloc(udc_controller-td_pool, gfp_flags, dma); + dtd = dma_pool_alloc(udc-td_pool, gfp_flags, dma); if (dtd == NULL) return dtd; @@ -848,7 +847,8 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length, } /* Generate dtd chain for a request */ -static int fsl_req_to_dtd(struct fsl_req *req, gfp_t gfp_flags) +static int fsl_req_to_dtd(struct fsl_udc *udc, struct fsl_req *req, + gfp_t gfp_flags) { unsignedcount; int is_last; @@ -857,7 +857,8 @@ static int fsl_req_to_dtd(struct fsl_req *req, gfp_t gfp_flags) dma_addr_t dma; do { - dtd = fsl_build_dtd(req, count, dma, is_last, gfp_flags); + dtd = fsl_build_dtd(udc, req, count, dma, is_last, + gfp_flags); if (dtd == NULL) return -ENOMEM; @@ -932,7 +933,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) req-dtd_count = 0; /* build dtds and push them to device queue */ - if (!fsl_req_to_dtd(req, gfp_flags)) { + if (!fsl_req_to_dtd(udc, req, gfp_flags)) { spin_lock_irqsave(udc-lock, flags); fsl_queue_td(ep, req); } else { @@ -1258,9 +1259,10 @@ static int fsl_pullup(struct usb_gadget *gadget, int is_on) return 0; } -static int fsl_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)); -static int fsl_stop(struct usb_gadget_driver *driver); +static int fsl_udc_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); +static int fsl_udc_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); /* defined in gadget.h */ static struct usb_gadget_ops fsl_gadget_ops = { .get_frame = fsl_get_frame, @@ -1269,8 +1271,8 @@ static struct usb_gadget_ops fsl_gadget_ops = { .vbus_session = fsl_vbus_session, .vbus_draw = fsl_vbus_draw, .pullup = fsl_pullup, - .start = fsl_start, - .stop = fsl_stop, + .udc_start = fsl_udc_start, + .udc_stop = fsl_udc_stop, }; /* Set protocol stall on ep0, protocol stall will automatically be cleared @@ -1314,7 +1316,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction) ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); req-mapped = 1; - if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0) + if (fsl_req_to_dtd(udc, req, GFP_ATOMIC) == 0) fsl_queue_td(ep, req); else return -ENOMEM; @@ -1398,7 +1400,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, req-mapped = 1; /* prime the data phase */ - if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0)) + if ((fsl_req_to_dtd(udc, req, GFP_ATOMIC) == 0)) fsl_queue_td(ep, req); else/* no mem */ goto stall; @@ -1422,7 +1424,7 @@ static void setup_received_irq(struct fsl_udc *udc, udc_reset_ep_queue(udc, 0); - /* We process some stardard setup requests here */ + /* We process some standard setup
[PATCH 4/7] usb: gadget: fsl_udc: drop ARCH dependency
Drop the big-/little-endian helpers and make use of generic writel()/readl() routines. Signed-off-by: Christoph Fritz chf.fr...@googlemail.com --- drivers/usb/gadget/fsl_udc_core.c | 331 + 1 files changed, 118 insertions(+), 213 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index d113f39..53df9c0 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -20,32 +20,14 @@ #undef VERBOSE #include linux/module.h -#include linux/kernel.h -#include linux/ioport.h -#include linux/types.h -#include linux/errno.h -#include linux/err.h -#include linux/slab.h -#include linux/init.h -#include linux/list.h #include linux/interrupt.h #include linux/proc_fs.h -#include linux/mm.h -#include linux/moduleparam.h -#include linux/device.h -#include linux/usb/ch9.h #include linux/usb/gadget.h #include linux/usb/otg.h #include linux/dma-mapping.h #include linux/platform_device.h #include linux/fsl_devices.h #include linux/dmapool.h -#include linux/delay.h - -#include asm/byteorder.h -#include asm/io.h -#include asm/unaligned.h -#include asm/dma.h #include fsl_usb2_udc.h @@ -74,78 +56,6 @@ fsl_ep0_desc = { static void fsl_ep_fifo_flush(struct usb_ep *_ep); -#ifdef CONFIG_PPC32 -/* - * On some SoCs, the USB controller registers can be big or little endian, - * depending on the version of the chip. In order to be able to run the - * same kernel binary on 2 different versions of an SoC, the BE/LE decision - * must be made at run time. _fsl_readl and fsl_writel are pointers to the - * BE or LE readl() and writel() functions, and fsl_readl() and fsl_writel() - * call through those pointers. Platform code for SoCs that have BE USB - * registers should set pdata-big_endian_mmio flag. - * - * This also applies to controller-to-cpu accessors for the USB descriptors, - * since their endianness is also SoC dependant. Platform code for SoCs that - * have BE USB descriptors should set pdata-big_endian_desc flag. - */ -static u32 _fsl_readl_be(const unsigned __iomem *p) -{ - return in_be32(p); -} - -static u32 _fsl_readl_le(const unsigned __iomem *p) -{ - return in_le32(p); -} - -static void _fsl_writel_be(u32 v, unsigned __iomem *p) -{ - out_be32(p, v); -} - -static void _fsl_writel_le(u32 v, unsigned __iomem *p) -{ - out_le32(p, v); -} - -static u32 (*_fsl_readl)(const unsigned __iomem *p); -static void (*_fsl_writel)(u32 v, unsigned __iomem *p); - -#define fsl_readl(p) (*_fsl_readl)((p)) -#define fsl_writel(v, p) (*_fsl_writel)((v), (p)) - -static inline void fsl_set_accessors(struct fsl_usb2_platform_data *pdata) -{ - if (pdata-big_endian_mmio) { - _fsl_readl = _fsl_readl_be; - _fsl_writel = _fsl_writel_be; - } else { - _fsl_readl = _fsl_readl_le; - _fsl_writel = _fsl_writel_le; - } -} - -static inline u32 cpu_to_hc32(const u32 x) -{ - return udc_controller-pdata-big_endian_desc - ? (__force u32)cpu_to_be32(x) - : (__force u32)cpu_to_le32(x); -} - -static inline u32 hc32_to_cpu(const u32 x) -{ - return udc_controller-pdata-big_endian_desc - ? be32_to_cpu((__force __be32)x) - : le32_to_cpu((__force __le32)x); -} -#else /* !CONFIG_PPC32 */ -static inline void fsl_set_accessors(struct fsl_usb2_platform_data *pdata) {} - -#define fsl_readl(addr)readl(addr) -#define fsl_writel(val32, addr) writel(val32, addr) -#define cpu_to_hc32(x) cpu_to_le32(x) -#define hc32_to_cpu(x) le32_to_cpu(x) -#endif /* CONFIG_PPC32 */ / * Internal Used Function @@ -248,7 +158,7 @@ static int dr_controller_setup(struct fsl_udc *udc) #define FSL_UDC_RESET_TIMEOUT 1000 /* Config PHY interface */ - portctrl = fsl_readl(dr_regs-portsc1); + portctrl = readl(dr_regs-portsc1); portctrl = ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH); switch (udc-phy_mode) { case FSL_USB2_PHY_ULPI: @@ -286,20 +196,20 @@ static int dr_controller_setup(struct fsl_udc *udc) default: return -EINVAL; } - fsl_writel(portctrl, dr_regs-portsc1); + writel(portctrl, dr_regs-portsc1); /* Stop and reset the usb controller */ - tmp = fsl_readl(dr_regs-usbcmd); + tmp = readl(dr_regs-usbcmd); tmp = ~USB_CMD_RUN_STOP; - fsl_writel(tmp, dr_regs-usbcmd); + writel(tmp, dr_regs-usbcmd); - tmp = fsl_readl(dr_regs-usbcmd); + tmp = readl(dr_regs-usbcmd); tmp |= USB_CMD_CTRL_RESET; - fsl_writel(tmp, dr_regs-usbcmd); + writel(tmp, dr_regs-usbcmd); /* Wait for reset to complete */ timeout = jiffies + FSL_UDC_RESET_TIMEOUT; - while (fsl_readl(dr_regs-usbcmd) USB_CMD_CTRL_RESET) { + while (readl
[PATCH 5/7] usb: gadget: fsl_udc: postpone freeing current dTD
USB controller may access a wrong address for the dTD (endpoint transfer descriptor) and then hang. This happens a lot when doing tests with g_ether module and iperf, a tool for measuring maximum TCP and UDP bandwidth. This hardware bug is explained in detail by errata number 2858 for i.MX23: http://cache.freescale.com/files/dsp/doc/errata/IMX23CE.pdf All (?) SOCs with an IP from chipidea suffer from this problem. mv_udc_core fixes this bug by commit daec765. There still may be unfixed drivers. Signed-off-by: Christoph Fritz chf.fr...@googlemail.com Signed-off-by: Christian Hemp c.h...@phytec.de Reviewed-by: Peter Chen peter.c...@freescale.com --- drivers/usb/gadget/fsl_udc_core.c | 12 +++- drivers/usb/gadget/fsl_usb2_udc.h |2 ++ 2 files changed, 13 insertions(+), 1 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 53df9c0..deaab62 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -88,8 +88,13 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status) curr_td = next_td; if (j != req-dtd_count - 1) { next_td = curr_td-next_td_virt; + dma_pool_free(udc-td_pool, curr_td, curr_td-td_dma); + } else { + if (udc-last_free_td != NULL) + dma_pool_free(udc-td_pool, udc-last_free_td, + udc-last_free_td-td_dma); + udc-last_free_td = curr_td; } - dma_pool_free(udc-td_pool, curr_td, curr_td-td_dma); } if (req-mapped) { @@ -2439,6 +2444,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) udc-gadget.speed = USB_SPEED_UNKNOWN; udc-gadget.name = driver_name; udc-vbus_active = true; + udc-last_free_td = NULL; /* Setup gadget.dev and register with kernel */ dev_set_name(udc-gadget.dev, gadget); @@ -2533,6 +2539,10 @@ static int __exit fsl_udc_remove(struct platform_device *pdev) kfree(udc-status_req); kfree(udc-eps); + if (udc-last_free_td != NULL) + dma_pool_free(udc-td_pool, udc-last_free_td, + udc-last_free_td-td_dma); + dma_pool_destroy(udc-td_pool); free_irq(udc-irq, udc); iounmap(dr_regs); diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index f61a967..a0123ae 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -497,6 +497,8 @@ struct fsl_udc { size_t ep_qh_size; /* size after alignment adjustment*/ dma_addr_t ep_qh_dma; /* dma address of QH */ + struct ep_td_struct *last_free_td; + u32 max_pipes; /* Device max pipes */ u32 bus_reset; /* Device is bus resetting */ u32 resume_state; /* USB state to resume */ -- 1.7.2.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 6/7] usb: gadget: fsl_udc: purge global pointer usb_sys_regs
Move global driver pointer usb_sys_regs to private struct fsl_udc. Signed-off-by: Christoph Fritz chf.fr...@googlemail.com Reviewed-by: Teresa Gamez t.ga...@phytec.de --- drivers/usb/gadget/fsl_udc_core.c | 26 -- drivers/usb/gadget/fsl_usb2_udc.h |1 + 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index deaab62..35ebcd4 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -43,8 +43,6 @@ static const char driver_desc[] = DRIVER_DESC; static struct usb_dr_device *dr_regs; -static struct usb_sys_interface *usb_sys_regs; - static const struct usb_endpoint_descriptor fsl_ep0_desc = { .bLength = USB_DT_ENDPOINT_SIZE, @@ -170,10 +168,10 @@ static int dr_controller_setup(struct fsl_udc *udc) if (udc-pdata-have_sysif_regs) { if (udc-pdata-controller_ver) { /* controller version 1.6 or above */ - ctrl = __raw_readl(usb_sys_regs-control); + ctrl = readl(udc-usb_sys_regs-control); ctrl = ~USB_CTRL_UTMI_PHY_EN; ctrl |= USB_CTRL_USB_EN; - __raw_writel(ctrl, usb_sys_regs-control); + writel(ctrl, udc-usb_sys_regs-control); } } portctrl |= PORTSCX_PTS_ULPI; @@ -185,10 +183,10 @@ static int dr_controller_setup(struct fsl_udc *udc) if (udc-pdata-have_sysif_regs) { if (udc-pdata-controller_ver) { /* controller version 1.6 or above */ - ctrl = __raw_readl(usb_sys_regs-control); + ctrl = readl(udc-usb_sys_regs-control); ctrl |= (USB_CTRL_UTMI_PHY_EN | USB_CTRL_USB_EN); - __raw_writel(ctrl, usb_sys_regs-control); + writel(ctrl, udc-usb_sys_regs-control); mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to become stable - 10ms*/ } @@ -254,9 +252,9 @@ static int dr_controller_setup(struct fsl_udc *udc) /* Config control enable i/o output, cpu endian register */ #ifndef CONFIG_ARCH_MXC if (udc-pdata-have_sysif_regs) { - ctrl = __raw_readl(usb_sys_regs-control); + ctrl = readl(udc-usb_sys_regs-control); ctrl |= USB_CTRL_IOENB; - __raw_writel(ctrl, usb_sys_regs-control); + writel(ctrl, udc-usb_sys_regs-control); } #endif @@ -267,9 +265,9 @@ static int dr_controller_setup(struct fsl_udc *udc) if (udc-pdata-have_sysif_regs) { /* Setup Snooping for all the 4GB space */ tmp = SNOOP_SIZE_2GB; /* starts from 0x0, size 2G */ - __raw_writel(tmp, usb_sys_regs-snoop1); + writel(tmp, udc-usb_sys_regs-snoop1); tmp |= 0x8000; /* starts from 0x800, size 2G */ - __raw_writel(tmp, usb_sys_regs-snoop2); + writel(tmp, udc-usb_sys_regs-snoop2); } #endif @@ -326,7 +324,7 @@ static void dr_controller_stop(struct fsl_udc *udc) udc-stopped = 1; /* disable IO output */ -/* usb_sys_regs-control = 0; */ +/* udc-usb_sys_regs-control = 0; */ /* set controller to Stop */ tmp = readl(dr_regs-usbcmd); @@ -2130,12 +2128,12 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, #ifndef CONFIG_ARCH_MXC if (udc-pdata-have_sysif_regs) { - tmp_reg = usb_sys_regs-snoop1; + tmp_reg = udc-usb_sys_regs-snoop1; t = scnprintf(next, size, Snoop1 Reg : = [0x%x]\n\n, tmp_reg); size -= t; next += t; - tmp_reg = usb_sys_regs-control; + tmp_reg = udc-usb_sys_regs-control; t = scnprintf(next, size, General Control Reg : = [0x%x]\n\n, tmp_reg); size -= t; @@ -2388,7 +2386,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) #ifndef CONFIG_ARCH_MXC if (pdata-have_sysif_regs) - usb_sys_regs = (void *)dr_regs + USB_DR_SYS_OFFSET; + udc-usb_sys_regs = (void *)dr_regs + USB_DR_SYS_OFFSET; #endif /* Initialize USB clocks */ diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index a0123ae..0d888f4 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -498,6 +498,7 @@ struct fsl_udc { dma_addr_t ep_qh_dma; /* dma
[PATCH 7/7] usb: gadget: fsl_udc: purge global pointer dr_regs
Move global driver pointer dr_regs to private struct fsl_udc. Signed-off-by: Christoph Fritz chf.fr...@googlemail.com --- drivers/usb/gadget/fsl_udc_core.c | 252 +++-- drivers/usb/gadget/fsl_usb2_udc.h |1 + 2 files changed, 130 insertions(+), 123 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 35ebcd4..f9c4eb9 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -41,8 +41,6 @@ static const char driver_name[] = DRIVER_NAME; static const char driver_desc[] = DRIVER_DESC; -static struct usb_dr_device *dr_regs; - static const struct usb_endpoint_descriptor fsl_ep0_desc = { .bLength = USB_DT_ENDPOINT_SIZE, @@ -161,7 +159,7 @@ static int dr_controller_setup(struct fsl_udc *udc) #define FSL_UDC_RESET_TIMEOUT 1000 /* Config PHY interface */ - portctrl = readl(dr_regs-portsc1); + portctrl = readl(udc-dr_regs-portsc1); portctrl = ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH); switch (udc-phy_mode) { case FSL_USB2_PHY_ULPI: @@ -199,20 +197,20 @@ static int dr_controller_setup(struct fsl_udc *udc) default: return -EINVAL; } - writel(portctrl, dr_regs-portsc1); + writel(portctrl, udc-dr_regs-portsc1); /* Stop and reset the usb controller */ - tmp = readl(dr_regs-usbcmd); + tmp = readl(udc-dr_regs-usbcmd); tmp = ~USB_CMD_RUN_STOP; - writel(tmp, dr_regs-usbcmd); + writel(tmp, udc-dr_regs-usbcmd); - tmp = readl(dr_regs-usbcmd); + tmp = readl(udc-dr_regs-usbcmd); tmp |= USB_CMD_CTRL_RESET; - writel(tmp, dr_regs-usbcmd); + writel(tmp, udc-dr_regs-usbcmd); /* Wait for reset to complete */ timeout = jiffies + FSL_UDC_RESET_TIMEOUT; - while (readl(dr_regs-usbcmd) USB_CMD_CTRL_RESET) { + while (readl(udc-dr_regs-usbcmd) USB_CMD_CTRL_RESET) { if (time_after(jiffies, timeout)) { ERR(udc reset timeout!\n); return -ETIMEDOUT; @@ -221,33 +219,33 @@ static int dr_controller_setup(struct fsl_udc *udc) } /* Set the controller as device mode */ - tmp = readl(dr_regs-usbmode); + tmp = readl(udc-dr_regs-usbmode); tmp = ~USB_MODE_CTRL_MODE_MASK;/* clear mode bits */ tmp |= USB_MODE_CTRL_MODE_DEVICE; /* Disable Setup Lockout */ tmp |= USB_MODE_SETUP_LOCK_OFF; if (udc-pdata-es) tmp |= USB_MODE_ES; - writel(tmp, dr_regs-usbmode); + writel(tmp, udc-dr_regs-usbmode); /* Clear the setup status */ - writel(0, dr_regs-usbsts); + writel(0, udc-dr_regs-usbsts); tmp = udc-ep_qh_dma; tmp = USB_EP_LIST_ADDRESS_MASK; - writel(tmp, dr_regs-endpointlistaddr); + writel(tmp, udc-dr_regs-endpointlistaddr); VDBG(vir[qh_base] is %p phy[qh_base] is 0x%8x reg is 0x%8x, udc-ep_qh, (int)tmp, - readl(dr_regs-endpointlistaddr)); + readl(udc-dr_regs-endpointlistaddr)); - max_no_of_ep = (0x001F readl(dr_regs-dccparams)); + max_no_of_ep = (0x001F readl(udc-dr_regs-dccparams)); for (ep_num = 1; ep_num max_no_of_ep; ep_num++) { - tmp = readl(dr_regs-endptctrl[ep_num]); + tmp = readl(udc-dr_regs-endptctrl[ep_num]); tmp = ~(EPCTRL_TX_TYPE | EPCTRL_RX_TYPE); tmp |= (EPCTRL_EP_TYPE_BULK EPCTRL_TX_EP_TYPE_SHIFT) | (EPCTRL_EP_TYPE_BULK EPCTRL_RX_EP_TYPE_SHIFT); - writel(tmp, dr_regs-endptctrl[ep_num]); + writel(tmp, udc-dr_regs-endptctrl[ep_num]); } /* Config control enable i/o output, cpu endian register */ #ifndef CONFIG_ARCH_MXC @@ -284,20 +282,20 @@ static void dr_controller_run(struct fsl_udc *udc) | USB_INTR_PTC_DETECT_EN | USB_INTR_RESET_EN | USB_INTR_DEVICE_SUSPEND | USB_INTR_SYS_ERR_EN; - writel(temp, dr_regs-usbintr); + writel(temp, udc-dr_regs-usbintr); /* Clear stopped bit */ udc-stopped = 0; /* Set the controller as device mode */ - temp = readl(dr_regs-usbmode); + temp = readl(udc-dr_regs-usbmode); temp |= USB_MODE_CTRL_MODE_DEVICE; - writel(temp, dr_regs-usbmode); + writel(temp, udc-dr_regs-usbmode); /* Set controller to Run */ - temp = readl(dr_regs-usbcmd); + temp = readl(udc-dr_regs-usbcmd); temp |= USB_CMD_RUN_STOP; - writel(temp, dr_regs-usbcmd); + writel(temp, udc-dr_regs-usbcmd); } static void dr_controller_stop(struct fsl_udc *udc) @@ -311,14 +309,14 @@ static void dr_controller_stop(struct fsl_udc *udc) * ehci driver */ if (udc-gadget.is_otg) { - if (!(readl(dr_regs-otgsc
Re: [PATCH 5/7] usb: gadget: fsl_udc: postpone freeing current dTD
On Fri, 2012-10-19 at 13:30 +0300, Felipe Balbi wrote: On Fri, Oct 19, 2012 at 12:24:43PM +0200, Christoph Fritz wrote: USB controller may access a wrong address for the dTD (endpoint transfer descriptor) and then hang. This happens a lot when doing tests with g_ether module and iperf, a tool for measuring maximum TCP and UDP bandwidth. This hardware bug is explained in detail by errata number 2858 for i.MX23: http://cache.freescale.com/files/dsp/doc/errata/IMX23CE.pdf All (?) SOCs with an IP from chipidea suffer from this problem. mv_udc_core fixes this bug by commit daec765. There still may be unfixed drivers. why aren't you using that driver instead ? Is it really necessary to keep this driver around ? I would really like to see uniformization towards that, if you use the same IP, then the same driver ought to suffice. What's the reason for not using drivers/usb/chipidea ? I thought about this too but wasn't able to use chipidea with MXC_EHCI_INTERNAL_PHY as it's called in fsl_udc. Sascha, do you know if i.mx35 works with usb/chipidea? Thanks -- Christoph ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2] usb: fsl_udc: errata - postpone freeing current dTD
Hi Fabio On Sun, 2012-06-10 at 15:41 -0300, Fabio Estevam wrote: Hi Christoph, On Mon, Jun 4, 2012 at 8:37 AM, Christoph Fritz chf.fr...@googlemail.com wrote: After that, I stumbled upon this dmesg: Freescale High-Speed USB SOC Device Controller driver (Apr 20, 2007) fsl-usb2-udc fsl-usb2-udc: clk_get(usb) failed fsl-usb2-udc: probe of fsl-usb2-udc failed with error -2 Sascha, could you give me a hint? Does the patch below fix your problem? Thanks for your patch. It does indeed load Freescale High-Speed USB SOC Device Controller driver (Apr 20, 2007) fine - but now when I want to use it: modprobe g_ether [ 17.099363] g_ether gadget: using random self ethernet address [ 17.105316] g_ether gadget: using random host ethernet address [ 17.111974] usb0: MAC 1a:c7:9e:76:cc:45 [ 17.115866] usb0: HOST MAC 66:a2:4a:0a:46:17 [ 17.120199] g_ether gadget: Ethernet Gadget, version: Memorial Day 2008 [ 17.126861] g_ether gadget: g_ether ready these are the last words: System hangs completely. Same behavior with g_serial (these two I've tested). Currently I can't investigate this further, not because of a bug - but a flu. Thanks, -- Christoph ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2] usb: fsl_udc: errata - postpone freeing current dTD
Hi, On Mon, 2012-05-21 at 22:04 +0300, Felipe Balbi wrote: On Mon, May 21, 2012 at 08:57:22AM +0200, Christoph Fritz wrote: USB controller may access a wrong address for the dTD (endpoint transfer descriptor) and then hang. This happens a lot when doing tests with g_ether module and iperf, a tool for measuring maximum TCP and UDP bandwidth. This hardware bug is explained in detail by errata number 2858 for i.MX23: http://cache.freescale.com/files/dsp/doc/errata/IMX23CE.pdf All (?) SOCs with an IP from chipidea suffer from this problem. mv_udc_core fixes this bug by commit daec765. There still may be unfixed drivers. Signed-off-by: Christoph Fritz chf.fr...@googlemail.com Signed-off-by: Christian Hemp c.h...@phytec.de --- drivers/usb/gadget/fsl_udc_core.c | 15 ++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 55abfb6..72f2139 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -65,6 +65,8 @@ static struct usb_sys_interface *usb_sys_regs; /* it is initialized in probe() */ static struct fsl_udc *udc_controller = NULL; +static struct ep_td_struct *last_free_td; I don't want to see global variables anymore. In fact, please convert this to the new udc_start()/udc_stop() calls and use the generic map/unmap routines. That'll help you get rid of a bunch of useless code on the driver. After that you should remove all asm/* header includes and drop the ARCH dependency. You can also drop the big-/little-endian helpers as you can make use of generic writel()/readl() routines. Please make sure these series comes in with enough time to reach v3.6 merge window in about 3 months. You can put this fix together on that series after you drop the global. Before I came to do the proposed changes, I stumbled upon this: In file included from drivers/usb/gadget/fsl_udc_core.c:49: drivers/usb/gadget/fsl_usb2_udc.h: In function ‘get_qh_by_ep’: drivers/usb/gadget/fsl_usb2_udc.h:585: error: ‘struct fsl_ep’ has no member named ‘desc’ drivers/usb/gadget/fsl_udc_core.c: In function ‘done’: drivers/usb/gadget/fsl_udc_core.c:187: error: ‘struct fsl_ep’ has no member named ‘desc’ drivers/usb/gadget/fsl_udc_core.c:187: error: ‘struct fsl_ep’ has no member named ‘desc’ snip my proposed regression patch: --- From: Christoph Fritz chf.fr...@googlemail.com Date: Mon, 4 Jun 2012 12:58:21 +0200 Subject: [PATCH] usb: gadget: regression fix - useage of usb_ep This patch removes redundant pointer to struct usb_endpoint_descriptor which were missed in commit 79149b8: usb: gadget: Update fsl_udc_core to use usb_endpoint_descriptor inside the struct usb_ep Signed-off-by: Christoph Fritz chf.fr...@googlemail.com --- drivers/usb/gadget/fsl_udc_core.c |2 +- drivers/usb/gadget/fsl_usb2_udc.h |4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 2831685..678ec4d 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -2575,7 +2575,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) /* for ep0: the desc defined here; * for other eps, gadget layer called ep_enable with defined desc */ - udc_controller-eps[0].desc = fsl_ep0_desc; + udc_controller-eps[0].ep.desc = fsl_ep0_desc; udc_controller-eps[0].ep.maxpacket = USB_MAX_CTRL_PAYLOAD; /* setup the udc-eps[] for non-control endpoints and link diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index 5cd7b7e..f61a967 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -568,10 +568,10 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length) /* * ### internal used help routines. */ -#define ep_index(EP) ((EP)-desc-bEndpointAddress0xF) +#define ep_index(EP) ((EP)-ep.desc-bEndpointAddress0xF) #define ep_maxpacket(EP) ((EP)-ep.maxpacket) #define ep_is_in(EP) ( (ep_index(EP) == 0) ? (EP-udc-ep0_dir == \ - USB_DIR_IN ):((EP)-desc-bEndpointAddress \ + USB_DIR_IN) : ((EP)-ep.desc-bEndpointAddress \ USB_DIR_IN)==USB_DIR_IN) #define get_ep_by_pipe(udc, pipe) ((pipe == 1)? udc-eps[0]: \ udc-eps[pipe]) -- 1.7.2.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2] usb: fsl_udc: errata - postpone freeing current dTD
On Mon, 2012-06-04 at 13:30 +0200, Christoph Fritz wrote: Hi, On Mon, 2012-05-21 at 22:04 +0300, Felipe Balbi wrote: On Mon, May 21, 2012 at 08:57:22AM +0200, Christoph Fritz wrote: USB controller may access a wrong address for the dTD (endpoint transfer descriptor) and then hang. This happens a lot when doing tests with g_ether module and iperf, a tool for measuring maximum TCP and UDP bandwidth. This hardware bug is explained in detail by errata number 2858 for i.MX23: http://cache.freescale.com/files/dsp/doc/errata/IMX23CE.pdf All (?) SOCs with an IP from chipidea suffer from this problem. mv_udc_core fixes this bug by commit daec765. There still may be unfixed drivers. Signed-off-by: Christoph Fritz chf.fr...@googlemail.com Signed-off-by: Christian Hemp c.h...@phytec.de --- drivers/usb/gadget/fsl_udc_core.c | 15 ++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 55abfb6..72f2139 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -65,6 +65,8 @@ static struct usb_sys_interface *usb_sys_regs; /* it is initialized in probe() */ static struct fsl_udc *udc_controller = NULL; +static struct ep_td_struct *last_free_td; I don't want to see global variables anymore. In fact, please convert this to the new udc_start()/udc_stop() calls and use the generic map/unmap routines. That'll help you get rid of a bunch of useless code on the driver. After that you should remove all asm/* header includes and drop the ARCH dependency. You can also drop the big-/little-endian helpers as you can make use of generic writel()/readl() routines. Please make sure these series comes in with enough time to reach v3.6 merge window in about 3 months. You can put this fix together on that series after you drop the global. Before I came to do the proposed changes, I stumbled upon this: In file included from drivers/usb/gadget/fsl_udc_core.c:49: drivers/usb/gadget/fsl_usb2_udc.h: In function ‘get_qh_by_ep’: drivers/usb/gadget/fsl_usb2_udc.h:585: error: ‘struct fsl_ep’ has no member named ‘desc’ drivers/usb/gadget/fsl_udc_core.c: In function ‘done’: drivers/usb/gadget/fsl_udc_core.c:187: error: ‘struct fsl_ep’ has no member named ‘desc’ drivers/usb/gadget/fsl_udc_core.c:187: error: ‘struct fsl_ep’ has no member named ‘desc’ snip my proposed regression patch: --- From: Christoph Fritz chf.fr...@googlemail.com Date: Mon, 4 Jun 2012 12:58:21 +0200 Subject: [PATCH] usb: gadget: regression fix - useage of usb_ep snip After that, I stumbled upon this dmesg: Freescale High-Speed USB SOC Device Controller driver (Apr 20, 2007) fsl-usb2-udc fsl-usb2-udc: clk_get(usb) failed fsl-usb2-udc: probe of fsl-usb2-udc failed with error -2 Sascha, could you give me a hint? Thanks, -- Christoph ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] usb: gadget: regression fix - useage of usb_ep
This patch removes redundant pointer to struct usb_endpoint_descriptor which were missed in commit 79149b8: usb: gadget: Update fsl_udc_core to use usb_endpoint_descriptor inside the struct usb_ep Due to clock framework regressions, this patch is only compile tested! Signed-off-by: Christoph Fritz chf.fr...@googlemail.com --- drivers/usb/gadget/fsl_udc_core.c |2 +- drivers/usb/gadget/fsl_usb2_udc.h |4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 2831685..678ec4d 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -2575,7 +2575,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) /* for ep0: the desc defined here; * for other eps, gadget layer called ep_enable with defined desc */ - udc_controller-eps[0].desc = fsl_ep0_desc; + udc_controller-eps[0].ep.desc = fsl_ep0_desc; udc_controller-eps[0].ep.maxpacket = USB_MAX_CTRL_PAYLOAD; /* setup the udc-eps[] for non-control endpoints and link diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index 5cd7b7e..f61a967 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -568,10 +568,10 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length) /* * ### internal used help routines. */ -#define ep_index(EP) ((EP)-desc-bEndpointAddress0xF) +#define ep_index(EP) ((EP)-ep.desc-bEndpointAddress0xF) #define ep_maxpacket(EP) ((EP)-ep.maxpacket) #define ep_is_in(EP) ( (ep_index(EP) == 0) ? (EP-udc-ep0_dir == \ - USB_DIR_IN ):((EP)-desc-bEndpointAddress \ + USB_DIR_IN) : ((EP)-ep.desc-bEndpointAddress \ USB_DIR_IN)==USB_DIR_IN) #define get_ep_by_pipe(udc, pipe) ((pipe == 1)? udc-eps[0]: \ udc-eps[pipe]) -- 1.7.2.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
RE: [PATCH] usb: fsl_udc: errata - postpone freeing current dTD
Hi Chen, On Mon, 2012-05-21 at 01:05 +, Chen Peter-B29397 wrote: USB controller may access a wrong address for the dTD (endpoint transfer descriptor) and then hang. This happens a lot when doing tests with g_ether module and iperf, a tool for measuring maximum TCP and UDP bandwidth. This hardware bug is explained in detail by errata number 2858 for i.MX23: http://cache.freescale.com/files/dsp/doc/errata/IMX23CE.pdf Does this patch fix your problem? yes, it does! :-) +#if defined CONFIG_ARCH_MX51 || defined CONFIG_SOC_IMX35 +#define POSTPONE_FREE_LAST_DTD +#else +#undef POSTPONE_FREE_LAST_DTD +#endif + All i.mx SoC has this problem, if PowerPC also has this problem, you can delete #if defined. Else, you can define it for all i.mx SoC (CONFIG_ARCH_MXC | CONFIG_ARCH_MXS) I was unsure about this too. I can only test imx35. And mx51 was defined in your tree. So these two should be defined anyway. Marvell doesn't use any defines in mv_udc_core for their fix, so I would be fine without ifdefs too. Any objections? Please see next mail with patch v2. Thanks, -- Christoph ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2] usb: fsl_udc: errata - postpone freeing current dTD
USB controller may access a wrong address for the dTD (endpoint transfer descriptor) and then hang. This happens a lot when doing tests with g_ether module and iperf, a tool for measuring maximum TCP and UDP bandwidth. This hardware bug is explained in detail by errata number 2858 for i.MX23: http://cache.freescale.com/files/dsp/doc/errata/IMX23CE.pdf All (?) SOCs with an IP from chipidea suffer from this problem. mv_udc_core fixes this bug by commit daec765. There still may be unfixed drivers. Signed-off-by: Christoph Fritz chf.fr...@googlemail.com Signed-off-by: Christian Hemp c.h...@phytec.de --- drivers/usb/gadget/fsl_udc_core.c | 15 ++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 55abfb6..72f2139 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -65,6 +65,8 @@ static struct usb_sys_interface *usb_sys_regs; /* it is initialized in probe() */ static struct fsl_udc *udc_controller = NULL; +static struct ep_td_struct *last_free_td; + static const struct usb_endpoint_descriptor fsl_ep0_desc = { .bLength = USB_DT_ENDPOINT_SIZE, @@ -180,8 +182,13 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status) curr_td = next_td; if (j != req-dtd_count - 1) { next_td = curr_td-next_td_virt; + dma_pool_free(udc-td_pool, curr_td, curr_td-td_dma); + } else { + if (last_free_td != NULL) + dma_pool_free(udc-td_pool, last_free_td, + last_free_td-td_dma); + last_free_td = curr_td; } - dma_pool_free(udc-td_pool, curr_td, curr_td-td_dma); } if (req-mapped) { @@ -2579,6 +2586,8 @@ static int __init fsl_udc_probe(struct platform_device *pdev) goto err_unregister; } + last_free_td = NULL; + ret = usb_add_gadget_udc(pdev-dev, udc_controller-gadget); if (ret) goto err_del_udc; @@ -2633,6 +2642,10 @@ static int __exit fsl_udc_remove(struct platform_device *pdev) kfree(udc_controller-status_req); kfree(udc_controller-eps); + if (last_free_td != NULL) + dma_pool_free(udc_controller-td_pool, last_free_td, + last_free_td-td_dma); + dma_pool_destroy(udc_controller-td_pool); free_irq(udc_controller-irq, udc_controller); iounmap(dr_regs); -- 1.7.2.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] usb: fsl_udc: errata - postpone freeing current dTD
USB controller may access a wrong address for the dTD (endpoint transfer descriptor) and then hang. This happens a lot when doing tests with g_ether module and iperf, a tool for measuring maximum TCP and UDP bandwidth. This hardware bug is explained in detail by errata number 2858 for i.MX23: http://cache.freescale.com/files/dsp/doc/errata/IMX23CE.pdf mv_udc_core fixes this bug by commit daec765. There still may be unfixed drivers. Signed-off-by: Christoph Fritz chf.fr...@googlemail.com Signed-off-by: Christian Hemp c.h...@phytec.de --- drivers/usb/gadget/fsl_udc_core.c | 22 ++ drivers/usb/gadget/fsl_usb2_udc.h |6 ++ 2 files changed, 28 insertions(+), 0 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 55abfb6..f9bfafd 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -65,6 +65,9 @@ static struct usb_sys_interface *usb_sys_regs; /* it is initialized in probe() */ static struct fsl_udc *udc_controller = NULL; +#ifdef POSTPONE_FREE_LAST_DTD +static struct ep_td_struct *last_free_td; +#endif static const struct usb_endpoint_descriptor fsl_ep0_desc = { .bLength = USB_DT_ENDPOINT_SIZE, @@ -180,8 +183,18 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status) curr_td = next_td; if (j != req-dtd_count - 1) { next_td = curr_td-next_td_virt; +#ifdef POSTPONE_FREE_LAST_DTD + dma_pool_free(udc-td_pool, curr_td, curr_td-td_dma); + } else { + if (last_free_td != NULL) + dma_pool_free(udc-td_pool, last_free_td, + last_free_td-td_dma); + last_free_td = curr_td; + } +#else } dma_pool_free(udc-td_pool, curr_td, curr_td-td_dma); +#endif } if (req-mapped) { @@ -2579,6 +2592,10 @@ static int __init fsl_udc_probe(struct platform_device *pdev) goto err_unregister; } +#ifdef POSTPONE_FREE_LAST_DTD + last_free_td = NULL; +#endif + ret = usb_add_gadget_udc(pdev-dev, udc_controller-gadget); if (ret) goto err_del_udc; @@ -2633,6 +2650,11 @@ static int __exit fsl_udc_remove(struct platform_device *pdev) kfree(udc_controller-status_req); kfree(udc_controller-eps); +#ifdef POSTPONE_FREE_LAST_DTD + if (last_free_td != NULL) + dma_pool_free(udc_controller-td_pool, last_free_td, + last_free_td-td_dma); +#endif dma_pool_destroy(udc_controller-td_pool); free_irq(udc_controller-irq, udc_controller); iounmap(dr_regs); diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index e651469..03ae07f 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -4,6 +4,12 @@ #ifndef __FSL_USB2_UDC_H #define __FSL_USB2_UDC_H +#if defined CONFIG_ARCH_MX51 || defined CONFIG_SOC_IMX35 +#define POSTPONE_FREE_LAST_DTD +#else +#undef POSTPONE_FREE_LAST_DTD +#endif + /* ### define USB registers here */ #define USB_MAX_CTRL_PAYLOAD 64 -- 1.7.2.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC] [PATCH] usb: gadget: fix dtd dma confusion
On Wed, May 09, 2012 at 02:02:22AM +0200, Christoph Fritz wrote: Hi to All, after a while of testing and searching I can come up with a patch that fixes g_ether - iperf for fsl_udc on ARM i.MX35. The sad part is that this kind of fix is already implemented for marvell mv_udc driver since last year but still _not_ in the ~15 other *udc.c drivers. See here: daec765da767e4a6a30e1298862b28f2cae9a73f usb: gadget: mv_udc: fix dtd dma confusion So hereby I'm CC-ing all *udc.c maintainers to point out that this issue maybe affects you too. --- Subject: [PATCH] usb: gadget: fsl_udc: fix dtd dma confusion The controller will hang when doing testings with g_ether and iperf (tool for measuring maximum TCP and UDP bandwidth). This patch adds a delay to wait for controller to release dtd dma before freeing it. Signed-off-by: Christoph Fritz chf.fr...@googlemail.com --- drivers/usb/gadget/fsl_udc_core.c |9 + 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 55abfb6..fc86108 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1638,6 +1638,15 @@ static int process_ep_req(struct fsl_udc *udc, int pipe, status = REQ_UNCOMPLETE; return status; } else if (remaining_length) { + /* wait controller release dtd dma */ + while ((curr_qh-curr_dtd_ptr == curr_td-td_dma)) { + if (curr_td-next_td_ptr == + EP_QUEUE_HEAD_NEXT_TERMINATE) { + udelay(100); + break; + } + udelay(1); + } if (direction) { VDBG(Transmit dTD remaining length not zero); status = -EPROTO; -- 1.7.2.5 ping - what about this patch? Will it be applied? Thanks, -- Christoph ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC] [PATCH] usb: gadget: fix dtd dma confusion
Hi Neil, thanks for you help. What about the fix for mv_udc, shouldn't they have a similar limitation? How do you explain? Or maybe someone from Marvell has an answer? Yes, we encountered the same issue, and I have answered your question several hours ago. Please have a look. Thanks for that. Relating to the other *udc.c driver, do you think they should implement a similar workaround there too or at least check their errataS? Thanks, -- Christoph ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC] [PATCH] usb: gadget: fix dtd dma confusion
On Wed, Apr 11, 2012 at 10:15:49AM -0300, Fabio Estevam wrote: On Wed, Apr 11, 2012 at 4:39 AM, Christoph Fritz chf.fr...@googlemail.com wrote: Can you approve this behaviour of g_ether/usbnet when using iperf? I am not very familiar with iperf, so I will let others comment. Hi to All, after a while of testing and searching I can come up with a patch that fixes g_ether - iperf for fsl_udc on ARM i.MX35. The sad part is that this kind of fix is already implemented for marvell mv_udc driver since last year but still _not_ in the ~15 other *udc.c drivers. See here: daec765da767e4a6a30e1298862b28f2cae9a73f usb: gadget: mv_udc: fix dtd dma confusion So hereby I'm CC-ing all *udc.c maintainers to point out that this issue maybe affects you too. And maybe someone can explain if this: + if (curr_td-next_td_ptr == EP_QUEUE_HEAD_NEXT_TERMINATE) { is necessary and why (please see below). Thanks, -- Christoph --- Subject: [PATCH] usb: gadget: fsl_udc: fix dtd dma confusion The controller will hang when doing testings with g_ether and iperf (tool for measuring maximum TCP and UDP bandwidth). This patch adds a delay to wait for controller to release dtd dma before freeing it. Signed-off-by: Christoph Fritz chf.fr...@googlemail.com --- drivers/usb/gadget/fsl_udc_core.c |9 + 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 55abfb6..fc86108 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1638,6 +1638,15 @@ static int process_ep_req(struct fsl_udc *udc, int pipe, status = REQ_UNCOMPLETE; return status; } else if (remaining_length) { + /* wait controller release dtd dma */ + while ((curr_qh-curr_dtd_ptr == curr_td-td_dma)) { + if (curr_td-next_td_ptr == + EP_QUEUE_HEAD_NEXT_TERMINATE) { + udelay(100); + break; + } + udelay(1); + } if (direction) { VDBG(Transmit dTD remaining length not zero); status = -EPROTO; -- 1.7.2.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC] [PATCH] usb: gadget: fix dtd dma confusion
Hi Peter, thanks you for your help. On Wed, May 09, 2012 at 02:11:56AM +, Chen Peter-B29397 wrote: after a while of testing and searching I can come up with a patch that fixes g_ether - iperf for fsl_udc on ARM i.MX35. The sad part is that this kind of fix is already implemented for marvell mv_udc driver since last year but still _not_ in the ~15 other *udc.c drivers. It is a controller limitation (bug?) for chipidea controller when using dtd list to handle multi-dtds situation. The controller will read dtd's next pointer after this dtd's active bit has already been cleared. Freescale has an errata for this problem's description and solution. http://cache.freescale.com/files/dsp/doc/errata/IMX23CE.pdf See 2858 I'm hacking here an i.MX35 not an i.MX23. So I already had a look at its errata sheet http://cache.freescale.com/files/dsp/doc/errata/IMX35CE.pdf but didn't find a similar limitation as you now pointed out by errata number 2858 for i.MX23. What about the fix for mv_udc, shouldn't they have a similar limitation? How do you explain? Or maybe someone from Marvell has an answer? Thanks, -- Christoph ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC] [PATCH] usb: gadget: fix dtd dma confusion
On Wed, May 09, 2012 at 05:43:11AM +, Chen Peter-B29397 wrote: I'm hacking here an i.MX35 not an i.MX23. So I already had a look at its errata sheet http://cache.freescale.com/files/dsp/doc/errata/IMX35CE.pdf but didn't find a similar limitation as you now pointed out by errata number 2858 for i.MX23. i.mx35 and i.mx23 uses the same controller. A link or short note in i.MX35 its errata sheet to the i.MX23 one would be nice. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev