hrev52990 adds 5 changesets to branch 'master'
old head: d51c92f8724e5d4d81e65d8e0d63ad0ed8f73cf4
new head: 19151d0134b448de0cf51c152629586f8c9b1dd6
overview:
https://git.haiku-os.org/haiku/log/?qt=range&q=19151d0134b4+%5Ed51c92f8724e
----------------------------------------------------------------------------
1d79fe616f62: XHCI: Implement CancelQueuedTransfers and RemoveEndpointForPipe.
Seems to work OK on my hardware now. Possibly helps with device unplug/replug
issues; though that worked on my hardware before this change, too. This is
now more correct at least.
dda9c0278969: XHCI: Use MutexLocker in HandleTransferComplete.
4d03f448749d: multi_audio_test: Fix the build.
d592cab849ae: usb_webcam: We won't be building for Zeta.
19151d0134b4: usb_audio: Clean up and fix device management code.
* Actually use the global mutex instead of creating useless MutexLockers.
* Don't delete the device object on _free(), then it can't be opened again,
which we want to be possible. Matches the behavior of other audio drivers.
* Clean up device detection code to better match other drivers.
At least under XHCI, multi_audio_test throws a variety of errors and then
crashes while attempting to use this driver. But following implementing
CancelQueuedTransfers, the system no longer KDLs after that. Progress!
[ Augustin Cavalier <waddlesplash@xxxxxxxxx> ]
----------------------------------------------------------------------------
5 files changed, 110 insertions(+), 44 deletions(-)
src/add-ons/kernel/busses/usb/xhci.cpp | 101 +++++++++++++++++--
src/add-ons/kernel/drivers/audio/usb/Driver.cpp | 37 +++----
.../media/media-add-ons/usb_webcam/Jamfile | 12 +--
src/tests/add-ons/kernel/drivers/audio/Jamfile | 2 +-
.../kernel/drivers/audio/multi_audio_test.cpp | 2 +-
############################################################################
Commit: 1d79fe616f62046c964bad789ea0324431272dd4
URL: https://git.haiku-os.org/haiku/commit/?id=1d79fe616f62
Author: Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date: Wed Mar 13 04:09:39 2019 UTC
XHCI: Implement CancelQueuedTransfers and RemoveEndpointForPipe.
Seems to work OK on my hardware now. Possibly helps with device unplug/replug
issues; though that worked on my hardware before this change, too. This is
now more correct at least.
----------------------------------------------------------------------------
diff --git a/src/add-ons/kernel/busses/usb/xhci.cpp
b/src/add-ons/kernel/busses/usb/xhci.cpp
index 6d1489a283..f60ca296f4 100644
--- a/src/add-ons/kernel/busses/usb/xhci.cpp
+++ b/src/add-ons/kernel/busses/usb/xhci.cpp
@@ -862,6 +862,61 @@ XHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
{
TRACE_ALWAYS("cancel queued transfers for pipe %p (%d)\n", pipe,
pipe->EndpointAddress());
+
+ xhci_endpoint *endpoint = (xhci_endpoint *)pipe->ControllerCookie();
+ if (endpoint == NULL || endpoint->trbs == NULL) {
+ // Someone's de-allocated this pipe or endpoint in the meantime.
+ // (Possibly AllocateDevice failed, and we were the temporary
pipe.)
+ return B_NO_INIT;
+ }
+
+ MutexLocker endpointLocker(endpoint->lock);
+
+ if (endpoint->td_head == NULL) {
+ // There aren't any currently pending transfers to cancel.
+ return B_OK;
+ }
+
+ // Get the head TD from the endpoint. We don't want to free the TDs
while
+ // holding the endpoint lock, as the callbacks could potentially cause
+ // deadlocks.
+ xhci_td* td_head = endpoint->td_head;
+ endpoint->td_head = NULL;
+
+ if (StopEndpoint(false, endpoint->id + 1, endpoint->device->slot) ==
B_OK) {
+ // Clear the endpoint's TRBs.
+ memset(endpoint->trbs, 0, sizeof(xhci_trb) *
XHCI_MAX_TRANSFERS);
+ endpoint->used = 0;
+ endpoint->current = 0;
+
+ // Set dequeue pointer location to the beginning of the ring.
+ SetTRDequeue(endpoint->trb_addr, 0, endpoint->id + 1,
+ endpoint->device->slot);
+
+ // We don't need to do anything else to restart the ring, as it
will resume
+ // operation as normal upon the next doorbell. (XHCI 1.1 §
4.6.9 p132.)
+ } else {
+ // We couldn't stop the endpoint. Most likely the device has
been
+ // removed and the endpoint was stopped by the hardware.
+ TRACE("CancelQueuedTransfers: could not stop endpoint\n");
+ }
+
+ endpointLocker.Unlock();
+
+ xhci_td* td;
+ while ((td = td_head) != NULL) {
+ td_head = td_head->next;
+
+ // We can't cancel or delete transfers under "force", as they
probably
+ // are not safe to use anymore.
+ if (!force && td->transfer != NULL) {
+ td->transfer->Finished(B_CANCELED, 0);
+ delete td->transfer;
+ td->transfer = NULL;
+ }
+ FreeDescriptor(td);
+ }
+
return B_OK;
}
@@ -1486,6 +1541,11 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8
hubPort,
device->state = XHCI_STATE_DISABLED;
return NULL;
}
+
+ // We don't want to disable the default endpoint, naturally, which would
+ // otherwise happen when this Pipe object is destroyed.
+ pipe.SetControllerCookie(NULL);
+
fPortSlots[hubPort] = slot;
TRACE("AllocateDevice() port %d slot %d\n", hubPort, slot);
return deviceObject;
@@ -1517,8 +1577,7 @@ XHCI::FreeDevice(Device *device)
status_t
XHCI::_InsertEndpointForPipe(Pipe *pipe)
{
- TRACE("_InsertEndpointForPipe endpoint address %" B_PRId8 "\n",
- pipe->EndpointAddress());
+ TRACE("insert endpoint for pipe %p (%d)\n", pipe,
pipe->EndpointAddress());
if (pipe->ControllerCookie() != NULL
|| pipe->Parent()->Type() != USB_OBJECT_DEVICE) {
@@ -1618,9 +1677,40 @@ XHCI::_InsertEndpointForPipe(Pipe *pipe)
status_t
XHCI::_RemoveEndpointForPipe(Pipe *pipe)
{
+ TRACE("remove endpoint for pipe %p (%d)\n", pipe,
pipe->EndpointAddress());
+
if (pipe->Parent()->Type() != USB_OBJECT_DEVICE)
return B_OK;
- //Device* device = (Device *)pipe->Parent();
+ Device* usbDevice = (Device *)pipe->Parent();
+ if (usbDevice->Parent() == RootObject())
+ return B_BAD_VALUE;
+
+ xhci_endpoint *endpoint = (xhci_endpoint *)pipe->ControllerCookie();
+ if (endpoint == NULL || endpoint->trbs == NULL)
+ return B_NO_INIT;
+
+ xhci_device *device = endpoint->device;
+
+ if (endpoint->id > 0) {
+ mutex_lock(&endpoint->lock);
+
+ uint8 epNumber = endpoint->id + 1;
+ StopEndpoint(true, epNumber, device->slot);
+
+ mutex_destroy(&endpoint->lock);
+ memset(endpoint, 0, sizeof(xhci_endpoint));
+
+ _WriteContext(&device->input_ctx->input.dropFlags, (1 <<
epNumber));
+ _WriteContext(&device->input_ctx->input.addFlags, 0);
+
+ if (epNumber > 1)
+ ConfigureEndpoint(device->input_ctx_addr, true,
device->slot);
+ else
+ EvaluateContext(device->input_ctx_addr, device->slot);
+
+ device->state = XHCI_STATE_ADDRESSED;
+ }
+ pipe->SetControllerCookie(NULL);
return B_OK;
}
############################################################################
Commit: dda9c02789693918ef542475d6eadf818c47db0b
URL: https://git.haiku-os.org/haiku/commit/?id=dda9c0278969
Author: Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date: Wed Mar 13 04:32:25 2019 UTC
XHCI: Use MutexLocker in HandleTransferComplete.
----------------------------------------------------------------------------
diff --git a/src/add-ons/kernel/busses/usb/xhci.cpp
b/src/add-ons/kernel/busses/usb/xhci.cpp
index f60ca296f4..9e1303364b 100644
--- a/src/add-ons/kernel/busses/usb/xhci.cpp
+++ b/src/add-ons/kernel/busses/usb/xhci.cpp
@@ -2297,6 +2297,7 @@ XHCI::HandleTransferComplete(xhci_trb* trb)
// Use mutex_trylock first, in case we are in KDL.
if (mutex_trylock(&endpoint->lock) != B_OK)
mutex_lock(&endpoint->lock);
+ MutexLocker endpointLocker(endpoint->lock, true);
addr_t source = trb->qwtrb0;
uint8 completionCode = TRB_2_COMP_CODE_GET(trb->dwtrb2);
@@ -2317,7 +2318,7 @@ XHCI::HandleTransferComplete(xhci_trb* trb)
// likely failed midway; so just accept it anyway.
if (offset == (td->trb_used - 1) || completionCode !=
COMP_SUCCESS) {
_UnlinkDescriptorForPipe(td, endpoint);
- mutex_unlock(&endpoint->lock);
+ endpointLocker.Unlock();
td->trb_completion_code = completionCode;
td->trb_left = remainder;
@@ -2332,13 +2333,11 @@ XHCI::HandleTransferComplete(xhci_trb* trb)
release_sem_etc(fFinishTransfersSem, 1,
B_DO_NOT_RESCHEDULE);
TRACE("HandleTransferComplete td %p done\n", td);
} else {
- mutex_unlock(&endpoint->lock);
TRACE_ERROR("successful TRB %" B_PRIxADDR " was found,
but it wasn't "
"the last in the TD!\n", source);
}
return;
}
- mutex_unlock(&endpoint->lock);
TRACE_ERROR("TRB 0x%" B_PRIxADDR " was not found in the endpoint!\n",
source);
}
############################################################################
Commit: 4d03f448749dc8e36912445e0239f0e08d355a6c
URL: https://git.haiku-os.org/haiku/commit/?id=4d03f448749d
Author: Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date: Wed Mar 13 04:33:27 2019 UTC
multi_audio_test: Fix the build.
----------------------------------------------------------------------------
diff --git a/src/tests/add-ons/kernel/drivers/audio/Jamfile
b/src/tests/add-ons/kernel/drivers/audio/Jamfile
index 260a56f82b..c5a886d44b 100644
--- a/src/tests/add-ons/kernel/drivers/audio/Jamfile
+++ b/src/tests/add-ons/kernel/drivers/audio/Jamfile
@@ -1,7 +1,7 @@
SubDir HAIKU_TOP src tests add-ons kernel drivers audio ;
SubDirHdrs [ FDirName $(HAIKU_TOP) src tests add-ons kernel file_systems
fs_shell ] ;
-UsePrivateHeaders [ FDirName media ] ;
+UsePrivateHeaders [ FDirName audio ] ;
SubDirCcFlags [ FDefines HAIKU_MULTI_AUDIO=1 ] ;
diff --git a/src/tests/add-ons/kernel/drivers/audio/multi_audio_test.cpp
b/src/tests/add-ons/kernel/drivers/audio/multi_audio_test.cpp
index 04068a9de5..c5fe911410 100644
--- a/src/tests/add-ons/kernel/drivers/audio/multi_audio_test.cpp
+++ b/src/tests/add-ons/kernel/drivers/audio/multi_audio_test.cpp
@@ -156,7 +156,7 @@ get_kind_name(uint32 kind)
return "bus-in";
case B_MULTI_AUX_BUS:
return "bus-aux";
-
+
default:
return "unknown";
}
############################################################################
Commit: d592cab849aed2d6e3a0408dd5b00b5d81535206
URL: https://git.haiku-os.org/haiku/commit/?id=d592cab849ae
Author: Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date: Wed Mar 13 04:33:47 2019 UTC
usb_webcam: We won't be building for Zeta.
----------------------------------------------------------------------------
diff --git a/src/add-ons/media/media-add-ons/usb_webcam/Jamfile
b/src/add-ons/media/media-add-ons/usb_webcam/Jamfile
index 8d3eb6b729..137b4a310e 100644
--- a/src/add-ons/media/media-add-ons/usb_webcam/Jamfile
+++ b/src/add-ons/media/media-add-ons/usb_webcam/Jamfile
@@ -2,17 +2,7 @@ SubDir HAIKU_TOP src add-ons media media-add-ons usb_webcam ;
SetSubDirSupportedPlatformsBeOSCompatible ;
-# Zeta has a libusb.so, we have it in libdevice.so
-if $(TARGET_PLATFORM_HAIKU_COMPATIBLE) {
- usbKitLibraryName = libdevice.so ;
-} else {
-# usbKitLibraryName = USBKit.a ;
-# UsePublicHeaders [ FDirName drivers ] ;
-# UsePublicHeaders [ FDirName device ] ;
- # use -lusb on ZETA
- usbKitLibraryName = usb ;
-}
-
+usbKitLibraryName = libdevice.so ;
# source directories
local sourceDirs =
############################################################################
Revision: hrev52990
Commit: 19151d0134b448de0cf51c152629586f8c9b1dd6
URL: https://git.haiku-os.org/haiku/commit/?id=19151d0134b4
Author: Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date: Wed Mar 13 04:34:58 2019 UTC
usb_audio: Clean up and fix device management code.
* Actually use the global mutex instead of creating useless MutexLockers.
* Don't delete the device object on _free(), then it can't be opened again,
which we want to be possible. Matches the behavior of other audio drivers.
* Clean up device detection code to better match other drivers.
At least under XHCI, multi_audio_test throws a variety of errors and then
crashes while attempting to use this driver. But following implementing
CancelQueuedTransfers, the system no longer KDLs after that. Progress!
----------------------------------------------------------------------------
diff --git a/src/add-ons/kernel/drivers/audio/usb/Driver.cpp
b/src/add-ons/kernel/drivers/audio/usb/Driver.cpp
index d304850dd6..75af6a97b2 100644
--- a/src/add-ons/kernel/drivers/audio/usb/Driver.cpp
+++ b/src/add-ons/kernel/drivers/audio/usb/Driver.cpp
@@ -30,7 +30,7 @@ usb_audio_device_added(usb_device device, void** cookie)
{
*cookie = NULL;
- MutexLocker driverLock;
+ MutexLocker _(gDriverLock);
// check if this is a replug of an existing device first
for (int32 i = 0; i < MAX_DEVICES; i++) {
@@ -84,7 +84,7 @@ usb_audio_device_added(usb_device device, void** cookie)
status_t
usb_audio_device_removed(void* cookie)
{
- MutexLocker driverLock;
+ MutexLocker _(gDriverLock);
Device* device = (Device*)cookie;
for (int32 i = 0; i < MAX_DEVICES; i++) {
@@ -173,14 +173,16 @@ uninit_driver()
static status_t
usb_audio_open(const char* name, uint32 flags, void** cookie)
{
- MutexLocker driverLock;
+ MutexLocker _(gDriverLock);
*cookie = NULL;
status_t status = ENODEV;
- int32 index = strtol(name + strlen(sDeviceBaseName), NULL, 10) - 1;
- if (index >= 0 && index < MAX_DEVICES && gDevices[index]) {
- status = gDevices[index]->Open(flags);
- *cookie = gDevices[index];
+ for (int32 i = 0; i < MAX_DEVICES && gDevices[i] != NULL; i++) {
+ if (strcmp(gDeviceNames[i], name) == 0) {
+ status = gDevices[i]->Open(flags);
+ *cookie = gDevices[i];
+ break;
+ }
}
return status;
@@ -224,35 +226,20 @@ static status_t
usb_audio_free(void* cookie)
{
Device* device = (Device*)cookie;
-
- MutexLocker driverLock;
-
- status_t status = device->Free();
- for (int32 i = 0; i < MAX_DEVICES; i++) {
- if (gDevices[i] == device) {
- // the device is removed already but as it was open the
- // removed hook has not deleted the object
- gDevices[i] = NULL;
- delete device;
- TRACE(INF, "Device at %ld deleted.\n", i);
- break;
- }
- }
-
- return status;
+ return device->Free();
}
const char**
publish_devices()
{
+ MutexLocker _(gDriverLock);
+
for (int32 i = 0; gDeviceNames[i]; i++) {
free(gDeviceNames[i]);
gDeviceNames[i] = NULL;
}
- MutexLocker driverLock;
-
int32 deviceCount = 0;
for (size_t i = 0; i < MAX_DEVICES; i++) {
if (gDevices[i] == NULL)