Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f3bff70 authored by Len Brown's avatar Len Brown
Browse files

Merge branch 'thermal' into release

parents 2ddb9f17 03a971a2
Loading
Loading
Loading
Loading
+12 −8
Original line number Original line Diff line number Diff line
@@ -68,31 +68,35 @@ static struct acpi_driver acpi_fan_driver = {
};
};


/* thermal cooling device callbacks */
/* thermal cooling device callbacks */
static int fan_get_max_state(struct thermal_cooling_device *cdev, char *buf)
static int fan_get_max_state(struct thermal_cooling_device *cdev, unsigned long
			     *state)
{
{
	/* ACPI fan device only support two states: ON/OFF */
	/* ACPI fan device only support two states: ON/OFF */
	return sprintf(buf, "1\n");
	*state = 1;
	return 0;
}
}


static int fan_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
			     *state)
{
{
	struct acpi_device *device = cdev->devdata;
	struct acpi_device *device = cdev->devdata;
	int state;
	int result;
	int result;
	int acpi_state;


	if (!device)
	if (!device)
		return -EINVAL;
		return -EINVAL;


	result = acpi_bus_get_power(device->handle, &state);
	result = acpi_bus_get_power(device->handle, &acpi_state);
	if (result)
	if (result)
		return result;
		return result;


	return sprintf(buf, "%s\n", state == ACPI_STATE_D3 ? "0" :
	*state = (acpi_state == ACPI_STATE_D3 ? 0 :
			 (state == ACPI_STATE_D0 ? "1" : "unknown"));
		 (acpi_state == ACPI_STATE_D0 ? 1 : -1));
	return 0;
}
}


static int
static int
fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state)
fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
{
{
	struct acpi_device *device = cdev->devdata;
	struct acpi_device *device = cdev->devdata;
	int result;
	int result;
+11 −9
Original line number Original line Diff line number Diff line
@@ -373,7 +373,8 @@ static int acpi_processor_max_state(struct acpi_processor *pr)
	return max_state;
	return max_state;
}
}
static int
static int
processor_get_max_state(struct thermal_cooling_device *cdev, char *buf)
processor_get_max_state(struct thermal_cooling_device *cdev,
			unsigned long *state)
{
{
	struct acpi_device *device = cdev->devdata;
	struct acpi_device *device = cdev->devdata;
	struct acpi_processor *pr = acpi_driver_data(device);
	struct acpi_processor *pr = acpi_driver_data(device);
@@ -381,28 +382,29 @@ processor_get_max_state(struct thermal_cooling_device *cdev, char *buf)
	if (!device || !pr)
	if (!device || !pr)
		return -EINVAL;
		return -EINVAL;


	return sprintf(buf, "%d\n", acpi_processor_max_state(pr));
	*state = acpi_processor_max_state(pr);
	return 0;
}
}


static int
static int
processor_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
processor_get_cur_state(struct thermal_cooling_device *cdev,
			unsigned long *cur_state)
{
{
	struct acpi_device *device = cdev->devdata;
	struct acpi_device *device = cdev->devdata;
	struct acpi_processor *pr = acpi_driver_data(device);
	struct acpi_processor *pr = acpi_driver_data(device);
	int cur_state;


	if (!device || !pr)
	if (!device || !pr)
		return -EINVAL;
		return -EINVAL;


	cur_state = cpufreq_get_cur_state(pr->id);
	*cur_state = cpufreq_get_cur_state(pr->id);
	if (pr->flags.throttling)
	if (pr->flags.throttling)
		cur_state += pr->throttling.state;
		*cur_state += pr->throttling.state;

	return 0;
	return sprintf(buf, "%d\n", cur_state);
}
}


