找回密码
 注册
关于网站域名变更的通知
查看: 394|回复: 1
打印 上一主题 下一主题

Linux动态频率调节系统CPUFreq之怎样注册一个cpufreq_driver驱动

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-10-25 16:36 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
Linux动态频率调节系统CPUFreq之怎样注册一个cpufreq_driver驱动& P$ s$ n) d3 j7 \8 E8 P9 r

! }" w; H( _7 I7 C! D与governor不同,系统中只会存在一个cpufreq_driver驱动,根据上一篇Linux动态频率调节系统CPUFreq之概述的介绍,cpufreq_driver是平台相关的,负责最终实施频率的调整动作,而选择工作频率的策略是由governor完成的。所以,系统中只需要注册一个cpufreq_driver即可,它只负责知道如何控制该平台的时钟系统,从而设定由governor确定的工作频率。注册cpufreq_driver驱动会触发cpufreq核心的一系列额外的初始化动作,第一节所说的核心初始化工作非常简单,实际上,更多的初始化动作在注册cpufreq_driver阶段完成。核心提供了一个API:cpufreq_register_driver来完成注册工作。下面我们分析一下这个函数的工作过程:
/ {7 `8 M6 f# G9 q/ E; N. n# T% ^2 i+ i  l' w- U9 n4 k
  • int cpufreq_register_driver(struct cpufreq_driver *driver_data)
  • {
  •         ......

  • ! m  g6 [1 z! l) r- {2 ~, P
  •         if (cpufreq_disabled())
  •                 return -ENODEV;
  • . t7 J; X, \6 y" r$ H
  •         if (!driver_data || !driver_data->verify || !driver_data->init ||
  •             ((!driver_data->setpolicy) && (!driver_data->target)))
  •                 return -EINVAL;# P  y8 @+ d# N* o" K
  * f6 W" H: ^% k( c& u" Q
# M2 P* I7 r1 n+ i- R0 [' {5 Q; [& ^
该API只有一个参数:一个cpufreq_driver指针,driver_data,该结构事先在驱动的代码中定义,调用该API时作为参数传入。函数先判断系统目前是否禁止了调频功能,然后检查cpufreq_driver的几个回调函数是否被实现,由代码可以看出,verify和init回调函数必须要实现,而setpolicy和target回调则至少要被实现其中的一个。这几个回调的作用请参考本系列的第一篇文章。接下来:
% P2 |* r( }" z+ g: N( u
  • write_lock_irqsave(&cpufreq_driver_lock, flags);
  •         if (cpufreq_driver) {
  •                 write_unlock_irqrestore(&cpufreq_driver_lock, flags);
  •                 return -EBUSY;
  •         }
  •         cpufreq_driver = driver_data;
  •         write_unlock_irqrestore(&cpufreq_driver_lock, flags);
    # }5 G. m( |( K; {9 A4 J) \
1 S. L; z' W  ~& n( C7 T" L9 \, X# ?5 e
/ A) K3 f( [6 O$ Z  J( T
检查全局变量cpufreq_driver是否已经被赋值,如果没有,则传入的参数被赋值给全局变量cpufreq_driver,从而保证了系统中只会注册一个cpufreq_driver驱动。然后:

# a6 `( i, W& U! U' Z* m3 B. q. M; h/ N
  •         ret = subsys_inteRFace_register(&cpufreq_interface);
  •         
  •         ......
  •         ......
  • 5 U4 ~3 ?+ x9 o" ]
  •         register_hotcpu_notifier(&cpufreq_cpu_notifier);
    & l- A: w( U* l  d! V) w
9 `* o5 c, _$ b% W' C/ S, D
/ X& `3 I1 t, Q' O: `0 m: B
通过subsys_interface_register给每一个cpu建立一个cpufreq_policy,最后注册cpu hot plug通知,以便在cpu hot plug的时候,能够动态地处理各个cpu policy之间的关系(比如迁移负责管理的cpu等等)。这里要重点讨论一下subsys_interface_register的过程,回到第一节的内容,我们知道初始化阶段,cpu_subsys被建立,从而每个cpu都会在cpu总线设备下建立一个属于自己的设备:sys/devices/system/cpu/cpux。subsys_interface_register负责在cpu_subsys子系统的子设备下面注册公共的接口。我们看看参数cpufreq_interface的定义:
8 L% |# Q* d* `- c7 Y8 D* P- W6 d. G. `7 n4 U; r# w* a
  • static struct subsys_interface cpufreq_interface = {
  •         .name           = "cpufreq",
  •         .subsys         = &cpu_subsys,
  •         .add_dev        = cpufreq_add_dev,
  •         .remove_dev     = cpufreq_remove_dev,
  • };
    * P% C- y2 _1 |
9 p5 `, q4 q3 u# |/ r
7 \+ ^. P7 l+ l2 y7 e( `
subsys_interface_register函数的代码我就不再展开了,它的大致作用就是:遍历子系统下面的每一个子设备,然后用这个子设备作为参数,调用cpufrq_interface结构的add_dev回调函数,这里的回调函数被指向了cpufreq_add_dev,它的具体工作方式我们在下一节中讨论。: W7 ^! m6 o7 Y8 q9 r% ^/ Z4 i% y

1 O! w& q. K1 U8 o" ]7 {driver注册完成后,驱动被保存在全局变量cpufreq_driver中,供核心层使用,同时,每个cpu也会建立自己的policy策略,governor也开始工作,实时地监控着cpu的负载并计算合适的工作频率,然后通过driver调整真正的工作频率。下图是cpufreq_driver注册过程的序列图:
% r/ z% g# t5 J- `- I* r* t- ^2 J2 C* Q2 q& ], S: H
+ m  i7 b- o5 {% `1 S
9 b1 Q4 R# ~6 o& y
图 3.1   cpufreq_driver的注册过程

( O, ]5 \# c$ w! z
6 c4 B3 w  u/ T! V, d$ O
8 y5 O! ~+ a3 K7 a
9 E4 c' N4 i( O# }2 n

6 j0 A5 b+ u" H" Z- y
: e2 l) g# Q( p& _0 G+ V
, u" i. _" S/ S* p& }$ K2 `4 ~
' y0 `2 \  q! n9 J

( C8 O) l/ B9 i8 U

5 V  C: N  T: @% I+ X
4 y3 p- @$ t& d  m; Z
/ G& I8 r+ l! o

该用户从未签到

2#
发表于 2019-10-25 18:56 | 只看该作者
Linux动态频率调节系统CPUFreq之怎样注册一个cpufreq_driver驱动。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-8-24 11:32 , Processed in 0.109375 second(s), 26 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表