]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
Revert "Merge branch 'stable/cpufreq-xen.v6.rebased' into uek2-merge"
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Wed, 14 Mar 2012 00:43:38 +0000 (20:43 -0400)
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Wed, 14 Mar 2012 16:15:49 +0000 (12:15 -0400)
This reverts commit 2fa5344c95525da55cd6896af85541fc23c1bdc0, reversing
changes made to d696e467d97b748cab14eb1b9910bf45f2044033.

As the upstream version has changed course..

and also remove xen/processor-passthru.c which the git commit:
 696e467d97b748cab14eb1b9910bf45f2044033 should have done.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
drivers/xen/Kconfig
drivers/xen/Makefile
drivers/xen/cpufreq_xen.c [deleted file]
drivers/xen/processor-passthru.c [deleted file]

index e2a7d748187a169a5d855d50587452b27e99393a..73dced0107658e1546d4e2f4f1941473901a33c8 100644 (file)
@@ -151,21 +151,20 @@ config XEN_MCE_LOG
          Allow kernel fetching mce log from xen platform and
          converting it into linux mcelog format for mcelog tools
 
-config CPU_FREQ_GOV_XEN
-       tristate "'xen' governor for hypervisor scaling"
-       depends on XEN && X86 && ACPI_PROCESSOR && CPU_FREQ
-       default m
-       help
-          This cpufreq governor leaves the frequency decision to the Xen hypervisor.
-
-         To do that the driver parses the Power Management data and uploads said
-         information to the Xen hypervisor. Then the Xen hypervisor can select the
-          proper Cx and Pxx states.
 
-          To compile this driver as a module, choose M here: the
-          module will be called cpufreq_xen.  If you do not know what to choose,
-          select M here.
+config XEN_PROCESSOR_PASSTHRU
+       tristate "Processor passthrough driver for Xen"
+       depends on XEN
+       depends on ACPI_PROCESSOR
+       depends on X86
+       depends on CPU_FREQ
+       help
+         This driver parses the processor structure and passes the information
+         to the Xen hypervisor. It is used to allow the Xen hypervisor to have the
+         full power management data and be able to select proper Cx and Pxx states.
 
+         The driver should be loaded after acpi processor and cpufreq drivers have
+         been loaded. If you do not know what to choose, select M here.
 
 
 config XEN_PRIVCMD
index 9b25bcc059452e08bf40fa25b7d7663751b7eea1..2f3ba85a3c84c794018f575fcbb6edf95c6b523a 100644 (file)
@@ -19,7 +19,7 @@ obj-$(CONFIG_XEN_TMEM)                        += tmem.o
 obj-$(CONFIG_SWIOTLB_XEN)              += swiotlb-xen.o
 obj-$(CONFIG_XEN_DOM0)                 += pci.o acpi.o
 obj-$(CONFIG_XEN_PRIVCMD)              += xen-privcmd.o
-obj-$(CONFIG_CPU_FREQ_GOV_XEN)         += cpufreq_xen.o
+obj-$(CONFIG_XEN_PROCESSOR_PASSTHRU)   += processor-passthru.o
 obj-$(CONFIG_XEN_PCIDEV_BACKEND)       += xen-pciback/
 xen-evtchn-y                           := evtchn.o
 xen-gntdev-y                           := gntdev.o