static int
static int
processor_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state)
processor_set_cur_state(struct thermal_cooling_device *cdev,
			unsigned long state)
{
{
	struct acpi_device *device = cdev->devdata;
	struct acpi_device *device = cdev->devdata;
	struct acpi_processor *pr = acpi_driver_data(device);
	struct acpi_processor *pr = acpi_driver_data(device);
+99 −440
Original line number Original line Diff line number Diff line
@@ -37,11 +37,11 @@
#include <linux/init.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/proc_fs.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/jiffies.h>
#include <linux/kmod.h>
#include <linux/kmod.h>
#include <linux/seq_file.h>
#include <linux/seq_file.h>
#include <linux/reboot.h>
#include <linux/reboot.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include <linux/thermal.h>
#include <linux/thermal.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_bus.h>
@@ -190,7 +190,6 @@ struct acpi_thermal {
	struct acpi_thermal_state state;
	struct acpi_thermal_state state;
	struct acpi_thermal_trips trips;
	struct acpi_thermal_trips trips;
	struct acpi_handle_list devices;
	struct acpi_handle_list devices;
	struct timer_list timer;
	struct thermal_zone_device *thermal_zone;
	struct thermal_zone_device *thermal_zone;
	int tz_enabled;
	int tz_enabled;
	struct mutex lock;
	struct mutex lock;
@@ -290,6 +289,11 @@ static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds)


	tz->polling_frequency = seconds * 10;	/* Convert value to deci-seconds */
	tz->polling_frequency = seconds * 10;	/* Convert value to deci-seconds */


	tz->thermal_zone->polling_delay = seconds * 1000;

	if (tz->tz_enabled)
		thermal_zone_device_update(tz->thermal_zone);

	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
			  "Polling frequency set to %lu seconds\n",
			  "Polling frequency set to %lu seconds\n",
			  tz->polling_frequency/10));
			  tz->polling_frequency/10));
@@ -569,392 +573,18 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
	return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
	return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
}
}


static int acpi_thermal_critical(struct acpi_thermal *tz)
{
	if (!tz || !tz->trips.critical.flags.valid)
		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;

	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,
					  dev_name(&tz->device->dev),
					  ACPI_THERMAL_NOTIFY_CRITICAL,
					  tz->trips.critical.flags.enabled);

	/* take no action if nocrt is set */
	if(!nocrt) {
		printk(KERN_EMERG
			"Critical temperature reached (%ld C), shutting down.\n",
			KELVIN_TO_CELSIUS(tz->temperature));
		orderly_poweroff(true);
	}

	return 0;
}

static int acpi_thermal_hot(struct acpi_thermal *tz)
{
	if (!tz || !tz->trips.hot.flags.valid)
		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,
					  dev_name(&tz->device->dev),
					  ACPI_THERMAL_NOTIFY_HOT,
					  tz->trips.hot.flags.enabled);

	/* TBD: Call user-mode "sleep(S4)" function if nocrt is cleared */

	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_active_off(void *data)
{
	int result = 0;
	struct acpi_thermal *tz = data;
	int i = 0;
	int j = 0;
	struct acpi_thermal_active *active = NULL;

	if (!tz) {
		printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
		return;
	}

	result = acpi_thermal_get_temperature(tz);
	if (result)
		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) {
			/*
			 * If the thermal temperature is greater than the
			 * active threshod, unnecessary to turn off the
			 * the active cooling device.
			 */
			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);
	}
}

