mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/3] media: qcom: iris: improve error diagnostics
@ 2026-11-06 15:31 Dipayaan Roy
  2026-11-06 15:31 ` [PATCH 1/3] media: qcom: iris: improve probe error reporting Dipayaan Roy
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Dipayaan Roy @ 2026-11-06 15:31 UTC (permalink / raw)
  To: linux-media
  Cc: vikash.garodia, dikshita.agarwal, abhinav.kumar, bod, mchehab,
	p.zabel, linux-arm-msm, linux-kernel

The Iris driver can return probe errors or enter error states without
logging enough context to identify the failed operation or firmware
response. This makes failures difficult to diagnose from kernel logs.

Improve probe error reporting, include available return codes and status
values in existing messages, and add focused diagnostics for system and
session failures. Report recovery failures and provide debug-level
messages for successful recovery and less actionable events.

Dipayaan Roy (3):
  media: qcom: iris: improve probe error reporting
  media: qcom: iris: add error and status details to diagnostics
  media: qcom: iris: Improve diagnostics for system and session failures

 drivers/media/platform/qcom/iris/iris_core.c  |  2 +
 .../platform/qcom/iris/iris_hfi_common.c      |  4 +-
 .../qcom/iris/iris_hfi_gen1_response.c        | 16 +++-
 .../qcom/iris/iris_hfi_gen2_response.c        | 15 ++-
 .../media/platform/qcom/iris/iris_hfi_queue.c | 12 ++-
 drivers/media/platform/qcom/iris/iris_probe.c | 95 ++++++++++++++-----
 drivers/media/platform/qcom/iris/iris_state.c |  5 +-
 drivers/media/platform/qcom/iris/iris_utils.c |  2 +
 drivers/media/platform/qcom/iris/iris_vb2.c   |  2 +-
 drivers/media/platform/qcom/iris/iris_vdec.c  |  3 +-
 drivers/media/platform/qcom/iris/iris_venc.c  |  3 +-
 drivers/media/platform/qcom/iris/iris_vidc.c  |  2 +-
 drivers/media/platform/qcom/iris/iris_vpu3x.c | 19 ++--
 drivers/media/platform/qcom/iris/iris_vpu4x.c |  4 +-
 .../platform/qcom/iris/iris_vpu_common.c      | 15 +--
 15 files changed, 141 insertions(+), 58 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] media: qcom: iris: improve probe error reporting
  2026-11-06 15:31 [PATCH 0/3] media: qcom: iris: improve error diagnostics Dipayaan Roy
@ 2026-11-06 15:31 ` Dipayaan Roy
  2026-11-09  7:17   ` Vishnu Reddy
  2026-11-06 15:31 ` [PATCH 2/3] media: qcom: iris: add error and status details to diagnostics Dipayaan Roy
  2026-11-06 15:31 ` [PATCH 3/3] media: qcom: iris: Improve diagnostics for system and session failures Dipayaan Roy
  2 siblings, 1 reply; 7+ messages in thread
From: Dipayaan Roy @ 2026-11-06 15:31 UTC (permalink / raw)
  To: linux-media
  Cc: vikash.garodia, dikshita.agarwal, abhinav.kumar, bod, mchehab,
	p.zabel, linux-arm-msm, linux-kernel

The Iris probe path returned errors from resource initialization and
device registration without identifying the operation that failed. This
made failures difficult to diagnose, especially when several resources
were acquired during probe.

Use dev_err_probe() at probe and resource initialization failure paths to
report useful context while preserving deferred-probe handling. Also
validate the platform match data before it is dereferenced.

Successful probe behavior and existing cleanup paths remain unchanged.

Signed-off-by: Dipayaan Roy <dipayaan.roy@oss.qualcomm.com>
---
 drivers/media/platform/qcom/iris/iris_probe.c | 98 ++++++++++++++++++++-------
 1 file changed, 74 insertions(+), 24 deletions(-)

diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
index 41dec90f3e2b..dd48fa750013 100644
--- a/drivers/media/platform/qcom/iris/iris_probe.c
+++ b/drivers/media/platform/qcom/iris/iris_probe.c
@@ -19,6 +19,7 @@
 static int iris_init_icc(struct iris_core *core)
 {
 	const struct icc_info *icc_tbl;
+	int ret;
 	u32 i = 0;
 
 	icc_tbl = core->iris_platform_data->icc_tbl;
@@ -36,7 +37,12 @@ static int iris_init_icc(struct iris_core *core)
 		core->icc_tbl[i].peak_bw = 0;
 	}
 
-	return devm_of_icc_bulk_get(core->dev, core->icc_count, core->icc_tbl);
+	ret = devm_of_icc_bulk_get(core->dev, core->icc_count, core->icc_tbl);
+	if (ret)
+		return dev_err_probe(core->dev, ret,
+				     "failed to acquire interconnects\n");
+
+	return 0;
 }
 
 static int iris_init_power_domains(struct iris_core *core)
@@ -62,7 +68,8 @@ static int iris_init_power_domains(struct iris_core *core)
 
 	ret = devm_pm_domain_attach_list(core->dev, &iris_pd_data, &core->pmdomain_tbl);
 	if (ret < 0)
-		return ret;
+		return dev_err_probe(core->dev, ret,
+				     "failed to attach power domains\n");
 
 	ret =  devm_pm_domain_attach_list(core->dev, &iris_opp_pd_data, &core->opp_pmdomain_tbl);
 	/* backwards compatibility for incomplete ABI SM8250 */
@@ -73,13 +80,20 @@ static int iris_init_power_domains(struct iris_core *core)
 						 &core->opp_pmdomain_tbl);
 	}
 	if (ret < 0)
-		return ret;
+		return dev_err_probe(core->dev, ret,
+				     "failed to attach OPP power domains\n");
 
 	ret = devm_pm_opp_set_config(core->dev, &iris_opp_clk_data);
 	if (ret)
-		return ret;
+		return dev_err_probe(core->dev, ret,
+				     "failed to configure OPP clocks\n");
 
-	return devm_pm_opp_of_add_table(core->dev);
+	ret = devm_pm_opp_of_add_table(core->dev);
+	if (ret)
+		return dev_err_probe(core->dev, ret,
+				     "failed to add OPP table\n");
+
+	return 0;
 }
 
 static int iris_init_clocks(struct iris_core *core)
@@ -88,7 +102,8 @@ static int iris_init_clocks(struct iris_core *core)
 
 	ret = devm_clk_bulk_get_all(core->dev, &core->clock_tbl);
 	if (ret < 0)
-		return ret;
+		return dev_err_probe(core->dev, ret,
+				     "failed to acquire clocks\n");
 
 	core->clk_count = ret;
 
@@ -97,8 +112,10 @@ static int iris_init_clocks(struct iris_core *core)
 
 static int iris_init_reset_table(struct iris_core *core,
 				 struct reset_control_bulk_data **resets,
-				 const char * const *rst_tbl, u32 rst_tbl_size)
+				 const char * const *rst_tbl, u32 rst_tbl_size,
+				 const char *name)
 {
+	int ret;
 	u32 i = 0;
 
 	*resets = devm_kzalloc(core->dev,
@@ -110,25 +127,34 @@ static int iris_init_reset_table(struct iris_core *core,
 	for (i = 0; i < rst_tbl_size; i++)
 		(*resets)[i].id = rst_tbl[i];
 
-	return devm_reset_control_bulk_get_exclusive(core->dev, rst_tbl_size, *resets);
+	ret = devm_reset_control_bulk_get_exclusive(core->dev, rst_tbl_size,
+						    *resets);
+	if (ret)
+		return dev_err_probe(core->dev, ret,
+				     "failed to acquire %s resets\n", name);
+
+	return 0;
 }
 
 static int iris_init_resets(struct iris_core *core)
 {
+	const struct iris_platform_data *data = core->iris_platform_data;
 	int ret;
 
 	ret = iris_init_reset_table(core, &core->resets,
-				    core->iris_platform_data->clk_rst_tbl,
-				    core->iris_platform_data->clk_rst_tbl_size);
+				    data->clk_rst_tbl,
+				    data->clk_rst_tbl_size,
+				    "clock");
 	if (ret)
 		return ret;
 
-	if (!core->iris_platform_data->controller_rst_tbl_size)
+	if (!data->controller_rst_tbl_size)
 		return 0;
 
 	return iris_init_reset_table(core, &core->controller_resets,
-				     core->iris_platform_data->controller_rst_tbl,
-				     core->iris_platform_data->controller_rst_tbl_size);
+				     data->controller_rst_tbl,
+				     data->controller_rst_tbl_size,
+				     "controller");
 }
 
 static int iris_init_resources(struct iris_core *core)
@@ -195,6 +221,8 @@ static int iris_reserve_iova_region(struct device *dev, struct dma_iova_state **
 	return 0;
 
 err_free_iova:
+	dev_err(dev, "failed to reserve IOVA range %#lx-%#lx\n",
+		end - chunk, end - 1);
 	iris_unreserve_iova_region(dev, state);
 	dev->bus_dma_limit = dma_limit;
 
@@ -204,8 +232,17 @@ static int iris_reserve_iova_region(struct device *dev, struct dma_iova_state **
 static int iris_register_video_device(struct iris_core *core, enum domain_type type)
 {
 	struct video_device *vdev;
+	const char *name;
 	int ret;
 
+	if (type == DECODER)
+		name = "decoder";
+	else if (type == ENCODER)
+		name = "encoder";
+	else
+		return dev_err_probe(core->dev, -EINVAL,
+				     "invalid video device type %d\n", type);
+
 	vdev = video_device_alloc();
 	if (!vdev)
 		return -ENOMEM;
@@ -220,18 +257,18 @@ static int iris_register_video_device(struct iris_core *core, enum domain_type t
 		strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name));
 		vdev->ioctl_ops = core->iris_v4l2_ioctl_ops_dec;
 		core->vdev_dec = vdev;
-	} else if (type == ENCODER) {
+	} else {
 		strscpy(vdev->name, "qcom-iris-encoder", sizeof(vdev->name));
 		vdev->ioctl_ops = core->iris_v4l2_ioctl_ops_enc;
 		core->vdev_enc = vdev;
-	} else {
-		ret = -EINVAL;
-		goto err_vdev_release;
 	}
 
 	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
-	if (ret)
+	if (ret) {
+		dev_err_probe(core->dev, ret,
+			      "failed to register %s video device\n", name);
 		goto err_vdev_release;
+	}
 
 	video_set_drvdata(vdev, core);
 
@@ -306,17 +343,22 @@ static int iris_probe(struct platform_device *pdev)
 		return core->irq;
 
 	core->iris_platform_data = of_device_get_match_data(core->dev);
+	if (!core->iris_platform_data)
+		return dev_err_probe(dev, -ENODEV,
+				     "missing platform match data\n");
 
 	core->ubwc_cfg = qcom_ubwc_config_get_data();
 	if (IS_ERR(core->ubwc_cfg))
-		return PTR_ERR(core->ubwc_cfg);
+		return dev_err_probe(dev, PTR_ERR(core->ubwc_cfg),
+				     "failed to get UBWC configuration\n");
 
 	ret = devm_request_threaded_irq(core->dev, core->irq, iris_hfi_isr,
 					iris_hfi_isr_handler,
 					IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN,
 					"iris", core);
 	if (ret)
-		return ret;
+		return dev_err_probe(dev, ret, "failed to request IRQ %d\n",
+				     core->irq);
 
 	iris_init_ops(core);
 
@@ -327,11 +369,14 @@ static int iris_probe(struct platform_device *pdev)
 	ret = iris_reserve_iova_region(dev, &core->iova_state, IRIS_NP_RESERVE_IOVA_START,
 				       IRIS_NP_RESERVE_IOVA_SIZE);
 	if (ret)
-		return ret;
+		return dev_err_probe(dev, ret,
+				     "failed to reserve IOVA region\n");
 
 	ret = v4l2_device_register(dev, &core->v4l2_dev);
-	if (ret)
+	if (ret) {
+		dev_err_probe(dev, ret, "failed to register V4L2 device\n");
 		goto err_unresv_iova_region;
+	}
 
 	ret = iris_register_video_device(core, DECODER);
 	if (ret)
@@ -346,8 +391,11 @@ static int iris_probe(struct platform_device *pdev)
 	dma_mask = core->iris_platform_data->dma_mask;
 
 	ret = dma_set_mask_and_coherent(dev, dma_mask);
-	if (ret)
+	if (ret) {
+		dev_err_probe(dev, ret, "failed to set DMA mask %#llx\n",
+			      (unsigned long long)dma_mask);
 		goto err_vdev_unreg_enc;
+	}
 
 	dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
 	dma_set_seg_boundary(&pdev->dev, DMA_BIT_MASK(32));
@@ -355,8 +403,10 @@ static int iris_probe(struct platform_device *pdev)
 	pm_runtime_set_autosuspend_delay(core->dev, AUTOSUSPEND_DELAY_VALUE);
 	pm_runtime_use_autosuspend(core->dev);
 	ret = devm_pm_runtime_enable(core->dev);
-	if (ret)
+	if (ret) {
+		dev_err_probe(dev, ret, "failed to enable runtime PM\n");
 		goto err_vdev_unreg_enc;
+	}
 
 	return 0;
 

-- 
2.43.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/3] media: qcom: iris: add error and status details to diagnostics
  2026-11-06 15:31 [PATCH 0/3] media: qcom: iris: improve error diagnostics Dipayaan Roy
  2026-11-06 15:31 ` [PATCH 1/3] media: qcom: iris: improve probe error reporting Dipayaan Roy
