1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#![allow(dead_code)]
use crate::{bindings, error::from_kernel_result, types::PointerWrapper, Result};
use core::marker::PhantomData;
pub trait Operations {
type Data: PointerWrapper + Sync + Send;
fn suspend(_data: <Self::Data as PointerWrapper>::Borrowed<'_>) -> Result {
Ok(())
}
fn resume(_data: <Self::Data as PointerWrapper>::Borrowed<'_>) -> Result {
Ok(())
}
fn freeze(_data: <Self::Data as PointerWrapper>::Borrowed<'_>) -> Result {
Ok(())
}
fn restore(_data: <Self::Data as PointerWrapper>::Borrowed<'_>) -> Result {
Ok(())
}
}
macro_rules! pm_callback {
($callback:ident, $method:ident) => {
unsafe extern "C" fn $callback<T: Operations>(
dev: *mut bindings::device,
) -> core::ffi::c_int {
from_kernel_result! {
let ptr = unsafe { bindings::dev_get_drvdata(dev) };
let data = unsafe { T::Data::borrow(ptr) };
T::$method(data)?;
Ok(0)
}
}
};
}
pm_callback!(suspend_callback, suspend);
pm_callback!(resume_callback, resume);
pm_callback!(freeze_callback, freeze);
pm_callback!(restore_callback, restore);
pub(crate) struct OpsTable<T: Operations>(PhantomData<*const T>);
impl<T: Operations> OpsTable<T> {
const VTABLE: bindings::dev_pm_ops = bindings::dev_pm_ops {
prepare: None,
complete: None,
suspend: Some(suspend_callback::<T>),
resume: Some(resume_callback::<T>),
freeze: Some(freeze_callback::<T>),
thaw: None,
poweroff: None,
restore: Some(restore_callback::<T>),
suspend_late: None,
resume_early: None,
freeze_late: None,
thaw_early: None,
poweroff_late: None,
restore_early: None,
suspend_noirq: None,
resume_noirq: None,
freeze_noirq: None,
thaw_noirq: None,
poweroff_noirq: None,
restore_noirq: None,
runtime_suspend: None,
runtime_resume: None,
runtime_idle: None,
};
pub(crate) const unsafe fn build() -> &'static bindings::dev_pm_ops {
&Self::VTABLE
}
}
pub struct NoOperations<T: PointerWrapper>(PhantomData<T>);
impl<T: PointerWrapper + Send + Sync> Operations for NoOperations<T> {
type Data = T;
}
unsafe impl<T: PointerWrapper> Sync for NoOperations<T> {}
unsafe impl<T: PointerWrapper> Send for NoOperations<T> {}