Browse Source

[xhci] Abort commands on timeout

When a command times out, abort it (via the Command Abort bit in the
Command Ring Control Register) so that subsequent commands may execute
as expected.

This improves robustness when a device fails to respond to the Set
Address command, since the subsequent Disable Slot command will now
succeed.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
645458e5a0
2 changed files with 82 additions and 15 deletions
  1. 69
    13
      src/drivers/usb/xhci.c
  2. 13
    2
      src/drivers/usb/xhci.h

+ 69
- 13
src/drivers/usb/xhci.c View File

@@ -1198,6 +1198,22 @@ static int xhci_ring_alloc ( struct xhci_device *xhci,
1198 1198
 	return rc;
1199 1199
 }
1200 1200
 
1201
+/**
1202
+ * Reset transfer request block ring
1203
+ *
1204
+ * @v ring		TRB ring
1205
+ */
1206
+static void xhci_ring_reset ( struct xhci_trb_ring *ring ) {
1207
+	unsigned int count = ( 1U << ring->shift );
1208
+
1209
+	/* Reset producer and consumer counters */
1210
+	ring->prod = 0;
1211
+	ring->cons = 0;
1212
+
1213
+	/* Reset TRBs (except Link TRB) */
1214
+	memset ( ring->trb, 0, ( count * sizeof ( ring->trb[0] ) ) );
1215
+}
1216
+
1201 1217
 /**
1202 1218
  * Free transfer request block ring
1203 1219
  *
@@ -1574,6 +1590,22 @@ static void xhci_transfer ( struct xhci_device *xhci,
1574 1590
  */