static void acpi_thermal_check(void *data)
static void acpi_thermal_check(void *data)
{
{
	int result = 0;
	struct acpi_thermal *tz = data;
	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;

	if (!tz->tz_enabled)
		goto unlock;

	memset(&tz->state, 0, sizeof(tz->state));


	/*
	thermal_zone_device_update(tz->thermal_zone);
	 * 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);
}
}


/* sys I/F for generic thermal sysfs support */
/* sys I/F for generic thermal sysfs support */
#define KELVIN_TO_MILLICELSIUS(t) (t * 100 - 273200)
#define KELVIN_TO_MILLICELSIUS(t) (t * 100 - 273200)


static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
static int thermal_get_temp(struct thermal_zone_device *thermal,
			    unsigned long *temp)
{
{
	struct acpi_thermal *tz = thermal->devdata;
	struct acpi_thermal *tz = thermal->devdata;
	int result;
	int result;
@@ -966,25 +596,28 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
	if (result)
	if (result)
		return result;
		return result;


	return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(tz->temperature));
	*temp = KELVIN_TO_MILLICELSIUS(tz->temperature);
	return 0;
}
}


static const char enabled[] = "kernel";
static const char enabled[] = "kernel";
static const char disabled[] = "user";
static const char disabled[] = "user";
static int thermal_get_mode(struct thermal_zone_device *thermal,
static int thermal_get_mode(struct thermal_zone_device *thermal,
				char *buf)
				enum thermal_device_mode *mode)
{
{
	struct acpi_thermal *tz = thermal->devdata;
	struct acpi_thermal *tz = thermal->devdata;


	if (!tz)
	if (!tz)
		return -EINVAL;
		return -EINVAL;


	return sprintf(buf, "%s\n", tz->tz_enabled ?
	*mode = tz->tz_enabled ? THERMAL_DEVICE_ENABLED :
			enabled : disabled);
		THERMAL_DEVICE_DISABLED;

	return 0;
}
}


static int thermal_set_mode(struct thermal_zone_device *thermal,
static int thermal_set_mode(struct thermal_zone_device *thermal,
				const char *buf)
				enum thermal_device_mode mode)
{
{
	struct acpi_thermal *tz = thermal->devdata;
	struct acpi_thermal *tz = thermal->devdata;
	int enable;
	int enable;
@@ -995,9 +628,9 @@ static int thermal_set_mode(struct thermal_zone_device *thermal,
	/*
	/*
	 * enable/disable thermal management from ACPI thermal driver
	 * enable/disable thermal management from ACPI thermal driver
	 */
	 */
	if (!strncmp(buf, enabled, sizeof enabled - 1))
	if (mode == THERMAL_DEVICE_ENABLED)
		enable = 1;
		enable = 1;
	else if (!strncmp(buf, disabled, sizeof disabled - 1))
	else if (mode == THERMAL_DEVICE_DISABLED)
		enable = 0;
		enable = 0;
	else
	else
		return -EINVAL;
		return -EINVAL;
@@ -1013,7 +646,7 @@ static int thermal_set_mode(struct thermal_zone_device *thermal,
}
}


static int thermal_get_trip_type(struct thermal_zone_device *thermal,
static int thermal_get_trip_type(struct thermal_zone_device *thermal,
				 int trip, char *buf)
				 int trip, enum thermal_trip_type *type)
{
{
	struct acpi_thermal *tz = thermal->devdata;
	struct acpi_thermal *tz = thermal->devdata;
	int i;
	int i;
@@ -1022,27 +655,35 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal,
		return -EINVAL;
		return -EINVAL;


	if (tz->trips.critical.flags.valid) {
	if (tz->trips.critical.flags.valid) {
		if (!trip)
		if (!trip) {
			return sprintf(buf, "critical\n");
			*type = THERMAL_TRIP_CRITICAL;
			return 0;
		}
		trip--;
		trip--;
	}
	}


	if (tz->trips.hot.flags.valid) {
	if (tz->trips.hot.flags.valid) {
		if (!trip)
		if (!trip) {
			return sprintf(buf, "hot\n");
			*type = THERMAL_TRIP_HOT;
			return 0;
		}
		trip--;
		trip--;
	}
	}


	if (tz->trips.passive.flags.valid) {
	if (tz->trips.passive.flags.valid) {
		if (!trip)
		if (!trip) {
			return sprintf(buf, "passive\n");
			*type = THERMAL_TRIP_PASSIVE;
			return 0;
		}
		trip--;
		trip--;
	}
	}


	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
		tz->trips.active[i].flags.valid; i++) {
		tz->trips.active[i].flags.valid; i++) {
		if (!trip)
		if (!trip) {
			return sprintf(buf, "active%d\n", i);
			*type = THERMAL_TRIP_ACTIVE;
			return 0;
		}
		trip--;
		trip--;
	}
	}


@@ -1050,7 +691,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal,
}
}


static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
				 int trip, char *buf)
				 int trip, unsigned long *temp)
{
{
	struct acpi_thermal *tz = thermal->devdata;
	struct acpi_thermal *tz = thermal->devdata;
	int i;
	int i;
@@ -1059,31 +700,39 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
		return -EINVAL;
		return -EINVAL;


	if (tz->trips.critical.flags.valid) {
	if (tz->trips.critical.flags.valid) {
		if (!trip)
		if (!trip) {
			return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
			*temp = KELVIN_TO_MILLICELSIUS(
				tz->trips.critical.temperature));
				tz->trips.critical.temperature);
			return 0;
		}
		trip--;
		trip--;
	}
	}


	if (tz->trips.hot.flags.valid) {
	if (tz->trips.hot.flags.valid) {
		if (!trip)
		if (!trip) {
			return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
			*temp = KELVIN_TO_MILLICELSIUS(
					tz->trips.hot.temperature));
				tz->trips.hot.temperature);
			return 0;
		}
		trip--;
		trip--;
	}
	}


	if (tz->trips.passive.flags.valid) {
	if (tz->trips.passive.flags.valid) {
		if (!trip)
		if (!trip) {
			return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
			*temp = KELVIN_TO_MILLICELSIUS(
					tz->trips.passive.temperature));
				tz->trips.passive.temperature);
			return 0;
		}
		trip--;
		trip--;
	}
	}


	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
		tz->trips.active[i].flags.valid; i++) {
		tz->trips.active[i].flags.valid; i++) {
		if (!trip)
		if (!trip) {
			return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
			*temp = KELVIN_TO_MILLICELSIUS(
					tz->trips.active[i].temperature));
				tz->trips.active[i].temperature);
			return 0;
		}
		trip--;
		trip--;
	}
	}


