aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c166
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,
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}
307EXPORT_SYMBOL(acpi_match_device_ids); 274EXPORT_SYMBOL(acpi_match_device_ids);
308 275
276static 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
309static void acpi_device_release(struct device *dev) 286static 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
1031static struct acpica_device_id_list* 1004char *acpi_device_hid(struct acpi_device *device)
1032acpi_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; 1011EXPORT_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 */ 1013static 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
1089static void acpi_device_set_id(struct acpi_device *device) 1031static 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);