diff options
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 130 |
1 files changed, 103 insertions, 27 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 7c26fed0bdf0..cbcda30c172d 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -65,14 +65,14 @@ static ssize_t acpi_device_attr_show(struct kobject *kobj, | |||
65 | { | 65 | { |
66 | struct acpi_device *device = to_acpi_device(kobj); | 66 | struct acpi_device *device = to_acpi_device(kobj); |
67 | struct acpi_device_attribute *attribute = to_handle_attr(attr); | 67 | struct acpi_device_attribute *attribute = to_handle_attr(attr); |
68 | return attribute->show ? attribute->show(device, buf) : 0; | 68 | return attribute->show ? attribute->show(device, buf) : -EIO; |
69 | } | 69 | } |
70 | static ssize_t acpi_device_attr_store(struct kobject *kobj, | 70 | static ssize_t acpi_device_attr_store(struct kobject *kobj, |
71 | struct attribute *attr, const char *buf, size_t len) | 71 | struct attribute *attr, const char *buf, size_t len) |
72 | { | 72 | { |
73 | struct acpi_device *device = to_acpi_device(kobj); | 73 | struct acpi_device *device = to_acpi_device(kobj); |
74 | struct acpi_device_attribute *attribute = to_handle_attr(attr); | 74 | struct acpi_device_attribute *attribute = to_handle_attr(attr); |
75 | return attribute->store ? attribute->store(device, buf, len) : len; | 75 | return attribute->store ? attribute->store(device, buf, len) : -EIO; |
76 | } | 76 | } |
77 | 77 | ||
78 | static struct sysfs_ops acpi_device_sysfs_ops = { | 78 | static struct sysfs_ops acpi_device_sysfs_ops = { |
@@ -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); |
@@ -1142,7 +1152,7 @@ acpi_bus_add ( | |||
1142 | * | 1152 | * |
1143 | * TBD: Assumes LDM provides driver hot-plug capability. | 1153 | * TBD: Assumes LDM provides driver hot-plug capability. |
1144 | */ | 1154 | */ |
1145 | acpi_bus_find_driver(device); | 1155 | result = acpi_bus_find_driver(device); |
1146 | 1156 | ||
1147 | end: | 1157 | end: |
1148 | if (!result) | 1158 | if (!result) |
@@ -1155,10 +1165,10 @@ end: | |||
1155 | 1165 | ||
1156 | return_VALUE(result); | 1166 | return_VALUE(result); |
1157 | } | 1167 | } |
1158 | EXPORT_SYMBOL(acpi_bus_add); | ||
1159 | 1168 | ||
1160 | 1169 | ||
1161 | int acpi_bus_scan (struct acpi_device *start) | 1170 | static int acpi_bus_scan (struct acpi_device *start, |
1171 | struct acpi_bus_ops *ops) | ||
1162 | { | 1172 | { |
1163 | acpi_status status = AE_OK; | 1173 | acpi_status status = AE_OK; |
1164 | struct acpi_device *parent = NULL; | 1174 | struct acpi_device *parent = NULL; |
@@ -1231,9 +1241,20 @@ int acpi_bus_scan (struct acpi_device *start) | |||
1231 | continue; | 1241 | continue; |
1232 | } | 1242 | } |
1233 | 1243 | ||
1234 | status = acpi_bus_add(&child, parent, chandle, type); | 1244 | if (ops->acpi_op_add) |
1235 | if (ACPI_FAILURE(status)) | 1245 | status = acpi_add_single_object(&child, parent, |
1236 | continue; | 1246 | chandle, type); |
1247 | else | ||
1248 | status = acpi_bus_get_device(chandle, &child); | ||
1249 | |||
1250 | if (ACPI_FAILURE(status)) | ||
1251 | continue; | ||
1252 | |||
1253 | if (ops->acpi_op_start) { | ||
1254 | status = acpi_start_single_object(child); | ||
1255 | if (ACPI_FAILURE(status)) | ||
1256 | continue; | ||
1257 | } | ||
1237 | 1258 | ||
1238 | /* | 1259 | /* |
1239 | * If the device is present, enabled, and functioning then | 1260 | * If the device is present, enabled, and functioning then |
@@ -1259,8 +1280,50 @@ int acpi_bus_scan (struct acpi_device *start) | |||
1259 | 1280 | ||
1260 | return_VALUE(0); | 1281 | return_VALUE(0); |
1261 | } | 1282 | } |
1262 | EXPORT_SYMBOL(acpi_bus_scan); | ||
1263 | 1283 | ||
1284 | int | ||
1285 | acpi_bus_add ( | ||
1286 | struct acpi_device **child, | ||
1287 | struct acpi_device *parent, | ||
1288 | acpi_handle handle, | ||
1289 | int type) | ||
1290 | { | ||
1291 | int result; | ||
1292 | struct acpi_bus_ops ops; | ||
1293 | |||
1294 | ACPI_FUNCTION_TRACE("acpi_bus_add"); | ||
1295 | |||
1296 | result = acpi_add_single_object(child, parent, handle, type); | ||
1297 | if (!result) { | ||
1298 | memset(&ops, 0, sizeof(ops)); | ||
1299 | ops.acpi_op_add = 1; | ||
1300 | result = acpi_bus_scan(*child, &ops); | ||
1301 | } | ||
1302 | return_VALUE(result); | ||
1303 | } | ||
1304 | EXPORT_SYMBOL(acpi_bus_add); | ||
1305 | |||
1306 | int | ||
1307 | acpi_bus_start ( | ||
1308 | struct acpi_device *device) | ||
1309 | { | ||
1310 | int result; | ||
1311 | struct acpi_bus_ops ops; | ||
1312 | |||
1313 | ACPI_FUNCTION_TRACE("acpi_bus_start"); | ||
1314 | |||
1315 | if (!device) | ||
1316 | return_VALUE(-EINVAL); | ||
1317 | |||
1318 | result = acpi_start_single_object(device); | ||
1319 | if (!result) { | ||
1320 | memset(&ops, 0, sizeof(ops)); | ||
1321 | ops.acpi_op_start = 1; | ||
1322 | result = acpi_bus_scan(device, &ops); | ||
1323 | } | ||
1324 | return_VALUE(result); | ||
1325 | } | ||
1326 | EXPORT_SYMBOL(acpi_bus_start); | ||
1264 | 1327 | ||
1265 | static int | 1328 | static int |
1266 | acpi_bus_trim(struct acpi_device *start, | 1329 | acpi_bus_trim(struct acpi_device *start, |
@@ -1333,13 +1396,19 @@ acpi_bus_scan_fixed ( | |||
1333 | /* | 1396 | /* |
1334 | * Enumerate all fixed-feature devices. | 1397 | * Enumerate all fixed-feature devices. |
1335 | */ | 1398 | */ |
1336 | if (acpi_fadt.pwr_button == 0) | 1399 | if (acpi_fadt.pwr_button == 0) { |
1337 | result = acpi_bus_add(&device, acpi_root, | 1400 | result = acpi_add_single_object(&device, acpi_root, |
1338 | NULL, ACPI_BUS_TYPE_POWER_BUTTON); | 1401 | NULL, ACPI_BUS_TYPE_POWER_BUTTON); |
1402 | if (!result) | ||
1403 | result = acpi_start_single_object(device); | ||
1404 | } | ||
1339 | 1405 | ||
1340 | if (acpi_fadt.sleep_button == 0) | 1406 | if (acpi_fadt.sleep_button == 0) { |
1341 | result = acpi_bus_add(&device, acpi_root, | 1407 | result = acpi_add_single_object(&device, acpi_root, |
1342 | NULL, ACPI_BUS_TYPE_SLEEP_BUTTON); | 1408 | NULL, ACPI_BUS_TYPE_SLEEP_BUTTON); |
1409 | if (!result) | ||
1410 | result = acpi_start_single_object(device); | ||
1411 | } | ||
1343 | 1412 | ||
1344 | return_VALUE(result); | 1413 | return_VALUE(result); |
1345 | } | 1414 | } |
@@ -1348,6 +1417,7 @@ acpi_bus_scan_fixed ( | |||
1348 | static int __init acpi_scan_init(void) | 1417 | static int __init acpi_scan_init(void) |
1349 | { | 1418 | { |
1350 | int result; | 1419 | int result; |
1420 | struct acpi_bus_ops ops; | ||
1351 | 1421 | ||
1352 | ACPI_FUNCTION_TRACE("acpi_scan_init"); | 1422 | ACPI_FUNCTION_TRACE("acpi_scan_init"); |
1353 | 1423 | ||
@@ -1359,17 +1429,23 @@ static int __init acpi_scan_init(void) | |||
1359 | /* | 1429 | /* |
1360 | * Create the root device in the bus's device tree | 1430 | * Create the root device in the bus's device tree |
1361 | */ | 1431 | */ |
1362 | result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT, | 1432 | result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT, |
1363 | ACPI_BUS_TYPE_SYSTEM); | 1433 | ACPI_BUS_TYPE_SYSTEM); |
1364 | if (result) | 1434 | if (result) |
1365 | goto Done; | 1435 | goto Done; |
1366 | 1436 | ||
1437 | result = acpi_start_single_object(acpi_root); | ||
1438 | |||
1367 | /* | 1439 | /* |
1368 | * Enumerate devices in the ACPI namespace. | 1440 | * Enumerate devices in the ACPI namespace. |
1369 | */ | 1441 | */ |
1370 | result = acpi_bus_scan_fixed(acpi_root); | 1442 | result = acpi_bus_scan_fixed(acpi_root); |
1371 | if (!result) | 1443 | if (!result) { |
1372 | result = acpi_bus_scan(acpi_root); | 1444 | memset(&ops, 0, sizeof(ops)); |
1445 | ops.acpi_op_add = 1; | ||
1446 | ops.acpi_op_start = 1; | ||
1447 | result = acpi_bus_scan(acpi_root, &ops); | ||
1448 | } | ||
1373 | 1449 | ||
1374 | if (result) | 1450 | if (result) |
1375 | acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); | 1451 | acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); |