Kernel: Reset xHCI control endpoint on command stall

This commit is contained in:
2026-08-22 11:57:19 +03:00
parent fdbfda189f
commit 6a7c1c1281
2 changed files with 64 additions and 13 deletions
@@ -373,6 +373,33 @@ namespace Kernel::XHCI
uint32_t slot_id : 8; uint32_t slot_id : 8;
} configure_endpoint_command; } configure_endpoint_command;
struct
{
uint32_t : 32;
uint32_t : 32;
uint32_t : 32;
uint32_t cycle_bit : 1;
uint32_t : 8;
uint32_t tsp : 1;
uint32_t trb_type : 6;
uint32_t endpoint_id : 5;
uint32_t : 3;
uint32_t slot_id : 8;
} reset_endpoint_command;
struct
{
uint64_t new_tr_deque_pointer : 64;
uint32_t : 16;
uint32_t stream_id : 16;
uint32_t cycle_bit : 1;
uint32_t : 9;
uint32_t trb_type : 6;
uint32_t endpoint_id : 5;
uint32_t : 3;
uint32_t slot_id : 8;
} set_tr_deque_pointer_command;
struct struct
{ {
uint64_t ring_segment_ponter : 64; uint64_t ring_segment_ponter : 64;
+34 -10
View File
@@ -273,19 +273,14 @@ namespace Kernel
if (!endpoint.transfer_ring) if (!endpoint.transfer_ring)
{ {
endpoint.transfer_ring = TRY(DMARegion::create(m_transfer_ring_trb_count * sizeof(XHCI::TRB))); endpoint.transfer_ring = TRY(DMARegion::create(m_transfer_ring_trb_count * sizeof(XHCI::TRB), PageTable::MemoryType::Normal));
endpoint.max_packet_size = max_packet_size; endpoint.max_packet_size = max_packet_size;
endpoint.dequeue_index = 0;
endpoint.enqueue_index = 0;
endpoint.cycle_bit = 1;
endpoint.callback = (is_interrupt || is_bulk) ? &XHCIDevice::on_interrupt_or_bulk_endpoint_event : nullptr; endpoint.callback = (is_interrupt || is_bulk) ? &XHCIDevice::on_interrupt_or_bulk_endpoint_event : nullptr;
} }
else
{
endpoint.dequeue_index = 0; endpoint.dequeue_index = 0;
endpoint.enqueue_index = 0; endpoint.enqueue_index = 0;
endpoint.cycle_bit = 1; endpoint.cycle_bit = 1;
}
memset(reinterpret_cast<void*>(endpoint.transfer_ring->vaddr()), 0, endpoint.transfer_ring->size()); memset(reinterpret_cast<void*>(endpoint.transfer_ring->vaddr()), 0, endpoint.transfer_ring->size());
@@ -421,7 +416,8 @@ namespace Kernel
const bool status_stage_dir = !((request.wLength > 0) && (request.bmRequestType & USB::RequestType::DeviceToHost)); const bool status_stage_dir = !((request.wLength > 0) && (request.bmRequestType & USB::RequestType::DeviceToHost));
auto& endpoint = m_endpoints[0]; const uint32_t endpoint_id = 1;
auto& endpoint = m_endpoints[endpoint_id - 1];
LockGuard _(endpoint.mutex); LockGuard _(endpoint.mutex);
@@ -496,9 +492,37 @@ namespace Kernel
endpoint.dequeue_index = endpoint.enqueue_index; endpoint.dequeue_index = endpoint.enqueue_index;
if (completion_trb.transfer_event.completion_code != 1) if (const uint32_t completion_code = completion_trb.transfer_event.completion_code; completion_code != 1)
{ {
dwarnln("Completion error: {}", +completion_trb.transfer_event.completion_code); if (completion_code != 6)
dwarnln("Completion code: {}", completion_code);
else
{
dprintln_if(DEBUG_XHCI, "Completion error: {}", completion_code);
XHCI::TRB command;
command.reset_endpoint_command = {};
command.reset_endpoint_command.slot_id = m_info.slot_id;
command.reset_endpoint_command.endpoint_id = endpoint_id;
command.reset_endpoint_command.trb_type = XHCI::TRBType::ResetEndpointCommand;
command.reset_endpoint_command.tsp = 0;
TRY(m_controller.send_command(command));
uint64_t tr_dequeue_pointer = endpoint.transfer_ring->paddr();
tr_dequeue_pointer += endpoint.dequeue_index * sizeof(XHCI::TRB);
tr_dequeue_pointer |= endpoint.cycle_bit;
// FIXME: streams
command.set_tr_deque_pointer_command = {};
command.set_tr_deque_pointer_command.new_tr_deque_pointer = tr_dequeue_pointer;
command.set_tr_deque_pointer_command.stream_id = 0;
command.set_tr_deque_pointer_command.slot_id = m_info.slot_id;
command.set_tr_deque_pointer_command.endpoint_id = endpoint_id;
command.set_tr_deque_pointer_command.trb_type = XHCI::TRBType::SetTRDequeuePointerCommand;
TRY(m_controller.send_command(command));
}
return BAN::Error::from_errno(EFAULT); return BAN::Error::from_errno(EFAULT);
} }