[PATCH] acpi bridge hotadd: Allow ACPI .add and .start operations to be done independently

Create new interfaces to recursively add an acpi namespace object to the acpi
device list, and recursively start the namespace object. This is needed for
ACPI based hotplug of a root bridge hierarchy where the add operation must be
performed first and the start operation must be performed separately after the
hot-plugged devices have been properly configured.

Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Rajesh Shah and committed by
Greg Kroah-Hartman
3fb02738 f7d473d9

+119 -28
+1 -1
drivers/acpi/container.c
··· 153 153 return_VALUE(-ENODEV); 154 154 } 155 155 156 - result = acpi_bus_scan(*device); 156 + result = acpi_bus_start(*device); 157 157 158 158 return_VALUE(result); 159 159 }
+1 -1
drivers/acpi/processor_core.c
··· 723 723 return_VALUE(-ENODEV); 724 724 } 725 725 726 - acpi_bus_scan(*device); 726 + acpi_bus_start(*device); 727 727 728 728 pr = acpi_driver_data(*device); 729 729 if (!pr)
+101 -25
drivers/acpi/scan.c
··· 553 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 572 if (driver->ops.start) { 557 573 result = driver->ops.start(device); 558 574 if (result && driver->ops.remove) 559 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")); 564 - 565 - if (driver->ops.scan) { 566 - driver->ops.scan(device); 567 - } 568 - 569 - return_VALUE(0); 578 + return_VALUE(result); 570 579 } 571 580 572 581 static int acpi_driver_attach(struct acpi_driver * drv) ··· 595 586 596 587 if (!acpi_bus_match(dev, drv)) { 597 588 if (!acpi_bus_driver_init(dev, drv)) { 589 + acpi_start_single_object(dev); 598 590 atomic_inc(&drv->references); 599 591 count++; 600 592 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", ··· 1019 1009 } 1020 1010 1021 1011 1022 - int 1023 - acpi_bus_add ( 1012 + static int 1013 + acpi_add_single_object ( 1024 1014 struct acpi_device **child, 1025 1015 struct acpi_device *parent, 1026 1016 acpi_handle handle, ··· 1029 1019 int result = 0; 1030 1020 struct acpi_device *device = NULL; 1031 1021 1032 - ACPI_FUNCTION_TRACE("acpi_bus_add"); 1022 + ACPI_FUNCTION_TRACE("acpi_add_single_object"); 1033 1023 1034 1024 if (!child) 1035 1025 return_VALUE(-EINVAL); ··· 1150 1140 * 1151 1141 * TBD: Assumes LDM provides driver hot-plug capability. 1152 1142 */ 1153 - acpi_bus_find_driver(device); 1143 + result = acpi_bus_find_driver(device); 1154 1144 1155 1145 end: 1156 1146 if (!result) ··· 1163 1153 1164 1154 return_VALUE(result); 1165 1155 } 1166 - EXPORT_SYMBOL(acpi_bus_add); 1167 1156 1168 1157 1169 - int acpi_bus_scan (struct acpi_device *start) 1158 + static int acpi_bus_scan (struct acpi_device *start, 1159 + struct acpi_bus_ops *ops) 1170 1160 { 1171 1161 acpi_status status = AE_OK; 1172 1162 struct acpi_device *parent = NULL; ··· 1239 1229 continue; 1240 1230 } 1241 1231 1242 - status = acpi_bus_add(&child, parent, chandle, type); 1243 - if (ACPI_FAILURE(status)) 1244 - continue; 1232 + if (ops->acpi_op_add) 1233 + status = acpi_add_single_object(&child, parent, 1234 + chandle, type); 1235 + else 1236 + status = acpi_bus_get_device(chandle, &child); 1237 + 1238 + if (ACPI_FAILURE(status)) 1239 + continue; 1240 + 1241 + if (ops->acpi_op_start) { 1242 + status = acpi_start_single_object(child); 1243 + if (ACPI_FAILURE(status)) 1244 + continue; 1245 + } 1245 1246 1246 1247 /* 1247 1248 * If the device is present, enabled, and functioning then ··· 1278 1257 1279 1258 return_VALUE(0); 1280 1259 } 1281 - EXPORT_SYMBOL(acpi_bus_scan); 1282 1260 1261 + int 1262 + acpi_bus_add ( 1263 + struct acpi_device **child, 1264 + struct acpi_device *parent, 1265 + acpi_handle handle, 1266 + int type) 1267 + { 1268 + int result; 1269 + struct acpi_bus_ops ops; 1270 + 1271 + ACPI_FUNCTION_TRACE("acpi_bus_add"); 1272 + 1273 + result = acpi_add_single_object(child, parent, handle, type); 1274 + if (!result) { 1275 + memset(&ops, 0, sizeof(ops)); 1276 + ops.acpi_op_add = 1; 1277 + result = acpi_bus_scan(*child, &ops); 1278 + } 1279 + return_VALUE(result); 1280 + } 1281 + EXPORT_SYMBOL(acpi_bus_add); 1282 + 1283 + int 1284 + acpi_bus_start ( 1285 + struct acpi_device *device) 1286 + { 1287 + int result; 1288 + struct acpi_bus_ops ops; 1289 + 1290 + ACPI_FUNCTION_TRACE("acpi_bus_start"); 1291 + 1292 + if (!device) 1293 + return_VALUE(-EINVAL); 1294 + 1295 + result = acpi_start_single_object(device); 1296 + if (!result) { 1297 + memset(&ops, 0, sizeof(ops)); 1298 + ops.acpi_op_start = 1; 1299 + result = acpi_bus_scan(device, &ops); 1300 + } 1301 + return_VALUE(result); 1302 + } 1303 + EXPORT_SYMBOL(acpi_bus_start); 1283 1304 1284 1305 static int 1285 1306 acpi_bus_trim(struct acpi_device *start, ··· 1394 1331 /* 1395 1332 * Enumerate all fixed-feature devices. 1396 1333 */ 1397 - if (acpi_fadt.pwr_button == 0) 1398 - result = acpi_bus_add(&device, acpi_root, 1334 + if (acpi_fadt.pwr_button == 0) { 1335 + result = acpi_add_single_object(&device, acpi_root, 1399 1336 NULL, ACPI_BUS_TYPE_POWER_BUTTON); 1337 + if (!result) 1338 + result = acpi_start_single_object(device); 1339 + } 1400 1340 1401 - if (acpi_fadt.sleep_button == 0) 1402 - result = acpi_bus_add(&device, acpi_root, 1341 + if (acpi_fadt.sleep_button == 0) { 1342 + result = acpi_add_single_object(&device, acpi_root, 1403 1343 NULL, ACPI_BUS_TYPE_SLEEP_BUTTON); 1344 + if (!result) 1345 + result = acpi_start_single_object(device); 1346 + } 1404 1347 1405 1348 return_VALUE(result); 1406 1349 } ··· 1415 1346 static int __init acpi_scan_init(void) 1416 1347 { 1417 1348 int result; 1349 + struct acpi_bus_ops ops; 1418 1350 1419 1351 ACPI_FUNCTION_TRACE("acpi_scan_init"); 1420 1352 ··· 1427 1357 /* 1428 1358 * Create the root device in the bus's device tree 1429 1359 */ 1430 - result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT, 1360 + result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT, 1431 1361 ACPI_BUS_TYPE_SYSTEM); 1432 1362 if (result) 1433 1363 goto Done; 1364 + 1365 + result = acpi_start_single_object(acpi_root); 1434 1366 1435 1367 /* 1436 1368 * Enumerate devices in the ACPI namespace. 1437 1369 */ 1438 1370 result = acpi_bus_scan_fixed(acpi_root); 1439 - if (!result) 1440 - result = acpi_bus_scan(acpi_root); 1371 + if (!result) { 1372 + memset(&ops, 0, sizeof(ops)); 1373 + ops.acpi_op_add = 1; 1374 + ops.acpi_op_start = 1; 1375 + result = acpi_bus_scan(acpi_root, &ops); 1376 + } 1441 1377 1442 1378 if (result) 1443 1379 acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
+16 -1
include/acpi/acpi_bus.h
··· 108 108 typedef int (*acpi_op_match) (struct acpi_device *device, 109 109 struct acpi_driver *driver); 110 110 111 + struct acpi_bus_ops { 112 + u32 acpi_op_add:1; 113 + u32 acpi_op_remove:1; 114 + u32 acpi_op_lock:1; 115 + u32 acpi_op_start:1; 116 + u32 acpi_op_stop:1; 117 + u32 acpi_op_suspend:1; 118 + u32 acpi_op_resume:1; 119 + u32 acpi_op_scan:1; 120 + u32 acpi_op_bind:1; 121 + u32 acpi_op_unbind:1; 122 + u32 acpi_op_match:1; 123 + u32 reserved:21; 124 + }; 125 + 111 126 struct acpi_device_ops { 112 127 acpi_op_add add; 113 128 acpi_op_remove remove; ··· 342 327 int acpi_bus_receive_event (struct acpi_bus_event *event); 343 328 int acpi_bus_register_driver (struct acpi_driver *driver); 344 329 int acpi_bus_unregister_driver (struct acpi_driver *driver); 345 - int acpi_bus_scan (struct acpi_device *start); 346 330 int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent, 347 331 acpi_handle handle, int type); 332 + int acpi_bus_start (struct acpi_device *device); 348 333 349 334 350 335 int acpi_match_ids (struct acpi_device *device, char *ids);