linux-stable/drivers/cpufreq
Srivatsa S. Bhat ca654dc3a9 cpufreq: Catch double invocations of cpufreq_freq_transition_begin/end
Some cpufreq drivers were redundantly invoking the _begin() and _end()
APIs around frequency transitions, and this double invocation (one from
the cpufreq core and the other from the cpufreq driver) used to result
in a self-deadlock, leading to system hangs during boot. (The _begin()
API makes contending callers wait until the previous invocation is
complete. Hence, the cpufreq driver would end up waiting on itself!).

Now all such drivers have been fixed, but debugging this issue was not
very straight-forward (even lockdep didn't catch this). So let us add a
debug infrastructure to the cpufreq core to catch such issues more easily
in the future.

We add a new field called 'transition_task' to the policy structure, to keep
track of the task which is performing the frequency transition. Using this
field, we make note of this task during _begin() and print a warning if we
find a case where the same task is calling _begin() again, before completing
the previous frequency transition using the corresponding _end().

We have left out ASYNC_NOTIFICATION drivers from this debug infrastructure
for 2 reasons:

1. At the moment, we have no way to avoid a particular scenario where this
   debug infrastructure can emit false-positive warnings for such drivers.
   The scenario is depicted below:

         Task A						Task B

    /* 1st freq transition */
    Invoke _begin() {
            ...
            ...
    }

    Change the frequency

    /* 2nd freq transition */
    Invoke _begin() {
	    ...	//waiting for B to
            ... //finish _end() for
	    ... //the 1st transition
	    ...	      |				Got interrupt for successful
	    ...	      |				change of frequency (1st one).
	    ...       |
	    ...	      |				/* 1st freq transition */
	    ...	      |				Invoke _end() {
	    ...	      |					...
	    ...	      V				}
	    ...
	    ...
    }

   This scenario is actually deadlock-free because, once Task A changes the
   frequency, it is Task B's responsibility to invoke the corresponding
   _end() for the 1st frequency transition. Hence it is perfectly legal for
   Task A to go ahead and attempt another frequency transition in the meantime.
   (Of course it won't be able to proceed until Task B finishes the 1st _end(),
   but this doesn't cause a deadlock or a hang).

   The debug infrastructure cannot handle this scenario and will treat it as
   a deadlock and print a warning. To avoid this, we exclude such drivers
   from the purview of this code.

2. Luckily, we don't _need_ this infrastructure for ASYNC_NOTIFICATION drivers
   at all! The cpufreq core does not automatically invoke the _begin() and
   _end() APIs during frequency transitions in such drivers. Thus, the driver
   alone is responsible for invoking _begin()/_end() and hence there shouldn't
   be any conflicts which lead to double invocations. So, we can skip these
   drivers, since the probability that such drivers will hit this problem is
   extremely low, as outlined above.

Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2014-05-07 00:32:39 +02:00
..
acpi-cpufreq.c cpufreq: Use cpufreq_for_each_* macros for frequency table iteration 2014-04-30 00:06:21 +02:00
amd_freq_sensitivity.c cpufreq: AMD "frequency sensitivity feedback" powersave bias for ondemand governor 2013-04-10 13:19:26 +02:00
arm_big_little.c cpufreq: Use cpufreq_for_each_* macros for frequency table iteration 2014-04-30 00:06:21 +02:00
arm_big_little.h cpufreq: arm_big_little: add in-kernel switching (IKS) support 2013-10-31 00:10:53 +01:00
arm_big_little_dt.c PM / OPP: rename header to linux/pm_opp.h 2013-10-25 22:33:23 +02:00
at32ap-cpufreq.c cpufreq: at32ap: don't declare local variable as static 2014-04-07 14:31:33 +02:00
blackfin-cpufreq.c cpufreq: Remove cpufreq_generic_exit() 2014-03-12 01:06:00 +01:00
cpufreq-cpu0.c cpufreq: Remove cpufreq_generic_exit() 2014-03-12 01:06:00 +01:00
cpufreq-nforce2.c cpufreq: Convert existing drivers to use cpufreq_freq_transition_{begin|end} 2014-03-26 16:41:41 +01:00
cpufreq.c cpufreq: Catch double invocations of cpufreq_freq_transition_begin/end 2014-05-07 00:32:39 +02:00
cpufreq_conservative.c cpufreq: conservative: set requested_freq to policy max when it is over policy max 2013-11-12 23:18:20 +01:00
cpufreq_governor.c cpufreq: Fix timer/workqueue corruption by protecting reading governor_enabled 2014-01-06 01:22:02 +01:00
cpufreq_governor.h cpufreq: Fix timer/workqueue corruption by protecting reading governor_enabled 2014-01-06 01:22:02 +01:00
cpufreq_ondemand.c cpufreq: ondemand: Remove redundant return statement 2013-11-01 00:44:34 +01:00
cpufreq_performance.c cpufreq: Clean up header files included in the core 2013-08-07 23:34:09 +02:00
cpufreq_powersave.c cpufreq: Clean up header files included in the core 2013-08-07 23:34:09 +02:00
cpufreq_stats.c cpufreq: Use cpufreq_for_each_* macros for frequency table iteration 2014-04-30 00:06:21 +02:00
cpufreq_userspace.c cpufreq / governor: Remove fossil comment 2013-10-17 23:00:20 +02:00
cris-artpec3-cpufreq.c cpufreq: create another field .flags in cpufreq_frequency_table 2014-04-07 14:43:50 +02:00
cris-etraxfs-cpufreq.c cpufreq: create another field .flags in cpufreq_frequency_table 2014-04-07 14:43:50 +02:00
davinci-cpufreq.c cpufreq: Remove cpufreq_generic_exit() 2014-03-12 01:06:00 +01:00
dbx500-cpufreq.c cpufreq: Use cpufreq_for_each_* macros for frequency table iteration 2014-04-30 00:06:21 +02:00
e_powersaver.c cpufreq: add 'freq_table' in struct cpufreq_policy 2014-03-12 01:06:00 +01:00
elanfreq.c cpufreq: Use cpufreq_for_each_* macros for frequency table iteration 2014-04-30 00:06:21 +02:00
exynos-cpufreq.c cpufreq: exynos: Use dev_err/info function instead of pr_err/info 2014-05-01 01:00:39 +02:00
exynos-cpufreq.h cpufreq: exynos: Use dev_err/info function instead of pr_err/info 2014-05-01 01:00:39 +02:00
exynos4x12-cpufreq.c cpufreq: create another field .flags in cpufreq_frequency_table 2014-04-07 14:43:50 +02:00
exynos4210-cpufreq.c cpufreq: create another field .flags in cpufreq_frequency_table 2014-04-07 14:43:50 +02:00
exynos5250-cpufreq.c cpufreq: create another field .flags in cpufreq_frequency_table 2014-04-07 14:43:50 +02:00
exynos5440-cpufreq.c cpufreq: Use cpufreq_for_each_* macros for frequency table iteration 2014-04-30 00:06:21 +02:00
freq_table.c cpufreq: Use cpufreq_for_each_* macros for frequency table iteration 2014-04-30 00:06:21 +02:00
gx-suspmod.c cpufreq: Convert existing drivers to use cpufreq_freq_transition_{begin|end} 2014-03-26 16:41:41 +01:00
highbank-cpufreq.c cpufreq: highbank-cpufreq: Enable Midway/ECX-2000 2013-10-17 00:53:08 +02:00
ia64-acpi-cpufreq.c cpufreq: use kzalloc() to allocate memory for cpufreq_frequency_table 2014-04-07 14:43:49 +02:00
imx6q-cpufreq.c cpufreq: Remove cpufreq_generic_exit() 2014-03-12 01:06:00 +01:00
integrator-cpufreq.c cpufreq: Convert existing drivers to use cpufreq_freq_transition_{begin|end} 2014-03-26 16:41:41 +01:00
intel_pstate.c intel_pstate: Remove sample parameter in intel_pstate_calc_busy 2014-05-07 00:29:51 +02:00
Kconfig cpufreq: enable ARM drivers on arm64 2014-03-01 00:55:40 +01:00
Kconfig.arm cpufreq: Kconfig: Fix spelling errors 2014-05-01 01:18:19 +02:00
Kconfig.powerpc cpufreq: powernv: cpufreq driver for powernv platform 2014-04-07 14:35:27 +02:00
Kconfig.x86 cpufreq: Kconfig: Fix spelling errors 2014-05-01 01:18:19 +02:00
kirkwood-cpufreq.c cpufreq: create another field .flags in cpufreq_frequency_table 2014-04-07 14:43:50 +02:00
longhaul.c Merge branch 'cpufreq-macros' into pm-cpufreq 2014-05-01 00:50:47 +02:00
longhaul.h cpufreq: delete __cpuinit usage from all cpufreq files 2013-07-14 19:36:57 -04:00
longrun.c cpufreq: add new routine cpufreq_verify_within_cpu_limits() 2013-10-16 00:50:23 +02:00
loongson2_cpufreq.c cpufreq: loongson2_cpufreq: don't declare local variable as static 2014-04-07 14:30:13 +02:00
Makefile cpufreq: powernv: cpufreq driver for powernv platform 2014-04-07 14:35:27 +02:00
maple-cpufreq.c cpufreq: create another field .flags in cpufreq_frequency_table 2014-04-07 14:43:50 +02:00
omap-cpufreq.c cpufreq: add 'freq_table' in struct cpufreq_policy 2014-03-12 01:06:00 +01:00
p4-clockmod.c cpufreq: create another field .flags in cpufreq_frequency_table 2014-04-07 14:43:50 +02:00
pasemi-cpufreq.c cpufreq: Use cpufreq_for_each_* macros for frequency table iteration 2014-04-30 00:06:21 +02:00
pcc-cpufreq.c cpufreq: Convert existing drivers to use cpufreq_freq_transition_{begin|end} 2014-03-26 16:41:41 +01:00
pmac32-cpufreq.c cpufreq: create another field .flags in cpufreq_frequency_table 2014-04-07 14:43:50 +02:00
pmac64-cpufreq.c cpufreq: create another field .flags in cpufreq_frequency_table 2014-04-07 14:43:50 +02:00
powernow-k6.c Merge branch 'cpufreq-macros' into pm-cpufreq 2014-05-01 00:50:47 +02:00
powernow-k7.c cpufreq: powernow-k7: Fix double invocation of cpufreq_freq_transition_begin/end 2014-04-29 01:22:54 +02:00
powernow-k7.h
powernow-k8.c cpufreq: use kzalloc() to allocate memory for cpufreq_frequency_table 2014-04-07 14:43:49 +02:00
powernow-k8.h cpufreq: Remove support for hardware P-state chips from powernow-k8 2012-09-09 22:05:30 +02:00
powernv-cpufreq.c cpufreq, powernv: Fix build failure on UP 2014-04-21 23:43:38 +02:00
ppc-corenet-cpufreq.c cpufreq: ppc-corenet-cpufreq: Fix __udivdi3 modpost error 2014-04-29 01:28:17 +02:00
ppc_cbe_cpufreq.c cpufreq: Use cpufreq_for_each_* macros for frequency table iteration 2014-04-30 00:06:21 +02:00
ppc_cbe_cpufreq.h cpufreq: powerpc/platforms/cell: move cpufreq driver to drivers/cpufreq 2013-04-10 13:19:26 +02:00
ppc_cbe_cpufreq_pervasive.c cpufreq: powerpc/platforms/cell: move cpufreq driver to drivers/cpufreq 2013-04-10 13:19:26 +02:00
ppc_cbe_cpufreq_pmi.c cpufreq: powerpc/platforms/cell: move cpufreq driver to drivers/cpufreq 2013-04-10 13:19:26 +02:00
pxa2xx-cpufreq.c cpufreq: Remove cpufreq_generic_exit() 2014-03-12 01:06:00 +01:00
pxa3xx-cpufreq.c cpufreq: Remove cpufreq_generic_exit() 2014-03-12 01:06:00 +01:00
s3c24xx-cpufreq-debugfs.c cpufreq: s3c24xx: move cpufreq driver to drivers/cpufreq 2013-05-20 23:04:28 +09:00
s3c24xx-cpufreq.c cpufreq: use kzalloc() to allocate memory for cpufreq_frequency_table 2014-04-07 14:43:49 +02:00
s3c64xx-cpufreq.c cpufreq: Use cpufreq_for_each_* macros for frequency table iteration 2014-04-30 00:06:21 +02:00
s3c2410-cpufreq.c cpufreq: s3c24xx: move cpufreq driver to drivers/cpufreq 2013-05-20 23:04:28 +09:00
s3c2412-cpufreq.c cpufreq: s3c24xx: move cpufreq driver to drivers/cpufreq 2013-05-20 23:04:28 +09:00
s3c2416-cpufreq.c cpufreq: Use cpufreq_for_each_* macros for frequency table iteration 2014-04-30 00:06:21 +02:00
s3c2440-cpufreq.c cpufreq: s3c2440: Staticize local variables 2014-01-06 01:18:33 +01:00
s5pv210-cpufreq.c cpufreq: create another field .flags in cpufreq_frequency_table 2014-04-07 14:43:50 +02:00
sa1100-cpufreq.c cpufreq: Mark ARM drivers with CPUFREQ_NEED_INITIAL_FREQ_CHECK flag 2014-01-06 14:17:25 +01:00
sa1110-cpufreq.c cpufreq: Mark ARM drivers with CPUFREQ_NEED_INITIAL_FREQ_CHECK flag 2014-01-06 14:17:25 +01:00
sc520_freq.c cpufreq: create another field .flags in cpufreq_frequency_table 2014-04-07 14:43:50 +02:00
sh-cpufreq.c cpufreq: Convert existing drivers to use cpufreq_freq_transition_{begin|end} 2014-03-26 16:41:41 +01:00
sparc-us2e-cpufreq.c cpufreq: add 'freq_table' in struct cpufreq_policy 2014-03-12 01:06:00 +01:00
sparc-us3-cpufreq.c cpufreq: add 'freq_table' in struct cpufreq_policy 2014-03-12 01:06:00 +01:00
spear-cpufreq.c cpufreq: use kzalloc() to allocate memory for cpufreq_frequency_table 2014-04-07 14:43:49 +02:00
speedstep-centrino.c cpufreq: Make linux-pm@vger.kernel.org official mailing list 2014-05-01 01:15:32 +02:00
speedstep-ich.c cpufreq: create another field .flags in cpufreq_frequency_table 2014-04-07 14:43:50 +02:00
speedstep-lib.c cpufreq: Add support for x86 cpuinfo auto loading v4 2012-01-26 16:49:06 -08:00
speedstep-lib.h
speedstep-smi.c cpufreq: create another field .flags in cpufreq_frequency_table 2014-04-07 14:43:50 +02:00
tegra-cpufreq.c cpufreq: add 'freq_table' in struct cpufreq_policy 2014-03-12 01:06:00 +01:00
unicore2-cpufreq.c cpufreq: unicore32: replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO 2014-04-21 23:42:27 +02:00
vexpress-spc-cpufreq.c cpufreq: arm_big_little: add vexpress SPC interface driver 2013-10-30 00:48:26 +01:00