diff options
Diffstat (limited to 'target/linux/brcm2708/patches-4.14/950-0176-drm-vc4-Fix-sleeps-during-the-IRQ-handler-for-DSI-tr.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.14/950-0176-drm-vc4-Fix-sleeps-during-the-IRQ-handler-for-DSI-tr.patch | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-4.14/950-0176-drm-vc4-Fix-sleeps-during-the-IRQ-handler-for-DSI-tr.patch b/target/linux/brcm2708/patches-4.14/950-0176-drm-vc4-Fix-sleeps-during-the-IRQ-handler-for-DSI-tr.patch new file mode 100644 index 0000000000..d6949b617b --- /dev/null +++ b/target/linux/brcm2708/patches-4.14/950-0176-drm-vc4-Fix-sleeps-during-the-IRQ-handler-for-DSI-tr.patch @@ -0,0 +1,73 @@ +From 659c52fe8a86264c5119c0592654898d09fe8f28 Mon Sep 17 00:00:00 2001 +From: Eric Anholt <eric@anholt.net> +Date: Fri, 13 Oct 2017 17:12:55 -0700 +Subject: [PATCH 176/454] drm/vc4: Fix sleeps during the IRQ handler for DSI + transactions. + +VC4's DSI1 has a bug where the AXI connection is broken for 32-bit +writes from the CPU, so we use the DMA engine to DMA 32-bit values +into registers instead. That sleeps, so we can't do it from the top +half. + +As a solution, use an interrupt thread so that all our writes happen +when sleeping is is allowed. + +v2: Use IRQF_ONESHOT (suggested by Boris) +v3: Style nitpicks. + +Signed-off-by: Eric Anholt <eric@anholt.net> +Link: https://patchwork.freedesktop.org/patch/msgid/20171014001255.32005-1-eric@anholt.net +Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com> (v2) +(cherry picked from commit af0c8c10564aac5b6d67308129ec09c4ad5db476) +--- + drivers/gpu/drm/vc4/vc4_dsi.c | 32 ++++++++++++++++++++++++++++++-- + 1 file changed, 30 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_dsi.c ++++ b/drivers/gpu/drm/vc4/vc4_dsi.c +@@ -1383,6 +1383,27 @@ static void dsi_handle_error(struct vc4_ + *ret = IRQ_HANDLED; + } + ++/* ++ * Initial handler for port 1 where we need the reg_dma workaround. ++ * The register DMA writes sleep, so we can't do it in the top half. ++ * Instead we use IRQF_ONESHOT so that the IRQ gets disabled in the ++ * parent interrupt contrller until our interrupt thread is done. ++ */ ++static irqreturn_t vc4_dsi_irq_defer_to_thread_handler(int irq, void *data) ++{ ++ struct vc4_dsi *dsi = data; ++ u32 stat = DSI_PORT_READ(INT_STAT); ++ ++ if (!stat) ++ return IRQ_NONE; ++ ++ return IRQ_WAKE_THREAD; ++} ++ ++/* ++ * Normal IRQ handler for port 0, or the threaded IRQ handler for port ++ * 1 where we need the reg_dma workaround. ++ */ + static irqreturn_t vc4_dsi_irq_handler(int irq, void *data) + { + struct vc4_dsi *dsi = data; +@@ -1566,8 +1587,15 @@ static int vc4_dsi_bind(struct device *d + /* Clear any existing interrupt state. */ + DSI_PORT_WRITE(INT_STAT, DSI_PORT_READ(INT_STAT)); + +- ret = devm_request_irq(dev, platform_get_irq(pdev, 0), +- vc4_dsi_irq_handler, 0, "vc4 dsi", dsi); ++ if (dsi->reg_dma_mem) ++ ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0), ++ vc4_dsi_irq_defer_to_thread_handler, ++ vc4_dsi_irq_handler, ++ IRQF_ONESHOT, ++ "vc4 dsi", dsi); ++ else ++ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), ++ vc4_dsi_irq_handler, 0, "vc4 dsi", dsi); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get interrupt: %d\n", ret); |