ipu_prg_channel_configure() waits for both PRG double buffers to become ready, but ignores readl_poll_timeout() failures. A timeout is therefore reported as a successful configuration and chan->enabled is set even though the hardware did not report ready buffers.
Propagate the timeout error. Before returning, put the channel back into bypass mode and release the PRE allocated for this configuration so the software state stays consistent with the failed setup. Signed-off-by: Pengpeng Hou <[email protected]> --- drivers/gpu/ipu-v3/ipu-prg.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/ipu-v3/ipu-prg.c b/drivers/gpu/ipu-v3/ipu-prg.c index d38d3ba54..ff32f4ca5 100644 --- a/drivers/gpu/ipu-v3/ipu-prg.c +++ b/drivers/gpu/ipu-v3/ipu-prg.c @@ -327,10 +327,22 @@ int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan, writel(val, prg->regs + IPU_PRG_REG_UPDATE); /* wait for both double buffers to be filled */ - readl_poll_timeout(prg->regs + IPU_PRG_STATUS, val, - (val & IPU_PRG_STATUS_BUFFER0_READY(prg_chan)) && - (val & IPU_PRG_STATUS_BUFFER1_READY(prg_chan)), - 5, 1000); + ret = readl_poll_timeout(prg->regs + IPU_PRG_STATUS, val, + (val & IPU_PRG_STATUS_BUFFER0_READY(prg_chan)) && + (val & IPU_PRG_STATUS_BUFFER1_READY(prg_chan)), + 5, 1000); + if (ret) { + val = readl(prg->regs + IPU_PRG_CTL); + val |= IPU_PRG_CTL_BYPASS(prg_chan); + writel(val, prg->regs + IPU_PRG_CTL); + + val = IPU_PRG_REG_UPDATE_REG_UPDATE; + writel(val, prg->regs + IPU_PRG_REG_UPDATE); + + pm_runtime_put(prg->dev); + ipu_prg_put_pre(prg, prg_chan); + return ret; + } pm_runtime_put(prg->dev); -- 2.50.1 (Apple Git-155)
