kernel/cpufreq.rs
1// SPDX-License-Identifier: GPL-2.0
2
3//! CPU frequency scaling.
4//!
5//! This module provides rust abstractions for interacting with the cpufreq subsystem.
6//!
7//! C header: [`include/linux/cpufreq.h`](srctree/include/linux/cpufreq.h)
8//!
9//! Reference: <https://docs.kernel.org/admin-guide/pm/cpufreq.html>
10
11use crate::{
12 clk::Hertz,
13 cpumask,
14 device::{Bound, Device},
15 devres::Devres,
16 error::{code::*, from_err_ptr, from_result, to_result, Result, VTABLE_DEFAULT_ERROR},
17 ffi::{c_char, c_ulong},
18 prelude::*,
19 types::ForeignOwnable,
20 types::Opaque,
21};
22
23#[cfg(CONFIG_COMMON_CLK)]
24use crate::clk::Clk;
25
26use core::{
27 cell::UnsafeCell,
28 marker::PhantomData,
29 mem::MaybeUninit,
30 ops::{Deref, DerefMut},
31 pin::Pin,
32 ptr,
33};
34
35use macros::vtable;
36
37/// Maximum length of CPU frequency driver's name.
38const CPUFREQ_NAME_LEN: usize = bindings::CPUFREQ_NAME_LEN as usize;
39
40/// Default transition latency value in nanoseconds.
41pub const ETERNAL_LATENCY_NS: u32 = bindings::CPUFREQ_ETERNAL as u32;
42
43/// CPU frequency driver flags.
44pub mod flags {
45 /// Driver needs to update internal limits even if frequency remains unchanged.
46 pub const NEED_UPDATE_LIMITS: u16 = 1 << 0;
47
48 /// Platform where constants like `loops_per_jiffy` are unaffected by frequency changes.
49 pub const CONST_LOOPS: u16 = 1 << 1;
50
51 /// Register driver as a thermal cooling device automatically.
52 pub const IS_COOLING_DEV: u16 = 1 << 2;
53
54 /// Supports multiple clock domains with per-policy governors in `cpu/cpuN/cpufreq/`.
55 pub const HAVE_GOVERNOR_PER_POLICY: u16 = 1 << 3;
56
57 /// Allows post-change notifications outside of the `target()` routine.
58 pub const ASYNC_NOTIFICATION: u16 = 1 << 4;
59
60 /// Ensure CPU starts at a valid frequency from the driver's freq-table.
61 pub const NEED_INITIAL_FREQ_CHECK: u16 = 1 << 5;
62
63 /// Disallow governors with `dynamic_switching` capability.
64 pub const NO_AUTO_DYNAMIC_SWITCHING: u16 = 1 << 6;
65}
66
67/// Relations from the C code.
68const CPUFREQ_RELATION_L: u32 = 0;
69const CPUFREQ_RELATION_H: u32 = 1;
70const CPUFREQ_RELATION_C: u32 = 2;
71
72/// Can be used with any of the above values.
73const CPUFREQ_RELATION_E: u32 = 1 << 2;
74
75/// CPU frequency selection relations.
76///
77/// CPU frequency selection relations, each optionally marked as "efficient".
78#[derive(Copy, Clone, Debug, Eq, PartialEq)]
79pub enum Relation {
80 /// Select the lowest frequency at or above target.
81 Low(bool),
82 /// Select the highest frequency below or at target.
83 High(bool),
84 /// Select the closest frequency to the target.
85 Close(bool),
86}
87
88impl Relation {
89 // Construct from a C-compatible `u32` value.
90 fn new(val: u32) -> Result<Self> {
91 let efficient = val & CPUFREQ_RELATION_E != 0;
92
93 Ok(match val & !CPUFREQ_RELATION_E {
94 CPUFREQ_RELATION_L => Self::Low(efficient),
95 CPUFREQ_RELATION_H => Self::High(efficient),
96 CPUFREQ_RELATION_C => Self::Close(efficient),
97 _ => return Err(EINVAL),
98 })
99 }
100}
101
102impl From<Relation> for u32 {
103 // Convert to a C-compatible `u32` value.
104 fn from(rel: Relation) -> Self {
105 let (mut val, efficient) = match rel {
106 Relation::Low(e) => (CPUFREQ_RELATION_L, e),
107 Relation::High(e) => (CPUFREQ_RELATION_H, e),
108 Relation::Close(e) => (CPUFREQ_RELATION_C, e),
109 };
110
111 if efficient {
112 val |= CPUFREQ_RELATION_E;
113 }
114
115 val
116 }
117}
118
119/// Policy data.
120///
121/// Rust abstraction for the C `struct cpufreq_policy_data`.
122///
123/// # Invariants
124///
125/// A [`PolicyData`] instance always corresponds to a valid C `struct cpufreq_policy_data`.
126///
127/// The callers must ensure that the `struct cpufreq_policy_data` is valid for access and remains
128/// valid for the lifetime of the returned reference.
129#[repr(transparent)]
130pub struct PolicyData(Opaque<bindings::cpufreq_policy_data>);
131
132impl PolicyData {
133 /// Creates a mutable reference to an existing `struct cpufreq_policy_data` pointer.
134 ///
135 /// # Safety
136 ///
137 /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime
138 /// of the returned reference.
139 #[inline]
140 pub unsafe fn from_raw_mut<'a>(ptr: *mut bindings::cpufreq_policy_data) -> &'a mut Self {
141 // SAFETY: Guaranteed by the safety requirements of the function.
142 //
143 // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the
144 // lifetime of the returned reference.
145 unsafe { &mut *ptr.cast() }
146 }
147
148 /// Returns a raw pointer to the underlying C `cpufreq_policy_data`.
149 #[inline]
150 pub fn as_raw(&self) -> *mut bindings::cpufreq_policy_data {
151 let this: *const Self = self;
152 this.cast_mut().cast()
153 }
154
155 /// Wrapper for `cpufreq_generic_frequency_table_verify`.
156 #[inline]
157 pub fn generic_verify(&self) -> Result {
158 // SAFETY: By the type invariant, the pointer stored in `self` is valid.
159 to_result(unsafe { bindings::cpufreq_generic_frequency_table_verify(self.as_raw()) })
160 }
161}
162
163/// The frequency table index.
164///
165/// Represents index with a frequency table.
166///
167/// # Invariants
168///
169/// The index must correspond to a valid entry in the [`Table`] it is used for.
170#[derive(Copy, Clone, PartialEq, Eq, Debug)]
171pub struct TableIndex(usize);
172
173impl TableIndex {
174 /// Creates an instance of [`TableIndex`].
175 ///
176 /// # Safety
177 ///
178 /// The caller must ensure that `index` correspond to a valid entry in the [`Table`] it is used
179 /// for.
180 pub unsafe fn new(index: usize) -> Self {
181 // INVARIANT: The caller ensures that `index` correspond to a valid entry in the [`Table`].
182 Self(index)
183 }
184}
185
186impl From<TableIndex> for usize {
187 #[inline]
188 fn from(index: TableIndex) -> Self {
189 index.0
190 }
191}
192
193/// CPU frequency table.
194///
195/// Rust abstraction for the C `struct cpufreq_frequency_table`.
196///
197/// # Invariants
198///
199/// A [`Table`] instance always corresponds to a valid C `struct cpufreq_frequency_table`.
200///
201/// The callers must ensure that the `struct cpufreq_frequency_table` is valid for access and
202/// remains valid for the lifetime of the returned reference.
203///
204/// ## Examples
205///
206/// The following example demonstrates how to read a frequency value from [`Table`].
207///
208/// ```
209/// use kernel::cpufreq::{Policy, TableIndex};
210///
211/// fn show_freq(policy: &Policy) -> Result {
212/// let table = policy.freq_table()?;
213///
214/// // SAFETY: Index is a valid entry in the table.
215/// let index = unsafe { TableIndex::new(0) };
216///
217/// pr_info!("The frequency at index 0 is: {:?}\n", table.freq(index)?);
218/// pr_info!("The flags at index 0 is: {}\n", table.flags(index));
219/// pr_info!("The data at index 0 is: {}\n", table.data(index));
220/// Ok(())
221/// }
222/// ```
223#[repr(transparent)]
224pub struct Table(Opaque<bindings::cpufreq_frequency_table>);
225
226impl Table {
227 /// Creates a reference to an existing C `struct cpufreq_frequency_table` pointer.
228 ///
229 /// # Safety
230 ///
231 /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime
232 /// of the returned reference.
233 #[inline]
234 pub unsafe fn from_raw<'a>(ptr: *const bindings::cpufreq_frequency_table) -> &'a Self {
235 // SAFETY: Guaranteed by the safety requirements of the function.
236 //
237 // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the
238 // lifetime of the returned reference.
239 unsafe { &*ptr.cast() }
240 }
241
242 /// Returns the raw mutable pointer to the C `struct cpufreq_frequency_table`.
243 #[inline]
244 pub fn as_raw(&self) -> *mut bindings::cpufreq_frequency_table {
245 let this: *const Self = self;
246 this.cast_mut().cast()
247 }
248
249 /// Returns frequency at `index` in the [`Table`].
250 #[inline]
251 pub fn freq(&self, index: TableIndex) -> Result<Hertz> {
252 // SAFETY: By the type invariant, the pointer stored in `self` is valid and `index` is
253 // guaranteed to be valid by its safety requirements.
254 Ok(Hertz::from_khz(unsafe {
255 (*self.as_raw().add(index.into())).frequency.try_into()?
256 }))
257 }
258
259 /// Returns flags at `index` in the [`Table`].
260 #[inline]
261 pub fn flags(&self, index: TableIndex) -> u32 {
262 // SAFETY: By the type invariant, the pointer stored in `self` is valid and `index` is
263 // guaranteed to be valid by its safety requirements.
264 unsafe { (*self.as_raw().add(index.into())).flags }
265 }
266
267 /// Returns data at `index` in the [`Table`].
268 #[inline]
269 pub fn data(&self, index: TableIndex) -> u32 {
270 // SAFETY: By the type invariant, the pointer stored in `self` is valid and `index` is
271 // guaranteed to be valid by its safety requirements.
272 unsafe { (*self.as_raw().add(index.into())).driver_data }
273 }
274}
275
276/// CPU frequency table owned and pinned in memory, created from a [`TableBuilder`].
277pub struct TableBox {
278 entries: Pin<KVec<bindings::cpufreq_frequency_table>>,
279}
280
281impl TableBox {
282 /// Constructs a new [`TableBox`] from a [`KVec`] of entries.
283 ///
284 /// # Errors
285 ///
286 /// Returns `EINVAL` if the entries list is empty.
287 #[inline]
288 fn new(entries: KVec<bindings::cpufreq_frequency_table>) -> Result<Self> {
289 if entries.is_empty() {
290 return Err(EINVAL);
291 }
292
293 Ok(Self {
294 // Pin the entries to memory, since we are passing its pointer to the C code.
295 entries: Pin::new(entries),
296 })
297 }
298
299 /// Returns a raw pointer to the underlying C `cpufreq_frequency_table`.
300 #[inline]
301 fn as_raw(&self) -> *const bindings::cpufreq_frequency_table {
302 // The pointer is valid until the table gets dropped.
303 self.entries.as_ptr()
304 }
305}
306
307impl Deref for TableBox {
308 type Target = Table;
309
310 fn deref(&self) -> &Self::Target {
311 // SAFETY: The caller owns TableBox, it is safe to deref.
312 unsafe { Self::Target::from_raw(self.as_raw()) }
313 }
314}
315
316/// CPU frequency table builder.
317///
318/// This is used by the CPU frequency drivers to build a frequency table dynamically.
319///
320/// ## Examples
321///
322/// The following example demonstrates how to create a CPU frequency table.
323///
324/// ```
325/// use kernel::cpufreq::{TableBuilder, TableIndex};
326/// use kernel::clk::Hertz;
327///
328/// let mut builder = TableBuilder::new();
329///
330/// // Adds few entries to the table.
331/// builder.add(Hertz::from_mhz(700), 0, 1).unwrap();
332/// builder.add(Hertz::from_mhz(800), 2, 3).unwrap();
333/// builder.add(Hertz::from_mhz(900), 4, 5).unwrap();
334/// builder.add(Hertz::from_ghz(1), 6, 7).unwrap();
335///
336/// let table = builder.to_table().unwrap();
337///
338/// // SAFETY: Index values correspond to valid entries in the table.
339/// let (index0, index2) = unsafe { (TableIndex::new(0), TableIndex::new(2)) };
340///
341/// assert_eq!(table.freq(index0), Ok(Hertz::from_mhz(700)));
342/// assert_eq!(table.flags(index0), 0);
343/// assert_eq!(table.data(index0), 1);
344///
345/// assert_eq!(table.freq(index2), Ok(Hertz::from_mhz(900)));
346/// assert_eq!(table.flags(index2), 4);
347/// assert_eq!(table.data(index2), 5);
348/// ```
349#[derive(Default)]
350#[repr(transparent)]
351pub struct TableBuilder {
352 entries: KVec<bindings::cpufreq_frequency_table>,
353}
354
355impl TableBuilder {
356 /// Creates a new instance of [`TableBuilder`].
357 #[inline]
358 pub fn new() -> Self {
359 Self {
360 entries: KVec::new(),
361 }
362 }
363
364 /// Adds a new entry to the table.
365 pub fn add(&mut self, freq: Hertz, flags: u32, driver_data: u32) -> Result {
366 // Adds the new entry at the end of the vector.
367 Ok(self.entries.push(
368 bindings::cpufreq_frequency_table {
369 flags,
370 driver_data,
371 frequency: freq.as_khz() as u32,
372 },
373 GFP_KERNEL,
374 )?)
375 }
376
377 /// Consumes the [`TableBuilder`] and returns [`TableBox`].
378 pub fn to_table(mut self) -> Result<TableBox> {
379 // Add last entry to the table.
380 self.add(Hertz(c_ulong::MAX), 0, 0)?;
381
382 TableBox::new(self.entries)
383 }
384}
385
386/// CPU frequency policy.
387///
388/// Rust abstraction for the C `struct cpufreq_policy`.
389///
390/// # Invariants
391///
392/// A [`Policy`] instance always corresponds to a valid C `struct cpufreq_policy`.
393///
394/// The callers must ensure that the `struct cpufreq_policy` is valid for access and remains valid
395/// for the lifetime of the returned reference.
396///
397/// ## Examples
398///
399/// The following example demonstrates how to create a CPU frequency table.
400///
401/// ```
402/// use kernel::cpufreq::{ETERNAL_LATENCY_NS, Policy};
403///
404/// fn update_policy(policy: &mut Policy) {
405/// policy
406/// .set_dvfs_possible_from_any_cpu(true)
407/// .set_fast_switch_possible(true)
408/// .set_transition_latency_ns(ETERNAL_LATENCY_NS);
409///
410/// pr_info!("The policy details are: {:?}\n", (policy.cpu(), policy.cur()));
411/// }
412/// ```
413#[repr(transparent)]
414pub struct Policy(Opaque<bindings::cpufreq_policy>);
415
416impl Policy {
417 /// Creates a reference to an existing `struct cpufreq_policy` pointer.
418 ///
419 /// # Safety
420 ///
421 /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime
422 /// of the returned reference.
423 #[inline]
424 pub unsafe fn from_raw<'a>(ptr: *const bindings::cpufreq_policy) -> &'a Self {
425 // SAFETY: Guaranteed by the safety requirements of the function.
426 //
427 // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the
428 // lifetime of the returned reference.
429 unsafe { &*ptr.cast() }
430 }
431
432 /// Creates a mutable reference to an existing `struct cpufreq_policy` pointer.
433 ///
434 /// # Safety
435 ///
436 /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime
437 /// of the returned reference.
438 #[inline]
439 pub unsafe fn from_raw_mut<'a>(ptr: *mut bindings::cpufreq_policy) -> &'a mut Self {
440 // SAFETY: Guaranteed by the safety requirements of the function.
441 //
442 // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the
443 // lifetime of the returned reference.
444 unsafe { &mut *ptr.cast() }
445 }
446
447 /// Returns a raw mutable pointer to the C `struct cpufreq_policy`.
448 #[inline]
449 fn as_raw(&self) -> *mut bindings::cpufreq_policy {
450 let this: *const Self = self;
451 this.cast_mut().cast()
452 }
453
454 #[inline]
455 fn as_ref(&self) -> &bindings::cpufreq_policy {
456 // SAFETY: By the type invariant, the pointer stored in `self` is valid.
457 unsafe { &*self.as_raw() }
458 }
459
460 #[inline]
461 fn as_mut_ref(&mut self) -> &mut bindings::cpufreq_policy {
462 // SAFETY: By the type invariant, the pointer stored in `self` is valid.
463 unsafe { &mut *self.as_raw() }
464 }
465
466 /// Returns the primary CPU for the [`Policy`].
467 #[inline]
468 pub fn cpu(&self) -> u32 {
469 self.as_ref().cpu
470 }
471
472 /// Returns the minimum frequency for the [`Policy`].
473 #[inline]
474 pub fn min(&self) -> Hertz {
475 Hertz::from_khz(self.as_ref().min as usize)
476 }
477
478 /// Set the minimum frequency for the [`Policy`].
479 #[inline]
480 pub fn set_min(&mut self, min: Hertz) -> &mut Self {
481 self.as_mut_ref().min = min.as_khz() as u32;
482 self
483 }
484
485 /// Returns the maximum frequency for the [`Policy`].
486 #[inline]
487 pub fn max(&self) -> Hertz {
488 Hertz::from_khz(self.as_ref().max as usize)
489 }
490
491 /// Set the maximum frequency for the [`Policy`].
492 #[inline]
493 pub fn set_max(&mut self, max: Hertz) -> &mut Self {
494 self.as_mut_ref().max = max.as_khz() as u32;
495 self
496 }
497
498 /// Returns the current frequency for the [`Policy`].
499 #[inline]
500 pub fn cur(&self) -> Hertz {
501 Hertz::from_khz(self.as_ref().cur as usize)
502 }
503
504 /// Returns the suspend frequency for the [`Policy`].
505 #[inline]
506 pub fn suspend_freq(&self) -> Hertz {
507 Hertz::from_khz(self.as_ref().suspend_freq as usize)
508 }
509
510 /// Sets the suspend frequency for the [`Policy`].
511 #[inline]
512 pub fn set_suspend_freq(&mut self, freq: Hertz) -> &mut Self {
513 self.as_mut_ref().suspend_freq = freq.as_khz() as u32;
514 self
515 }
516
517 /// Provides a wrapper to the generic suspend routine.
518 #[inline]
519 pub fn generic_suspend(&mut self) -> Result {
520 // SAFETY: By the type invariant, the pointer stored in `self` is valid.
521 to_result(unsafe { bindings::cpufreq_generic_suspend(self.as_mut_ref()) })
522 }
523
524 /// Provides a wrapper to the generic get routine.
525 #[inline]
526 pub fn generic_get(&self) -> Result<u32> {
527 // SAFETY: By the type invariant, the pointer stored in `self` is valid.
528 Ok(unsafe { bindings::cpufreq_generic_get(self.cpu()) })
529 }
530
531 /// Provides a wrapper to the register with energy model using the OPP core.
532 #[cfg(CONFIG_PM_OPP)]
533 #[inline]
534 pub fn register_em_opp(&mut self) {
535 // SAFETY: By the type invariant, the pointer stored in `self` is valid.
536 unsafe { bindings::cpufreq_register_em_with_opp(self.as_mut_ref()) };
537 }
538
539 /// Gets [`cpumask::Cpumask`] for a cpufreq [`Policy`].
540 #[inline]
541 pub fn cpus(&mut self) -> &mut cpumask::Cpumask {
542 // SAFETY: The pointer to `cpus` is valid for writing and remains valid for the lifetime of
543 // the returned reference.
544 unsafe { cpumask::CpumaskVar::as_mut_ref(&mut self.as_mut_ref().cpus) }
545 }
546
547 /// Sets clock for the [`Policy`].
548 ///
549 /// # Safety
550 ///
551 /// The caller must guarantee that the returned [`Clk`] is not dropped while it is getting used
552 /// by the C code.
553 #[cfg(CONFIG_COMMON_CLK)]
554 pub unsafe fn set_clk(&mut self, dev: &Device, name: Option<&CStr>) -> Result<Clk> {
555 let clk = Clk::get(dev, name)?;
556 self.as_mut_ref().clk = clk.as_raw();
557 Ok(clk)
558 }
559
560 /// Allows / disallows frequency switching code to run on any CPU.
561 #[inline]
562 pub fn set_dvfs_possible_from_any_cpu(&mut self, val: bool) -> &mut Self {
563 self.as_mut_ref().dvfs_possible_from_any_cpu = val;
564 self
565 }
566
567 /// Returns if fast switching of frequencies is possible or not.
568 #[inline]
569 pub fn fast_switch_possible(&self) -> bool {
570 self.as_ref().fast_switch_possible
571 }
572
573 /// Enables / disables fast frequency switching.
574 #[inline]
575 pub fn set_fast_switch_possible(&mut self, val: bool) -> &mut Self {
576 self.as_mut_ref().fast_switch_possible = val;
577 self
578 }
579
580 /// Sets transition latency (in nanoseconds) for the [`Policy`].
581 #[inline]
582 pub fn set_transition_latency_ns(&mut self, latency_ns: u32) -> &mut Self {
583 self.as_mut_ref().cpuinfo.transition_latency = latency_ns;
584 self
585 }
586
587 /// Sets cpuinfo `min_freq`.
588 #[inline]
589 pub fn set_cpuinfo_min_freq(&mut self, min_freq: Hertz) -> &mut Self {
590 self.as_mut_ref().cpuinfo.min_freq = min_freq.as_khz() as u32;
591 self
592 }
593
594 /// Sets cpuinfo `max_freq`.
595 #[inline]
596 pub fn set_cpuinfo_max_freq(&mut self, max_freq: Hertz) -> &mut Self {
597 self.as_mut_ref().cpuinfo.max_freq = max_freq.as_khz() as u32;
598 self
599 }
600
601 /// Set `transition_delay_us`, i.e. the minimum time between successive frequency change
602 /// requests.
603 #[inline]
604 pub fn set_transition_delay_us(&mut self, transition_delay_us: u32) -> &mut Self {
605 self.as_mut_ref().transition_delay_us = transition_delay_us;
606 self
607 }
608
609 /// Returns reference to the CPU frequency [`Table`] for the [`Policy`].
610 pub fn freq_table(&self) -> Result<&Table> {
611 if self.as_ref().freq_table.is_null() {
612 return Err(EINVAL);
613 }
614
615 // SAFETY: The `freq_table` is guaranteed to be valid for reading and remains valid for the
616 // lifetime of the returned reference.
617 Ok(unsafe { Table::from_raw(self.as_ref().freq_table) })
618 }
619
620 /// Sets the CPU frequency [`Table`] for the [`Policy`].
621 ///
622 /// # Safety
623 ///
624 /// The caller must guarantee that the [`Table`] is not dropped while it is getting used by the
625 /// C code.
626 #[inline]
627 pub unsafe fn set_freq_table(&mut self, table: &Table) -> &mut Self {
628 self.as_mut_ref().freq_table = table.as_raw();
629 self
630 }
631
632 /// Returns the [`Policy`]'s private data.
633 pub fn data<T: ForeignOwnable>(&mut self) -> Option<<T>::Borrowed<'_>> {
634 if self.as_ref().driver_data.is_null() {
635 None
636 } else {
637 // SAFETY: The data is earlier set from [`set_data`].
638 Some(unsafe { T::borrow(self.as_ref().driver_data.cast()) })
639 }
640 }
641
642 /// Sets the private data of the [`Policy`] using a foreign-ownable wrapper.
643 ///
644 /// # Errors
645 ///
646 /// Returns `EBUSY` if private data is already set.
647 fn set_data<T: ForeignOwnable>(&mut self, data: T) -> Result {
648 if self.as_ref().driver_data.is_null() {
649 // Transfer the ownership of the data to the foreign interface.
650 self.as_mut_ref().driver_data = <T as ForeignOwnable>::into_foreign(data) as _;
651 Ok(())
652 } else {
653 Err(EBUSY)
654 }
655 }
656
657 /// Clears and returns ownership of the private data.
658 fn clear_data<T: ForeignOwnable>(&mut self) -> Option<T> {
659 if self.as_ref().driver_data.is_null() {
660 None
661 } else {
662 let data = Some(
663 // SAFETY: The data is earlier set by us from [`set_data`]. It is safe to take
664 // back the ownership of the data from the foreign interface.
665 unsafe { <T as ForeignOwnable>::from_foreign(self.as_ref().driver_data.cast()) },
666 );
667 self.as_mut_ref().driver_data = ptr::null_mut();
668 data
669 }
670 }
671}
672
673/// CPU frequency policy created from a CPU number.
674///
675/// This struct represents the CPU frequency policy obtained for a specific CPU, providing safe
676/// access to the underlying `cpufreq_policy` and ensuring proper cleanup when the `PolicyCpu` is
677/// dropped.
678struct PolicyCpu<'a>(&'a mut Policy);
679
680impl<'a> PolicyCpu<'a> {
681 fn from_cpu(cpu: u32) -> Result<Self> {
682 // SAFETY: It is safe to call `cpufreq_cpu_get` for any valid CPU.
683 let ptr = from_err_ptr(unsafe { bindings::cpufreq_cpu_get(cpu) })?;
684
685 Ok(Self(
686 // SAFETY: The `ptr` is guaranteed to be valid and remains valid for the lifetime of
687 // the returned reference.
688 unsafe { Policy::from_raw_mut(ptr) },
689 ))
690 }
691}
692
693impl<'a> Deref for PolicyCpu<'a> {
694 type Target = Policy;
695
696 fn deref(&self) -> &Self::Target {
697 self.0
698 }
699}
700
701impl<'a> DerefMut for PolicyCpu<'a> {
702 fn deref_mut(&mut self) -> &mut Policy {
703 self.0
704 }
705}
706
707impl<'a> Drop for PolicyCpu<'a> {
708 fn drop(&mut self) {
709 // SAFETY: The underlying pointer is guaranteed to be valid for the lifetime of `self`.
710 unsafe { bindings::cpufreq_cpu_put(self.0.as_raw()) };
711 }
712}
713
714/// CPU frequency driver.
715///
716/// Implement this trait to provide a CPU frequency driver and its callbacks.
717///
718/// Reference: <https://docs.kernel.org/cpu-freq/cpu-drivers.html>
719#[vtable]
720pub trait Driver {
721 /// Driver's name.
722 const NAME: &'static CStr;
723
724 /// Driver's flags.
725 const FLAGS: u16;
726
727 /// Boost support.
728 const BOOST_ENABLED: bool;
729
730 /// Policy specific data.
731 ///
732 /// Require that `PData` implements `ForeignOwnable`. We guarantee to never move the underlying
733 /// wrapped data structure.
734 type PData: ForeignOwnable;
735
736 /// Driver's `init` callback.
737 fn init(policy: &mut Policy) -> Result<Self::PData>;
738
739 /// Driver's `exit` callback.
740 fn exit(_policy: &mut Policy, _data: Option<Self::PData>) -> Result {
741 build_error!(VTABLE_DEFAULT_ERROR)
742 }
743
744 /// Driver's `online` callback.
745 fn online(_policy: &mut Policy) -> Result {
746 build_error!(VTABLE_DEFAULT_ERROR)
747 }
748
749 /// Driver's `offline` callback.
750 fn offline(_policy: &mut Policy) -> Result {
751 build_error!(VTABLE_DEFAULT_ERROR)
752 }
753
754 /// Driver's `suspend` callback.
755 fn suspend(_policy: &mut Policy) -> Result {
756 build_error!(VTABLE_DEFAULT_ERROR)
757 }
758
759 /// Driver's `resume` callback.
760 fn resume(_policy: &mut Policy) -> Result {
761 build_error!(VTABLE_DEFAULT_ERROR)
762 }
763
764 /// Driver's `ready` callback.
765 fn ready(_policy: &mut Policy) {
766 build_error!(VTABLE_DEFAULT_ERROR)
767 }
768
769 /// Driver's `verify` callback.
770 fn verify(data: &mut PolicyData) -> Result;
771
772 /// Driver's `setpolicy` callback.
773 fn setpolicy(_policy: &mut Policy) -> Result {
774 build_error!(VTABLE_DEFAULT_ERROR)
775 }
776
777 /// Driver's `target` callback.
778 fn target(_policy: &mut Policy, _target_freq: u32, _relation: Relation) -> Result {
779 build_error!(VTABLE_DEFAULT_ERROR)
780 }
781
782 /// Driver's `target_index` callback.
783 fn target_index(_policy: &mut Policy, _index: TableIndex) -> Result {
784 build_error!(VTABLE_DEFAULT_ERROR)
785 }
786
787 /// Driver's `fast_switch` callback.
788 fn fast_switch(_policy: &mut Policy, _target_freq: u32) -> u32 {
789 build_error!(VTABLE_DEFAULT_ERROR)
790 }
791
792 /// Driver's `adjust_perf` callback.
793 fn adjust_perf(_policy: &mut Policy, _min_perf: usize, _target_perf: usize, _capacity: usize) {
794 build_error!(VTABLE_DEFAULT_ERROR)
795 }
796
797 /// Driver's `get_intermediate` callback.
798 fn get_intermediate(_policy: &mut Policy, _index: TableIndex) -> u32 {
799 build_error!(VTABLE_DEFAULT_ERROR)
800 }
801
802 /// Driver's `target_intermediate` callback.
803 fn target_intermediate(_policy: &mut Policy, _index: TableIndex) -> Result {
804 build_error!(VTABLE_DEFAULT_ERROR)
805 }
806
807 /// Driver's `get` callback.
808 fn get(_policy: &mut Policy) -> Result<u32> {
809 build_error!(VTABLE_DEFAULT_ERROR)
810 }
811
812 /// Driver's `update_limits` callback.
813 fn update_limits(_policy: &mut Policy) {
814 build_error!(VTABLE_DEFAULT_ERROR)
815 }
816
817 /// Driver's `bios_limit` callback.
818 fn bios_limit(_policy: &mut Policy, _limit: &mut u32) -> Result {
819 build_error!(VTABLE_DEFAULT_ERROR)
820 }
821
822 /// Driver's `set_boost` callback.
823 fn set_boost(_policy: &mut Policy, _state: i32) -> Result {
824 build_error!(VTABLE_DEFAULT_ERROR)
825 }
826
827 /// Driver's `register_em` callback.
828 fn register_em(_policy: &mut Policy) {
829 build_error!(VTABLE_DEFAULT_ERROR)
830 }
831}
832
833/// CPU frequency driver Registration.
834///
835/// ## Examples
836///
837/// The following example demonstrates how to register a cpufreq driver.
838///
839/// ```
840/// use kernel::{
841/// cpufreq,
842/// c_str,
843/// device::{Core, Device},
844/// macros::vtable,
845/// of, platform,
846/// sync::Arc,
847/// };
848/// struct SampleDevice;
849///
850/// #[derive(Default)]
851/// struct SampleDriver;
852///
853/// #[vtable]
854/// impl cpufreq::Driver for SampleDriver {
855/// const NAME: &'static CStr = c_str!("cpufreq-sample");
856/// const FLAGS: u16 = cpufreq::flags::NEED_INITIAL_FREQ_CHECK | cpufreq::flags::IS_COOLING_DEV;
857/// const BOOST_ENABLED: bool = true;
858///
859/// type PData = Arc<SampleDevice>;
860///
861/// fn init(policy: &mut cpufreq::Policy) -> Result<Self::PData> {
862/// // Initialize here
863/// Ok(Arc::new(SampleDevice, GFP_KERNEL)?)
864/// }
865///
866/// fn exit(_policy: &mut cpufreq::Policy, _data: Option<Self::PData>) -> Result {
867/// Ok(())
868/// }
869///
870/// fn suspend(policy: &mut cpufreq::Policy) -> Result {
871/// policy.generic_suspend()
872/// }
873///
874/// fn verify(data: &mut cpufreq::PolicyData) -> Result {
875/// data.generic_verify()
876/// }
877///
878/// fn target_index(policy: &mut cpufreq::Policy, index: cpufreq::TableIndex) -> Result {
879/// // Update CPU frequency
880/// Ok(())
881/// }
882///
883/// fn get(policy: &mut cpufreq::Policy) -> Result<u32> {
884/// policy.generic_get()
885/// }
886/// }
887///
888/// impl platform::Driver for SampleDriver {
889/// type IdInfo = ();
890/// const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
891///
892/// fn probe(
893/// pdev: &platform::Device<Core>,
894/// _id_info: Option<&Self::IdInfo>,
895/// ) -> Result<Pin<KBox<Self>>> {
896/// cpufreq::Registration::<SampleDriver>::new_foreign_owned(pdev.as_ref())?;
897/// Ok(KBox::new(Self {}, GFP_KERNEL)?.into())
898/// }
899/// }
900/// ```
901#[repr(transparent)]
902pub struct Registration<T: Driver>(KBox<UnsafeCell<bindings::cpufreq_driver>>, PhantomData<T>);
903
904/// SAFETY: `Registration` doesn't offer any methods or access to fields when shared between threads
905/// or CPUs, so it is safe to share it.
906unsafe impl<T: Driver> Sync for Registration<T> {}
907
908#[allow(clippy::non_send_fields_in_send_ty)]
909/// SAFETY: Registration with and unregistration from the cpufreq subsystem can happen from any
910/// thread.
911unsafe impl<T: Driver> Send for Registration<T> {}
912
913impl<T: Driver> Registration<T> {
914 const VTABLE: bindings::cpufreq_driver = bindings::cpufreq_driver {
915 name: Self::copy_name(T::NAME),
916 boost_enabled: T::BOOST_ENABLED,
917 flags: T::FLAGS,
918
919 // Initialize mandatory callbacks.
920 init: Some(Self::init_callback),
921 verify: Some(Self::verify_callback),
922
923 // Initialize optional callbacks based on the traits of `T`.
924 setpolicy: if T::HAS_SETPOLICY {
925 Some(Self::setpolicy_callback)
926 } else {
927 None
928 },
929 target: if T::HAS_TARGET {
930 Some(Self::target_callback)
931 } else {
932 None
933 },
934 target_index: if T::HAS_TARGET_INDEX {
935 Some(Self::target_index_callback)
936 } else {
937 None
938 },
939 fast_switch: if T::HAS_FAST_SWITCH {
940 Some(Self::fast_switch_callback)
941 } else {
942 None
943 },
944 adjust_perf: if T::HAS_ADJUST_PERF {
945 Some(Self::adjust_perf_callback)
946 } else {
947 None
948 },
949 get_intermediate: if T::HAS_GET_INTERMEDIATE {
950 Some(Self::get_intermediate_callback)
951 } else {
952 None
953 },
954 target_intermediate: if T::HAS_TARGET_INTERMEDIATE {
955 Some(Self::target_intermediate_callback)
956 } else {
957 None
958 },
959 get: if T::HAS_GET {
960 Some(Self::get_callback)
961 } else {
962 None
963 },
964 update_limits: if T::HAS_UPDATE_LIMITS {
965 Some(Self::update_limits_callback)
966 } else {
967 None
968 },
969 bios_limit: if T::HAS_BIOS_LIMIT {
970 Some(Self::bios_limit_callback)
971 } else {
972 None
973 },
974 online: if T::HAS_ONLINE {
975 Some(Self::online_callback)
976 } else {
977 None
978 },
979 offline: if T::HAS_OFFLINE {
980 Some(Self::offline_callback)
981 } else {
982 None
983 },
984 exit: if T::HAS_EXIT {
985 Some(Self::exit_callback)
986 } else {
987 None
988 },
989 suspend: if T::HAS_SUSPEND {
990 Some(Self::suspend_callback)
991 } else {
992 None
993 },
994 resume: if T::HAS_RESUME {
995 Some(Self::resume_callback)
996 } else {
997 None
998 },
999 ready: if T::HAS_READY {
1000 Some(Self::ready_callback)
1001 } else {
1002 None
1003 },
1004 set_boost: if T::HAS_SET_BOOST {
1005 Some(Self::set_boost_callback)
1006 } else {
1007 None
1008 },
1009 register_em: if T::HAS_REGISTER_EM {
1010 Some(Self::register_em_callback)
1011 } else {
1012 None
1013 },
1014 // SAFETY: All zeros is a valid value for `bindings::cpufreq_driver`.
1015 ..unsafe { MaybeUninit::zeroed().assume_init() }
1016 };
1017
1018 const fn copy_name(name: &'static CStr) -> [c_char; CPUFREQ_NAME_LEN] {
1019 let src = name.as_bytes_with_nul();
1020 let mut dst = [0; CPUFREQ_NAME_LEN];
1021
1022 build_assert!(src.len() <= CPUFREQ_NAME_LEN);
1023
1024 let mut i = 0;
1025 while i < src.len() {
1026 dst[i] = src[i];
1027 i += 1;
1028 }
1029
1030 dst
1031 }
1032
1033 /// Registers a CPU frequency driver with the cpufreq core.
1034 pub fn new() -> Result<Self> {
1035 // We can't use `&Self::VTABLE` directly because the cpufreq core modifies some fields in
1036 // the C `struct cpufreq_driver`, which requires a mutable reference.
1037 let mut drv = KBox::new(UnsafeCell::new(Self::VTABLE), GFP_KERNEL)?;
1038
1039 // SAFETY: `drv` is guaranteed to be valid for the lifetime of `Registration`.
1040 to_result(unsafe { bindings::cpufreq_register_driver(drv.get_mut()) })?;
1041
1042 Ok(Self(drv, PhantomData))
1043 }
1044
1045 /// Same as [`Registration::new`], but does not return a [`Registration`] instance.
1046 ///
1047 /// Instead the [`Registration`] is owned by [`Devres`] and will be revoked / dropped, once the
1048 /// device is detached.
1049 pub fn new_foreign_owned(dev: &Device<Bound>) -> Result {
1050 Devres::new_foreign_owned(dev, Self::new()?, GFP_KERNEL)
1051 }
1052}
1053
1054/// CPU frequency driver callbacks.
1055impl<T: Driver> Registration<T> {
1056 /// Driver's `init` callback.
1057 ///
1058 /// SAFETY: Called from C. Inputs must be valid pointers.
1059 extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
1060 from_result(|| {
1061 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1062 // lifetime of `policy`.
1063 let policy = unsafe { Policy::from_raw_mut(ptr) };
1064
1065 let data = T::init(policy)?;
1066 policy.set_data(data)?;
1067 Ok(0)
1068 })
1069 }
1070
1071 /// Driver's `exit` callback.
1072 ///
1073 /// SAFETY: Called from C. Inputs must be valid pointers.
1074 extern "C" fn exit_callback(ptr: *mut bindings::cpufreq_policy) {
1075 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1076 // lifetime of `policy`.
1077 let policy = unsafe { Policy::from_raw_mut(ptr) };
1078
1079 let data = policy.clear_data();
1080 let _ = T::exit(policy, data);
1081 }
1082
1083 /// Driver's `online` callback.
1084 ///
1085 /// SAFETY: Called from C. Inputs must be valid pointers.
1086 extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
1087 from_result(|| {
1088 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1089 // lifetime of `policy`.
1090 let policy = unsafe { Policy::from_raw_mut(ptr) };
1091 T::online(policy).map(|()| 0)
1092 })
1093 }
1094
1095 /// Driver's `offline` callback.
1096 ///
1097 /// SAFETY: Called from C. Inputs must be valid pointers.
1098 extern "C" fn offline_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
1099 from_result(|| {
1100 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1101 // lifetime of `policy`.
1102 let policy = unsafe { Policy::from_raw_mut(ptr) };
1103 T::offline(policy).map(|()| 0)
1104 })
1105 }
1106
1107 /// Driver's `suspend` callback.
1108 ///
1109 /// SAFETY: Called from C. Inputs must be valid pointers.
1110 extern "C" fn suspend_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
1111 from_result(|| {
1112 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1113 // lifetime of `policy`.
1114 let policy = unsafe { Policy::from_raw_mut(ptr) };
1115 T::suspend(policy).map(|()| 0)
1116 })
1117 }
1118
1119 /// Driver's `resume` callback.
1120 ///
1121 /// SAFETY: Called from C. Inputs must be valid pointers.
1122 extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
1123 from_result(|| {
1124 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1125 // lifetime of `policy`.
1126 let policy = unsafe { Policy::from_raw_mut(ptr) };
1127 T::resume(policy).map(|()| 0)
1128 })
1129 }
1130
1131 /// Driver's `ready` callback.
1132 ///
1133 /// SAFETY: Called from C. Inputs must be valid pointers.
1134 extern "C" fn ready_callback(ptr: *mut bindings::cpufreq_policy) {
1135 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1136 // lifetime of `policy`.
1137 let policy = unsafe { Policy::from_raw_mut(ptr) };
1138 T::ready(policy);
1139 }
1140
1141 /// Driver's `verify` callback.
1142 ///
1143 /// SAFETY: Called from C. Inputs must be valid pointers.
1144 extern "C" fn verify_callback(ptr: *mut bindings::cpufreq_policy_data) -> kernel::ffi::c_int {
1145 from_result(|| {
1146 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1147 // lifetime of `policy`.
1148 let data = unsafe { PolicyData::from_raw_mut(ptr) };
1149 T::verify(data).map(|()| 0)
1150 })
1151 }
1152
1153 /// Driver's `setpolicy` callback.
1154 ///
1155 /// SAFETY: Called from C. Inputs must be valid pointers.
1156 extern "C" fn setpolicy_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
1157 from_result(|| {
1158 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1159 // lifetime of `policy`.
1160 let policy = unsafe { Policy::from_raw_mut(ptr) };
1161 T::setpolicy(policy).map(|()| 0)
1162 })
1163 }
1164
1165 /// Driver's `target` callback.
1166 ///
1167 /// SAFETY: Called from C. Inputs must be valid pointers.
1168 extern "C" fn target_callback(
1169 ptr: *mut bindings::cpufreq_policy,
1170 target_freq: u32,
1171 relation: u32,
1172 ) -> kernel::ffi::c_int {
1173 from_result(|| {
1174 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1175 // lifetime of `policy`.
1176 let policy = unsafe { Policy::from_raw_mut(ptr) };
1177 T::target(policy, target_freq, Relation::new(relation)?).map(|()| 0)
1178 })
1179 }
1180
1181 /// Driver's `target_index` callback.
1182 ///
1183 /// SAFETY: Called from C. Inputs must be valid pointers.
1184 extern "C" fn target_index_callback(
1185 ptr: *mut bindings::cpufreq_policy,
1186 index: u32,
1187 ) -> kernel::ffi::c_int {
1188 from_result(|| {
1189 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1190 // lifetime of `policy`.
1191 let policy = unsafe { Policy::from_raw_mut(ptr) };
1192
1193 // SAFETY: The C code guarantees that `index` corresponds to a valid entry in the
1194 // frequency table.
1195 let index = unsafe { TableIndex::new(index as usize) };
1196
1197 T::target_index(policy, index).map(|()| 0)
1198 })
1199 }
1200
1201 /// Driver's `fast_switch` callback.
1202 ///
1203 /// SAFETY: Called from C. Inputs must be valid pointers.
1204 extern "C" fn fast_switch_callback(
1205 ptr: *mut bindings::cpufreq_policy,
1206 target_freq: u32,
1207 ) -> kernel::ffi::c_uint {
1208 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1209 // lifetime of `policy`.
1210 let policy = unsafe { Policy::from_raw_mut(ptr) };
1211 T::fast_switch(policy, target_freq)
1212 }
1213
1214 /// Driver's `adjust_perf` callback.
1215 extern "C" fn adjust_perf_callback(
1216 cpu: u32,
1217 min_perf: usize,
1218 target_perf: usize,
1219 capacity: usize,
1220 ) {
1221 if let Ok(mut policy) = PolicyCpu::from_cpu(cpu) {
1222 T::adjust_perf(&mut policy, min_perf, target_perf, capacity);
1223 }
1224 }
1225
1226 /// Driver's `get_intermediate` callback.
1227 ///
1228 /// SAFETY: Called from C. Inputs must be valid pointers.
1229 extern "C" fn get_intermediate_callback(
1230 ptr: *mut bindings::cpufreq_policy,
1231 index: u32,
1232 ) -> kernel::ffi::c_uint {
1233 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1234 // lifetime of `policy`.
1235 let policy = unsafe { Policy::from_raw_mut(ptr) };
1236
1237 // SAFETY: The C code guarantees that `index` corresponds to a valid entry in the
1238 // frequency table.
1239 let index = unsafe { TableIndex::new(index as usize) };
1240
1241 T::get_intermediate(policy, index)
1242 }
1243
1244 /// Driver's `target_intermediate` callback.
1245 ///
1246 /// SAFETY: Called from C. Inputs must be valid pointers.
1247 extern "C" fn target_intermediate_callback(
1248 ptr: *mut bindings::cpufreq_policy,
1249 index: u32,
1250 ) -> kernel::ffi::c_int {
1251 from_result(|| {
1252 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1253 // lifetime of `policy`.
1254 let policy = unsafe { Policy::from_raw_mut(ptr) };
1255
1256 // SAFETY: The C code guarantees that `index` corresponds to a valid entry in the
1257 // frequency table.
1258 let index = unsafe { TableIndex::new(index as usize) };
1259
1260 T::target_intermediate(policy, index).map(|()| 0)
1261 })
1262 }
1263
1264 /// Driver's `get` callback.
1265 extern "C" fn get_callback(cpu: u32) -> kernel::ffi::c_uint {
1266 PolicyCpu::from_cpu(cpu).map_or(0, |mut policy| T::get(&mut policy).map_or(0, |f| f))
1267 }
1268
1269 /// Driver's `update_limit` callback.
1270 extern "C" fn update_limits_callback(ptr: *mut bindings::cpufreq_policy) {
1271 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1272 // lifetime of `policy`.
1273 let policy = unsafe { Policy::from_raw_mut(ptr) };
1274 T::update_limits(policy);
1275 }
1276
1277 /// Driver's `bios_limit` callback.
1278 ///
1279 /// SAFETY: Called from C. Inputs must be valid pointers.
1280 extern "C" fn bios_limit_callback(cpu: i32, limit: *mut u32) -> kernel::ffi::c_int {
1281 from_result(|| {
1282 let mut policy = PolicyCpu::from_cpu(cpu as u32)?;
1283
1284 // SAFETY: `limit` is guaranteed by the C code to be valid.
1285 T::bios_limit(&mut policy, &mut (unsafe { *limit })).map(|()| 0)
1286 })
1287 }
1288
1289 /// Driver's `set_boost` callback.
1290 ///
1291 /// SAFETY: Called from C. Inputs must be valid pointers.
1292 extern "C" fn set_boost_callback(
1293 ptr: *mut bindings::cpufreq_policy,
1294 state: i32,
1295 ) -> kernel::ffi::c_int {
1296 from_result(|| {
1297 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1298 // lifetime of `policy`.
1299 let policy = unsafe { Policy::from_raw_mut(ptr) };
1300 T::set_boost(policy, state).map(|()| 0)
1301 })
1302 }
1303
1304 /// Driver's `register_em` callback.
1305 ///
1306 /// SAFETY: Called from C. Inputs must be valid pointers.
1307 extern "C" fn register_em_callback(ptr: *mut bindings::cpufreq_policy) {
1308 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1309 // lifetime of `policy`.
1310 let policy = unsafe { Policy::from_raw_mut(ptr) };
1311 T::register_em(policy);
1312 }
1313}
1314
1315impl<T: Driver> Drop for Registration<T> {
1316 /// Unregisters with the cpufreq core.
1317 fn drop(&mut self) {
1318 // SAFETY: `self.0` is guaranteed to be valid for the lifetime of `Registration`.
1319 unsafe { bindings::cpufreq_unregister_driver(self.0.get_mut()) };
1320 }
1321}