[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 return_VALUE(-ENODEV); 154 } 155 156 - result = acpi_bus_scan(*device); 157 158 return_VALUE(result); 159 }
··· 153 return_VALUE(-ENODEV); 154 } 155 156 + result = acpi_bus_start(*device); 157 158 return_VALUE(result); 159 }
+1 -1
drivers/acpi/processor_core.c
··· 723 return_VALUE(-ENODEV); 724 } 725 726 - acpi_bus_scan(*device); 727 728 pr = acpi_driver_data(*device); 729 if (!pr)
··· 723 return_VALUE(-ENODEV); 724 } 725 726 + acpi_bus_start(*device); 727 728 pr = acpi_driver_data(*device); 729 if (!pr)
+101 -25
drivers/acpi/scan.c
··· 553 * upon possible configuration and currently allocated resources. 554 */ 555 556 if (driver->ops.start) { 557 result = driver->ops.start(device); 558 if (result && driver->ops.remove) 559 driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); 560 - return_VALUE(result); 561 } 562 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); 570 } 571 572 static int acpi_driver_attach(struct acpi_driver * drv) ··· 595 596 if (!acpi_bus_match(dev, drv)) { 597 if (!acpi_bus_driver_init(dev, drv)) { 598 atomic_inc(&drv->references); 599 count++; 600 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", ··· 1019 } 1020 1021 1022 - int 1023 - acpi_bus_add ( 1024 struct acpi_device **child, 1025 struct acpi_device *parent, 1026 acpi_handle handle, ··· 1029 int result = 0; 1030 struct acpi_device *device = NULL; 1031 1032 - ACPI_FUNCTION_TRACE("acpi_bus_add"); 1033 1034 if (!child) 1035 return_VALUE(-EINVAL); ··· 1150 * 1151 * TBD: Assumes LDM provides driver hot-plug capability. 1152 */ 1153 - acpi_bus_find_driver(device); 1154 1155 end: 1156 if (!result) ··· 1163 1164 return_VALUE(result); 1165 } 1166 - EXPORT_SYMBOL(acpi_bus_add); 1167 1168 1169 - int acpi_bus_scan (struct acpi_device *start) 1170 { 1171 acpi_status status = AE_OK; 1172 struct acpi_device *parent = NULL; ··· 1239 continue; 1240 } 1241 1242 - status = acpi_bus_add(&child, parent, chandle, type); 1243 - if (ACPI_FAILURE(status)) 1244 - continue; 1245 1246 /* 1247 * If the device is present, enabled, and functioning then ··· 1278 1279 return_VALUE(0); 1280 } 1281 - EXPORT_SYMBOL(acpi_bus_scan); 1282 1283 1284 static int 1285 acpi_bus_trim(struct acpi_device *start, ··· 1394 /* 1395 * Enumerate all fixed-feature devices. 1396 */ 1397 - if (acpi_fadt.pwr_button == 0) 1398 - result = acpi_bus_add(&device, acpi_root, 1399 NULL, ACPI_BUS_TYPE_POWER_BUTTON); 1400 1401 - if (acpi_fadt.sleep_button == 0) 1402 - result = acpi_bus_add(&device, acpi_root, 1403 NULL, ACPI_BUS_TYPE_SLEEP_BUTTON); 1404 1405 return_VALUE(result); 1406 } ··· 1415 static int __init acpi_scan_init(void) 1416 { 1417 int result; 1418 1419 ACPI_FUNCTION_TRACE("acpi_scan_init"); 1420 ··· 1427 /* 1428 * Create the root device in the bus's device tree 1429 */ 1430 - result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT, 1431 ACPI_BUS_TYPE_SYSTEM); 1432 if (result) 1433 goto Done; 1434 1435 /* 1436 * Enumerate devices in the ACPI namespace. 1437 */ 1438 result = acpi_bus_scan_fixed(acpi_root); 1439 - if (!result) 1440 - result = acpi_bus_scan(acpi_root); 1441 1442 if (result) 1443 acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
··· 553 * upon possible configuration and currently allocated resources. 554 */ 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 + 572 if (driver->ops.start) { 573 result = driver->ops.start(device); 574 if (result && driver->ops.remove) 575 driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); 576 } 577 578 + return_VALUE(result); 579 } 580 581 static int acpi_driver_attach(struct acpi_driver * drv) ··· 586 587 if (!acpi_bus_match(dev, drv)) { 588 if (!acpi_bus_driver_init(dev, drv)) { 589 + acpi_start_single_object(dev); 590 atomic_inc(&drv->references); 591 count++; 592 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", ··· 1009 } 1010 1011 1012 + static int 1013 + acpi_add_single_object ( 1014 struct acpi_device **child, 1015 struct acpi_device *parent, 1016 acpi_handle handle, ··· 1019 int result = 0; 1020 struct acpi_device *device = NULL; 1021 1022 + ACPI_FUNCTION_TRACE("acpi_add_single_object"); 1023 1024 if (!child) 1025 return_VALUE(-EINVAL); ··· 1140 * 1141 * TBD: Assumes LDM provides driver hot-plug capability. 1142 */ 1143 + result = acpi_bus_find_driver(device); 1144 1145 end: 1146 if (!result) ··· 1153 1154 return_VALUE(result); 1155 } 1156 1157 1158 + static int acpi_bus_scan (struct acpi_device *start, 1159 + struct acpi_bus_ops *ops) 1160 { 1161 acpi_status status = AE_OK; 1162 struct acpi_device *parent = NULL; ··· 1229 continue; 1230 } 1231 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 + } 1246 1247 /* 1248 * If the device is present, enabled, and functioning then ··· 1257 1258 return_VALUE(0); 1259 } 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); 1304 1305 static int 1306 acpi_bus_trim(struct acpi_device *start, ··· 1331 /* 1332 * Enumerate all fixed-feature devices. 1333 */ 1334 + if (acpi_fadt.pwr_button == 0) { 1335 + result = acpi_add_single_object(&device, acpi_root, 1336 NULL, ACPI_BUS_TYPE_POWER_BUTTON); 1337 + if (!result) 1338 + result = acpi_start_single_object(device); 1339 + } 1340 1341 + if (acpi_fadt.sleep_button == 0) { 1342 + result = acpi_add_single_object(&device, acpi_root, 1343 NULL, ACPI_BUS_TYPE_SLEEP_BUTTON); 1344 + if (!result) 1345 + result = acpi_start_single_object(device); 1346 + } 1347 1348 return_VALUE(result); 1349 } ··· 1346 static int __init acpi_scan_init(void) 1347 { 1348 int result; 1349 + struct acpi_bus_ops ops; 1350 1351 ACPI_FUNCTION_TRACE("acpi_scan_init"); 1352 ··· 1357 /* 1358 * Create the root device in the bus's device tree 1359 */ 1360 + result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT, 1361 ACPI_BUS_TYPE_SYSTEM); 1362 if (result) 1363 goto Done; 1364 + 1365 + result = acpi_start_single_object(acpi_root); 1366 1367 /* 1368 * Enumerate devices in the ACPI namespace. 1369 */ 1370 result = acpi_bus_scan_fixed(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 + } 1377 1378 if (result) 1379 acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
+16 -1
include/acpi/acpi_bus.h
··· 108 typedef int (*acpi_op_match) (struct acpi_device *device, 109 struct acpi_driver *driver); 110 111 struct acpi_device_ops { 112 acpi_op_add add; 113 acpi_op_remove remove; ··· 342 int acpi_bus_receive_event (struct acpi_bus_event *event); 343 int acpi_bus_register_driver (struct acpi_driver *driver); 344 int acpi_bus_unregister_driver (struct acpi_driver *driver); 345 - int acpi_bus_scan (struct acpi_device *start); 346 int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent, 347 acpi_handle handle, int type); 348 349 350 int acpi_match_ids (struct acpi_device *device, char *ids);
··· 108 typedef int (*acpi_op_match) (struct acpi_device *device, 109 struct acpi_driver *driver); 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 + 126 struct acpi_device_ops { 127 acpi_op_add add; 128 acpi_op_remove remove; ··· 327 int acpi_bus_receive_event (struct acpi_bus_event *event); 328 int acpi_bus_register_driver (struct acpi_driver *driver); 329 int acpi_bus_unregister_driver (struct acpi_driver *driver); 330 int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent, 331 acpi_handle handle, int type); 332 + int acpi_bus_start (struct acpi_device *device); 333 334 335 int acpi_match_ids (struct acpi_device *device, char *ids);