Received: by 2002:a05:6358:701b:b0:131:369:b2a3 with SMTP id 27csp3912218rwo; Mon, 24 Jul 2023 19:58:32 -0700 (PDT) X-Google-Smtp-Source: APBJJlGHwKZfXC0K34G+KSyld5jxhCe9Ot0Axepyg2hAf58jehU8rODEduKeZY4UFifbgfsohqgZ X-Received: by 2002:a05:6402:7da:b0:521:d2ab:e4df with SMTP id u26-20020a05640207da00b00521d2abe4dfmr1035058edy.19.1690253912135; Mon, 24 Jul 2023 19:58:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1690253912; cv=none; d=google.com; s=arc-20160816; b=qajE82I1qp9I10+S7t0D0znmdqF4pb7WRIAV37F4uVYwjEhhw3j55yO73mYV1IbLDW WmJlSJQ/dUMrl6jQTi1EleMIaao+r0t4gz6gwHMGtg00/db6y9mT+eBZ/lqXncVhVMpv gU6t1c3ntb63HnI05V1u01P5unXN0WmC5Bz4O2PgFfatWpD8FH2cJ3vVvCOlGQidYApb WXr6tFOTk5goCqxmrx5vy7cK4sWNeyjcsXsT8nhy/LQKJLeaoJS/ZmYJbrot0ZtqJujg xMOLLhmqCYKJCcYTKXCZuln9RUVebajyHp8Y/dnSqJvkO9SvjXTM31zFVJLL/8Ml5+61 FH9g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=29NLIw+H5LDwCkEEPDf5wgBGQfWcfB2YWb8BBRJILZ4=; fh=K7xcz7pVtnDSJqstuhcz5nwpW/ROujEJ3AOhMThi/Z0=; b=ihbpXq0gL4J42HS15NcA88x9H405ozz+mwmDCFAk+wckPQIZUtg6SaDM18lmla4rnX 5lm2l9BxfmHJHXZXuH20ZiJic4AxddkwjDYGTt8jO7d0UlGA+3+vL98mhizCYwM/SNel //31EkNJ3vZ/oqF/2RoN1TIoHiROC40S9AKaaslQvOdlKLu8Bbp3/Nm9ZLiH5GMSnjQp XOKEXPyvOTqwj0pX/E4JX04Agi5NrdkAoeD4YvaB6RbMuWjYcVhsDf6t8SWkB1/HDjSo aQyYQ3U4N08QAugZHaGZIcD1qZR/8ruQAAonx+ZtzCS05+tB9Z2x2R1aGIjlGo1w8zFx ckUg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=YuzWtmSD; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id t21-20020aa7d4d5000000b0051e0e5d86absi7208304edr.269.2023.07.24.19.58.08; Mon, 24 Jul 2023 19:58:32 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=YuzWtmSD; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231562AbjGYChi (ORCPT + 99 others); Mon, 24 Jul 2023 22:37:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35998 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231350AbjGYCgJ (ORCPT ); Mon, 24 Jul 2023 22:36:09 -0400 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8DBC92106; Mon, 24 Jul 2023 19:35:26 -0700 (PDT) Received: from pps.filterd (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 36P20MTg010539; Tue, 25 Jul 2023 02:34:57 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=qcppdkim1; bh=29NLIw+H5LDwCkEEPDf5wgBGQfWcfB2YWb8BBRJILZ4=; b=YuzWtmSDgR5mCFdRQ7pHT30JyLvSmOgnrsdHrmmTXWKYC9YeQymldF0PQDpgwHqHKbuF 0UVm5Lm7hqca2SCwpCkp7kd9elRt04OiZXLCAnnTSVplTBxV+t6/M+fsejY1K9E5oX4d 6TE1R/CapIfBZMFgrNCznIIqvmaBmQxoLYULxufBs0k+WSYl7mKntb3eAL1kGvanP20Q GzMt4ihoYIY0YqebI6ZSvpEslqrymoOSBI2lJvnTEM9xOuOQmlB6aC98LU1B7yaLnWG4 wO6MXs2hRp9XN6PFuX/lmKKrxkwaCU+LLzame/dVsbRrkX+zD7Qnc1IKg2hbXjZFYAPT Bg== Received: from nasanppmta01.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3s1rs5hn7y-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 25 Jul 2023 02:34:57 +0000 Received: from nasanex01b.na.qualcomm.com (nasanex01b.na.qualcomm.com [10.46.141.250]) by NASANPPMTA01.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 36P2YVgC020001 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 25 Jul 2023 02:34:31 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nasanex01b.na.qualcomm.com (10.46.141.250) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.30; Mon, 24 Jul 2023 19:34:29 -0700 From: Wesley Cheng To: , , , , , , , , , , , , , , , CC: , , , , , , , , , , , Mathias Nyman , Wesley Cheng Subject: [PATCH v4 02/32] xhci: add helper to stop endpoint and wait for completion Date: Mon, 24 Jul 2023 19:33:46 -0700 Message-ID: <20230725023416.11205-3-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230725023416.11205-1-quic_wcheng@quicinc.com> References: <20230725023416.11205-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01a.na.qualcomm.com (10.47.209.196) To nasanex01b.na.qualcomm.com (10.46.141.250) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: 5g7YNjASXvQgmxhJey8uZNu_N53_9zNy X-Proofpoint-ORIG-GUID: 5g7YNjASXvQgmxhJey8uZNu_N53_9zNy X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.254,Aquarius:18.0.957,Hydra:6.0.591,FMLib:17.11.176.26 definitions=2023-07-24_18,2023-07-24_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 malwarescore=0 lowpriorityscore=0 phishscore=0 priorityscore=1501 mlxlogscore=999 mlxscore=0 adultscore=0 clxscore=1015 bulkscore=0 suspectscore=0 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2306200000 definitions=main-2307250021 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Mathias Nyman Expose xhci_stop_endpoint_sync() which is a synchronous variant of xhci_queue_stop_endpoint(). This is useful for client drivers that are using the secondary interrupters, and need to stop/clean up the current session. The stop endpoint command handler will also take care of cleaning up the ring. Modifications to repurpose the new API into existing stop endpoint sequences was implemented by Wesley Cheng. Signed-off-by: Mathias Nyman Co-developed-by: Wesley Cheng Signed-off-by: Wesley Cheng --- drivers/usb/host/xhci-hub.c | 29 +++--------------- drivers/usb/host/xhci.c | 60 +++++++++++++++++++++++++++---------- drivers/usb/host/xhci.h | 2 ++ 3 files changed, 50 insertions(+), 41 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 0054d02239e2..2f7309bdc922 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -489,7 +489,6 @@ EXPORT_SYMBOL_GPL(xhci_find_slot_id_by_port); static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) { struct xhci_virt_device *virt_dev; - struct xhci_command *cmd; unsigned long flags; int ret; int i; @@ -501,10 +500,6 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) trace_xhci_stop_device(virt_dev); - cmd = xhci_alloc_command(xhci, true, GFP_NOIO); - if (!cmd) - return -ENOMEM; - spin_lock_irqsave(&xhci->lock, flags); for (i = LAST_EP_INDEX; i > 0; i--) { if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue) { @@ -521,7 +516,7 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) if (!command) { spin_unlock_irqrestore(&xhci->lock, flags); ret = -ENOMEM; - goto cmd_cleanup; + goto out; } ret = xhci_queue_stop_endpoint(xhci, command, slot_id, @@ -529,30 +524,14 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) if (ret) { spin_unlock_irqrestore(&xhci->lock, flags); xhci_free_command(xhci, command); - goto cmd_cleanup; + goto out; } } } - ret = xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend); - if (ret) { - spin_unlock_irqrestore(&xhci->lock, flags); - goto cmd_cleanup; - } - - xhci_ring_cmd_db(xhci); spin_unlock_irqrestore(&xhci->lock, flags); + ret = xhci_stop_endpoint_sync(xhci, &virt_dev->eps[0], suspend); - /* Wait for last stop endpoint command to finish */ - wait_for_completion(cmd->completion); - - if (cmd->status == COMP_COMMAND_ABORTED || - cmd->status == COMP_COMMAND_RING_STOPPED) { - xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n"); - ret = -ETIME; - } - -cmd_cleanup: - xhci_free_command(xhci, cmd); +out: return ret; } diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 58d75b412bad..21413721f278 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2764,6 +2764,46 @@ static int xhci_reserve_bandwidth(struct xhci_hcd *xhci, return -ENOMEM; } +/* + * Synchronous XHCI stop endpoint helper. Issues the stop endpoint command and + * waits for the command completion before returning. + */ +int xhci_stop_endpoint_sync(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, int suspend) +{ + struct xhci_command *command; + unsigned long flags; + int ret; + + command = xhci_alloc_command(xhci, true, GFP_KERNEL); + if (!command) + return -ENOMEM; + + spin_lock_irqsave(&xhci->lock, flags); + ret = xhci_queue_stop_endpoint(xhci, command, ep->vdev->slot_id, + ep->ep_index, suspend); + if (ret < 0) { + spin_unlock_irqrestore(&xhci->lock, flags); + goto out; + } + + xhci_ring_cmd_db(xhci); + spin_unlock_irqrestore(&xhci->lock, flags); + + ret = wait_for_completion_timeout(command->completion, msecs_to_jiffies(3000)); + if (!ret) + xhci_warn(xhci, "%s: Unable to stop endpoint.\n", + __func__); + + if (command->status == COMP_COMMAND_ABORTED || + command->status == COMP_COMMAND_RING_STOPPED) { + xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n"); + ret = -ETIME; + } +out: + xhci_free_command(xhci, command); + + return ret; +} /* Issue a configure endpoint command or evaluate context command * and wait for it to finish. @@ -3084,7 +3124,7 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd, struct xhci_virt_device *vdev; struct xhci_virt_ep *ep; struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_command *stop_cmd, *cfg_cmd; + struct xhci_command *cfg_cmd; unsigned int ep_index; unsigned long flags; u32 ep_flag; @@ -3124,10 +3164,6 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd, if (ep_flag == SLOT_FLAG || ep_flag == EP0_FLAG) return; - stop_cmd = xhci_alloc_command(xhci, true, GFP_NOWAIT); - if (!stop_cmd) - return; - cfg_cmd = xhci_alloc_command_with_ctx(xhci, true, GFP_NOWAIT); if (!cfg_cmd) goto cleanup; @@ -3150,23 +3186,16 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd, goto cleanup; } - err = xhci_queue_stop_endpoint(xhci, stop_cmd, udev->slot_id, - ep_index, 0); + spin_unlock_irqrestore(&xhci->lock, flags); + + err = xhci_stop_endpoint_sync(xhci, ep, 0); if (err < 0) { - spin_unlock_irqrestore(&xhci->lock, flags); - xhci_free_command(xhci, cfg_cmd); xhci_dbg(xhci, "%s: Failed to queue stop ep command, %d ", __func__, err); goto cleanup; } - xhci_ring_cmd_db(xhci); - spin_unlock_irqrestore(&xhci->lock, flags); - - wait_for_completion(stop_cmd->completion); - spin_lock_irqsave(&xhci->lock, flags); - /* config ep command clears toggle if add and drop ep flags are set */ ctrl_ctx = xhci_get_input_control_ctx(cfg_cmd->in_ctx); if (!ctrl_ctx) { @@ -3198,7 +3227,6 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd, xhci_free_command(xhci, cfg_cmd); cleanup: - xhci_free_command(xhci, stop_cmd); spin_lock_irqsave(&xhci->lock, flags); if (ep->ep_state & EP_SOFT_CLEAR_TOGGLE) ep->ep_state &= ~EP_SOFT_CLEAR_TOGGLE; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index d706a27ec0a3..898b6434dc27 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -2125,6 +2125,8 @@ void xhci_ring_doorbell_for_active_rings(struct xhci_hcd *xhci, void xhci_cleanup_command_queue(struct xhci_hcd *xhci); void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring); unsigned int count_trbs(u64 addr, u64 len); +int xhci_stop_endpoint_sync(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, + int suspend); /* xHCI roothub code */ void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port,