From 78bc8425c0c4162848aa056708b79900e332f43a Mon Sep 17 00:00:00 2001
From: Greg Crain <gcrain70@gmail.com>
Date: Wed, 8 Nov 2017 08:12:08 -0500
Subject: [PATCH] xhci: Transfer complete semaphore was not being released.
The 'fFinishTransfersSem' semaphore is timing out and not being
released after a successful transfer due to an off by 1 offset.
Quad word in command transfer was not cleared and sometimes
contained garbage.
Add some additional debugging output.
---
src/add-ons/kernel/busses/usb/xhci.cpp | 34 ++++++++++++++++-----------
src/add-ons/kernel/busses/usb/xhci_hardware.h | 4 ++++
2 files changed, 24 insertions(+), 14 deletions(-)
diff --git a/src/add-ons/kernel/busses/usb/xhci.cpp b/src/add-ons/kernel/busses/usb/xhci.cpp
index 6009621..605c207 100644
a
|
b
|
|
1 | 1 | /* |
2 | | * Copyright 2006-2014, Haiku Inc. All rights reserved. |
| 2 | * Copyright 2006-2017, Haiku Inc. All rights reserved. |
3 | 3 | * Distributed under the terms of the MIT License. |
4 | 4 | * |
5 | 5 | * Some code borrowed from the Haiku EHCI driver |
… |
… |
XHCI::Start()
|
517 | 517 | dmaAddress += sizeof(xhci_erst_element) + XHCI_MAX_EVENTS |
518 | 518 | * sizeof(xhci_trb); |
519 | 519 | TRACE("setting CRCR addr = 0x%" B_PRIxPHYSADDR "\n", dmaAddress); |
| 520 | //Make sure Command Ring is stopped |
| 521 | WriteOpReg(XHCI_CRCR_LO, CRCR_CA ); |
520 | 522 | WriteOpReg(XHCI_CRCR_LO, (uint32)dmaAddress | CRCR_RCS); |
521 | 523 | WriteOpReg(XHCI_CRCR_HI, /*(uint32)(dmaAddress >> 32)*/0); |
522 | 524 | // link trb |
… |
… |
XHCI::Start()
|
566 | 568 | SetRootHub(fRootHub); |
567 | 569 | |
568 | 570 | TRACE_ALWAYS("successfully started the controller\n"); |
569 | | #ifdef TRACE_USB |
| 571 | //#ifdef TRACE_USB |
| 572 | #if 1 |
570 | 573 | TRACE("No-Op test...\n"); |
571 | 574 | status_t noopResult = Noop(); |
572 | | TRACE("No-Op %ssuccessful\n", noopResult < B_OK ? "un" : ""); |
| 575 | TRACE_ALWAYS("No-Op %ssuccessful\n", noopResult < B_OK ? "un" : ""); |
573 | 576 | #endif |
574 | 577 | |
575 | 578 | //DumpRing(fCmdRing, (XHCI_MAX_COMMANDS - 1)); |
… |
… |
XHCI::SubmitControlRequest(Transfer *transfer)
|
637 | 640 | } |
638 | 641 | |
639 | 642 | // set StatusStage |
| 643 | setupDescriptor->trbs[index].qwtrb0 = 0; |
640 | 644 | setupDescriptor->trbs[index].dwtrb2 = TRB_2_IRQ(0); |
641 | 645 | setupDescriptor->trbs[index].dwtrb3 = B_HOST_TO_LENDIAN_INT32( |
642 | 646 | TRB_3_TYPE(TRB_TYPE_STATUS_STAGE) |
… |
… |
XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
1095 | 1099 | |
1096 | 1100 | uint8 slot = XHCI_MAX_SLOTS; |
1097 | 1101 | if (EnableSlot(&slot) != B_OK) { |
1098 | | TRACE_ERROR("AllocateDevice() failed enable slot\n"); |
| 1102 | TRACE_ERROR("AllocateDevice() failed enable slot %d\n",slot); |
1099 | 1103 | return NULL; |
| 1104 | } else { |
| 1105 | TRACE_ALWAYS("EnableSlot %d\n",slot); |
1100 | 1106 | } |
1101 | 1107 | |
1102 | 1108 | if (slot == 0 || slot > fSlotCount) { |
… |
… |
XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
1310 | 1316 | return NULL; |
1311 | 1317 | } |
1312 | 1318 | |
1313 | | TRACE("device_class: %d device_subclass %d device_protocol %d\n", |
| 1319 | TRACE_ALWAYS("device_class: %d device_subclass %d device_protocol %d\n", |
1314 | 1320 | deviceDescriptor.device_class, deviceDescriptor.device_subclass, |
1315 | 1321 | deviceDescriptor.device_protocol); |
1316 | 1322 | |
… |
… |
XHCI::_LinkDescriptorForPipe(xhci_td *descriptor, xhci_endpoint *endpoint)
|
1525 | 1531 | TRACE("_LinkDescriptorForPipe\n"); |
1526 | 1532 | MutexLocker endpointLocker(endpoint->lock); |
1527 | 1533 | if (endpoint->used >= XHCI_MAX_TRANSFERS) { |
1528 | | TRACE_ERROR("_LinkDescriptorForPipe max transfers count exceeded\n"); |
| 1534 | TRACE_ERROR("_LinkDescriptorForPipe max transfers count exceeded %d\n",endpoint->used ); |
| 1535 | //Seem to have a problem with interupts not occuring when this happens |
| 1536 | //and endpoints are not being freed. |
1529 | 1537 | return B_BAD_VALUE; |
1530 | 1538 | } |
1531 | 1539 | |
… |
… |
XHCI::SetPortFeature(uint8 index, uint16 feature)
|
1812 | 1820 | default: |
1813 | 1821 | return B_BAD_VALUE; |
1814 | 1822 | } |
1815 | | ReadOpReg(portRegister); |
1816 | 1823 | return B_OK; |
1817 | 1824 | } |
1818 | 1825 | |
… |
… |
XHCI::ClearPortFeature(uint8 index, uint16 feature)
|
1861 | 1868 | return B_BAD_VALUE; |
1862 | 1869 | } |
1863 | 1870 | |
1864 | | ReadOpReg(portRegister); |
1865 | 1871 | return B_OK; |
1866 | 1872 | } |
1867 | 1873 | |
… |
… |
XHCI::ControllerReset()
|
1893 | 1899 | while (ReadOpReg(XHCI_CMD) & CMD_HCRST) { |
1894 | 1900 | snooze(1000); |
1895 | 1901 | if (tries-- < 0) { |
1896 | | TRACE("ControllerReset() failed CMD_HCRST\n"); |
| 1902 | TRACE_ERROR("ControllerReset() failed CMD_HCRST\n"); |
1897 | 1903 | return B_ERROR; |
1898 | 1904 | } |
1899 | 1905 | } |
… |
… |
XHCI::ControllerReset()
|
1902 | 1908 | while (ReadOpReg(XHCI_STS) & STS_CNR) { |
1903 | 1909 | snooze(1000); |
1904 | 1910 | if (tries-- < 0) { |
1905 | | TRACE("ControllerReset() failed STS_CNR\n"); |
| 1911 | TRACE_ERROR("ControllerReset() failed STS_CNR\n"); |
1906 | 1912 | return B_ERROR; |
1907 | 1913 | } |
1908 | 1914 | } |
… |
… |
XHCI::HandleTransferComplete(xhci_trb* trb)
|
2051 | 2057 | int64 offset = source - td_chain->this_phy; |
2052 | 2058 | TRACE("HandleTransferComplete td %p offset %" B_PRId64 " %" |
2053 | 2059 | B_PRIxADDR "\n", td_chain, offset, source); |
2054 | | offset = offset / sizeof(xhci_trb); |
| 2060 | offset = offset / sizeof(xhci_trb) +1; |
2055 | 2061 | if (offset <= td_chain->trb_count && offset >= 0) { |
2056 | 2062 | TRACE("HandleTransferComplete td %p trb %" B_PRId64 " found " |
2057 | 2063 | "\n", td_chain, offset); |
… |
… |
XHCI::DoCommand(xhci_trb* trb)
|
2129 | 2135 | |
2130 | 2136 | trb->dwtrb2 = fCmdResult[0]; |
2131 | 2137 | trb->dwtrb3 = fCmdResult[1]; |
2132 | | TRACE("Storing trb 0x%08" B_PRIx32 " 0x%08" B_PRIx32 "\n", trb->dwtrb2, |
| 2138 | TRACE("Storing command trb 0x%08" B_PRIx32 " 0x%08" B_PRIx32 "\n", trb->dwtrb2, |
2133 | 2139 | trb->dwtrb3); |
2134 | 2140 | |
2135 | 2141 | Unlock(); |
… |
… |
XHCI::EnableSlot(uint8* slot)
|
2171 | 2177 | status_t |
2172 | 2178 | XHCI::DisableSlot(uint8 slot) |
2173 | 2179 | { |
2174 | | TRACE("Disable Slot\n"); |
| 2180 | TRACE("Disable Slot %d\n", slot); |
2175 | 2181 | xhci_trb trb; |
2176 | 2182 | trb.qwtrb0 = 0; |
2177 | 2183 | trb.dwtrb2 = 0; |
… |
… |
XHCI::DisableSlot(uint8 slot)
|
2184 | 2190 | status_t |
2185 | 2191 | XHCI::SetAddress(uint64 inputContext, bool bsr, uint8 slot) |
2186 | 2192 | { |
2187 | | TRACE("Set Address\n"); |
| 2193 | TRACE_ALWAYS("Set Address slot %d 0x%016" B_PRIx64 "\n", slot, inputContext); |
2188 | 2194 | xhci_trb trb; |
2189 | 2195 | trb.qwtrb0 = inputContext; |
2190 | 2196 | trb.dwtrb2 = 0; |
diff --git a/src/add-ons/kernel/busses/usb/xhci_hardware.h b/src/add-ons/kernel/busses/usb/xhci_hardware.h
index a9619d9..bfe9356 100644
a
|
b
|
|
91 | 91 | #define XHCI_CRCR_LO 0x18 |
92 | 92 | #define XHCI_CRCR_HI 0x1C |
93 | 93 | #define CRCR_RCS (1<<0) |
| 94 | #define CRCR_CS (1<<1) |
| 95 | #define CRCR_CA (1<<2) |
| 96 | #define CRCR_CRR (1<<3) |
| 97 | |
94 | 98 | // Section 5.4.6 |
95 | 99 | #define XHCI_DCBAAP_LO 0x30 |
96 | 100 | #define XHCI_DCBAAP_HI 0x34 |