[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [linux-2.6.18-xen] merge with linux-2.6.18-xen.hg



# HG changeset patch
# User Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
# Date 1221567954 -32400
# Node ID 7d032c5bb346a7254f364f9692437d49504259ce
# Parent  6fcc6c1e87f612b16cff3ef967e0afd0abdd8f9b
# Parent  8ca4d2b16eb3c3ee4ec670c392a2e129163754ee
merge with linux-2.6.18-xen.hg
---
 arch/i386/kernel/acpi/processor_extcntl_xen.c   |   96 +-
 arch/i386/kernel/io_apic-xen.c                  |    3 
 arch/x86_64/kernel/io_apic-xen.c                |    3 
 buildconfigs/linux-defconfig_xen0_x86_32        |    2 
 buildconfigs/linux-defconfig_xen0_x86_64        |    2 
 buildconfigs/linux-defconfig_xen_x86_32         |    2 
 buildconfigs/linux-defconfig_xen_x86_64         |    2 
 drivers/acpi/processor_core.c                   |    7 
 drivers/acpi/processor_extcntl.c                |   17 
 drivers/acpi/processor_throttling.c             | 1049 ++++++++++++++++++++++--
 drivers/pci/msi-xen.c                           |   28 
 drivers/xen/blktap/common.h                     |    1 
 drivers/xen/blktap/interface.c                  |    7 
 drivers/xen/blktap/xenbus.c                     |    2 
 drivers/xen/core/evtchn.c                       |  157 ++-
 drivers/xen/pciback/conf_space_capability_msi.c |   30 
 drivers/xen/xenoprof/xenoprofile.c              |   27 
 include/acpi/processor.h                        |   59 +
 include/asm-i386/mach-xen/irq_vectors.h         |   14 
 include/asm-ia64/irq.h                          |    6 
 include/asm-powerpc/xen/asm/hypervisor.h        |    7 
 include/asm-x86_64/mach-xen/irq_vectors.h       |    6 
 include/xen/evtchn.h                            |    7 
 include/xen/interface/memory.h                  |   17 
 include/xen/interface/platform.h                |    4 
 25 files changed, 1340 insertions(+), 215 deletions(-)

diff -r 6fcc6c1e87f6 -r 7d032c5bb346 
arch/i386/kernel/acpi/processor_extcntl_xen.c
--- a/arch/i386/kernel/acpi/processor_extcntl_xen.c     Fri Sep 12 11:28:00 
2008 +0900
+++ b/arch/i386/kernel/acpi/processor_extcntl_xen.c     Tue Sep 16 21:25:54 
2008 +0900
@@ -31,8 +31,6 @@
 #include <linux/cpufreq.h>
 #include <acpi/processor.h>
 #include <asm/hypercall.h>
-
-static int xen_processor_pmbits;
 
 static int xen_cx_notifier(struct acpi_processor *pr, int action)
 {
@@ -143,7 +141,7 @@ static void convert_psd_pack(struct xen_
 
 static int xen_px_notifier(struct acpi_processor *pr, int action)
 {
-       int ret;
+       int ret = -EINVAL;
        xen_platform_op_t op = {
                .cmd                    = XENPF_set_processor_pminfo,
                .interface_version      = XENPF_INTERFACE_VERSION,
@@ -155,48 +153,66 @@ static int xen_px_notifier(struct acpi_p
        struct acpi_processor_performance *px;
        struct acpi_psd_package *pdomain;
 
-       /* leave dynamic ppc handle in the future */
-       if (action == PROCESSOR_PM_CHANGE)
-               return 0;
+       if (!pr)
+               return -EINVAL;
 
        perf = &op.u.set_pminfo.perf;
        px = pr->performance;
 
-       perf->flags = XEN_PX_PPC | 
-                     XEN_PX_PCT | 
-                     XEN_PX_PSS | 
-                     XEN_PX_PSD;
-
-       /* ppc */
-       perf->ppc = pr->performance_platform_limit;
-
-       /* pct */
-       convert_pct_reg(&perf->control_register, &px->control_register);
-       convert_pct_reg(&perf->status_register, &px->status_register);
-
-       /* pss */
-       perf->state_count = px->state_count;
-       states = kzalloc(px->state_count*sizeof(xen_processor_px_t),GFP_KERNEL);
-       if (!states)
-               return -ENOMEM;
-       convert_pss_states(states, px->states, px->state_count);
-       set_xen_guest_handle(perf->states, states);
-
-       /* psd */
-       pdomain = &px->domain_info;
-       convert_psd_pack(&perf->domain_info, pdomain);
-       if (perf->domain_info.num_processors) {
+       switch(action) {
+       case PROCESSOR_PM_CHANGE:
+               /* ppc dynamic handle */
+               perf->flags = XEN_PX_PPC;
+               perf->platform_limit = pr->performance_platform_limit;
+
+               ret = HYPERVISOR_platform_op(&op);
+               break;
+
+       case PROCESSOR_PM_INIT:
+               /* px normal init */
+               perf->flags = XEN_PX_PPC | 
+                             XEN_PX_PCT | 
+                             XEN_PX_PSS | 
+                             XEN_PX_PSD;
+
+               /* ppc */
+               perf->platform_limit = pr->performance_platform_limit;
+
+               /* pct */
+               convert_pct_reg(&perf->control_register, &px->control_register);
+               convert_pct_reg(&perf->status_register, &px->status_register);
+
+               /* pss */
+               perf->state_count = px->state_count;
+               states = 
kzalloc(px->state_count*sizeof(xen_processor_px_t),GFP_KERNEL);
+               if (!states)
+                       return -ENOMEM;
+               convert_pss_states(states, px->states, px->state_count);
+               set_xen_guest_handle(perf->states, states);
+
+               /* psd */
+               pdomain = &px->domain_info;
+               convert_psd_pack(&perf->domain_info, pdomain);
                if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL)
                        perf->shared_type = CPUFREQ_SHARED_TYPE_ALL;
                else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY)
                        perf->shared_type = CPUFREQ_SHARED_TYPE_ANY;
                else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL)
                        perf->shared_type = CPUFREQ_SHARED_TYPE_HW;
-       } else
-               perf->shared_type = CPUFREQ_SHARED_TYPE_NONE;
-
-       ret = HYPERVISOR_platform_op(&op);
-       kfree(states);
+               else {
+                       ret = -ENODEV;
+                       kfree(states);
+                       break;
+               }
+
+               ret = HYPERVISOR_platform_op(&op);
+               kfree(states);
+               break;
+
+       default:
+               break;
+       }
+
        return ret;
 }
 
@@ -215,13 +231,13 @@ static struct processor_extcntl_ops xen_
 
 void arch_acpi_processor_init_extcntl(const struct processor_extcntl_ops **ops)
 {
-       xen_processor_pmbits = (xen_start_info->flags & SIF_PM_MASK) >> 8;
-
-       if (xen_processor_pmbits & XEN_PROCESSOR_PM_CX)
+       unsigned int pmbits = (xen_start_info->flags & SIF_PM_MASK) >> 8;
+
+       if (pmbits & XEN_PROCESSOR_PM_CX)
                xen_extcntl_ops.pm_ops[PM_TYPE_IDLE] = xen_cx_notifier;
-       if (xen_processor_pmbits & XEN_PROCESSOR_PM_PX)
+       if (pmbits & XEN_PROCESSOR_PM_PX)
                xen_extcntl_ops.pm_ops[PM_TYPE_PERF] = xen_px_notifier;
-       if (xen_processor_pmbits & XEN_PROCESSOR_PM_TX)
+       if (pmbits & XEN_PROCESSOR_PM_TX)
                xen_extcntl_ops.pm_ops[PM_TYPE_THR] = xen_tx_notifier;
 
        *ops = &xen_extcntl_ops;
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 arch/i386/kernel/io_apic-xen.c
--- a/arch/i386/kernel/io_apic-xen.c    Fri Sep 12 11:28:00 2008 +0900
+++ b/arch/i386/kernel/io_apic-xen.c    Tue Sep 16 21:25:54 2008 +0900
@@ -47,6 +47,7 @@
 
 #include <xen/interface/xen.h>
 #include <xen/interface/physdev.h>
+#include <xen/evtchn.h>
 
 /* Fake i8259 */
 #define make_8259A_irq(_irq)     (io_apic_irqs &= ~(1UL<<(_irq)))
@@ -1260,7 +1261,7 @@ static void ioapic_register_intr(int irq
        set_intr_gate(vector, interrupt[idx]);
 }
 #else
-#define ioapic_register_intr(_irq,_vector,_trigger) ((void)0)
+#define ioapic_register_intr(irq, vector, trigger) evtchn_register_pirq(irq)
 #endif
 
 static void __init setup_IO_APIC_irqs(void)
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 arch/x86_64/kernel/io_apic-xen.c
--- a/arch/x86_64/kernel/io_apic-xen.c  Fri Sep 12 11:28:00 2008 +0900
+++ b/arch/x86_64/kernel/io_apic-xen.c  Tue Sep 16 21:25:54 2008 +0900
@@ -95,6 +95,7 @@ int vector_irq[NR_VECTORS] __read_mostly
 
 #include <xen/interface/xen.h>
 #include <xen/interface/physdev.h>
+#include <xen/evtchn.h>
 
 /* Fake i8259 */
 #define make_8259A_irq(_irq)     (io_apic_irqs &= ~(1UL<<(_irq)))
@@ -940,7 +941,7 @@ static void ioapic_register_intr(int irq
        set_intr_gate(vector, interrupt[idx]);
 }
 #else
-#define ioapic_register_intr(_irq,_vector,_trigger) ((void)0)
+#define ioapic_register_intr(irq, vector, trigger) evtchn_register_pirq(irq)
 #endif /* !CONFIG_XEN */
 
 static void __init setup_IO_APIC_irqs(void)
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 buildconfigs/linux-defconfig_xen0_x86_32
--- a/buildconfigs/linux-defconfig_xen0_x86_32  Fri Sep 12 11:28:00 2008 +0900
+++ b/buildconfigs/linux-defconfig_xen0_x86_32  Tue Sep 16 21:25:54 2008 +0900
@@ -248,7 +248,7 @@ CONFIG_XEN_PCIDEV_FRONTEND=y
 CONFIG_XEN_PCIDEV_FRONTEND=y
 # CONFIG_XEN_PCIDEV_FE_DEBUG is not set
 # CONFIG_PCIEPORTBUS is not set
-# CONFIG_PCI_MSI is not set
+CONFIG_PCI_MSI=y
 # CONFIG_PCI_DEBUG is not set
 CONFIG_ISA_DMA_API=y
 # CONFIG_SCx200 is not set
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 buildconfigs/linux-defconfig_xen0_x86_64
--- a/buildconfigs/linux-defconfig_xen0_x86_64  Fri Sep 12 11:28:00 2008 +0900
+++ b/buildconfigs/linux-defconfig_xen0_x86_64  Tue Sep 16 21:25:54 2008 +0900
@@ -204,7 +204,7 @@ CONFIG_XEN_PCIDEV_FRONTEND=y
 CONFIG_XEN_PCIDEV_FRONTEND=y
 # CONFIG_XEN_PCIDEV_FE_DEBUG is not set
 # CONFIG_PCIEPORTBUS is not set
-# CONFIG_PCI_MSI is not set
+CONFIG_PCI_MSI=y
 # CONFIG_PCI_DEBUG is not set
 
 #
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 buildconfigs/linux-defconfig_xen_x86_32
--- a/buildconfigs/linux-defconfig_xen_x86_32   Fri Sep 12 11:28:00 2008 +0900
+++ b/buildconfigs/linux-defconfig_xen_x86_32   Tue Sep 16 21:25:54 2008 +0900
@@ -254,7 +254,7 @@ CONFIG_XEN_PCIDEV_FRONTEND=y
 CONFIG_XEN_PCIDEV_FRONTEND=y
 # CONFIG_XEN_PCIDEV_FE_DEBUG is not set
 # CONFIG_PCIEPORTBUS is not set
-# CONFIG_PCI_MSI is not set
+CONFIG_PCI_MSI=y
 # CONFIG_PCI_DEBUG is not set
 CONFIG_ISA_DMA_API=y
 CONFIG_SCx200=m
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 buildconfigs/linux-defconfig_xen_x86_64
--- a/buildconfigs/linux-defconfig_xen_x86_64   Fri Sep 12 11:28:00 2008 +0900
+++ b/buildconfigs/linux-defconfig_xen_x86_64   Tue Sep 16 21:25:54 2008 +0900
@@ -209,7 +209,7 @@ CONFIG_XEN_PCIDEV_FRONTEND=y
 CONFIG_XEN_PCIDEV_FRONTEND=y
 # CONFIG_XEN_PCIDEV_FE_DEBUG is not set
 # CONFIG_PCIEPORTBUS is not set
-# CONFIG_PCI_MSI is not set
+CONFIG_PCI_MSI=y
 # CONFIG_PCI_DEBUG is not set
 
 #
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 drivers/acpi/processor_core.c
--- a/drivers/acpi/processor_core.c     Fri Sep 12 11:28:00 2008 +0900
+++ b/drivers/acpi/processor_core.c     Tue Sep 16 21:25:54 2008 +0900
@@ -67,6 +67,7 @@
 #define ACPI_PROCESSOR_FILE_LIMIT      "limit"
 #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
 #define ACPI_PROCESSOR_NOTIFY_POWER    0x81
+#define ACPI_PROCESSOR_NOTIFY_THROTTLING     0x82
 
 #define ACPI_PROCESSOR_LIMIT_USER      0
 #define ACPI_PROCESSOR_LIMIT_THERMAL   1
@@ -618,6 +619,10 @@ static void acpi_processor_notify(acpi_h
                acpi_processor_cst_has_changed(pr);
                acpi_bus_generate_event(device, event, 0);
                break;
+       case ACPI_PROCESSOR_NOTIFY_THROTTLING:
+               acpi_processor_tstate_has_changed(pr);
+               acpi_bus_generate_event(device, event, 0);
+               break;
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Unsupported event [0x%x]\n", event));
@@ -965,6 +970,8 @@ static int __init acpi_processor_init(vo
 
        acpi_processor_ppc_init();
 
+       acpi_processor_throttling_init();
+
        return 0;
 }
 
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 drivers/acpi/processor_extcntl.c
--- a/drivers/acpi/processor_extcntl.c  Fri Sep 12 11:28:00 2008 +0900
+++ b/drivers/acpi/processor_extcntl.c  Tue Sep 16 21:25:54 2008 +0900
@@ -203,13 +203,22 @@ static int processor_extcntl_get_perform
         * processor objects to external logic. In this case, it's preferred
         * to use ACPI ID instead.
         */
-       pr->performance->domain_info.num_processors = 0;
+       pdomain = &pr->performance->domain_info;
+       pdomain->num_processors = 0;
        ret = acpi_processor_get_psd(pr);
-       if (ret < 0)
-               goto err_out;
+       if (ret < 0) {
+               /*
+                * _PSD is optional - assume no coordination if absent (or
+                * broken), matching native kernels' behavior.
+                */
+               pdomain->num_entries = ACPI_PSD_REV0_ENTRIES;
+               pdomain->revision = ACPI_PSD_REV0_REVISION;
+               pdomain->domain = pr->acpi_id;
+               pdomain->coord_type = DOMAIN_COORD_TYPE_SW_ALL;
+               pdomain->num_processors = 1;
+       }
 
        /* Some sanity check */
-       pdomain = &pr->performance->domain_info;
        if ((pdomain->revision != ACPI_PSD_REV0_REVISION) ||
            (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) ||
            ((pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL) &&
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 drivers/acpi/processor_throttling.c
--- a/drivers/acpi/processor_throttling.c       Fri Sep 12 11:28:00 2008 +0900
+++ b/drivers/acpi/processor_throttling.c       Tue Sep 16 21:25:54 2008 +0900
@@ -29,6 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 #include <linux/cpufreq.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
@@ -41,21 +42,559 @@
 
 #define ACPI_PROCESSOR_COMPONENT        0x01000000
 #define ACPI_PROCESSOR_CLASS            "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME      "ACPI Processor Driver"
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_throttling");
+
+struct throttling_tstate {
+       unsigned int cpu;               /* cpu nr */
+       int target_state;               /* target T-state */
+};
+
+#define THROTTLING_PRECHANGE       (1)
+#define THROTTLING_POSTCHANGE      (2)
+
+static int acpi_processor_get_throttling(struct acpi_processor *pr);
+int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
+
+static int acpi_processor_update_tsd_coord(void)
+{
+       int count, count_target;
+       int retval = 0;
+       unsigned int i, j;
+       cpumask_t covered_cpus;
+       struct acpi_processor *pr, *match_pr;
+       struct acpi_tsd_package *pdomain, *match_pdomain;
+       struct acpi_processor_throttling *pthrottling, *match_pthrottling;
+
+       /*
+        * Now that we have _TSD data from all CPUs, lets setup T-state
+        * coordination between all CPUs.
+        */
+       for_each_possible_cpu(i) {
+               pr = processors[i];
+               if (!pr)
+                       continue;
+
+               /* Basic validity check for domain info */
+               pthrottling = &(pr->throttling);
+
+               /*
+                * If tsd package for one cpu is invalid, the coordination
+                * among all CPUs is thought as invalid.
+                * Maybe it is ugly.
+                */
+               if (!pthrottling->tsd_valid_flag) {
+                       retval = -EINVAL;
+                       break;
+               }
+       }
+       if (retval)
+               goto err_ret;
+
+       cpus_clear(covered_cpus);
+       for_each_possible_cpu(i) {
+               pr = processors[i];
+               if (!pr)
+                       continue;
+
+               if (cpu_isset(i, covered_cpus))
+                       continue;
+               pthrottling = &pr->throttling;
+
+               pdomain = &(pthrottling->domain_info);
+               cpu_set(i, pthrottling->shared_cpu_map);
+               cpu_set(i, covered_cpus);
+               /*
+                * If the number of processor in the TSD domain is 1, it is
+                * unnecessary to parse the coordination for this CPU.
+                */
+               if (pdomain->num_processors <= 1)
+                       continue;
+
+               /* Validate the Domain info */
+               count_target = pdomain->num_processors;
+               count = 1;
+
+               for_each_possible_cpu(j) {
+                       if (i == j)
+                               continue;
+
+                       match_pr = processors[j];
+                       if (!match_pr)
+                               continue;
+
+                       match_pthrottling = &(match_pr->throttling);
+                       match_pdomain = &(match_pthrottling->domain_info);
+                       if (match_pdomain->domain != pdomain->domain)
+                               continue;
+
+                       /* Here i and j are in the same domain.
+                        * If two TSD packages have the same domain, they
+                        * should have the same num_porcessors and
+                        * coordination type. Otherwise it will be regarded
+                        * as illegal.
+                        */
+                       if (match_pdomain->num_processors != count_target) {
+                               retval = -EINVAL;
+                               goto err_ret;
+                       }
+
+                       if (pdomain->coord_type != match_pdomain->coord_type) {
+                               retval = -EINVAL;
+                               goto err_ret;
+                       }
+
+                       cpu_set(j, covered_cpus);
+                       cpu_set(j, pthrottling->shared_cpu_map);
+                       count++;
+               }
+               for_each_possible_cpu(j) {
+                       if (i == j)
+                               continue;
+
+                       match_pr = processors[j];
+                       if (!match_pr)
+                               continue;
+
+                       match_pthrottling = &(match_pr->throttling);
+                       match_pdomain = &(match_pthrottling->domain_info);
+                       if (match_pdomain->domain != pdomain->domain)
+                               continue;
+
+                       /*
+                        * If some CPUS have the same domain, they
+                        * will have the same shared_cpu_map.
+                        */
+                       match_pthrottling->shared_cpu_map =
+                               pthrottling->shared_cpu_map;
+               }
+       }
+
+err_ret:
+       for_each_possible_cpu(i) {
+               pr = processors[i];
+               if (!pr)
+                       continue;
+
+               /*
+                * Assume no coordination on any error parsing domain info.
+                * The coordination type will be forced as SW_ALL.
+                */
+               if (retval) {
+                       pthrottling = &(pr->throttling);
+                       cpus_clear(pthrottling->shared_cpu_map);
+                       cpu_set(i, pthrottling->shared_cpu_map);
+                       pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
+               }
+       }
+
+       return retval;
+}
+
+/*
+ * Update the T-state coordination after the _TSD
+ * data for all cpus is obtained.
+ */
+void acpi_processor_throttling_init(void)
+{
+       if (acpi_processor_update_tsd_coord())
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                       "Assume no T-state coordination\n"));
+
+       return;
+}
+
+static int acpi_processor_throttling_notifier(unsigned long event, void *data)
+{
+       struct throttling_tstate *p_tstate = data;
+       struct acpi_processor *pr;
+       unsigned int cpu ;
+       int target_state;
+       struct acpi_processor_limit *p_limit;
+       struct acpi_processor_throttling *p_throttling;
+
+       cpu = p_tstate->cpu;
+       pr = processors[cpu];
+       if (!pr) {
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid pr pointer\n"));
+               return 0;
+       }
+       if (!pr->flags.throttling) {
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Throttling control is "
+                               "unsupported on CPU %d\n", cpu));
+               return 0;
+       }
+       target_state = p_tstate->target_state;
+       p_throttling = &(pr->throttling);
+       switch (event) {
+       case THROTTLING_PRECHANGE:
+               /*
+                * Prechange event is used to choose one proper t-state,
+                * which meets the limits of thermal, user and _TPC.
+                */
+               p_limit = &pr->limit;
+               if (p_limit->thermal.tx > target_state)
+                       target_state = p_limit->thermal.tx;
+               if (p_limit->user.tx > target_state)
+                       target_state = p_limit->user.tx;
+               if (pr->throttling_platform_limit > target_state)
+                       target_state = pr->throttling_platform_limit;
+               if (target_state >= p_throttling->state_count) {
+                       printk(KERN_WARNING
+                               "Exceed the limit of T-state \n");
+                       target_state = p_throttling->state_count - 1;
+               }
+               p_tstate->target_state = target_state;
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PreChange Event:"
+                               "target T-state of CPU %d is T%d\n",
+                               cpu, target_state));
+               break;
+       case THROTTLING_POSTCHANGE:
+               /*
+                * Postchange event is only used to update the
+                * T-state flag of acpi_processor_throttling.
+                */
+               p_throttling->state = target_state;
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PostChange Event:"
+                               "CPU %d is switched to T%d\n",
+                               cpu, target_state));
+               break;
+       default:
+               printk(KERN_WARNING
+                       "Unsupported Throttling notifier event\n");
+               break;
+       }
+
+       return 0;
+}
+
+/*
+ * _TPC - Throttling Present Capabilities
+ */
+static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
+{
+       acpi_status status = 0;
+       unsigned long tpc = 0;
+
+       if (!pr)
+               return -EINVAL;
+       status = acpi_evaluate_integer(pr->handle, "_TPC", NULL, &tpc);
+       if (ACPI_FAILURE(status)) {
+               if (status != AE_NOT_FOUND) {
+                       ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TPC"));
+               }
+               return -ENODEV;
+       }
+       pr->throttling_platform_limit = (int)tpc;
+       return 0;
+}
+
+int acpi_processor_tstate_has_changed(struct acpi_processor *pr)
+{
+       int result = 0;
+       int throttling_limit;
+       int current_state;
+       struct acpi_processor_limit *limit;
+       int target_state;
+
+       result = acpi_processor_get_platform_limit(pr);
+       if (result) {
+               /* Throttling Limit is unsupported */
+               return result;
+       }
+
+       throttling_limit = pr->throttling_platform_limit;
+       if (throttling_limit >= pr->throttling.state_count) {
+               /* Uncorrect Throttling Limit */
+               return -EINVAL;
+       }
+
+       current_state = pr->throttling.state;
+       if (current_state > throttling_limit) {
+               /*
+                * The current state can meet the requirement of
+                * _TPC limit. But it is reasonable that OSPM changes
+                * t-states from high to low for better performance.
+                * Of course the limit condition of thermal
+                * and user should be considered.
+                */
+               limit = &pr->limit;
+               target_state = throttling_limit;
+               if (limit->thermal.tx > target_state)
+                       target_state = limit->thermal.tx;
+               if (limit->user.tx > target_state)
+                       target_state = limit->user.tx;
+       } else if (current_state == throttling_limit) {
+               /*
+                * Unnecessary to change the throttling state
+                */
+               return 0;
+       } else {
+               /*
+                * If the current state is lower than the limit of _TPC, it
+                * will be forced to switch to the throttling state defined
+                * by throttling_platfor_limit.
+                * Because the previous state meets with the limit condition
+                * of thermal and user, it is unnecessary to check it again.
+                */
+               target_state = throttling_limit;
+       }
+       return acpi_processor_set_throttling(pr, target_state);
+}
+
+/*
+ * _PTC - Processor Throttling Control (and status) register location
+ */
+static int acpi_processor_get_throttling_control(struct acpi_processor *pr)
+{
+       int result = 0;
+       acpi_status status = 0;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *ptc = NULL;
+       union acpi_object obj = { 0 };
+       struct acpi_processor_throttling *throttling;
+
+       status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer);
+       if (ACPI_FAILURE(status)) {
+               if (status != AE_NOT_FOUND) {
+                       ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PTC"));
+               }
+               return -ENODEV;
+       }
+
+       ptc = (union acpi_object *)buffer.pointer;
+       if (!ptc || (ptc->type != ACPI_TYPE_PACKAGE)
+           || (ptc->package.count != 2)) {
+               printk(KERN_ERR PREFIX "Invalid _PTC data\n");
+               result = -EFAULT;
+               goto end;
+       }
+
+       /*
+        * control_register
+        */
+
+       obj = ptc->package.elements[0];
+
+       if ((obj.type != ACPI_TYPE_BUFFER)
+           || (obj.buffer.length < sizeof(struct acpi_ptc_register))
+           || (obj.buffer.pointer == NULL)) {
+               printk(KERN_ERR PREFIX
+                      "Invalid _PTC data (control_register)\n");
+               result = -EFAULT;
+               goto end;
+       }
+       memcpy(&pr->throttling.control_register, obj.buffer.pointer,
+              sizeof(struct acpi_ptc_register));
+
+       /*
+        * status_register
+        */
+
+       obj = ptc->package.elements[1];
+
+       if ((obj.type != ACPI_TYPE_BUFFER)
+           || (obj.buffer.length < sizeof(struct acpi_ptc_register))
+           || (obj.buffer.pointer == NULL)) {
+               printk(KERN_ERR PREFIX "Invalid _PTC data (status_register)\n");
+               result = -EFAULT;
+               goto end;
+       }
+
+       memcpy(&pr->throttling.status_register, obj.buffer.pointer,
+              sizeof(struct acpi_ptc_register));
+
+       throttling = &pr->throttling;
+
+       if ((throttling->control_register.bit_width +
+               throttling->control_register.bit_offset) > 32) {
+               printk(KERN_ERR PREFIX "Invalid _PTC control register\n");
+               result = -EFAULT;
+               goto end;
+       }
+
+       if ((throttling->status_register.bit_width +
+               throttling->status_register.bit_offset) > 32) {
+               printk(KERN_ERR PREFIX "Invalid _PTC status register\n");
+               result = -EFAULT;
+               goto end;
+       }
+
+      end:
+       kfree(buffer.pointer);
+
+       return result;
+}
+
+/*
+ * _TSS - Throttling Supported States
+ */
+static int acpi_processor_get_throttling_states(struct acpi_processor *pr)
+{
+       int result = 0;
+       acpi_status status = AE_OK;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" };
+       struct acpi_buffer state = { 0, NULL };
+       union acpi_object *tss = NULL;
+       int i;
+
+       status = acpi_evaluate_object(pr->handle, "_TSS", NULL, &buffer);
+       if (ACPI_FAILURE(status)) {
+               if (status != AE_NOT_FOUND) {
+                       ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TSS"));
+               }
+               return -ENODEV;
+       }
+
+       tss = buffer.pointer;
+       if (!tss || (tss->type != ACPI_TYPE_PACKAGE)) {
+               printk(KERN_ERR PREFIX "Invalid _TSS data\n");
+               result = -EFAULT;
+               goto end;
+       }
+
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n",
+                         tss->package.count));
+
+       pr->throttling.state_count = tss->package.count;
+       pr->throttling.states_tss =
+           kmalloc(sizeof(struct acpi_processor_tx_tss) * tss->package.count,
+                   GFP_KERNEL);
+       if (!pr->throttling.states_tss) {
+               result = -ENOMEM;
+               goto end;
+       }
+
+       for (i = 0; i < pr->throttling.state_count; i++) {
+
+               struct acpi_processor_tx_tss *tx =
+                   (struct acpi_processor_tx_tss *)&(pr->throttling.
+                                                     states_tss[i]);
+
+               state.length = sizeof(struct acpi_processor_tx_tss);
+               state.pointer = tx;
+
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
+
+               status = acpi_extract_package(&(tss->package.elements[i]),
+                                             &format, &state);
+               if (ACPI_FAILURE(status)) {
+                       ACPI_EXCEPTION((AE_INFO, status, "Invalid _TSS data"));
+                       result = -EFAULT;
+                       kfree(pr->throttling.states_tss);
+                       goto end;
+               }
+
+               if (!tx->freqpercentage) {
+                       printk(KERN_ERR PREFIX
+                              "Invalid _TSS data: freq is zero\n");
+                       result = -EFAULT;
+                       kfree(pr->throttling.states_tss);
+                       goto end;
+               }
+       }
+
+      end:
+       kfree(buffer.pointer);
+
+       return result;
+}
+
+/*
+ * _TSD - T-State Dependencies
+ */
+static int acpi_processor_get_tsd(struct acpi_processor *pr)
+{
+       int result = 0;
+       acpi_status status = AE_OK;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" };
+       struct acpi_buffer state = { 0, NULL };
+       union acpi_object *tsd = NULL;
+       struct acpi_tsd_package *pdomain;
+       struct acpi_processor_throttling *pthrottling;
+
+       pthrottling = &pr->throttling;
+       pthrottling->tsd_valid_flag = 0;
+
+       status = acpi_evaluate_object(pr->handle, "_TSD", NULL, &buffer);
+       if (ACPI_FAILURE(status)) {
+               if (status != AE_NOT_FOUND) {
+                       ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TSD"));
+               }
+               return -ENODEV;
+       }
+
+       tsd = buffer.pointer;
+       if (!tsd || (tsd->type != ACPI_TYPE_PACKAGE)) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
+               result = -EFAULT;
+               goto end;
+       }
+
+       if (tsd->package.count != 1) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
+               result = -EFAULT;
+               goto end;
+       }
+
+       pdomain = &(pr->throttling.domain_info);
+
+       state.length = sizeof(struct acpi_tsd_package);
+       state.pointer = pdomain;
+
+       status = acpi_extract_package(&(tsd->package.elements[0]),
+                                     &format, &state);
+       if (ACPI_FAILURE(status)) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
+               result = -EFAULT;
+               goto end;
+       }
+
+       if (pdomain->num_entries != ACPI_TSD_REV0_ENTRIES) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:num_entries\n"));
+               result = -EFAULT;
+               goto end;
+       }
+
+       if (pdomain->revision != ACPI_TSD_REV0_REVISION) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:revision\n"));
+               result = -EFAULT;
+               goto end;
+       }
+
+       pthrottling = &pr->throttling;
+       pthrottling->tsd_valid_flag = 1;
+       pthrottling->shared_type = pdomain->coord_type;
+       cpu_set(pr->id, pthrottling->shared_cpu_map);
+       /*
+        * If the coordination type is not defined in ACPI spec,
+        * the tsd_valid_flag will be clear and coordination type
+        * will be forecd as DOMAIN_COORD_TYPE_SW_ALL.
+        */
+       if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL &&
+               pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY &&
+               pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) {
+               pthrottling->tsd_valid_flag = 0;
+               pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
+       }
+
+      end:
+       kfree(buffer.pointer);
+       return result;
+}
 
 /* --------------------------------------------------------------------------
                               Throttling Control
    -------------------------------------------------------------------------- 
*/
-static int acpi_processor_get_throttling(struct acpi_processor *pr)
+static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr)
 {
        int state = 0;
        u32 value = 0;
        u32 duty_mask = 0;
        u32 duty_value = 0;
 
-
        if (!pr)
                return -EINVAL;
 
@@ -95,13 +634,259 @@ static int acpi_processor_get_throttling
        return 0;
 }
 
