Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp4473910ybz; Tue, 28 Apr 2020 11:54:53 -0700 (PDT) X-Google-Smtp-Source: APiQypIzGxL5Zu8mc706x+zCnRj35dcYRtCAjxvJzjjLtNKVrdL5FuRhSLXIV3sQigzz6J7YhBOm X-Received: by 2002:a17:906:54cd:: with SMTP id c13mr25033706ejp.307.1588100093096; Tue, 28 Apr 2020 11:54:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1588100093; cv=none; d=google.com; s=arc-20160816; b=wLlaukO81rDhR3Gcwe04JpDowDToa6/D72fJt+pAez6tGiZlQoErSQgh9mcgkmKDqb adzty8WEokgtXrrisFnzopXo8nGkgsNI0/js7B0WZceLtuzjROH1HYjLp33+ugY9ufb0 Yf0pSwdaOHeeqyoQEyrd4zolR18zfM8dReef7nPrj4XD5Mn4FTTIVe2pDMgN2CF6Hh/I x+xIoWImrwkOd96TO/Oy0dax2yUj3QWjn+oVTT894pDjj86mNq9XgGS4H/GmaNOkd2O1 aO8u9AtC1SugmWFMkpQg6wyp+uM5XdWomA3kShReNsKdXW8W88X3dPge0dewi8YH81jB 7N+Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=6FGYn6B7Z2jLb3QEVCXPGAyt5T8HzBndRVGu5S+po/g=; b=zmBYsB62TthE6R8O1i+C7yca/apd3eRn7FGuuBX//DA3u+az5JpMi3OjxPE9VqGRB+ vaUlsNtGrtcsXAh5ycY77vp7dU6nEdEy65hfU4bXiY/sL5YCBdIfcI4hAr8tb/UEavX7 2eNSpbx0vw6QVBdBildkHm2Ag2+Al8GnXX0lDLJjco39zRs0/1UweIVlJzjaiUJdVNDc cva+iMytixVadMid2Iwq0e30gLVlp9aafco/uVAFCwSNfoHUX6iQ/3e9P352wwrk2eZi JWVKyutqhwA3Tz/nk8CvfH6AJ4K2x3OHxQ5IoHPeT7oy76L+OyWXAIp+uuxVOpWcpkqk 9mmQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=DxMD20oZ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id x14si1903829ede.22.2020.04.28.11.54.29; Tue, 28 Apr 2020 11:54:53 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=DxMD20oZ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730592AbgD1SiH (ORCPT + 99 others); Tue, 28 Apr 2020 14:38:07 -0400 Received: from mail.kernel.org ([198.145.29.99]:56426 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730573AbgD1SiF (ORCPT ); Tue, 28 Apr 2020 14:38:05 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 5BC2F20B1F; Tue, 28 Apr 2020 18:38:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1588099084; bh=U6hfCKu4VrLDOD8g9QDkTLm3FSi8gFvlg1e705NQIHI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DxMD20oZDoE4N+tkhC8j+5gK4LIAFg15LOzYVmjcaUOx73HpMU5kOtlZOASYC/M2f IbliQY7DS15mbt3bByzPaF/NeTTHgijA7a51UzAyqQMky5dldsbflnBMQdhz7r68nZ tJyKksBzn3QlrFXLm8psNKlA69gxlneBDW7N4ARI= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jeremy Compostella , Mathias Nyman Subject: [PATCH 5.6 153/167] xhci: Fix handling halted endpoint even if endpoint ring appears empty Date: Tue, 28 Apr 2020 20:25:29 +0200 Message-Id: <20200428182244.916228870@linuxfoundation.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200428182225.451225420@linuxfoundation.org> References: <20200428182225.451225420@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Mathias Nyman commit 93ceaa808e8defc67ebca1396e2f42f812a2efc0 upstream. If a class driver cancels its only URB then the endpoint ring buffer will appear empty to the xhci driver. xHC hardware may still process cached TRBs, and complete with a STALL, halting the endpoint. This halted endpoint was not handled correctly by xhci driver as events on empty rings were all assumed to be spurious events. xhci driver refused to restart the ring with EP_HALTED flag set, so class driver was never informed the endpoint halted even if it queued new URBs. The host side of the endpoint needs to be reset, and dequeue pointer should be moved in order to clear the cached TRBs and resetart the endpoint. Small adjustments in finding the new dequeue pointer are needed to support the case of stall on an empty ring and unknown current TD. Cc: cc: Jeremy Compostella Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20200421140822.28233-2-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 30 +++++++++++++++++++++++++++++- drivers/usb/host/xhci.c | 14 +++++++------- drivers/usb/host/xhci.h | 5 +++-- 3 files changed, 39 insertions(+), 10 deletions(-) --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -547,6 +547,23 @@ void xhci_find_new_dequeue_state(struct stream_id); return; } + /* + * A cancelled TD can complete with a stall if HW cached the trb. + * In this case driver can't find cur_td, but if the ring is empty we + * can move the dequeue pointer to the current enqueue position. + */ + if (!cur_td) { + if (list_empty(&ep_ring->td_list)) { + state->new_deq_seg = ep_ring->enq_seg; + state->new_deq_ptr = ep_ring->enqueue; + state->new_cycle_state = ep_ring->cycle_state; + goto done; + } else { + xhci_warn(xhci, "Can't find new dequeue state, missing cur_td\n"); + return; + } + } + /* Dig out the cycle state saved by the xHC during the stop ep cmd */ xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, "Finding endpoint context"); @@ -592,6 +609,7 @@ void xhci_find_new_dequeue_state(struct state->new_deq_seg = new_seg; state->new_deq_ptr = new_deq; +done: /* Don't update the ring cycle state for the producer (us). */ xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, "Cycle state = 0x%x", state->new_cycle_state); @@ -1852,7 +1870,8 @@ static void xhci_cleanup_halted_endpoint if (reset_type == EP_HARD_RESET) { ep->ep_state |= EP_HARD_CLEAR_TOGGLE; - xhci_cleanup_stalled_ring(xhci, ep_index, stream_id, td); + xhci_cleanup_stalled_ring(xhci, slot_id, ep_index, stream_id, + td); xhci_clear_hub_tt_buffer(xhci, td, ep); } xhci_ring_cmd_db(xhci); @@ -2531,6 +2550,15 @@ static int handle_tx_event(struct xhci_h xhci_dbg(xhci, "td_list is empty while skip flag set. Clear skip flag for slot %u ep %u.\n", slot_id, ep_index); } + if (trb_comp_code == COMP_STALL_ERROR || + xhci_requires_manual_halt_cleanup(xhci, ep_ctx, + trb_comp_code)) { + xhci_cleanup_halted_endpoint(xhci, slot_id, + ep_index, + ep_ring->stream_id, + NULL, + EP_HARD_RESET); + } goto cleanup; } --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3031,19 +3031,19 @@ static void xhci_setup_input_ctx_for_qui added_ctxs, added_ctxs); } -void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index, - unsigned int stream_id, struct xhci_td *td) +void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int slot_id, + unsigned int ep_index, unsigned int stream_id, + struct xhci_td *td) { struct xhci_dequeue_state deq_state; - struct usb_device *udev = td->urb->dev; xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep, "Cleaning up stalled endpoint ring"); /* We need to move the HW's dequeue pointer past this TD, * or it will attempt to resend it on the next doorbell ring. */ - xhci_find_new_dequeue_state(xhci, udev->slot_id, - ep_index, stream_id, td, &deq_state); + xhci_find_new_dequeue_state(xhci, slot_id, ep_index, stream_id, td, + &deq_state); if (!deq_state.new_deq_ptr || !deq_state.new_deq_seg) return; @@ -3054,7 +3054,7 @@ void xhci_cleanup_stalled_ring(struct xh if (!(xhci->quirks & XHCI_RESET_EP_QUIRK)) { xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep, "Queueing new dequeue state"); - xhci_queue_new_dequeue_state(xhci, udev->slot_id, + xhci_queue_new_dequeue_state(xhci, slot_id, ep_index, &deq_state); } else { /* Better hope no one uses the input context between now and the @@ -3065,7 +3065,7 @@ void xhci_cleanup_stalled_ring(struct xh xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "Setting up input context for " "configure endpoint command"); - xhci_setup_input_ctx_for_quirk(xhci, udev->slot_id, + xhci_setup_input_ctx_for_quirk(xhci, slot_id, ep_index, &deq_state); } } --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -2116,8 +2116,9 @@ void xhci_find_new_dequeue_state(struct void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, struct xhci_dequeue_state *deq_state); -void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index, - unsigned int stream_id, struct xhci_td *td); +void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int slot_id, + unsigned int ep_index, unsigned int stream_id, + struct xhci_td *td); void xhci_stop_endpoint_command_watchdog(struct timer_list *t); void xhci_handle_command_timeout(struct work_struct *work);