diff options
| author | Andy Grover <agrover@groveronline.com> | 2002-10-22 01:43:39 -0700 |
|---|---|---|
| committer | Andy Grover <agrover@groveronline.com> | 2002-10-22 01:43:39 -0700 |
| commit | ff26a502efbb8ff0697ca9c885f14a204a5f279e (patch) | |
| tree | e6fd6fd03f218fb9ef6e37cff2cb70f4a7b5b54b | |
| parent | 7e167397f7e003336ddcc8d28571ff3232298f42 (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.c | 92 | ||||
| -rw-r--r-- | include/linux/acpi.h | 2 |
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 */ |