-int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
+#ifdef CONFIG_X86
+static int acpi_throttling_rdmsr(struct acpi_processor *pr,
+                                       acpi_integer * value)
+{
+       struct cpuinfo_x86 *c;
+       u64 msr_high, msr_low;
+       unsigned int cpu;
+       u64 msr = 0;
+       int ret = -1;
+
+       cpu = pr->id;
+       c = &cpu_data[cpu];
+
+       if ((c->x86_vendor != X86_VENDOR_INTEL) ||
+               !cpu_has(c, X86_FEATURE_ACPI)) {
+               printk(KERN_ERR PREFIX
+                       "HARDWARE addr space,NOT supported yet\n");
+       } else {
+               msr_low = 0;
+               msr_high = 0;
+               rdmsr_safe(MSR_IA32_THERM_CONTROL,
+                       (u32 *)&msr_low , (u32 *) &msr_high);
+               msr = (msr_high << 32) | msr_low;
+               *value = (acpi_integer) msr;
+               ret = 0;
+       }
+       return ret;
+}
+
+static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value)
+{
+       struct cpuinfo_x86 *c;
+       unsigned int cpu;
+       int ret = -1;
+       u64 msr;
+
+       cpu = pr->id;
+       c = &cpu_data[cpu];
+
+       if ((c->x86_vendor != X86_VENDOR_INTEL) ||
+               !cpu_has(c, X86_FEATURE_ACPI)) {
+               printk(KERN_ERR PREFIX
+                       "HARDWARE addr space,NOT supported yet\n");
+       } else {
+               msr = value;
+               wrmsr_safe(MSR_IA32_THERM_CONTROL,
+                          (u32)msr, (u32)(msr >> 32));
+               ret = 0;
+       }
+       return ret;
+}
+#else
+static int acpi_throttling_rdmsr(struct acpi_processor *pr,
+                               acpi_integer * value)
+{
+       printk(KERN_ERR PREFIX
+               "HARDWARE addr space,NOT supported yet\n");
+       return -1;
+}
+
+static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value)
+{
+       printk(KERN_ERR PREFIX
+               "HARDWARE addr space,NOT supported yet\n");
+       return -1;
+}
+#endif
+
+static int acpi_read_throttling_status(struct acpi_processor *pr,
+                                       acpi_integer *value)
+{
+       u32 bit_width, bit_offset;
+       u64 ptc_value;
+       u64 ptc_mask;
+       struct acpi_processor_throttling *throttling;
+       int ret = -1;
+
+       throttling = &pr->throttling;
+       switch (throttling->status_register.space_id) {
+       case ACPI_ADR_SPACE_SYSTEM_IO:
+               ptc_value = 0;
+               bit_width = throttling->status_register.bit_width;
+               bit_offset = throttling->status_register.bit_offset;
+
+               acpi_os_read_port((acpi_io_address) throttling->status_register.
+                                 address, (u32 *) &ptc_value,
+                                 (u32) (bit_width + bit_offset));
+               ptc_mask = (1 << bit_width) - 1;
+               *value = (acpi_integer) ((ptc_value >> bit_offset) & ptc_mask);
+               ret = 0;
+               break;
+       case ACPI_ADR_SPACE_FIXED_HARDWARE:
+               ret = acpi_throttling_rdmsr(pr, value);
+               break;
+       default:
+               printk(KERN_ERR PREFIX "Unknown addr space %d\n",
+                      (u32) (throttling->status_register.space_id));
+       }
+       return ret;
+}
+
+static int acpi_write_throttling_state(struct acpi_processor *pr,
+                               acpi_integer value)
+{
+       u32 bit_width, bit_offset;
+       u64 ptc_value;
+       u64 ptc_mask;
+       struct acpi_processor_throttling *throttling;
+       int ret = -1;
+
+       throttling = &pr->throttling;
+       switch (throttling->control_register.space_id) {
+       case ACPI_ADR_SPACE_SYSTEM_IO:
+               bit_width = throttling->control_register.bit_width;
+               bit_offset = throttling->control_register.bit_offset;
+               ptc_mask = (1 << bit_width) - 1;
+               ptc_value = value & ptc_mask;
+
+               acpi_os_write_port((acpi_io_address) throttling->
+                                       control_register.address,
+                                       (u32) (ptc_value << bit_offset),
+                                       (u32) (bit_width + bit_offset));
+               ret = 0;
+               break;
+       case ACPI_ADR_SPACE_FIXED_HARDWARE:
+               ret = acpi_throttling_wrmsr(pr, value);
+               break;
+       default:
+               printk(KERN_ERR PREFIX "Unknown addr space %d\n",
+                      (u32) (throttling->control_register.space_id));
+       }
+       return ret;
+}
+
+static int acpi_get_throttling_state(struct acpi_processor *pr,
+                               acpi_integer value)
+{
+       int i;
+
+       for (i = 0; i < pr->throttling.state_count; i++) {
+               struct acpi_processor_tx_tss *tx =
+                   (struct acpi_processor_tx_tss *)&(pr->throttling.
+                                                     states_tss[i]);
+               if (tx->control == value)
+                       break;
+       }
+       if (i > pr->throttling.state_count)
+               i = -1;
+       return i;
+}
+
+static int acpi_get_throttling_value(struct acpi_processor *pr,
+                       int state, acpi_integer *value)
+{
+       int ret = -1;
+
+       if (state >= 0 && state <= pr->throttling.state_count) {
+               struct acpi_processor_tx_tss *tx =
+                   (struct acpi_processor_tx_tss *)&(pr->throttling.
+                                                     states_tss[state]);
+               *value = tx->control;
+               ret = 0;
+       }
+       return ret;
+}
+
+static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
+{
+       int state = 0;
+       int ret;
+       acpi_integer value;
+
+       if (!pr)
+               return -EINVAL;
+
+       if (!pr->flags.throttling)
+               return -ENODEV;
+
+       pr->throttling.state = 0;
+
+       value = 0;
+       ret = acpi_read_throttling_status(pr, &value);
+       if (ret >= 0) {
+               state = acpi_get_throttling_state(pr, value);
+               pr->throttling.state = state;
+       }
+
+       return 0;
+}
+
+static int acpi_processor_get_throttling(struct acpi_processor *pr)
+{
+       cpumask_t saved_mask;
+       int ret;
+
+       if (!pr)
+               return -EINVAL;
+
+       if (!pr->flags.throttling)
+               return -ENODEV;
+       /*
+        * Migrate task to the cpu pointed by pr.
+        */
+       saved_mask = current->cpus_allowed;
+       set_cpus_allowed(current, cpumask_of_cpu(pr->id));
+       ret = pr->throttling.acpi_processor_get_throttling(pr);
+       /* restore the previous state */
+       set_cpus_allowed(current, saved_mask);
+
+       return ret;
+}
+
+static int acpi_processor_get_fadt_info(struct acpi_processor *pr)
+{
+       int i, step;
+
+       if (!pr->throttling.address) {
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n"));
+               return -EINVAL;
+       } else if (!pr->throttling.duty_width) {
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n"));
+               return -EINVAL;
+       }
+       /* TBD: Support duty_cycle values that span bit 4. */
+       else if ((pr->throttling.duty_offset + pr->throttling.duty_width) > 4) {
+               printk(KERN_WARNING PREFIX "duty_cycle spans bit 4\n");
+               return -EINVAL;
+       }
+
+       pr->throttling.state_count = 1 << acpi_fadt.duty_width;
+
+       /*
+        * Compute state values. Note that throttling displays a linear power
+        * performance relationship (at 50% performance the CPU will consume
+        * 50% power).  Values are in 1/10th of a percent to preserve accuracy.
+        */
+
+       step = (1000 / pr->throttling.state_count);
+
+       for (i = 0; i < pr->throttling.state_count; i++) {
+               pr->throttling.states[i].performance = 1000 - step * i;
+               pr->throttling.states[i].power = 1000 - step * i;
+       }
+       return 0;
+}
+
+static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr,
+                                             int state)
 {
        u32 value = 0;
        u32 duty_mask = 0;
        u32 duty_value = 0;
 
-
        if (!pr)
                return -EINVAL;
 
@@ -114,6 +899,8 @@ int acpi_processor_set_throttling(struct
        if (state == pr->throttling.state)
                return 0;
 
+       if (state < pr->throttling_platform_limit)
+               return -EPERM;
        /*
         * Calculate the duty_value and duty_mask.
         */
@@ -166,12 +953,135 @@ int acpi_processor_set_throttling(struct
        return 0;
 }
 
+static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
+                                            int state)
+{
+       int ret;
+       acpi_integer value;
+
+       if (!pr)
+               return -EINVAL;
+
+       if ((state < 0) || (state > (pr->throttling.state_count - 1)))
+               return -EINVAL;
+
+       if (!pr->flags.throttling)
+               return -ENODEV;
+
+       if (state == pr->throttling.state)
+               return 0;
+
+       if (state < pr->throttling_platform_limit)
+               return -EPERM;
+
+       value = 0;
+       ret = acpi_get_throttling_value(pr, state, &value);
+       if (ret >= 0) {
+               acpi_write_throttling_state(pr, value);
+               pr->throttling.state = state;
+       }
+
+       return 0;
+}
+
+int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
+{
+       cpumask_t saved_mask;
+       int ret = 0;
+       unsigned int i;
+       struct acpi_processor *match_pr;
+       struct acpi_processor_throttling *p_throttling;
+       struct throttling_tstate t_state;
+       cpumask_t online_throttling_cpus;
+
+       if (!pr)
+               return -EINVAL;
+
+       if (!pr->flags.throttling)
+               return -ENODEV;
+
+       if ((state < 0) || (state > (pr->throttling.state_count - 1)))
+               return -EINVAL;
+
+       saved_mask = current->cpus_allowed;
+       t_state.target_state = state;
+       p_throttling = &(pr->throttling);
+       cpus_and(online_throttling_cpus, cpu_online_map,
+                       p_throttling->shared_cpu_map);
+       /*
+        * The throttling notifier will be called for every
+        * affected cpu in order to get one proper T-state.
+        * The notifier event is THROTTLING_PRECHANGE.
+        */
+       for_each_cpu_mask(i, online_throttling_cpus) {
+               t_state.cpu = i;
+               acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
+                                                       &t_state);
+       }
+       /*
+        * The function of acpi_processor_set_throttling will be called
+        * to switch T-state. If the coordination type is SW_ALL or HW_ALL,
+        * it is necessary to call it for every affected cpu. Otherwise
+        * it can be called only for the cpu pointed by pr.
+        */
+       if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
+               set_cpus_allowed(current, cpumask_of_cpu(pr->id));
+               ret = p_throttling->acpi_processor_set_throttling(pr,
+                                               t_state.target_state);
+       } else {
+               /*
+                * When the T-state coordination is SW_ALL or HW_ALL,
+                * it is necessary to set T-state for every affected
+                * cpus.
+                */
+               for_each_cpu_mask(i, online_throttling_cpus) {
+                       match_pr = processors[i];
+                       /*
+                        * If the pointer is invalid, we will report the
+                        * error message and continue.
+                        */
+                       if (!match_pr) {
+                               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                       "Invalid Pointer for CPU %d\n", i));
+                               continue;
+                       }
+                       /*
+                        * If the throttling control is unsupported on CPU i,
+                        * we will report the error message and continue.
+                        */
+                       if (!match_pr->flags.throttling) {
+                               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                       "Throttling Controll is unsupported "
+                                       "on CPU %d\n", i));
+                               continue;
+                       }
+                       t_state.cpu = i;
+                       set_cpus_allowed(current, cpumask_of_cpu(i));
+                       ret = match_pr->throttling.
+                               acpi_processor_set_throttling(
+                               match_pr, t_state.target_state);
+               }
+       }
+       /*
+        * After the set_throttling is called, the
+        * throttling notifier is called for every
+        * affected cpu to update the T-states.
+        * The notifier event is THROTTLING_POSTCHANGE
+        */
+       for_each_cpu_mask(i, online_throttling_cpus) {
+               t_state.cpu = i;
+               acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
+                                                       &t_state);
+       }
+       /* restore the previous state */
+       set_cpus_allowed(current, saved_mask);
+       return ret;
+}
+
 int acpi_processor_get_throttling_info(struct acpi_processor *pr)
 {
        int result = 0;
-       int step = 0;
-       int i = 0;
-
+       struct acpi_processor_throttling *pthrottling;
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "pblk_address[0x%08x] duty_offset[%d] 
duty_width[%d]\n",
@@ -182,19 +1092,36 @@ int acpi_processor_get_throttling_info(s
        if (!pr)
                return -EINVAL;
 
-       /* TBD: Support ACPI 2.0 objects */
-
-       if (!pr->throttling.address) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n"));
-               return 0;
-       } else if (!pr->throttling.duty_width) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n"));
-               return 0;
-       }
-       /* TBD: Support duty_cycle values that span bit 4. */
-       else if ((pr->throttling.duty_offset + pr->throttling.duty_width) > 4) {
-               printk(KERN_WARNING PREFIX "duty_cycle spans bit 4\n");
-               return 0;
+       /*
+        * Evaluate _PTC, _TSS and _TPC
+        * They must all be present or none of them can be used.
+        */
+       if (acpi_processor_get_throttling_control(pr) ||
+               acpi_processor_get_throttling_states(pr) ||
+               acpi_processor_get_platform_limit(pr))
+       {
+               pr->throttling.acpi_processor_get_throttling =
+                   &acpi_processor_get_throttling_fadt;
+               pr->throttling.acpi_processor_set_throttling =
+                   &acpi_processor_set_throttling_fadt;
+               if (acpi_processor_get_fadt_info(pr))
+                       return 0;
+       } else {
+               pr->throttling.acpi_processor_get_throttling =
+                   &acpi_processor_get_throttling_ptc;
+               pr->throttling.acpi_processor_set_throttling =
+                   &acpi_processor_set_throttling_ptc;
+       }
+
+       /*
+        * If TSD package for one CPU can't be parsed successfully, it means
+        * that this CPU will have no coordination with other CPUs.
+        */
+       if (acpi_processor_get_tsd(pr)) {
+               pthrottling = &pr->throttling;
+               pthrottling->tsd_valid_flag = 0;
+               cpu_set(pr->id, pthrottling->shared_cpu_map);
+               pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
        }
 
        /*
@@ -206,21 +1133,6 @@ int acpi_processor_get_throttling_info(s
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Throttling not supported on PIIX4 A- or 
B-step\n"));
                return 0;
-       }
-
-       pr->throttling.state_count = 1 << acpi_fadt.duty_width;
-
-       /*
-        * Compute state values. Note that throttling displays a linear power/
-        * performance relationship (at 50% performance the CPU will consume
-        * 50% power).  Values are in 1/10th of a percent to preserve accuracy.
-        */
-
-       step = (1000 / pr->throttling.state_count);
-
-       for (i = 0; i < pr->throttling.state_count; i++) {
-               pr->throttling.states[i].performance = step * i;
-               pr->throttling.states[i].power = step * i;
        }
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n",
@@ -259,10 +1171,9 @@ static int acpi_processor_throttling_seq
 static int acpi_processor_throttling_seq_show(struct seq_file *seq,
                                              void *offset)
 {
-       struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+       struct acpi_processor *pr = seq->private;
        int i = 0;
        int result = 0;
-
 
        if (!pr)
                goto end;
@@ -281,15 +1192,27 @@ static int acpi_processor_throttling_seq
        }
 
        seq_printf(seq, "state count:             %d\n"
-                  "active state:            T%d\n",
-                  pr->throttling.state_count, pr->throttling.state);
+                  "active state:            T%d\n"
+                  "state available: T%d to T%d\n",
+                  pr->throttling.state_count, pr->throttling.state,
+                  pr->throttling_platform_limit,
+                  pr->throttling.state_count - 1);
 
        seq_puts(seq, "states:\n");
