From a7178df5e7e5730e5daa6cf6d8b8bf73adbe75c0 Mon Sep 17 00:00:00 2001 From: Li Shaohua Date: Thu, 7 Dec 2006 20:56:34 +0800 Subject: ACPI: adjust init order Adjust link order to add ACPI devices to global list before PCI devices. In addition, acpi_bus type must be initialized before any driver loads. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi/Makefile') diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index bce7ca27b42..a7495107057 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 @@ -56,7 +57,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 -- cgit v1.2.3-70-g09d2 From 5eca338fb510af78eee5372ff6a3525768ab913f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 18 Jan 2007 16:44:48 -0700 Subject: ACPI: remove motherboard driver (redundant with PNP system driver) The PNP system board driver (drivers/pnp/system.c) contains all the same functionality, so we don't need the ACPI version. Previously, a motherboard device would be claimed by *both* the ACPI and PNP drivers, resulting in stuff like this in /proc/ioports: 1200-121f : motherboard <-- from drivers/acpi/motherboard.c 1200-121f : pnp 00:0d <-- from drivers/pnp/system.c Make sure to enable CONFIG_PNP (and CONFIG_PNPACPI) to include the PNP system board driver. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/Makefile | 2 +- drivers/acpi/motherboard.c | 131 --------------------------------------------- 2 files changed, 1 insertion(+), 132 deletions(-) delete mode 100644 drivers/acpi/motherboard.c (limited to 'drivers/acpi/Makefile') diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index a7495107057..62b3dd5ce73 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -37,7 +37,7 @@ endif obj-y += sleep/ obj-y += bus.o glue.o -obj-y += scan.o motherboard.o +obj-y += scan.o obj-$(CONFIG_ACPI_AC) += ac.o obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_BUTTON) += button.o diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c deleted file mode 100644 index cddab7b29de..00000000000 --- a/drivers/acpi/motherboard.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -/* Purpose: Prevent PCMCIA cards from using motherboard resources. */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#define _COMPONENT ACPI_SYSTEM_COMPONENT -ACPI_MODULE_NAME("acpi_motherboard") - -/* Dell use PNP0C01 instead of 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 - * the io ports as well - */ -#define IS_RESERVED_ADDR(base, len) \ - (((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \ - && ((base) + (len) > PCIBIOS_MIN_IO)) -/* - * Clearing the flag (IORESOURCE_BUSY) allows drivers to use - * the io ports if they really know they can use it, while - * still preventing hotplug PCI devices from using it. - */ - -/* - * When CONFIG_PNP is enabled, pnp/system.c binds to PNP0C01 - * and PNP0C02, redundant with acpi_reserve_io_ranges(). - * But acpi_reserve_io_ranges() is necessary for !CONFIG_PNP. - */ -static acpi_status acpi_reserve_io_ranges(struct acpi_resource *res, void *data) -{ - struct resource *requested_res = NULL; - - - if (res->type == ACPI_RESOURCE_TYPE_IO) { - struct acpi_resource_io *io_res = &res->data.io; - - if (io_res->minimum != io_res->maximum) - return AE_OK; - if (IS_RESERVED_ADDR - (io_res->minimum, io_res->address_length)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Motherboard resources 0x%08x - 0x%08x\n", - io_res->minimum, - io_res->minimum + - io_res->address_length)); - requested_res = - request_region(io_res->minimum, - io_res->address_length, "motherboard"); - } - } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_IO) { - struct acpi_resource_fixed_io *fixed_io_res = - &res->data.fixed_io; - - if (IS_RESERVED_ADDR - (fixed_io_res->address, fixed_io_res->address_length)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Motherboard resources 0x%08x - 0x%08x\n", - fixed_io_res->address, - fixed_io_res->address + - fixed_io_res->address_length)); - requested_res = - request_region(fixed_io_res->address, - fixed_io_res->address_length, - "motherboard"); - } - } else { - /* Memory mapped IO? */ - } - - if (requested_res) - requested_res->flags &= ~IORESOURCE_BUSY; - return AE_OK; -} - -static int acpi_motherboard_add(struct acpi_device *device) -{ - if (!device) - return -EINVAL; - acpi_walk_resources(device->handle, METHOD_NAME__CRS, - acpi_reserve_io_ranges, NULL); - - return 0; -} - -static struct acpi_driver acpi_motherboard_driver = { - .name = "motherboard", - .class = "", - .ids = ACPI_MB_HID, - .ops = { - .add = acpi_motherboard_add, - }, -}; - -static int __init acpi_motherboard_init(void) -{ - acpi_bus_register_driver(&acpi_motherboard_driver); - return 0; -} - -/** - * Reserve motherboard resources after PCI claim BARs, - * but before PCI assign resources for uninitialized PCI devices - */ -fs_initcall(acpi_motherboard_init); -- cgit v1.2.3-70-g09d2 From 01b57e73728880b787c85e27ad06c249412813b1 Mon Sep 17 00:00:00 2001 From: Kristen Carlson Accardi Date: Fri, 20 Oct 2006 14:30:25 -0700 Subject: ACPI: bay: new driver adding removable drive bay support Signed-off-by: Kristen Carlson Accardi Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 7 + drivers/acpi/Makefile | 3 +- drivers/acpi/bay.c | 592 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 601 insertions(+), 1 deletion(-) create mode 100644 drivers/acpi/bay.c (limited to 'drivers/acpi/Makefile') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index f4f000abc4e..2caef098379 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -139,6 +139,13 @@ config ACPI_DOCK help This driver adds support for ACPI controlled docking stations +config ACPI_BAY + tristate "Removable Drive Bay" + depends on EXPERIMENTAL + help + This driver adds support for ACPI controlled removable drive + bays such as the IBM ultrabay or the Dell Module Bay. + config ACPI_PROCESSOR tristate "Processor" default y diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index bce7ca27b42..1a738056558 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -43,7 +43,8 @@ obj-$(CONFIG_ACPI_BUTTON) += button.o obj-$(CONFIG_ACPI_EC) += ec.o obj-$(CONFIG_ACPI_FAN) += fan.o obj-$(CONFIG_ACPI_DOCK) += dock.o -obj-$(CONFIG_ACPI_VIDEO) += video.o +obj-$(CONFIG_ACPI_BAY) += bay.o +obj-$(CONFIG_ACPI_VIDEO) += video.o obj-$(CONFIG_ACPI_HOTKEY) += hotkey.o obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o obj-$(CONFIG_ACPI_POWER) += power.o diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c new file mode 100644 index 00000000000..1cfc0b74b58 --- /dev/null +++ b/drivers/acpi/bay.c @@ -0,0 +1,592 @@ +/* + * bay.c - ACPI removable drive bay driver + * + * Copyright (C) 2006 Kristen Carlson Accardi + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ACPI_BAY_DRIVER_NAME "ACPI Removable Drive Bay Driver" + +ACPI_MODULE_NAME("bay") +MODULE_AUTHOR("Kristen Carlson Accardi"); +MODULE_DESCRIPTION(ACPI_BAY_DRIVER_NAME); +MODULE_LICENSE("GPL"); +#define ACPI_BAY_CLASS "bay" +#define ACPI_BAY_COMPONENT 0x10000000 +#define _COMPONENT ACPI_BAY_COMPONENT +#define bay_dprintk(h,s) {\ + char prefix[80] = {'\0'};\ + struct acpi_buffer buffer = {sizeof(prefix), prefix};\ + acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\ + printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); } + +static void bay_notify(acpi_handle handle, u32 event, void *data); +static int acpi_bay_add(struct acpi_device *device); +static int acpi_bay_remove(struct acpi_device *device, int type); +static int acpi_bay_match(struct acpi_device *device, + struct acpi_driver *driver); + +static struct acpi_driver acpi_bay_driver = { + .name = ACPI_BAY_DRIVER_NAME, + .class = ACPI_BAY_CLASS, + .ops = { + .add = acpi_bay_add, + .remove = acpi_bay_remove, + .match = acpi_bay_match, + }, +}; + +struct bay { + acpi_handle handle; + char *name; + struct list_head list; + struct proc_dir_entry *proc; +}; + +LIST_HEAD(drive_bays); + +static struct proc_dir_entry *acpi_bay_dir; + +/***************************************************************************** + * Drive Bay functions * + *****************************************************************************/ +/** + * is_ejectable - see if a device is ejectable + * @handle: acpi handle of the device + * + * If an acpi object has a _EJ0 method, then it is ejectable + */ +static int is_ejectable(acpi_handle handle) +{ + acpi_status status; + acpi_handle tmp; + + status = acpi_get_handle(handle, "_EJ0", &tmp); + if (ACPI_FAILURE(status)) + return 0; + return 1; +} + +/** + * bay_present - see if the bay device is present + * @bay: the drive bay + * + * execute the _STA method. + */ +static int bay_present(struct bay *bay) +{ + unsigned long sta; + acpi_status status; + + if (bay) { + status = acpi_evaluate_integer(bay->handle, "_STA", NULL, &sta); + if (ACPI_SUCCESS(status) && sta) + return 1; + } + return 0; +} + +/** + * eject_device - respond to an eject request + * @handle - the device to eject + * + * Call this devices _EJ0 method. + */ +static void eject_device(acpi_handle handle) +{ + struct acpi_object_list arg_list; + union acpi_object arg; + + bay_dprintk(handle, "Ejecting device"); + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = 1; + + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0", + &arg_list, NULL))) + pr_debug("Failed to evaluate _EJ0!\n"); +} + + +/** + * is_ata - see if a device is an ata device + * @handle: acpi handle of the device + * + * If an acpi object has one of 4 ATA ACPI methods defined, + * then it is an ATA device + */ +static int is_ata(acpi_handle handle) +{ + acpi_handle tmp; + + if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) || + (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) || + (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) || + (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp)))) + return 1; + + return 0; +} + +/** + * parent_is_ata(acpi_handle handle) + * + */ +static int parent_is_ata(acpi_handle handle) +{ + acpi_handle phandle; + + if (acpi_get_parent(handle, &phandle)) + return 0; + + return is_ata(phandle); +} + +/** + * is_ejectable_bay - see if a device is an ejectable drive bay + * @handle: acpi handle of the device + * + * If an acpi object is ejectable and has one of the ACPI ATA + * methods defined, then we can safely call it an ejectable + * drive bay + */ +static int is_ejectable_bay(acpi_handle handle) +{ + if ((is_ata(handle) || parent_is_ata(handle)) && is_ejectable(handle)) + return 1; + return 0; +} + +/** + * eject_removable_drive - try to eject this drive + * @dev : the device structure of the drive + * + * If a device is a removable drive that requires an _EJ0 method + * to be executed in order to safely remove from the system, do + * it. ATM - always returns success + */ +int eject_removable_drive(struct device *dev) +{ + acpi_handle handle = DEVICE_ACPI_HANDLE(dev); + + if (handle) { + bay_dprintk(handle, "Got device handle"); + if (is_ejectable_bay(handle)) + eject_device(handle); + } else { + printk("No acpi handle for device\n"); + } + + /* should I return an error code? */ + return 0; +} +EXPORT_SYMBOL_GPL(eject_removable_drive); + +static int acpi_bay_add(struct acpi_device *device) +{ + bay_dprintk(device->handle, "adding bay device"); + strcpy(acpi_device_name(device), "Dockable Bay"); + strcpy(acpi_device_class(device), "bay"); + return 0; +} + +static int acpi_bay_status_seq_show(struct seq_file *seq, void *offset) +{ + struct bay *bay = (struct bay *)seq->private; + + if (!bay) + return 0; + + if (bay_present(bay)) + seq_printf(seq, "present\n"); + else + seq_printf(seq, "removed\n"); + + return 0; +} + +static ssize_t +acpi_bay_write_eject(struct file *file, + const char __user * buffer, + size_t count, loff_t * data) +{ + struct seq_file *m = (struct seq_file *)file->private_data; + struct bay *bay = (struct bay *)m->private; + char str[12] = { 0 }; + u32 state = 0; + + /* FIXME - our only valid value here is 1 */ + if (!bay || count + 1 > sizeof str) + return -EINVAL; + + if (copy_from_user(str, buffer, count)) + return -EFAULT; + + str[count] = 0; + state = simple_strtoul(str, NULL, 0); + if (state) + eject_device(bay->handle); + + return count; +} + +static int +acpi_bay_status_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_bay_status_seq_show, + PDE(inode)->data); +} + +static int +acpi_bay_eject_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_bay_status_seq_show, + PDE(inode)->data); +} + +static struct file_operations acpi_bay_status_fops = { + .open = acpi_bay_status_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations acpi_bay_eject_fops = { + .open = acpi_bay_eject_open_fs, + .read = seq_read, + .write = acpi_bay_write_eject, + .llseek = seq_lseek, + .release = single_release, +}; +#if 0 +static struct file_operations acpi_bay_insert_fops = { + .open = acpi_bay_insert_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif +static int acpi_bay_add_fs(struct bay *bay) +{ + struct proc_dir_entry *entry = NULL; + + if (!bay) + return -EINVAL; + + /* + * create a proc entry for this device + * we need to do this a little bit differently than normal + * acpi device drivers because our device may not be present + * at the moment, and therefore we have no acpi_device struct + */ + + bay->proc = proc_mkdir(bay->name, acpi_bay_dir); + + /* 'status' [R] */ + entry = create_proc_entry("status", + S_IRUGO, bay->proc); + if (!entry) + return -EIO; + else { + entry->proc_fops = &acpi_bay_status_fops; + entry->data = bay; + entry->owner = THIS_MODULE; + } + /* 'eject' [W] */ + entry = create_proc_entry("eject", + S_IWUGO, bay->proc); + if (!entry) + return -EIO; + else { + entry->proc_fops = &acpi_bay_eject_fops; + entry->data = bay; + entry->owner = THIS_MODULE; + } +#if 0 + /* 'insert' [W] */ + entry = create_proc_entry("insert", + S_IWUGO, bay->proc); + if (!entry) + return -EIO; + else { + entry->proc_fops = &acpi_bay_insert_fops; + entry->data = bay; + entry->owner = THIS_MODULE; + } +#endif + return 0; +} + +static void acpi_bay_remove_fs(struct bay *bay) +{ + if (!bay) + return; + + if (bay->proc) { + remove_proc_entry("status", bay->proc); + remove_proc_entry("eject", bay->proc); +#if 0 + remove_proc_entry("insert", bay->proc); +#endif + remove_proc_entry(bay->name, acpi_bay_dir); + bay->proc = NULL; + } +} + +static int bay_is_dock_device(acpi_handle handle) +{ + acpi_handle parent; + + acpi_get_parent(handle, &parent); + + /* if the device or it's parent is dependent on the + * dock, then we are a dock device + */ + return (is_dock_device(handle) || is_dock_device(parent)); +} + +static int bay_add(acpi_handle handle) +{ + acpi_status status; + struct bay *new_bay; + struct acpi_buffer nbuffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_get_name(handle, ACPI_FULL_PATHNAME, &nbuffer); + + bay_dprintk(handle, "Adding notify handler"); + + /* + * if this is the first bay device found, make the root + * proc entry + */ + if (acpi_bay_dir == NULL) + acpi_bay_dir = proc_mkdir(ACPI_BAY_CLASS, acpi_root_dir); + + /* + * Initialize bay device structure + */ + new_bay = kmalloc(GFP_ATOMIC, sizeof(*new_bay)); + INIT_LIST_HEAD(&new_bay->list); + new_bay->handle = handle; + new_bay->name = (char *)nbuffer.pointer; + list_add(&new_bay->list, &drive_bays); + acpi_bay_add_fs(new_bay); + + /* register for events on this device */ + status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + bay_notify, new_bay); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Error installing bay notify handler\n"); + } + + /* if we are on a dock station, we should register for dock + * notifications. + */ + if (bay_is_dock_device(handle)) { + bay_dprintk(handle, "Is dependent on dock\n"); + register_hotplug_dock_device(handle, bay_notify, new_bay); + } + printk(KERN_INFO PREFIX "Bay [%s] Added\n", new_bay->name); + return 0; +} + +static int acpi_bay_remove(struct acpi_device *device, int type) +{ + /*** FIXME: do something here */ + return 0; +} + +static int acpi_bay_match(struct acpi_device *device, + struct acpi_driver *driver) +{ + if (!device || !driver) + return -EINVAL; + + if (is_ejectable_bay(device->handle)) { + bay_dprintk(device->handle, "matching bay device"); + return 0; + } + + return -ENODEV; +} + +/** + * bay_create_acpi_device - add new devices to acpi + * @handle - handle of the device to add + * + * This function will create a new acpi_device for the given + * handle if one does not exist already. This should cause + * acpi to scan for drivers for the given devices, and call + * matching driver's add routine. + * + * Returns a pointer to the acpi_device corresponding to the handle. + */ +static struct acpi_device * bay_create_acpi_device(acpi_handle handle) +{ + struct acpi_device *device = NULL; + struct acpi_device *parent_device; + acpi_handle parent; + int ret; + + bay_dprintk(handle, "Trying to get device"); + if (acpi_bus_get_device(handle, &device)) { + /* + * no device created for this object, + * so we should create one. + */ + bay_dprintk(handle, "No device for handle"); + acpi_get_parent(handle, &parent); + if (acpi_bus_get_device(parent, &parent_device)) + parent_device = NULL; + + ret = acpi_bus_add(&device, parent_device, handle, + ACPI_BUS_TYPE_DEVICE); + if (ret) { + pr_debug("error adding bus, %x\n", + -ret); + return NULL; + } + } + return device; +} + +/** + * bay_notify - act upon an acpi bay notification + * @handle: the bay handle + * @event: the acpi event + * @data: our driver data struct + * + */ +static void bay_notify(acpi_handle handle, u32 event, void *data) +{ + struct acpi_device *dev; + struct bay *bay = data; + + bay_dprintk(handle, "Bay event"); + + switch(event) { + case ACPI_NOTIFY_BUS_CHECK: + printk("Bus Check\n"); + case ACPI_NOTIFY_DEVICE_CHECK: + printk("Device Check\n"); + dev = bay_create_acpi_device(handle); + if (dev) + acpi_bus_generate_event(dev, event, 0); + else + printk("No device for generating event\n"); + /* wouldn't it be a good idea to just rescan SATA + * right here? + */ + break; + case ACPI_NOTIFY_EJECT_REQUEST: + printk("Eject request\n"); + dev = bay_create_acpi_device(handle); + if (dev) + acpi_bus_generate_event(dev, event, 0); + else + printk("No device for generating eventn"); + + /* wouldn't it be a good idea to just call the + * eject_device here if we were a SATA device? + */ + break; + default: + printk("unknown event %d\n", event); + } +} + +static acpi_status +find_bay(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + int *count = (int *)context; + + /* + * there could be more than one ejectable bay. + * so, just return AE_OK always so that every object + * will be checked. + */ + if (is_ejectable_bay(handle)) { + bay_dprintk(handle, "found ejectable bay"); + bay_add(handle); + (*count)++; + } + return AE_OK; +} + +static int __init bay_init(void) +{ + int bays = 0; + + acpi_bay_dir = NULL; + INIT_LIST_HEAD(&drive_bays); + + /* look for dockable drive bays */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_bay, &bays, NULL); + + if (bays) { + if ((acpi_bus_register_driver(&acpi_bay_driver) < 0)) { + printk(KERN_ERR "Unable to register bay driver\n"); + if (acpi_bay_dir) + remove_proc_entry(ACPI_BAY_CLASS, + acpi_root_dir); + } + } + + if (!bays) + return -ENODEV; + + return 0; +} + +static void __exit bay_exit(void) +{ + struct bay *bay, *tmp; + + list_for_each_entry_safe(bay, tmp, &drive_bays, list) { + if (is_dock_device(bay->handle)) + unregister_hotplug_dock_device(bay->handle); + acpi_bay_remove_fs(bay); + acpi_remove_notify_handler(bay->handle, ACPI_SYSTEM_NOTIFY, + bay_notify); + kfree(bay->name); + kfree(bay); + } + + if (acpi_bay_dir) + remove_proc_entry(ACPI_BAY_CLASS, acpi_root_dir); + + acpi_bus_unregister_driver(&acpi_bay_driver); +} + +postcore_initcall(bay_init); +module_exit(bay_exit); + -- cgit v1.2.3-70-g09d2 From 5ee6edbcde4d3b14e4e03d4b331df1099a34aa8d Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 10 Feb 2007 01:18:25 -0500 Subject: ACPI: hotkey: remove driver, per feature-removal-schedule.txt Signed-off-by: Len Brown --- Documentation/acpi-hotkey.txt | 38 - Documentation/feature-removal-schedule.txt | 23 - drivers/acpi/Kconfig | 9 - drivers/acpi/Makefile | 1 - drivers/acpi/asus_acpi.c | 4 - drivers/acpi/hotkey.c | 1042 ---------------------------- drivers/acpi/ibm_acpi.c | 5 - drivers/acpi/osl.c | 11 - drivers/acpi/toshiba_acpi.c | 4 - drivers/misc/asus-laptop.c | 5 - include/acpi/acpi_drivers.h | 6 - 11 files changed, 1148 deletions(-) delete mode 100644 Documentation/acpi-hotkey.txt delete mode 100644 drivers/acpi/hotkey.c (limited to 'drivers/acpi/Makefile') diff --git a/Documentation/acpi-hotkey.txt b/Documentation/acpi-hotkey.txt deleted file mode 100644 index 38040fa3764..00000000000 --- a/Documentation/acpi-hotkey.txt +++ /dev/null @@ -1,38 +0,0 @@ -driver/acpi/hotkey.c implement: -1. /proc/acpi/hotkey/event_config -(event based hotkey or event config interface): -a. add a event based hotkey(event) : -echo "0:bus::action:method:num:num" > event_config - -b. delete a event based hotkey(event): -echo "1:::::num:num" > event_config - -c. modify a event based hotkey(event): -echo "2:bus::action:method:num:num" > event_config - -2. /proc/acpi/hotkey/poll_config -(polling based hotkey or event config interface): -a.add a polling based hotkey(event) : -echo "0:bus:method:action:method:num" > poll_config -this adding command will create a proc file -/proc/acpi/hotkey/method, which is used to get -result of polling. - -b.delete a polling based hotkey(event): -echo "1:::::num" > event_config - -c.modify a polling based hotkey(event): -echo "2:bus:method:action:method:num" > poll_config - -3./proc/acpi/hotkey/action -(interface to call aml method associated with a -specific hotkey(event)) -echo "event_num:event_type:event_argument" > - /proc/acpi/hotkey/action. -The result of the execution of this aml method is -attached to /proc/acpi/hotkey/poll_method, which is dynamically -created. Please use command "cat /proc/acpi/hotkey/polling_method" -to retrieve it. - -Note: Use cmdline "acpi_generic_hotkey" to over-ride -platform-specific with generic driver. diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index fa844fd7bde..7dec8e0193c 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -246,29 +246,6 @@ Who: Venkatesh Pallipadi --------------------------- -<<<<<<< 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 - ACPI to implement hotkeys. However, hotkeys are not documented - in the ACPI specification, so the drivers used undocumented - vendor-specific hooks and turned out to be more different than - the same. - - Further, the keys and the features supplied by each platform - are different, so there will always be a need for - platform-specific drivers. - - So the new plan is to delete hotkey.c and instead, work on the - platform specific drivers to try to make them look the same - to the user when they supply the same features. - - hotkey.c has always depended on CONFIG_EXPERIMENTAL - -Who: Len Brown - ---------------------------- - What: /sys/firmware/acpi/namespace When: 2.6.21 Why: The ACPI namespace is effectively the symbol list for diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 20eacc2c9e0..4f5bfb1e629 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -132,15 +132,6 @@ config ACPI_VIDEO Note that this is an ref. implementation only. It may or may not work for your integrated video device. -config ACPI_HOTKEY - tristate "Generic Hotkey (EXPERIMENTAL)" - depends on EXPERIMENTAL - depends on X86 - default n - help - Experimental consolidated hotkey driver. - If you are unsure, say N. - config ACPI_FAN tristate "Fan" default y diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 856c32bccac..5956e9f64a8 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -46,7 +46,6 @@ obj-$(CONFIG_ACPI_FAN) += fan.o obj-$(CONFIG_ACPI_DOCK) += dock.o obj-$(CONFIG_ACPI_BAY) += bay.o obj-$(CONFIG_ACPI_VIDEO) += video.o -obj-$(CONFIG_ACPI_HOTKEY) += hotkey.o obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o obj-$(CONFIG_ACPI_POWER) += power.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index 31ad70a6e22..ab8c5cb8384 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -1365,10 +1365,6 @@ static int __init asus_acpi_init(void) if (acpi_disabled) return -ENODEV; - if (!acpi_specific_hotkey_enabled) { - printk(KERN_ERR "Using generic hotkey driver\n"); - return -ENODEV; - } asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir); if (!asus_proc_dir) { printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n"); diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c deleted file mode 100644 index 8edfb92f7ed..00000000000 --- a/drivers/acpi/hotkey.c +++ /dev/null @@ -1,1042 +0,0 @@ -/* - * hotkey.c - ACPI Hotkey Driver ($Revision: 0.2 $) - * - * Copyright (C) 2004 Luming Yu - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define HOTKEY_ACPI_VERSION "0.1" - -#define HOTKEY_PROC "hotkey" -#define HOTKEY_EV_CONFIG "event_config" -#define HOTKEY_PL_CONFIG "poll_config" -#define HOTKEY_ACTION "action" -#define HOTKEY_INFO "info" - -#define ACPI_HOTK_NAME "Generic Hotkey Driver" -#define ACPI_HOTK_CLASS "Hotkey" -#define ACPI_HOTK_DEVICE_NAME "Hotkey" -#define ACPI_HOTK_HID "Unknown?" -#define ACPI_HOTKEY_COMPONENT 0x20000000 - -#define ACPI_HOTKEY_EVENT 0x1 -#define ACPI_HOTKEY_POLLING 0x2 -#define ACPI_UNDEFINED_EVENT 0xf - -#define RESULT_STR_LEN 80 - -#define ACTION_METHOD 0 -#define POLL_METHOD 1 - -#define IS_EVENT(e) ((e) <= 10000 && (e) >0) -#define IS_POLL(e) ((e) > 10000) -#define IS_OTHERS(e) ((e)<=0 || (e)>=20000) -#define _COMPONENT ACPI_HOTKEY_COMPONENT -ACPI_MODULE_NAME("acpi_hotkey") - - MODULE_AUTHOR("luming.yu@intel.com"); -MODULE_DESCRIPTION(ACPI_HOTK_NAME); -MODULE_LICENSE("GPL"); - -/* standardized internal hotkey number/event */ -enum { - /* Video Extension event */ - HK_EVENT_CYCLE_OUTPUT_DEVICE = 0x80, - HK_EVENT_OUTPUT_DEVICE_STATUS_CHANGE, - HK_EVENT_CYCLE_DISPLAY_OUTPUT, - HK_EVENT_NEXT_DISPLAY_OUTPUT, - HK_EVENT_PREVIOUS_DISPLAY_OUTPUT, - HK_EVENT_CYCLE_BRIGHTNESS, - HK_EVENT_INCREASE_BRIGHTNESS, - HK_EVENT_DECREASE_BRIGHTNESS, - HK_EVENT_ZERO_BRIGHTNESS, - HK_EVENT_DISPLAY_DEVICE_OFF, - - /* Snd Card event */ - HK_EVENT_VOLUME_MUTE, - HK_EVENT_VOLUME_INCLREASE, - HK_EVENT_VOLUME_DECREASE, - - /* running state control */ - HK_EVENT_ENTERRING_S3, - HK_EVENT_ENTERRING_S4, - HK_EVENT_ENTERRING_S5, -}; - -enum conf_entry_enum { - bus_handle = 0, - bus_method = 1, - action_handle = 2, - method = 3, - LAST_CONF_ENTRY -}; - -/* procdir we use */ -static struct proc_dir_entry *hotkey_proc_dir; -static struct proc_dir_entry *hotkey_config; -static struct proc_dir_entry *hotkey_poll_config; -static struct proc_dir_entry *hotkey_action; -static struct proc_dir_entry *hotkey_info; - -/* linkage for all type of hotkey */ -struct acpi_hotkey_link { - struct list_head entries; - int hotkey_type; /* event or polling based hotkey */ - int hotkey_standard_num; /* standardized hotkey(event) number */ -}; - -/* event based hotkey */ -struct acpi_event_hotkey { - struct acpi_hotkey_link hotkey_link; - int flag; - acpi_handle bus_handle; /* bus to install notify handler */ - int external_hotkey_num; /* external hotkey/event number */ - acpi_handle action_handle; /* acpi handle attached aml action method */ - char *action_method; /* action method */ -}; - -/* - * There are two ways to poll status - * 1. directy call read_xxx method, without any arguments passed in - * 2. call write_xxx method, with arguments passed in, you need - * the result is saved in acpi_polling_hotkey.poll_result. - * anthoer read command through polling interface. - * - */ - -/* polling based hotkey */ -struct acpi_polling_hotkey { - struct acpi_hotkey_link hotkey_link; - int flag; - acpi_handle poll_handle; /* acpi handle attached polling method */ - char *poll_method; /* poll method */ - acpi_handle action_handle; /* acpi handle attached action method */ - char *action_method; /* action method */ - union acpi_object *poll_result; /* polling_result */ - struct proc_dir_entry *proc; -}; - -/* hotkey object union */ -union acpi_hotkey { - struct list_head entries; - struct acpi_hotkey_link link; - struct acpi_event_hotkey event_hotkey; - struct acpi_polling_hotkey poll_hotkey; -}; - -/* hotkey object list */ -struct acpi_hotkey_list { - struct list_head *entries; - int count; -}; - -static int auto_hotkey_add(struct acpi_device *device); -static int auto_hotkey_remove(struct acpi_device *device, int type); - -static struct acpi_driver hotkey_driver = { - .name = ACPI_HOTK_NAME, - .class = ACPI_HOTK_CLASS, - .ids = ACPI_HOTK_HID, - .ops = { - .add = auto_hotkey_add, - .remove = auto_hotkey_remove, - }, -}; - -static void free_hotkey_device(union acpi_hotkey *key); -static void free_hotkey_buffer(union acpi_hotkey *key); -static void free_poll_hotkey_buffer(union acpi_hotkey *key); -static int hotkey_open_config(struct inode *inode, struct file *file); -static int hotkey_poll_open_config(struct inode *inode, struct file *file); -static ssize_t hotkey_write_config(struct file *file, - const char __user * buffer, - size_t count, loff_t * data); -static int hotkey_info_open_fs(struct inode *inode, struct file *file); -static int hotkey_action_open_fs(struct inode *inode, struct file *file); -static ssize_t hotkey_execute_aml_method(struct file *file, - const char __user * buffer, - size_t count, loff_t * data); -static int hotkey_config_seq_show(struct seq_file *seq, void *offset); -static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset); -static int hotkey_polling_open_fs(struct inode *inode, struct file *file); -static union acpi_hotkey *get_hotkey_by_event(struct - acpi_hotkey_list - *hotkey_list, int event); - -/* event based config */ -static const struct file_operations hotkey_config_fops = { - .open = hotkey_open_config, - .read = seq_read, - .write = hotkey_write_config, - .llseek = seq_lseek, - .release = single_release, -}; - -/* polling based config */ -static const struct file_operations hotkey_poll_config_fops = { - .open = hotkey_poll_open_config, - .read = seq_read, - .write = hotkey_write_config, - .llseek = seq_lseek, - .release = single_release, -}; - -/* hotkey driver info */ -static const struct file_operations hotkey_info_fops = { - .open = hotkey_info_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* action */ -static const struct file_operations hotkey_action_fops = { - .open = hotkey_action_open_fs, - .read = seq_read, - .write = hotkey_execute_aml_method, - .llseek = seq_lseek, - .release = single_release, -}; - -/* polling results */ -static const struct file_operations hotkey_polling_fops = { - .open = hotkey_polling_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -struct acpi_hotkey_list global_hotkey_list; /* link all ev or pl hotkey */ -struct list_head hotkey_entries; /* head of the list of hotkey_list */ - -static int hotkey_info_seq_show(struct seq_file *seq, void *offset) -{ - - seq_printf(seq, "Hotkey generic driver ver: %s\n", HOTKEY_ACPI_VERSION); - - return 0; -} - -static int hotkey_info_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, hotkey_info_seq_show, PDE(inode)->data); -} - -static char *format_result(union acpi_object *object) -{ - char *buf; - - buf = kzalloc(RESULT_STR_LEN, GFP_KERNEL); - if (!buf) - return NULL; - /* Now, just support integer type */ - if (object->type == ACPI_TYPE_INTEGER) - sprintf(buf, "%d\n", (u32) object->integer.value); - return buf; -} - -static int hotkey_polling_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_polling_hotkey *poll_hotkey = seq->private; - char *buf; - - - if (poll_hotkey->poll_result) { - buf = format_result(poll_hotkey->poll_result); - if (buf) - seq_printf(seq, "%s", buf); - kfree(buf); - } - return 0; -} - -static int hotkey_polling_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, hotkey_polling_seq_show, PDE(inode)->data); -} - -static int hotkey_action_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, hotkey_info_seq_show, PDE(inode)->data); -} - -/* Mapping external hotkey number to standardized hotkey event num */ -static int hotkey_get_internal_event(int event, struct acpi_hotkey_list *list) -{ - struct list_head *entries; - int val = -1; - - - list_for_each(entries, list->entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_type == ACPI_HOTKEY_EVENT - && key->event_hotkey.external_hotkey_num == event) { - val = key->link.hotkey_standard_num; - break; - } - } - - return val; -} - -static void -acpi_hotkey_notify_handler(acpi_handle handle, u32 event, void *data) -{ - struct acpi_device *device = NULL; - u32 internal_event; - - - if (acpi_bus_get_device(handle, &device)) - return; - - internal_event = hotkey_get_internal_event(event, &global_hotkey_list); - acpi_bus_generate_event(device, internal_event, 0); - - return; -} - -/* Need to invent automatically hotkey add method */ -static int auto_hotkey_add(struct acpi_device *device) -{ - /* Implement me */ - return 0; -} - -/* Need to invent automatically hotkey remove method */ -static int auto_hotkey_remove(struct acpi_device *device, int type) -{ - /* Implement me */ - return 0; -} - -/* Create a proc file for each polling method */ -static int create_polling_proc(union acpi_hotkey *device) -{ - struct proc_dir_entry *proc; - char proc_name[80]; - mode_t mode; - - mode = S_IFREG | S_IRUGO | S_IWUGO; - - sprintf(proc_name, "%d", device->link.hotkey_standard_num); - /* - strcat(proc_name, device->poll_hotkey.poll_method); - */ - proc = create_proc_entry(proc_name, mode, hotkey_proc_dir); - - if (!proc) { - return -ENODEV; - } else { - proc->proc_fops = &hotkey_polling_fops; - proc->owner = THIS_MODULE; - proc->data = device; - proc->uid = 0; - proc->gid = 0; - device->poll_hotkey.proc = proc; - } - return 0; -} - -static int hotkey_add(union acpi_hotkey *device) -{ - int status = 0; - struct acpi_device *dev = NULL; - - - if (device->link.hotkey_type == ACPI_HOTKEY_EVENT) { - acpi_bus_get_device(device->event_hotkey.bus_handle, &dev); - status = acpi_install_notify_handler(dev->handle, - ACPI_DEVICE_NOTIFY, - acpi_hotkey_notify_handler, - dev); - } else /* Add polling hotkey */ - create_polling_proc(device); - - global_hotkey_list.count++; - - list_add_tail(&device->link.entries, global_hotkey_list.entries); - - return status; -} - -static int hotkey_remove(union acpi_hotkey *device) -{ - struct list_head *entries, *next; - - - list_for_each_safe(entries, next, global_hotkey_list.entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_standard_num == - device->link.hotkey_standard_num) { - list_del(&key->link.entries); - free_hotkey_device(key); - global_hotkey_list.count--; - break; - } - } - kfree(device); - return 0; -} - -static int hotkey_update(union acpi_hotkey *key) -{ - struct list_head *entries; - - - list_for_each(entries, global_hotkey_list.entries) { - union acpi_hotkey *tmp = - container_of(entries, union acpi_hotkey, entries); - if (tmp->link.hotkey_standard_num == - key->link.hotkey_standard_num) { - if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { - free_hotkey_buffer(tmp); - tmp->event_hotkey.bus_handle = - key->event_hotkey.bus_handle; - tmp->event_hotkey.external_hotkey_num = - key->event_hotkey.external_hotkey_num; - tmp->event_hotkey.action_handle = - key->event_hotkey.action_handle; - tmp->event_hotkey.action_method = - key->event_hotkey.action_method; - kfree(key); - } else { - /* - char proc_name[80]; - - sprintf(proc_name, "%d", tmp->link.hotkey_standard_num); - strcat(proc_name, tmp->poll_hotkey.poll_method); - remove_proc_entry(proc_name,hotkey_proc_dir); - */ - free_poll_hotkey_buffer(tmp); - tmp->poll_hotkey.poll_handle = - key->poll_hotkey.poll_handle; - tmp->poll_hotkey.poll_method = - key->poll_hotkey.poll_method; - tmp->poll_hotkey.action_handle = - key->poll_hotkey.action_handle; - tmp->poll_hotkey.action_method = - key->poll_hotkey.action_method; - tmp->poll_hotkey.poll_result = - key->poll_hotkey.poll_result; - /* - create_polling_proc(tmp); - */ - kfree(key); - } - return 0; - break; - } - } - - return -ENODEV; -} - -static void free_hotkey_device(union acpi_hotkey *key) -{ - struct acpi_device *dev; - - - if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { - acpi_bus_get_device(key->event_hotkey.bus_handle, &dev); - if (dev->handle) - acpi_remove_notify_handler(dev->handle, - ACPI_DEVICE_NOTIFY, - acpi_hotkey_notify_handler); - free_hotkey_buffer(key); - } else { - char proc_name[80]; - - sprintf(proc_name, "%d", key->link.hotkey_standard_num); - /* - strcat(proc_name, key->poll_hotkey.poll_method); - */ - remove_proc_entry(proc_name, hotkey_proc_dir); - free_poll_hotkey_buffer(key); - } - kfree(key); - return; -} - -static void free_hotkey_buffer(union acpi_hotkey *key) -{ - /* key would never be null, action method could be */ - kfree(key->event_hotkey.action_method); -} - -static void free_poll_hotkey_buffer(union acpi_hotkey *key) -{ - /* key would never be null, others could be*/ - kfree(key->poll_hotkey.action_method); - kfree(key->poll_hotkey.poll_method); - kfree(key->poll_hotkey.poll_result); -} -static int -init_hotkey_device(union acpi_hotkey *key, char **config_entry, - int std_num, int external_num) -{ - acpi_handle tmp_handle; - acpi_status status = AE_OK; - - if (std_num < 0 || IS_POLL(std_num) || !key) - goto do_fail; - - if (!config_entry[bus_handle] || !config_entry[action_handle] - || !config_entry[method]) - goto do_fail; - - key->link.hotkey_type = ACPI_HOTKEY_EVENT; - key->link.hotkey_standard_num = std_num; - key->event_hotkey.flag = 0; - key->event_hotkey.action_method = config_entry[method]; - - status = acpi_get_handle(NULL, config_entry[bus_handle], - &(key->event_hotkey.bus_handle)); - if (ACPI_FAILURE(status)) - goto do_fail_zero; - key->event_hotkey.external_hotkey_num = external_num; - status = acpi_get_handle(NULL, config_entry[action_handle], - &(key->event_hotkey.action_handle)); - if (ACPI_FAILURE(status)) - goto do_fail_zero; - status = acpi_get_handle(key->event_hotkey.action_handle, - config_entry[method], &tmp_handle); - if (ACPI_FAILURE(status)) - goto do_fail_zero; - return AE_OK; -do_fail_zero: - key->event_hotkey.action_method = NULL; -do_fail: - return -ENODEV; -} - -static int -init_poll_hotkey_device(union acpi_hotkey *key, char **config_entry, - int std_num) -{ - acpi_status status = AE_OK; - acpi_handle tmp_handle; - - if (std_num < 0 || IS_EVENT(std_num) || !key) - goto do_fail; - if (!config_entry[bus_handle] ||!config_entry[bus_method] || - !config_entry[action_handle] || !config_entry[method]) - goto do_fail; - - key->link.hotkey_type = ACPI_HOTKEY_POLLING; - key->link.hotkey_standard_num = std_num; - key->poll_hotkey.flag = 0; - key->poll_hotkey.poll_method = config_entry[bus_method]; - key->poll_hotkey.action_method = config_entry[method]; - - status = acpi_get_handle(NULL, config_entry[bus_handle], - &(key->poll_hotkey.poll_handle)); - if (ACPI_FAILURE(status)) - goto do_fail_zero; - status = acpi_get_handle(key->poll_hotkey.poll_handle, - config_entry[bus_method], &tmp_handle); - if (ACPI_FAILURE(status)) - goto do_fail_zero; - status = - acpi_get_handle(NULL, config_entry[action_handle], - &(key->poll_hotkey.action_handle)); - if (ACPI_FAILURE(status)) - goto do_fail_zero; - status = acpi_get_handle(key->poll_hotkey.action_handle, - config_entry[method], &tmp_handle); - if (ACPI_FAILURE(status)) - goto do_fail_zero; - key->poll_hotkey.poll_result = - kmalloc(sizeof(union acpi_object), GFP_KERNEL); - if (!key->poll_hotkey.poll_result) - goto do_fail_zero; - return AE_OK; - -do_fail_zero: - key->poll_hotkey.poll_method = NULL; - key->poll_hotkey.action_method = NULL; -do_fail: - return -ENODEV; -} - -static int hotkey_open_config(struct inode *inode, struct file *file) -{ - return (single_open - (file, hotkey_config_seq_show, PDE(inode)->data)); -} - -static int hotkey_poll_open_config(struct inode *inode, struct file *file) -{ - return (single_open - (file, hotkey_poll_config_seq_show, PDE(inode)->data)); -} - -static int hotkey_config_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; - struct list_head *entries; - char bus_name[ACPI_PATHNAME_MAX] = { 0 }; - char action_name[ACPI_PATHNAME_MAX] = { 0 }; - struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name }; - struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name }; - - - list_for_each(entries, hotkey_list->entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { - acpi_get_name(key->event_hotkey.bus_handle, - ACPI_NAME_TYPE_MAX, &bus); - acpi_get_name(key->event_hotkey.action_handle, - ACPI_NAME_TYPE_MAX, &act); - seq_printf(seq, "%s:%s:%s:%d:%d\n", bus_name, - action_name, - key->event_hotkey.action_method, - key->link.hotkey_standard_num, - key->event_hotkey.external_hotkey_num); - } - } - seq_puts(seq, "\n"); - return 0; -} - -static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; - struct list_head *entries; - char bus_name[ACPI_PATHNAME_MAX] = { 0 }; - char action_name[ACPI_PATHNAME_MAX] = { 0 }; - struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name }; - struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name }; - - - list_for_each(entries, hotkey_list->entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_type == ACPI_HOTKEY_POLLING) { - acpi_get_name(key->poll_hotkey.poll_handle, - ACPI_NAME_TYPE_MAX, &bus); - acpi_get_name(key->poll_hotkey.action_handle, - ACPI_NAME_TYPE_MAX, &act); - seq_printf(seq, "%s:%s:%s:%s:%d\n", bus_name, - key->poll_hotkey.poll_method, - action_name, - key->poll_hotkey.action_method, - key->link.hotkey_standard_num); - } - } - seq_puts(seq, "\n"); - return 0; -} - -static int -get_parms(char *config_record, int *cmd, char **config_entry, - int *internal_event_num, int *external_event_num) -{ -/* the format of *config_record = - * "1:\d+:*" : "cmd:internal_event_num" - * "\d+:\w+:\w+:\w+:\w+:\d+:\d+" : - * "cmd:bus_handle:bus_method:action_handle:method:internal_event_num:external_event_num" - */ - char *tmp, *tmp1, count; - int i; - - sscanf(config_record, "%d", cmd); - if (*cmd == 1) { - if (sscanf(config_record, "%d:%d", cmd, internal_event_num) != - 2) - goto do_fail; - else - return (6); - } - tmp = strchr(config_record, ':'); - if (!tmp) - goto do_fail; - tmp++; - for (i = 0; i < LAST_CONF_ENTRY; i++) { - tmp1 = strchr(tmp, ':'); - if (!tmp1) { - goto do_fail; - } - count = tmp1 - tmp; - config_entry[i] = kzalloc(count + 1, GFP_KERNEL); - if (!config_entry[i]) - goto handle_failure; - strncpy(config_entry[i], tmp, count); - tmp = tmp1 + 1; - } - if (sscanf(tmp, "%d:%d", internal_event_num, external_event_num) <= 0) - goto handle_failure; - if (!IS_OTHERS(*internal_event_num)) { - return 6; - } -handle_failure: - while (i-- > 0) - kfree(config_entry[i]); -do_fail: - return -1; -} - -/* count is length for one input record */ -static ssize_t hotkey_write_config(struct file *file, - const char __user * buffer, - size_t count, loff_t * data) -{ - char *config_record = NULL; - char *config_entry[LAST_CONF_ENTRY]; - int cmd, internal_event_num, external_event_num; - int ret = 0; - union acpi_hotkey *key = kzalloc(sizeof(union acpi_hotkey), GFP_KERNEL); - - if (!key) - return -ENOMEM; - - config_record = kzalloc(count + 1, GFP_KERNEL); - if (!config_record) { - kfree(key); - return -ENOMEM; - } - - if (copy_from_user(config_record, buffer, count)) { - kfree(config_record); - kfree(key); - printk(KERN_ERR PREFIX "Invalid data\n"); - return -EINVAL; - } - ret = get_parms(config_record, &cmd, config_entry, - &internal_event_num, &external_event_num); - kfree(config_record); - if (ret != 6) { - printk(KERN_ERR PREFIX "Invalid data format ret=%d\n", ret); - return -EINVAL; - } - - if (cmd == 1) { - union acpi_hotkey *tmp = NULL; - tmp = get_hotkey_by_event(&global_hotkey_list, - internal_event_num); - if (!tmp) - printk(KERN_ERR PREFIX "Invalid key\n"); - else - memcpy(key, tmp, sizeof(union acpi_hotkey)); - goto cont_cmd; - } - if (IS_EVENT(internal_event_num)) { - if (init_hotkey_device(key, config_entry, - internal_event_num, external_event_num)) - goto init_hotkey_fail; - } else { - if (init_poll_hotkey_device(key, config_entry, - internal_event_num)) - goto init_poll_hotkey_fail; - } -cont_cmd: - switch (cmd) { - case 0: - if (get_hotkey_by_event(&global_hotkey_list, - key->link.hotkey_standard_num)) - goto fail_out; - else - hotkey_add(key); - break; - case 1: - hotkey_remove(key); - break; - case 2: - /* key is kfree()ed if matched*/ - if (hotkey_update(key)) - goto fail_out; - break; - default: - goto fail_out; - break; - } - return count; - -init_poll_hotkey_fail: /* failed init_poll_hotkey_device */ - kfree(config_entry[bus_method]); - config_entry[bus_method] = NULL; -init_hotkey_fail: /* failed init_hotkey_device */ - kfree(config_entry[method]); -fail_out: - kfree(config_entry[bus_handle]); - kfree(config_entry[action_handle]); - /* No double free since elements =NULL for error cases */ - if (IS_EVENT(internal_event_num)) { - if (config_entry[bus_method]) - kfree(config_entry[bus_method]); - free_hotkey_buffer(key); /* frees [method] */ - } else - free_poll_hotkey_buffer(key); /* frees [bus_method]+[method] */ - kfree(key); - printk(KERN_ERR PREFIX "invalid key\n"); - return -EINVAL; -} - -/* - * This function evaluates an ACPI method, given an int as parameter, the - * method is searched within the scope of the handle, can be NULL. The output - * of the method is written is output, which can also be NULL - * - * returns 1 if write is successful, 0 else. - */ -static int write_acpi_int(acpi_handle handle, const char *method, int val, - struct acpi_buffer *output) -{ - struct acpi_object_list params; /* list of input parameters (an int here) */ - union acpi_object in_obj; /* the only param we use */ - acpi_status status; - - params.count = 1; - params.pointer = &in_obj; - in_obj.type = ACPI_TYPE_INTEGER; - in_obj.integer.value = val; - - status = acpi_evaluate_object(handle, (char *)method, ¶ms, output); - - return (status == AE_OK); -} - -static int read_acpi_int(acpi_handle handle, const char *method, - union acpi_object *val) -{ - struct acpi_buffer output; - union acpi_object out_obj; - acpi_status status; - - output.length = sizeof(out_obj); - output.pointer = &out_obj; - - status = acpi_evaluate_object(handle, (char *)method, NULL, &output); - if (val) { - val->integer.value = out_obj.integer.value; - val->type = out_obj.type; - } else - printk(KERN_ERR PREFIX "null val pointer\n"); - return ((status == AE_OK) - && (out_obj.type == ACPI_TYPE_INTEGER)); -} - -static union acpi_hotkey *get_hotkey_by_event(struct - acpi_hotkey_list - *hotkey_list, int event) -{ - struct list_head *entries; - - list_for_each(entries, hotkey_list->entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_standard_num == event) { - return (key); - } - } - return (NULL); -} - -/* - * user call AML method interface: - * Call convention: - * echo "event_num: arg type : value" - * example: echo "1:1:30" > /proc/acpi/action - * Just support 1 integer arg passing to AML method - */ - -static ssize_t hotkey_execute_aml_method(struct file *file, - const char __user * buffer, - size_t count, loff_t * data) -{ - struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; - char *arg; - int event, method_type, type, value; - union acpi_hotkey *key; - - - arg = kzalloc(count + 1, GFP_KERNEL); - if (!arg) - return -ENOMEM; - - if (copy_from_user(arg, buffer, count)) { - kfree(arg); - printk(KERN_ERR PREFIX "Invalid argument 2\n"); - return -EINVAL; - } - - if (sscanf(arg, "%d:%d:%d:%d", &event, &method_type, &type, &value) != - 4) { - kfree(arg); - printk(KERN_ERR PREFIX "Invalid argument 3\n"); - return -EINVAL; - } - kfree(arg); - if (type == ACPI_TYPE_INTEGER) { - key = get_hotkey_by_event(hotkey_list, event); - if (!key) - goto do_fail; - if (IS_EVENT(event)) - write_acpi_int(key->event_hotkey.action_handle, - key->event_hotkey.action_method, value, - NULL); - else if (IS_POLL(event)) { - if (method_type == POLL_METHOD) - read_acpi_int(key->poll_hotkey.poll_handle, - key->poll_hotkey.poll_method, - key->poll_hotkey.poll_result); - else if (method_type == ACTION_METHOD) - write_acpi_int(key->poll_hotkey.action_handle, - key->poll_hotkey.action_method, - value, NULL); - else - goto do_fail; - - } - } else { - printk(KERN_WARNING "Not supported\n"); - return -EINVAL; - } - return count; - do_fail: - return -EINVAL; - -} - -static int __init hotkey_init(void) -{ - int result; - mode_t mode = S_IFREG | S_IRUGO | S_IWUGO; - - - if (acpi_disabled) - return -ENODEV; - - if (acpi_specific_hotkey_enabled) { - printk("Using specific hotkey driver\n"); - return -ENODEV; - } - - hotkey_proc_dir = proc_mkdir(HOTKEY_PROC, acpi_root_dir); - if (!hotkey_proc_dir) { - return (-ENODEV); - } - hotkey_proc_dir->owner = THIS_MODULE; - - hotkey_config = - create_proc_entry(HOTKEY_EV_CONFIG, mode, hotkey_proc_dir); - if (!hotkey_config) { - goto do_fail1; - } else { - hotkey_config->proc_fops = &hotkey_config_fops; - hotkey_config->data = &global_hotkey_list; - hotkey_config->owner = THIS_MODULE; - hotkey_config->uid = 0; - hotkey_config->gid = 0; - } - - hotkey_poll_config = - create_proc_entry(HOTKEY_PL_CONFIG, mode, hotkey_proc_dir); - if (!hotkey_poll_config) { - goto do_fail2; - } else { - hotkey_poll_config->proc_fops = &hotkey_poll_config_fops; - hotkey_poll_config->data = &global_hotkey_list; - hotkey_poll_config->owner = THIS_MODULE; - hotkey_poll_config->uid = 0; - hotkey_poll_config->gid = 0; - } - - hotkey_action = create_proc_entry(HOTKEY_ACTION, mode, hotkey_proc_dir); - if (!hotkey_action) { - goto do_fail3; - } else { - hotkey_action->proc_fops = &hotkey_action_fops; - hotkey_action->owner = THIS_MODULE; - hotkey_action->uid = 0; - hotkey_action->gid = 0; - } - - hotkey_info = create_proc_entry(HOTKEY_INFO, mode, hotkey_proc_dir); - if (!hotkey_info) { - goto do_fail4; - } else { - hotkey_info->proc_fops = &hotkey_info_fops; - hotkey_info->owner = THIS_MODULE; - hotkey_info->uid = 0; - hotkey_info->gid = 0; - } - - result = acpi_bus_register_driver(&hotkey_driver); - if (result < 0) - goto do_fail5; - global_hotkey_list.count = 0; - global_hotkey_list.entries = &hotkey_entries; - - INIT_LIST_HEAD(&hotkey_entries); - - return (0); - - do_fail5: - remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir); - do_fail4: - remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir); - do_fail3: - remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir); - do_fail2: - remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir); - do_fail1: - remove_proc_entry(HOTKEY_PROC, acpi_root_dir); - return (-ENODEV); -} - -static void __exit hotkey_exit(void) -{ - struct list_head *entries, *next; - - - list_for_each_safe(entries, next, global_hotkey_list.entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - - acpi_os_wait_events_complete(NULL); - list_del(&key->link.entries); - global_hotkey_list.count--; - free_hotkey_device(key); - } - acpi_bus_unregister_driver(&hotkey_driver); - remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir); - remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir); - remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir); - remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir); - remove_proc_entry(HOTKEY_PROC, acpi_root_dir); - return; -} - -module_init(hotkey_init); -module_exit(hotkey_exit); diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index c6144ca6663..4def52ca69e 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -2696,11 +2696,6 @@ static int __init acpi_ibm_init(void) if (acpi_disabled) return -ENODEV; - if (!acpi_specific_hotkey_enabled) { - printk(IBM_ERR "using generic hotkey driver\n"); - return -ENODEV; - } - /* ec is required because many other handles are relative to it */ IBM_HANDLE_INIT(ec); if (!ec_handle) { diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 0f6f3bcbc8e..368e111100b 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -68,9 +68,6 @@ EXPORT_SYMBOL(acpi_in_debugger); extern char line_buf[80]; #endif /*ENABLE_DEBUGGER */ -int acpi_specific_hotkey_enabled = TRUE; -EXPORT_SYMBOL(acpi_specific_hotkey_enabled); - static unsigned int acpi_irq_irq; static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; @@ -1012,14 +1009,6 @@ static int __init acpi_wake_gpes_always_on_setup(char *str) __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); -static int __init acpi_hotkey_setup(char *str) -{ - acpi_specific_hotkey_enabled = FALSE; - return 1; -} - -__setup("acpi_generic_hotkey", acpi_hotkey_setup); - /* * max_cstate is defined in the base kernel so modules can * change it w/o depending on the state of the processor module. diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index d9b651ffcdc..56ec5503a12 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c @@ -561,10 +561,6 @@ static int __init toshiba_acpi_init(void) if (acpi_disabled) return -ENODEV; - if (!acpi_specific_hotkey_enabled) { - printk(MY_INFO "Using generic hotkey driver\n"); - return -ENODEV; - } /* simple device detection: look for HCI method */ if (is_valid_acpi_path(METHOD_HCI_1)) method_hci = METHOD_HCI_1; diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index 861c39935f9..e4e2b707a35 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c @@ -1088,11 +1088,6 @@ static int __init asus_laptop_init(void) if (acpi_disabled) return -ENODEV; - if (!acpi_specific_hotkey_enabled) { - printk(ASUS_ERR "Using generic hotkey driver\n"); - return -ENODEV; - } - result = acpi_bus_register_driver(&asus_hotk_driver); if (result < 0) return result; diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index 4dc8a5043ef..0e21efb6f64 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -105,12 +105,6 @@ int acpi_ec_ecdt_probe(void); int acpi_processor_set_thermal_limit(acpi_handle handle, int type); -/* -------------------------------------------------------------------------- - Hot Keys - -------------------------------------------------------------------------- */ - -extern int acpi_specific_hotkey_enabled; - /*-------------------------------------------------------------------------- Dock Station -------------------------------------------------------------------------- */ -- cgit v1.2.3-70-g09d2