| From 361a2ebb5cad211732ec3c5d962de49b21895590 Mon Sep 17 00:00:00 2001 |
| From: Devarsh Thakkar <devarsht@ti.com> |
| Date: Mon, 21 Oct 2024 17:07:49 +0300 |
| Subject: drm/tidss: Clear the interrupt status for interrupts being disabled |
| |
| From: Devarsh Thakkar <devarsht@ti.com> |
| |
| commit 361a2ebb5cad211732ec3c5d962de49b21895590 upstream. |
| |
| The driver does not touch the irqstatus register when it is disabling |
| interrupts. This might cause an interrupt to trigger for an interrupt |
| that was just disabled. |
| |
| To fix the issue, clear the irqstatus registers right after disabling |
| the interrupts. |
| |
| Fixes: 32a1795f57ee ("drm/tidss: New driver for TI Keystone platform Display SubSystem") |
| Cc: stable@vger.kernel.org |
| Reported-by: Jonathan Cormier <jcormier@criticallink.com> |
| Closes: https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1394222/am625-issue-about-tidss-rcu_preempt-self-detected-stall-on-cpu/5424479#5424479 |
| Signed-off-by: Devarsh Thakkar <devarsht@ti.com> |
| [Tomi: mostly rewrote the patch] |
| Reviewed-by: Jonathan Cormier <jcormier@criticallink.com> |
| Tested-by: Jonathan Cormier <jcormier@criticallink.com> |
| Reviewed-by: Aradhya Bhatia <aradhya.bhatia@linux.dev> |
| Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> |
| Link: https://patchwork.freedesktop.org/patch/msgid/20241021-tidss-irq-fix-v1-5-82ddaec94e4a@ideasonboard.com |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/gpu/drm/tidss/tidss_dispc.c | 10 ++++++++-- |
| 1 file changed, 8 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/gpu/drm/tidss/tidss_dispc.c |
| +++ b/drivers/gpu/drm/tidss/tidss_dispc.c |
| @@ -700,7 +700,7 @@ void dispc_k2g_set_irqenable(struct disp |
| { |
| dispc_irq_t old_mask = dispc_k2g_read_irqenable(dispc); |
| |
| - /* clear the irqstatus for newly enabled irqs */ |
| + /* clear the irqstatus for irqs that will be enabled */ |
| dispc_k2g_clear_irqstatus(dispc, (mask ^ old_mask) & mask); |
| |
| dispc_k2g_vp_set_irqenable(dispc, 0, mask); |
| @@ -708,6 +708,9 @@ void dispc_k2g_set_irqenable(struct disp |
| |
| dispc_write(dispc, DISPC_IRQENABLE_SET, (1 << 0) | (1 << 7)); |
| |
| + /* clear the irqstatus for irqs that were disabled */ |
| + dispc_k2g_clear_irqstatus(dispc, (mask ^ old_mask) & old_mask); |
| + |
| /* flush posted write */ |
| dispc_k2g_read_irqenable(dispc); |
| } |
| @@ -839,7 +842,7 @@ static void dispc_k3_set_irqenable(struc |
| |
| old_mask = dispc_k3_read_irqenable(dispc); |
| |
| - /* clear the irqstatus for newly enabled irqs */ |
| + /* clear the irqstatus for irqs that will be enabled */ |
| dispc_k3_clear_irqstatus(dispc, (old_mask ^ mask) & mask); |
| |
| for (i = 0; i < dispc->feat->num_vps; ++i) { |
| @@ -864,6 +867,9 @@ static void dispc_k3_set_irqenable(struc |
| if (main_disable) |
| dispc_write(dispc, DISPC_IRQENABLE_CLR, main_disable); |
| |
| + /* clear the irqstatus for irqs that were disabled */ |
| + dispc_k3_clear_irqstatus(dispc, (old_mask ^ mask) & old_mask); |
| + |
| /* Flush posted writes */ |
| dispc_read(dispc, DISPC_IRQENABLE_SET); |
| } |