|
@@ -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
|
|