13.12.2019 17:29, Dmitry Osipenko пишет: > 13.12.2019 02:34, Dmitry Osipenko пишет: >> I noticed that sometime I2C clock is kept enabled during suspend-resume. >> This happens because runtime PM defers dynamic suspension and thus it may >> happen that runtime PM is in active state when system enters into suspend. >> In particular I2C controller that is used for CPU's DVFS is often kept ON >> during suspend because CPU's voltage scaling happens quite often. >> >> Note: we marked runtime PM as IRQ-safe during the driver's probe in the >> "Support atomic transfers" patch, thus it's okay to enforce runtime PM >> suspend/resume in the NOIRQ phase which is used for the system-level >> suspend/resume of the driver. >> >> Signed-off-by: Dmitry Osipenko <digetx@xxxxxxxxx> >> --- >> drivers/i2c/busses/i2c-tegra.c | 9 +++++++++ >> 1 file changed, 9 insertions(+) >> >> diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c >> index b3ecdd87e91f..d309a314f4d6 100644 >> --- a/drivers/i2c/busses/i2c-tegra.c >> +++ b/drivers/i2c/busses/i2c-tegra.c >> @@ -1790,9 +1790,14 @@ static int tegra_i2c_remove(struct platform_device *pdev) >> static int __maybe_unused tegra_i2c_suspend(struct device *dev) >> { >> struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); >> + int err; >> >> i2c_mark_adapter_suspended(&i2c_dev->adapter); > > I'm now in a doubt that it is correct to use NOIRQ level at all for the > suspend because i2c_mark_adapter_suspended() uses mutex, thus I'm > wondering what will happen if there is an asynchronous transfer > happening during suspend.. > > The i2c_mark_adapter_suspended() will try to block and will never return? Moreover, the I2C interrupt should be disabled during the NOIRQ phase. So, yes.. looks like making use of NOIRQ level wasn't a correct decision. On the other hand, I don't think that any I2C client driver used by Tegra SoCs in the upstream kernel could cause the problem at the moment, so it shouldn't be critical. BTW: Jon, please CC me next time ;) [I'll try to find a better solution for the PCIE problem] >> + err = pm_runtime_force_suspend(dev); >> + if (err < 0) >> + return err; >> + >> return 0; >> } >> >> @@ -1813,6 +1818,10 @@ static int __maybe_unused tegra_i2c_resume(struct device *dev) >> if (err) >> return err; >> >> + err = pm_runtime_force_resume(dev); >> + if (err < 0) >> + return err; >> + >> i2c_mark_adapter_resumed(&i2c_dev->adapter); >> >> return 0; >> >