ia64/linux-2.6.18-xen.hg

changeset 532:e97855b90cc2

Notify xen about Cx acpi info, such as table returned by _CST/_CSD methods.

Add notifiers for P/T & hotplug as placeholders.
Add option "xen_processor_pmbits" for enable/disable control.

Signed-off-by: Tian Kevin <kevin.tian@intel.com>
Signed-off-by: Wei Gang <gang.wei@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu May 01 10:53:07 2008 +0100 (2008-05-01)
parents 3c564f80f2ef
children d62d60eaba6e
files arch/i386/kernel/acpi/Makefile arch/i386/kernel/acpi/processor_extcntl_xen.c arch/x86_64/kernel/acpi/Makefile drivers/acpi/Kconfig drivers/acpi/processor_extcntl.c drivers/acpi/processor_idle.c include/acpi/processor.h include/xen/interface/platform.h
line diff
     1.1 --- a/arch/i386/kernel/acpi/Makefile	Thu May 01 10:52:31 2008 +0100
     1.2 +++ b/arch/i386/kernel/acpi/Makefile	Thu May 01 10:53:07 2008 +0100
     1.3 @@ -1,6 +1,7 @@
     1.4  obj-$(CONFIG_ACPI)		+= boot.o
     1.5  obj-$(CONFIG_X86_IO_APIC)	+= earlyquirk.o
     1.6  obj-$(CONFIG_ACPI_SLEEP)	+= sleep.o wakeup.o
     1.7 +obj-$(CONFIG_XEN)		+= processor_extcntl_xen.o
     1.8  
     1.9  ifneq ($(CONFIG_ACPI_PROCESSOR),)
    1.10  obj-y				+= cstate.o processor.o
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/arch/i386/kernel/acpi/processor_extcntl_xen.c	Thu May 01 10:53:07 2008 +0100
     2.3 @@ -0,0 +1,142 @@
     2.4 +/*
     2.5 + * processor_extcntl_xen.c - interface to notify Xen
     2.6 + *
     2.7 + *  Copyright (C) 2008, Intel corporation
     2.8 + *
     2.9 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    2.10 + *
    2.11 + *  This program is free software; you can redistribute it and/or modify
    2.12 + *  it under the terms of the GNU General Public License as published by
    2.13 + *  the Free Software Foundation; either version 2 of the License, or (at
    2.14 + *  your option) any later version.
    2.15 + *
    2.16 + *  This program is distributed in the hope that it will be useful, but
    2.17 + *  WITHOUT ANY WARRANTY; without even the implied warranty of
    2.18 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    2.19 + *  General Public License for more details.
    2.20 + *
    2.21 + *  You should have received a copy of the GNU General Public License along
    2.22 + *  with this program; if not, write to the Free Software Foundation, Inc.,
    2.23 + *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
    2.24 + *
    2.25 + */
    2.26 +
    2.27 +#include <linux/kernel.h>
    2.28 +#include <linux/init.h>
    2.29 +#include <linux/types.h>
    2.30 +#include <linux/acpi.h>
    2.31 +#include <linux/pm.h>
    2.32 +#include <linux/cpu.h>
    2.33 +
    2.34 +#include <acpi/processor.h>
    2.35 +#include <asm/hypercall.h>
    2.36 +
    2.37 +static int xen_processor_pmbits;
    2.38 +static int __init set_xen_processor_pmbits(char *str)
    2.39 +{
    2.40 +	get_option(&str, &xen_processor_pmbits);
    2.41 +
    2.42 +	return 1;
    2.43 +}
    2.44 +__setup("xen_processor_pmbits=", set_xen_processor_pmbits);
    2.45 +EXPORT_SYMBOL(xen_processor_pmbits);
    2.46 +
    2.47 +static int xen_cx_notifier(struct acpi_processor *pr, int action)
    2.48 +{
    2.49 +	int ret, count = 0, i;
    2.50 +	xen_platform_op_t op = {
    2.51 +		.cmd			= XENPF_set_processor_pminfo,
    2.52 +		.interface_version	= XENPF_INTERFACE_VERSION,
    2.53 +		.u.set_pminfo.id	= pr->acpi_id,
    2.54 +		.u.set_pminfo.type	= XEN_PM_CX,
    2.55 +	};
    2.56 +	struct xen_processor_cx *data, *buf;
    2.57 +	struct acpi_processor_cx *cx;
    2.58 +
    2.59 +	if (action == PROCESSOR_PM_CHANGE)
    2.60 +		return -EINVAL;
    2.61 +
    2.62 +	/* Convert to Xen defined structure and hypercall */
    2.63 +	buf = kzalloc(pr->power.count * sizeof(struct xen_processor_cx),
    2.64 +			GFP_KERNEL);
    2.65 +	if (!buf)
    2.66 +		return -ENOMEM;
    2.67 +
    2.68 +	data = buf;
    2.69 +	for (i = 1; i <= pr->power.count; i++) {
    2.70 +		cx = &pr->power.states[i];
    2.71 +		/* Skip invalid cstate entry */
    2.72 +		if (!cx->valid)
    2.73 +			continue;
    2.74 +
    2.75 +		data->type = cx->type;
    2.76 +		data->latency = cx->latency;
    2.77 +		data->power = cx->power;
    2.78 +		data->reg.space_id = cx->reg.space_id;
    2.79 +		data->reg.bit_width = cx->reg.bit_width;
    2.80 +		data->reg.bit_offset = cx->reg.bit_offset;
    2.81 +		data->reg.access_size = cx->reg.reserved;
    2.82 +		data->reg.address = cx->reg.address;
    2.83 +
    2.84 +		/* Get dependency relationships */
    2.85 +		if (cx->csd_count) {
    2.86 +			printk("Wow! _CSD is found. Not support for now!\n");
    2.87 +			kfree(buf);
    2.88 +			return -EINVAL;
    2.89 +		} else {
    2.90 +			data->dpcnt = 0;
    2.91 +			set_xen_guest_handle(data->dp, NULL);
    2.92 +		}
    2.93 +
    2.94 +		data++;
    2.95 +		count++;
    2.96 +	}
    2.97 +
    2.98 +	if (!count) {
    2.99 +		printk("No available Cx info for cpu %d\n", pr->acpi_id);
   2.100 +		kfree(buf);
   2.101 +		return -EINVAL;
   2.102 +	}
   2.103 +
   2.104 +	op.u.set_pminfo.power.count = count;
   2.105 +	op.u.set_pminfo.power.flags.bm_control = pr->flags.bm_control;
   2.106 +	op.u.set_pminfo.power.flags.bm_check = pr->flags.bm_check;
   2.107 +	op.u.set_pminfo.power.flags.has_cst = pr->flags.has_cst;
   2.108 +	op.u.set_pminfo.power.flags.power_setup_done = pr->flags.power_setup_done;
   2.109 +
   2.110 +	set_xen_guest_handle(op.u.set_pminfo.power.states, buf);
   2.111 +	ret = HYPERVISOR_platform_op(&op);
   2.112 +	kfree(buf);
   2.113 +	return ret;
   2.114 +}
   2.115 +
   2.116 +static int xen_px_notifier(struct acpi_processor *pr, int action)
   2.117 +{
   2.118 +	return -EINVAL;
   2.119 +}
   2.120 +
   2.121 +static int xen_tx_notifier(struct acpi_processor *pr, int action)
   2.122 +{
   2.123 +	return -EINVAL;
   2.124 +}
   2.125 +static int xen_hotplug_notifier(struct acpi_processor *pr, int event)
   2.126 +{
   2.127 +	return -EINVAL;
   2.128 +}
   2.129 +
   2.130 +static struct processor_extcntl_ops xen_extcntl_ops = {
   2.131 +	.hotplug		= xen_hotplug_notifier,
   2.132 +};
   2.133 +
   2.134 +static int __cpuinit xen_init_processor_extcntl(void)
   2.135 +{
   2.136 +	if (xen_processor_pmbits & XEN_PROCESSOR_PM_CX)
   2.137 +		xen_extcntl_ops.pm_ops[PM_TYPE_IDLE] = xen_cx_notifier;
   2.138 +	if (xen_processor_pmbits & XEN_PROCESSOR_PM_PX)
   2.139 +		xen_extcntl_ops.pm_ops[PM_TYPE_PERF] = xen_px_notifier;
   2.140 +	if (xen_processor_pmbits & XEN_PROCESSOR_PM_TX)
   2.141 +		xen_extcntl_ops.pm_ops[PM_TYPE_THR] = xen_tx_notifier;
   2.142 +
   2.143 +	return processor_register_extcntl(&xen_extcntl_ops);
   2.144 +}
   2.145 +core_initcall(xen_init_processor_extcntl);
     3.1 --- a/arch/x86_64/kernel/acpi/Makefile	Thu May 01 10:52:31 2008 +0100
     3.2 +++ b/arch/x86_64/kernel/acpi/Makefile	Thu May 01 10:53:07 2008 +0100
     3.3 @@ -8,4 +8,6 @@ processor-y		:= ../../../i386/kernel/acp
     3.4  processor-$(CONFIG_XEN)	:= ../../../i386/kernel/acpi/processor.o
     3.5  endif
     3.6  
     3.7 +obj-$(CONFIG_XEN)	+= processor_extcnt_xen.o
     3.8 +processor_extcnt_xen-$(CONFIG_XEN) := ../../../i386/kernel/acpi/processor_extcntl_xen.o
     3.9  disabled-obj-$(CONFIG_XEN) := wakeup.o
     4.1 --- a/drivers/acpi/Kconfig	Thu May 01 10:52:31 2008 +0100
     4.2 +++ b/drivers/acpi/Kconfig	Thu May 01 10:53:07 2008 +0100
     4.3 @@ -371,6 +371,7 @@ config ACPI_PV_SLEEP
     4.4  config PROCESSOR_EXTERNAL_CONTROL
     4.5  	bool
     4.6  	depends on X86 && XEN
     4.7 +	select ACPI_PROCESSOR
     4.8  	default y
     4.9  endif	# ACPI
    4.10  
     5.1 --- a/drivers/acpi/processor_extcntl.c	Thu May 01 10:52:31 2008 +0100
     5.2 +++ b/drivers/acpi/processor_extcntl.c	Thu May 01 10:53:07 2008 +0100
     5.3 @@ -30,6 +30,7 @@
     5.4  
     5.5  #include <acpi/processor.h>
     5.6  
     5.7 +static int processor_extcntl_parse_csd(struct acpi_processor *pr);
     5.8  /*
     5.9   * External processor control logic may register with its own set of
    5.10   * ops to get ACPI related notification. One example is like VMM.
    5.11 @@ -107,5 +108,30 @@ int processor_unregister_extcntl(struct 
    5.12   */
    5.13  int processor_extcntl_init(struct acpi_processor *pr)
    5.14  {
    5.15 +	/* parse cstate dependency information */
    5.16 +	processor_extcntl_parse_csd(pr);
    5.17 +
    5.18  	return 0;
    5.19  }
    5.20 +
    5.21 +/*
    5.22 + * Currently no _CSD is implemented which is why existing ACPI code
    5.23 + * doesn't parse _CSD at all. But to keep interface complete with
    5.24 + * external control logic, we put a placeholder here for future
    5.25 + * compatibility.
    5.26 + */
    5.27 +static int processor_extcntl_parse_csd(struct acpi_processor *pr)
    5.28 +{
    5.29 +	int i;
    5.30 +
    5.31 +	for (i = 0; i < pr->power.count; i++) {
    5.32 +		if (!pr->power.states[i].valid)
    5.33 +			continue;
    5.34 +
    5.35 +		/* No dependency by default */
    5.36 +		pr->power.states[i].domain_info = NULL;
    5.37 +		pr->power.states[i].csd_count = 0;
    5.38 +	}
    5.39 +
    5.40 +	return 0;
    5.41 +}
     6.1 --- a/drivers/acpi/processor_idle.c	Thu May 01 10:52:31 2008 +0100
     6.2 +++ b/drivers/acpi/processor_idle.c	Thu May 01 10:53:07 2008 +0100
     6.3 @@ -714,8 +714,12 @@ static int acpi_processor_get_power_info
     6.4  		    (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE))
     6.5  			continue;
     6.6  
     6.7 -		cx.address = (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) ?
     6.8 -		    0 : reg->address;
     6.9 +		if (!processor_pm_external())
    6.10 +			cx.address = (reg->space_id ==
    6.11 +				      ACPI_ADR_SPACE_FIXED_HARDWARE) ?
    6.12 +		    		      0 : reg->address;
    6.13 +		else
    6.14 +			cx.address = reg->address;
    6.15  
    6.16  		/* There should be an easy way to extract an integer... */
    6.17  		obj = (union acpi_object *)&(element->package.elements[1]);
    6.18 @@ -724,9 +728,11 @@ static int acpi_processor_get_power_info
    6.19  
    6.20  		cx.type = obj->integer.value;
    6.21  
    6.22 -		if ((cx.type != ACPI_STATE_C1) &&
    6.23 -		    (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO))
    6.24 -			continue;
    6.25 +		/* Following check doesn't apply to external control case */
    6.26 +		if (!processor_pm_external())
    6.27 +			if ((cx.type != ACPI_STATE_C1) &&
    6.28 +			    (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO))
    6.29 +				continue;
    6.30  
    6.31  		if ((cx.type < ACPI_STATE_C2) || (cx.type > ACPI_STATE_C3))
    6.32  			continue;
    6.33 @@ -743,6 +749,12 @@ static int acpi_processor_get_power_info
    6.34  
    6.35  		cx.power = obj->integer.value;
    6.36  
    6.37 +#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
    6.38 +		/* cache control methods to notify external logic */
    6.39 +		if (processor_pm_external())
    6.40 +			memcpy(&cx.reg, reg, sizeof(*reg));
    6.41 +#endif
    6.42 +
    6.43  		current_count++;
    6.44  		memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx));
    6.45  
     7.1 --- a/include/acpi/processor.h	Thu May 01 10:52:31 2008 +0100
     7.2 +++ b/include/acpi/processor.h	Thu May 01 10:53:07 2008 +0100
     7.3 @@ -33,6 +33,17 @@
     7.4  
     7.5  struct acpi_processor_cx;
     7.6  
     7.7 +#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
     7.8 +struct acpi_csd_package {
     7.9 +	acpi_integer num_entries;
    7.10 +	acpi_integer revision;
    7.11 +	acpi_integer domain;
    7.12 +	acpi_integer coord_type;
    7.13 +	acpi_integer num_processors;
    7.14 +	acpi_integer index;
    7.15 +} __attribute__ ((packed));
    7.16 +#endif
    7.17 +
    7.18  struct acpi_power_register {
    7.19  	u8 descriptor;
    7.20  	u16 length;
    7.21 @@ -63,6 +74,12 @@ struct acpi_processor_cx {
    7.22  	u32 power;
    7.23  	u32 usage;
    7.24  	u64 time;
    7.25 +#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
    7.26 +	/* Require raw information for external control logic */
    7.27 +	struct acpi_power_register reg;
    7.28 +	u32 csd_count;
    7.29 +	struct acpi_csd_package *domain_info;
    7.30 +#endif
    7.31  	struct acpi_processor_cx_policy promotion;
    7.32  	struct acpi_processor_cx_policy demotion;
    7.33  };
     8.1 --- a/include/xen/interface/platform.h	Thu May 01 10:52:31 2008 +0100
     8.2 +++ b/include/xen/interface/platform.h	Thu May 01 10:53:07 2008 +0100
     8.3 @@ -199,6 +199,78 @@ struct xenpf_getidletime {
     8.4  typedef struct xenpf_getidletime xenpf_getidletime_t;
     8.5  DEFINE_XEN_GUEST_HANDLE(xenpf_getidletime_t);
     8.6  
     8.7 +#define XENPF_set_processor_pminfo      54
     8.8 +
     8.9 +/* ability bits */
    8.10 +#define XEN_PROCESSOR_PM_CX	1
    8.11 +#define XEN_PROCESSOR_PM_PX	2
    8.12 +#define XEN_PROCESSOR_PM_TX	4
    8.13 +
    8.14 +/* cmd type */
    8.15 +#define XEN_PM_CX   0
    8.16 +#define XEN_PM_PX   1
    8.17 +#define XEN_PM_TX   2
    8.18 +
    8.19 +struct xen_power_register {
    8.20 +    uint32_t     space_id;
    8.21 +    uint32_t     bit_width;
    8.22 +    uint32_t     bit_offset;
    8.23 +    uint32_t     access_size;
    8.24 +    uint64_t     address;
    8.25 +};
    8.26 +
    8.27 +struct xen_processor_csd {
    8.28 +    uint32_t    domain;      /* domain number of one dependent group */
    8.29 +    uint32_t    coord_type;  /* coordination type */
    8.30 +    uint32_t    num;         /* number of processors in same domain */
    8.31 +};
    8.32 +typedef struct xen_processor_csd xen_processor_csd_t;
    8.33 +DEFINE_XEN_GUEST_HANDLE(xen_processor_csd_t);
    8.34 +
    8.35 +struct xen_processor_cx {
    8.36 +    struct xen_power_register  reg; /* GAS for Cx trigger register */
    8.37 +    uint8_t     type;     /* cstate value, c0: 0, c1: 1, ... */
    8.38 +    uint32_t    latency;  /* worst latency (ms) to enter/exit this cstate */
    8.39 +    uint32_t    power;    /* average power consumption(mW) */
    8.40 +    uint32_t    dpcnt;    /* number of dependency entries */
    8.41 +    XEN_GUEST_HANDLE(xen_processor_csd_t) dp; /* NULL if no dependency */
    8.42 +};
    8.43 +typedef struct xen_processor_cx xen_processor_cx_t;
    8.44 +DEFINE_XEN_GUEST_HANDLE(xen_processor_cx_t);
    8.45 +
    8.46 +struct xen_processor_flags {
    8.47 +    uint8_t bm_control:1;
    8.48 +    uint8_t bm_check:1;
    8.49 +    uint8_t has_cst:1;
    8.50 +    uint8_t power_setup_done:1;
    8.51 +    uint8_t bm_rld_set:1;
    8.52 +};
    8.53 +
    8.54 +struct xen_processor_power {
    8.55 +    uint32_t count;  /* number of C state entries in array below */
    8.56 +    struct xen_processor_flags flags;  /* global flags of this processor */
    8.57 +    XEN_GUEST_HANDLE(xen_processor_cx_t) states; /* supported c states */
    8.58 +};
    8.59 +
    8.60 +struct xen_processor_performance {
    8.61 +};
    8.62 +
    8.63 +struct xen_processor_throttling {
    8.64 +};
    8.65 +
    8.66 +struct xenpf_set_processor_pminfo {
    8.67 +    /* IN variables */
    8.68 +    uint32_t id;    /* ACPI CPU ID */
    8.69 +    uint32_t type;  /* {XEN_PM_CX, XEN_PM_PX, XEN_PM_TX} */
    8.70 +    union {
    8.71 +        struct xen_processor_power          power;/* Cx: _CST/_CSD */
    8.72 +        struct xen_processor_performance    perf; /* Px: _PPC/_PCT/_PSS/_PSD */
    8.73 +        struct xen_processor_throttling     throt;/* Tx: _TPC/_PTC/_TSS/_TSD */
    8.74 +    };
    8.75 +};
    8.76 +typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t;
    8.77 +DEFINE_XEN_GUEST_HANDLE(xenpf_set_processor_pminfo_t);
    8.78 +
    8.79  struct xen_platform_op {
    8.80      uint32_t cmd;
    8.81      uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
    8.82 @@ -213,6 +285,7 @@ struct xen_platform_op {
    8.83          struct xenpf_enter_acpi_sleep  enter_acpi_sleep;
    8.84          struct xenpf_change_freq       change_freq;
    8.85          struct xenpf_getidletime       getidletime;
    8.86 +        struct xenpf_set_processor_pminfo set_pminfo;
    8.87          uint8_t                        pad[128];
    8.88      } u;
    8.89  };