diff options
author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2009-09-21 21:35:19 +0200 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-09-25 21:09:31 +0200 |
commit | 7f47fa6c2ff15f5e59cdbb350f86faef6829294a (patch) | |
tree | 02167bcbc5e6fd4eee044798ef142ff604d8eab1 /drivers/acpi/scan.c | |
parent | ACPI: make sure every acpi_device has an ID (diff) | |
download | linux-7f47fa6c2ff15f5e59cdbb350f86faef6829294a.tar.xz linux-7f47fa6c2ff15f5e59cdbb350f86faef6829294a.zip |
ACPI: maintain a single list of _HID and _CID IDs
There's no need to treat _HID and _CID differently. Keeping them in
a single list makes code that uses the IDs a little simpler because it
can just traverse the list rather than checking "do we have a HID?",
"do we have any CIDs?"
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Reviewed-by: Alex Chiang <achiang@hp.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 166 |
1 files changed, 46 insertions, 120 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 53b96e7a64ab..2e8889f62666 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -45,6 +45,7 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, { int len; int count; + struct acpi_hardware_id *id; if (!acpi_dev->flags.hardware_id && !acpi_dev->flags.compatible_ids) return -ENODEV; @@ -52,33 +53,14 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, len = snprintf(modalias, size, "acpi:"); size -= len; - if (acpi_dev->flags.hardware_id) { - count = snprintf(&modalias[len], size, "%s:", - acpi_dev->pnp.hardware_id); + list_for_each_entry(id, &acpi_dev->pnp.ids, list) { + count = snprintf(&modalias[len], size, "%s:", id->id); if (count < 0 || count >= size) return -EINVAL; len += count; size -= count; } - if (acpi_dev->flags.compatible_ids) { - 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->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); - break; - } - len += count; - size -= count; - } - } - modalias[len] = '\0'; return len; } @@ -273,6 +255,7 @@ int acpi_match_device_ids(struct acpi_device *device, const struct acpi_device_id *ids) { const struct acpi_device_id *id; + struct acpi_hardware_id *hwid; /* * If the device is not present, it is unnecessary to load device @@ -281,40 +264,30 @@ int acpi_match_device_ids(struct acpi_device *device, if (!device->status.present) return -ENODEV; - if (device->flags.hardware_id) { - for (id = ids; id->id[0]; id++) { - if (!strcmp((char*)id->id, device->pnp.hardware_id)) + for (id = ids; id->id[0]; id++) + list_for_each_entry(hwid, &device->pnp.ids, list) + if (!strcmp((char *) id->id, hwid->id)) return 0; - } - } - - if (device->flags.compatible_ids) { - 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->ids[i].string)) - return 0; - } - } - } return -ENOENT; } EXPORT_SYMBOL(acpi_match_device_ids); +static void acpi_free_ids(struct acpi_device *device) +{ + struct acpi_hardware_id *id, *tmp; + + list_for_each_entry_safe(id, tmp, &device->pnp.ids, list) { + kfree(id->id); + kfree(id); + } +} + static void acpi_device_release(struct device *dev) { struct acpi_device *acpi_dev = to_acpi_device(dev); - kfree(acpi_dev->pnp.cid_list); - if (acpi_dev->flags.hardware_id) - kfree(acpi_dev->pnp.hardware_id); - if (acpi_dev->flags.unique_id) - kfree(acpi_dev->pnp.unique_id); + acpi_free_ids(acpi_dev); kfree(acpi_dev); } @@ -1028,62 +1001,31 @@ 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) +char *acpi_device_hid(struct acpi_device *device) { - 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 */ + struct acpi_hardware_id *hid; - 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; - } + hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list); + return hid->id; +} +EXPORT_SYMBOL(acpi_device_hid); - /* Append the new CID */ +static void acpi_add_id(struct acpi_device *device, const char *dev_id) +{ + struct acpi_hardware_id *id; - if (new_cid) { - cid->ids[i].string = next_id_string; - cid->ids[i].length = new_cid->length; + id = kmalloc(sizeof(*id), GFP_KERNEL); + if (!id) + return; - ACPI_MEMCPY(next_id_string, new_cid->string, new_cid->length); + id->id = kmalloc(strlen(dev_id) + 1, GFP_KERNEL); + if (!id->id) { + kfree(id); + return; } - return cid; + strcpy(id->id, dev_id); + list_add_tail(&id->list, &device->pnp.ids); } static void acpi_device_set_id(struct acpi_device *device) @@ -1094,6 +1036,7 @@ static void acpi_device_set_id(struct acpi_device *device) struct acpica_device_id_list *cid_list = NULL; char *cid_add = NULL; acpi_status status; + int i; switch (device->device_type) { case ACPI_BUS_TYPE_DEVICE: @@ -1166,15 +1109,9 @@ static void acpi_device_set_id(struct acpi_device *device) hid = "device"; if (hid) { - 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; - } + acpi_add_id(device, hid); + device->flags.hardware_id = 1; } - if (!device->flags.hardware_id) - device->pnp.hardware_id = ""; - if (uid) { device->pnp.unique_id = ACPI_ALLOCATE_ZEROED(strlen (uid) + 1); if (device->pnp.unique_id) { @@ -1185,24 +1122,12 @@ static void acpi_device_set_id(struct acpi_device *device) if (!device->flags.unique_id) device->pnp.unique_id = ""; - if (cid_list || cid_add) { - 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 (list) { - device->pnp.cid_list = list; - if (cid_add) - device->flags.compatible_ids = 1; - } + if (cid_list) + for (i = 0; i < cid_list->count; i++) + acpi_add_id(device, cid_list->ids[i].string); + if (cid_add) { + acpi_add_id(device, cid_add); + device->flags.compatible_ids = 1; } kfree(info); @@ -1269,6 +1194,7 @@ static int acpi_add_single_object(struct acpi_device **child, return -ENOMEM; } + INIT_LIST_HEAD(&device->pnp.ids); device->device_type = type; device->handle = handle; device->parent = acpi_bus_get_parent(handle); |