Locking around descriptors list handling isn't enough, locking is also needed when traversing the list: we instead lock the whole traversing/handling loop.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42623 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval
2011-08-11 17:32:14 +00:00
parent a823207363
commit 425eff67d6
+27 -37
View File
@@ -835,20 +835,16 @@ isochronous_transfer_data *
EHCI::FindIsochronousTransfer(ehci_itd *itd) EHCI::FindIsochronousTransfer(ehci_itd *itd)
{ {
// Simply check every last descriptor of the isochronous transfer list // Simply check every last descriptor of the isochronous transfer list
if (LockIsochronous()) { isochronous_transfer_data *transfer = fFirstIsochronousTransfer;
isochronous_transfer_data *transfer = fFirstIsochronousTransfer; if (transfer) {
if (transfer) { while (transfer->descriptors[transfer->last_to_process]
while (transfer->descriptors[transfer->last_to_process] != itd) {
!= itd) { transfer = transfer->link;
transfer = transfer->link; if (!transfer)
if (!transfer) break;
break;
}
} }
UnlockIsochronous();
return transfer;
} }
return NULL; return transfer;
} }
@@ -1690,6 +1686,9 @@ EHCI::FinishIsochronousTransfers()
" at frame %ld\n", itd, itd->this_phy, itd->prev, " at frame %ld\n", itd, itd->this_phy, itd->prev,
itd->prev != NULL ? itd->prev->this_phy : 0, currentFrame); itd->prev != NULL ? itd->prev->this_phy : 0, currentFrame);
if (!LockIsochronous())
continue;
// Process the frame till it has isochronous descriptors in it. // Process the frame till it has isochronous descriptors in it.
while (!(itd->next_phy & EHCI_ITEM_TERMINATE) && itd->prev != NULL) { while (!(itd->next_phy & EHCI_ITEM_TERMINATE) && itd->prev != NULL) {
TRACE("FinishIsochronousTransfers checking itd %p last_token" TRACE("FinishIsochronousTransfers checking itd %p last_token"
@@ -1720,25 +1719,22 @@ EHCI::FinishIsochronousTransfers()
} }
// Remove the transfer // Remove the transfer
if (LockIsochronous()) { if (transfer == fFirstIsochronousTransfer) {
if (transfer == fFirstIsochronousTransfer) { fFirstIsochronousTransfer = transfer->link;
fFirstIsochronousTransfer = transfer->link; if (transfer == fLastIsochronousTransfer)
if (transfer == fLastIsochronousTransfer) fLastIsochronousTransfer = NULL;
fLastIsochronousTransfer = NULL; } else {
} else { isochronous_transfer_data *temp
isochronous_transfer_data *temp = fFirstIsochronousTransfer;
= fFirstIsochronousTransfer; while (temp != NULL && transfer != temp->link)
while (temp != NULL && transfer != temp->link) temp = temp->link;
temp = temp->link;
if (transfer == fLastIsochronousTransfer) if (transfer == fLastIsochronousTransfer)
fLastIsochronousTransfer = temp; fLastIsochronousTransfer = temp;
if (temp != NULL && temp->link != NULL) if (temp != NULL && temp->link != NULL)
temp->link = temp->link->link; temp->link = temp->link->link;
}
transfer->link = NULL;
UnlockIsochronous();
} }
transfer->link = NULL;
transfer->transfer->Finished(B_OK, actualLength); transfer->transfer->Finished(B_OK, actualLength);
@@ -1759,6 +1755,8 @@ EHCI::FinishIsochronousTransfers()
itd = itd->prev; itd = itd->prev;
} }
UnlockIsochronous();
TRACE("FinishIsochronousTransfers next frame\n"); TRACE("FinishIsochronousTransfers next frame\n");
// Make sure to reset the frame bandwidth // Make sure to reset the frame bandwidth
@@ -2243,7 +2241,6 @@ EHCI::LinkDescriptors(ehci_qtd *first, ehci_qtd *last, ehci_qtd *alt)
void void
EHCI::LinkITDescriptors(ehci_itd *itd, ehci_itd **_last) EHCI::LinkITDescriptors(ehci_itd *itd, ehci_itd **_last)
{ {
LockIsochronous();
ehci_itd *last = *_last; ehci_itd *last = *_last;
itd->next_phy = last->next_phy; itd->next_phy = last->next_phy;
itd->next = NULL; itd->next = NULL;
@@ -2251,14 +2248,12 @@ EHCI::LinkITDescriptors(ehci_itd *itd, ehci_itd **_last)
last->next = itd; last->next = itd;
last->next_phy = itd->this_phy; last->next_phy = itd->this_phy;
*_last = itd; *_last = itd;
UnlockIsochronous();
} }
void void
EHCI::LinkSITDescriptors(ehci_sitd *sitd, ehci_sitd **_last) EHCI::LinkSITDescriptors(ehci_sitd *sitd, ehci_sitd **_last)
{ {
LockIsochronous();
ehci_sitd *last = *_last; ehci_sitd *last = *_last;
sitd->next_phy = last->next_phy; sitd->next_phy = last->next_phy;
sitd->next = NULL; sitd->next = NULL;
@@ -2266,34 +2261,29 @@ EHCI::LinkSITDescriptors(ehci_sitd *sitd, ehci_sitd **_last)
last->next = sitd; last->next = sitd;
last->next_phy = sitd->this_phy; last->next_phy = sitd->this_phy;
*_last = sitd; *_last = sitd;
UnlockIsochronous();
} }
void void
EHCI::UnlinkITDescriptors(ehci_itd *itd, ehci_itd **last) EHCI::UnlinkITDescriptors(ehci_itd *itd, ehci_itd **last)
{ {
LockIsochronous();
itd->prev->next_phy = itd->next_phy; itd->prev->next_phy = itd->next_phy;
itd->prev->next = itd->next; itd->prev->next = itd->next;
if (itd->next != NULL) if (itd->next != NULL)
itd->next->prev = itd->prev; itd->next->prev = itd->prev;
if (itd == *last) if (itd == *last)
*last = itd->prev; *last = itd->prev;
UnlockIsochronous();
} }
void void
EHCI::UnlinkSITDescriptors(ehci_sitd *sitd, ehci_sitd **last) EHCI::UnlinkSITDescriptors(ehci_sitd *sitd, ehci_sitd **last)
{ {
LockIsochronous();
sitd->prev->next_phy = sitd->next_phy; sitd->prev->next_phy = sitd->next_phy;
sitd->prev->next = sitd->next; sitd->prev->next = sitd->next;
if (sitd->next != NULL) if (sitd->next != NULL)
sitd->next->prev = sitd->prev; sitd->next->prev = sitd->prev;
if (sitd == *last) if (sitd == *last)
*last = sitd->prev; *last = sitd->prev;
UnlockIsochronous();
} }