pci: the host bridge arrives by delegation too
pci-bus joins usb-xhci-bus in receiving its device from the manager rather
than claiming the id it found in argv[1]. Its hello moves ahead of the ECAM
mapping, since that is where the bridge now arrives, and its hello was
already mandatory so nothing about its failure behaviour changes.
isDelegated compared whole strings, which silently missed this driver: the
manager records the boot-snapshot match as the bare "pci-bus" and a
devices.csv match as the full "/system/drivers/pci-bus". pci-bus was then
neither claiming nor delegated and died on "ECAM mmio_map failed". It now
matches on the last path component. Reintroducing the whole-string compare
breaks usb-xhci-bus instead of pci-bus — the two spellings swap which driver
loses — so usb-hid is the case that catches it, not pci-scan.
pci-scan asserts the delegation on the initial bring-up AND after the
restart drill, with the device id backreferenced so both must name the same
device. That is what proves the manager re-takes a device when its driver
dies and hands it to the replacement, which is the property the whole
supervision design rests on.
The remaining three claimants are NOT converted, and the plan records why
rather than working around it. ps2-bus and the acpi service never hello at
all, which device-manager.md states deliberately ("legacy drivers ... not
yet required to hello"), so delegating to them means either promoting them
out of legacy or giving the grant a delivery point that is not hello.
virtio-gpu hellos best-effort by design — "standalone bring-up has no
manager" — and delegation would make it mandatory. Both are decisions, not
mechanical steps.
Consequence: D6 is blocked, because device_claim cannot be closed off while
three claimants still depend on it. D7-D9 are unaffected — they concern what
the kernel stores and how its table is sized.
Suite 118/118.
This commit is contained in:
@@ -75,11 +75,20 @@ fn configWrite16(bus: u64, dev: u64, function: u64, offset: u64, value: u16) voi
|
||||
configWrite(bus, dev, function, aligned, (word & ~mask) | (@as(u32, value) << shift));
|
||||
}
|
||||
|
||||
/// Claim the bridge, map the ECAM, hello the manager, then scan.
|
||||
/// Hello the manager (which is where the bridge arrives), map the ECAM, then scan.
|
||||
fn initialise(endpoint: ipc.Handle) bool {
|
||||
_ = endpoint;
|
||||
device.claim(bridge_id) catch |e| {
|
||||
std.log.info("unable to claim bridge device {d}: {s}", .{ bridge_id, @errorName(e) });
|
||||
// **The handshake first, because it is where the device arrives.** This driver
|
||||
// used to claim `bridge_id` here — first-come-first-served, so the manager's
|
||||
// matching was advisory and any process could have claimed the bridge by naming
|
||||
// the same id. The manager now holds it and transfers it in the hello reply
|
||||
// (docs/os-development/device-authority.md). `hello` is synchronous, so the
|
||||
// transfer has completed by the time this returns.
|
||||
//
|
||||
// Keep the manager handle to report children through; a supervised bus that
|
||||
// cannot reach its manager has nothing to serve.
|
||||
manager_handle = device_manager.hello(.bus, bridge_id) orelse {
|
||||
std.log.info("no hello with the device manager; bridge {d} not delegated", .{bridge_id});
|
||||
return false;
|
||||
};
|
||||
const buffer = memory.allocator().alloc(device.DeviceDescriptor, 64) catch {
|
||||
@@ -113,11 +122,6 @@ fn initialise(endpoint: ipc.Handle) bool {
|
||||
return false;
|
||||
};
|
||||
|
||||
// The handshake (role: bus — we enumerate PCI and report the functions we
|
||||
// find), then the scan. Keep the manager handle to report children through;
|
||||
// a supervised bus that cannot reach its manager has nothing to serve.
|
||||
manager_handle = device_manager.hello(.bus, bridge_id) orelse return false;
|
||||
|
||||
scan();
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user