obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND) += sfc_netfront/
obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND) += sfc_netback/
+obj-$(CONFIG_XEN_ACPI_WMI_WRAPPER) += acpi-wmi/
+diff --git a/drivers/xen/acpi-wmi/Makefile b/drivers/xen/acpi-wmi/Makefile
+new file mode 100644
+index 0000000..afe5d9d
+--- /dev/null
++++ b/drivers/xen/acpi-wmi/Makefile
+@@ -0,0 +1,2 @@
++
++obj-y := acpi-wmi.o
+diff --git a/drivers/xen/acpi-wmi/acpi-wmi.c b/drivers/xen/acpi-wmi/acpi-wmi.c
+new file mode 100644
+index 0000000..90d1e3f
+--- /dev/null
++++ b/drivers/xen/acpi-wmi/acpi-wmi.c
+@@ -0,0 +1,352 @@
++/******************************************************************************
++ * drivers/xen/acpi-wmi/acpi-wmi.c
++ *
++ * Copyright (c) 2009 Kamala Narasimhan
++ * Copyright (c) 2009 Citrix Systems, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++/* Xen acpi-wmi implementation provides the interface required for userspace
++ * module (qemu) to communicate with acpi wmi wrapper kernel driver.
++ * Upon receiving request from qemu to call a WMI method or query or set WMI
++ * data, it communicates the request to kernel acpi wmi layer which then
++ * interacts with the base firmware to get the necessary information/execute
++ * relevant AML method etc. The result returned by the base firmware is then
++ * communicated back to the userspace module (qemu).
++ */
++
++#include <linux/module.h>
++#include <linux/miscdevice.h>
++#include <linux/acpi.h>
++#include <asm/uaccess.h>
++#include <xen/public/acpi-wmi.h>
++
++/* #define XEN_WMI_DEBUG */
++
++static bool xen_wmi_misc_dev_registered = false;
++static int xen_wmi_ioctl(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++
++static struct file_operations xen_wmi_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = xen_wmi_ioctl,
++};
++
++static struct miscdevice xen_wmi_misc = {
++ .minor = MISC_DYNAMIC_MINOR,
++ .name = XEN_WMI_DEVICE_NAME,
++ .fops = &xen_wmi_fops,
++};
++
++/*
++ * xen_wmi_copy_input_buffer
++ */
++int xen_wmi_copy_input_buffer(xen_wmi_buffer_t *user_buf, struct acpi_buffer *acpi_buf)
++{
++ if ( user_buf->length <= 0 )
++ return XEN_WMI_SUCCESS;
++
++ acpi_buf->pointer = kmalloc(user_buf->length, GFP_KERNEL);
++ if ( acpi_buf->pointer == NULL )
++ {
++ printk("XEN WMI: xen_wmi_copy_input_buffer - Buffer allocation failure\n");
++ return XEN_WMI_NOT_ENOUGH_MEMORY;
++ }
++
++ if ( copy_from_user(acpi_buf->pointer,
++ (char __user *)user_buf->pointer,
++ user_buf->length) )
++ {
++ printk("XEN WMI: Unable to copy input buffer argument\n");
++ kfree(acpi_buf->pointer);
++ return XEN_WMI_EFAULT;
++ }
++
++ acpi_buf->length = user_buf->length;
++ return XEN_WMI_SUCCESS;
++}
++
++/*
++ * xen_wmi_copy_output_buffer
++ */
++int xen_wmi_copy_output_buffer(struct acpi_buffer *acpi_buf, xen_wmi_buffer_t *user_buf)
++{
++ /* IMPORTANT NOTE: It is a little short sighted to assume that the return type
++ * will not be anything other than buffer type. A follow-up check-in will
++ * cover more types.
++ */
++
++ union acpi_object *acpi_obj = acpi_buf->pointer;
++
++ if ( acpi_obj == NULL )
++ {
++ printk("XEN WMI: Invalid acpi buffer!\n");
++ return XEN_WMI_EFAULT;
++ }
++
++ if ( acpi_obj->type != ACPI_TYPE_BUFFER )
++ {
++ printk("XEN WMI: Unsupported acpi return object type - %d\n", acpi_obj->type);
++ return XEN_WMI_UNSUPPORTED_TYPE;
++ }
++
++ if ( copy_to_user((char __user *) user_buf->copied_length, &acpi_obj->buffer.length, sizeof(size_t)) )
++ {
++ printk("XEN WMI: Invalid copied length user buffer!\n");
++ return XEN_WMI_INVALID_ARGUMENT;
++ }
++
++ if ( user_buf->length < acpi_obj->buffer.length )
++ {
++ printk("XEN WMI: Required buffer length is - %d\n", acpi_obj->buffer.length);
++ printk("XEN WMI: Passed in length is - %d\n", user_buf->length);
++ return XEN_WMI_BUFFER_TOO_SMALL;
++ }
++
++ if ( copy_to_user((char __user *) user_buf->pointer, acpi_obj->buffer.pointer, acpi_obj->buffer.length) )
++ {
++ printk("XEN WMI: Invalid user output buffer\n");
++ return XEN_WMI_NOT_ENOUGH_MEMORY;
++ }
++
++ return XEN_WMI_SUCCESS;
++}
++
++#ifdef XEN_WMI_DEBUG
++
++/*
++ * xen_wmi_print_buffer
++ */
++void xen_wmi_print_buffer(struct acpi_buffer *acpi_buf)
++{
++ int count;
++ union acpi_object *acpi_obj = acpi_buf->pointer;
++
++ if ( acpi_obj == NULL || acpi_obj->type != ACPI_TYPE_BUFFER )
++ {
++ printk("XEN WMI: Unsupported output buffer data!\n");
++ return ;
++ }
++
++ printk("XEN WMI: Output buffer length is - %d\n", acpi_obj->buffer.length);
++ printk("XEN WMI: Buffer: ");
++ for (count=0; count < acpi_obj->buffer.length; count++)
++ printk("%d ", ((byte *)(acpi_obj->buffer.pointer))[count]);
++ printk("\n");
++}
++
++#endif /* XEN_WMI_DEBUG */
++
++/*
++ * xen_wmi_invoke_method
++ */
++int xen_wmi_invoke_method(xen_wmi_obj_invocation_data_t *obj_inv_data)
++{
++ int result;
++ struct acpi_buffer in_buf, *in_arg = NULL, out_buf = {ACPI_ALLOCATE_BUFFER, NULL};
++
++ result = xen_wmi_copy_input_buffer(&obj_inv_data->xen_wmi_arg.xen_wmi_method_arg.in_buf,
++ &in_buf);
++ if ( result != XEN_WMI_SUCCESS )
++ return result;
++
++ if ( in_buf.length > 0 )
++ in_arg = &in_buf;
++
++ result = wmi_evaluate_method(obj_inv_data->guid,
++ obj_inv_data->xen_wmi_arg.xen_wmi_method_arg.instance,
++ obj_inv_data->xen_wmi_arg.xen_wmi_method_arg.method_id,
++ in_arg, &out_buf);
++
++ if ( in_arg != NULL )
++ kfree(in_buf.pointer);
++
++ if ( out_buf.length > 0 && result == XEN_WMI_SUCCESS )
++ {
++#ifdef XEN_WMI_DEBUG
++ xen_wmi_print_buffer(&out_buf);
++#endif
++ result = xen_wmi_copy_output_buffer(&out_buf,
++ &obj_inv_data->xen_wmi_arg.xen_wmi_method_arg.out_buf);
++ kfree(out_buf.pointer);
++ }
++ else if ( result != XEN_WMI_SUCCESS )
++ printk("XEN WMI- Invoke WMI method failed with error - %d\n", result);
++
++ return result;
++}
++
++/*
++ * xen_wmi_query_object
++ */
++int xen_wmi_query_object(xen_wmi_obj_invocation_data_t *obj_inv_data)
++{
++ int result;
++ struct acpi_buffer out_buf = {ACPI_ALLOCATE_BUFFER, NULL};
++
++ result = wmi_query_block(obj_inv_data->guid,
++ obj_inv_data->xen_wmi_arg.xen_wmi_query_obj_arg.instance,
++ &out_buf);
++
++ if ( out_buf.length > 0 && result == XEN_WMI_SUCCESS )
++ {
++#ifdef XEN_WMI_DEBUG
++ xen_wmi_print_buffer(&out_buf);
++#endif
++ result = xen_wmi_copy_output_buffer(&out_buf,
++ &obj_inv_data->xen_wmi_arg.xen_wmi_query_obj_arg.out_buf);
++ kfree(out_buf.pointer);
++ }
++ else
++ printk("XEN WMI - Query WMI object failed with error - %d; output buffer length - %d\n",
++ result, out_buf.length);
++
++ return result;
++}
++
++/*
++ * xen_wmi_set_object
++ */
++int xen_wmi_set_object(xen_wmi_obj_invocation_data_t *obj_inv_data)
++{
++ int result;
++ struct acpi_buffer in_buf;
++
++ if ( obj_inv_data->xen_wmi_arg.xen_wmi_set_obj_arg.in_buf.length <= 0 )
++ return XEN_WMI_INVALID_ARGUMENT;
++
++ result = xen_wmi_copy_input_buffer(&obj_inv_data->xen_wmi_arg.xen_wmi_set_obj_arg.in_buf,
++ &in_buf);
++ if ( result != XEN_WMI_SUCCESS )
++ return result;
++
++ result = wmi_set_block(obj_inv_data->guid,
++ obj_inv_data->xen_wmi_arg.xen_wmi_set_obj_arg.instance,
++ &in_buf);
++ if ( result != XEN_WMI_SUCCESS )
++ printk("XEN WMI: Set object failed with error - %d\n", result);
++
++ kfree(in_buf.pointer);
++ return result;
++}
++
++/*
++ * xen_wmi_get_event_data
++ */
++int xen_wmi_get_event_data(xen_wmi_obj_invocation_data_t *obj_inv_data)
++{
++ int result;
++ struct acpi_buffer out_buf = {ACPI_ALLOCATE_BUFFER, NULL};
++
++ result = wmi_get_event_data(obj_inv_data->xen_wmi_arg.xen_wmi_event_data_arg.event_id,
++ &out_buf);
++
++ if ( out_buf.length > 0 && result == XEN_WMI_SUCCESS )
++ {
++#ifdef XEN_WMI_DEBUG
++ xen_wmi_print_buffer(&out_buf);
++#endif
++ result = xen_wmi_copy_output_buffer(&out_buf,
++ &obj_inv_data->xen_wmi_arg.xen_wmi_event_data_arg.out_buf);
++ kfree(out_buf.pointer);
++ }
++ else
++ printk("XEN WMI: Get event data failed with error - %d\n", result);
++
++ return result;
++}
++
++/*
++ * xen_wmi_ioctl
++ */
++static int xen_wmi_ioctl(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
++{
++ xen_wmi_obj_invocation_data_t obj_inv_data;
++
++#ifdef XEN_WMI_DEBUG
++ printk("XEN WMI: In xen_wmi_ioctl - %d\n", cmd);
++#endif
++
++ memset(&obj_inv_data, 0, sizeof(obj_inv_data));
++ if ( copy_from_user(&obj_inv_data, (char __user *)arg, sizeof(obj_inv_data)) )
++ {
++ printk("XEN WMI: Invalid object invocation parameter\n");
++ return XEN_WMI_EFAULT;
++ }
++
++ switch ( cmd )
++ {
++ case XEN_WMI_IOCTL_CALL_METHOD:
++ return xen_wmi_invoke_method(&obj_inv_data);
++ case XEN_WMI_IOCTL_QUERY_OBJECT:
++ return xen_wmi_query_object(&obj_inv_data);
++ case XEN_WMI_IOCTL_SET_OBJECT:
++ return xen_wmi_set_object(&obj_inv_data);
++ case XEN_WMI_IOCTL_GET_EVENT_DATA:
++ return xen_wmi_get_event_data(&obj_inv_data);
++ }
++
++ return XEN_WMI_ENOIOCTLCMD;
++}
++
++/*
++ * xen_wmi_init
++ */
++static int __init xen_wmi_init(void)
++{
++ int ret;
++
++ ret = misc_register(&xen_wmi_misc);
++ if ( ret < 0 )
++ printk("XEN WMI: misc_register failed with error - %d\n", ret);
++ else
++ xen_wmi_misc_dev_registered = true;
++
++#ifdef XEN_WMI_DEBUG
++ printk("XEN WMI: xen-acpi-wmi misc_register succeeded!\n");
++#endif
++ return ret;
++}
++
++/*
++ * xen_wmi_exit
++ */
++static void xen_wmi_exit(void)
++{
++ int ret;
++
++ if ( xen_wmi_misc_dev_registered == false )
++ return;
++
++ if ( (ret = misc_deregister(&xen_wmi_misc)) < 0 )
++ printk("XEN WMI: misc_deregister failed with error - %d\n", ret);
++}
++
++module_init(xen_wmi_init);
++module_exit(xen_wmi_exit);
++MODULE_LICENSE("Dual BSD/GPL");
++
+diff --git a/include/xen/public/acpi-wmi.h b/include/xen/public/acpi-wmi.h
+new file mode 100644
+index 0000000..097639b
+--- /dev/null
++++ b/include/xen/public/acpi-wmi.h
+@@ -0,0 +1,94 @@
++/******************************************************************************
++ * acpi-wmi.h
++ *
++ * Interface to /proc/misc/xen-acpi-wmi
++ *
++ * Copyright (c) 2009 Kamala Narasimhan
++ * Copyright (c) 2009 Citrix Systems, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++
++#ifndef _XEN_WMI_ACPI
++#define _XEN_WMI_ACPI
++
++/*
++ * Userspace Interface
++ */
++
++#define XEN_WMI_DEVICE_NAME "xen-acpi-wmi"
++#define XEN_WMI_GUID_SIZE 16
++
++#define XEN_WMI_SUCCESS 0
++#define XEN_WMI_UNSUPPORTED_TYPE -1
++#define XEN_WMI_BUFFER_TOO_SMALL -11
++#define XEN_WMI_NOT_ENOUGH_MEMORY -12
++#define XEN_WMI_EFAULT -14
++#define XEN_WMI_INVALID_ARGUMENT -22
++#define XEN_WMI_ENOIOCTLCMD -515
++
++#define XEN_WMI_IOCTL_CALL_METHOD 100
++#define XEN_WMI_IOCTL_QUERY_OBJECT 101
++#define XEN_WMI_IOCTL_SET_OBJECT 102
++#define XEN_WMI_IOCTL_GET_EVENT_DATA 103
++
++typedef unsigned char byte;
++
++typedef struct xen_wmi_buffer {
++ size_t length;
++ void *pointer;
++ size_t *copied_length;
++} xen_wmi_buffer_t;
++
++typedef struct xen_wmi_obj_invocation_data {
++ byte guid[XEN_WMI_GUID_SIZE];
++ union {
++ struct {
++ ushort instance;
++ uint method_id;
++ xen_wmi_buffer_t in_buf;
++ xen_wmi_buffer_t out_buf;
++ } xen_wmi_method_arg;
++
++ struct {
++ ushort instance;
++ xen_wmi_buffer_t out_buf;
++ } xen_wmi_query_obj_arg;
++
++ struct {
++ ushort instance;
++ xen_wmi_buffer_t in_buf;
++ } xen_wmi_set_obj_arg;
++
++ struct {
++ ushort event_id;
++ xen_wmi_buffer_t out_buf;
++ } xen_wmi_event_data_arg;
++ } xen_wmi_arg;
++} xen_wmi_obj_invocation_data_t;
++
++#endif /* _XEN_WMI_ACPI */
++