linux/drivers
Viresh Kumar 732b6d617a cpufreq: governor: Serialize governor callbacks
There are several races reported in cpufreq core around governors (only
ondemand and conservative) by different people.

There are at least two race scenarios present in governor code:
 (a) Concurrent access/updates of governor internal structures.

 It is possible that fields such as 'dbs_data->usage_count', etc.  are
 accessed simultaneously for different policies using same governor
 structure (i.e. CPUFREQ_HAVE_GOVERNOR_PER_POLICY flag unset). And
 because of this we can dereference bad pointers.

 For example consider a system with two CPUs with separate 'struct
 cpufreq_policy' instances. CPU0 governor: ondemand and CPU1: powersave.
 CPU0 switching to powersave and CPU1 to ondemand:
	CPU0				CPU1

	store*				store*

	cpufreq_governor_exit()		cpufreq_governor_init()
					dbs_data = cdata->gdbs_data;

	if (!--dbs_data->usage_count)
		kfree(dbs_data);

					dbs_data->usage_count++;
					*Bad pointer dereference*

 There are other races possible between EXIT and START/STOP/LIMIT as
 well. Its really complicated.

 (b) Switching governor state in bad sequence:

 For example trying to switch a governor to START state, when the
 governor is in EXIT state. There are some checks present in
 __cpufreq_governor() but they aren't sufficient as they compare events
 against 'policy->governor_enabled', where as we need to take governor's
 state into account, which can be used by multiple policies.

These two issues need to be solved separately and the responsibility
should be properly divided between cpufreq and governor core.

The first problem is more about the governor core, as it needs to
protect its structures properly. And the second problem should be fixed
in cpufreq core instead of governor, as its all about sequence of
events.

This patch is trying to solve only the first problem.

There are two types of data we need to protect,
- 'struct common_dbs_data': No matter what, there is going to be a
  single copy of this per governor.
- 'struct dbs_data': With CPUFREQ_HAVE_GOVERNOR_PER_POLICY flag set, we
  will have per-policy copy of this data, otherwise a single copy.

Because of such complexities, the mutex present in 'struct dbs_data' is
insufficient to solve our problem. For example we need to protect
fetching of 'dbs_data' from different structures at the beginning of
cpufreq_governor_dbs(), to make sure it isn't currently being updated.

This can be fixed if we can guarantee serialization of event parsing
code for an individual governor. This is best solved with a mutex per
governor, and the placeholder for that is 'struct common_dbs_data'.

And so this patch moves the mutex from 'struct dbs_data' to 'struct
common_dbs_data' and takes it at the beginning and drops it at the end
of cpufreq_governor_dbs().

Tested with and without following configuration options:

