Skip to content

Commit

Permalink
[PATCH] acpi bridge hotadd: Allow ACPI .add and .start operations to …
Browse files Browse the repository at this point in the history
…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 <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
Rajesh Shah authored and gregkh committed Jun 28, 2005
1 parent f7d473d commit 3fb0273
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 28 deletions.
2 changes: 1 addition & 1 deletion drivers/acpi/container.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ container_device_add(struct acpi_device **device, acpi_handle handle)
return_VALUE(-ENODEV);
}

result = acpi_bus_scan(*device);
result = acpi_bus_start(*device);

return_VALUE(result);
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/acpi/processor_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ int acpi_processor_device_add(
return_VALUE(-ENODEV);
}

acpi_bus_scan(*device);
acpi_bus_start(*device);

pr = acpi_driver_data(*device);
if (!pr)
Expand Down
126 changes: 101 additions & 25 deletions drivers/acpi/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,20 +553,29 @@ acpi_bus_driver_init (
* upon possible configuration and currently allocated resources.
*/

ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n"));
return_VALUE(0);
}

int
acpi_start_single_object (
struct acpi_device *device)
{
int result = 0;
struct acpi_driver *driver;

ACPI_FUNCTION_TRACE("acpi_start_single_object");

if (!(driver = device->driver))
return_VALUE(0);

if (driver->ops.start) {
result = driver->ops.start(device);
if (result && driver->ops.remove)
driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);
return_VALUE(result);
}

ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n"));

if (driver->ops.scan) {
driver->ops.scan(device);
}

return_VALUE(0);
return_VALUE(result);
}

static int acpi_driver_attach(struct acpi_driver * drv)
Expand All @@ -586,6 +595,7 @@ static int acpi_driver_attach(struct acpi_driver * drv)

