1
0
Fork 0

Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c fixes from Wolfram Sang:
 "Two runtime PM fixes and one leak fix"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: iop3xx: Fix memory leak in probe error path
  i2c: tegra: Properly disable runtime PM on driver's probe error
  i2c: tegra: Fix suspending in active runtime PM state
alistair/sunxi64-5.5-dsi
Linus Torvalds 2020-01-19 12:02:06 -08:00
commit 5f43644394
2 changed files with 36 additions and 14 deletions

View File

@ -433,13 +433,17 @@ iop3xx_i2c_probe(struct platform_device *pdev)
adapter_data->gpio_scl = devm_gpiod_get_optional(&pdev->dev, adapter_data->gpio_scl = devm_gpiod_get_optional(&pdev->dev,
"scl", "scl",
GPIOD_ASIS); GPIOD_ASIS);
if (IS_ERR(adapter_data->gpio_scl)) if (IS_ERR(adapter_data->gpio_scl)) {
return PTR_ERR(adapter_data->gpio_scl); ret = PTR_ERR(adapter_data->gpio_scl);
goto free_both;
}
adapter_data->gpio_sda = devm_gpiod_get_optional(&pdev->dev, adapter_data->gpio_sda = devm_gpiod_get_optional(&pdev->dev,
"sda", "sda",
GPIOD_ASIS); GPIOD_ASIS);
if (IS_ERR(adapter_data->gpio_sda)) if (IS_ERR(adapter_data->gpio_sda)) {
return PTR_ERR(adapter_data->gpio_sda); ret = PTR_ERR(adapter_data->gpio_sda);
goto free_both;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res) {

View File

@ -1608,14 +1608,18 @@ static int tegra_i2c_probe(struct platform_device *pdev)
} }
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) if (!pm_runtime_enabled(&pdev->dev)) {
ret = tegra_i2c_runtime_resume(&pdev->dev); ret = tegra_i2c_runtime_resume(&pdev->dev);
else if (ret < 0) {
dev_err(&pdev->dev, "runtime resume failed\n");
goto unprepare_div_clk;
}
} else {
ret = pm_runtime_get_sync(i2c_dev->dev); ret = pm_runtime_get_sync(i2c_dev->dev);
if (ret < 0) {
if (ret < 0) { dev_err(&pdev->dev, "runtime resume failed\n");
dev_err(&pdev->dev, "runtime resume failed\n"); goto disable_rpm;
goto unprepare_div_clk; }
} }
if (i2c_dev->is_multimaster_mode) { if (i2c_dev->is_multimaster_mode) {
@ -1623,7 +1627,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
if (ret < 0) { if (ret < 0) {
dev_err(i2c_dev->dev, "div_clk enable failed %d\n", dev_err(i2c_dev->dev, "div_clk enable failed %d\n",
ret); ret);
goto disable_rpm; goto put_rpm;
} }
} }
@ -1671,11 +1675,16 @@ disable_div_clk:
if (i2c_dev->is_multimaster_mode) if (i2c_dev->is_multimaster_mode)
clk_disable(i2c_dev->div_clk); clk_disable(i2c_dev->div_clk);
disable_rpm: put_rpm:
pm_runtime_disable(&pdev->dev); if (pm_runtime_enabled(&pdev->dev))
if (!pm_runtime_status_suspended(&pdev->dev)) pm_runtime_put_sync(&pdev->dev);
else
tegra_i2c_runtime_suspend(&pdev->dev); tegra_i2c_runtime_suspend(&pdev->dev);
disable_rpm:
if (pm_runtime_enabled(&pdev->dev))
pm_runtime_disable(&pdev->dev);
unprepare_div_clk: unprepare_div_clk:
clk_unprepare(i2c_dev->div_clk); clk_unprepare(i2c_dev->div_clk);
@ -1710,9 +1719,14 @@ static int tegra_i2c_remove(struct platform_device *pdev)
static int __maybe_unused tegra_i2c_suspend(struct device *dev) static int __maybe_unused tegra_i2c_suspend(struct device *dev)
{ {
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
int err;
i2c_mark_adapter_suspended(&i2c_dev->adapter); i2c_mark_adapter_suspended(&i2c_dev->adapter);
err = pm_runtime_force_suspend(dev);
if (err < 0)
return err;
return 0; return 0;
} }
@ -1733,6 +1747,10 @@ static int __maybe_unused tegra_i2c_resume(struct device *dev)
if (err) if (err)
return err; return err;
err = pm_runtime_force_resume(dev);
if (err < 0)
return err;
i2c_mark_adapter_resumed(&i2c_dev->adapter); i2c_mark_adapter_resumed(&i2c_dev->adapter);
return 0; return 0;