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

@ -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));