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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
Linux动态频率调节系统CPUFreq之怎样注册一个cpufreq_driver驱动
- h/ ~3 {4 w# S/ ]. h& M
! S. V/ d2 ~2 r( G% `
与governor不同,系统中只会存在一个cpufreq_driver驱动,根据上一篇Linux动态频率调节系统CPUFreq之概述的介绍,cpufreq_driver是平台相关的,负责最终实施频率的调整动作,而选择工作频率的策略是由governor完成的。所以,系统中只需要注册一个cpufreq_driver即可,它只负责知道如何控制该平台的时钟系统,从而设定由governor确定的工作频率。注册cpufreq_driver驱动会触发cpufreq核心的一系列额外的初始化动作,第一节所说的核心初始化工作非常简单,实际上,更多的初始化动作在注册cpufreq_driver阶段完成。核心提供了一个API:cpufreq_register_driver来完成注册工作。下面我们分析一下这个函数的工作过程:" T. a/ J$ f6 V* q( K5 c- O: a

  R' x- ?! _; e# n
  • int cpufreq_register_driver(struct cpufreq_driver *driver_data)
  • {
  •         ......
  • 9 D7 L0 H. C* P9 d- }
  •         if (cpufreq_disabled())
  •                 return -ENODEV;

  • / T, W* S/ C' V0 @3 _7 l7 d, W
  •         if (!driver_data || !driver_data->verify || !driver_data->init ||
  •             ((!driver_data->setpolicy) && (!driver_data->target)))
  •                 return -EINVAL;0 s) r" S0 g1 ?
  
' Q0 K) w  {7 h) h

. T: Q& o; i1 d( _1 I7 l9 g该API只有一个参数:一个cpufreq_driver指针,driver_data,该结构事先在驱动的代码中定义,调用该API时作为参数传入。函数先判断系统目前是否禁止了调频功能,然后检查cpufreq_driver的几个回调函数是否被实现,由代码可以看出,verify和init回调函数必须要实现,而setpolicy和target回调则至少要被实现其中的一个。这几个回调的作用请参考本系列的第一篇文章。接下来:
# ~# T2 l  c0 d9 B
  • 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);) u$ g8 p, @0 t/ R& a; a
6 q- J6 K. P  T! A0 U

! h( |' b- p) S( r; V检查全局变量cpufreq_driver是否已经被赋值,如果没有,则传入的参数被赋值给全局变量cpufreq_driver,从而保证了系统中只会注册一个cpufreq_driver驱动。然后:
. W9 a# l" U* ~5 x0 S+ s& {) o

* x! }! ^0 |: D7 \. ^
  •         ret = subsys_inteRFace_register(&cpufreq_interface);
  •         
  •         ......
  •         ......

  • ) y1 _5 m. L. ]4 E0 l4 q3 `
  •         register_hotcpu_notifier(&cpufreq_cpu_notifier);+ k7 \- `, e# ]4 \& |

; ?4 {5 a9 U; p9 {" r/ Y2 Z( E
& `: y/ K% h7 c/ n$ i8 i1 m* ^
通过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的定义:
" e& i- t& h, Z
2 H% R/ `; k6 c2 Y
  • static struct subsys_interface cpufreq_interface = {
  •         .name           = "cpufreq",
  •         .subsys         = &cpu_subsys,
  •         .add_dev        = cpufreq_add_dev,
  •         .remove_dev     = cpufreq_remove_dev,
  • };
    % r: u% G0 U) G0 ^
3 V! @; g: P4 @6 M! b

& E2 H3 y2 W/ vsubsys_interface_register函数的代码我就不再展开了,它的大致作用就是:遍历子系统下面的每一个子设备,然后用这个子设备作为参数,调用cpufrq_interface结构的add_dev回调函数,这里的回调函数被指向了cpufreq_add_dev,它的具体工作方式我们在下一节中讨论。
# R" Q8 M9 {6 {
# H& d% ]1 ?, s' gdriver注册完成后,驱动被保存在全局变量cpufreq_driver中,供核心层使用,同时,每个cpu也会建立自己的policy策略,governor也开始工作,实时地监控着cpu的负载并计算合适的工作频率,然后通过driver调整真正的工作频率。下图是cpufreq_driver注册过程的序列图:3 y5 V) d" l* L$ l: k
/ j& `9 t( y: o% R

+ F) w( b  j! E! K0 r3 w( T& Q3 B% m* A! W# h5 A- E
图 3.1   cpufreq_driver的注册过程

: R& s1 t* d2 m8 r
( o' `/ H) c9 A- r/ G6 h
  {' k  E, A- q, b/ }, X

; ~, i1 |6 }5 P4 X% v$ C5 k7 E/ ^  a$ M# L

8 ]% Y" \3 H- G+ ]1 g) x# a2 a
1 R) o7 o# P/ r5 ]% F3 l
" ~: Y6 J0 \% P% _. ~; T
1 d" h2 D3 N, u# v
3 h, w9 X/ x) o; I% {1 S; M

2 b$ ^& N8 b7 z# p, S1 |" }
# @! ^6 ?+ F3 B4 [

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-11-25 01:46 , Processed in 0.218750 second(s), 27 queries , Gzip On.

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

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

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