static int cpu_has_cpufreq(unsigned int cpu)
{
struct cpufreq_policy policy;
- if (!acpi_thermal_cpufreq_is_init)
- return -ENODEV;
- if (!cpufreq_get_policy(&policy, cpu))
+ if (!acpi_thermal_cpufreq_is_init || cpufreq_get_policy(&policy, cpu))
return -ENODEV;
return 0;
}
if (!cpu_has_cpufreq(cpu))
return -ENODEV;
- if (cpufreq_thermal_reduction_pctg[cpu] >= 20) {
+ if (cpufreq_thermal_reduction_pctg[cpu] > 20)
cpufreq_thermal_reduction_pctg[cpu] -= 20;
- cpufreq_update_policy(cpu);
- return 0;
- }
-
- return -ERANGE;
+ else
+ cpufreq_thermal_reduction_pctg[cpu] = 0;
+ cpufreq_update_policy(cpu);
+ /* We reached max freq again and can leave passive mode */
+ return !cpufreq_thermal_reduction_pctg[cpu];
}
static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
int result = 0;
struct acpi_processor *pr = NULL;
struct acpi_device *device = NULL;
- int tx = 0;
+ int tx = 0, max_tx_px = 0;
ACPI_FUNCTION_TRACE("acpi_processor_set_thermal_limit");
/* if going down: T-states first, P-states later */
if (pr->flags.throttling) {
- if (tx == 0)
+ if (tx == 0) {
+ max_tx_px = 1;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"At minimum throttling state\n"));
- else {
+ } else {
tx--;
goto end;
}
}
result = acpi_thermal_cpufreq_decrease(pr->id);
- if (result == -ERANGE)
+ if (result) {
+ /*
+ * We only could get -ERANGE, 1 or 0.
+ * In the first two cases we reached max freq again.
+ */
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"At minimum performance state\n"));
+ max_tx_px = 1;
+ } else
+ max_tx_px = 0;
break;
}
pr->limit.thermal.px, pr->limit.thermal.tx));
} else
result = 0;
-
- return_VALUE(result);
+ if (max_tx_px)
+ return_VALUE(1);
+ else
+ return_VALUE(result);
}
int acpi_processor_get_limit_info(struct acpi_processor *pr)
#define _COMPONENT ACPI_THERMAL_COMPONENT
ACPI_MODULE_NAME("acpi_thermal")
- MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME);
MODULE_LICENSE("GPL");
return_VALUE(0);
}
-static int acpi_thermal_passive(struct acpi_thermal *tz)
+static void acpi_thermal_passive(struct acpi_thermal *tz)
{
- int result = 0;
+ int result = 1;
struct acpi_thermal_passive *passive = NULL;
int trend = 0;
int i = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_passive");
if (!tz || !tz->trips.passive.flags.valid)
- return_VALUE(-EINVAL);
+ return;
passive = &(tz->trips.passive);
trend, passive->tc1, tz->temperature,
tz->last_temperature, passive->tc2,
tz->temperature, passive->temperature));
- tz->trips.passive.flags.enabled = 1;
+ passive->flags.enabled = 1;
/* Heating up? */
if (trend > 0)
for (i = 0; i < passive->devices.count; i++)
handles[i],
ACPI_PROCESSOR_LIMIT_INCREMENT);
/* Cooling off? */
- else if (trend < 0)
+ else if (trend < 0) {
for (i = 0; i < passive->devices.count; i++)
- acpi_processor_set_thermal_limit(passive->
- devices.
- handles[i],
- ACPI_PROCESSOR_LIMIT_DECREMENT);
+ /*
+ * 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;
}
/*
* and avoid thrashing around the passive trip point. Note that we
* assume symmetry.
*/
- else if (tz->trips.passive.flags.enabled) {
- for (i = 0; i < passive->devices.count; i++)
- result =
- acpi_processor_set_thermal_limit(passive->devices.
- handles[i],
- ACPI_PROCESSOR_LIMIT_DECREMENT);
- if (result == 1) {
- tz->trips.passive.flags.enabled = 0;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Disabling passive cooling (zone is cool)\n"));
- }
+ 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"));
}
-
- return_VALUE(0);
}
-static int acpi_thermal_active(struct acpi_thermal *tz)
+static void acpi_thermal_active(struct acpi_thermal *tz)
{
int result = 0;
struct acpi_thermal_active *active = NULL;
ACPI_FUNCTION_TRACE("acpi_thermal_active");
if (!tz)
- return_VALUE(-EINVAL);
+ return;
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-
active = &(tz->trips.active[i]);
if (!active || !active->flags.valid)
break;
-
- /*
- * Above Threshold?
- * ----------------
- * If not already enabled, turn ON all cooling devices
- * associated with this active threshold.
- */
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) {
- for (j = 0; j < active->devices.count; j++) {
- result =
- acpi_bus_set_power(active->devices.
- handles[j],
- ACPI_STATE_D0);
- if (result) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "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]));
- }
- }
- }
- /*
- * Below Threshold?
- * ----------------
- * Turn OFF all cooling devices associated with this
- * threshold.
- */
- else if (active->flags.enabled) {
+ 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_D3);
+ ACPI_STATE_D0);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Unable to turn cooling device [%p] 'off'\n",
+ "Unable to turn cooling device [%p] 'on'\n",
active->devices.
handles[j]));
continue;
}
- active->flags.enabled = 0;
+ active->flags.enabled = 1;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Cooling device [%p] now 'off'\n",
+ "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) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "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]));
}
}
-
- return_VALUE(0);
}
static void acpi_thermal_check(void *context);
* Again, separated from the above two to allow independent policy
* decisions.
*/
- if (tz->trips.critical.flags.enabled)
- tz->state.critical = 1;
- if (tz->trips.hot.flags.enabled)
- tz->state.hot = 1;
- if (tz->trips.passive.flags.enabled)
- tz->state.passive = 1;
+ 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++)
- if (tz->trips.active[i].flags.enabled)
- tz->state.active = 1;
+ tz->state.active |= tz->trips.active[i].flags.enabled;
/*
* Calculate Sleep Time