mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 04:23:35 +02:00
regulator: Fix for v7.0
A fix from Alice for the rust bindings, they didn't handle the stub implementation of the C API used when CONFIG_REGULATOR is disabled leading to undefined behaviour. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmnGytAACgkQJNaLcl1U h9AVigf+Mh0lmITiHVfl799msXUT3Is5mc6WevhTF2OOpIClznAiTp1GAj7YbJWo fZee+ovNgRUhvx0XqYaGzuTkbQw3JkHFmmiXjkKa5wcWOPkyFnFNt20e56X7A+5f Ep0eN8gH3JEJbDU10m+12xNocYmTcuuU4fFbSj8qAHmSHCV2ZM39E0xuadIBPKS0 UvlTFI0aAxNA6rjlKzf5wLGZif5/Es+JjP6JX6xhmJmYrUXzi9FNcYLZQmdSPQOO NI9IifNooXo7zmYNS9zHg9YRSZHt6G+vtxxlpeRwnrTrkfG0/rXuGq2Bb14zm2jy 1Uv7wfo/zQ0CLVIne4wZ+HWJU7hkcw== =Lie6 -----END PGP SIGNATURE----- Merge tag 'regulator-fix-v7.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator Pull regulator fix from Mark Brown: "A fix from Alice for the rust bindings, they didn't handle the stub implementation of the C API used when CONFIG_REGULATOR is disabled leading to undefined behaviour" * tag 'regulator-fix-v7.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: rust: regulator: do not assume that regulator_get() returns non-null
This commit is contained in:
commit
cd0bbd5a66
|
|
@ -23,7 +23,10 @@
|
|||
prelude::*,
|
||||
};
|
||||
|
||||
use core::{marker::PhantomData, mem::ManuallyDrop, ptr::NonNull};
|
||||
use core::{
|
||||
marker::PhantomData,
|
||||
mem::ManuallyDrop, //
|
||||
};
|
||||
|
||||
mod private {
|
||||
pub trait Sealed {}
|
||||
|
|
@ -229,15 +232,17 @@ pub fn devm_enable_optional(dev: &Device<Bound>, name: &CStr) -> Result {
|
|||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// - `inner` is a non-null wrapper over a pointer to a `struct
|
||||
/// regulator` obtained from [`regulator_get()`].
|
||||
/// - `inner` is a pointer obtained from a successful call to
|
||||
/// [`regulator_get()`]. It is treated as an opaque token that may only be
|
||||
/// accessed using C API methods (e.g., it may be `NULL` if the C API returns
|
||||
/// `NULL`).
|
||||
///
|
||||
/// [`regulator_get()`]: https://docs.kernel.org/driver-api/regulator.html#c.regulator_get
|
||||
pub struct Regulator<State>
|
||||
where
|
||||
State: RegulatorState,
|
||||
{
|
||||
inner: NonNull<bindings::regulator>,
|
||||
inner: *mut bindings::regulator,
|
||||
_phantom: PhantomData<State>,
|
||||
}
|
||||
|
||||
|
|
@ -249,7 +254,7 @@ pub fn set_voltage(&self, min_voltage: Voltage, max_voltage: Voltage) -> Result
|
|||
// SAFETY: Safe as per the type invariants of `Regulator`.
|
||||
to_result(unsafe {
|
||||
bindings::regulator_set_voltage(
|
||||
self.inner.as_ptr(),
|
||||
self.inner,
|
||||
min_voltage.as_microvolts(),
|
||||
max_voltage.as_microvolts(),
|
||||
)
|
||||
|
|
@ -259,7 +264,7 @@ pub fn set_voltage(&self, min_voltage: Voltage, max_voltage: Voltage) -> Result
|
|||
/// Gets the current voltage of the regulator.
|
||||
pub fn get_voltage(&self) -> Result<Voltage> {
|
||||
// SAFETY: Safe as per the type invariants of `Regulator`.
|
||||
let voltage = unsafe { bindings::regulator_get_voltage(self.inner.as_ptr()) };
|
||||
let voltage = unsafe { bindings::regulator_get_voltage(self.inner) };
|
||||
|
||||
to_result(voltage).map(|()| Voltage::from_microvolts(voltage))
|
||||
}
|
||||
|
|
@ -270,10 +275,8 @@ fn get_internal(dev: &Device, name: &CStr) -> Result<Regulator<T>> {
|
|||
// received from the C code.
|
||||
from_err_ptr(unsafe { bindings::regulator_get(dev.as_raw(), name.as_char_ptr()) })?;
|
||||
|
||||
// SAFETY: We can safely trust `inner` to be a pointer to a valid
|
||||
// regulator if `ERR_PTR` was not returned.
|
||||
let inner = unsafe { NonNull::new_unchecked(inner) };
|
||||
|
||||
// INVARIANT: `inner` is a pointer obtained from `regulator_get()`, and
|
||||
// the call was successful.
|
||||
Ok(Self {
|
||||
inner,
|
||||
_phantom: PhantomData,
|
||||
|
|
@ -282,12 +285,12 @@ fn get_internal(dev: &Device, name: &CStr) -> Result<Regulator<T>> {
|
|||
|
||||
fn enable_internal(&self) -> Result {
|
||||
// SAFETY: Safe as per the type invariants of `Regulator`.
|
||||
to_result(unsafe { bindings::regulator_enable(self.inner.as_ptr()) })
|
||||
to_result(unsafe { bindings::regulator_enable(self.inner) })
|
||||
}
|
||||
|
||||
fn disable_internal(&self) -> Result {
|
||||
// SAFETY: Safe as per the type invariants of `Regulator`.
|
||||
to_result(unsafe { bindings::regulator_disable(self.inner.as_ptr()) })
|
||||
to_result(unsafe { bindings::regulator_disable(self.inner) })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -349,7 +352,7 @@ impl<T: IsEnabled> Regulator<T> {
|
|||
/// Checks if the regulator is enabled.
|
||||
pub fn is_enabled(&self) -> bool {
|
||||
// SAFETY: Safe as per the type invariants of `Regulator`.
|
||||
unsafe { bindings::regulator_is_enabled(self.inner.as_ptr()) != 0 }
|
||||
unsafe { bindings::regulator_is_enabled(self.inner) != 0 }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -359,11 +362,11 @@ fn drop(&mut self) {
|
|||
// SAFETY: By the type invariants, we know that `self` owns a
|
||||
// reference on the enabled refcount, so it is safe to relinquish it
|
||||
// now.
|
||||
unsafe { bindings::regulator_disable(self.inner.as_ptr()) };
|
||||
unsafe { bindings::regulator_disable(self.inner) };
|
||||
}
|
||||
// SAFETY: By the type invariants, we know that `self` owns a reference,
|
||||
// so it is safe to relinquish it now.
|
||||
unsafe { bindings::regulator_put(self.inner.as_ptr()) };
|
||||
unsafe { bindings::regulator_put(self.inner) };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user