1575 1591
 static void xhci_complete ( struct xhci_device *xhci,
1576 1592
 			    struct xhci_trb_complete *complete ) {
1593
+	int rc;
1594
+
1595
+	/* Ignore "command ring stopped" notifications */
1596
+	if ( complete->code == XHCI_CMPLT_CMD_STOPPED ) {
1597
+		DBGC2 ( xhci, "XHCI %p command ring stopped\n", xhci );
1598
+		return;
1599
+	}
1600
+
1601
+	/* Ignore unexpected completions */
1602
+	if ( ! xhci->pending ) {
1603
+		rc = -ECODE ( complete->code );
1604
+		DBGC ( xhci, "XHCI %p unexpected completion (code %d): %s\n",
1605
+		       xhci, complete->code, strerror ( rc ) );
1606
+		DBGC_HDA ( xhci, 0, complete, sizeof ( *complete ) );
1607
+		return;
1608
+	}
1577 1609
 
1578 1610
 	/* Dequeue command TRB */
1579 1611
 	xhci_dequeue ( &xhci->command );
@@ -1582,15 +1614,9 @@ static void xhci_complete ( struct xhci_device *xhci,
1582 1614
 	assert ( xhci_ring_consumed ( &xhci->command ) ==
1583 1615
 		 le64_to_cpu ( complete->command ) );
1584 1616
 
1585
-	/* Record completion if applicable */
1586
-	if ( xhci->completion ) {
1587
-		memcpy ( xhci->completion, complete,
1588
-			 sizeof ( *xhci->completion ) );
1589
-		xhci->completion = NULL;
1590
-	} else {
1591
-		DBGC ( xhci, "XHCI %p unexpected completion:\n", xhci );
1592
-		DBGC_HDA ( xhci, 0, complete, sizeof ( *complete ) );
1593
-	}
1617
+	/* Record completion */
1618
+	memcpy ( xhci->pending, complete, sizeof ( *xhci->pending ) );
1619
+	xhci->pending = NULL;
1594 1620
 }
1595 1621
 
1596 1622
 /**
@@ -1696,6 +1722,33 @@ static void xhci_event_poll ( struct xhci_device *xhci ) {
1696 1722
 	}
1697 1723
 }
1698 1724
 
1725
+/**
1726
+ * Abort command
1727
+ *
1728
+ * @v xhci		xHCI device
1729
+ */
1730
+static void xhci_abort ( struct xhci_device *xhci ) {
1731
+	physaddr_t crp;
1732
+
1733
+	/* Abort the command */
1734
+	DBGC2 ( xhci, "XHCI %p aborting command\n", xhci );
1735
+	xhci_writeq ( xhci, XHCI_CRCR_CA, xhci->op + XHCI_OP_CRCR );
1736
+
1737
+	/* Allow time for command to abort */
1738
+	mdelay ( XHCI_COMMAND_ABORT_DELAY_MS );
1739
+
1740
+	/* Sanity check */
1741
+	assert ( ( readl ( xhci->op + XHCI_OP_CRCR ) & XHCI_CRCR_CRR ) == 0 );
1742
+
1743
+	/* Consume (and ignore) any final command status */
1744
+	xhci_event_poll ( xhci );
1745
+
1746
+	/* Reset the command ring control register */
1747
+	xhci_ring_reset ( &xhci->command );
1748
+	crp = virt_to_phys ( xhci->command.trb );
1749
+	xhci_writeq ( xhci, ( crp | XHCI_CRCR_RCS ), xhci->op + XHCI_OP_CRCR );
1750
+}
1751
+
1699 1752
 /**
1700 1753
  * Issue command and wait for completion
1701 1754
  *
@@ -1711,8 +1764,8 @@ static int xhci_command ( struct xhci_device *xhci, union xhci_trb *trb ) {
1711 1764
 	unsigned int i;
1712 1765
 	int rc;
1713 1766
 
1714
-	/* Record the completion buffer */
1715
-	xhci->completion = trb;
1767
+	/* Record the pending command */
1768
+	xhci->pending = trb;
1716 1769
 
1717 1770
 	/* Enqueue the command */
1718 1771
 	if ( ( rc = xhci_enqueue ( &xhci->command, NULL, trb ) ) != 0 )
@@ -1728,7 +1781,7 @@ static int xhci_command ( struct xhci_device *xhci, union xhci_trb *trb ) {
1728 1781
 		xhci_event_poll ( xhci );
1729 1782
 
1730 1783
 		/* Check for completion */
1731
-		if ( ! xhci->completion ) {
1784
+		if ( ! xhci->pending ) {
1732 1785
 			if ( complete->code != XHCI_CMPLT_SUCCESS ) {
1733 1786
 				rc = -ECODE ( complete->code );
1734 1787
 				DBGC ( xhci, "XHCI %p command failed (code "
@@ -1748,8 +1801,11 @@ static int xhci_command ( struct xhci_device *xhci, union xhci_trb *trb ) {
1748 1801
 	DBGC ( xhci, "XHCI %p timed out waiting for completion\n", xhci );
1749 1802
 	rc = -ETIMEDOUT;
1750 1803
 
1804
+	/* Abort command */
1805
+	xhci_abort ( xhci );
1806
+
1751 1807
  err_enqueue:
1752
-	xhci->completion = NULL;
1808
+	xhci->pending = NULL;
1753 1809
 	return rc;
1754 1810
 }
1755 1811
 

+ 13
- 2
src/drivers/usb/xhci.h View File

@@ -178,6 +178,9 @@ enum xhci_default_psi_value {
178 178
 /** Command ring cycle state */
179 179
 #define XHCI_CRCR_RCS 0x00000001UL
180 180
 
181
+/** Command abort */
182
+#define XHCI_CRCR_CA 0x00000004UL
183
+
181 184
 /** Command ring running */
182 185
 #define XHCI_CRCR_CRR 0x00000008UL
183 186
 
@@ -629,6 +632,8 @@ enum xhci_completion_code {
629 632
 	XHCI_CMPLT_SUCCESS = 1,
630 633
 	/** Short packet */
631 634
 	XHCI_CMPLT_SHORT = 13,
635
+	/** Command ring stopped */
636
+	XHCI_CMPLT_CMD_STOPPED = 24,
632 637
 };
633 638
 
634 639
 /** A port status change transfer request block */
@@ -987,6 +992,12 @@ xhci_ring_consumed ( struct xhci_trb_ring *ring ) {
987 992
  */
988 993
 #define XHCI_COMMAND_MAX_WAIT_MS 500
989 994
 
995
+/** Time to delay after aborting a command
996
+ *
997
+ * This is a policy decision
998
+ */
999
+#define XHCI_COMMAND_ABORT_DELAY_MS 500
1000
+
990 1001
 /** Maximum time to wait for a port reset to complete
991 1002
  *
992 1003
  * This is a policy decision.
@@ -1042,8 +1053,8 @@ struct xhci_device {
1042 1053
 	struct xhci_trb_ring command;
1043 1054
 	/** Event ring */
1044 1055
 	struct xhci_event_ring event;
1045
-	/** Current command completion buffer (if any) */
1046
-	union xhci_trb *completion;
1056
+	/** Current command (if any) */
1057
+	union xhci_trb *pending;
1047 1058
 
1048 1059
 	/** Device slots, indexed by slot ID */
1049 1060
 	struct xhci_slot **slot;

Loading…
Cancel
Save