Received: by 2002:a05:7412:d8a:b0:e2:908c:2ebd with SMTP id b10csp494076rdg; Tue, 10 Oct 2023 17:25:29 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGRX0Qhcb86ygkUu+7RT62iMW5CY1JALRP7uHcY+Ibt6c3TBvF5teY/1mpUyS1U5lCNl2Mv X-Received: by 2002:a05:6358:785:b0:143:82e0:8cbc with SMTP id n5-20020a056358078500b0014382e08cbcmr22308487rwj.1.1696983929326; Tue, 10 Oct 2023 17:25:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1696983929; cv=none; d=google.com; s=arc-20160816; b=ByEJEKtITgdeuepHTp2P+23TZm+hpXhzhaW+ZwcJkJ0lxGs19kuND/K8SIhS6juo2j Zz2uQAdWKFKneE8gP+xAaXFz+MJ6wTkET5/ETaOoa9NZVfOJHC6JpO/NVfOGBctcmj9u poOjRfPPL8qtCY9lF3pGre1ToG42/FA/HBRAaj5K6vUk/aCnTTjC5u0im6GMSalRq4+3 CDEXMZyIRSg5lfrxhHx27LyHEtzpEhi/FL7GPXYhLLwYMHrUccUSPYNRWnt0sz0hicna 25ADOJxMdF0m2YthH0p3Ns1GbY0b5XmnNHNvIa1u9an50Wo+z71URyMhYH3eGMEsawSr VeuA== 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=rL6A530uumVVL+EUAHQtJ9O8tolT/IqcxFXcAWvLHno=; fh=ASZxE/GudOQkGCAz0d02NHHSpg4iNHYOcDWl1imlof0=; b=dGGRa6BJvWdEAw2Ei/NYORwrBdpG8eOdst0+LgadDmXj9QhbQR0bKiD+ESmZ/b6mpB oOSzCs6zYaGIHEWI5Zyz32mBx5gnaUP9Zlf8e/OYkrVR2t6oRj5JOgr8AMVAZGywHHV5 sF4KYHU4forcX9qoaEH3N41xTFLsJGmnWlUWPUJA+cqI1IEjMs0oHmAcXQcry0mve4+8 kQSg/us+8Y4/dLBaIaR9MstfDkHBUrWqwjiQoLD9TKXDmvZN2xRflIeSyQyMEe5iDsW4 LuDKtZCcR9Acfxo8c+XkT/jUJEgSDh58Yy+T6dYpgu58S8kUS8iHe0dY6evlC7Kn7vAX nryw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=CtPhqkYx; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 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 fry.vger.email (fry.vger.email. [2620:137:e000::3:8]) by mx.google.com with ESMTPS id i68-20020a639d47000000b00578db6172fdsi11518622pgd.325.2023.10.10.17.25.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 10 Oct 2023 17:25:29 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) client-ip=2620:137:e000::3:8; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=CtPhqkYx; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id 40D2381CAFBF; Tue, 10 Oct 2023 17:25:20 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344637AbjJKAYU (ORCPT + 99 others); Tue, 10 Oct 2023 20:24:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36482 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344327AbjJKAXR (ORCPT ); Tue, 10 Oct 2023 20:23:17 -0400 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BEBF5E1; Tue, 10 Oct 2023 17:23:12 -0700 (PDT) Received: from pps.filterd (m0279866.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 39B0KqRk006816; Wed, 11 Oct 2023 00:22:31 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=rL6A530uumVVL+EUAHQtJ9O8tolT/IqcxFXcAWvLHno=; b=CtPhqkYxmHSV4xwu8mJoxscwpgdH9NoXWeJ4cQj7CjQlXm2a/BPSYBUMrFA9yLryagXD GyKmy23dhyQM9LKsImOezsadTr64w+voQzC3l1rfOuJYhPQx9//qyO1OksDA7YZfLk5B QM3paIigKdVOTvqk5M/DBAfOj08TGyUSOG3nRYvhCePrB2nZtXmdC37RN5+5NKK4MKpd cF8Mgzl8pbGxaEEhFJODL19DYe4FnG6LbvqTyBSyyqS9KkOjG4C0IWyuRpDQJXTvyfmu bdijOFeTJGxvMctQcFWvzH0itlPHyovK4kpOLnOHYa5po69lfb1UquaJiHXJXKSOPhB9 Mg== Received: from nalasppmta05.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3tngtp80ta-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 11 Oct 2023 00:22:30 +0000 Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA05.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 39B0MUtC027060 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 11 Oct 2023 00:22:30 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.36; Tue, 10 Oct 2023 17:22:29 -0700 From: Wesley Cheng To: , , , , , , , , , , , , , , CC: , , , , , Wesley Cheng Subject: [PATCH v8 05/34] usb: host: xhci-mem: Cleanup pending secondary event ring events Date: Tue, 10 Oct 2023 17:21:17 -0700 Message-ID: <20231011002146.1821-6-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20231011002146.1821-1-quic_wcheng@quicinc.com> References: <20231011002146.1821-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: TS7qYMhJ0LXPLPbQ3-A1OiZeFySw8OsV X-Proofpoint-GUID: TS7qYMhJ0LXPLPbQ3-A1OiZeFySw8OsV X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-10_19,2023-10-10_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 adultscore=0 lowpriorityscore=0 clxscore=1015 phishscore=0 mlxlogscore=833 priorityscore=1501 bulkscore=0 impostorscore=0 mlxscore=0 malwarescore=0 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2309180000 definitions=main-2310110001 X-Spam-Status: No, score=2.7 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, RCVD_IN_SBL_CSS,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (fry.vger.email [0.0.0.0]); Tue, 10 Oct 2023 17:25:20 -0700 (PDT) X-Spam-Level: ** As part of xHCI bus suspend, the XHCI is halted. However, if there are pending events in the secondary event ring, it is observed that the xHCI controller stops responding to further commands upon host or device initiated bus resume. Iterate through all pending events and update the dequeue pointer to the beginning of the event ring. Signed-off-by: Wesley Cheng --- drivers/usb/host/xhci-mem.c | 13 +++++---- drivers/usb/host/xhci-ring.c | 51 +++++++++++++++++++++++++++++++++++- drivers/usb/host/xhci.c | 2 +- drivers/usb/host/xhci.h | 6 +++++ 4 files changed, 63 insertions(+), 9 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 908b8c9d5837..e6df1cb15e5b 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1815,9 +1815,7 @@ xhci_remove_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir) tmp &= ERST_SIZE_MASK; writel(tmp, &ir->ir_set->erst_size); - tmp64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue); - tmp64 &= (u64) ERST_PTR_MASK; - xhci_write_64(xhci, tmp64, &ir->ir_set->erst_dequeue); + xhci_update_erst_dequeue(xhci, ir, ir->event_ring->first_seg->trbs); } } @@ -1855,11 +1853,12 @@ void xhci_remove_secondary_interrupter(struct usb_hcd *hcd, struct xhci_interrup if (!ir || !ir->intr_num || ir->intr_num >= xhci->max_interrupters) xhci_dbg(xhci, "Invalid secondary interrupter, can't remove\n"); - /* fixme, should we check xhci->interrupter[intr_num] == ir */ - /* fixme locking */ - spin_lock_irq(&xhci->lock); - + /* + * Cleanup secondary interrupter to ensure there are no pending events. + * This also updates event ring dequeue pointer back to the start. + */ + xhci_skip_sec_intr_events(xhci, ir->event_ring, ir); intr_num = ir->intr_num; xhci_remove_interrupter(xhci, ir); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 93233cf5ff21..13080f82406a 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2994,7 +2994,7 @@ static int xhci_handle_event(struct xhci_hcd *xhci, struct xhci_interrupter *ir) * - When all events have finished * - To avoid "Event Ring Full Error" condition */ -static void xhci_update_erst_dequeue(struct xhci_hcd *xhci, +void xhci_update_erst_dequeue(struct xhci_hcd *xhci, struct xhci_interrupter *ir, union xhci_trb *event_ring_deq) { @@ -3026,6 +3026,55 @@ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci, xhci_write_64(xhci, temp_64, &ir->ir_set->erst_dequeue); } +/* + * Move the event ring dequeue pointer to skip events kept in the secondary + * event ring. This is used to ensure that pending events in the ring are + * acknowledged, so the XHCI HCD can properly enter suspend/resume. The + * secondary ring is typically maintained by an external component. + */ +void xhci_skip_sec_intr_events(struct xhci_hcd *xhci, + struct xhci_ring *ring, struct xhci_interrupter *ir) +{ + union xhci_trb *erdp_trb, *current_trb; + struct xhci_segment *seg; + u64 erdp_reg; + u32 iman_reg; + dma_addr_t deq; + unsigned long segment_offset; + + /* disable irq, ack pending interrupt and ack all pending events */ + xhci_disable_interrupter(ir); + iman_reg = readl_relaxed(&ir->ir_set->irq_pending); + if (iman_reg & IMAN_IP) + writel_relaxed(iman_reg, &ir->ir_set->irq_pending); + + /* last acked event trb is in erdp reg */ + erdp_reg = xhci_read_64(xhci, &ir->ir_set->erst_dequeue); + deq = (dma_addr_t)(erdp_reg & ~ERST_PTR_MASK); + if (!deq) { + xhci_dbg(xhci, "event ring handling not required\n"); + return; + } + + seg = ring->first_seg; + segment_offset = deq - seg->dma; + + erdp_trb = current_trb = ir->event_ring->dequeue; + /* read cycle state of the last acked trb to find out CCS */ + ring->cycle_state = le32_to_cpu(current_trb->event_cmd.flags) & TRB_CYCLE; + + while (1) { + inc_deq(xhci, ir->event_ring); + erdp_trb = ir->event_ring->dequeue; + /* cycle state transition */ + if ((le32_to_cpu(erdp_trb->event_cmd.flags) & TRB_CYCLE) != + ring->cycle_state) + break; + } + + xhci_update_erst_dequeue(xhci, ir, current_trb); +} + /* * xHCI spec says we can get an interrupt, and if the HC has an error condition, * we might get bad data out of the event ring. Section 4.10.2.7 has a list of diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 6465acca7c79..f947526ce3ff 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -309,7 +309,7 @@ static int xhci_enable_interrupter(struct xhci_interrupter *ir) return 0; } -static int xhci_disable_interrupter(struct xhci_interrupter *ir) +int xhci_disable_interrupter(struct xhci_interrupter *ir) { u32 iman; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index ce482267e219..9ef375e5c27e 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -2095,6 +2095,9 @@ void xhci_free_container_ctx(struct xhci_hcd *xhci, struct xhci_interrupter *xhci_create_secondary_interrupter(struct usb_hcd *hcd); void xhci_remove_secondary_interrupter(struct usb_hcd *hcd, struct xhci_interrupter *ir); +void xhci_skip_sec_intr_events(struct xhci_hcd *xhci, + struct xhci_ring *ring, struct xhci_interrupter *ir); +int xhci_disable_interrupter(struct xhci_interrupter *ir); /* xHCI host controller glue */ typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); @@ -2180,6 +2183,9 @@ 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, gfp_t gfp_flags); +void xhci_update_erst_dequeue(struct xhci_hcd *xhci, + struct xhci_interrupter *ir, + union xhci_trb *event_ring_deq); /* xHCI roothub code */ void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port,