ACPI: change registration interface to follow driver model
ACPI device/driver registration Interfaces are modified to follow Linux driver model. Signed-off-by: Li Shaohua <shaohua.li@intel.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
This commit is contained in:
parent
5d9464a469
commit
1890a97ab3
@ -25,7 +25,7 @@ DEFINE_SPINLOCK(acpi_device_lock);
|
|||||||
LIST_HEAD(acpi_wakeup_device_list);
|
LIST_HEAD(acpi_wakeup_device_list);
|
||||||
|
|
||||||
|
|
||||||
static void acpi_device_release(struct kobject *kobj)
|
static void acpi_device_release_legacy(struct kobject *kobj)
|
||||||
{
|
{
|
||||||
struct acpi_device *dev = container_of(kobj, struct acpi_device, kobj);
|
struct acpi_device *dev = container_of(kobj, struct acpi_device, kobj);
|
||||||
kfree(dev->pnp.cid_list);
|
kfree(dev->pnp.cid_list);
|
||||||
@ -75,7 +75,7 @@ static struct sysfs_ops acpi_device_sysfs_ops = {
|
|||||||
|
|
||||||
static struct kobj_type ktype_acpi_ns = {
|
static struct kobj_type ktype_acpi_ns = {
|
||||||
.sysfs_ops = &acpi_device_sysfs_ops,
|
.sysfs_ops = &acpi_device_sysfs_ops,
|
||||||
.release = acpi_device_release,
|
.release = acpi_device_release_legacy,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int namespace_uevent(struct kset *kset, struct kobject *kobj,
|
static int namespace_uevent(struct kset *kset, struct kobject *kobj,
|
||||||
@ -222,6 +222,14 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count)
|
|||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
ACPI Bus operations
|
ACPI Bus operations
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
static void acpi_device_release(struct device *dev)
|
||||||
|
{
|
||||||
|
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||||
|
|
||||||
|
kfree(acpi_dev->pnp.cid_list);
|
||||||
|
kfree(acpi_dev);
|
||||||
|
}
|
||||||
|
|
||||||
static int acpi_device_suspend(struct device *dev, pm_message_t state)
|
static int acpi_device_suspend(struct device *dev, pm_message_t state)
|
||||||
{
|
{
|
||||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||||
@ -377,6 +385,14 @@ static void acpi_device_register(struct acpi_device *device,
|
|||||||
printk(KERN_WARNING "%s: kobject_register error: %d\n",
|
printk(KERN_WARNING "%s: kobject_register error: %d\n",
|
||||||
__FUNCTION__, err);
|
__FUNCTION__, err);
|
||||||
create_sysfs_device_files(device);
|
create_sysfs_device_files(device);
|
||||||
|
|
||||||
|
if (device->parent)
|
||||||
|
device->dev.parent = &parent->dev;
|
||||||
|
device->dev.bus = &acpi_bus_type;
|
||||||
|
device_initialize(&device->dev);
|
||||||
|
sprintf(device->dev.bus_id, "%s", device->pnp.bus_id);
|
||||||
|
device->dev.release = &acpi_device_release;
|
||||||
|
device_add(&device->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void acpi_device_unregister(struct acpi_device *device, int type)
|
static void acpi_device_unregister(struct acpi_device *device, int type)
|
||||||
@ -395,20 +411,20 @@ static void acpi_device_unregister(struct acpi_device *device, int type)
|
|||||||
acpi_detach_data(device->handle, acpi_bus_data_handler);
|
acpi_detach_data(device->handle, acpi_bus_data_handler);
|
||||||
remove_sysfs_device_files(device);
|
remove_sysfs_device_files(device);
|
||||||
kobject_unregister(&device->kobj);
|
kobject_unregister(&device->kobj);
|
||||||
|
|
||||||
|
device_unregister(&device->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
Driver Management
|
Driver Management
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
static LIST_HEAD(acpi_bus_drivers);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* acpi_bus_driver_init - add a device to a driver
|
* acpi_bus_driver_init - add a device to a driver
|
||||||
* @device: the device to add and initialize
|
* @device: the device to add and initialize
|
||||||
* @driver: driver for the device
|
* @driver: driver for the device
|
||||||
*
|
*
|
||||||
* Used to initialize a device via its device driver. Called whenever a
|
* Used to initialize a device via its device driver. Called whenever a
|
||||||
* driver is bound to a device. Invokes the driver's add() and start() ops.
|
* driver is bound to a device. Invokes the driver's add() ops.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver)
|
acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver)
|
||||||
@ -459,57 +475,6 @@ static int acpi_start_single_object(struct acpi_device *device)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void acpi_driver_attach(struct acpi_driver *drv)
|
|
||||||
{
|
|
||||||
struct list_head *node, *next;
|
|
||||||
|
|
||||||
|
|
||||||
spin_lock(&acpi_device_lock);
|
|
||||||
list_for_each_safe(node, next, &acpi_device_list) {
|
|
||||||
struct acpi_device *dev =
|
|
||||||
container_of(node, struct acpi_device, g_list);
|
|
||||||
|
|
||||||
if (dev->driver || !dev->status.present)
|
|
||||||
continue;
|
|
||||||
spin_unlock(&acpi_device_lock);
|
|
||||||
|
|
||||||
if (!acpi_bus_match(&(dev->dev), &(drv->drv))) {
|
|
||||||
if (!acpi_bus_driver_init(dev, drv)) {
|
|
||||||
acpi_start_single_object(dev);
|
|
||||||
atomic_inc(&drv->references);
|
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
|
||||||
"Found driver [%s] for device [%s]\n",
|
|
||||||
drv->name, dev->pnp.bus_id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spin_lock(&acpi_device_lock);
|
|
||||||
}
|
|
||||||
spin_unlock(&acpi_device_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void acpi_driver_detach(struct acpi_driver *drv)
|
|
||||||
{
|
|
||||||
struct list_head *node, *next;
|
|
||||||
|
|
||||||
|
|
||||||
spin_lock(&acpi_device_lock);
|
|
||||||
list_for_each_safe(node, next, &acpi_device_list) {
|
|
||||||
struct acpi_device *dev =
|
|
||||||
container_of(node, struct acpi_device, g_list);
|
|
||||||
|
|
||||||
if (dev->driver == drv) {
|
|
||||||
spin_unlock(&acpi_device_lock);
|
|
||||||
if (drv->ops.remove)
|
|
||||||
drv->ops.remove(dev, ACPI_BUS_REMOVAL_NORMAL);
|
|
||||||
spin_lock(&acpi_device_lock);
|
|
||||||
dev->driver = NULL;
|
|
||||||
dev->driver_data = NULL;
|
|
||||||
atomic_dec(&drv->references);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spin_unlock(&acpi_device_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* acpi_bus_register_driver - register a driver with the ACPI bus
|
* acpi_bus_register_driver - register a driver with the ACPI bus
|
||||||
* @driver: driver being registered
|
* @driver: driver being registered
|
||||||
@ -520,16 +485,16 @@ static void acpi_driver_detach(struct acpi_driver *drv)
|
|||||||
*/
|
*/
|
||||||
int acpi_bus_register_driver(struct acpi_driver *driver)
|
int acpi_bus_register_driver(struct acpi_driver *driver)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (acpi_disabled)
|
if (acpi_disabled)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
driver->drv.name = driver->name;
|
||||||
|
driver->drv.bus = &acpi_bus_type;
|
||||||
|
driver->drv.owner = driver->owner;
|
||||||
|
|
||||||
spin_lock(&acpi_device_lock);
|
ret = driver_register(&driver->drv);
|
||||||
list_add_tail(&driver->node, &acpi_bus_drivers);
|
return ret;
|
||||||
spin_unlock(&acpi_device_lock);
|
|
||||||
acpi_driver_attach(driver);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(acpi_bus_register_driver);
|
EXPORT_SYMBOL(acpi_bus_register_driver);
|
||||||
@ -543,52 +508,11 @@ EXPORT_SYMBOL(acpi_bus_register_driver);
|
|||||||
*/
|
*/
|
||||||
void acpi_bus_unregister_driver(struct acpi_driver *driver)
|
void acpi_bus_unregister_driver(struct acpi_driver *driver)
|
||||||
{
|
{
|
||||||
acpi_driver_detach(driver);
|
driver_unregister(&driver->drv);
|
||||||
|
|
||||||
if (!atomic_read(&driver->references)) {
|
|
||||||
spin_lock(&acpi_device_lock);
|
|
||||||
list_del_init(&driver->node);
|
|
||||||
spin_unlock(&acpi_device_lock);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(acpi_bus_unregister_driver);
|
EXPORT_SYMBOL(acpi_bus_unregister_driver);
|
||||||
|
|
||||||
/**
|
|
||||||
* acpi_bus_find_driver - check if there is a driver installed for the device
|
|
||||||
* @device: device that we are trying to find a supporting driver for
|
|
||||||
*
|
|
||||||
* Parses the list of registered drivers looking for a driver applicable for
|
|
||||||
* the specified device.
|
|
||||||
*/
|
|
||||||
static int acpi_bus_find_driver(struct acpi_device *device)
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
struct list_head *node, *next;
|
|
||||||
|
|
||||||
|
|
||||||
spin_lock(&acpi_device_lock);
|
|
||||||
list_for_each_safe(node, next, &acpi_bus_drivers) {
|
|
||||||
struct acpi_driver *driver =
|
|
||||||
container_of(node, struct acpi_driver, node);
|
|
||||||
|
|
||||||
atomic_inc(&driver->references);
|
|
||||||
spin_unlock(&acpi_device_lock);
|
|
||||||
if (!acpi_bus_match(&(device->dev), &(driver->drv))) {
|
|
||||||
result = acpi_bus_driver_init(device, driver);
|
|
||||||
if (!result)
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
atomic_dec(&driver->references);
|
|
||||||
spin_lock(&acpi_device_lock);
|
|
||||||
}
|
|
||||||
spin_unlock(&acpi_device_lock);
|
|
||||||
|
|
||||||
Done:
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
Device Enumeration
|
Device Enumeration
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
@ -1033,32 +957,10 @@ static void acpi_device_get_debug_info(struct acpi_device *device,
|
|||||||
|
|
||||||
static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
|
static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
|
||||||
{
|
{
|
||||||
int result = 0;
|
|
||||||
struct acpi_driver *driver;
|
|
||||||
|
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
driver = dev->driver;
|
device_release_driver(&dev->dev);
|
||||||
|
|
||||||
if ((driver) && (driver->ops.remove)) {
|
|
||||||
|
|
||||||
if (driver->ops.stop) {
|
|
||||||
result = driver->ops.stop(dev, ACPI_BUS_REMOVAL_EJECT);
|
|
||||||
if (result)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = dev->driver->ops.remove(dev, ACPI_BUS_REMOVAL_EJECT);
|
|
||||||
if (result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
atomic_dec(&dev->driver->references);
|
|
||||||
dev->driver = NULL;
|
|
||||||
acpi_driver_data(dev) = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rmdevice)
|
if (!rmdevice)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1193,17 +1095,6 @@ acpi_add_single_object(struct acpi_device **child,
|
|||||||
device->parent->ops.bind(device);
|
device->parent->ops.bind(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Locate & Attach Driver
|
|
||||||
* ----------------------
|
|
||||||
* If there's a hardware id (_HID) or compatible ids (_CID) we check
|
|
||||||
* to see if there's a driver installed for this kind of device. Note
|
|
||||||
* that drivers can install before or after a device is enumerated.
|
|
||||||
*
|
|
||||||
* TBD: Assumes LDM provides driver hot-plug capability.
|
|
||||||
*/
|
|
||||||
acpi_bus_find_driver(device);
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (!result)
|
if (!result)
|
||||||
*child = device;
|
*child = device;
|
||||||
@ -1484,14 +1375,6 @@ static int __init acpi_scan_init(void)
|
|||||||
if (result)
|
if (result)
|
||||||
goto Done;
|
goto Done;
|
||||||
|
|
||||||
acpi_root->dev.bus = &acpi_bus_type;
|
|
||||||
snprintf(acpi_root->dev.bus_id, BUS_ID_SIZE, "%s", acpi_bus_type.name);
|
|
||||||
result = device_register(&acpi_root->dev);
|
|
||||||
if (result) {
|
|
||||||
/* We don't want to quit even if we failed to add suspend/resume */
|
|
||||||
printk(KERN_ERR PREFIX "Could not register device\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enumerate devices in the ACPI namespace.
|
* Enumerate devices in the ACPI namespace.
|
||||||
*/
|
*/
|
||||||
|
@ -133,13 +133,12 @@ struct acpi_device_ops {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct acpi_driver {
|
struct acpi_driver {
|
||||||
struct list_head node;
|
|
||||||
char name[80];
|
char name[80];
|
||||||
char class[80];
|
char class[80];
|
||||||
atomic_t references;
|
|
||||||
char *ids; /* Supported Hardware IDs */
|
char *ids; /* Supported Hardware IDs */
|
||||||
struct acpi_device_ops ops;
|
struct acpi_device_ops ops;
|
||||||
struct device_driver drv;
|
struct device_driver drv;
|
||||||
|
struct module *owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user