Skip to content

Commit

Permalink
Merge branch 'bugfixes' into test
Browse files Browse the repository at this point in the history
  • Loading branch information
lenb committed Oct 23, 2008
2 parents aa58329 + 383d7a1 commit 955ba39
Show file tree
Hide file tree
Showing 9 changed files with 183 additions and 86 deletions.
55 changes: 41 additions & 14 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
53 changes: 43 additions & 10 deletions drivers/acpi/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
-------------------------------------------------------------------------- */
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/acpi/pci_link.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
68 changes: 45 additions & 23 deletions drivers/acpi/power.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -128,45 +136,47 @@ 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;

*state = (sta & 0x01)?ACPI_POWER_RESOURCE_STATE_ON:
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;
}

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;


if (!list || !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;

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down
Loading

0 comments on commit 955ba39

Please sign in to comment.