Re: [PATCH] drm/rockchip: vop: fix irq disabled after vop driver probed

From: Tomasz Figa
Date: Fri May 25 2018 - 07:59:19 EST


Hi Heiko, Sandy,

On Fri, May 25, 2018 at 7:07 AM Heiko StÃbner <heiko@xxxxxxxxx> wrote:

> From: Sandy Huang <hjc@xxxxxxxxxxxxxx>

> The vop irq is shared between vop and iommu and irq probing in the
> iommu driver moved to the probe function recently. This can in some
> cases lead to a stall if the irq is triggered while the vop driver
> still has it disabled.

> But there is no real need to disable the irq, as the vop can simply
> also track its enabled state and ignore irqs in that case.

> So remove the enable/disable handling and add appropriate condition
> to the irq handler.

> Signed-off-by: Sandy Huang <hjc@xxxxxxxxxxxxxx>
> [added an actual commit message]
> Signed-off-by: Heiko Stuebner <heiko@xxxxxxxxx>
> ---
> Hi Ezequiel,

> this patch came from a discussion I had with Rockchip people over the
> iommu changes and resulting issues back in april, but somehow was
> forgotten and not posted to the lists. Correcting that now.

> So removing the enable/disable voodoo on the shared interrupt is
> the preferred way.

> drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 13 ++++++-------
> 1 file changed, 7 insertions(+), 7 deletions(-)

> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> index 510cdf0..61493d4 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> @@ -549,8 +549,6 @@ static int vop_enable(struct drm_crtc *crtc)

> spin_unlock(&vop->reg_lock);

> - enable_irq(vop->irq);
> -

While this one should be okay (+/- my comment for vop_isr()), because the
hardware is already powered on and clocked at this point...

> drm_crtc_vblank_on(crtc);

> return 0;
> @@ -596,8 +594,6 @@ static void vop_crtc_atomic_disable(struct drm_crtc
*crtc,

> vop_dsp_hold_valid_irq_disable(vop);

> - disable_irq(vop->irq);
> -
> vop->is_enabled = false;

...this one is more tricky. There might be an interrupt handler still
running at this point. disable_irq() waits for any running handler to
complete before disabling, so we might want to call synchronize_irq() after
setting is_enabled to false.


> /*
> @@ -1168,6 +1164,13 @@ static irqreturn_t vop_isr(int irq, void *data)
> int ret = IRQ_NONE;

> /*
> + * since the irq is shared with iommu, iommu irq is enabled
before vop
> + * enable, so before vop enable we do nothing.
> + */
> + if (!vop->is_enabled)
> + return IRQ_NONE;

This doesn't seem to be properly synchronized. We don't even call it under
a spinlock, so no barriers are issued. Perhaps we should make this atomic_t?

Best regards,
Tomasz