linux/drivers/cpufreq
Stephen Boyd 3617f2ca6d cpufreq: Fix timer/workqueue corruption due to double queueing
When a CPU is hot removed we'll cancel all the delayed work items
via gov_cancel_work(). Normally this will just cancels a delayed
timer on each CPU that the policy is managing and the work won't
run, but if the work is already running the workqueue code will
wait for the work to finish before continuing to prevent the
work items from re-queuing themselves like they normally do. This
scheme will work most of the time, except for the case where the
work function determines that it should adjust the delay for all
other CPUs that the policy is managing. If this scenario occurs,
the canceling CPU will cancel its own work but queue up the other
CPUs works to run. For example:

 CPU0                                        CPU1
 ----                                        ----
 cpu_down()
  ...
  __cpufreq_remove_dev()
   cpufreq_governor_dbs()
    case CPUFREQ_GOV_STOP:
     gov_cancel_work(dbs_data, policy);
      cpu0 work is canceled
       timer is canceled
       cpu1 work is canceled                    <work runs>
       <waits for cpu1>                         od_dbs_timer()
                                                 gov_queue_work(*, *, true);
 						  cpu0 work queued
 						  cpu1 work queued
						  cpu2 work queued
						  ...
       cpu1 work is canceled
       cpu2 work is canceled
       ...

At the end of the GOV_STOP case cpu0 still has a work queued to
run although the code is expecting all of the works to be
canceled. __cpufreq_remove_dev() will then proceed to
re-initialize all the other CPUs works except for the CPU that is
going down. The CPUFREQ_GOV_START case in cpufreq_governor_dbs()
will trample over the queued work and debugobjects will spit out
a warning:

