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