dw-i2c: deliver scheme capability fd to init in endpoint::serve (fix boot hang)

endpoint::serve used register_sync_scheme, which registers the scheme to
the daemon's own namespace but never returns the capability fd to init.
For type={scheme} services init blocks in call_ro(FD) waiting for that
fd, so the boot deadlocked right after 'Started Intel LPSS I2C
controller' (CPU halted, init asleep) — the ptyd-class bug.

Replace register_sync_scheme with an explicit capability-fd creation +
notify_init_scheme_fd() that writes the fd to the INIT_NOTIFY pipe
(same mechanism as SchemeDaemon::ready_with_fd / ready_sync_scheme,
which i2cd, ucsid, and ptyd already use). init then registers
/scheme/<name> and the boot proceeds.

Affects intel-lpss-i2cd and dw-acpi-i2cd, both type={scheme} services
using this endpoint.
This commit is contained in:
Red Bear OS
2026-07-24 03:33:42 +09:00
parent 374a95aca7
commit 62e7651fe7
+22 -3
View File
@@ -595,7 +595,7 @@ pub mod endpoint {
use anyhow::{Context, Result};
use i2c_interface::{I2cTransferRequest, I2cTransferResponse, I2cTransferStatus};
use redox_scheme::scheme::{register_sync_scheme, SchemeSync};
use redox_scheme::scheme::SchemeSync;
use redox_scheme::{CallerCtx, OpenResult, Socket};
use scheme_utils::{Blocking, HandleMap};
use syscall::schemev2::NewFdFlags;
@@ -861,8 +861,17 @@ pub mod endpoint {
handles: HandleMap::new(),
controllers,
};
register_sync_scheme(&socket, scheme_name, &mut endpoint)
.with_context(|| format!("failed to register {scheme_name} scheme"))?;
// type={scheme} handshake: deliver the capability fd to init over
// INIT_NOTIFY so init registers /scheme/<name> and returns from
// call_ro(FD). register_sync_scheme alone deadlocks init (ptyd-class).
let cap_id = endpoint
.scheme_root()
.context("failed to compute scheme root")?;
let cap_fd = socket
.create_this_scheme_fd(0, cap_id, 0, 0)
.context("failed to create scheme capability fd")?;
notify_init_scheme_fd(cap_fd).context("failed to deliver scheme fd to init")?;
log::info!(
"dw-i2c: serving /scheme/{scheme_name} with {} controller(s)",
@@ -882,6 +891,16 @@ pub mod endpoint {
Ok(())
}
fn notify_init_scheme_fd(cap_fd: usize) -> Result<()> {
let pipe_fd: usize = std::env::var("INIT_NOTIFY")
.context("INIT_NOTIFY is not set")?
.parse()
.context("INIT_NOTIFY is not a valid fd")?;
syscall::call_wo(pipe_fd, &cap_fd.to_ne_bytes(), syscall::CallFlags::FD, &[])
.context("failed to write scheme fd to the INIT_NOTIFY pipe")?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;