2022-02-02 09:14:20

by Daniel Thompson

[permalink] [raw]
Subject: [PATCH v2 0/2] drm/msm: Remove spurious IRQF_ONESHOT flags from dsi & hdmi

This series corrects incorrect calls to
request_irq(..., IRQF_ONESHOT, ...). These anomalies are harmless on
regular kernels but cause odd behaviour on threadirq kernels and
break entirely on PREEMPT_RT kernels

I'm pretty certain these problems would also provoke lockdep splats on
kernels with CONFIG_PROVE_RAW_LOCK_NESTING enabled (because that is
intended to find code that breaks entirely on PREEMPT_RT kernels ;-) ).

Finally, and just in case anybody asks, yes! I did use coccinelle to do
a quick scan for similar issues. I didn't find any other instances in
drivers/drm/ .

Changes in v2:
- Split into separate patches (Dmitry B)

Daniel Thompson (2):
drm/msm/dsi: Remove spurious IRQF_ONESHOT flag
drm/msm/hdmi: Remove spurious IRQF_ONESHOT flag

drivers/gpu/drm/msm/dsi/dsi_host.c | 2 +-
drivers/gpu/drm/msm/hdmi/hdmi.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)


base-commit: 26291c54e111ff6ba87a164d85d4a4e134b7315c
--
2.34.1


2022-02-02 11:05:19

by Daniel Thompson

[permalink] [raw]
Subject: [PATCH v2 1/2] drm/msm/dsi: Remove spurious IRQF_ONESHOT flag

Quoting the header comments, IRQF_ONESHOT is "Used by threaded interrupts
which need to keep the irq line disabled until the threaded handler has
been run.". When applied to an interrupt that doesn't request a threaded
irq then IRQF_ONESHOT has a lesser known (undocumented?) side effect,
which it to disable the forced threading of irqs (and for "normal" kernels
it is a nop). In this case I can find no evidence that suppressing forced
threading is intentional. Had it been intentional then a driver must adopt
the raw_spinlock API in order to avoid deadlocks on PREEMPT_RT kernels
(and avoid calling any kernel API that uses regular spinlocks).

Fix this by removing the spurious additional flag.

This change is required for my Snapdragon 7cx Gen2 tablet to boot-to-GUI
with PREEMPT_RT enabled.

Signed-off-by: Daniel Thompson <[email protected]>
---
drivers/gpu/drm/msm/dsi/dsi_host.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 6b3ced4aaaf5d..3a3f53f0c8ae1 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1877,7 +1877,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)

