Merge branch 'bugfixes' into test

This commit is contained in:
Len Brown 2008-10-22 23:19:50 -04:00
commit 955ba39561
9 changed files with 183 additions and 86 deletions

View File

@ -217,20 +217,47 @@ and is between 256 and 4096 characters. It is defined in the file
acpi.debug_level= [HW,ACPI]
Format: <int>
Each bit of the <int> indicates an ACPI debug level,
1: enable, 0: disable. It is useful for boot time
debugging. After system has booted up, it can be set
via /sys/module/acpi/parameters/debug_level.
CONFIG_ACPI_DEBUG must be enabled for this to produce any output.
Available bits (add the numbers together) to enable different
debug output levels of the ACPI subsystem:
0x01 error 0x02 warn 0x04 init 0x08 debug object
0x10 info 0x20 init names 0x40 parse 0x80 load
0x100 dispatch 0x200 execute 0x400 names 0x800 operation region
0x1000 bfield 0x2000 tables 0x4000 values 0x8000 objects
0x10000 resources 0x20000 user requests 0x40000 package.
The number can be in decimal or prefixed with 0x in hex.
Warning: Many of these options can produce a lot of
output and make your system unusable. Be very careful.
which corresponds to the level in an ACPI_DEBUG_PRINT
statement. After system has booted up, this mask
can be set via /sys/module/acpi/parameters/debug_level.
CONFIG_ACPI_DEBUG must be enabled for this to produce
any output. The number can be in decimal or prefixed
with 0x in hex. Some of these options produce so much
output that the system is unusable.
The following global components are defined by the
ACPI CA:
0x01 error
0x02 warn
0x04 init
0x08 debug object
0x10 info
0x20 init names
0x40 parse
0x80 load
0x100 dispatch
0x200 execute
0x400 names
0x800 operation region
0x1000 bfield
0x2000 tables
0x4000 values
0x8000 objects
0x10000 resources
0x20000 user requests
0x40000 package
The number can be in decimal or prefixed with 0x in hex.
Warning: Many of these options can produce a lot of
output and make your system unusable. Be very careful.
acpi.power_nocheck= [HW,ACPI]
Format: 1/0 enable/disable the check of power state.
On some bogus BIOS the _PSC object/_STA object of
power resource can't return the correct device power
state. In such case it is unneccessary to check its
power state again in power transition.
1 : disable the power state check
acpi_pm_good [X86-32,X86-64]
Override the pmtimer bug detection: force the kernel

View File

@ -48,6 +48,23 @@ EXPORT_SYMBOL(acpi_root_dir);
#define STRUCT_TO_INT(s) (*((int*)&s))
static int set_power_nocheck(const struct dmi_system_id *id)
{
printk(KERN_NOTICE PREFIX "%s detected - "
"disable power check in power transistion\n", id->ident);
acpi_power_nocheck = 1;
return 0;
}
static struct dmi_system_id __cpuinitdata power_nocheck_dmi_table[] = {
{
set_power_nocheck, "HP Pavilion 05", {
DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
DMI_MATCH(DMI_SYS_VENDOR, "HP Pavilion 05"),
DMI_MATCH(DMI_PRODUCT_VERSION, "2001211RE101GLEND") }, NULL},
{},
};
/* --------------------------------------------------------------------------
Device Management
-------------------------------------------------------------------------- */
@ -95,21 +112,21 @@ int acpi_bus_get_status(struct acpi_device *device)
}
/*
* Otherwise we assume the status of our parent (unless we don't
* have one, in which case status is implied).
* According to ACPI spec some device can be present and functional
* even if the parent is not present but functional.
* In such conditions the child device should not inherit the status
* from the parent.
*/
else if (device->parent)
device->status = device->parent->status;
else
STRUCT_TO_INT(device->status) =
ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING;
if (device->status.functional && !device->status.present) {
printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: "
"functional but not present; setting present\n",
device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status));
device->status.present = 1;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: "
"functional but not present;\n",
device->pnp.bus_id,
(u32) STRUCT_TO_INT(device->status)));
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n",
@ -223,7 +240,19 @@ int acpi_bus_set_power(acpi_handle handle, int state)
/*
* Get device's current power state
*/
acpi_bus_get_power(device->handle, &device->power.state);
if (!acpi_power_nocheck) {
/*
* Maybe the incorrect power state is returned on the bogus
* bios, which is different with the real power state.
* For example: the bios returns D0 state and the real power
* state is D3. OS expects to set the device to D0 state. In
* such case if OS uses the power state returned by the BIOS,
* the device can't be transisted to the correct power state.
* So if the acpi_power_nocheck is set, it is unnecessary to
* get the power state by calling acpi_bus_get_power.
*/
acpi_bus_get_power(device->handle, &device->power.state);
}
if ((state == device->power.state) && !device->flags.force_power_state) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
state));
@ -818,7 +847,11 @@ static int __init acpi_init(void)
}
} else
disable_acpi();
/*
* If the laptop falls into the DMI check table, the power state check
* will be disabled in the course of device power transistion.
*/
dmi_check_system(power_nocheck_dmi_table);
return result;
}

