aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2007-02-03 01:14:35 -0500
committerLen Brown <len.brown@intel.com>2007-02-03 01:14:35 -0500
commit975a8e3ed2b9eab9f062a1e0ba7fe180e15204e1 (patch)
tree59b654df0b066b6d6b8ea16f5ae581b8fb45c1d5
parent1fcb71b84b05ff3bfd5b5b2eca9a9b3d13a76e3a (diff)
parentbfd80223d73f80e1d1c69dace9151756b3ef3b49 (diff)
Pull sysfs into test branch
Conflicts: Documentation/feature-removal-schedule.txt include/acpi/acpi_drivers.h Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--Documentation/feature-removal-schedule.txt10
-rw-r--r--drivers/acpi/Kconfig14
-rw-r--r--drivers/acpi/Makefile2
-rw-r--r--drivers/acpi/battery.c4
-rw-r--r--drivers/acpi/bus.c2
-rw-r--r--drivers/acpi/button.c2
-rw-r--r--drivers/acpi/container.c6
-rw-r--r--drivers/acpi/debug.c62
-rw-r--r--drivers/acpi/fan.c8
-rw-r--r--drivers/acpi/motherboard.c19
-rw-r--r--drivers/acpi/pci_root.c25
-rw-r--r--drivers/acpi/processor_core.c8
-rw-r--r--drivers/acpi/scan.c1176
-rw-r--r--drivers/acpi/system.c24
-rw-r--r--drivers/acpi/thermal.c4
-rw-r--r--drivers/acpi/video.c37
-rw-r--r--include/acpi/acpi_bus.h22
-rw-r--r--include/acpi/acpi_drivers.h13
18 files changed, 717 insertions, 721 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 0ba6af02cda..b3d1ce7e3ba 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -274,6 +274,7 @@ Who: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
---------------------------
+<<<<<<< test:Documentation/feature-removal-schedule.txt
What: ACPI hotkey driver (CONFIG_ACPI_HOTKEY)
When: 2.6.21
Why: hotkey.c was an attempt to consolidate multiple drivers that use
@@ -306,11 +307,18 @@ Why: The ACPI namespace is effectively the symbol list for
the BIOS can be extracted and disassembled with acpidump
and iasl as documented in the pmtools package here:
http://ftp.kernel.org/pub/linux/kernel/people/lenb/acpi/utils
-
Who: Len Brown <len.brown@intel.com>
---------------------------
+What: ACPI procfs interface
+When: July 2007
+Why: After ACPI sysfs conversion, ACPI attributes will be duplicated
+ in sysfs and the ACPI procfs interface should be removed.
+Who: Zhang Rui <rui.zhang@intel.com>
+
+---------------------------
+
What: /proc/acpi/button
When: August 2007
Why: /proc/acpi/button has been replaced by events to the input layer
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 1422a11b5bb..5c087a5bddf 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -77,6 +77,20 @@ config ACPI_SLEEP_PROC_SLEEP
Create /proc/acpi/sleep
Deprecated by /sys/power/state
+config ACPI_PROCFS
+ bool "Procfs interface (deprecated)"
+ depends on ACPI
+ default y
+ ---help---
+ Procfs interface for ACPI is made optional for back-compatible.
+ As the same functions are duplicated in sysfs interface
+ and this proc interface will be removed some time later,
+ it's marked as deprecated.
+ ( /proc/acpi/debug_layer && debug_level are deprecated by
+ /sys/module/acpi/parameters/debug_layer && debug_level.
+ /proc/acpi/info is deprecated by
+ /sys/module/acpi/parameters/acpica_version )
+
config ACPI_AC
tristate "AC Adapter"
depends on X86
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 1a738056558..399b0e8c41c 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -37,6 +37,7 @@ endif
obj-y += sleep/
obj-y += bus.o glue.o
+obj-y += scan.o motherboard.o
obj-$(CONFIG_ACPI_AC) += ac.o
obj-$(CONFIG_ACPI_BATTERY) += battery.o
obj-$(CONFIG_ACPI_BUTTON) += button.o
@@ -57,7 +58,6 @@ obj-$(CONFIG_ACPI_NUMA) += numa.o
obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
-obj-y += scan.o motherboard.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
obj-y += cm_sbs.o
obj-$(CONFIG_ACPI_SBS) += i2c_ec.o sbs.o
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 5f43e0d1489..2f4521a48fe 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -64,7 +64,7 @@ extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
static int acpi_battery_add(struct acpi_device *device);
static int acpi_battery_remove(struct acpi_device *device, int type);
-static int acpi_battery_resume(struct acpi_device *device, int status);
+static int acpi_battery_resume(struct acpi_device *device);
static struct acpi_driver acpi_battery_driver = {
.name = ACPI_BATTERY_DRIVER_NAME,
@@ -753,7 +753,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
}
/* this is needed to learn about changes made in suspended state */
-static int acpi_battery_resume(struct acpi_device *device, int state)
+static int acpi_battery_resume(struct acpi_device *device)
{
struct acpi_battery *battery;
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 15d677e6cee..c26468da429 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -192,7 +192,7 @@ int acpi_bus_set_power(acpi_handle handle, int state)
if (!device->flags.power_manageable) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n",
- device->kobj.name));
+ device->dev.kobj.name));
return -ENODEV;
}
/*
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index ac860583c20..c726612fafb 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -75,7 +75,7 @@ static int acpi_button_state_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_button_driver = {
.name = ACPI_BUTTON_DRIVER_NAME,
.class = ACPI_BUTTON_CLASS,
- .ids = "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E",
+ .ids = "button_power,button_sleep,PNP0C0D,PNP0C0C,PNP0C0E",
.ops = {
.add = acpi_button_add,
.remove = acpi_button_remove,
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 0a1863ec91f..69a68fd394c 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -167,7 +167,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
if (ACPI_FAILURE(status) || !device) {
result = container_device_add(&device, handle);
if (!result)
- kobject_uevent(&device->kobj,
+ kobject_uevent(&device->dev.kobj,
KOBJ_ONLINE);
else
printk("Failed to add container\n");
@@ -175,13 +175,13 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
} else {
if (ACPI_SUCCESS(status)) {
/* device exist and this is a remove request */
- kobject_uevent(&device->kobj, KOBJ_OFFLINE);
+ kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
}
}
break;
case ACPI_NOTIFY_EJECT_REQUEST:
if (!acpi_bus_get_device(handle, &device) && device) {
- kobject_uevent(&device->kobj, KOBJ_OFFLINE);
+ kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
}
break;
default:
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
index 35c6af8a83c..d48f65a8f65 100644
--- a/drivers/acpi/debug.c
+++ b/drivers/acpi/debug.c
@@ -13,14 +13,11 @@
#define _COMPONENT ACPI_SYSTEM_COMPONENT
ACPI_MODULE_NAME("debug")
-#define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer"
-#define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level"
+
#ifdef MODULE_PARAM_PREFIX
#undef MODULE_PARAM_PREFIX
#endif
-#define MODULE_PARAM_PREFIX
- module_param(acpi_dbg_layer, uint, 0400);
-module_param(acpi_dbg_level, uint, 0400);
+#define MODULE_PARAM_PREFIX "acpi."
struct acpi_dlayer {
const char *name;
@@ -86,6 +83,60 @@ static const struct acpi_dlevel acpi_debug_levels[] = {
ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
};
+/* --------------------------------------------------------------------------
+ FS Interface (/sys)
+ -------------------------------------------------------------------------- */
+static int param_get_debug_layer(char *buffer, struct kernel_param *kp) {
+ int result = 0;
+ int i;
+
+ result = sprintf(buffer, "%-25s\tHex SET\n", "Description");
+
+ for(i = 0; i <ARRAY_SIZE(acpi_debug_layers); i++) {
+ result += sprintf(buffer+result, "%-25s\t0x%08lX [%c]\n",
+ acpi_debug_layers[i].name,
+ acpi_debug_layers[i].value,
+ (acpi_dbg_layer & acpi_debug_layers[i].value) ? '*' : ' ');
+ }
+ result += sprintf(buffer+result, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
+ ACPI_ALL_DRIVERS,
+ (acpi_dbg_layer & ACPI_ALL_DRIVERS) ==
+ ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer &
+ ACPI_ALL_DRIVERS) == 0 ? ' ' : '-');
+ result += sprintf(buffer+result, "--\ndebug_layer = 0x%08X ( * = enabled)\n", acpi_dbg_layer);
+
+ return result;
+}
+
+static int param_get_debug_level(char *buffer, struct kernel_param *kp) {
+ int result = 0;
+ int i;
+
+ result = sprintf(buffer, "%-25s\tHex SET\n", "Description");
+
+ for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
+ result += sprintf(buffer+result, "%-25s\t0x%08lX [%c]\n",
+ acpi_debug_levels[i].name,
+ acpi_debug_levels[i].value,
+ (acpi_dbg_level & acpi_debug_levels[i].
+ value) ? '*' : ' ');
+ }
+ result += sprintf(buffer+result, "--\ndebug_level = 0x%08X (* = enabled)\n",
+ acpi_dbg_level);
+
+ return result;
+}
+
+module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644);
+module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644);
+
+/* --------------------------------------------------------------------------
+ FS Interface (/proc)
+ -------------------------------------------------------------------------- */
+#ifdef CONFIG_ACPI_PROCFS
+#define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer"
+#define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level"
+
static int
acpi_system_read_debug(char *page,
char **start, off_t off, int count, int *eof, void *data)
@@ -221,3 +272,4 @@ static int __init acpi_debug_init(void)
}
subsys_initcall(acpi_debug_init);
+#endif
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index f305a826ca2..af22fdf7341 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -48,8 +48,8 @@ MODULE_LICENSE("GPL");
static int acpi_fan_add(struct acpi_device *device);
static int acpi_fan_remove(struct acpi_device *device, int type);
-static int acpi_fan_suspend(struct acpi_device *device, int state);
-static int acpi_fan_resume(struct acpi_device *device, int state);
+static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state);
+static int acpi_fan_resume(struct acpi_device *device);
static struct acpi_driver acpi_fan_driver = {
.name = ACPI_FAN_DRIVER_NAME,
@@ -237,7 +237,7 @@ static int acpi_fan_remove(struct acpi_device *device, int type)
return 0;
}
-static int acpi_fan_suspend(struct acpi_device *device, int state)
+static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state)
{
if (!device)
return -EINVAL;
@@ -247,7 +247,7 @@ static int acpi_fan_suspend(struct acpi_device *device, int state)
return AE_OK;
}
-static int acpi_fan_resume(struct acpi_device *device, int state)
+static int acpi_fan_resume(struct acpi_device *device)
{
int result = 0;
int power_state = 0;
diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c
index b61107b0526..8f13b4f3e90 100644
--- a/drivers/acpi/motherboard.c
+++ b/drivers/acpi/motherboard.c
@@ -33,8 +33,7 @@
ACPI_MODULE_NAME("acpi_motherboard")
/* Dell use PNP0C01 instead of PNP0C02 */
-#define ACPI_MB_HID1 "PNP0C01"
-#define ACPI_MB_HID2 "PNP0C02"
+#define ACPI_MB_HID "PNP0C01,PNP0C02"
/**
* Doesn't care about legacy IO ports, only IO ports beyond 0x1000 are reserved
* Doesn't care about the failure of 'request_region', since other may reserve
@@ -110,19 +109,10 @@ static int acpi_motherboard_add(struct acpi_device *device)
return 0;
}
-static struct acpi_driver acpi_motherboard_driver1 = {
+static struct acpi_driver acpi_motherboard_driver = {
.name = "motherboard",
.class = "",
- .ids = ACPI_MB_HID1,
- .ops = {
- .add = acpi_motherboard_add,
- },
-};
-
-static struct acpi_driver acpi_motherboard_driver2 = {
- .name = "motherboard",
- .class = "",
- .ids = ACPI_MB_HID2,
+ .ids = ACPI_MB_HID,
.ops = {
.add = acpi_motherboard_add,
},
@@ -173,8 +163,7 @@ static void __init acpi_reserve_resources(void)
static int __init acpi_motherboard_init(void)
{
- acpi_bus_register_driver(&acpi_motherboard_driver1);
- acpi_bus_register_driver(&acpi_motherboard_driver2);
+ acpi_bus_register_driver(&acpi_motherboard_driver);
/*
* Guarantee motherboard IO reservation first
* This module must run after scan.c
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 1f06229040a..4ecf701687e 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -165,6 +165,21 @@ static acpi_status try_get_root_bridge_busnr(acpi_handle handle, int *busnum)
return AE_OK;
}
+static void acpi_pci_bridge_scan(struct acpi_device *device)
+{
+ int status;
+ struct acpi_device *child = NULL;
+
+ if (device->flags.bus_address)
+ if (device->parent && device->parent->ops.bind) {
+ status = device->parent->ops.bind(device);
+ if (!status) {
+ list_for_each_entry(child, &device->children, node)
+ acpi_pci_bridge_scan(child);
+ }
+ }
+}
+
static int acpi_pci_root_add(struct acpi_device *device)
{
int result = 0;
@@ -173,6 +188,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
acpi_status status = AE_OK;
unsigned long value = 0;
acpi_handle handle = NULL;
+ struct acpi_device *child;
if (!device)
@@ -188,9 +204,6 @@ static int acpi_pci_root_add(struct acpi_device *device)
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
acpi_driver_data(device) = root;
- /*
- * TBD: Doesn't the bus driver automatically set this?
- */
device->ops.bind = acpi_pci_bind;
/*
@@ -312,6 +325,12 @@ static int acpi_pci_root_add(struct acpi_device *device)
result = acpi_pci_irq_add_prt(device->handle, root->id.segment,
root->id.bus);
+ /*
+ * Scan and bind all _ADR-Based Devices
+ */
+ list_for_each_entry(child, &device->children, node)
+ acpi_pci_bridge_scan(child);
+
end:
if (result) {
if (!list_empty(&root->node))
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index eacf9a25201..0079bc51082 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -814,7 +814,7 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
return -ENODEV;
if ((pr->id >= 0) && (pr->id < NR_CPUS)) {
- kobject_uevent(&(*device)->kobj, KOBJ_ONLINE);
+ kobject_uevent(&(*device)->dev.kobj, KOBJ_ONLINE);
}
return 0;
}
@@ -852,13 +852,13 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
}
if (pr->id >= 0 && (pr->id < NR_CPUS)) {
- kobject_uevent(&device->kobj, KOBJ_OFFLINE);
+ kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
break;
}
result = acpi_processor_start(device);
if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) {
- kobject_uevent(&device->kobj, KOBJ_ONLINE);
+ kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
} else {
printk(KERN_ERR PREFIX "Device [%s] failed to start\n",
acpi_device_bid(device));
@@ -881,7 +881,7 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
}
if ((pr->id < NR_CPUS) && (cpu_present(pr->id)))
- kobject_uevent(&device->kobj, KOBJ_OFFLINE);
+ kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 0de45866464..5049230ccf4 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -21,101 +21,305 @@ extern struct acpi_device *acpi_root;
#define ACPI_BUS_DEVICE_NAME "System Bus"
static LIST_HEAD(acpi_device_list);
+static LIST_HEAD(acpi_bus_id_list);
DEFINE_SPINLOCK(acpi_device_lock);
LIST_HEAD(acpi_wakeup_device_list);
+struct acpi_device_bus_id{
+ char bus_id[15];
+ unsigned int instance_no;
+ struct list_head node;
+};
+static int acpi_eject_operation(acpi_handle handle, int lockable)
+{
+ struct acpi_object_list arg_list;
+ union acpi_object arg;
+ acpi_status status = AE_OK;
+
+ /*
+ * TBD: evaluate _PS3?
+ */
+
+ if (lockable) {
+ arg_list.count = 1;
+ arg_list.pointer = &arg;
+ arg.type = ACPI_TYPE_INTEGER;
+ arg.integer.value = 0;
+ acpi_evaluate_object(handle, "_LCK", &arg_list, NULL);
+ }
+
+ arg_list.count = 1;
+ arg_list.pointer = &arg;
+ arg.type = ACPI_TYPE_INTEGER;
+ arg.integer.value = 1;
-static void acpi_device_release(struct kobject *kobj)
+ /*
+ * TBD: _EJD support.
+ */
+
+ status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
+ if (ACPI_FAILURE(status)) {
+ return (-ENODEV);
+ }
+
+ return (0);
+}
+
+static ssize_t
+acpi_eject_store(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct acpi_device *dev = container_of(kobj, struct acpi_device, kobj);
- kfree(dev->pnp.cid_list);
- kfree(dev);
+ int result;
+ int ret = count;
+ int islockable;
+ acpi_status status;
+ acpi_handle handle;
+ acpi_object_type type = 0;
+ struct acpi_device *acpi_device = to_acpi_device(d);
+
+ if ((!count) || (buf[0] != '1')) {
+ return -EINVAL;
+ }
+#ifndef FORCE_EJECT
+ if (acpi_device->driver == NULL) {
+ ret = -ENODEV;
+ goto err;
+ }
+#endif
+ status = acpi_get_type(acpi_device->handle, &type);
+ if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) {
+ ret = -ENODEV;
+ goto err;
+ }
+
+ islockable = acpi_device->flags.lockable;
+ handle = acpi_device->handle;
+
+ result = acpi_bus_trim(acpi_device, 1);
+
+ if (!result)
+ result = acpi_eject_operation(handle, islockable);
+
+ if (result) {
+ ret = -EBUSY;
+ }
+ err:
+ return ret;
}
-struct acpi_device_attribute {
- struct attribute attr;
- ssize_t(*show) (struct acpi_device *, char *);
- ssize_t(*store) (struct acpi_device *, const char *, size_t);
-};
+static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
-typedef void acpi_device_sysfs_files(struct kobject *,
- const struct attribute *);
+static ssize_t
+acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) {
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
-static void setup_sys_fs_device_files(struct acpi_device *dev,
- acpi_device_sysfs_files * func);
+ return sprintf(buf, "%s\n", acpi_dev->pnp.hardware_id);
+}
+static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
-#define create_sysfs_device_files(dev) \
- setup_sys_fs_device_files(dev, (acpi_device_sysfs_files *)&sysfs_create_file)
-#define remove_sysfs_device_files(dev) \
- setup_sys_fs_device_files(dev, (acpi_device_sysfs_files *)&sysfs_remove_file)
+static ssize_t
+acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
+ int result;
+
+ result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path);
+ if(result)
+ goto end;
-#define to_acpi_device(n) container_of(n, struct acpi_device, kobj)
-#define to_handle_attr(n) container_of(n, struct acpi_device_attribute, attr);
+ result = sprintf(buf, "%s\n", (char*)path.pointer);
+ kfree(path.pointer);
+ end:
+ return result;
+}
+static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
-static ssize_t acpi_device_attr_show(struct kobject *kobj,
- struct attribute *attr, char *buf)
+static int acpi_device_setup_files(struct acpi_device *dev)
{
- struct acpi_device *device = to_acpi_device(kobj);
- struct acpi_device_attribute *attribute = to_handle_attr(attr);
- return attribute->show ? attribute->show(device, buf) : -EIO;
+ acpi_status status;
+ acpi_handle temp;
+ int result = 0;
+
+ /*
+ * Devices gotten from FADT don't have a "path" attribute
+ */
+ if(dev->handle) {
+ result = device_create_file(&dev->dev, &dev_attr_path);
+ if(result)
+ goto end;
+ }
+
+ if(dev->flags.hardware_id) {
+ result = device_create_file(&dev->dev, &dev_attr_hid);
+ if(result)
+ goto end;
+ }
+
+ /*
+ * If device has _EJ0, 'eject' file is created that is used to trigger
+ * hot-removal function from userland.
+ */
+ status = acpi_get_handle(dev->handle, "_EJ0", &temp);
+ if (ACPI_SUCCESS(status))
+ result = device_create_file(&dev->dev, &dev_attr_eject);
+ end:
+ return result;
}
-static ssize_t acpi_device_attr_store(struct kobject *kobj,
- struct attribute *attr, const char *buf,
- size_t len)
+
+static void acpi_device_remove_files(struct acpi_device *dev)
{
- struct acpi_device *device = to_acpi_device(kobj);
- struct acpi_device_attribute *attribute = to_handle_attr(attr);
- return attribute->store ? attribute->store(device, buf, len) : -EIO;
+ acpi_status status;
+ acpi_handle temp;
+
+ /*
+ * If device has _EJ0, 'eject' file is created that is used to trigger
+ * hot-removal function from userland.
+ */
+ status = acpi_get_handle(dev->handle, "_EJ0", &temp);
+ if (ACPI_SUCCESS(status))
+ device_remove_file(&dev->dev, &dev_attr_eject);
+
+ if(dev->flags.hardware_id)
+ device_remove_file(&dev->dev, &dev_attr_hid);
+ if(dev->handle)
+ device_remove_file(&dev->dev, &dev_attr_path);
}
+/* --------------------------------------------------------------------------
+ ACPI Bus operations
+ -------------------------------------------------------------------------- */
+static void acpi_device_release(struct device *dev)
+{
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
-static struct sysfs_ops acpi_device_sysfs_ops = {
- .show = acpi_device_attr_show,
- .store = acpi_device_attr_store,
-};
+ kfree(acpi_dev->pnp.cid_list);
+ kfree(acpi_dev);
+}
-static struct kobj_type ktype_acpi_ns = {
- .sysfs_ops = &acpi_device_sysfs_ops,
- .release = acpi_device_release,
-};
+static int acpi_device_suspend(struct device *dev, pm_message_t state)
+{
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ struct acpi_driver *acpi_drv = acpi_dev->driver;
+
+ if (acpi_drv && acpi_drv->ops.suspend)
+ return acpi_drv->ops.suspend(acpi_dev, state);
+ return 0;
+}
-static int namespace_uevent(struct kset *kset, struct kobject *kobj,
- char **envp, int num_envp, char *buffer,
- int buffer_size)
+static int acpi_device_resume(struct device *dev)
{
- struct acpi_device *dev = to_acpi_device(kobj);
- int i = 0;
- int len = 0;
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ struct acpi_driver *acpi_drv = acpi_dev->driver;
- if (!dev->driver)
- return 0;
+ if (acpi_drv && acpi_drv->ops.resume)
+ return acpi_drv->ops.resume(acpi_dev);
+ return 0;
+}
+
+static int acpi_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ struct acpi_driver *acpi_drv = to_acpi_driver(drv);
- if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
- "PHYSDEVDRIVER=%s", dev->driver->name))
+ return !acpi_match_ids(acpi_dev, acpi_drv->ids);
+}
+
+static int acpi_device_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
+{
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ int i = 0, length = 0, ret = 0;
+
+ if (acpi_dev->flags.hardware_id)
+ ret = add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "HWID=%s", acpi_dev->pnp.hardware_id);
+ if (ret)
return -ENOMEM;
+ if (acpi_dev->flags.compatible_ids) {
+ int j;
+ struct acpi_compatible_id_list *cid_list;
+
+ cid_list = acpi_dev->pnp.cid_list;
+
+ for (j = 0; j < cid_list->count; j++) {
+ ret = add_uevent_var(envp, num_envp, &i, buffer,
+ buffer_size, &length, "COMPTID=%s",
+ cid_list->id[j].value);
+ if (ret)
+ return -ENOMEM;
+ }
+ }
envp[i] = NULL;
+ return 0;
+}
+
+static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *);
+static int acpi_start_single_object(struct acpi_device *);
+static int acpi_device_probe(struct device * dev)
+{
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
+ int ret;
+
+ ret = acpi_bus_driver_init(acpi_dev, acpi_drv);
+ if (!ret) {
+ if (acpi_dev->bus_ops.acpi_op_start)
+ acpi_start_single_object(acpi_dev);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found driver [%s] for device [%s]\n",
+ acpi_drv->name, acpi_dev->pnp.bus_id));
+ get_device(dev);
+ }
+ return ret;
+}
+
+static int acpi_device_remove(struct device * dev)
+{
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ struct acpi_driver *acpi_drv = acpi_dev->driver;
+
+ if (acpi_drv) {
+ if (acpi_drv->ops.stop)
+ acpi_drv->ops.stop(acpi_dev, acpi_dev->removal_type);
+ if (acpi_drv->ops.remove)
+ acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type);
+ }
+ acpi_dev->driver = NULL;
+ acpi_driver_data(dev) = NULL;
+ put_device(dev);
return 0;
}
-static struct kset_uevent_ops namespace_uevent_ops = {
- .uevent = &namespace_uevent,
-};
+static void acpi_device_shutdown(struct device *dev)
+{
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ struct acpi_driver *acpi_drv = acpi_dev->driver;
-static struct kset acpi_namespace_kset = {
- .kobj = {
- .name = "namespace",
- },
- .subsys = &acpi_subsys,
- .ktype = &ktype_acpi_ns,
- .uevent_ops = &namespace_uevent_ops,
+ if (acpi_drv && acpi_drv->ops.shutdown)
+ acpi_drv->ops.shutdown(acpi_dev);
+
+ return ;
+}
+
+static struct bus_type acpi_bus_type = {
+ .name = "acpi",
+ .suspend = acpi_device_suspend,
+ .resume = acpi_device_resume,
+ .shutdown = acpi_device_shutdown,
+ .match = acpi_bus_match,
+ .probe = acpi_device_probe,
+ .remove = acpi_device_remove,
+ .uevent = acpi_device_uevent,
};
-static void acpi_device_register(struct acpi_device *device,
+static int acpi_device_register(struct acpi_device *device,
struct acpi_device *parent)
{
- int err;
-
+ int result;
+ struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id;
+ int found = 0;
/*
* Linkage
* -------
@@ -126,7 +330,33 @@ static void acpi_device_register(struct acpi_device *device,
INIT_LIST_HEAD(&device->g_list);
INIT_LIST_HEAD(&device->wakeup_list);
+ new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
+ if (!new_bus_id) {
+ printk(KERN_ERR PREFIX "Memory allocation error\n");
+ return -ENOMEM;
+ }
+
spin_lock(&acpi_device_lock);
+ /*
+ * Find suitable bus_id and instance number in acpi_bus_id_list
+ * If failed, create one and link it into acpi_bus_id_list
+ */
+ list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) {
+ if(!strcmp(acpi_device_bus_id->bus_id, device->flags.hardware_id? device->pnp.hardware_id : "device")) {
+ acpi_device_bus_id->instance_no ++;
+ found = 1;
+ kfree(new_bus_id);
+ break;
+ }
+ }
+ if(!found) {
+ acpi_device_bus_id = new_bus_id;
+ strcpy(acpi_device_bus_id->bus_id, device->flags.hardware_id ? device->pnp.hardware_id : "device");
+ acpi_device_bus_id->instance_no = 0;
+ list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list);
+ }
+ sprintf(device->dev.bus_id, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no);
+
if (device->parent) {
list_add_tail(&device->node, &device->parent->children);
list_add_tail(&device->g_list, &device->parent->g_list);
@@ -136,16 +366,33 @@ static void acpi_device_register(struct acpi_device *device,
list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list);
spin_unlock(&acpi_device_lock);
- strlcpy(device->kobj.name, device->pnp.bus_id, KOBJ_NAME_LEN);
- if (parent)
- device->kobj.parent = &parent->kobj;
- device->kobj.ktype = &ktype_acpi_ns;
- device->kobj.kset = &acpi_namespace_kset;
- err = kobject_register(&device->kobj);
- if (err < 0)
- printk(KERN_WARNING "%s: kobject_register error: %d\n",
- __FUNCTION__, err);
- create_sysfs_device_files(device);
+ if (device->parent)
+ device->dev.parent = &parent->dev;
+ device->dev.bus = &acpi_bus_type;
+ device_initialize(&device->dev);
+ device->dev.release = &acpi_device_release;
+ result = device_add(&device->dev);
+ if(result) {
+ printk("Error adding device %s", device->dev.bus_id);
+ goto end;
+ }
+
+ result = acpi_device_setup_files(device);
+ if(result)
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error creating sysfs interface for device %s\n", device->dev.bus_id));
+
+ device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
+ return 0;
+ end:
+ spin_lock(&acpi_device_lock);
+ if (device->parent) {
+ list_del(&device->node);
+ list_del(&device->g_list);
+ } else
+ list_del(&device->g_list);
+ list_del(&device->wakeup_list);
+ spin_unlock(&acpi_device_lock);
+ return result;
}
static void acpi_device_unregister(struct acpi_device *device, int type)
@@ -158,81 +405,143 @@ static void acpi_device_unregister(struct acpi_device *device, int type)
list_del(&device->g_list);
list_del(&device->wakeup_list);
-
spin_unlock(&acpi_device_lock);
acpi_detach_data(device->handle, acpi_bus_data_handler);
- remove_sysfs_device_files(device);
- kobject_unregister(&device->kobj);
+
+ acpi_device_remove_files(device);
+ device_unregister(&device->dev);
}
-void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context)
+/* --------------------------------------------------------------------------
+ Driver Management
+ -------------------------------------------------------------------------- */
+/**
+ * acpi_bus_driver_init - add a device to a driver
+ * @device: the device to add and initialize
+ * @driver: driver for the device
+ *
+ * Used to initialize a device via its device driver. Called whenever a
+ * driver is bound to a device. Invokes the driver's add() ops.
+ */
+static int
+acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver)
{
+ int result = 0;
- /* TBD */
- return;
-}
+ if (!device || !driver)
+ return -EINVAL;
-static int acpi_bus_get_power_flags(struct acpi_device *device)
-{
- acpi_status status = 0;
- acpi_handle handle = NULL;
- u32 i = 0;
+ if (!driver->ops.add)
+ return -ENOSYS;
+ result = driver->op