From patchwork Fri Oct 19 10:24:43 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Fritz X-Patchwork-Id: 192640 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 52ACB2C084E for ; Fri, 19 Oct 2012 21:28:16 +1100 (EST) Received: from mail-bk0-f51.google.com (mail-bk0-f51.google.com [209.85.214.51]) (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 F09CD2C033D for ; Fri, 19 Oct 2012 21:25:36 +1100 (EST) Received: by mail-bk0-f51.google.com with SMTP id e19so111780bku.38 for ; Fri, 19 Oct 2012 03:25:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=N+NV5DvMbJ+ZTdawTe6zpoXjU7svOab5l4Z+Cdy7sJs=; b=WuxGFFFsTyKj2hzyttESAUNpW+wd3QPCUHv8Qgs2LFQX2yJcP0pR35q3nm+3MZ9Tm3 nDYWO+Aybeobj/PUP2CZXWB27D9/h+DtC2vEKUJgj1BEmOMAXfIYP42TysAVLmNgYQCr WnA1rbYMe63IfSW8dPOIAomsEafUdu8/5uO7htF2uYXIUkjDPlcul5fcVlMRAay9LhwM /367crtpEWzo9h8mp9TBZ5tGxpc28VxPIbba/I1kyaDAwg1o4f+phjN4lrUJX2n6uLkP leWa+jG7fIEBeBVYLacWn5WYsDIfbjCEBa0JmDnRJW7awO0WgCKAGjqs9DshLrMGjCQ1 0aPw== Received: by 10.204.148.21 with SMTP id n21mr228261bkv.124.1350642336197; Fri, 19 Oct 2012 03:25:36 -0700 (PDT) Received: from localhost.localdomain (p5DD1557F.dip.t-dialin.net. [93.209.85.127]) by mx.google.com with ESMTPS id v14sm598539bkv.10.2012.10.19.03.25.33 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 19 Oct 2012 03:25:35 -0700 (PDT) From: Christoph Fritz To: Felipe Balbi Subject: [PATCH 5/7] usb: gadget: fsl_udc: postpone freeing current dTD Date: Fri, 19 Oct 2012 12:24:43 +0200 Message-Id: <1350642285-8145-5-git-send-email-chf.fritz@googlemail.com> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1350642156-8034-1-git-send-email-chf.fritz@googlemail.com> References: <1350642156-8034-1-git-send-email-chf.fritz@googlemail.com> Cc: Estevam Fabio-R49496 , Li Yang-R58472 , Greg Kroah-Hartman , Chen Peter-B29397 , Sascha Hauer , linux-usb@vger.kernel.org, "Hans J. Koch" , Daniel Mack , Christian Hemp , linuxppc-dev@lists.ozlabs.org, Teresa Gamez , Sebastian Andrzej Siewior X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" 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 Signed-off-by: Christian Hemp Reviewed-by: Peter Chen --- 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 */