diff mbox series

[v4,11/31] i2c: tegra: Factor out runtime PM and hardware initialization

Message ID 20200905204151.25343-12-digetx@gmail.com
State Superseded
Headers show
Series Improvements for Tegra I2C driver | expand

Commit Message

Dmitry Osipenko Sept. 5, 2020, 8:41 p.m. UTC
Factor out runtime PM and hardware initialization into separate function
in order have a cleaner error unwinding in the probe function.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 68 +++++++++++++++++++---------------
 1 file changed, 38 insertions(+), 30 deletions(-)

Comments

Michał Mirosław Sept. 5, 2020, 10:10 p.m. UTC | #1
On Sat, Sep 05, 2020 at 11:41:31PM +0300, Dmitry Osipenko wrote:
> Factor out runtime PM and hardware initialization into separate function
> in order have a cleaner error unwinding in the probe function.
[...]
> +	ret = tegra_i2c_init_runtime_pm_and_hardware(i2c_dev);
[...]

This one doesn't improve the code for me. The problems are: 1) putting two
unrelated parts in one function, 2) silently reordered initialization.

Best Regards,
Michał Mirosław
Dmitry Osipenko Sept. 5, 2020, 10:24 p.m. UTC | #2
06.09.2020 01:10, Michał Mirosław пишет:
> On Sat, Sep 05, 2020 at 11:41:31PM +0300, Dmitry Osipenko wrote:
>> Factor out runtime PM and hardware initialization into separate function
>> in order have a cleaner error unwinding in the probe function.
> [...]
>> +	ret = tegra_i2c_init_runtime_pm_and_hardware(i2c_dev);
> [...]
> 
> This one doesn't improve the code for me. The problems are: 1) putting two
> unrelated parts in one function, 2) silently reordered initialization.

The hardware initialization depends on the resumed RPM and the rest of
the probe function doesn't care about the RPM. I don't quite understand
why you're saying that they are unrelated, could you please explain?

The DMA/RPM initialization is intentionally reordered in order to clean
up the error handling, like the commit message says. To me it's a clear
improvement :)
Michał Mirosław Sept. 5, 2020, 10:51 p.m. UTC | #3
On Sun, Sep 06, 2020 at 01:24:14AM +0300, Dmitry Osipenko wrote:
> 06.09.2020 01:10, Michał Mirosław пишет:
> > On Sat, Sep 05, 2020 at 11:41:31PM +0300, Dmitry Osipenko wrote:
> >> Factor out runtime PM and hardware initialization into separate function
> >> in order have a cleaner error unwinding in the probe function.
> > [...]
> >> +	ret = tegra_i2c_init_runtime_pm_and_hardware(i2c_dev);
> > [...]
> > 
> > This one doesn't improve the code for me. The problems are: 1) putting two
> > unrelated parts in one function, 2) silently reordered initialization.
> 
> The hardware initialization depends on the resumed RPM and the rest of
> the probe function doesn't care about the RPM. I don't quite understand
> why you're saying that they are unrelated, could you please explain?
> 
> The DMA/RPM initialization is intentionally reordered in order to clean
> up the error handling, like the commit message says. To me it's a clear
> improvement :)

Ok, then wouldn't it be enough to just move this part in the probe()?
A sign of a problem for me is how much information you had to put in
the name of the new function.

Best Regards,
Michał Mirosław
Dmitry Osipenko Sept. 5, 2020, 11:10 p.m. UTC | #4
06.09.2020 01:51, Michał Mirosław пишет:
> On Sun, Sep 06, 2020 at 01:24:14AM +0300, Dmitry Osipenko wrote:
>> 06.09.2020 01:10, Michał Mirosław пишет:
>>> On Sat, Sep 05, 2020 at 11:41:31PM +0300, Dmitry Osipenko wrote:
>>>> Factor out runtime PM and hardware initialization into separate function
>>>> in order have a cleaner error unwinding in the probe function.
>>> [...]
>>>> +	ret = tegra_i2c_init_runtime_pm_and_hardware(i2c_dev);
>>> [...]
>>>
>>> This one doesn't improve the code for me. The problems are: 1) putting two
>>> unrelated parts in one function, 2) silently reordered initialization.
>>
>> The hardware initialization depends on the resumed RPM and the rest of
>> the probe function doesn't care about the RPM. I don't quite understand
>> why you're saying that they are unrelated, could you please explain?
>>
>> The DMA/RPM initialization is intentionally reordered in order to clean
>> up the error handling, like the commit message says. To me it's a clear
>> improvement :)
> 
> Ok, then wouldn't it be enough to just move this part in the probe()?
> A sign of a problem for me is how much information you had to put in
> the name of the new function.

