From mboxrd@z Thu Jan 1 00:00:00 1970 From: Konrad Rzeszutek Wilk Subject: Re: Is: drivers/cpufreq/cpufreq-xen.c Was:Re: [PATCH 2 of 2] linux-xencommons: Load processor-passthru Date: Tue, 13 Mar 2012 12:46:28 -0400 Message-ID: <20120313164628.GD19228@phenom.dumpdata.com> References: <20120306175948.GA6656@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Return-path: Content-Disposition: inline In-Reply-To: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: Konrad Rzeszutek Wilk , davej@redhat.com Cc: xen-devel@lists.xensource.com, Ian.Jackson@eu.citrix.com, Ian.Campbell@citrix.com, Jan Beulich , stefano.stabellini@eu.citrix.com List-Id: xen-devel@lists.xenproject.org On Wed, Mar 07, 2012 at 09:12:00PM -0500, Konrad Rzeszutek Wilk wrote: > > =A0> I think what you are suggesting is that to write a driver in drive= rs/cpufreq/ > > =A0> that gets either started before the other ones (if built-in) or if= as > > =A0> a module gets > > =A0> loaded from xencommons. That driver would then make the call > > =A0> to acpi_processor_preregister_performance(), > > =A0> acpi_processor_register_performance() and acpi_processor_notify_sm= m(). > > =A0> It would function as a cpufreq-scaling driver but > > =A0> in reality all calls to it from cpufreq gov-* drivers would end up= with nop. > > =A0> > > =A0> Dave, would you be Ok with a driver like that in your tree? > > > > I joined this thread half-way through, so I'm not sure what the origina= l problem was. > > How is a driver that does nothing better than just masking out the cpuf= req capabilities to guests ? > Hey Dave, > = > The problem statement is three-fold: > 1). Parse and upload ACPI0007 (or PROCESSOR_TYPE) information to the > hypervisor - aka P-states. > 2). Upload the Cx state information. > 3). Inhibit CPU frequency scaling drivers from loading. .. snip.. > So my big question is whether could be a 'cpufreq.off=3D1' API, similar > to the "disable_cpuidle()" > call that inhibit the cpuidle drivers? Which would look like this (compile tested, but not extensivly): diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 1236623..1ba8dff 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -10,6 +10,7 @@ #include #include #include +#include = #include #include @@ -420,6 +421,7 @@ void __init xen_arch_setup(void) boot_cpu_data.hlt_works_ok =3D 1; #endif disable_cpuidle(); + disable_cpufreq(); WARN_ON(set_pm_idle_to_default()); fiddle_vdso(); } diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 622013f..7f2f149 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -126,6 +126,15 @@ static int __init init_cpufreq_transition_notifier_lis= t(void) } pure_initcall(init_cpufreq_transition_notifier_list); = +static int off __read_mostly; +int cpufreq_disabled(void) +{ + return off; +} +void disable_cpufreq(void) +{ + off =3D 1; +} static LIST_HEAD(cpufreq_governor_list); static DEFINE_MUTEX(cpufreq_governor_mutex); = @@ -1441,6 +1450,9 @@ int __cpufreq_driver_target(struct cpufreq_policy *po= licy, { int retval =3D -EINVAL; = + if (cpufreq_disabled()) + return -ENODEV; + pr_debug("target for CPU %u: %u kHz, relation %u\n", policy->cpu, target_freq, relation); if (cpu_online(policy->cpu) && cpufreq_driver->target) @@ -1549,6 +1561,9 @@ int cpufreq_register_governor(struct cpufreq_governor= *governor) if (!governor) return -EINVAL; = + if (cpufreq_disabled()) + return -ENODEV; + mutex_lock(&cpufreq_governor_mutex); = err =3D -EBUSY; @@ -1572,6 +1587,9 @@ void cpufreq_unregister_governor(struct cpufreq_gover= nor *governor) if (!governor) return; = + if (cpufreq_disabled()) + return; + #ifdef CONFIG_HOTPLUG_CPU for_each_present_cpu(cpu) { if (cpu_online(cpu)) @@ -1814,6 +1832,9 @@ int cpufreq_register_driver(struct cpufreq_driver *dr= iver_data) unsigned long flags; int ret; = + if (cpufreq_disabled()) + return -ENODEV; + if (!driver_data || !driver_data->verify || !driver_data->init || ((!driver_data->setpolicy) && (!driver_data->target))) return -EINVAL; @@ -1901,6 +1922,9 @@ static int __init cpufreq_core_init(void) { int cpu; = + if (cpufreq_disabled()) + return -ENODEV; + for_each_possible_cpu(cpu) { per_cpu(cpufreq_policy_cpu, cpu) =3D -1; init_rwsem(&per_cpu(cpu_policy_rwsem, cpu)); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 6216115..8ff4427 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -35,6 +35,7 @@ #ifdef CONFIG_CPU_FREQ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list= ); int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int li= st); +extern void disable_cpufreq(void); #else /* CONFIG_CPU_FREQ */ static inline int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) @@ -46,6 +47,7 @@ static inline int cpufreq_unregister_notifier(struct noti= fier_block *nb, { return 0; } +static inline void disable_cpufreq(void) { } #endif /* CONFIG_CPU_FREQ */ = /* if (cpufreq_driver->target) exists, the ->governor decides what frequen= cy