We need to guarantee that when cancel returns that the callback won't be called
anymore. It could happen that the transfer was already in the process of being finished, so wasn't in the list of pending transfers anymore. Cancel would then return even though the callback wasn't called yet. This could lead to a callback being called after a driver was already unloaded (even after it cleaned up the pipes it used). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33239 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -119,6 +119,7 @@ EHCI::EHCI(pci_info *info, Stack *stack)
|
||||
fCleanupThread(-1),
|
||||
fStopThreads(false),
|
||||
fFreeListHead(NULL),
|
||||
fProcessingPipe(NULL),
|
||||
fRootHub(NULL),
|
||||
fRootHubAddress(0),
|
||||
fPortCount(0),
|
||||
@@ -941,6 +942,10 @@ EHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
|
||||
list = next;
|
||||
}
|
||||
|
||||
// wait for any transfers that might have made it before canceling
|
||||
while (fProcessingPipe == pipe)
|
||||
snooze(1000);
|
||||
|
||||
// notify the finisher so it can clean up the canceled transfers
|
||||
release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
|
||||
return B_OK;
|
||||
@@ -1075,6 +1080,11 @@ EHCI::FinishTransfers()
|
||||
if (transfer == fLastTransfer)
|
||||
fLastTransfer = lastTransfer;
|
||||
|
||||
// store the currently processing pipe here so we can wait
|
||||
// in cancel if we are processing something on the target pipe
|
||||
if (!transfer->canceled)
|
||||
fProcessingPipe = transfer->transfer->TransferPipe();
|
||||
|
||||
transfer->link = NULL;
|
||||
Unlock();
|
||||
}
|
||||
@@ -1135,6 +1145,7 @@ EHCI::FinishTransfers()
|
||||
}
|
||||
|
||||
transfer->transfer->Finished(callbackStatus, actualLength);
|
||||
fProcessingPipe = NULL;
|
||||
}
|
||||
|
||||
// unlink hardware queue and delete the transfer
|
||||
|
||||
@@ -157,6 +157,7 @@ static pci_module_info * sPCIModule;
|
||||
thread_id fCleanupThread;
|
||||
bool fStopThreads;
|
||||
ehci_qh * fFreeListHead;
|
||||
Pipe * fProcessingPipe;
|
||||
|
||||
// Root Hub
|
||||
EHCIRootHub * fRootHub;
|
||||
|
||||
@@ -71,6 +71,7 @@ OHCI::OHCI(pci_info *info, Stack *stack)
|
||||
fFinishTransfersSem(-1),
|
||||
fFinishThread(-1),
|
||||
fStopFinishThread(false),
|
||||
fProcessingPipe(NULL),
|
||||
fRootHub(NULL),
|
||||
fRootHubAddress(0),
|
||||
fPortCount(0)
|
||||
@@ -472,6 +473,10 @@ OHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
|
||||
list = next;
|
||||
}
|
||||
|
||||
// wait for any transfers that might have made it before canceling
|
||||
while (fProcessingPipe == pipe)
|
||||
snooze(1000);
|
||||
|
||||
// notify the finisher so it can clean up the canceled transfers
|
||||
release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
|
||||
return B_OK;
|
||||
@@ -1021,6 +1026,11 @@ OHCI::_FinishTransfers()
|
||||
if (transfer == fLastTransfer)
|
||||
fLastTransfer = lastTransfer;
|
||||
|
||||
// store the currently processing pipe here so we can wait
|
||||
// in cancel if we are processing something on the target pipe
|
||||
if (!transfer->canceled)
|
||||
fProcessingPipe = transfer->transfer->TransferPipe();
|
||||
|
||||
transfer->link = NULL;
|
||||
Unlock();
|
||||
}
|
||||
@@ -1071,6 +1081,7 @@ OHCI::_FinishTransfers()
|
||||
}
|
||||
|
||||
transfer->transfer->Finished(callbackStatus, actualLength);
|
||||
fProcessingPipe = NULL;
|
||||
}
|
||||
|
||||
if (callbackStatus != B_OK) {
|
||||
|
||||
@@ -163,6 +163,7 @@ static pci_module_info * sPCIModule;
|
||||
sem_id fFinishTransfersSem;
|
||||
thread_id fFinishThread;
|
||||
bool fStopFinishThread;
|
||||
Pipe * fProcessingPipe;
|
||||
|
||||
// Root Hub
|
||||
OHCIRootHub * fRootHub;
|
||||
|
||||
@@ -335,6 +335,7 @@ UHCI::UHCI(pci_info *info, Stack *stack)
|
||||
fFinishTransfersSem(-1),
|
||||
fFinishThread(-1),
|
||||
fStopThreads(false),
|
||||
fProcessingPipe(NULL),
|
||||
fFreeList(NULL),
|
||||
fCleanupThread(-1),
|
||||
fCleanupSem(-1),
|
||||
@@ -795,6 +796,10 @@ UHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
|
||||
list = next;
|
||||
}
|
||||
|
||||
// wait for any transfers that might have made it before canceling
|
||||
while (fProcessingPipe == pipe)
|
||||
snooze(1000);
|
||||
|
||||
// notify the finisher so it can clean up the canceled transfers
|
||||
release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
|
||||
return B_OK;
|
||||
@@ -1340,6 +1345,11 @@ UHCI::FinishTransfers()
|
||||
if (transfer == fLastTransfer)
|
||||
fLastTransfer = lastTransfer;
|
||||
|
||||
// store the currently processing pipe here so we can wait
|
||||
// in cancel if we are processing something on the target pipe
|
||||
if (!transfer->canceled)
|
||||
fProcessingPipe = transfer->transfer->TransferPipe();
|
||||
|
||||
transfer->link = NULL;
|
||||
Unlock();
|
||||
}
|
||||
@@ -1399,6 +1409,7 @@ UHCI::FinishTransfers()
|
||||
}
|
||||
|
||||
transfer->transfer->Finished(callbackStatus, actualLength);
|
||||
fProcessingPipe = NULL;
|
||||
}
|
||||
|
||||
// remove and free the hardware queue and its descriptors
|
||||
|
||||
@@ -233,6 +233,7 @@ static pci_module_info * sPCIModule;
|
||||
sem_id fFinishTransfersSem;
|
||||
thread_id fFinishThread;
|
||||
bool fStopThreads;
|
||||
Pipe * fProcessingPipe;
|
||||
|
||||
transfer_data * fFreeList;
|
||||
thread_id fCleanupThread;
|
||||
|
||||
Reference in New Issue
Block a user