aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajesh Shah <rajesh.shah@intel.com>2005-04-28 03:25:52 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-06-28 00:52:42 -0400
commit3fb02738b0fd36f47710a2bf207129efd2f5daa2 (patch)
tree56bd70ea1b957b601402745ee03b4c1b293ab23b
parentf7d473d919627262816459f8dba70d72812be074 (diff)
[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>
-rw-r--r--drivers/acpi/container.c2
-rw-r--r--drivers/acpi/processor_core.c2
-rw-r--r--drivers/acpi/scan.c126
-rw-r--r--include/acpi/acpi_bus.h17
4 files changed, 119 insertions, 28 deletions
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 5a0adbf8bc04..97013ddfa202 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -153,7 +153,7 @@ container_device_add(struct acpi_device **device, acpi_handle handle)
153 return_VALUE(-ENODEV); 153 return_VALUE(-ENODEV);
154 } 154 }
155 155
156 result = acpi_bus_scan(*device); 156 result = acpi_bus_start(*device);
157 157
158 return_VALUE(result); 158 return_VALUE(result);
159} 159}
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index f4778747e889..76156ac91bd3 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -723,7 +723,7 @@ int acpi_processor_device_add(
723 return_VALUE(-ENODEV); 723 return_VALUE(-ENODEV);
724 } 724 }
725 725
726 acpi_bus_scan(*device); 726 acpi_bus_start(*device);
727 727
728 pr = acpi_driver_data(*device); 728 pr = acpi_driver_data(*device);
729 if (!pr) 729 if (!pr)
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);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index c627bc408a6b..9ad142476f33 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -108,6 +108,21 @@ typedef int (*acpi_op_unbind) (struct acpi_device *device);
108typedef int (*acpi_op_match) (struct acpi_device *device, 108typedef int (*acpi_op_match) (struct acpi_device *device,
109 struct acpi_driver *driver); 109 struct acpi_driver *driver);
110 110
111struct 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
111struct acpi_device_ops { 126struct acpi_device_ops {
112 acpi_op_add add; 127 acpi_op_add add;
113 acpi_op_remove remove; 128 acpi_op_remove remove;
@@ -327,9 +342,9 @@ int acpi_bus_generate_event (struct acpi_device *device, u8 type, int data);
327int acpi_bus_receive_event (struct acpi_bus_event *event); 342int acpi_bus_receive_event (struct acpi_bus_event *event);
328int acpi_bus_register_driver (struct acpi_driver *driver); 343int acpi_bus_register_driver (struct acpi_driver *driver);
329int acpi_bus_unregister_driver (struct acpi_driver *driver); 344int acpi_bus_unregister_driver (struct acpi_driver *driver);
330int acpi_bus_scan (struct acpi_device *start);
331int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent, 345int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent,
332 acpi_handle handle, int type); 346 acpi_handle handle, int type);
347int acpi_bus_start (struct acpi_device *device);
333 348
334 349
335int acpi_match_ids (struct acpi_device *device, char *ids); 350int acpi_match_ids (struct acpi_device *device, char *ids);