diff options
author | Len Brown <len.brown@intel.com> | 2009-09-19 01:45:22 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-09-19 01:45:22 -0400 |
commit | 985f38781d19101aba121df423f92c87b208c6df (patch) | |
tree | 21b10413b6e24c0eaf5c3b2432e936749a672644 /drivers/acpi/scan.c | |
parent | d093d70a81b08673d1577ad73419998f02be9d29 (diff) | |
parent | c9766237afa92e8d7f27bbcd4964f1b43fa0bce8 (diff) |
Merge branch 'acpica' into release
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 163 |
1 files changed, 106 insertions, 57 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5699d979596d..297d8b94fbbc 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 | ||
@@ -687,7 +691,7 @@ acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd) | |||
687 | } | 691 | } |
688 | EXPORT_SYMBOL_GPL(acpi_bus_get_ejd); | 692 | EXPORT_SYMBOL_GPL(acpi_bus_get_ejd); |
689 | 693 | ||
690 | void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context) | 694 | void acpi_bus_data_handler(acpi_handle handle, void *context) |
691 | { | 695 | { |
692 | 696 | ||
693 | /* TBD */ | 697 | /* TBD */ |
@@ -1000,33 +1004,89 @@ static int acpi_dock_match(struct acpi_device *device) | |||
1000 | return acpi_get_handle(device->handle, "_DCK", &tmp); | 1004 | return acpi_get_handle(device->handle, "_DCK", &tmp); |
1001 | } | 1005 | } |
1002 | 1006 | ||
1007 | static struct acpica_device_id_list* | ||
1008 | acpi_add_cid( | ||
1009 | struct acpi_device_info *info, | ||
1010 | struct acpica_device_id *new_cid) | ||
1011 | { | ||
1012 | struct acpica_device_id_list *cid; | ||
1013 | char *next_id_string; | ||
1014 | acpi_size cid_length; | ||
1015 | acpi_size new_cid_length; | ||
1016 | u32 i; | ||
1017 | |||
1018 | |||
1019 | /* Allocate new CID list with room for the new CID */ | ||
1020 | |||
1021 | if (!new_cid) | ||
1022 | new_cid_length = info->compatible_id_list.list_size; | ||
1023 | else if (info->compatible_id_list.list_size) | ||
1024 | new_cid_length = info->compatible_id_list.list_size + | ||
1025 | new_cid->length + sizeof(struct acpica_device_id); | ||
1026 | else | ||
1027 | new_cid_length = sizeof(struct acpica_device_id_list) + new_cid->length; | ||
1028 | |||
1029 | cid = ACPI_ALLOCATE_ZEROED(new_cid_length); | ||
1030 | if (!cid) { | ||
1031 | return NULL; | ||
1032 | } | ||
1033 | |||
1034 | cid->list_size = new_cid_length; | ||
1035 | cid->count = info->compatible_id_list.count; | ||
1036 | if (new_cid) | ||
1037 | cid->count++; | ||
1038 | next_id_string = (char *) cid->ids + (cid->count * sizeof(struct acpica_device_id)); | ||
1039 | |||
1040 | /* Copy all existing CIDs */ | ||
1041 | |||
1042 | for (i = 0; i < info->compatible_id_list.count; i++) { | ||
1043 | cid_length = info->compatible_id_list.ids[i].length; | ||
1044 | cid->ids[i].string = next_id_string; | ||
1045 | cid->ids[i].length = cid_length; | ||
1046 | |||
1047 | ACPI_MEMCPY(next_id_string, info->compatible_id_list.ids[i].string, | ||
1048 | cid_length); | ||
1049 | |||
1050 | next_id_string += cid_length; | ||
1051 | } | ||
1052 | |||
1053 | /* Append the new CID */ | ||
1054 | |||
1055 | if (new_cid) { | ||
1056 | cid->ids[i].string = next_id_string; | ||
1057 | cid->ids[i].length = new_cid->length; | ||
1058 | |||
1059 | ACPI_MEMCPY(next_id_string, new_cid->string, new_cid->length); | ||
1060 | } | ||
1061 | |||
1062 | return cid; | ||
1063 | } | ||
1064 | |||
1003 | static void acpi_device_set_id(struct acpi_device *device, | 1065 | static void acpi_device_set_id(struct acpi_device *device, |
1004 | struct acpi_device *parent, acpi_handle handle, | 1066 | struct acpi_device *parent, acpi_handle handle, |
1005 | int type) | 1067 | int type) |
1006 | { | 1068 | { |
1007 | struct acpi_device_info *info; | 1069 | struct acpi_device_info *info = NULL; |
1008 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
1009 | char *hid = NULL; | 1070 | char *hid = NULL; |
1010 | char *uid = NULL; | 1071 | char *uid = NULL; |
1011 | struct acpi_compatible_id_list *cid_list = NULL; | 1072 | struct acpica_device_id_list *cid_list = NULL; |
1012 | const char *cid_add = NULL; | 1073 | char *cid_add = NULL; |
1013 | acpi_status status; | 1074 | acpi_status status; |
1014 | 1075 | ||
1015 | switch (type) { | 1076 | switch (type) { |
1016 | case ACPI_BUS_TYPE_DEVICE: | 1077 | case ACPI_BUS_TYPE_DEVICE: |
1017 | status = acpi_get_object_info(handle, &buffer); | 1078 | status = acpi_get_object_info(handle, &info); |
1018 | if (ACPI_FAILURE(status)) { | 1079 | if (ACPI_FAILURE(status)) { |
1019 | printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__); | 1080 | printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__); |
1020 | return; | 1081 | return; |
1021 | } | 1082 | } |
1022 | 1083 | ||
1023 | info = buffer.pointer; | ||
1024 | if (info->valid & ACPI_VALID_HID) | 1084 | if (info->valid & ACPI_VALID_HID) |
1025 | hid = info->hardware_id.value; | 1085 | hid = info->hardware_id.string; |
1026 | if (info->valid & ACPI_VALID_UID) | 1086 | if (info->valid & ACPI_VALID_UID) |
1027 | uid = info->unique_id.value; | 1087 | uid = info->unique_id.string; |
1028 | if (info->valid & ACPI_VALID_CID) | 1088 | if (info->valid & ACPI_VALID_CID) |
1029 | cid_list = &info->compatibility_id; | 1089 | cid_list = &info->compatible_id_list; |
1030 | if (info->valid & ACPI_VALID_ADR) { | 1090 | if (info->valid & ACPI_VALID_ADR) { |
1031 | device->pnp.bus_address = info->address; | 1091 | device->pnp.bus_address = info->address; |
1032 | device->flags.bus_address = 1; | 1092 | device->flags.bus_address = 1; |
@@ -1077,55 +1137,46 @@ static void acpi_device_set_id(struct acpi_device *device, | |||
1077 | } | 1137 | } |
1078 | 1138 | ||
1079 | if (hid) { | 1139 | if (hid) { |
1080 | strcpy(device->pnp.hardware_id, hid); | 1140 | device->pnp.hardware_id = ACPI_ALLOCATE_ZEROED(strlen (hid) + 1); |
1081 | device->flags.hardware_id = 1; | 1141 | if (device->pnp.hardware_id) { |
1142 | strcpy(device->pnp.hardware_id, hid); | ||
1143 | device->flags.hardware_id = 1; | ||
1144 | } | ||
1082 | } | 1145 | } |
1146 | if (!device->flags.hardware_id) | ||
1147 | device->pnp.hardware_id = ""; | ||
1148 | |||
1083 | if (uid) { | 1149 | if (uid) { |
1084 | strcpy(device->pnp.unique_id, uid); | 1150 | device->pnp.unique_id = ACPI_ALLOCATE_ZEROED(strlen (uid) + 1); |
1085 | device->flags.unique_id = 1; | 1151 | if (device->pnp.unique_id) { |
1152 | strcpy(device->pnp.unique_id, uid); | ||
1153 | device->flags.unique_id = 1; | ||
1154 | } | ||
1086 | } | 1155 | } |
1156 | if (!device->flags.unique_id) | ||
1157 | device->pnp.unique_id = ""; | ||
1158 | |||
1087 | if (cid_list || cid_add) { | 1159 | if (cid_list || cid_add) { |
1088 | struct acpi_compatible_id_list *list; | 1160 | struct acpica_device_id_list *list; |
1089 | int size = 0; | 1161 | |
1090 | int count = 0; | 1162 | if (cid_add) { |
1091 | 1163 | struct acpica_device_id cid; | |
1092 | if (cid_list) { | 1164 | cid.length = strlen (cid_add) + 1; |
1093 | size = cid_list->size; | 1165 | cid.string = cid_add; |
1094 | } else if (cid_add) { | 1166 | |
1095 | size = sizeof(struct acpi_compatible_id_list); | 1167 | list = acpi_add_cid(info, &cid); |
1096 | cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); | 1168 | } else { |
1097 | if (!cid_list) { | 1169 | 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 | } | 1170 | } |
1106 | if (cid_add) | ||
1107 | size += sizeof(struct acpi_compatible_id); | ||
1108 | list = kmalloc(size, GFP_KERNEL); | ||
1109 | 1171 | ||
1110 | if (list) { | 1172 | 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; | 1173 | device->pnp.cid_list = list; |
1124 | } else | 1174 | if (cid_add) |
1125 | printk(KERN_ERR PREFIX "Memory allocation error\n"); | 1175 | device->flags.compatible_ids = 1; |
1176 | } | ||
1126 | } | 1177 | } |
1127 | 1178 | ||
1128 | kfree(buffer.pointer); | 1179 | kfree(info); |
1129 | } | 1180 | } |
1130 | 1181 | ||
1131 | static int acpi_device_set_context(struct acpi_device *device, int type) | 1182 | static int acpi_device_set_context(struct acpi_device *device, int type) |
@@ -1310,10 +1361,8 @@ acpi_add_single_object(struct acpi_device **child, | |||
1310 | end: | 1361 | end: |
1311 | if (!result) | 1362 | if (!result) |
1312 | *child = device; | 1363 | *child = device; |
1313 | else { | 1364 | else |
1314 | kfree(device->pnp.cid_list); | 1365 | acpi_device_release(&device->dev); |
1315 | kfree(device); | ||
1316 | } | ||
1317 | 1366 | ||
1318 | return result; | 1367 | return result; |
1319 | } | 1368 | } |