diff options
| author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2009-09-21 15:35:19 -0400 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2009-09-25 15:09:31 -0400 |
| commit | 7f47fa6c2ff15f5e59cdbb350f86faef6829294a (patch) | |
| tree | 02167bcbc5e6fd4eee044798ef142ff604d8eab1 | |
| parent | b1fbfb2ae8f2f0e04219218da6f52f7313466899 (diff) | |
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>
| -rw-r--r-- | drivers/acpi/scan.c | 166 | ||||
| -rw-r--r-- | drivers/pnp/pnpacpi/core.c | 16 | ||||
| -rw-r--r-- | include/acpi/acpi_bus.h | 10 |
3 files changed, 60 insertions, 132 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, | |||
| 45 | { | 45 | { |
| 46 | int len; | 46 | int len; |
| 47 | int count; | 47 | int count; |
| 48 | struct acpi_hardware_id *id; | ||
| 48 | 49 | ||
| 49 | if (!acpi_dev->flags.hardware_id && !acpi_dev->flags.compatible_ids) | 50 | if (!acpi_dev->flags.hardware_id && !acpi_dev->flags.compatible_ids) |
| 50 | return -ENODEV; | 51 | return -ENODEV; |
| @@ -52,33 +53,14 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
| 52 | len = snprintf(modalias, size, "acpi:"); | 53 | len = snprintf(modalias, size, "acpi:"); |
| 53 | size -= len; | 54 | size -= len; |
| 54 | 55 | ||
| 55 | if (acpi_dev->flags.hardware_id) { | 56 | list_for_each_entry(id, &acpi_dev->pnp.ids, list) { |
| 56 | count = snprintf(&modalias[len], size, "%s:", | 57 | count = snprintf(&modalias[len], size, "%s:", id->id); |
| 57 | acpi_dev->pnp.hardware_id); | ||
| 58 | if (count < 0 || count >= size) | 58 | if (count < 0 || count >= size) |
| 59 | return -EINVAL; | 59 | return -EINVAL; |
| 60 | len += count; | 60 | len += count; |
| 61 | size -= count; | 61 | size -= count; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | if (acpi_dev->flags.compatible_ids) { | ||
| 65 | struct acpica_device_id_list *cid_list; | ||
| 66 | int i; | ||
| 67 | |||
| 68 | cid_list = acpi_dev->pnp.cid_list; | ||
| 69 | for (i = 0; i < cid_list->count; i++) { | ||
| 70 | count = snprintf(&modalias[len], size, "%s:", | ||
| 71 | cid_list->ids[i].string); | ||
| 72 | if (count < 0 || count >= size) { | ||
| 73 | printk(KERN_ERR PREFIX "%s cid[%i] exceeds event buffer size", | ||
| 74 | acpi_dev->pnp.device_name, i); | ||
| 75 | break; | ||
| 76 | } | ||
| 77 | len += count; | ||
| 78 | size -= count; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | modalias[len] = '\0'; | 64 | modalias[len] = '\0'; |
| 83 | return len; | 65 | return len; |
| 84 | } | 66 | } |
| @@ -273,6 +255,7 @@ int acpi_match_device_ids(struct acpi_device *device, | |||
| 273 | const struct acpi_device_id *ids) | 255 | const struct acpi_device_id *ids) |
| 274 | { | 256 | { |
| 275 | const struct acpi_device_id *id; | 257 | const struct acpi_device_id *id; |
| 258 | struct acpi_hardware_id *hwid; | ||
| 276 | 259 | ||
| 277 | /* | 260 | /* |
| 278 | * If the device is not present, it is unnecessary to load device | 261 | * 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, | |||
| 281 | if (!device->status.present) | 264 | if (!device->status.present) |
| 282 | return -ENODEV; | 265 | return -ENODEV; |
| 283 | 266 | ||
| 284 | if (device->flags.hardware_id) { | 267 | for (id = ids; id->id[0]; id++) |
| 285 | for (id = ids; id->id[0]; id++) { | 268 | list_for_each_entry(hwid, &device->pnp.ids, list) |
| 286 | if (!strcmp((char*)id->id, device->pnp.hardware_id)) | 269 | if (!strcmp((char *) id->id, hwid->id)) |
| 287 | return 0; | 270 | return 0; |
| 288 | } | ||
| 289 | } | ||
| 290 | |||
| 291 | if (device->flags.compatible_ids) { | ||
| 292 | struct acpica_device_id_list *cid_list = device->pnp.cid_list; | ||
| 293 | int i; | ||
| 294 | |||
| 295 | for (id = ids; id->id[0]; id++) { | ||
| 296 | /* compare multiple _CID entries against driver ids */ | ||
| 297 | for (i = 0; i < cid_list->count; i++) { | ||
| 298 | if (!strcmp((char*)id->id, | ||
| 299 | cid_list->ids[i].string)) | ||
| 300 | return 0; | ||
| 301 | } | ||
| 302 | } | ||
| 303 | } | ||
| 304 | 271 | ||
| 305 | return -ENOENT; | 272 | return -ENOENT; |
| 306 | } | 273 | } |
| 307 | EXPORT_SYMBOL(acpi_match_device_ids); | 274 | EXPORT_SYMBOL(acpi_match_device_ids); |
| 308 | 275 | ||
| 276 | static void acpi_free_ids(struct acpi_device *device) | ||
| 277 | { | ||
| 278 | struct acpi_hardware_id *id, *tmp; | ||
| 279 | |||
| 280 | list_for_each_entry_safe(id, tmp, &device->pnp.ids, list) { | ||
| 281 | kfree(id->id); | ||
| 282 | kfree(id); | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 309 | static void acpi_device_release(struct device *dev) | 286 | static void acpi_device_release(struct device *dev) |
| 310 | { | 287 | { |
| 311 | struct acpi_device *acpi_dev = to_acpi_device(dev); | 288 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
| 312 | 289 | ||
| 313 | kfree(acpi_dev->pnp.cid_list); | 290 | acpi_free_ids(acpi_dev); |
| 314 | if (acpi_dev->flags.hardware_id) | ||
| 315 | kfree(acpi_dev->pnp.hardware_id); | ||
| 316 | if (acpi_dev->flags.unique_id) | ||
| 317 | kfree(acpi_dev->pnp.unique_id); | ||
| 318 | kfree(acpi_dev); | 291 | kfree(acpi_dev); |
| 319 | } | 292 | } |
| 320 | 293 | ||
| @@ -1028,62 +1001,31 @@ static int acpi_dock_match(struct acpi_device *device) | |||
| 1028 | return acpi_get_handle(device->handle, "_DCK", &tmp); | 1001 | return acpi_get_handle(device->handle, "_DCK", &tmp); |
| 1029 | } | 1002 | } |
| 1030 | 1003 | ||
| 1031 | static struct acpica_device_id_list* | 1004 | char *acpi_device_hid(struct acpi_device *device) |
| 1032 | acpi_add_cid( | ||
| 1033 | struct acpi_device_info *info, | ||
| 1034 | struct acpica_device_id *new_cid) | ||
| 1035 | { | 1005 | { |
| 1036 | struct acpica_device_id_list *cid; | 1006 | struct acpi_hardware_id *hid; |
| 1037 | char *next_id_string; | ||
| 1038 | acpi_size cid_length; | ||
| 1039 | acpi_size new_cid_length; | ||
| 1040 | u32 i; | ||
| 1041 | |||
| 1042 | |||
| 1043 | /* Allocate new CID list with room for the new CID */ | ||
| 1044 | |||
| 1045 | if (!new_cid) | ||
| 1046 | new_cid_length = info->compatible_id_list.list_size; | ||
| 1047 | else if (info->compatible_id_list.list_size) | ||
| 1048 | new_cid_length = info->compatible_id_list.list_size + | ||
| 1049 | new_cid->length + sizeof(struct acpica_device_id); | ||
| 1050 | else | ||
| 1051 | new_cid_length = sizeof(struct acpica_device_id_list) + new_cid->length; | ||
| 1052 | |||
| 1053 | cid = ACPI_ALLOCATE_ZEROED(new_cid_length); | ||
| 1054 | if (!cid) { | ||
| 1055 | return NULL; | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | cid->list_size = new_cid_length; | ||
| 1059 | cid->count = info->compatible_id_list.count; | ||
| 1060 | if (new_cid) | ||
| 1061 | cid->count++; | ||
| 1062 | next_id_string = (char *) cid->ids + (cid->count * sizeof(struct acpica_device_id)); | ||
| 1063 | |||
| 1064 | /* Copy all existing CIDs */ | ||
| 1065 | 1007 | ||
| 1066 | for (i = 0; i < info->compatible_id_list.count; i++) { | 1008 | hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list); |
| 1067 | cid_length = info->compatible_id_list.ids[i].length; | 1009 | return hid->id; |
| 1068 | cid->ids[i].string = next_id_string; | 1010 | } |
| 1069 | cid->ids[i].length = cid_length; | 1011 | EXPORT_SYMBOL(acpi_device_hid); |
| 1070 | |||
| 1071 | ACPI_MEMCPY(next_id_string, info->compatible_id_list.ids[i].string, | ||
| 1072 | cid_length); | ||
| 1073 | |||
| 1074 | next_id_string += cid_length; | ||
| 1075 | } | ||
| 1076 | 1012 | ||
| 1077 | /* Append the new CID */ | 1013 | static void acpi_add_id(struct acpi_device *device, const char *dev_id) |
| 1014 | { | ||
| 1015 | struct acpi_hardware_id *id; | ||
| 1078 | 1016 | ||
| 1079 | if (new_cid) { | 1017 | id = kmalloc(sizeof(*id), GFP_KERNEL); |
| 1080 | cid->ids[i].string = next_id_string; | 1018 | if (!id) |
| 1081 | cid->ids[i].length = new_cid->length; | 1019 | return; |
| 1082 | 1020 | ||
| 1083 | ACPI_MEMCPY(next_id_string, new_cid->string, new_cid->length); | 1021 | id->id = kmalloc(strlen(dev_id) + 1, GFP_KERNEL); |
| 1022 | if (!id->id) { | ||
| 1023 | kfree(id); | ||
| 1024 | return; | ||
| 1084 | } | 1025 | } |
| 1085 | 1026 | ||
| 1086 | return cid; | 1027 | strcpy(id->id, dev_id); |
| 1028 | list_add_tail(&id->list, &device->pnp.ids); | ||
| 1087 | } | 1029 | } |
| 1088 | 1030 | ||
| 1089 | static void acpi_device_set_id(struct acpi_device *device) | 1031 | static void acpi_device_set_id(struct acpi_device *device) |
| @@ -1094,6 +1036,7 @@ static void acpi_device_set_id(struct acpi_device *device) | |||
| 1094 | struct acpica_device_id_list *cid_list = NULL; | 1036 | struct acpica_device_id_list *cid_list = NULL; |
| 1095 | char *cid_add = NULL; | 1037 | char *cid_add = NULL; |
| 1096 | acpi_status status; | 1038 | acpi_status status; |
| 1039 | int i; | ||
| 1097 | 1040 | ||
| 1098 | switch (device->device_type) { | 1041 | switch (device->device_type) { |
| 1099 | case ACPI_BUS_TYPE_DEVICE: | 1042 | case ACPI_BUS_TYPE_DEVICE: |
| @@ -1166,15 +1109,9 @@ static void acpi_device_set_id(struct acpi_device *device) | |||
| 1166 | hid = "device"; | 1109 | hid = "device"; |
| 1167 | 1110 | ||
| 1168 | if (hid) { | 1111 | if (hid) { |
| 1169 | device->pnp.hardware_id = ACPI_ALLOCATE_ZEROED(strlen (hid) + 1); | 1112 | acpi_add_id(device, hid); |
| 1170 | if (device->pnp.hardware_id) { | 1113 | device->flags.hardware_id = 1; |
| 1171 | strcpy(device->pnp.hardware_id, hid); | ||
| 1172 | device->flags.hardware_id = 1; | ||
| 1173 | } | ||
| 1174 | } | 1114 | } |
| 1175 | if (!device->flags.hardware_id) | ||
| 1176 | device->pnp.hardware_id = ""; | ||
| 1177 | |||
| 1178 | if (uid) { | 1115 | if (uid) { |
| 1179 | device->pnp.unique_id = ACPI_ALLOCATE_ZEROED(strlen (uid) + 1); | 1116 | device->pnp.unique_id = ACPI_ALLOCATE_ZEROED(strlen (uid) + 1); |
| 1180 | if (device->pnp.unique_id) { | 1117 | if (device->pnp.unique_id) { |
| @@ -1185,24 +1122,12 @@ static void acpi_device_set_id(struct acpi_device *device) | |||
| 1185 | if (!device->flags.unique_id) | 1122 | if (!device->flags.unique_id) |
| 1186 | device->pnp.unique_id = ""; | 1123 | device->pnp.unique_id = ""; |
| 1187 | 1124 | ||
| 1188 | if (cid_list || cid_add) { | 1125 | if (cid_list) |
| 1189 | struct acpica_device_id_list *list; | 1126 | for (i = 0; i < cid_list->count; i++) |
| 1190 | 1127 | acpi_add_id(device, cid_list->ids[i].string); | |
| 1191 | if (cid_add) { | 1128 | if (cid_add) { |
| 1192 | struct acpica_device_id cid; | 1129 | acpi_add_id(device, cid_add); |
| 1193 | cid.length = strlen (cid_add) + 1; | 1130 | device->flags.compatible_ids = 1; |
| 1194 | cid.string = cid_add; | ||
| 1195 | |||
| 1196 | list = acpi_add_cid(info, &cid); | ||
| 1197 | } else { | ||
| 1198 | list = acpi_add_cid(info, NULL); | ||
| 1199 | } | ||
| 1200 | |||
| 1201 | if (list) { | ||
| 1202 | device->pnp.cid_list = list; | ||
| 1203 | if (cid_add) | ||
| 1204 | device->flags.compatible_ids = 1; | ||
| 1205 | } | ||
| 1206 | } | 1131 | } |
| 1207 | 1132 | ||
| 1208 | kfree(info); | 1133 | kfree(info); |
| @@ -1269,6 +1194,7 @@ static int acpi_add_single_object(struct acpi_device **child, | |||
| 1269 | return -ENOMEM; | 1194 | return -ENOMEM; |
| 1270 | } | 1195 | } |
| 1271 | 1196 | ||
| 1197 | INIT_LIST_HEAD(&device->pnp.ids); | ||
| 1272 | device->device_type = type; | 1198 | device->device_type = type; |
| 1273 | device->handle = handle; | 1199 | device->handle = handle; |
| 1274 | device->parent = acpi_bus_get_parent(handle); | 1200 | device->parent = acpi_bus_get_parent(handle); |
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index ff963d4dab46..3a4478f1fc72 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c | |||
| @@ -153,6 +153,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) | |||
| 153 | acpi_handle temp = NULL; | 153 | acpi_handle temp = NULL; |
| 154 | acpi_status status; | 154 | acpi_status status; |
| 155 | struct pnp_dev *dev; | 155 | struct pnp_dev *dev; |
| 156 | struct acpi_hardware_id *id; | ||
| 156 | 157 | ||
| 157 | /* | 158 | /* |
| 158 | * If a PnPacpi device is not present , the device | 159 | * If a PnPacpi device is not present , the device |
| @@ -193,15 +194,12 @@ static int __init pnpacpi_add_device(struct acpi_device *device) | |||
| 193 | if (dev->capabilities & PNP_CONFIGURABLE) | 194 | if (dev->capabilities & PNP_CONFIGURABLE) |
| 194 | pnpacpi_parse_resource_option_data(dev); | 195 | pnpacpi_parse_resource_option_data(dev); |
| 195 | 196 | ||
| 196 | if (device->flags.compatible_ids) { | 197 | list_for_each_entry(id, &device->pnp.ids, list) { |
| 197 | struct acpica_device_id_list *cid_list = device->pnp.cid_list; | 198 | if (!strcmp(id->id, acpi_device_hid(device))) |
| 198 | int i; | 199 | continue; |
| 199 | 200 | if (!ispnpidacpi(id->id)) | |
| 200 | for (i = 0; i < cid_list->count; i++) { | 201 | continue; |
| 201 | if (!ispnpidacpi(cid_list->ids[i].string)) | 202 | pnp_add_id(dev, id->id); |
| 202 | continue; | ||
| 203 | pnp_add_id(dev, cid_list->ids[i].string); | ||
| 204 | } | ||
| 205 | } | 203 | } |
| 206 | 204 | ||
| 207 | /* clear out the damaged flags */ | 205 | /* clear out the damaged flags */ |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 670f7f33837e..c2c434626edc 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
| @@ -171,19 +171,23 @@ typedef unsigned long acpi_bus_address; | |||
| 171 | typedef char acpi_device_name[40]; | 171 | typedef char acpi_device_name[40]; |
| 172 | typedef char acpi_device_class[20]; | 172 | typedef char acpi_device_class[20]; |
| 173 | 173 | ||
| 174 | struct acpi_hardware_id { | ||
| 175 | struct list_head list; | ||
| 176 | char *id; | ||
| 177 | }; | ||
| 178 | |||
| 174 | struct acpi_device_pnp { | 179 | struct acpi_device_pnp { |
| 175 | acpi_bus_id bus_id; /* Object name */ | 180 | acpi_bus_id bus_id; /* Object name */ |
| 176 | acpi_bus_address bus_address; /* _ADR */ | 181 | acpi_bus_address bus_address; /* _ADR */ |
| 177 | char *hardware_id; /* _HID */ | ||
| 178 | struct acpica_device_id_list *cid_list; /* _CIDs */ | ||
| 179 | char *unique_id; /* _UID */ | 182 | char *unique_id; /* _UID */ |
| 183 | struct list_head ids; /* _HID and _CIDs */ | ||
| 180 | acpi_device_name device_name; /* Driver-determined */ | 184 | acpi_device_name device_name; /* Driver-determined */ |
| 181 | acpi_device_class device_class; /* " */ | 185 | acpi_device_class device_class; /* " */ |
| 182 | }; | 186 | }; |
| 183 | 187 | ||
| 184 | #define acpi_device_bid(d) ((d)->pnp.bus_id) | 188 | #define acpi_device_bid(d) ((d)->pnp.bus_id) |
| 185 | #define acpi_device_adr(d) ((d)->pnp.bus_address) | 189 | #define acpi_device_adr(d) ((d)->pnp.bus_address) |
| 186 | #define acpi_device_hid(d) ((d)->pnp.hardware_id) | 190 | char *acpi_device_hid(struct acpi_device *device); |
| 187 | #define acpi_device_uid(d) ((d)->pnp.unique_id) | 191 | #define acpi_device_uid(d) ((d)->pnp.unique_id) |
| 188 | #define acpi_device_name(d) ((d)->pnp.device_name) | 192 | #define acpi_device_name(d) ((d)->pnp.device_name) |
| 189 | #define acpi_device_class(d) ((d)->pnp.device_class) | 193 | #define acpi_device_class(d) ((d)->pnp.device_class) |
