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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user