n Mon, 20 Sep 2004 09:35:33 -0700 Keshavamurthy Anil S wrote:
In acpi_eject_store(), eject_operation() is called regardless of the
result of acpi_bus_trim(). I think that eject_operation() should be
called only when acpi_bus_trim() returns success. Otherwise, a
device stil being online will be ejected forcibly.
Two steps might be needed to do this.
1. Modify acpi_bus_trim() to return success only when all the
acpi_bus_remove() are done successfully.
2. Modify acpi_eject_store() to see the result and call eject_operation()
only when the result is success.
Here is a patch just to show what I have in mind. It is still based on
the recursion, so please fix it as appropriate ;)
Thanks,
Keiichiro Tokunaga
Name: acpi_core_eject_fix.patch
Status: Tested on 2.6.9-rc2
---
linux-2.6.9-rc2-fix-kei/drivers/acpi/scan.c | 26 +++++++++++++++---------
linux-2.6.9-rc2-fix-kei/include/acpi/acpi_bus.h | 2 -
2 files changed, 18 insertions(+), 10 deletions(-)
diff -puN drivers/acpi/scan.c~acpi_core_eject_fix drivers/acpi/scan.c
--- linux-2.6.9-rc2-fix/drivers/acpi/scan.c~acpi_core_eject_fix 2004-09-22 08:42:49.402689136 +0900
+++ linux-2.6.9-rc2-fix-kei/drivers/acpi/scan.c 2004-09-22 09:29:51.056265232 +0900
@@ -404,11 +404,14 @@ acpi_eject_store(struct subsystem *subsy
* remove from ACPI bus.
*/
if (type == ACPI_BUS_TYPE_PROCESSOR)
- acpi_bus_trim(device, 0);
+ result = acpi_bus_trim(device, 0);
else
- acpi_bus_trim(device, 1);
+ result = acpi_bus_trim(device, 1);
-
+ if (result) {
+ ret = -EBUSY;
+ goto err;
+ }
result = eject_operation(hlsb, islockable);
if (result) {
ret = -EBUSY;
@@ -1203,7 +1206,7 @@ int acpi_bus_scan (struct acpi_device *s
return_VALUE(0);
}
-void
+int
acpi_bus_trim(struct acpi_device *start,
int rmdevice)
{
@@ -1212,25 +1215,30 @@ acpi_bus_trim(struct acpi_device *start,
struct acpi_device *child = NULL;
acpi_handle phandle = 0;
acpi_handle chandle = 0;
-
+ int err = 0;
parent = start;
phandle = start->handle;
/*
* NOTE: must be freed in a depth-first manner.
*/
- while (1) {
+ while (1) {
status = acpi_get_next_object(ACPI_TYPE_ANY, phandle,
chandle, &chandle);
- if (ACPI_SUCCESS(status) && chandle != NULL) {
+ if (ACPI_SUCCESS(status) && chandle != NULL) {
if (acpi_bus_get_device(chandle, &child) == 0)
- acpi_bus_trim(child, 1);
+ if (acpi_bus_trim(child, 1))
+ err = 1;
} else {
/* this is a leaf */
- acpi_bus_remove(parent, rmdevice);
+ if (!err) {
+ if (acpi_bus_remove(parent, rmdevice))
+ err = 1;
+ }
break;
}
}
+ return err;
}
static int
diff -puN include/acpi/acpi_bus.h~acpi_core_eject_fix include/acpi/acpi_bus.h
--- linux-2.6.9-rc2-fix/include/acpi/acpi_bus.h~acpi_core_eject_fix 2004-09-22 08:42:49.404642274 +0900
+++ linux-2.6.9-rc2-fix-kei/include/acpi/acpi_bus.h 2004-09-22 08:42:49.408548551 +0900
@@ -325,7 +325,7 @@ int acpi_bus_receive_event (struct acpi_
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);
-void acpi_bus_trim(struct acpi_device *start, int rmdevice);
+int acpi_bus_trim(struct acpi_device *start, int rmdevice);
int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type);