【policy】【driver】【governor】

之前看过interactive调度器,对应的还有ondemand、performance等调度器,调度器是上层策略,而调度器的实现则是通过policy来实现的。

policy

Governor是调频的上层策略, policy是一次调频操作的实体 (句柄), 一个policy可以与多个cpu对应.

 

 

struct cpufreq_policy {
	/* CPUs sharing clock, require sw coordination(协调) */
	cpumask_var_t		cpus;	/* Online CPUs only */
	cpumask_var_t		related_cpus; /* Online + Offline CPUs */
	cpumask_var_t		real_cpus; /* Related and present */

	unsigned int		shared_type; /* ACPI: ANY or ALL affected CPUs
						should set cpufreq */
	//  policy的managed cpu号. 一般为注册policy的cpu; 当该cpu offline时, 
	// 会选取cpus的下一cpu作为新的managed cpu. 此时前面的cpu称为last_cpu.
	unsigned int		cpu;    /* cpu managing this policy, must be online */

	struct clk		*clk;
	
	// 硬件特性
	struct cpufreq_cpuinfo	cpuinfo;/* see above */
	
	// 软件特性
	unsigned int		min;    /* in kHz */
	unsigned int		max;    /* in kHz */
	unsigned int		cur;    /* in kHz, only needed if cpufreq
					 * governors are used */

	// 类似变频之前的freq和目标freq
	unsigned int		restore_freq; /* = policy->cur before transition */
	unsigned int		target_freq; /* freq that the policy wants to set */
	unsigned int		suspend_freq; /* freq to set during suspend */
	

	unsigned int		policy; /* see above */
	unsigned int		last_policy; /* policy before unplug(拔核) */

	// 当前使用的governor,governor_data是tuables,governor_enabled是witch开关
	struct cpufreq_governor	*governor; /* see below */
	void			*governor_data;
	bool			governor_enabled; /* governor start/stop flag */
	
	// 因为governor是可以切换的
	char			last_governor[CPUFREQ_NAME_LEN]; /* last governor used */

	struct work_struct	update; /* if update_policy() needs to be
					 * called, but you're in IRQ context */

	// user_policy一般用于保存原始参数,因为温度过高的时候最大频率可能会发生变化
	struct cpufreq_user_policy user_policy;
	struct cpufreq_frequency_table	*freq_table;

	struct list_head        policy_list;
	struct kobject		kobj;
	struct completion	kobj_unregister;
	struct notifier_block pm_qos_freq_nb;

	/*
	 * The rules for this semaphore:
	 * - Any routine that wants to read from the policy structure will
	 *   do a down_read on this semaphore.
	 * - Any routine that will write to the policy structure and/or may take away
	 *   the policy altogether (eg. CPU hotplug), will hold this lock in write
	 *   mode before doing so.
	 *
	 * Additional rules:
	 * - Lock should not be held across
	 *     __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
	 */
	struct rw_semaphore	rwsem;(信号量)


	/*
	 * Fast switch flags:
	 * - fast_switch_possible should be set by the driver if it can
	 *   guarantee that frequency can be changed on any CPU sharing the
	 *   policy and that the change will affect all of the policy CPUs then.
	 * - fast_switch_enabled is to be set by governors that support fast
	 *   freqnency switching with the help of cpufreq_enable_fast_switch().
	 */
	bool                    fast_switch_possible;
	bool                    fast_switch_enabled;

	/*
	 * Preferred average time interval between consecutive invocations of
	 * the driver to set the frequency for this policy.  To be set by the
	 * scaling driver (0, which is the default, means no preference).
	 */
	unsigned int		up_transition_delay_us;
	unsigned int		down_transition_delay_us;

	 /* Cached frequency lookup from cpufreq_driver_resolve_freq. */
	unsigned int cached_target_freq;
	int cached_resolved_idx;

	/* Synchronization for frequency transitions */
	bool			transition_ongoing; /* Tracks transition status */
	spinlock_t		transition_lock;
	wait_queue_head_t	transition_wait;
	struct task_struct	*transition_task; /* Task which is doing the transition */

	/* cpufreq-stats */
	// 对应的是stat这个节点
	struct cpufreq_stats	*stats;

	/* For cpufreq driver's internal use */
	void			*driver_data;
};

其中

struct cpufreq_cpuinfo {
	// 硬件特性
	unsigned int		max_freq;
	unsigned int		min_freq;

	/* in 10^(-9) s = nanoseconds */纳秒为单位
	unsigned int		transition_latency;
};
struct cpufreq_user_policy {
	unsigned int		min;    /* in kHz */
	unsigned int		max;    /* in kHz */
};

不管具体的驱动如何变化,核心层都提供了节点,而不是每家驱动各自添加的,这就解释了为什么不同芯片厂商,只要架构是相同的,他们的节点就都相同

/**
 * show_cpuinfo_cur_freq - current CPU frequency as detected by hardware
 */
