From 62e7651fe70d5a0456ff37525fbdb744a53680e9 Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Fri, 24 Jul 2026 03:33:42 +0900 Subject: [PATCH] dw-i2c: deliver scheme capability fd to init in endpoint::serve (fix boot hang) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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/ and the boot proceeds. Affects intel-lpss-i2cd and dw-acpi-i2cd, both type={scheme} services using this endpoint. --- drivers/i2c/designware/src/lib.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/designware/src/lib.rs b/drivers/i2c/designware/src/lib.rs index c90bcb775b..e3c868c855 100644 --- a/drivers/i2c/designware/src/lib.rs +++ b/drivers/i2c/designware/src/lib.rs @@ -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/ 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::*;