Commit 00c1bd54 authored by Linus Torvalds's avatar Linus Torvalds
parents 5666c094 220ec706
...@@ -638,6 +638,13 @@ static int __init acpi_parse_fadt(unsigned long phys, unsigned long size) ...@@ -638,6 +638,13 @@ static int __init acpi_parse_fadt(unsigned long phys, unsigned long size)
return 0; return 0;
pmtmr_ioport = fadt->xpm_tmr_blk.address; pmtmr_ioport = fadt->xpm_tmr_blk.address;
/*
* "X" fields are optional extensions to the original V1.0
* fields, so we must selectively expand V1.0 fields if the
* corresponding X field is zero.
*/
if (!pmtmr_ioport)
pmtmr_ioport = fadt->V1_pm_tmr_blk;
} else { } else {
/* FADT rev. 1 */ /* FADT rev. 1 */
pmtmr_ioport = fadt->V1_pm_tmr_blk; pmtmr_ioport = fadt->V1_pm_tmr_blk;
......
...@@ -197,7 +197,6 @@ config ACPI_ASUS ...@@ -197,7 +197,6 @@ config ACPI_ASUS
config ACPI_IBM config ACPI_IBM
tristate "IBM ThinkPad Laptop Extras" tristate "IBM ThinkPad Laptop Extras"
depends on X86 depends on X86
default y
---help--- ---help---
This is a Linux ACPI driver for the IBM ThinkPad laptops. It adds This is a Linux ACPI driver for the IBM ThinkPad laptops. It adds
support for Fn-Fx key combinations, Bluetooth control, video support for Fn-Fx key combinations, Bluetooth control, video
......
...@@ -16,7 +16,7 @@ EXTRA_CFLAGS += $(ACPI_CFLAGS) ...@@ -16,7 +16,7 @@ EXTRA_CFLAGS += $(ACPI_CFLAGS)
# ACPI Boot-Time Table Parsing # ACPI Boot-Time Table Parsing
# #
obj-y += tables.o obj-y += tables.o
obj-y += blacklist.o obj-$(CONFIG_X86) += blacklist.o
# #
# ACPI Core Subsystem (Interpreter) # ACPI Core Subsystem (Interpreter)
......
...@@ -543,6 +543,8 @@ static int acpi_processor_get_info(struct acpi_processor *pr) ...@@ -543,6 +543,8 @@ static int acpi_processor_get_info(struct acpi_processor *pr)
return_VALUE(0); return_VALUE(0);
} }
static void *processor_device_array[NR_CPUS];
static int acpi_processor_start(struct acpi_device *device) static int acpi_processor_start(struct acpi_device *device)
{ {
int result = 0; int result = 0;
...@@ -561,6 +563,19 @@ static int acpi_processor_start(struct acpi_device *device) ...@@ -561,6 +563,19 @@ static int acpi_processor_start(struct acpi_device *device)
BUG_ON((pr->id >= NR_CPUS) || (pr->id < 0)); BUG_ON((pr->id >= NR_CPUS) || (pr->id < 0));
/*
* Buggy BIOS check
* ACPI id of processors can be reported wrongly by the BIOS.
* Don't trust it blindly
*/
if (processor_device_array[pr->id] != NULL &&
processor_device_array[pr->id] != (void *)device) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "BIOS reporting wrong ACPI id"
"for the processor\n"));
return_VALUE(-ENODEV);
}
processor_device_array[pr->id] = (void *)device;
processors[pr->id] = pr; processors[pr->id] = pr;
result = acpi_processor_add_fs(device); result = acpi_processor_add_fs(device);
......
...@@ -280,6 +280,16 @@ static void acpi_processor_idle(void) ...@@ -280,6 +280,16 @@ static void acpi_processor_idle(void)
cx->usage++; cx->usage++;
#ifdef CONFIG_HOTPLUG_CPU
/*
* Check for P_LVL2_UP flag before entering C2 and above on
* an SMP system. We do it here instead of doing it at _CST/P_LVL
* detection phase, to work cleanly with logical CPU hotplug.
*/
if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
!pr->flags.has_cst && acpi_fadt.plvl2_up)
cx->type = ACPI_STATE_C1;
#endif
/* /*
* Sleep: * Sleep:
* ------ * ------
...@@ -534,6 +544,15 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) ...@@ -534,6 +544,15 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
pr->power.states[ACPI_STATE_C0].valid = 1; pr->power.states[ACPI_STATE_C0].valid = 1;
pr->power.states[ACPI_STATE_C1].valid = 1; pr->power.states[ACPI_STATE_C1].valid = 1;
#ifndef CONFIG_HOTPLUG_CPU
/*
* Check for P_LVL2_UP flag before entering C2 and above on
* an SMP system.
*/
if ((num_online_cpus() > 1) && acpi_fadt.plvl2_up)
return_VALUE(-ENODEV);
#endif
/* determine C2 and C3 address from pblk */ /* determine C2 and C3 address from pblk */
pr->power.states[ACPI_STATE_C2].address = pr->pblk + 4; pr->power.states[ACPI_STATE_C2].address = pr->pblk + 4;
pr->power.states[ACPI_STATE_C3].address = pr->pblk + 5; pr->power.states[ACPI_STATE_C3].address = pr->pblk + 5;
...@@ -690,7 +709,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) ...@@ -690,7 +709,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
/* Validate number of power states discovered */ /* Validate number of power states discovered */
if (pr->power.count < 2) if (pr->power.count < 2)
status = -ENODEV; status = -EFAULT;
end: end:
acpi_os_free(buffer.pointer); acpi_os_free(buffer.pointer);
...@@ -841,11 +860,11 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr) ...@@ -841,11 +860,11 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr)
* this function */ * this function */
result = acpi_processor_get_power_info_cst(pr); result = acpi_processor_get_power_info_cst(pr);
if ((result) || (acpi_processor_power_verify(pr) < 2)) { if (result == -ENODEV)
result = acpi_processor_get_power_info_fadt(pr); result = acpi_processor_get_power_info_fadt(pr);
if ((result) || (acpi_processor_power_verify(pr) < 2))
result = acpi_processor_get_power_info_default_c1(pr); if ((result) || (acpi_processor_power_verify(pr) < 2))
} result = acpi_processor_get_power_info_default_c1(pr);
/* /*
* Set Default Policy * Set Default Policy
......
...@@ -101,9 +101,7 @@ static unsigned int acpi_thermal_cpufreq_is_init = 0; ...@@ -101,9 +101,7 @@ static unsigned int acpi_thermal_cpufreq_is_init = 0;
static int cpu_has_cpufreq(unsigned int cpu) static int cpu_has_cpufreq(unsigned int cpu)
{ {
struct cpufreq_policy policy; struct cpufreq_policy policy;
if (!acpi_thermal_cpufreq_is_init) if (!acpi_thermal_cpufreq_is_init || cpufreq_get_policy(&policy, cpu))
return -ENODEV;
if (!cpufreq_get_policy(&policy, cpu))
return -ENODEV; return -ENODEV;
return 0; return 0;
} }
...@@ -127,13 +125,13 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu) ...@@ -127,13 +125,13 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
if (!cpu_has_cpufreq(cpu)) if (!cpu_has_cpufreq(cpu))
return -ENODEV; return -ENODEV;
if (cpufreq_thermal_reduction_pctg[cpu] >= 20) { if (cpufreq_thermal_reduction_pctg[cpu] > 20)
cpufreq_thermal_reduction_pctg[cpu] -= 20; cpufreq_thermal_reduction_pctg[cpu] -= 20;
cpufreq_update_policy(cpu); else
return 0; cpufreq_thermal_reduction_pctg[cpu] = 0;
} cpufreq_update_policy(cpu);
/* We reached max freq again and can leave passive mode */
return -ERANGE; return !cpufreq_thermal_reduction_pctg[cpu];
} }
static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
...@@ -200,7 +198,7 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type) ...@@ -200,7 +198,7 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type)
int result = 0; int result = 0;
struct acpi_processor *pr = NULL; struct acpi_processor *pr = NULL;
struct acpi_device *device = NULL; struct acpi_device *device = NULL;
int tx = 0; int tx = 0, max_tx_px = 0;
ACPI_FUNCTION_TRACE("acpi_processor_set_thermal_limit"); ACPI_FUNCTION_TRACE("acpi_processor_set_thermal_limit");
...@@ -259,19 +257,27 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type) ...@@ -259,19 +257,27 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type)
/* if going down: T-states first, P-states later */ /* if going down: T-states first, P-states later */
if (pr->flags.throttling) { if (pr->flags.throttling) {
if (tx == 0) if (tx == 0) {
max_tx_px = 1;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"At minimum throttling state\n")); "At minimum throttling state\n"));
else { } else {
tx--; tx--;
goto end; goto end;
} }
} }
result = acpi_thermal_cpufreq_decrease(pr->id); 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, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"At minimum performance state\n")); "At minimum performance state\n"));
max_tx_px = 1;
} else
max_tx_px = 0;
break; break;
} }
...@@ -290,8 +296,10 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type) ...@@ -290,8 +296,10 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type)
pr->limit.thermal.px, pr->limit.thermal.tx)); pr->limit.thermal.px, pr->limit.thermal.tx));
} else } else
result = 0; result = 0;
if (max_tx_px)
return_VALUE(result); return_VALUE(1);
else
return_VALUE(result);
} }
int acpi_processor_get_limit_info(struct acpi_processor *pr) int acpi_processor_get_limit_info(struct acpi_processor *pr)
......
...@@ -1110,7 +1110,7 @@ acpi_add_single_object(struct acpi_device **child, ...@@ -1110,7 +1110,7 @@ acpi_add_single_object(struct acpi_device **child,
* *
* TBD: Assumes LDM provides driver hot-plug capability. * TBD: Assumes LDM provides driver hot-plug capability.
*/ */
result = acpi_bus_find_driver(device); acpi_bus_find_driver(device);
end: end:
if (!result) if (!result)
......
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
#define _COMPONENT ACPI_THERMAL_COMPONENT #define _COMPONENT ACPI_THERMAL_COMPONENT
ACPI_MODULE_NAME("acpi_thermal") ACPI_MODULE_NAME("acpi_thermal")
MODULE_AUTHOR("Paul Diefenbaugh"); MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME); MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -517,9 +517,9 @@ static int acpi_thermal_hot(struct acpi_thermal *tz) ...@@ -517,9 +517,9 @@ static int acpi_thermal_hot(struct acpi_thermal *tz)
return_VALUE(0); 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; struct acpi_thermal_passive *passive = NULL;
int trend = 0; int trend = 0;
int i = 0; int i = 0;
...@@ -527,7 +527,7 @@ static int acpi_thermal_passive(struct acpi_thermal *tz) ...@@ -527,7 +527,7 @@ static int acpi_thermal_passive(struct acpi_thermal *tz)
ACPI_FUNCTION_TRACE("acpi_thermal_passive"); ACPI_FUNCTION_TRACE("acpi_thermal_passive");
if (!tz || !tz->trips.passive.flags.valid) if (!tz || !tz->trips.passive.flags.valid)
return_VALUE(-EINVAL); return;
passive = &(tz->trips.passive); passive = &(tz->trips.passive);
...@@ -547,7 +547,7 @@ static int acpi_thermal_passive(struct acpi_thermal *tz) ...@@ -547,7 +547,7 @@ static int acpi_thermal_passive(struct acpi_thermal *tz)
trend, passive->tc1, tz->temperature, trend, passive->tc1, tz->temperature,
tz->last_temperature, passive->tc2, tz->last_temperature, passive->tc2,
tz->temperature, passive->temperature)); tz->temperature, passive->temperature));
tz->trips.passive.flags.enabled = 1; passive->flags.enabled = 1;
/* Heating up? */ /* Heating up? */
if (trend > 0) if (trend > 0)
for (i = 0; i < passive->devices.count; i++) for (i = 0; i < passive->devices.count; i++)
...@@ -556,12 +556,32 @@ static int acpi_thermal_passive(struct acpi_thermal *tz) ...@@ -556,12 +556,32 @@ static int acpi_thermal_passive(struct acpi_thermal *tz)
handles[i], handles[i],
ACPI_PROCESSOR_LIMIT_INCREMENT); ACPI_PROCESSOR_LIMIT_INCREMENT);
/* Cooling off? */ /* Cooling off? */
else if (trend < 0) else if (trend < 0) {
for (i = 0; i < passive->devices.count; i++) for (i = 0; i < passive->devices.count; i++)
acpi_processor_set_thermal_limit(passive-> /*
devices. * assume that we are on highest
handles[i], * freq/lowest thrott and can leave
ACPI_PROCESSOR_LIMIT_DECREMENT); * 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;
} }
/* /*
...@@ -571,23 +591,21 @@ static int acpi_thermal_passive(struct acpi_thermal *tz) ...@@ -571,23 +591,21 @@ static int acpi_thermal_passive(struct acpi_thermal *tz)
* and avoid thrashing around the passive trip point. Note that we * and avoid thrashing around the passive trip point. Note that we
* assume symmetry. * assume symmetry.
*/ */
else if (tz->trips.passive.flags.enabled) { if (!passive->flags.enabled)
for (i = 0; i < passive->devices.count; i++) return;
result = for (i = 0; i < passive->devices.count; i++)
acpi_processor_set_thermal_limit(passive->devices. if (!acpi_processor_set_thermal_limit
handles[i], (passive->devices.handles[i],
ACPI_PROCESSOR_LIMIT_DECREMENT); ACPI_PROCESSOR_LIMIT_DECREMENT))
if (result == 1) { result = 0;
tz->trips.passive.flags.enabled = 0; if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, passive->flags.enabled = 0;
"Disabling passive cooling (zone is cool)\n")); 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; int result = 0;
struct acpi_thermal_active *active = NULL; struct acpi_thermal_active *active = NULL;
...@@ -598,74 +616,66 @@ static int acpi_thermal_active(struct acpi_thermal *tz) ...@@ -598,74 +616,66 @@ static int acpi_thermal_active(struct acpi_thermal *tz)
ACPI_FUNCTION_TRACE("acpi_thermal_active"); ACPI_FUNCTION_TRACE("acpi_thermal_active");
if (!tz) if (!tz)
return_VALUE(-EINVAL); return;
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
active = &(tz->trips.active[i]); active = &(tz->trips.active[i]);
if (!active || !active->flags.valid) if (!active || !active->flags.valid)
break; break;
/*
* Above Threshold?
* ----------------
* If not already enabled, turn ON all cooling devices
* associated with this active threshold.
*/
if (tz->temperature >= active->temperature) { 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) if (active->temperature > maxtemp)
tz->state.active_index = i, maxtemp = tz->state.active_index = i;
active->temperature; maxtemp = active->temperature;
if (!active->flags.enabled) { if (active->flags.enabled)
for (j = 0; j < active->devices.count; j++) { continue;
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) {
for (j = 0; j < active->devices.count; j++) { for (j = 0; j < active->devices.count; j++) {
result = result =
acpi_bus_set_power(active->devices. acpi_bus_set_power(active->devices.
handles[j], handles[j],
ACPI_STATE_D3); ACPI_STATE_D0);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Unable to turn cooling device [%p] 'off'\n", "Unable to turn cooling device [%p] 'on'\n",
active->devices. active->devices.
handles[j])); handles[j]));
continue; continue;
} }
active->flags.enabled = 0; active->flags.enabled = 1;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Cooling device [%p] now 'off'\n", "Cooling device [%p] now 'on'\n",
active->devices.handles[j])); 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); static void acpi_thermal_check(void *context);
...@@ -744,15 +754,12 @@ static void acpi_thermal_check(void *data) ...@@ -744,15 +754,12 @@ static void acpi_thermal_check(void *data)
* Again, separated from the above two to allow independent policy * Again, separated from the above two to allow independent policy
* decisions. * decisions.
*/ */
if (tz->trips.critical.flags.enabled) tz->state.critical = tz->trips.critical.flags.enabled;
tz->state.critical = 1; tz->state.hot = tz->trips.hot.flags.enabled;
if (tz->trips.hot.flags.enabled) tz->state.passive = tz->trips.passive.flags.enabled;
tz->state.hot = 1; tz->state.active = 0;
if (tz->trips.passive.flags.enabled)
tz->state.passive = 1;
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
if (tz->trips.active[i].flags.enabled) tz->state.active |= tz->trips.active[i].flags.enabled;
tz->state.active = 1;
/* /*
* Calculate Sleep Time * Calculate Sleep Time
......
...@@ -812,7 +812,7 @@ acpi_video_device_write_brightness(struct file *file, ...@@ -812,7 +812,7 @@ acpi_video_device_write_brightness(struct file *file,
ACPI_FUNCTION_TRACE("acpi_video_device_write_brightness"); ACPI_FUNCTION_TRACE("acpi_video_device_write_brightness");
if (!dev || count + 1 > sizeof str) if (!dev || !dev->brightness || count + 1 > sizeof str)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
if (copy_from_user(str, buffer, count)) if (copy_from_user(str, buffer, count))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment