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.
Post-implementation review returned FAIL with two verified-CRITICAL
findings; all legitimate findings fixed in this round:
CRITICAL — engine wrote IC_CON/IC_TAR while enabled (DesignWare
databook forbids; Linux i2c_dw_xfer_init disables first). Engine
restructured: wait-idle -> disable -> program -> enable with
IC_ENABLE_STATUS polling on every transfer.
CRITICAL — Intel LPSS PCI bring-up skipped parent-device init.
intel-lpss-i2cd now claims functions via pcid_interface
(connect_by_path + enable_device), validates the real BAR size, and
performs intel_lpss_init_dev's sequence (reset-deassert + 64-bit
remap address at BAR0+0x200), ported from Linux drivers/mfd/intel-lpss.c.
MAJOR fixes:
- wait_for checks TX_ABRT before success predicates — a NACKed write
no longer reports success via post-abort idle state
- SCL timing corrected to Linux's formulas: HCNT uses sda_fall_ns,
round-to-nearest division (FS 100/200, SS 552/652 for bxt 133 MHz)
- stop=false rejected honestly instead of hanging on the idle wait
- recover(): ABORT-bit cycle + disable + state flush after any failed
transfer
- validate_request: segment/byte/address/10-bit limits before any MMIO
- i2cd + endpoint: exact-first adapter resolution; last-component
matching accepted only when unambiguous
- i2cd registration validates provider_scheme as a single safe
scheme-name component
- I2cTransferResponse gains typed status (I2cTransferStatus,
serde-defaulted, wire-compatible)
- endpoint::serve takes a Result-returning on_ready callback;
setrens failure is fatal (fail-closed namespace reduction)
- unexpected i2cd registration responses are fatal for that controller
Tests: dw-i2c 5 (timing vectors, validation, resolution),
intel-lpss-i2cd 1 (PCI ID table coverage), full workspace cargo check
clean, base cooks for x86_64-unknown-redox.
Refs: local/docs/LG-GRAM-16Z90TP-COMPATIBILITY-PLAN.md review-fix round
The I2C transfer chain was stubbed end-to-end:
- i2cd's transfer path returned 'not implemented yet' for every
transfer, and its wire format didn't match the only in-tree consumer
(i2c-hidd sends a bare I2cTransferRequest, i2cd expected
I2cControlRequest::Transfer).
- intel-lpss-i2cd / dw-acpi-i2cd / amd-mp2-i2cd registered an adapter
name and parked forever without initializing the controller or
executing a transfer.
- intel-lpss-i2cd matched only legacy ACPI HIDs, which do not exist on
Meteor Lake / Arrow Lake platforms (LPSS I2C binds by PCI ID there,
per Linux drivers/mfd/intel-lpss-pci.c).
Replace with real implementations:
- New shared crate drivers/i2c/designware (dw-i2c): DesignWare I2C
master engine ported from Linux 7.1 i2c-designware-master.c and
i2c-designware-common.c — IC_CON + SCL timing computed from ic_clk
with Linux's exact hcnt/lcnt formulas (bxt_i2c_info 133 MHz for
LPSS, 100 MHz for ACPI-designated blocks), SDA hold with RX-hold
workaround, polling transfer engine with RESTART/STOP sequencing,
TX_ABRT decode (Nack/arbitration-lost/abort/timeout), 7/10-bit
addressing, bounded timeouts. Also provides the shared
/scheme/<name> transfer endpoint with register-then-ready ordering.
- intel-lpss-i2cd: PCI discovery for ARL-H (0x7750/0x7751,
0x7778-0x777b) and MTL-P (0x7e50/0x7e51, 0x7e78-0x7e7b) with 32/64-bit
BAR0 decode, ACPI alias resolution via FixedMemory32 == BAR0 across
/scheme/acpi/resources, legacy ACPI-HID path kept, i2cd registration
with bounded retry, serves /scheme/i2c-lpss.
- dw-acpi-i2cd: converted from register-and-park to the shared engine,
serves /scheme/dw-acpi-i2c.
- i2cd: real transfer routing — adapter resolution by name/alias
(exact, normalized, last-component) and forwarding to the provider
daemon's /scheme/<provider>/transfer endpoint.
- i2c-interface: I2cAdapterInfo gains provider_scheme + aliases
(serde-default, wire-compatible).
Tests: dw-i2c 3, intel-lpss-i2cd 3; full workspace cargo check clean;
base cooks for x86_64-unknown-redox.
Refs: local/docs/LG-GRAM-16Z90TP-COMPATIBILITY-PLAN.md Phase 4