diff --git a/drivers/xen/cpufreq_xen.c b/drivers/xen/cpufreq_xen.c
deleted file mode 100644 (file)
index 1b709bf..0000000
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Copyright 2012 by Oracle Inc
- * Author: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
- *
- * This code borrows ideas from https://lkml.org/lkml/2011/11/30/249
- * so many thanks go to Kevin Tian <kevin.tian@intel.com>
- * and Yu Ke <ke.yu@intel.com>.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- *
- */
-
-#include <linux/cpumask.h>
-#include <linux/cpufreq.h>
-#include <linux/freezer.h>
-#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/processor.h>
-
-#include <xen/interface/platform.h>
-#include <asm/xen/hypercall.h>
-
-#define DRV_NAME "cpufreq-xen"
-
-static int no_hypercall;
-MODULE_PARM_DESC(off, "Inhibit the hypercall.");
-module_param_named(off, no_hypercall, int, 0400);
-
-/*
- * Mutex to protect the acpi_ids_done.
- */
-static DEFINE_MUTEX(acpi_ids_mutex);
-/*
- * Don't think convert this to cpumask_var_t or use cpumask_bit - as those
- * shrink to nr_cpu_bits (which is dependent on possible_cpu), which can be
- * less than what we want to put in.
- */
-#define NR_ACPI_CPUS   NR_CPUS
-#define MAX_ACPI_BITS  (BITS_TO_LONGS(NR_ACPI_CPUS))
-static unsigned long *acpi_ids_done;
-/*
- * Again, don't convert to cpumask - as we are reading the raw ACPI CPU ids
- * which can go beyond what we presently see.
- */
-static unsigned long *acpi_id_present;
-
-/*
- * Pertient data for the timer to be launched to check if the # of
- * ACPI CPU ids is different from the one we have processed.
- */
-#define DELAY_TIMER    msecs_to_jiffies(5000 /* 5 sec */)
-static struct acpi_processor *pr_backup;
-static struct delayed_work work;
-
-static int push_cxx_to_hypervisor(struct acpi_processor *_pr)
-{
-       struct xen_platform_op op = {
-               .cmd                    = XENPF_set_processor_pminfo,
-               .interface_version      = XENPF_INTERFACE_VERSION,
-               .u.set_pminfo.id        = _pr->acpi_id,
-               .u.set_pminfo.type      = XEN_PM_CX,
-       };
-       struct xen_processor_cx *dst_cx, *dst_cx_states = NULL;
-       struct acpi_processor_cx *cx;
-       int i, ok, ret = 0;
-
-       dst_cx_states = kcalloc(_pr->power.count,
-                               sizeof(struct xen_processor_cx), GFP_KERNEL);
-       if (!dst_cx_states)
-               return -ENOMEM;
-
-       for (ok = 0, i = 1; i <= _pr->power.count; i++) {
-               cx = &_pr->power.states[i];
-               if (!cx->valid)
-                       continue;
-
-               dst_cx = &(dst_cx_states[ok++]);
-
-               dst_cx->reg.space_id = ACPI_ADR_SPACE_SYSTEM_IO;
-               if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) {
-                       dst_cx->reg.bit_width = 8;
-                       dst_cx->reg.bit_offset = 0;
-                       dst_cx->reg.access_size = 1;
-               } else {
-                       dst_cx->reg.space_id = ACPI_ADR_SPACE_FIXED_HARDWARE;
-                       if (cx->entry_method == ACPI_CSTATE_FFH) {
-                               /* NATIVE_CSTATE_BEYOND_HALT */
-                               dst_cx->reg.bit_offset = 2;
-                               dst_cx->reg.bit_width = 1; /* VENDOR_INTEL */
-                       }
-                       dst_cx->reg.access_size = 0;
-               }
-               dst_cx->reg.address = cx->address;
-
-               dst_cx->type = cx->type;
-               dst_cx->latency = cx->latency;
-               dst_cx->power = cx->power;
-
-               dst_cx->dpcnt = 0;
-               set_xen_guest_handle(dst_cx->dp, NULL);
-#ifdef DEBUG
-               pr_debug(DRV_NAME ": CX: ID:%d [C%d:%s] entry:%d\n",
-                       _pr->acpi_id, cx->type, cx->desc, cx->entry_method);
-#endif
-       }
-       if (!ok) {
-               pr_err(DRV_NAME ": No _Cx for CPU %d\n", _pr->acpi_id);
-               kfree(dst_cx_states);
-               return -EINVAL;
-       }
-       op.u.set_pminfo.power.count = ok;
-       op.u.set_pminfo.power.flags.bm_control = _pr->flags.bm_control;
-       op.u.set_pminfo.power.flags.bm_check = _pr->flags.bm_check;
-       op.u.set_pminfo.power.flags.has_cst = _pr->flags.has_cst;
-       op.u.set_pminfo.power.flags.power_setup_done =
-               _pr->flags.power_setup_done;
-
-       set_xen_guest_handle(op.u.set_pminfo.power.states, dst_cx_states);
-
-       if (!no_hypercall)
-               ret = HYPERVISOR_dom0_op(&op);
-
-       if (ret)
-               pr_err(DRV_NAME "(CX): Hypervisor error (%d) for ACPI ID: %d\n",
-                      ret, _pr->acpi_id);
-
-       kfree(dst_cx_states);
-
-       return ret;
-}
-static struct xen_processor_px *
-xen_copy_pss_data(struct acpi_processor *_pr,
-                 struct xen_processor_performance *dst_perf)
-{
-       struct xen_processor_px *dst_states = NULL;
-       int i;
-
-       BUILD_BUG_ON(sizeof(struct xen_processor_px) !=
-                    sizeof(struct acpi_processor_px));
-
-       dst_states = kcalloc(_pr->performance->state_count,
-                            sizeof(struct xen_processor_px), GFP_KERNEL);
-       if (!dst_states)
-               return ERR_PTR(-ENOMEM);
-
-       dst_perf->state_count = _pr->performance->state_count;
-       for (i = 0; i < _pr->performance->state_count; i++) {
-               /* Fortunatly for us, they are both the same size */
-               memcpy(&(dst_states[i]), &(_pr->performance->states[i]),
-                      sizeof(struct acpi_processor_px));
-       }
-       return dst_states;
-}
-static int xen_copy_psd_data(struct acpi_processor *_pr,
-                            struct xen_processor_performance *dst)
-{
-       BUILD_BUG_ON(sizeof(struct xen_psd_package) !=
-                    sizeof(struct acpi_psd_package));
-
-       if (_pr->performance->shared_type != CPUFREQ_SHARED_TYPE_NONE) {
-               dst->shared_type = _pr->performance->shared_type;
-
-               memcpy(&(dst->domain_info), &(_pr->performance->domain_info),
-                      sizeof(struct acpi_psd_package));
-       } else {
-               if ((&cpu_data(0))->x86_vendor != X86_VENDOR_AMD)
-                       return -EINVAL;
-
-               /* On AMD, the powernow-k8 is loaded before acpi_cpufreq
-                * meaning that acpi_processor_preregister_performance never
-                * gets called which would parse the _PSD. The only relevant
-                * information from _PSD we need is whether it is HW_ALL or any
-                * other type. AMD K8 >= are SW_ALL or SW_ANY, AMD K7<= HW_ANY.
-                * This driver checks at the start whether it is K8 so it
-                * if we get here it can only be K8.
-                */
-               dst->shared_type = CPUFREQ_SHARED_TYPE_ANY;
-               dst->domain_info.coord_type = DOMAIN_COORD_TYPE_SW_ANY;
-               dst->domain_info.num_processors = num_online_cpus();
-       }
-       return 0;
-}
-static int xen_copy_pct_data(struct acpi_pct_register *pct,
-                            struct xen_pct_register *dst_pct)
-{
-       /* It would be nice if you could just do 'memcpy(pct, dst_pct') but
-        * sadly the Xen structure did not have the proper padding so the
-        * descriptor field takes two (dst_pct) bytes instead of one (pct).
-        */
-       dst_pct->descriptor = pct->descriptor;
-       dst_pct->length = pct->length;
-       dst_pct->space_id = pct->space_id;
-       dst_pct->bit_width = pct->bit_width;
-       dst_pct->bit_offset = pct->bit_offset;
-       dst_pct->reserved = pct->reserved;
-       dst_pct->address = pct->address;
-       return 0;
-}
-static int push_pxx_to_hypervisor(struct acpi_processor *_pr)
-{
-       int ret = 0;
-       struct xen_platform_op op = {
-               .cmd                    = XENPF_set_processor_pminfo,
-               .interface_version      = XENPF_INTERFACE_VERSION,
-               .u.set_pminfo.id        = _pr->acpi_id,
-               .u.set_pminfo.type      = XEN_PM_PX,
-       };
-       struct xen_processor_performance *dst_perf;
-       struct xen_processor_px *dst_states = NULL;
-
-       dst_perf = &op.u.set_pminfo.perf;
-
-       dst_perf->platform_limit = _pr->performance_platform_limit;
-       dst_perf->flags |= XEN_PX_PPC;
-       xen_copy_pct_data(&(_pr->performance->control_register),
-                         &dst_perf->control_register);
-       xen_copy_pct_data(&(_pr->performance->status_register),
-                         &dst_perf->status_register);
-       dst_perf->flags |= XEN_PX_PCT;
-       dst_states = xen_copy_pss_data(_pr, dst_perf);
-       if (!IS_ERR_OR_NULL(dst_states)) {
-               set_xen_guest_handle(dst_perf->states, dst_states);
-               dst_perf->flags |= XEN_PX_PSS;
-       }
-       if (!xen_copy_psd_data(_pr, dst_perf))
-               dst_perf->flags |= XEN_PX_PSD;
-
-       if (!no_hypercall)
-               ret = HYPERVISOR_dom0_op(&op);
-
-       if (ret)
-               pr_err(DRV_NAME "(_PXX): Hypervisor error (%d) for ACPI ID %d\n",
-                      ret, _pr->acpi_id);
-
-       if (!IS_ERR_OR_NULL(dst_states))
-               kfree(dst_states);
-
-       return ret;
-}
-static int upload_pm_data(struct acpi_processor *_pr)
-{
-       int err = 0;
-
-       if (__test_and_set_bit(_pr->acpi_id, acpi_ids_done))
-               return -EBUSY;
-
-       if (_pr->flags.power)
-               err = push_cxx_to_hypervisor(_pr);
-
-       if (_pr->performance && _pr->performance->states)
-               err |= push_pxx_to_hypervisor(_pr);
-
-       return err;
-}
-static acpi_status
-read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-       u32 acpi_id;
-       acpi_status status;
-       acpi_object_type acpi_type;
-       unsigned long long tmp;
-       union acpi_object object = { 0 };
-       struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
-
-       status = acpi_get_type(handle, &acpi_type);
-       if (ACPI_FAILURE(status))
-               return AE_OK;
-
-       switch (acpi_type) {
-       case ACPI_TYPE_PROCESSOR:
-               status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
-               if (ACPI_FAILURE(status))
-                       return AE_OK;
-               acpi_id = object.processor.proc_id;
-               break;
-       case ACPI_TYPE_DEVICE:
-               status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
-               if (ACPI_FAILURE(status))
-                       return AE_OK;
-               acpi_id = tmp;
-               break;
-       default:
-               return AE_OK;
-       }
-       if (acpi_id > NR_ACPI_CPUS) {
-               WARN_ONCE(1, "There are %d ACPI processors, but kernel can only do %d!\n",
-                    acpi_id, NR_ACPI_CPUS);
-               return AE_OK;
-       }
-       __set_bit(acpi_id, acpi_id_present);
-
-       return AE_OK;
-}
-static unsigned int more_acpi_ids(void)
-{
-       unsigned int n = 0;
-
-       acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
-                           ACPI_UINT32_MAX,
-                           read_acpi_id, NULL, NULL, NULL);
-       acpi_get_devices("ACPI0007", read_acpi_id, NULL, NULL);
-
-       mutex_lock(&acpi_ids_mutex);
-       if (!bitmap_equal(acpi_id_present, acpi_ids_done, MAX_ACPI_BITS))
-               n = bitmap_weight(acpi_id_present, MAX_ACPI_BITS);
-       mutex_unlock(&acpi_ids_mutex);
-
-       return n;
-}
-static void do_check_acpi_id_timer(struct work_struct *_work)
-{
-       /* All online CPUs have been processed at this stage. Now verify
-        * whether in fact "online CPUs" == physical CPUs.
-        */
-       acpi_id_present = kcalloc(MAX_ACPI_BITS, sizeof(unsigned long), GFP_KERNEL);
-       if (!acpi_id_present)
-               return;
-       memset(acpi_id_present, 0, MAX_ACPI_BITS * sizeof(unsigned long));
-
-       if (more_acpi_ids()) {
-               int cpu;
-               if (!pr_backup) {
-                       schedule_delayed_work(&work, DELAY_TIMER);
-                       return;
-               }
-               for_each_set_bit(cpu, acpi_id_present, MAX_ACPI_BITS) {
-                       pr_backup->acpi_id = cpu;
-                       mutex_lock(&acpi_ids_mutex);
-                       (void)upload_pm_data(pr_backup);
-                       mutex_unlock(&acpi_ids_mutex);
-               }
-       }
-       kfree(acpi_id_present);
-       acpi_id_present = NULL;
-}
-
-static int cpufreq_governor_xen(struct cpufreq_policy *policy,
-                               unsigned int event)
-{
-       struct acpi_processor *_pr;
-
-       switch (event) {
-       case CPUFREQ_GOV_START:
-       case CPUFREQ_GOV_LIMITS:
-               /* Set it to max and let the hypervisor take over */
-               __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
-
-               _pr = per_cpu(processors, policy->cpu /* APIC ID */);
-               if (!_pr)
-                       break;
-
-               mutex_lock(&acpi_ids_mutex);
-               if (!pr_backup) {
-                       pr_backup = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
-                       memcpy(pr_backup, _pr, sizeof(struct acpi_processor));
-
-                       INIT_DELAYED_WORK_DEFERRABLE(&work, do_check_acpi_id_timer);
-                       schedule_delayed_work(&work, DELAY_TIMER);
-               }
-               (void)upload_pm_data(_pr);
-               mutex_unlock(&acpi_ids_mutex);
-               break;
-       default:
-               break;
-       }
-       return 0;
-}
-static struct cpufreq_governor cpufreq_gov_xen = {
-       .name           = "xen",
-       .governor       = cpufreq_governor_xen,
-       .owner          = THIS_MODULE,
-};
-static int __init check_prereq(void)
-{
-       struct cpuinfo_x86 *c = &cpu_data(0);
-
-       if (!xen_initial_domain())
-               return -ENODEV;
-
-       if (!acpi_gbl_FADT.smi_command)
-               return -ENODEV;
-
-       if (c->x86_vendor == X86_VENDOR_INTEL) {
-               if (!cpu_has(c, X86_FEATURE_EST))
-                       return -ENODEV;
-
-               return 0;
-       }
-       if (c->x86_vendor == X86_VENDOR_AMD) {
-               u32 hi = 0, lo = 0;
-               /* Copied from powernow-k8.h, can't include ../cpufreq/powernow
-                * as we get compile warnings for the static functions.
-                */
-#define MSR_PSTATE_CUR_LIMIT    0xc0010061 /* pstate current limit MSR */
-               rdmsr(MSR_PSTATE_CUR_LIMIT, lo, hi);
-
-               /* If the MSR cannot provide the data, the powernow-k8
-                * won't process the data properly either.
-                */
-               if (hi || lo)
-                       return 0;
-       }
-       return -ENODEV;
-}
-
-static int __init xen_processor_passthru_init(void)
-{
-       int rc = check_prereq();
-
-       if (rc)
-               return rc;
-
-       acpi_ids_done = kcalloc(MAX_ACPI_BITS, sizeof(unsigned long), GFP_KERNEL);
-       if (!acpi_ids_done)
-               return -ENOMEM;
-       memset(acpi_ids_done, 0, MAX_ACPI_BITS * sizeof(unsigned long));
-
-       return cpufreq_register_governor(&cpufreq_gov_xen);
-}
-static void __exit xen_processor_passthru_exit(void)
-{
-       cpufreq_unregister_governor(&cpufreq_gov_xen);
-       cancel_delayed_work_sync(&work);
-       kfree(acpi_ids_done);
-       kfree(pr_backup);
-}
-
-MODULE_AUTHOR("Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>");
-MODULE_DESCRIPTION("CPUfreq policy governor 'xen' which uploads PM data to Xen hypervisor");
-MODULE_LICENSE("GPL");
-
-late_initcall(xen_processor_passthru_init);
-module_exit(xen_processor_passthru_exit);
diff --git a/drivers/xen/processor-passthru.c b/drivers/xen/processor-passthru.c
deleted file mode 100644 (file)
index e4dff42..0000000
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright 2012 by Oracle Inc
- * Author: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
- *
- * This code borrows ideas from https://lkml.org/lkml/2011/11/30/249
- * so many thanks go to Kevin Tian <kevin.tian@intel.com>
- * and Yu Ke <ke.yu@intel.com>.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- *
- */
-
-#include <linux/cpumask.h>
-#include <linux/cpufreq.h>
-#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/processor.h>
-
-#include <xen/interface/platform.h>
-#include <asm/xen/hypercall.h>
-
-#define DRV_NAME "xen-processor-thru"
-MODULE_AUTHOR("Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>");
-MODULE_DESCRIPTION("ACPI Power Management driver to pass Cx and Pxx data to Xen hypervisor");
-MODULE_LICENSE("GPL");
-
-
-static int no_hypercall;
-MODULE_PARM_DESC(off, "Inhibit the hypercall.");
-module_param_named(off, no_hypercall, int, 0400);
-
-/*
- * Mutex to protect the acpi_ids_done.
- */
-static DEFINE_MUTEX(acpi_ids_mutex);
-/*
- * Don't think convert this to cpumask_var_t or use cpumask_bit - as those
- * shrink to nr_cpu_bits (which is dependent on possible_cpu), which can be
- * less than what we want to put in.
- */
-#define NR_ACPI_CPUS   NR_CPUS
-#define MAX_ACPI_BITS  (BITS_TO_LONGS(NR_ACPI_CPUS))
-static unsigned long *acpi_ids_done;
-/*
- * Again, don't convert to cpumask - as we are reading the raw ACPI CPU ids
- * which can go beyond what we presently see.
- */
-static unsigned long *acpi_id_present;
-
-
-#define POLL_TIMER     msecs_to_jiffies(5000 /* 5 sec */)
-static struct task_struct *xen_processor_thread;
-
-static int xen_push_cxx_to_hypervisor(struct acpi_processor *_pr)
-{
-       struct xen_platform_op op = {
-               .cmd                    = XENPF_set_processor_pminfo,
-               .interface_version      = XENPF_INTERFACE_VERSION,
-               .u.set_pminfo.id        = _pr->acpi_id,
-               .u.set_pminfo.type      = XEN_PM_CX,
-       };
-       struct xen_processor_cx *xen_cx, *xen_cx_states = NULL;
-       struct acpi_processor_cx *cx;
-       int i, ok, ret = 0;
-
-       xen_cx_states = kcalloc(_pr->power.count,
-                               sizeof(struct xen_processor_cx), GFP_KERNEL);
-       if (!xen_cx_states)
-               return -ENOMEM;
-
-       for (ok = 0, i = 1; i <= _pr->power.count; i++) {
-               cx = &_pr->power.states[i];
-               if (!cx->valid)
-                       continue;
-
-               xen_cx = &(xen_cx_states[ok++]);
-
-               xen_cx->reg.space_id = ACPI_ADR_SPACE_SYSTEM_IO;
-               if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) {
-                       xen_cx->reg.bit_width = 8;
-                       xen_cx->reg.bit_offset = 0;
-                       xen_cx->reg.access_size = 1;
-               } else {
-                       xen_cx->reg.space_id = ACPI_ADR_SPACE_FIXED_HARDWARE;
-                       if (cx->entry_method == ACPI_CSTATE_FFH) {
-                               /* NATIVE_CSTATE_BEYOND_HALT */
-                               xen_cx->reg.bit_offset = 2;
-                               xen_cx->reg.bit_width = 1; /* VENDOR_INTEL */
-                       }
-                       xen_cx->reg.access_size = 0;
-               }
-               xen_cx->reg.address = cx->address;
-
-               xen_cx->type = cx->type;
-               xen_cx->latency = cx->latency;
-               xen_cx->power = cx->power;
-
-               xen_cx->dpcnt = 0;
-               set_xen_guest_handle(xen_cx->dp, NULL);
-#ifdef DEBUG
-               pr_debug(DRV_NAME ": CX: ID:%d [C%d:%s] entry:%d\n", _pr->acpi_id,
-                        cx->type, cx->desc, cx->entry_method);
-#endif
-       }
-       if (!ok) {
-               pr_err(DRV_NAME ": No available Cx info for cpu %d\n", _pr->acpi_id);
-               kfree(xen_cx_states);
-               return -EINVAL;
-       }
-       op.u.set_pminfo.power.count = ok;
-       op.u.set_pminfo.power.flags.bm_control = _pr->flags.bm_control;
-       op.u.set_pminfo.power.flags.bm_check = _pr->flags.bm_check;
-       op.u.set_pminfo.power.flags.has_cst = _pr->flags.has_cst;
-       op.u.set_pminfo.power.flags.power_setup_done =
-               _pr->flags.power_setup_done;
-
-       set_xen_guest_handle(op.u.set_pminfo.power.states, xen_cx_states);
-
-       if (!no_hypercall)
-               ret = HYPERVISOR_dom0_op(&op);
-
-       if (ret)
-               pr_err(DRV_NAME "(CX): Hypervisor returned (%d) for ACPI ID: %d\n",
-                      ret, _pr->acpi_id);
-
-       kfree(xen_cx_states);
-
-       return ret;
-}
-static struct xen_processor_px *xen_copy_pss_data(struct acpi_processor *_pr,
-                                                 struct xen_processor_performance *xen_perf)
-{
-       struct xen_processor_px *xen_states = NULL;
-       int i;
-
-       BUILD_BUG_ON(sizeof(struct xen_processor_px) !=
-                    sizeof(struct acpi_processor_px));
-
-       xen_states = kcalloc(_pr->performance->state_count,
-                            sizeof(struct xen_processor_px), GFP_KERNEL);
-       if (!xen_states)
-               return ERR_PTR(-ENOMEM);
-
-       xen_perf->state_count = _pr->performance->state_count;
-       for (i = 0; i < _pr->performance->state_count; i++) {
-               /* Fortunatly for us, they are both the same size */
-               memcpy(&(xen_states[i]), &(_pr->performance->states[i]),
-                      sizeof(struct acpi_processor_px));
-       }
-       return xen_states;
-}
-static int xen_copy_psd_data(struct acpi_processor *_pr,
-                            struct xen_processor_performance *xen_perf)
-{
-       BUILD_BUG_ON(sizeof(struct xen_psd_package) !=
-                    sizeof(struct acpi_psd_package));
-
-       if (_pr->performance->shared_type != CPUFREQ_SHARED_TYPE_NONE) {
-               xen_perf->shared_type = _pr->performance->shared_type;
-
-               memcpy(&(xen_perf->domain_info), &(_pr->performance->domain_info),
-                      sizeof(struct acpi_psd_package));
-       } else {
-               if ((&cpu_data(0))->x86_vendor != X86_VENDOR_AMD)
-                       return -EINVAL;
-
-               /* On AMD, the powernow-k8 is loaded before acpi_cpufreq
-                * meaning that acpi_processor_preregister_performance never
-                * gets called which would parse the _PSD. The only relevant
-                * information from _PSD we need is whether it is HW_ALL or any
-                * other type. AMD K8 >= are SW_ALL or SW_ANY, AMD K7<= HW_ANY.
-                * This driver checks at the start whether it is K8 so it
-                * if we get here it can only be K8.
-                */
-               xen_perf->shared_type = CPUFREQ_SHARED_TYPE_ANY;
-               xen_perf->domain_info.coord_type = DOMAIN_COORD_TYPE_SW_ANY;
-               xen_perf->domain_info.num_processors = num_online_cpus();
-       }
-       return 0;
-}
-static int xen_copy_pct_data(struct acpi_pct_register *pct,
-                            struct xen_pct_register *_pct)
-{
-       /* It would be nice if you could just do 'memcpy(pct, _pct') but
-        * sadly the Xen structure did not have the proper padding
-        * so the descriptor field takes two (_pct) bytes instead of one (pct).
-        */
-       _pct->descriptor = pct->descriptor;
-       _pct->length = pct->length;
-       _pct->space_id = pct->space_id;
-       _pct->bit_width = pct->bit_width;
-       _pct->bit_offset = pct->bit_offset;
-       _pct->reserved = pct->reserved;
-       _pct->address = pct->address;
-       return 0;
-}
-static int xen_push_pxx_to_hypervisor(struct acpi_processor *_pr)
-{
-       int ret = 0;
-       struct xen_platform_op op = {
-               .cmd                    = XENPF_set_processor_pminfo,
-               .interface_version      = XENPF_INTERFACE_VERSION,
-               .u.set_pminfo.id        = _pr->acpi_id,
-               .u.set_pminfo.type      = XEN_PM_PX,
-       };
-       struct xen_processor_performance *xen_perf;
-       struct xen_processor_px *xen_states = NULL;
-
-       xen_perf = &op.u.set_pminfo.perf;
-
-       xen_perf->platform_limit = _pr->performance_platform_limit;
-       xen_perf->flags |= XEN_PX_PPC;
-       xen_copy_pct_data(&(_pr->performance->control_register),
-                         &xen_perf->control_register);
-       xen_copy_pct_data(&(_pr->performance->status_register),
-                         &xen_perf->status_register);
-       xen_perf->flags |= XEN_PX_PCT;
-       xen_states = xen_copy_pss_data(_pr, xen_perf);
-       if (!IS_ERR_OR_NULL(xen_states)) {
-               set_xen_guest_handle(xen_perf->states, xen_states);
-               xen_perf->flags |= XEN_PX_PSS;
-       }
-       if (!xen_copy_psd_data(_pr, xen_perf))
-               xen_perf->flags |= XEN_PX_PSD;
-
-       if (!no_hypercall)
-               ret = HYPERVISOR_dom0_op(&op);
-
-       if (ret)
-               pr_err(DRV_NAME "(_PXX): Hypervisor returned (%d) for ACPI ID %d\n",
-                      ret, _pr->acpi_id);
-
-       if (!IS_ERR_OR_NULL(xen_states))
-               kfree(xen_states);
-
-       return ret;
-}
-/*
- * We read out the struct acpi_processor, and serialize access
- * so that there is only one caller. This is so that we won't
- * race with the CPU hotplug code (xen_cpu_soft_notify).
- */
-static int xen_process_data(struct acpi_processor *_pr)
-{
-       int err = 0;
-
-       mutex_lock(&acpi_ids_mutex);
-       if (__test_and_set_bit(_pr->acpi_id, acpi_ids_done)) {
-               mutex_unlock(&acpi_ids_mutex);
-               return -EBUSY;
-       }
-       if (_pr->flags.power)
-               err = xen_push_cxx_to_hypervisor(_pr);
-
-       if (_pr->performance && _pr->performance->states)
-               err |= xen_push_pxx_to_hypervisor(_pr);
-
-       mutex_unlock(&acpi_ids_mutex);
-       return err;
-}
-static acpi_status
-xen_read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-       u32 acpi_id;
-       acpi_status status;
-       acpi_object_type acpi_type;
-       unsigned long long tmp;
-       union acpi_object object = { 0 };
-       struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
-
-       status = acpi_get_type(handle, &acpi_type);
-       if (ACPI_FAILURE(status))
-               return AE_OK;
-
-       switch (acpi_type) {
-       case ACPI_TYPE_PROCESSOR:
-               status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
-               if (ACPI_FAILURE(status))
-                       return AE_OK;
-               acpi_id = object.processor.proc_id;
-               break;
-       case ACPI_TYPE_DEVICE:
-               status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
-               if (ACPI_FAILURE(status))
-                       return AE_OK;
-               acpi_id = tmp;
-               break;
-       default:
-               return AE_OK;
-       }
-       if (acpi_id > NR_ACPI_CPUS) {
-               WARN_ONCE(1, "There are %d ACPI processors, but kernel can only do %d!\n",
-                    acpi_id, NR_ACPI_CPUS);
-               return AE_OK;
-       }
-       __set_bit(acpi_id, acpi_id_present);
-
-       return AE_OK;
-}
-static unsigned int xen_acpi_ids_more(void)
-{
-       unsigned int n = 0;
-
-       acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
-                           ACPI_UINT32_MAX,
-                           xen_read_acpi_id, NULL, NULL, NULL);
-       acpi_get_devices("ACPI0007", xen_read_acpi_id, NULL, NULL);
-
-       mutex_lock(&acpi_ids_mutex);
-       if (!bitmap_equal(acpi_id_present, acpi_ids_done, MAX_ACPI_BITS))
-               n = bitmap_weight(acpi_id_present, MAX_ACPI_BITS);
-       mutex_unlock(&acpi_ids_mutex);
-
-       return n;
-}
-
-static int xen_processor_check(void)
-{
-       struct cpufreq_policy *policy;
-       struct acpi_processor *pr_backup = NULL;
-       int cpu, err = 0;
-
-       cpu = get_cpu();
-       put_cpu();
-       policy = cpufreq_cpu_get(cpu);
-       if (!policy)
-               return -EBUSY;
-
-       get_online_cpus();
-       for_each_online_cpu(cpu) {
-               struct acpi_processor *_pr;
-
-               _pr = per_cpu(processors, cpu /* APIC ID */);
-               if (!_pr)
-                       continue;
-
-               if (!pr_backup) {
-                       pr_backup = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
-                       memcpy(pr_backup, _pr, sizeof(struct acpi_processor));
-               }
-               (void)xen_process_data(_pr);
-       }
-       put_online_cpus();
-
-       cpufreq_cpu_put(policy);
-
-       /* All online CPUs have been processed at this stage. Now verify
-        * whether in fact "online CPUs" == physical CPUs.
-        */
-       acpi_id_present = kcalloc(MAX_ACPI_BITS, sizeof(unsigned long), GFP_KERNEL);
-       if (!acpi_id_present) {
-               err = -ENOMEM;
-               goto err_out;
-       }
-       memset(acpi_id_present, 0, MAX_ACPI_BITS * sizeof(unsigned long));
-
-       if (xen_acpi_ids_more() && pr_backup) {
-               for_each_set_bit(cpu, acpi_id_present, MAX_ACPI_BITS) {
-                       pr_backup->acpi_id = cpu;
-                       /* We will get -EBUSY if it has been programmed already. */
-                       (void)xen_process_data(pr_backup);
-               }
-       }
-       kfree(acpi_id_present);
-       acpi_id_present = NULL;
-err_out:
-       kfree(pr_backup);
-       pr_backup = NULL;
-       return err;
-}
-/*
- * The purpose of this timer/thread is to wait for the ACPI processor
- * and CPUfreq drivers to load up and parse the Pxx and Cxx information
- * before we attempt to read it.
- */
-static void xen_processor_timeout(unsigned long arg)
-{
-       wake_up_process((struct task_struct *)arg);
-}
-static int xen_processor_thread_func(void *dummy)
-{
-       struct timer_list timer;
-       int err = 0;
-
-       setup_deferrable_timer_on_stack(&timer, xen_processor_timeout,
-                                       (unsigned long)current);
-       do {
-               __set_current_state(TASK_INTERRUPTIBLE);
-               mod_timer(&timer, jiffies + POLL_TIMER);
-               schedule();
-               err = xen_processor_check();
-               if (err != -EBUSY)
-                       break;
-       } while (!kthread_should_stop());
-
-       if (err)
-               pr_err(DRV_NAME ": Failed to upload data (%d)!\n", err);
-       del_timer_sync(&timer);
-       destroy_timer_on_stack(&timer);
-       return 0;
-}
-
-static int xen_cpu_soft_notify(struct notifier_block *nfb,
-                              unsigned long action, void *hcpu)
-{
-       unsigned int cpu = (unsigned long)hcpu;
-       struct acpi_processor *_pr = per_cpu(processors, cpu);
-
-       if (action == CPU_ONLINE && _pr)
-               (void)xen_process_data(_pr);
-
-       return NOTIFY_OK;
-}
-
-static struct notifier_block xen_cpu_notifier = {
-       .notifier_call = xen_cpu_soft_notify,
-       .priority = -1, /* Be the last one */
-};
-
-static int __init check_prereq(void)
-{
-       struct cpuinfo_x86 *c = &cpu_data(0);
-
-       if (!xen_initial_domain())
-               return -ENODEV;
-
-       if (!acpi_gbl_FADT.smi_command)
-               return -ENODEV;
-
-       if (c->x86_vendor == X86_VENDOR_INTEL) {
-               if (!cpu_has(c, X86_FEATURE_EST))
-                       return -ENODEV;
-
-               return 0;
-       }
-       if (c->x86_vendor == X86_VENDOR_AMD) {
-               u32 hi = 0, lo = 0;
-               /* Copied from powernow-k8.h, can't include ../cpufreq/powernow
-                * as we get compile warnings for the static functions.
-                */
-#define MSR_PSTATE_CUR_LIMIT    0xc0010061 /* pstate current limit MSR */
-               rdmsr(MSR_PSTATE_CUR_LIMIT, lo, hi);
-
-               /* If the MSR cannot provide the data, the powernow-k8
-                * won't process the data properly either.
-                */
-               if (hi || lo)
-                       return 0;
-       }
-       return -ENODEV;
-}
-
-static int __init xen_processor_passthru_init(void)
-{
-       int rc = check_prereq();
-
-       if (rc)
-               return rc;
-
-       acpi_ids_done = kcalloc(MAX_ACPI_BITS, sizeof(unsigned long), GFP_KERNEL);
-       if (!acpi_ids_done)
-               return -ENOMEM;
-       memset(acpi_ids_done, 0, MAX_ACPI_BITS * sizeof(unsigned long));
-       xen_processor_thread = kthread_run(xen_processor_thread_func, NULL, DRV_NAME);
-       if (IS_ERR(xen_processor_thread)) {
-               pr_err(DRV_NAME ": Failed to create thread. Aborting.\n");
-               return -ENOMEM;
-       }
-       register_hotcpu_notifier(&xen_cpu_notifier);
-       return 0;
-}
-static void __exit xen_processor_passthru_exit(void)
-{
-       unregister_hotcpu_notifier(&xen_cpu_notifier);
-       if (xen_processor_thread)
-               kthread_stop(xen_processor_thread);
-       kfree(acpi_ids_done);
-}
-late_initcall(xen_processor_passthru_init);
-module_exit(xen_processor_passthru_exit);