Commit 33ffb0aa authored by Tamir Duberstein's avatar Tamir Duberstein Committed by Viresh Kumar
Browse files

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: default avatarTamir Duberstein <tamird@kernel.org>
Tested-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
parent 173e02d6
Loading
Loading
Loading
Loading
+58 −54
Original line number Diff line number Diff line
@@ -443,23 +443,16 @@ 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 (_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()),
        };
        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
@@ -498,11 +491,22 @@ pub fn set(self, dev: &Device) -> Result<ConfigToken> {
            };

            // 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.
            // 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))
        };

        // 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;

        set_config()
    }

    /// Config's clk callback.