@ 2026-11-06 15:31 ` Dipayaan Roy
  2026-11-09  7:25   ` Vishnu Reddy
  2026-11-06 15:31 ` [PATCH 3/3] media: qcom: iris: Improve diagnostics for system and session failures Dipayaan Roy
  2 siblings, 1 reply; 7+ messages in thread
From: Dipayaan Roy @ 2026-11-06 15:31 UTC (permalink / raw)
  To: linux-media
  Cc: vikash.garodia, dikshita.agarwal, abhinav.kumar, bod, mchehab,
	p.zabel, linux-arm-msm, linux-kernel

Several Iris error messages identify a failed operation without showing
the return code or state that caused it, making failures difficult to
diagnose.

Include available return codes, hardware status, queue positions, and
packet or session identifiers in these messages. Also report the header
details when an HFI response fails validation.

Error handling remains unchanged.

Signed-off-by: Dipayaan Roy <dipayaan.roy@oss.qualcomm.com>
---
 drivers/media/platform/qcom/iris/iris_hfi_common.c |  4 ++--
 .../platform/qcom/iris/iris_hfi_gen1_response.c    |  9 ++++++---
 .../platform/qcom/iris/iris_hfi_gen2_response.c    |  5 ++++-
 drivers/media/platform/qcom/iris/iris_hfi_queue.c  | 14 +++++++++----
 drivers/media/platform/qcom/iris/iris_vb2.c        |  2 +-
 drivers/media/platform/qcom/iris/iris_vdec.c       |  3 ++-
 drivers/media/platform/qcom/iris/iris_venc.c       |  3 ++-
 drivers/media/platform/qcom/iris/iris_vidc.c       |  2 +-
 drivers/media/platform/qcom/iris/iris_vpu3x.c      | 23 +++++++++++-----------
 drivers/media/platform/qcom/iris/iris_vpu4x.c      |  6 ++++--
 drivers/media/platform/qcom/iris/iris_vpu_common.c | 15 ++++++++------
 11 files changed, 53 insertions(+), 33 deletions(-)

diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.c b/drivers/media/platform/qcom/iris/iris_hfi_common.c
index dad906d03fdc..1fd4cecd7956 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_common.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_common.c
@@ -138,7 +138,7 @@ int iris_hfi_pm_suspend(struct iris_core *core)
 	return 0;
 
 error:
-	dev_err(core->dev, "failed to suspend\n");
+	dev_err(core->dev, "failed to suspend: %d\n", ret);
 
 	return ret;
 }
@@ -179,7 +179,7 @@ int iris_hfi_pm_resume(struct iris_core *core)
 err_power_off:
 	iris_vpu_power_off(core);
 error:
-	dev_err(core->dev, "failed to resume\n");
+	dev_err(core->dev, "failed to resume: %d\n", ret);
 
 	return -EBUSY;
 }
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 ffa98139f0eb..1ce7f97d4087 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
@@ -301,7 +301,8 @@ iris_hfi_gen1_sys_get_prop_image_version(struct iris_core *core,
 	u32 i;
 
 	if (req_bytes < IRIS_FW_VERSION_LENGTH - 1 || !pkt->data[0] || pkt->num_properties > 1) {
-		dev_err(core->dev, "bad packet\n");
+		dev_err(core->dev, "invalid firmware version packet (size %u, properties %u)\n",
+			pkt->hdr.size, pkt->num_properties);
 		return;
 	}
 
@@ -382,7 +383,8 @@ static void iris_hfi_gen1_session_etb_done(struct iris_inst *inst, void *packet)
 
 error:
 	iris_inst_change_state(inst, IRIS_INST_ERROR);
-	dev_err(inst->core->dev, "error in etb done\n");
+	dev_err(inst->core->dev, "ETB done without input buffer (session %#x, tag %u)\n",
+		inst->session_id, pkt->input_tag);
 }
 
 static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
@@ -530,7 +532,8 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
 
 error:
 	iris_inst_change_state(inst, IRIS_INST_ERROR);
-	dev_err(core->dev, "error in ftb done\n");
+	dev_err(core->dev, "FTB done without output buffer (session %#x, tag %u, offset %u)\n",
+		inst->session_id, output_tag, offset);
 }
 
 static enum iris_buffer_type iris_hfi_gen1_buf_type(struct iris_inst *inst, u32 type)
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 f0782c4b1e6e..b82f50458fe1 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
@@ -980,8 +980,11 @@ static int iris_hfi_gen2_handle_response(struct iris_core *core, void *response)
 	int ret;
 
 	ret = iris_hfi_gen2_validate_hdr_packet(core, hdr);
-	if (ret)
+	if (ret) {
+		dev_err(core->dev, "invalid HFI response (size %u, packets %u): %d\n",
+			hdr->size, hdr->num_packets, ret);
 		return iris_hfi_gen2_handle_system_error(core, NULL);
+	}
 
 	if (!hdr->session_id)
 		return iris_hfi_gen2_handle_system_response(core, hdr);
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c
index bf6db23b53e2..ef556e54f6f1 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c
@@ -112,14 +112,18 @@ static int iris_hfi_queue_read(struct iris_iface_q_info *qinfo, void *packet)
 int iris_hfi_queue_cmd_write_locked(struct iris_core *core, void *pkt, u32 pkt_size)
 {
 	struct iris_iface_q_info *q_info = &core->command_queue;
+	int ret;
 
 	if (core->state == IRIS_CORE_ERROR || core->state == IRIS_CORE_DEINIT)
 		return -EINVAL;
 
-	if (!iris_hfi_queue_write(q_info, pkt, pkt_size)) {
+	ret = iris_hfi_queue_write(q_info, pkt, pkt_size);
+	if (!ret) {
 		iris_vpu_raise_interrupt(core);
 	} else {
-		dev_err(core->dev, "queue full\n");
+		dev_err(core->dev, "command queue write failed: %d (size %u, read %u, write %u)\n",
+			ret, pkt_size, q_info->qhdr->read_idx,
+			q_info->qhdr->write_idx);
 		return -ENODATA;
 	}
 
@@ -254,7 +258,8 @@ int iris_hfi_queues_init(struct iris_core *core)
 						    &core->iface_q_table_daddr,
 						    GFP_KERNEL, DMA_ATTR_WRITE_COMBINE);
 	if (!core->iface_q_table_vaddr) {
-		dev_err(core->dev, "queues alloc and map failed\n");
+		dev_err(core->dev, "failed to allocate HFI queues (%u bytes)\n",
+			queue_size);
 		return -ENOMEM;
 	}
 
@@ -262,7 +267,8 @@ int iris_hfi_queues_init(struct iris_core *core)
 					  &core->sfr_daddr,
 					  GFP_KERNEL, DMA_ATTR_WRITE_COMBINE);
 	if (!core->sfr_vaddr) {
-		dev_err(core->dev, "sfr alloc and map failed\n");
+		dev_err(core->dev, "failed to allocate SFR (%u bytes)\n",
+			(unsigned int)SFR_SIZE);
 		dma_free_attrs(core->dev, queue_size, core->iface_q_table_vaddr,
 			       core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE);
 		return -ENOMEM;
diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c
index 8faf709c26c1..b770cd5349b6 100644
--- a/drivers/media/platform/qcom/iris/iris_vb2.c
+++ b/drivers/media/platform/qcom/iris/iris_vb2.c
@@ -135,8 +135,8 @@ int iris_vb2_queue_setup(struct vb2_queue *q,
 
 		ret = inst->hfi_session_ops->session_open(inst);
 		if (ret) {
+			dev_err(core->dev, "session open failed: %d\n", ret);
 			ret = -EINVAL;
-			dev_err(core->dev, "session open failed\n");
 			goto unlock;
 		}
 
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
index 0dd33ff447bb..d359d3716ba1 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/iris/iris_vdec.c
@@ -529,7 +529,8 @@ int iris_vdec_start_cmd(struct iris_inst *inst)
 			clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
 		}
 	} else {
-		dev_err(inst->core->dev, "start called before receiving last_flag\n");
+		dev_err(inst->core->dev, "start before last buffer (sub-state %#x)\n",
+			inst->sub_state);
 		iris_inst_change_state(inst, IRIS_INST_ERROR);
 		return -EBUSY;
 	}
diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
index 2f2c56bf9122..a7a0f14a78d1 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.c
+++ b/drivers/media/platform/qcom/iris/iris_venc.c
@@ -602,7 +602,8 @@ int iris_venc_start_cmd(struct iris_inst *inst)
 			clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
 		}
 	} else {
-		dev_err(inst->core->dev, "start called before receiving last_flag\n");
+		dev_err(inst->core->dev, "start before last buffer (sub-state %#x)\n",
+			inst->sub_state);
 		iris_inst_change_state(inst, IRIS_INST_ERROR);
 		return -EBUSY;
 	}
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index 05aab6e3005d..80f0a56712bf 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -168,7 +168,7 @@ int iris_open(struct file *filp)
 
 	ret = iris_core_init(core);
 	if (ret) {
-		dev_err(core->dev, "core init failed\n");
+		dev_err(core->dev, "core init failed: %d\n", ret);
 		pm_runtime_put_sync(core->dev);
 		return ret;
 	}
diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c
index c3b760730c98..cd22534c0904 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu3x.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c
@@ -17,14 +17,12 @@
 #define NOC_HALT				BIT(0)
 #define AON_WRAPPER_SPARE			(AON_BASE_OFFS + 0x28)
 
-static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core)
+static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core,
+					  u32 *power_status)
 {
-	u32 value, pwr_status;
+	*power_status = readl(core->reg_base + WRAPPER_CORE_POWER_STATUS);
 
-	value = readl(core->reg_base + WRAPPER_CORE_POWER_STATUS);
-	pwr_status = value & BIT(1);
-
-	return pwr_status ? false : true;
+	return !(*power_status & BIT(1));
 }
 
 static void iris_vpu3_power_off_hardware(struct iris_core *core)
@@ -32,10 +30,11 @@ static void iris_vpu3_power_off_hardware(struct iris_core *core)
 	u32 reg_val = 0, value, i;
 	int ret;
 
-	if (iris_vpu3x_hw_power_collapsed(core))
+	if (iris_vpu3x_hw_power_collapsed(core, &value))
 		goto disable_power;
 
-	dev_err(core->dev, "video hw is power on\n");
+	dev_err(core->dev, "video hardware still powered on (status %#x)\n",
+		value);
 
 	value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG);
 	if (value)
@@ -78,10 +77,11 @@ static void iris_vpu33_power_off_hardware(struct iris_core *core)
 	u32 count = 0;
 	int ret;
 
-	if (iris_vpu3x_hw_power_collapsed(core))
+	if (iris_vpu3x_hw_power_collapsed(core, &value))
 		goto disable_power;
 
-	dev_err(core->dev, "video hw is power on\n");
+	dev_err(core->dev, "video hardware still powered on (status %#x)\n",
+		value);
 
 	value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG);
 	if (value)
@@ -116,7 +116,8 @@ static void iris_vpu33_power_off_hardware(struct iris_core *core)
 	} while (++count < 1000);
 
 	if (!handshake_done && handshake_busy)
-		dev_err(core->dev, "LPI handshake timeout\n");
+		dev_err(core->dev, "LPI handshake timeout (status %#x)\n",
+			value);
 
 	ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS,
 				 reg_val, reg_val & BIT(0), 200, 2000);
diff --git a/drivers/media/platform/qcom/iris/iris_vpu4x.c b/drivers/media/platform/qcom/iris/iris_vpu4x.c
index 90ccdc0d2a07..0369f2497f76 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu4x.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu4x.c
@@ -117,7 +117,8 @@ static void iris_vpu4x_power_off_apv(struct iris_core *core)
 	} while (++count < 1000);
 
 	if (!handshake_done && handshake_busy)
-		dev_err(core->dev, "LPI handshake timeout\n");
+		dev_err(core->dev, "APV LPI handshake timeout (status %#x)\n",
+			value);
 
 	writel(0x080200, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ);
 	ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK,
@@ -314,7 +315,8 @@ static void iris_vpu4x_power_off_hardware(struct iris_core *core)
 	} while (++count < 1000);
 
 	if (!handshake_done && handshake_busy)
-		dev_err(core->dev, "LPI handshake timeout\n");
+		dev_err(core->dev, "hardware LPI handshake timeout (status %#x)\n",
+			value);
 
 	writel(MVP_NOC_RESET_REQ_MASK, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ);
 	ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK,
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c
index 243bd845349f..4a56856a8df5 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_common.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c
@@ -83,7 +83,8 @@ int iris_vpu_boot_firmware(struct iris_core *core)
 	while (!ctrl_status && count < max_tries) {
 		ctrl_status = readl(core->reg_base + CTRL_STATUS);
 		if ((ctrl_status & CTRL_ERROR_STATUS__M) == 0x4) {
-			dev_err(core->dev, "invalid setting for uc_region\n");
+			dev_err(core->dev, "invalid UC region setting (CTRL_STATUS %#x)\n",
+				ctrl_status);
 			return -EINVAL;
 		}
 
@@ -92,7 +93,8 @@ int iris_vpu_boot_firmware(struct iris_core *core)
 	}
 
 	if (count >= max_tries) {
-		dev_err(core->dev, "error booting up iris firmware\n");
+		dev_err(core->dev, "firmware boot timed out (CTRL_STATUS %#x)\n",
+			ctrl_status);
 		return -ETIME;
 	}
 
@@ -128,7 +130,8 @@ int iris_vpu_watchdog(struct iris_core *core, u32 intr_status)
 	u32 wd_intr_mask = core->iris_platform_data->wd_intr_mask;
 
 	if (intr_status & wd_intr_mask) {
-		dev_err(core->dev, "received watchdog interrupt\n");
+		dev_err(core->dev, "received watchdog interrupt (status %#x)\n",
+			intr_status);
 		return -ETIME;
 	}
 
@@ -172,7 +175,7 @@ int iris_vpu_prepare_pc(struct iris_core *core)
 	ctrl_status = readl(core->reg_base + CTRL_STATUS);
 	wfi_status = readl(core->reg_base + WRAPPER_TZ_CPU_STATUS);
 	wfi_status &= BIT(0);
-	dev_err(core->dev, "skip power collapse, wfi=%#x, idle=%#x, pcr=%#x, ctrl=%#x)\n",
+	dev_err(core->dev, "skip power collapse (wfi=%#x, idle=%#x, pcr=%#x, ctrl=%#x)\n",
 		wfi_status, idle_status, pc_ready, ctrl_status);
 
 	return -EAGAIN;
@@ -365,7 +368,7 @@ int iris_vpu35_vpu4x_power_off_controller(struct iris_core *core)
 	} while (++count < 1000);
 
 	if (!handshake_done && handshake_busy)
-		dev_err(core->dev, "LPI handshake timeout\n");
+		dev_err(core->dev, "LPI handshake timeout (status %#x)\n", val);
 
 	ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS,
 				 val, val & BIT(0), 200, 2000);
@@ -530,7 +533,7 @@ int iris_vpu_power_on(struct iris_core *core)
 err_unvote_icc:
 	iris_unset_icc_bw(core);
 err:
-	dev_err(core->dev, "power on failed\n");
+	dev_err(core->dev, "power on failed: %d\n", ret);
 
 	return ret;
 }

-- 
2.43.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 3/3] media: qcom: iris: Improve diagnostics for system and session failures
  2026-11-06 15:31 [PATCH 0/3] media: qcom: iris: improve error diagnostics Dipayaan Roy
  2026-11-06 15:31 ` [PATCH 1/3] media: qcom: iris: improve probe error reporting Dipayaan Roy
  2026-11-06 15:31 ` [PATCH 2/3] media: qcom: iris: add error and status details to diagnostics Dipayaan Roy
@ 2026-11-06 15:31 ` Dipayaan Roy
  2026-11-09  7:53   ` Vishnu Reddy
  2 siblings, 1 reply; 7+ messages in thread
From: Dipayaan Roy @ 2026-11-06 15:31 UTC (permalink / raw)
  To: linux-media
  Cc: vikash.garodia, dikshita.agarwal, abhinav.kumar, bod, mchehab,
	p.zabel, linux-arm-msm, linux-kernel

Log system and session response timeouts, firmware-reported failures,
and failed recovery attempts so the cause of an error is visible.

Add debug messages for unknown sessions, invalid state transitions,
and successful recovery. Avoid a redundant system init timeout message
after firmware reports an error, and rate-limit Gen2 session response
errors.

Signed-off-by: Dipayaan Roy <dipayaan.roy@oss.qualcomm.com>
---
 drivers/media/platform/qcom/iris/iris_core.c              |  2 ++
 drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c |  8 +++++++-
 drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c | 13 ++++++++++++-
 drivers/media/platform/qcom/iris/iris_probe.c             |  8 +++++++-
 drivers/media/platform/qcom/iris/iris_state.c             |  5 ++++-
 drivers/media/platform/qcom/iris/iris_utils.c             |  2 ++
 6 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c
index d558475986ff..4224feaf1caf 100644
--- a/drivers/media/platform/qcom/iris/iris_core.c
+++ b/drivers/media/platform/qcom/iris/iris_core.c
@@ -43,6 +43,8 @@ static int iris_wait_for_system_response(struct iris_core *core)
 	ret = wait_for_completion_timeout(&core->core_init_done,
 					  msecs_to_jiffies(HW_RESPONSE_TIMEOUT_VALUE));
 	if (!ret) {
+		if (core->state != IRIS_CORE_ERROR)
+			dev_err(core->dev, "system init response timed out\n");
 		core->state = IRIS_CORE_ERROR;
 		return -ETIMEDOUT;
 	}
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 1ce7f97d4087..5c411e69e5fd 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
@@ -284,6 +284,8 @@ static void iris_hfi_gen1_sys_init_done(struct iris_core *core, void *packet)
 	struct hfi_msg_sys_init_done_pkt *pkt = packet;
 
 	if (pkt->error_type != HFI_ERR_NONE) {
+		dev_err(core->dev, "system init failed (HFI error %#x)\n",
+			pkt->error_type);
 		core->state = IRIS_CORE_ERROR;
 		return;
 	}
@@ -740,8 +742,12 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response
 			struct hfi_msg_session_hdr_pkt *shdr;
 
 			shdr = (struct hfi_msg_session_hdr_pkt *)hdr;
-			if (shdr->error_type != HFI_ERR_NONE)
+			if (shdr->error_type != HFI_ERR_NONE) {
+				dev_err(dev, "session %#x response %#x failed (HFI error %#x)\n",
+					inst->session_id, hdr->pkt_type,
+					shdr->error_type);
 				iris_inst_change_state(inst, IRIS_INST_ERROR);
+			}
 
 			if (pkt_info->pkt == HFI_MSG_SESSION_FLUSH) {
 				if (!(--inst->flush_responses_pending))
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 b82f50458fe1..d5b4b27e0549 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
@@ -296,6 +296,8 @@ static int iris_hfi_gen2_handle_system_init(struct iris_core *core,
 					    struct iris_hfi_packet *pkt)
 {
 	if (!(pkt->flags & HFI_FW_FLAGS_SUCCESS)) {
+		dev_err(core->dev, "system command %#x failed (flags %#x)\n",
+			pkt->type, pkt->flags);
 		core->state = IRIS_CORE_ERROR;
 		return 0;
 	}
@@ -929,8 +931,11 @@ static int iris_hfi_gen2_handle_session_response(struct iris_core *core,
 	};
 
 	inst = iris_get_instance(core, hdr->session_id);
-	if (!inst)
+	if (!inst) {
+		dev_dbg(core->dev, "response for unknown session %#x\n",
+			hdr->session_id);
 		return -EINVAL;
+	}
 
 	mutex_lock(&inst->lock);
 	inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
@@ -958,6 +963,12 @@ static int iris_hfi_gen2_handle_session_response(struct iris_core *core,
 			if (packet->type > range[i].begin && packet->type < range[i].end) {
 				dequeue |= (packet->type == HFI_CMD_BUFFER);
 				ret = range[i].handle(inst, packet);
+				if (ret && !(packet->flags &
+					     HFI_FW_FLAGS_SESSION_ERROR))
+					dev_err_ratelimited(core->dev,
+							    "session %#x response %#x failed: %d\n",
+							    inst->session_id,
+							    packet->type, ret);
 				if (ret)
 					iris_inst_change_state(inst, IRIS_INST_ERROR);
 			}
diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
index dd48fa750013..9cefe090466b 100644
--- a/drivers/media/platform/qcom/iris/iris_probe.c
+++ b/drivers/media/platform/qcom/iris/iris_probe.c
@@ -306,9 +306,15 @@ static void iris_sys_error_handler(struct work_struct *work)
 {
 	struct iris_core *core =
 			container_of(work, struct iris_core, sys_error_handler.work);
+	int ret;
 
 	iris_core_deinit(core);
-	iris_core_init(core);
+	ret = iris_core_init(core);
+	if (ret)
+		dev_err(core->dev, "failed to recover from system error: %d\n",
+			ret);
+	else
+		dev_dbg(core->dev, "recovered from system error\n");
 }
 
 static int iris_probe(struct platform_device *pdev)
diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c
index 5552725c614e..bcb138ccf08c 100644
--- a/drivers/media/platform/qcom/iris/iris_state.c
+++ b/drivers/media/platform/qcom/iris/iris_state.c
@@ -56,8 +56,11 @@ int iris_inst_change_state(struct iris_inst *inst,
 	if (request_state == IRIS_INST_ERROR)
 		goto change_state;
 
-	if (!iris_allow_inst_state_change(inst, request_state))
+	if (!iris_allow_inst_state_change(inst, request_state)) {
+		dev_dbg(inst->core->dev, "session %#x invalid state change %x -> %x\n",
+			inst->session_id, inst->state, request_state);
 		return -EINVAL;
+	}
 
 change_state:
 	dev_dbg(inst->core->dev, "state changed from %x to %x\n",
diff --git a/drivers/media/platform/qcom/iris/iris_utils.c b/drivers/media/platform/qcom/iris/iris_utils.c
index 1096cc4b01c3..5ca4d8e0836b 100644
--- a/drivers/media/platform/qcom/iris/iris_utils.c
+++ b/drivers/media/platform/qcom/iris/iris_utils.c
@@ -78,6 +78,8 @@ int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush)
 	ret = wait_for_completion_timeout(done, msecs_to_jiffies(HW_RESPONSE_TIMEOUT_VALUE));
 	mutex_lock(&inst->lock);
 	if (!ret) {
+		dev_err(inst->core->dev, "session %#x %s response timed out\n",
+			inst->session_id, is_flush ? "flush" : "command");
 		iris_inst_change_state(inst, IRIS_INST_ERROR);
 		return -ETIMEDOUT;
 	}

-- 
2.43.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] media: qcom: iris: improve probe error reporting
  2026-11-06 15:31 ` [PATCH 1/3] media: qcom: iris: improve probe error reporting Dipayaan Roy
