下来我们看看cpufreq的init。具体code如下:
2527 static struct syscore_ops cpufreq_syscore_ops = {
2528 .shutdown = cpufreq_suspend,
2529 };
2530
2531 struct kobject *cpufreq_global_kobject;
2532 EXPORT_SYMBOL(cpufreq_global_kobject);
2533
2534 static int __init cpufreq_core_init(void)
2535 {
2536 if (cpufreq_disabled())
2537 return -ENODEV;
2538
2539 cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj);
2540 BUG_ON(!cpufreq_global_kobject);
2541
2542 register_syscore_ops(&cpufreq_syscore_ops);
2543
2544 return 0;
2545 }
2546 core_initcall(cpufreq_core_init);
首选调用kobject_create_and_add 在sys下面建立cpufreq的文件夹。
cpu_subsys是在哪里init的呢?
source/drivers/base/cpu.c
501 void __init cpu_dev_init(void)
502 {
503 if (subsys_system_register(&cpu_subsys, cpu_root_attr_groups))
504 panic("Failed to register CPU subsystem");
505
506 cpu_dev_register_generic();
507 }
cpu_subsys是一个bus_type
125 struct bus_type cpu_subsys = {
126 .name = "cpu",
127 .dev_name = "cpu",
128 .match = cpu_subsys_match,
129 #ifdef CONFIG_HOTPLUG_CPU
130 .online = cpu_subsys_online,
131 .offline = cpu_subsys_offline,
132 #endif
133 };
然后调用2542上的register_syscore_ops来注册一个callback,这个callback的实现在2528行主要是在关机的时候且除cpu0 外的cpu都停止时关掉cprfreq,确保cpufreq没有持有任何锁或者信号量,
看看cpufreq_suspend的实现
1617 void cpufreq_suspend(void)
1618 {
1619 struct cpufreq_policy *policy;
1620
1621 if (!cpufreq_driver)
1622 return;
1623
1624 if (!has_target() && !cpufreq_driver->suspend)
1625 goto suspend;
1626
1627 pr_debug("%s: Suspending Governors\n", __func__);
1628
1629 for_each_active_policy(policy) {
1630 if (has_target()) {
1631 down_write(&policy->rwsem);
1632 cpufreq_stop_governor(policy);
1633 up_write(&policy->rwsem);
1634 }
1635
1636 if (cpufreq_driver->suspend && cpufreq_driver->suspend(policy))
1637 pr_err("%s: Failed to suspend driver: %p\n", __func__,
1638 policy);
1639 }
1640
1641 suspend:
1642 cpufreq_suspended = true;
1643 }
主要做3件事。
1:1632行关掉每一个governor
2:调用cpufreq driver的suspend函数。
3:设置cpufreq_suspended = true.
既然有suspend 那肯定有resume,那什么时候调用resume呢?
具体在drivers/base/power/main.c 中的dpm_resume函数会调用cpufreq_resume。这个函数做的事情刚好和suspend相反.
2527 static struct syscore_ops cpufreq_syscore_ops = {
2528 .shutdown = cpufreq_suspend,
2529 };
2530
2531 struct kobject *cpufreq_global_kobject;
2532 EXPORT_SYMBOL(cpufreq_global_kobject);
2533
2534 static int __init cpufreq_core_init(void)
2535 {
2536 if (cpufreq_disabled())
2537 return -ENODEV;
2538
2539 cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj);
2540 BUG_ON(!cpufreq_global_kobject);
2541
2542 register_syscore_ops(&cpufreq_syscore_ops);
2543
2544 return 0;
2545 }
2546 core_initcall(cpufreq_core_init);
首选调用kobject_create_and_add 在sys下面建立cpufreq的文件夹。
cpu_subsys是在哪里init的呢?
source/drivers/base/cpu.c
501 void __init cpu_dev_init(void)
502 {
503 if (subsys_system_register(&cpu_subsys, cpu_root_attr_groups))
504 panic("Failed to register CPU subsystem");
505
506 cpu_dev_register_generic();
507 }
cpu_subsys是一个bus_type
125 struct bus_type cpu_subsys = {
126 .name = "cpu",
127 .dev_name = "cpu",
128 .match = cpu_subsys_match,
129 #ifdef CONFIG_HOTPLUG_CPU
130 .online = cpu_subsys_online,
131 .offline = cpu_subsys_offline,
132 #endif
133 };
然后调用2542上的register_syscore_ops来注册一个callback,这个callback的实现在2528行主要是在关机的时候且除cpu0 外的cpu都停止时关掉cprfreq,确保cpufreq没有持有任何锁或者信号量,
看看cpufreq_suspend的实现
1617 void cpufreq_suspend(void)
1618 {
1619 struct cpufreq_policy *policy;
1620
1621 if (!cpufreq_driver)
1622 return;
1623
1624 if (!has_target() && !cpufreq_driver->suspend)
1625 goto suspend;
1626
1627 pr_debug("%s: Suspending Governors\n", __func__);
1628
1629 for_each_active_policy(policy) {
1630 if (has_target()) {
1631 down_write(&policy->rwsem);
1632 cpufreq_stop_governor(policy);
1633 up_write(&policy->rwsem);
1634 }
1635
1636 if (cpufreq_driver->suspend && cpufreq_driver->suspend(policy))
1637 pr_err("%s: Failed to suspend driver: %p\n", __func__,
1638 policy);
1639 }
1640
1641 suspend:
1642 cpufreq_suspended = true;
1643 }
主要做3件事。
1:1632行关掉每一个governor
2:调用cpufreq driver的suspend函数。
3:设置cpufreq_suspended = true.
既然有suspend 那肯定有resume,那什么时候调用resume呢?
具体在drivers/base/power/main.c 中的dpm_resume函数会调用cpufreq_resume。这个函数做的事情刚好和suspend相反.