From patchwork Sun May 20 23:17:24 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Fritz X-Patchwork-Id: 160296 X-Patchwork-Delegate: galak@kernel.crashing.org Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [IPv6:::1]) by ozlabs.org (Postfix) with ESMTP id 93BECB6FA0 for ; Mon, 21 May 2012 09:18:39 +1000 (EST) Received: from mail-we0-f179.google.com (mail-we0-f179.google.com [74.125.82.179]) (using TLSv1 with cipher ECDHE-RSA-RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority" (not verified)) by ozlabs.org (Postfix) with ESMTPS id C6DD6B6EE6 for ; Mon, 21 May 2012 09:17:34 +1000 (EST) Received: by werh12 with SMTP id h12so2981658wer.38 for ; Sun, 20 May 2012 16:17:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20120113; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; bh=Z3xPU0UUnQxfnQdcdXvlTxho0fdvEG/7+qsG+UTuyXo=; b=wCdzmHNH505xI569mSdWHQM7VT3nxMPiCLUBgCb4MkO1w9QHM4TibAEGiBJQHhxeKH O54bBLcr2eI8WGUmYvxBo9G0kaYO4ssto17IkTNPW0RXKFP5164UoB+U6SU2IMSaYIY/ V/LAFEy1cVqMcFMofEGmBgYorMe9dNsmirqeGgql0G7dW56vzWEg25HwgUaYbjkCwOw3 3lhm7YLizL/3rvBxvcERnynz3cL0T29QDOn/YX9lz/ri32hbgqqmZKzoALTSK79Tfdih YNSt/myw1ueEJytK5verJa+JRwC2st/LiRgt6TJesne5MSI09nU2Ps4YGfOPZ87SDww9 WcYQ== Received: by 10.180.88.194 with SMTP id bi2mr19665289wib.20.1337555849951; Sun, 20 May 2012 16:17:29 -0700 (PDT) Received: from mars (fritzc.com. [78.47.220.26]) by mx.google.com with ESMTPS id eo5sm2949440wib.0.2012.05.20.16.17.26 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 20 May 2012 16:17:28 -0700 (PDT) Date: Mon, 21 May 2012 01:17:24 +0200 From: Christoph Fritz To: Li Yang , Felipe Balbi , Greg Kroah-Hartman , Chen Peter-B29397 Subject: [PATCH] usb: fsl_udc: errata - postpone freeing current dTD Message-ID: <20120520231724.GA7941@mars> References: <20120409200656.GD2640@local> <20120410001017.GF2640@local> <20120410021151.GB23044@lovely.krouter> <20120411073918.GA9180@lovely.krouter> <20120509000221.GA19525@lovely.krouter> <20120513225126.GA3683@lovely.krouter> <20120514042142.GD9750@kroah.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20120514042142.GD9750@kroah.com> User-Agent: Mutt/1.5.21 (2010-09-15) Cc: Oliver Neukum , Kukjin Kim , Eric Miao , Ben Dooks , Fabio Estevam , Sascha Hauer , linux-usb@vger.kernel.org, Nicolas Ferre , Haojian Zhuang , Ido Shayevitz , Thomas Dahlmann , Estevam Fabio-R49496 , "Hans J. Koch" , Daniel Mack , Christian Hemp , Russell King , Neil Zhang , linuxppc-dev@lists.ozlabs.org X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org 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 Signed-off-by: Christian Hemp --- 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