From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S942138AbcLWGxG (ORCPT ); Fri, 23 Dec 2016 01:53:06 -0500 Received: from mga06.intel.com ([134.134.136.31]:56654 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758193AbcLWGxE (ORCPT ); Fri, 23 Dec 2016 01:53:04 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,392,1477983600"; d="scan'208";a="1085826013" From: Lu Baolu To: Mathias Nyman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH 2/4] usb: xhci: remove CRR polling in xhci_abort_cmd_ring() Date: Fri, 23 Dec 2016 14:52:56 +0800 Message-Id: <1482475978-18203-3-git-send-email-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1482475978-18203-1-git-send-email-baolu.lu@linux.intel.com> References: <1482475978-18203-1-git-send-email-baolu.lu@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org xHCI driver aborts the command ring by setting CA (Command Abort) bit in the command register. With this setting, host should abort all command executions and generate a command completion event with the completion code set to command ring stopped. Software should time the completion of command abort by checking the CRR (Command Ring Running) and waiting for the command ring stopped event. Current xhci_abort_cmd_ring() does this in the following way: setting CA bit; busy polling CRR bit until it negates; sleep and wait for the command ring stopped event. This is not an efficient way since cpu cycles are wasted on polling registers. This patch removes polling for CRR (Command Ring Running). Wait for completion, and check CRR if completion times out is enough. Suggested-by: Mathias Nyman Signed-off-by: Lu Baolu --- drivers/usb/host/xhci-ring.c | 49 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index e3bcf6d..5935dce 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -323,7 +323,6 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long *flags) { unsigned long timeleft; u64 temp_64; - int ret; xhci_dbg(xhci, "Abort command ring\n"); @@ -333,34 +332,34 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long *flags) xhci_write_64(xhci, temp_64 | CMD_RING_ABORT, &xhci->op_regs->cmd_ring); - /* Section 4.6.1.2 of xHCI 1.0 spec says software should - * time the completion od all xHCI commands, including - * the Command Abort operation. If software doesn't see - * CRR negated in a timely manner (e.g. longer than 5 - * seconds), then it should assume that the there are - * larger problems with the xHC and assert HCRST. - */ - ret = xhci_handshake(&xhci->op_regs->cmd_ring, - CMD_RING_RUNNING, 0, 5 * 1000 * 1000); - if (ret < 0) { - xhci_err(xhci, - "Stop command ring failed, maybe the host is dead\n"); - xhci->xhc_state |= XHCI_STATE_DYING; - xhci_halt(xhci); - return -ESHUTDOWN; - } - /* - * Writing the CMD_RING_ABORT bit should cause a cmd completion event, - * however on some host hw the CMD_RING_RUNNING bit is correctly cleared - * but the completion event in never sent. Wait 2 secs (arbitrary - * number) to handle those cases after negation of CMD_RING_RUNNING. - */ spin_unlock_irqrestore(&xhci->lock, *flags); timeleft = wait_for_completion_timeout(&xhci->cmd_ring_stop_completion, - 2 * HZ); + XHCI_CMD_DEFAULT_TIMEOUT); spin_lock_irqsave(&xhci->lock, *flags); if (!timeleft) { - xhci_dbg(xhci, "No stop event for abort, ring start fail?\n"); + /* Section 4.6.1.2 of xHCI 1.0 spec says software should + * time the completion of all xHCI commands, including + * the Command Abort operation. If software doesn't see + * CRR negated in a timely manner (e.g. longer than 5 + * seconds), then it should assume that the there are + * larger problems with the xHC and assert HCRST. + */ + temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); + if (temp_64 & CMD_RING_RUNNING) { + xhci_err(xhci, + "Stop command ring failed, maybe the host is dead\n"); + xhci->xhc_state |= XHCI_STATE_DYING; + xhci_halt(xhci); + return -ESHUTDOWN; + } + + /* + * Writing the CMD_RING_ABORT bit should cause a cmd + * completion event, however on some hosts the bit is + * correctly cleared but the completion event is never + * sent. + */ + xhci_warn(xhci, "No stop event for abort, ring start fail?\n"); xhci_cleanup_command_queue(xhci); } else { xhci_handle_stopped_cmd_ring(xhci, xhci_next_queued_cmd(xhci)); -- 2.1.4