thermal周期性调节温度

在通过thermal_zone_device_register注册zone device的时候会初始化一个work
	INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check);
其回调函数是thermal_zone_device_check
thermal_zone_device_check->thermal_zone_device_update
void thermal_zone_device_update(struct thermal_zone_device *tz,
				enum thermal_notify_event event)
{
	int count;

	if (atomic_read(&in_suspend))
		return;

	if (!tz->ops->get_temp)
		return;
//更新温度
	update_temperature(tz);

	thermal_zone_set_trips(tz);

	tz->notify_event = event;
//处理触发点,会调用governor来调节温度
	for (count = 0; count < tz->trips; count++)
		handle_thermal_trip(tz, count);
}
static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
{
	enum thermal_trip_type type;

	/* Ignore disabled trip points */
	if (test_bit(trip, &tz->trips_disabled))
		return;

	tz->ops->get_trip_type(tz, trip, &type);
//触发点处理,后面分析
	if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
		handle_critical_trips(tz, trip, type);
	else
		handle_non_critical_trips(tz, trip, type);
	/*
	 * Alright, we handled this trip successfully.
	 * So, start monitoring again.
	 */
//再次激活workqueue
	monitor_thermal_zone(tz);
}
static void monitor_thermal_zone(struct thermal_zone_device *tz)
{
	mutex_lock(&tz->lock);

	if (tz->passive)
		thermal_zone_device_set_polling(tz, tz->passive_delay);
	else if (tz->polling_delay)
		thermal_zone_device_set_polling(tz, tz->polling_delay);
	else
		thermal_zone_device_set_polling(tz, 0);

	mutex_unlock(&tz->lock);
}
继续看thermal_zone_device_set_polling
static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
					    int delay)
{
	if (delay > 1000)
		mod_delayed_work(system_freezable_wq, &tz->poll_queue,
				 round_jiffies(msecs_to_jiffies(delay)));
	else if (delay)
		mod_delayed_work(system_freezable_wq, &tz->poll_queue,
				 msecs_to_jiffies(delay));
	else
		cancel_delayed_work(&tz->poll_queue);
}
原来thermal_zone_device_set_polling 中会修改delayqueue的下次运行的时间间隔。这样下次这个delayqueue运行的时候又会调用thermal_zone_device_check。从而完成周而复始的检测。除非delay为0的话,就取消这个delayqueue

在handle_thermal_trip中会根据得到的trip来处理,这里的trip分为4中。
enum thermal_trip_type {
	THERMAL_TRIP_ACTIVE = 0,
	THERMAL_TRIP_PASSIVE,
	THERMAL_TRIP_HOT,
	THERMAL_TRIP_CRITICAL,
};
如果是	if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
		handle_critical_trips(tz, trip, type);

static void handle_critical_trips(struct thermal_zone_device *tz,
				  int trip, enum thermal_trip_type trip_type)
{
	int trip_temp;

	tz->ops->get_trip_temp(tz, trip, &trip_temp);

	/* If we have not crossed the trip_temp, we do not care. */
	if (trip_temp <= 0 || tz->temperature < trip_temp)
		return;

	trace_thermal_zone_trip(tz, trip, trip_type);

	if (tz->ops->notify)
		tz->ops->notify(tz, trip, trip_type);
//可以看到如果是THERMAL_TRIP_CRITICAL的话,就调用thermal_emergency_poweroff准备关机操作
	if (trip_type == THERMAL_TRIP_CRITICAL) {
		dev_emerg(&tz->device,
			  "critical temperature reached(%d C),shutting down\n",
			  tz->temperature / 1000);
		mutex_lock(&poweroff_lock);
		if (!power_off_triggered) {
			/*
			 * Queue a backup emergency shutdown in the event of
			 * orderly_poweroff failure
			 */
			thermal_emergency_poweroff();
			orderly_poweroff(true);
			power_off_triggered = true;
		}
		mutex_unlock(&poweroff_lock);
	}
}
static void thermal_emergency_poweroff(void)
{
可以看到这里会决定是否等一段时间在关机。
	int poweroff_delay_ms = CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS;
	/*
	 * poweroff_delay_ms must be a carefully profiled positive value.
	 * Its a must for thermal_emergency_poweroff_work to be scheduled
	 */
	if (poweroff_delay_ms <= 0)
		return;
如果poweroff_delay_ms 不等于0的话。就让thermal_emergency_poweroff_work来关机 
	schedule_delayed_work(&thermal_emergency_poweroff_work,
			      msecs_to_jiffies(poweroff_delay_ms));
}

static DECLARE_DELAYED_WORK(thermal_emergency_poweroff_work,
			    thermal_emergency_poweroff_func);

可以看到thermal_emergency_poweroff_work的回调函数为thermal_emergency_poweroff_func
static void thermal_emergency_poweroff_func(struct work_struct *work)
{
	/*
	 * We have reached here after the emergency thermal shutdown
	 * Waiting period has expired. This means orderly_poweroff has
	 * not been able to shut off the system for some reason.
	 * Try to shut down the system immediately using kernel_power_off
	 * if populated
	 */
//温度太高会先试着通过kernel_power_off关机,如果失败的话,则调用emergency_restart 重启系统
	WARN(1, "Attempting kernel_power_off: Temperature too high\n");
	kernel_power_off();

	/*
	 * Worst of the worst case trigger emergency restart
	 */
	WARN(1, "Attempting emergency_restart: Temperature too high\n");
	emergency_restart();
}

你可能感兴趣的:(Linux,源码分析)