From 15b8dd53f5ffaf8e2d9095c423f713423f576c0f Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 29 Jun 2009 13:39:29 +0800 Subject: ACPICA: Major update for acpi_get_object_info external interface Completed a major update for the acpi_get_object_info external interface. Changes include: - Support for variable, unlimited length HID, UID, and CID strings - Support Processor objects the same as Devices (HID,UID,CID,ADR,STA, etc.) - Call the _SxW power methods on behalf of a device object - Determine if a device is a PCI root bridge - Change the ACPI_BUFFER parameter to ACPI_DEVICE_INFO. These changes will require an update to all callers of this interface. See the ACPICA Programmer Reference for details. Also, update all invocations of acpi_get_object_info interface Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/scan.c | 153 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 99 insertions(+), 54 deletions(-) (limited to 'drivers/acpi/scan.c') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 781435d7e369..0ab526de7c55 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -60,13 +60,13 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, } if (acpi_dev->flags.compatible_ids) { - struct acpi_compatible_id_list *cid_list; + struct acpica_device_id_list *cid_list; int i; cid_list = acpi_dev->pnp.cid_list; for (i = 0; i < cid_list->count; i++) { count = snprintf(&modalias[len], size, "%s:", - cid_list->id[i].value); + cid_list->ids[i].string); if (count < 0 || count >= size) { printk(KERN_ERR PREFIX "%s cid[%i] exceeds event buffer size", acpi_dev->pnp.device_name, i); @@ -287,14 +287,14 @@ int acpi_match_device_ids(struct acpi_device *device, } if (device->flags.compatible_ids) { - struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; + struct acpica_device_id_list *cid_list = device->pnp.cid_list; int i; for (id = ids; id->id[0]; id++) { /* compare multiple _CID entries against driver ids */ for (i = 0; i < cid_list->count; i++) { if (!strcmp((char*)id->id, - cid_list->id[i].value)) + cid_list->ids[i].string)) return 0; } } @@ -999,33 +999,89 @@ static int acpi_dock_match(struct acpi_device *device) return acpi_get_handle(device->handle, "_DCK", &tmp); } +static struct acpica_device_id_list* +acpi_add_cid( + struct acpi_device_info *info, + struct acpica_device_id *new_cid) +{ + struct acpica_device_id_list *cid; + char *next_id_string; + acpi_size cid_length; + acpi_size new_cid_length; + u32 i; + + + /* Allocate new CID list with room for the new CID */ + + if (!new_cid) + new_cid_length = info->compatible_id_list.list_size; + else if (info->compatible_id_list.list_size) + new_cid_length = info->compatible_id_list.list_size + + new_cid->length + sizeof(struct acpica_device_id); + else + new_cid_length = sizeof(struct acpica_device_id_list) + new_cid->length; + + cid = ACPI_ALLOCATE_ZEROED(new_cid_length); + if (!cid) { + return NULL; + } + + cid->list_size = new_cid_length; + cid->count = info->compatible_id_list.count; + if (new_cid) + cid->count++; + next_id_string = (char *) cid->ids + (cid->count * sizeof(struct acpica_device_id)); + + /* Copy all existing CIDs */ + + for (i = 0; i < info->compatible_id_list.count; i++) { + cid_length = info->compatible_id_list.ids[i].length; + cid->ids[i].string = next_id_string; + cid->ids[i].length = cid_length; + + ACPI_MEMCPY(next_id_string, info->compatible_id_list.ids[i].string, + cid_length); + + next_id_string += cid_length; + } + + /* Append the new CID */ + + if (new_cid) { + cid->ids[i].string = next_id_string; + cid->ids[i].length = new_cid->length; + + ACPI_MEMCPY(next_id_string, new_cid->string, new_cid->length); + } + + return cid; +} + static void acpi_device_set_id(struct acpi_device *device, struct acpi_device *parent, acpi_handle handle, int type) { - struct acpi_device_info *info; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_device_info *info = NULL; char *hid = NULL; char *uid = NULL; - struct acpi_compatible_id_list *cid_list = NULL; - const char *cid_add = NULL; + struct acpica_device_id_list *cid_list = NULL; + char *cid_add = NULL; acpi_status status; switch (type) { case ACPI_BUS_TYPE_DEVICE: - status = acpi_get_object_info(handle, &buffer); + status = acpi_get_object_info(handle, &info); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__); return; } - info = buffer.pointer; if (info->valid & ACPI_VALID_HID) - hid = info->hardware_id.value; + hid = info->hardware_id.string; if (info->valid & ACPI_VALID_UID) - uid = info->unique_id.value; + uid = info->unique_id.string; if (info->valid & ACPI_VALID_CID) - cid_list = &info->compatibility_id; + cid_list = &info->compatible_id_list; if (info->valid & ACPI_VALID_ADR) { device->pnp.bus_address = info->address; device->flags.bus_address = 1; @@ -1076,55 +1132,44 @@ static void acpi_device_set_id(struct acpi_device *device, } if (hid) { - strcpy(device->pnp.hardware_id, hid); - device->flags.hardware_id = 1; - } + device->pnp.hardware_id = ACPI_ALLOCATE_ZEROED(strlen (hid) + 1); + if (device->pnp.hardware_id) { + strcpy(device->pnp.hardware_id, hid); + device->flags.hardware_id = 1; + } + } else + device->pnp.hardware_id = NULL; + if (uid) { - strcpy(device->pnp.unique_id, uid); - device->flags.unique_id = 1; - } + device->pnp.unique_id = ACPI_ALLOCATE_ZEROED(strlen (uid) + 1); + if (device->pnp.unique_id) { + strcpy(device->pnp.unique_id, uid); + device->flags.unique_id = 1; + } + } else + device->pnp.unique_id = NULL; + if (cid_list || cid_add) { - struct acpi_compatible_id_list *list; - int size = 0; - int count = 0; - - if (cid_list) { - size = cid_list->size; - } else if (cid_add) { - size = sizeof(struct acpi_compatible_id_list); - cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); - if (!cid_list) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(buffer.pointer); - return; - } else { - cid_list->count = 0; - cid_list->size = size; - } + struct acpica_device_id_list *list; + + if (cid_add) { + struct acpica_device_id cid; + cid.length = strlen (cid_add) + 1; + cid.string = cid_add; + + list = acpi_add_cid(info, &cid); + } else { + list = acpi_add_cid(info, NULL); } - if (cid_add) - size += sizeof(struct acpi_compatible_id); - list = kmalloc(size, GFP_KERNEL); if (list) { - if (cid_list) { - memcpy(list, cid_list, cid_list->size); - count = cid_list->count; - } - if (cid_add) { - strncpy(list->id[count].value, cid_add, - ACPI_MAX_CID_LENGTH); - count++; - device->flags.compatible_ids = 1; - } - list->size = size; - list->count = count; device->pnp.cid_list = list; - } else - printk(KERN_ERR PREFIX "Memory allocation error\n"); + if (cid_add) + device->flags.compatible_ids = 1; + } } - kfree(buffer.pointer); + kfree(info); } static int acpi_device_set_context(struct acpi_device *device, int type) -- cgit v1.2.1