Commit bb721a7a authored by Andy Grover's avatar Andy Grover Committed by Andy Grover

ACPI driver updates

Better IRQ routing
ACPI 2.0-enumerated processor perf state support
ACPI poweroff via magic sysrq
parent 7a47fa52
...@@ -9,7 +9,7 @@ export ACPI_CFLAGS ...@@ -9,7 +9,7 @@ export ACPI_CFLAGS
ACPI_CFLAGS := -D_LINUX -I$(CURDIR)/include ACPI_CFLAGS := -D_LINUX -I$(CURDIR)/include
ifdef CONFIG_ACPI_DEBUG ifdef CONFIG_ACPI_DEBUG
ACPI_CFLAGS += -DACPI_DEBUG -Wno-unused ACPI_CFLAGS += -DACPI_DEBUG
endif endif
EXTRA_CFLAGS += $(ACPI_CFLAGS) EXTRA_CFLAGS += $(ACPI_CFLAGS)
......
/* /*
* acpi_ac.c - ACPI AC Adapter Driver ($Revision: 22 $) * acpi_ac.c - ACPI AC Adapter Driver ($Revision: 23 $)
* *
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
...@@ -296,6 +296,7 @@ acpi_ac_remove ( ...@@ -296,6 +296,7 @@ acpi_ac_remove (
struct acpi_ac *ac = NULL; struct acpi_ac *ac = NULL;
ACPI_FUNCTION_TRACE("acpi_ac_remove"); ACPI_FUNCTION_TRACE("acpi_ac_remove");
if (!device || !acpi_driver_data(device)) if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
......
/* /*
* acpi_battery.c - ACPI Battery Driver ($Revision: 31 $) * acpi_battery.c - ACPI Battery Driver ($Revision: 32 $)
* *
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
...@@ -112,8 +112,9 @@ acpi_battery_get_info ( ...@@ -112,8 +112,9 @@ acpi_battery_get_info (
struct acpi_battery *battery, struct acpi_battery *battery,
struct acpi_battery_info **bif) struct acpi_battery_info **bif)
{ {
int result = 0;
acpi_status status = 0; acpi_status status = 0;
acpi_buffer buffer = {0, NULL}; acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BIF), acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BIF),
ACPI_BATTERY_FORMAT_BIF}; ACPI_BATTERY_FORMAT_BIF};
acpi_buffer data = {0, NULL}; acpi_buffer data = {0, NULL};
...@@ -126,9 +127,11 @@ acpi_battery_get_info ( ...@@ -126,9 +127,11 @@ acpi_battery_get_info (
/* Evalute _BIF */ /* Evalute _BIF */
status = acpi_evaluate(battery->handle, "_BIF", NULL, &buffer); status = acpi_evaluate_object(battery->handle, "_BIF", NULL, &buffer);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BIF\n"));
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
}
package = (acpi_object *) buffer.pointer; package = (acpi_object *) buffer.pointer;
...@@ -136,29 +139,33 @@ acpi_battery_get_info ( ...@@ -136,29 +139,33 @@ acpi_battery_get_info (
status = acpi_extract_package(package, &format, &data); status = acpi_extract_package(package, &format, &data);
if (status != AE_BUFFER_OVERFLOW) { if (status != AE_BUFFER_OVERFLOW) {
kfree(buffer.pointer); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n"));
return_VALUE(-ENODEV); result = -ENODEV;
goto end;
} }
data.pointer = kmalloc(data.length, GFP_KERNEL); data.pointer = kmalloc(data.length, GFP_KERNEL);
if (!data.pointer) { if (!data.pointer) {
kfree(buffer.pointer); result = -ENOMEM;
return_VALUE(-ENOMEM); goto end;
} }
memset(data.pointer, 0, data.length); memset(data.pointer, 0, data.length);
status = acpi_extract_package(package, &format, &data); status = acpi_extract_package(package, &format, &data);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
kfree(buffer.pointer); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n"));
kfree(data.pointer); kfree(data.pointer);
return_VALUE(-ENODEV); result = -ENODEV;
goto end;
} }
end:
kfree(buffer.pointer); kfree(buffer.pointer);
(*bif) = data.pointer; if (0 == result)
(*bif) = (struct acpi_battery_info *) data.pointer;
return_VALUE(0); return_VALUE(result);
} }
static int static int
...@@ -166,8 +173,9 @@ acpi_battery_get_status ( ...@@ -166,8 +173,9 @@ acpi_battery_get_status (
struct acpi_battery *battery, struct acpi_battery *battery,
struct acpi_battery_status **bst) struct acpi_battery_status **bst)
{ {
int result = 0;
acpi_status status = 0; acpi_status status = 0;
acpi_buffer buffer = {0, NULL}; acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BST), acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BST),
ACPI_BATTERY_FORMAT_BST}; ACPI_BATTERY_FORMAT_BST};
acpi_buffer data = {0, NULL}; acpi_buffer data = {0, NULL};
...@@ -180,9 +188,11 @@ acpi_battery_get_status ( ...@@ -180,9 +188,11 @@ acpi_battery_get_status (
/* Evalute _BST */ /* Evalute _BST */
status = acpi_evaluate(battery->handle, "_BST", NULL, &buffer); status = acpi_evaluate_object(battery->handle, "_BST", NULL, &buffer);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BST\n"));
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
}
package = (acpi_object *) buffer.pointer; package = (acpi_object *) buffer.pointer;
...@@ -190,29 +200,33 @@ acpi_battery_get_status ( ...@@ -190,29 +200,33 @@ acpi_battery_get_status (
status = acpi_extract_package(package, &format, &data); status = acpi_extract_package(package, &format, &data);
if (status != AE_BUFFER_OVERFLOW) { if (status != AE_BUFFER_OVERFLOW) {
kfree(buffer.pointer); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n"));
return_VALUE(-ENODEV); result = -ENODEV;
goto end;
} }
data.pointer = kmalloc(data.length, GFP_KERNEL); data.pointer = kmalloc(data.length, GFP_KERNEL);
if (!data.pointer) { if (!data.pointer) {
kfree(buffer.pointer); result = -ENOMEM;
return_VALUE(-ENOMEM); goto end;
} }
memset(data.pointer, 0, data.length); memset(data.pointer, 0, data.length);
status = acpi_extract_package(package, &format, &data); status = acpi_extract_package(package, &format, &data);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
kfree(buffer.pointer); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n"));
kfree(data.pointer); kfree(data.pointer);
return_VALUE(-ENODEV); result = -ENODEV;
goto end;
} }
end:
kfree(buffer.pointer); kfree(buffer.pointer);
(*bst) = data.pointer; if (0 == result)
(*bst) = (struct acpi_battery_status *) data.pointer;
return_VALUE(0); return_VALUE(result);
} }
...@@ -328,7 +342,7 @@ acpi_battery_read_info ( ...@@ -328,7 +342,7 @@ acpi_battery_read_info (
{ {
int result = 0; int result = 0;
struct acpi_battery *battery = (struct acpi_battery *) data; struct acpi_battery *battery = (struct acpi_battery *) data;
struct acpi_battery_info *bif = 0; struct acpi_battery_info *bif = NULL;
char *units = "?"; char *units = "?";
char *p = page; char *p = page;
int len = 0; int len = 0;
...@@ -403,8 +417,7 @@ acpi_battery_read_info ( ...@@ -403,8 +417,7 @@ acpi_battery_read_info (
bif->oem_info); bif->oem_info);
end: end:
if (bif) kfree(bif);
kfree(bif);
len = (p - page); len = (p - page);
if (len <= off+count) *eof = 1; if (len <= off+count) *eof = 1;
...@@ -490,8 +503,7 @@ acpi_battery_read_state ( ...@@ -490,8 +503,7 @@ acpi_battery_read_state (
(u32) bst->present_voltage); (u32) bst->present_voltage);
end: end:
if (bst) kfree(bst);
kfree(bst);
len = (p - page); len = (p - page);
if (len <= off+count) *eof = 1; if (len <= off+count) *eof = 1;
......
/* /*
* acpi_bus.c - ACPI Bus Driver ($Revision: 56 $) * acpi_bus.c - ACPI Bus Driver ($Revision: 66 $)
* *
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
* *
...@@ -77,6 +77,8 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata = ...@@ -77,6 +77,8 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata =
{"SONY ", "U0 ", 0x20010313, ACPI_TABLE_DSDT, less_than_or_equal, "ACPI driver problem", 1}, {"SONY ", "U0 ", 0x20010313, ACPI_TABLE_DSDT, less_than_or_equal, "ACPI driver problem", 1},
/* Compaq Presario 800, Insyde BIOS */ /* Compaq Presario 800, Insyde BIOS */
{"INT440", "SYSFexxx", 0x00001001, ACPI_TABLE_DSDT, less_than_or_equal, "Does not use _REG to protect EC OpRegions", 1}, {"INT440", "SYSFexxx", 0x00001001, ACPI_TABLE_DSDT, less_than_or_equal, "Does not use _REG to protect EC OpRegions", 1},
/* IBM 600E - _ADR should return 7, but it returns 1 */
{"IBM ", "TP600E ", 0x00000105, ACPI_TABLE_DSDT, less_than_or_equal, "Incorrect _ADR", 1},
{""} {""}
}; };
...@@ -266,34 +268,6 @@ acpi_bus_data_handler ( ...@@ -266,34 +268,6 @@ acpi_bus_data_handler (
} }
static void
acpi_bus_data_handler_powerf (
acpi_handle handle,
u32 function,
void *context)
{
ACPI_FUNCTION_TRACE("acpi_bus_data_handler_powerf");
/* TBD */
return_VOID;
}
static void
acpi_bus_data_handler_sleepf (
acpi_handle handle,
u32 function,
void *context)
{
ACPI_FUNCTION_TRACE("acpi_bus_data_handler_sleepf");
/* TBD */
return_VOID;
}
int int
acpi_bus_get_device ( acpi_bus_get_device (
acpi_handle handle, acpi_handle handle,
...@@ -1044,8 +1018,10 @@ acpi_bus_match ( ...@@ -1044,8 +1018,10 @@ acpi_bus_match (
if (!device || !driver) if (!device || !driver)
return -EINVAL; return -EINVAL;
if (0 != strstr(driver->ids, device->pnp.hardware_id)) if (device->flags.hardware_id) {
return 0; if (0 != strstr(driver->ids, device->pnp.hardware_id))
return 0;
}
if (device->flags.compatible_ids) { if (device->flags.compatible_ids) {
acpi_status status = AE_OK; acpi_status status = AE_OK;
...@@ -1055,8 +1031,8 @@ acpi_bus_match ( ...@@ -1055,8 +1031,8 @@ acpi_bus_match (
memset(cid, 0, sizeof(cid)); memset(cid, 0, sizeof(cid));
status = acpi_evaluate_object(device->handle, "_CID", status = acpi_evaluate_object(device->handle, "_CID", NULL,
NULL, &buffer); &buffer);
if (ACPI_FAILURE(status) || !buffer.pointer) if (ACPI_FAILURE(status) || !buffer.pointer)
return -ENOENT; return -ENOENT;
...@@ -1072,10 +1048,11 @@ acpi_bus_match ( ...@@ -1072,10 +1048,11 @@ acpi_bus_match (
break; break;
case ACPI_TYPE_PACKAGE: case ACPI_TYPE_PACKAGE:
/* TBD: Support CID packages */ /* TBD: Support CID packages */
default:
return -ENOENT;
} }
if (!cid[0])
return -ENOENT;
if (0 != strstr(cid, device->pnp.hardware_id)) if (0 != strstr(cid, device->pnp.hardware_id))
return 0; return 0;
} }
...@@ -1144,13 +1121,13 @@ acpi_bus_driver_init ( ...@@ -1144,13 +1121,13 @@ acpi_bus_driver_init (
/** /**
* acpi_bus_bind * acpi_bus_attach
* ------------- * -------------
* Callback for acpi_bus_walk() used to find devices that match a specific * Callback for acpi_bus_walk() used to find devices that match a specific
* driver's criteria and bind the driver to the device. * driver's criteria and then attach the driver.
*/ */
static int static int
acpi_bus_bind ( acpi_bus_attach (
struct acpi_device *device, struct acpi_device *device,
int level, int level,
void *data) void *data)
...@@ -1158,7 +1135,7 @@ acpi_bus_bind ( ...@@ -1158,7 +1135,7 @@ acpi_bus_bind (
int result = 0; int result = 0;
struct acpi_driver *driver = NULL; struct acpi_driver *driver = NULL;
ACPI_FUNCTION_TRACE("acpi_bus_bind"); ACPI_FUNCTION_TRACE("acpi_bus_attach");
if (!device || !data) if (!device || !data)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
...@@ -1191,13 +1168,13 @@ acpi_bus_bind ( ...@@ -1191,13 +1168,13 @@ acpi_bus_bind (
/** /**
* acpi_bus_unbind * acpi_bus_unattach
* --------------- * -----------------
* Callback for acpi_bus_walk() used to find devices that match a specific * Callback for acpi_bus_walk() used to find devices that match a specific
* driver's criteria and unbind the driver from the device. * driver's criteria and unattach the driver.
*/ */
static int static int
acpi_bus_unbind ( acpi_bus_unattach (
struct acpi_device *device, struct acpi_device *device,
int level, int level,
void *data) void *data)
...@@ -1205,7 +1182,7 @@ acpi_bus_unbind ( ...@@ -1205,7 +1182,7 @@ acpi_bus_unbind (
int result = 0; int result = 0;
struct acpi_driver *driver = (struct acpi_driver *) data; struct acpi_driver *driver = (struct acpi_driver *) data;
ACPI_FUNCTION_TRACE("acpi_bus_unbind"); ACPI_FUNCTION_TRACE("acpi_bus_unattach");
if (!device || !driver) if (!device || !driver)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
...@@ -1291,7 +1268,7 @@ acpi_bus_register_driver ( ...@@ -1291,7 +1268,7 @@ acpi_bus_register_driver (
list_add_tail(&driver->node, &acpi_bus_drivers); list_add_tail(&driver->node, &acpi_bus_drivers);
up(&acpi_bus_drivers_lock); up(&acpi_bus_drivers_lock);
acpi_bus_walk(acpi_root, acpi_bus_bind, acpi_bus_walk(acpi_root, acpi_bus_attach,
WALK_DOWN, driver); WALK_DOWN, driver);
return_VALUE(driver->references); return_VALUE(driver->references);
...@@ -1313,7 +1290,7 @@ acpi_bus_unregister_driver ( ...@@ -1313,7 +1290,7 @@ acpi_bus_unregister_driver (
if (!driver) if (!driver)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
acpi_bus_walk(acpi_root, acpi_bus_unbind, WALK_UP, driver); acpi_bus_walk(acpi_root, acpi_bus_unattach, WALK_UP, driver);
if (driver->references) if (driver->references)
return_VALUE(driver->references); return_VALUE(driver->references);
...@@ -1395,8 +1372,8 @@ acpi_bus_add ( ...@@ -1395,8 +1372,8 @@ acpi_bus_add (
char bus_id[5] = {'?',0}; char bus_id[5] = {'?',0};
acpi_buffer buffer = {sizeof(bus_id), bus_id}; acpi_buffer buffer = {sizeof(bus_id), bus_id};
acpi_device_info info; acpi_device_info info;
char *hid = "?"; char *hid = NULL;
char *uid = "0"; char *uid = NULL;
int i = 0; int i = 0;
ACPI_FUNCTION_TRACE("acpi_bus_add"); ACPI_FUNCTION_TRACE("acpi_bus_add");
...@@ -1414,6 +1391,37 @@ acpi_bus_add ( ...@@ -1414,6 +1391,37 @@ acpi_bus_add (
device->handle = handle; device->handle = handle;
device->parent = parent; device->parent = parent;
memset(&info, 0, sizeof(acpi_device_info));
/*
* Bus ID
* ------
* The device's Bus ID is simply the object name.
* TBD: Shouldn't this value be unique (within the ACPI namespace)?
*/
switch (type) {
case ACPI_BUS_TYPE_SYSTEM:
sprintf(device->pnp.bus_id, "%s", "ACPI");
break;
case ACPI_BUS_TYPE_POWER_BUTTON:
sprintf(device->pnp.bus_id, "%s", "PWRF");
break;
case ACPI_BUS_TYPE_SLEEP_BUTTON:
sprintf(device->pnp.bus_id, "%s", "SLPF");
break;
default:
acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
/* Clean up trailing underscores (if any) */
for (i = 3; i > 1; i--) {
if (bus_id[i] == '_')
bus_id[i] = '\0';
else
break;
}
sprintf(device->pnp.bus_id, "%s", bus_id);
break;
}
/* /*
* Flags * Flags
* ----- * -----
...@@ -1456,35 +1464,6 @@ acpi_bus_add ( ...@@ -1456,35 +1464,6 @@ acpi_bus_add (
* TBD: Synch with Core's enumeration/initialization process. * TBD: Synch with Core's enumeration/initialization process.
*/ */
/*
* Bus ID
* ------
* The device's Bus ID is simply the object name.
* TBD: Shouldn't this value be unique (within the ACPI namespace)?
*/
switch (type) {
case ACPI_BUS_TYPE_SYSTEM:
sprintf(device->pnp.bus_id, "%s", "ACPI");
break;
case ACPI_BUS_TYPE_POWER_BUTTON:
sprintf(device->pnp.bus_id, "%s", "PWRF");
break;
case ACPI_BUS_TYPE_SLEEP_BUTTON:
sprintf(device->pnp.bus_id, "%s", "SLPF");
break;
default:
acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
/* Clean up trailing underscores (if any) */
for (i = 3; i > 1; i--) {
if (bus_id[i] == '_')
bus_id[i] = '\0';
else
break;
}
sprintf(device->pnp.bus_id, "%s", bus_id);
break;
}
/* /*
* Hardware ID, Unique ID, & Bus Address * Hardware ID, Unique ID, & Bus Address
* ------------------------------------- * -------------------------------------
...@@ -1505,8 +1484,10 @@ acpi_bus_add ( ...@@ -1505,8 +1484,10 @@ acpi_bus_add (
hid = info.hardware_id; hid = info.hardware_id;
if (info.valid & ACPI_VALID_UID) if (info.valid & ACPI_VALID_UID)
uid = info.unique_id; uid = info.unique_id;
if (info.valid & ACPI_VALID_ADR) if (info.valid & ACPI_VALID_ADR) {
device->pnp.bus_address = info.address; device->pnp.bus_address = info.address;
device->flags.bus_address = 1;
}
break; break;
case ACPI_BUS_TYPE_POWER: case ACPI_BUS_TYPE_POWER:
hid = ACPI_POWER_HID; hid = ACPI_POWER_HID;
...@@ -1528,8 +1509,25 @@ acpi_bus_add ( ...@@ -1528,8 +1509,25 @@ acpi_bus_add (
break; break;
} }
sprintf(device->pnp.hardware_id, "%s", hid); /*
sprintf(device->pnp.unique_id, "%s", uid); * \_SB
* ----
* Fix for the system root bus device -- the only root-level device.
*/
if ((parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) {
hid = ACPI_BUS_HID;
sprintf(device->pnp.device_name, "%s", ACPI_BUS_DEVICE_NAME);
sprintf(device->pnp.device_class, "%s", ACPI_BUS_CLASS);
}
if (hid) {
sprintf(device->pnp.hardware_id, "%s", hid);
device->flags.hardware_id = 1;
}
if (uid) {
sprintf(device->pnp.unique_id, "%s", uid);
device->flags.unique_id = 1;
}
/* /*
* Power Management * Power Management
...@@ -1555,18 +1553,13 @@ acpi_bus_add ( ...@@ -1555,18 +1553,13 @@ acpi_bus_add (
* Context * Context
* ------- * -------
* Attach this 'struct acpi_device' to the ACPI object. This makes * Attach this 'struct acpi_device' to the ACPI object. This makes
* resolutions from handle->device very efficient. Note that since we * resolutions from handle->device very efficient. Note that we need
* attach multiple context to the root object (system device plus all * to be careful with fixed-feature devices as they all attach to the
* fixed-feature devices) we must use alternate handlers. * root object.
*/ */
switch (type) { switch (type) {
case ACPI_BUS_TYPE_POWER_BUTTON: case ACPI_BUS_TYPE_POWER_BUTTON:
status = acpi_attach_data(device->handle,
acpi_bus_data_handler_powerf, device);
break;
case ACPI_BUS_TYPE_SLEEP_BUTTON: case ACPI_BUS_TYPE_SLEEP_BUTTON:
status = acpi_attach_data(device->handle,
acpi_bus_data_handler_sleepf, device);
break; break;
default: default:
status = acpi_attach_data(device->handle, status = acpi_attach_data(device->handle,
...@@ -1591,21 +1584,9 @@ acpi_bus_add ( ...@@ -1591,21 +1584,9 @@ acpi_bus_add (
else else
list_add_tail(&device->node, &device->parent->children); list_add_tail(&device->node, &device->parent->children);
/*
* \_SB
* ----
* Fix for the system root bus device -- the only root-level device.
*/
if ((type == ACPI_BUS_TYPE_DEVICE) && (parent == ACPI_ROOT_OBJECT)) {
sprintf(device->pnp.hardware_id, "%s", ACPI_BUS_HID);
sprintf(device->pnp.device_name, "%s", ACPI_BUS_DEVICE_NAME);
sprintf(device->pnp.device_class, "%s", ACPI_BUS_CLASS);
}
#ifdef CONFIG_ACPI_DEBUG #ifdef CONFIG_ACPI_DEBUG
{ {
char *type_string = NULL; char *type_string = NULL;
char *message = NULL;
char name[80] = {'?','\0'}; char name[80] = {'?','\0'};
acpi_buffer buffer = {sizeof(name), name}; acpi_buffer buffer = {sizeof(name), name};
...@@ -1640,7 +1621,7 @@ acpi_bus_add ( ...@@ -1640,7 +1621,7 @@ acpi_bus_add (
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s %s [%p]\n", ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s %s [%p]\n",
type_string, name, handle)); type_string, name, handle));
} }
#endif #endif /*CONFIG_ACPI_DEBUG*/
/* /*
* Global Device Hierarchy: * Global Device Hierarchy:
...@@ -1650,14 +1631,30 @@ acpi_bus_add ( ...@@ -1650,14 +1631,30 @@ acpi_bus_add (
acpi_device_register(device, parent); acpi_device_register(device, parent);
/* /*
* Find Driver * Bind _ADR-Based Devices
* ----------- * -----------------------
* Check to see if there's a driver installed for this kind of device. * If there's a a bus address (_ADR) then we utilize the parent's
* 'bind' function (if exists) to bind the ACPI- and natively-
* enumerated device representations.
*/ */
acpi_bus_find_driver(device); if (device->flags.bus_address) {
if (device->parent && device->parent->ops.bind)
device->parent->ops.bind(device);
}
end: /*
* Locate & Attach Driver
* ----------------------
* If there's a hardware id (_HID) or compatible ids (_CID) we check
* to see if there's a driver installed for this kind of device. Note
* that drivers can install before or after a device in enumerated.
*
* TBD: Assumes LDM provides driver hot-plug capability.
*/
if (device->flags.hardware_id || device->flags.compatible_ids)
acpi_bus_find_driver(device);
end:
if (0 != result) { if (0 != result) {
kfree(device); kfree(device);
return_VALUE(result); return_VALUE(result);
...@@ -1774,13 +1771,11 @@ acpi_bus_scan ( ...@@ -1774,13 +1771,11 @@ acpi_bus_scan (
* If the device is present, enabled, and functioning then * If the device is present, enabled, and functioning then
* parse its scope (depth-first). Note that we need to * parse its scope (depth-first). Note that we need to
* represent absent devices to facilitate PnP notifications * represent absent devices to facilitate PnP notifications
* -- but we only the subtree head (not all of its children, * -- but only the subtree head (not all of its children,
* which will be enumerated when the parent is inserted). * which will be enumerated when the parent is inserted).
* *
* TBD: Need notifications and other detection mechanisms * TBD: Need notifications and other detection mechanisms
* in place before we can fully implement this. * in place before we can fully implement this.
*
* if (STRUCT_TO_INT(child->status) & 0x0B) {
*/ */
if (child->status.present) { if (child->status.present) {
status = acpi_get_next_object(ACPI_TYPE_ANY, chandle, status = acpi_get_next_object(ACPI_TYPE_ANY, chandle,
...@@ -1883,6 +1878,55 @@ acpi_blacklisted(void) ...@@ -1883,6 +1878,55 @@ acpi_blacklisted(void)
} }
static int __init
acpi_bus_init_irq (void)
{
int result = 0;
acpi_status status = AE_OK;
acpi_object arg = {ACPI_TYPE_INTEGER};
acpi_object_list arg_list = {1, &arg};
int irq_model = 0;
char *message = NULL;
ACPI_FUNCTION_TRACE("acpi_bus_init_irq");
/*
* Let the system know what interrupt model we are using by
* evaluating the \_PIC object, if exists.
*/
result = acpi_get_interrupt_model(&irq_model);
if (0 != result)
return_VALUE(result);
switch (irq_model) {
case ACPI_INT_MODEL_PIC:
message = "PIC";
break;
case ACPI_INT_MODEL_IOAPIC:
message = "IOAPIC";
break;
case ACPI_INT_MODEL_IOSAPIC:
message = "IOSAPIC";
break;
default:
message = "UNKNOWN";
break;
}
printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message);
arg.integer.value = irq_model;
status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL);
if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PIC\n"));
return_VALUE(-ENODEV);
}
return_VALUE(0);
}
static int __init static int __init
acpi_bus_init (void) acpi_bus_init (void)
{ {
...@@ -1928,7 +1972,7 @@ acpi_bus_init (void) ...@@ -1928,7 +1972,7 @@ acpi_bus_init (void)
progress++; progress++;
/* /*
* [2] Get a separate copy of the FADT for use by other drivers. * [3] Get a separate copy of the FADT for use by other drivers.
*/ */
status = acpi_get_table(ACPI_TABLE_FADT, 1, &buffer); status = acpi_get_table(ACPI_TABLE_FADT, 1, &buffer);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
...@@ -1940,7 +1984,7 @@ acpi_bus_init (void) ...@@ -1940,7 +1984,7 @@ acpi_bus_init (void)
progress++; progress++;
/* /*
* [3] Enable the ACPI Core Subsystem. * [4] Enable the ACPI Core Subsystem.
*/ */
status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION); status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
...@@ -1954,7 +1998,14 @@ acpi_bus_init (void) ...@@ -1954,7 +1998,14 @@ acpi_bus_init (void)
progress++; progress++;
/* /*
* [4] Register for all standard device notifications. * [5] Register for all standard device notifications.
*/
result = acpi_bus_init_irq();
if (0 != result)
goto end;
/*
* [6] Register for all standard device notifications.
*/ */
status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, &acpi_bus_notify, NULL); status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, &acpi_bus_notify, NULL);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
...@@ -1966,7 +2017,7 @@ acpi_bus_init (void) ...@@ -1966,7 +2017,7 @@ acpi_bus_init (void)
progress++; progress++;
/* /*
* [5] Create the root device. * [7] Create the root device.
*/ */
result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT, result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT,
ACPI_BUS_TYPE_SYSTEM); ACPI_BUS_TYPE_SYSTEM);
...@@ -1976,7 +2027,7 @@ acpi_bus_init (void) ...@@ -1976,7 +2027,7 @@ acpi_bus_init (void)
progress++; progress++;
/* /*
* [6] Create the root file system. * [8] Create the root file system.
*/ */
acpi_device_dir(acpi_root) = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL); acpi_device_dir(acpi_root) = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL);
if (!acpi_root) { if (!acpi_root) {
...@@ -1988,7 +2039,7 @@ acpi_bus_init (void) ...@@ -1988,7 +2039,7 @@ acpi_bus_init (void)
progress++; progress++;
/* /*
* [7] Install drivers required for proper enumeration of the * [9] Install drivers required for proper enumeration of the
* ACPI namespace. * ACPI namespace.
*/ */
acpi_system_init(); /* ACPI System */ acpi_system_init(); /* ACPI System */
...@@ -2003,7 +2054,7 @@ acpi_bus_init (void) ...@@ -2003,7 +2054,7 @@ acpi_bus_init (void)
progress++; progress++;
/* /*
* [8] Enumerate devices in the ACPI namespace. * [10] Enumerate devices in the ACPI namespace.
*/ */
result = acpi_bus_scan_fixed(acpi_root); result = acpi_bus_scan_fixed(acpi_root);
...@@ -2017,11 +2068,12 @@ acpi_bus_init (void) ...@@ -2017,11 +2068,12 @@ acpi_bus_init (void)
end: end:
if (0 != result) { if (0 != result) {
switch (progress) { switch (progress) {
case 9: case 10:
case 8: remove_proc_entry("ACPI", NULL); case 9: remove_proc_entry("ACPI", NULL);
case 7: acpi_bus_remove(acpi_root, ACPI_BUS_REMOVAL_NORMAL); case 8: acpi_bus_remove(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
case 6: acpi_remove_notify_handler(ACPI_ROOT_OBJECT, case 7: acpi_remove_notify_handler(ACPI_ROOT_OBJECT,
ACPI_SYSTEM_NOTIFY, &acpi_bus_notify); ACPI_SYSTEM_NOTIFY, &acpi_bus_notify);
case 6:
case 5: case 5:
case 4: case 4:
case 3: case 3:
...@@ -2085,6 +2137,9 @@ acpi_init (void) ...@@ -2085,6 +2137,9 @@ acpi_init (void)
printk(KERN_INFO PREFIX "Core Subsystem revision %08x\n", printk(KERN_INFO PREFIX "Core Subsystem revision %08x\n",
ACPI_CA_VERSION); ACPI_CA_VERSION);
/* Initial core debug level excludes drivers, so include them now */
acpi_set_debug(ACPI_DEBUG_LOW);
if (acpi_disabled) { if (acpi_disabled) {
printk(KERN_INFO PREFIX "Disabled via command line (acpi=off)\n"); printk(KERN_INFO PREFIX "Disabled via command line (acpi=off)\n");
return -ENODEV; return -ENODEV;
...@@ -2143,3 +2198,4 @@ subsys_initcall(acpi_init); ...@@ -2143,3 +2198,4 @@ subsys_initcall(acpi_init);
#endif #endif
__setup("acpi=", acpi_setup); __setup("acpi=", acpi_setup);
/* /*
* acpi_bus.h - ACPI Bus Driver ($Revision: 17 $) * acpi_bus.h - ACPI Bus Driver ($Revision: 19 $)
* *
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
...@@ -96,8 +96,9 @@ typedef int (*acpi_op_stop) (struct acpi_device *device, int type); ...@@ -96,8 +96,9 @@ typedef int (*acpi_op_stop) (struct acpi_device *device, int type);
typedef int (*acpi_op_suspend) (struct acpi_device *device, int state); typedef int (*acpi_op_suspend) (struct acpi_device *device, int state);
typedef int (*acpi_op_resume) (struct acpi_device *device, int state); typedef int (*acpi_op_resume) (struct acpi_device *device, int state);
typedef int (*acpi_op_scan) (struct acpi_device *device); typedef int (*acpi_op_scan) (struct acpi_device *device);
typedef int (*acpi_op_bind) (struct acpi_device *device);
struct acpi_driver_ops { struct acpi_device_ops {
acpi_op_add add; acpi_op_add add;
acpi_op_remove remove; acpi_op_remove remove;
acpi_op_lock lock; acpi_op_lock lock;
...@@ -106,6 +107,7 @@ struct acpi_driver_ops { ...@@ -106,6 +107,7 @@ struct acpi_driver_ops {
acpi_op_suspend suspend; acpi_op_suspend suspend;
acpi_op_resume resume; acpi_op_resume resume;
acpi_op_scan scan; acpi_op_scan scan;
acpi_op_bind bind;
}; };
struct acpi_driver { struct acpi_driver {
...@@ -114,7 +116,7 @@ struct acpi_driver { ...@@ -114,7 +116,7 @@ struct acpi_driver {
char class[80]; char class[80];
int references; int references;
char *ids; /* Supported Hardware IDs */ char *ids; /* Supported Hardware IDs */
struct acpi_driver_ops ops; struct acpi_device_ops ops;
}; };
enum acpi_blacklist_predicates enum acpi_blacklist_predicates
...@@ -157,14 +159,18 @@ struct acpi_device_status { ...@@ -157,14 +159,18 @@ struct acpi_device_status {
/* Flags */ /* Flags */
struct acpi_device_flags { struct acpi_device_flags {
u8 dynamic_status:1; u32 dynamic_status:1;
u8 compatible_ids:1; u32 hardware_id:1;
u8 removable:1; u32 compatible_ids:1;
u8 ejectable:1; u32 bus_address:1;
u8 lockable:1; u32 unique_id:1;
u8 suprise_removal_ok:1; u32 removable:1;
u8 power_manageable:1; u32 ejectable:1;
u8 performance_manageable:1; u32 lockable:1;
u32 suprise_removal_ok:1;
u32 power_manageable:1;
u32 performance_manageable:1;
u32 reserved:21;
}; };
...@@ -206,13 +212,13 @@ struct acpi_device_pnp { ...@@ -206,13 +212,13 @@ struct acpi_device_pnp {
/* Power Management */ /* Power Management */
struct acpi_device_power_flags { struct acpi_device_power_flags {
u8 explicit_get:1; /* _PSC present? */ u32 explicit_get:1; /* _PSC present? */
u8 power_resources:1; /* Power resources */ u32 power_resources:1; /* Power resources */
u8 inrush_current:1; /* Serialize Dx->D0 */ u32 inrush_current:1; /* Serialize Dx->D0 */
u8 wake_capable:1; /* Wakeup supported? */ u32 wake_capable:1; /* Wakeup supported? */
u8 wake_enabled:1; /* Enabled for wakeup */ u32 wake_enabled:1; /* Enabled for wakeup */
u8 power_removed:1; /* Optimize Dx->D0 */ u32 power_removed:1; /* Optimize Dx->D0 */
u8 reserved:2; u32 reserved:26;
}; };
struct acpi_device_power_state { struct acpi_device_power_state {
...@@ -270,6 +276,7 @@ struct acpi_device { ...@@ -270,6 +276,7 @@ struct acpi_device {
struct acpi_device_power power; struct acpi_device_power power;
struct acpi_device_perf performance; struct acpi_device_perf performance;
struct acpi_device_dir dir; struct acpi_device_dir dir;
struct acpi_device_ops ops;
struct acpi_driver *driver; struct acpi_driver *driver;
void *driver_data; void *driver_data;
#ifdef CONFIG_LDM #ifdef CONFIG_LDM
......
/* /*
* acpi_button.c - ACPI Button Driver ($Revision: 22 $) * acpi_button.c - ACPI Button Driver ($Revision: 24 $)
* *
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
...@@ -69,7 +69,7 @@ struct acpi_button { ...@@ -69,7 +69,7 @@ struct acpi_button {
#include <linux/compatmac.h> #include <linux/compatmac.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
struct proc_dir_entry *acpi_button_dir = NULL; static struct proc_dir_entry *acpi_button_dir = NULL;
static int static int
...@@ -81,7 +81,6 @@ acpi_button_read_info ( ...@@ -81,7 +81,6 @@ acpi_button_read_info (
int *eof, int *eof,
void *data) void *data)
{ {
int result = 0;
struct acpi_button *button = (struct acpi_button *) data; struct acpi_button *button = (struct acpi_button *) data;
char *p = page; char *p = page;
int len = 0; int len = 0;
...@@ -111,22 +110,42 @@ acpi_button_add_fs ( ...@@ -111,22 +110,42 @@ acpi_button_add_fs (
struct acpi_device *device) struct acpi_device *device)
{ {
struct proc_dir_entry *entry = NULL; struct proc_dir_entry *entry = NULL;
struct acpi_button *button = NULL;
ACPI_FUNCTION_TRACE("acpi_button_add_fs"); ACPI_FUNCTION_TRACE("acpi_button_add_fs");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
button = acpi_driver_data(device);
if (!acpi_button_dir) { if (!acpi_button_dir) {
acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
if (!acpi_button_dir) if (!acpi_button_dir)
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
} }
if (!acpi_device_dir(device)) { switch (button->type) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), case ACPI_BUTTON_TYPE_POWER:
case ACPI_BUTTON_TYPE_POWERF:
entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER,
acpi_button_dir); acpi_button_dir);
if (!acpi_device_dir(device)) break;
return_VALUE(-ENODEV); case ACPI_BUTTON_TYPE_SLEEP:
case ACPI_BUTTON_TYPE_SLEEPF:
entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP,
acpi_button_dir);
break;
case ACPI_BUTTON_TYPE_LID:
entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID,
acpi_button_dir);
break;
} }
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
/* 'info' [R] */ /* 'info' [R] */
entry = create_proc_entry(ACPI_BUTTON_FILE_INFO, entry = create_proc_entry(ACPI_BUTTON_FILE_INFO,
S_IRUGO, acpi_device_dir(device)); S_IRUGO, acpi_device_dir(device));
...@@ -227,37 +246,46 @@ acpi_button_add ( ...@@ -227,37 +246,46 @@ acpi_button_add (
button->device = device; button->device = device;
button->handle = device->handle; button->handle = device->handle;
sprintf(acpi_device_class(device), "%s", ACPI_BUTTON_CLASS);
acpi_driver_data(device) = button; acpi_driver_data(device) = button;
/* /*
* Determine the button type (via hid), as fixed-feature buttons * Determine the button type (via hid), as fixed-feature buttons
* need to be handled a bit differently than generic-space. * need to be handled a bit differently than generic-space.
*/ */
if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) { if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWER)) {
button->type = ACPI_BUTTON_TYPE_POWERF;
sprintf(acpi_device_name(device), "%s",
ACPI_BUTTON_DEVICE_NAME_POWERF);
}
else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) {
button->type = ACPI_BUTTON_TYPE_SLEEPF;
sprintf(acpi_device_name(device), "%s",
ACPI_BUTTON_DEVICE_NAME_SLEEPF);
}
else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWER)) {
button->type = ACPI_BUTTON_TYPE_POWER; button->type = ACPI_BUTTON_TYPE_POWER;
sprintf(acpi_device_name(device), "%s", sprintf(acpi_device_name(device), "%s",
ACPI_BUTTON_DEVICE_NAME_POWER); ACPI_BUTTON_DEVICE_NAME_POWER);
sprintf(acpi_device_class(device), "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
}
else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) {
button->type = ACPI_BUTTON_TYPE_POWERF;
sprintf(acpi_device_name(device), "%s",
ACPI_BUTTON_DEVICE_NAME_POWERF);
sprintf(acpi_device_class(device), "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
} }
else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEP)) { else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEP)) {
button->type = ACPI_BUTTON_TYPE_SLEEP; button->type = ACPI_BUTTON_TYPE_SLEEP;
sprintf(acpi_device_name(device), "%s", sprintf(acpi_device_name(device), "%s",
ACPI_BUTTON_DEVICE_NAME_SLEEP); ACPI_BUTTON_DEVICE_NAME_SLEEP);
sprintf(acpi_device_class(device), "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
}
else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) {
button->type = ACPI_BUTTON_TYPE_SLEEPF;
sprintf(acpi_device_name(device), "%s",
ACPI_BUTTON_DEVICE_NAME_SLEEPF);
sprintf(acpi_device_class(device), "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
} }
else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_LID)) { else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_LID)) {
button->type = ACPI_BUTTON_TYPE_LID; button->type = ACPI_BUTTON_TYPE_LID;
sprintf(acpi_device_name(device), "%s", sprintf(acpi_device_name(device), "%s",
ACPI_BUTTON_DEVICE_NAME_LID); ACPI_BUTTON_DEVICE_NAME_LID);
sprintf(acpi_device_class(device), "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
} }
else { else {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unsupported hid [%s]\n", ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unsupported hid [%s]\n",
......
/* /*
* acpi_drivers.h ($Revision: 17 $) * acpi_drivers.h ($Revision: 23 $)
* *
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include "acpi_bus.h" #include "acpi_bus.h"
#define ACPI_DRIVER_VERSION 0x20020308 #define ACPI_DRIVER_VERSION 0x20020404
#define ACPI_MAX_STRING 80 #define ACPI_MAX_STRING 80
...@@ -84,26 +84,32 @@ ...@@ -84,26 +84,32 @@
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
#define ACPI_BUTTON_COMPONENT 0x00080000 #define ACPI_BUTTON_COMPONENT 0x00080000
#define ACPI_BUTTON_CLASS "button"
#define ACPI_BUTTON_HID_LID "PNP0C0D"
#define ACPI_BUTTON_HID_POWER "PNP0C0C"
#define ACPI_BUTTON_HID_POWERF "ACPI_FPB"
#define ACPI_BUTTON_HID_SLEEP "PNP0C0E"
#define ACPI_BUTTON_HID_SLEEPF "ACPI_FSB"
#define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver" #define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver"
#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button" #define ACPI_BUTTON_CLASS "button"
#define ACPI_BUTTON_DEVICE_NAME_POWERF "Power Button"
#define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button"
#define ACPI_BUTTON_DEVICE_NAME_SLEEPF "Sleep Button"
#define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch"
#define ACPI_BUTTON_FILE_INFO "info" #define ACPI_BUTTON_FILE_INFO "info"
#define ACPI_BUTTON_TYPE_UNKNOWN 0x00 #define ACPI_BUTTON_TYPE_UNKNOWN 0x00
#define ACPI_BUTTON_NOTIFY_STATUS 0x80
#define ACPI_BUTTON_SUBCLASS_POWER "power"
#define ACPI_BUTTON_HID_POWER "PNP0C0C"
#define ACPI_BUTTON_HID_POWERF "ACPI_FPB"
#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button (CM)"
#define ACPI_BUTTON_DEVICE_NAME_POWERF "Power Button (FF)"
#define ACPI_BUTTON_TYPE_POWER 0x01 #define ACPI_BUTTON_TYPE_POWER 0x01
#define ACPI_BUTTON_TYPE_POWERF 0x02 #define ACPI_BUTTON_TYPE_POWERF 0x02
#define ACPI_BUTTON_SUBCLASS_SLEEP "sleep"
#define ACPI_BUTTON_HID_SLEEP "PNP0C0E"
#define ACPI_BUTTON_HID_SLEEPF "ACPI_FSB"
#define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button (CM)"
#define ACPI_BUTTON_DEVICE_NAME_SLEEPF "Sleep Button (FF)"
#define ACPI_BUTTON_TYPE_SLEEP 0x03 #define ACPI_BUTTON_TYPE_SLEEP 0x03
#define ACPI_BUTTON_TYPE_SLEEPF 0x04 #define ACPI_BUTTON_TYPE_SLEEPF 0x04
#define ACPI_BUTTON_SUBCLASS_LID "lid"
#define ACPI_BUTTON_HID_LID "PNP0C0D"
#define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch"
#define ACPI_BUTTON_TYPE_LID 0x05 #define ACPI_BUTTON_TYPE_LID 0x05
#define ACPI_BUTTON_NOTIFY_STATUS 0x80
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
...@@ -217,7 +223,7 @@ void acpi_power_exit (void); ...@@ -217,7 +223,7 @@ void acpi_power_exit (void);
#define ACPI_PROCESSOR_LIMIT_INCREMENT 0x01 #define ACPI_PROCESSOR_LIMIT_INCREMENT 0x01
#define ACPI_PROCESSOR_LIMIT_DECREMENT 0x02 #define ACPI_PROCESSOR_LIMIT_DECREMENT 0x02
int acpi_processor_set_limit(acpi_handle handle, int flags, int *state); int acpi_processor_set_thermal_limit(acpi_handle handle, int type);
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
......
/* /*
* acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 27 $) * acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 28 $)
* *
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
...@@ -345,7 +345,7 @@ acpi_ec_gpe_handler ( ...@@ -345,7 +345,7 @@ acpi_ec_gpe_handler (
if (0 != acpi_ec_query(ec, &value)) if (0 != acpi_ec_query(ec, &value))
return; return;
query_data = kmalloc(sizeof(struct acpi_ec_query_data), GFP_KERNEL); query_data = kmalloc(sizeof(struct acpi_ec_query_data), GFP_ATOMIC);
if (!query_data) if (!query_data)
return; return;
query_data->handle = ec->handle; query_data->handle = ec->handle;
......
/* /*
* acpi_osl.c - OS-dependent functions ($Revision: 65 $) * acpi_osl.c - OS-dependent functions ($Revision: 69 $)
* *
* Copyright (C) 2000 Andrew Henroid * Copyright (C) 2000 Andrew Henroid
* Copyright (C) 2001 Andrew Grover * Copyright (C) 2001 Andrew Grover
...@@ -125,13 +125,13 @@ acpi_os_vprintf(const NATIVE_CHAR *fmt, va_list args) ...@@ -125,13 +125,13 @@ acpi_os_vprintf(const NATIVE_CHAR *fmt, va_list args)
} }
void * void *
acpi_os_allocate(u32 size) acpi_os_allocate(ACPI_SIZE size)
{ {
return kmalloc(size, GFP_KERNEL); return kmalloc(size, GFP_KERNEL);
} }
void * void *
acpi_os_callocate(u32 size) acpi_os_callocate(ACPI_SIZE size)
{ {
void *ptr = acpi_os_allocate(size); void *ptr = acpi_os_allocate(size);
if (ptr) if (ptr)
...@@ -148,21 +148,22 @@ acpi_os_free(void *ptr) ...@@ -148,21 +148,22 @@ acpi_os_free(void *ptr)
acpi_status acpi_status
acpi_os_get_root_pointer(u32 flags, ACPI_PHYSICAL_ADDRESS *phys_addr) acpi_os_get_root_pointer(u32 flags, ACPI_POINTER *addr)
{ {
#ifndef CONFIG_ACPI_EFI #ifndef CONFIG_ACPI_EFI
if (ACPI_FAILURE(acpi_find_root_pointer(flags, phys_addr))) { if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) {
printk(KERN_ERR PREFIX "System description tables not found\n"); printk(KERN_ERR PREFIX "System description tables not found\n");
return AE_NOT_FOUND; return AE_NOT_FOUND;
} }
#else /*CONFIG_ACPI_EFI*/ #else /*CONFIG_ACPI_EFI*/
addr->pointer_type = ACPI_PHYSICAL_POINTER;
if (efi.acpi20) if (efi.acpi20)
*phys_addr = (ACPI_PHYSICAL_ADDRESS) efi.acpi20; addr->pointer.physical = (ACPI_PHYSICAL_ADDRESS) efi.acpi20;
else if (efi.acpi) else if (efi.acpi)
*phys_addr = (ACPI_PHYSICAL_ADDRESS) efi.acpi; addr->pointer.physical = (ACPI_PHYSICAL_ADDRESS) efi.acpi;
else { else {
printk(KERN_ERR PREFIX "System description tables not found\n"); printk(KERN_ERR PREFIX "System description tables not found\n");
*phys_addr = 0; addr->pointer.physical = 0;
return AE_NOT_FOUND; return AE_NOT_FOUND;
} }
#endif /*CONFIG_ACPI_EFI*/ #endif /*CONFIG_ACPI_EFI*/
...@@ -171,7 +172,7 @@ acpi_os_get_root_pointer(u32 flags, ACPI_PHYSICAL_ADDRESS *phys_addr) ...@@ -171,7 +172,7 @@ acpi_os_get_root_pointer(u32 flags, ACPI_PHYSICAL_ADDRESS *phys_addr)
} }
acpi_status acpi_status
acpi_os_map_memory(ACPI_PHYSICAL_ADDRESS phys, u32 size, void **virt) acpi_os_map_memory(ACPI_PHYSICAL_ADDRESS phys, ACPI_SIZE size, void **virt)
{ {
if (phys > ULONG_MAX) { if (phys > ULONG_MAX) {
printk(KERN_ERR PREFIX "Cannot map memory that high\n"); printk(KERN_ERR PREFIX "Cannot map memory that high\n");
...@@ -189,7 +190,7 @@ acpi_os_map_memory(ACPI_PHYSICAL_ADDRESS phys, u32 size, void **virt) ...@@ -189,7 +190,7 @@ acpi_os_map_memory(ACPI_PHYSICAL_ADDRESS phys, u32 size, void **virt)
} }
void void
acpi_os_unmap_memory(void *virt, u32 size) acpi_os_unmap_memory(void *virt, ACPI_SIZE size)
{ {
iounmap(virt); iounmap(virt);
} }
...@@ -441,14 +442,14 @@ acpi_os_load_module ( ...@@ -441,14 +442,14 @@ acpi_os_load_module (
ACPI_FUNCTION_TRACE ("os_load_module"); ACPI_FUNCTION_TRACE ("os_load_module");
if (!module_name) if (!module_name)
return AE_BAD_PARAMETER; return_ACPI_STATUS (AE_BAD_PARAMETER);
if (0 > request_module(module_name)) { if (0 > request_module(module_name)) {
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to load module [%s].\n", module_name)); ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to load module [%s].\n", module_name));
return AE_ERROR; return_ACPI_STATUS (AE_ERROR);
} }
return AE_OK; return_ACPI_STATUS (AE_OK);
} }
acpi_status acpi_status
...@@ -481,7 +482,7 @@ acpi_os_queue_exec ( ...@@ -481,7 +482,7 @@ acpi_os_queue_exec (
strcpy(current->comm, "kacpidpc"); strcpy(current->comm, "kacpidpc");
if (!dpc || !dpc->function) if (!dpc || !dpc->function)
return AE_BAD_PARAMETER; return_ACPI_STATUS (AE_BAD_PARAMETER);
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Executing function [%p(%p)].\n", dpc->function, dpc->context)); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Executing function [%p(%p)].\n", dpc->function, dpc->context));
...@@ -489,7 +490,7 @@ acpi_os_queue_exec ( ...@@ -489,7 +490,7 @@ acpi_os_queue_exec (
kfree(dpc); kfree(dpc);
return 1; return_ACPI_STATUS (AE_OK);
} }
static void static void
...@@ -504,7 +505,7 @@ acpi_os_schedule_exec ( ...@@ -504,7 +505,7 @@ acpi_os_schedule_exec (
dpc = (ACPI_OS_DPC*)context; dpc = (ACPI_OS_DPC*)context;
if (!dpc) { if (!dpc) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n")); ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
return; return_VOID;
} }
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Creating new thread to run function [%p(%p)].\n", dpc->function, dpc->context)); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Creating new thread to run function [%p(%p)].\n", dpc->function, dpc->context));
...@@ -515,6 +516,7 @@ acpi_os_schedule_exec ( ...@@ -515,6 +516,7 @@ acpi_os_schedule_exec (
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to kernel_thread() failed.\n")); ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to kernel_thread() failed.\n"));
acpi_os_free(dpc); acpi_os_free(dpc);
} }
return_VOID;
} }
acpi_status acpi_status
...@@ -531,7 +533,7 @@ acpi_os_queue_for_execution( ...@@ -531,7 +533,7 @@ acpi_os_queue_for_execution(
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Scheduling function [%p(%p)] for deferred execution.\n", function, context));
if (!function) if (!function)
return AE_BAD_PARAMETER; return_ACPI_STATUS (AE_BAD_PARAMETER);
/* /*
* Queue via DPC: * Queue via DPC:
...@@ -554,7 +556,7 @@ acpi_os_queue_for_execution( ...@@ -554,7 +556,7 @@ acpi_os_queue_for_execution(
*/ */
dpc = kmalloc(sizeof(ACPI_OS_DPC), GFP_ATOMIC); dpc = kmalloc(sizeof(ACPI_OS_DPC), GFP_ATOMIC);
if (!dpc) if (!dpc)
return AE_NO_MEMORY; return_ACPI_STATUS (AE_NO_MEMORY);
dpc->function = function; dpc->function = function;
dpc->context = context; dpc->context = context;
...@@ -578,7 +580,7 @@ acpi_os_queue_for_execution( ...@@ -578,7 +580,7 @@ acpi_os_queue_for_execution(
*/ */
dpc = kmalloc(sizeof(ACPI_OS_DPC), GFP_KERNEL); dpc = kmalloc(sizeof(ACPI_OS_DPC), GFP_KERNEL);
if (!dpc) if (!dpc)
return AE_NO_MEMORY; return_ACPI_STATUS (AE_NO_MEMORY);
dpc->function = function; dpc->function = function;
dpc->context = context; dpc->context = context;
...@@ -587,7 +589,7 @@ acpi_os_queue_for_execution( ...@@ -587,7 +589,7 @@ acpi_os_queue_for_execution(
break; break;
} }
return status; return_ACPI_STATUS (status);
} }
...@@ -603,7 +605,7 @@ acpi_os_create_semaphore( ...@@ -603,7 +605,7 @@ acpi_os_create_semaphore(
sem = acpi_os_callocate(sizeof(struct semaphore)); sem = acpi_os_callocate(sizeof(struct semaphore));
if (!sem) if (!sem)
return AE_NO_MEMORY; return_ACPI_STATUS (AE_NO_MEMORY);
sema_init(sem, initial_units); sema_init(sem, initial_units);
...@@ -611,7 +613,7 @@ acpi_os_create_semaphore( ...@@ -611,7 +613,7 @@ acpi_os_create_semaphore(
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Creating semaphore[%p|%d].\n", *handle, initial_units)); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Creating semaphore[%p|%d].\n", *handle, initial_units));
return AE_OK; return_ACPI_STATUS (AE_OK);
} }
...@@ -631,13 +633,13 @@ acpi_os_delete_semaphore( ...@@ -631,13 +633,13 @@ acpi_os_delete_semaphore(
ACPI_FUNCTION_TRACE ("os_delete_semaphore"); ACPI_FUNCTION_TRACE ("os_delete_semaphore");
if (!sem) if (!sem)
return AE_BAD_PARAMETER; return_ACPI_STATUS (AE_BAD_PARAMETER);
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Deleting semaphore[%p].\n", handle)); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Deleting semaphore[%p].\n", handle));
acpi_os_free(sem); sem = NULL; acpi_os_free(sem); sem = NULL;
return AE_OK; return_ACPI_STATUS (AE_OK);
} }
...@@ -663,10 +665,10 @@ acpi_os_wait_semaphore( ...@@ -663,10 +665,10 @@ acpi_os_wait_semaphore(
ACPI_FUNCTION_TRACE ("os_wait_semaphore"); ACPI_FUNCTION_TRACE ("os_wait_semaphore");
if (!sem || (units < 1)) if (!sem || (units < 1))
return AE_BAD_PARAMETER; return_ACPI_STATUS (AE_BAD_PARAMETER);
if (units > 1) if (units > 1)
return AE_SUPPORT; return_ACPI_STATUS (AE_SUPPORT);
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout)); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout));
...@@ -724,7 +726,7 @@ acpi_os_wait_semaphore( ...@@ -724,7 +726,7 @@ acpi_os_wait_semaphore(
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Acquired semaphore[%p|%d|%d]\n", handle, units, timeout)); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Acquired semaphore[%p|%d|%d]\n", handle, units, timeout));
} }
return status; return_ACPI_STATUS (status);
} }
...@@ -741,16 +743,16 @@ acpi_os_signal_semaphore( ...@@ -741,16 +743,16 @@ acpi_os_signal_semaphore(
ACPI_FUNCTION_TRACE ("os_signal_semaphore"); ACPI_FUNCTION_TRACE ("os_signal_semaphore");
if (!sem || (units < 1)) if (!sem || (units < 1))
return AE_BAD_PARAMETER; return_ACPI_STATUS (AE_BAD_PARAMETER);
if (units > 1) if (units > 1)
return AE_SUPPORT; return_ACPI_STATUS (AE_SUPPORT);
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Signaling semaphore[%p|%d]\n", handle, units)); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Signaling semaphore[%p|%d]\n", handle, units));
up(sem); up(sem);
return AE_OK; return_ACPI_STATUS (AE_OK);
} }
u32 u32
......
/* /*
* acpi_pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 19 $) * acpi_pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 22 $)
* *
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
...@@ -92,35 +92,23 @@ struct acpi_pci_link { ...@@ -92,35 +92,23 @@ struct acpi_pci_link {
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
static int static int
acpi_pci_link_get_current ( acpi_pci_link_get_possible (
struct acpi_pci_link *link) struct acpi_pci_link *link)
{ {
int result = 0; int result = 0;
acpi_status status = AE_OK; acpi_status status = AE_OK;
acpi_buffer buffer = {0, NULL}; acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_resource *resource = NULL; acpi_resource *resource = NULL;
int i = 0;
ACPI_FUNCTION_TRACE("acpi_pci_link_get_current"); ACPI_FUNCTION_TRACE("acpi_pci_link_get_possible");
if (!link || !link->handle) if (!link)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
link->irq.active = 0; status = acpi_get_possible_resources(link->handle, &buffer);
if (ACPI_FAILURE(status) || !buffer.pointer) {
status = acpi_get_current_resources(link->handle, &buffer); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRS\n"));
if (status != AE_BUFFER_OVERFLOW) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _CRS\n"));
return_VALUE(-ENODEV);
}
buffer.pointer = kmalloc(buffer.length, GFP_KERNEL);
if (!buffer.pointer)
return_VALUE(-ENOMEM);
memset(buffer.pointer, 0, buffer.length);
status = acpi_get_current_resources(link->handle, &buffer);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _CRS\n"));
result = -ENODEV; result = -ENODEV;
goto end; goto end;
} }
...@@ -131,69 +119,84 @@ acpi_pci_link_get_current ( ...@@ -131,69 +119,84 @@ acpi_pci_link_get_current (
case ACPI_RSTYPE_IRQ: case ACPI_RSTYPE_IRQ:
{ {
acpi_resource_irq *p = &resource->data.irq; acpi_resource_irq *p = &resource->data.irq;
if (p->number_of_interrupts > 0)
link->irq.active = p->interrupts[0]; if (!p || !p->number_of_interrupts) {
else { ACPI_DEBUG_PRINT((ACPI_DB_WARN,
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Blank IRQ resource\n")); "Blank IRQ resource\n"));
result = -ENODEV; result = -ENODEV;
goto end; goto end;
} }
for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_IRQS); i++) {
link->irq.possible[i] = p->interrupts[i];
link->irq.possible_count++;
}
link->irq.flags.trigger = p->edge_level;
link->irq.flags.polarity = p->active_high_low;
link->irq.flags.shareable = p->shared_exclusive;
break; break;
} }
case ACPI_RSTYPE_EXT_IRQ: case ACPI_RSTYPE_EXT_IRQ:
{ {
acpi_resource_ext_irq *p = &resource->data.extended_irq; acpi_resource_ext_irq *p = &resource->data.extended_irq;
if (p->number_of_interrupts > 0)
link->irq.active = p->interrupts[0]; if (!p || !p->number_of_interrupts) {
else { ACPI_DEBUG_PRINT((ACPI_DB_WARN,
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Blank IRQ resource\n")); "Blank IRQ resource\n"));
result = -ENODEV; result = -ENODEV;
goto end; goto end;
} }
for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_IRQS); i++) {
link->irq.possible[i] = p->interrupts[i];
link->irq.possible_count++;
}
link->irq.flags.trigger = p->edge_level;
link->irq.flags.polarity = p->active_high_low;
link->irq.flags.shareable = p->shared_exclusive;
break; break;
} }
default: default:
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"First resource is not an IRQ entry\n")); "Resource is not an IRQ entry\n"));
result = -ENODEV;
goto end;
break; break;
} }
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Found %d possible IRQs\n", link->irq.possible_count));
end: end:
kfree(buffer.pointer); kfree(buffer.pointer);
return_VALUE(0); return_VALUE(result);
} }
static int static int
acpi_pci_link_get_possible ( acpi_pci_link_get_current (
struct acpi_pci_link *link) struct acpi_pci_link *link)
{ {
int result = 0; int result = 0;
acpi_status status = AE_OK; acpi_status status = AE_OK;
acpi_buffer buffer = {0, NULL}; acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_resource *resource = NULL; acpi_resource *resource = NULL;
int i = 0;
ACPI_FUNCTION_TRACE("acpi_pci_link_get_possible"); ACPI_FUNCTION_TRACE("acpi_pci_link_get_current");
if (!link) if (!link || !link->handle)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
status = acpi_get_possible_resources(link->handle, &buffer); link->irq.active = 0;
if (status != AE_BUFFER_OVERFLOW) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRS\n"));
return_VALUE(-ENODEV);
}
buffer.pointer = kmalloc(buffer.length, GFP_KERNEL);
if (!buffer.pointer)
return_VALUE(-ENOMEM);
memset(buffer.pointer, 0, buffer.length);
status = acpi_get_possible_resources(link->handle, &buffer); status = acpi_get_current_resources(link->handle, &buffer);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRS\n")); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _CRS\n"));
result = -ENODEV; result = -ENODEV;
goto end; goto end;
} }
...@@ -205,20 +208,14 @@ acpi_pci_link_get_possible ( ...@@ -205,20 +208,14 @@ acpi_pci_link_get_possible (
{ {
acpi_resource_irq *p = &resource->data.irq; acpi_resource_irq *p = &resource->data.irq;
for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_IRQS); i++) { if (!p || !p->number_of_interrupts) {
link->irq.possible[i] = p->interrupts[i]; ACPI_DEBUG_PRINT((ACPI_DB_WARN,
link->irq.possible_count++; "Blank IRQ resource\n"));
}
if (!p->number_of_interrupts) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Blank IRQ resource\n"));
result = -ENODEV; result = -ENODEV;
goto end; goto end;
} }
link->irq.flags.trigger = p->edge_level; link->irq.active = p->interrupts[0];
link->irq.flags.polarity = p->active_high_low;
link->irq.flags.shareable = p->shared_exclusive;
break; break;
} }
...@@ -226,32 +223,36 @@ acpi_pci_link_get_possible ( ...@@ -226,32 +223,36 @@ acpi_pci_link_get_possible (
{ {
acpi_resource_ext_irq *p = &resource->data.extended_irq; acpi_resource_ext_irq *p = &resource->data.extended_irq;
for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_IRQS); i++) { if (!p || !p->number_of_interrupts) {
link->irq.possible[i] = p->interrupts[i]; ACPI_DEBUG_PRINT((ACPI_DB_WARN,
link->irq.possible_count++; "Blank IRQ resource\n"));
}
if (!p->number_of_interrupts) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Blank IRQ resource\n"));
result = -ENODEV; result = -ENODEV;
goto end; goto end;
} }
link->irq.flags.trigger = p->edge_level; link->irq.active = p->interrupts[0];
link->irq.flags.polarity = p->active_high_low;
link->irq.flags.shareable = p->shared_exclusive;
break; break;
} }
default: default:
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"First resource is not an IRQ entry\n")); "Resource is not an IRQ entry\n"));
break; break;
} }
if (!link->irq.active) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Invalid IRQ %d\n", link->irq.active));
result = -ENODEV;
}
end: end:
kfree(buffer.pointer); kfree(buffer.pointer);
if (0 == result)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n",
link->irq.active));
return_VALUE(result); return_VALUE(result);
} }
...@@ -259,7 +260,7 @@ acpi_pci_link_get_possible ( ...@@ -259,7 +260,7 @@ acpi_pci_link_get_possible (
static int static int
acpi_pci_link_set ( acpi_pci_link_set (
struct acpi_pci_link *link, struct acpi_pci_link *link,
u32 irq) int irq)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
struct { struct {
...@@ -290,6 +291,8 @@ acpi_pci_link_set ( ...@@ -290,6 +291,8 @@ acpi_pci_link_set (
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
} }
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Set IRQ %d\n", irq));
return_VALUE(0); return_VALUE(0);
} }
...@@ -328,8 +331,10 @@ acpi_pci_link_get_irq ( ...@@ -328,8 +331,10 @@ acpi_pci_link_get_irq (
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
} }
if (!link->irq.flags.valid) if (!link->irq.flags.valid) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link IRQ invalid\n"));
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
}
/* TBD: Support multiple index (IRQ) entries per Link Device */ /* TBD: Support multiple index (IRQ) entries per Link Device */
if (0 != entry->source.index) { if (0 != entry->source.index) {
...@@ -361,7 +366,7 @@ acpi_pci_link_set_irq ( ...@@ -361,7 +366,7 @@ acpi_pci_link_set_irq (
if (!entry || !entry->source.handle || !irq) if (!entry || !entry->source.handle || !irq)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
/* TBD: Support multiple index values (not just first). */ /* TBD: Support multiple index (IRQ) entries per Link Device */
if (0 != entry->source.index) { if (0 != entry->source.index) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unsupported resource index [%d]\n", "Unsupported resource index [%d]\n",
...@@ -386,7 +391,8 @@ acpi_pci_link_set_irq ( ...@@ -386,7 +391,8 @@ acpi_pci_link_set_irq (
/* Is the target IRQ the same as the currently enabled IRQ? */ /* Is the target IRQ the same as the currently enabled IRQ? */
if (link->irq.flags.enabled && (irq == link->irq.active)) { if (link->irq.flags.enabled && (irq == link->irq.active)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link IRQ already at target\n")); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link already at IRQ %d\n",
irq));
return_VALUE(0); return_VALUE(0);
} }
...@@ -413,6 +419,85 @@ acpi_pci_link_set_irq ( ...@@ -413,6 +419,85 @@ acpi_pci_link_set_irq (
} }
static int
acpi_pci_link_enable (
struct acpi_device *device,
struct acpi_pci_link *link)
{
int result = -ENODEV;
ACPI_FUNCTION_TRACE("acpi_pci_link_enable");
if (!device || !link)
return_VALUE(-EINVAL);
result = acpi_pci_link_get_possible(link);
if (0 != result)
return_VALUE(result);
result = acpi_bus_get_status(device);
if (0 != result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n"));
return_VALUE(-ENODEV);
}
/*
* If this link device isn't enabled (_STA bit 1) then we enable it
* by setting an IRQ.
*/
if (!device->status.enabled) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Attempting to enable at IRQ [%d]\n",
link->irq.possible[0]));
result = acpi_pci_link_set(link, link->irq.possible[0]);
if (0 != result)
return_VALUE(result);
result = acpi_bus_get_status(device);
if (0 != result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to read status\n"));
return_VALUE(-ENODEV);
}
if (!device->status.enabled) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Enable failed\n"));
return_VALUE(-ENODEV);
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link enabled at IRQ %d\n",
link->irq.possible[0]));
}
/*
* Now we get the current IRQ just to make sure everything is kosher.
*/
result = acpi_pci_link_get_current(link);
if (0 != result) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Current IRQ invalid, setting to default\n"));
result = acpi_pci_link_set(link, link->irq.possible[0]);
if (0 != result)
return_VALUE(result);
result = acpi_pci_link_get_current(link);
if (0 != result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to read current IRQ\n"));
return_VALUE(result);
}
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Using IRQ %d\n", link->irq.active));
link->irq.flags.valid = 1;
return_VALUE(0);
}
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
Driver Interface Driver Interface
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
...@@ -440,34 +525,9 @@ acpi_pci_link_add ( ...@@ -440,34 +525,9 @@ acpi_pci_link_add (
sprintf(acpi_device_class(device), "%s", ACPI_PCI_LINK_CLASS); sprintf(acpi_device_class(device), "%s", ACPI_PCI_LINK_CLASS);
acpi_driver_data(device) = link; acpi_driver_data(device) = link;
result = acpi_pci_link_get_possible(link); result = acpi_pci_link_enable(device, link);
if (0 != result)
return_VALUE(result);
if (!device->status.enabled) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Enabling at IRQ [%d]\n",
link->irq.possible[0]));
result = acpi_pci_link_set(link, link->irq.possible[0]);
if (0 != result)
return_VALUE(result);
result = acpi_bus_get_status(device);
if (0 != result)
return_VALUE(result);
if (!device->status.enabled) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Enable failed\n"));
return_VALUE(-EFAULT);
}
}
result = acpi_pci_link_get_current(link);
if (0 != result) if (0 != result)
return_VALUE(result); goto end;
link->irq.flags.valid = 1;
printk(PREFIX "%s [%s] (IRQs", printk(PREFIX "%s [%s] (IRQs",
acpi_device_name(device), acpi_device_bid(device)); acpi_device_name(device), acpi_device_bid(device));
...@@ -477,7 +537,11 @@ acpi_pci_link_add ( ...@@ -477,7 +537,11 @@ acpi_pci_link_add (
link->irq.possible[i]); link->irq.possible[i]);
printk(")\n"); printk(")\n");
return_VALUE(0); end:
if (0 != result)
kfree(link);
return_VALUE(result);
} }
......
/* /*
* acpi_pci_root.c - ACPI PCI Root Bridge Driver ($Revision: 22 $) * acpi_pci_root.c - ACPI PCI Root Bridge Driver ($Revision: 30 $)
* *
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
...@@ -48,6 +48,7 @@ extern struct pci_ops *pci_root_ops; ...@@ -48,6 +48,7 @@ extern struct pci_ops *pci_root_ops;
static int acpi_pci_root_add (struct acpi_device *device); static int acpi_pci_root_add (struct acpi_device *device);
static int acpi_pci_root_remove (struct acpi_device *device, int type); static int acpi_pci_root_remove (struct acpi_device *device, int type);
static int acpi_pci_root_bind (struct acpi_device *device);
static struct acpi_driver acpi_pci_root_driver = { static struct acpi_driver acpi_pci_root_driver = {
name: ACPI_PCI_ROOT_DRIVER_NAME, name: ACPI_PCI_ROOT_DRIVER_NAME,
...@@ -56,20 +57,20 @@ static struct acpi_driver acpi_pci_root_driver = { ...@@ -56,20 +57,20 @@ static struct acpi_driver acpi_pci_root_driver = {
ops: { ops: {
add: acpi_pci_root_add, add: acpi_pci_root_add,
remove: acpi_pci_root_remove, remove: acpi_pci_root_remove,
bind: acpi_pci_root_bind,
}, },
}; };
struct acpi_pci_root_context { struct acpi_pci_data {
acpi_handle handle; acpi_pci_id id;
struct {
u8 seg; /* Root's segment number */
u8 bus; /* Root's bus number */
u8 sub; /* Max subordinate bus */
} id;
struct pci_bus *bus;
struct pci_dev *dev; struct pci_dev *dev;
}; };
struct acpi_pci_root {
acpi_handle handle;
struct acpi_pci_data data;
};
struct acpi_prt_list acpi_prts; struct acpi_prt_list acpi_prts;
...@@ -77,25 +78,33 @@ struct acpi_prt_list acpi_prts; ...@@ -77,25 +78,33 @@ struct acpi_prt_list acpi_prts;
PCI Routing Table (PRT) Support PCI Routing Table (PRT) Support
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
static struct acpi_prt_entry * static int
acpi_prt_find_entry ( acpi_prt_find_entry (
struct pci_dev *dev, acpi_pci_id *id,
u8 pin) u8 pin,
struct acpi_prt_entry **entry)
{ {
struct acpi_prt_entry *entry = NULL;
struct list_head *node = NULL; struct list_head *node = NULL;
ACPI_FUNCTION_TRACE("acpi_prt_find_entry"); ACPI_FUNCTION_TRACE("acpi_prt_find_entry");
if (!id || !entry)
return_VALUE(-ENODEV);
/* TBD: Locking */ /* TBD: Locking */
list_for_each(node, &acpi_prts.entries) { list_for_each(node, &acpi_prts.entries) {
entry = list_entry(node, struct acpi_prt_entry, node); (*entry) = list_entry(node, struct acpi_prt_entry, node);
if ((entry->id.dev == PCI_SLOT(dev->devfn)) /* TBD: Include check for segment when supported by pci_dev */
&& (entry->id.pin == pin)) if ((id->bus == (*entry)->id.bus)
return_PTR(entry); && (id->device == (*entry)->id.dev)
&& (pin == (*entry)->id.pin)) {
return_VALUE(0);
}
} }
return_PTR(NULL); (*entry) = NULL;
return_VALUE(-ENODEV);
} }
...@@ -107,23 +116,49 @@ acpi_prt_get_irq ( ...@@ -107,23 +116,49 @@ acpi_prt_get_irq (
{ {
int result = 0; int result = 0;
struct acpi_prt_entry *entry = NULL; struct acpi_prt_entry *entry = NULL;
acpi_pci_id id = {0, 0, 0, 0};
ACPI_FUNCTION_TRACE("acpi_pci_get_current_irq"); ACPI_FUNCTION_TRACE("acpi_prt_get_irq");
if (!dev || !irq) if (!dev || !irq)
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
entry = acpi_prt_find_entry(dev, pin); if (!dev->bus) {
if (!entry) ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
return_VALUE(-ENODEV); "Device has invalid 'bus' field\n"));
return_VALUE(-EFAULT);
}
id.segment = 0;
id.bus = dev->bus->number;
id.device = PCI_SLOT(dev->devfn);
id.function = PCI_FUNC(dev->devfn);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Resolving IRQ for %02x:%02x:%02x.%02x[%c]\n",
id.segment, id.bus, id.device, id.function, ('A'+pin)));
result = acpi_prt_find_entry(&id, pin, &entry);
if (0 != result)
return_VALUE(result);
/* Type 1: Dynamic (e.g. PCI Link Device) */ /* Type 1: Dynamic (e.g. PCI Link Device) */
if (entry->source.handle) if (entry->source.handle)
result = acpi_pci_link_get_irq(entry, irq); result = acpi_pci_link_get_irq(entry, irq);
/* Type 2: Static (e.g. I/O [S]APIC Direct) */ /* Type 2: Static (e.g. I/O [S]APIC Direct) */
else else {
*irq = entry->source.index; if (entry->source.index)
*irq = entry->source.index;
else
result = -ENODEV;
}
if (0 == result)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", *irq));
else
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to reslove IRQ\n"));
return_VALUE(0); return_VALUE(0);
} }
...@@ -135,18 +170,32 @@ acpi_prt_set_irq ( ...@@ -135,18 +170,32 @@ acpi_prt_set_irq (
int irq) int irq)
{ {
int result = 0; int result = 0;
int i = 0;
int valid = 0;
struct acpi_prt_entry *entry = NULL; struct acpi_prt_entry *entry = NULL;
acpi_pci_id id = {0, 0, 0, 0};
ACPI_FUNCTION_TRACE("acpi_pci_set_current_irq"); ACPI_FUNCTION_TRACE("acpi_pci_set_irq");
if (!dev || !irq) if (!dev || !irq)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
entry = acpi_prt_find_entry(dev, pin); if (!dev->bus) {
if (!entry) ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
return_VALUE(-ENODEV); "Device has invalid 'bus' field\n"));
return_VALUE(-EFAULT);
}
id.segment = 0;
id.bus = dev->bus->number;
id.device = PCI_SLOT(dev->devfn);
id.function = PCI_FUNC(dev->devfn);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Setting %02x:%02x:%02x.%02x[%c] to IRQ%d\n",
id.segment, id.bus, id.device, id.function, ('A'+pin), irq));
result = acpi_prt_find_entry(&id, pin, &entry);
if (0 != result)
return_VALUE(result);
/* Type 1: Dynamic (e.g. PCI Link Device) */ /* Type 1: Dynamic (e.g. PCI Link Device) */
if (entry->source.handle) if (entry->source.handle)
...@@ -155,6 +204,11 @@ acpi_prt_set_irq ( ...@@ -155,6 +204,11 @@ acpi_prt_set_irq (
else else
result = -EFAULT; result = -EFAULT;
if (0 == result)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "IRQ set\n"));
else
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to set IRQ\n"));
return_VALUE(result); return_VALUE(result);
} }
...@@ -212,9 +266,9 @@ acpi_prt_add_entry ( ...@@ -212,9 +266,9 @@ acpi_prt_add_entry (
* namespace). * namespace).
*/ */
printk(KERN_INFO " %02X:%02X:%02X[%c] -> %s[%d]\n", ACPI_DEBUG_PRINT_RAW((ACPI_DB_OK, " %02X:%02X:%02X[%c] -> %s[%d]\n",
entry->id.seg, entry->id.bus, entry->id.dev, entry->id.seg, entry->id.bus, entry->id.dev,
('A' + entry->id.pin), prt->source, entry->source.index); ('A' + entry->id.pin), prt->source, entry->source.index));
/* TBD: Acquire/release lock */ /* TBD: Acquire/release lock */
list_add_tail(&entry->node, &acpi_prts.entries); list_add_tail(&entry->node, &acpi_prts.entries);
...@@ -225,57 +279,23 @@ acpi_prt_add_entry ( ...@@ -225,57 +279,23 @@ acpi_prt_add_entry (
} }
static acpi_status static int
acpi_prt_callback ( acpi_prt_parse (
acpi_handle handle, acpi_handle handle,
u32 nesting_level, u8 seg,
void *context, u8 bus)
void **return_value)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
acpi_handle prt_handle = NULL;
char pathname[PATHNAME_MAX] = {0}; char pathname[PATHNAME_MAX] = {0};
acpi_buffer buffer = {0, NULL}; acpi_buffer buffer = {0, NULL};
acpi_pci_routing_table *prt = NULL; acpi_pci_routing_table *prt = NULL;
unsigned long sta = 0;
struct acpi_pci_root_context *root = (struct acpi_pci_root_context *) context;
u8 bus_number = 0;
ACPI_FUNCTION_TRACE("acpi_prt_callback"); ACPI_FUNCTION_TRACE("acpi_prt_parse");
if (!root)
return_VALUE(AE_BAD_PARAMETER);
status = acpi_get_handle(handle, METHOD_NAME__PRT, &prt_handle);
if (ACPI_FAILURE(status))
return_VALUE(AE_OK);
buffer.length = sizeof(pathname); buffer.length = sizeof(pathname);
buffer.pointer = pathname; buffer.pointer = pathname;
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
/*
* Evalute _STA to see if the device containing this _PRT is present.
*/
status = acpi_evaluate_integer(handle, METHOD_NAME__STA, NULL, &sta);
switch (status) {
case AE_OK:
if (!(sta & 0x01)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Found _PRT but device [%s] not present\n",
pathname));
return_VALUE(AE_OK);
}
break;
case AE_NOT_FOUND:
/* assume present */
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating %s._STA [%s]\n",
pathname, acpi_format_exception(status)));
return_VALUE(status);
}
printk(KERN_INFO PREFIX "%s [%s._PRT]\n", ACPI_PCI_PRT_DEVICE_NAME, printk(KERN_INFO PREFIX "%s [%s._PRT]\n", ACPI_PCI_PRT_DEVICE_NAME,
pathname); pathname);
...@@ -287,9 +307,10 @@ acpi_prt_callback ( ...@@ -287,9 +307,10 @@ acpi_prt_callback (
buffer.pointer = NULL; buffer.pointer = NULL;
status = acpi_get_irq_routing_table(handle, &buffer); status = acpi_get_irq_routing_table(handle, &buffer);
if (status != AE_BUFFER_OVERFLOW) { if (status != AE_BUFFER_OVERFLOW) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating _PRT [%s]\n", ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error evaluating _PRT [%s]\n",
acpi_format_exception(status))); acpi_format_exception(status)));
return_VALUE(status); return_VALUE(-ENODEV);
} }
prt = kmalloc(buffer.length, GFP_KERNEL); prt = kmalloc(buffer.length, GFP_KERNEL);
...@@ -300,144 +321,401 @@ acpi_prt_callback ( ...@@ -300,144 +321,401 @@ acpi_prt_callback (
status = acpi_get_irq_routing_table(handle, &buffer); status = acpi_get_irq_routing_table(handle, &buffer);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating _PRT [%s]\n", ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error evaluating _PRT [%s]\n",
acpi_format_exception(status))); acpi_format_exception(status)));
kfree(buffer.pointer); kfree(buffer.pointer);
return_VALUE(status); return_VALUE(-ENODEV);
}
if (root->handle == handle)
bus_number = root->id.bus;
else {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Need to get subordinate bus number!\n"));
/* get the bus number for this device */
} }
while (prt && (prt->length > 0)) { while (prt && (prt->length > 0)) {
acpi_prt_add_entry(handle, root->id.seg, bus_number, prt); acpi_prt_add_entry(handle, seg, bus, prt);
prt = (acpi_pci_routing_table*)((unsigned long)prt + prt->length); prt = (acpi_pci_routing_table*)((unsigned long)prt + prt->length);
} }
return_VALUE(AE_OK); return_VALUE(0);
} }
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
Driver Interface PCI Device Binding
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
int static void
acpi_pci_root_add ( acpi_pci_data_handler (
acpi_handle handle,
u32 function,
void *context)
{
ACPI_FUNCTION_TRACE("acpi_pci_data_handler");
/* TBD: Anything we need to do here? */
return_VOID;
}
/**
* acpi_os_get_pci_id
* ------------------
* This function gets used by the ACPI Interpreter (a.k.a. Core Subsystem)
* to resolve PCI information for ACPI-PCI devices defined in the namespace.
*/
acpi_status
acpi_os_get_pci_id (
acpi_handle handle,
acpi_pci_id *id)
{
int result = 0;
acpi_status status = AE_OK;
struct acpi_device *device = NULL;
struct acpi_pci_data *data = NULL;
ACPI_FUNCTION_TRACE("acpi_os_get_pci_id");
if (!id)
return_ACPI_STATUS(AE_BAD_PARAMETER);
result = acpi_bus_get_device(handle, &device);
if (0 != result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Invalid ACPI Bus context for device %s\n",
acpi_device_bid(device)));
return_ACPI_STATUS(AE_NOT_EXIST);
}
status = acpi_get_data(handle, acpi_pci_data_handler, (void**) &data);
if (ACPI_FAILURE(status) || !data || !data->dev) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Invalid ACPI-PCI context for device %s\n",
acpi_device_bid(device)));
return_ACPI_STATUS(status);
}
id->segment = data->id.segment;
id->bus = data->id.bus;
id->device = data->id.device;
id->function = data->id.function;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Device %s has PCI address %02x:%02x:%02x.%02x\n",
acpi_device_bid(device), id->segment, id->bus,
id->device, id->function));
return_ACPI_STATUS(AE_OK);
}
static int
acpi_pci_root_bind (
struct acpi_device *device) struct acpi_device *device)
{ {
int result = 0;
acpi_status status = AE_OK; acpi_status status = AE_OK;
struct acpi_pci_root_context *context = NULL; struct acpi_pci_data *data = NULL;
unsigned long temp = 0; struct acpi_pci_data *parent_data = NULL;
acpi_handle handle = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_root_add"); ACPI_FUNCTION_TRACE("acpi_pci_root_bind");
if (!device) if (!device || !device->parent)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
context = kmalloc(sizeof(struct acpi_pci_root_context), GFP_KERNEL); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Attempting to bind PCI device %s.%s\n",
if (!context) acpi_device_bid(device->parent), acpi_device_bid(device)));
data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
if (!data)
return_VALUE(-ENOMEM); return_VALUE(-ENOMEM);
memset(context, 0, sizeof(struct acpi_pci_root_context)); memset(data, 0, sizeof(struct acpi_pci_data));
context->handle = device->handle; /*
sprintf(acpi_device_name(device), "%s", ACPI_PCI_ROOT_DEVICE_NAME); * Segment & Bus
sprintf(acpi_device_class(device), "%s", ACPI_PCI_ROOT_CLASS); * -------------
acpi_driver_data(device) = context; * These are obtained via the parent device's ACPI-PCI context..
* Note that PCI root bridge devices don't have a 'dev->subordinate'.
*/
status = acpi_get_data(device->parent->handle, acpi_pci_data_handler,
(void**) &parent_data);
if (ACPI_FAILURE(status) || !parent_data || !parent_data->dev) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Invalid ACPI-PCI context for parent device %s\n",
acpi_device_bid(device->parent)));
result = -ENODEV;
goto end;
}
status = acpi_evaluate_integer(context->handle, METHOD_NAME__SEG, data->id.segment = parent_data->id.segment;
NULL, &temp);
if (ACPI_SUCCESS(status))
context->id.seg = temp;
else
context->id.seg = 0;
status = acpi_evaluate_integer(context->handle, METHOD_NAME__BBN, if (parent_data->dev->subordinate) /* e.g. PCI-PCI bridge */
NULL, &temp); data->id.bus = parent_data->dev->subordinate->number;
if (ACPI_SUCCESS(status)) else if (parent_data->dev->bus) /* PCI root bridge */
context->id.bus = temp; data->id.bus = parent_data->dev->bus->number;
else else {
context->id.bus = 0; ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Parent device %s is not a PCI bridge\n",
acpi_device_bid(device->parent)));
result = -ENODEV;
goto end;
}
/* TBD: Evaluate _CRS for bus range of child P2P (bus min/max/len) */ /*
* Device & Function
* -----------------
* These are simply obtained from the device's _ADR method. Note
* that a value of zero is valid.
*/
data->id.device = device->pnp.bus_address >> 16;
data->id.function = device->pnp.bus_address & 0xFFFF;
printk(KERN_INFO PREFIX "%s [%s] (%02x:%02x)\n", ACPI_DEBUG_PRINT((ACPI_DB_INFO,
acpi_device_name(device), acpi_device_bid(device), "Binding device %s.%s to %02x:%02x:%02x.%02x\n",
context->id.seg, context->id.bus); acpi_device_bid(device->parent), acpi_device_bid(device),
data->id.segment, data->id.bus, data->id.device,
data->id.function));
/*
* Locate PCI Device
* -----------------
* Locate matching device in PCI namespace. If it doesn't exist
* this typically means that the device isn't currently inserted
* (e.g. docking station, port replicator, etc.).
*/
data->dev = pci_find_slot(data->id.bus,
PCI_DEVFN(data->id.device, data->id.function));
if (!data->dev) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
data->id.segment, data->id.bus,
data->id.device, data->id.function));
result = -ENODEV;
goto end;
}
if (!data->dev->bus) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Device %02x:%02x:%02x.%02x has invalid 'bus' field\n",
data->id.segment, data->id.bus,
data->id.device, data->id.function));
result = -ENODEV;
goto end;
}
/* /*
* Scan all devices on this root bridge. Note that this must occur * Attach ACPI-PCI Context
* now to get the correct bus number assignments for subordinate * -----------------------
* PCI-PCI bridges. * Thus binding the ACPI and PCI devices.
*/ */
pci_scan_bus(context->id.bus, pci_root_ops, NULL); status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to attach ACPI-PCI context to device %s\n",
acpi_device_bid(device)));
result = -ENODEV;
goto end;
}
/* Evaluate _PRT for this root bridge. */ /*
acpi_prt_callback(context->handle, 0, context, NULL); * PCI Bridge?
* -----------
* If so, install the 'bind' function to facilitate callbacks for
* all of its children.
*/
if (data->dev->subordinate)
device->ops.bind = acpi_pci_root_bind;
/* Evaluate all subordinate _PRTs. */ /*
acpi_walk_namespace(ACPI_TYPE_DEVICE, context->handle, ACPI_UINT32_MAX, * PCI Routing Table
acpi_prt_callback, context, NULL); * -----------------
* Evaluate and parse _PRT, if exists. This code is independent of
* PCI bridges (above) to allow parsing of _PRT objects within the
* scope of non-bridge devices. Note that _PRTs within the scope of
* a PCI bridge assume the bridge's subordinate bus number.
*
* TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
*/
status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
if (ACPI_SUCCESS(status)) {
if (data->dev->subordinate) /* PCI-PCI bridge */
acpi_prt_parse(device->handle, data->id.segment,
data->dev->subordinate->number);
else /* non-bridge PCI device */
acpi_prt_parse(device->handle, data->id.segment,
data->id.bus);
}
return_VALUE(0); end:
if (0 != result)
kfree(data);
return_VALUE(result);
} }
int /* --------------------------------------------------------------------------
acpi_pci_root_remove ( Driver Interface
struct acpi_device *device, -------------------------------------------------------------------------- */
int type)
static int
acpi_pci_root_add (
struct acpi_device *device)
{ {
struct acpi_pci_dev_context *context = NULL; int result = 0;
struct acpi_pci_root *root = NULL;
acpi_status status = AE_OK;
unsigned long value = 0;
ACPI_FUNCTION_TRACE("acpi_pci_root_add");
if (!device) if (!device)
return -EINVAL; return_VALUE(-EINVAL);
if (device->driver_data) root = kmalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
/* Root bridge */ if (!root)
kfree(device->driver_data); return_VALUE(-ENOMEM);
else { memset(root, 0, sizeof(struct acpi_pci_root));
/* Standard PCI device */
context = acpi_driver_data(device); root->handle = device->handle;
if (context) sprintf(acpi_device_name(device), "%s", ACPI_PCI_ROOT_DEVICE_NAME);
kfree(context); sprintf(acpi_device_class(device), "%s", ACPI_PCI_ROOT_CLASS);
acpi_driver_data(device) = root;
/*
* TBD: Doesn't the bus driver automatically set this?
*/
device->ops.bind = acpi_pci_root_bind;
/*
* Segment
* -------
* Obtained via _SEG, if exists, otherwise assumed to be zero (0).
*/
status = acpi_evaluate_integer(root->handle, METHOD_NAME__SEG, NULL,
&value);
switch (status) {
case AE_OK:
root->data.id.segment = (u16) value;
break;
case AE_NOT_FOUND:
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Assuming segment 0 (no _SEG)\n"));
root->data.id.segment = 0;
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SEG\n"));
result = -ENODEV;
goto end;
} }
return 0; /*
} * Bus
* ---
* Obtained via _BBN, if exists, otherwise assumed to be zero (0).
*/
status = acpi_evaluate_integer(root->handle, METHOD_NAME__BBN, NULL,
&value);
switch (status) {
case AE_OK:
root->data.id.bus = (u16) value;
break;
case AE_NOT_FOUND:
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Assuming bus 0 (no _BBN)\n"));
root->data.id.bus = 0;
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BBN\n"));
result = -ENODEV;
goto end;
}
/*
* Device & Function
* -----------------
* Obtained from _ADR (which has already been evaluated for us).
*/
root->data.id.device = device->pnp.bus_address >> 16;
root->data.id.function = device->pnp.bus_address & 0xFFFF;
int __init /*
acpi_pci_irq_init (void) * TBD: Evaluate _CRS to get root bridge resources
{ * TBD: Need PCI interface for enumeration/configuration of roots.
int result = 0; */
acpi_status status = AE_OK;
acpi_object arg = {ACPI_TYPE_INTEGER};
acpi_object_list arg_list = {1, &arg};
int irq_model = 0;
ACPI_FUNCTION_TRACE("acpi_pci_irq_init"); printk(KERN_INFO PREFIX "%s [%s] (%02x:%02x:%02x.%02x)\n",
acpi_device_name(device), acpi_device_bid(device),
root->data.id.segment, root->data.id.bus,
root->data.id.device, root->data.id.function);
/*
* Scan the Root Bridge
* --------------------
* Must do this prior to any attempt to bind the root device, as the
* PCI namespace does not get created until this call is made (and
* thus the root bridge's pci_dev does not exist).
*/
pci_scan_bus(root->data.id.bus, pci_root_ops, NULL);
/* /*
* Let the system know what interrupt model we are using by * Locate PCI Device
* evaluating the \_PIC object, if exists. * -----------------
* Locate the matching PCI root bridge device in the PCI namespace.
*/ */
root->data.dev = pci_find_slot(root->data.id.bus,
PCI_DEVFN(root->data.id.device, root->data.id.function));
if (!root->data.dev) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Device %02x:%02x:%02x.%02x not present\n",
root->data.id.segment, root->data.id.bus,
root->data.id.device, root->data.id.function));
result = -ENODEV;
goto end;
}
result = acpi_get_interrupt_model(&irq_model); /*
* Attach ACPI-PCI Context
* -----------------------
* Thus binding the ACPI and PCI devices.
*/
status = acpi_attach_data(root->handle, acpi_pci_data_handler,
&root->data);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to attach ACPI-PCI context to device %s\n",
acpi_device_bid(device)));
result = -ENODEV;
goto end;
}
/*
* PCI Routing Table
* -----------------
* Evaluate and parse _PRT, if exists. Note that root bridges
* must have a _PRT (optional for subordinate bridges).
*/
result = acpi_prt_parse(device->handle, root->data.id.segment,
root->data.id.bus);
end:
if (0 != result) if (0 != result)
return_VALUE(result); kfree(root);
arg.integer.value = irq_model; return_VALUE(result);
}
status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL);
if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { static int
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PIC\n")); acpi_pci_root_remove (
return_VALUE(-ENODEV); struct acpi_device *device,
} int type)
{
struct acpi_pci_root *root = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_root_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
root = (struct acpi_pci_root *) acpi_driver_data(device);
kfree(root);
return_VALUE(0); return_VALUE(0);
} }
...@@ -446,17 +724,11 @@ acpi_pci_irq_init (void) ...@@ -446,17 +724,11 @@ acpi_pci_irq_init (void)
int __init int __init
acpi_pci_root_init (void) acpi_pci_root_init (void)
{ {
int result = 0;
ACPI_FUNCTION_TRACE("acpi_pci_root_init"); ACPI_FUNCTION_TRACE("acpi_pci_root_init");
acpi_prts.count = 0; acpi_prts.count = 0;
INIT_LIST_HEAD(&acpi_prts.entries); INIT_LIST_HEAD(&acpi_prts.entries);
result = acpi_pci_irq_init();
if (0 != result)
return_VALUE(result);
if (0 > acpi_bus_register_driver(&acpi_pci_root_driver)) if (0 > acpi_bus_register_driver(&acpi_pci_root_driver))
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
...@@ -470,5 +742,6 @@ acpi_pci_root_exit (void) ...@@ -470,5 +742,6 @@ acpi_pci_root_exit (void)
ACPI_FUNCTION_TRACE("acpi_pci_root_exit"); ACPI_FUNCTION_TRACE("acpi_pci_root_exit");
acpi_bus_unregister_driver(&acpi_pci_root_driver); acpi_bus_unregister_driver(&acpi_pci_root_driver);
}
return_VOID;
}
/* /*
* acpi_processor.c - ACPI Processor Driver ($Revision: 50 $) * acpi_processor.c - ACPI Processor Driver ($Revision: 57 $)
* *
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
...@@ -23,16 +23,12 @@ ...@@ -23,16 +23,12 @@
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* TBD: * TBD:
* 1. Make # power/performance states dynamic. * 1. Make # power/performance states dynamic.
* 2. Includes support for _real_ performance states (not just throttle). * 2. Support duty_cycle values that span bit 4.
* 3. Support duty_cycle values that span bit 4. * 3. Optimize by having scheduler determine business instead of
* 4. Optimize by having scheduler determine business instead of * having us try to calculate it here.
* having us try to calculate it here. * 4. Need C1 timing -- must modify kernel (IRQ handler) to get this.
* 5. Need C1 timing -- must modify kernel (IRQ handler) to get this. * 5. Convert time values to ticks (initially) to avoid having to do
* 6. Convert time values to ticks (initially) to avoid having to do * the math (acpi_get_timer_duration).
* the math (acpi_get_timer_duration).
* 7. What is a good default value for the OS busy_metric?
* 8. Support both thermal and power limits.
* 9. Resolve PIIX4 BMISX errata issue (getting an I/O port value of 0).
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -43,6 +39,7 @@ ...@@ -43,6 +39,7 @@
#include <linux/pm.h> #include <linux/pm.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/delay.h>
#include "acpi_bus.h" #include "acpi_bus.h"
#include "acpi_drivers.h" #include "acpi_drivers.h"
...@@ -56,20 +53,22 @@ MODULE_LICENSE("GPL"); ...@@ -56,20 +53,22 @@ MODULE_LICENSE("GPL");
#define PREFIX "ACPI: " #define PREFIX "ACPI: "
#define ACPI_PROCESSOR_BUSY_METRIC 10
#define ACPI_PROCESSOR_MAX_POWER ACPI_C_STATE_COUNT #define ACPI_PROCESSOR_MAX_POWER ACPI_C_STATE_COUNT
#define ACPI_PROCESSOR_MAX_C2_LATENCY 100 #define ACPI_PROCESSOR_MAX_C2_LATENCY 100
#define ACPI_PROCESSOR_MAX_C3_LATENCY 1000 #define ACPI_PROCESSOR_MAX_C3_LATENCY 1000
#define ACPI_PROCESSOR_MAX_PERFORMANCE 4 #define ACPI_PROCESSOR_MAX_PERFORMANCE 8
#define ACPI_PROCESSOR_MAX_THROTTLING 16 #define ACPI_PROCESSOR_MAX_THROTTLING 16
#define ACPI_PROCESSOR_MAX_THROTTLE 500 /* 50% */ #define ACPI_PROCESSOR_MAX_THROTTLE 250 /* 25% */
#define ACPI_PROCESSOR_MAX_DUTY_WIDTH 4 #define ACPI_PROCESSOR_MAX_DUTY_WIDTH 4
const u32 POWER_OF_2[] = {1,2,4,8,16,32,64}; const u32 POWER_OF_2[] = {1,2,4,8,16,32,64};
#define ACPI_PROCESSOR_MAX_LIMIT 20 #define ACPI_PROCESSOR_LIMIT_USER 0
#define ACPI_PROCESSOR_LIMIT_THERMAL 1
static int acpi_processor_add (struct acpi_device *device); static int acpi_processor_add (struct acpi_device *device);
static int acpi_processor_remove (struct acpi_device *device, int type); static int acpi_processor_remove (struct acpi_device *device, int type);
...@@ -110,24 +109,35 @@ struct acpi_processor_power { ...@@ -110,24 +109,35 @@ struct acpi_processor_power {
int state; int state;
int default_state; int default_state;
u32 bm_activity; u32 bm_activity;
u32 busy_metric;
struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER]; struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];
}; };
/* Performance Management */ /* Performance Management */
struct acpi_pct_register {
u8 descriptor;
u16 length;
u8 space_id;
u8 bit_width;
u8 bit_offset;
u8 reserved;
u64 address;
} __attribute__ ((packed));
struct acpi_processor_px { struct acpi_processor_px {
u8 valid; acpi_integer core_frequency; /* megahertz */
u32 core_frequency; acpi_integer power; /* milliWatts */
u32 power; acpi_integer transition_latency; /* microseconds */
u32 transition_latency; acpi_integer bus_master_latency; /* microseconds */
u32 bus_master_latency; acpi_integer control; /* control value */
u32 control; acpi_integer status; /* success indicator */
u32 status;
}; };
struct acpi_processor_performance { struct acpi_processor_performance {
int state; int state;
int platform_limit;
u16 control_register;
u16 status_register;
int state_count; int state_count;
struct acpi_processor_px states[ACPI_PROCESSOR_MAX_PERFORMANCE]; struct acpi_processor_px states[ACPI_PROCESSOR_MAX_PERFORMANCE];
}; };
...@@ -136,7 +146,6 @@ struct acpi_processor_performance { ...@@ -136,7 +146,6 @@ struct acpi_processor_performance {
/* Throttling Control */ /* Throttling Control */
struct acpi_processor_tx { struct acpi_processor_tx {
u8 valid;
u16 power; u16 power;
u16 performance; u16 performance;
}; };
...@@ -153,37 +162,25 @@ struct acpi_processor_throttling { ...@@ -153,37 +162,25 @@ struct acpi_processor_throttling {
/* Limit Interface */ /* Limit Interface */
struct acpi_processor_lx { struct acpi_processor_lx {
u8 valid; int px; /* performace state */
u16 performance; int tx; /* throttle level */
int px;
int tx;
}; };
struct acpi_processor_limit { struct acpi_processor_limit {
int state; struct acpi_processor_lx state; /* current limit */
int state_count; struct acpi_processor_lx thermal; /* thermal limit */
struct { struct acpi_processor_lx user; /* user limit */
u8 valid;
u16 performance;
int px;
int tx;
} states[ACPI_PROCESSOR_MAX_LIMIT];
}; };
struct acpi_processor_flags { struct acpi_processor_flags {
u8 bm_control:1;
u8 power:1; u8 power:1;
u8 performance:1; u8 performance:1;
u8 throttling:1; u8 throttling:1;
u8 limit:1; u8 limit:1;
u8 reserved:3; u8 bm_control:1;
}; u8 bm_check:1;
u8 reserved:2;
struct acpi_processor_errata {
struct {
u8 reverse_throttle;
u32 bmisx;
} piix4;
}; };
struct acpi_processor { struct acpi_processor {
...@@ -191,15 +188,25 @@ struct acpi_processor { ...@@ -191,15 +188,25 @@ struct acpi_processor {
u32 acpi_id; u32 acpi_id;
u32 id; u32 id;
struct acpi_processor_flags flags; struct acpi_processor_flags flags;
struct acpi_processor_errata errata;
struct acpi_processor_power power; struct acpi_processor_power power;
struct acpi_processor_performance performance; struct acpi_processor_performance performance;
struct acpi_processor_throttling throttling; struct acpi_processor_throttling throttling;
struct acpi_processor_limit limit; struct acpi_processor_limit limit;
}; };
struct acpi_processor_errata {
u8 smp;
struct {
u8 throttle:1;
u8 fdma:1;
u8 reserved:6;
u32 bmisx;
} piix4;
};
static u8 acpi_processor_smp = 0; static struct acpi_processor *processors[NR_CPUS];
static struct acpi_processor_errata errata;
static void (*pm_idle_save)(void) = NULL;
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
...@@ -207,68 +214,138 @@ static u8 acpi_processor_smp = 0; ...@@ -207,68 +214,138 @@ static u8 acpi_processor_smp = 0;
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
int int
acpi_processor_get_errata ( acpi_processor_errata_piix4 (
struct acpi_processor *pr) struct pci_dev *dev)
{ {
struct pci_dev *dev = NULL; u8 rev = 0;
u8 value1 = 0;
u8 value2 = 0;
ACPI_FUNCTION_TRACE("acpi_processor_get_errata"); ACPI_FUNCTION_TRACE("acpi_processor_errata_piix4");
if (!pr) if (!dev)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
/* /*
* PIIX4 * Note that 'dev' references the PIIX4 ACPI Controller.
* -----
*/ */
dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, PCI_ANY_ID, dev);
if (dev) {
u8 rev = 0;
pci_read_config_byte(dev, PCI_REVISION_ID, &rev); pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PIIX4 ACPI rev %d\n", rev)); switch (rev) {
case 0:
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n"));
break;
case 1:
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n"));
break;
case 2:
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n"));
break;
case 3:
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n"));
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n"));
break;
}
switch (rev) { switch (rev) {
case 0: /* PIIX4 A-step */ case 0: /* PIIX4 A-step */
case 1: /* PIIX4 B-step */ case 1: /* PIIX4 B-step */
/* /*
* Workaround for reverse-notation on throttling states * See specification changes #13 ("Manual Throttle Duty Cycle")
* used by early PIIX4 models. * and #14 ("Enabling and Disabling Manual Throttle"), plus
*/ * erratum #5 ("STPCLK# Deassertion Time") from the January
pr->errata.piix4.reverse_throttle = 1; * 2002 PIIX4 specification update. Applies to only older
ACPI_DEBUG_PRINT((ACPI_DB_INFO, * PIIX4 models.
"Reverse-throttle errata enabled\n")); */
errata.piix4.throttle = 1;
case 2: /* PIIX4E */
case 3: /* PIIX4M */ case 2: /* PIIX4E */
/* case 3: /* PIIX4M */
* Workaround for errata #18 "C3 Power State/BMIDE and /*
* Type-F DMA Livelock" from the July 2001 PIIX4 * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA
* specification update. Applies to all PIIX4 models. * Livelock") from the January 2002 PIIX4 specification update.
*/ * Applies to all PIIX4 models.
/* TBD: Why is the bmisx value always ZERO? */ */
pr->errata.piix4.bmisx = pci_resource_start(dev, 4);
if (pr->errata.piix4.bmisx) /*
ACPI_DEBUG_PRINT((ACPI_DB_INFO, * BM-IDE
"BM-IDE errata enabled\n")); * ------
break; * Find the PIIX4 IDE Controller and get the Bus Master IDE
* Status register address. We'll use this later to read
* each IDE controller's DMA status to make sure we catch all
* DMA activity.
*/
dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82371AB,
PCI_ANY_ID, PCI_ANY_ID, NULL);
if (dev)
errata.piix4.bmisx = pci_resource_start(dev, 4);
/*
* Type-F DMA
* ----------
* Find the PIIX4 ISA Controller and read the Motherboard
* DMA controller's status to see if Type-F (Fast) DMA mode
* is enabled (bit 7) on either channel. Note that we'll
* disable C3 support if this is enabled, as some legacy
* devices won't operate well if fast DMA is disabled.
*/
dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82371AB_0,
PCI_ANY_ID, PCI_ANY_ID, NULL);
if (dev) {
pci_read_config_byte(dev, 0x76, &value1);
pci_read_config_byte(dev, 0x77, &value2);
if ((value1 & 0x80) || (value2 & 0x80))
errata.piix4.fdma = 1;
} }
break;
} }
if (errata.piix4.bmisx)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Bus master activity detection (BM-IDE) erratum enabled\n"));
if (errata.piix4.fdma)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Type-F DMA livelock erratum (C3 disabled)\n"));
return_VALUE(0); return_VALUE(0);
} }
int
acpi_processor_errata (
struct acpi_processor *pr)
{
int result = 0;
struct pci_dev *dev = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_errata");
if (!pr)
return_VALUE(-EINVAL);
/*
* PIIX4
*/
dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, PCI_ANY_ID, NULL);
if (dev)
result = acpi_processor_errata_piix4(dev);
return_VALUE(result);
}
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
Power Management Power Management
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
static struct acpi_processor *acpi_processor_list[NR_CPUS];
static void (*pm_idle_save)(void) = NULL;
static void static void
acpi_processor_power_activate ( acpi_processor_power_activate (
struct acpi_processor *pr, struct acpi_processor *pr,
...@@ -311,9 +388,8 @@ acpi_processor_idle (void) ...@@ -311,9 +388,8 @@ acpi_processor_idle (void)
u32 start_ticks = 0; u32 start_ticks = 0;
u32 end_ticks = 0; u32 end_ticks = 0;
u32 time_elapsed = 0; u32 time_elapsed = 0;
static unsigned long last_idle_jiffies = 0;
pr = acpi_processor_list[smp_processor_id()]; pr = processors[smp_processor_id()];
if (!pr) if (!pr)
return; return;
...@@ -323,55 +399,47 @@ acpi_processor_idle (void) ...@@ -323,55 +399,47 @@ acpi_processor_idle (void)
*/ */
__cli(); __cli();
next_state = pr->power.state; cx = &(pr->power.states[pr->power.state]);
/* /*
* Check OS Idleness: * Check BM Activity
* ------------------ * -----------------
* If the OS has been busy (hasn't called the idle handler in a while) * Check for bus mastering activity (if required), record, and check
* then automatically demote to the default power state (e.g. C1). * for demotion.
*
* TBD: Optimize by having scheduler determine business instead
* of having us try to calculate it here.
*/ */
if (pr->power.state != pr->power.default_state) { if (pr->flags.bm_check) {
if ((jiffies - last_idle_jiffies) >= pr->power.busy_metric) {
next_state = pr->power.default_state;
if (next_state != pr->power.state)
acpi_processor_power_activate(pr, next_state);
}
}
/*
* Log BM Activity:
* ----------------
* Read BM_STS and record its value for later use by C3 policy.
* (Note that we save the BM_STS values for the last 32 cycles).
*/
if (pr->flags.bm_control) {
pr->power.bm_activity <<= 1; pr->power.bm_activity <<= 1;
pr->power.bm_activity &= 0xFFFFFFFE;
if (acpi_hw_bit_register_read(ACPI_BITREG_BUS_MASTER_STATUS, ACPI_MTX_DO_NOT_LOCK)) { if (acpi_hw_bit_register_read(ACPI_BITREG_BUS_MASTER_STATUS, ACPI_MTX_DO_NOT_LOCK)) {
pr->power.bm_activity |= 1; pr->power.bm_activity++;
acpi_hw_bit_register_write(ACPI_BITREG_BUS_MASTER_STATUS, acpi_hw_bit_register_write(ACPI_BITREG_BUS_MASTER_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
1, ACPI_MTX_DO_NOT_LOCK);
} }
/* /*
* PIIX4 Errata: * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect
* ------------- * the true state of bus mastering activity; forcing us to
* This code is a workaround for errata #18 "C3 Power State/ * manually check the BMIDEA bit of each IDE channel.
* BMIDE and Type-F DMA Livelock" from the July '01 PIIX4
* specification update. Note that BM_STS doesn't always
* reflect the true state of bus mastering activity; forcing
* us to manually check the BMIDEA bit of each IDE channel.
*/ */
else if (pr->errata.piix4.bmisx) { else if (errata.piix4.bmisx) {
if ((inb_p(pr->errata.piix4.bmisx + 0x02) & 0x01) || if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01)
(inb_p(pr->errata.piix4.bmisx + 0x0A) & 0x01)) || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01))
pr->power.bm_activity |= 1; pr->power.bm_activity++;
}
/*
* Apply bus mastering demotion policy. Automatically demote
* to avoid a faulty transition. Note that the processor
* won't enter a low-power state during this call (to this
* funciton) but should upon the next.
*/
if (pr->power.bm_activity & cx->demotion.threshold.bm) {
__sti();
next_state = cx->demotion.state;
goto end;
} }
} }
cx = &(pr->power.states[pr->power.state]);
cx->usage++; cx->usage++;
/* /*
...@@ -416,7 +484,7 @@ acpi_processor_idle (void) ...@@ -416,7 +484,7 @@ acpi_processor_idle (void)
acpi_hw_bit_register_write(ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK); acpi_hw_bit_register_write(ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
/* See how long we're asleep for */ /* See how long we're asleep for */
start_ticks = inl(acpi_fadt.Xpm_tmr_blk.address); start_ticks = inl(acpi_fadt.Xpm_tmr_blk.address);
/* Invoke C2 */ /* Invoke C3 */
inb(pr->power.states[ACPI_STATE_C3].address); inb(pr->power.states[ACPI_STATE_C3].address);
/* Dummy op - must do something useless after P_LVL3 read */ /* Dummy op - must do something useless after P_LVL3 read */
end_ticks = inl(acpi_fadt.Xpm_tmr_blk.address); end_ticks = inl(acpi_fadt.Xpm_tmr_blk.address);
...@@ -439,6 +507,8 @@ acpi_processor_idle (void) ...@@ -439,6 +507,8 @@ acpi_processor_idle (void)
return; return;
} }
next_state = pr->power.state;
/* /*
* Promotion? * Promotion?
* ---------- * ----------
...@@ -451,12 +521,16 @@ acpi_processor_idle (void) ...@@ -451,12 +521,16 @@ acpi_processor_idle (void)
cx->promotion.count++; cx->promotion.count++;
cx->demotion.count = 0; cx->demotion.count = 0;
if (cx->promotion.count >= cx->promotion.threshold.count) { if (cx->promotion.count >= cx->promotion.threshold.count) {
if (pr->flags.bm_control) { if (pr->flags.bm_check) {
if (!(pr->power.bm_activity & cx->promotion.threshold.bm)) if (!(pr->power.bm_activity & cx->promotion.threshold.bm)) {
next_state = cx->promotion.state; next_state = cx->promotion.state;
goto end;
}
} }
else else {
next_state = cx->promotion.state; next_state = cx->promotion.state;
goto end;
}
} }
} }
} }
...@@ -466,21 +540,20 @@ acpi_processor_idle (void) ...@@ -466,21 +540,20 @@ acpi_processor_idle (void)
* --------- * ---------
* Track the number of shorts (time asleep is less than time threshold) * Track the number of shorts (time asleep is less than time threshold)
* and demote when the usage threshold is reached. Note that bus * and demote when the usage threshold is reached. Note that bus
* mastering activity may cause immediate demotions. * mastering demotions are checked prior to state transitions (above).
*/ */
if (cx->demotion.state) { if (cx->demotion.state) {
if (time_elapsed < cx->demotion.threshold.time) { if (time_elapsed < cx->demotion.threshold.time) {
cx->demotion.count++; cx->demotion.count++;
cx->promotion.count = 0; cx->promotion.count = 0;
if (cx->demotion.count >= cx->demotion.threshold.count) if (cx->demotion.count >= cx->demotion.threshold.count) {
next_state = cx->demotion.state;
}
if (pr->flags.bm_control) {
if (pr->power.bm_activity & cx->demotion.threshold.bm)
next_state = cx->demotion.state; next_state = cx->demotion.state;
goto end;
}
} }
} }
end:
/* /*
* New Cx State? * New Cx State?
* ------------- * -------------
...@@ -490,14 +563,6 @@ acpi_processor_idle (void) ...@@ -490,14 +563,6 @@ acpi_processor_idle (void)
if (next_state != pr->power.state) if (next_state != pr->power.state)
acpi_processor_power_activate(pr, next_state); acpi_processor_power_activate(pr, next_state);
/*
* Track OS Idleness:
* ------------------
* Record a jiffies timestamp to compute time elapsed between calls
* to the idle handler.
*/
last_idle_jiffies = jiffies;
return; return;
} }
...@@ -520,47 +585,31 @@ acpi_processor_set_power_policy ( ...@@ -520,47 +585,31 @@ acpi_processor_set_power_policy (
if (!pr) if (!pr)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
/*
* The Busy Metric is used to determine when the OS has been busy
* and thus when policy should return to using the default Cx state
* (e.g. C1). On Linux we use the number of jiffies (scheduler
* quantums) that transpire between calls to the idle handler.
*
* TBD: What is a good value for the OS busy_metric?
*/
pr->power.busy_metric = 2;
/* /*
* C0/C1 * C0/C1
* ----- * -----
*/ */
if (pr->power.states[ACPI_STATE_C1].valid) { pr->power.state = ACPI_STATE_C1;
pr->power.state = ACPI_STATE_C1; pr->power.default_state = ACPI_STATE_C1;
pr->power.default_state = ACPI_STATE_C1;
}
else {
pr->power.state = ACPI_STATE_C0;
pr->power.default_state = ACPI_STATE_C0;
return_VALUE(0);
}
/* /*
* C1/C2 * C1/C2
* ----- * -----
* Set the default C1 promotion and C2 demotion policies, where we * Set the default C1 promotion and C2 demotion policies, where we
* promote from C1 to C2 anytime we're asleep in C1 for longer than * promote from C1 to C2 after several (10) successive C1 transitions,
* two times the C2 latency (to amortize cost of transitions). Demote * as we cannot (currently) measure the time spent in C1. Demote from
* from C2 to C1 anytime we're asleep in C2 for less than this time. * C2 to C1 after experiencing several (3) 'shorts' (time spent in C2
* is less than the C2 transtional latency).
*/ */
if (pr->power.states[ACPI_STATE_C2].valid) { if (pr->power.states[ACPI_STATE_C2].valid) {
pr->power.states[ACPI_STATE_C1].promotion.threshold.count = 10; pr->power.states[ACPI_STATE_C1].promotion.threshold.count = 10;
pr->power.states[ACPI_STATE_C1].promotion.threshold.time = pr->power.states[ACPI_STATE_C1].promotion.threshold.time =
(2 * pr->power.states[ACPI_STATE_C2].latency); pr->power.states[ACPI_STATE_C2].latency;
pr->power.states[ACPI_STATE_C1].promotion.state = ACPI_STATE_C2; pr->power.states[ACPI_STATE_C1].promotion.state = ACPI_STATE_C2;
pr->power.states[ACPI_STATE_C2].demotion.threshold.count = 1; pr->power.states[ACPI_STATE_C2].demotion.threshold.count = 3;
pr->power.states[ACPI_STATE_C2].demotion.threshold.time = pr->power.states[ACPI_STATE_C2].demotion.threshold.time =
(2 * pr->power.states[ACPI_STATE_C2].latency); pr->power.states[ACPI_STATE_C2].latency;
pr->power.states[ACPI_STATE_C2].demotion.state = ACPI_STATE_C1; pr->power.states[ACPI_STATE_C2].demotion.state = ACPI_STATE_C1;
} }
...@@ -576,13 +625,13 @@ acpi_processor_set_power_policy ( ...@@ -576,13 +625,13 @@ acpi_processor_set_power_policy (
(pr->power.states[ACPI_STATE_C3].valid)) { (pr->power.states[ACPI_STATE_C3].valid)) {
pr->power.states[ACPI_STATE_C2].promotion.threshold.count = 1; pr->power.states[ACPI_STATE_C2].promotion.threshold.count = 1;
pr->power.states[ACPI_STATE_C2].promotion.threshold.time = pr->power.states[ACPI_STATE_C2].promotion.threshold.time =
(2 * pr->power.states[ACPI_STATE_C3].latency); pr->power.states[ACPI_STATE_C3].latency;
pr->power.states[ACPI_STATE_C2].promotion.threshold.bm = 0x0F; pr->power.states[ACPI_STATE_C2].promotion.threshold.bm = 0x0F;
pr->power.states[ACPI_STATE_C2].promotion.state = ACPI_STATE_C3; pr->power.states[ACPI_STATE_C2].promotion.state = ACPI_STATE_C3;
pr->power.states[ACPI_STATE_C3].demotion.threshold.count = 1; pr->power.states[ACPI_STATE_C3].demotion.threshold.count = 1;
pr->power.states[ACPI_STATE_C3].demotion.threshold.time = pr->power.states[ACPI_STATE_C3].demotion.threshold.time =
(2 * pr->power.states[ACPI_STATE_C3].latency); pr->power.states[ACPI_STATE_C3].latency;
pr->power.states[ACPI_STATE_C3].demotion.threshold.bm = 0x0F; pr->power.states[ACPI_STATE_C3].demotion.threshold.bm = 0x0F;
pr->power.states[ACPI_STATE_C3].demotion.state = ACPI_STATE_C2; pr->power.states[ACPI_STATE_C3].demotion.state = ACPI_STATE_C2;
} }
...@@ -614,7 +663,7 @@ acpi_processor_get_power_info ( ...@@ -614,7 +663,7 @@ acpi_processor_get_power_info (
* -- * --
* This state exists only as filler in our array. * This state exists only as filler in our array.
*/ */
pr->power.states[ACPI_STATE_C0].valid = TRUE; pr->power.states[ACPI_STATE_C0].valid = 1;
/* /*
* C1 * C1
...@@ -623,7 +672,7 @@ acpi_processor_get_power_info ( ...@@ -623,7 +672,7 @@ acpi_processor_get_power_info (
* *
* TBD: What about PROC_C1? * TBD: What about PROC_C1?
*/ */
pr->power.states[ACPI_STATE_C1].valid = TRUE; pr->power.states[ACPI_STATE_C1].valid = 1;
/* /*
* C2 * C2
...@@ -633,32 +682,82 @@ acpi_processor_get_power_info ( ...@@ -633,32 +682,82 @@ acpi_processor_get_power_info (
* TBD: Support for C2 on MP (P_LVL2_UP). * TBD: Support for C2 on MP (P_LVL2_UP).
*/ */
if (pr->power.states[ACPI_STATE_C2].address) { if (pr->power.states[ACPI_STATE_C2].address) {
pr->power.states[ACPI_STATE_C2].latency = acpi_fadt.plvl2_lat; pr->power.states[ACPI_STATE_C2].latency = acpi_fadt.plvl2_lat;
if (acpi_fadt.plvl2_lat > ACPI_PROCESSOR_MAX_C2_LATENCY)
/*
* C2 latency must be less than or equal to 100 microseconds.
*/
if (acpi_fadt.plvl2_lat >= ACPI_PROCESSOR_MAX_C2_LATENCY)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"C2 latency too large [%d]\n", "C2 latency too large [%d]\n",
acpi_fadt.plvl2_lat)); acpi_fadt.plvl2_lat));
else if (!acpi_processor_smp) /*
pr->power.states[ACPI_STATE_C2].valid = TRUE; * Only support C2 on UP systems (see TBD above).
*/
else if (errata.smp)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"C2 not supported in SMP mode\n"));
/*
* Otherwise we've met all of our C2 requirements.
*/
else
pr->power.states[ACPI_STATE_C2].valid = 1;
} }
/* /*
* C3 * C3
* -- * --
* We're (currently) only supporting C3 on UP systems that include * TBD: Investigate use of WBINVD on UP/SMP system in absence of
* bus mastering arbitration control. Note that this method of * bm_control.
* maintaining cache coherency (disabling of bus mastering) cannot be
* used on SMP systems, and flushing caches (e.g. WBINVD) is simply
* too costly (at this time).
*/ */
if (pr->power.states[ACPI_STATE_C3].address) { if (pr->power.states[ACPI_STATE_C3].address) {
pr->power.states[ACPI_STATE_C3].latency = acpi_fadt.plvl3_lat; pr->power.states[ACPI_STATE_C3].latency = acpi_fadt.plvl3_lat;
if (acpi_fadt.plvl3_lat > ACPI_PROCESSOR_MAX_C3_LATENCY)
/*
* C3 latency must be less than or equal to 1000 microseconds.
*/
if (acpi_fadt.plvl3_lat >= ACPI_PROCESSOR_MAX_C3_LATENCY)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"C3 latency too large [%d]\n", "C3 latency too large [%d]\n",
acpi_fadt.plvl3_lat)); acpi_fadt.plvl3_lat));
else if (!acpi_processor_smp && pr->flags.bm_control) /*
* Only support C3 when bus mastering arbitration control
* is present (able to disable bus mastering to maintain
* cache coherency while in C3).
*/
else if (!pr->flags.bm_control)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"C3 support requires bus mastering control\n"));
/*
* Only support C3 on UP systems, as bm_control is only viable
* on a UP system and flushing caches (e.g. WBINVD) is simply
* too costly (at this time).
*/
else if (errata.smp)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"C3 not supported in SMP mode\n"));
/*
* PIIX4 Erratum #18: We don't support C3 when Type-F (fast)
* DMA transfers are used by any ISA device to avoid livelock.
* Note that we could disable Type-F DMA (as recommended by
* the erratum), but this is known to disrupt certain ISA
* devices thus we take the conservative approach.
*/
else if (errata.piix4.fdma) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"C3 not supported on PIIX4 with Type-F DMA\n"));
}
/*
* Otherwise we've met all of our C3 requirements. Enable
* checking of bus mastering status (bm_check) so we can
* use this in our C3 policy.
*/
else {
pr->power.states[ACPI_STATE_C3].valid = 1; pr->power.states[ACPI_STATE_C3].valid = 1;
pr->flags.bm_check = 1;
}
} }
/* /*
...@@ -678,7 +777,7 @@ acpi_processor_get_power_info ( ...@@ -678,7 +777,7 @@ acpi_processor_get_power_info (
* manageable'. Note that there's really no policy involved for * manageable'. Note that there's really no policy involved for
* when only C1 is supported. * when only C1 is supported.
*/ */
if (pr->power.states[ACPI_STATE_C2].valid if (pr->power.states[ACPI_STATE_C2].valid
|| pr->power.states[ACPI_STATE_C3].valid) || pr->power.states[ACPI_STATE_C3].valid)
pr->flags.power = 1; pr->flags.power = 1;
...@@ -690,30 +789,214 @@ acpi_processor_get_power_info ( ...@@ -690,30 +789,214 @@ acpi_processor_get_power_info (
Performance Management Performance Management
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
static int static int
acpi_processor_get_performance ( acpi_processor_get_platform_limit (
struct acpi_processor *pr) struct acpi_processor* pr)
{ {
ACPI_FUNCTION_TRACE("acpi_processor_get_performance_state"); acpi_status status = 0;
unsigned long ppc = 0;
ACPI_FUNCTION_TRACE("acpi_processor_get_platform_limit");
if (!pr) if (!pr)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
if (!pr->flags.performance) /*
return_VALUE(0); * _PPC indicates the maximum state currently supported by the platform
* (e.g. 0 = states 0..n; 1 = states 1..n; etc.
*/
status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc);
if(ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PPC\n"));
return_VALUE(-ENODEV);
}
/* TBD */ pr->performance.platform_limit = (int) ppc;
return_VALUE(0); return_VALUE(0);
} }
static int
acpi_processor_get_performance_control (
struct acpi_processor *pr)
{
int result = 0;
acpi_status status = 0;
acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_object *pct = NULL;
acpi_object obj = {0};
struct acpi_pct_register *reg = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_get_performance_control");
status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
if(ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PCT\n"));
return_VALUE(-ENODEV);
}
pct = (acpi_object *) buffer.pointer;
if (!pct || (pct->type != ACPI_TYPE_PACKAGE)
|| (pct->package.count != 2)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PCT data\n"));
result = -EFAULT;
goto end;
}
/*
* control_register
*/
obj = pct->package.elements[0];
if ((obj.type != ACPI_TYPE_BUFFER)
|| (obj.buffer.length < sizeof(struct acpi_pct_register))
|| (obj.buffer.pointer == NULL)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Invalid _PCT data (control_register)\n"));
result = -EFAULT;
goto end;
}
reg = (struct acpi_pct_register *) (obj.buffer.pointer);
if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unsupported address space [%d] (control_register)\n",
(u32) reg->space_id));
result = -EFAULT;
goto end;
}
pr->performance.control_register = (u16) reg->address;
/*
* status_register
*/
obj = pct->package.elements[1];
if ((obj.type != ACPI_TYPE_BUFFER)
|| (obj.buffer.length < sizeof(struct acpi_pct_register))
|| (obj.buffer.pointer == NULL)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Invalid _PCT data (status_register)\n"));
result = -EFAULT;
goto end;
}
reg = (struct acpi_pct_register *) (obj.buffer.pointer);
if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unsupported address space [%d] (status_register)\n",
(u32) reg->space_id));
result = -EFAULT;
goto end;
}
pr->performance.status_register = (u16) reg->address;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"control_register[0x%04x] status_register[0x%04x]\n",
pr->performance.control_register,
pr->performance.status_register));
end:
kfree(buffer.pointer);
return_VALUE(result);
}
static int
acpi_processor_get_performance_states (
struct acpi_processor* pr)
{
int result = 0;
acpi_status status = AE_OK;
acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_buffer format = {sizeof("NNNNNN"), "NNNNNN"};
acpi_buffer state = {0, NULL};
acpi_object *pss = NULL;
int i = 0;
ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states");
status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
if(ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PSS\n"));
return_VALUE(-ENODEV);
}
pss = (acpi_object *) buffer.pointer;
if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
result = -EFAULT;
goto end;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n",
pss->package.count));
if (pss->package.count > ACPI_PROCESSOR_MAX_PERFORMANCE) {
pr->performance.state_count = ACPI_PROCESSOR_MAX_PERFORMANCE;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Limiting number of states to max (%d)\n",
ACPI_PROCESSOR_MAX_PERFORMANCE));
}
else
pr->performance.state_count = pss->package.count;
if (pr->performance.state_count > 1)
pr->flags.performance = 1;
for (i = 0; i < pr->performance.state_count; i++) {
struct acpi_processor_px *px = &(pr->performance.states[i]);
state.length = sizeof(struct acpi_processor_px);
state.pointer = px;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
status = acpi_extract_package(&(pss->package.elements[i]),
&format, &state);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
result = -EFAULT;
goto end;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
i,
(u32) px->core_frequency,
(u32) px->power,
(u32) px->transition_latency,
(u32) px->bus_master_latency,
(u32) px->control,
(u32) px->status));
}
end:
kfree(buffer.pointer);
return_VALUE(result);
}
static int static int
acpi_processor_set_performance ( acpi_processor_set_performance (
struct acpi_processor *pr, struct acpi_processor *pr,
int state) int state)
{ {
ACPI_FUNCTION_TRACE("acpi_processor_set_performance_state"); u16 port = 0;
u8 value = 0;
int i = 0;
ACPI_FUNCTION_TRACE("acpi_processor_set_performance");
if (!pr) if (!pr)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
...@@ -721,13 +1004,71 @@ acpi_processor_set_performance ( ...@@ -721,13 +1004,71 @@ acpi_processor_set_performance (
if (!pr->flags.performance) if (!pr->flags.performance)
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
if (state >= pr->performance.state_count) if (state >= pr->performance.state_count) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Invalid target state (P%d)\n", state));
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
}
if (state < pr->performance.platform_limit) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Platform limit (P%d) overrides target state (P%d)\n",
pr->performance.platform_limit, state));
return_VALUE(-ENODEV);
}
if (state == pr->performance.state) if (state == pr->performance.state) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Already at target state (P%d)\n", state));
return_VALUE(0); return_VALUE(0);
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Transitioning from P%d to P%d\n",
pr->performance.state, state));
/*
* First we write the target state's 'control' value to the
* control_register.
*/
port = pr->performance.control_register;
value = (u16) pr->performance.states[state].control;
/* TBD */ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Writing 0x%02x to port 0x%04x\n", value, port));
outb(value, port);
/*
* Then we read the 'status_register' and compare the value with the
* target state's 'status' to make sure the transition was successful.
* Note that we'll poll for up to 1ms (100 cycles of 10us) before
* giving up.
*/
port = pr->performance.status_register;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Looking for 0x%02x from port 0x%04x\n",
(u8) pr->performance.states[state].status, port));
for (i=0; i<100; i++) {
value = inb(port);
if (value == (u8) pr->performance.states[state].status)
break;
udelay(10);
}
if (value != pr->performance.states[state].status) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Transition failed\n"));
return_VALUE(-ENODEV);
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Transition successful after %d microseconds\n",
i * 10));
pr->performance.state = state;
return_VALUE(0); return_VALUE(0);
} }
...@@ -738,13 +1079,37 @@ acpi_processor_get_performance_info ( ...@@ -738,13 +1079,37 @@ acpi_processor_get_performance_info (
struct acpi_processor *pr) struct acpi_processor *pr)
{ {
int result = 0; int result = 0;
acpi_status status = AE_OK;
acpi_handle handle = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_get_performance_info"); ACPI_FUNCTION_TRACE("acpi_processor_get_performance_info");
if (!pr) if (!pr)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
/* TBD: Support ACPI 2.0 objects */ status = acpi_get_handle(pr->handle, "_PCT", &handle);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"ACPI-based processor performance control unavailable\n"));
return_VALUE(0);
}
result = acpi_processor_get_performance_control(pr);
if (0 != result)
return_VALUE(result);
result = acpi_processor_get_performance_states(pr);
if (0 != result)
return_VALUE(result);
result = acpi_processor_get_platform_limit(pr);
if (0 != result)
return_VALUE(result);
/*
* TBD: Don't trust the latency values we get from BIOS, but rather
* measure the latencies during run-time (e.g. get_latencies).
*/
return_VALUE(0); return_VALUE(0);
} }
...@@ -776,32 +1141,29 @@ acpi_processor_get_throttling ( ...@@ -776,32 +1141,29 @@ acpi_processor_get_throttling (
__cli(); __cli();
duty_mask = pr->throttling.state_count - 1; duty_mask = pr->throttling.state_count - 1;
duty_mask <<= pr->throttling.duty_offset; duty_mask <<= pr->throttling.duty_offset;
value = inb(pr->throttling.address); value = inl(pr->throttling.address);
/* /*
* Compute the current throttling state when throttling is enabled * Compute the current throttling state when throttling is enabled
* (bit 4 is on). Note that the reverse_throttling flag indicates * (bit 4 is on).
* that the duty_value is opposite of that specified by ACPI.
*/ */
if (value & 0x10) { if (value & 0x10) {
duty_value = value & duty_mask; duty_value = value & duty_mask;
duty_value >>= pr->throttling.duty_offset; duty_value >>= pr->throttling.duty_offset;
if (duty_value) { if (duty_value)
if (pr->errata.piix4.reverse_throttle) state = pr->throttling.state_count-duty_value;
state = duty_value;
else
state = pr->throttling.state_count-duty_value;
}
} }
pr->throttling.state = state; pr->throttling.state = state;
__sti(); __sti();
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Throttling state is T%d (%d%% throttling applied)\n", ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Throttling state is T%d (%d%% throttling applied)\n",
state, pr->throttling.states[state].performance)); state, pr->throttling.states[state].performance));
return_VALUE(0); return_VALUE(0);
...@@ -825,7 +1187,7 @@ acpi_processor_set_throttling ( ...@@ -825,7 +1187,7 @@ acpi_processor_set_throttling (
if ((state < 0) || (state > (pr->throttling.state_count - 1))) if ((state < 0) || (state > (pr->throttling.state_count - 1)))
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
if (!pr->flags.throttling || !pr->throttling.states[state].valid) if (!pr->flags.throttling)
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
if (state == pr->throttling.state) if (state == pr->throttling.state)
...@@ -834,20 +1196,16 @@ acpi_processor_set_throttling ( ...@@ -834,20 +1196,16 @@ acpi_processor_set_throttling (
__cli(); __cli();
/* /*
* Calculate the duty_value and duty_mask. Note that the * Calculate the duty_value and duty_mask.
* reverse_throttling flag indicates that the duty_value is
* opposite of that specified by ACPI.
*/ */
if (state) { if (state) {
if (pr->errata.piix4.reverse_throttle) duty_value = pr->throttling.state_count - state;
duty_value = state;
else
duty_value = pr->throttling.state_count - state;
duty_value <<= pr->throttling.duty_offset; duty_value <<= pr->throttling.duty_offset;
/* Used to clear all duty_value bits */ /* Used to clear all duty_value bits */
duty_mask = pr->performance.state_count - 1; duty_mask = pr->throttling.state_count - 1;
duty_mask <<= acpi_fadt.duty_offset; duty_mask <<= acpi_fadt.duty_offset;
duty_mask = ~duty_mask; duty_mask = ~duty_mask;
} }
...@@ -856,7 +1214,7 @@ acpi_processor_set_throttling ( ...@@ -856,7 +1214,7 @@ acpi_processor_set_throttling (
* Disable throttling by writing a 0 to bit 4. Note that we must * Disable throttling by writing a 0 to bit 4. Note that we must
* turn it off before you can change the duty_value. * turn it off before you can change the duty_value.
*/ */
value = inb(pr->throttling.address); value = inl(pr->throttling.address);
if (value & 0x10) { if (value & 0x10) {
value &= 0xFFFFFFEF; value &= 0xFFFFFFEF;
outl(value, pr->throttling.address); outl(value, pr->throttling.address);
...@@ -879,8 +1237,9 @@ acpi_processor_set_throttling ( ...@@ -879,8 +1237,9 @@ acpi_processor_set_throttling (
__sti(); __sti();
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Throttling state set to T%d (%d%%)\n", ACPI_DEBUG_PRINT((ACPI_DB_INFO,
state, (pr->throttling.states[state].performance?pr->throttling.states[state].performance/10:0))); "Throttling state set to T%d (%d%%)\n", state,
(pr->throttling.states[state].performance?pr->throttling.states[state].performance/10:0)));
return_VALUE(0); return_VALUE(0);
} }
...@@ -912,13 +1271,24 @@ acpi_processor_get_throttling_info ( ...@@ -912,13 +1271,24 @@ acpi_processor_get_throttling_info (
return_VALUE(0); return_VALUE(0);
} }
else if (!pr->throttling.duty_width) { else if (!pr->throttling.duty_width) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid duty_width\n")); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n"));
return_VALUE(-EFAULT); return_VALUE(0);
} }
/* TBD: Support duty_cycle values that span bit 4. */ /* TBD: Support duty_cycle values that span bit 4. */
else if ((pr->throttling.duty_offset else if ((pr->throttling.duty_offset
+ pr->throttling.duty_width) > 4) { + pr->throttling.duty_width) > 4) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "duty_cycle spans bit 4\n")); ACPI_DEBUG_PRINT((ACPI_DB_WARN, "duty_cycle spans bit 4\n"));
return_VALUE(0);
}
/*
* PIIX4 Errata: We don't support throttling on the original PIIX4.
* This shouldn't be an issue as few (if any) mobile systems ever
* used this part.
*/
if (errata.piix4.throttle) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Throttling not supported on PIIX4 A- or B-step\n"));
return_VALUE(0); return_VALUE(0);
} }
...@@ -935,7 +1305,6 @@ acpi_processor_get_throttling_info ( ...@@ -935,7 +1305,6 @@ acpi_processor_get_throttling_info (
for (i=0; i<pr->throttling.state_count; i++) { for (i=0; i<pr->throttling.state_count; i++) {
pr->throttling.states[i].performance = step * i; pr->throttling.states[i].performance = step * i;
pr->throttling.states[i].power = step * i; pr->throttling.states[i].power = step * i;
pr->throttling.states[i].valid = 1;
} }
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n", ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n",
...@@ -973,19 +1342,76 @@ acpi_processor_get_throttling_info ( ...@@ -973,19 +1342,76 @@ acpi_processor_get_throttling_info (
Limit Interface Limit Interface
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
static int
acpi_processor_apply_limit (
struct acpi_processor* pr)
{
int result = 0;
u16 px = 0;
u16 tx = 0;
ACPI_FUNCTION_TRACE("acpi_processor_apply_limit");
if (!pr)
return_VALUE(-EINVAL);
if (!pr->flags.limit)
return_VALUE(-ENODEV);
if (pr->flags.performance) {
px = pr->performance.platform_limit;
if (pr->limit.user.px > px)
px = pr->limit.user.px;
if (pr->limit.thermal.px > px)
px = pr->limit.thermal.px;
result = acpi_processor_set_performance(pr, px);
if (0 != result)
goto end;
}
if (pr->flags.throttling) {
if (pr->limit.user.tx > tx)
tx = pr->limit.user.tx;
if (pr->limit.thermal.tx > tx)
tx = pr->limit.thermal.tx;
result = acpi_processor_set_throttling(pr, tx);
if (0 != result)
goto end;
}
pr->limit.state.px = px;
pr->limit.state.tx = tx;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d] limit set to (P%d:T%d)\n",
pr->id,
pr->limit.state.px,
pr->limit.state.tx));
end:
if (0 != result)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to set limit\n"));
return_VALUE(result);
}
int int
acpi_processor_set_limit ( acpi_processor_set_thermal_limit (
acpi_handle handle, acpi_handle handle,
int type, int type)
int *state)
{ {
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 px = 0;
int tx = 0;
ACPI_FUNCTION_TRACE("acpi_processor_set_limit"); ACPI_FUNCTION_TRACE("acpi_processor_set_thermal_limit");
if (!state) if ((type < ACPI_PROCESSOR_LIMIT_NONE)
|| (type > ACPI_PROCESSOR_LIMIT_DECREMENT))
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
result = acpi_bus_get_device(handle, &device); result = acpi_bus_get_device(handle, &device);
...@@ -999,56 +1425,75 @@ acpi_processor_set_limit ( ...@@ -999,56 +1425,75 @@ acpi_processor_set_limit (
if (!pr->flags.limit) if (!pr->flags.limit)
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
/* Thermal limits are always relative to the current Px/Tx state. */
if (pr->flags.performance)
pr->limit.thermal.px = pr->performance.state;
if (pr->flags.throttling)
pr->limit.thermal.tx = pr->throttling.state;
/*
* Our default policy is to only use throttling at the lowest
* performance state.
*/
switch (type) { switch (type) {
case ACPI_PROCESSOR_LIMIT_NONE: case ACPI_PROCESSOR_LIMIT_NONE:
*state = 0; px = 0;
pr->limit.state = 0; tx = 0;
break; break;
case ACPI_PROCESSOR_LIMIT_INCREMENT: case ACPI_PROCESSOR_LIMIT_INCREMENT:
if (*state == (pr->limit.state_count - 1)) { if (pr->flags.performance) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Already at maximum limit state\n")); if (px == (pr->performance.state_count - 1))
return_VALUE(1); ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"At maximum performance state\n"));
else {
px++;
goto end;
}
}
if (pr->flags.throttling) {
if (tx == (pr->throttling.state_count - 1))
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"At maximum throttling state\n"));
else
tx++;
} }
*state = ++pr->limit.state;
break; break;
case ACPI_PROCESSOR_LIMIT_DECREMENT: case ACPI_PROCESSOR_LIMIT_DECREMENT:
if (*state == 0) { if (pr->flags.performance) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Already at minimum limit state\n")); if (px == pr->performance.platform_limit)
return_VALUE(1); ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"At minimum performance state\n"));
else {
px--;
goto end;
}
}
if (pr->flags.throttling) {
if (tx == 0)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"At minimum throttling state\n"));
else
tx--;
} }
*state = --pr->limit.state;
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid limit type [%d]\n",
type));
*state = pr->limit.state;
return_VALUE(-EINVAL);
break; break;
} }
if (pr->flags.performance) {
result = acpi_processor_set_performance(pr,
pr->limit.states[*state].px);
if (0 != result)
goto end;
}
if (pr->flags.throttling) {
result = acpi_processor_set_throttling(pr,
pr->limit.states[*state].tx);
if (0 != result)
goto end;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d] limit now %d%% (P%d:T%d)\n",
pr->id,
pr->limit.states[*state].performance / 10,
pr->limit.states[*state].px,
pr->limit.states[*state].tx));
end: end:
pr->limit.thermal.px = px;
pr->limit.thermal.tx = tx;
result = acpi_processor_apply_limit(pr);
if (0 != result) if (0 != result)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to set limit\n")); ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to set thermal limit\n"));
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Thermal limit now (P%d:T%d)\n",
pr->limit.thermal.px,
pr->limit.thermal.tx));
return_VALUE(result); return_VALUE(result);
} }
...@@ -1058,58 +1503,12 @@ static int ...@@ -1058,58 +1503,12 @@ static int
acpi_processor_get_limit_info ( acpi_processor_get_limit_info (
struct acpi_processor *pr) struct acpi_processor *pr)
{ {
int i = 0;
int px = 0;
int tx = 0;
int base_perf = 1000;
int throttle = 0;
ACPI_FUNCTION_TRACE("acpi_processor_get_limit_info"); ACPI_FUNCTION_TRACE("acpi_processor_get_limit_info");
if (!pr) if (!pr)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
/* if (pr->flags.performance || pr->flags.throttling)
* Limit
* -----
* Our default policy is to only use throttling at the lowest
* performance state. This is enforced by adding throttling states
* after perormance states. We also only expose throttling states
* less than the maximum throttle value (e.g. 50%).
*/
if (pr->flags.performance) {
for (px=0; px<pr->performance.state_count; px++) {
if (!pr->performance.states[px].valid)
continue;
i = pr->limit.state_count++;
pr->limit.states[i].px = px;
pr->limit.states[i].performance = (pr->performance.states[px].core_frequency / pr->performance.states[0].core_frequency) * 1000;
pr->limit.states[i].valid = 1;
}
px--;
base_perf = pr->limit.states[i].performance;
}
if (pr->flags.throttling) {
for (tx=0; tx<pr->throttling.state_count; tx++) {
if (!pr->throttling.states[tx].valid)
continue;
if (pr->throttling.states[tx].performance > ACPI_PROCESSOR_MAX_THROTTLE)
continue;
i = pr->limit.state_count++;
pr->limit.states[i].px = px;
pr->limit.states[i].tx = tx;
throttle = (base_perf * pr->throttling.states[tx].performance) / 1000;
pr->limit.states[i].performance = base_perf - throttle;
pr->limit.states[i].valid = 1;
}
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d limit states\n",
pr->limit.state_count));
if (pr->limit.state_count)
pr->flags.limit = 1; pr->flags.limit = 1;
return_VALUE(0); return_VALUE(0);
...@@ -1278,11 +1677,11 @@ acpi_processor_read_performance ( ...@@ -1278,11 +1677,11 @@ acpi_processor_read_performance (
p += sprintf(p, "states:\n"); p += sprintf(p, "states:\n");
for (i=0; i<pr->performance.state_count; i++) for (i=0; i<pr->performance.state_count; i++)
p += sprintf(p, " %cP%d: %d Mhz, %d mW %s\n", p += sprintf(p, " %cP%d: %d Mhz, %d mW, %d uS\n",
(i == pr->performance.state?'*':' '), i, (i == pr->performance.state?'*':' '), i,
pr->performance.states[i].core_frequency, (u32) pr->performance.states[i].core_frequency,
pr->performance.states[i].power, (u32) pr->performance.states[i].power,
(pr->performance.states[i].valid?"":"(disabled)")); (u32) pr->performance.states[i].transition_latency);
end: end:
len = (p - page); len = (p - page);
...@@ -1316,8 +1715,8 @@ acpi_processor_write_performance ( ...@@ -1316,8 +1715,8 @@ acpi_processor_write_performance (
return_VALUE(-EFAULT); return_VALUE(-EFAULT);
state_string[count] = '\0'; state_string[count] = '\0';
result = acpi_processor_set_throttling(pr, result = acpi_processor_set_performance(pr,
simple_strtoul(state_string, NULL, 0)); simple_strtoul(state_string, NULL, 0));
if (0 != result) if (0 != result)
return_VALUE(result); return_VALUE(result);
...@@ -1339,6 +1738,7 @@ acpi_processor_read_throttling ( ...@@ -1339,6 +1738,7 @@ acpi_processor_read_throttling (
char *p = page; char *p = page;
int len = 0; int len = 0;
int i = 0; int i = 0;
int result = 0;
ACPI_FUNCTION_TRACE("acpi_processor_read_throttling"); ACPI_FUNCTION_TRACE("acpi_processor_read_throttling");
...@@ -1350,6 +1750,13 @@ acpi_processor_read_throttling ( ...@@ -1350,6 +1750,13 @@ acpi_processor_read_throttling (
goto end; goto end;
} }
result = acpi_processor_get_throttling(pr);
if (result) {
p += sprintf(p, "Could not determine current throttling state.\n");
goto end;
}
p += sprintf(p, "state count: %d\n", p += sprintf(p, "state count: %d\n",
pr->throttling.state_count); pr->throttling.state_count);
...@@ -1359,10 +1766,9 @@ acpi_processor_read_throttling ( ...@@ -1359,10 +1766,9 @@ acpi_processor_read_throttling (
p += sprintf(p, "states:\n"); p += sprintf(p, "states:\n");
for (i=0; i<pr->throttling.state_count; i++) for (i=0; i<pr->throttling.state_count; i++)
p += sprintf(p, " %cT%d: %02d%% %s\n", p += sprintf(p, " %cT%d: %02d%%\n",
(i == pr->throttling.state?'*':' '), i, (i == pr->throttling.state?'*':' '), i,
(pr->throttling.states[i].performance?pr->throttling.states[i].performance/10:0), (pr->throttling.states[i].performance?pr->throttling.states[i].performance/10:0));
(pr->throttling.states[i].valid?"":"(disabled)"));
end: end:
len = (p - page); len = (p - page);
...@@ -1418,7 +1824,6 @@ acpi_processor_read_limit ( ...@@ -1418,7 +1824,6 @@ acpi_processor_read_limit (
struct acpi_processor *pr = (struct acpi_processor *) data; struct acpi_processor *pr = (struct acpi_processor *) data;
char *p = page; char *p = page;
int len = 0; int len = 0;
int i = 0;
ACPI_FUNCTION_TRACE("acpi_processor_read_limit"); ACPI_FUNCTION_TRACE("acpi_processor_read_limit");
...@@ -1430,22 +1835,17 @@ acpi_processor_read_limit ( ...@@ -1430,22 +1835,17 @@ acpi_processor_read_limit (
goto end; goto end;
} }
p += sprintf(p, "state count: %d\n", p += sprintf(p, "active limit: P%d:T%d\n",
pr->limit.state_count); pr->limit.state.px, pr->limit.state.tx);
p += sprintf(p, "active state: L%d\n", p += sprintf(p, "platform limit: P%d:T0\n",
pr->limit.state); pr->flags.performance?pr->performance.platform_limit:0);
p += sprintf(p, "states:\n"); p += sprintf(p, "user limit: P%d:T%d\n",
pr->limit.user.px, pr->limit.user.tx);
for (i=0; i<pr->limit.state_count; i++) p += sprintf(p, "thermal limit: P%d:T%d\n",
p += sprintf(p, " %cL%d: %02d%% [P%d:T%d] %s\n", pr->limit.thermal.px, pr->limit.thermal.tx);
(i == pr->limit.state?'*':' '),
i,
pr->limit.states[i].performance / 10,
pr->limit.states[i].px,
pr->limit.states[i].tx,
pr->limit.states[i].valid?"":"(disabled)");
end: end:
len = (p - page); len = (p - page);
...@@ -1468,25 +1868,47 @@ acpi_processor_write_limit ( ...@@ -1468,25 +1868,47 @@ acpi_processor_write_limit (
{ {
int result = 0; int result = 0;
struct acpi_processor *pr = (struct acpi_processor *) data; struct acpi_processor *pr = (struct acpi_processor *) data;
char limit_string[12] = {'\0'}; char limit_string[25] = {'\0'};
int limit = 0; int px = 0;
int state = 0; int tx = 0;
ACPI_FUNCTION_TRACE("acpi_processor_write_limit"); ACPI_FUNCTION_TRACE("acpi_processor_write_limit");
if (!pr || (count > sizeof(limit_string) - 1)) if (!pr || (count > sizeof(limit_string) - 1)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument\n"));
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
}
if (copy_from_user(limit_string, buffer, count)) if (copy_from_user(limit_string, buffer, count)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n"));
return_VALUE(-EFAULT); return_VALUE(-EFAULT);
}
limit_string[count] = '\0'; limit_string[count] = '\0';
limit = simple_strtoul(limit_string, NULL, 0); if (sscanf(limit_string, "%d:%d", &px, &tx) != 2) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n"));
result = acpi_processor_set_limit(pr->handle, limit, &state); return_VALUE(-EINVAL);
if (0 != result) }
return_VALUE(result);
if (pr->flags.performance) {
if ((px < pr->performance.platform_limit)
|| (px > (pr->performance.state_count - 1))) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid px\n"));
return_VALUE(-EINVAL);
}
pr->limit.user.px = px;
}
if (pr->flags.throttling) {
if ((tx < 0) || (tx > (pr->throttling.state_count - 1))) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid tx\n"));
return_VALUE(-EINVAL);
}
pr->limit.user.tx = tx;
}
result = acpi_processor_apply_limit(pr);
return_VALUE(count); return_VALUE(count);
} }
...@@ -1564,7 +1986,7 @@ acpi_processor_add_fs ( ...@@ -1564,7 +1986,7 @@ acpi_processor_add_fs (
entry->data = acpi_driver_data(device); entry->data = acpi_driver_data(device);
} }
/* 'thermal_limit' [R/W] */ /* 'limit' [R/W] */
entry = create_proc_entry(ACPI_PROCESSOR_FILE_LIMIT, entry = create_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
if (!entry) if (!entry)
...@@ -1617,10 +2039,10 @@ acpi_processor_get_info ( ...@@ -1617,10 +2039,10 @@ acpi_processor_get_info (
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
if (smp_num_cpus > 1) if (smp_num_cpus > 1)
acpi_processor_smp = smp_num_cpus; errata.smp = smp_num_cpus;
#endif #endif
acpi_processor_get_errata(pr); acpi_processor_errata(pr);
/* /*
* Check to see if we have bus mastering arbitration control. This * Check to see if we have bus mastering arbitration control. This
...@@ -1687,6 +2109,7 @@ acpi_processor_notify ( ...@@ -1687,6 +2109,7 @@ acpi_processor_notify (
u32 event, u32 event,
void *data) void *data)
{ {
int result = 0;
struct acpi_processor *pr = (struct acpi_processor *) data; struct acpi_processor *pr = (struct acpi_processor *) data;
struct acpi_device *device = NULL; struct acpi_device *device = NULL;
...@@ -1700,7 +2123,15 @@ acpi_processor_notify ( ...@@ -1700,7 +2123,15 @@ acpi_processor_notify (
switch (event) { switch (event) {
case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
result = acpi_processor_get_platform_limit(pr);
if (0 == result)
acpi_processor_apply_limit(pr);
acpi_bus_generate_event(device, event,
pr->performance.platform_limit);
break;
case ACPI_PROCESSOR_NOTIFY_POWER: case ACPI_PROCESSOR_NOTIFY_POWER:
/* TBD */
acpi_bus_generate_event(device, event, 0); acpi_bus_generate_event(device, event, 0);
break; break;
default: default:
...@@ -1745,9 +2176,6 @@ acpi_processor_add ( ...@@ -1745,9 +2176,6 @@ acpi_processor_add (
if (0 != result) if (0 != result)
goto end; goto end;
/*
* TBD: Fix notify handler installation for processors.
*
status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
acpi_processor_notify, pr); acpi_processor_notify, pr);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
...@@ -1756,16 +2184,13 @@ acpi_processor_add ( ...@@ -1756,16 +2184,13 @@ acpi_processor_add (
result = -ENODEV; result = -ENODEV;
goto end; goto end;
} }
*/
acpi_processor_list[pr->id] = pr; processors[pr->id] = pr;
/* /*
* Set Idle Handler * Install the idle handler if processor power management is supported.
* ---------------- * Note that the default idle handler (default_idle) will be used on
* Install the idle handler if power management (states other than C1) * platforms that only support C1.
* is supported. Note that the default idle handler (default_idle)
* will be used on platforms that only support C1.
*/ */
if ((pr->id == 0) && (pr->flags.power)) { if ((pr->id == 0) && (pr->flags.power)) {
pm_idle_save = pm_idle; pm_idle_save = pm_idle;
...@@ -1781,8 +2206,6 @@ acpi_processor_add ( ...@@ -1781,8 +2206,6 @@ acpi_processor_add (
printk(", %d performance states", pr->performance.state_count); printk(", %d performance states", pr->performance.state_count);
if (pr->flags.throttling) if (pr->flags.throttling)
printk(", %d throttling states", pr->throttling.state_count); printk(", %d throttling states", pr->throttling.state_count);
if (pr->errata.piix4.bmisx)
printk(", PIIX4 errata");
printk(")\n"); printk(")\n");
end: end:
...@@ -1810,7 +2233,10 @@ acpi_processor_remove ( ...@@ -1810,7 +2233,10 @@ acpi_processor_remove (
pr = (struct acpi_processor *) acpi_driver_data(device); pr = (struct acpi_processor *) acpi_driver_data(device);
/* /* Unregister the idle handler when processor #0 is removed. */
if (pr->id == 0)
pm_idle = pm_idle_save;
status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
acpi_processor_notify); acpi_processor_notify);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
...@@ -1818,15 +2244,10 @@ acpi_processor_remove ( ...@@ -1818,15 +2244,10 @@ acpi_processor_remove (
"Error removing notify handler\n")); "Error removing notify handler\n"));
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
} }
*/
/* Unregister the idle handler when processor #0 is removed. */
if (pr->id == 0)
pm_idle = pm_idle_save;
acpi_processor_remove_fs(device); acpi_processor_remove_fs(device);
acpi_processor_list[pr->id] = NULL; processors[pr->id] = NULL;
kfree(pr); kfree(pr);
...@@ -1841,7 +2262,8 @@ acpi_processor_init (void) ...@@ -1841,7 +2262,8 @@ acpi_processor_init (void)
ACPI_FUNCTION_TRACE("acpi_processor_init"); ACPI_FUNCTION_TRACE("acpi_processor_init");
memset(&acpi_processor_list, 0, sizeof(acpi_processor_list)); memset(&processors, 0, sizeof(processors));
memset(&errata, 0, sizeof(errata));
result = acpi_bus_register_driver(&acpi_processor_driver); result = acpi_bus_register_driver(&acpi_processor_driver);
if (0 > result) if (0 > result)
......
/* /*
* acpi_system.c - ACPI System Driver ($Revision: 40 $) * acpi_system.c - ACPI System Driver ($Revision: 45 $)
* *
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/sysrq.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/acpi.h> #include <asm/acpi.h>
...@@ -86,9 +87,8 @@ static void ...@@ -86,9 +87,8 @@ static void
acpi_power_off (void) acpi_power_off (void)
{ {
acpi_enter_sleep_state_prep(ACPI_STATE_S5); acpi_enter_sleep_state_prep(ACPI_STATE_S5);
acpi_disable_irqs(); ACPI_DISABLE_IRQS();
acpi_enter_sleep_state(ACPI_STATE_S5); acpi_enter_sleep_state(ACPI_STATE_S5);
acpi_disable_irqs();
} }
#endif /*CONFIG_PM*/ #endif /*CONFIG_PM*/
...@@ -123,7 +123,7 @@ acpi_system_restore_state ( ...@@ -123,7 +123,7 @@ acpi_system_restore_state (
device_resume(RESUME_POWER_ON); device_resume(RESUME_POWER_ON);
/* enable interrupts once again */ /* enable interrupts once again */
acpi_enable_irqs(); ACPI_ENABLE_IRQS();
/* restore device context */ /* restore device context */
device_resume(RESUME_RESTORE_STATE); device_resume(RESUME_RESTORE_STATE);
...@@ -200,7 +200,7 @@ acpi_system_save_state( ...@@ -200,7 +200,7 @@ acpi_system_save_state(
* But, we want it done early, so we don't get any suprises during * But, we want it done early, so we don't get any suprises during
* the device suspend sequence. * the device suspend sequence.
*/ */
acpi_disable_irqs(); ACPI_DISABLE_IRQS();
/* Unconditionally turn off devices. /* Unconditionally turn off devices.
* Obvious if we enter a sleep state. * Obvious if we enter a sleep state.
...@@ -304,7 +304,7 @@ acpi_suspend ( ...@@ -304,7 +304,7 @@ acpi_suspend (
return status; return status;
/* disable interrupts and flush caches */ /* disable interrupts and flush caches */
acpi_disable_irqs(); ACPI_DISABLE_IRQS();
wbinvd(); wbinvd();
/* perform OS-specific sleep actions */ /* perform OS-specific sleep actions */
...@@ -318,7 +318,7 @@ acpi_suspend ( ...@@ -318,7 +318,7 @@ acpi_suspend (
acpi_leave_sleep_state(state); acpi_leave_sleep_state(state);
/* make sure interrupts are enabled */ /* make sure interrupts are enabled */
acpi_enable_irqs(); ACPI_ENABLE_IRQS();
/* reset firmware waking vector */ /* reset firmware waking vector */
acpi_set_firmware_waking_vector((ACPI_PHYSICAL_ADDRESS) 0); acpi_set_firmware_waking_vector((ACPI_PHYSICAL_ADDRESS) 0);
...@@ -570,7 +570,6 @@ acpi_system_read_debug ( ...@@ -570,7 +570,6 @@ acpi_system_read_debug (
{ {
char *p = page; char *p = page;
int size = 0; int size = 0;
u32 var;
if (off != 0) if (off != 0)
goto end; goto end;
...@@ -607,7 +606,6 @@ acpi_system_write_debug ( ...@@ -607,7 +606,6 @@ acpi_system_write_debug (
void *data) void *data)
{ {
char debug_string[12] = {'\0'}; char debug_string[12] = {'\0'};
u32 *pvar;
ACPI_FUNCTION_TRACE("acpi_system_write_debug"); ACPI_FUNCTION_TRACE("acpi_system_write_debug");
...@@ -1126,6 +1124,23 @@ acpi_system_remove_fs ( ...@@ -1126,6 +1124,23 @@ acpi_system_remove_fs (
Driver Interface Driver Interface
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
#if defined(CONFIG_MAGIC_SYSRQ) && defined(CONFIG_PM)
/* Simple wrapper calling power down function. */
static void acpi_sysrq_power_off(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty)
{
acpi_power_off();
}
struct sysrq_key_op sysrq_acpi_poweroff_op = {
handler: &acpi_sysrq_power_off,
help_msg: "Off",
action_msg: "Power Off\n"
};
#endif /* CONFIG_MAGIC_SYSRQ */
static int static int
acpi_system_add ( acpi_system_add (
struct acpi_device *device) struct acpi_device *device)
...@@ -1168,8 +1183,10 @@ acpi_system_add ( ...@@ -1168,8 +1183,10 @@ acpi_system_add (
#ifdef CONFIG_PM #ifdef CONFIG_PM
/* Install the soft-off (S5) handler. */ /* Install the soft-off (S5) handler. */
if (system->states[ACPI_STATE_S5]) if (system->states[ACPI_STATE_S5]) {
pm_power_off = acpi_power_off; pm_power_off = acpi_power_off;
register_sysrq_key('o', &sysrq_acpi_poweroff_op);
}
#endif #endif
end: end:
...@@ -1196,8 +1213,10 @@ acpi_system_remove ( ...@@ -1196,8 +1213,10 @@ acpi_system_remove (
#ifdef CONFIG_PM #ifdef CONFIG_PM
/* Remove the soft-off (S5) handler. */ /* Remove the soft-off (S5) handler. */
if (system->states[ACPI_STATE_S5]) if (system->states[ACPI_STATE_S5]) {
unregister_sysrq_key('o', &sysrq_acpi_poweroff_op);
pm_power_off = NULL; pm_power_off = NULL;
}
#endif #endif
acpi_system_remove_fs(device); acpi_system_remove_fs(device);
......
/* /*
* acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 33 $) * acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 36 $)
* *
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
...@@ -78,7 +78,6 @@ struct acpi_thermal_state { ...@@ -78,7 +78,6 @@ struct acpi_thermal_state {
u8 passive:1; u8 passive:1;
u8 active:1; u8 active:1;
u8 reserved:4; u8 reserved:4;
int passive_index; /* a.k.a. limit state */
int active_index; int active_index;
}; };
...@@ -467,15 +466,23 @@ acpi_thermal_passive ( ...@@ -467,15 +466,23 @@ acpi_thermal_passive (
*/ */
if (tz->temperature >= passive->temperature) { if (tz->temperature >= passive->temperature) {
trend = (passive->tc1 * (tz->temperature - tz->last_temperature)) + (passive->tc2 * (tz->temperature - passive->temperature)); trend = (passive->tc1 * (tz->temperature - tz->last_temperature)) + (passive->tc2 * (tz->temperature - passive->temperature));
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n", trend, passive->tc1, tz->temperature, tz->last_temperature, passive->tc2, tz->temperature, passive->temperature)); ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n",
trend, passive->tc1, tz->temperature,
tz->last_temperature, passive->tc2,
tz->temperature, passive->temperature));
/* 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++)
acpi_processor_set_limit(passive->devices.handles[i], ACPI_PROCESSOR_LIMIT_INCREMENT, &tz->state.passive_index); acpi_processor_set_thermal_limit(
passive->devices.handles[i],
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_limit(passive->devices.handles[i], ACPI_PROCESSOR_LIMIT_DECREMENT, &tz->state.passive_index); acpi_processor_set_thermal_limit(
passive->devices.handles[i],
ACPI_PROCESSOR_LIMIT_DECREMENT);
} }
/* /*
...@@ -487,10 +494,13 @@ acpi_thermal_passive ( ...@@ -487,10 +494,13 @@ acpi_thermal_passive (
*/ */
else if (tz->trips.passive.flags.enabled) { else if (tz->trips.passive.flags.enabled) {
for (i=0; i<passive->devices.count; i++) for (i=0; i<passive->devices.count; i++)
acpi_processor_set_limit(passive->devices.handles[i], ACPI_PROCESSOR_LIMIT_DECREMENT, &tz->state.passive_index); result = acpi_processor_set_thermal_limit(
if (0 == tz->state.passive_index) { passive->devices.handles[i],
ACPI_PROCESSOR_LIMIT_DECREMENT);
if (1 == result) {
tz->trips.passive.flags.enabled = 0; tz->trips.passive.flags.enabled = 0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabling passive cooling (zone is cool)\n")); ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Disabling passive cooling (zone is cool)\n"));
} }
} }
...@@ -671,7 +681,7 @@ acpi_thermal_check ( ...@@ -671,7 +681,7 @@ acpi_thermal_check (
if (timer_pending(&(tz->timer))) if (timer_pending(&(tz->timer)))
mod_timer(&(tz->timer), (HZ * sleep_time) / 1000); mod_timer(&(tz->timer), (HZ * sleep_time) / 1000);
else { else {
tz->timer.data = (u32) tz; tz->timer.data = (unsigned long) tz;
tz->timer.function = acpi_thermal_run; tz->timer.function = acpi_thermal_run;
tz->timer.expires = jiffies + (HZ * sleep_time) / 1000; tz->timer.expires = jiffies + (HZ * sleep_time) / 1000;
add_timer(&(tz->timer)); add_timer(&(tz->timer));
...@@ -720,7 +730,7 @@ acpi_thermal_read_state ( ...@@ -720,7 +730,7 @@ acpi_thermal_read_state (
if (tz->state.hot) if (tz->state.hot)
p += sprintf(p, "hot "); p += sprintf(p, "hot ");
if (tz->state.passive) if (tz->state.passive)
p += sprintf(p, "passive[%d] ", tz->state.passive_index); p += sprintf(p, "passive ");
if (tz->state.active) if (tz->state.active)
p += sprintf(p, "active[%d]", tz->state.active_index); p += sprintf(p, "active[%d]", tz->state.active_index);
p += sprintf(p, "\n"); p += sprintf(p, "\n");
...@@ -810,9 +820,10 @@ acpi_thermal_read_trip_points ( ...@@ -810,9 +820,10 @@ acpi_thermal_read_trip_points (
tz->trips.passive.tc1, tz->trips.passive.tc1,
tz->trips.passive.tc2, tz->trips.passive.tc2,
tz->trips.passive.tsp); tz->trips.passive.tsp);
for (j=0; j<tz->trips.passive.devices.count; j++) for (j=0; j<tz->trips.passive.devices.count; j++) {
p += sprintf(p, "0x%p ",
tz->trips.passive.devices.handles[j]); p += sprintf(p, "0x%p ", tz->trips.passive.devices.handles[j]);
}
p += sprintf(p, "\n"); p += sprintf(p, "\n");
} }
......
/****************************************************************************** /******************************************************************************
* *
* Name: acenv.h - Generation environment specific items * Name: acenv.h - Generation environment specific items
* $Revision: 85 $ * $Revision: 86 $
* *
*****************************************************************************/ *****************************************************************************/
...@@ -284,11 +284,9 @@ typedef char *va_list; ...@@ -284,11 +284,9 @@ typedef char *va_list;
#define ACPI_INTERNAL_VAR_XFACE #define ACPI_INTERNAL_VAR_XFACE
#define ACPI_ASM_MACROS #define ACPI_ASM_MACROS
#define causeinterrupt(level)
#define BREAKPOINT3 #define BREAKPOINT3
#define acpi_disable_irqs() #define ACPI_DISABLE_IRQS()
#define acpi_enable_irqs() #define ACPI_ENABLE_IRQS()
#define halt()
#define ACPI_ACQUIRE_GLOBAL_LOCK(Glptr, acq) #define ACPI_ACQUIRE_GLOBAL_LOCK(Glptr, acq)
#define ACPI_RELEASE_GLOBAL_LOCK(Glptr, acq) #define ACPI_RELEASE_GLOBAL_LOCK(Glptr, acq)
...@@ -299,9 +297,7 @@ typedef char *va_list; ...@@ -299,9 +297,7 @@ typedef char *va_list;
/* Don't want software interrupts within a ring3 application */ /* Don't want software interrupts within a ring3 application */
#undef causeinterrupt
#undef BREAKPOINT3 #undef BREAKPOINT3
#define causeinterrupt(level)
#define BREAKPOINT3 #define BREAKPOINT3
#endif #endif
......
/****************************************************************************** /******************************************************************************
* *
* Name: acgcc.h - GCC specific defines, etc. * Name: acgcc.h - GCC specific defines, etc.
* $Revision: 19 $ * $Revision: 22 $
* *
*****************************************************************************/ *****************************************************************************/
...@@ -30,7 +30,8 @@ ...@@ -30,7 +30,8 @@
#ifdef __ia64__ #ifdef __ia64__
#define _IA64 #define _IA64
#define COMPILER_DEPENDENT_UINT64 unsigned long #define COMPILER_DEPENDENT_INT64 long
#define COMPILER_DEPENDENT_UINT64 unsigned long
/* /*
* Calling conventions: * Calling conventions:
...@@ -52,10 +53,9 @@ ...@@ -52,10 +53,9 @@
/* Asm macros */ /* Asm macros */
#define ACPI_ASM_MACROS #define ACPI_ASM_MACROS
#define causeinterrupt(level)
#define BREAKPOINT3 #define BREAKPOINT3
#define acpi_disable_irqs() __cli() #define ACPI_DISABLE_IRQS() __cli()
#define acpi_enable_irqs() __sti() #define ACPI_ENABLE_IRQS() __sti()
/*! [Begin] no source code translation */ /*! [Begin] no source code translation */
...@@ -111,7 +111,8 @@ ...@@ -111,7 +111,8 @@
#else /* DO IA32 */ #else /* DO IA32 */
#define COMPILER_DEPENDENT_UINT64 unsigned long long #define COMPILER_DEPENDENT_INT64 long long
#define COMPILER_DEPENDENT_UINT64 unsigned long long
/* /*
* Calling conventions: * Calling conventions:
...@@ -129,11 +130,9 @@ ...@@ -129,11 +130,9 @@
/* Asm macros */ /* Asm macros */
#define ACPI_ASM_MACROS #define ACPI_ASM_MACROS
#define causeinterrupt(level)
#define BREAKPOINT3 #define BREAKPOINT3
#define acpi_disable_irqs() __cli() #define ACPI_DISABLE_IRQS() __cli()
#define acpi_enable_irqs() __sti() #define ACPI_ENABLE_IRQS() __sti()
#define halt() __asm__ __volatile__ ("sti; hlt":::"memory")
/*! [Begin] no source code translation /*! [Begin] no source code translation
* *
......
/****************************************************************************** /******************************************************************************
* *
* Name: aclinux.h - OS specific defines, etc. * Name: aclinux.h - OS specific defines, etc.
* $Revision: 15 $ * $Revision: 19 $
* *
*****************************************************************************/ *****************************************************************************/
...@@ -42,14 +42,20 @@ ...@@ -42,14 +42,20 @@
#define strtoul simple_strtoul #define strtoul simple_strtoul
#ifdef _IA64
#define ACPI_FLUSH_CPU_CACHE()
#else #else
#define ACPI_FLUSH_CPU_CACHE() wbinvd()
#endif
#else /* !__KERNEL__ */
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#endif #endif /* __KERNEL__ */
/* Linux uses GCC */ /* Linux uses GCC */
......
...@@ -33,9 +33,12 @@ ...@@ -33,9 +33,12 @@
/* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */ /* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */
#define FIX_ACPI_PAGES 4 #define FIX_ACPI_PAGES 4
extern int acpi_mp_config;
char * __acpi_map_table (unsigned long phys_addr, unsigned long size); char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
extern int acpi_find_rsdp (unsigned long *phys_addr); extern int acpi_find_rsdp (unsigned long *phys_addr);
extern int acpi_parse_madt (unsigned long phys_addr, unsigned long size); extern int acpi_parse_madt (unsigned long phys_addr, unsigned long size);
extern int acpi_boot_init (char *cmdline);
#endif /*CONFIG_ACPI_BOOT*/ #endif /*CONFIG_ACPI_BOOT*/
......
...@@ -29,6 +29,12 @@ ...@@ -29,6 +29,12 @@
#define _LINUX #define _LINUX
#endif #endif
/*
* YES this is ugly.
* But, moving all of ACPI's private headers to include/acpi isn't the right
* answer either.
* Please just ignore it for now.
*/
#include "../../drivers/acpi/include/acpi.h" #include "../../drivers/acpi/include/acpi.h"
#include <asm/acpi.h> #include <asm/acpi.h>
...@@ -270,7 +276,7 @@ struct acpi_table_slit { ...@@ -270,7 +276,7 @@ struct acpi_table_slit {
struct acpi_table_header header; struct acpi_table_header header;
u64 localities; u64 localities;
u8 entry[1]; /* real size = localities^2 */ u8 entry[1]; /* real size = localities^2 */
}; } __attribute__ ((packed));
/* Smart Battery Description Table (SBST) */ /* Smart Battery Description Table (SBST) */
...@@ -283,7 +289,6 @@ struct acpi_table_sbst { ...@@ -283,7 +289,6 @@ struct acpi_table_sbst {
/* Embedded Controller Boot Resources Table (ECDT) */ /* Embedded Controller Boot Resources Table (ECDT) */
/* TBD: acpi_generic_address
struct acpi_table_ecdt { struct acpi_table_ecdt {
struct acpi_table_header header; struct acpi_table_header header;
acpi_generic_address ec_control; acpi_generic_address ec_control;
...@@ -292,7 +297,6 @@ struct acpi_table_ecdt { ...@@ -292,7 +297,6 @@ struct acpi_table_ecdt {
u8 gpe_bit; u8 gpe_bit;
char *ec_id; char *ec_id;
} __attribute__ ((packed)); } __attribute__ ((packed));
*/
/* Table Handlers */ /* Table Handlers */
...@@ -343,9 +347,9 @@ void acpi_table_print_madt_entry (acpi_table_entry_header *); ...@@ -343,9 +347,9 @@ void acpi_table_print_madt_entry (acpi_table_entry_header *);
#ifdef CONFIG_ACPI_PCI #ifdef CONFIG_ACPI_PCI
#define ACPI_PCI_ROUTING_PIC 0 #define ACPI_INT_MODEL_PIC 0
#define ACPI_PCI_ROUTING_IOAPIC 1 #define ACPI_INT_MODEL_IOAPIC 1
#define ACPI_PCI_ROUTING_IOSAPIC 2 #define ACPI_INT_MODEL_IOSAPIC 2
struct acpi_prt_entry { struct acpi_prt_entry {
struct list_head node; struct list_head node;
......
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