Commit 975a8e3e authored by Len Brown's avatar Len Brown

Pull sysfs into test branch

Conflicts:

	Documentation/feature-removal-schedule.txt
	include/acpi/acpi_drivers.h
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parents 1fcb71b8 bfd80223
...@@ -274,6 +274,7 @@ Who: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> ...@@ -274,6 +274,7 @@ Who: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
--------------------------- ---------------------------
<<<<<<< test:Documentation/feature-removal-schedule.txt
What: ACPI hotkey driver (CONFIG_ACPI_HOTKEY) What: ACPI hotkey driver (CONFIG_ACPI_HOTKEY)
When: 2.6.21 When: 2.6.21
Why: hotkey.c was an attempt to consolidate multiple drivers that use 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 ...@@ -306,11 +307,18 @@ Why: The ACPI namespace is effectively the symbol list for
the BIOS can be extracted and disassembled with acpidump the BIOS can be extracted and disassembled with acpidump
and iasl as documented in the pmtools package here: and iasl as documented in the pmtools package here:
http://ftp.kernel.org/pub/linux/kernel/people/lenb/acpi/utils http://ftp.kernel.org/pub/linux/kernel/people/lenb/acpi/utils
Who: Len Brown <len.brown@intel.com> 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 What: /proc/acpi/button
When: August 2007 When: August 2007
Why: /proc/acpi/button has been replaced by events to the input layer Why: /proc/acpi/button has been replaced by events to the input layer
......
...@@ -77,6 +77,20 @@ config ACPI_SLEEP_PROC_SLEEP ...@@ -77,6 +77,20 @@ config ACPI_SLEEP_PROC_SLEEP
Create /proc/acpi/sleep Create /proc/acpi/sleep
Deprecated by /sys/power/state 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 config ACPI_AC
tristate "AC Adapter" tristate "AC Adapter"
depends on X86 depends on X86
......
...@@ -37,6 +37,7 @@ endif ...@@ -37,6 +37,7 @@ endif
obj-y += sleep/ obj-y += sleep/
obj-y += bus.o glue.o obj-y += bus.o glue.o
obj-y += scan.o motherboard.o
obj-$(CONFIG_ACPI_AC) += ac.o obj-$(CONFIG_ACPI_AC) += ac.o
obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_BATTERY) += battery.o
obj-$(CONFIG_ACPI_BUTTON) += button.o obj-$(CONFIG_ACPI_BUTTON) += button.o
...@@ -57,7 +58,6 @@ obj-$(CONFIG_ACPI_NUMA) += numa.o ...@@ -57,7 +58,6 @@ obj-$(CONFIG_ACPI_NUMA) += numa.o
obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
obj-y += scan.o motherboard.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
obj-y += cm_sbs.o obj-y += cm_sbs.o
obj-$(CONFIG_ACPI_SBS) += i2c_ec.o sbs.o obj-$(CONFIG_ACPI_SBS) += i2c_ec.o sbs.o
...@@ -64,7 +64,7 @@ extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); ...@@ -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_add(struct acpi_device *device);
static int acpi_battery_remove(struct acpi_device *device, int type); 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 = { static struct acpi_driver acpi_battery_driver = {
.name = ACPI_BATTERY_DRIVER_NAME, .name = ACPI_BATTERY_DRIVER_NAME,
...@@ -753,7 +753,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) ...@@ -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 */ /* 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; struct acpi_battery *battery;
......
...@@ -192,7 +192,7 @@ int acpi_bus_set_power(acpi_handle handle, int state) ...@@ -192,7 +192,7 @@ int acpi_bus_set_power(acpi_handle handle, int state)
if (!device->flags.power_manageable) { if (!device->flags.power_manageable) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n", ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n",
device->kobj.name)); device->dev.kobj.name));
return -ENODEV; return -ENODEV;
} }
/* /*
......
...@@ -75,7 +75,7 @@ static int acpi_button_state_open_fs(struct inode *inode, struct file *file); ...@@ -75,7 +75,7 @@ static int acpi_button_state_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_button_driver = { static struct acpi_driver acpi_button_driver = {
.name = ACPI_BUTTON_DRIVER_NAME, .name = ACPI_BUTTON_DRIVER_NAME,
.class = ACPI_BUTTON_CLASS, .class = ACPI_BUTTON_CLASS,
.ids = "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E", .ids = "button_power,button_sleep,PNP0C0D,PNP0C0C,PNP0C0E",
.ops = { .ops = {
.add = acpi_button_add, .add = acpi_button_add,
.remove = acpi_button_remove, .remove = acpi_button_remove,
......
...@@ -167,7 +167,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) ...@@ -167,7 +167,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
if (ACPI_FAILURE(status) || !device) { if (ACPI_FAILURE(status) || !device) {
result = container_device_add(&device, handle); result = container_device_add(&device, handle);
if (!result) if (!result)
kobject_uevent(&device->kobj, kobject_uevent(&device->dev.kobj,
KOBJ_ONLINE); KOBJ_ONLINE);
else else
printk("Failed to add container\n"); printk("Failed to add container\n");
...@@ -175,13 +175,13 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) ...@@ -175,13 +175,13 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
} else { } else {
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
/* device exist and this is a remove request */ /* device exist and this is a remove request */
kobject_uevent(&device->kobj, KOBJ_OFFLINE); kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
} }
} }
break; break;
case ACPI_NOTIFY_EJECT_REQUEST: case ACPI_NOTIFY_EJECT_REQUEST:
if (!acpi_bus_get_device(handle, &device) && device) { if (!acpi_bus_get_device(handle, &device) && device) {
kobject_uevent(&device->kobj, KOBJ_OFFLINE); kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
} }
break; break;
default: default:
......
...@@ -13,14 +13,11 @@ ...@@ -13,14 +13,11 @@
#define _COMPONENT ACPI_SYSTEM_COMPONENT #define _COMPONENT ACPI_SYSTEM_COMPONENT
ACPI_MODULE_NAME("debug") ACPI_MODULE_NAME("debug")
#define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer"
#define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level"
#ifdef MODULE_PARAM_PREFIX #ifdef MODULE_PARAM_PREFIX
#undef MODULE_PARAM_PREFIX #undef MODULE_PARAM_PREFIX
#endif #endif
#define MODULE_PARAM_PREFIX #define MODULE_PARAM_PREFIX "acpi."
module_param(acpi_dbg_layer, uint, 0400);
module_param(acpi_dbg_level, uint, 0400);
struct acpi_dlayer { struct acpi_dlayer {
const char *name; const char *name;
...@@ -86,6 +83,60 @@ static const struct acpi_dlevel acpi_debug_levels[] = { ...@@ -86,6 +83,60 @@ static const struct acpi_dlevel acpi_debug_levels[] = {
ACPI_DEBUG_INIT(ACPI_LV_EVENTS), 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 static int
acpi_system_read_debug(char *page, acpi_system_read_debug(char *page,
char **start, off_t off, int count, int *eof, void *data) char **start, off_t off, int count, int *eof, void *data)
...@@ -221,3 +272,4 @@ static int __init acpi_debug_init(void) ...@@ -221,3 +272,4 @@ static int __init acpi_debug_init(void)
} }
subsys_initcall(acpi_debug_init); subsys_initcall(acpi_debug_init);
#endif
...@@ -48,8 +48,8 @@ MODULE_LICENSE("GPL"); ...@@ -48,8 +48,8 @@ MODULE_LICENSE("GPL");
static int acpi_fan_add(struct acpi_device *device); static int acpi_fan_add(struct acpi_device *device);
static int acpi_fan_remove(struct acpi_device *device, int type); 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_suspend(struct acpi_device *device, pm_message_t state);
static int acpi_fan_resume(struct acpi_device *device, int state); static int acpi_fan_resume(struct acpi_device *device);
static struct acpi_driver acpi_fan_driver = { static struct acpi_driver acpi_fan_driver = {
.name = ACPI_FAN_DRIVER_NAME, .name = ACPI_FAN_DRIVER_NAME,
...@@ -237,7 +237,7 @@ static int acpi_fan_remove(struct acpi_device *device, int type) ...@@ -237,7 +237,7 @@ static int acpi_fan_remove(struct acpi_device *device, int type)
return 0; 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) if (!device)
return -EINVAL; return -EINVAL;
...@@ -247,7 +247,7 @@ static int acpi_fan_suspend(struct acpi_device *device, int state) ...@@ -247,7 +247,7 @@ static int acpi_fan_suspend(struct acpi_device *device, int state)
return AE_OK; 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 result = 0;
int power_state = 0; int power_state = 0;
......
...@@ -33,8 +33,7 @@ ...@@ -33,8 +33,7 @@
ACPI_MODULE_NAME("acpi_motherboard") ACPI_MODULE_NAME("acpi_motherboard")
/* Dell use PNP0C01 instead of PNP0C02 */ /* Dell use PNP0C01 instead of PNP0C02 */
#define ACPI_MB_HID1 "PNP0C01" #define ACPI_MB_HID "PNP0C01,PNP0C02"
#define ACPI_MB_HID2 "PNP0C02"
/** /**
* Doesn't care about legacy IO ports, only IO ports beyond 0x1000 are reserved * 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 * 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) ...@@ -110,19 +109,10 @@ static int acpi_motherboard_add(struct acpi_device *device)
return 0; return 0;
} }
static struct acpi_driver acpi_motherboard_driver1 = { static struct acpi_driver acpi_motherboard_driver = {
.name = "motherboard", .name = "motherboard",
.class = "", .class = "",
.ids = ACPI_MB_HID1, .ids = ACPI_MB_HID,
.ops = {
.add = acpi_motherboard_add,
},
};
static struct acpi_driver acpi_motherboard_driver2 = {
.name = "motherboard",
.class = "",
.ids = ACPI_MB_HID2,
.ops = { .ops = {
.add = acpi_motherboard_add, .add = acpi_motherboard_add,
}, },
...@@ -173,8 +163,7 @@ static void __init acpi_reserve_resources(void) ...@@ -173,8 +163,7 @@ static void __init acpi_reserve_resources(void)
static int __init acpi_motherboard_init(void) static int __init acpi_motherboard_init(void)
{ {
acpi_bus_register_driver(&acpi_motherboard_driver1); acpi_bus_register_driver(&acpi_motherboard_driver);
acpi_bus_register_driver(&acpi_motherboard_driver2);
/* /*
* Guarantee motherboard IO reservation first * Guarantee motherboard IO reservation first
* This module must run after scan.c * This module must run after scan.c
......
...@@ -165,6 +165,21 @@ static acpi_status try_get_root_bridge_busnr(acpi_handle handle, int *busnum) ...@@ -165,6 +165,21 @@ static acpi_status try_get_root_bridge_busnr(acpi_handle handle, int *busnum)
return AE_OK; 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) static int acpi_pci_root_add(struct acpi_device *device)
{ {
int result = 0; int result = 0;
...@@ -173,6 +188,7 @@ static int acpi_pci_root_add(struct acpi_device *device) ...@@ -173,6 +188,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
acpi_status status = AE_OK; acpi_status status = AE_OK;
unsigned long value = 0; unsigned long value = 0;
acpi_handle handle = NULL; acpi_handle handle = NULL;
struct acpi_device *child;
if (!device) if (!device)
...@@ -188,9 +204,6 @@ static int acpi_pci_root_add(struct acpi_device *device) ...@@ -188,9 +204,6 @@ static int acpi_pci_root_add(struct acpi_device *device)
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
acpi_driver_data(device) = root; acpi_driver_data(device) = root;
/*
* TBD: Doesn't the bus driver automatically set this?
*/
device->ops.bind = acpi_pci_bind; device->ops.bind = acpi_pci_bind;
/* /*
...@@ -312,6 +325,12 @@ static int acpi_pci_root_add(struct acpi_device *device) ...@@ -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, result = acpi_pci_irq_add_prt(device->handle, root->id.segment,
root->id.bus); root->id.bus);
/*
* Scan and bind all _ADR-Based Devices
*/
list_for_each_entry(child, &device->children, node)
acpi_pci_bridge_scan(child);
end: end:
if (result) { if (result) {
if (!list_empty(&root->node)) if (!list_empty(&root->node))
......
...@@ -814,7 +814,7 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) ...@@ -814,7 +814,7 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
return -ENODEV; return -ENODEV;
if ((pr->id >= 0) && (pr->id < NR_CPUS)) { if ((pr->id >= 0) && (pr->id < NR_CPUS)) {
kobject_uevent(&(*device)->kobj, KOBJ_ONLINE); kobject_uevent(&(*device)->dev.kobj, KOBJ_ONLINE);
} }
return 0; return 0;
} }
...@@ -852,13 +852,13 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) ...@@ -852,13 +852,13 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
} }
if (pr->id >= 0 && (pr->id < NR_CPUS)) { if (pr->id >= 0 && (pr->id < NR_CPUS)) {
kobject_uevent(&device->kobj, KOBJ_OFFLINE); kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
break; break;
} }
result = acpi_processor_start(device); result = acpi_processor_start(device);
if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) { if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) {
kobject_uevent(&device->kobj, KOBJ_ONLINE); kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
} else { } else {
printk(KERN_ERR PREFIX "Device [%s] failed to start\n", printk(KERN_ERR PREFIX "Device [%s] failed to start\n",
acpi_device_bid(device)); acpi_device_bid(device));
...@@ -881,7 +881,7 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) ...@@ -881,7 +881,7 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
} }
if ((pr->id < NR_CPUS) && (cpu_present(pr->id))) if ((pr->id < NR_CPUS) && (cpu_present(pr->id)))
kobject_uevent(&device->kobj, KOBJ_OFFLINE); kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
break; break;
default: default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
......
...@@ -21,470 +21,408 @@ extern struct acpi_device *acpi_root; ...@@ -21,470 +21,408 @@ extern struct acpi_device *acpi_root;
#define ACPI_BUS_DEVICE_NAME "System Bus" #define ACPI_BUS_DEVICE_NAME "System Bus"
static LIST_HEAD(acpi_device_list); static LIST_HEAD(acpi_device_list);
static LIST_HEAD(acpi_bus_id_list);
DEFINE_SPINLOCK(acpi_device_lock); DEFINE_SPINLOCK(acpi_device_lock);
LIST_HEAD(acpi_wakeup_device_list); LIST_HEAD(acpi_wakeup_device_list);
struct acpi_device_bus_id{
static void acpi_device_release(struct kobject *kobj) char bus_id[15];
{ unsigned int instance_no;
struct acpi_device *dev = container_of(kobj, struct acpi_device, kobj); struct list_head node;
kfree(dev->pnp.cid_list);
kfree(dev);
}
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 int acpi_eject_operation(acpi_handle handle, int lockable)
typedef void acpi_device_sysfs_files(struct kobject *,
const struct attribute *);
static void setup_sys_fs_device_files(struct acpi_device *dev,
acpi_device_sysfs_files * func);
#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)
#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);
static ssize_t acpi_device_attr_show(struct kobject *kobj,
struct attribute *attr, char *buf)
{
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;
}
static ssize_t acpi_device_attr_store(struct kobject *kobj,
struct attribute *attr, const char *buf,
size_t len)
{ {
struct acpi_device *device = to_acpi_device(kobj); struct acpi_object_list arg_list;
struct acpi_device_attribute *attribute = to_handle_attr(attr); union acpi_object arg;
return attribute->store ? attribute->store(device, buf, len) : -EIO; acpi_status status = AE_OK;
}
static struct sysfs_ops acpi_device_sysfs_ops = {
.show = acpi_device_attr_show,
.store = acpi_device_attr_store,
};
static struct kobj_type ktype_acpi_ns = { /*
.sysfs_ops = &acpi_device_sysfs_ops, * TBD: evaluate _PS3?
.release = acpi_device_release, */
};
static int namespace_uevent(struct kset *kset, struct kobject *kobj, if (lockable) {
char **envp, int num_envp, char *buffer, arg_list.count = 1;
int buffer_size) arg_list.pointer = &arg;
{ arg.type = ACPI_TYPE_INTEGER;
struct acpi_device *dev = to_acpi_device(kobj); arg.integer.value = 0;
int i = 0; acpi_evaluate_object(handle, "_LCK", &arg_list, NULL);
int len = 0; }
if (!dev->driver) arg_list.count = 1;
return 0; arg_list.pointer = &arg;
arg.type = ACPI_TYPE_INTEGER;
arg.integer.value = 1;
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, /*
"PHYSDEVDRIVER=%s", dev->driver->name)) * TBD: _EJD support.
return -ENOMEM; */
envp[i] = NULL; status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
if (ACPI_FAILURE(status)) {
return (-ENODEV);
}
return 0; return (0);
} }
static struct kset_uevent_ops namespace_uevent_ops = { static ssize_t
.uevent = &namespace_uevent, acpi_eject_store(struct device *d, struct device_attribute *attr,
}; const char *buf, size_t count)
{
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);
static struct kset acpi_namespace_kset = { if ((!count) || (buf[0] != '1')) {
.kobj = { return -EINVAL;
.name = "namespace", }
}, #ifndef FORCE_EJECT
.subsys = &acpi_subsys, if (acpi_device->driver == NULL) {
.ktype = &ktype_acpi_ns, ret = -ENODEV;
.uevent_ops = &namespace_uevent_ops, goto err;
}; }
#endif
status = acpi_get_type(acpi_device->handle, &type);
if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) {
ret = -ENODEV;
goto err;
}
static void acpi_device_register(struct acpi_device *device, islockable = acpi_device->flags.lockable;
struct acpi_device *parent) handle = acpi_device->handle;
{
int err;
/* result = acpi_bus_trim(acpi_device, 1);
* Linkage
* -------
* Link this device to its parent and siblings.
*/
INIT_LIST_HEAD(&device->children);
INIT_LIST_HEAD(&device->node);
INIT_LIST_HEAD(&device->g_list);
INIT_LIST_HEAD(&device->wakeup_list);
spin_lock(&acpi_device_lock); if (!result)
if (device->parent) { result = acpi_eject_operation(handle, islockable);
list_add_tail(&device->node, &device->parent->children);
list_add_tail(&device->g_list, &device->parent->g_list);
} else
list_add_tail(&device->g_list, &acpi_device_list);
if (device->wakeup.flags.valid)
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 (result) {
if (parent) ret = -EBUSY;
device->kobj.parent = &parent->kobj; }
device->kobj.ktype = &ktype_acpi_ns; err:
device->kobj.kset = &acpi_namespace_kset; return ret;
err = kobject_register(&device->kobj);
if (err < 0)
printk(KERN_WARNING "%s: kobject_register error: %d\n",
__FUNCTION__, err);
create_sysfs_device_files(device);
} }
static void acpi_device_unregister(struct acpi_device *device, int type) static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
{
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); static ssize_t
acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) {
spin_unlock(&acpi_device_lock); struct acpi_device *acpi_dev = to_acpi_device(dev);
acpi_detach_data(device->handle, acpi_bus_data_handler); return sprintf(buf, "%s\n", acpi_dev->pnp.hardware_id);
remove_sysfs_device_files(device);
kobject_unregister(&device->kobj);
} }
static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context) 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;
/* TBD */ result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path);
if(result)
goto end;
return; 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 int acpi_bus_get_power_flags(struct acpi_device *device) static int acpi_device_setup_files(struct acpi_device *dev)
{ {
acpi_status status = 0; acpi_status status;
acpi_handle handle = NULL; acpi_handle temp;
u32 i = 0; int result = 0;
/*
* Power Management Flags
*/
status = acpi_get_handle(device->handle, "_PSC", &handle);
if (ACPI_SUCCESS(status))
device->power.flags.explicit_get = 1;
status = acpi_get_handle(device->handle, "_IRC", &handle);
if (ACPI_SUCCESS(status))
device->power.flags.inrush_current = 1;
/* /*
* Enumerate supported power management states * Devices gotten from FADT don't have a "path" attribute
*/ */
for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) { if(dev->handle) {
struct acpi_device_power_state *ps = &device->power.states[i]; result = device_create_file(&dev->dev, &dev_attr_path);
char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' }; if(result)
goto end;
/* Evaluate "_PRx" to se if power resources are referenced */
acpi_evaluate_reference(device->handle, object_name, NULL,
&ps->resources);
if (ps->resources.count) {
device->power.flags.power_resources = 1;
ps->flags.valid = 1;
} }
/* Evaluate "_PSx" to see if we can do explicit sets */ if(dev->flags.hardware_id) {
object_name[2] = 'S'; result = device_create_file(&dev->dev, &dev_attr_hid);
status = acpi_get_handle(device->handle, object_name, &handle); if(result)
if (ACPI_SUCCESS(status)) { goto end;
ps->flags.explicit_set = 1;
ps->flags.valid = 1;
} }
/* State is valid if we have some power control */ /*
if (ps->resources.count || ps->flags.explicit_set) * If device has _EJ0, 'eject' file is created that is used to trigger
ps->flags.valid = 1; * hot-removal function from userland.
*/
ps->power = -1; /* Unknown - driver assigned */ status = acpi_get_handle(dev->handle, "_EJ0", &temp);
ps->latency = -1; /* Unknown - driver assigned */ if (ACPI_SUCCESS(status))
} result = device_create_file(&dev->dev, &dev_attr_eject);
end:
return result;
}
/* Set defaults for D0 and D3 states (always valid) */ static void acpi_device_remove_files(struct acpi_device *dev)
device->power.states[ACPI_STATE_D0].flags.valid = 1; {
device->power.states[ACPI_STATE_D0].power = 100; acpi_status status;
device->power.states[ACPI_STATE_D3].flags.valid = 1; acpi_handle temp;
device->power.states[ACPI_STATE_D3].power = 0;
/* TBD: System wake support and resource requirements. */ /*
* 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);
device->power.state = ACPI_STATE_UNKNOWN; 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);
return 0; kfree(acpi_dev->pnp.cid_list);
kfree(acpi_dev);
} }
int acpi_match_ids(struct acpi_device *device, char *ids) static int acpi_device_suspend(struct device *dev, pm_message_t state)
{ {
if (device->flags.hardware_id) struct acpi_device *acpi_dev = to_acpi_device(dev);
if (strstr(ids, device->pnp.hardware_id)) struct acpi_driver *acpi_drv = acpi_dev->driver;
return 0;
if (device->flags.compatible_ids) {
struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
int i;
/* compare multiple _CID entries against driver ids */ if (acpi_drv && acpi_drv->ops.suspend)
for (i = 0; i < cid_list->count; i++) { return acpi_drv->ops.suspend(acpi_dev, state);
if (strstr(ids, cid_list->id[i].value))
return 0; return 0;
}
}
return -ENOENT;
} }
static acpi_status static int acpi_device_resume(struct device *dev)
acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device,
union acpi_object *package)
{ {
int i = 0; struct acpi_device *acpi_dev = to_acpi_device(dev);
union acpi_object *element = NULL; struct acpi_driver *acpi_drv = acpi_dev->driver;
if (!device || !package || (package->package.count < 2)) if (acpi_drv && acpi_drv->ops.resume)
return AE_BAD_PARAMETER; return acpi_drv->ops.resume(acpi_dev);
return 0;
element = &(package->package.elements[0]); }
if (!element)
return AE_BAD_PARAMETER;
if (element->type == ACPI_TYPE_PACKAGE) {
if ((element->package.count < 2) ||
(element->package.elements[0].type !=
ACPI_TYPE_LOCAL_REFERENCE)
|| (element->package.elements[1].type != ACPI_TYPE_INTEGER))
return AE_BAD_DATA;
device->wakeup.gpe_device =
element->package.elements[0].reference.handle;
device->wakeup.gpe_number =
(u32) element->package.elements[1].integer.value;
} else if (element->type == ACPI_TYPE_INTEGER) {
device->wakeup.gpe_number = element->integer.value;
} else
return AE_BAD_DATA;
element = &(package->package.elements[1]);
if (element->type != ACPI_TYPE_INTEGER) {
return AE_BAD_DATA;
}
device->wakeup.sleep_state = element->integer.value;
if ((package->package.count - 2) > ACPI_MAX_HANDLES) {
return AE_NO_MEMORY;
}
device->wakeup.resources.count = package->package.count - 2;
for (i = 0; i < device->wakeup.resources.count; i++) {
element = &(package->package.elements[i + 2]);
if (element->type != ACPI_TYPE_ANY) {
return AE_BAD_DATA;
}
device->wakeup.resources.handles[i] = element->reference.handle; 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);
return AE_OK; return !acpi_match_ids(acpi_dev, acpi_drv->ids);
} }
static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) static int acpi_device_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{ {
acpi_status status = 0; struct acpi_device *acpi_dev = to_acpi_device(dev);
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; int i = 0, length = 0, ret = 0;
union acpi_object *package = NULL;
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;
/* _PRW */ for (j = 0; j < cid_list->count; j++) {
status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); ret = add_uevent_var(envp, num_envp, &i, buffer,
if (ACPI_FAILURE(status)) { buffer_size, &length, "COMPTID=%s",
ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW")); cid_list->id[j].value);
goto end; if (ret)
return -ENOMEM;
} }
package = (union acpi_object *)buffer.pointer;
status = acpi_bus_extract_wakeup_device_power_package(device, package);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package"));
goto end;
} }
kfree(buffer.pointer); envp[i] = NULL;
device->wakeup.flags.valid = 1;
/* Power button, Lid switch always enable wakeup */
if (!acpi_match_ids(device, "PNP0C0D,PNP0C0C,PNP0C0E"))
device->wakeup.flags.run_wake = 1;
end:
if (ACPI_FAILURE(status))
device->flags.wake_capable = 0;
return 0; return 0;
} }
/* -------------------------------------------------------------------------- static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *);
ACPI sysfs device file support static int acpi_start_single_object(struct acpi_device *);
-------------------------------------------------------------------------- */ static int acpi_device_probe(struct device * dev)
static ssize_t acpi_eject_store(struct acpi_device *device,
const char *buf, size_t count);
#define ACPI_DEVICE_ATTR(_name,_mode,_show,_store) \
static struct acpi_device_attribute acpi_device_attr_##_name = \
__ATTR(_name, _mode, _show, _store)
ACPI_DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
/**
* setup_sys_fs_device_files - sets up the device files under device namespace
* @dev: acpi_device object
* @func: function pointer to create or destroy the device file
*/
static void
setup_sys_fs_device_files(struct acpi_device *dev,
acpi_device_sysfs_files * func)
{ {
acpi_status status; struct acpi_device *acpi_dev = to_acpi_device(dev);
acpi_handle temp = NULL; struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
int ret;
/*
* If device has _EJ0, 'eject' file is created that is used to trigger ret = acpi_bus_driver_init(acpi_dev, acpi_drv);
* hot-removal function from userland. if (!ret) {
*/ if (acpi_dev->bus_ops.acpi_op_start)
status = acpi_get_handle(dev->handle, "_EJ0", &temp); acpi_start_single_object(acpi_dev);
if (ACPI_SUCCESS(status)) ACPI_DEBUG_PRINT((ACPI_DB_INFO,
(*(func)) (&dev->kobj, &acpi_device_attr_eject.attr); "Found driver [%s] for device [%s]\n",
acpi_drv->name, acpi_dev->pnp.bus_id));
get_device(dev);
}
return ret;
} }
static int acpi_eject_operation(acpi_handle handle, int lockable) static int acpi_device_remove(struct device * dev)
{ {
struct acpi_object_list arg_list; struct acpi_device *acpi_dev = to_acpi_device(dev);
union acpi_object arg; struct acpi_driver *acpi_drv = acpi_dev->driver;
acpi_status status = AE_OK;
/*
* TBD: evaluate _PS3?
*/
if (lockable) { if (acpi_drv) {
arg_list.count = 1; if (acpi_drv->ops.stop)
arg_list.pointer = &arg; acpi_drv->ops.stop(acpi_dev, acpi_dev->removal_type);
arg.type = ACPI_TYPE_INTEGER; if (acpi_drv->ops.remove)
arg.integer.value = 0; acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type);
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;
/*
* TBD: _EJD support.
*/
status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
if (ACPI_FAILURE(status)) {
return (-ENODEV);
} }
acpi_dev->driver = NULL;
acpi_driver_data(dev) = NULL;
return (0); put_device(dev);
return 0;
} }
static ssize_t static void acpi_device_shutdown(struct device *dev)
acpi_eject_store(struct acpi_device *device, const char *buf, size_t count) {
struct acpi_device *acpi_dev = to_acpi_device(dev);
struct acpi_driver *acpi_drv = acpi_dev->driver;
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 int acpi_device_register(struct acpi_device *device,
struct acpi_device *parent)
{ {
int result; int result;
int ret = count; struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id;
int islockable; int found = 0;
acpi_status status; /*
acpi_handle handle; * Linkage
acpi_object_type type = 0; * -------
* Link this device to its parent and siblings.
*/
INIT_LIST_HEAD(&device->children);
INIT_LIST_HEAD(&device->node);
INIT_LIST_HEAD(&device->g_list);
INIT_LIST_HEAD(&device->wakeup_list);
if ((!count) || (buf[0] != '1')) { new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
return -EINVAL; if (!new_bus_id) {
printk(KERN_ERR PREFIX "Memory allocation error\n");
return -ENOMEM;
} }
#ifndef FORCE_EJECT
if (device->driver == NULL) { spin_lock(&acpi_device_lock);
ret = -ENODEV; /*
goto err; * 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;
} }
#endif
status = acpi_get_type(device->handle, &type);
if (ACPI_FAILURE(status) || (!device->flags.ejectable)) {
ret = -ENODEV;
goto err;
} }
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);
islockable = device->flags.lockable; if (device->parent) {
handle = device->handle; list_add_tail(&device->node, &device->parent->children);
list_add_tail(&device->g_list, &device->parent->g_list);
result = acpi_bus_trim(device, 1); } else
list_add_tail(&device->g_list, &acpi_device_list);
if (!result) if (device->wakeup.flags.valid)
result = acpi_eject_operation(handle, islockable); list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list);
spin_unlock(&acpi_device_lock);
if (result) { if (device->parent)
ret = -EBUSY; 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;
} }
err:
return ret;
}
/* -------------------------------------------------------------------------- result = acpi_device_setup_files(device);
Performance Management if(result)
-------------------------------------------------------------------------- */ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error creating sysfs interface for device %s\n", device->dev.bus_id));
static int acpi_bus_get_perf_flags(struct acpi_device *device) device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
{
device->performance.state = ACPI_STATE_UNKNOWN;
return 0; 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)
Driver Management {
-------------------------------------------------------------------------- */ spin_lock(&acpi_device_lock);
if (device->parent) {
list_del(&device->node);
list_del(&device->g_list);
} else
list_del(&device->g_list);
static LIST_HEAD(acpi_bus_drivers); list_del(&device->wakeup_list);
spin_unlock(&acpi_device_lock);
/** acpi_detach_data(device->handle, acpi_bus_data_handler);
* acpi_bus_match - match device IDs to driver's supported IDs
* @device: the device that we are trying to match to a driver acpi_device_remove_files(device);
* @driver: driver whose device id table is being checked device_unregister(&device->dev);
*
* Checks the device's hardware (_HID) or compatible (_CID) ids to see if it
* matches the specified driver's criteria.
*/
static int
acpi_bus_match(struct acpi_device *device, struct acpi_driver *driver)
{
if (driver && driver->ops.match)
return driver->ops.match(device, driver);
return acpi_match_ids(device, driver->ids);
} }
/* --------------------------------------------------------------------------
Driver Management
-------------------------------------------------------------------------- */
/** /**
* 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)
...@@ -535,162 +473,246 @@ static int acpi_start_single_object(struct acpi_device *device) ...@@ -535,162 +473,246 @@ static int acpi_start_single_object(struct acpi_device *device)
return result; return result;
} }
static void acpi_driver_attach(struct acpi_driver *drv) /**
* acpi_bus_register_driver - register a driver with the ACPI bus
* @driver: driver being registered
*
* Registers a driver with the ACPI bus. Searches the namespace for all
* devices that match the driver's criteria and binds. Returns zero for
* success or a negative error status for failure.
*/
int acpi_bus_register_driver(struct acpi_driver *driver)
{ {
struct list_head *node, *next; int ret;
if (acpi_disabled)
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_for_each_safe(node, next, &acpi_device_list) { return ret;
struct acpi_device *dev = }
container_of(node, struct acpi_device, g_list);
if (dev->driver || !dev->status.present) EXPORT_SYMBOL(acpi_bus_register_driver);
continue;
spin_unlock(&acpi_device_lock);
if (!acpi_bus_match(dev, drv)) { /**
if (!acpi_bus_driver_init(dev, drv)) { * acpi_bus_unregister_driver - unregisters a driver with the APIC bus
acpi_start_single_object(dev); * @driver: driver to unregister
atomic_inc(&drv->references); *
ACPI_DEBUG_PRINT((ACPI_DB_INFO, * Unregisters a driver with the ACPI bus. Searches the namespace for all
"Found driver [%s] for device [%s]\n", * devices that match the driver's criteria and unbinds.
drv->name, dev->pnp.bus_id)); */
void acpi_bus_unregister_driver(struct acpi_driver *driver)
{
driver_unregister(&driver->drv);
}
EXPORT_SYMBOL(acpi_bus_unregister_driver);
/* --------------------------------------------------------------------------
Device Enumeration
-------------------------------------------------------------------------- */
acpi_status
acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd)
{
acpi_status status;
acpi_handle tmp;
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
union acpi_object *obj;
status = acpi_get_handle(handle, "_EJD", &tmp);
if (ACPI_FAILURE(status))
return status;
status = acpi_evaluate_object(handle, "_EJD", NULL, &buffer);
if (ACPI_SUCCESS(status)) {
obj = buffer.pointer;
status = acpi_get_handle(NULL, obj->string.pointer, ejd);
kfree(buffer.pointer);
} }
return status;
}
EXPORT_SYMBOL_GPL(acpi_bus_get_ejd);
void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context)
{
/* TBD */
return;
}
int acpi_match_ids(struct acpi_device *device, char *ids)
{
if (device->flags.hardware_id)
if (strstr(ids, device->pnp.hardware_id))
return 0;
if (device->flags.compatible_ids) {
struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
int i;
/* compare multiple _CID entries against driver ids */
for (i = 0; i < cid_list->count; i++) {
if (strstr(ids, cid_list->id[i].value))
return 0;
} }
spin_lock(&acpi_device_lock);
} }
spin_unlock(&acpi_device_lock); return -ENOENT;
}
static int acpi_bus_get_perf_flags(struct acpi_device *device)
{
device->performance.state = ACPI_STATE_UNKNOWN;
return 0;
} }
static void acpi_driver_detach(struct acpi_driver *drv) static acpi_status
acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device,
union acpi_object *package)
{ {
struct list_head *node, *next; int i = 0;
union acpi_object *element = NULL;
if (!device || !package || (package->package.count < 2))
return AE_BAD_PARAMETER;
spin_lock(&acpi_device_lock); element = &(package->package.elements[0]);
list_for_each_safe(node, next, &acpi_device_list) { if (!element)
struct acpi_device *dev = return AE_BAD_PARAMETER;
container_of(node, struct acpi_device, g_list); if (element->type == ACPI_TYPE_PACKAGE) {
if ((element->package.count < 2) ||
(element->package.elements[0].type !=
ACPI_TYPE_LOCAL_REFERENCE)
|| (element->package.elements[1].type != ACPI_TYPE_INTEGER))
return AE_BAD_DATA;
device->wakeup.gpe_device =
element->package.elements[0].reference.handle;
device->wakeup.gpe_number =
(u32) element->package.elements[1].integer.value;
} else if (element->type == ACPI_TYPE_INTEGER) {
device->wakeup.gpe_number = element->integer.value;
} else
return AE_BAD_DATA;
if (dev->driver == drv) { element = &(package->package.elements[1]);
spin_unlock(&acpi_device_lock); if (element->type != ACPI_TYPE_INTEGER) {
if (drv->ops.remove) return AE_BAD_DATA;
drv->ops.remove(dev, ACPI_BUS_REMOVAL_NORMAL);
spin_lock(&acpi_device_lock);
dev->driver = NULL;
dev->driver_data = NULL;
atomic_dec(&drv->references);
} }
device->wakeup.sleep_state = element->integer.value;
if ((package->package.count - 2) > ACPI_MAX_HANDLES) {
return AE_NO_MEMORY;
} }
spin_unlock(&acpi_device_lock); device->wakeup.resources.count = package->package.count - 2;
for (i = 0; i < device->wakeup.resources.count; i++) {
element = &(package->package.elements[i + 2]);
if (element->type != ACPI_TYPE_ANY) {
return AE_BAD_DATA;
}
device->wakeup.resources.handles[i] = element->reference.handle;
}
return AE_OK;
} }
/** static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
* acpi_bus_register_driver - register a driver with the ACPI bus
* @driver: driver being registered
*
* Registers a driver with the ACPI bus. Searches the namespace for all
* devices that match the driver's criteria and binds. Returns zero for
* success or a negative error status for failure.
*/
int acpi_bus_register_driver(struct acpi_driver *driver)
{ {
acpi_status status = 0;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *package = NULL;
/* _PRW */
status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW"));
goto end;
}
if (acpi_disabled) package = (union acpi_object *)buffer.pointer;
return -ENODEV; status = acpi_bus_extract_wakeup_device_power_package(device, package);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package"));
goto end;
}
spin_lock(&acpi_device_lock); kfree(buffer.pointer);
list_add_tail(&driver->node, &acpi_bus_drivers);
spin_unlock(&acpi_device_lock); device->wakeup.flags.valid = 1;
acpi_driver_attach(driver); /* Power button, Lid switch always enable wakeup */
if (!acpi_match_ids(device, "PNP0C0D,PNP0C0C,PNP0C0E"))
device->wakeup.flags.run_wake = 1;
end:
if (ACPI_FAILURE(status))
device->flags.wake_capable = 0;
return 0; return 0;
} }
EXPORT_SYMBOL(acpi_bus_register_driver); static int acpi_bus_get_power_flags(struct acpi_device *device)
/**
* acpi_bus_unregister_driver - unregisters a driver with the APIC bus
* @driver: driver to unregister
*
* Unregisters a driver with the ACPI bus. Searches the namespace for all
* devices that match the driver's criteria and unbinds.
*/
void acpi_bus_unregister_driver(struct acpi_driver *driver)
{ {
acpi_driver_detach(driver); acpi_status status = 0;
acpi_handle handle = NULL;
if (!atomic_read(&driver->references)) { u32 i = 0;
spin_lock(&acpi_device_lock);
list_del_init(&driver->node);
spin_unlock(&acpi_device_lock);
}
return;
}
EXPORT_SYMBOL(acpi_bus_unregister_driver);
/** /*
* acpi_bus_find_driver - check if there is a driver installed for the device * Power Management Flags
* @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) status = acpi_get_handle(device->handle, "_PSC", &handle);
{ if (ACPI_SUCCESS(status))
int result = 0; device->power.flags.explicit_get = 1;
struct list_head *node, *next; status = acpi_get_handle(device->handle, "_IRC", &handle);
if (ACPI_SUCCESS(status))
device->power.flags.inrush_current = 1;
spin_lock(&acpi_device_lock); /*
list_for_each_safe(node, next, &acpi_bus_drivers) { * Enumerate supported power management states
struct acpi_driver *driver = */
container_of(node, struct acpi_driver, node); for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) {
struct acpi_device_power_state *ps = &device->power.states[i];
char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' };
atomic_inc(&driver->references); /* Evaluate "_PRx" to se if power resources are referenced */
spin_unlock(&acpi_device_lock); acpi_evaluate_reference(device->handle, object_name, NULL,
if (!acpi_bus_match(device, driver)) { &ps->resources);
result = acpi_bus_driver_init(device, driver); if (ps->resources.count) {
if (!result) device->power.flags.power_resources = 1;
goto Done; ps->flags.valid = 1;
} }
atomic_dec(&driver->references);
spin_lock(&acpi_device_lock); /* Evaluate "_PSx" to see if we can do explicit sets */
object_name[2] = 'S';
status = acpi_get_handle(device->handle, object_name, &handle);
if (ACPI_SUCCESS(status)) {
ps->flags.explicit_set = 1;
ps->flags.valid = 1;
} }
spin_unlock(&acpi_device_lock);
Done: /* State is valid if we have some power control */
return result; if (ps->resources.count || ps->flags.explicit_set)
} ps->flags.valid = 1;
/* -------------------------------------------------------------------------- ps->power = -1; /* Unknown - driver assigned */
Device Enumeration ps->latency = -1; /* Unknown - driver assigned */
-------------------------------------------------------------------------- */ }
acpi_status /* Set defaults for D0 and D3 states (always valid) */
acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd) device->power.states[ACPI_STATE_D0].flags.valid = 1;
{ device->power.states[ACPI_STATE_D0].power = 100;
acpi_status status; device->power.states[ACPI_STATE_D3].flags.valid = 1;
acpi_handle tmp; device->power.states[ACPI_STATE_D3].power = 0;
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
union acpi_object *obj;
status = acpi_get_handle(handle, "_EJD", &tmp); /* TBD: System wake support and resource requirements. */
if (ACPI_FAILURE(status))
return status;
status = acpi_evaluate_object(handle, "_EJD", NULL, &buffer); device->power.state = ACPI_STATE_UNKNOWN;
if (ACPI_SUCCESS(status)) {
obj = buffer.pointer;
status = acpi_get_handle(NULL, obj->string.pointer, ejd);
kfree(buffer.pointer);
}
return status;
}
EXPORT_SYMBOL_GPL(acpi_bus_get_ejd);
return 0;
}
static int acpi_bus_get_flags(struct acpi_device *device) static int acpi_bus_get_flags(struct acpi_device *device)
{ {
...@@ -782,6 +804,39 @@ static void acpi_device_get_busid(struct acpi_device *device, ...@@ -782,6 +804,39 @@ static void acpi_device_get_busid(struct acpi_device *device,
} }
} }
static int
acpi_video_bus_match(struct acpi_device *device)
{
acpi_handle h_dummy1;
acpi_handle h_dummy2;
acpi_handle h_dummy3;
if (!device)
return -EINVAL;
/* Since there is no HID, CID for ACPI Video drivers, we have
* to check well known required nodes for each feature we support.
*/
/* Does this device able to support video switching ? */
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) &&
ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2)))
return 0;
/* Does this device able to retrieve a video ROM ? */
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1)))
return 0;
/* Does this device able to configure which video head to be POSTed ? */
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) &&
ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) &&
ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3)))
return 0;
return -ENODEV;
}
static void acpi_device_set_id(struct acpi_device *device, static void acpi_device_set_id(struct acpi_device *device,
struct acpi_device *parent, acpi_handle handle, struct acpi_device *parent, acpi_handle handle,
int type) int type)
...@@ -812,6 +867,12 @@ static void acpi_device_set_id(struct acpi_device *device, ...@@ -812,6 +867,12 @@ static void acpi_device_set_id(struct acpi_device *device,
device->pnp.bus_address = info->address; device->pnp.bus_address = info->address;
device->flags.bus_address = 1; device->flags.bus_address = 1;
} }
if(!(info->valid & (ACPI_VALID_HID | ACPI_VALID_CID))){
status = acpi_video_bus_match(device);
if(ACPI_SUCCESS(status))
hid = ACPI_VIDEO_HID;
}
break; break;
case ACPI_BUS_TYPE_POWER: case ACPI_BUS_TYPE_POWER:
hid = ACPI_POWER_HID; hid = ACPI_POWER_HID;
...@@ -933,41 +994,22 @@ static void acpi_device_get_debug_info(struct acpi_device *device, ...@@ -933,41 +994,22 @@ 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; dev->removal_type = ACPI_BUS_REMOVAL_EJECT;
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;
/*
* unbind _ADR-Based Devices when hot removal
*/
if (dev->flags.bus_address) { if (dev->flags.bus_address) {
if ((dev->parent) && (dev->parent->ops.unbind)) if ((dev->parent) && (dev->parent->ops.unbind))
dev->parent->ops.unbind(dev); dev->parent->ops.unbind(dev);
} }
acpi_device_unregister(dev, ACPI_BUS_REMOVAL_EJECT); acpi_device_unregister(dev, ACPI_BUS_REMOVAL_EJECT);
return 0; return 0;
...@@ -975,7 +1017,8 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) ...@@ -975,7 +1017,8 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
static int static int
acpi_add_single_object(struct acpi_device **child, acpi_add_single_object(struct acpi_device **child,
struct acpi_device *parent, acpi_handle handle, int type) struct acpi_device *parent, acpi_handle handle, int type,
struct acpi_bus_ops *ops)
{ {
int result = 0; int result = 0;
struct acpi_device *device = NULL; struct acpi_device *device = NULL;
...@@ -992,6 +1035,8 @@ acpi_add_single_object(struct acpi_device **child, ...@@ -992,6 +1035,8 @@ acpi_add_single_object(struct acpi_device **child,
device->handle = handle; device->handle = handle;
device->parent = parent; device->parent = parent;
device->bus_ops = *ops; /* workround for not call .start */
acpi_device_get_busid(device, handle, type); acpi_device_get_busid(device, handle, type);
...@@ -1078,31 +1123,16 @@ acpi_add_single_object(struct acpi_device **child, ...@@ -1078,31 +1123,16 @@ acpi_add_single_object(struct acpi_device **child,
acpi_device_get_debug_info(device, handle, type); acpi_device_get_debug_info(device, handle, type);
acpi_device_register(device, parent); result = acpi_device_register(device, parent);
/* /*
* Bind _ADR-Based Devices * Bind _ADR-Based Devices when hot add
* -----------------------
* If there's a a bus address (_ADR) then we utilize the parent's
* 'bind' function (if exists) to bind the ACPI- and natively-
* enumerated device representations.
*/ */
if (device->flags.bus_address) { if (device->flags.bus_address) {
if (device->parent && device->parent->ops.bind) if (device->parent && device->parent->ops.bind)
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;
...@@ -1188,14 +1218,14 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops) ...@@ -1188,14 +1218,14 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops)
if (ops->acpi_op_add) if (ops->acpi_op_add)
status = acpi_add_single_object(&child, parent, status = acpi_add_single_object(&child, parent,
chandle, type); chandle, type, ops);
else else
status = acpi_bus_get_device(chandle, &child); status = acpi_bus_get_device(chandle, &child);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
continue; continue;
if (ops->acpi_op_start) { if (ops->acpi_op_start && !(ops->acpi_op_add)) {
status = acpi_start_single_object(child); status = acpi_start_single_object(child);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
continue; continue;
...@@ -1233,13 +1263,13 @@ acpi_bus_add(struct acpi_device **child, ...@@ -1233,13 +1263,13 @@ acpi_bus_add(struct acpi_device **child,
int result; int result;
struct acpi_bus_ops ops; struct acpi_bus_ops ops;
result = acpi_add_single_object(child, parent, handle, type);
if (!result) {
memset(&ops, 0, sizeof(ops)); memset(&ops, 0, sizeof(ops));
ops.acpi_op_add = 1; ops.acpi_op_add = 1;
result = acpi_add_single_object(child, parent, handle, type, &ops);
if (!result)
result = acpi_bus_scan(*child, &ops); result = acpi_bus_scan(*child, &ops);
}
return result; return result;
} }
...@@ -1325,127 +1355,35 @@ static int acpi_bus_scan_fixed(struct acpi_device *root) ...@@ -1325,127 +1355,35 @@ static int acpi_bus_scan_fixed(struct acpi_device *root)
{ {
int result = 0; int result = 0;
struct acpi_device *device = NULL; struct acpi_device *device = NULL;
struct acpi_bus_ops ops;
if (!root) if (!root)
return -ENODEV; return -ENODEV;
memset(&ops, 0, sizeof(ops));
ops.acpi_op_add = 1;
ops.acpi_op_start = 1;
/* /*
* Enumerate all fixed-feature devices. * Enumerate all fixed-feature devices.
*/ */
if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) { if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) {
result = acpi_add_single_object(&device, acpi_root, result = acpi_add_single_object(&device, acpi_root,
NULL, NULL,
ACPI_BUS_TYPE_POWER_BUTTON); ACPI_BUS_TYPE_POWER_BUTTON,
if (!result) &ops);
result = acpi_start_single_object(device);
} }
if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) { if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
result = acpi_add_single_object(&device, acpi_root, result = acpi_add_single_object(&device, acpi_root,
NULL, NULL,
ACPI_BUS_TYPE_SLEEP_BUTTON); ACPI_BUS_TYPE_SLEEP_BUTTON,
if (!result) &ops);
result = acpi_start_single_object(device);
} }
return result; return result;
} }
static inline struct acpi_device * to_acpi_dev(struct device * dev)
{
return container_of(dev, struct acpi_device, dev);
}
static int root_suspend(struct acpi_device * acpi_dev, pm_message_t state)
{
struct acpi_device * dev, * next;
int result;
spin_lock(&acpi_device_lock);
list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) {
if (dev->driver && dev->driver->ops.suspend) {
spin_unlock(&acpi_device_lock);
result = dev->driver->ops.suspend(dev, 0);
if (result) {
printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n",
acpi_device_name(dev),
acpi_device_bid(dev), result);
}
spin_lock(&acpi_device_lock);
}
}
spin_unlock(&acpi_device_lock);
return 0;
}
static int acpi_device_suspend(struct device * dev, pm_message_t state)
{
struct acpi_device * acpi_dev = to_acpi_dev(dev);
/*
* For now, we should only register 1 generic device -
* the ACPI root device - and from there, we walk the
* tree of ACPI devices to suspend each one using the
* ACPI driver methods.
*/
if (acpi_dev->handle == ACPI_ROOT_OBJECT)
root_suspend(acpi_dev, state);
return 0;
}
static int root_resume(struct acpi_device * acpi_dev)
{
struct acpi_device * dev, * next;
int result;
spin_lock(&acpi_device_lock);
list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) {
if (dev->driver && dev->driver->ops.resume) {
spin_unlock(&acpi_device_lock);
result = dev->driver->ops.resume(dev, 0);
if (result) {
printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n",
acpi_device_name(dev),
acpi_device_bid(dev), result);
}
spin_lock(&acpi_device_lock);
}
}
spin_unlock(&acpi_device_lock);
return 0;
}
static int acpi_device_resume(struct device * dev)
{
struct acpi_device * acpi_dev = to_acpi_dev(dev);
/*
* For now, we should only register 1 generic device -
* the ACPI root device - and from there, we walk the
* tree of ACPI devices to resume each one using the
* ACPI driver methods.
*/
if (acpi_dev->handle == ACPI_ROOT_OBJECT)
root_resume(acpi_dev);
return 0;
}
static struct bus_type acpi_bus_type = {
.name = "acpi",
.suspend = acpi_device_suspend,
.resume = acpi_device_resume,
};
static int __init acpi_scan_init(void) static int __init acpi_scan_init(void)
{ {
int result; int result;
...@@ -1455,9 +1393,9 @@ static int __init acpi_scan_init(void) ...@@ -1455,9 +1393,9 @@ static int __init acpi_scan_init(void)
if (acpi_disabled) if (acpi_disabled)
return 0; return 0;
result = kset_register(&acpi_namespace_kset); memset(&ops, 0, sizeof(ops));
if (result < 0) ops.acpi_op_add = 1;
printk(KERN_ERR PREFIX "kset_register error: %d\n", result); ops.acpi_op_start = 1;
result = bus_register(&acpi_bus_type); result = bus_register(&acpi_bus_type);
if (result) { if (result) {
...@@ -1469,32 +1407,16 @@ static int __init acpi_scan_init(void) ...@@ -1469,32 +1407,16 @@ static int __init acpi_scan_init(void)
* Create the root device in the bus's device tree * Create the root device in the bus's device tree
*/ */
result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT, result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT,
ACPI_BUS_TYPE_SYSTEM); ACPI_BUS_TYPE_SYSTEM, &ops);
if (result)
goto Done;
result = acpi_start_single_object(acpi_root);
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.
*/ */
result = acpi_bus_scan_fixed(acpi_root); result = acpi_bus_scan_fixed(acpi_root);
if (!result) { if (!result)
memset(&ops, 0, sizeof(ops));
ops.acpi_op_add = 1;
ops.acpi_op_start = 1;
result = acpi_bus_scan(acpi_root, &ops); result = acpi_bus_scan(acpi_root, &ops);
}
if (result) if (result)
acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
......
...@@ -32,6 +32,11 @@ ...@@ -32,6 +32,11 @@
#define _COMPONENT ACPI_SYSTEM_COMPONENT #define _COMPONENT ACPI_SYSTEM_COMPONENT
ACPI_MODULE_NAME("acpi_system") ACPI_MODULE_NAME("acpi_system")
#ifdef MODULE_PARAM_PREFIX
#undef MODULE_PARAM_PREFIX
#endif
#define MODULE_PARAM_PREFIX "acpi."
#define ACPI_SYSTEM_CLASS "system" #define ACPI_SYSTEM_CLASS "system"
#define ACPI_SYSTEM_DRIVER_NAME "ACPI System Driver" #define ACPI_SYSTEM_DRIVER_NAME "ACPI System Driver"
#define ACPI_SYSTEM_DEVICE_NAME "System" #define ACPI_SYSTEM_DEVICE_NAME "System"
...@@ -40,9 +45,23 @@ ACPI_MODULE_NAME("acpi_system") ...@@ -40,9 +45,23 @@ ACPI_MODULE_NAME("acpi_system")
#define ACPI_SYSTEM_FILE_DSDT "dsdt" #define ACPI_SYSTEM_FILE_DSDT "dsdt"
#define ACPI_SYSTEM_FILE_FADT "fadt" #define ACPI_SYSTEM_FILE_FADT "fadt"
/*
* Make ACPICA version work as module param
*/
static int param_get_acpica_version(char *buffer, struct kernel_param *kp) {
int result;
result = sprintf(buffer, "%x", ACPI_CA_VERSION);
return result;
}
module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444);
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
FS Interface (/proc) FS Interface (/proc)
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_PROCFS
static int acpi_system_read_info(struct seq_file *seq, void *offset) static int acpi_system_read_info(struct seq_file *seq, void *offset)
{ {
...@@ -62,6 +81,7 @@ static const struct file_operations acpi_system_info_ops = { ...@@ -62,6 +81,7 @@ static const struct file_operations acpi_system_info_ops = {
.llseek = seq_lseek, .llseek = seq_lseek,
.release = single_release, .release = single_release,
}; };
#endif
static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t, static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t,
loff_t *); loff_t *);
...@@ -125,6 +145,7 @@ static int __init acpi_system_init(void) ...@@ -125,6 +145,7 @@ static int __init acpi_system_init(void)
if (acpi_disabled) if (acpi_disabled)
return 0; return 0;
#ifdef CONFIG_ACPI_PROCFS
/* 'info' [R] */ /* 'info' [R] */
name = ACPI_SYSTEM_FILE_INFO; name = ACPI_SYSTEM_FILE_INFO;
entry = create_proc_entry(name, S_IRUGO, acpi_root_dir); entry = create_proc_entry(name, S_IRUGO, acpi_root_dir);
...@@ -133,6 +154,7 @@ static int __init acpi_system_init(void) ...@@ -133,6 +154,7 @@ static int __init acpi_system_init(void)
else { else {
entry->proc_fops = &acpi_system_info_ops; entry->proc_fops = &acpi_system_info_ops;
} }
#endif
/* 'dsdt' [R] */ /* 'dsdt' [R] */
name = ACPI_SYSTEM_FILE_DSDT; name = ACPI_SYSTEM_FILE_DSDT;
...@@ -156,7 +178,9 @@ static int __init acpi_system_init(void) ...@@ -156,7 +178,9 @@ static int __init acpi_system_init(void)
Error: Error:
remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir); remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir);
remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir); remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir);
#ifdef CONFIG_ACPI_PROCFS
remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_root_dir); remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_root_dir);
#endif
error = -EFAULT; error = -EFAULT;
goto Done; goto Done;
......
...@@ -82,7 +82,7 @@ MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n"); ...@@ -82,7 +82,7 @@ MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
static int acpi_thermal_add(struct acpi_device *device); static int acpi_thermal_add(struct acpi_device *device);
static int acpi_thermal_remove(struct acpi_device *device, int type); static int acpi_thermal_remove(struct acpi_device *device, int type);
static int acpi_thermal_resume(struct acpi_device *device, int state); static int acpi_thermal_resume(struct acpi_device *device);
static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
...@@ -1353,7 +1353,7 @@ static int acpi_thermal_remove(struct acpi_device *device, int type) ...@@ -1353,7 +1353,7 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
return 0; return 0;
} }
static int acpi_thermal_resume(struct acpi_device *device, int state) static int acpi_thermal_resume(struct acpi_device *device)
{ {
struct acpi_thermal *tz = NULL; struct acpi_thermal *tz = NULL;
int i; int i;
......
...@@ -73,16 +73,14 @@ MODULE_LICENSE("GPL"); ...@@ -73,16 +73,14 @@ MODULE_LICENSE("GPL");
static int acpi_video_bus_add(struct acpi_device *device); static int acpi_video_bus_add(struct acpi_device *device);
static int acpi_video_bus_remove(struct acpi_device *device, int type); static int acpi_video_bus_remove(struct acpi_device *device, int type);
static int acpi_video_bus_match(struct acpi_device *device,
struct acpi_driver *driver);
static struct acpi_driver acpi_video_bus = { static struct acpi_driver acpi_video_bus = {
.name = ACPI_VIDEO_DRIVER_NAME, .name = ACPI_VIDEO_DRIVER_NAME,
.class = ACPI_VIDEO_CLASS, .class = ACPI_VIDEO_CLASS,
.ids = ACPI_VIDEO_HID,
.ops = { .ops = {
.add = acpi_video_bus_add, .add = acpi_video_bus_add,
.remove = acpi_video_bus_remove, .remove = acpi_video_bus_remove,
.match = acpi_video_bus_match,
}, },
}; };
...@@ -1885,39 +1883,6 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) ...@@ -1885,39 +1883,6 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
return 0; return 0;
} }
static int
acpi_video_bus_match(struct acpi_device *device, struct acpi_driver *driver)
{
acpi_handle h_dummy1;
acpi_handle h_dummy2;
acpi_handle h_dummy3;
if (!device || !driver)
return -EINVAL;
/* Since there is no HID, CID for ACPI Video drivers, we have
* to check well known required nodes for each feature we support.
*/
/* Does this device able to support video switching ? */
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) &&
ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2)))
return 0;
/* Does this device able to retrieve a video ROM ? */
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1)))
return 0;
/* Does this device able to configure which video head to be POSTed ? */
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) &&
ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) &&
ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3)))
return 0;
return -ENODEV;
}
static int __init acpi_video_init(void) static int __init acpi_video_init(void)
{ {
int result = 0; int result = 0;
......
...@@ -91,13 +91,12 @@ typedef int (*acpi_op_remove) (struct acpi_device * device, int type); ...@@ -91,13 +91,12 @@ typedef int (*acpi_op_remove) (struct acpi_device * device, int type);
typedef int (*acpi_op_lock) (struct acpi_device * device, int type); typedef int (*acpi_op_lock) (struct acpi_device * device, int type);
typedef int (*acpi_op_start) (struct acpi_device * device); typedef int (*acpi_op_start) (struct acpi_device * device);
typedef int (*acpi_op_stop) (struct acpi_device * device, int type); typedef int (*acpi_op_stop) (struct acpi_device * device, int type);
typedef int (*acpi_op_suspend) (struct acpi_device * device, int state); typedef int (*acpi_op_suspend) (struct acpi_device * device, pm_message_t state);
typedef int (*acpi_op_resume) (struct acpi_device * device, int state); typedef int (*acpi_op_resume) (struct acpi_device * device);
typedef int (*acpi_op_scan) (struct acpi_device * device); typedef int (*acpi_op_scan) (struct acpi_device * device);
typedef int (*acpi_op_bind) (struct acpi_device * device); typedef int (*acpi_op_bind) (struct acpi_device * device);
typedef int (*acpi_op_unbind) (struct acpi_device * device); typedef int (*acpi_op_unbind) (struct acpi_device * device);
typedef int (*acpi_op_match) (struct acpi_device * device, typedef int (*acpi_op_shutdown) (struct acpi_device * device);
struct acpi_driver * driver);
struct acpi_bus_ops { struct acpi_bus_ops {
u32 acpi_op_add:1; u32 acpi_op_add:1;
...@@ -110,7 +109,7 @@ struct acpi_bus_ops { ...@@ -110,7 +109,7 @@ struct acpi_bus_ops {
u32 acpi_op_scan:1; u32 acpi_op_scan:1;
u32 acpi_op_bind:1; u32 acpi_op_bind:1;
u32 acpi_op_unbind:1; u32 acpi_op_unbind:1;
u32 acpi_op_match:1; u32 acpi_op_shutdown:1;
u32 reserved:21; u32 reserved:21;
}; };
...@@ -125,16 +124,16 @@ struct acpi_device_ops { ...@@ -125,16 +124,16 @@ struct acpi_device_ops {
acpi_op_scan scan; acpi_op_scan scan;
acpi_op_bind bind; acpi_op_bind bind;
acpi_op_unbind unbind; acpi_op_unbind unbind;
acpi_op_match match; acpi_op_shutdown shutdown;
}; };
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 module *owner;
}; };
/* /*
...@@ -184,7 +183,7 @@ struct acpi_device_dir { ...@@ -184,7 +183,7 @@ struct acpi_device_dir {
typedef char acpi_bus_id[5]; typedef char acpi_bus_id[5];
typedef unsigned long acpi_bus_address; typedef unsigned long acpi_bus_address;
typedef char acpi_hardware_id[9]; typedef char acpi_hardware_id[15];
typedef char acpi_unique_id[9]; typedef char acpi_unique_id[9];
typedef char acpi_device_name[40]; typedef char acpi_device_name[40];
typedef char acpi_device_class[20]; typedef char acpi_device_class[20];
...@@ -295,11 +294,14 @@ struct acpi_device { ...@@ -295,11 +294,14 @@ struct acpi_device {
struct acpi_device_ops ops; struct acpi_device_ops ops;
struct acpi_driver *driver; struct acpi_driver *driver;
void *driver_data; void *driver_data;
struct kobject kobj;
struct device dev; struct device dev;
struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */
enum acpi_bus_removal_type removal_type; /* indicate for different removal type */
}; };
#define acpi_driver_data(d) ((d)->driver_data) #define acpi_driver_data(d) ((d)->driver_data)
#define to_acpi_device(d) container_of(d, struct acpi_device, dev)
#define to_acpi_driver(d) container_of(d, struct acpi_driver, drv)
/* /*
* Events * Events
......
...@@ -36,13 +36,14 @@ ...@@ -36,13 +36,14 @@
/* _HID definitions */ /* _HID definitions */
#define ACPI_POWER_HID "ACPI_PWR" #define ACPI_POWER_HID "power_resource"
#define ACPI_PROCESSOR_HID "ACPI0007" #define ACPI_PROCESSOR_HID "ACPI0007"
#define ACPI_SYSTEM_HID "ACPI_SYS" #define ACPI_SYSTEM_HID "acpi_system"
#define ACPI_THERMAL_HID "ACPI_THM" #define ACPI_THERMAL_HID "thermal"
#define ACPI_BUTTON_HID_POWERF "ACPI_FPB" #define ACPI_BUTTON_HID_POWERF "button_power"
#define ACPI_BUTTON_HID_SLEEPF "ACPI_FSB" #define ACPI_BUTTON_HID_SLEEPF "button_sleep"
#define ACPI_VIDEO_HID "video"
#define ACPI_BAY_HID "bay"
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
PCI PCI
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment