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