[v3,4/5] drm: xlnx: zynqmp_dpsub: Filter interrupts against mask

Message ID 20240124025402.373620-5-anatoliy.klymenko@amd.com
State New
Headers
Series Fixing live video input in ZynqMP DPSUB |

Commit Message

Klymenko, Anatoliy Jan. 24, 2024, 2:54 a.m. UTC
  Filter out status register against the interrupts' mask.

Some events are being reported via DP status register, even if
corresponding interrupts have been disabled. One instance of such event
leads to generation of VBLANK when the driver is in DRM bridge mode,
which in turn results in NULL pointer dereferencing. We should avoid
processing such events in an interrupt handler context.

This problem is less noticeable when the driver operates in DMA mode, as
in this case we have DRM CRTC object instantiated and DRM framework
simply discards unwanted VBLANKs in drm_handle_vblank().

Signed-off-by: Anatoliy Klymenko <anatoliy.klymenko@amd.com>
---
 drivers/gpu/drm/xlnx/zynqmp_dp.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
  

Comments

Tomi Valkeinen Feb. 1, 2024, 7:41 a.m. UTC | #1
On 24/01/2024 04:54, Anatoliy Klymenko wrote:
> Filter out status register against the interrupts' mask.
> 
> Some events are being reported via DP status register, even if
> corresponding interrupts have been disabled. One instance of such event
> leads to generation of VBLANK when the driver is in DRM bridge mode,
> which in turn results in NULL pointer dereferencing. We should avoid
> processing such events in an interrupt handler context.
> 
> This problem is less noticeable when the driver operates in DMA mode, as
> in this case we have DRM CRTC object instantiated and DRM framework
> simply discards unwanted VBLANKs in drm_handle_vblank().
> 
> Signed-off-by: Anatoliy Klymenko <anatoliy.klymenko@amd.com>
> ---
>   drivers/gpu/drm/xlnx/zynqmp_dp.c | 9 ++++++++-
>   1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
> index 5a3335e1fffa..9f48e5bbcdec 100644
> --- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
> +++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
> @@ -1627,7 +1627,14 @@ static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data)
>   	/* clear status register as soon as we read it */
>   	zynqmp_dp_write(dp, ZYNQMP_DP_INT_STATUS, status);
>   	mask = zynqmp_dp_read(dp, ZYNQMP_DP_INT_MASK);
> -	if (!(status & ~mask))
> +
> +	/*
> +	 * Status register may report some events, which corresponding interrupts
> +	 * have been disabled. Filter out those events against interrupts' mask.
> +	 */
> +	status &= ~mask;
> +
> +	if (!status)
>   		return IRQ_NONE;
>   
>   	/* dbg for diagnostic, but not much that the driver can do */

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi
  
Laurent Pinchart Feb. 5, 2024, 7:35 a.m. UTC | #2
Hi Anatoliy,

Thank you for the patch.

On Tue, Jan 23, 2024 at 06:54:01PM -0800, Anatoliy Klymenko wrote:
> Filter out status register against the interrupts' mask.
> 
> Some events are being reported via DP status register, even if
> corresponding interrupts have been disabled. One instance of such event
> leads to generation of VBLANK when the driver is in DRM bridge mode,
> which in turn results in NULL pointer dereferencing. We should avoid
> processing such events in an interrupt handler context.
> 
> This problem is less noticeable when the driver operates in DMA mode, as
> in this case we have DRM CRTC object instantiated and DRM framework
> simply discards unwanted VBLANKs in drm_handle_vblank().
> 
> Signed-off-by: Anatoliy Klymenko <anatoliy.klymenko@amd.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/gpu/drm/xlnx/zynqmp_dp.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
> index 5a3335e1fffa..9f48e5bbcdec 100644
> --- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
> +++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
> @@ -1627,7 +1627,14 @@ static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data)
>  	/* clear status register as soon as we read it */
>  	zynqmp_dp_write(dp, ZYNQMP_DP_INT_STATUS, status);
>  	mask = zynqmp_dp_read(dp, ZYNQMP_DP_INT_MASK);
> -	if (!(status & ~mask))
> +
> +	/*
> +	 * Status register may report some events, which corresponding interrupts
> +	 * have been disabled. Filter out those events against interrupts' mask.
> +	 */
> +	status &= ~mask;
> +
> +	if (!status)
>  		return IRQ_NONE;
>  
>  	/* dbg for diagnostic, but not much that the driver can do */
  

Patch

diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
index 5a3335e1fffa..9f48e5bbcdec 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
@@ -1627,7 +1627,14 @@  static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data)
 	/* clear status register as soon as we read it */
 	zynqmp_dp_write(dp, ZYNQMP_DP_INT_STATUS, status);
 	mask = zynqmp_dp_read(dp, ZYNQMP_DP_INT_MASK);
-	if (!(status & ~mask))
+
+	/*
+	 * Status register may report some events, which corresponding interrupts
+	 * have been disabled. Filter out those events against interrupts' mask.
+	 */
+	status &= ~mask;
+
+	if (!status)
 		return IRQ_NONE;
 
 	/* dbg for diagnostic, but not much that the driver can do */