[PATCH v2 03/10] drm/bridge: analogix_dp: Add IRQF_ONESHOT and simplify IRQ handling
Damon Ding
damon.ding at rock-chips.com
Tue Aug 4 01:17:10 PDT 2026
The threaded IRQ is requested without IRQF_ONESHOT, allowing hardirq to
preempt the threaded handler. This creates a read-modify-write race on
HPD interrupt mask registers between the hardirq mute and thread unmute
operations.
Add IRQF_ONESHOT to keep the IRQ line masked during thread execution,
which eliminates the race and makes the per-event mute/unmute calls in
hardirq and thread handlers redundant. Move interrupt status clearing
to the beginning of the threaded handler, before
drm_helper_hpd_irq_event(), to avoid losing events that arrive during
the event handling.
Signed-off-by: Damon Ding <damon.ding at rock-chips.com>
---
.../gpu/drm/bridge/analogix/analogix_dp_core.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 7ef8ef812b55..4fe248e66515 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -707,10 +707,8 @@ static irqreturn_t analogix_dp_hardirq(int irq, void *arg)
u32 irq_type;
irq_type = analogix_dp_get_irq_type(dp);
- if (irq_type) {
- analogix_dp_mute_hpd_interrupt(dp);
+ if (irq_type)
ret = IRQ_WAKE_THREAD;
- }
return ret;
}
@@ -721,6 +719,9 @@ static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
u32 irq_type;
irq_type = analogix_dp_get_irq_type(dp);
+ if (irq_type)
+ analogix_dp_clear_hotplug_interrupts(dp);
+
if (irq_type & DP_IRQ_TYPE_HP_CABLE_IN ||
irq_type & DP_IRQ_TYPE_HP_CABLE_OUT) {
dev_dbg(dp->dev, "Detected cable status changed!\n");
@@ -728,11 +729,6 @@ static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
drm_helper_hpd_irq_event(dp->drm_dev);
}
- if (irq_type) {
- analogix_dp_clear_hotplug_interrupts(dp);
- analogix_dp_unmute_hpd_interrupt(dp);
- }
-
return IRQ_HANDLED;
}
@@ -1403,10 +1399,11 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data)
* that we can get the current state of the GPIO.
*/
dp->irq = gpiod_to_irq(dp->hpd_gpiod);
- irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN;
+ irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN |
+ IRQF_ONESHOT;
} else {
dp->irq = platform_get_irq(pdev, 0);
- irq_flags = IRQF_NO_AUTOEN;
+ irq_flags = IRQF_NO_AUTOEN | IRQF_ONESHOT;
}
if (dp->irq == -ENXIO) {
--
2.34.1
More information about the linux-arm-kernel
mailing list