Message ID | 20241021-tidss-irq-fix-v1-5-82ddaec94e4a@ideasonboard.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/tidss: Interrupt fixes and cleanups | expand |
On Mon, Oct 21, 2024 at 10:08 AM Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> wrote: > > From: Devarsh Thakkar <devarsht@ti.com> > > 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] > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> Thanks for the updates. They look pretty similar to the changes I proposed and thus look good to me. Reviewed-by: Jonathan Cormier <jcormier@criticallink.com> Tested an equivalent patch for several weeks. Tested-by: Jonathan Cormier <jcormier@criticallink.com> > --- > drivers/gpu/drm/tidss/tidss_dispc.c | 10 ++++++++-- > 1 file changed, 8 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c > index 99a1138f3e69..515f82e8a0a5 100644 > --- a/drivers/gpu/drm/tidss/tidss_dispc.c > +++ b/drivers/gpu/drm/tidss/tidss_dispc.c
diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c index 99a1138f3e69..515f82e8a0a5 100644 --- 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 dispc_device *dispc, dispc_irq_t mask) { 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 dispc_device *dispc, dispc_irq_t mask) 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); } @@ -837,7 +840,7 @@ static void dispc_k3_set_irqenable(struct dispc_device *dispc, 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) { @@ -862,6 +865,9 @@ static void dispc_k3_set_irqenable(struct dispc_device *dispc, 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); }