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 <[email protected]>
This commit is contained in:
Augustin Cavalier
2021-09-20 16:28:03 +00:00
committed by waddlesplash
parent faae5dd726
commit 8d046e2689
4 changed files with 18 additions and 9 deletions
@@ -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
+12 -6
View File
@@ -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;
}
+2 -1
View File
@@ -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);
@@ -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;