aboutsummaryrefslogtreecommitdiff
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/Kconfig11
-rw-r--r--drivers/acpi/ec.c40
-rw-r--r--drivers/acpi/events/evmisc.c25
-rw-r--r--drivers/acpi/ibm_acpi.c28
-rw-r--r--drivers/acpi/power.c13
-rw-r--r--drivers/acpi/resources/rscreate.c25
6 files changed, 113 insertions, 29 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 3208ce08d66..e2ce4a9c1c9 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -244,6 +244,17 @@ config ACPI_IBM_DOCK
If you are not sure, say N here.
+config ACPI_IBM_BAY
+ bool "Legacy Removable Bay Support"
+ depends on ACPI_IBM
+ default y
+ ---help---
+ Allows the ibm_acpi driver to handle removable bays. It will allow
+ disabling the device in the bay, and also generate notifications when
+ the bay lever is ejected or inserted.
+
+ If you are not sure, say Y here.
+
config ACPI_TOSHIBA
tristate "Toshiba Laptop Extras"
depends on X86
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index ab688837379..a802962ff2b 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -100,6 +100,7 @@ static struct acpi_ec {
unsigned long global_lock;
struct mutex lock;
atomic_t query_pending;
+ atomic_t event_count;
atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */
wait_queue_head_t wait;
} *ec_ecdt;
@@ -131,10 +132,12 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
outb(data, ec->data_addr);
}
-static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
+static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event,
+ unsigned old_count)
{
u8 status = acpi_ec_read_status(ec);
-
+ if (old_count == atomic_read(&ec->event_count))
+ return 0;
if (event == ACPI_EC_EVENT_OBF_1) {
if (status & ACPI_EC_FLAG_OBF)
return 1;
@@ -146,19 +149,19 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
return 0;
}
-static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event)
+static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count)
{
if (acpi_ec_mode == EC_POLL) {
unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
while (time_before(jiffies, delay)) {
- if (acpi_ec_check_status(ec, event))
+ if (acpi_ec_check_status(ec, event, 0))
return 0;
}
} else {
if (wait_event_timeout(ec->wait,
- acpi_ec_check_status(ec, event),
+ acpi_ec_check_status(ec, event, count),
msecs_to_jiffies(ACPI_EC_DELAY)) ||
- acpi_ec_check_status(ec, event)) {
+ acpi_ec_check_status(ec, event, 0)) {
return 0;
} else {
printk(KERN_ERR PREFIX "acpi_ec_wait timeout,"
@@ -225,21 +228,22 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
u8 * rdata, unsigned rdata_len)
{
int result = 0;
-
+ unsigned count = atomic_read(&ec->event_count);
acpi_ec_write_cmd(ec, command);
for (; wdata_len > 0; --wdata_len) {
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count);
if (result) {
printk(KERN_ERR PREFIX
"write_cmd timeout, command = %d\n", command);
goto end;
}
+ count = atomic_read(&ec->event_count);
acpi_ec_write_data(ec, *(wdata++));
}
if (!rdata_len) {
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count);
if (result) {
printk(KERN_ERR PREFIX
"finish-write timeout, command = %d\n", command);
@@ -250,13 +254,13 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
}
for (; rdata_len > 0; --rdata_len) {
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1);
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count);
if (result) {
printk(KERN_ERR PREFIX "read timeout, command = %d\n",
command);
goto end;
}
-
+ count = atomic_read(&ec->event_count);
*(rdata++) = acpi_ec_read_data(ec);
}
end:
@@ -288,7 +292,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
/* Make sure GPE is enabled before doing transaction */
acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
+ status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0);
if (status) {
printk(KERN_DEBUG PREFIX
"input buffer is not empty, aborting transaction\n");
@@ -369,8 +373,8 @@ int ec_write(u8 addr, u8 val)
EXPORT_SYMBOL(ec_write);
int ec_transaction(u8 command,
- const u8 * wdata, unsigned wdata_len,
- u8 * rdata, unsigned rdata_len)
+ const u8 * wdata, unsigned wdata_len,
+ u8 * rdata, unsigned rdata_len)
{
struct acpi_ec *ec;
@@ -435,7 +439,7 @@ static u32 acpi_ec_gpe_handler(void *data)
acpi_status status = AE_OK;
u8 value;
struct acpi_ec *ec = (struct acpi_ec *)data;
-
+ atomic_inc(&ec->event_count);
if (acpi_ec_mode == EC_INTR) {
wake_up(&ec->wait);
}
@@ -633,6 +637,7 @@ static int acpi_ec_add(struct acpi_device *device)
ec->uid = -1;
mutex_init(&ec->lock);
atomic_set(&ec->query_pending, 0);
+ atomic_set(&ec->event_count, 1);
if (acpi_ec_mode == EC_INTR) {
atomic_set(&ec->leaving_burst, 1);
init_waitqueue_head(&ec->wait);
@@ -807,6 +812,7 @@ acpi_fake_ecdt_callback(acpi_handle handle,
acpi_status status;
mutex_init(&ec_ecdt->lock);
+ atomic_set(&ec_ecdt->event_count, 1);
if (acpi_ec_mode == EC_INTR) {
init_waitqueue_head(&ec_ecdt->wait);
}
@@ -888,6 +894,7 @@ static int __init acpi_ec_get_real_ecdt(void)
return -ENOMEM;
mutex_init(&ec_ecdt->lock);
+ atomic_set(&ec_ecdt->event_count, 1);
if (acpi_ec_mode == EC_INTR) {
init_waitqueue_head(&ec_ecdt->wait);
}
@@ -1016,8 +1023,7 @@ static int __init acpi_ec_set_intr_mode(char *str)
acpi_ec_mode = EC_POLL;
}
acpi_ec_driver.ops.add = acpi_ec_add;
- printk(KERN_NOTICE PREFIX "%s mode.\n",
- intr ? "interrupt" : "polling");
+ printk(KERN_NOTICE PREFIX "%s mode.\n", intr ? "interrupt" : "polling");
return 1;
}
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index d572700197f..8dcade63b04 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -423,6 +423,8 @@ static acpi_status acpi_ev_remove_global_lock_handler(void)
* the global lock appear as a standard mutex on the OS side.
*
*****************************************************************************/
+static acpi_thread_id acpi_ev_global_lock_thread_id;
+static int acpi_ev_global_lock_acquired;
acpi_status acpi_ev_acquire_global_lock(u16 timeout)
{
@@ -435,11 +437,24 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
* Only one thread can acquire the GL at a time, the global_lock_mutex
* enforces this. This interface releases the interpreter if we must wait.
*/
- status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout);
+ status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 0);
+ if (status == AE_TIME) {
+ if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) {
+ acpi_ev_global_lock_acquired++;
+ return AE_OK;
+ }
+ }
+
+ if (ACPI_FAILURE(status)) {
+ status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout);
+ }
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
+ acpi_ev_global_lock_thread_id = acpi_os_get_thread_id();
+ acpi_ev_global_lock_acquired++;
+
/*
* Make sure that a global lock actually exists. If not, just treat
* the lock as a standard mutex.
@@ -506,6 +521,11 @@ acpi_status acpi_ev_release_global_lock(void)
return_ACPI_STATUS(AE_NOT_ACQUIRED);
}
+ acpi_ev_global_lock_acquired--;
+ if (acpi_ev_global_lock_acquired > 0) {
+ return AE_OK;
+ }
+
if (acpi_gbl_global_lock_present) {
/* Allow any thread to release the lock */
@@ -529,7 +549,8 @@ acpi_status acpi_ev_release_global_lock(void)
acpi_gbl_global_lock_acquired = FALSE;
/* Release the local GL mutex */
-
+ acpi_ev_global_lock_thread_id = 0;
+ acpi_ev_global_lock_acquired = 0;
acpi_os_release_mutex(acpi_gbl_global_lock_mutex);
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
index 4cc534e36e8..36901362fd2 100644
--- a/drivers/acpi/ibm_acpi.c
+++ b/drivers/acpi/ibm_acpi.c
@@ -86,6 +86,7 @@
#include <linux/proc_fs.h>
#include <linux/backlight.h>
+#include <linux/fb.h>
#include <asm/uaccess.h>
#include <linux/dmi.h>
@@ -157,6 +158,7 @@ IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */
"\\_SB.PCI.ISA.SLCE", /* 570 */
); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
#endif
+#ifdef CONFIG_ACPI_IBM_BAY
IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */
"\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */
"\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */
@@ -174,6 +176,7 @@ IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */
IBM_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */
"_EJ0", /* 770x */
); /* all others */
+#endif /* CONFIG_ACPI_IBM_BAY */
/* don't list other alternatives as we install a notify handler on the 570 */
IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */
@@ -1044,6 +1047,7 @@ static int light_write(char *buf)
return 0;
}
+#if defined(CONFIG_ACPI_IBM_DOCK) || defined(CONFIG_ACPI_IBM_BAY)
static int _sta(acpi_handle handle)
{
int status;
@@ -1053,6 +1057,7 @@ static int _sta(acpi_handle handle)
return status;
}
+#endif
#ifdef CONFIG_ACPI_IBM_DOCK
#define dock_docked() (_sta(dock_handle) & 1)
@@ -1119,6 +1124,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event)
}
#endif
+#ifdef CONFIG_ACPI_IBM_BAY
static int bay_status_supported;
static int bay_status2_supported;
static int bay_eject_supported;
@@ -1194,6 +1200,7 @@ static void bay_notify(struct ibm_struct *ibm, u32 event)
{
acpi_bus_generate_event(ibm->device, event, 0);
}
+#endif /* CONFIG_ACPI_IBM_BAY */
static int cmos_read(char *p)
{
@@ -1701,7 +1708,10 @@ static int brightness_write(char *buf)
static int brightness_update_status(struct backlight_device *bd)
{
- return brightness_set(bd->props.brightness);
+ return brightness_set(
+ (bd->props.fb_blank == FB_BLANK_UNBLANK &&
+ bd->props.power == FB_BLANK_UNBLANK) ?
+ bd->props.brightness : 0);
}
static struct backlight_ops ibm_backlight_data = {
@@ -1711,6 +1721,12 @@ static struct backlight_ops ibm_backlight_data = {
static int brightness_init(void)
{
+ int b;
+
+ b = brightness_get(NULL);
+ if (b < 0)
+ return b;
+
ibm_backlight_device = backlight_device_register("ibm", NULL, NULL,
&ibm_backlight_data);
if (IS_ERR(ibm_backlight_device)) {
@@ -1718,7 +1734,9 @@ static int brightness_init(void)
return PTR_ERR(ibm_backlight_device);
}
- ibm_backlight_device->props.max_brightness = 7;
+ ibm_backlight_device->props.max_brightness = 7;
+ ibm_backlight_device->props.brightness = b;
+ backlight_update_status(ibm_backlight_device);
return 0;
}
@@ -2353,6 +2371,7 @@ static struct ibm_struct ibms[] = {
.type = ACPI_SYSTEM_NOTIFY,
},
#endif
+#ifdef CONFIG_ACPI_IBM_BAY
{
.name = "bay",
.init = bay_init,
@@ -2362,6 +2381,7 @@ static struct ibm_struct ibms[] = {
.handle = &bay_handle,
.type = ACPI_SYSTEM_NOTIFY,
},
+#endif /* CONFIG_ACPI_IBM_BAY */
{
.name = "cmos",
.read = cmos_read,
@@ -2647,7 +2667,9 @@ IBM_PARAM(light);
#ifdef CONFIG_ACPI_IBM_DOCK
IBM_PARAM(dock);
#endif
+#ifdef CONFIG_ACPI_IBM_BAY
IBM_PARAM(bay);
+#endif /* CONFIG_ACPI_IBM_BAY */
IBM_PARAM(cmos);
IBM_PARAM(led);
IBM_PARAM(beep);
@@ -2723,12 +2745,14 @@ static int __init acpi_ibm_init(void)
IBM_HANDLE_INIT(dock);
#endif
IBM_HANDLE_INIT(pci);
+#ifdef CONFIG_ACPI_IBM_BAY
IBM_HANDLE_INIT(bay);
if (bay_handle)
IBM_HANDLE_INIT(bay_ej);
IBM_HANDLE_INIT(bay2);
if (bay2_handle)
IBM_HANDLE_INIT(bay2_ej);
+#endif /* CONFIG_ACPI_IBM_BAY */
IBM_HANDLE_INIT(beep);
IBM_HANDLE_INIT(ecrd);
IBM_HANDLE_INIT(ecwr);
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index ccecfe0d695..4ffecd17970 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -436,8 +436,6 @@ int acpi_power_transition(struct acpi_device *device, int state)
cl = &device->power.states[device->power.state].resources;
tl = &device->power.states[state].resources;
- device->power.state = ACPI_STATE_UNKNOWN;
-
if (!cl->count && !tl->count) {
result = -ENODEV;
goto end;
@@ -468,12 +466,15 @@ int acpi_power_transition(struct acpi_device *device, int state)
goto end;
}
- /* We shouldn't change the state till all above operations succeed */
- device->power.state = state;
- end:
- if (result)
+ end:
+ if (result) {
+ device->power.state = ACPI_STATE_UNKNOWN;
printk(KERN_WARNING PREFIX "Transitioning device [%s] to D%d\n",
device->pnp.bus_id, state);
+ } else {
+ /* We shouldn't change the state till all above operations succeed */
+ device->power.state = state;
+ }
return result;
}
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c
index 1358c06a969..cc48ab05676 100644
--- a/drivers/acpi/resources/rscreate.c
+++ b/drivers/acpi/resources/rscreate.c
@@ -191,6 +191,9 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
for (index = 0; index < number_of_elements; index++) {
+ int source_name_index = 2;
+ int source_index_index = 3;
+
/*
* Point user_prt past this current structure
*
@@ -261,10 +264,28 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
}
/*
+ * If BIOS erroneously reversed the _PRT source_name and source_index,
+ * then reverse them back.
+ */
+ if (ACPI_GET_OBJECT_TYPE (sub_object_list[3]) != ACPI_TYPE_INTEGER) {
+ if (acpi_gbl_enable_interpreter_slack) {
+ source_name_index = 3;
+ source_index_index = 2;
+ printk(KERN_WARNING "ACPI: Handling Garbled _PRT entry\n");
+ } else {
+ ACPI_ERROR((AE_INFO,
+ "(PRT[%X].source_index) Need Integer, found %s",
+ index,
+ acpi_ut_get_object_type_name(sub_object_list[3])));
+ return_ACPI_STATUS(AE_BAD_DATA);
+ }
+ }
+
+ /*
* 3) Third subobject: Dereference the PRT.source_name
* The name may be unresolved (slack mode), so allow a null object
*/
- obj_desc = sub_object_list[2];
+ obj_desc = sub_object_list[source_name_index];
if (obj_desc) {
switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_LOCAL_REFERENCE:
@@ -339,7 +360,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
/* 4) Fourth subobject: Dereference the PRT.source_index */
- obj_desc = sub_object_list[3];
+ obj_desc = sub_object_list[source_index_index];
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
user_prt->source_index = (u32) obj_desc->integer.value;
} else {