When adding a transfer, the current tail descriptor of the endpoint will be

reused and overwritten by the first descriptor of the new transfer and the first
descriptor will become the new tail. We anticipate this situation in
_AddPendingTransfer() and set the first_descriptor of the transfer data to the
tail already. Since the tail was pretty much cleared to zero, this introduced
a race condition. After adding the pending transfer it can already be found
in the finisher thread. If this happened before actually switching the tail
and first descriptor it would find a descriptor with a condition of 0, meaning
"No Error" and would process the transfer incorrectly. Depending on the count
of descriptors and the timing of the switch taking place this could have
resulted in aborted transfers with actual length 0 or with the correct actual
length but invalid data. In the very worst case it could have freed things still
in use by the controller, resulting in all sorts of device errors. Sadly it
doesn't fix #4067.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32534 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2009-08-20 07:24:49 +00:00
parent 177e730557
commit 840cdc9efc
+3 -2
View File
@@ -813,7 +813,7 @@ OHCI::_AddPendingTransfer(Transfer *transfer,
data->canceled = false;
data->link = NULL;
// the current tail will become the fist descriptor
// the current tail will become the first descriptor
data->first_descriptor = (ohci_general_td *)endpoint->tail_logical_descriptor;
// the data and first descriptors might be the same
@@ -1231,7 +1231,7 @@ OHCI::_SwitchEndpointTail(ohci_endpoint_descriptor *endpoint,
tail->next_logical_descriptor = first->next_logical_descriptor;
// the first descriptor becomes the new tail
first->flags = 0;
first->flags = OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED);
first->buffer_physical = 0;
first->next_physical_descriptor = 0;
first->last_physical_byte_address = 0;
@@ -1410,6 +1410,7 @@ OHCI::_InsertEndpointForPipe(Pipe *pipe)
return B_ERROR;
} else {
ohci_general_td *tail = _CreateGeneralDescriptor(0);
tail->flags = OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED);
endpoint->tail_logical_descriptor = tail;
endpoint->head_physical_descriptor = tail->physical_address;
endpoint->tail_physical_descriptor = tail->physical_address;