From patchwork Tue Sep 4 16:58:52 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enrico Scholz X-Patchwork-Id: 181692 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 66E7C2C02FA for ; Wed, 5 Sep 2012 07:45:15 +1000 (EST) Received: from mail.cvg.de (mail.cvg.de [62.153.82.30]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "mail.cvg.de", Issuer "SIGMA Chemnitz Server CA" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 9290F2C0098 for ; Wed, 5 Sep 2012 03:31:01 +1000 (EST) Received: from ensc-virt.intern.sigma-chemnitz.de (ensc-virt.intern.sigma-chemnitz.de [192.168.3.24]) by mail.cvg.de (8.14.4/8.14.4) with ESMTP id q84H0FTX021519 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 4 Sep 2012 19:00:16 +0200 Received: from ensc by ensc-virt.intern.sigma-chemnitz.de with local (Exim 4.76) (envelope-from ) id 1T8wUJ-0000tQ-FN; Tue, 04 Sep 2012 19:00:31 +0200 From: Enrico Scholz To: linux-usb@vger.kernel.org, linuxppc-dev@lists.ozlabs.org Subject: [PATCH] usb: gadget: fsl_udc_core: do not immediatly prime STATUS for IN xfer Date: Tue, 4 Sep 2012 18:58:52 +0200 Message-Id: <1346777932-3362-1-git-send-email-enrico.scholz@sigma-chemnitz.de> X-Mailer: git-send-email 1.7.11.4 X-DSPAM-Result: Innocent X-DSPAM-Probability: 0 X-DSPAM-Confidence: 0.8775 X-Spam-Score: -5.5 X-Spam-Level: ----- X-Spam-Tests: AWL,BAYES_00,RP_MATCHES_RCVD,SPF_NEUTRAL,DSPAM_INNOCENT X-Scanned-By: MIMEDefang 2.73 X-Mailman-Approved-At: Wed, 05 Sep 2012 07:44:18 +1000 Cc: gregkh@linuxfoundation.org, balbi@ti.com, Enrico Scholz 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" Because the fsl_udc_core driver shares one 'status_req' object for the complete ep0 control transfer, it is not possible to prime the final STATUS phase immediately after the IN transaction. E.g. ch9getstatus() executed: | req = udc->status_req; | ... | list_add_tail(&req->queue, &ep->queue); | if (ep0_prime_status(udc, EP_DIR_OUT)) | .... | struct fsl_req *req = udc->status_req; | list_add_tail(&req->queue, &ep->queue); which corrupts the ep->queue list by inserting 'status_req' twice. This causes a kernel oops e.g. when 'lsusb -v' is executed on the host. Patch delays the final 'ep0_prime_status(udc, EP_DIR_OUT))' by moving it into the ep0 completion handler. Signed-off-by: Enrico Scholz Acked-by: Li Yang --- drivers/usb/gadget/fsl_udc_core.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index d7138cc..55c4a61 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1294,8 +1294,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction) udc->ep0_dir = USB_DIR_OUT; ep = &udc->eps[0]; - if (udc->ep0_state != DATA_STATE_XMIT) - udc->ep0_state = WAIT_FOR_OUT_STATUS; + udc->ep0_state = WAIT_FOR_OUT_STATUS; req->ep = ep; req->req.length = 0; @@ -1400,8 +1399,6 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, list_add_tail(&req->queue, &ep->queue); udc->ep0_state = DATA_STATE_XMIT; - if (ep0_prime_status(udc, EP_DIR_OUT)) - ep0stall(udc); return; stall: @@ -1511,14 +1508,6 @@ static void setup_received_irq(struct fsl_udc *udc, spin_lock(&udc->lock); udc->ep0_state = (setup->bRequestType & USB_DIR_IN) ? DATA_STATE_XMIT : DATA_STATE_RECV; - /* - * If the data stage is IN, send status prime immediately. - * See 2.0 Spec chapter 8.5.3.3 for detail. - */ - if (udc->ep0_state == DATA_STATE_XMIT) - if (ep0_prime_status(udc, EP_DIR_OUT)) - ep0stall(udc); - } else { /* No data phase, IN status from gadget */ udc->ep0_dir = USB_DIR_IN; @@ -1548,7 +1537,8 @@ static void ep0_req_complete(struct fsl_udc *udc, struct fsl_ep *ep0, switch (udc->ep0_state) { case DATA_STATE_XMIT: /* already primed at setup_received_irq */ - udc->ep0_state = WAIT_FOR_OUT_STATUS; + if (ep0_prime_status(udc, EP_DIR_OUT)) + ep0stall(udc); break; case DATA_STATE_RECV: /* send status phase */