[PATCH] media: qcom: venus: reduce impact of verbose firmware logging

From: Renjiang Han

Date: Thu Sep 10 2026 - 22:56:20 EST


Firmware debug logging can generate a large amount of traffic. When
verbose firmware logging is enabled, debug queue packets can delay
normal HFI responses enough to hit the existing response timeout.

Increase the HFI response timeout, power collapse delay timeout, and
runtime PM autosuspend delay when fw_level enables log classes beyond
error and fatal. Restore the default values when fw_level is changed
back to error and fatal only.

Print firmware error and fatal messages with dev_err_ratelimited().
Other firmware debug messages continue to use dev_dbg(). Bound firmware
log printing by the packet size so messages do not need to be NUL
terminated by firmware.

Signed-off-by: Renjiang Han <renjiang.han@xxxxxxxxxxxxxxxx>
---
Verbose firmware logging can generate a large amount of debug queue
traffic. When many firmware log classes are enabled, normal HFI response
messages may be delayed behind debug packets and synchronous HFI
commands may hit their response timeout.

Reduce that impact by increasing the HFI response timeout, power
collapse delay timeout, and runtime PM autosuspend delay when fw_level
enables verbose firmware logs beyond the default error and fatal levels.
Restore the default values when fw_level is changed back to error and
fatal only.

Firmware error and fatal messages are printed with
dev_err_ratelimited(), so important firmware errors remain visible
without enabling dynamic debug. Other firmware debug messages continue
to use dev_dbg(). Firmware log printing is bounded by the packet size
and no longer depends on firmware providing a NUL-terminated string.
---
drivers/media/platform/qcom/venus/core.c | 5 +-
drivers/media/platform/qcom/venus/core.h | 8 +++
drivers/media/platform/qcom/venus/dbgfs.c | 51 +++++++++++++-
drivers/media/platform/qcom/venus/hfi.c | 10 +--
drivers/media/platform/qcom/venus/hfi_venus.c | 95 ++++++++++++++++++---------
drivers/media/platform/qcom/venus/vdec.c | 2 +-
drivers/media/platform/qcom/venus/venc.c | 2 +-
7 files changed, 133 insertions(+), 40 deletions(-)

diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
index 243e342b0ae75336af17bf630712417e34caa96b..2282926369d1e04b9a4bd990acacdf3aa344f614 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -429,6 +429,8 @@ static int venus_probe(struct platform_device *pdev)

INIT_LIST_HEAD(&core->instances);
mutex_init(&core->lock);
+ core->hw_rsp_timeout = VENUS_HW_RSP_TIMEOUT_MS;
+ core->pc_delay_timeout = VENUS_PC_DELAY_TIMEOUT_US;
INIT_DELAYED_WORK(&core->work, venus_sys_error_handler);
init_waitqueue_head(&core->sys_err_done);

@@ -545,6 +547,8 @@ static void venus_remove(struct platform_device *pdev)
ret = hfi_core_deinit(core, true);
WARN_ON(ret);

+ venus_dbgfs_deinit(core);
+
venus_shutdown(core);
of_platform_depopulate(dev);

@@ -564,7 +568,6 @@ static void venus_remove(struct platform_device *pdev)

mutex_destroy(&core->pm_lock);
mutex_destroy(&core->lock);
- venus_dbgfs_deinit(core);
}

static void venus_core_shutdown(struct platform_device *pdev)
diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
index 46705a6667762e8975e32947b4cb3355e20754d0..8a9649745fa18bcba69baf29c3ed6242fd68bd87 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -23,6 +23,10 @@
#define VDBGH "VenusHigh: "
#define VDBGFW "VenusFW : "

