xhci: Enhance endpoint state handling
* Expands on previous change to no enter a stopped state on an endpoint teardown. * Doorbells could re-awaken the port in a stopped state Change-Id: Ib5d9c89c4b721ea36ca22aaaf3ff92760a3ec2ff Reviewed-on: https://review.haiku-os.org/c/haiku/+/3996 Reviewed-by: Alex von Gluck IV <[email protected]> Reviewed-by: Adrien Destugues <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
a60e5cb46e
commit
37db8e9aed
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2019, Haiku, Inc. All rights reserved.
|
* Copyright 2011-2021, Haiku, Inc. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
* Jérôme Duval <[email protected]>
|
* Jérôme Duval <[email protected]>
|
||||||
* Akshay Jaggi <[email protected]>
|
* Akshay Jaggi <[email protected]>
|
||||||
* Michael Lotz <[email protected]>
|
* Michael Lotz <[email protected]>
|
||||||
|
* Alexander von Gluck <[email protected]>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -969,6 +970,12 @@ XHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
|
|||||||
// order to avoid a deadlock, we must unlock the endpoint.
|
// order to avoid a deadlock, we must unlock the endpoint.
|
||||||
endpointLocker.Unlock();
|
endpointLocker.Unlock();
|
||||||
status_t status = StopEndpoint(false, endpoint);
|
status_t status = StopEndpoint(false, endpoint);
|
||||||
|
if (status == B_NOT_ALLOWED) {
|
||||||
|
// XHCI 1.2, 4.8.3 Endpoint State Diagram
|
||||||
|
// Only exit from a HALTED state is a reset
|
||||||
|
TRACE_ERROR("cancel queued transfers: halted endpoint. reset!");
|
||||||
|
status = ResetEndpoint(false, endpoint);
|
||||||
|
}
|
||||||
endpointLocker.Lock();
|
endpointLocker.Lock();
|
||||||
|
|
||||||
// Detach the head TD from the endpoint.
|
// Detach the head TD from the endpoint.
|
||||||
@@ -1665,6 +1672,16 @@ XHCI::FreeDevice(Device *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8
|
||||||
|
XHCI::_GetEndpointState(xhci_endpoint* endpoint)
|
||||||
|
{
|
||||||
|
struct xhci_device_ctx* device_ctx = endpoint->device->device_ctx;
|
||||||
|
return ENDPOINT_0_STATE_GET(
|
||||||
|
_ReadContext(&device_ctx->endpoints[endpoint->id].dwendpoint0));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
XHCI::_InsertEndpointForPipe(Pipe *pipe)
|
XHCI::_InsertEndpointForPipe(Pipe *pipe)
|
||||||
{
|
{
|
||||||
@@ -2689,6 +2706,16 @@ XHCI::ResetEndpoint(bool preserve, xhci_endpoint* endpoint)
|
|||||||
{
|
{
|
||||||
TRACE("Reset Endpoint\n");
|
TRACE("Reset Endpoint\n");
|
||||||
|
|
||||||
|
switch (_GetEndpointState(endpoint)) {
|
||||||
|
case ENDPOINT_STATE_STOPPED:
|
||||||
|
TRACE("Reset Endpoint: already stopped");
|
||||||
|
return B_OK;
|
||||||
|
case ENDPOINT_STATE_HALTED:
|
||||||
|
TRACE("Reset Endpoint: warning, weird state!");
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
xhci_trb trb;
|
xhci_trb trb;
|
||||||
trb.address = 0;
|
trb.address = 0;
|
||||||
trb.status = 0;
|
trb.status = 0;
|
||||||
@@ -2705,16 +2732,13 @@ status_t
|
|||||||
XHCI::StopEndpoint(bool suspend, xhci_endpoint* endpoint)
|
XHCI::StopEndpoint(bool suspend, xhci_endpoint* endpoint)
|
||||||
{
|
{
|
||||||
TRACE("Stop Endpoint\n");
|
TRACE("Stop Endpoint\n");
|
||||||
struct xhci_device_ctx* device_ctx = endpoint->device->device_ctx;
|
|
||||||
|
|
||||||
// XHCI 1.2, 4.8.3 Endpoint State Diagram
|
switch (_GetEndpointState(endpoint)) {
|
||||||
// Only exit from a HALTED state is a reset which will also stop the ep
|
|
||||||
switch (ENDPOINT_0_STATE_GET(_ReadContext(
|
|
||||||
&device_ctx->endpoints[endpoint->id].dwendpoint0))) {
|
|
||||||
case ENDPOINT_STATE_HALTED:
|
case ENDPOINT_STATE_HALTED:
|
||||||
TRACE("Detected XHCI endpoint in halted state. Calling reset.");
|
TRACE("Stop Endpoint: error, halted");
|
||||||
return ResetEndpoint(false, endpoint);
|
return B_NOT_ALLOWED;
|
||||||
case ENDPOINT_STATE_STOPPED:
|
case ENDPOINT_STATE_STOPPED:
|
||||||
|
TRACE("Stop Endpoint: already stopped");
|
||||||
return B_OK;
|
return B_OK;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ private:
|
|||||||
uint16 interval, uint16 maxPacketSize,
|
uint16 interval, uint16 maxPacketSize,
|
||||||
usb_speed speed, uint8 maxBurst,
|
usb_speed speed, uint8 maxBurst,
|
||||||
uint16 bytesPerInterval);
|
uint16 bytesPerInterval);
|
||||||
|
uint8 _GetEndpointState(xhci_endpoint* ep);
|
||||||
|
|
||||||
status_t _InsertEndpointForPipe(Pipe *pipe);
|
status_t _InsertEndpointForPipe(Pipe *pipe);
|
||||||
status_t _RemoveEndpointForPipe(Pipe *pipe);
|
status_t _RemoveEndpointForPipe(Pipe *pipe);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user