Received: by 10.192.165.148 with SMTP id m20csp2538899imm; Sun, 22 Apr 2018 09:07:48 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+kKIQfKvxj0MJqR2xznF+zNt7Z3+ZPzI8n5IywxqlSBcsv1wennOCxqBF7w19xnnNtiqAU X-Received: by 10.101.101.150 with SMTP id u22mr14270137pgv.368.1524413268849; Sun, 22 Apr 2018 09:07:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524413268; cv=none; d=google.com; s=arc-20160816; b=Ea+ggB8Db9F0tYHybpzFgzc5dlPJ0YmMfdS0x6752OpaLO0qfw/RjSOVre2xQPOi2y E2UYZ31Vh9l1AYmJ65hlp0DV15EPCg6gRca0DzWnWeMjIgmvE8W210NBhFDi3g+GuWDx 7ZBTxfFA0Ef4M34Z/Q7yTKWYyPpM4JFSU/0K2g20JxWHAqmrBsz725GZdmPPCY3eDpaa pDn+CtY3KwYQGnKerUyKHewyMgTbrj/Dcs13iTKKpc+6oGD66DbnTkQEDO2vu+vTtoQD kmbtp9cLpEit2Vm+g/2aFfTI08SxofEJh/sfyU/nloFcpZtpLCHv+pWAG/DMHuBMwOim 81dA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=8/GZbm7aH3ZYkgC3ocCdNkmDiH7XVh6P4ZvrDHXr75Q=; b=eccqiybDtSmYdz8cdd1vGwJs//+Yw7KJoSODew3TcRlQjwFqjrOZyFVYwPQFVcKwt7 VtQaUQcqCCLDi0w16yYETOqpqNZrJlIgA1zG0SJkIhat3TQH7p4yVmmpZXhUGVokhK0h PubmIlmkS6k7qG4xoZQKQ4iLg3HZePlItBm1n+fEOANJOZpPINXNLJ/9vaYFqwzrqUi9 oiMohBl+NotFjPnVKwYPv2aGtVB7CGimxLxBKZSsLc7wbtlg4FBkzzn3DlUYgDcYpk8N Vi5uUXaIfBXoVjQtqpHt0FR5k1AM4caijlDbfV24sDNgxq0wfDduN8df6dT73Wxa3eSR ufIQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c23-v6si10130826plk.245.2018.04.22.09.07.34; Sun, 22 Apr 2018 09:07:48 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753937AbeDVN5M (ORCPT + 99 others); Sun, 22 Apr 2018 09:57:12 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:45538 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753838AbeDVN5F (ORCPT ); Sun, 22 Apr 2018 09:57:05 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id C0AFD9CE; Sun, 22 Apr 2018 13:57:03 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Tuba Yavuz , Felipe Balbi Subject: [PATCH 4.16 044/196] usb: dwc3: gadget: never call ->complete() from ->ep_queue() Date: Sun, 22 Apr 2018 15:51:04 +0200 Message-Id: <20180422135106.353321075@linuxfoundation.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180422135104.278511750@linuxfoundation.org> References: <20180422135104.278511750@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.16-stable review patch. If anyone has any objections, please let me know. ------------------ From: Felipe Balbi commit c91815b596245fd7da349ecc43c8def670d2269e upstream. This is a requirement which has always existed but, somehow, wasn't reflected in the documentation and problems weren't found until now when Tuba Yavuz found a possible deadlock happening between dwc3 and f_hid. She described the situation as follows: spin_lock_irqsave(&hidg->write_spinlock, flags); // first acquire /* we our function has been disabled by host */ if (!hidg->req) { free_ep_req(hidg->in_ep, hidg->req); goto try_again; } [...] status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC); => [...] => usb_gadget_giveback_request => f_hidg_req_complete => spin_lock_irqsave(&hidg->write_spinlock, flags); // second acquire Note that this happens because dwc3 would call ->complete() on a failed usb_ep_queue() due to failed Start Transfer command. This is, anyway, a theoretical situation because dwc3 currently uses "No Response Update Transfer" command for Bulk and Interrupt endpoints. It's still good to make this case impossible to happen even if the "No Reponse Update Transfer" command is changed. Reported-by: Tuba Yavuz Signed-off-by: Felipe Balbi Cc: stable Signed-off-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/gadget.c | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -166,18 +166,8 @@ static void dwc3_ep_inc_deq(struct dwc3_ dwc3_ep_inc_trb(&dep->trb_dequeue); } -/** - * dwc3_gadget_giveback - call struct usb_request's ->complete callback - * @dep: The endpoint to whom the request belongs to - * @req: The request we're giving back - * @status: completion code for the request - * - * Must be called with controller's lock held and interrupts disabled. This - * function will unmap @req and call its ->complete() callback to notify upper - * layers that it has completed. - */ -void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, - int status) +void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep, + struct dwc3_request *req, int status) { struct dwc3 *dwc = dep->dwc; @@ -190,18 +180,35 @@ void dwc3_gadget_giveback(struct dwc3_ep if (req->trb) usb_gadget_unmap_request_by_dev(dwc->sysdev, - &req->request, req->direction); + &req->request, req->direction); req->trb = NULL; - trace_dwc3_gadget_giveback(req); + if (dep->number > 1) + pm_runtime_put(dwc->dev); +} + +/** + * dwc3_gadget_giveback - call struct usb_request's ->complete callback + * @dep: The endpoint to whom the request belongs to + * @req: The request we're giving back + * @status: completion code for the request + * + * Must be called with controller's lock held and interrupts disabled. This + * function will unmap @req and call its ->complete() callback to notify upper + * layers that it has completed. + */ +void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, + int status) +{ + struct dwc3 *dwc = dep->dwc; + + dwc3_gadget_del_and_unmap_request(dep, req, status); + spin_unlock(&dwc->lock); usb_gadget_giveback_request(&dep->endpoint, &req->request); spin_lock(&dwc->lock); - - if (dep->number > 1) - pm_runtime_put(dwc->dev); } /** @@ -1227,7 +1234,7 @@ static int __dwc3_gadget_kick_transfer(s if (req->trb) memset(req->trb, 0, sizeof(struct dwc3_trb)); dep->queued_requests--; - dwc3_gadget_giveback(dep, req, ret); + dwc3_gadget_del_and_unmap_request(dep, req, ret); return ret; }