Skip to content

Commit

Permalink
ACPI / container: Use common hotplug code
Browse files Browse the repository at this point in the history
Switch the ACPI container driver to using common device hotplug code
introduced previously.  This reduces the driver down to a trivial
definition and registration of a struct acpi_scan_handler object.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Toshi Kani <toshi.kani@hp.com>
Tested-by: Toshi Kani <toshi.kani@hp.com>
  • Loading branch information
Rafael J. Wysocki committed Mar 4, 2013
1 parent a33ec39 commit 68a67f6
Showing 1 changed file with 10 additions and 136 deletions.
146 changes: 10 additions & 136 deletions drivers/acpi/container.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
* acpi_container.c - ACPI Generic Container Driver
* ($Revision: )
* container.c - ACPI Generic Container Driver
*
* Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com)
* Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com)
* Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com)
* Copyright (C) 2004 Intel Corp.
* Copyright (C) 2004 FUJITSU LIMITED
* Copyright (C) 2004, 2013 Intel Corp.
* Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
Expand All @@ -26,14 +26,9 @@
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>

#include "internal.h"

#define PREFIX "ACPI: "

Expand All @@ -50,141 +45,20 @@ static const struct acpi_device_id container_device_ids[] = {
static int container_device_attach(struct acpi_device *device,
const struct acpi_device_id *not_used)
{
/*
* FIXME: This is necessary, so that acpi_eject_store() doesn't return
* -ENODEV for containers.
*/
/* This is necessary for container hotplug to work. */
return 1;
}

static struct acpi_scan_handler container_device_handler = {
.ids = container_device_ids,
.attach = container_device_attach,
.hotplug = {
.enabled = true,
.mode = AHM_CONTAINER,
},
};

static int is_device_present(acpi_handle handle)
{
acpi_handle temp;
acpi_status status;
unsigned long long sta;


status = acpi_get_handle(handle, "_STA", &temp);
if (ACPI_FAILURE(status))
return 1; /* _STA not found, assume device present */

status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status))
return 0; /* Firmware error */

return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
}

static void container_notify_cb(acpi_handle handle, u32 type, void *context)
{
struct acpi_device *device = NULL;
int result;
int present;
acpi_status status;
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */

acpi_scan_lock_acquire();

switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
/* Fall through */
case ACPI_NOTIFY_DEVICE_CHECK:
pr_debug("Container driver received %s event\n",
(type == ACPI_NOTIFY_BUS_CHECK) ?
"ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");

present = is_device_present(handle);
status = acpi_bus_get_device(handle, &device);
if (!present) {
if (ACPI_SUCCESS(status)) {
/* device exist and this is a remove request */
device->flags.eject_pending = 1;
kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
goto out;
}
break;
}

if (!ACPI_FAILURE(status) || device)
break;

result = acpi_bus_scan(handle);
if (result) {
acpi_handle_warn(handle, "Failed to add container\n");
break;
}
result = acpi_bus_get_device(handle, &device);
if (result) {
acpi_handle_warn(handle, "Missing device object\n");
break;
}

kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
ost_code = ACPI_OST_SC_SUCCESS;
break;

case ACPI_NOTIFY_EJECT_REQUEST:
if (!acpi_bus_get_device(handle, &device) && device) {
device->flags.eject_pending = 1;
kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
goto out;
}
break;

default:
/* non-hotplug event; possibly handled by other handler */
goto out;
}

/* Inform firmware that the hotplug operation has completed */
(void) acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);

out:
acpi_scan_lock_release();
}

static bool is_container(acpi_handle handle)
{
struct acpi_device_info *info;
bool ret = false;

if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
return false;

if (info->valid & ACPI_VALID_HID) {
const struct acpi_device_id *id;

for (id = container_device_ids; id->id[0]; id++) {
ret = !strcmp((char *)id->id, info->hardware_id.string);
if (ret)
break;
}
}
kfree(info);
return ret;
}

static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
u32 lvl, void *ctxt,
void **retv)
{
if (is_container(handle))
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
container_notify_cb, NULL);

return AE_OK;
}

void __init acpi_container_init(void)
{
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
acpi_container_register_notify_handler, NULL,
NULL, NULL);

acpi_scan_add_handler(&container_device_handler);
}

0 comments on commit 68a67f6

Please sign in to comment.