@ 2026-11-09  7:17   ` Vishnu Reddy
  0 siblings, 0 replies; 7+ messages in thread
From: Vishnu Reddy @ 2026-11-09  7:17 UTC (permalink / raw)
  To: Dipayaan Roy, linux-media
  Cc: vikash.garodia, dikshita.agarwal, abhinav.kumar, bod, mchehab,
	p.zabel, linux-arm-msm, linux-kernel


On 11/6/2026 9:01 PM, Dipayaan Roy wrote:
> The Iris probe path returned errors from resource initialization and
> device registration without identifying the operation that failed. This
> made failures difficult to diagnose, especially when several resources
> were acquired during probe.
>
> Use dev_err_probe() at probe and resource initialization failure paths to
> report useful context while preserving deferred-probe handling. Also
> validate the platform match data before it is dereferenced.
>
> Successful probe behavior and existing cleanup paths remain unchanged.
>
> Signed-off-by: Dipayaan Roy <dipayaan.roy@oss.qualcomm.com>
> ---
>  drivers/media/platform/qcom/iris/iris_probe.c | 98 ++++++++++++++++++++-------
>  1 file changed, 74 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
> index 41dec90f3e2b..dd48fa750013 100644
> --- a/drivers/media/platform/qcom/iris/iris_probe.c
> +++ b/drivers/media/platform/qcom/iris/iris_probe.c
> @@ -19,6 +19,7 @@
>  static int iris_init_icc(struct iris_core *core)
>  {
>  	const struct icc_info *icc_tbl;
> +	int ret;
>  	u32 i = 0;
>  
>  	icc_tbl = core->iris_platform_data->icc_tbl;
> @@ -36,7 +37,12 @@ static int iris_init_icc(struct iris_core *core)
>  		core->icc_tbl[i].peak_bw = 0;
>  	}
>  
> -	return devm_of_icc_bulk_get(core->dev, core->icc_count, core->icc_tbl);
> +	ret = devm_of_icc_bulk_get(core->dev, core->icc_count, core->icc_tbl);
> +	if (ret)
> +		return dev_err_probe(core->dev, ret,
> +				     "failed to acquire interconnects\n");
> +
> +	return 0;
>  }
>  
>  static int iris_init_power_domains(struct iris_core *core)
> @@ -62,7 +68,8 @@ static int iris_init_power_domains(struct iris_core *core)
>  
>  	ret = devm_pm_domain_attach_list(core->dev, &iris_pd_data, &core->pmdomain_tbl);
>  	if (ret < 0)
> -		return ret;
> +		return dev_err_probe(core->dev, ret,
> +				     "failed to attach power domains\n");
>  
>  	ret =  devm_pm_domain_attach_list(core->dev, &iris_opp_pd_data, &core->opp_pmdomain_tbl);
>  	/* backwards compatibility for incomplete ABI SM8250 */
> @@ -73,13 +80,20 @@ static int iris_init_power_domains(struct iris_core *core)
>  						 &core->opp_pmdomain_tbl);
>  	}
>  	if (ret < 0)
> -		return ret;
> +		return dev_err_probe(core->dev, ret,
> +				     "failed to attach OPP power domains\n");
>  
>  	ret = devm_pm_opp_set_config(core->dev, &iris_opp_clk_data);
>  	if (ret)
> -		return ret;
> +		return dev_err_probe(core->dev, ret,
> +				     "failed to configure OPP clocks\n");
>  
> -	return devm_pm_opp_of_add_table(core->dev);
> +	ret = devm_pm_opp_of_add_table(core->dev);
> +	if (ret)
> +		return dev_err_probe(core->dev, ret,
> +				     "failed to add OPP table\n");
> +
> +	return 0;
>  }
>  
>  static int iris_init_clocks(struct iris_core *core)
> @@ -88,7 +102,8 @@ static int iris_init_clocks(struct iris_core *core)
>  
>  	ret = devm_clk_bulk_get_all(core->dev, &core->clock_tbl);
>  	if (ret < 0)
> -		return ret;
> +		return dev_err_probe(core->dev, ret,
> +				     "failed to acquire clocks\n");
>  
>  	core->clk_count = ret;
>  
> @@ -97,8 +112,10 @@ static int iris_init_clocks(struct iris_core *core)
>  
>  static int iris_init_reset_table(struct iris_core *core,
>  				 struct reset_control_bulk_data **resets,
> -				 const char * const *rst_tbl, u32 rst_tbl_size)
> +				 const char * const *rst_tbl, u32 rst_tbl_size,
> +				 const char *name)
>  {
> +	int ret;
>  	u32 i = 0;
>  
>  	*resets = devm_kzalloc(core->dev,
> @@ -110,25 +127,34 @@ static int iris_init_reset_table(struct iris_core *core,
>  	for (i = 0; i < rst_tbl_size; i++)
>  		(*resets)[i].id = rst_tbl[i];
>  
> -	return devm_reset_control_bulk_get_exclusive(core->dev, rst_tbl_size, *resets);
> +	ret = devm_reset_control_bulk_get_exclusive(core->dev, rst_tbl_size,
> +						    *resets);
> +	if (ret)
> +		return dev_err_probe(core->dev, ret,
> +				     "failed to acquire %s resets\n", name);
> +
> +	return 0;
>  }
>  
>  static int iris_init_resets(struct iris_core *core)
>  {
> +	const struct iris_platform_data *data = core->iris_platform_data;
>  	int ret;
>  
>  	ret = iris_init_reset_table(core, &core->resets,
> -				    core->iris_platform_data->clk_rst_tbl,
> -				    core->iris_platform_data->clk_rst_tbl_size);
> +				    data->clk_rst_tbl,
> +				    data->clk_rst_tbl_size,
> +				    "clock");
>  	if (ret)
>  		return ret;
>  
> -	if (!core->iris_platform_data->controller_rst_tbl_size)
> +	if (!data->controller_rst_tbl_size)
>  		return 0;
>  
>  	return iris_init_reset_table(core, &core->controller_resets,
> -				     core->iris_platform_data->controller_rst_tbl,
> -				     core->iris_platform_data->controller_rst_tbl_size);
> +				     data->controller_rst_tbl,
> +				     data->controller_rst_tbl_size,
> +				     "controller");
>  }
>  
>  static int iris_init_resources(struct iris_core *core)
> @@ -195,6 +221,8 @@ static int iris_reserve_iova_region(struct device *dev, struct dma_iova_state **
>  	return 0;
>  
>  err_free_iova:
> +	dev_err(dev, "failed to reserve IOVA range %#lx-%#lx\n",
> +		end - chunk, end - 1);
>  	iris_unreserve_iova_region(dev, state);
>  	dev->bus_dma_limit = dma_limit;
>  
> @@ -204,8 +232,17 @@ static int iris_reserve_iova_region(struct device *dev, struct dma_iova_state **
>  static int iris_register_video_device(struct iris_core *core, enum domain_type type)
>  {
>  	struct video_device *vdev;
> +	const char *name;
>  	int ret;
>  
> +	if (type == DECODER)
> +		name = "decoder";
> +	else if (type == ENCODER)
> +		name = "encoder";
> +	else
> +		return dev_err_probe(core->dev, -EINVAL,
> +				     "invalid video device type %d\n", type);
> +
>  	vdev = video_device_alloc();
>  	if (!vdev)
>  		return -ENOMEM;
> @@ -220,18 +257,18 @@ static int iris_register_video_device(struct iris_core *core, enum domain_type t
>  		strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name));
>  		vdev->ioctl_ops = core->iris_v4l2_ioctl_ops_dec;
>  		core->vdev_dec = vdev;
> -	} else if (type == ENCODER) {
> +	} else {
>  		strscpy(vdev->name, "qcom-iris-encoder", sizeof(vdev->name));
>  		vdev->ioctl_ops = core->iris_v4l2_ioctl_ops_enc;
>  		core->vdev_enc = vdev;
> -	} else {
> -		ret = -EINVAL;
> -		goto err_vdev_release;
>  	}
>  
>  	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
> -	if (ret)
> +	if (ret) {
> +		dev_err_probe(core->dev, ret,
> +			      "failed to register %s video device\n", name);
>  		goto err_vdev_release;
> +	}
>  
>  	video_set_drvdata(vdev, core);
>  
> @@ -306,17 +343,22 @@ static int iris_probe(struct platform_device *pdev)
>  		return core->irq;
>  
>  	core->iris_platform_data = of_device_get_match_data(core->dev);
> +	if (!core->iris_platform_data)
> +		return dev_err_probe(dev, -ENODEV,
> +				     "missing platform match data\n");
>  
>  	core->ubwc_cfg = qcom_ubwc_config_get_data();
>  	if (IS_ERR(core->ubwc_cfg))
> -		return PTR_ERR(core->ubwc_cfg);
> +		return dev_err_probe(dev, PTR_ERR(core->ubwc_cfg),
> +				     "failed to get UBWC configuration\n");
>  
>  	ret = devm_request_threaded_irq(core->dev, core->irq, iris_hfi_isr,
>  					iris_hfi_isr_handler,
>  					IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN,
>  					"iris", core);
>  	if (ret)
> -		return ret;
> +		return dev_err_probe(dev, ret, "failed to request IRQ %d\n",
> +				     core->irq);
>  
>  	iris_init_ops(core);
>  
> @@ -327,11 +369,14 @@ static int iris_probe(struct platform_device *pdev)
>  	ret = iris_reserve_iova_region(dev, &core->iova_state, IRIS_NP_RESERVE_IOVA_START,
>  				       IRIS_NP_RESERVE_IOVA_SIZE);
>  	if (ret)
> -		return ret;
> +		return dev_err_probe(dev, ret,
> +				     "failed to reserve IOVA region\n");
>  
>  	ret = v4l2_device_register(dev, &core->v4l2_dev);
> -	if (ret)
> +	if (ret) {
> +		dev_err_probe(dev, ret, "failed to register V4L2 device\n");
>  		goto err_unresv_iova_region;
> +	}
>  
>  	ret = iris_register_video_device(core, DECODER);
>  	if (ret)
> @@ -346,8 +391,11 @@ static int iris_probe(struct platform_device *pdev)
>  	dma_mask = core->iris_platform_data->dma_mask;
>  
>  	ret = dma_set_mask_and_coherent(dev, dma_mask);
> -	if (ret)
> +	if (ret) {
> +		dev_err_probe(dev, ret, "failed to set DMA mask %#llx\n",
> +			      (unsigned long long)dma_mask);
>  		goto err_vdev_unreg_enc;
> +	}
>  
>  	dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
>  	dma_set_seg_boundary(&pdev->dev, DMA_BIT_MASK(32));
> @@ -355,8 +403,10 @@ static int iris_probe(struct platform_device *pdev)
>  	pm_runtime_set_autosuspend_delay(core->dev, AUTOSUSPEND_DELAY_VALUE);
>  	pm_runtime_use_autosuspend(core->dev);
>  	ret = devm_pm_runtime_enable(core->dev);
> -	if (ret)
> +	if (ret) {
> +		dev_err_probe(dev, ret, "failed to enable runtime PM\n");
>  		goto err_vdev_unreg_enc;
> +	}
>  
>  	return 0;
>  

Reviewed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] media: qcom: iris: add error and status details to diagnostics
  2026-11-06 15:31 ` [PATCH 2/3] media: qcom: iris: add error and status details to diagnostics Dipayaan Roy
@ 2026-11-09  7:25   ` Vishnu Reddy
  0 siblings, 0 replies; 7+ messages in thread
From: Vishnu Reddy @ 2026-11-09  7:25 UTC (permalink / raw)
  To: Dipayaan Roy, linux-media
  Cc: vikash.garodia, dikshita.agarwal, abhinav.kumar, bod, mchehab,
	p.zabel, linux-arm-msm, linux-kernel


On 11/6/2026 9:01 PM, Dipayaan Roy wrote:
> Several Iris error messages identify a failed operation without showing
> the return code or state that caused it, making failures difficult to
> diagnose.
>
> Include available return codes, hardware status, queue positions, and
> packet or session identifiers in these messages. Also report the header
> details when an HFI response fails validation.
>
> Error handling remains unchanged.
>
> Signed-off-by: Dipayaan Roy <dipayaan.roy@oss.qualcomm.com>
> ---
>  drivers/media/platform/qcom/iris/iris_hfi_common.c |  4 ++--
>  .../platform/qcom/iris/iris_hfi_gen1_response.c    |  9 ++++++---
>  .../platform/qcom/iris/iris_hfi_gen2_response.c    |  5 ++++-
>  drivers/media/platform/qcom/iris/iris_hfi_queue.c  | 14 +++++++++----
>  drivers/media/platform/qcom/iris/iris_vb2.c        |  2 +-
>  drivers/media/platform/qcom/iris/iris_vdec.c       |  3 ++-
>  drivers/media/platform/qcom/iris/iris_venc.c       |  3 ++-
>  drivers/media/platform/qcom/iris/iris_vidc.c       |  2 +-
>  drivers/media/platform/qcom/iris/iris_vpu3x.c      | 23 +++++++++++-----------
>  drivers/media/platform/qcom/iris/iris_vpu4x.c      |  6 ++++--
>  drivers/media/platform/qcom/iris/iris_vpu_common.c | 15 ++++++++------
>  11 files changed, 53 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.c b/drivers/media/platform/qcom/iris/iris_hfi_common.c
> index dad906d03fdc..1fd4cecd7956 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_common.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.c
> @@ -138,7 +138,7 @@ int iris_hfi_pm_suspend(struct iris_core *core)
>  	return 0;
>  
>  error:
> -	dev_err(core->dev, "failed to suspend\n");
> +	dev_err(core->dev, "failed to suspend: %d\n", ret);
>  
>  	return ret;
>  }
> @@ -179,7 +179,7 @@ int iris_hfi_pm_resume(struct iris_core *core)
>  err_power_off:
>  	iris_vpu_power_off(core);
>  error:
> -	dev_err(core->dev, "failed to resume\n");
> +	dev_err(core->dev, "failed to resume: %d\n", ret);
>  
>  	return -EBUSY;
>  }
> 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 ffa98139f0eb..1ce7f97d4087 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> @@ -301,7 +301,8 @@ iris_hfi_gen1_sys_get_prop_image_version(struct iris_core *core,
>  	u32 i;
>  
>  	if (req_bytes < IRIS_FW_VERSION_LENGTH - 1 || !pkt->data[0] || pkt->num_properties > 1) {
> -		dev_err(core->dev, "bad packet\n");
> +		dev_err(core->dev, "invalid firmware version packet (size %u, properties %u)\n",
> +			pkt->hdr.size, pkt->num_properties);
>  		return;
>  	}
>  
> @@ -382,7 +383,8 @@ static void iris_hfi_gen1_session_etb_done(struct iris_inst *inst, void *packet)
>  
>  error:
>  	iris_inst_change_state(inst, IRIS_INST_ERROR);
> -	dev_err(inst->core->dev, "error in etb done\n");
> +	dev_err(inst->core->dev, "ETB done without input buffer (session %#x, tag %u)\n",
> +		inst->session_id, pkt->input_tag);
>  }
>  
>  static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
> @@ -530,7 +532,8 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
>  
>  error:
>  	iris_inst_change_state(inst, IRIS_INST_ERROR);
> -	dev_err(core->dev, "error in ftb done\n");
> +	dev_err(core->dev, "FTB done without output buffer (session %#x, tag %u, offset %u)\n",
> +		inst->session_id, output_tag, offset);
>  }
>  
>  static enum iris_buffer_type iris_hfi_gen1_buf_type(struct iris_inst *inst, u32 type)
> 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 f0782c4b1e6e..b82f50458fe1 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
> @@ -980,8 +980,11 @@ static int iris_hfi_gen2_handle_response(struct iris_core *core, void *response)
>  	int ret;
>  
>  	ret = iris_hfi_gen2_validate_hdr_packet(core, hdr);
> -	if (ret)
> +	if (ret) {
> +		dev_err(core->dev, "invalid HFI response (size %u, packets %u): %d\n",
> +			hdr->size, hdr->num_packets, ret);
>  		return iris_hfi_gen2_handle_system_error(core, NULL);
> +	}
>  
>  	if (!hdr->session_id)
>  		return iris_hfi_gen2_handle_system_response(core, hdr);
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c
> index bf6db23b53e2..ef556e54f6f1 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c
> @@ -112,14 +112,18 @@ static int iris_hfi_queue_read(struct iris_iface_q_info *qinfo, void *packet)
>  int iris_hfi_queue_cmd_write_locked(struct iris_core *core, void *pkt, u32 pkt_size)
>  {
>  	struct iris_iface_q_info *q_info = &core->command_queue;
> +	int ret;
>  
>  	if (core->state == IRIS_CORE_ERROR || core->state == IRIS_CORE_DEINIT)
>  		return -EINVAL;
>  
> -	if (!iris_hfi_queue_write(q_info, pkt, pkt_size)) {
> +	ret = iris_hfi_queue_write(q_info, pkt, pkt_size);
> +	if (!ret) {
>  		iris_vpu_raise_interrupt(core);
>  	} else {
> -		dev_err(core->dev, "queue full\n");
> +		dev_err(core->dev, "command queue write failed: %d (size %u, read %u, write %u)\n",
> +			ret, pkt_size, q_info->qhdr->read_idx,
> +			q_info->qhdr->write_idx);
>  		return -ENODATA;
>  	}
>  
> @@ -254,7 +258,8 @@ int iris_hfi_queues_init(struct iris_core *core)
>  						    &core->iface_q_table_daddr,
>  						    GFP_KERNEL, DMA_ATTR_WRITE_COMBINE);
>  	if (!core->iface_q_table_vaddr) {
> -		dev_err(core->dev, "queues alloc and map failed\n");
> +		dev_err(core->dev, "failed to allocate HFI queues (%u bytes)\n",
> +			queue_size);
>  		return -ENOMEM;
>  	}
>  
> @@ -262,7 +267,8 @@ int iris_hfi_queues_init(struct iris_core *core)
>  					  &core->sfr_daddr,
>  					  GFP_KERNEL, DMA_ATTR_WRITE_COMBINE);
>  	if (!core->sfr_vaddr) {
> -		dev_err(core->dev, "sfr alloc and map failed\n");
> +		dev_err(core->dev, "failed to allocate SFR (%u bytes)\n",
> +			(unsigned int)SFR_SIZE);
>  		dma_free_attrs(core->dev, queue_size, core->iface_q_table_vaddr,
>  			       core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE);
>  		return -ENOMEM;
> diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c
> index 8faf709c26c1..b770cd5349b6 100644
> --- a/drivers/media/platform/qcom/iris/iris_vb2.c
> +++ b/drivers/media/platform/qcom/iris/iris_vb2.c
> @@ -135,8 +135,8 @@ int iris_vb2_queue_setup(struct vb2_queue *q,
>  
>  		ret = inst->hfi_session_ops->session_open(inst);
>  		if (ret) {
> +			dev_err(core->dev, "session open failed: %d\n", ret);
>  			ret = -EINVAL;
> -			dev_err(core->dev, "session open failed\n");
>  			goto unlock;
>  		}
>  
> diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
> index 0dd33ff447bb..d359d3716ba1 100644
> --- a/drivers/media/platform/qcom/iris/iris_vdec.c
> +++ b/drivers/media/platform/qcom/iris/iris_vdec.c
> @@ -529,7 +529,8 @@ int iris_vdec_start_cmd(struct iris_inst *inst)
>  			clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
>  		}
>  	} else {
> -		dev_err(inst->core->dev, "start called before receiving last_flag\n");
> +		dev_err(inst->core->dev, "start before last buffer (sub-state %#x)\n",
> +			inst->sub_state);
>  		iris_inst_change_state(inst, IRIS_INST_ERROR);
>  		return -EBUSY;
>  	}
> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
> index 2f2c56bf9122..a7a0f14a78d1 100644
> --- a/drivers/media/platform/qcom/iris/iris_venc.c
> +++ b/drivers/media/platform/qcom/iris/iris_venc.c
> @@ -602,7 +602,8 @@ int iris_venc_start_cmd(struct iris_inst *inst)
>  			clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
>  		}
>  	} else {
> -		dev_err(inst->core->dev, "start called before receiving last_flag\n");
> +		dev_err(inst->core->dev, "start before last buffer (sub-state %#x)\n",
> +			inst->sub_state);
>  		iris_inst_change_state(inst, IRIS_INST_ERROR);
>  		return -EBUSY;
>  	}
> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
> index 05aab6e3005d..80f0a56712bf 100644
> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
> @@ -168,7 +168,7 @@ int iris_open(struct file *filp)
>  
>  	ret = iris_core_init(core);
>  	if (ret) {
> -		dev_err(core->dev, "core init failed\n");
> +		dev_err(core->dev, "core init failed: %d\n", ret);
>  		pm_runtime_put_sync(core->dev);
>  		return ret;
>  	}
> diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c
> index c3b760730c98..cd22534c0904 100644
> --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c
> +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c
> @@ -17,14 +17,12 @@
>  #define NOC_HALT				BIT(0)
>  #define AON_WRAPPER_SPARE			(AON_BASE_OFFS + 0x28)
>  
> -static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core)
> +static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core,
> +					  u32 *power_status)
>  {
> -	u32 value, pwr_status;
> +	*power_status = readl(core->reg_base + WRAPPER_CORE_POWER_STATUS);
>  
> -	value = readl(core->reg_base + WRAPPER_CORE_POWER_STATUS);
> -	pwr_status = value & BIT(1);
> -
> -	return pwr_status ? false : true;
> +	return !(*power_status & BIT(1));
>  }
>  
>  static void iris_vpu3_power_off_hardware(struct iris_core *core)
> @@ -32,10 +30,11 @@ static void iris_vpu3_power_off_hardware(struct iris_core *core)
>  	u32 reg_val = 0, value, i;
>  	int ret;
>  
> -	if (iris_vpu3x_hw_power_collapsed(core))
> +	if (iris_vpu3x_hw_power_collapsed(core, &value))
>  		goto disable_power;
>  
> -	dev_err(core->dev, "video hw is power on\n");
> +	dev_err(core->dev, "video hardware still powered on (status %#x)\n",
> +		value);
>  
>  	value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG);
>  	if (value)
> @@ -78,10 +77,11 @@ static void iris_vpu33_power_off_hardware(struct iris_core *core)
>  	u32 count = 0;
>  	int ret;
>  
> -	if (iris_vpu3x_hw_power_collapsed(core))
> +	if (iris_vpu3x_hw_power_collapsed(core, &value))
>  		goto disable_power;
>  
> -	dev_err(core->dev, "video hw is power on\n");
> +	dev_err(core->dev, "video hardware still powered on (status %#x)\n",
> +		value);
>  
>  	value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG);
>  	if (value)
> @@ -116,7 +116,8 @@ static void iris_vpu33_power_off_hardware(struct iris_core *core)
>  	} while (++count < 1000);
>  
>  	if (!handshake_done && handshake_busy)
> -		dev_err(core->dev, "LPI handshake timeout\n");
> +		dev_err(core->dev, "LPI handshake timeout (status %#x)\n",
> +			value);
>  
>  	ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS,
>  				 reg_val, reg_val & BIT(0), 200, 2000);
> diff --git a/drivers/media/platform/qcom/iris/iris_vpu4x.c b/drivers/media/platform/qcom/iris/iris_vpu4x.c
> index 90ccdc0d2a07..0369f2497f76 100644
> --- a/drivers/media/platform/qcom/iris/iris_vpu4x.c
> +++ b/drivers/media/platform/qcom/iris/iris_vpu4x.c
> @@ -117,7 +117,8 @@ static void iris_vpu4x_power_off_apv(struct iris_core *core)
>  	} while (++count < 1000);
>  
>  	if (!handshake_done && handshake_busy)
> -		dev_err(core->dev, "LPI handshake timeout\n");
> +		dev_err(core->dev, "APV LPI handshake timeout (status %#x)\n",
> +			value);
>  
>  	writel(0x080200, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ);
>  	ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK,
> @@ -314,7 +315,8 @@ static void iris_vpu4x_power_off_hardware(struct iris_core *core)
>  	} while (++count < 1000);
>  
>  	if (!handshake_done && handshake_busy)
> -		dev_err(core->dev, "LPI handshake timeout\n");
> +		dev_err(core->dev, "hardware LPI handshake timeout (status %#x)\n",
> +			value);
>  
>  	writel(MVP_NOC_RESET_REQ_MASK, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ);
>  	ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK,
> diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c
> index 243bd845349f..4a56856a8df5 100644
> --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c
> +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c
> @@ -83,7 +83,8 @@ int iris_vpu_boot_firmware(struct iris_core *core)
>  	while (!ctrl_status && count < max_tries) {
>  		ctrl_status = readl(core->reg_base + CTRL_STATUS);
>  		if ((ctrl_status & CTRL_ERROR_STATUS__M) == 0x4) {
> -			dev_err(core->dev, "invalid setting for uc_region\n");
> +			dev_err(core->dev, "invalid UC region setting (CTRL_STATUS %#x)\n",
> +				ctrl_status);
>  			return -EINVAL;
>  		}
>  
> @@ -92,7 +93,8 @@ int iris_vpu_boot_firmware(struct iris_core *core)
>  	}
>  
>  	if (count >= max_tries) {
> -		dev_err(core->dev, "error booting up iris firmware\n");
> +		dev_err(core->dev, "firmware boot timed out (CTRL_STATUS %#x)\n",
> +			ctrl_status);
>  		return -ETIME;
>  	}
>  
> @@ -128,7 +130,8 @@ int iris_vpu_watchdog(struct iris_core *core, u32 intr_status)
>  	u32 wd_intr_mask = core->iris_platform_data->wd_intr_mask;
>  
>  	if (intr_status & wd_intr_mask) {
> -		dev_err(core->dev, "received watchdog interrupt\n");
> +		dev_err(core->dev, "received watchdog interrupt (status %#x)\n",
> +			intr_status);
>  		return -ETIME;
>  	}
>  
> @@ -172,7 +175,7 @@ int iris_vpu_prepare_pc(struct iris_core *core)
>  	ctrl_status = readl(core->reg_base + CTRL_STATUS);
>  	wfi_status = readl(core->reg_base + WRAPPER_TZ_CPU_STATUS);
>  	wfi_status &= BIT(0);
> -	dev_err(core->dev, "skip power collapse, wfi=%#x, idle=%#x, pcr=%#x, ctrl=%#x)\n",
> +	dev_err(core->dev, "skip power collapse (wfi=%#x, idle=%#x, pcr=%#x, ctrl=%#x)\n",
>  		wfi_status, idle_status, pc_ready, ctrl_status);
>  
>  	return -EAGAIN;
> @@ -365,7 +368,7 @@ int iris_vpu35_vpu4x_power_off_controller(struct iris_core *core)
>  	} while (++count < 1000);
>  
>  	if (!handshake_done && handshake_busy)
> -		dev_err(core->dev, "LPI handshake timeout\n");
> +		dev_err(core->dev, "LPI handshake timeout (status %#x)\n", val);
>  
>  	ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS,
>  				 val, val & BIT(0), 200, 2000);
> @@ -530,7 +533,7 @@ int iris_vpu_power_on(struct iris_core *core)
>  err_unvote_icc:
>  	iris_unset_icc_bw(core);
>  err:
> -	dev_err(core->dev, "power on failed\n");
> +	dev_err(core->dev, "power on failed: %d\n", ret);
>  
>  	return ret;
>  }

Reviewed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/3] media: qcom: iris: Improve diagnostics for system and session failures
  2026-11-06 15:31 ` [PATCH 3/3] media: qcom: iris: Improve diagnostics for system and session failures Dipayaan Roy
@ 2026-11-09  7:53   ` Vishnu Reddy
  0 siblings, 0 replies; 7+ messages in thread
From: Vishnu Reddy @ 2026-11-09  7:53 UTC (permalink / raw)
  To: Dipayaan Roy, linux-media
  Cc: vikash.garodia, dikshita.agarwal, abhinav.kumar, bod, mchehab,
	p.zabel, linux-arm-msm, linux-kernel


On 11/6/2026 9:01 PM, Dipayaan Roy wrote:
> Log system and session response timeouts, firmware-reported failures,
> and failed recovery attempts so the cause of an error is visible.
>
> Add debug messages for unknown sessions, invalid state transitions,
> and successful recovery. Avoid a redundant system init timeout message
> after firmware reports an error, and rate-limit Gen2 session response
> errors.
>
> Signed-off-by: Dipayaan Roy <dipayaan.roy@oss.qualcomm.com>
> ---
>  drivers/media/platform/qcom/iris/iris_core.c              |  2 ++
>  drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c |  8 +++++++-
>  drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c | 13 ++++++++++++-
>  drivers/media/platform/qcom/iris/iris_probe.c             |  8 +++++++-
>  drivers/media/platform/qcom/iris/iris_state.c             |  5 ++++-
>  drivers/media/platform/qcom/iris/iris_utils.c             |  2 ++
>  6 files changed, 34 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c
> index d558475986ff..4224feaf1caf 100644
> --- a/drivers/media/platform/qcom/iris/iris_core.c
> +++ b/drivers/media/platform/qcom/iris/iris_core.c
> @@ -43,6 +43,8 @@ static int iris_wait_for_system_response(struct iris_core *core)
>  	ret = wait_for_completion_timeout(&core->core_init_done,
>  					  msecs_to_jiffies(HW_RESPONSE_TIMEOUT_VALUE));
>  	if (!ret) {
> +		if (core->state != IRIS_CORE_ERROR)
> +			dev_err(core->dev, "system init response timed out\n");
>  		core->state = IRIS_CORE_ERROR;
>  		return -ETIMEDOUT;
>  	}
> 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 1ce7f97d4087..5c411e69e5fd 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> @@ -284,6 +284,8 @@ static void iris_hfi_gen1_sys_init_done(struct iris_core *core, void *packet)
>  	struct hfi_msg_sys_init_done_pkt *pkt = packet;
>  
>  	if (pkt->error_type != HFI_ERR_NONE) {
> +		dev_err(core->dev, "system init failed (HFI error %#x)\n",
> +			pkt->error_type);
>  		core->state = IRIS_CORE_ERROR;
>  		return;
>  	}
> @@ -740,8 +742,12 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response
>  			struct hfi_msg_session_hdr_pkt *shdr;
>  
>  			shdr = (struct hfi_msg_session_hdr_pkt *)hdr;
> -			if (shdr->error_type != HFI_ERR_NONE)
> +			if (shdr->error_type != HFI_ERR_NONE) {
> +				dev_err(dev, "session %#x response %#x failed (HFI error %#x)\n",
> +					inst->session_id, hdr->pkt_type,
> +					shdr->error_type);
>  				iris_inst_change_state(inst, IRIS_INST_ERROR);
> +			}
>  
>  			if (pkt_info->pkt == HFI_MSG_SESSION_FLUSH) {
>  				if (!(--inst->flush_responses_pending))
> 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 b82f50458fe1..d5b4b27e0549 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
> @@ -296,6 +296,8 @@ static int iris_hfi_gen2_handle_system_init(struct iris_core *core,
>  					    struct iris_hfi_packet *pkt)
>  {
>  	if (!(pkt->flags & HFI_FW_FLAGS_SUCCESS)) {
> +		dev_err(core->dev, "system command %#x failed (flags %#x)\n",
> +			pkt->type, pkt->flags);
>  		core->state = IRIS_CORE_ERROR;
>  		return 0;
>  	}
> @@ -929,8 +931,11 @@ static int iris_hfi_gen2_handle_session_response(struct iris_core *core,
>  	};
>  
>  	inst = iris_get_instance(core, hdr->session_id);
> -	if (!inst)
> +	if (!inst) {
> +		dev_dbg(core->dev, "response for unknown session %#x\n",
> +			hdr->session_id);
>  		return -EINVAL;
> +	}
>  
>  	mutex_lock(&inst->lock);
>  	inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
> @@ -958,6 +963,12 @@ static int iris_hfi_gen2_handle_session_response(struct iris_core *core,
>  			if (packet->type > range[i].begin && packet->type < range[i].end) {
>  				dequeue |= (packet->type == HFI_CMD_BUFFER);
>  				ret = range[i].handle(inst, packet);
> +				if (ret && !(packet->flags &
> +					     HFI_FW_FLAGS_SESSION_ERROR))
> +					dev_err_ratelimited(core->dev,
> +							    "session %#x response %#x failed: %d\n",
> +							    inst->session_id,
> +							    packet->type, ret);
>  				if (ret)
>  					iris_inst_change_state(inst, IRIS_INST_ERROR);
>  			}
> diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
> index dd48fa750013..9cefe090466b 100644
> --- a/drivers/media/platform/qcom/iris/iris_probe.c
> +++ b/drivers/media/platform/qcom/iris/iris_probe.c
> @@ -306,9 +306,15 @@ static void iris_sys_error_handler(struct work_struct *work)
>  {
>  	struct iris_core *core =
>  			container_of(work, struct iris_core, sys_error_handler.work);
> +	int ret;
>  
>  	iris_core_deinit(core);
> -	iris_core_init(core);
> +	ret = iris_core_init(core);
> +	if (ret)
> +		dev_err(core->dev, "failed to recover from system error: %d\n",
> +			ret);
> +	else
> +		dev_dbg(core->dev, "recovered from system error\n");
>  }
>  
>  static int iris_probe(struct platform_device *pdev)
> diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c
> index 5552725c614e..bcb138ccf08c 100644
> --- a/drivers/media/platform/qcom/iris/iris_state.c
> +++ b/drivers/media/platform/qcom/iris/iris_state.c
> @@ -56,8 +56,11 @@ int iris_inst_change_state(struct iris_inst *inst,
>  	if (request_state == IRIS_INST_ERROR)
>  		goto change_state;
>  
> -	if (!iris_allow_inst_state_change(inst, request_state))
> +	if (!iris_allow_inst_state_change(inst, request_state)) {
> +		dev_dbg(inst->core->dev, "session %#x invalid state change %x -> %x\n",
> +			inst->session_id, inst->state, request_state);
>  		return -EINVAL;
> +	}
>  
>  change_state:
>  	dev_dbg(inst->core->dev, "state changed from %x to %x\n",
> diff --git a/drivers/media/platform/qcom/iris/iris_utils.c b/drivers/media/platform/qcom/iris/iris_utils.c
> index 1096cc4b01c3..5ca4d8e0836b 100644
> --- a/drivers/media/platform/qcom/iris/iris_utils.c
> +++ b/drivers/media/platform/qcom/iris/iris_utils.c
> @@ -78,6 +78,8 @@ int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush)
>  	ret = wait_for_completion_timeout(done, msecs_to_jiffies(HW_RESPONSE_TIMEOUT_VALUE));
>  	mutex_lock(&inst->lock);
>  	if (!ret) {
> +		dev_err(inst->core->dev, "session %#x %s response timed out\n",
> +			inst->session_id, is_flush ? "flush" : "command");
>  		iris_inst_change_state(inst, IRIS_INST_ERROR);
>  		return -ETIMEDOUT;
>  	}

Reviewed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-11-09  7:53 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-06 15:31 [PATCH 0/3] media: qcom: iris: improve error diagnostics Dipayaan Roy
2026-11-06 15:31 ` [PATCH 1/3] media: qcom: iris: improve probe error reporting Dipayaan Roy
2026-11-09  7:17   ` Vishnu Reddy
2026-11-06 15:31 ` [PATCH 2/3] media: qcom: iris: add error and status details to diagnostics Dipayaan Roy
2026-11-09  7:25   ` Vishnu Reddy
2026-11-06 15:31 ` [PATCH 3/3] media: qcom: iris: Improve diagnostics for system and session failures Dipayaan Roy
2026-11-09  7:53   ` Vishnu Reddy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®