static ssize_t show_cpuinfo_cur_freq(struct cpufreq_policy *policy,
					char *buf)
{
	unsigned int cur_freq = __cpufreq_get(policy);

	if (cur_freq)
		return sprintf(buf, "%u\n", cur_freq);

	return sprintf(buf, "<unknown>\n");
}
/**
 * show_scaling_driver - show the cpufreq driver currently loaded
 */
static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf)
{
	return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", cpufreq_driver->name);
}
/**
 * show_scaling_governor - show the current policy for the specified CPU
 */
 
static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
{
	// 也就是说policy里面的powersave和performance,和governor里面的是不一样的嘛!
	if (policy->policy == CPUFREQ_POLICY_POWERSAVE)
		return sprintf(buf, "powersave\n");
	else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
		return sprintf(buf, "performance\n");
	else if (policy->governor)
		return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", policy->governor->name);
	return -EINVAL;
}
static ssize_t show_scaling_cur_freq(struct cpufreq_policy *policy, char *buf)
{
	ssize_t ret;

	if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get)
		ret = sprintf(buf, "%u\n", cpufreq_driver->get(policy->cpu));
	else
		ret = sprintf(buf, "%u\n", policy->cur);
	return ret;
}
static ssize_t show_scaling_cur_freq(struct cpufreq_policy *policy, char *buf)
{
	ssize_t ret;

	// 一般都是没有设置setpolicy函数的
	if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get)
		ret = sprintf(buf, "%u\n", cpufreq_driver->get(policy->cpu));
	else
		ret = sprintf(buf, "%u\n", policy->cur);
	return ret;
}

driver

struct cpufreq_driver {
	char		name[CPUFREQ_NAME_LEN];
	u8		flags;
	void		*driver_data;

	/* needed by all drivers */
	int		(*init)(struct cpufreq_policy *policy);
	int		(*verify)(struct cpufreq_policy *policy);//检查policy的参数是否被支持

	// 定义下面两个中的一个
	/* define one out of two */
	//如果不支持通过governor选择合适的运行频率,则实现setpolicy回调函数,
    //这样系统只能支持CPUFREQ_POLICY_POWERSAVE和CPUFREQ_POLICY_PERFORMANCE这两种工作策略 
	int		(*setpolicy)(struct cpufreq_policy *policy);

	/*
	 * On failure, should always restore frequency to policy->restore_freq
	 * (i.e. old freq).
	 */
	 //实现target回调函数,通过target回调设定governor所需要的频率
	 //target或者target_index设定目标频率
	int		(*target)(struct cpufreq_policy *policy,
				  unsigned int target_freq,
				  unsigned int relation);	/* Deprecated */
	int		(*target_index)(struct cpufreq_policy *policy,
					unsigned int index);
	
	/*
	 * Only for drivers with target_index() and CPUFREQ_ASYNC_NOTIFICATION
	 * unset.
	 *
	 * get_intermediate should return a stable intermediate frequency
	 * platform wants to switch to and target_intermediate() should set CPU
	 * to to that frequency, before jumping to the frequency corresponding
	 * to 'index'. Core will take care of sending notifications and driver
	 * doesn't have to handle them in target_intermediate() or
	 * target_index().
	 *
	 * Drivers can return '0' from get_intermediate() in case they don't
	 * wish to switch to intermediate frequency for some target frequency.
	 * In that case core will directly call ->target_index().
	 */
	unsigned int	(*get_intermediate)(struct cpufreq_policy *policy,
					    unsigned int index);
	int		(*target_intermediate)(struct cpufreq_policy *policy,
					       unsigned int index);

	/* should be defined, if possible */
	// 从硬件获取当前freq
	unsigned int	(*get)(unsigned int cpu);

	/* optional */
	int		(*bios_limit)(int cpu, unsigned int *limit);

	// 与init对应
	int		(*exit)(struct cpufreq_policy *policy);

	void		(*stop_cpu)(struct cpufreq_policy *policy);

	// 针对boot cpu, 因为其他cpu已经在suspend前offline了
	int		(*suspend)(struct cpufreq_policy *policy);
	
	int		(*resume)(struct cpufreq_policy *policy);

	/* Will be called after the driver is fully initialized */
	void		(*ready)(struct cpufreq_policy *policy);

	struct freq_attr **attr;

	/* platform specific boost support code */
	bool		boost_supported;
	bool		boost_enabled;
	int		(*set_boost)(int state);
};

governor

struct cpufreq_governor {
	char	name[CPUFREQ_NAME_LEN];
	int	initialized;
	//指向一个回调函数,CPUFreq Core会在不同的阶段调用该回调函数,用于该governor的启动、停止、初始化、退出动作
	int	(*governor)	(struct cpufreq_policy *policy,
				 unsigned int event);
	ssize_t	(*show_setspeed)	(struct cpufreq_policy *policy,
					 char *buf);
	int	(*store_setspeed)	(struct cpufreq_policy *policy,
					 unsigned int freq);
	unsigned int max_transition_latency; /* HW must be able to switch to
			next freq faster than this value in nano secs or we
			will fallback to performance governor */
	//所有注册的governor都会利用该字段链接在一个全局链表中,以供系统查询和使用
	struct list_head	governor_list;
	struct module		*owner;
};

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值