mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 11:06:41 -05:00
rust: opp: simplify callers of to_c_str_array
Use `Option` combinators to make this a bit less noisy. Wrap the `dev_pm_opp_set_config` operation in a closure and use type ascription to leverage the compiler to check for use after free. Signed-off-by: Tamir Duberstein <tamird@kernel.org> Tested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
This commit is contained in:
committed by
Viresh Kumar
parent
173e02d674
commit
33ffb0aa8c
@@ -443,66 +443,70 @@ pub fn set_supported_hw(mut self, hw: KVec<u32>) -> Result<Self> {
|
||||
///
|
||||
/// The returned [`ConfigToken`] will remove the configuration when dropped.
|
||||
pub fn set(self, dev: &Device) -> Result<ConfigToken> {
|
||||
let (_clk_list, clk_names) = match &self.clk_names {
|
||||
Some(x) => {
|
||||
let list = to_c_str_array(x)?;
|
||||
let ptr = list.as_ptr();
|
||||
(Some(list), ptr)
|
||||
}
|
||||
None => (None, ptr::null()),
|
||||
let clk_names = self.clk_names.as_deref().map(to_c_str_array).transpose()?;
|
||||
let regulator_names = self
|
||||
.regulator_names
|
||||
.as_deref()
|
||||
.map(to_c_str_array)
|
||||
.transpose()?;
|
||||
|
||||
let set_config = || {
|
||||
let clk_names = clk_names.as_ref().map_or(ptr::null(), |c| c.as_ptr());
|
||||
let regulator_names = regulator_names.as_ref().map_or(ptr::null(), |c| c.as_ptr());
|
||||
|
||||
let prop_name = self
|
||||
.prop_name
|
||||
.as_ref()
|
||||
.map_or(ptr::null(), |p| p.as_char_ptr());
|
||||
|
||||
let (supported_hw, supported_hw_count) = self
|
||||
.supported_hw
|
||||
.as_ref()
|
||||
.map_or((ptr::null(), 0), |hw| (hw.as_ptr(), hw.len() as u32));
|
||||
|
||||
let (required_dev, required_dev_index) = self
|
||||
.required_dev
|
||||
.as_ref()
|
||||
.map_or((ptr::null_mut(), 0), |(dev, idx)| (dev.as_raw(), *idx));
|
||||
|
||||
let mut config = bindings::dev_pm_opp_config {
|
||||
clk_names,
|
||||
config_clks: if T::HAS_CONFIG_CLKS {
|
||||
Some(Self::config_clks)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
prop_name,
|
||||
regulator_names,
|
||||
config_regulators: if T::HAS_CONFIG_REGULATORS {
|
||||
Some(Self::config_regulators)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
supported_hw,
|
||||
supported_hw_count,
|
||||
|
||||
required_dev,
|
||||
required_dev_index,
|
||||
};
|
||||
|
||||
// SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety
|
||||
// requirements. The OPP core guarantees not to access fields of [`Config`] after this
|
||||
// call and so we don't need to save a copy of them for future use.
|
||||
let ret = unsafe { bindings::dev_pm_opp_set_config(dev.as_raw(), &mut config) };
|
||||
|
||||
to_result(ret).map(|()| ConfigToken(ret))
|
||||
};
|
||||
|
||||
let (_regulator_list, regulator_names) = match &self.regulator_names {
|
||||
Some(x) => {
|
||||
let list = to_c_str_array(x)?;
|
||||
let ptr = list.as_ptr();
|
||||
(Some(list), ptr)
|
||||
}
|
||||
None => (None, ptr::null()),
|
||||
};
|
||||
// Ensure the closure does not accidentally drop owned data; if violated, the compiler
|
||||
// produces E0525 with e.g.:
|
||||
//
|
||||
// ```
|
||||
// closure is `FnOnce` because it moves the variable `clk_names` out of its environment
|
||||
// ```
|
||||
let _: &dyn Fn() -> _ = &set_config;
|
||||
|
||||
let prop_name = self
|
||||
.prop_name
|
||||
.as_ref()
|
||||
.map_or(ptr::null(), |p| p.as_char_ptr());
|
||||
|
||||
let (supported_hw, supported_hw_count) = self
|
||||
.supported_hw
|
||||
.as_ref()
|
||||
.map_or((ptr::null(), 0), |hw| (hw.as_ptr(), hw.len() as u32));
|
||||
|
||||
let (required_dev, required_dev_index) = self
|
||||
.required_dev
|
||||
.as_ref()
|
||||
.map_or((ptr::null_mut(), 0), |(dev, idx)| (dev.as_raw(), *idx));
|
||||
|
||||
let mut config = bindings::dev_pm_opp_config {
|
||||
clk_names,
|
||||
config_clks: if T::HAS_CONFIG_CLKS {
|
||||
Some(Self::config_clks)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
prop_name,
|
||||
regulator_names,
|
||||
config_regulators: if T::HAS_CONFIG_REGULATORS {
|
||||
Some(Self::config_regulators)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
supported_hw,
|
||||
supported_hw_count,
|
||||
|
||||
required_dev,
|
||||
required_dev_index,
|
||||
};
|
||||
|
||||
// SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety
|
||||
// requirements. The OPP core guarantees not to access fields of [`Config`] after this call
|
||||
// and so we don't need to save a copy of them for future use.
|
||||
let ret = unsafe { bindings::dev_pm_opp_set_config(dev.as_raw(), &mut config) };
|
||||
|
||||
to_result(ret).map(|()| ConfigToken(ret))
|
||||
set_config()
|
||||
}
|
||||
|
||||
/// Config's clk callback.
|
||||
|
||||
Reference in New Issue
Block a user