if (!acpi_bus_match(dev, drv)) {
if (!acpi_bus_driver_init(dev, drv)) {
acpi_start_single_object(dev);
atomic_inc(&drv->references);
count++;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",
Expand Down Expand Up @@ -1009,8 +1019,8 @@ acpi_bus_remove (
}


int
acpi_bus_add (
static int
acpi_add_single_object (
struct acpi_device **child,
struct acpi_device *parent,
acpi_handle handle,
Expand All @@ -1019,7 +1029,7 @@ acpi_bus_add (
int result = 0;
struct acpi_device *device = NULL;

ACPI_FUNCTION_TRACE("acpi_bus_add");
ACPI_FUNCTION_TRACE("acpi_add_single_object");

if (!child)
return_VALUE(-EINVAL);
Expand Down Expand Up @@ -1140,7 +1150,7 @@ acpi_bus_add (
*
* TBD: Assumes LDM provides driver hot-plug capability.
*/
acpi_bus_find_driver(device);
result = acpi_bus_find_driver(device);

end:
if (!result)
Expand All @@ -1153,10 +1163,10 @@ acpi_bus_add (

return_VALUE(result);
}
EXPORT_SYMBOL(acpi_bus_add);


int acpi_bus_scan (struct acpi_device *start)
static int acpi_bus_scan (struct acpi_device *start,
struct acpi_bus_ops *ops)
{
acpi_status status = AE_OK;
struct acpi_device *parent = NULL;
Expand Down Expand Up @@ -1229,9 +1239,20 @@ int acpi_bus_scan (struct acpi_device *start)
continue;
}

status = acpi_bus_add(&child, parent, chandle, type);
if (ACPI_FAILURE(status))
continue;
if (ops->acpi_op_add)
status = acpi_add_single_object(&child, parent,
chandle, type);
else
status = acpi_bus_get_device(chandle, &child);

if (ACPI_FAILURE(status))
continue;

if (ops->acpi_op_start) {
status = acpi_start_single_object(child);
if (ACPI_FAILURE(status))
continue;
}

/*
* If the device is present, enabled, and functioning then
Expand All @@ -1257,8 +1278,50 @@ int acpi_bus_scan (struct acpi_device *start)

return_VALUE(0);
}
EXPORT_SYMBOL(acpi_bus_scan);

int
acpi_bus_add (
struct acpi_device **child,
struct acpi_device *parent,
acpi_handle handle,
int type)
{
int result;
struct acpi_bus_ops ops;

ACPI_FUNCTION_TRACE("acpi_bus_add");

result = acpi_add_single_object(child, parent, handle, type);
if (!result) {
memset(&ops, 0, sizeof(ops));
ops.acpi_op_add = 1;
result = acpi_bus_scan(*child, &ops);
}
return_VALUE(result);
}
EXPORT_SYMBOL(acpi_bus_add);

int
acpi_bus_start (
struct acpi_device *device)
{
int result;
struct acpi_bus_ops ops;

ACPI_FUNCTION_TRACE("acpi_bus_start");

if (!device)
return_VALUE(-EINVAL);

result = acpi_start_single_object(device);
if (!result) {
memset(&ops, 0, sizeof(ops));
ops.acpi_op_start = 1;
result = acpi_bus_scan(device, &ops);
}
return_VALUE(result);
}
EXPORT_SYMBOL(acpi_bus_start);

static int
acpi_bus_trim(struct acpi_device *start,
Expand Down Expand Up @@ -1331,13 +1394,19 @@ acpi_bus_scan_fixed (
/*
* Enumerate all fixed-feature devices.
*/
if (acpi_fadt.pwr_button == 0)
result = acpi_bus_add(&device, acpi_root,
if (acpi_fadt.pwr_button == 0) {
result = acpi_add_single_object(&device, acpi_root,
NULL, ACPI_BUS_TYPE_POWER_BUTTON);
if (!result)
result = acpi_start_single_object(device);
}

if (acpi_fadt.sleep_button == 0)
result = acpi_bus_add(&device, acpi_root,
if (acpi_fadt.sleep_button == 0) {
result = acpi_add_single_object(&device, acpi_root,
NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);
if (!result)
result = acpi_start_single_object(device);
}

return_VALUE(result);
}
Expand All @@ -1346,6 +1415,7 @@ acpi_bus_scan_fixed (
static int __init acpi_scan_init(void)
{
int result;
struct acpi_bus_ops ops;

ACPI_FUNCTION_TRACE("acpi_scan_init");

Expand All @@ -1357,17 +1427,23 @@ static int __init acpi_scan_init(void)
/*
* Create the root device in the bus's device tree
*/
result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT,
result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT,
ACPI_BUS_TYPE_SYSTEM);
if (result)
goto Done;

result = acpi_start_single_object(acpi_root);

/*
* Enumerate devices in the ACPI namespace.
*/
result = acpi_bus_scan_fixed(acpi_root);
if (!result)
result = acpi_bus_scan(acpi_root);
if (!result) {
memset(&ops, 0, sizeof(ops));
ops.acpi_op_add = 1;
ops.acpi_op_start = 1;
result = acpi_bus_scan(acpi_root, &ops);
}

if (result)
acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
Expand Down
17 changes: 16 additions & 1 deletion include/acpi/acpi_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,21 @@ typedef int (*acpi_op_unbind) (struct acpi_device *device);
typedef int (*acpi_op_match) (struct acpi_device *device,
struct acpi_driver *driver);

struct acpi_bus_ops {
u32 acpi_op_add:1;
u32 acpi_op_remove:1;
u32 acpi_op_lock:1;
u32 acpi_op_start:1;
u32 acpi_op_stop:1;
u32 acpi_op_suspend:1;
u32 acpi_op_resume:1;
u32 acpi_op_scan:1;
u32 acpi_op_bind:1;
u32 acpi_op_unbind:1;
u32 acpi_op_match:1;
u32 reserved:21;
};

struct acpi_device_ops {
acpi_op_add add;
acpi_op_remove remove;
Expand Down Expand Up @@ -327,9 +342,9 @@ int acpi_bus_generate_event (struct acpi_device *device, u8 type, int data);
int acpi_bus_receive_event (struct acpi_bus_event *event);
int acpi_bus_register_driver (struct acpi_driver *driver);
int acpi_bus_unregister_driver (struct acpi_driver *driver);
int acpi_bus_scan (struct acpi_device *start);
int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent,
acpi_handle handle, int type);
int acpi_bus_start (struct acpi_device *device);


int acpi_match_ids (struct acpi_device *device, char *ids);
Expand Down

0 comments on commit 3fb0273

Please sign in to comment.