Merge branch 'bugfixes' into test
This commit is contained in:
commit
955ba39561
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user