-       for (i = 0; i < pr->throttling.state_count; i++)
-               seq_printf(seq, "   %cT%d:                  %02d%%\n",
-                          (i == pr->throttling.state ? '*' : ' '), i,
-                          (pr->throttling.states[i].performance ? pr->
-                           throttling.states[i].performance / 10 : 0));
+       if (pr->throttling.acpi_processor_get_throttling ==
+                       acpi_processor_get_throttling_fadt) {
+               for (i = 0; i < pr->throttling.state_count; i++)
+                       seq_printf(seq, "   %cT%d:                  %02d%%\n",
+                                  (i == pr->throttling.state ? '*' : ' '), i,
+                                  (pr->throttling.states[i].performance ? pr->
+                                   throttling.states[i].performance / 10 : 0));
+       } else {
+               for (i = 0; i < pr->throttling.state_count; i++)
+                       seq_printf(seq, "   %cT%d:                  %02d%%\n",
+                                  (i == pr->throttling.state ? '*' : ' '), i,
+                                  (int)pr->throttling.states_tss[i].
+                                  freqpercentage);
+       }
 
       end:
        return 0;
@@ -302,15 +1225,17 @@ static int acpi_processor_throttling_ope
                           PDE(inode)->data);
 }
 
-static ssize_t acpi_processor_write_throttling(struct file * file,
+static ssize_t acpi_processor_write_throttling(struct file *file,
                                               const char __user * buffer,
                                               size_t count, loff_t * data)
 {
        int result = 0;
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_processor *pr = (struct acpi_processor *)m->private;
-       char state_string[12] = { '\0' };
-
+       struct seq_file *m = file->private_data;
+       struct acpi_processor *pr = m->private;
+       char state_string[5] = "";
+       char *charp = NULL;
+       size_t state_val = 0;
+       char tmpbuf[5] = "";
 
        if (!pr || (count > sizeof(state_string) - 1))
                return -EINVAL;
@@ -319,10 +1244,23 @@ static ssize_t acpi_processor_write_thro
                return -EFAULT;
 
        state_string[count] = '\0';
-
-       result = acpi_processor_set_throttling(pr,
-                                              simple_strtoul(state_string,
-                                                             NULL, 0));
+       if ((count > 0) && (state_string[count-1] == '\n'))
+               state_string[count-1] = '\0';
+
+       charp = state_string;
+       if ((state_string[0] == 't') || (state_string[0] == 'T'))
+               charp++;
+
+       state_val = simple_strtoul(charp, NULL, 0);
+       if (state_val >= pr->throttling.state_count)
+               return -EINVAL;
+
+       snprintf(tmpbuf, 5, "%zu", state_val);
+
+       if (strcmp(tmpbuf, charp) != 0)
+               return -EINVAL;
+
+       result = acpi_processor_set_throttling(pr, state_val);
        if (result)
                return result;
 
@@ -330,6 +1268,7 @@ static ssize_t acpi_processor_write_thro
 }
 
 struct file_operations acpi_processor_throttling_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_processor_throttling_open_fs,
        .read = seq_read,
        .write = acpi_processor_write_throttling,
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 drivers/pci/msi-xen.c
--- a/drivers/pci/msi-xen.c     Fri Sep 12 11:28:00 2008 +0900
+++ b/drivers/pci/msi-xen.c     Tue Sep 16 21:25:54 2008 +0900
@@ -15,6 +15,8 @@
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 
+#include <xen/evtchn.h>
+
 #include <asm/errno.h>
 #include <asm/io.h>
 #include <asm/smp.h>
@@ -156,13 +158,15 @@ static int msi_unmap_pirq(struct pci_dev
        int rc;
 
        unmap.domid = msi_get_dev_owner(dev);
-       unmap.pirq = pirq;
+       unmap.pirq = evtchn_get_xen_pirq(pirq);
 
        if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap)))
                printk(KERN_WARNING "unmap irq %x failed\n", pirq);
 
        if (rc < 0)
                return rc;
+
+       evtchn_map_pirq(pirq, 0);
        return 0;
 }
 
@@ -197,7 +201,7 @@ static int msi_map_pirq_to_vector(struct
        map_irq.domid = domid;
        map_irq.type = MAP_PIRQ_TYPE_MSI;
        map_irq.index = -1;
-       map_irq.pirq = pirq;
+       map_irq.pirq = pirq < 0 ? -1 : evtchn_get_xen_pirq(pirq);
        map_irq.bus = dev->bus->number;
        map_irq.devfn = dev->devfn;
        map_irq.entry_nr = entry_nr;
@@ -208,8 +212,12 @@ static int msi_map_pirq_to_vector(struct
 
        if (rc < 0)
                return rc;
-
-       return map_irq.pirq;
+       /* This happens when MSI support is not enabled in Xen. */
+       if (rc == 0 && map_irq.pirq < 0)
+               return -ENOSYS;
+
+       BUG_ON(map_irq.pirq <= 0);
+       return evtchn_map_pirq(pirq, map_irq.pirq);
 }
 
 static int msi_map_vector(struct pci_dev *dev, int entry_nr, u64 table_base)
@@ -364,9 +372,15 @@ void pci_restore_msix_state(struct pci_d
 
        spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
        list_for_each_entry_safe(pirq_entry, tmp,
-                                &msi_dev_entry->pirq_list_head, list)
-               msi_map_pirq_to_vector(dev, pirq_entry->pirq,
-                                      pirq_entry->entry_nr, table_base);
+                                &msi_dev_entry->pirq_list_head, list) {
+               int rc = msi_map_pirq_to_vector(dev, pirq_entry->pirq,
+                                               pirq_entry->entry_nr, 
table_base);
+               if (rc < 0)
+                       printk(KERN_WARNING
+                              "%s: re-mapping irq #%d (pirq%d) failed: %d\n",
+                              pci_name(dev), pirq_entry->entry_nr,
+                              pirq_entry->pirq, rc);
+       }
        spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
 
        enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 drivers/xen/blktap/common.h
--- a/drivers/xen/blktap/common.h       Fri Sep 12 11:28:00 2008 +0900
+++ b/drivers/xen/blktap/common.h       Tue Sep 16 21:25:54 2008 +0900
@@ -89,6 +89,7 @@ typedef struct blkif_st {
 
 blkif_t *tap_alloc_blkif(domid_t domid);
 void tap_blkif_free(blkif_t *blkif);
+void tap_blkif_kmem_cache_free(blkif_t *blkif);
 int tap_blkif_map(blkif_t *blkif, unsigned long shared_page, 
                  unsigned int evtchn);
 void tap_blkif_unmap(blkif_t *blkif);
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 drivers/xen/blktap/interface.c
--- a/drivers/xen/blktap/interface.c    Fri Sep 12 11:28:00 2008 +0900
+++ b/drivers/xen/blktap/interface.c    Tue Sep 16 21:25:54 2008 +0900
@@ -162,8 +162,15 @@ void tap_blkif_free(blkif_t *blkif)
 {
        atomic_dec(&blkif->refcnt);
        wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0);
+       atomic_inc(&blkif->refcnt);
 
        tap_blkif_unmap(blkif);
+}
+
+void tap_blkif_kmem_cache_free(blkif_t *blkif)
+{
+       if (!atomic_dec_and_test(&blkif->refcnt))
+               BUG();
        kmem_cache_free(blkif_cachep, blkif);
 }
 
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 drivers/xen/blktap/xenbus.c
--- a/drivers/xen/blktap/xenbus.c       Fri Sep 12 11:28:00 2008 +0900
+++ b/drivers/xen/blktap/xenbus.c       Tue Sep 16 21:25:54 2008 +0900
@@ -182,6 +182,7 @@ static int blktap_remove(struct xenbus_d
                        kthread_stop(be->blkif->xenblkd);
                signal_tapdisk(be->blkif->dev_num);
                tap_blkif_free(be->blkif);
+               tap_blkif_kmem_cache_free(be->blkif);
                be->blkif = NULL;
        }
        kfree(be);
@@ -364,6 +365,7 @@ static void tap_frontend_changed(struct 
                        kthread_stop(be->blkif->xenblkd);
                        be->blkif->xenblkd = NULL;
                }
+               tap_blkif_free(be->blkif);
                xenbus_switch_state(dev, XenbusStateClosing);
                break;
 
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 drivers/xen/core/evtchn.c
--- a/drivers/xen/core/evtchn.c Fri Sep 12 11:28:00 2008 +0900
+++ b/drivers/xen/core/evtchn.c Tue Sep 16 21:25:54 2008 +0900
@@ -66,13 +66,27 @@ enum {
        IRQT_VIRQ,
        IRQT_IPI,
        IRQT_LOCAL_PORT,
-       IRQT_CALLER_PORT
+       IRQT_CALLER_PORT,
+       _IRQT_COUNT
 };
+
+#define _IRQT_BITS 4
+#define _EVTCHN_BITS 12
+#define _INDEX_BITS (32 - _IRQT_BITS - _EVTCHN_BITS)
 
 /* Constructor for packed IRQ information. */
 static inline u32 mk_irq_info(u32 type, u32 index, u32 evtchn)
 {
-       return ((type << 24) | (index << 16) | evtchn);
+       BUILD_BUG_ON(_IRQT_COUNT > (1U << _IRQT_BITS));
+
+       BUILD_BUG_ON(NR_PIRQS > (1U << _INDEX_BITS));
+       BUILD_BUG_ON(NR_VIRQS > (1U << _INDEX_BITS));
+       BUILD_BUG_ON(NR_IPIS > (1U << _INDEX_BITS));
+       BUG_ON(index >> _INDEX_BITS);
+
+       BUILD_BUG_ON(NR_EVENT_CHANNELS > (1U << _EVTCHN_BITS));
+
+       return ((type << (32 - _IRQT_BITS)) | (index << _EVTCHN_BITS) | evtchn);
 }
 
 /* Convenient shorthand for packed representation of an unbound IRQ. */
@@ -84,17 +98,17 @@ static inline u32 mk_irq_info(u32 type, 
 
 static inline unsigned int evtchn_from_irq(int irq)
 {
-       return (u16)(irq_info[irq]);
+       return irq_info[irq] & ((1U << _EVTCHN_BITS) - 1);
 }
 
 static inline unsigned int index_from_irq(int irq)
 {
-       return (u8)(irq_info[irq] >> 16);
+       return (irq_info[irq] >> _EVTCHN_BITS) & ((1U << _INDEX_BITS) - 1);
 }
 
 static inline unsigned int type_from_irq(int irq)
 {
-       return (u8)(irq_info[irq] >> 24);
+       return irq_info[irq] >> (32 - _IRQT_BITS);
 }
 
 /* IRQ <-> VIRQ mapping. */
@@ -305,13 +319,11 @@ static int find_unbound_irq(void)
 static int find_unbound_irq(void)
 {
        static int warned;
-       int dynirq, irq;
-
-       for (dynirq = 0; dynirq < NR_DYNIRQS; dynirq++) {
-               irq = dynirq_to_irq(dynirq);
+       int irq;
+
+       for (irq = DYNIRQ_BASE; irq < (DYNIRQ_BASE + NR_DYNIRQS); irq++)
                if (irq_bindcount[irq] == 0)
                        return irq;
-       }
 
        if (!warned) {
                warned = 1;
@@ -742,22 +754,78 @@ static struct hw_interrupt_type dynirq_t
        .retrigger = resend_irq_on_evtchn,
 };
 
-static inline void pirq_unmask_notify(int pirq)
-{
-       struct physdev_eoi eoi = { .irq = pirq };
-       if (unlikely(test_bit(pirq, pirq_needs_eoi)))
+void evtchn_register_pirq(int irq)
+{
+       irq_info[irq] = mk_irq_info(IRQT_PIRQ, irq, 0);
+}
+
+#if defined(CONFIG_X86_IO_APIC)
+#define identity_mapped_irq(irq) (!IO_APIC_IRQ((irq) - PIRQ_BASE))
+#elif defined(CONFIG_X86)
+#define identity_mapped_irq(irq) (((irq) - PIRQ_BASE) < 16)
+#else
+#define identity_mapped_irq(irq) (1)
+#endif
+
+int evtchn_map_pirq(int irq, int xen_pirq)
+{
+       if (irq < 0) {
+               static DEFINE_SPINLOCK(irq_alloc_lock);
+
+               irq = PIRQ_BASE + NR_PIRQS - 1;
+               spin_lock(&irq_alloc_lock);
+               do {
+                       if (identity_mapped_irq(irq))
+                               continue;
+                       if (!index_from_irq(irq)) {
+                               BUG_ON(type_from_irq(irq) != IRQT_UNBOUND);
+                               irq_info[irq] = mk_irq_info(IRQT_PIRQ,
+                                                           xen_pirq, 0);
+                               break;
+                       }
+               } while (--irq >= PIRQ_BASE);
+               spin_unlock(&irq_alloc_lock);
+               if (irq < PIRQ_BASE)
+                       return -ENOSPC;
+       } else if (!xen_pirq) {
+               if (unlikely(type_from_irq(irq) != IRQT_PIRQ))
+                       return -EINVAL;
+               irq_info[irq] = IRQ_UNBOUND;
+               return 0;
+       } else if (type_from_irq(irq) != IRQT_PIRQ
+                  || index_from_irq(irq) != xen_pirq) {
+               printk(KERN_ERR "IRQ#%d is already mapped to %d:%u - "
+                               "cannot map to PIRQ#%u\n",
+                      irq, type_from_irq(irq), index_from_irq(irq), xen_pirq);
+               return -EINVAL;
+       }
+       return index_from_irq(irq) ? irq : -EINVAL;
+}
+
+int evtchn_get_xen_pirq(int irq)
+{
+       if (identity_mapped_irq(irq))
+               return irq;
+       BUG_ON(type_from_irq(irq) != IRQT_PIRQ);
+       return index_from_irq(irq);
+}
+
+static inline void pirq_unmask_notify(int irq)
+{
+       struct physdev_eoi eoi = { .irq = evtchn_get_xen_pirq(irq) };
+       if (unlikely(test_bit(irq - PIRQ_BASE, pirq_needs_eoi)))
                VOID(HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi));
 }
 
-static inline void pirq_query_unmask(int pirq)
+static inline void pirq_query_unmask(int irq)
 {
        struct physdev_irq_status_query irq_status;
-       irq_status.irq = pirq;
+       irq_status.irq = evtchn_get_xen_pirq(irq);
        if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status))
                irq_status.flags = 0;
-       clear_bit(pirq, pirq_needs_eoi);
+       clear_bit(irq - PIRQ_BASE, pirq_needs_eoi);
        if (irq_status.flags & XENIRQSTAT_needs_eoi)
-               set_bit(pirq, pirq_needs_eoi);
+               set_bit(irq - PIRQ_BASE, pirq_needs_eoi);
 }
 
 /*
@@ -774,7 +842,7 @@ static unsigned int startup_pirq(unsigne
        if (VALID_EVTCHN(evtchn))
                goto out;
 
-       bind_pirq.pirq  = irq;
+       bind_pirq.pirq = evtchn_get_xen_pirq(irq);
        /* NB. We are happy to share unless we are probing. */
        bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE;
        if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq) != 0) {
@@ -785,15 +853,15 @@ static unsigned int startup_pirq(unsigne
        }
        evtchn = bind_pirq.port;
 
-       pirq_query_unmask(irq_to_pirq(irq));
+       pirq_query_unmask(irq);
 
        evtchn_to_irq[evtchn] = irq;
        bind_evtchn_to_cpu(evtchn, 0);
-       irq_info[irq] = mk_irq_info(IRQT_PIRQ, irq, evtchn);
+       irq_info[irq] = mk_irq_info(IRQT_PIRQ, bind_pirq.pirq, evtchn);
 
  out:
        unmask_evtchn(evtchn);
-       pirq_unmask_notify(irq_to_pirq(irq));
+       pirq_unmask_notify(irq);
 
        return 0;
 }
