From 2ff21540de3f5f41fcf1aa76b6cf0ac021257f27 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Sun, 28 Jul 2024 22:16:40 +0800 Subject: [PATCH 01/14] Add clkops trait callback --- .gitignore | 3 ++ rust/kernel/clk_hw.rs | 74 ----------------------------------- rust/kernel/clk_provider.rs | 77 ++++++++++++++++++++++++++++++------- rust/kernel/lib.rs | 1 - 4 files changed, 66 insertions(+), 89 deletions(-) delete mode 100644 rust/kernel/clk_hw.rs diff --git a/.gitignore b/.gitignore index 0bbae167bf93e9..3754c68bae4661 100644 --- a/.gitignore +++ b/.gitignore @@ -170,3 +170,6 @@ sphinx_*/ # Rust analyzer configuration /rust-project.json + +# lsp config +code_init.sh diff --git a/rust/kernel/clk_hw.rs b/rust/kernel/clk_hw.rs deleted file mode 100644 index 9e419133f763de..00000000000000 --- a/rust/kernel/clk_hw.rs +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -//! Common clock framework. -//! -//! C header: [`include/linux/clk.h`](../../../../include/linux/clk-provider.h) - -use crate::{ - bindings, - error::{to_result, Result}, - str::CStr, - types::Opaque, -}; - -/// Represents `struct clk_hw` -/// -/// # Invariants -/// -/// The pointer is valid. -pub struct ClkHw(Opaque); - -impl ClkHw { - /// Create ClkHw from raw ptr - pub fn from_raw<'a>(ptr: *mut bindings::clk_hw) -> &'a mut Self { - let ptr = ptr.cast::(); - unsafe { &mut *ptr } - } - - /// Returns a raw pointer to the inner C struct. - #[inline] - pub fn as_ptr(&self) -> *mut bindings::clk_hw { - self.0.get() - } - - pub fn register_clkdev(&mut self, con_id: &'static CStr, dev_id: &'static CStr) -> i32 { - unsafe { - bindings::clk_hw_register_clkdev( - self.0.get(), - con_id.as_char_ptr(), - dev_id.as_char_ptr(), - ) - } - } - // How to implement clk_hw api? - /* - pub fn prepare_enable(&mut self) -> Result { - // SAFETY: call ffi and ptr is valid - unsafe { - to_result(bindings::clk_ops::prepare(self.as_ptr()))?; - let ret = to_result(bindings::clk_ops::enable(self.as_ptr())); - if ret.is_err() { - bindings::clk_ops::unprepare(self.as_ptr()); - return ret; - } - } - Ok(()) - } - */ -} - -/* -impl Drop for ClkHw { - fn drop(&mut self) { - // SAFETY: Type Invariant ptr is valid. - unsafe { - bindings::clk_ops::terminate(self.as_ptr()); - } - } -} -*/ - -// TODO: Implement clk_hw_register_clkdev -// unsafe fn clk_hw_register_clkdev() -> Result {} -// TODO: Implement devm_clk_hw_register -// unsafe fn devm_clk_hw_register() -> Result {} diff --git a/rust/kernel/clk_provider.rs b/rust/kernel/clk_provider.rs index 768c1e6b8fb445..b9e88d7ee3f2c9 100644 --- a/rust/kernel/clk_provider.rs +++ b/rust/kernel/clk_provider.rs @@ -6,11 +6,11 @@ use crate::{ bindings, - error::{to_result, Result}, + error::{from_result, Result}, str::CStr, - types::Opaque, + types::{ForeignOwnable, Opaque}, }; - +use macros::vtable; /// Represents `struct clk_core` /// /// # Invariants @@ -42,6 +42,17 @@ impl ClkHw { self.0.get() } + // Unsafe: Argumets Wrapped in CStr. + unsafe fn register_clkdev(&mut self, con_id: &'static CStr, dev_id: &'static CStr) -> i32 { + unsafe { + bindings::clk_hw_register_clkdev( + self.0.get(), + con_id.as_char_ptr(), + dev_id.as_char_ptr(), + ) + } + } + // How to implement clk_hw api? /* pub fn prepare_enable(&mut self) -> Result { @@ -57,17 +68,6 @@ impl ClkHw { Ok(()) } */ - - // Unsafe: Argumets Wrapped in CStr. - unsafe fn register_clkdev(&mut self, con_id: &'static CStr, dev_id: &'static CStr) -> i32 { - unsafe { - bindings::clk_hw_register_clkdev( - self.0.get(), - con_id.as_char_ptr(), - dev_id.as_char_ptr(), - ) - } - } } /* @@ -103,3 +103,52 @@ impl ClkOps { self.0.get() } } + +// TODO: Implement All ClkOps methods +#[vtable] +pub trait ClkOpsBase { + /// User data that will be accessible to all operations + type Data: ForeignOwnable + Send + Sync = (); + + fn set_rate(_hw: &mut ClkHw, _rate: u32, _parent_rate: u32) -> Result; + + fn round_rate(_hw: &mut ClkHw, _rate: u32, _round_rate: *mut u32) -> Result; + + fn recalc_rate(_hw: &mut ClkHw, parent_rate: u32) -> u32; +} + +unsafe extern "C" fn set_rate_callback( + hw: *mut bindings::clk_hw, + rate: core::ffi::c_ulong, + parent_rate: core::ffi::c_ulong, +) -> core::ffi::c_int { + from_result(|| { + unsafe { + let hw = ClkHw::from_raw(hw); + } + T::set_rate(hw, rate, parent_rate) + }) +} + +unsafe extern "C" fn round_rate_callback( + hw: *mut bindings::clk_hw, + rate: core::ffi::c_ulong, + round_rate: *mut core::ffi::c_ulong, +) -> core::ffi::c_int { + from_result(|| { + unsafe { + let hw = ClkHw::from_raw(hw); + } + T::round_rate(hw, rate, round_rate) + }) +} + +unsafe extern "C" fn recalc_rate_callback( + hw: *mut bindings::clk_hw, + parent_rate: core::ffi::c_ulong, +) -> core::ffi::c_ulong { + unsafe { + let hw = ClkHw::from_raw(hw); + } + T::recalc_rate(hw, parent_rate) +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 25a4ec9edb81ea..ffd6ea115cb0a5 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -39,7 +39,6 @@ mod allocator; pub mod amba; mod build_assert; pub mod clk; -pub mod clk_hw; pub mod clk_provider; pub mod completion; pub mod cred; From 04533c77de067bc9653aa84ed5c67cc9c1a2fc59 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Mon, 29 Jul 2024 09:37:15 +0800 Subject: [PATCH 02/14] Add ClkInitData --- rust/kernel/clk.rs | 33 ++++++++++++++++------ rust/kernel/clk_provider.rs | 55 ++++++++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 9 deletions(-) diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs index 787cdc92e52d12..14a34898263499 100644 --- a/rust/kernel/clk.rs +++ b/rust/kernel/clk.rs @@ -5,8 +5,8 @@ //! C header: [`include/linux/clk.h`](../../../../include/linux/clk.h) use crate::{ - bindings, - error::{ Result, to_result}, + bindings, + error::{to_result, Result}, types::Opaque, }; use core::mem::ManuallyDrop; @@ -22,7 +22,7 @@ impl Clk { /// Create Clk from raw ptr pub fn from_raw<'a>(ptr: *mut bindings::clk) -> &'a mut Self { let ptr = ptr.cast::(); - unsafe {&mut *ptr} + unsafe { &mut *ptr } } /// Returns a raw pointer to the inner C struct. @@ -30,19 +30,19 @@ impl Clk { pub fn as_ptr(&self) -> *mut bindings::clk { self.0.get() } - + /// Get clk rate pub fn get_rate(&self) -> u64 { // SAFETY: call ffi and ptr is valid - unsafe{bindings::clk_get_rate(self.0.get())} + unsafe { bindings::clk_get_rate(self.0.get()) } } /// clk enable pub fn prepare_enable(&self) -> Result { // SAFETY: call ffi and ptr is valid - unsafe{ + unsafe { to_result(bindings::clk_prepare(self.0.get()))?; - let ret = to_result(bindings::clk_enable(self.0.get())); + let ret = to_result(bindings::clk_enable(self.0.get())); if ret.is_err() { bindings::clk_unprepare(self.0.get()); return ret; @@ -50,6 +50,23 @@ impl Clk { } Ok(()) } + + /// clk_get_name + pub fn clk_get_name(&self) -> Option { + // SAFETY: call ffi and ptr is valid + unsafe { + let name = bindings::clk_get_name(self.0.get()); + if name.is_null() { + None + } else { + Some( + core::ffi::CStr::from_ptr(name) + .to_string_lossy() + .into_owned(), + ) + } + } + } } impl Drop for Clk { @@ -88,4 +105,4 @@ impl Drop for EnabledClk { // SAFETY: The pointer is valid by the type invariant.a unsafe { bindings::clk_disable_unprepare(self.0.as_ptr()) }; } -} \ No newline at end of file +} diff --git a/rust/kernel/clk_provider.rs b/rust/kernel/clk_provider.rs index b9e88d7ee3f2c9..8523828f7c6ced 100644 --- a/rust/kernel/clk_provider.rs +++ b/rust/kernel/clk_provider.rs @@ -7,7 +7,7 @@ use crate::{ bindings, error::{from_result, Result}, - str::CStr, + str::{CStr, CString}, types::{ForeignOwnable, Opaque}, }; use macros::vtable; @@ -42,6 +42,17 @@ impl ClkHw { self.0.get() } + pub fn clk_hw_get_name(&self) -> Option { + unsafe { + let name_ptr = bindings::clk_hw_get_name(self.as_ptr()); + if name_ptr.is_null() { + None + } else { + Some(CStr::from_ptr(name_ptr).to_string_lossy().into_owned()) + } + } + } + // Unsafe: Argumets Wrapped in CStr. unsafe fn register_clkdev(&mut self, con_id: &'static CStr, dev_id: &'static CStr) -> i32 { unsafe { @@ -86,6 +97,48 @@ impl Drop for ClkHw { // TODO: Implement devm_clk_hw_register // unsafe fn devm_clk_hw_register() -> Result {} +pub struct ClkInitData(bindings::clk_init_data); + +impl ClkInitData { + /// Create a new ClkInitData + pub fn new() -> Self { + let up = unsafe { MaybeUninit::::zeroed().assume_init() }; + Self(up) + } + + /// Set the name config of the clk_init_data + /// + /// It will automatically set the num_parents to the length of parent_names. + pub fn name_config(mut self, name: &str, parent_names: impl IntoIterator) -> Self { + self.0.name = CString::new(name).unwrap(); + let c_parents: Vec = parent_names + .iter() + .map(|s| CString::new(s).unwrap()) + .collect(); + self.num_parents = c_parents.len(); + self + } + + pub fn ops(mut self, ops: ClkOps) -> Self { + self.0.ops = ops.as_ptr(); + self + } + + pub fn flags(mut self, flags: u32) -> Self { + self.0.flags = flags; + self + } + /// Create ClkInitData from raw ptr + /// + /// # Safety + /// + /// The pointer must be valid. + pub unsafe fn from_raw(ptr: *const bindings::clk_init_data) -> Self { + let ptr = ptr.cast::(); + *ptr + } +} + /// Represents `struct clk_ops` pub struct ClkOps(Opaque); From 865ff35742d354ec152d324656a84586fbbb09ca Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Mon, 29 Jul 2024 10:14:11 +0800 Subject: [PATCH 03/14] Add ClkInitData Modify impl ClkHw --- rust/kernel/clk_provider.rs | 57 +++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/rust/kernel/clk_provider.rs b/rust/kernel/clk_provider.rs index 4c722dec4d1977..7e007e142517e4 100644 --- a/rust/kernel/clk_provider.rs +++ b/rust/kernel/clk_provider.rs @@ -42,15 +42,9 @@ impl ClkHw { self.0.get() } - pub fn clk_hw_get_name(&self) -> Option { - unsafe { - let name_ptr = bindings::clk_hw_get_name(self.as_ptr()); - if name_ptr.is_null() { - None - } else { - Some(CStr::from_ptr(name_ptr).to_string_lossy().into_owned()) - } - } + pub fn name(&self) -> &CStr { + // SAFETY: call ffi and ptr is valid + unsafe { CStr::from_char_ptr(bindings::__clk_hw_get_name(self.0.get())) } } // Register one clock lookup for a struct clk_hw pub fn register_clkdev(&mut self, con_id: &'static CStr, dev_id: &'static CStr) -> Result { @@ -134,6 +128,51 @@ impl ClkInitData { } } +/// Represents `struct clk_ops` +pub struct ClkOps(Opaque); + +// TODO: Create (new) from functions ptr +impl ClkOps { + // TODO! + pub fn from_raw(ptr: *const bindings::clk_ops) -> Self { + // let ptr = ptr.cast::(); + // unsafe { *ptr } + unimplemented!() + } + + /// Set the name config of the clk_init_data + /// + /// It will automatically set the num_parents to the length of parent_names. + pub fn name_config(mut self, name: &str, parent_names: impl IntoIterator) -> Self { + self.0.name = CString::new(name).unwrap(); + let c_parents: Vec = parent_names + .iter() + .map(|s| CString::new(s).unwrap()) + .collect(); + self.num_parents = c_parents.len(); + self + } + + pub fn ops(mut self, ops: ClkOps) -> Self { + self.0.ops = ops.as_ptr(); + self + } + + pub fn flags(mut self, flags: u32) -> Self { + self.0.flags = flags; + self + } + /// Create ClkInitData from raw ptr + /// + /// # Safety + /// + /// The pointer must be valid. + pub unsafe fn from_raw(ptr: *const bindings::clk_init_data) -> Self { + let ptr = ptr.cast::(); + *ptr + } +} + /// Trait about a clock device's operations #[vtable] pub trait ClkOps { From 41eefe6ddca5d26acf43a136f2ee5ec774878551 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Mon, 29 Jul 2024 10:34:18 +0800 Subject: [PATCH 04/14] Merge remote branch for amend --- rust/kernel/clk_provider.rs | 45 ------------------------------------- 1 file changed, 45 deletions(-) diff --git a/rust/kernel/clk_provider.rs b/rust/kernel/clk_provider.rs index 7e007e142517e4..e548a7c751b391 100644 --- a/rust/kernel/clk_provider.rs +++ b/rust/kernel/clk_provider.rs @@ -128,51 +128,6 @@ impl ClkInitData { } } -/// Represents `struct clk_ops` -pub struct ClkOps(Opaque); - -// TODO: Create (new) from functions ptr -impl ClkOps { - // TODO! - pub fn from_raw(ptr: *const bindings::clk_ops) -> Self { - // let ptr = ptr.cast::(); - // unsafe { *ptr } - unimplemented!() - } - - /// Set the name config of the clk_init_data - /// - /// It will automatically set the num_parents to the length of parent_names. - pub fn name_config(mut self, name: &str, parent_names: impl IntoIterator) -> Self { - self.0.name = CString::new(name).unwrap(); - let c_parents: Vec = parent_names - .iter() - .map(|s| CString::new(s).unwrap()) - .collect(); - self.num_parents = c_parents.len(); - self - } - - pub fn ops(mut self, ops: ClkOps) -> Self { - self.0.ops = ops.as_ptr(); - self - } - - pub fn flags(mut self, flags: u32) -> Self { - self.0.flags = flags; - self - } - /// Create ClkInitData from raw ptr - /// - /// # Safety - /// - /// The pointer must be valid. - pub unsafe fn from_raw(ptr: *const bindings::clk_init_data) -> Self { - let ptr = ptr.cast::(); - *ptr - } -} - /// Trait about a clock device's operations #[vtable] pub trait ClkOps { From cd6e155131b7ab32bd6a07bb688dd913878372b0 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Mon, 29 Jul 2024 10:54:21 +0800 Subject: [PATCH 05/14] Modify ClkHw:name --- rust/kernel/clk.rs | 11 +++++++---- rust/kernel/clk_provider.rs | 21 +++++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs index b99e90f0d22be4..c9ef11bb624216 100644 --- a/rust/kernel/clk.rs +++ b/rust/kernel/clk.rs @@ -6,7 +6,6 @@ use crate::{ bindings, - clk_provider::ClkHw, error::{to_result, Result}, str::CStr, types::Opaque, @@ -53,9 +52,13 @@ impl Clk { Ok(()) } - pub fn name(&self) -> &CStr { - // SAFETY: call ffi and ptr is valid - unsafe { CStr::from_char_ptr(bindings::__clk_get_name(self.0.get())) } + pub fn name(&self) -> &str { + // SAFETY: if clk is valid, name is valid. name must be a UTF-8 string. + unsafe { + CStr::from_char_ptr(bindings::__clk_get_name(self.0.get())) + .to_str() + .unwrap() + } } } diff --git a/rust/kernel/clk_provider.rs b/rust/kernel/clk_provider.rs index e548a7c751b391..097700ea7d6fa4 100644 --- a/rust/kernel/clk_provider.rs +++ b/rust/kernel/clk_provider.rs @@ -10,6 +10,7 @@ use crate::{ str::{CStr, CString}, types::{ForeignOwnable, Opaque}, }; +use core::{marker::PhantomData, mem::MaybeUninit}; use macros::vtable; /// Represents `struct clk_core` /// @@ -42,9 +43,13 @@ impl ClkHw { self.0.get() } - pub fn name(&self) -> &CStr { - // SAFETY: call ffi and ptr is valid - unsafe { CStr::from_char_ptr(bindings::__clk_hw_get_name(self.0.get())) } + pub fn name(&self) -> &str { + // SAFETY: if clk_hw is valid, name is valid. name must be UTF-8 string. + unsafe { + CStr::from_char_ptr(bindings::__clk_hw_get_name(self.0.get())) + .to_str() + .unwrap() + } } // Register one clock lookup for a struct clk_hw pub fn register_clkdev(&mut self, con_id: &'static CStr, dev_id: &'static CStr) -> Result { @@ -98,9 +103,13 @@ impl ClkInitData { /// Set the name config of the clk_init_data /// /// It will automatically set the num_parents to the length of parent_names. - pub fn name_config(mut self, name: &str, parent_names: impl IntoIterator) -> Self { + pub fn name_config( + mut self, + name: &str, + parent_names: impl IntoIterator, + ) -> Self { self.0.name = CString::new(name).unwrap(); - let c_parents: Vec = parent_names + let c_parents = parent_names .iter() .map(|s| CString::new(s).unwrap()) .collect(); @@ -108,7 +117,7 @@ impl ClkInitData { self } - pub fn ops(mut self, ops: ClkOps) -> Self { + pub fn ops(mut self, ops: impl ClkOps) -> Self { self.0.ops = ops.as_ptr(); self } From 9040eb4635f84a363f53c83fc7391d5a8a6c457e Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Mon, 29 Jul 2024 13:23:39 +0800 Subject: [PATCH 06/14] Modify ClkOps: from_result --- drivers/i2c/busses/i2c_bcm2835_rust.rs | 4 +++ rust/kernel/clk_provider.rs | 50 +++++++++++++++++--------- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/drivers/i2c/busses/i2c_bcm2835_rust.rs b/drivers/i2c/busses/i2c_bcm2835_rust.rs index 021d79a5b93923..154034cb7d678e 100644 --- a/drivers/i2c/busses/i2c_bcm2835_rust.rs +++ b/drivers/i2c/busses/i2c_bcm2835_rust.rs @@ -221,6 +221,10 @@ fn clk_bcm2835_i2c_recalc_rate(hw: &mut ClkHw, parent_rate: u32) -> u32 { parent_rate.div_ceil(divider) } +struct ClkBcm2835I2cOps; + +impl ClkOps for ClkBcm2835I2cOps {} + impl kernel::Module for Bcm2835I2cDevice { fn init(_module: &'static ThisModule) -> Result { pr_info!("BCM2835 i2c bus device driver (init)\n"); diff --git a/rust/kernel/clk_provider.rs b/rust/kernel/clk_provider.rs index 097700ea7d6fa4..25dc95ea21d07e 100644 --- a/rust/kernel/clk_provider.rs +++ b/rust/kernel/clk_provider.rs @@ -171,28 +171,36 @@ pub trait ClkOps { /// parent clock that should be used to provide the clock rate. fn determine_rate(hw: &ClkHw, req: *mut bindings::clk_rate_request) -> i32; /// Change the input source of this clock - fn set_parent(hw: &ClkHw, index: u8) -> i32; + /// Returns 0 on success, -EERROR otherwise. + fn set_parent(hw: &ClkHw, index: u8) -> Result; /// Queries the hardware to determine the parent of a clock fn get_parent(hw: &ClkHw) -> u8; /// Change the rate of this clock - fn set_rate(hw: &ClkHw, rate: u64, parent_rate: u64) -> i32; + /// Returns 0 on success, -EERROR otherwise. + fn set_rate(hw: &ClkHw, rate: u64, parent_rate: u64) -> Result; /// Change the rate and the parent of this clock - fn set_rate_and_parent(hw: &ClkHw, rate: u64, parent_rate: u64, index: u8) -> i32; + /// Returns 0 on success, -EERROR otherwise. + fn set_rate_and_parent(hw: &ClkHw, rate: u64, parent_rate: u64, index: u8) -> Result; /// Recalculate the accuracy of this clock fn recalc_accuracy(hw: &ClkHw, parent_accuracy: u64) -> u64; /// Queries the hardware to get the current phase of a clock + /// error codes on failure. fn get_phase(hw: &ClkHw) -> i32; /// Shift the phase this clock signal in degrees specified by the second argument - fn set_phase(hw: &ClkHw, degrees: i32) -> i32; + /// Returns 0 on success, -EERROR otherwise. + fn set_phase(hw: &ClkHw, degrees: i32) -> Result; /// Queries the hardware to get the current duty cycle ratio of a clock fn get_duty_cycle(hw: &ClkHw, duty: *mut bindings::clk_duty) -> i32; /// Apply the duty cycle ratio to this clock signal specified by the numerator (2nd argurment) and denominator (3rd argument) - fn set_duty_cycle(hw: &ClkHw, duty: *mut bindings::clk_duty) -> i32; + /// Returns 0 on success, -EERROR otherwise. + fn set_duty_cycle(hw: &ClkHw, duty: *mut bindings::clk_duty) -> Result; /// Perform platform-specific initialization magic - fn init(hw: &ClkHw) -> i32; + /// Returns 0 on success, -EERROR otherwise. + fn init(hw: &ClkHw) -> Result; /// Free any resource allocated by init fn terminate(hw: &ClkHw); /// Set up type-specific debugfs entries for this clock + /// Returns 0 on success, -EERROR otherwise. fn debug_init(hw: &ClkHw, dentry: *mut bindings::dentry); } @@ -280,8 +288,10 @@ impl Adapter { clk_hw: *mut bindings::clk_hw, index: u8, ) -> core::ffi::c_int { - let hw = unsafe { ClkHw::from_raw(clk_hw) }; - T::set_parent(&hw, index) + from_result(|| { + let hw = unsafe { ClkHw::from_raw(clk_hw) }; + T::set_parent(&hw, index) + }) } unsafe extern "C" fn get_parent_callback(clk_hw: *mut bindings::clk_hw) -> bindings::u8_ { @@ -306,8 +316,10 @@ impl Adapter { parent_rate: u64, index: u8, ) -> core::ffi::c_int { - let hw = unsafe { ClkHw::from_raw(clk_hw) }; - T::set_rate_and_parent(&hw, rate, parent_rate, index) + from_result(|| { + let hw = unsafe { ClkHw::from_raw(clk_hw) }; + T::set_rate_and_parent(&hw, rate, parent_rate, index) + }) } unsafe extern "C" fn recalc_accuracy_callback( @@ -327,8 +339,10 @@ impl Adapter { clk_hw: *mut bindings::clk_hw, degrees: i32, ) -> core::ffi::c_int { - let hw = unsafe { ClkHw::from_raw(clk_hw) }; - T::set_phase(&hw, degrees) + from_result(|| { + let hw = unsafe { ClkHw::from_raw(clk_hw) }; + T::set_phase(&hw, degrees) + }) } unsafe extern "C" fn get_duty_cycle_callback( @@ -343,13 +357,17 @@ impl Adapter { clk_hw: *mut bindings::clk_hw, duty: *mut bindings::clk_duty, ) -> core::ffi::c_int { - let hw = unsafe { ClkHw::from_raw(clk_hw) }; - T::set_duty_cycle(&hw, duty) + from_result(|| { + let hw = unsafe { ClkHw::from_raw(clk_hw) }; + T::set_duty_cycle(&hw, duty) + }) } unsafe extern "C" fn init_callback(clk_hw: *mut bindings::clk_hw) -> core::ffi::c_int { - let hw = unsafe { ClkHw::from_raw(clk_hw) }; - T::init(&hw) + from_result(|| { + let hw = unsafe { ClkHw::from_raw(clk_hw) }; + T::init(&hw) + }) } unsafe extern "C" fn terminate_callback(clk_hw: *mut bindings::clk_hw) { From 4e3dfd6f083f89069f75c6810af0d2aac4369eb0 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Mon, 29 Jul 2024 13:23:39 +0800 Subject: [PATCH 07/14] Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia --- rust/kernel/clk.rs | 4 +-- rust/kernel/clk_provider.rs | 50 ++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 32 deletions(-) diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs index c9ef11bb624216..b4c9f8a06d586d 100644 --- a/rust/kernel/clk.rs +++ b/rust/kernel/clk.rs @@ -52,12 +52,10 @@ impl Clk { Ok(()) } - pub fn name(&self) -> &str { + pub fn name(&self) -> &CStr { // SAFETY: if clk is valid, name is valid. name must be a UTF-8 string. unsafe { CStr::from_char_ptr(bindings::__clk_get_name(self.0.get())) - .to_str() - .unwrap() } } } diff --git a/rust/kernel/clk_provider.rs b/rust/kernel/clk_provider.rs index 25dc95ea21d07e..db6997dcc7fa51 100644 --- a/rust/kernel/clk_provider.rs +++ b/rust/kernel/clk_provider.rs @@ -6,10 +6,11 @@ use crate::{ bindings, - error::{from_result, Result}, + error::{from_result, to_result, Result}, str::{CStr, CString}, types::{ForeignOwnable, Opaque}, }; +use alloc::vec::Vec; use core::{marker::PhantomData, mem::MaybeUninit}; use macros::vtable; /// Represents `struct clk_core` @@ -43,13 +44,9 @@ impl ClkHw { self.0.get() } - pub fn name(&self) -> &str { + pub fn name(&self) -> &CStr { // SAFETY: if clk_hw is valid, name is valid. name must be UTF-8 string. - unsafe { - CStr::from_char_ptr(bindings::__clk_hw_get_name(self.0.get())) - .to_str() - .unwrap() - } + unsafe { CStr::from_char_ptr(bindings::clk_hw_get_name(self.0.get())) } } // Register one clock lookup for a struct clk_hw pub fn register_clkdev(&mut self, con_id: &'static CStr, dev_id: &'static CStr) -> Result { @@ -103,26 +100,23 @@ impl ClkInitData { /// Set the name config of the clk_init_data /// /// It will automatically set the num_parents to the length of parent_names. - pub fn name_config( - mut self, - name: &str, - parent_names: impl IntoIterator, - ) -> Self { - self.0.name = CString::new(name).unwrap(); - let c_parents = parent_names - .iter() - .map(|s| CString::new(s).unwrap()) - .collect(); - self.num_parents = c_parents.len(); + pub fn name_config(mut self, name: &CStr, parent_names: &[CStr]) -> Self { + self.0.name = name.as_char_ptr(); + self.0.num_parents = parent_names.len() as u8; + self.0.parent_names = parent_names + .into_iter() + .map(|s| s.as_char_ptr()) + .collect::>() + .as_ptr(); self } pub fn ops(mut self, ops: impl ClkOps) -> Self { - self.0.ops = ops.as_ptr(); + self.0.ops = ops; self } - pub fn flags(mut self, flags: u32) -> Self { + pub fn flags(mut self, flags: u64) -> Self { self.0.flags = flags; self } @@ -270,10 +264,8 @@ impl Adapter { rate: u64, parent_rate: *mut u64, ) -> core::ffi::c_long { - from_result(|| { - let hw = unsafe { ClkHw::from_raw(clk_hw) }; - T::round_rate(&hw, rate, unsafe { &mut *parent_rate }) - }) + let hw = unsafe { ClkHw::from_raw(clk_hw) }; + T::round_rate(&hw, rate, unsafe { &mut *parent_rate }) } unsafe extern "C" fn determine_rate_callback( @@ -290,7 +282,7 @@ impl Adapter { ) -> core::ffi::c_int { from_result(|| { let hw = unsafe { ClkHw::from_raw(clk_hw) }; - T::set_parent(&hw, index) + T::set_parent(&hw, index).and(Ok(0)) }) } @@ -306,7 +298,7 @@ impl Adapter { ) -> core::ffi::c_int { from_result(|| { let hw = unsafe { ClkHw::from_raw(clk_hw) }; - T::set_rate(&hw, rate, parent_rate) + T::set_rate(&hw, rate, parent_rate).and(Ok(0)) }) } @@ -318,7 +310,7 @@ impl Adapter { ) -> core::ffi::c_int { from_result(|| { let hw = unsafe { ClkHw::from_raw(clk_hw) }; - T::set_rate_and_parent(&hw, rate, parent_rate, index) + T::set_rate_and_parent(&hw, rate, parent_rate, index).and(Ok(0)) }) } @@ -341,7 +333,7 @@ impl Adapter { ) -> core::ffi::c_int { from_result(|| { let hw = unsafe { ClkHw::from_raw(clk_hw) }; - T::set_phase(&hw, degrees) + T::set_phase(&hw, degrees).and(Ok(0)) }) } @@ -359,7 +351,7 @@ impl Adapter { ) -> core::ffi::c_int { from_result(|| { let hw = unsafe { ClkHw::from_raw(clk_hw) }; - T::set_duty_cycle(&hw, duty) + T::set_duty_cycle(&hw, duty).and(Ok(0)) }) } From 3698e1a89830bc631e39190e707999a2d0f9508c Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Mon, 29 Jul 2024 13:23:39 +0800 Subject: [PATCH 08/14] Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia --- rust/kernel/clk_provider.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/kernel/clk_provider.rs b/rust/kernel/clk_provider.rs index db6997dcc7fa51..18d8aed221ab70 100644 --- a/rust/kernel/clk_provider.rs +++ b/rust/kernel/clk_provider.rs @@ -100,7 +100,7 @@ impl ClkInitData { /// Set the name config of the clk_init_data /// /// It will automatically set the num_parents to the length of parent_names. - pub fn name_config(mut self, name: &CStr, parent_names: &[CStr]) -> Self { + pub fn name_config(mut self, name: &CStr, parent_names: Vec<&CStr>) -> Self { self.0.name = name.as_char_ptr(); self.0.num_parents = parent_names.len() as u8; self.0.parent_names = parent_names From dde95957aeed3e4210e82e78272ee77900868fc9 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Mon, 29 Jul 2024 13:23:39 +0800 Subject: [PATCH 09/14] Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia --- rust/kernel/clk_provider.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/rust/kernel/clk_provider.rs b/rust/kernel/clk_provider.rs index 18d8aed221ab70..c776552b452a2d 100644 --- a/rust/kernel/clk_provider.rs +++ b/rust/kernel/clk_provider.rs @@ -7,7 +7,7 @@ use crate::{ bindings, error::{from_result, to_result, Result}, - str::{CStr, CString}, + str::CStr, types::{ForeignOwnable, Opaque}, }; use alloc::vec::Vec; @@ -100,19 +100,23 @@ impl ClkInitData { /// Set the name config of the clk_init_data /// /// It will automatically set the num_parents to the length of parent_names. - pub fn name_config(mut self, name: &CStr, parent_names: Vec<&CStr>) -> Self { + pub fn name_config(mut self, name: &CStr, parent_names: Vec<&'static CStr>) -> Self { self.0.name = name.as_char_ptr(); self.0.num_parents = parent_names.len() as u8; self.0.parent_names = parent_names .into_iter() .map(|s| s.as_char_ptr()) - .collect::>() + .collect::>() .as_ptr(); self } - pub fn ops(mut self, ops: impl ClkOps) -> Self { - self.0.ops = ops; + pub fn ops(mut self, ops: T) -> Self + where + T: ClkOps, + { + let ops = Adapter::::build(); + self.0.ops = ops as *const bindings::clk_ops; self } @@ -358,7 +362,7 @@ impl Adapter { unsafe extern "C" fn init_callback(clk_hw: *mut bindings::clk_hw) -> core::ffi::c_int { from_result(|| { let hw = unsafe { ClkHw::from_raw(clk_hw) }; - T::init(&hw) + T::init(&hw).and(Ok(0)) }) } From 2a9a04b3e8881f18ee400b861fe528ac4f3f159d Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Mon, 29 Jul 2024 13:23:39 +0800 Subject: [PATCH 10/14] Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia --- rust/kernel/clk_provider.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/rust/kernel/clk_provider.rs b/rust/kernel/clk_provider.rs index c776552b452a2d..541090279e80e9 100644 --- a/rust/kernel/clk_provider.rs +++ b/rust/kernel/clk_provider.rs @@ -103,11 +103,13 @@ impl ClkInitData { pub fn name_config(mut self, name: &CStr, parent_names: Vec<&'static CStr>) -> Self { self.0.name = name.as_char_ptr(); self.0.num_parents = parent_names.len() as u8; - self.0.parent_names = parent_names - .into_iter() - .map(|s| s.as_char_ptr()) - .collect::>() - .as_ptr(); + self.0.parent_names = { + let mut vec: Vec<*const i8> = Vec::with_capacity(parent_names.len()); + for s in parent_names { + vec.try_push(s.as_char_ptr()); + } + vec + }; self } From ef7b5ba90ac9dedecc27dff0a8abd59ad946a9bb Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Mon, 29 Jul 2024 13:23:39 +0800 Subject: [PATCH 11/14] Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia --- rust/kernel/clk_provider.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/kernel/clk_provider.rs b/rust/kernel/clk_provider.rs index 541090279e80e9..8b10d95cd5d584 100644 --- a/rust/kernel/clk_provider.rs +++ b/rust/kernel/clk_provider.rs @@ -104,7 +104,7 @@ impl ClkInitData { self.0.name = name.as_char_ptr(); self.0.num_parents = parent_names.len() as u8; self.0.parent_names = { - let mut vec: Vec<*const i8> = Vec::with_capacity(parent_names.len()); + let mut vec: Vec<*const i8> = Vec::new(); for s in parent_names { vec.try_push(s.as_char_ptr()); } From 33df0462d37f6b8fcdc42745f619a0fa37da1e51 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Mon, 29 Jul 2024 13:23:39 +0800 Subject: [PATCH 12/14] Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia --- rust/kernel/clk_provider.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/kernel/clk_provider.rs b/rust/kernel/clk_provider.rs index 8b10d95cd5d584..e9c4ba6bc9350e 100644 --- a/rust/kernel/clk_provider.rs +++ b/rust/kernel/clk_provider.rs @@ -108,7 +108,7 @@ impl ClkInitData { for s in parent_names { vec.try_push(s.as_char_ptr()); } - vec + vec.as_ptr() }; self } From fa0d069b35aa1854c13c45c6ada9a053de0679cc Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Mon, 29 Jul 2024 13:23:39 +0800 Subject: [PATCH 13/14] Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia --- rust/kernel/clk_provider.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rust/kernel/clk_provider.rs b/rust/kernel/clk_provider.rs index e9c4ba6bc9350e..a50a92b9bdd7c2 100644 --- a/rust/kernel/clk_provider.rs +++ b/rust/kernel/clk_provider.rs @@ -11,7 +11,7 @@ use crate::{ types::{ForeignOwnable, Opaque}, }; use alloc::vec::Vec; -use core::{marker::PhantomData, mem::MaybeUninit}; +use core::{cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit}; use macros::vtable; /// Represents `struct clk_core` /// @@ -33,7 +33,7 @@ pub struct ClkHw(Opaque); impl ClkHw { /// Create ClkHw from raw ptr - pub fn from_raw<'a>(ptr: *mut bindings::clk_hw) -> &'a Self { + pub unsafe fn from_raw<'a>(ptr: *mut bindings::clk_hw) -> &'a Self { let ptr = ptr.cast::(); unsafe { &*ptr } } @@ -113,7 +113,7 @@ impl ClkInitData { self } - pub fn ops(mut self, ops: T) -> Self + pub fn ops(mut self, _ops: T) -> Self where T: ClkOps, { @@ -131,9 +131,9 @@ impl ClkInitData { /// # Safety /// /// The pointer must be valid. - pub unsafe fn from_raw(ptr: *const bindings::clk_init_data) -> Self { + pub unsafe fn from_raw<'a>(ptr: *const bindings::clk_init_data) -> &'a Self { let ptr = ptr.cast::(); - *ptr + unsafe { &*ptr } } } From 9829db2926f96894263c4c8a3057ad41117fca48 Mon Sep 17 00:00:00 2001 From: Nostalgia Date: Mon, 29 Jul 2024 13:23:39 +0800 Subject: [PATCH 14/14] Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia Modify ClkOps: from_result ClkInitData: Config Modify methods of ClkOps for Result<()>, Modify initiation of ClkInitData. Signed-off-by: Nostalgia