I know the almost same patch was in -mm (dropped), but this one is given by K.Tokunaga in past. == Provide an emulation environment to generate SCI interrupt on ACPI object. Thanks, Keiichiro Tokunaga Signed-off-by: Keiichiro Tokunaga <tokunaga.keiich at jp.fujitsu.com> Index: linux-2.6.17-rc5-mm2/drivers/acpi/Kconfig =================================================================== --- linux-2.6.17-rc5-mm2.orig/drivers/acpi/Kconfig 2006-06-07 13:47:34.000000000 +0900 +++ linux-2.6.17-rc5-mm2/drivers/acpi/Kconfig 2006-06-07 13:48:04.000000000 +0900 @@ -379,4 +379,15 @@ $>modprobe acpi_memhotplug endif # ACPI +config ACPI_SCI_EMULATE + bool "ACPI SCI Event Emulation Support" + depends on ACPI + depends on !IA64_SGI_SN + default n + help + This driver will enable your system to emulate sci hotplug event + notification through proc file system. For example user needs to + echo "XXX 0" > /proc/acpi/sci/notify (where, XXX is a target ACPI + device object name). + endmenu Index: linux-2.6.17-rc5-mm2/drivers/acpi/bus.c =================================================================== --- linux-2.6.17-rc5-mm2.orig/drivers/acpi/bus.c 2006-06-07 13:47:34.000000000 +0900 +++ linux-2.6.17-rc5-mm2/drivers/acpi/bus.c 2006-06-07 13:48:04.000000000 +0900 @@ -37,6 +37,20 @@ #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> +#ifdef CONFIG_ACPI_SCI_EMULATE +#include <acpi/acpi.h> +#include <acpi/acnamesp.h> +#include <acpi/acevents.h> +#include <acpi/acinterp.h> + +static int acpi_init_sci_emulate(void); +static void acpi_sci_notify_client(char *acpi_name, u32 event); +static int acpi_sci_notify_write_proc(struct file *file, const char *buffer, \ + unsigned long count, void *data); +#else +#define acpi_init_sci_emulate() +#endif + #define _COMPONENT ACPI_BUS_COMPONENT ACPI_MODULE_NAME("acpi_bus") #ifdef CONFIG_X86 @@ -49,6 +63,9 @@ struct acpi_device *acpi_root; struct proc_dir_entry *acpi_root_dir; EXPORT_SYMBOL(acpi_root_dir); +#ifdef CONFIG_ACPI_SCI_EMULATE +struct proc_dir_entry *acpi_sci_dir; +#endif #define STRUCT_TO_INT(s) (*((int*)&s)) @@ -702,6 +719,8 @@ */ acpi_root_dir = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL); + acpi_init_sci_emulate(); + return 0; /* Mimic structured exception handling */ @@ -745,3 +764,125 @@ } subsys_initcall(acpi_init); + +#ifdef CONFIG_ACPI_SCI_EMULATE +/****** Code to emulate SCI interrupt for Hotplug node insertion/removal ******/ + +static int acpi_sci_notify_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + u32 event; + char *name1 = NULL; + char *name2 = NULL; + char *end_name = NULL; + const char *delim = " "; + char *temp_buf = NULL; + char *temp_buf_addr = NULL; + + printk(KERN_INFO PREFIX "Inside acpi_sci_notify_write_proc\n"); + + temp_buf = kmalloc(count+1, GFP_ATOMIC); + if (!temp_buf) { + printk(KERN_WARNING PREFIX "Inside acpi_sci_notify_wire_proc: Memory allocation failed\n"); + return count; + } + temp_buf[count] = '\0'; + temp_buf_addr = temp_buf; + memcpy(temp_buf, buffer, count); + name1 = strsep(&temp_buf, delim); + name2 = strsep(&temp_buf, delim); + + if(name1 && name2) + event = simple_strtoul(name2, &end_name, 10); + else { + printk(KERN_WARNING PREFIX "unknown device\n"); + kfree(temp_buf_addr); + return count; + } + + printk(KERN_INFO PREFIX "ACPI device name is <%s>, event code is <%d>\n",\ + name1, event); + + acpi_sci_notify_client(name1, event); + + kfree(temp_buf_addr); + + return count; +} + +static void acpi_sci_notify_client(char *acpi_name, u32 event) +{ + struct acpi_namespace_node *node; + acpi_status status, status1; + acpi_handle hlsb, hsb; + union acpi_operand_object *obj_desc; + + status = acpi_get_handle(NULL, "\\_SB", &hsb); + status1 = acpi_get_handle(hsb, acpi_name, &hlsb); + if(ACPI_FAILURE(status) || ACPI_FAILURE(status1)){ + printk(KERN_ERR PREFIX "acpi getting handle to <\\_SB.%s> failed inside notify_client\n", \ + acpi_name); + return; + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if(ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Acquiring acpi namespace mutext failed\n"); + return; + } + + node = acpi_ns_map_handle_to_node(hlsb); + if(!node) { + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + printk(KERN_ERR PREFIX "Mapping handle to node failed\n"); + return; + } + + /* Check for internal object and make sure there is a handler registered for this object */ + + obj_desc = acpi_ns_get_attached_object (node); + if(obj_desc) { + if(obj_desc->common_notify.system_notify){ + /* Release the lock and queue the item for later exectuion */ + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ev_queue_notify_request(node, event); + if(ACPI_FAILURE(status)){ + printk(KERN_ERR PREFIX "acpi_ev_queue_notify_request failed\n"); + }else { + printk(KERN_INFO PREFIX "Notify event is queued\n"); + } + return; + } + }else { + printk(KERN_INFO PREFIX "Notify handler not registered for this device\n"); + } + + + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + return; +} + + +static int acpi_init_sci_emulate(void) +{ + struct proc_dir_entry *notify_entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_init_sci_emulate"); + + acpi_sci_dir = proc_mkdir("sci", acpi_root_dir); + if (!acpi_sci_dir) + return_VALUE(-ENODEV); + + notify_entry = create_proc_entry("notify", \ + S_IWUGO|S_IRUGO, acpi_sci_dir); + if (!notify_entry) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", "notify")); + } else { + notify_entry->write_proc = acpi_sci_notify_write_proc; + notify_entry->data = NULL; + } + + return_VALUE(0); +} +#endif