【dvfs】【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 */
};
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;
};


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;
};



猜你喜欢

转载自blog.csdn.net/feifei_csdn/article/details/80843963
今日推荐