Commit 462bcde6 authored by Andy Grover's avatar Andy Grover

ACPI: Allow multiple compatible IDs for PnP purposes

parent ce7d8354
...@@ -28,6 +28,8 @@ static spinlock_t acpi_device_lock = SPIN_LOCK_UNLOCKED; ...@@ -28,6 +28,8 @@ static spinlock_t acpi_device_lock = SPIN_LOCK_UNLOCKED;
static void acpi_device_release(struct kobject * kobj) static void acpi_device_release(struct kobject * kobj)
{ {
struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj); struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj);
if (dev->pnp.cid_list)
kfree(dev->pnp.cid_list);
kfree(dev); kfree(dev);
} }
...@@ -201,33 +203,16 @@ acpi_bus_match ( ...@@ -201,33 +203,16 @@ acpi_bus_match (
goto Done; goto Done;
if (device->flags.compatible_ids) { if (device->flags.compatible_ids) {
acpi_status status = AE_OK; struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
union acpi_object *object = NULL; int i;
char cid[256] = {};
status = acpi_evaluate_object(device->handle, "_CID", NULL,
&buffer);
if (ACPI_FAILURE(status) || !buffer.pointer)
return -ENOENT;
object = (union acpi_object *) buffer.pointer;
switch (object->type) {
case ACPI_TYPE_INTEGER:
acpi_ex_eisa_id_to_string((u32) object->integer.value,
cid);
break;
case ACPI_TYPE_STRING:
strncpy(cid, object->string.pointer, sizeof(cid) - 1);
break;
case ACPI_TYPE_PACKAGE:
/* TBD: Support CID packages */
break;
}
if (strlen(cid) && strstr(driver->ids,cid)) /* compare multiple _CID entries against driver ids */
for (i = 0; i < cid_list->count; i++)
{
if (strstr(driver->ids, cid_list->id[i].value))
goto Done; goto Done;
} }
}
error = -ENOENT; error = -ENOENT;
Done: Done:
...@@ -523,27 +508,30 @@ static void acpi_device_get_busid(struct acpi_device * device, acpi_handle handl ...@@ -523,27 +508,30 @@ static void acpi_device_get_busid(struct acpi_device * device, acpi_handle handl
static void acpi_device_set_id(struct acpi_device * device, struct acpi_device * parent, static void acpi_device_set_id(struct acpi_device * device, struct acpi_device * parent,
acpi_handle handle, int type) acpi_handle handle, int type)
{ {
struct acpi_device_info info; struct acpi_device_info *info;
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
char *hid = NULL; char *hid = NULL;
char *uid = NULL; char *uid = NULL;
struct acpi_compatible_id_list *cid_list = NULL;
acpi_status status; acpi_status status;
switch (type) { switch (type) {
case ACPI_BUS_TYPE_DEVICE: case ACPI_BUS_TYPE_DEVICE:
status = acpi_get_object_info(handle, &info); status = acpi_get_object_info(handle, &buffer);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
printk("%s: Error reading device info\n",__FUNCTION__); printk("%s: Error reading device info\n",__FUNCTION__);
return; return;
} }
/* Clean up info strings (not NULL terminated) */
info.hardware_id[sizeof(info.hardware_id)-1] = '\0'; info = buffer.pointer;
info.unique_id[sizeof(info.unique_id)-1] = '\0'; if (info->valid & ACPI_VALID_HID)
if (info.valid & ACPI_VALID_HID) hid = info->hardware_id.value;
hid = info.hardware_id; if (info->valid & ACPI_VALID_UID)
if (info.valid & ACPI_VALID_UID) uid = info->unique_id.value;
uid = info.unique_id; if (info->valid & ACPI_VALID_CID)
if (info.valid & ACPI_VALID_ADR) { cid_list = &info->compatibility_id;
device->pnp.bus_address = info.address; if (info->valid & ACPI_VALID_ADR) {
device->pnp.bus_address = info->address;
device->flags.bus_address = 1; device->flags.bus_address = 1;
} }
break; break;
...@@ -586,6 +574,15 @@ static void acpi_device_set_id(struct acpi_device * device, struct acpi_device * ...@@ -586,6 +574,15 @@ static void acpi_device_set_id(struct acpi_device * device, struct acpi_device *
sprintf(device->pnp.unique_id, "%s", uid); sprintf(device->pnp.unique_id, "%s", uid);
device->flags.unique_id = 1; device->flags.unique_id = 1;
} }
if (cid_list) {
device->pnp.cid_list = kmalloc(cid_list->size, GFP_KERNEL);
if (device->pnp.cid_list)
memcpy(device->pnp.cid_list, cid_list, cid_list->size);
else
printk(KERN_ERR "Memory allocation error\n");
}
acpi_os_free(buffer.pointer);
} }
int acpi_device_set_context(struct acpi_device * device, int type) int acpi_device_set_context(struct acpi_device * device, int type)
...@@ -781,8 +778,12 @@ acpi_bus_add ( ...@@ -781,8 +778,12 @@ acpi_bus_add (
end: end:
if (!result) if (!result)
*child = device; *child = device;
else else {
if (device->pnp.cid_list)
kfree(device->pnp.cid_list);
kfree(device); kfree(device);
}
return_VALUE(result); return_VALUE(result);
} }
......
...@@ -186,6 +186,7 @@ struct acpi_device_pnp { ...@@ -186,6 +186,7 @@ struct acpi_device_pnp {
acpi_bus_id bus_id; /* Object name */ acpi_bus_id bus_id; /* Object name */
acpi_bus_address bus_address; /* _ADR */ acpi_bus_address bus_address; /* _ADR */
acpi_hardware_id hardware_id; /* _HID */ acpi_hardware_id hardware_id; /* _HID */
struct acpi_compatible_id_list *cid_list; /* _CIDs */
acpi_unique_id unique_id; /* _UID */ acpi_unique_id unique_id; /* _UID */
acpi_device_name device_name; /* Driver-determined */ acpi_device_name device_name; /* Driver-determined */
acpi_device_class device_class; /* " */ acpi_device_class device_class; /* " */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment