From patchwork Fri Oct 17 17:10:01 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Felipe Balbi X-Patchwork-Id: 38918 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f198.google.com (mail-wi0-f198.google.com [209.85.212.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 8C2DE20973 for ; Fri, 17 Oct 2014 17:10:59 +0000 (UTC) Received: by mail-wi0-f198.google.com with SMTP id hi2sf794093wib.5 for ; Fri, 17 Oct 2014 10:10:58 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe:content-type; bh=53Z1VNGqFz63zilbktKH+EG/zVBEytJ7V86Rhv/9+Rg=; b=cFR9BzZ9M0ENgXMeitHeV4pSCXZZt7GgOl0MVP8LCQlQPgSDGMSXwy5Nn5AQHpWE70 YfDEgtFypsD5U2fY94d6sgfdM3V8LHStR5UeFD3o9xLI5/UND81Hgbt7WmpKdnXx1n6n TmHXUmKbD+OstKAV7PyI3JsMBbRInCCoR+mZoKZ0taBjyne7AOrnW0t+NNd3o+UG/4Vy 6RykbIFkrAFfV4WenLtHr7Nel0axhhLbOauEzOkLsRiCBfJC+rN1wDYcjbp8XMlywztT jF4mUfFlkH1d+Mf5zcxkBrjB77WazEN/kdEKptZTTFp/KoFcJnPJPHi7weyE2H4+s8Cs DnKQ== X-Gm-Message-State: ALoCoQkxzBvSjBPA8518b68sV3WrQPa0pLCdqNJLQnLcF+qyplB7SoEWDi3UDZTbb+vpzfhmj8U1 X-Received: by 10.180.98.165 with SMTP id ej5mr845980wib.1.1413565858814; Fri, 17 Oct 2014 10:10:58 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.88.80 with SMTP id be16ls287473lab.107.gmail; Fri, 17 Oct 2014 10:10:58 -0700 (PDT) X-Received: by 10.112.189.10 with SMTP id ge10mr10089373lbc.23.1413565858662; Fri, 17 Oct 2014 10:10:58 -0700 (PDT) Received: from mail-lb0-f179.google.com (mail-lb0-f179.google.com. [209.85.217.179]) by mx.google.com with ESMTPS id m2si2931770lbp.105.2014.10.17.10.10.58 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 17 Oct 2014 10:10:58 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.179 as permitted sender) client-ip=209.85.217.179; Received: by mail-lb0-f179.google.com with SMTP id l4so1021718lbv.24 for ; Fri, 17 Oct 2014 10:10:58 -0700 (PDT) X-Received: by 10.112.167.38 with SMTP id zl6mr10217706lbb.34.1413565858574; Fri, 17 Oct 2014 10:10:58 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.84.229 with SMTP id c5csp266790lbz; Fri, 17 Oct 2014 10:10:57 -0700 (PDT) X-Received: by 10.66.194.17 with SMTP id hs17mr10064140pac.72.1413565856801; Fri, 17 Oct 2014 10:10:56 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id uh4si1701428pbc.36.2014.10.17.10.10.56 for ; Fri, 17 Oct 2014 10:10:56 -0700 (PDT) Received-SPF: none (google.com: linux-usb-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753581AbaJQRKm (ORCPT + 3 others); Fri, 17 Oct 2014 13:10:42 -0400 Received: from devils.ext.ti.com ([198.47.26.153]:36011 "EHLO devils.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753568AbaJQRKk (ORCPT ); Fri, 17 Oct 2014 13:10:40 -0400 Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by devils.ext.ti.com (8.13.7/8.13.7) with ESMTP id s9HHAeQA024920 for ; Fri, 17 Oct 2014 12:10:40 -0500 Received: from DFLE72.ent.ti.com (dfle72.ent.ti.com [128.247.5.109]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id s9HHAehR027903 for ; Fri, 17 Oct 2014 12:10:40 -0500 Received: from dflp33.itg.ti.com (10.64.6.16) by DFLE72.ent.ti.com (128.247.5.109) with Microsoft SMTP Server id 14.3.174.1; Fri, 17 Oct 2014 12:10:40 -0500 Received: from localhost (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp33.itg.ti.com (8.14.3/8.13.8) with ESMTP id s9HHAdPc027227; Fri, 17 Oct 2014 12:10:40 -0500 From: Felipe Balbi To: Linux USB Mailing List CC: Felipe Balbi Subject: [PATCH 25/28] usb: gadget: loopback: don't queue requests to bogus endpoints Date: Fri, 17 Oct 2014 12:10:01 -0500 Message-ID: <1413565804-13061-26-git-send-email-balbi@ti.com> X-Mailer: git-send-email 2.1.0.GIT In-Reply-To: <1413565804-13061-1-git-send-email-balbi@ti.com> References: <1413565804-13061-1-git-send-email-balbi@ti.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: balbi@ti.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.179 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , A request allocated from e.g. ep1out cannot be queued to any other endpoint. This bug has been in f_loopback at least since mid-2011 and since nobody has really screamed about it, we're not backporting to any stable kernels. Debugged with MUSB since that's the only controller which complains about this case. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_loopback.c | 87 +++++++++++++++----------------- 1 file changed, 42 insertions(+), 45 deletions(-) diff --git a/drivers/usb/gadget/function/f_loopback.c b/drivers/usb/gadget/function/f_loopback.c index bf04389..298b461 100644 --- a/drivers/usb/gadget/function/f_loopback.c +++ b/drivers/usb/gadget/function/f_loopback.c @@ -253,22 +253,13 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req) case 0: /* normal completion? */ if (ep == loop->out_ep) { - /* loop this OUT packet back IN to the host */ req->zero = (req->actual < req->length); req->length = req->actual; - status = usb_ep_queue(loop->in_ep, req, GFP_ATOMIC); - if (status == 0) - return; - - /* "should never get here" */ - ERROR(cdev, "can't loop %s to %s: %d\n", - ep->name, loop->in_ep->name, - status); } /* queue the buffer for some later OUT packet */ req->length = buflen; - status = usb_ep_queue(loop->out_ep, req, GFP_ATOMIC); + status = usb_ep_queue(ep, req, GFP_ATOMIC); if (status == 0) return; @@ -308,60 +299,66 @@ static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len) return alloc_ep_req(ep, len, buflen); } -static int -enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop) +static int enable_endpoint(struct usb_composite_dev *cdev, struct f_loopback *loop, + struct usb_ep *ep) { - int result = 0; - struct usb_ep *ep; struct usb_request *req; unsigned i; + int result; - /* one endpoint writes data back IN to the host */ - ep = loop->in_ep; + /* + * one endpoint writes data back IN to the host while another endpoint + * just reads OUT packets + */ result = config_ep_by_speed(cdev->gadget, &(loop->function), ep); if (result) - return result; + goto fail0; result = usb_ep_enable(ep); if (result < 0) - return result; - ep->driver_data = loop; - - /* one endpoint just reads OUT packets */ - ep = loop->out_ep; - result = config_ep_by_speed(cdev->gadget, &(loop->function), ep); - if (result) goto fail0; - - result = usb_ep_enable(ep); - if (result < 0) { -fail0: - ep = loop->in_ep; - usb_ep_disable(ep); - ep->driver_data = NULL; - return result; - } ep->driver_data = loop; - /* allocate a bunch of read buffers and queue them all at once. + /* + * allocate a bunch of read buffers and queue them all at once. * we buffer at most 'qlen' transfers; fewer if any need more * than 'buflen' bytes each. */ for (i = 0; i < qlen && result == 0; i++) { req = lb_alloc_ep_req(ep, 0); - if (req) { - req->complete = loopback_complete; - result = usb_ep_queue(ep, req, GFP_ATOMIC); - if (result) - ERROR(cdev, "%s queue req --> %d\n", - ep->name, result); - } else { - usb_ep_disable(ep); - ep->driver_data = NULL; - result = -ENOMEM; - goto fail0; + if (!req) + goto fail1; + + req->complete = loopback_complete; + result = usb_ep_queue(ep, req, GFP_ATOMIC); + if (result) { + ERROR(cdev, "%s queue req --> %d\n", + ep->name, result); + goto fail1; } } + return 0; + +fail1: + usb_ep_disable(ep); + +fail0: + return result; +} + +static int +enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop) +{ + int result = 0; + + result = enable_endpoint(cdev, loop, loop->in_ep); + if (result) + return result; + + result = enable_endpoint(cdev, loop, loop->out_ep); + if (result) + return result; + DBG(cdev, "%s enabled\n", loop->function.name); return result; }