Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i2c: davinci: fix the cpufreq transition

i2c_davinci_cpufreq_transition() is implemented in a way that will
block if it ever gets called while no transfer is in progress.

Not only that, but reinit_completion() is never called for xfr_complete.

Use the fact that cpufreq uses an srcu_notifier (running in process
context) for transitions and that the bus_lock is taken during the call
to master_xfer() and simplify the code by removing the transfer
completion entirely and protecting i2c_davinci_cpufreq_transition()
with i2c_lock/unlock_adapter().

Reported-by: David Lechner <david@lechnology.com>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Reviewed-by: Sekhar Nori <nsekhar@ti.com>
Tested-by: David Lechner <david@lechnology.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>

authored by

Bartosz Golaszewski and committed by
Wolfram Sang
19cfcafd 5bacb56b

+4 -8
+4 -8
drivers/i2c/busses/i2c-davinci.c
··· 139 139 u8 terminate; 140 140 struct i2c_adapter adapter; 141 141 #ifdef CONFIG_CPU_FREQ 142 - struct completion xfr_complete; 143 142 struct notifier_block freq_transition; 144 143 #endif 145 144 struct davinci_i2c_platform_data *pdata; ··· 566 567 } 567 568 568 569 ret = num; 569 - #ifdef CONFIG_CPU_FREQ 570 - complete(&dev->xfr_complete); 571 - #endif 572 570 573 571 out: 574 572 pm_runtime_mark_last_busy(dev->dev); ··· 713 717 struct davinci_i2c_dev *dev; 714 718 715 719 dev = container_of(nb, struct davinci_i2c_dev, freq_transition); 720 + 721 + i2c_lock_adapter(&dev->adapter); 716 722 if (val == CPUFREQ_PRECHANGE) { 717 - wait_for_completion(&dev->xfr_complete); 718 723 davinci_i2c_reset_ctrl(dev, 0); 719 724 } else if (val == CPUFREQ_POSTCHANGE) { 720 725 i2c_davinci_calc_clk_dividers(dev); 721 726 davinci_i2c_reset_ctrl(dev, 1); 722 727 } 728 + i2c_unlock_adapter(&dev->adapter); 723 729 724 730 return 0; 725 731 } ··· 788 790 } 789 791 790 792 init_completion(&dev->cmd_complete); 791 - #ifdef CONFIG_CPU_FREQ 792 - init_completion(&dev->xfr_complete); 793 - #endif 793 + 794 794 dev->dev = &pdev->dev; 795 795 dev->irq = irq; 796 796 dev->pdata = dev_get_platdata(&pdev->dev);