2019-01-15 17:19:14

by Laurentiu Tudor

[permalink] [raw]
Subject: [PATCH] i2c: imx: defer probing on dma channel request

If the dma controller is not yet probed, defer i2c probe.
The error path in probe was slightly modified (no functional change)
to avoid triggering this WARN_ON():
"cg-pll0-div1 already disabled
WARNING: CPU: 1 PID: 1 at drivers/clk/clk.c:828 clk_core_disable+0xa8/0xb0"

Signed-off-by: Laurentiu Tudor <[email protected]>
---
drivers/i2c/busses/i2c-imx.c | 45 +++++++++++++++++++++---------------
1 file changed, 27 insertions(+), 18 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index fa9ad53845d9..5a28d25ff9b6 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -273,8 +273,8 @@ static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx,
}

/* Functions for DMA support */
-static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
- dma_addr_t phy_addr)
+static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
+ dma_addr_t phy_addr)
{
struct imx_i2c_dma *dma;
struct dma_slave_config dma_sconfig;
@@ -283,11 +283,12 @@ static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,

dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
if (!dma)
- return;
+ return -ENOMEM;

- dma->chan_tx = dma_request_slave_channel(dev, "tx");
- if (!dma->chan_tx) {
- dev_dbg(dev, "can't request DMA tx channel\n");
+ dma->chan_tx = dma_request_slave_channel_reason(dev, "tx");
+ if (IS_ERR(dma->chan_tx)) {
+ ret = PTR_ERR(dma->chan_tx);
+ dma->chan_tx = NULL;
goto fail_al;
}

@@ -301,10 +302,10 @@ static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
dev_dbg(dev, "can't configure tx channel\n");
goto fail_tx;
}
-
- dma->chan_rx = dma_request_slave_channel(dev, "rx");
- if (!dma->chan_rx) {
- dev_dbg(dev, "can't request DMA rx channel\n");
+ dma->chan_rx = dma_request_slave_channel_reason(dev, "rx");
+ if (IS_ERR(dma->chan_rx)) {
+ ret = PTR_ERR(dma->chan_rx);
+ dma->chan_rx = NULL;
goto fail_tx;
}

@@ -324,7 +325,7 @@ static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
dev_info(dev, "using %s (tx) and %s (rx) for DMA transfers\n",
dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx));

- return;
+ return 0;

fail_rx:
dma_release_channel(dma->chan_rx);
@@ -332,7 +333,8 @@ static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
dma_release_channel(dma->chan_tx);
fail_al:
devm_kfree(dev, dma);
- dev_info(dev, "can't use DMA, using PIO instead.\n");
+
+ return ret;
}

static void i2c_imx_dma_callback(void *arg)
@@ -1106,7 +1108,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
pdev->name, i2c_imx);
if (ret) {
dev_err(&pdev->dev, "can't claim irq %d\n", irq);
- goto clk_disable;
+ clk_disable_unprepare(i2c_imx->clk);
+ return ret;
}

/* Init queue */
@@ -1156,17 +1159,25 @@ static int i2c_imx_probe(struct platform_device *pdev)
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);

+ /* Init DMA config if supported */
+ ret = i2c_imx_dma_request(i2c_imx, phy_addr);
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ dev_info(&pdev->dev, "can't use DMA, using PIO instead.\n");
+ else
+ goto del_adapter;
+ }
+
dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", irq);
dev_dbg(&i2c_imx->adapter.dev, "device resources: %pR\n", res);
dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n",
i2c_imx->adapter.name);
dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");

- /* Init DMA config if supported */
- i2c_imx_dma_request(i2c_imx, phy_addr);
-
return 0; /* Return OK */

+del_adapter:
+ i2c_del_adapter(&i2c_imx->adapter);
clk_notifier_unregister:
clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
rpm_disable:
@@ -1175,8 +1186,6 @@ static int i2c_imx_probe(struct platform_device *pdev)
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);

-clk_disable:
- clk_disable_unprepare(i2c_imx->clk);
return ret;
}

--
2.17.1



2019-01-16 14:40:02

by Wolfram Sang

[permalink] [raw]
Subject: Re: [PATCH] i2c: imx: defer probing on dma channel request

Hi,

On Tue, Jan 15, 2019 at 04:03:32PM +0200, Laurentiu Tudor wrote:
> If the dma controller is not yet probed, defer i2c probe.
> The error path in probe was slightly modified (no functional change)
> to avoid triggering this WARN_ON():
> "cg-pll0-div1 already disabled
> WARNING: CPU: 1 PID: 1 at drivers/clk/clk.c:828 clk_core_disable+0xa8/0xb0"
>
> Signed-off-by: Laurentiu Tudor <[email protected]>

I just applied this series to i2c/for-next:

http://patchwork.ozlabs.org/project/linux-i2c/list/?series=85099&state=*

I haven't checked carefully but maybe it fixes/changes your issue? If
not, your patch most likely will need a rebase on top of the above.

Thanks,

Wolfram


Attachments:
(No filename) (714.00 B)
signature.asc (849.00 B)
Download all attachments

2019-01-16 21:20:33

by Laurentiu Tudor

[permalink] [raw]
Subject: Re: [PATCH] i2c: imx: defer probing on dma channel request

Hello,

On 15.01.2019 23:55, Wolfram Sang wrote:
> Hi,
>
> On Tue, Jan 15, 2019 at 04:03:32PM +0200, Laurentiu Tudor wrote:
>> If the dma controller is not yet probed, defer i2c probe.
>> The error path in probe was slightly modified (no functional change)
>> to avoid triggering this WARN_ON():
>> "cg-pll0-div1 already disabled
>> WARNING: CPU: 1 PID: 1 at drivers/clk/clk.c:828 clk_core_disable+0xa8/0xb0"
>>
>> Signed-off-by: Laurentiu Tudor <[email protected]>
>
> I just applied this series to i2c/for-next:
>
> http://patchwork.ozlabs.org/project/linux-i2c/list/?series=85099&state=*
>
> I haven't checked carefully but maybe it fixes/changes your issue?

Not really as it doesn't seem to defer probing until the dma controller
gets probed.

> If not, your patch most likely will need a rebase on top of the above.

Will rebase on latest i2c tree and re-send.

---
Best Regards, Laurentiu