@@ -1102,6 +751,29 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
		return -EINVAL;
		return -EINVAL;
}
}


static int thermal_notify(struct thermal_zone_device *thermal, int trip,
			   enum thermal_trip_type trip_type)
{
	u8 type = 0;
	struct acpi_thermal *tz = thermal->devdata;

	if (trip_type == THERMAL_TRIP_CRITICAL)
		type = ACPI_THERMAL_NOTIFY_CRITICAL;
	else if (trip_type == THERMAL_TRIP_HOT)
		type = ACPI_THERMAL_NOTIFY_HOT;
	else
		return 0;

	acpi_bus_generate_proc_event(tz->device, type, 1);
	acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
					dev_name(&tz->device->dev), type, 1);

	if (trip_type == THERMAL_TRIP_CRITICAL && nocrt)
		return 1;

	return 0;
}

typedef int (*cb)(struct thermal_zone_device *, int,
typedef int (*cb)(struct thermal_zone_device *, int,
		  struct thermal_cooling_device *);
		  struct thermal_cooling_device *);
static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
@@ -1194,6 +866,7 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
	.get_trip_type = thermal_get_trip_type,
	.get_trip_type = thermal_get_trip_type,
	.get_trip_temp = thermal_get_trip_temp,
	.get_trip_temp = thermal_get_trip_temp,
	.get_crit_temp = thermal_get_crit_temp,
	.get_crit_temp = thermal_get_crit_temp,
	.notify = thermal_notify,
};
};


static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
@@ -1214,8 +887,21 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)


	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
			tz->trips.active[i].flags.valid; i++, trips++);
			tz->trips.active[i].flags.valid; i++, trips++);
	tz->thermal_zone = thermal_zone_device_register("acpitz",

					trips, tz, &acpi_thermal_zone_ops);
	if (tz->trips.passive.flags.valid)
		tz->thermal_zone =
			thermal_zone_device_register("acpitz", trips, tz,
						     &acpi_thermal_zone_ops,
						     tz->trips.passive.tc1,
						     tz->trips.passive.tc2,
						     tz->trips.passive.tsp*100,
						     tz->polling_frequency*100);
	else
		tz->thermal_zone =
			thermal_zone_device_register("acpitz", trips, tz,
						     &acpi_thermal_zone_ops,
						     0, 0, 0,
						     tz->polling_frequency);
	if (IS_ERR(tz->thermal_zone))
	if (IS_ERR(tz->thermal_zone))
		return -ENODEV;
		return -ENODEV;


