diff options
author | Len Brown <len.brown@intel.com> | 2008-10-22 23:19:50 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2008-10-22 23:19:50 -0400 |
commit | 955ba395616a78780e70dc3f3b0b56ca4db52e5c (patch) | |
tree | f5978cfdc2b5ede82445de6675301a0171e66ea0 /drivers/acpi/scan.c | |
parent | aa58329fc8ec50b379388fcad55f62c3493730d3 (diff) | |
parent | 383d7a11c9989205db44c7f1be339e5097062f03 (diff) |
Merge branch 'bugfixes' into test
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 62 |
1 files changed, 36 insertions, 26 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f6f52c1a2aba..91fed422bae8 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -276,6 +276,13 @@ int acpi_match_device_ids(struct acpi_device *device, | |||
276 | { | 276 | { |
277 | const struct acpi_device_id *id; | 277 | const struct acpi_device_id *id; |
278 | 278 | ||
279 | /* | ||
280 | * If the device is not present, it is unnecessary to load device | ||
281 | * driver for it. | ||
282 | */ | ||
283 | if (!device->status.present) | ||
284 | return -ENODEV; | ||
285 | |||
279 | if (device->flags.hardware_id) { | 286 | if (device->flags.hardware_id) { |
280 | for (id = ids; id->id[0]; id++) { | 287 | for (id = ids; id->id[0]; id++) { |
281 | if (!strcmp((char*)id->id, device->pnp.hardware_id)) | 288 | if (!strcmp((char*)id->id, device->pnp.hardware_id)) |
@@ -807,6 +814,7 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) | |||
807 | /* TBD: System wake support and resource requirements. */ | 814 | /* TBD: System wake support and resource requirements. */ |
808 | 815 | ||
809 | device->power.state = ACPI_STATE_UNKNOWN; | 816 | device->power.state = ACPI_STATE_UNKNOWN; |
817 | acpi_bus_get_power(device->handle, &(device->power.state)); | ||
810 | 818 | ||
811 | return 0; | 819 | return 0; |
812 | } | 820 | } |
@@ -1153,20 +1161,6 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) | |||
1153 | } | 1161 | } |
1154 | 1162 | ||
1155 | static int | 1163 | static int |
1156 | acpi_is_child_device(struct acpi_device *device, | ||
1157 | int (*matcher)(struct acpi_device *)) | ||
1158 | { | ||
1159 | int result = -ENODEV; | ||
1160 | |||
1161 | do { | ||
1162 | if (ACPI_SUCCESS(matcher(device))) | ||
1163 | return AE_OK; | ||
1164 | } while ((device = device->parent)); | ||
1165 | |||
1166 | return result; | ||
1167 | } | ||
1168 | |||
1169 | static int | ||
1170 | acpi_add_single_object(struct acpi_device **child, | 1164 | acpi_add_single_object(struct acpi_device **child, |
1171 | struct acpi_device *parent, acpi_handle handle, int type, | 1165 | struct acpi_device *parent, acpi_handle handle, int type, |
1172 | struct acpi_bus_ops *ops) | 1166 | struct acpi_bus_ops *ops) |
@@ -1221,15 +1215,18 @@ acpi_add_single_object(struct acpi_device **child, | |||
1221 | result = -ENODEV; | 1215 | result = -ENODEV; |
1222 | goto end; | 1216 | goto end; |
1223 | } | 1217 | } |
1224 | if (!device->status.present) { | 1218 | /* |
1225 | /* Bay and dock should be handled even if absent */ | 1219 | * When the device is neither present nor functional, the |
1226 | if (!ACPI_SUCCESS( | 1220 | * device should not be added to Linux ACPI device tree. |
1227 | acpi_is_child_device(device, acpi_bay_match)) && | 1221 | * When the status of the device is not present but functinal, |
1228 | !ACPI_SUCCESS( | 1222 | * it should be added to Linux ACPI tree. For example : bay |
1229 | acpi_is_child_device(device, acpi_dock_match))) { | 1223 | * device , dock device. |
1230 | result = -ENODEV; | 1224 | * In such conditions it is unncessary to check whether it is |
1231 | goto end; | 1225 | * bay device or dock device. |
1232 | } | 1226 | */ |
1227 | if (!device->status.present && !device->status.functional) { | ||
1228 | result = -ENODEV; | ||
1229 | goto end; | ||
1233 | } | 1230 | } |
1234 | break; | 1231 | break; |
1235 | default: | 1232 | default: |
@@ -1252,6 +1249,16 @@ acpi_add_single_object(struct acpi_device **child, | |||
1252 | acpi_device_set_id(device, parent, handle, type); | 1249 | acpi_device_set_id(device, parent, handle, type); |
1253 | 1250 | ||
1254 | /* | 1251 | /* |
1252 | * The ACPI device is attached to acpi handle before getting | ||
1253 | * the power/wakeup/peformance flags. Otherwise OS can't get | ||
1254 | * the corresponding ACPI device by the acpi handle in the course | ||
1255 | * of getting the power/wakeup/performance flags. | ||
1256 | */ | ||
1257 | result = acpi_device_set_context(device, type); | ||
1258 | if (result) | ||
1259 | goto end; | ||
1260 | |||
1261 | /* | ||
1255 | * Power Management | 1262 | * Power Management |
1256 | * ---------------- | 1263 | * ---------------- |
1257 | */ | 1264 | */ |
@@ -1281,8 +1288,6 @@ acpi_add_single_object(struct acpi_device **child, | |||
1281 | goto end; | 1288 | goto end; |
1282 | } | 1289 | } |
1283 | 1290 | ||
1284 | if ((result = acpi_device_set_context(device, type))) | ||
1285 | goto end; | ||
1286 | 1291 | ||
1287 | result = acpi_device_register(device, parent); | 1292 | result = acpi_device_register(device, parent); |
1288 | 1293 | ||
@@ -1402,7 +1407,12 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops) | |||
1402 | * TBD: Need notifications and other detection mechanisms | 1407 | * TBD: Need notifications and other detection mechanisms |
1403 | * in place before we can fully implement this. | 1408 | * in place before we can fully implement this. |
1404 | */ | 1409 | */ |
1405 | if (child->status.present) { | 1410 | /* |
1411 | * When the device is not present but functional, it is also | ||
1412 | * necessary to scan the children of this device. | ||
1413 | */ | ||
1414 | if (child->status.present || (!child->status.present && | ||
1415 | child->status.functional)) { | ||
1406 | status = acpi_get_next_object(ACPI_TYPE_ANY, chandle, | 1416 | status = acpi_get_next_object(ACPI_TYPE_ANY, chandle, |
1407 | NULL, NULL); | 1417 | NULL, NULL); |
1408 | if (ACPI_SUCCESS(status)) { | 1418 | if (ACPI_SUCCESS(status)) { |