⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thermal.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		return -EINVAL;	if (tz->temperature >= tz->trips.critical.temperature) {		printk(KERN_WARNING PREFIX "Critical trip point\n");		tz->trips.critical.flags.enabled = 1;	} else if (tz->trips.critical.flags.enabled)		tz->trips.critical.flags.enabled = 0;	printk(KERN_EMERG	       "Critical temperature reached (%ld C), shutting down.\n",	       KELVIN_TO_CELSIUS(tz->temperature));	acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL,				tz->trips.critical.flags.enabled);	acpi_bus_generate_netlink_event(tz->device->pnp.device_class,					  tz->device->dev.bus_id,					  ACPI_THERMAL_NOTIFY_CRITICAL,					  tz->trips.critical.flags.enabled);	orderly_poweroff(true);	return 0;}static int acpi_thermal_hot(struct acpi_thermal *tz){	if (!tz || !tz->trips.hot.flags.valid || nocrt)		return -EINVAL;	if (tz->temperature >= tz->trips.hot.temperature) {		printk(KERN_WARNING PREFIX "Hot trip point\n");		tz->trips.hot.flags.enabled = 1;	} else if (tz->trips.hot.flags.enabled)		tz->trips.hot.flags.enabled = 0;	acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_HOT,				tz->trips.hot.flags.enabled);	acpi_bus_generate_netlink_event(tz->device->pnp.device_class,					  tz->device->dev.bus_id,					  ACPI_THERMAL_NOTIFY_HOT,					  tz->trips.hot.flags.enabled);	/* TBD: Call user-mode "sleep(S4)" function */	return 0;}static void acpi_thermal_passive(struct acpi_thermal *tz){	int result = 1;	struct acpi_thermal_passive *passive = NULL;	int trend = 0;	int i = 0;	if (!tz || !tz->trips.passive.flags.valid)		return;	passive = &(tz->trips.passive);	/*	 * Above Trip?	 * -----------	 * Calculate the thermal trend (using the passive cooling equation)	 * and modify the performance limit for all passive cooling devices	 * accordingly.  Note that we assume symmetry.	 */	if (tz->temperature >= passive->temperature) {		trend =		    (passive->tc1 * (tz->temperature - tz->last_temperature)) +		    (passive->tc2 * (tz->temperature - passive->temperature));		ACPI_DEBUG_PRINT((ACPI_DB_INFO,				  "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n",				  trend, passive->tc1, tz->temperature,				  tz->last_temperature, passive->tc2,				  tz->temperature, passive->temperature));		passive->flags.enabled = 1;		/* Heating up? */		if (trend > 0)			for (i = 0; i < passive->devices.count; i++)				acpi_processor_set_thermal_limit(passive->								 devices.								 handles[i],								 ACPI_PROCESSOR_LIMIT_INCREMENT);		/* Cooling off? */		else if (trend < 0) {			for (i = 0; i < passive->devices.count; i++)				/*				 * assume that we are on highest				 * freq/lowest thrott and can leave				 * passive mode, even in error case				 */				if (!acpi_processor_set_thermal_limit				    (passive->devices.handles[i],				     ACPI_PROCESSOR_LIMIT_DECREMENT))					result = 0;			/*			 * Leave cooling mode, even if the temp might			 * higher than trip point This is because some			 * machines might have long thermal polling			 * frequencies (tsp) defined. We will fall back			 * into passive mode in next cycle (probably quicker)			 */			if (result) {				passive->flags.enabled = 0;				ACPI_DEBUG_PRINT((ACPI_DB_INFO,						  "Disabling passive cooling, still above threshold,"						  " but we are cooling down\n"));			}		}		return;	}	/*	 * Below Trip?	 * -----------	 * Implement passive cooling hysteresis to slowly increase performance	 * and avoid thrashing around the passive trip point.  Note that we	 * assume symmetry.	 */	if (!passive->flags.enabled)		return;	for (i = 0; i < passive->devices.count; i++)		if (!acpi_processor_set_thermal_limit		    (passive->devices.handles[i],		     ACPI_PROCESSOR_LIMIT_DECREMENT))			result = 0;	if (result) {		passive->flags.enabled = 0;		ACPI_DEBUG_PRINT((ACPI_DB_INFO,				  "Disabling passive cooling (zone is cool)\n"));	}}static void acpi_thermal_active(struct acpi_thermal *tz){	int result = 0;	struct acpi_thermal_active *active = NULL;	int i = 0;	int j = 0;	unsigned long maxtemp = 0;	if (!tz)		return;	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {		active = &(tz->trips.active[i]);		if (!active || !active->flags.valid)			break;		if (tz->temperature >= active->temperature) {			/*			 * Above Threshold?			 * ----------------			 * If not already enabled, turn ON all cooling devices			 * associated with this active threshold.			 */			if (active->temperature > maxtemp)				tz->state.active_index = i;			maxtemp = active->temperature;			if (active->flags.enabled)				continue;			for (j = 0; j < active->devices.count; j++) {				result =				    acpi_bus_set_power(active->devices.						       handles[j],						       ACPI_STATE_D0);				if (result) {					printk(KERN_WARNING PREFIX						      "Unable to turn cooling device [%p] 'on'\n",						      active->devices.						      handles[j]);					continue;				}				active->flags.enabled = 1;				ACPI_DEBUG_PRINT((ACPI_DB_INFO,						  "Cooling device [%p] now 'on'\n",						  active->devices.handles[j]));			}			continue;		}		if (!active->flags.enabled)			continue;		/*		 * Below Threshold?		 * ----------------		 * Turn OFF all cooling devices associated with this		 * threshold.		 */		for (j = 0; j < active->devices.count; j++) {			result = acpi_bus_set_power(active->devices.handles[j],						    ACPI_STATE_D3);			if (result) {				printk(KERN_WARNING PREFIX					      "Unable to turn cooling device [%p] 'off'\n",					      active->devices.handles[j]);				continue;			}			active->flags.enabled = 0;			ACPI_DEBUG_PRINT((ACPI_DB_INFO,					  "Cooling device [%p] now 'off'\n",					  active->devices.handles[j]));		}	}}static void acpi_thermal_check(void *context);static void acpi_thermal_run(unsigned long data){	struct acpi_thermal *tz = (struct acpi_thermal *)data;	if (!tz->zombie)		acpi_os_execute(OSL_GPE_HANDLER, acpi_thermal_check, (void *)data);}static void acpi_thermal_check(void *data){	int result = 0;	struct acpi_thermal *tz = data;	unsigned long sleep_time = 0;	unsigned long timeout_jiffies = 0;	int i = 0;	struct acpi_thermal_state state;	if (!tz) {		printk(KERN_ERR PREFIX "Invalid (NULL) context\n");		return;	}	/* Check if someone else is already running */	if (!mutex_trylock(&tz->lock))		return;	state = tz->state;	result = acpi_thermal_get_temperature(tz);	if (result)		goto unlock;	memset(&tz->state, 0, sizeof(tz->state));	/*	 * Check Trip Points	 * -----------------	 * Compare the current temperature to the trip point values to see	 * if we've entered one of the thermal policy states.  Note that	 * this function determines when a state is entered, but the 	 * individual policy decides when it is exited (e.g. hysteresis).	 */	if (tz->trips.critical.flags.valid)		state.critical |=		    (tz->temperature >= tz->trips.critical.temperature);	if (tz->trips.hot.flags.valid)		state.hot |= (tz->temperature >= tz->trips.hot.temperature);	if (tz->trips.passive.flags.valid)		state.passive |=		    (tz->temperature >= tz->trips.passive.temperature);	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)		if (tz->trips.active[i].flags.valid)			state.active |=			    (tz->temperature >=			     tz->trips.active[i].temperature);	/*	 * Invoke Policy	 * -------------	 * Separated from the above check to allow individual policy to 	 * determine when to exit a given state.	 */	if (state.critical)		acpi_thermal_critical(tz);	if (state.hot)		acpi_thermal_hot(tz);	if (state.passive)		acpi_thermal_passive(tz);	if (state.active)		acpi_thermal_active(tz);	/*	 * Calculate State	 * ---------------	 * Again, separated from the above two to allow independent policy	 * decisions.	 */	tz->state.critical = tz->trips.critical.flags.enabled;	tz->state.hot = tz->trips.hot.flags.enabled;	tz->state.passive = tz->trips.passive.flags.enabled;	tz->state.active = 0;	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)		tz->state.active |= tz->trips.active[i].flags.enabled;	/*	 * Calculate Sleep Time	 * --------------------	 * If we're in the passive state, use _TSP's value.  Otherwise	 * use the default polling frequency (e.g. _TZP).  If no polling	 * frequency is specified then we'll wait forever (at least until	 * a thermal event occurs).  Note that _TSP and _TZD values are	 * given in 1/10th seconds (we must covert to milliseconds).	 */	if (tz->state.passive) {		sleep_time = tz->trips.passive.tsp * 100;		timeout_jiffies =  jiffies + (HZ * sleep_time) / 1000;	} else if (tz->polling_frequency > 0) {		sleep_time = tz->polling_frequency * 100;		timeout_jiffies =  round_jiffies(jiffies + (HZ * sleep_time) / 1000);	}	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n",			  tz->name, tz->temperature, sleep_time));	/*	 * Schedule Next Poll	 * ------------------	 */	if (!sleep_time) {		if (timer_pending(&(tz->timer)))			del_timer(&(tz->timer));	} else {		if (timer_pending(&(tz->timer)))			mod_timer(&(tz->timer), timeout_jiffies);		else {			tz->timer.data = (unsigned long)tz;			tz->timer.function = acpi_thermal_run;			tz->timer.expires = timeout_jiffies;			add_timer(&(tz->timer));		}	}      unlock:	mutex_unlock(&tz->lock);}/* --------------------------------------------------------------------------                              FS Interface (/proc)   -------------------------------------------------------------------------- */static struct proc_dir_entry *acpi_thermal_dir;static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset){	struct acpi_thermal *tz = seq->private;	if (!tz)		goto end;	seq_puts(seq, "state:                   ");	if (!tz->state.critical && !tz->state.hot && !tz->state.passive	    && !tz->state.active)		seq_puts(seq, "ok\n");	else {		if (tz->state.critical)			seq_puts(seq, "critical ");		if (tz->state.hot)			seq_puts(seq, "hot ");		if (tz->state.passive)			seq_puts(seq, "passive ");		if (tz->state.active)			seq_printf(seq, "active[%d]", tz->state.active_index);		seq_puts(seq, "\n");	}      end:	return 0;}static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file){	return single_open(file, acpi_thermal_state_seq_show, PDE(inode)->data);}static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset){	int result = 0;	struct acpi_thermal *tz = seq->private;	if (!tz)		goto end;	result = acpi_thermal_get_temperature(tz);	if (result)		goto end;	seq_printf(seq, "temperature:             %ld C\n",		   KELVIN_TO_CELSIUS(tz->temperature));      end:	return 0;}static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file){	return single_open(file, acpi_thermal_temp_seq_show, PDE(inode)->data);}static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset){	struct acpi_thermal *tz = seq->private;	struct acpi_device *device;	acpi_status status;	int i = 0;	int j = 0;	if (!tz)		goto end;	if (tz->trips.critical.flags.valid)		seq_printf(seq, "critical (S5):           %ld C%s",			   KELVIN_TO_CELSIUS(tz->trips.critical.temperature),			   nocrt ? " <disabled>\n" : "\n");	if (tz->trips.hot.flags.valid)		seq_printf(seq, "hot (S4):                %ld C%s",			   KELVIN_TO_CELSIUS(tz->trips.hot.temperature),			   nocrt ? " <disabled>\n" : "\n");	if (tz->trips.passive.flags.valid) {		seq_printf(seq,			   "passive:                 %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",			   KELVIN_TO_CELSIUS(tz->trips.passive.temperature),			   tz->trips.passive.tc1, tz->trips.passive.tc2,			   tz->trips.passive.tsp);		for (j = 0; j < tz->trips.passive.devices.count; j++) {			status = acpi_bus_get_device(tz->trips.passive.devices.						     handles[j], &device);			seq_printf(seq, "%4.4s ", status ? "" :				   acpi_device_bid(device));		}		seq_puts(seq, "\n");	}	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {		if (!(tz->trips.active[i].flags.valid))			break;		seq_printf(seq, "active[%d]:               %ld C: devices=",			   i,			   KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));		for (j = 0; j < tz->trips.active[i].devices.count; j++){			status = acpi_bus_get_device(tz->trips.active[i].						     devices.handles[j],						     &device);			seq_printf(seq, "%4.4s ", status ? "" :				   acpi_device_bid(device));		}		seq_puts(seq, "\n");	}      end:	return 0;}static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file){	return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data);}static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset){	struct acpi_thermal *tz = seq->private;	if (!tz)		goto end;	if (!tz->flags.cooling_mode)		seq_puts(seq, "<setting not supported>\n");	else		seq_puts(seq, "0 - Active; 1 - Passive\n");      end:	return 0;}static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file){	return single_open(file, acpi_thermal_cooling_seq_show,			   PDE(inode)->data);}static ssize_tacpi_thermal_write_cooling_mode(struct file *file,				const char __user * buffer,				size_t count, loff_t * ppos){	struct seq_file *m = file->private_data;	struct acpi_thermal *tz = m->private;	int result = 0;	char mode_string[12] = { '\0' };	if (!tz || (count > sizeof(mode_string) - 1))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -