[PATCH v2 2/2] media: qcom: iris: reduce impact of verbose firmware logging
From: Renjiang Han
Date: Thu Sep 10 2026 - 22:47:35 EST
Verbose firmware logging can produce a large number of debug queue
packets. The Iris interrupt thread used to drain the message queue once
and then drain the debug queue. With heavy firmware logging, response
packets that arrive while debug packets are being drained can remain
pending until a later interrupt.
Increase the HFI response timeout and runtime PM autosuspend delay when
firmware logging is enabled beyond the default error and fatal levels.
Restore the default values when the firmware log level is reduced again.
Signed-off-by: Renjiang Han <renjiang.han@xxxxxxxxxxxxxxxx>
---
drivers/media/platform/qcom/iris/iris_core.c | 2 +-
drivers/media/platform/qcom/iris/iris_core.h | 2 ++
drivers/media/platform/qcom/iris/iris_debugfs.c | 16 ++++++++++++++-
drivers/media/platform/qcom/iris/iris_hfi_common.h | 1 +
.../platform/qcom/iris/iris_hfi_gen1_response.c | 24 ++++++++++++++++------
.../platform/qcom/iris/iris_hfi_gen2_response.c | 24 ++++++++++++++++------
drivers/media/platform/qcom/iris/iris_probe.c | 3 ++-
drivers/media/platform/qcom/iris/iris_utils.c | 4 +++-
8 files changed, 60 insertions(+), 16 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c
index 8c335dbfce166848892c2b323cdcafe43af4a2d9..bbbb7191c4778d842d4fef32fa95a0a9aeeecf7a 100644
--- a/drivers/media/platform/qcom/iris/iris_core.c
+++ b/drivers/media/platform/qcom/iris/iris_core.c
@@ -40,7 +40,7 @@ static int iris_wait_for_system_response(struct iris_core *core)
return -EIO;
ret = wait_for_completion_timeout(&core->core_init_done,
- msecs_to_jiffies(HW_RESPONSE_TIMEOUT_VALUE));
+ msecs_to_jiffies(READ_ONCE(core->hw_response_timeout)));
if (!ret) {
core->state = IRIS_CORE_ERROR;
return -ETIMEDOUT;
diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h
index a8e34c456ce3f3f178ca66a278d06d1ab50dafc4..5449e6b0e11c3122d1f57aedb6dd374ffa816497 100644
--- a/drivers/media/platform/qcom/iris/iris_core.h
+++ b/drivers/media/platform/qcom/iris/iris_core.h
@@ -68,6 +68,7 @@ struct dentry;
* @debug_queue: shared interface queue to receive debug info from firmware
* @root: debugfs root directory
* @fw_debug: firmware debug log mask
+ * @hw_response_timeout: hardware response timeout
* @lock: a lock for this structure
* @response_packet: a pointer to response packet from fw to driver
* @header_id: id of packet header
@@ -115,6 +116,7 @@ struct iris_core {
struct iris_iface_q_info debug_queue;
struct dentry *root;
u32 fw_debug;
+ u32 hw_response_timeout;
struct mutex lock; /* lock for core related operations */
u8 *response_packet;
u32 header_id;
diff --git a/drivers/media/platform/qcom/iris/iris_debugfs.c b/drivers/media/platform/qcom/iris/iris_debugfs.c
index 6122b994ad0aa70c0c4f26ea4ce076f1b025f810..77726270b11777acb5ea85203223c6943365a5ce 100644
--- a/drivers/media/platform/qcom/iris/iris_debugfs.c
+++ b/drivers/media/platform/qcom/iris/iris_debugfs.c
@@ -4,6 +4,7 @@
*/
#include <linux/debugfs.h>
+#include <linux/pm_runtime.h>
#include "iris_core.h"
#include "iris_debugfs.h"
@@ -20,8 +21,21 @@ static int iris_fw_level_get(void *data, u64 *val)
static int iris_fw_level_set(void *data, u64 val)
{
struct iris_core *core = data;
+ bool debug_enabled;
+ u32 fw_debug;
- WRITE_ONCE(core->fw_debug, (u32)val & IRIS_FW_DEBUG_LOGMASK);
+ fw_debug = (u32)val & IRIS_FW_DEBUG_LOGMASK;
+ debug_enabled = fw_debug & ~IRIS_FW_DEBUG_DEFAULT;
+
+ WRITE_ONCE(core->fw_debug, fw_debug);
+
+ if (debug_enabled) {
+ WRITE_ONCE(core->hw_response_timeout, 4 * HW_RESPONSE_TIMEOUT_VALUE);
+ pm_runtime_set_autosuspend_delay(core->dev, 4 * AUTOSUSPEND_DELAY_VALUE);
+ } else {
+ WRITE_ONCE(core->hw_response_timeout, HW_RESPONSE_TIMEOUT_VALUE);
+ pm_runtime_set_autosuspend_delay(core->dev, AUTOSUSPEND_DELAY_VALUE);
+ }
return 0;
}
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h
index d8bc0862c54bd229d575113752526d51e863e303..18c852d8b818f41bf5e1b0afd35082eeaf5240b4 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_common.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h
@@ -112,6 +112,7 @@ struct iris_hfi_prop_type_handle {
#define IRIS_FW_DEBUG_FATAL 0x00000010
#define IRIS_FW_DEBUG_PERF 0x00000020
#define IRIS_FW_DEBUG_LOGMASK 0x0fffffff
+#define IRIS_FW_DEBUG_DEFAULT (IRIS_FW_DEBUG_ERROR | IRIS_FW_DEBUG_FATAL)
struct iris_hfi_sys_ops {
int (*sys_init)(struct iris_core *core);
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
index 903b60a7380559f4711b0907fb1de405fe1707f3..6b8f952d0d4b54f37596728f1823c9265c637bbe 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
@@ -672,15 +672,17 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response
}
}
-static void iris_hfi_gen1_flush_debug_queue(struct iris_core *core, u8 *packet)
+static int iris_hfi_gen1_flush_debug_queue(struct iris_core *core, u8 *packet)
{
struct hfi_msg_sys_debug_pkt *pkt;
struct hfi_pkt_hdr *hdr;
+ int num_pkts = 0;
u32 log_size;
u8 *log;
while (!iris_hfi_queue_dbg_read(core, packet)) {
hdr = (struct hfi_pkt_hdr *)packet;
+ num_pkts++;
if (hdr->size <= sizeof(*hdr))
continue;
@@ -705,15 +707,25 @@ static void iris_hfi_gen1_flush_debug_queue(struct iris_core *core, u8 *packet)
dev_dbg(core->dev, "%.*s", (int)log_size, log);
}
}
+
+ return num_pkts;
}
void iris_hfi_gen1_response_handler(struct iris_core *core)
{
- memset(core->response_packet, 0, sizeof(struct hfi_pkt_hdr));
- while (!iris_hfi_queue_msg_read(core, core->response_packet)) {
- iris_hfi_gen1_handle_response(core, core->response_packet);
+ int num_debug_pkts;
+ int num_msg_pkts;
+
+ do {
+ num_msg_pkts = 0;
memset(core->response_packet, 0, sizeof(struct hfi_pkt_hdr));
- }
+ while (!iris_hfi_queue_msg_read(core, core->response_packet)) {
+ iris_hfi_gen1_handle_response(core, core->response_packet);
+ num_msg_pkts++;
+ memset(core->response_packet, 0, sizeof(struct hfi_pkt_hdr));
+ }
- iris_hfi_gen1_flush_debug_queue(core, core->response_packet);
+ num_debug_pkts =
+ iris_hfi_gen1_flush_debug_queue(core, core->response_packet);
+ } while (num_msg_pkts || num_debug_pkts);
}
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
index e8dc8751ea939bd544699f464a831736fcc10b7f..1bd4ec0c5ada1ef17de4f07fe19d1fac611db04f 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
@@ -988,14 +988,16 @@ static int iris_hfi_gen2_handle_response(struct iris_core *core, void *response)
return iris_hfi_gen2_handle_session_response(core, hdr);
}
-static void iris_hfi_gen2_flush_debug_queue(struct iris_core *core, u8 *packet)
+static int iris_hfi_gen2_flush_debug_queue(struct iris_core *core, u8 *packet)
{
struct hfi_debug_header *pkt;
+ int num_pkts = 0;
u32 log_size;
u8 *log;
while (!iris_hfi_queue_dbg_read(core, packet)) {
pkt = (struct hfi_debug_header *)packet;
+ num_pkts++;
if (pkt->size <= sizeof(*pkt) + 1)
continue;
@@ -1010,10 +1012,15 @@ static void iris_hfi_gen2_flush_debug_queue(struct iris_core *core, u8 *packet)
else
dev_dbg(core->dev, "%.*s", (int)log_size, log);
}
+
+ return num_pkts;
}
void iris_hfi_gen2_response_handler(struct iris_core *core)
{
+ int num_debug_pkts;
+ int num_msg_pkts;
+
if (iris_vpu_watchdog(core, core->intr_status)) {
struct iris_hfi_packet pkt = {.type = HFI_SYS_ERROR_WD_TIMEOUT};
@@ -1024,11 +1031,16 @@ void iris_hfi_gen2_response_handler(struct iris_core *core)
return;
}
- memset(core->response_packet, 0, sizeof(struct iris_hfi_header));
- while (!iris_hfi_queue_msg_read(core, core->response_packet)) {
- iris_hfi_gen2_handle_response(core, core->response_packet);
+ do {
+ num_msg_pkts = 0;
memset(core->response_packet, 0, sizeof(struct iris_hfi_header));
- }
+ while (!iris_hfi_queue_msg_read(core, core->response_packet)) {
+ iris_hfi_gen2_handle_response(core, core->response_packet);
+ num_msg_pkts++;
+ memset(core->response_packet, 0, sizeof(struct iris_hfi_header));
+ }
- iris_hfi_gen2_flush_debug_queue(core, core->response_packet);
+ num_debug_pkts =
+ iris_hfi_gen2_flush_debug_queue(core, core->response_packet);
+ } while (num_msg_pkts || num_debug_pkts);
}
diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
index 8bc94acc4f58ce7792ddaeaad036475c476d5c36..318a548a7ac606594a41d9dae25e73205de1fd0d 100644
--- a/drivers/media/platform/qcom/iris/iris_probe.c
+++ b/drivers/media/platform/qcom/iris/iris_probe.c
@@ -233,7 +233,8 @@ static int iris_probe(struct platform_device *pdev)
if (!core)
return -ENOMEM;
core->dev = dev;
- core->fw_debug = IRIS_FW_DEBUG_ERROR | IRIS_FW_DEBUG_FATAL;
+ core->fw_debug = IRIS_FW_DEBUG_DEFAULT;
+ core->hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE;
core->state = IRIS_CORE_DEINIT;
mutex_init(&core->lock);
diff --git a/drivers/media/platform/qcom/iris/iris_utils.c b/drivers/media/platform/qcom/iris/iris_utils.c
index ba5c8dc1280c2e147cd33498b69a815cf7c75683..dbddfd770edce22fba58eff15cb6d45eae5ed638 100644
--- a/drivers/media/platform/qcom/iris/iris_utils.c
+++ b/drivers/media/platform/qcom/iris/iris_utils.c
@@ -70,12 +70,14 @@ void iris_helper_buffers_done(struct iris_inst *inst, unsigned int type,
int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush)
{
struct completion *done;
+ unsigned int timeout;
int ret;
done = is_flush ? &inst->flush_completion : &inst->completion;
+ timeout = READ_ONCE(inst->core->hw_response_timeout);
mutex_unlock(&inst->lock);
- ret = wait_for_completion_timeout(done, msecs_to_jiffies(HW_RESPONSE_TIMEOUT_VALUE));
+ ret = wait_for_completion_timeout(done, msecs_to_jiffies(timeout));
mutex_lock(&inst->lock);
if (!ret) {
iris_inst_change_state(inst, IRIS_INST_ERROR);
--
2.34.1