PM定义了一个notifier_chain:
27 static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
PM在休眠和唤醒的过程中会发出一些EVENTS,
246 /* Hibernation and suspend events */
247 #define PM_HIBERNATION_PREPARE 0x0001 /* Going to hibernate */
248 #define PM_POST_HIBERNATION 0x0002 /* Hibernation finished */
249 #define PM_SUSPEND_PREPARE 0x0003 /* Going to suspend the system */
250 #define PM_POST_SUSPEND 0x0004 /* Suspend finished */
251 #define PM_RESTORE_PREPARE 0x0005 /* Going to restore a saved image */
252 #define PM_POST_RESTORE 0x0006 /* Restore failed */
如果哪个内核模块想得到这些EVENTS,就需要定义一个notifier_block, 并把它挂载到pm_chain_head上。为此,PM定义了挂载和卸载函数:
29 int register_pm_notifier(struct notifier_block *nb)
30 {
31 return blocking_notifier_chain_register(&pm_chain_head, nb);
32 }
33 EXPORT_SYMBOL_GPL(register_pm_notifier);
34
35 int unregister_pm_notifier(struct notifier_block *nb)
36 {
37 return blocking_notifier_chain_unregister(&pm_chain_head, nb);
38 }
39 EXPORT_SYMBOL_GPL(unregister_pm_notifier);
在PM休眠或者唤醒进行到某个特定阶段时,PM就会使用下面这个函数向链上所有的内核模块发送一个EVENT。
41 int pm_notifier_call_chain(unsigned long val)
42 {
43 return (blocking_notifier_call_chain(&pm_chain_head, val, NULL)
44 == NOTIFY_BAD) ? -EINVAL : 0;
45 }
比如, 我们可以在suspend_prepare()中发现这样的代码:
88 error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);
89 if (error)
90 goto Finish;
91
102 Finish:
103 pm_notifier_call_chain(PM_POST_SUSPEND);
我们可以在vmwatchdog.c中看到使用pm_chain的例子。
vmwatchdog想获得下面的四个EVENTS,
PM_POST_HIBERNATION
PM_POST_SUSPEND
PM_HIBERNATION_PREPARE
PM_SUSPEND_PREPARE:
并在这4个EVENTS发生时调用对应的函数。 于是它定义了vmwdt_power_event()函数:
272 /*
273 * This function is called for suspend and resume.
274 */
275 static int vmwdt_power_event(struct notifier_block *this, unsigned long event,
276 void *ptr)
277 {
278 switch (event) {
279 case PM_POST_HIBERNATION:
280 case PM_POST_SUSPEND:
281 return vmwdt_resume();
282 case PM_HIBERNATION_PREPARE:
283 case PM_SUSPEND_PREPARE:
284 return vmwdt_suspend();
285 default:
286 return NOTIFY_DONE;
287 }
288 }
vmwatch定义了一个notifier_block结构,叫做vmwdt_power_notifier,
290 static struct notifier_block vmwdt_power_notifier = {
291 .notifier_call = vmwdt_power_event,
292 };
并把它挂载到pm_chain链上,
315 ret = register_pm_notifier(&vmwdt_power_notifier);
这样,每次PM通过pm_notifier_call_chain()发出一些EVENTS时,vmwatchdog就可以接收到这些EVENTS并执行相应的函数了。
阅读(1119) | 评论(0) | 转发(0) |