[PATCH 3/5] media: verisilicon: Reset the Rockchip encoder cores on timeout
Arun Iyengar via B4 Relay
devnull+aiyengar1990.gmail.com at kernel.org
Mon Nov 9 23:17:33 PST 2026
From: Arun Iyengar <aiyengar1990 at gmail.com>
On a job timeout, the Rockchip VEPU1 and VEPU2 reset operations mask the
interrupt and clear the encode enable and AXI control registers. That
only stops a core that is still responsive. On RK3588, when a VEPU121
core reads an IOVA that isn't mapped, the IOMMU reports a page fault and
the core never becomes idle again: its AXI transactions stay
outstanding, the IOMMU can't be stalled anymore ("Enable stall request
timed out", then "Disable paging request timed out" on runtime
suspend), every later job times out as well, and unbinding the driver
can lock up the system.
The driver already gets the optional reset lines of the device and
deasserts them at probe. Pulse them in the encoder reset operations,
after stopping the core through its registers, to return it to a clean
idle state. The clocks are still enabled at that point, as the job that
timed out holds them. This is a no-op on device trees that don't
describe the resets, which is the case for all of them so far.
The Rockchip BSP MPP driver resets these cores the same way, through
their AXI and AHB reset lines.
Signed-off-by: Arun Iyengar <aiyengar1990 at gmail.com>
---
.../media/platform/verisilicon/rockchip_vpu_hw.c | 30 ++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c
index 02673be9878e..0dced7515833 100644
--- a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c
+++ b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c
@@ -7,6 +7,7 @@
*/
#include <linux/clk.h>
+#include <linux/delay.h>
#include "hantro.h"
#include "hantro_jpeg.h"
@@ -468,6 +469,33 @@ static void rk3066_vpu_dec_reset(struct hantro_ctx *ctx)
vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG);
}
+/*
+ * Stopping the encoder through its registers isn't enough when it is stuck
+ * on the bus, for instance after a translation fault in its IOMMU: it keeps
+ * AXI transactions outstanding and never becomes idle, which also prevents
+ * the IOMMU from stalling. Pulse the reset lines of the core, if the device
+ * tree describes them, to return it to its idle state.
+ */
+static void rockchip_vpu_enc_hw_reset(struct hantro_dev *vpu)
+{
+ int ret;
+
+ if (!vpu->resets)
+ return;
+
+ ret = reset_control_assert(vpu->resets);
+ if (ret) {
+ dev_warn(vpu->dev, "Failed to assert resets: %d\n", ret);
+ return;
+ }
+
+ udelay(5);
+
+ ret = reset_control_deassert(vpu->resets);
+ if (ret)
+ dev_err(vpu->dev, "Failed to deassert resets: %d\n", ret);
+}
+
static void rockchip_vpu1_enc_reset(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
@@ -475,6 +503,7 @@ static void rockchip_vpu1_enc_reset(struct hantro_ctx *ctx)
vepu_write(vpu, H1_REG_INTERRUPT_DIS_BIT, H1_REG_INTERRUPT);
vepu_write(vpu, 0, H1_REG_ENC_CTRL);
vepu_write(vpu, 0, H1_REG_AXI_CTRL);
+ rockchip_vpu_enc_hw_reset(vpu);
}
static void rockchip_vpu2_dec_reset(struct hantro_ctx *ctx)
@@ -493,6 +522,7 @@ static void rockchip_vpu2_enc_reset(struct hantro_ctx *ctx)
vepu_write(vpu, VEPU_REG_INTERRUPT_DIS_BIT, VEPU_REG_INTERRUPT);
vepu_write(vpu, 0, VEPU_REG_ENCODE_START);
vepu_write(vpu, 0, VEPU_REG_AXI_CTRL);
+ rockchip_vpu_enc_hw_reset(vpu);
}
/*
--
2.55.0
More information about the Linux-rockchip
mailing list