@@ -1447,13 +1133,13 @@ static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
	if (!tz)
	if (!tz)
		goto end;
		goto end;


	if (!tz->polling_frequency) {
	if (!tz->thermal_zone->polling_delay) {
		seq_puts(seq, "<polling disabled>\n");
		seq_puts(seq, "<polling disabled>\n");
		goto end;
		goto end;
	}
	}


	seq_printf(seq, "polling frequency:       %lu seconds\n",
	seq_printf(seq, "polling frequency:       %d seconds\n",
		   (tz->polling_frequency / 10));
		   (tz->thermal_zone->polling_delay / 1000));


      end:
      end:
	return 0;
	return 0;
@@ -1683,12 +1369,6 @@ static int acpi_thermal_add(struct acpi_device *device)
	if (result)
	if (result)
		goto unregister_thermal_zone;
		goto unregister_thermal_zone;


	init_timer(&tz->timer);

	acpi_thermal_active_off(tz);

	acpi_thermal_check(tz);

	status = acpi_install_notify_handler(device->handle,
	status = acpi_install_notify_handler(device->handle,
					     ACPI_DEVICE_NOTIFY,
					     ACPI_DEVICE_NOTIFY,
					     acpi_thermal_notify, tz);
					     acpi_thermal_notify, tz);
@@ -1717,36 +1397,15 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
	acpi_status status = AE_OK;
	acpi_status status = AE_OK;
	struct acpi_thermal *tz = NULL;
	struct acpi_thermal *tz = NULL;



	if (!device || !acpi_driver_data(device))
	if (!device || !acpi_driver_data(device))
		return -EINVAL;
		return -EINVAL;


	tz = acpi_driver_data(device);
	tz = acpi_driver_data(device);


	/* avoid timer adding new defer task */
	tz->zombie = 1;
	/* wait for running timer (on other CPUs) finish */
	del_timer_sync(&(tz->timer));
	/* synchronize deferred task */
	acpi_os_wait_events_complete(NULL);
	/* deferred task may reinsert timer */
	del_timer_sync(&(tz->timer));

	status = acpi_remove_notify_handler(device->handle,
	status = acpi_remove_notify_handler(device->handle,
					    ACPI_DEVICE_NOTIFY,
					    ACPI_DEVICE_NOTIFY,
					    acpi_thermal_notify);
					    acpi_thermal_notify);


	/* Terminate policy */
	if (tz->trips.passive.flags.valid && tz->trips.passive.flags.enabled) {
		tz->trips.passive.flags.enabled = 0;
		acpi_thermal_passive(tz);
	}
	if (tz->trips.active[0].flags.valid
	    && tz->trips.active[0].flags.enabled) {
		tz->trips.active[0].flags.enabled = 0;
		acpi_thermal_active(tz);
	}

	acpi_thermal_remove_fs(device);
	acpi_thermal_remove_fs(device);
	acpi_thermal_unregister_thermal_zone(tz);
	acpi_thermal_unregister_thermal_zone(tz);
	mutex_destroy(&tz->lock);
	mutex_destroy(&tz->lock);
