summaryrefslogtreecommitdiffstats
path: root/linux-2.6-autoload-wmi.patch
diff options
context:
space:
mode:
authorJesse Keating <jkeating@redhat.com>2010-07-29 17:18:45 -0700
committerJesse Keating <jkeating@redhat.com>2010-07-29 17:18:45 -0700
commit2f82dda4a9bf41e64e864889bf06564bdf826e25 (patch)
tree118a7b483ae5de4dbf83d20001302f1404866ef0 /linux-2.6-autoload-wmi.patch
parent64ba2e5ffde5f2418eb26c700cb0ab62b04e5013 (diff)
downloaddom0-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.patch244
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) {