diff options
Diffstat (limited to 'drivers/acpi/scan.c')
| -rw-r--r-- | drivers/acpi/scan.c | 126 |
1 files changed, 101 insertions, 25 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index e85885593280..337d49b5564b 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -553,20 +553,29 @@ acpi_bus_driver_init ( | |||
| 553 | * upon possible configuration and currently allocated resources. | 553 | * upon possible configuration and currently allocated resources. |
| 554 | */ | 554 | */ |
| 555 | 555 | ||
| 556 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n")); | ||
| 557 | return_VALUE(0); | ||
| 558 | } | ||
| 559 | |||
| 560 | int | ||
| 561 | acpi_start_single_object ( | ||
| 562 | struct acpi_device *device) | ||
| 563 | { | ||
| 564 | int result = 0; | ||
| 565 | struct acpi_driver *driver; | ||
| 566 | |||
| 567 | ACPI_FUNCTION_TRACE("acpi_start_single_object"); | ||
| 568 | |||
| 569 | if (!(driver = device->driver)) | ||
| 570 | return_VALUE(0); | ||
| 571 | |||
| 556 | if (driver->ops.start) { | 572 | if (driver->ops.start) { |
| 557 | result = driver->ops.start(device); | 573 | result = driver->ops.start(device); |
| 558 | if (result && driver->ops.remove) | 574 | if (result && driver->ops.remove) |
| 559 | driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); | 575 | driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); |
| 560 | return_VALUE(result); | ||
| 561 | } | 576 | } |
| 562 | 577 | ||
| 563 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n")); | 578 | return_VALUE(result); |
| 564 | |||
| 565 | if (driver->ops.scan) { | ||
| 566 | driver->ops.scan(device); | ||
| 567 | } | ||
| 568 | |||
| 569 | return_VALUE(0); | ||
| 570 | } | 579 | } |
| 571 | 580 | ||
| 572 | static int acpi_driver_attach(struct acpi_driver * drv) | 581 | static int acpi_driver_attach(struct acpi_driver * drv) |
| @@ -586,6 +595,7 @@ static int acpi_driver_attach(struct acpi_driver * drv) | |||
| 586 | 595 | ||
| 587 | if (!acpi_bus_match(dev, drv)) { | 596 | if (!acpi_bus_match(dev, drv)) { |
| 588 | if (!acpi_bus_driver_init(dev, drv)) { | 597 | if (!acpi_bus_driver_init(dev, drv)) { |
| 598 | acpi_start_single_object(dev); | ||
| 589 | atomic_inc(&drv->references); | 599 | atomic_inc(&drv->references); |
| 590 | count++; | 600 | count++; |
| 591 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", | 601 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", |
| @@ -1009,8 +1019,8 @@ acpi_bus_remove ( | |||
| 1009 | } | 1019 | } |
| 1010 | 1020 | ||
| 1011 | 1021 | ||
| 1012 | int | 1022 | static int |
| 1013 | acpi_bus_add ( | 1023 | acpi_add_single_object ( |
| 1014 | struct acpi_device **child, | 1024 | struct acpi_device **child, |
| 1015 | struct acpi_device *parent, | 1025 | struct acpi_device *parent, |
| 1016 | acpi_handle handle, | 1026 | acpi_handle handle, |
| @@ -1019,7 +1029,7 @@ acpi_bus_add ( | |||
| 1019 | int result = 0; | 1029 | int result = 0; |
| 1020 | struct acpi_device *device = NULL; | 1030 | struct acpi_device *device = NULL; |
| 1021 | 1031 | ||
| 1022 | ACPI_FUNCTION_TRACE("acpi_bus_add"); | 1032 | ACPI_FUNCTION_TRACE("acpi_add_single_object"); |
| 1023 | 1033 | ||
| 1024 | if (!child) | 1034 | if (!child) |
| 1025 | return_VALUE(-EINVAL); | 1035 | return_VALUE(-EINVAL); |
| @@ -1140,7 +1150,7 @@ acpi_bus_add ( | |||
| 1140 | * | 1150 | * |
| 1141 | * TBD: Assumes LDM provides driver hot-plug capability. | 1151 | * TBD: Assumes LDM provides driver hot-plug capability. |
| 1142 | */ | 1152 | */ |
| 1143 | acpi_bus_find_driver(device); | 1153 | result = acpi_bus_find_driver(device); |
| 1144 | 1154 | ||
| 1145 | end: | 1155 | end: |
| 1146 | if (!result) | 1156 | if (!result) |
| @@ -1153,10 +1163,10 @@ end: | |||
| 1153 | 1163 | ||
| 1154 | return_VALUE(result); | 1164 | return_VALUE(result); |
| 1155 | } | 1165 | } |
| 1156 | EXPORT_SYMBOL(acpi_bus_add); | ||
| 1157 | 1166 | ||
| 1158 | 1167 | ||
| 1159 | int acpi_bus_scan (struct acpi_device *start) | 1168 | static int acpi_bus_scan (struct acpi_device *start, |
| 1169 | struct acpi_bus_ops *ops) | ||
| 1160 | { | 1170 | { |
| 1161 | acpi_status status = AE_OK; | 1171 | acpi_status status = AE_OK; |
| 1162 | struct acpi_device *parent = NULL; | 1172 | struct acpi_device *parent = NULL; |
| @@ -1229,9 +1239,20 @@ int acpi_bus_scan (struct acpi_device *start) | |||
| 1229 | continue; | 1239 | continue; |
| 1230 | } | 1240 | } |
| 1231 | 1241 | ||
| 1232 | status = acpi_bus_add(&child, parent, chandle, type); | 1242 | if (ops->acpi_op_add) |
| 1233 | if (ACPI_FAILURE(status)) | 1243 | status = acpi_add_single_object(&child, parent, |
| 1234 | continue; | 1244 | chandle, type); |
| 1245 | else | ||
| 1246 | status = acpi_bus_get_device(chandle, &child); | ||
| 1247 | |||
| 1248 | if (ACPI_FAILURE(status)) | ||
| 1249 | continue; | ||
| 1250 | |||
| 1251 | if (ops->acpi_op_start) { | ||
| 1252 | status = acpi_start_single_object(child); | ||
| 1253 | if (ACPI_FAILURE(status)) | ||
| 1254 | continue; | ||
| 1255 | } | ||
| 1235 | 1256 | ||
| 1236 | /* | 1257 | /* |
| 1237 | * If the device is present, enabled, and functioning then | 1258 | * If the device is present, enabled, and functioning then |
| @@ -1257,8 +1278,50 @@ int acpi_bus_scan (struct acpi_device *start) | |||
| 1257 | 1278 | ||
| 1258 | return_VALUE(0); | 1279 | return_VALUE(0); |
| 1259 | } | 1280 | } |
| 1260 | EXPORT_SYMBOL(acpi_bus_scan); | ||
| 1261 | 1281 | ||
| 1282 | int | ||
| 1283 | acpi_bus_add ( | ||
| 1284 | struct acpi_device **child, | ||
| 1285 | struct acpi_device *parent, | ||
| 1286 | acpi_handle handle, | ||
| 1287 | int type) | ||
| 1288 | { | ||
| 1289 | int result; | ||
| 1290 | struct acpi_bus_ops ops; | ||
| 1291 | |||
| 1292 | ACPI_FUNCTION_TRACE("acpi_bus_add"); | ||
| 1293 | |||
| 1294 | result = acpi_add_single_object(child, parent, handle, type); | ||
| 1295 | if (!result) { | ||
| 1296 | memset(&ops, 0, sizeof(ops)); | ||
| 1297 | ops.acpi_op_add = 1; | ||
| 1298 | result = acpi_bus_scan(*child, &ops); | ||
| 1299 | } | ||
| 1300 | return_VALUE(result); | ||
| 1301 | } | ||
| 1302 | EXPORT_SYMBOL(acpi_bus_add); | ||
| 1303 | |||
| 1304 | int | ||
| 1305 | acpi_bus_start ( | ||
| 1306 | struct acpi_device *device) | ||
| 1307 | { | ||
| 1308 | int result; | ||
| 1309 | struct acpi_bus_ops ops; | ||
| 1310 | |||
| 1311 | ACPI_FUNCTION_TRACE("acpi_bus_start"); | ||
| 1312 | |||
| 1313 | if (!device) | ||
| 1314 | return_VALUE(-EINVAL); | ||
| 1315 | |||
| 1316 | result = acpi_start_single_object(device); | ||
| 1317 | if (!result) { | ||
| 1318 | memset(&ops, 0, sizeof(ops)); | ||
| 1319 | ops.acpi_op_start = 1; | ||
| 1320 | result = acpi_bus_scan(device, &ops); | ||
| 1321 | } | ||
| 1322 | return_VALUE(result); | ||
| 1323 | } | ||
| 1324 | EXPORT_SYMBOL(acpi_bus_start); | ||
| 1262 | 1325 | ||
| 1263 | static int | 1326 | static int |
| 1264 | acpi_bus_trim(struct acpi_device *start, | 1327 | acpi_bus_trim(struct acpi_device *start, |
| @@ -1331,13 +1394,19 @@ acpi_bus_scan_fixed ( | |||
| 1331 | /* | 1394 | /* |
| 1332 | * Enumerate all fixed-feature devices. | 1395 | * Enumerate all fixed-feature devices. |
| 1333 | */ | 1396 | */ |
| 1334 | if (acpi_fadt.pwr_button == 0) | 1397 | if (acpi_fadt.pwr_button == 0) { |
| 1335 | result = acpi_bus_add(&device, acpi_root, | 1398 | result = acpi_add_single_object(&device, acpi_root, |
| 1336 | NULL, ACPI_BUS_TYPE_POWER_BUTTON); | 1399 | NULL, ACPI_BUS_TYPE_POWER_BUTTON); |
| 1400 | if (!result) | ||
| 1401 | result = acpi_start_single_object(device); | ||
| 1402 | } | ||
| 1337 | 1403 | ||
| 1338 | if (acpi_fadt.sleep_button == 0) | 1404 | if (acpi_fadt.sleep_button == 0) { |
| 1339 | result = acpi_bus_add(&device, acpi_root, | 1405 | result = acpi_add_single_object(&device, acpi_root, |
| 1340 | NULL, ACPI_BUS_TYPE_SLEEP_BUTTON); | 1406 | NULL, ACPI_BUS_TYPE_SLEEP_BUTTON); |
| 1407 | if (!result) | ||
| 1408 | result = acpi_start_single_object(device); | ||
| 1409 | } | ||
| 1341 | 1410 | ||
| 1342 | return_VALUE(result); | 1411 | return_VALUE(result); |
| 1343 | } | 1412 | } |
| @@ -1346,6 +1415,7 @@ acpi_bus_scan_fixed ( | |||
| 1346 | static int __init acpi_scan_init(void) | 1415 | static int __init acpi_scan_init(void) |
| 1347 | { | 1416 | { |
| 1348 | int result; | 1417 | int result; |
| 1418 | struct acpi_bus_ops ops; | ||
| 1349 | 1419 | ||
| 1350 | ACPI_FUNCTION_TRACE("acpi_scan_init"); | 1420 | ACPI_FUNCTION_TRACE("acpi_scan_init"); |
| 1351 | 1421 | ||
| @@ -1357,17 +1427,23 @@ static int __init acpi_scan_init(void) | |||
| 1357 | /* | 1427 | /* |
| 1358 | * Create the root device in the bus's device tree | 1428 | * Create the root device in the bus's device tree |
| 1359 | */ | 1429 | */ |
| 1360 | result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT, | 1430 | result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT, |
| 1361 | ACPI_BUS_TYPE_SYSTEM); | 1431 | ACPI_BUS_TYPE_SYSTEM); |
| 1362 | if (result) | 1432 | if (result) |
| 1363 | goto Done; | 1433 | goto Done; |
| 1364 | 1434 | ||
| 1435 | result = acpi_start_single_object(acpi_root); | ||
| 1436 | |||
| 1365 | /* | 1437 | /* |
| 1366 | * Enumerate devices in the ACPI namespace. | 1438 | * Enumerate devices in the ACPI namespace. |
| 1367 | */ | 1439 | */ |
| 1368 | result = acpi_bus_scan_fixed(acpi_root); | 1440 | result = acpi_bus_scan_fixed(acpi_root); |
| 1369 | if (!result) | 1441 | if (!result) { |
| 1370 | result = acpi_bus_scan(acpi_root); | 1442 | memset(&ops, 0, sizeof(ops)); |
| 1443 | ops.acpi_op_add = 1; | ||
| 1444 | ops.acpi_op_start = 1; | ||
| 1445 | result = acpi_bus_scan(acpi_root, &ops); | ||
| 1446 | } | ||
| 1371 | 1447 | ||
| 1372 | if (result) | 1448 | if (result) |
| 1373 | acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); | 1449 | acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); |
