mirror of
https://review.haiku-os.org/haiku
synced 2025-01-31 02:35:03 +01:00
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 <kallisti5@unixzen.com> Reviewed-by: Adrien Destugues <pulkomandy@gmail.com> Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
This commit is contained in:
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.
|
||||
*
|
||||
* Authors:
|
||||
@ -8,6 +8,7 @@
|
||||
* Jérôme Duval <jerome.duval@gmail.com>
|
||||
* Akshay Jaggi <akshay1994.leo@gmail.com>
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
* Alexander von Gluck <kallisti5@unixzen.com>
|
||||
*/
|
||||
|
||||
|
||||
@ -969,6 +970,12 @@ XHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
|
||||
// order to avoid a deadlock, we must unlock the endpoint.
|
||||
endpointLocker.Unlock();
|
||||
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();
|
||||
|
||||
// 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
|
||||
XHCI::_InsertEndpointForPipe(Pipe *pipe)
|
||||
{
|
||||
@ -2689,6 +2706,16 @@ XHCI::ResetEndpoint(bool preserve, xhci_endpoint* endpoint)
|
||||
{
|
||||
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;
|
||||
trb.address = 0;
|
||||
trb.status = 0;
|
||||
@ -2705,16 +2732,13 @@ status_t
|
||||
XHCI::StopEndpoint(bool suspend, xhci_endpoint* endpoint)
|
||||
{
|
||||
TRACE("Stop Endpoint\n");
|
||||
struct xhci_device_ctx* device_ctx = endpoint->device->device_ctx;
|
||||
|
||||
// XHCI 1.2, 4.8.3 Endpoint State Diagram
|
||||
// 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))) {
|
||||
switch (_GetEndpointState(endpoint)) {
|
||||
case ENDPOINT_STATE_HALTED:
|
||||
TRACE("Detected XHCI endpoint in halted state. Calling reset.");
|
||||
return ResetEndpoint(false, endpoint);
|
||||
TRACE("Stop Endpoint: error, halted");
|
||||
return B_NOT_ALLOWED;
|
||||
case ENDPOINT_STATE_STOPPED:
|
||||
TRACE("Stop Endpoint: already stopped");
|
||||
return B_OK;
|
||||
default:
|
||||
break;
|
||||
|
@ -138,6 +138,8 @@ private:
|
||||
uint16 interval, uint16 maxPacketSize,
|
||||
usb_speed speed, uint8 maxBurst,
|
||||
uint16 bytesPerInterval);
|
||||
uint8 _GetEndpointState(xhci_endpoint* ep);
|
||||
|
||||
status_t _InsertEndpointForPipe(Pipe *pipe);
|
||||
status_t _RemoveEndpointForPipe(Pipe *pipe);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user