From mboxrd@z Thu Jan 1 00:00:00 1970 From: Claude Code Review Bot To: dri-devel-reviews@example.com Subject: Claude review: rust: add basic serial device bus abstractions Date: Thu, 04 Jun 2026 15:28:18 +1000 Message-ID: In-Reply-To: <20260530-rust_serdev-v9-1-f8b5fccb49c3@posteo.de> References: <20260530-rust_serdev-v9-0-f8b5fccb49c3@posteo.de> <20260530-rust_serdev-v9-1-f8b5fccb49c3@posteo.de> X-Mailer: Claude Code Patch Reviewer Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Patch Review This is the main patch =E2=80=94 574 lines of new Rust code, plus C helpers= and build plumbing. **C helpers (`rust/helpers/serdev.c`):** Correct. The three helpers wrap st= atic inline functions that bindgen cannot see through. **Kconfig:** Clean. `RUST_SERIAL_DEV_BUS_ABSTRACTIONS` is a `bool` that sel= ects `SERIAL_DEV_BUS`, which is the right dependency direction. **Typo in Parity doc comment:** ```rust /// Even partiy. Even =3D bindings::serdev_parity_SERDEV_PARITY_EVEN, ``` Should be `/// Even parity.` **Broken rustdoc link in `write()` documentation:** ```rust /// Note that any accepted data has only been buffered by the controlle= r. Use /// [ Device::wait_until_sent`] to make sure the controller write buffe= r has actually been /// emptied. ``` The link is malformed =E2=80=94 `[ Device::wait_until_sent`]` has a space a= fter `[` and mismatched backtick placement. Should be `[`Device::wait_until= _sent`]` to match the correct form used elsewhere, e.g. in `write_all`: ```rust /// [`Device::wait_until_sent`] to make sure the controller write buffe= r has actually been ``` **`Timeout::Max` documentation:** ```rust /// Wait as long as possible. /// /// This is equivalent to [`kernel::task::MAX_SCHEDULE_TIMEOUT`]. Max, ``` And the implementation: ```rust Self::Max =3D> 0, ``` This works correctly because both `serdev_device_write` (line 271-272 of `c= ore.c`) and `tty_wait_until_sent` convert `timeout =3D=3D 0` to `MAX_SCHEDU= LE_TIMEOUT` internally. However, saying `Timeout::Max` "is equivalent to `M= AX_SCHEDULE_TIMEOUT`" is misleading =E2=80=94 it maps to 0, not to the `MAX= _SCHEDULE_TIMEOUT` constant value (`LONG_MAX`). A reader unfamiliar with th= e C side's `if (timeout =3D=3D 0) timeout =3D MAX_SCHEDULE_TIMEOUT;` conven= tion could be confused. Consider rewording to something like "The underlyin= g C API treats a timeout of 0 as waiting indefinitely (equivalent to `MAX_S= CHEDULE_TIMEOUT`)." **`Timeout::into_jiffies` overflow behavior:** ```rust Self::Jiffies(value) =3D> value.get().try_into().unwrap_or_default(), ``` On overflow, `unwrap_or_default()` yields 0, which means "wait forever" per= the C API convention. This is a safe fallback (infinite wait rather than s= purious timeout), but it might be worth documenting this intentional semant= ic since it's non-obvious. **`probe_callback` =E2=80=94 drvdata lifecycle on probe failure:** ```rust sdev.as_ref().set_drvdata(try_pin_init!(PrivateData:: { ... }))?; // ... to_result(unsafe { bindings::serdev_device_open(sdev.as_raw()) })?; // ... let result =3D unsafe { data.__pinned_init(driver.as_mut_ptr()) }; unsafe { *private_data.error.get() =3D result.is_err() }; private_data.probe_complete.complete_all(); result.map(|()| 0) ``` If `serdev_device_open` succeeds but `T::probe` fails, the `PrivateData` is= in drvdata with `error =3D=3D true` and a successfully opened device. `Pin= nedDrop` for `PrivateData` calls `serdev_device_close`, but only if `Privat= eData` is actually dropped. Since `remove_callback` won't be called on prob= e failure, cleanup depends on the prerequisite driver-lifetime framework dr= opping drvdata on error. This should work given the dependencies, but it's = worth verifying the guarantee with the `device::CoreInternal` infrastructur= e. **`receive_buf_callback` =E2=80=94 completion wait:** ```rust private_data.probe_complete.wait_for_completion(); ``` This uses an unbounded wait. If probe hangs (e.g., firmware loading blocks)= , `receive_buf` will also hang. The serdev `receive_buf` callback is docume= nted as "may sleep," so this is permitted, but worth noting. **`write_all` return type handling:** ```rust let ret =3D unsafe { bindings::serdev_device_write(self.as_raw(), data.as_ptr(), data.len(),= timeout.into_jiffies()) }; to_result(ret as i32).map(|()| ret.unsigned_abs()) ``` The `ret as i32` cast is safe here because only the error check uses the tr= uncated value, and negative errnos always fit in `i32` (documented in the i= nline comment). The actual byte count comes from `ret.unsigned_abs()` using= the original `isize` value. Correct. **SAFETY comments:** Generally thorough and appropriate. The `unsafe impl S= end/Sync` blocks have adequate justification based on reference counting an= d thread-safe method implementations. --- Generated by Claude Code Patch Reviewer