CONFIG_LOCKDEP_SUPPORT=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_PI_LIST=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_PROVE_LOCKING=y
CONFIG_LOCKDEP=y
CONFIG_DEBUG_ATOMIC_SLEEP=y

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-06-15 15:42:53 +02:00
..
accessibility
acpi ACPI / SBS: Enable battery manager when present 2015-04-29 00:04:29 +02:00
amba
android
ata powerpc updates for 4.1 2015-04-16 13:53:32 -05:00
atm
auxdisplay
base Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2015-04-26 17:22:07 -07:00
bcma Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus 2015-04-17 15:50:54 -04:00
block rbd: end I/O the entire obj_request on error 2015-05-01 16:44:30 -07:00
bluetooth
bus ARM: SoC driver updates for v4.1 2015-04-22 09:18:17 -07:00
cdrom
char Char/Misc driver patches for 4.1-rc1 2015-04-21 09:42:58 -07:00
clk ARM: SoC multiplatform code changes for v4.1 2015-04-22 09:20:15 -07:00
clocksource Initial ACPI support for arm64: 2015-04-24 08:23:45 -07:00
connector
cpufreq cpufreq: governor: Serialize governor callbacks 2015-06-15 15:42:53 +02:00
cpuidle cpuidle: Run tick_broadcast_exit() with disabled interrupts 2015-04-29 15:19:21 +02:00
crypto Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6 2015-04-26 13:51:05 -07:00
dca
devfreq
dio
dma dmaengine: increment privatecnt when using dma_get_any_slave_channel 2015-04-29 16:47:57 +05:30
dma-buf dma-buf: cleanup dma_buf_export() to make it easily extensible 2015-04-21 14:47:16 +05:30
edac
eisa
extcon Char/Misc driver patches for 4.1-rc1 2015-04-21 09:42:58 -07:00
firewire
firmware ARM: SoC driver updates for v4.1 2015-04-22 09:18:17 -07:00
fmc
gpio ARM: SoC cleanups for v4.1 2015-04-22 09:04:39 -07:00
gpu Merge tag 'drm-intel-fixes-2015-04-30' of git://anongit.freedesktop.org/drm-intel into drm-fixes 2015-05-04 08:56:47 +10:00
hid Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input 2015-04-14 18:25:15 -07:00
hsi
hv
hwmon hwmon: (w83795) use find_closest_descending() in pwm_freq_to_reg() 2015-04-17 09:03:55 -04:00
hwspinlock
hwtracing/coresight Char/Misc driver patches for 4.1-rc1 2015-04-21 09:42:58 -07:00
i2c Merge branch 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux 2015-04-26 17:44:09 -07:00
ide ide: remove deprecated use of pci api 2015-04-17 15:32:07 -04:00
idle Power management and ACPI updates for v4.1-rc1 2015-04-14 20:21:54 -07:00
iio Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial 2015-04-14 09:50:27 -07:00
infiniband Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2015-04-26 17:22:07 -07:00
input platform/chrome: Updates for v4.1 2015-04-26 13:36:02 -07:00
iommu Merge git://git.infradead.org/intel-iommu 2015-04-26 17:47:46 -07:00
ipack
irqchip Initial ACPI support for arm64: 2015-04-24 08:23:45 -07:00
isdn Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next 2015-04-15 09:00:47 -07:00
leds This is the bulk of GPIO changes for the v4.1 development 2015-04-18 08:22:10 -04:00
lguest Some virtio internal cleanups, a new virtio device "virtio input", and 2015-04-22 10:55:06 -07:00
macintosh
mailbox
mcb
md dm: fix free_rq_clone() NULL pointer when requeueing unmapped request 2015-04-30 10:25:21 -04:00
media v4l: xilinx: fix for include file movement 2015-04-26 09:56:08 -07:00
memory ARM: SoC driver updates for v4.1 2015-04-22 09:18:17 -07:00
memstick memstick: mspro_block: add missing curly braces 2015-04-17 09:04:09 -04:00
message
mfd platform/chrome: Updates for v4.1 2015-04-26 13:36:02 -07:00
misc Char/Misc driver patches for 4.1-rc1 2015-04-21 09:42:58 -07:00
mmc Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma 2015-04-24 09:49:37 -07:00
mtd Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2015-04-26 17:22:07 -07:00
net net: fec: Fix RGMII-ID mode 2015-04-30 16:48:53 -04:00
nfc
ntb
nubus
of Devicetree updates for 4.1: 2015-04-24 08:46:18 -07:00
oprofile Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2015-04-26 17:22:07 -07:00
parisc parisc: Eliminate sg_virt_addr() and private scatterlist.h 2015-04-21 22:02:43 +02:00
parport
pci xen: features and fixes for 4.1-rc0 2015-04-16 14:01:03 -05:00
pcmcia ARM: SoC cleanups for v4.1 2015-04-22 09:04:39 -07:00
phy USB patches for 4.1-rc1 2015-04-13 17:07:21 -07:00
pinctrl pinctrl: fix allmodconfig noise 2015-04-15 10:02:42 +02:00
platform platform-drivers-x86 for 4.1 2015-04-26 13:44:46 -07:00
pnp Power management and ACPI updates for v4.1-rc1 2015-04-14 20:21:54 -07:00
power
powercap powercap / RAPL: Add support for Intel Skylake processors 2015-04-15 23:06:16 +02:00
pps
ps3
ptp
pwm pwm: Remove __init initializer for pwm_add_table() 2015-04-23 14:50:52 +02:00
rapidio
ras
regulator == Changes to existing drivers == 2015-04-14 17:29:55 -07:00
remoteproc
reset
rpmsg
rtc drivers/rtc/rtc-at91rm9200.c: make IO endian agnostic 2015-04-17 09:04:12 -04:00
s390 s390/3215: free memory in error path 2015-04-23 16:55:50 +02:00
sbus drivers/sbus/char/envctrl.c: ignore orderly_poweroff return value 2015-04-15 16:35:23 -07:00
scsi 3w-9xxx: fix command completion race 2015-04-27 10:10:19 -07:00
sfi
sh drivers: sh: Remove test for now unsupported sh7372 2015-04-27 13:08:14 +09:00
sn
soc - fix unused variable warning for pmic-wrapper 2015-04-14 00:43:28 +02:00
spi Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma 2015-04-24 09:49:37 -07:00
spmi
ssb Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus 2015-04-17 15:50:54 -04:00
staging Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2015-04-26 17:22:07 -07:00
target Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending 2015-04-24 10:22:09 -07:00
tc
thermal
thunderbolt
tty serial: 8250_pci: Add support for 16 port Exar boards 2015-04-28 20:22:31 +02:00
uio
usb cdc-acm: prevent infinite loop when parsing CDC headers. 2015-04-28 12:53:16 +02:00
uwb
vfio
vhost Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending 2015-04-24 10:22:09 -07:00
video fbdev changes for v4.1 2015-04-20 15:16:25 -07:00
virt
virtio virtio: drop virtio_device_is_legacy_only 2015-04-15 12:41:14 +09:30
vlynq
vme
w1
watchdog Merge git://www.linux-watchdog.org/linux-watchdog 2015-04-22 11:22:55 -07:00
xen Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending 2015-04-24 10:22:09 -07:00
zorro
Kconfig
Makefile