From 8d046e26898d4a44b3028f97278653bad8a77f20 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Mon, 20 Sep 2021 11:40:46 -0400 Subject: [PATCH] USB: Split WaitForUnbusy from Object::PutUSBID. In a few instances, we need to not wait for objects to become unbusy during ID puts because we expect they still will be, e.g. in the case of Control pipes with submitted transfers that are still running. There, we need to put the ID, cancel transfers, and only then wait for the object to become unbusy. Technically, this is a functional change, but at least in practice it will have little real-world effect, for two reasons: 1. The DefaultPipe's Busy flag is basically never updated (the Device's busy flag is generally used instead), so it will virtually never be "busy". 2. Most devices have no Control endpoints besides that default one. Change-Id: I32ff4094effeac9ec74546c9643ea2025418e1c1 Reviewed-on: https://review.haiku-os.org/c/haiku/+/4491 Reviewed-by: waddlesplash --- src/add-ons/kernel/bus_managers/usb/Device.cpp | 3 ++- src/add-ons/kernel/bus_managers/usb/Object.cpp | 18 ++++++++++++------ src/add-ons/kernel/bus_managers/usb/Pipe.cpp | 3 ++- .../kernel/bus_managers/usb/usb_private.h | 3 ++- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/add-ons/kernel/bus_managers/usb/Device.cpp b/src/add-ons/kernel/bus_managers/usb/Device.cpp index e80ecd0e47..5e4bc842b6 100644 --- a/src/add-ons/kernel/bus_managers/usb/Device.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Device.cpp @@ -329,8 +329,9 @@ Device::~Device() // Cancel transfers on the default pipe and put its USBID to prevent // further transfers from being queued. if (fDefaultPipe != NULL) { - fDefaultPipe->PutUSBID(); + fDefaultPipe->PutUSBID(false); fDefaultPipe->CancelQueuedTransfers(true); + fDefaultPipe->WaitForUnbusy(); } // Destroy open endpoints. Do not send a device request to unconfigure diff --git a/src/add-ons/kernel/bus_managers/usb/Object.cpp b/src/add-ons/kernel/bus_managers/usb/Object.cpp index d2a3f5966b..595dbc03de 100644 --- a/src/add-ons/kernel/bus_managers/usb/Object.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Object.cpp @@ -36,20 +36,26 @@ Object::~Object() void -Object::PutUSBID() +Object::PutUSBID(bool waitForUnbusy) { - if (fUSBID == UINT32_MAX) - return; + if (fUSBID != UINT32_MAX) { + fStack->PutUSBID(this); + fUSBID = UINT32_MAX; + } - fStack->PutUSBID(this); + if (waitForUnbusy) + WaitForUnbusy(); +} + +void +Object::WaitForUnbusy() +{ int32 retries = 20; while (atomic_get(&fBusy) != 0 && retries--) snooze(100); if (retries <= 0) panic("USB object did not become unbusy!"); - - fUSBID = UINT32_MAX; } diff --git a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp index 106b8857ec..58249e7a01 100644 --- a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp @@ -338,8 +338,9 @@ ControlPipe::ControlPipe(Object *parent) ControlPipe::~ControlPipe() { // We do this here in case a submitted request is still running. - PutUSBID(); + PutUSBID(false); ControlPipe::CancelQueuedTransfers(true); + WaitForUnbusy(); if (fNotifySem >= 0) delete_sem(fNotifySem); diff --git a/src/add-ons/kernel/bus_managers/usb/usb_private.h b/src/add-ons/kernel/bus_managers/usb/usb_private.h index a5bd1ba43d..a5bcd77fa4 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_private.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_private.h @@ -278,7 +278,8 @@ virtual status_t ClearFeature(uint16 selector); virtual status_t GetStatus(uint16 *status); protected: - void PutUSBID(); + void PutUSBID(bool waitForUnbusy = true); + void WaitForUnbusy(); private: Object * fParent;