Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/kernel/cpufreq.rs
29266 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 ETERNAL_LATENCY_NS: u32 = bindings::CPUFREQ_ETERNAL as u32;
42
43
/// CPU frequency driver flags.
44
pub 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.
68
const CPUFREQ_RELATION_L: u32 = 0;
69
const CPUFREQ_RELATION_H: u32 = 1;
70
const CPUFREQ_RELATION_C: u32 = 2;
71
72
/// Can be used with any of the above values.
73
const 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)]
79
pub 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
88
impl 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
102
impl 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)]
130
pub struct PolicyData(Opaque<bindings::cpufreq_policy_data>);
131
132
impl 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)]
171
pub struct TableIndex(usize);
172
173
impl 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
186
impl 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)]
224
pub struct Table(Opaque<bindings::cpufreq_frequency_table>);
225
226
impl 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`].
277
pub struct TableBox {
278
entries: Pin<KVec<bindings::cpufreq_frequency_table>>,
279
}
280
281
impl 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
307
impl 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)]
351
pub struct TableBuilder {
352
entries: KVec<bindings::cpufreq_frequency_table>,
353
}
354
355
impl 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)]
414
pub struct Policy(Opaque<bindings::cpufreq_policy>);
415
416
impl 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) -> CpuId {
469
// SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
470
unsafe { CpuId::from_u32_unchecked(self.as_ref().cpu) }
471
}
472
473
/// Returns the minimum frequency for the [`Policy`].
474
#[inline]
475
pub fn min(&self) -> Hertz {
476
Hertz::from_khz(self.as_ref().min as usize)
477
}
478
479
/// Set the minimum frequency for the [`Policy`].
480
#[inline]
481
pub fn set_min(&mut self, min: Hertz) -> &mut Self {
482
self.as_mut_ref().min = min.as_khz() as u32;
483
self
484
}
485
486
/// Returns the maximum frequency for the [`Policy`].
487
#[inline]
488
pub fn max(&self) -> Hertz {
489
Hertz::from_khz(self.as_ref().max as usize)
490
}
491
492
/// Set the maximum frequency for the [`Policy`].
493
#[inline]
494
pub fn set_max(&mut self, max: Hertz) -> &mut Self {
495
self.as_mut_ref().max = max.as_khz() as u32;
496
self
497
}
498
499
/// Returns the current frequency for the [`Policy`].
500
#[inline]
501
pub fn cur(&self) -> Hertz {
502
Hertz::from_khz(self.as_ref().cur as usize)
503
}
504
505
/// Returns the suspend frequency for the [`Policy`].
506
#[inline]
507
pub fn suspend_freq(&self) -> Hertz {
508
Hertz::from_khz(self.as_ref().suspend_freq as usize)
509
}
510
511
/// Sets the suspend frequency for the [`Policy`].
512
#[inline]
513
pub fn set_suspend_freq(&mut self, freq: Hertz) -> &mut Self {
514
self.as_mut_ref().suspend_freq = freq.as_khz() as u32;
515
self
516
}
517
518
/// Provides a wrapper to the generic suspend routine.
519
#[inline]
520
pub fn generic_suspend(&mut self) -> Result {
521
// SAFETY: By the type invariant, the pointer stored in `self` is valid.
522
to_result(unsafe { bindings::cpufreq_generic_suspend(self.as_mut_ref()) })
523
}
524
525
/// Provides a wrapper to the generic get routine.
526
#[inline]
527
pub fn generic_get(&self) -> Result<u32> {
528
// SAFETY: By the type invariant, the pointer stored in `self` is valid.
529
Ok(unsafe { bindings::cpufreq_generic_get(u32::from(self.cpu())) })
530
}
531
532
/// Provides a wrapper to the register with energy model using the OPP core.
533
#[cfg(CONFIG_PM_OPP)]
534
#[inline]
535
pub fn register_em_opp(&mut self) {
536
// SAFETY: By the type invariant, the pointer stored in `self` is valid.
537
unsafe { bindings::cpufreq_register_em_with_opp(self.as_mut_ref()) };
538
}
539
540
/// Gets [`cpumask::Cpumask`] for a cpufreq [`Policy`].
541
#[inline]
542
pub fn cpus(&mut self) -> &mut cpumask::Cpumask {
543
// SAFETY: The pointer to `cpus` is valid for writing and remains valid for the lifetime of
544
// the returned reference.
545
unsafe { cpumask::CpumaskVar::from_raw_mut(&mut self.as_mut_ref().cpus) }
546
}
547
548
/// Sets clock for the [`Policy`].
549
///
550
/// # Safety
551
///
552
/// The caller must guarantee that the returned [`Clk`] is not dropped while it is getting used
553
/// by the C code.
554
#[cfg(CONFIG_COMMON_CLK)]
555
pub unsafe fn set_clk(&mut self, dev: &Device, name: Option<&CStr>) -> Result<Clk> {
556
let clk = Clk::get(dev, name)?;
557
self.as_mut_ref().clk = clk.as_raw();
558
Ok(clk)
559
}
560
561
/// Allows / disallows frequency switching code to run on any CPU.
562
#[inline]
563
pub fn set_dvfs_possible_from_any_cpu(&mut self, val: bool) -> &mut Self {
564
self.as_mut_ref().dvfs_possible_from_any_cpu = val;
565
self
566
}
567
568
/// Returns if fast switching of frequencies is possible or not.
569
#[inline]
570
pub fn fast_switch_possible(&self) -> bool {
571
self.as_ref().fast_switch_possible
572
}
573
574
/// Enables / disables fast frequency switching.
575
#[inline]
576
pub fn set_fast_switch_possible(&mut self, val: bool) -> &mut Self {
577
self.as_mut_ref().fast_switch_possible = val;
578
self
579
}
580
581
/// Sets transition latency (in nanoseconds) for the [`Policy`].
582
#[inline]
583
pub fn set_transition_latency_ns(&mut self, latency_ns: u32) -> &mut Self {
584
self.as_mut_ref().cpuinfo.transition_latency = latency_ns;
585
self
586
}
587
588
/// Sets cpuinfo `min_freq`.
589
#[inline]
590
pub fn set_cpuinfo_min_freq(&mut self, min_freq: Hertz) -> &mut Self {
591
self.as_mut_ref().cpuinfo.min_freq = min_freq.as_khz() as u32;
592
self
593
}
594
595
/// Sets cpuinfo `max_freq`.
596
#[inline]
597
pub fn set_cpuinfo_max_freq(&mut self, max_freq: Hertz) -> &mut Self {
598
self.as_mut_ref().cpuinfo.max_freq = max_freq.as_khz() as u32;
599
self
600
}
601
602
/// Set `transition_delay_us`, i.e. the minimum time between successive frequency change
603
/// requests.
604
#[inline]
605
pub fn set_transition_delay_us(&mut self, transition_delay_us: u32) -> &mut Self {
606
self.as_mut_ref().transition_delay_us = transition_delay_us;
607
self
608
}
609
610
/// Returns reference to the CPU frequency [`Table`] for the [`Policy`].
611
pub fn freq_table(&self) -> Result<&Table> {
612
if self.as_ref().freq_table.is_null() {
613
return Err(EINVAL);
614
}
615
616
// SAFETY: The `freq_table` is guaranteed to be valid for reading and remains valid for the
617
// lifetime of the returned reference.
618
Ok(unsafe { Table::from_raw(self.as_ref().freq_table) })
619
}
620
621
/// Sets the CPU frequency [`Table`] for the [`Policy`].
622
///
623
/// # Safety
624
///
625
/// The caller must guarantee that the [`Table`] is not dropped while it is getting used by the
626
/// C code.
627
#[inline]
628
pub unsafe fn set_freq_table(&mut self, table: &Table) -> &mut Self {
629
self.as_mut_ref().freq_table = table.as_raw();
630
self
631
}
632
633
/// Returns the [`Policy`]'s private data.
634
pub fn data<T: ForeignOwnable>(&mut self) -> Option<<T>::Borrowed<'_>> {
635
if self.as_ref().driver_data.is_null() {
636
None
637
} else {
638
// SAFETY: The data is earlier set from [`set_data`].
639
Some(unsafe { T::borrow(self.as_ref().driver_data.cast()) })
640
}
641
}
642
643
/// Sets the private data of the [`Policy`] using a foreign-ownable wrapper.
644
///
645
/// # Errors
646
///
647
/// Returns `EBUSY` if private data is already set.
648
fn set_data<T: ForeignOwnable>(&mut self, data: T) -> Result {
649
if self.as_ref().driver_data.is_null() {
650
// Transfer the ownership of the data to the foreign interface.
651
self.as_mut_ref().driver_data = <T as ForeignOwnable>::into_foreign(data).cast();
652
Ok(())
653
} else {
654
Err(EBUSY)
655
}
656
}
657
658
/// Clears and returns ownership of the private data.
659
fn clear_data<T: ForeignOwnable>(&mut self) -> Option<T> {
660
if self.as_ref().driver_data.is_null() {
661
None
662
} else {
663
let data = Some(
664
// SAFETY: The data is earlier set by us from [`set_data`]. It is safe to take
665
// back the ownership of the data from the foreign interface.
666
unsafe { <T as ForeignOwnable>::from_foreign(self.as_ref().driver_data.cast()) },
667
);
668
self.as_mut_ref().driver_data = ptr::null_mut();
669
data
670
}
671
}
672
}
673
674
/// CPU frequency policy created from a CPU number.
675
///
676
/// This struct represents the CPU frequency policy obtained for a specific CPU, providing safe
677
/// access to the underlying `cpufreq_policy` and ensuring proper cleanup when the `PolicyCpu` is
678
/// dropped.
679
struct PolicyCpu<'a>(&'a mut Policy);
680
681
impl<'a> PolicyCpu<'a> {
682
fn from_cpu(cpu: CpuId) -> Result<Self> {
683
// SAFETY: It is safe to call `cpufreq_cpu_get` for any valid CPU.
684
let ptr = from_err_ptr(unsafe { bindings::cpufreq_cpu_get(u32::from(cpu)) })?;
685
686
Ok(Self(
687
// SAFETY: The `ptr` is guaranteed to be valid and remains valid for the lifetime of
688
// the returned reference.
689
unsafe { Policy::from_raw_mut(ptr) },
690
))
691
}
692
}
693
694
impl<'a> Deref for PolicyCpu<'a> {
695
type Target = Policy;
696
697
fn deref(&self) -> &Self::Target {
698
self.0
699
}
700
}
701
702
impl<'a> DerefMut for PolicyCpu<'a> {
703
fn deref_mut(&mut self) -> &mut Policy {
704
self.0
705
}
706
}
707
708
impl<'a> Drop for PolicyCpu<'a> {
709
fn drop(&mut self) {
710
// SAFETY: The underlying pointer is guaranteed to be valid for the lifetime of `self`.
711
unsafe { bindings::cpufreq_cpu_put(self.0.as_raw()) };
712
}
713
}
714
715
/// CPU frequency driver.
716
///
717
/// Implement this trait to provide a CPU frequency driver and its callbacks.
718
///
719
/// Reference: <https://docs.kernel.org/cpu-freq/cpu-drivers.html>
720
#[vtable]
721
pub trait Driver {
722
/// Driver's name.
723
const NAME: &'static CStr;
724
725
/// Driver's flags.
726
const FLAGS: u16;
727
728
/// Boost support.
729
const BOOST_ENABLED: bool;
730
731
/// Policy specific data.
732
///
733
/// Require that `PData` implements `ForeignOwnable`. We guarantee to never move the underlying
734
/// wrapped data structure.
735
type PData: ForeignOwnable;
736
737
/// Driver's `init` callback.
738
fn init(policy: &mut Policy) -> Result<Self::PData>;
739
740
/// Driver's `exit` callback.
741
fn exit(_policy: &mut Policy, _data: Option<Self::PData>) -> Result {
742
build_error!(VTABLE_DEFAULT_ERROR)
743
}
744
745
/// Driver's `online` callback.
746
fn online(_policy: &mut Policy) -> Result {
747
build_error!(VTABLE_DEFAULT_ERROR)
748
}
749
750
/// Driver's `offline` callback.
751
fn offline(_policy: &mut Policy) -> Result {
752
build_error!(VTABLE_DEFAULT_ERROR)
753
}
754
755
/// Driver's `suspend` callback.
756
fn suspend(_policy: &mut Policy) -> Result {
757
build_error!(VTABLE_DEFAULT_ERROR)
758
}
759
760
/// Driver's `resume` callback.
761
fn resume(_policy: &mut Policy) -> Result {
762
build_error!(VTABLE_DEFAULT_ERROR)
763
}
764
765
/// Driver's `ready` callback.
766
fn ready(_policy: &mut Policy) {
767
build_error!(VTABLE_DEFAULT_ERROR)
768
}
769
770
/// Driver's `verify` callback.
771
fn verify(data: &mut PolicyData) -> Result;
772
773
/// Driver's `setpolicy` callback.
774
fn setpolicy(_policy: &mut Policy) -> Result {
775
build_error!(VTABLE_DEFAULT_ERROR)
776
}
777
778
/// Driver's `target` callback.
779
fn target(_policy: &mut Policy, _target_freq: u32, _relation: Relation) -> Result {
780
build_error!(VTABLE_DEFAULT_ERROR)
781
}
782
783
/// Driver's `target_index` callback.
784
fn target_index(_policy: &mut Policy, _index: TableIndex) -> Result {
785
build_error!(VTABLE_DEFAULT_ERROR)
786
}
787
788
/// Driver's `fast_switch` callback.
789
fn fast_switch(_policy: &mut Policy, _target_freq: u32) -> u32 {
790
build_error!(VTABLE_DEFAULT_ERROR)
791
}
792
793
/// Driver's `adjust_perf` callback.
794
fn adjust_perf(_policy: &mut Policy, _min_perf: usize, _target_perf: usize, _capacity: usize) {
795
build_error!(VTABLE_DEFAULT_ERROR)
796
}
797
798
/// Driver's `get_intermediate` callback.
799
fn get_intermediate(_policy: &mut Policy, _index: TableIndex) -> u32 {
800
build_error!(VTABLE_DEFAULT_ERROR)
801
}
802
803
/// Driver's `target_intermediate` callback.
804
fn target_intermediate(_policy: &mut Policy, _index: TableIndex) -> Result {
805
build_error!(VTABLE_DEFAULT_ERROR)
806
}
807
808
/// Driver's `get` callback.
809
fn get(_policy: &mut Policy) -> Result<u32> {
810
build_error!(VTABLE_DEFAULT_ERROR)
811
}
812
813
/// Driver's `update_limits` callback.
814
fn update_limits(_policy: &mut Policy) {
815
build_error!(VTABLE_DEFAULT_ERROR)
816
}
817
818
/// Driver's `bios_limit` callback.
819
fn bios_limit(_policy: &mut Policy, _limit: &mut u32) -> Result {
820
build_error!(VTABLE_DEFAULT_ERROR)
821
}
822
823
/// Driver's `set_boost` callback.
824
fn set_boost(_policy: &mut Policy, _state: i32) -> Result {
825
build_error!(VTABLE_DEFAULT_ERROR)
826
}
827
828
/// Driver's `register_em` callback.
829
fn register_em(_policy: &mut Policy) {
830
build_error!(VTABLE_DEFAULT_ERROR)
831
}
832
}
833
834
/// CPU frequency driver Registration.
835
///
836
/// # Examples
837
///
838
/// The following example demonstrates how to register a cpufreq driver.
839
///
840
/// ```
841
/// use kernel::{
842
/// cpufreq,
843
/// c_str,
844
/// device::{Core, Device},
845
/// macros::vtable,
846
/// of, platform,
847
/// sync::Arc,
848
/// };
849
/// struct SampleDevice;
850
///
851
/// #[derive(Default)]
852
/// struct SampleDriver;
853
///
854
/// #[vtable]
855
/// impl cpufreq::Driver for SampleDriver {
856
/// const NAME: &'static CStr = c_str!("cpufreq-sample");
857
/// const FLAGS: u16 = cpufreq::flags::NEED_INITIAL_FREQ_CHECK | cpufreq::flags::IS_COOLING_DEV;
858
/// const BOOST_ENABLED: bool = true;
859
///
860
/// type PData = Arc<SampleDevice>;
861
///
862
/// fn init(policy: &mut cpufreq::Policy) -> Result<Self::PData> {
863
/// // Initialize here
864
/// Ok(Arc::new(SampleDevice, GFP_KERNEL)?)
865
/// }
866
///
867
/// fn exit(_policy: &mut cpufreq::Policy, _data: Option<Self::PData>) -> Result {
868
/// Ok(())
869
/// }
870
///
871
/// fn suspend(policy: &mut cpufreq::Policy) -> Result {
872
/// policy.generic_suspend()
873
/// }
874
///
875
/// fn verify(data: &mut cpufreq::PolicyData) -> Result {
876
/// data.generic_verify()
877
/// }
878
///
879
/// fn target_index(policy: &mut cpufreq::Policy, index: cpufreq::TableIndex) -> Result {
880
/// // Update CPU frequency
881
/// Ok(())
882
/// }
883
///
884
/// fn get(policy: &mut cpufreq::Policy) -> Result<u32> {
885
/// policy.generic_get()
886
/// }
887
/// }
888
///
889
/// impl platform::Driver for SampleDriver {
890
/// type IdInfo = ();
891
/// const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
892
///
893
/// fn probe(
894
/// pdev: &platform::Device<Core>,
895
/// _id_info: Option<&Self::IdInfo>,
896
/// ) -> Result<Pin<KBox<Self>>> {
897
/// cpufreq::Registration::<SampleDriver>::new_foreign_owned(pdev.as_ref())?;
898
/// Ok(KBox::new(Self {}, GFP_KERNEL)?.into())
899
/// }
900
/// }
901
/// ```
902
#[repr(transparent)]
903
pub struct Registration<T: Driver>(KBox<UnsafeCell<bindings::cpufreq_driver>>, PhantomData<T>);
904
905
/// SAFETY: `Registration` doesn't offer any methods or access to fields when shared between threads
906
/// or CPUs, so it is safe to share it.
907
unsafe impl<T: Driver> Sync for Registration<T> {}
908
909
#[allow(clippy::non_send_fields_in_send_ty)]
910
/// SAFETY: Registration with and unregistration from the cpufreq subsystem can happen from any
911
/// thread.
912
unsafe impl<T: Driver> Send for Registration<T> {}
913
914
impl<T: Driver> Registration<T> {
915
const VTABLE: bindings::cpufreq_driver = bindings::cpufreq_driver {
916
name: Self::copy_name(T::NAME),
917
boost_enabled: T::BOOST_ENABLED,
918
flags: T::FLAGS,
919
920
// Initialize mandatory callbacks.
921
init: Some(Self::init_callback),
922
verify: Some(Self::verify_callback),
923
924
// Initialize optional callbacks based on the traits of `T`.
925
setpolicy: if T::HAS_SETPOLICY {
926
Some(Self::setpolicy_callback)
927
} else {
928
None
929
},
930
target: if T::HAS_TARGET {
931
Some(Self::target_callback)
932
} else {
933
None
934
},
935
target_index: if T::HAS_TARGET_INDEX {
936
Some(Self::target_index_callback)
937
} else {
938
None
939
},
940
fast_switch: if T::HAS_FAST_SWITCH {
941
Some(Self::fast_switch_callback)
942
} else {
943
None
944
},
945
adjust_perf: if T::HAS_ADJUST_PERF {
946
Some(Self::adjust_perf_callback)
947
} else {
948
None
949
},
950
get_intermediate: if T::HAS_GET_INTERMEDIATE {
951
Some(Self::get_intermediate_callback)
952
} else {
953
None
954
},
955
target_intermediate: if T::HAS_TARGET_INTERMEDIATE {
956
Some(Self::target_intermediate_callback)
957
} else {
958
None
959
},
960
get: if T::HAS_GET {
961
Some(Self::get_callback)
962
} else {
963
None
964
},
965
update_limits: if T::HAS_UPDATE_LIMITS {
966
Some(Self::update_limits_callback)
967
} else {
968
None
969
},
970
bios_limit: if T::HAS_BIOS_LIMIT {
971
Some(Self::bios_limit_callback)
972
} else {
973
None
974
},
975
online: if T::HAS_ONLINE {
976
Some(Self::online_callback)
977
} else {
978
None
979
},
980
offline: if T::HAS_OFFLINE {
981
Some(Self::offline_callback)
982
} else {
983
None
984
},
985
exit: if T::HAS_EXIT {
986
Some(Self::exit_callback)
987
} else {
988
None
989
},
990
suspend: if T::HAS_SUSPEND {
991
Some(Self::suspend_callback)
992
} else {
993
None
994
},
995
resume: if T::HAS_RESUME {
996
Some(Self::resume_callback)
997
} else {
998
None
999
},
1000
ready: if T::HAS_READY {
1001
Some(Self::ready_callback)
1002
} else {
1003
None
1004
},
1005
set_boost: if T::HAS_SET_BOOST {
1006
Some(Self::set_boost_callback)
1007
} else {
1008
None
1009
},
1010
register_em: if T::HAS_REGISTER_EM {
1011
Some(Self::register_em_callback)
1012
} else {
1013
None
1014
},
1015
..pin_init::zeroed()
1016
};
1017
1018
const fn copy_name(name: &'static CStr) -> [c_char; CPUFREQ_NAME_LEN] {
1019
let src = name.to_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::register`] and will be dropped, once the
1048
/// device is detached.
1049
pub fn new_foreign_owned(dev: &Device<Bound>) -> Result
1050
where
1051
T: 'static,
1052
{
1053
devres::register(dev, Self::new()?, GFP_KERNEL)
1054
}
1055
}
1056
1057
/// CPU frequency driver callbacks.
1058
impl<T: Driver> Registration<T> {
1059
/// Driver's `init` callback.
1060
///
1061
/// # Safety
1062
///
1063
/// - This function may only be called from the cpufreq C infrastructure.
1064
/// - The pointer arguments must be valid pointers.
1065
unsafe extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
1066
from_result(|| {
1067
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1068
// lifetime of `policy`.
1069
let policy = unsafe { Policy::from_raw_mut(ptr) };
1070
1071
let data = T::init(policy)?;
1072
policy.set_data(data)?;
1073
Ok(0)
1074
})
1075
}
1076
1077
/// Driver's `exit` callback.
1078
///
1079
/// # Safety
1080
///
1081
/// - This function may only be called from the cpufreq C infrastructure.
1082
/// - The pointer arguments must be valid pointers.
1083
unsafe extern "C" fn exit_callback(ptr: *mut bindings::cpufreq_policy) {
1084
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1085
// lifetime of `policy`.
1086
let policy = unsafe { Policy::from_raw_mut(ptr) };
1087
1088
let data = policy.clear_data();
1089
let _ = T::exit(policy, data);
1090
}
1091
1092
/// Driver's `online` callback.
1093
///
1094
/// # Safety
1095
///
1096
/// - This function may only be called from the cpufreq C infrastructure.
1097
/// - The pointer arguments must be valid pointers.
1098
unsafe extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> 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::online(policy).map(|()| 0)
1104
})
1105
}
1106
1107
/// Driver's `offline` callback.
1108
///
1109
/// # Safety
1110
///
1111
/// - This function may only be called from the cpufreq C infrastructure.
1112
/// - The pointer arguments must be valid pointers.
1113
unsafe extern "C" fn offline_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
1114
from_result(|| {
1115
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1116
// lifetime of `policy`.
1117
let policy = unsafe { Policy::from_raw_mut(ptr) };
1118
T::offline(policy).map(|()| 0)
1119
})
1120
}
1121
1122
/// Driver's `suspend` callback.
1123
///
1124
/// # Safety
1125
///
1126
/// - This function may only be called from the cpufreq C infrastructure.
1127
/// - The pointer arguments must be valid pointers.
1128
unsafe extern "C" fn suspend_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
1129
from_result(|| {
1130
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1131
// lifetime of `policy`.
1132
let policy = unsafe { Policy::from_raw_mut(ptr) };
1133
T::suspend(policy).map(|()| 0)
1134
})
1135
}
1136
1137
/// Driver's `resume` callback.
1138
///
1139
/// # Safety
1140
///
1141
/// - This function may only be called from the cpufreq C infrastructure.
1142
/// - The pointer arguments must be valid pointers.
1143
unsafe extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
1144
from_result(|| {
1145
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1146
// lifetime of `policy`.
1147
let policy = unsafe { Policy::from_raw_mut(ptr) };
1148
T::resume(policy).map(|()| 0)
1149
})
1150
}
1151
1152
/// Driver's `ready` callback.
1153
///
1154
/// # Safety
1155
///
1156
/// - This function may only be called from the cpufreq C infrastructure.
1157
/// - The pointer arguments must be valid pointers.
1158
unsafe extern "C" fn ready_callback(ptr: *mut bindings::cpufreq_policy) {
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::ready(policy);
1163
}
1164
1165
/// Driver's `verify` callback.
1166
///
1167
/// # Safety
1168
///
1169
/// - This function may only be called from the cpufreq C infrastructure.
1170
/// - The pointer arguments must be valid pointers.
1171
unsafe extern "C" fn verify_callback(ptr: *mut bindings::cpufreq_policy_data) -> c_int {
1172
from_result(|| {
1173
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1174
// lifetime of `policy`.
1175
let data = unsafe { PolicyData::from_raw_mut(ptr) };
1176
T::verify(data).map(|()| 0)
1177
})
1178
}
1179
1180
/// Driver's `setpolicy` callback.
1181
///
1182
/// # Safety
1183
///
1184
/// - This function may only be called from the cpufreq C infrastructure.
1185
/// - The pointer arguments must be valid pointers.
1186
unsafe extern "C" fn setpolicy_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
1187
from_result(|| {
1188
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1189
// lifetime of `policy`.
1190
let policy = unsafe { Policy::from_raw_mut(ptr) };
1191
T::setpolicy(policy).map(|()| 0)
1192
})
1193
}
1194
1195
/// Driver's `target` callback.
1196
///
1197
/// # Safety
1198
///
1199
/// - This function may only be called from the cpufreq C infrastructure.
1200
/// - The pointer arguments must be valid pointers.
1201
unsafe extern "C" fn target_callback(
1202
ptr: *mut bindings::cpufreq_policy,
1203
target_freq: c_uint,
1204
relation: c_uint,
1205
) -> c_int {
1206
from_result(|| {
1207
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1208
// lifetime of `policy`.
1209
let policy = unsafe { Policy::from_raw_mut(ptr) };
1210
T::target(policy, target_freq, Relation::new(relation)?).map(|()| 0)
1211
})
1212
}
1213
1214
/// Driver's `target_index` callback.
1215
///
1216
/// # Safety
1217
///
1218
/// - This function may only be called from the cpufreq C infrastructure.
1219
/// - The pointer arguments must be valid pointers.
1220
unsafe extern "C" fn target_index_callback(
1221
ptr: *mut bindings::cpufreq_policy,
1222
index: c_uint,
1223
) -> c_int {
1224
from_result(|| {
1225
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1226
// lifetime of `policy`.
1227
let policy = unsafe { Policy::from_raw_mut(ptr) };
1228
1229
// SAFETY: The C code guarantees that `index` corresponds to a valid entry in the
1230
// frequency table.
1231
let index = unsafe { TableIndex::new(index as usize) };
1232
1233
T::target_index(policy, index).map(|()| 0)
1234
})
1235
}
1236
1237
/// Driver's `fast_switch` callback.
1238
///
1239
/// # Safety
1240
///
1241
/// - This function may only be called from the cpufreq C infrastructure.
1242
/// - The pointer arguments must be valid pointers.
1243
unsafe extern "C" fn fast_switch_callback(
1244
ptr: *mut bindings::cpufreq_policy,
1245
target_freq: c_uint,
1246
) -> c_uint {
1247
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1248
// lifetime of `policy`.
1249
let policy = unsafe { Policy::from_raw_mut(ptr) };
1250
T::fast_switch(policy, target_freq)
1251
}
1252
1253
/// Driver's `adjust_perf` callback.
1254
///
1255
/// # Safety
1256
///
1257
/// - This function may only be called from the cpufreq C infrastructure.
1258
unsafe extern "C" fn adjust_perf_callback(
1259
cpu: c_uint,
1260
min_perf: c_ulong,
1261
target_perf: c_ulong,
1262
capacity: c_ulong,
1263
) {
1264
// SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
1265
let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) };
1266
1267
if let Ok(mut policy) = PolicyCpu::from_cpu(cpu_id) {
1268
T::adjust_perf(&mut policy, min_perf, target_perf, capacity);
1269
}
1270
}
1271
1272
/// Driver's `get_intermediate` callback.
1273
///
1274
/// # Safety
1275
///
1276
/// - This function may only be called from the cpufreq C infrastructure.
1277
/// - The pointer arguments must be valid pointers.
1278
unsafe extern "C" fn get_intermediate_callback(
1279
ptr: *mut bindings::cpufreq_policy,
1280
index: c_uint,
1281
) -> c_uint {
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
1286
// SAFETY: The C code guarantees that `index` corresponds to a valid entry in the
1287
// frequency table.
1288
let index = unsafe { TableIndex::new(index as usize) };
1289
1290
T::get_intermediate(policy, index)
1291
}
1292
1293
/// Driver's `target_intermediate` callback.
1294
///
1295
/// # Safety
1296
///
1297
/// - This function may only be called from the cpufreq C infrastructure.
1298
/// - The pointer arguments must be valid pointers.
1299
unsafe extern "C" fn target_intermediate_callback(
1300
ptr: *mut bindings::cpufreq_policy,
1301
index: c_uint,
1302
) -> c_int {
1303
from_result(|| {
1304
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1305
// lifetime of `policy`.
1306
let policy = unsafe { Policy::from_raw_mut(ptr) };
1307
1308
// SAFETY: The C code guarantees that `index` corresponds to a valid entry in the
1309
// frequency table.
1310
let index = unsafe { TableIndex::new(index as usize) };
1311
1312
T::target_intermediate(policy, index).map(|()| 0)
1313
})
1314
}
1315
1316
/// Driver's `get` callback.
1317
///
1318
/// # Safety
1319
///
1320
/// - This function may only be called from the cpufreq C infrastructure.
1321
unsafe extern "C" fn get_callback(cpu: c_uint) -> c_uint {
1322
// SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
1323
let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) };
1324
1325
PolicyCpu::from_cpu(cpu_id).map_or(0, |mut policy| T::get(&mut policy).map_or(0, |f| f))
1326
}
1327
1328
/// Driver's `update_limit` callback.
1329
///
1330
/// # Safety
1331
///
1332
/// - This function may only be called from the cpufreq C infrastructure.
1333
/// - The pointer arguments must be valid pointers.
1334
unsafe extern "C" fn update_limits_callback(ptr: *mut bindings::cpufreq_policy) {
1335
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1336
// lifetime of `policy`.
1337
let policy = unsafe { Policy::from_raw_mut(ptr) };
1338
T::update_limits(policy);
1339
}
1340
1341
/// Driver's `bios_limit` callback.
1342
///
1343
/// # Safety
1344
///
1345
/// - This function may only be called from the cpufreq C infrastructure.
1346
/// - The pointer arguments must be valid pointers.
1347
unsafe extern "C" fn bios_limit_callback(cpu: c_int, limit: *mut c_uint) -> c_int {
1348
// SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
1349
let cpu_id = unsafe { CpuId::from_i32_unchecked(cpu) };
1350
1351
from_result(|| {
1352
let mut policy = PolicyCpu::from_cpu(cpu_id)?;
1353
1354
// SAFETY: `limit` is guaranteed by the C code to be valid.
1355
T::bios_limit(&mut policy, &mut (unsafe { *limit })).map(|()| 0)
1356
})
1357
}
1358
1359
/// Driver's `set_boost` callback.
1360
///
1361
/// # Safety
1362
///
1363
/// - This function may only be called from the cpufreq C infrastructure.
1364
/// - The pointer arguments must be valid pointers.
1365
unsafe extern "C" fn set_boost_callback(
1366
ptr: *mut bindings::cpufreq_policy,
1367
state: c_int,
1368
) -> c_int {
1369
from_result(|| {
1370
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1371
// lifetime of `policy`.
1372
let policy = unsafe { Policy::from_raw_mut(ptr) };
1373
T::set_boost(policy, state).map(|()| 0)
1374
})
1375
}
1376
1377
/// Driver's `register_em` callback.
1378
///
1379
/// # Safety
1380
///
1381
/// - This function may only be called from the cpufreq C infrastructure.
1382
/// - The pointer arguments must be valid pointers.
1383
unsafe extern "C" fn register_em_callback(ptr: *mut bindings::cpufreq_policy) {
1384
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1385
// lifetime of `policy`.
1386
let policy = unsafe { Policy::from_raw_mut(ptr) };
1387
T::register_em(policy);
1388
}
1389
}
1390
1391
impl<T: Driver> Drop for Registration<T> {
1392
/// Unregisters with the cpufreq core.
1393
fn drop(&mut self) {
1394
// SAFETY: `self.0` is guaranteed to be valid for the lifetime of `Registration`.
1395
unsafe { bindings::cpufreq_unregister_driver(self.0.get_mut()) };
1396
}
1397
}
1398
1399