summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Grover <agrover@groveronline.com>2002-10-22 01:43:39 -0700
committerAndy Grover <agrover@groveronline.com>2002-10-22 01:43:39 -0700
commitff26a502efbb8ff0697ca9c885f14a204a5f279e (patch)
treee6fd6fd03f218fb9ef6e37cff2cb70f4a7b5b54b
parent7e167397f7e003336ddcc8d28571ff3232298f42 (diff)
ACPI: EC update
- Move call to acpi_ec_query out of the interrupt handler. This will ensure that we do not try to acquire the Global Lock at interrupt level. - Get the handle for the ECDT.
-rw-r--r--drivers/acpi/ec.c92
-rw-r--r--include/linux/acpi.h2
2 files changed, 43 insertions, 51 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 3734121a2048..902cf66d6014 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -80,6 +80,7 @@ static struct acpi_driver acpi_ec_driver = {
struct acpi_ec {
acpi_handle handle;
+ unsigned long uid;
unsigned long gpe_bit;
acpi_generic_address status_addr;
acpi_generic_address command_addr;
@@ -90,9 +91,6 @@ struct acpi_ec {
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
static struct acpi_ec *ec_ecdt;
-/* compare this against UIDs in properly enumerated ECs to determine if we
- have a dupe */
-static unsigned long ecdt_uid = 0xFFFFFFFF;
/* --------------------------------------------------------------------------
Transaction Management
@@ -297,80 +295,65 @@ struct acpi_ec_query_data {
u8 data;
};
-
static void
acpi_ec_gpe_query (
- void *data)
+ void *ec_cxt)
{
- struct acpi_ec_query_data *query_data = NULL;
+ struct acpi_ec *ec = (struct acpi_ec *) ec_cxt;
+ u32 value = 0;
+ unsigned long flags = 0;
static char object_name[5] = {'_','Q','0','0','\0'};
const char hex[] = {'0','1','2','3','4','5','6','7',
'8','9','A','B','C','D','E','F'};
ACPI_FUNCTION_TRACE("acpi_ec_gpe_query");
- if (!data)
- return;
+ if (!ec_cxt)
+ goto end;
- query_data = (struct acpi_ec_query_data *) data;
+ spin_lock_irqsave(&ec->lock, flags);
+ acpi_hw_low_level_read(8, &value, &ec->command_addr, 0);
+ spin_unlock_irqrestore(&ec->lock, flags);
- object_name[2] = hex[((query_data->data >> 4) & 0x0F)];
- object_name[3] = hex[(query_data->data & 0x0F)];
+ /* TBD: Implement asynch events!
+ * NOTE: All we care about are EC-SCI's. Other EC events are
+ * handled via polling (yuck!). This is because some systems
+ * treat EC-SCIs as level (versus EDGE!) triggered, preventing
+ * a purely interrupt-driven approach (grumble, grumble).
+ */
+ if (!(value & ACPI_EC_FLAG_SCI))
+ goto end;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name));
+ if (acpi_ec_query(ec, &value))
+ goto end;
+
+ object_name[2] = hex[((value >> 4) & 0x0F)];
+ object_name[3] = hex[(value & 0x0F)];
- acpi_evaluate_object(query_data->handle, object_name, NULL, NULL);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name));
- kfree(query_data);
+ acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
- return;
+end:
+ acpi_enable_event(ec->gpe_bit, ACPI_EVENT_GPE, 0);
}
-
static void
acpi_ec_gpe_handler (
void *data)
{
acpi_status status = AE_OK;
struct acpi_ec *ec = (struct acpi_ec *) data;
- u32 value = 0;
- unsigned long flags = 0;
- struct acpi_ec_query_data *query_data = NULL;
if (!ec)
return;
- spin_lock_irqsave(&ec->lock, flags);
- acpi_hw_low_level_read(8, &value, &ec->command_addr, 0);
- spin_unlock_irqrestore(&ec->lock, flags);
-
- /* TBD: Implement asynch events!
- * NOTE: All we care about are EC-SCI's. Other EC events are
- * handled via polling (yuck!). This is because some systems
- * treat EC-SCIs as level (versus EDGE!) triggered, preventing
- * a purely interrupt-driven approach (grumble, grumble).
- */
- if (!(value & ACPI_EC_FLAG_SCI))
- return;
-
- if (acpi_ec_query(ec, &value))
- return;
-
- query_data = kmalloc(sizeof(struct acpi_ec_query_data), GFP_ATOMIC);
- if (!query_data)
- return;
- query_data->handle = ec->handle;
- query_data->data = value;
+ acpi_disable_event(ec->gpe_bit, ACPI_EVENT_GPE, 0);
status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
- acpi_ec_gpe_query, query_data);
- if (ACPI_FAILURE(status))
- kfree(query_data);
-
- return;
+ acpi_ec_gpe_query, ec);
}
-
/* --------------------------------------------------------------------------
Address Space Management
-------------------------------------------------------------------------- */
@@ -559,6 +542,7 @@ acpi_ec_add (
memset(ec, 0, sizeof(struct acpi_ec));
ec->handle = device->handle;
+ ec->uid = -1;
ec->lock = SPIN_LOCK_UNLOCKED;
sprintf(acpi_device_name(device), "%s", ACPI_EC_DEVICE_NAME);
sprintf(acpi_device_class(device), "%s", ACPI_EC_CLASS);
@@ -567,10 +551,10 @@ acpi_ec_add (
/* Use the global lock for all EC transactions? */
acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock);
- /* If our UID matches ecdt_uid, we already found this EC via the
- ECDT. Abort. */
+ /* If our UID matches the UID for the ECDT-enumerated EC,
+ we already found this EC, so abort. */
acpi_evaluate_integer(ec->handle, "_UID", NULL, &uid);
- if (ecdt_uid == uid) {
+ if (ec_ecdt && ec_ecdt->uid == uid) {
result = -ENODEV;
goto end;
}
@@ -758,7 +742,12 @@ acpi_ec_ecdt_probe (void)
ec_ecdt->lock = SPIN_LOCK_UNLOCKED;
/* use the GL just to be safe */
ec_ecdt->global_lock = TRUE;
- ecdt_uid = ecdt_ptr->uid;
+ ec_ecdt->uid = ecdt_ptr->uid;
+
+ status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle);
+ if (ACPI_FAILURE(status)) {
+ goto error;
+ }
/*
* Install GPE handler
@@ -783,7 +772,9 @@ acpi_ec_ecdt_probe (void)
return 0;
error:
+ printk(KERN_ERR PREFIX "Could not use ECDT\n");
kfree(ec_ecdt);
+ ec_ecdt = NULL;
return -ENODEV;
}
@@ -835,3 +826,4 @@ acpi_ec_exit (void)
return_VOID;
}
+
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index cb30a1c7878a..58b82b4d016a 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -330,7 +330,7 @@ struct acpi_table_ecdt {
acpi_generic_address ec_data;
u32 uid;
u8 gpe_bit;
- char *ec_id;
+ char ec_id[0];
} __attribute__ ((packed));
/* Table Handlers */