aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2009-06-29 01:39:29 -0400
committerLen Brown <len.brown@intel.com>2009-08-27 10:17:15 -0400
commit15b8dd53f5ffaf8e2d9095c423f713423f576c0f (patch)
tree773f09435b14a810372642502352d46c29b6f148 /drivers/acpi/scan.c
parent9c61b34cf7078da72cce276ff8cfae5d6e9955bc (diff)
ACPICA: Major update for acpi_get_object_info external interface
Completed a major update for the acpi_get_object_info external interface. Changes include: - Support for variable, unlimited length HID, UID, and CID strings - Support Processor objects the same as Devices (HID,UID,CID,ADR,STA, etc.) - Call the _SxW power methods on behalf of a device object - Determine if a device is a PCI root bridge - Change the ACPI_BUFFER parameter to ACPI_DEVICE_INFO. These changes will require an update to all callers of this interface. See the ACPICA Programmer Reference for details. Also, update all invocations of acpi_get_object_info interface Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c153
1 files changed, 99 insertions, 54 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 781435d7e369..0ab526de7c55 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 }
@@ -999,33 +999,89 @@ static int acpi_dock_match(struct acpi_device *device)
999 return acpi_get_handle(device->handle, "_DCK", &tmp); 999 return acpi_get_handle(device->handle, "_DCK", &tmp);
1000} 1000}
1001 1001
1002static struct acpica_device_id_list*
1003acpi_add_cid(
1004 struct acpi_device_info *info,
1005 struct acpica_device_id *new_cid)
1006{
1007 struct acpica_device_id_list *cid;
1008 char *next_id_string;
1009 acpi_size cid_length;
1010 acpi_size new_cid_length;
1011 u32 i;
1012
1013
1014 /* Allocate new CID list with room for the new CID */
1015
1016 if (!new_cid)
1017 new_cid_length = info->compatible_id_list.list_size;
1018 else if (info->compatible_id_list.list_size)
1019 new_cid_length = info->compatible_id_list.list_size +
1020 new_cid->length + sizeof(struct acpica_device_id);
1021 else
1022 new_cid_length = sizeof(struct acpica_device_id_list) + new_cid->length;
1023
1024 cid = ACPI_ALLOCATE_ZEROED(new_cid_length);
1025 if (!cid) {
1026 return NULL;
1027 }
1028
1029 cid->list_size = new_cid_length;
1030 cid->count = info->compatible_id_list.count;
1031 if (new_cid)
1032 cid->count++;
1033 next_id_string = (char *) cid->ids + (cid->count * sizeof(struct acpica_device_id));
1034
1035 /* Copy all existing CIDs */
1036
1037 for (i = 0; i < info->compatible_id_list.count; i++) {
1038 cid_length = info->compatible_id_list.ids[i].length;
1039 cid->ids[i].string = next_id_string;
1040 cid->ids[i].length = cid_length;
1041
1042 ACPI_MEMCPY(next_id_string, info->compatible_id_list.ids[i].string,
1043 cid_length);
1044
1045 next_id_string += cid_length;
1046 }
1047
1048 /* Append the new CID */
1049
1050 if (new_cid) {
1051 cid->ids[i].string = next_id_string;
1052 cid->ids[i].length = new_cid->length;
1053
1054 ACPI_MEMCPY(next_id_string, new_cid->string, new_cid->length);
1055 }
1056
1057 return cid;
1058}
1059
1002static void acpi_device_set_id(struct acpi_device *device, 1060static void acpi_device_set_id(struct acpi_device *device,
1003 struct acpi_device *parent, acpi_handle handle, 1061 struct acpi_device *parent, acpi_handle handle,
1004 int type) 1062 int type)
1005{ 1063{
1006 struct acpi_device_info *info; 1064 struct acpi_device_info *info = NULL;
1007 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1008 char *hid = NULL; 1065 char *hid = NULL;
1009 char *uid = NULL; 1066 char *uid = NULL;
1010 struct acpi_compatible_id_list *cid_list = NULL; 1067 struct acpica_device_id_list *cid_list = NULL;
1011 const char *cid_add = NULL; 1068 char *cid_add = NULL;
1012 acpi_status status; 1069 acpi_status status;
1013 1070
1014 switch (type) { 1071 switch (type) {
1015 case ACPI_BUS_TYPE_DEVICE: 1072 case ACPI_BUS_TYPE_DEVICE:
1016 status = acpi_get_object_info(handle, &buffer); 1073 status = acpi_get_object_info(handle, &info);
1017 if (ACPI_FAILURE(status)) { 1074 if (ACPI_FAILURE(status)) {
1018 printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__); 1075 printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__);
1019 return; 1076 return;
1020 } 1077 }
1021 1078
1022 info = buffer.pointer;
1023 if (info->valid & ACPI_VALID_HID) 1079 if (info->valid & ACPI_VALID_HID)
1024 hid = info->hardware_id.value; 1080 hid = info->hardware_id.string;
1025 if (info->valid & ACPI_VALID_UID) 1081 if (info->valid & ACPI_VALID_UID)
1026 uid = info->unique_id.value; 1082 uid = info->unique_id.string;
1027 if (info->valid & ACPI_VALID_CID) 1083 if (info->valid & ACPI_VALID_CID)
1028 cid_list = &info->compatibility_id; 1084 cid_list = &info->compatible_id_list;
1029 if (info->valid & ACPI_VALID_ADR) { 1085 if (info->valid & ACPI_VALID_ADR) {
1030 device->pnp.bus_address = info->address; 1086 device->pnp.bus_address = info->address;
1031 device->flags.bus_address = 1; 1087 device->flags.bus_address = 1;
@@ -1076,55 +1132,44 @@ static void acpi_device_set_id(struct acpi_device *device,
1076 } 1132 }
1077 1133
1078 if (hid) { 1134 if (hid) {
1079 strcpy(device->pnp.hardware_id, hid); 1135 device->pnp.hardware_id = ACPI_ALLOCATE_ZEROED(strlen (hid) + 1);
1080 device->flags.hardware_id = 1; 1136 if (device->pnp.hardware_id) {
1081 } 1137 strcpy(device->pnp.hardware_id, hid);
1138 device->flags.hardware_id = 1;
1139 }
1140 } else
1141 device->pnp.hardware_id = NULL;
1142
1082 if (uid) { 1143 if (uid) {
1083 strcpy(device->pnp.unique_id, uid); 1144 device->pnp.unique_id = ACPI_ALLOCATE_ZEROED(strlen (uid) + 1);
1084 device->flags.unique_id = 1; 1145 if (device->pnp.unique_id) {
1085 } 1146 strcpy(device->pnp.unique_id, uid);
1147 device->flags.unique_id = 1;
1148 }
1149 } else
1150 device->pnp.unique_id = NULL;
1151
1086 if (cid_list || cid_add) { 1152 if (cid_list || cid_add) {
1087 struct acpi_compatible_id_list *list; 1153 struct acpica_device_id_list *list;
1088 int size = 0; 1154
1089 int count = 0; 1155 if (cid_add) {
1090 1156 struct acpica_device_id cid;
1091 if (cid_list) { 1157 cid.length = strlen (cid_add) + 1;
1092 size = cid_list->size; 1158 cid.string = cid_add;
1093 } else if (cid_add) { 1159
1094 size = sizeof(struct acpi_compatible_id_list); 1160 list = acpi_add_cid(info, &cid);
1095 cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); 1161 } else {
1096 if (!cid_list) { 1162 list = acpi_add_cid(info, NULL);
1097 printk(KERN_ERR "Memory allocation error\n");
1098 kfree(buffer.pointer);
1099 return;
1100 } else {
1101 cid_list->count = 0;
1102 cid_list->size = size;
1103 }
1104 } 1163 }
1105 if (cid_add)
1106 size += sizeof(struct acpi_compatible_id);
1107 list = kmalloc(size, GFP_KERNEL);
1108 1164
1109 if (list) { 1165 if (list) {
1110 if (cid_list) {
1111 memcpy(list, cid_list, cid_list->size);
1112 count = cid_list->count;
1113 }
1114 if (cid_add) {
1115 strncpy(list->id[count].value, cid_add,
1116 ACPI_MAX_CID_LENGTH);
1117 count++;
1118 device->flags.compatible_ids = 1;
1119 }
1120 list->size = size;
1121 list->count = count;
1122 device->pnp.cid_list = list; 1166 device->pnp.cid_list = list;
1123 } else 1167 if (cid_add)
1124 printk(KERN_ERR PREFIX "Memory allocation error\n"); 1168 device->flags.compatible_ids = 1;
1169 }
1125 } 1170 }
1126 1171
1127 kfree(buffer.pointer); 1172 kfree(info);
1128} 1173}
1129 1174
1130static int acpi_device_set_context(struct acpi_device *device, int type) 1175static int acpi_device_set_context(struct acpi_device *device, int type)