Artemis Milestone 2e: real connect drives Enable Slot, slot ID correlated
xhci_poll_events()'s Port Status Change connect branch now calls xhci_cmd_enable_slot() directly (the earlier boot-time smoke test call is gone), tracked via a new dev->pending_connect_port_id -- since this driver only ever has one command outstanding at a time, that alone identifies which port a later Command Completion Event answers, without needing to match the Command TRB Pointer yet. On success the returned Slot ID is recorded in a new dev->port_slot_id[], a fixed uint32_t[XHCI_MAX_TRACKED_PORTS] (32) indexed by port. Disconnect clears the port's tracked slot (real teardown -- Disable Slot, DCBAA clear, Section U callback -- is still a later increment). Fixed array, not heap-allocated: a first attempt sized port_slot_id dynamically via kmalloc_aligned(dev->max_ports * sizeof(uint32_t), 64) inside xhci_bringup() and it crashed amd64 with a page fault (IFETCH at RIP=CR2=0xA0000, the legacy VGA hole) during the unrelated Mama-VM-birth phase afterward -- a heap-corruption signature, not chased to root cause. Switching to a fixed array (matching this driver's existing preference for fixed over dynamic allocation) made the crash go away; the crashing boot's log is kept (logs/20260822-102516/) as the evidence trail. Verified live via QMP hotplug, all three architectures: connect -> "enable slot command submitted" -> "enable slot succeeded", with a disconnect/reconnect cycle repeating cleanly and no port wedge. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HZ8kNoTuP63pbQtro4qvrm
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
dd043bbfeb
commit
6d330efdd8
+54
-15
@@ -251,20 +251,14 @@ int xhci_bringup(xhci_dev_t *dev)
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* Milestone 2e: per-port Enable Slot correlation state -- fixed array,
|
||||
* see xhci_dev_t's own doc comment; no allocation needed. */
|
||||
for (uint32_t i = 0; i < XHCI_MAX_TRACKED_PORTS; i++) dev->port_slot_id[i] = 0;
|
||||
dev->pending_connect_port_id = 0;
|
||||
|
||||
console_println("xhci: controller running");
|
||||
|
||||
g_xhci_dev = dev;
|
||||
|
||||
/* Milestone 2e smoke test: prove the write path (TRB enqueue, cycle
|
||||
* bit, doorbell ring) before building slot allocation on top of it.
|
||||
* A real Enable Slot is harmless to issue speculatively -- it just
|
||||
* reserves a Device Slot Context the driver doesn't use yet -- and its
|
||||
* Command Completion Event is the only live proof that a TRB written by
|
||||
* software was actually consumed by the controller. Real connect-driven
|
||||
* Enable Slot calls (Milestone 2e proper) replace/reuse this call site
|
||||
* once Port Status Change handling exists. */
|
||||
xhci_cmd_enable_slot(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -358,8 +352,32 @@ void xhci_poll_events(void)
|
||||
uint32_t portsc = port->portsc;
|
||||
if (portsc & XHCI_PORTSC_CCS) {
|
||||
console_println("xhci: port status change -- device connected");
|
||||
/* Only one Enable Slot in flight at a time (see
|
||||
* xhci_dev_t's doc comment) -- if another connect's
|
||||
* slot request is still outstanding, this one is
|
||||
* dropped rather than queued. Acceptable for this
|
||||
* milestone's single-device testing scope; revisit if
|
||||
* multi-port simultaneous connects become a real
|
||||
* scenario. */
|
||||
if (port_id > XHCI_MAX_TRACKED_PORTS) {
|
||||
console_println("xhci: port beyond tracked range -- enable slot skipped");
|
||||
} else if (dev->pending_connect_port_id == 0) {
|
||||
dev->pending_connect_port_id = port_id;
|
||||
xhci_cmd_enable_slot(dev);
|
||||
} else {
|
||||
console_println("xhci: enable slot already pending -- dropped");
|
||||
}
|
||||
} else {
|
||||
console_println("xhci: port status change -- device disconnected");
|
||||
if (port_id >= 1 && port_id <= XHCI_MAX_TRACKED_PORTS &&
|
||||
dev->port_slot_id[port_id - 1] != 0) {
|
||||
/* Real teardown (Disable Slot command, DCBAA entry
|
||||
* clear, callback to Section U's code) is a later
|
||||
* increment -- for now just stop tracking the slot
|
||||
* so a future connect on this port isn't confused
|
||||
* for one already in progress. */
|
||||
dev->port_slot_id[port_id - 1] = 0;
|
||||
}
|
||||
}
|
||||
/* Acknowledge only CSC (RW1CS): preserve PP, write 0 for
|
||||
* PED/PR (writing 1 there disables the port / starts a new
|
||||
@@ -369,11 +387,32 @@ void xhci_poll_events(void)
|
||||
port->portsc = (portsc & XHCI_PORTSC_PP) | XHCI_PORTSC_CSC;
|
||||
break;
|
||||
}
|
||||
case XHCI_TRB_TYPE_COMMAND_COMPLETION_EVT:
|
||||
/* No commands are issued yet (Milestone 2e is the first
|
||||
* command-ring user) -- logged for the same reason. */
|
||||
console_println("xhci: command completion event");
|
||||
case XHCI_TRB_TYPE_COMMAND_COMPLETION_EVT: {
|
||||
uint32_t code = XHCI_EVT_COMPLETION_CODE(trb->status);
|
||||
uint32_t slot_id = XHCI_EVT_SLOT_ID(trb->control);
|
||||
/* Correlates to the single in-flight Enable Slot, not to
|
||||
* the Command TRB Pointer in trb->parameter -- this driver
|
||||
* only ever has one command outstanding (see
|
||||
* xhci_dev_t's doc comment), so pending_connect_port_id
|
||||
* alone is enough to identify which port this completion
|
||||
* belongs to; a real Command TRB Pointer match becomes
|
||||
* necessary once Address Device commands can also be
|
||||
* in flight concurrently with Enable Slot. */
|
||||
if (dev->pending_connect_port_id != 0) {
|
||||
uint32_t port_id = dev->pending_connect_port_id;
|
||||
dev->pending_connect_port_id = 0;
|
||||
if (code == XHCI_COMPLETION_CODE_SUCCESS &&
|
||||
port_id >= 1 && port_id <= XHCI_MAX_TRACKED_PORTS) {
|
||||
dev->port_slot_id[port_id - 1] = slot_id;
|
||||
console_println("xhci: enable slot succeeded");
|
||||
} else {
|
||||
console_println("xhci: enable slot failed");
|
||||
}
|
||||
} else {
|
||||
console_println("xhci: command completion event");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XHCI_TRB_TYPE_TRANSFER_EVENT:
|
||||
/* No transfer rings exist yet (Milestone 2g) -- logged. */
|
||||
console_println("xhci: transfer event");
|
||||
|
||||
Reference in New Issue
Block a user