Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1546758 > unrolled thread

[PATCH 1/1] usb: xhci: hold lock over xhci_abort_cmd_ring()

Started byLu Baolu <baolu.lu@linux.intel.com>
First post2016-12-23 07:50 +0100
Last post2016-12-23 13:20 +0100
Articles 2 — 2 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH 1/1] usb: xhci: hold lock over xhci_abort_cmd_ring() Lu Baolu <baolu.lu@linux.intel.com> - 2016-12-23 07:50 +0100
    Re: [PATCH 1/1] usb: xhci: hold lock over xhci_abort_cmd_ring() Mathias Nyman <mathias.nyman@linux.intel.com> - 2016-12-23 13:20 +0100

#1546758 — [PATCH 1/1] usb: xhci: hold lock over xhci_abort_cmd_ring()

FromLu Baolu <baolu.lu@linux.intel.com>
Date2016-12-23 07:50 +0100
Subject[PATCH 1/1] usb: xhci: hold lock over xhci_abort_cmd_ring()
Message-ID<sRrPX-3nH-1@gated-at.bofh.it>
In command timer function, xhci_handle_command_timeout(), xhci->lock
is unlocked before call into xhci_abort_cmd_ring(). This might cause
race between the timer function and the event handler.

The xhci_abort_cmd_ring() function sets the CMD_RING_ABORT bit in the
command register and polling it until the setting takes effect. A stop
command ring event might be handled between writing the abort bit and
polling for it. The event handler will restart the command ring, which
causes the failure of polling, and we ever believed that we failed to
stop it.

As a bonus, this also fixes some issues of calling functions without
locking in xhci_handle_command_timeout().

Cc: <stable@vger.kernel.org> # 3.7+
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
 drivers/usb/host/xhci-ring.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 797137e..0f99078 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1283,29 +1283,34 @@ void xhci_handle_command_timeout(unsigned long data)
 	hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
 	if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) &&
 	    (hw_ring_state & CMD_RING_RUNNING))  {
-		spin_unlock_irqrestore(&xhci->lock, flags);
 		xhci_dbg(xhci, "Command timeout\n");
 		ret = xhci_abort_cmd_ring(xhci);
 		if (unlikely(ret == -ESHUTDOWN)) {
 			xhci_err(xhci, "Abort command ring failed\n");
 			xhci_cleanup_command_queue(xhci);
+			spin_unlock_irqrestore(&xhci->lock, flags);
 			usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
 			xhci_dbg(xhci, "xHCI host controller is dead.\n");
+
+			return;
 		}
-		return;
+
+		goto time_out_completed;
 	}
 
 	/* command ring failed to restart, or host removed. Bail out */
 	if (second_timeout || xhci->xhc_state & XHCI_STATE_REMOVING) {
-		spin_unlock_irqrestore(&xhci->lock, flags);
 		xhci_dbg(xhci, "command timed out twice, ring start fail?\n");
 		xhci_cleanup_command_queue(xhci);
-		return;
+
+		goto time_out_completed;
 	}
 
 	/* command timeout on stopped ring, ring can't be aborted */
 	xhci_dbg(xhci, "Command timeout on stopped ring\n");
 	xhci_handle_stopped_cmd_ring(xhci, xhci->current_cmd);
+
+time_out_completed:
 	spin_unlock_irqrestore(&xhci->lock, flags);
 	return;
 }
-- 
2.1.4

[toc] | [next] | [standalone]


#1546849

FromMathias Nyman <mathias.nyman@linux.intel.com>
Date2016-12-23 13:20 +0100
Message-ID<sRwZj-6Li-15@gated-at.bofh.it>
In reply to#1546758
On 23.12.2016 08:46, Lu Baolu wrote:
> In command timer function, xhci_handle_command_timeout(), xhci->lock
> is unlocked before call into xhci_abort_cmd_ring(). This might cause
> race between the timer function and the event handler.
>
> The xhci_abort_cmd_ring() function sets the CMD_RING_ABORT bit in the
> command register and polling it until the setting takes effect. A stop
> command ring event might be handled between writing the abort bit and
> polling for it. The event handler will restart the command ring, which
> causes the failure of polling, and we ever believed that we failed to
> stop it.
>
> As a bonus, this also fixes some issues of calling functions without
> locking in xhci_handle_command_timeout().
>

Did the same thing, moved the unlock to cover also abort_cmd_ring(),

but this one takes care of locking the command ring cleanup as well
so I'll pick up this instead

-Mathias

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web