Re: [PATCH v6 2/6] ACPI: Add _OST support for sysfs eject

From: Yasuaki Ishimatsu
Date: Thu Jul 05 2012 - 19:38:08 EST


Hi Toshi,

2012/07/05 23:43, Toshi Kani wrote:
On Thu, 2012-07-05 at 20:16 +0900, Yasuaki Ishimatsu wrote:
Hi Toshi,

2012/06/27 5:42, Toshi Kani wrote:
Changed acpi_bus_hot_remove_device() to support _OST. This function is
also changed to global so that it can be called from hotplug notify
handlers to perform hot-remove operation.

Changed acpi_eject_store(), which is the sysfs eject handler. It checks
eject_pending to see if the request was originated from ACPI eject
notification. If not, it calls _OST(0x103,84,) per Figure 6-37 in ACPI
5.0 spec.

Added eject_pending bit to acpi_device_flags. This bit is set when the
kernel has received an ACPI eject notification, but does not initiate
its hot-remove operation by itself.

Added struct acpi_eject_event. This structure is used to pass extended
information to acpi_bus_hot_remove_device(), which has a single argument
to support asynchronous call

Signed-off-by: Toshi Kani <toshi.kani@xxxxxx>
---
drivers/acpi/scan.c | 57 +++++++++++++++++++++++++++++++++++++++-------
include/acpi/acpi_bus.h | 9 ++++++-
2 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index c8a1f3b..dbdb9fc 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -83,19 +83,29 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha
}
static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);

-static void acpi_bus_hot_remove_device(void *context)
+/**
+ * acpi_bus_hot_remove_device: hot-remove a device and its children
+ * @context: struct acpi_eject_event pointer (freed in this func)
+ *
+ * Hot-remove a device and its children. This function frees up the
+ * memory space passed by arg context, so that the caller may call
+ * this function asynchronously through acpi_os_hotplug_execute().
+ */
+void acpi_bus_hot_remove_device(void *context)
{
+ struct acpi_eject_event *ej_event = (struct acpi_eject_event *) context;
struct acpi_device *device;
- acpi_handle handle = context;
+ acpi_handle handle = ej_event->handle;
struct acpi_object_list arg_list;
union acpi_object arg;
acpi_status status = AE_OK;
+ u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */

if (acpi_bus_get_device(handle, &device))
- return;
+ goto err_out;

if (!device)
- return;
+ goto err_out;

ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Hot-removing device %s...\n", dev_name(&device->dev)));
@@ -103,7 +113,7 @@ static void acpi_bus_hot_remove_device(void *context)
if (acpi_bus_trim(device, 1)) {
printk(KERN_ERR PREFIX
"Removing device failed\n");
- return;
+ goto err_out;
}

/* power off device */
@@ -129,10 +139,20 @@ static void acpi_bus_hot_remove_device(void *context)
* TBD: _EJD support.
*/
status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
- if (ACPI_FAILURE(status))
- printk(KERN_WARNING PREFIX
- "Eject device failed\n");
+ if (ACPI_FAILURE(status)) {
+ if (status != AE_NOT_FOUND)
+ pr_warn(PREFIX "Eject device failed\n");
+ goto err_out;
+ }
+
+ kfree(context);
+ return;

+err_out:
+ /* Inform firmware the hot-remove operation has completed w/ error */
+ (void) acpi_evaluate_hotplug_ost(handle,
+ ej_event->event, ost_code, NULL);
+ kfree(context);
return;
}

When I read your patch named [PATCH] ACPI: Add ACPI CPU hot-remove support,
a question about this patch appeared.

The question is :
Why does not acpi_bus_hot_remove_device() inform firmware of
ACPI_OST_SC_SUCCESS, when it succeeded? Are thre any reasons?

If you have already discussed my question, please let me know the log.

Hi Yasuaki,

Please refer Figure 2, page 14, of the following document. _EJ0
substitutes _OST as it indicates to the firmware that the OS was
successful in offlining.

DIG64 Hot-Plug & Partitioning Flow (HPPF) Specification R1.0
http://www.dig64.org/home/DIG64_HPPF_R1_0.pdf

Figure 6-37 of ACPI 5.0 spec also has a similar example flow.

My question was solved by the document.

Thanks,
Yasuaki Ishimatsu


Thanks,
-Toshi


Thanks,
Yasuaki Ishimatsu



@@ -144,6 +164,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
acpi_status status;
acpi_object_type type = 0;
struct acpi_device *acpi_device = to_acpi_device(d);
+ struct acpi_eject_event *ej_event;

if ((!count) || (buf[0] != '1')) {
return -EINVAL;
@@ -160,7 +181,25 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
goto err;
}

- acpi_os_hotplug_execute(acpi_bus_hot_remove_device, acpi_device->handle);
+ ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
+ if (!ej_event) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ ej_event->handle = acpi_device->handle;
+ if (acpi_device->flags.eject_pending) {
+ /* event originated from ACPI eject notification */
+ ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
+ acpi_device->flags.eject_pending = 0;
+ } else {
+ /* event originated from user */
+ ej_event->event = ACPI_OST_EC_OSPM_EJECT;
+ (void) acpi_evaluate_hotplug_ost(ej_event->handle,
+ ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
+ }
+
+ acpi_os_hotplug_execute(acpi_bus_hot_remove_device, (void *)ej_event);
err:
return ret;
}
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 1d9e432..b22b774 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -182,7 +182,8 @@ struct acpi_device_flags {
u32 suprise_removal_ok:1;
u32 power_manageable:1;
u32 performance_manageable:1;
- u32 reserved:24;
+ u32 eject_pending:1;
+ u32 reserved:23;
};

/* File System */
@@ -334,6 +335,11 @@ struct acpi_bus_event {
u32 data;
};

+struct acpi_eject_event {
+ acpi_handle handle;
+ u32 event;
+};
+
extern struct kobject *acpi_kobj;
extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);
void acpi_bus_private_data_handler(acpi_handle, void *);
@@ -371,6 +377,7 @@ int acpi_bus_register_driver(struct acpi_driver *driver);
void acpi_bus_unregister_driver(struct acpi_driver *driver);
int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent,
acpi_handle handle, int type);
+void acpi_bus_hot_remove_device(void *context);
int acpi_bus_trim(struct acpi_device *start, int rmdevice);
int acpi_bus_start(struct acpi_device *device);
acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd);









--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/