/* do not autoenable, will be enabled later */
ret = devm_request_irq(&pdev->dev, msm_host->irq, dsi_host_irq,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN,
+ IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN,
"dsi_isr", msm_host);
if (ret < 0) {
dev_err(&pdev->dev, "failed to request IRQ%u: %d\n",
--
2.34.1

2022-02-02 16:02:10

by Daniel Thompson

[permalink] [raw]
Subject: [PATCH v2 2/2] drm/msm/hdmi: Remove spurious IRQF_ONESHOT flag

Quoting the header comments, IRQF_ONESHOT is "Used by threaded interrupts
which need to keep the irq line disabled until the threaded handler has
been run.". When applied to an interrupt that doesn't request a threaded
irq then IRQF_ONESHOT has a lesser known (undocumented?) side effect,
which it to disable the forced threading of irqs. For "normal" kernels
if there is no thread_fn then IRQF_ONESHOT is a nop.

In this case disabling forced threading is not appropriate because the
driver calls wake_up_all() (via msm_hdmi_i2c_irq) and also directly uses
the regular spinlock API for locking (in msm_hdmi_hdcp_irq() ). Neither
of these APIs can be called from no-thread interrupt handlers on
PREEMPT_RT systems.

Fix this by removing IRQF_ONESHOT.

Signed-off-by: Daniel Thompson <[email protected]>
---
drivers/gpu/drm/msm/hdmi/hdmi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 719720709e9e7..e167817b42958 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -306,7 +306,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
}

ret = devm_request_irq(&pdev->dev, hdmi->irq,
- msm_hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ msm_hdmi_irq, IRQF_TRIGGER_HIGH,
"hdmi_isr", hdmi);
if (ret < 0) {
DRM_DEV_ERROR(dev->dev, "failed to request IRQ%u: %d\n",
--
2.34.1

2022-02-09 23:32:45

by Dmitry Baryshkov

[permalink] [raw]
Subject: Re: [PATCH v2 2/2] drm/msm/hdmi: Remove spurious IRQF_ONESHOT flag

On 01/02/2022 20:47, Daniel Thompson wrote:
> Quoting the header comments, IRQF_ONESHOT is "Used by threaded interrupts
> which need to keep the irq line disabled until the threaded handler has
> been run.". When applied to an interrupt that doesn't request a threaded
> irq then IRQF_ONESHOT has a lesser known (undocumented?) side effect,
> which it to disable the forced threading of irqs. For "normal" kernels
> if there is no thread_fn then IRQF_ONESHOT is a nop.
>
> In this case disabling forced threading is not appropriate because the
> driver calls wake_up_all() (via msm_hdmi_i2c_irq) and also directly uses
> the regular spinlock API for locking (in msm_hdmi_hdcp_irq() ). Neither
> of these APIs can be called from no-thread interrupt handlers on
> PREEMPT_RT systems.
>
> Fix this by removing IRQF_ONESHOT.
>
> Signed-off-by: Daniel Thompson <[email protected]>

Reviewed-by: Dmitry Baryshkov <[email protected]>

> ---
> drivers/gpu/drm/msm/hdmi/hdmi.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
> index 719720709e9e7..e167817b42958 100644
> --- a/drivers/gpu/drm/msm/hdmi/hdmi.c
> +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
> @@ -306,7 +306,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
> }
>
> ret = devm_request_irq(&pdev->dev, hdmi->irq,
> - msm_hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
> + msm_hdmi_irq, IRQF_TRIGGER_HIGH,
> "hdmi_isr", hdmi);
> if (ret < 0) {
> DRM_DEV_ERROR(dev->dev, "failed to request IRQ%u: %d\n",


--
With best wishes
Dmitry

2022-02-09 23:56:30

by Dmitry Baryshkov

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] drm/msm/dsi: Remove spurious IRQF_ONESHOT flag

On 01/02/2022 20:47, Daniel Thompson wrote:
> Quoting the header comments, IRQF_ONESHOT is "Used by threaded interrupts
> which need to keep the irq line disabled until the threaded handler has
> been run.". When applied to an interrupt that doesn't request a threaded
> irq then IRQF_ONESHOT has a lesser known (undocumented?) side effect,
> which it to disable the forced threading of irqs (and for "normal" kernels
> it is a nop). In this case I can find no evidence that suppressing forced
> threading is intentional. Had it been intentional then a driver must adopt
> the raw_spinlock API in order to avoid deadlocks on PREEMPT_RT kernels
> (and avoid calling any kernel API that uses regular spinlocks).
>
> Fix this by removing the spurious additional flag.
>
> This change is required for my Snapdragon 7cx Gen2 tablet to boot-to-GUI
> with PREEMPT_RT enabled.
>
> Signed-off-by: Daniel Thompson <[email protected]>

Reviewed-by: Dmitry Baryshkov <[email protected]>

> ---
> drivers/gpu/drm/msm/dsi/dsi_host.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
> index 6b3ced4aaaf5d..3a3f53f0c8ae1 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_host.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
> @@ -1877,7 +1877,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
>
> /* do not autoenable, will be enabled later */
> ret = devm_request_irq(&pdev->dev, msm_host->irq, dsi_host_irq,
> - IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN,
> + IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN,
> "dsi_isr", msm_host);
> if (ret < 0) {
> dev_err(&pdev->dev, "failed to request IRQ%u: %d\n",


--
With best wishes
Dmitry