一点点读懂cpufreq(二)

目录

1、注册接口:

2、去注册接口:

3、使用样例

4、软件处理

4.1 对cpufreq_transition_notifier_list的处理

4.2 对cpufreq_policy_notifier_list的处理


本章节主要介绍cpufreq中的通知链实现,在调频策略以及频率变化时来通知对该事件敏感的模块,各个模块可以通过注册和去注册接口来加入到通知链中。

1、注册接口:


   
   
  1. /**
  2.  * cpufreq_register_notifier - Register a notifier with cpufreq.
  3.  * @nb: notifier function to register.
  4.  * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER.
  5.  * Add a notifier to one of two lists: either a list of notifiers that run on
  6.  * clock rate changes (once before and once after every transition), or a list
  7.  * of notifiers that ron on cpufreq policy changes.
  8.  * This function may sleep and it has the same return values as
  9.  * blocking_notifier_chain_register().
  10.  */
  11. int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
  12. {
  13.               int ret;
  14.               if ( cpufreq_disabled())
  15.                             return -EINVAL;
  16.               switch (list) {
  17.               case CPUFREQ_TRANSITION_NOTIFIER:
  18.                             mutex_lock(&cpufreq_fast_switch_lock);
  19.                             if (cpufreq_fast_switch_count > 0) {
  20.                                           mutex_unlock(&cpufreq_fast_switch_lock);
  21.                                           return -EBUSY;
  22.                             }
  23.                             ret = srcu_notifier_chain_register(
  24.                                                         &cpufreq_transition_notifier_list, nb);
  25.                             if (!ret)
  26.                                           cpufreq_fast_switch_count--;
  27.                             mutex_unlock(&cpufreq_fast_switch_lock);
  28.                             break;
  29.               case CPUFREQ_POLICY_NOTIFIER:
  30.                             ret = blocking_notifier_chain_register(
  31.                                                         &cpufreq_policy_notifier_list, nb);
  32.                             break;
  33.               default:
  34.                             ret = -EINVAL;
  35.               }
  36.               return ret;
  37. }
  38. EXPORT_SYMBOL(cpufreq_register_notifier);

CPUFREQ_TRANSITION_NOTIFIER:对频率变化敏感,注册进来的模块添加到cpufreq_transition_notifier_list链表中进行维护及后续操作,模块在回调中进行处理时,可以通过CPUFREQ_PRECHANGE和CPUFREQ_POSTCHANGE来区分是在频率变化前做动作还是在变化后做动作。

CPUFREQ_POLICY_NOTIFIER:对策略变化敏感,注册进来的模块,添加到cpufreq_policy_notifier_list链表中进行维护及后续操作,模块在回调中进行处理时,可以通过CPUFREQ_CREATE_POLICY和CPUFREQ_REMOVE_POLICY来区分是在策略变化前做动作还是在变化后做动作。

2、去注册接口:


   
   
  1. /**
  2.  * cpufreq_unregister_notifier - Unregister a notifier from cpufreq.
  3.  * @nb: notifier block to be unregistered.
  4.  * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER.
  5.  * Remove a notifier from one of the cpufreq notifier lists.
  6.  * This function may sleep and it has the same return values as
  7.  * blocking_notifier_chain_unregister().
  8.  */
  9. int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
  10. {
  11.               int ret;
  12.               if ( cpufreq_disabled())
  13.                             return -EINVAL;
  14.               switch (list) {
  15.               case CPUFREQ_TRANSITION_NOTIFIER:
  16.                             mutex_lock(&cpufreq_fast_switch_lock);
  17.                             ret = srcu_notifier_chain_unregister(
  18.                                                         &cpufreq_transition_notifier_list, nb);
  19.                             if (!ret && ! WARN_ON(cpufreq_fast_switch_count >= 0))
  20.                                           cpufreq_fast_switch_count++;
  21.                             mutex_unlock(&cpufreq_fast_switch_lock);
  22.                             break;
  23.               case CPUFREQ_POLICY_NOTIFIER:
  24.                             ret = blocking_notifier_chain_unregister(
  25.                                                         &cpufreq_policy_notifier_list, nb);
  26.                             break;
  27.               default:
  28.                             ret = -EINVAL;
  29.               }
  30.               return ret;
  31. }
  32. EXPORT_SYMBOL(cpufreq_unregister_notifier);

去注册接口为注册接口的逆向操作,不再做过多解析。

3、使用样例

我们以loongson1-cpufreq.c作为样例


   
   
  1. static int ls1x_cpufreq_notifier(struct notifier_block *nb,
  2. unsigned long val, void *data)
  3. {
  4. if (val == CPUFREQ_POSTCHANGE)
  5. current_cpu_data.udelay_val = loops_per_jiffy;
  6. return NOTIFY_OK;
  7. }
  8. static struct notifier_block ls1x_cpufreq_notifier_block = {
  9. .notifier_call = ls1x_cpufreq_notifier
  10. };

该模块需要感知到频率的变化,需要在频率变化后来做一些事务处理,于是该模块就在回调中通过判断阶段为CPUFREQ_POSTCHANGE时做对应动作,并在初始化时通过调用cpufreq_register_notifier来注册。

4、软件处理

4.1 对cpufreq_transition_notifier_list的处理

现在该注册的模块已经注册进来了,那么cpufreq.c是如何回调注册的回调函数呢?cpufreq对cpufreq_transition_notifier_list链表的处理,统一封装到了函数cpufreq_notify_transition中来实现。

 实际代码以cppc_cpufreq.c为例:

 其中核心函数cpufreq_notify_transition的实现也是正常的逻辑实现,根据入参的不同分别处理

cpufreq_notify_transition函数会分别被cpufreq_freq_transition_begin和cpufreq_freq_transition_end来调用,而这2个函数则分别嵌入在了频率调换前和调换后调用,如此以来用户注册的回调会被最终调用到。

4.2 对cpufreq_policy_notifier_list的处理

对cpufreq_policy_notifier_list的调用,分别在cpufreq_policy_free和cpufreq_online中调用,分别针对policy移除和生效

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值