WARNING: at lib/debugobjects.c:260 debug_print_object+0x94/0xbc()
ODEBUG: init active (active state 0) object type: timer_list hint: delayed_work_timer_fn+0x0/0x10
Modules linked in:
CPU: 0 PID: 1491 Comm: sh Tainted: G        W    3.10.0 #19
[<c010c178>] (unwind_backtrace+0x0/0x11c) from [<c0109dec>] (show_stack+0x10/0x14)
[<c0109dec>] (show_stack+0x10/0x14) from [<c01904cc>] (warn_slowpath_common+0x4c/0x6c)
[<c01904cc>] (warn_slowpath_common+0x4c/0x6c) from [<c019056c>] (warn_slowpath_fmt+0x2c/0x3c)
[<c019056c>] (warn_slowpath_fmt+0x2c/0x3c) from [<c0388a7c>] (debug_print_object+0x94/0xbc)
[<c0388a7c>] (debug_print_object+0x94/0xbc) from [<c0388e34>] (__debug_object_init+0x2d0/0x340)
[<c0388e34>] (__debug_object_init+0x2d0/0x340) from [<c019e3b0>] (init_timer_key+0x14/0xb0)
[<c019e3b0>] (init_timer_key+0x14/0xb0) from [<c0635f78>] (cpufreq_governor_dbs+0x3e8/0x5f8)
[<c0635f78>] (cpufreq_governor_dbs+0x3e8/0x5f8) from [<c06325a0>] (__cpufreq_governor+0xdc/0x1a4)
[<c06325a0>] (__cpufreq_governor+0xdc/0x1a4) from [<c0633704>] (__cpufreq_remove_dev.isra.10+0x3b4/0x434)
[<c0633704>] (__cpufreq_remove_dev.isra.10+0x3b4/0x434) from [<c08989f4>] (cpufreq_cpu_callback+0x60/0x80)
[<c08989f4>] (cpufreq_cpu_callback+0x60/0x80) from [<c08a43c0>] (notifier_call_chain+0x38/0x68)
[<c08a43c0>] (notifier_call_chain+0x38/0x68) from [<c01938e0>] (__cpu_notify+0x28/0x40)
[<c01938e0>] (__cpu_notify+0x28/0x40) from [<c0892ad4>] (_cpu_down+0x7c/0x2c0)
[<c0892ad4>] (_cpu_down+0x7c/0x2c0) from [<c0892d3c>] (cpu_down+0x24/0x40)
[<c0892d3c>] (cpu_down+0x24/0x40) from [<c0893ea8>] (store_online+0x2c/0x74)
[<c0893ea8>] (store_online+0x2c/0x74) from [<c04519d8>] (dev_attr_store+0x18/0x24)
[<c04519d8>] (dev_attr_store+0x18/0x24) from [<c02a69d4>] (sysfs_write_file+0x100/0x148)
[<c02a69d4>] (sysfs_write_file+0x100/0x148) from [<c0255c18>] (vfs_write+0xcc/0x174)
[<c0255c18>] (vfs_write+0xcc/0x174) from [<c0255f70>] (SyS_write+0x38/0x64)
[<c0255f70>] (SyS_write+0x38/0x64) from [<c0106120>] (ret_fast_syscall+0x0/0x30)

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2013-08-28 21:57:13 +02:00
..
acpi-cpufreq.c acpi-cpufreq: Use cpufreq_freq_attr_rw to define the cpb attribute 2013-08-14 22:24:22 +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_dt.c cpufreq: arm_big_little: remove device tree parsing for cpu nodes 2013-08-21 10:29:55 +01:00
arm_big_little.c cpufreq: arm-big-little: call CPUFREQ_POSTCHANGE notfier in error cases 2013-06-24 18:18:58 +05:30
arm_big_little.h cpufreq: ARM big LITTLE: Move cpu_to_cluster() to arm_big_little.h 2013-05-12 14:04:15 +02:00
at32ap-cpufreq.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
blackfin-cpufreq.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
cpufreq_conservative.c Merge back earlier 'pm-cpufreq' material 2013-08-14 22:21:16 +02:00
cpufreq_governor.c cpufreq: Fix timer/workqueue corruption due to double queueing 2013-08-28 21:57:13 +02:00
cpufreq_governor.h Merge back earlier 'pm-cpufreq' material 2013-08-14 22:21:16 +02:00
cpufreq_ondemand.c Merge back earlier 'pm-cpufreq' material 2013-08-14 22:21:16 +02: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 sizeof(*ptr) convetion for computing sizes 2013-08-07 23:34:10 +02:00
cpufreq_userspace.c cpufreq: Fix minor formatting issues 2013-06-21 01:06:34 +02:00
cpufreq-cpu0.c Merge branch 'cpu_of_node' of git://linux-arm.org/linux-skn into pm-cpufreq-next 2013-08-23 00:57:19 +02:00
cpufreq-nforce2.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
cpufreq.c cpufreq: fix bad unlock balance on !CONFIG_SMP 2013-08-21 02:04:31 +02:00
cris-artpec3-cpufreq.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
cris-etraxfs-cpufreq.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
davinci-cpufreq.c cpufreq: davinci: call CPUFREQ_POSTCHANGE notfier in error cases 2013-06-24 18:18:58 +05:30
dbx500-cpufreq.c cpufreq: delete __cpuinit usage from all cpufreq files 2013-07-14 19:36:57 -04:00
e_powersaver.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
elanfreq.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
exynos4x12-cpufreq.c arm-soc: cleanups 2013-02-21 14:58:40 -08:00
exynos4210-cpufreq.c arm-soc: cleanups 2013-02-21 14:58:40 -08:00
exynos5250-cpufreq.c arm-soc: cleanups 2013-02-21 14:58:40 -08:00
exynos5440-cpufreq.c cpufreq: exynos5440: Fix to skip when new frequency same as current 2013-08-12 12:00:18 +05:30
exynos-cpufreq.c Merge branch 'cpufreq-fixes' of git://git.linaro.org/people/vireshk/linux into pm-cpufreq 2013-08-14 22:22:57 +02:00
exynos-cpufreq.h cpufreq: fix EXYNOS drivers selection 2013-08-12 12:00:21 +05:30
freq_table.c cpufreq: Clean up header files included in the core 2013-08-07 23:34:09 +02:00
gx-suspmod.c cpufreq / gx: Fix gx_detect_chipset() __init attribute location 2013-08-14 22:24:23 +02:00
highbank-cpufreq.c cpufreq: highbank-cpufreq: remove device tree parsing for cpu nodes 2013-08-21 10:29:54 +01:00
ia64-acpi-cpufreq.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
imx6q-cpufreq.c Merge branch 'cpufreq-fixes' of git://git.linaro.org/people/vireshk/linux into pm-cpufreq 2013-08-27 02:37:54 +02:00
integrator-cpufreq.c cpufreq: integrator: move cpufreq driver to drivers/cpufreq 2013-04-08 13:02:31 +02:00
intel_pstate.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
Kconfig cpufreq: Fix incorrect dependecies for ARM SA11xx drivers 2013-05-12 14:04:16 +02:00
Kconfig.arm cpufreq: fix EXYNOS drivers selection 2013-08-12 12:00:21 +05:30
Kconfig.powerpc Merge branch 'pm-cpufreq-assorted' into pm-cpufreq 2013-06-27 21:46:45 +02:00
Kconfig.x86 cpufreq: X86_AMD_FREQ_SENSITIVITY: select CPU_FREQ_TABLE 2013-06-18 13:53:11 +05:30
kirkwood-cpufreq.c Merge branch 'cpu_of_node' of git://linux-arm.org/linux-skn into pm-cpufreq-next 2013-08-23 00:57:19 +02:00
longhaul.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
longhaul.h cpufreq: delete __cpuinit usage from all cpufreq files 2013-07-14 19:36:57 -04:00
longrun.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
loongson2_cpufreq.c Merge back earlier 'pm-cpufreq' material 2013-08-14 22:21:16 +02:00
Makefile cpufreq: Remove unused APERF/MPERF support 2013-07-26 01:06:43 +02:00
maple-cpufreq.c Merge branch 'cpu_of_node' of git://linux-arm.org/linux-skn into pm-cpufreq-next 2013-08-23 00:57:19 +02:00
omap-cpufreq.c cpufreq: delete __cpuinit usage from all cpufreq files 2013-07-14 19:36:57 -04:00
p4-clockmod.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
pasemi-cpufreq.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
pcc-cpufreq.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
pmac32-cpufreq.c Merge branch 'cpu_of_node' of git://linux-arm.org/linux-skn into pm-cpufreq-next 2013-08-23 00:57:19 +02:00
pmac64-cpufreq.c Merge branch 'cpu_of_node' of git://linux-arm.org/linux-skn into pm-cpufreq-next 2013-08-23 00:57:19 +02:00
powernow-k6.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
powernow-k7.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
powernow-k7.h [CPUFREQ] Move x86 drivers to drivers/cpufreq/ 2011-05-19 18:51:07 -04:00
powernow-k8.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
powernow-k8.h cpufreq: Remove support for hardware P-state chips from powernow-k8 2012-09-09 22:05:30 +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
ppc_cbe_cpufreq.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +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-corenet-cpufreq.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
pxa2xx-cpufreq.c cpufreq / pxa2xx: Fix pxa_cpufreq_init_voltages() __init attribute location 2013-08-14 22:24:23 +02:00
pxa3xx-cpufreq.c pxa3xx-cpufreq.c: Avoid using ARRAY_AND_SIZE(e) as a function argument 2013-08-14 22:24:23 +02: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 / s3c24xx: Fix s3c_cpufreq_initclks() __init attribute location 2013-08-14 22:24:24 +02:00
s3c64xx-cpufreq.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +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: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
s3c2440-cpufreq.c cpufreq: s3c24xx: move cpufreq driver to drivers/cpufreq 2013-05-20 23:04:28 +09:00
s5pv210-cpufreq.c cpufreq: Notify all policy->cpus in cpufreq_notify_transition() 2013-04-02 15:24:00 +02:00
sa1100-cpufreq.c cpufreq: sa11x0: move cpufreq driver to drivers/cpufreq 2013-04-10 13:19:24 +02:00
sa1110-cpufreq.c cpufreq: sa11x0: move cpufreq driver to drivers/cpufreq 2013-04-10 13:19:24 +02:00
sc520_freq.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
sh-cpufreq.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
sparc-us2e-cpufreq.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
sparc-us3-cpufreq.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
spear-cpufreq.c cpufreq: spear-cpufreq: remove device tree parsing for cpu nodes 2013-08-21 10:29:54 +01:00
speedstep-centrino.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
speedstep-ich.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +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 [CPUFREQ] Move x86 drivers to drivers/cpufreq/ 2011-05-19 18:51:07 -04:00
speedstep-smi.c cpufreq: Drop the owner field from struct cpufreq_driver 2013-08-10 03:24:47 +02:00
tegra-cpufreq.c cpufreq: tegra: fix the wrong clock name 2013-08-23 21:58:28 +05:30
unicore2-cpufreq.c cpufreq: unicore2: Staticize local symbol 2013-08-14 22:24:24 +02:00