@@ -814,7 +882,7 @@ static void shutdown_pirq(unsigned int i
 
        bind_evtchn_to_cpu(evtchn, 0);
        evtchn_to_irq[evtchn] = -1;
-       irq_info[irq] = IRQ_UNBOUND;
+       irq_info[irq] = mk_irq_info(IRQT_PIRQ, index_from_irq(irq), 0);
 }
 
 static void enable_pirq(unsigned int irq)
@@ -847,7 +915,7 @@ static void end_pirq(unsigned int irq)
                shutdown_pirq(irq);
        } else if (VALID_EVTCHN(evtchn)) {
                unmask_evtchn(evtchn);
-               pirq_unmask_notify(irq_to_pirq(irq));
+               pirq_unmask_notify(irq);
        }
 }
 
@@ -994,7 +1062,7 @@ static void restore_cpu_ipis(unsigned in
 
 void irq_resume(void)
 {
-       unsigned int cpu, pirq, irq, evtchn;
+       unsigned int cpu, irq, evtchn;
 
        init_evtchn_cpu_bindings();
 
@@ -1003,12 +1071,12 @@ void irq_resume(void)
                mask_evtchn(evtchn);
 
        /* Check that no PIRQs are still bound. */
-       for (pirq = 0; pirq < NR_PIRQS; pirq++)
-               BUG_ON(irq_info[pirq_to_irq(pirq)] != IRQ_UNBOUND);
+       for (irq = PIRQ_BASE; irq < (PIRQ_BASE + NR_PIRQS); irq++)
+               BUG_ON(irq_info[irq] != IRQ_UNBOUND);
 
        /* No IRQ <-> event-channel mappings. */
        for (irq = 0; irq < NR_IRQS; irq++)
-               irq_info[irq] &= ~0xFFFF; /* zap event-channel binding */
+               irq_info[irq] &= ~((1U << _EVTCHN_BITS) - 1);
        for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
                evtchn_to_irq[evtchn] = -1;
 
@@ -1034,28 +1102,29 @@ void __init xen_init_IRQ(void)
                irq_info[i] = IRQ_UNBOUND;
 
        /* Dynamic IRQ space is currently unbound. Zero the refcnts. */
-       for (i = 0; i < NR_DYNIRQS; i++) {
-               irq_bindcount[dynirq_to_irq(i)] = 0;
-
-               irq_desc[dynirq_to_irq(i)].status = IRQ_DISABLED;
-               irq_desc[dynirq_to_irq(i)].action = NULL;
-               irq_desc[dynirq_to_irq(i)].depth = 1;
-               irq_desc[dynirq_to_irq(i)].chip = &dynirq_type;
+       for (i = DYNIRQ_BASE; i < (DYNIRQ_BASE + NR_DYNIRQS); i++) {
+               irq_bindcount[i] = 0;
+
+               irq_desc[i].status = IRQ_DISABLED;
+               irq_desc[i].action = NULL;
+               irq_desc[i].depth = 1;
+               irq_desc[i].chip = &dynirq_type;
        }
 
        /* Phys IRQ space is statically bound (1:1 mapping). Nail refcnts. */
-       for (i = 0; i < NR_PIRQS; i++) {
-               irq_bindcount[pirq_to_irq(i)] = 1;
+       for (i = PIRQ_BASE; i < (PIRQ_BASE + NR_PIRQS); i++) {
+               irq_bindcount[i] = 1;
 
 #ifdef RTC_IRQ
                /* If not domain 0, force our RTC driver to fail its probe. */
-               if ((i == RTC_IRQ) && !is_initial_xendomain())
+               if (identity_mapped_irq(i) && ((i - PIRQ_BASE) == RTC_IRQ)
+                   && !is_initial_xendomain())
                        continue;
 #endif
 
-               irq_desc[pirq_to_irq(i)].status = IRQ_DISABLED;
-               irq_desc[pirq_to_irq(i)].action = NULL;
-               irq_desc[pirq_to_irq(i)].depth = 1;
-               irq_desc[pirq_to_irq(i)].chip = &pirq_type;
-       }
-}
+               irq_desc[i].status = IRQ_DISABLED;
+               irq_desc[i].action = NULL;
+               irq_desc[i].depth = 1;
+               irq_desc[i].chip = &pirq_type;
+       }
+}
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 
drivers/xen/pciback/conf_space_capability_msi.c
--- a/drivers/xen/pciback/conf_space_capability_msi.c   Fri Sep 12 11:28:00 
2008 +0900
+++ b/drivers/xen/pciback/conf_space_capability_msi.c   Tue Sep 16 21:25:54 
2008 +0900
@@ -2,6 +2,7 @@
  * PCI Backend -- Configuration overlay for MSI capability
  */
 #include <linux/pci.h>
+#include <linux/slab.h>
 #include "conf_space.h"
 #include "conf_space_capability.h"
 #include <xen/interface/io/pciif.h>
@@ -37,22 +38,31 @@ int pciback_enable_msix(struct pciback_d
 int pciback_enable_msix(struct pciback_device *pdev,
                struct pci_dev *dev, struct xen_pci_op *op)
 {
-       int result;
+       int i, result;
+       struct msix_entry *entries;
 
        if (op->value > SH_INFO_MAX_VEC)
                return -EINVAL;
-       else {
-               struct msix_entry entries[op->value];
-               int i;
 
-               for (i = 0; i < op->value; i++) {
-                       entries[i].entry = op->msix_entries[i].entry;
-                       entries[i].vector = op->msix_entries[i].vector;
-               }
+       entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL);
+       if (entries == NULL)
+               return -ENOMEM;
 
-               result = pci_enable_msix(dev, entries, op->value);
-               op->value = result;
+       for (i = 0; i < op->value; i++) {
+               entries[i].entry = op->msix_entries[i].entry;
+               entries[i].vector = op->msix_entries[i].vector;
        }
+
+       result = pci_enable_msix(dev, entries, op->value);
+
+       for (i = 0; i < op->value; i++) {
+               op->msix_entries[i].entry = entries[i].entry;
+               op->msix_entries[i].vector = entries[i].vector;
+       }
+
+       kfree(entries);
+
+       op->value = result;
 
        return result;
 }
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 drivers/xen/xenoprof/xenoprofile.c
--- a/drivers/xen/xenoprof/xenoprofile.c        Fri Sep 12 11:28:00 2008 +0900
+++ b/drivers/xen/xenoprof/xenoprofile.c        Tue Sep 16 21:25:54 2008 +0900
@@ -35,14 +35,14 @@
 #define MAX_XENOPROF_SAMPLES 16
 
 /* sample buffers shared with Xen */
-xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS];
+static xenoprof_buf_t *xenoprof_buf[MAX_VIRT_CPUS];
 /* Shared buffer area */
-struct xenoprof_shared_buffer shared_buffer;
+static struct xenoprof_shared_buffer shared_buffer;
 
 /* Passive sample buffers shared with Xen */
-xenoprof_buf_t *p_xenoprof_buf[MAX_OPROF_DOMAINS][MAX_VIRT_CPUS];
+static xenoprof_buf_t *p_xenoprof_buf[MAX_OPROF_DOMAINS][MAX_VIRT_CPUS];
 /* Passive shared buffer area */
-struct xenoprof_shared_buffer p_shared_buffer[MAX_OPROF_DOMAINS];
+static struct xenoprof_shared_buffer p_shared_buffer[MAX_OPROF_DOMAINS];
 
 static int xenoprof_start(void);
 static void xenoprof_stop(void);
@@ -54,11 +54,11 @@ extern unsigned long backtrace_depth;
 extern unsigned long backtrace_depth;
 
 /* Number of buffers in shared area (one per VCPU) */
-int nbuf;
+static int nbuf;
 /* Mappings of VIRQ_XENOPROF to irq number (per cpu) */
-int ovf_irq[NR_CPUS];
+static int ovf_irq[NR_CPUS];
 /* cpu model type string - copied from Xen on XENOPROF_init command */
-char cpu_type[XENOPROF_CPU_TYPE_SIZE];
+static char cpu_type[XENOPROF_CPU_TYPE_SIZE];
 
 #ifdef CONFIG_PM
 
@@ -111,11 +111,11 @@ static void exit_driverfs(void)
 #define exit_driverfs() do { } while (0)
 #endif /* CONFIG_PM */
 
-unsigned long long oprofile_samples = 0;
-unsigned long long p_oprofile_samples = 0;
-
-unsigned int pdomains;
-struct xenoprof_passive passive_domains[MAX_OPROF_DOMAINS];
+static unsigned long long oprofile_samples;
+static unsigned long long p_oprofile_samples;
+
+static unsigned int pdomains;
+static struct xenoprof_passive passive_domains[MAX_OPROF_DOMAINS];
 
 /* Check whether the given entry is an escape code */
 static int xenoprof_is_escape(xenoprof_buf_t * buf, int tail)
@@ -483,8 +483,7 @@ static void xenoprof_dummy_backtrace(str
 }
 
 
-
-struct oprofile_operations xenoprof_ops = {
+static struct oprofile_operations xenoprof_ops = {
 #ifdef HAVE_XENOPROF_CREATE_FILES
        .create_files   = xenoprof_create_files,
 #endif
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 include/acpi/processor.h
--- a/include/acpi/processor.h  Fri Sep 12 11:28:00 2008 +0900
+++ b/include/acpi/processor.h  Tue Sep 16 21:25:54 2008 +0900
@@ -18,8 +18,11 @@
 
 #define ACPI_PDC_REVISION_ID           0x1
 
-#define ACPI_PSD_REV0_REVISION         0 /* Support for _PSD as in ACPI 3.0 */
+#define ACPI_PSD_REV0_REVISION         0       /* Support for _PSD as in ACPI 
3.0 */
 #define ACPI_PSD_REV0_ENTRIES          5
+
+#define ACPI_TSD_REV0_REVISION         0       /* Support for _PSD as in ACPI 
3.0 */
+#define ACPI_TSD_REV0_ENTRIES          5
 
 #ifdef CONFIG_XEN
 #define NR_ACPI_CPUS                   (NR_CPUS < 256 ? 256 : NR_CPUS)
@@ -142,24 +145,62 @@ struct acpi_processor_performance {
 
 /* Throttling Control */
 
+struct acpi_tsd_package {
+       acpi_integer num_entries;
+       acpi_integer revision;
+       acpi_integer domain;
+       acpi_integer coord_type;
+       acpi_integer num_processors;
+} __attribute__ ((packed));
+
+struct acpi_ptc_register {
+       u8 descriptor;
+       u16 length;
+       u8 space_id;
+       u8 bit_width;
+       u8 bit_offset;
+       u8 reserved;
+       u64 address;
+} __attribute__ ((packed));
+
+struct acpi_processor_tx_tss {
+       acpi_integer freqpercentage;    /* */
+       acpi_integer power;     /* milliWatts */
+       acpi_integer transition_latency;        /* microseconds */
+       acpi_integer control;   /* control value */
+       acpi_integer status;    /* success indicator */
+};
 struct acpi_processor_tx {
        u16 power;
        u16 performance;
 };
 
+struct acpi_processor;
 struct acpi_processor_throttling {
-       int state;
+       unsigned int state;
+       unsigned int platform_limit;
+       struct acpi_pct_register control_register;
+       struct acpi_pct_register status_register;
+       unsigned int state_count;
+       struct acpi_processor_tx_tss *states_tss;
+       struct acpi_tsd_package domain_info;
+       cpumask_t shared_cpu_map;
+       int (*acpi_processor_get_throttling) (struct acpi_processor * pr);
+       int (*acpi_processor_set_throttling) (struct acpi_processor * pr,
+                                             int state);
+
        u32 address;
        u8 duty_offset;
        u8 duty_width;
-       int state_count;
+       u8 tsd_valid_flag;
+       unsigned int shared_type;
        struct acpi_processor_tx states[ACPI_PROCESSOR_MAX_THROTTLING];
 };
 
 /* Limit Interface */
 
 struct acpi_processor_lx {
-       int px;                 /* performace state */
+       int px;                 /* performance state */
        int tx;                 /* throttle level */
 };
 
@@ -186,6 +227,9 @@ struct acpi_processor {
        u32 id;
        u32 pblk;
        int performance_platform_limit;
+       int throttling_platform_limit;
+       /* 0 - states 0..n-th state available */
+
        struct acpi_processor_flags flags;
        struct acpi_processor_power power;
        struct acpi_processor_performance *performance;
@@ -273,10 +317,11 @@ static inline int acpi_processor_ppc_has
 #endif                         /* CONFIG_CPU_FREQ */
 
 /* in processor_throttling.c */
+int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
 int acpi_processor_get_throttling_info(struct acpi_processor *pr);
-int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
+extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
 extern struct file_operations acpi_processor_throttling_fops;
-
+extern void acpi_processor_throttling_init(void);
 /* in processor_idle.c */
 int acpi_processor_power_init(struct acpi_processor *pr,
                              struct acpi_device *device);
@@ -326,7 +371,7 @@ struct processor_extcntl_ops {
        /* Transfer processor PM events to external control logic */
        int (*pm_ops[PM_TYPE_MAX])(struct acpi_processor *pr, int event);
        /* Notify physical processor status to external control logic */
-       int (*hotplug)(struct acpi_processor *pr, int event);
+       int (*hotplug)(struct acpi_processor *pr, int type);
 };
 extern const struct processor_extcntl_ops *processor_extcntl_ops;
 
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 include/asm-i386/mach-xen/irq_vectors.h
--- a/include/asm-i386/mach-xen/irq_vectors.h   Fri Sep 12 11:28:00 2008 +0900
+++ b/include/asm-i386/mach-xen/irq_vectors.h   Tue Sep 16 21:25:54 2008 +0900
@@ -108,7 +108,13 @@
  */
 
 #define PIRQ_BASE              0
-#define NR_PIRQS               256
+#if !defined(MAX_IO_APICS)
+# define NR_PIRQS              (NR_VECTORS + 32 * NR_CPUS)
+#elif NR_CPUS < MAX_IO_APICS
+# define NR_PIRQS              (NR_VECTORS + 32 * NR_CPUS)
+#else
+# define NR_PIRQS              (NR_VECTORS + 32 * MAX_IO_APICS)
+#endif
 
 #define DYNIRQ_BASE            (PIRQ_BASE + NR_PIRQS)
 #define NR_DYNIRQS             256
@@ -116,10 +122,4 @@
 #define NR_IRQS                        (NR_PIRQS + NR_DYNIRQS)
 #define NR_IRQ_VECTORS         NR_IRQS
 
-#define pirq_to_irq(_x)                ((_x) + PIRQ_BASE)
-#define irq_to_pirq(_x)                ((_x) - PIRQ_BASE)
-
-#define dynirq_to_irq(_x)      ((_x) + DYNIRQ_BASE)
-#define irq_to_dynirq(_x)      ((_x) - DYNIRQ_BASE)
-
 #endif /* _ASM_IRQ_VECTORS_H */
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 include/asm-ia64/irq.h
--- a/include/asm-ia64/irq.h    Fri Sep 12 11:28:00 2008 +0900
+++ b/include/asm-ia64/irq.h    Tue Sep 16 21:25:54 2008 +0900
@@ -34,12 +34,6 @@
 #define NR_IRQS                        (NR_PIRQS + NR_DYNIRQS)
 #define NR_IRQ_VECTORS         NR_IRQS
 
-#define pirq_to_irq(_x)                ((_x) + PIRQ_BASE)
-#define irq_to_pirq(_x)                ((_x) - PIRQ_BASE)
-
-#define dynirq_to_irq(_x)      ((_x) + DYNIRQ_BASE)
-#define irq_to_dynirq(_x)      ((_x) - DYNIRQ_BASE)
-
 #define RESCHEDULE_VECTOR      0
 #define IPI_VECTOR             1
 #define CMCP_VECTOR            2
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 include/asm-powerpc/xen/asm/hypervisor.h
--- a/include/asm-powerpc/xen/asm/hypervisor.h  Fri Sep 12 11:28:00 2008 +0900
+++ b/include/asm-powerpc/xen/asm/hypervisor.h  Tue Sep 16 21:25:54 2008 +0900
@@ -154,13 +154,6 @@ int direct_remap_pfn_range(struct vm_are
 
 #define NR_IRQ_VECTORS         NR_IRQS
 
-#define pirq_to_irq(_x)                ((_x) + PIRQ_BASE)
-#define irq_to_pirq(_x)                ((_x) - PIRQ_BASE)
-
-#define dynirq_to_irq(_x)      ((_x) + DYNIRQ_BASE)
-#define irq_to_dynirq(_x)      ((_x) - DYNIRQ_BASE)
-
-
 /* END:  all of these need a new home */
 
 #if defined(CONFIG_X86_64)
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 include/asm-x86_64/mach-xen/irq_vectors.h
--- a/include/asm-x86_64/mach-xen/irq_vectors.h Fri Sep 12 11:28:00 2008 +0900
+++ b/include/asm-x86_64/mach-xen/irq_vectors.h Tue Sep 16 21:25:54 2008 +0900
@@ -114,10 +114,4 @@
 #define NR_IRQS                        (NR_PIRQS + NR_DYNIRQS)
 #define NR_IRQ_VECTORS         NR_IRQS
 
-#define pirq_to_irq(_x)                ((_x) + PIRQ_BASE)
-#define irq_to_pirq(_x)                ((_x) - PIRQ_BASE)
-
-#define dynirq_to_irq(_x)      ((_x) + DYNIRQ_BASE)
-#define irq_to_dynirq(_x)      ((_x) - DYNIRQ_BASE)
-
 #endif /* _ASM_IRQ_VECTORS_H */
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 include/xen/evtchn.h
--- a/include/xen/evtchn.h      Fri Sep 12 11:28:00 2008 +0900
+++ b/include/xen/evtchn.h      Tue Sep 16 21:25:54 2008 +0900
@@ -101,6 +101,13 @@ asmlinkage void evtchn_do_upcall(struct 
 /* Entry point for notifications into the userland character device. */
 void evtchn_device_upcall(int port);
 
+/* Mark a PIRQ as unavailable for dynamic allocation. */
+void evtchn_register_pirq(int irq);
+/* Map a Xen-supplied PIRQ to a dynamically allocated one. */
+int evtchn_map_pirq(int irq, int xen_pirq);
+/* Look up a Xen-supplied PIRQ for a dynamically allocated one. */
+int evtchn_get_xen_pirq(int irq);
+
 void mask_evtchn(int port);
 void disable_all_local_evtchn(void);
 void unmask_evtchn(int port);
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 include/xen/interface/memory.h
--- a/include/xen/interface/memory.h    Fri Sep 12 11:28:00 2008 +0900
+++ b/include/xen/interface/memory.h    Tue Sep 16 21:25:54 2008 +0900
@@ -204,6 +204,7 @@ struct xen_add_to_physmap {
     /* Source mapping space. */
 #define XENMAPSPACE_shared_info 0 /* shared info page */
 #define XENMAPSPACE_grant_table 1 /* grant table page */
+#define XENMAPSPACE_mfn         2 /* usual MFN */
     unsigned int space;
 
     /* Index into source mapping space. */
@@ -214,6 +215,22 @@ struct xen_add_to_physmap {
 };
 typedef struct xen_add_to_physmap xen_add_to_physmap_t;
 DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
+
+/*
+ * Unmaps the page appearing at a particular GPFN from the specified guest's
+ * pseudophysical address space.
+ * arg == addr of xen_remove_from_physmap_t.
+ */
+#define XENMEM_remove_from_physmap      15
+struct xen_remove_from_physmap {
+    /* Which domain to change the mapping for. */
+    domid_t domid;
+
+    /* GPFN of the current mapping of the page. */
+    xen_pfn_t     gpfn;
+};
+typedef struct xen_remove_from_physmap xen_remove_from_physmap_t;
+DEFINE_XEN_GUEST_HANDLE(xen_remove_from_physmap_t);
 
 /*
  * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
diff -r 6fcc6c1e87f6 -r 7d032c5bb346 include/xen/interface/platform.h
--- a/include/xen/interface/platform.h  Fri Sep 12 11:28:00 2008 +0900
+++ b/include/xen/interface/platform.h  Tue Sep 16 21:25:54 2008 +0900
@@ -97,7 +97,7 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_read_memty
 #define XENPF_microcode_update    35
 struct xenpf_microcode_update {
     /* IN variables. */
-    XEN_GUEST_HANDLE(void) data;      /* Pointer to microcode data */
+    XEN_GUEST_HANDLE(const_void) data;/* Pointer to microcode data */
     uint32_t length;                  /* Length of microcode data. */
 };
 typedef struct xenpf_microcode_update xenpf_microcode_update_t;
@@ -289,7 +289,7 @@ struct xen_psd_package {
 
 struct xen_processor_performance {
     uint32_t flags;     /* flag for Px sub info type */
-    uint32_t ppc;       /* Platform limitation on freq usage */
+    uint32_t platform_limit;  /* Platform limitation on freq usage */
     struct xen_pct_register control_register;
     struct xen_pct_register status_register;
     uint32_t state_count;     /* total available performance states */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.