summaryrefslogtreecommitdiff
path: root/include/linux/i2c.h
diff options
context:
space:
mode:
authorPaul Osmialowski <p.osmialowsk@samsung.com>2015-01-19 17:03:33 +0100
committerWolfram Sang <wsa@the-dreams.de>2015-01-24 05:43:45 +0100
commit34e81ad5f0b60007c95995eb7803da7e00c6c611 (patch)
tree1a1db92fad52fa30a10451ede89b3b206c1c9b2a /include/linux/i2c.h
parent2541f7f4c14e2198ed8d8c61c854b86cae238cf1 (diff)
i2c: s3c2410: fix ABBA deadlock by keeping clock prepared
This patch solves deadlock between clock prepare mutex and regmap mutex reported by Tomasz Figa in [1] by implementing solution from [2]: "always leave the clock of the i2c controller in a prepared state". [1] https://lkml.org/lkml/2014/7/2/171 [2] https://lkml.org/lkml/2014/7/2/207 On each i2c transfer handled by s3c24xx_i2c_xfer(), clk_prepare_enable() was called, which calls clk_prepare() then clk_enable(). clk_prepare() takes prepare_lock mutex before proceeding. Note that i2c transfer functions are invoked from many places in kernel, typically with some other additional lock held. It may happen that function on CPU1 (e.g. regmap_update_bits()) has taken a mutex (i.e. regmap lock mutex) then it attempts i2c communication in order to proceed (so it needs to obtain clock related prepare_lock mutex during transfer preparation stage due to clk_prepare() call). At the same time other task on CPU0 wants to operate on clock (e.g. to (un)prepare clock for some other reason) so it has taken prepare_lock mutex. CPU0: CPU1: clk_disable_unused() regulator_disable() clk_prepare_lock() map->lock(map->lock_arg) regmap_read() s3c24xx_i2c_xfer() map->lock(map->lock_arg) clk_prepare_lock() Implemented solution from [2] leaves i2c clock prepared. Preparation is done in s3c24xx_i2c_probe() function. Without this patch, it is immediately unprepared by clk_disable_unprepare() call. I've replaced this call with clk_disable() and I've added clk_unprepare() call in s3c24xx_i2c_remove(). The s3c24xx_i2c_xfer() function now uses clk_enable() instead of clk_prepare_enable() (and clk_disable() instead of clk_unprepare_disable()). Signed-off-by: Paul Osmialowski <p.osmialowsk@samsung.com> Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de> Cc: stable@kernel.org
Diffstat (limited to 'include/linux/i2c.h')
0 files changed, 0 insertions, 0 deletions