aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c126
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
560int
561acpi_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
572static int acpi_driver_attach(struct acpi_driver * drv) 581static 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
1012int 1022static int
1013acpi_bus_add ( 1023acpi_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
1145end: 1155end:
1146 if (!result) 1156 if (!result)
@@ -1153,10 +1163,10 @@ end:
1153 1163
1154 return_VALUE(result); 1164 return_VALUE(result);
1155} 1165}
1156EXPORT_SYMBOL(acpi_bus_add);
1157 1166
1158 1167
1159int acpi_bus_scan (struct acpi_device *start) 1168static 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}
1260EXPORT_SYMBOL(acpi_bus_scan);
1261 1281
1282int
1283acpi_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}
1302EXPORT_SYMBOL(acpi_bus_add);
1303
1304int
1305acpi_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}
1324EXPORT_SYMBOL(acpi_bus_start);
1262 1325
1263static int 1326static int
1264acpi_bus_trim(struct acpi_device *start, 1327acpi_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 (
1346static int __init acpi_scan_init(void) 1415static 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);