+#define VENUS_HW_RSP_TIMEOUT_MS 1000
+#define VENUS_AUTOSUSPEND_DELAY_MS 2000
+#define VENUS_PC_DELAY_TIMEOUT_US (100 * 1500)
+
#define VIDC_CLKS_NUM_MAX 4
#define VIDC_VCODEC_CLKS_NUM_MAX 2
#define VIDC_RESETS_NUM_MAX 2
@@ -169,6 +173,8 @@ struct venus_format {
* @state: the state of the venus core
* @done: a completion for sync HFI operations
* @error: an error returned during last HFI sync operations
+ * @hw_rsp_timeout: hardware response timeout
+ * @pc_delay_timeout: power collapse delay timeout
* @sys_error: an error flag that signal system error event
* @sys_err_done: a waitqueue to wait for system error recovery end
* @core_ops: the core operations
@@ -230,6 +236,8 @@ struct venus_core {
unsigned int state;
struct completion done;
unsigned int error;
+ unsigned int hw_rsp_timeout;
+ unsigned int pc_delay_timeout;
unsigned long sys_error;
wait_queue_head_t sys_err_done;
const struct hfi_core_ops *core_ops;
diff --git a/drivers/media/platform/qcom/venus/dbgfs.c b/drivers/media/platform/qcom/venus/dbgfs.c
index 726f4b730e69bc07fa925c747bfe9d7cf434b54a..4fd44b4a7e054503632e1d6f01f90e151532967b 100644
--- a/drivers/media/platform/qcom/venus/dbgfs.c
+++ b/drivers/media/platform/qcom/venus/dbgfs.c
@@ -5,6 +5,7 @@

#include <linux/debugfs.h>
#include <linux/fault-inject.h>
+#include <linux/pm_runtime.h>

#include "core.h"

@@ -12,10 +13,58 @@
DECLARE_FAULT_ATTR(venus_ssr_attr);
#endif

+static int venus_fw_level_get(void *data, u64 *val)
+{
+ *val = READ_ONCE(venus_fw_debug);
+
+ return 0;
+}
+
+static int venus_fw_level_set(void *data, u64 val)
+{
+ struct venus_core *core = data;
+ bool verbose;
+ u32 fw_debug;
+
+ fw_debug = (u32)val;
+ verbose = fw_debug & ~(HFI_DEBUG_MSG_ERROR | HFI_DEBUG_MSG_FATAL);
+ WRITE_ONCE(venus_fw_debug, fw_debug);
+
+ if (verbose) {
+ WRITE_ONCE(core->hw_rsp_timeout, 4 * VENUS_HW_RSP_TIMEOUT_MS);
+ WRITE_ONCE(core->pc_delay_timeout, 4 * VENUS_PC_DELAY_TIMEOUT_US);
+
+ if (core->dev_dec)
+ pm_runtime_set_autosuspend_delay(core->dev_dec,
+ 4 * VENUS_AUTOSUSPEND_DELAY_MS);
+
+ if (core->dev_enc)
+ pm_runtime_set_autosuspend_delay(core->dev_enc,
+ 4 * VENUS_AUTOSUSPEND_DELAY_MS);
+ } else {
+ WRITE_ONCE(core->hw_rsp_timeout, VENUS_HW_RSP_TIMEOUT_MS);
+ WRITE_ONCE(core->pc_delay_timeout, VENUS_PC_DELAY_TIMEOUT_US);
+
+ if (core->dev_dec)
+ pm_runtime_set_autosuspend_delay(core->dev_dec,
+ VENUS_AUTOSUSPEND_DELAY_MS);
+
+ if (core->dev_enc)
+ pm_runtime_set_autosuspend_delay(core->dev_enc,
+ VENUS_AUTOSUSPEND_DELAY_MS);
+ }
+
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(venus_fw_level_fops,
+ venus_fw_level_get, venus_fw_level_set, "0x%08llx\n");
+
void venus_dbgfs_init(struct venus_core *core)
{
core->root = debugfs_create_dir("venus", NULL);
- debugfs_create_x32("fw_level", 0644, core->root, &venus_fw_debug);
+ debugfs_create_file("fw_level", 0644, core->root, core,
+ &venus_fw_level_fops);

#ifdef CONFIG_FAULT_INJECTION
fault_create_debugfs_attr("fail_ssr", core->root, &venus_ssr_attr);
diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c
index 675e6fd1e9fae40177349c0bc68f38c326b9aa25..615f30d86c7bd86087ef274d2cfdbc5dd74baee9 100644
--- a/drivers/media/platform/qcom/venus/hfi.c
+++ b/drivers/media/platform/qcom/venus/hfi.c
@@ -15,8 +15,6 @@
#include "hfi_cmds.h"
#include "hfi_venus.h"

-#define TIMEOUT msecs_to_jiffies(1000)
-
static u32 to_codec_type(u32 pixfmt)
{
switch (pixfmt) {
@@ -49,6 +47,7 @@ static u32 to_codec_type(u32 pixfmt)

int hfi_core_init(struct venus_core *core)
{
+ unsigned int timeout;
int ret = 0;

mutex_lock(&core->lock);
@@ -62,7 +61,8 @@ int hfi_core_init(struct venus_core *core)
if (ret)
goto unlock;

- ret = wait_for_completion_timeout(&core->done, TIMEOUT);
+ timeout = READ_ONCE(core->hw_rsp_timeout);
+ ret = wait_for_completion_timeout(&core->done, msecs_to_jiffies(timeout));
if (!ret) {
ret = -ETIMEDOUT;
goto unlock;
@@ -140,9 +140,11 @@ int hfi_core_trigger_ssr(struct venus_core *core, u32 type)

static int wait_session_msg(struct venus_inst *inst)
{
+ unsigned int timeout;
int ret;

- ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
+ timeout = READ_ONCE(inst->core->hw_rsp_timeout);
+ ret = wait_for_completion_timeout(&inst->done, msecs_to_jiffies(timeout));
if (!ret)
return -ETIMEDOUT;

diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c
index bd82066bb6e77f68ac3fe1440a8b5429ad62a192..10cf9a775d8bf3781150c830583db4b190146be2 100644
--- a/drivers/media/platform/qcom/venus/hfi_venus.c
+++ b/drivers/media/platform/qcom/venus/hfi_venus.c
@@ -132,7 +132,6 @@ struct venus_hfi_device {
static bool venus_pkt_debug;
int venus_fw_debug = HFI_DEBUG_MSG_ERROR | HFI_DEBUG_MSG_FATAL;
static bool venus_fw_low_power_mode = true;
-static int venus_hw_rsp_timeout = 1000;
static bool venus_fw_coverage;

static void venus_set_state(struct venus_hfi_device *hdev,
@@ -949,7 +948,7 @@ static int venus_sys_set_default_properties(struct venus_hfi_device *hdev)
const struct venus_resources *res = hdev->core->res;
int ret;

- ret = venus_sys_set_debug(hdev, venus_fw_debug);
+ ret = venus_sys_set_debug(hdev, READ_ONCE(venus_fw_debug));
if (ret)
dev_warn(dev, "setting fw debug msg ON failed (%d)\n", ret);

@@ -985,29 +984,52 @@ static int venus_session_cmd(struct venus_inst *inst, u32 pkt_type, bool sync)
return venus_iface_cmdq_write(hdev, &pkt, sync);
}

-static void venus_flush_debug_queue(struct venus_hfi_device *hdev)
+static int venus_flush_debug_queue(struct venus_hfi_device *hdev)
{
struct device *dev = hdev->core->dev;
void *packet = hdev->dbg_buf;
+ int num_pkts = 0;

while (!venus_iface_dbgq_read(hdev, packet)) {
struct hfi_msg_sys_coverage_pkt *pkt = packet;

+ num_pkts++;
+
+ if (pkt->hdr.size <= sizeof(pkt->hdr))
+ continue;
+
+ if (pkt->hdr.size > IFACEQ_VAR_HUGE_PKT_SIZE)
+ continue;
+
if (pkt->hdr.pkt_type != HFI_MSG_SYS_COV) {
- struct hfi_msg_sys_debug_pkt *pkt = packet;
+ struct hfi_msg_sys_debug_pkt *dbg_pkt = packet;
+ u32 msg_size;
+
+ if (pkt->hdr.size <= sizeof(*dbg_pkt))
+ continue;

- dev_dbg(dev, VDBGFW "%s", pkt->msg_data);
+ msg_size = min_t(u32, pkt->hdr.size - sizeof(*dbg_pkt), dbg_pkt->msg_size);
+
+ if (dbg_pkt->msg_type & (HFI_DEBUG_MSG_ERROR | HFI_DEBUG_MSG_FATAL))
+ dev_err_ratelimited(dev, VDBGFW "%.*s",
+ (int)msg_size, dbg_pkt->msg_data);
+ else
+ dev_dbg(dev, VDBGFW "%.*s", (int)msg_size, dbg_pkt->msg_data);
}
}
+
+ return num_pkts;
}

static int venus_prepare_power_collapse(struct venus_hfi_device *hdev,
bool wait)
{
- unsigned long timeout = msecs_to_jiffies(venus_hw_rsp_timeout);
struct hfi_sys_pc_prep_pkt pkt;
+ unsigned long timeout;
int ret;

+ timeout = msecs_to_jiffies(READ_ONCE(hdev->core->hw_rsp_timeout));
+
init_completion(&hdev->pwr_collapse_prep);

pkt_sys_pc_prep(&pkt);
@@ -1091,6 +1113,8 @@ static irqreturn_t venus_isr_thread(struct venus_core *core)
{
struct venus_hfi_device *hdev = to_hfi_priv(core);
const struct venus_resources *res;
+ int num_debug_pkts;
+ int num_msg_pkts;
void *pkt;
u32 msg_ret;

@@ -1100,31 +1124,35 @@ static irqreturn_t venus_isr_thread(struct venus_core *core)
res = hdev->core->res;
pkt = hdev->pkt_buf;

-
- while (!venus_iface_msgq_read(hdev, pkt)) {
- msg_ret = hfi_process_msg_packet(core, pkt);
- switch (msg_ret) {
- case HFI_MSG_EVENT_NOTIFY:
- venus_process_msg_sys_error(hdev, pkt);
- break;
- case HFI_MSG_SYS_INIT:
- venus_hfi_core_set_resource(core, res->vmem_id,
- res->vmem_size,
- res->vmem_addr,
- hdev);
- break;
- case HFI_MSG_SYS_RELEASE_RESOURCE:
- complete(&hdev->release_resource);
- break;
- case HFI_MSG_SYS_PC_PREP:
- complete(&hdev->pwr_collapse_prep);
- break;
- default:
- break;
+ do {
+ num_msg_pkts = 0;
+
+ while (!venus_iface_msgq_read(hdev, pkt)) {
+ msg_ret = hfi_process_msg_packet(core, pkt);
+ num_msg_pkts++;
+ switch (msg_ret) {
+ case HFI_MSG_EVENT_NOTIFY:
+ venus_process_msg_sys_error(hdev, pkt);
+ break;
+ case HFI_MSG_SYS_INIT:
+ venus_hfi_core_set_resource(core, res->vmem_id,
+ res->vmem_size,
+ res->vmem_addr,
+ hdev);
+ break;
+ case HFI_MSG_SYS_RELEASE_RESOURCE:
+ complete(&hdev->release_resource);
+ break;
+ case HFI_MSG_SYS_PC_PREP:
+ complete(&hdev->pwr_collapse_prep);
+ break;
+ default:
+ break;
+ }
}
- }

- venus_flush_debug_queue(hdev);
+ num_debug_pkts = venus_flush_debug_queue(hdev);
+ } while (num_msg_pkts || num_debug_pkts);

return IRQ_HANDLED;
}
@@ -1227,7 +1255,7 @@ static int venus_session_init(struct venus_inst *inst, u32 session_type,
struct hfi_session_init_pkt pkt;
int ret;

- ret = venus_sys_set_debug(hdev, venus_fw_debug);
+ ret = venus_sys_set_debug(hdev, READ_ONCE(venus_fw_debug));
if (ret)
goto err;

@@ -1584,6 +1612,7 @@ static int venus_suspend_3xx(struct venus_core *core)
struct venus_hfi_device *hdev = to_hfi_priv(core);
struct device *dev = core->dev;
void __iomem *cpu_cs_base = hdev->core->cpu_cs_base;
+ unsigned int pc_delay_timeout;
u32 ctrl_status;
bool val;
int ret;
@@ -1612,8 +1641,10 @@ static int venus_suspend_3xx(struct venus_core *core)
* 2. Send a command to prepare for power collapse.
* 3. Check for WFI and PC_READY bits.
*/
+ pc_delay_timeout = READ_ONCE(core->pc_delay_timeout);
+
ret = readx_poll_timeout(venus_cpu_and_video_core_idle, hdev, val, val,
- 1500, 100 * 1500);
+ 1500, pc_delay_timeout);
if (ret) {
dev_err(dev, "wait for cpu and video core idle fail (%d)\n", ret);
return ret;
@@ -1626,7 +1657,7 @@ static int venus_suspend_3xx(struct venus_core *core)
}

ret = readx_poll_timeout(venus_cpu_idle_and_pc_ready, hdev, val, val,
- 1500, 100 * 1500);
+ 1500, pc_delay_timeout);
if (ret)
return ret;

diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c
index 6a43ea191da15fdfdbbf0a136b11ef85bcc7a73d..cb74318c6408f49354a75b768008e2edf2a347c3 100644
--- a/drivers/media/platform/qcom/venus/vdec.c
+++ b/drivers/media/platform/qcom/venus/vdec.c
@@ -1817,7 +1817,7 @@ static int vdec_probe(struct platform_device *pdev)
core->dev_dec = dev;

video_set_drvdata(vdev, core);
- pm_runtime_set_autosuspend_delay(dev, 2000);
+ pm_runtime_set_autosuspend_delay(dev, VENUS_AUTOSUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(dev);
pm_runtime_enable(dev);

diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
index 79acf7c1ec9a3a1b36f1a5e83af1f6c330802f08..e0350e6db45e72d47536b7539deca2f728393bea 100644
--- a/drivers/media/platform/qcom/venus/venc.c
+++ b/drivers/media/platform/qcom/venus/venc.c
@@ -1593,7 +1593,7 @@ static int venc_probe(struct platform_device *pdev)
core->dev_enc = dev;

video_set_drvdata(vdev, core);
- pm_runtime_set_autosuspend_delay(dev, 2000);
+ pm_runtime_set_autosuspend_delay(dev, VENUS_AUTOSUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(dev);
pm_runtime_enable(dev);


---
base-commit: f2bfbc3554ca6919484030729424b9dee2942d24
change-id: 20260911-media-qcom-venus-fw-log-perf-1a9d7308d3d5

Best regards,
--
Renjiang Han <renjiang.han@xxxxxxxxxxxxxxxx>