View File

@ -709,7 +709,7 @@ int acpi_pci_link_free_irq(acpi_handle handle)
acpi_device_bid(link->device)));
if (link->refcnt == 0) {
acpi_ut_evaluate_object(link->device->handle, "_DIS", 0, NULL);
acpi_evaluate_object(link->device->handle, "_DIS", NULL, NULL);
}
mutex_unlock(&acpi_link_lock);
return (link->irq.active);
@ -773,7 +773,7 @@ static int acpi_pci_link_add(struct acpi_device *device)
end:
/* disable all links -- to be activated on use */
acpi_ut_evaluate_object(device->handle, "_DIS", 0, NULL);
acpi_evaluate_object(device->handle, "_DIS", NULL, NULL);
mutex_unlock(&acpi_link_lock);
if (result)

View File

@ -54,6 +54,14 @@ ACPI_MODULE_NAME("power");
#define ACPI_POWER_RESOURCE_STATE_OFF 0x00
#define ACPI_POWER_RESOURCE_STATE_ON 0x01
#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
#ifdef MODULE_PARAM_PREFIX
#undef MODULE_PARAM_PREFIX
#endif
#define MODULE_PARAM_PREFIX "acpi."
int acpi_power_nocheck;
module_param_named(power_nocheck, acpi_power_nocheck, bool, 000);
static int acpi_power_add(struct acpi_device *device);
static int acpi_power_remove(struct acpi_device *device, int type);
static int acpi_power_resume(struct acpi_device *device);
@ -128,16 +136,16 @@ acpi_power_get_context(acpi_handle handle,
return 0;
}
static int acpi_power_get_state(struct acpi_power_resource *resource, int *state)
static int acpi_power_get_state(acpi_handle handle, int *state)
{
acpi_status status = AE_OK;
unsigned long sta = 0;
if (!resource || !state)
if (!handle || !state)
return -EINVAL;
status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta);
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status))
return -ENODEV;
@ -145,7 +153,7 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state
ACPI_POWER_RESOURCE_STATE_OFF;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
resource->name, state ? "on" : "off"));
acpi_ut_get_node_name(handle), state ? "on" : "off"));
return 0;
}
@ -153,7 +161,6 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state
static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
{
int result = 0, state1;
struct acpi_power_resource *resource = NULL;
u32 i = 0;
@ -161,12 +168,15 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
return -EINVAL;
/* The state of the list is 'on' IFF all resources are 'on'. */
/* */
for (i = 0; i < list->count; i++) {
result = acpi_power_get_context(list->handles[i], &resource);
if (result)
return result;
result = acpi_power_get_state(resource, &state1);
/*
* The state of the power resource can be obtained by
* using the ACPI handle. In such case it is unnecessary to
* get the Power resource first and then get its state again.
*/
result = acpi_power_get_state(list->handles[i], &state1);
if (result)
return result;
@ -226,12 +236,18 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
if (ACPI_FAILURE(status))
return -ENODEV;
result = acpi_power_get_state(resource, &state);
if (result)
return result;
if (state != ACPI_POWER_RESOURCE_STATE_ON)
return -ENOEXEC;
if (!acpi_power_nocheck) {
/*
* If acpi_power_nocheck is set, it is unnecessary to check
* the power state after power transition.
*/
result = acpi_power_get_state(resource->device->handle,
&state);
if (result)
return result;
if (state != ACPI_POWER_RESOURCE_STATE_ON)
return -ENOEXEC;
}
/* Update the power resource's _device_ power state */
resource->device->power.state = ACPI_STATE_D0;
@ -277,11 +293,17 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
if (ACPI_FAILURE(status))
return -ENODEV;
result = acpi_power_get_state(resource, &state);
if (result)
return result;
if (state != ACPI_POWER_RESOURCE_STATE_OFF)
return -ENOEXEC;
if (!acpi_power_nocheck) {
/*
* If acpi_power_nocheck is set, it is unnecessary to check
* the power state after power transition.
*/
result = acpi_power_get_state(handle, &state);
if (result)
return result;
if (state != ACPI_POWER_RESOURCE_STATE_OFF)
return -ENOEXEC;
}
/* Update the power resource's _device_ power state */
resource->device->power.state = ACPI_STATE_D3;
@ -555,7 +577,7 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
if (!resource)
goto end;
result = acpi_power_get_state(resource, &state);
result = acpi_power_get_state(resource->device->handle, &state);
if (result)
goto end;
@ -668,7 +690,7 @@ static int acpi_power_add(struct acpi_device *device)
resource->system_level = acpi_object.power_resource.system_level;
resource->order = acpi_object.power_resource.resource_order;
result = acpi_power_get_state(resource, &state);
result = acpi_power_get_state(device->handle, &state);
if (result)
goto end;
@ -735,7 +757,7 @@ static int acpi_power_resume(struct acpi_device *device)
resource = (struct acpi_power_resource *)acpi_driver_data(device);
result = acpi_power_get_state(resource, &state);
result = acpi_power_get_state(device->handle, &state);
if (result)
return result;

View File

@ -276,6 +276,13 @@ int acpi_match_device_ids(struct acpi_device *device,
{
const struct acpi_device_id *id;
/*
* If the device is not present, it is unnecessary to load device
* driver for it.
*/
if (!device->status.present)
return -ENODEV;
if (device->flags.hardware_id) {
for (id = ids; id->id[0]; id++) {
if (!strcmp((char*)id->id, device->pnp.hardware_id))
@ -807,6 +814,7 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
/* TBD: System wake support and resource requirements. */
device->power.state = ACPI_STATE_UNKNOWN;
acpi_bus_get_power(device->handle, &(device->power.state));
return 0;
}
@ -1152,20 +1160,6 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
return 0;
}
static int
acpi_is_child_device(struct acpi_device *device,
int (*matcher)(struct acpi_device *))
{
int result = -ENODEV;
do {
if (ACPI_SUCCESS(matcher(device)))
return AE_OK;
} while ((device = device->parent));
return result;
}
static int
acpi_add_single_object(struct acpi_device **child,
struct acpi_device *parent, acpi_handle handle, int type,
@ -1221,15 +1215,18 @@ acpi_add_single_object(struct acpi_device **child,
result = -ENODEV;
goto end;
}
if (!device->status.present) {
/* Bay and dock should be handled even if absent */
if (!ACPI_SUCCESS(
acpi_is_child_device(device, acpi_bay_match)) &&
!ACPI_SUCCESS(
acpi_is_child_device(device, acpi_dock_match))) {
result = -ENODEV;
goto end;
}
/*
* When the device is neither present nor functional, the
* device should not be added to Linux ACPI device tree.
* When the status of the device is not present but functinal,
* it should be added to Linux ACPI tree. For example : bay
* device , dock device.
* In such conditions it is unncessary to check whether it is
* bay device or dock device.
*/
if (!device->status.present && !device->status.functional) {
result = -ENODEV;
goto end;
}
break;
default:
@ -1251,6 +1248,16 @@ acpi_add_single_object(struct acpi_device **child,
*/
acpi_device_set_id(device, parent, handle, type);
/*
* The ACPI device is attached to acpi handle before getting
* the power/wakeup/peformance flags. Otherwise OS can't get
* the corresponding ACPI device by the acpi handle in the course
* of getting the power/wakeup/performance flags.
*/
result = acpi_device_set_context(device, type);
if (result)
goto end;
/*
* Power Management
* ----------------
@ -1281,8 +1288,6 @@ acpi_add_single_object(struct acpi_device **child,
goto end;
}
if ((result = acpi_device_set_context(device, type)))
goto end;
result = acpi_device_register(device, parent);
@ -1402,7 +1407,12 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops)
* TBD: Need notifications and other detection mechanisms
* in place before we can fully implement this.
*/
if (child->status.present) {
/*
* When the device is not present but functional, it is also
* necessary to scan the children of this device.
*/
if (child->status.present || (!child->status.present &&
child->status.functional)) {
status = acpi_get_next_object(ACPI_TYPE_ANY, chandle,
NULL, NULL);
if (ACPI_SUCCESS(status)) {

View File

@ -271,7 +271,7 @@ u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
char method[4] = "WM";
if (!find_guid(guid_string, &wblock))
return AE_BAD_ADDRESS;
return AE_ERROR;
block = &wblock->gblock;
handle = wblock->handle;
@ -333,7 +333,7 @@ struct acpi_buffer *out)
return AE_BAD_PARAMETER;
if (!find_guid(guid_string, &wblock))
return AE_BAD_ADDRESS;
return AE_ERROR;
block = &wblock->gblock;
handle = wblock->handle;
@ -343,7 +343,7 @@ struct acpi_buffer *out)
/* Check GUID is a data block */
if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
return AE_BAD_ADDRESS;
return AE_ERROR;
input.count = 1;
input.pointer = wq_params;
@ -414,7 +414,7 @@ const struct acpi_buffer *in)
return AE_BAD_DATA;
if (!find_guid(guid_string, &wblock))
return AE_BAD_ADDRESS;
return AE_ERROR;
block = &wblock->gblock;
handle = wblock->handle;
@ -424,7 +424,7 @@ const struct acpi_buffer *in)
/* Check GUID is a data block */
if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
return AE_BAD_ADDRESS;
return AE_ERROR;
input.count = 2;
input.pointer = params;

View File

@ -473,7 +473,7 @@ struct wmi_interface *iface)
}
break;
default:
return AE_BAD_ADDRESS;
return AE_ERROR;
}
return AE_OK;
}
@ -511,7 +511,7 @@ static acpi_status AMW0_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
break;
}
default:
return AE_BAD_ADDRESS;
return AE_ERROR;
}
/* Actually do the set */
@ -686,7 +686,7 @@ struct wmi_interface *iface)
return 0;
}
default:
return AE_BAD_ADDRESS;
return AE_ERROR;
}
status = WMI_execute_u32(method_id, 0, &result);
@ -732,7 +732,7 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
}
break;
default:
return AE_BAD_ADDRESS;
return AE_ERROR;
}
return WMI_execute_u32(method_id, (u32)value, NULL);
}
@ -782,7 +782,7 @@ static struct wmi_interface wmid_interface = {
static acpi_status get_u32(u32 *value, u32 cap)
{
acpi_status status = AE_BAD_ADDRESS;
acpi_status status = AE_ERROR;
switch (interface->type) {
case ACER_AMW0:

View File

@ -148,9 +148,13 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
acpi_status status;
struct pnp_dev *dev;
/*
* If a PnPacpi device is not present , the device
* driver should not be loaded.
*/
status = acpi_get_handle(device->handle, "_CRS", &temp);
if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) ||
is_exclusive_device(device))
is_exclusive_device(device) || (!device->status.present))
return 0;
dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device));

View File

@ -93,6 +93,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state);
int acpi_disable_wakeup_device_power(struct acpi_device *dev);
int acpi_power_get_inferred_state(struct acpi_device *device);
int acpi_power_transition(struct acpi_device *device, int state);
extern int acpi_power_nocheck;
#endif
/* --------------------------------------------------------------------------