diff options
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 110 |
1 files changed, 90 insertions, 20 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index d9d531cce27f..3fac011f9cf9 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -59,7 +59,7 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
59 | count = snprintf(&modalias[len], size, "%s:", | 59 | count = snprintf(&modalias[len], size, "%s:", |
60 | cid_list->id[i].value); | 60 | cid_list->id[i].value); |
61 | if (count < 0 || count >= size) { | 61 | if (count < 0 || count >= size) { |
62 | printk(KERN_ERR "acpi: %s cid[%i] exceeds event buffer size", | 62 | printk(KERN_ERR PREFIX "%s cid[%i] exceeds event buffer size", |
63 | acpi_dev->pnp.device_name, i); | 63 | acpi_dev->pnp.device_name, i); |
64 | break; | 64 | break; |
65 | } | 65 | } |
@@ -453,7 +453,7 @@ static int acpi_device_register(struct acpi_device *device, | |||
453 | device->dev.release = &acpi_device_release; | 453 | device->dev.release = &acpi_device_release; |
454 | result = device_add(&device->dev); | 454 | result = device_add(&device->dev); |
455 | if(result) { | 455 | if(result) { |
456 | printk("Error adding device %s", device->dev.bus_id); | 456 | printk(KERN_ERR PREFIX "Error adding device %s", device->dev.bus_id); |
457 | goto end; | 457 | goto end; |
458 | } | 458 | } |
459 | 459 | ||
@@ -941,6 +941,15 @@ static int acpi_bay_match(struct acpi_device *device){ | |||
941 | return -ENODEV; | 941 | return -ENODEV; |
942 | } | 942 | } |
943 | 943 | ||
944 | /* | ||
945 | * acpi_dock_match - see if a device has a _DCK method | ||
946 | */ | ||
947 | static int acpi_dock_match(struct acpi_device *device) | ||
948 | { | ||
949 | acpi_handle tmp; | ||
950 | return acpi_get_handle(device->handle, "_DCK", &tmp); | ||
951 | } | ||
952 | |||
944 | static void acpi_device_set_id(struct acpi_device *device, | 953 | static void acpi_device_set_id(struct acpi_device *device, |
945 | struct acpi_device *parent, acpi_handle handle, | 954 | struct acpi_device *parent, acpi_handle handle, |
946 | int type) | 955 | int type) |
@@ -950,13 +959,14 @@ static void acpi_device_set_id(struct acpi_device *device, | |||
950 | char *hid = NULL; | 959 | char *hid = NULL; |
951 | char *uid = NULL; | 960 | char *uid = NULL; |
952 | struct acpi_compatible_id_list *cid_list = NULL; | 961 | struct acpi_compatible_id_list *cid_list = NULL; |
962 | const char *cid_add = NULL; | ||
953 | acpi_status status; | 963 | acpi_status status; |
954 | 964 | ||
955 | switch (type) { | 965 | switch (type) { |
956 | case ACPI_BUS_TYPE_DEVICE: | 966 | case ACPI_BUS_TYPE_DEVICE: |
957 | status = acpi_get_object_info(handle, &buffer); | 967 | status = acpi_get_object_info(handle, &buffer); |
958 | if (ACPI_FAILURE(status)) { | 968 | if (ACPI_FAILURE(status)) { |
959 | printk("%s: Error reading device info\n", __FUNCTION__); | 969 | printk(KERN_ERR PREFIX "%s: Error reading device info\n", __FUNCTION__); |
960 | return; | 970 | return; |
961 | } | 971 | } |
962 | 972 | ||
@@ -972,15 +982,18 @@ static void acpi_device_set_id(struct acpi_device *device, | |||
972 | device->flags.bus_address = 1; | 982 | device->flags.bus_address = 1; |
973 | } | 983 | } |
974 | 984 | ||
975 | if(!(info->valid & (ACPI_VALID_HID | ACPI_VALID_CID))){ | 985 | /* If we have a video/bay/dock device, add our selfdefined |
976 | status = acpi_video_bus_match(device); | 986 | HID to the CID list. Like that the video/bay/dock drivers |
977 | if(ACPI_SUCCESS(status)) | 987 | will get autoloaded and the device might still match |
978 | hid = ACPI_VIDEO_HID; | 988 | against another driver. |
989 | */ | ||
990 | if (ACPI_SUCCESS(acpi_video_bus_match(device))) | ||
991 | cid_add = ACPI_VIDEO_HID; | ||
992 | else if (ACPI_SUCCESS(acpi_bay_match(device))) | ||
993 | cid_add = ACPI_BAY_HID; | ||
994 | else if (ACPI_SUCCESS(acpi_dock_match(device))) | ||
995 | cid_add = ACPI_DOCK_HID; | ||
979 | 996 | ||
980 | status = acpi_bay_match(device); | ||
981 | if (ACPI_SUCCESS(status)) | ||
982 | hid = ACPI_BAY_HID; | ||
983 | } | ||
984 | break; | 997 | break; |
985 | case ACPI_BUS_TYPE_POWER: | 998 | case ACPI_BUS_TYPE_POWER: |
986 | hid = ACPI_POWER_HID; | 999 | hid = ACPI_POWER_HID; |
@@ -1021,12 +1034,45 @@ static void acpi_device_set_id(struct acpi_device *device, | |||
1021 | strcpy(device->pnp.unique_id, uid); | 1034 | strcpy(device->pnp.unique_id, uid); |
1022 | device->flags.unique_id = 1; | 1035 | device->flags.unique_id = 1; |
1023 | } | 1036 | } |
1024 | if (cid_list) { | 1037 | if (cid_list || cid_add) { |
1025 | device->pnp.cid_list = kmalloc(cid_list->size, GFP_KERNEL); | 1038 | struct acpi_compatible_id_list *list; |
1026 | if (device->pnp.cid_list) | 1039 | int size = 0; |
1027 | memcpy(device->pnp.cid_list, cid_list, cid_list->size); | 1040 | int count = 0; |
1028 | else | 1041 | |
1029 | printk(KERN_ERR "Memory allocation error\n"); | 1042 | if (cid_list) { |
1043 | size = cid_list->size; | ||
1044 | } else if (cid_add) { | ||
1045 | size = sizeof(struct acpi_compatible_id_list); | ||
1046 | cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); | ||
1047 | if (!cid_list) { | ||
1048 | printk(KERN_ERR "Memory allocation error\n"); | ||
1049 | kfree(buffer.pointer); | ||
1050 | return; | ||
1051 | } else { | ||
1052 | cid_list->count = 0; | ||
1053 | cid_list->size = size; | ||
1054 | } | ||
1055 | } | ||
1056 | if (cid_add) | ||
1057 | size += sizeof(struct acpi_compatible_id); | ||
1058 | list = kmalloc(size, GFP_KERNEL); | ||
1059 | |||
1060 | if (list) { | ||
1061 | if (cid_list) { | ||
1062 | memcpy(list, cid_list, cid_list->size); | ||
1063 | count = cid_list->count; | ||
1064 | } | ||
1065 | if (cid_add) { | ||
1066 | strncpy(list->id[count].value, cid_add, | ||
1067 | ACPI_MAX_CID_LENGTH); | ||
1068 | count++; | ||
1069 | device->flags.compatible_ids = 1; | ||
1070 | } | ||
1071 | list->size = size; | ||
1072 | list->count = count; | ||
1073 | device->pnp.cid_list = list; | ||
1074 | } else | ||
1075 | printk(KERN_ERR PREFIX "Memory allocation error\n"); | ||
1030 | } | 1076 | } |
1031 | 1077 | ||
1032 | kfree(buffer.pointer); | 1078 | kfree(buffer.pointer); |
@@ -1050,7 +1096,7 @@ static int acpi_device_set_context(struct acpi_device *device, int type) | |||
1050 | acpi_bus_data_handler, device); | 1096 | acpi_bus_data_handler, device); |
1051 | 1097 | ||
1052 | if (ACPI_FAILURE(status)) { | 1098 | if (ACPI_FAILURE(status)) { |
1053 | printk("Error attaching device data\n"); | 1099 | printk(KERN_ERR PREFIX "Error attaching device data\n"); |
1054 | result = -ENODEV; | 1100 | result = -ENODEV; |
1055 | } | 1101 | } |
1056 | } | 1102 | } |
@@ -1081,6 +1127,20 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) | |||
1081 | } | 1127 | } |
1082 | 1128 | ||
1083 | static int | 1129 | static int |
1130 | acpi_is_child_device(struct acpi_device *device, | ||
1131 | int (*matcher)(struct acpi_device *)) | ||
1132 | { | ||
1133 | int result = -ENODEV; | ||
1134 | |||
1135 | do { | ||
1136 | if (ACPI_SUCCESS(matcher(device))) | ||
1137 | return AE_OK; | ||
1138 | } while ((device = device->parent)); | ||
1139 | |||
1140 | return result; | ||
1141 | } | ||
1142 | |||
1143 | static int | ||
1084 | acpi_add_single_object(struct acpi_device **child, | 1144 | acpi_add_single_object(struct acpi_device **child, |
1085 | struct acpi_device *parent, acpi_handle handle, int type, | 1145 | struct acpi_device *parent, acpi_handle handle, int type, |
1086 | struct acpi_bus_ops *ops) | 1146 | struct acpi_bus_ops *ops) |
@@ -1131,10 +1191,20 @@ acpi_add_single_object(struct acpi_device **child, | |||
1131 | case ACPI_BUS_TYPE_PROCESSOR: | 1191 | case ACPI_BUS_TYPE_PROCESSOR: |
1132 | case ACPI_BUS_TYPE_DEVICE: | 1192 | case ACPI_BUS_TYPE_DEVICE: |
1133 | result = acpi_bus_get_status(device); | 1193 | result = acpi_bus_get_status(device); |
1134 | if (ACPI_FAILURE(result) || !device->status.present) { | 1194 | if (ACPI_FAILURE(result)) { |
1135 | result = -ENOENT; | 1195 | result = -ENODEV; |
1136 | goto end; | 1196 | goto end; |
1137 | } | 1197 | } |
1198 | if (!device->status.present) { | ||
1199 | /* Bay and dock should be handled even if absent */ | ||
1200 | if (!ACPI_SUCCESS( | ||
1201 | acpi_is_child_device(device, acpi_bay_match)) && | ||
1202 | !ACPI_SUCCESS( | ||
1203 | acpi_is_child_device(device, acpi_dock_match))) { | ||
1204 | result = -ENODEV; | ||
1205 | goto end; | ||
1206 | } | ||
1207 | } | ||
1138 | break; | 1208 | break; |
1139 | default: | 1209 | default: |
1140 | STRUCT_TO_INT(device->status) = | 1210 | STRUCT_TO_INT(device->status) = |