+13 −9
Original line number Original line Diff line number Diff line
@@ -358,32 +358,36 @@ static struct output_properties acpi_output_properties = {




/* thermal cooling device callbacks */
/* thermal cooling device callbacks */
static int video_get_max_state(struct thermal_cooling_device *cdev, char *buf)
static int video_get_max_state(struct thermal_cooling_device *cdev, unsigned
			       long *state)
{
{
	struct acpi_device *device = cdev->devdata;
	struct acpi_device *device = cdev->devdata;
	struct acpi_video_device *video = acpi_driver_data(device);
	struct acpi_video_device *video = acpi_driver_data(device);


	return sprintf(buf, "%d\n", video->brightness->count - 3);
	*state = video->brightness->count - 3;
	return 0;
}
}


static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
static int video_get_cur_state(struct thermal_cooling_device *cdev, unsigned
			       long *state)
{
{
	struct acpi_device *device = cdev->devdata;
	struct acpi_device *device = cdev->devdata;
	struct acpi_video_device *video = acpi_driver_data(device);
	struct acpi_video_device *video = acpi_driver_data(device);
	unsigned long long level;
	unsigned long long level;
	int state;
	int offset;


	acpi_video_device_lcd_get_level_current(video, &level);
	acpi_video_device_lcd_get_level_current(video, &level);
	for (state = 2; state < video->brightness->count; state++)
	for (offset = 2; offset < video->brightness->count; offset++)
		if (level == video->brightness->levels[state])
		if (level == video->brightness->levels[offset]) {
			return sprintf(buf, "%d\n",
			*state = video->brightness->count - offset - 1;
				       video->brightness->count - state - 1);
			return 0;
		}


	return -EINVAL;
	return -EINVAL;
}
}


static int
static int
video_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state)
video_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
{
{
	struct acpi_device *device = cdev->devdata;
	struct acpi_device *device = cdev->devdata;
	struct acpi_video_device *video = acpi_driver_data(device);
	struct acpi_video_device *video = acpi_driver_data(device);
+10 −19
Original line number Original line Diff line number Diff line
@@ -57,7 +57,7 @@ MODULE_LICENSE("GPL");
 * In that case max_cstate would be n-1
 * In that case max_cstate would be n-1
 * GTHS returning '0' would mean that no bandwidth control states are supported
 * GTHS returning '0' would mean that no bandwidth control states are supported
 */
 */
static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev,
static int memory_get_max_bandwidth(struct thermal_cooling_device *cdev,
				    unsigned long *max_state)
				    unsigned long *max_state)
{
{
	struct acpi_device *device = cdev->devdata;
	struct acpi_device *device = cdev->devdata;
@@ -83,22 +83,12 @@ static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev,
	return 0;
	return 0;
}
}


static int memory_get_max_bandwidth(struct thermal_cooling_device *cdev,
				    char *buf)
{
	unsigned long value;
	if (memory_get_int_max_bandwidth(cdev, &value))
		return -EINVAL;

	return sprintf(buf, "%ld\n", value);
}

static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev,
static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev,
				    char *buf)
				    unsigned long *value)
{
{
	struct acpi_device *device = cdev->devdata;
	struct acpi_device *device = cdev->devdata;
	acpi_handle handle = device->handle;
	acpi_handle handle = device->handle;
	unsigned long long value;
	unsigned long long result;
	struct acpi_object_list arg_list;
	struct acpi_object_list arg_list;
	union acpi_object arg;
	union acpi_object arg;
	acpi_status status = AE_OK;
	acpi_status status = AE_OK;
@@ -108,15 +98,16 @@ static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev,
	arg.type = ACPI_TYPE_INTEGER;
	arg.type = ACPI_TYPE_INTEGER;
	arg.integer.value = MEMORY_ARG_CUR_BANDWIDTH;
	arg.integer.value = MEMORY_ARG_CUR_BANDWIDTH;
	status = acpi_evaluate_integer(handle, MEMORY_GET_BANDWIDTH,
	status = acpi_evaluate_integer(handle, MEMORY_GET_BANDWIDTH,
				       &arg_list, &value);
				       &arg_list, &result);
	if (ACPI_FAILURE(status))
	if (ACPI_FAILURE(status))
		return -EFAULT;
		return -EFAULT;


	return sprintf(buf, "%llu\n", value);
	*value = result;
	return 0;
}
}


static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
				    unsigned int state)
				    unsigned long state)
{
{
	struct acpi_device *device = cdev->devdata;
	struct acpi_device *device = cdev->devdata;
	acpi_handle handle = device->handle;
	acpi_handle handle = device->handle;
@@ -126,7 +117,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
	unsigned long long temp;
	unsigned long long temp;
	unsigned long max_state;
	unsigned long max_state;


	if (memory_get_int_max_bandwidth(cdev, &max_state))
	if (memory_get_max_bandwidth(cdev, &max_state))
		return -EFAULT;
		return -EFAULT;


	if (state > max_state)
	if (state > max_state)
@@ -142,7 +133,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
				  &temp);
				  &temp);


	printk(KERN_INFO
	printk(KERN_INFO
	       "Bandwidth value was %d: status is %d\n", state, status);
	       "Bandwidth value was %ld: status is %d\n", state, status);
	if (ACPI_FAILURE(status))
	if (ACPI_FAILURE(status))
		return -EFAULT;
		return -EFAULT;


Loading