[haiku-commits] haiku: hrev52990 - in src/add-ons: kernel/busses/usb kernel/drivers/audio/usb media/media-add-ons/usb_webcam

  • From: waddlesplash <waddlesplash@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 13 Mar 2019 00:41:23 -0400 (EDT)

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)


Other related posts: