diff options
author | Jesse Keating <jkeating@redhat.com> | 2010-07-29 17:18:45 -0700 |
---|---|---|
committer | Jesse Keating <jkeating@redhat.com> | 2010-07-29 17:18:45 -0700 |
commit | 2f82dda4a9bf41e64e864889bf06564bdf826e25 (patch) | |
tree | 118a7b483ae5de4dbf83d20001302f1404866ef0 /linux-2.6-autoload-wmi.patch | |
parent | 64ba2e5ffde5f2418eb26c700cb0ab62b04e5013 (diff) | |
download | dom0-kernel-2f82dda4a9bf41e64e864889bf06564bdf826e25.tar.gz dom0-kernel-2f82dda4a9bf41e64e864889bf06564bdf826e25.tar.xz dom0-kernel-2f82dda4a9bf41e64e864889bf06564bdf826e25.zip |
initial srpm import
Diffstat (limited to 'linux-2.6-autoload-wmi.patch')
-rw-r--r-- | linux-2.6-autoload-wmi.patch | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/linux-2.6-autoload-wmi.patch b/linux-2.6-autoload-wmi.patch new file mode 100644 index 0000000..f093a40 --- /dev/null +++ b/linux-2.6-autoload-wmi.patch @@ -0,0 +1,244 @@ +From: Matthew Garrett <mjg@redhat.com> +Date: Wed, 4 Nov 2009 19:17:53 +0000 (-0500) +Subject: wmi: Add support for module autoloading +X-Git-Tag: v2.6.33-rc1~47^2~5^2 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=1caab3c1a90be3aa4ec3599409d8fe044b077478 + +wmi: Add support for module autoloading + +WMI provides interface-specific GUIDs that are exported from modules as +modalises, but the core currently generates no events to trigger module +loading. This patch adds support for registering devices for each WMI GUID +and generating the appropriate uevent. + +Based heavily on a patch by Carlos Corbacho (<carlos@strangeworlds.co.uk>). + +Signed-off-by: Matthew Garrett <mjg@redhat.com> +Tested-by: Carlos Corbacho <carlos@strangeworlds.co.uk> +Acked-by: Carlos Corbacho <carlos@strangeworlds.co.uk> +Signed-off-by: Len Brown <len.brown@intel.com> +--- + +diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c +index 177f8d7..e425a86 100644 +--- a/drivers/platform/x86/wmi.c ++++ b/drivers/platform/x86/wmi.c +@@ -30,6 +30,7 @@ + #include <linux/kernel.h> + #include <linux/init.h> + #include <linux/types.h> ++#include <linux/device.h> + #include <linux/list.h> + #include <linux/acpi.h> + #include <acpi/acpi_bus.h> +@@ -65,6 +66,7 @@ struct wmi_block { + acpi_handle handle; + wmi_notify_handler handler; + void *handler_data; ++ struct device *dev; + }; + + static struct wmi_block wmi_blocks; +@@ -195,6 +197,34 @@ static bool wmi_parse_guid(const u8 *src, u8 *dest) + return true; + } + ++/* ++ * Convert a raw GUID to the ACII string representation ++ */ ++static int wmi_gtoa(const char *in, char *out) ++{ ++ int i; ++ ++ for (i = 3; i >= 0; i--) ++ out += sprintf(out, "%02X", in[i] & 0xFF); ++ ++ out += sprintf(out, "-"); ++ out += sprintf(out, "%02X", in[5] & 0xFF); ++ out += sprintf(out, "%02X", in[4] & 0xFF); ++ out += sprintf(out, "-"); ++ out += sprintf(out, "%02X", in[7] & 0xFF); ++ out += sprintf(out, "%02X", in[6] & 0xFF); ++ out += sprintf(out, "-"); ++ out += sprintf(out, "%02X", in[8] & 0xFF); ++ out += sprintf(out, "%02X", in[9] & 0xFF); ++ out += sprintf(out, "-"); ++ ++ for (i = 10; i <= 15; i++) ++ out += sprintf(out, "%02X", in[i] & 0xFF); ++ ++ out = '\0'; ++ return 0; ++} ++ + static bool find_guid(const char *guid_string, struct wmi_block **out) + { + char tmp[16], guid_input[16]; +@@ -555,6 +585,138 @@ bool wmi_has_guid(const char *guid_string) + EXPORT_SYMBOL_GPL(wmi_has_guid); + + /* ++ * sysfs interface ++ */ ++static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ char guid_string[37]; ++ struct wmi_block *wblock; ++ ++ wblock = dev_get_drvdata(dev); ++ if (!wblock) ++ return -ENOMEM; ++ ++ wmi_gtoa(wblock->gblock.guid, guid_string); ++ ++ return sprintf(buf, "wmi:%s\n", guid_string); ++} ++static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); ++ ++static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env) ++{ ++ char guid_string[37]; ++ ++ struct wmi_block *wblock; ++ ++ if (add_uevent_var(env, "MODALIAS=")) ++ return -ENOMEM; ++ ++ wblock = dev_get_drvdata(dev); ++ if (!wblock) ++ return -ENOMEM; ++ ++ wmi_gtoa(wblock->gblock.guid, guid_string); ++ ++ strcpy(&env->buf[env->buflen - 1], "wmi:"); ++ memcpy(&env->buf[env->buflen - 1 + 4], guid_string, 36); ++ env->buflen += 40; ++ ++ return 0; ++} ++ ++static void wmi_dev_free(struct device *dev) ++{ ++ kfree(dev); ++} ++ ++static struct class wmi_class = { ++ .name = "wmi", ++ .dev_release = wmi_dev_free, ++ .dev_uevent = wmi_dev_uevent, ++}; ++ ++static int wmi_create_devs(void) ++{ ++ int result; ++ char guid_string[37]; ++ struct guid_block *gblock; ++ struct wmi_block *wblock; ++ struct list_head *p; ++ struct device *guid_dev; ++ ++ /* Create devices for all the GUIDs */ ++ list_for_each(p, &wmi_blocks.list) { ++ wblock = list_entry(p, struct wmi_block, list); ++ ++ guid_dev = kzalloc(sizeof(struct device), GFP_KERNEL); ++ if (!guid_dev) ++ return -ENOMEM; ++ ++ wblock->dev = guid_dev; ++ ++ guid_dev->class = &wmi_class; ++ dev_set_drvdata(guid_dev, wblock); ++ ++ gblock = &wblock->gblock; ++ ++ wmi_gtoa(gblock->guid, guid_string); ++ dev_set_name(guid_dev, guid_string); ++ ++ result = device_register(guid_dev); ++ if (result) ++ return result; ++ ++ result = device_create_file(guid_dev, &dev_attr_modalias); ++ if (result) ++ return result; ++ } ++ ++ return 0; ++} ++ ++static void wmi_remove_devs(void) ++{ ++ struct guid_block *gblock; ++ struct wmi_block *wblock; ++ struct list_head *p; ++ struct device *guid_dev; ++ ++ /* Delete devices for all the GUIDs */ ++ list_for_each(p, &wmi_blocks.list) { ++ wblock = list_entry(p, struct wmi_block, list); ++ ++ guid_dev = wblock->dev; ++ gblock = &wblock->gblock; ++ ++ device_remove_file(guid_dev, &dev_attr_modalias); ++ ++ device_unregister(guid_dev); ++ } ++} ++ ++static void wmi_class_exit(void) ++{ ++ wmi_remove_devs(); ++ class_unregister(&wmi_class); ++} ++ ++static int wmi_class_init(void) ++{ ++ int ret; ++ ++ ret = class_register(&wmi_class); ++ if (ret) ++ return ret; ++ ++ ret = wmi_create_devs(); ++ if (ret) ++ wmi_class_exit(); ++ ++ return ret; ++} ++ ++/* + * Parse the _WDG method for the GUID data blocks + */ + static __init acpi_status parse_wdg(acpi_handle handle) +@@ -709,10 +871,17 @@ static int __init acpi_wmi_init(void) + + if (result < 0) { + printk(KERN_INFO PREFIX "Error loading mapper\n"); +- } else { +- printk(KERN_INFO PREFIX "Mapper loaded\n"); ++ return -ENODEV; ++ } ++ ++ result = wmi_class_init(); ++ if (result) { ++ acpi_bus_unregister_driver(&acpi_wmi_driver); ++ return result; + } + ++ printk(KERN_INFO PREFIX "Mapper loaded\n"); ++ + return result; + } + +@@ -721,6 +890,8 @@ static void __exit acpi_wmi_exit(void) + struct list_head *p, *tmp; + struct wmi_block *wblock; + ++ wmi_class_exit(); ++ + acpi_bus_unregister_driver(&acpi_wmi_driver); + + list_for_each_safe(p, tmp, &wmi_blocks.list) { |