Looking at it again now, I think you're right. I also now noticed that
the RPM isn't disabled now if tegra_i2c_init() fails.

I'll try to take another look, but probably will lean to yours variant
in the v5. Thanks!
diff mbox series

Patch

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 8e4e72dec6ea..6e5af03d0b1d 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -1670,6 +1670,37 @@  static void tegra_i2c_release_clocks(struct tegra_i2c_dev *i2c_dev)
 	clk_bulk_unprepare(i2c_dev->nclocks, i2c_dev->clocks);
 }
 
+static int tegra_i2c_init_runtime_pm_and_hardware(struct tegra_i2c_dev *i2c_dev)
+{
+	int ret;
+
+	/*
+	 * VI I2C is in VE power domain which is not always on and not
+	 * an IRQ safe. So, IRQ safe device can't be attached to a non-IRQ
+	 * safe domain as it prevents powering off the PM domain.
+	 * Also, VI I2C device don't need to use runtime IRQ safe as it will
+	 * not be used for atomic transfers.
+	 */
+	if (!i2c_dev->is_vi)
+		pm_runtime_irq_safe(i2c_dev->dev);
+
+	pm_runtime_enable(i2c_dev->dev);
+
+	ret = pm_runtime_get_sync(i2c_dev->dev);
+	if (ret < 0) {
+		dev_err(i2c_dev->dev, "runtime resume failed: %d\n", ret);
+		pm_runtime_disable(i2c_dev->dev);
+		return ret;
+	}
+
+	/* initialize hardware state */
+	ret = tegra_i2c_init(i2c_dev);
+
+	pm_runtime_put(i2c_dev->dev);
+
+	return ret;
+}
+
 static int tegra_i2c_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -1728,41 +1759,23 @@  static int tegra_i2c_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, i2c_dev);
 
-	/*
-	 * VI I2C is in VE power domain which is not always on and not
-	 * an IRQ safe. So, IRQ safe device can't be attached to a non-IRQ
-	 * safe domain as it prevents powering off the PM domain.
-	 * Also, VI I2C device don't need to use runtime IRQ safe as it will
-	 * not be used for atomic transfers.
-	 */
-	if (!i2c_dev->is_vi)
-		pm_runtime_irq_safe(&pdev->dev);
-	pm_runtime_enable(&pdev->dev);
-	ret = pm_runtime_get_sync(i2c_dev->dev);
-	if (ret < 0) {
-		dev_err(dev, "runtime resume failed\n");
-		goto disable_rpm;
-	}
-
 	if (i2c_dev->hw->supports_bus_clear)
 		i2c_dev->adapter.bus_recovery_info = &tegra_i2c_recovery_info;
 
 	ret = tegra_i2c_init_dma(i2c_dev);
 	if (ret < 0)
-		goto put_rpm;
+		goto release_clocks;
 
-	ret = tegra_i2c_init(i2c_dev);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to initialize i2c controller\n");
+	ret = tegra_i2c_init_runtime_pm_and_hardware(i2c_dev);
+	if (ret)
 		goto release_dma;
-	}
 
 	irq_set_status_flags(i2c_dev->irq, IRQ_NOAUTOEN);
 
 	ret = devm_request_irq(&pdev->dev, i2c_dev->irq, tegra_i2c_isr,
 			       IRQF_NO_SUSPEND, dev_name(&pdev->dev), i2c_dev);
 	if (ret)
-		goto release_dma;
+		goto release_rpm;
 
 	i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
 	i2c_dev->adapter.owner = THIS_MODULE;
@@ -1777,18 +1790,13 @@  static int tegra_i2c_probe(struct platform_device *pdev)
 	if (ret)
 		goto release_dma;
 
-	pm_runtime_put(&pdev->dev);
-
 	return 0;
 
+release_rpm:
+	pm_runtime_disable(i2c_dev->dev);
 release_dma:
 	tegra_i2c_release_dma(i2c_dev);
-
-put_rpm:
-	pm_runtime_put_sync(&pdev->dev);
-
-disable_rpm:
-	pm_runtime_disable(&pdev->dev);
+release_clocks:
 	tegra_i2c_release_clocks(i2c_dev);
 
 	return ret;