Commit c5a2ad1e authored by Devarsh Thakkar's avatar Devarsh Thakkar Committed by Wentao Guan
Browse files

drm/tidss: Clear the interrupt status for interrupts being disabled

stable inclusion
from stable-v6.6.79
commit e85e8d48bf6d514c0cc11d74fb7c5a2bb41931ed
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBXANC

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=e85e8d48bf6d514c0cc11d74fb7c5a2bb41931ed



--------------------------------

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: 32a1795f ("drm/tidss: New driver for TI Keystone platform Display SubSystem")
Cc: stable@vger.kernel.org
Reported-by: default avatarJonathan 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: default avatarDevarsh Thakkar <devarsht@ti.com>
[Tomi: mostly rewrote the patch]
Reviewed-by: default avatarJonathan Cormier <jcormier@criticallink.com>
Tested-by: default avatarJonathan Cormier <jcormier@criticallink.com>
Reviewed-by: default avatarAradhya Bhatia <aradhya.bhatia@linux.dev>
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241021-tidss-irq-fix-v1-5-82ddaec94e4a@ideasonboard.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit e85e8d48bf6d514c0cc11d74fb7c5a2bb41931ed)
Signed-off-by: default avatarWentao Guan <guanwentao@uniontech.com>
parent 5905959b
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -646,7 +646,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);
@@ -654,6 +654,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);
}
@@ -785,7 +788,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) {
@@ -810,6 +813,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);
}