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.c183
1 files changed, 110 insertions, 73 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 318b1ea7a5bf..408ebde18986 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,
60 } 60 }
61 61
62 if (acpi_dev->flags.compatible_ids) { 62 if (acpi_dev->flags.compatible_ids) {
63 struct acpi_compatible_id_list *cid_list; 63 struct acpica_device_id_list *cid_list;
64 int i; 64 int i;
65 65
66 cid_list = acpi_dev->pnp.cid_list; 66 cid_list = acpi_dev->pnp.cid_list;
67 for (i = 0; i < cid_list->count; i++) { 67 for (i = 0; i < cid_list->count; i++) {
68 count = snprintf(&modalias[len], size, "%s:", 68 count = snprintf(&modalias[len], size, "%s:",
69 cid_list->id[i].value); 69 cid_list->ids[i].string);
70 if (count < 0 || count >= size) { 70 if (count < 0 || count >= size) {
71 printk(KERN_ERR PREFIX "%s cid[%i] exceeds event buffer size", 71 printk(KERN_ERR PREFIX "%s cid[%i] exceeds event buffer size",
72 acpi_dev->pnp.device_name, i); 72 acpi_dev->pnp.device_name, i);
@@ -287,14 +287,14 @@ int acpi_match_device_ids(struct acpi_device *device,
287 } 287 }
288 288
289 if (device->flags.compatible_ids) { 289 if (device->flags.compatible_ids) {
290 struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; 290 struct acpica_device_id_list *cid_list = device->pnp.cid_list;
291 int i; 291 int i;
292 292
293 for (id = ids; id->id[0]; id++) { 293 for (id = ids; id->id[0]; id++) {
294 /* compare multiple _CID entries against driver ids */ 294 /* compare multiple _CID entries against driver ids */
295 for (i = 0; i < cid_list->count; i++) { 295 for (i = 0; i < cid_list->count; i++) {
296 if (!strcmp((char*)id->id, 296 if (!strcmp((char*)id->id,
297 cid_list->id[i].value)) 297 cid_list->ids[i].string))
298 return 0; 298 return 0;
299 } 299 }
300 } 300 }
@@ -309,6 +309,10 @@ static void acpi_device_release(struct device *dev)
309 struct acpi_device *acpi_dev = to_acpi_device(dev); 309 struct acpi_device *acpi_dev = to_acpi_device(dev);
310 310
311 kfree(acpi_dev->pnp.cid_list); 311 kfree(acpi_dev->pnp.cid_list);
312 if (acpi_dev->flags.hardware_id)
313 kfree(acpi_dev->pnp.hardware_id);
314 if (acpi_dev->flags.unique_id)
315 kfree(acpi_dev->pnp.unique_id);
312 kfree(acpi_dev); 316 kfree(acpi_dev);
313} 317}
314 318
@@ -366,7 +370,8 @@ static acpi_status acpi_device_notify_fixed(void *data)
366{ 370{
367 struct acpi_device *device = data; 371 struct acpi_device *device = data;
368 372
369 acpi_device_notify(device->handle, ACPI_FIXED_HARDWARE_EVENT, device); 373 /* Fixed hardware devices have no handles */
374 acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device);
370 return AE_OK; 375 return AE_OK;
371} 376}
372 377
@@ -426,9 +431,6 @@ static int acpi_device_probe(struct device * dev)
426 if (acpi_drv->ops.notify) { 431 if (acpi_drv->ops.notify) {
427 ret = acpi_device_install_notify_handler(acpi_dev); 432 ret = acpi_device_install_notify_handler(acpi_dev);
428 if (ret) { 433 if (ret) {
429 if (acpi_drv->ops.stop)
430 acpi_drv->ops.stop(acpi_dev,
431 acpi_dev->removal_type);
432 if (acpi_drv->ops.remove) 434 if (acpi_drv->ops.remove)
433 acpi_drv->ops.remove(acpi_dev, 435 acpi_drv->ops.remove(acpi_dev,
434 acpi_dev->removal_type); 436 acpi_dev->removal_type);
@@ -452,8 +454,6 @@ static int acpi_device_remove(struct device * dev)
452 if (acpi_drv) { 454 if (acpi_drv) {
453 if (acpi_drv->ops.notify) 455 if (acpi_drv->ops.notify)
454 acpi_device_remove_notify_handler(acpi_dev); 456 acpi_device_remove_notify_handler(acpi_dev);
455 if (acpi_drv->ops.stop)
456 acpi_drv->ops.stop(acpi_dev, acpi_dev->removal_type);
457 if (acpi_drv->ops.remove) 457 if (acpi_drv->ops.remove)
458 acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type); 458 acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type);
459 } 459 }
@@ -687,7 +687,7 @@ acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd)
687} 687}
688EXPORT_SYMBOL_GPL(acpi_bus_get_ejd); 688EXPORT_SYMBOL_GPL(acpi_bus_get_ejd);
689 689
690void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context) 690void acpi_bus_data_handler(acpi_handle handle, void *context)
691{ 691{
692 692
693 /* TBD */ 693 /* TBD */
@@ -1000,33 +1000,89 @@ static int acpi_dock_match(struct acpi_device *device)
1000 return acpi_get_handle(device->handle, "_DCK", &tmp); 1000 return acpi_get_handle(device->handle, "_DCK", &tmp);
1001} 1001}
1002 1002
1003static struct acpica_device_id_list*
1004acpi_add_cid(
1005 struct acpi_device_info *info,
1006 struct acpica_device_id *new_cid)
1007{
1008 struct acpica_device_id_list *cid;
1009 char *next_id_string;
1010 acpi_size cid_length;
1011 acpi_size new_cid_length;
1012 u32 i;
1013
1014
1015 /* Allocate new CID list with room for the new CID */
1016
1017 if (!new_cid)
1018 new_cid_length = info->compatible_id_list.list_size;
1019 else if (info->compatible_id_list.list_size)
1020 new_cid_length = info->compatible_id_list.list_size +
1021 new_cid->length + sizeof(struct acpica_device_id);
1022 else
1023 new_cid_length = sizeof(struct acpica_device_id_list) + new_cid->length;
1024
1025 cid = ACPI_ALLOCATE_ZEROED(new_cid_length);
1026 if (!cid) {
1027 return NULL;
1028 }
1029
1030 cid->list_size = new_cid_length;
1031 cid->count = info->compatible_id_list.count;
1032 if (new_cid)
1033 cid->count++;
1034 next_id_string = (char *) cid->ids + (cid->count * sizeof(struct acpica_device_id));
1035
1036 /* Copy all existing CIDs */
1037
1038 for (i = 0; i < info->compatible_id_list.count; i++) {
1039 cid_length = info->compatible_id_list.ids[i].length;
1040 cid->ids[i].string = next_id_string;
1041 cid->ids[i].length = cid_length;
1042
1043 ACPI_MEMCPY(next_id_string, info->compatible_id_list.ids[i].string,
1044 cid_length);
1045
1046 next_id_string += cid_length;
1047 }
1048
1049 /* Append the new CID */
1050
1051 if (new_cid) {
1052 cid->ids[i].string = next_id_string;
1053 cid->ids[i].length = new_cid->length;
1054
1055 ACPI_MEMCPY(next_id_string, new_cid->string, new_cid->length);
1056 }
1057
1058 return cid;
1059}
1060
1003static void acpi_device_set_id(struct acpi_device *device, 1061static void acpi_device_set_id(struct acpi_device *device,
1004 struct acpi_device *parent, acpi_handle handle, 1062 struct acpi_device *parent, acpi_handle handle,
1005 int type) 1063 int type)
1006{ 1064{
1007 struct acpi_device_info *info; 1065 struct acpi_device_info *info = NULL;
1008 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1009 char *hid = NULL; 1066 char *hid = NULL;
1010 char *uid = NULL; 1067 char *uid = NULL;
1011 struct acpi_compatible_id_list *cid_list = NULL; 1068 struct acpica_device_id_list *cid_list = NULL;
1012 const char *cid_add = NULL; 1069 char *cid_add = NULL;
1013 acpi_status status; 1070 acpi_status status;
1014 1071
1015 switch (type) { 1072 switch (type) {
1016 case ACPI_BUS_TYPE_DEVICE: 1073 case ACPI_BUS_TYPE_DEVICE:
1017 status = acpi_get_object_info(handle, &buffer); 1074 status = acpi_get_object_info(handle, &info);
1018 if (ACPI_FAILURE(status)) { 1075 if (ACPI_FAILURE(status)) {
1019 printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__); 1076 printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__);
1020 return; 1077 return;
1021 } 1078 }
1022 1079
1023 info = buffer.pointer;
1024 if (info->valid & ACPI_VALID_HID) 1080 if (info->valid & ACPI_VALID_HID)
1025 hid = info->hardware_id.value; 1081 hid = info->hardware_id.string;
1026 if (info->valid & ACPI_VALID_UID) 1082 if (info->valid & ACPI_VALID_UID)
1027 uid = info->unique_id.value; 1083 uid = info->unique_id.string;
1028 if (info->valid & ACPI_VALID_CID) 1084 if (info->valid & ACPI_VALID_CID)
1029 cid_list = &info->compatibility_id; 1085 cid_list = &info->compatible_id_list;
1030 if (info->valid & ACPI_VALID_ADR) { 1086 if (info->valid & ACPI_VALID_ADR) {
1031 device->pnp.bus_address = info->address; 1087 device->pnp.bus_address = info->address;
1032 device->flags.bus_address = 1; 1088 device->flags.bus_address = 1;
@@ -1077,55 +1133,46 @@ static void acpi_device_set_id(struct acpi_device *device,
1077 } 1133 }
1078 1134
1079 if (hid) { 1135 if (hid) {
1080 strcpy(device->pnp.hardware_id, hid); 1136 device->pnp.hardware_id = ACPI_ALLOCATE_ZEROED(strlen (hid) + 1);
1081 device->flags.hardware_id = 1; 1137 if (device->pnp.hardware_id) {
1138 strcpy(device->pnp.hardware_id, hid);
1139 device->flags.hardware_id = 1;
1140 }
1082 } 1141 }
1142 if (!device->flags.hardware_id)
1143 device->pnp.hardware_id = "";
1144
1083 if (uid) { 1145 if (uid) {
1084 strcpy(device->pnp.unique_id, uid); 1146 device->pnp.unique_id = ACPI_ALLOCATE_ZEROED(strlen (uid) + 1);
1085 device->flags.unique_id = 1; 1147 if (device->pnp.unique_id) {
1148 strcpy(device->pnp.unique_id, uid);
1149 device->flags.unique_id = 1;
1150 }
1086 } 1151 }
1152 if (!device->flags.unique_id)
1153 device->pnp.unique_id = "";
1154
1087 if (cid_list || cid_add) { 1155 if (cid_list || cid_add) {
1088 struct acpi_compatible_id_list *list; 1156 struct acpica_device_id_list *list;
1089 int size = 0; 1157
1090 int count = 0; 1158 if (cid_add) {
1091 1159 struct acpica_device_id cid;
1092 if (cid_list) { 1160 cid.length = strlen (cid_add) + 1;
1093 size = cid_list->size; 1161 cid.string = cid_add;
1094 } else if (cid_add) { 1162
1095 size = sizeof(struct acpi_compatible_id_list); 1163 list = acpi_add_cid(info, &cid);
1096 cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); 1164 } else {
1097 if (!cid_list) { 1165 list = acpi_add_cid(info, NULL);
1098 printk(KERN_ERR "Memory allocation error\n");
1099 kfree(buffer.pointer);
1100 return;
1101 } else {
1102 cid_list->count = 0;
1103 cid_list->size = size;
1104 }
1105 } 1166 }
1106 if (cid_add)
1107 size += sizeof(struct acpi_compatible_id);
1108 list = kmalloc(size, GFP_KERNEL);
1109 1167
1110 if (list) { 1168 if (list) {
1111 if (cid_list) {
1112 memcpy(list, cid_list, cid_list->size);
1113 count = cid_list->count;
1114 }
1115 if (cid_add) {
1116 strncpy(list->id[count].value, cid_add,
1117 ACPI_MAX_CID_LENGTH);
1118 count++;
1119 device->flags.compatible_ids = 1;
1120 }
1121 list->size = size;
1122 list->count = count;
1123 device->pnp.cid_list = list; 1169 device->pnp.cid_list = list;
1124 } else 1170 if (cid_add)
1125 printk(KERN_ERR PREFIX "Memory allocation error\n"); 1171 device->flags.compatible_ids = 1;
1172 }
1126 } 1173 }
1127 1174
1128 kfree(buffer.pointer); 1175 kfree(info);
1129} 1176}
1130 1177
1131static int acpi_device_set_context(struct acpi_device *device, int type) 1178static int acpi_device_set_context(struct acpi_device *device, int type)
@@ -1265,16 +1312,6 @@ acpi_add_single_object(struct acpi_device **child,
1265 acpi_device_set_id(device, parent, handle, type); 1312 acpi_device_set_id(device, parent, handle, type);
1266 1313
1267 /* 1314 /*
1268 * The ACPI device is attached to acpi handle before getting
1269 * the power/wakeup/peformance flags. Otherwise OS can't get
1270 * the corresponding ACPI device by the acpi handle in the course
1271 * of getting the power/wakeup/performance flags.
1272 */
1273 result = acpi_device_set_context(device, type);
1274 if (result)
1275 goto end;
1276
1277 /*
1278 * Power Management 1315 * Power Management
1279 * ---------------- 1316 * ----------------
1280 */ 1317 */
@@ -1304,6 +1341,8 @@ acpi_add_single_object(struct acpi_device **child,
1304 goto end; 1341 goto end;
1305 } 1342 }
1306 1343
1344 if ((result = acpi_device_set_context(device, type)))
1345 goto end;
1307 1346
1308 result = acpi_device_register(device, parent); 1347 result = acpi_device_register(device, parent);
1309 1348
@@ -1318,10 +1357,8 @@ acpi_add_single_object(struct acpi_device **child,
1318end: 1357end:
1319 if (!result) 1358 if (!result)
1320 *child = device; 1359 *child = device;
1321 else { 1360 else
1322 kfree(device->pnp.cid_list); 1361 acpi_device_release(&device->dev);
1323 kfree(device);
1324 }
1325 1362
1326 return result; 1363 return result;
1327} 1364}