diff mbox series

[v3,09/29] media: iris: introduce Host firmware interface with necessary hooks

Message ID 20240827-iris_v3-v3-9-c5fdbbe65e70@quicinc.com (mailing list archive)
State Not Applicable
Headers show
Series Qualcomm iris video decoder driver | expand

Commit Message

Dikshita Agarwal via B4 Relay Aug. 27, 2024, 10:05 a.m. UTC
From: Dikshita Agarwal <quic_dikshita@quicinc.com>

Host firmware interface (HFI) is well defined set of interfaces
for communication between host driver and firmware.
The command and responses are exchanged in form of packets.
One or multiple packets are grouped under packet header.
Each packet has packet type which describes the specific HFI
and payload which holds the corresponding value for that HFI.

Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
 drivers/media/platform/qcom/iris/Makefile          |   5 +
 drivers/media/platform/qcom/iris/iris_core.c       |  26 ++-
 drivers/media/platform/qcom/iris/iris_core.h       |  20 ++
 drivers/media/platform/qcom/iris/iris_hfi_common.c |  56 +++++
 drivers/media/platform/qcom/iris/iris_hfi_common.h |  60 ++++++
 drivers/media/platform/qcom/iris/iris_hfi_gen1.h   |   3 +
 .../platform/qcom/iris/iris_hfi_gen1_command.c     |  61 ++++++
 .../platform/qcom/iris/iris_hfi_gen1_defines.h     |  94 +++++++++
 .../platform/qcom/iris/iris_hfi_gen1_response.c    | 174 ++++++++++++++++
 drivers/media/platform/qcom/iris/iris_hfi_gen2.h   |   4 +
 .../platform/qcom/iris/iris_hfi_gen2_command.c     |  72 +++++++
 .../platform/qcom/iris/iris_hfi_gen2_defines.h     |  46 +++++
 .../platform/qcom/iris/iris_hfi_gen2_packet.c      | 164 +++++++++++++++
 .../platform/qcom/iris/iris_hfi_gen2_packet.h      |  69 +++++++
 .../platform/qcom/iris/iris_hfi_gen2_response.c    | 229 +++++++++++++++++++++
 drivers/media/platform/qcom/iris/iris_hfi_queue.c  | 201 ++++++++++++++++++
 drivers/media/platform/qcom/iris/iris_hfi_queue.h  |   5 +
 .../platform/qcom/iris/iris_platform_common.h      |  15 ++
 .../platform/qcom/iris/iris_platform_sm8250.c      |   3 +
 .../platform/qcom/iris/iris_platform_sm8550.c      |  14 ++
 drivers/media/platform/qcom/iris/iris_probe.c      |  40 ++++
 drivers/media/platform/qcom/iris/iris_state.c      |  15 ++
 drivers/media/platform/qcom/iris/iris_state.h      |   4 +
 drivers/media/platform/qcom/iris/iris_vpu_common.c |  42 ++++
 drivers/media/platform/qcom/iris/iris_vpu_common.h |   3 +
 25 files changed, 1424 insertions(+), 1 deletion(-)

Comments

Bryan O'Donoghue Sept. 5, 2024, 12:36 p.m. UTC | #1
On 27/08/2024 11:05, Dikshita Agarwal via B4 Relay wrote:
> +enum hfi_packet_port_type {
> +	HFI_PORT_NONE		= 0x00000000,
> +	HFI_PORT_BITSTREAM	= 0x00000001,
> +	HFI_PORT_RAW		= 0x00000002,
> +};
> +
> +enum hfi_packet_payload_info {
> +	HFI_PAYLOAD_NONE	= 0x00000000,
> +	HFI_PAYLOAD_U32		= 0x00000001,
> +	HFI_PAYLOAD_S32		= 0x00000002,
> +	HFI_PAYLOAD_U64		= 0x00000003,
> +	HFI_PAYLOAD_S64		= 0x00000004,
> +	HFI_PAYLOAD_STRUCTURE	= 0x00000005,
> +	HFI_PAYLOAD_BLOB	= 0x00000006,
> +	HFI_PAYLOAD_STRING	= 0x00000007,
> +	HFI_PAYLOAD_Q16		= 0x00000008,
> +	HFI_PAYLOAD_U32_ENUM	= 0x00000009,
> +	HFI_PAYLOAD_32_PACKED	= 0x0000000a,
> +	HFI_PAYLOAD_U32_ARRAY	= 0x0000000b,
> +	HFI_PAYLOAD_S32_ARRAY	= 0x0000000c,
> +	HFI_PAYLOAD_64_PACKED	= 0x0000000d,
> +};
> +
> +enum hfi_packet_host_flags {
> +	HFI_HOST_FLAGS_NONE			= 0x00000000,

Are these NONE flags used/necessary ?

If they are dead enum values, please drop in the next version.

---
bod
Bryan O'Donoghue Sept. 5, 2024, 1:10 p.m. UTC | #2
On 27/08/2024 11:05, Dikshita Agarwal via B4 Relay wrote:
> From: Dikshita Agarwal <quic_dikshita@quicinc.com>
> 
> Host firmware interface (HFI) is well defined set of interfaces
> for communication between host driver and firmware.
> The command and responses are exchanged in form of packets.
> One or multiple packets are grouped under packet header.
> Each packet has packet type which describes the specific HFI
> and payload which holds the corresponding value for that HFI.
> 
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
>   drivers/media/platform/qcom/iris/Makefile          |   5 +
>   drivers/media/platform/qcom/iris/iris_core.c       |  26 ++-
>   drivers/media/platform/qcom/iris/iris_core.h       |  20 ++
>   drivers/media/platform/qcom/iris/iris_hfi_common.c |  56 +++++
>   drivers/media/platform/qcom/iris/iris_hfi_common.h |  60 ++++++
>   drivers/media/platform/qcom/iris/iris_hfi_gen1.h   |   3 +
>   .../platform/qcom/iris/iris_hfi_gen1_command.c     |  61 ++++++
>   .../platform/qcom/iris/iris_hfi_gen1_defines.h     |  94 +++++++++
>   .../platform/qcom/iris/iris_hfi_gen1_response.c    | 174 ++++++++++++++++
>   drivers/media/platform/qcom/iris/iris_hfi_gen2.h   |   4 +
>   .../platform/qcom/iris/iris_hfi_gen2_command.c     |  72 +++++++
>   .../platform/qcom/iris/iris_hfi_gen2_defines.h     |  46 +++++
>   .../platform/qcom/iris/iris_hfi_gen2_packet.c      | 164 +++++++++++++++
>   .../platform/qcom/iris/iris_hfi_gen2_packet.h      |  69 +++++++
>   .../platform/qcom/iris/iris_hfi_gen2_response.c    | 229 +++++++++++++++++++++
>   drivers/media/platform/qcom/iris/iris_hfi_queue.c  | 201 ++++++++++++++++++
>   drivers/media/platform/qcom/iris/iris_hfi_queue.h  |   5 +
>   .../platform/qcom/iris/iris_platform_common.h      |  15 ++
>   .../platform/qcom/iris/iris_platform_sm8250.c      |   3 +
>   .../platform/qcom/iris/iris_platform_sm8550.c      |  14 ++
>   drivers/media/platform/qcom/iris/iris_probe.c      |  40 ++++
>   drivers/media/platform/qcom/iris/iris_state.c      |  15 ++
>   drivers/media/platform/qcom/iris/iris_state.h      |   4 +
>   drivers/media/platform/qcom/iris/iris_vpu_common.c |  42 ++++
>   drivers/media/platform/qcom/iris/iris_vpu_common.h |   3 +
>   25 files changed, 1424 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile
> index 95f4e92fe085..d1f0b933df3d 100644
> --- a/drivers/media/platform/qcom/iris/Makefile
> +++ b/drivers/media/platform/qcom/iris/Makefile
> @@ -1,12 +1,17 @@
>   iris-objs += iris_core.o \
>                iris_firmware.o \
> +             iris_hfi_common.o \
>                iris_hfi_gen1_command.o \
> +             iris_hfi_gen1_response.o \
>                iris_hfi_gen2_command.o \
> +             iris_hfi_gen2_packet.o \
> +             iris_hfi_gen2_response.o \
>                iris_hfi_queue.o \
>                iris_platform_sm8250.o \
>                iris_platform_sm8550.o \
>                iris_probe.o \
>                iris_resources.o \
> +             iris_state.o \
>                iris_vidc.o \
>                iris_vpu_common.o \
>   
> diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c
> index 5ad66ac113ae..92458d7f1e36 100644
> --- a/drivers/media/platform/qcom/iris/iris_core.c
> +++ b/drivers/media/platform/qcom/iris/iris_core.c
> @@ -17,6 +17,26 @@ void iris_core_deinit(struct iris_core *core)
>   	mutex_unlock(&core->lock);
>   }
>   
> +static int iris_wait_for_system_response(struct iris_core *core)
> +{
> +	u32 hw_response_timeout_val;
> +	int ret;
> +
> +	if (core->state == IRIS_CORE_ERROR)
> +		return -EIO;
> +
> +	hw_response_timeout_val = core->iris_platform_data->hw_response_timeout;
> +
> +	ret = wait_for_completion_timeout(&core->core_init_done,
> +					  msecs_to_jiffies(hw_response_timeout_val));
> +	if (!ret) {
> +		iris_change_core_state(core, IRIS_CORE_ERROR);
> +		return -ETIMEDOUT;
> +	}
> +
> +	return 0;
> +}
> +
>   int iris_core_init(struct iris_core *core)
>   {
>   	int ret;
> @@ -44,9 +64,13 @@ int iris_core_init(struct iris_core *core)
>   	if (ret)
>   		goto error_unload_fw;
>   
> +	ret = iris_hfi_core_init(core);
> +	if (ret)
> +		goto error_unload_fw;
> +
>   	mutex_unlock(&core->lock);
>   
> -	return 0;
> +	return iris_wait_for_system_response(core);
>   
>   error_unload_fw:
>   	iris_fw_unload(core);
> diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h
> index 13c5932f9110..409f9822807d 100644
> --- a/drivers/media/platform/qcom/iris/iris_core.h
> +++ b/drivers/media/platform/qcom/iris/iris_core.h
> @@ -9,11 +9,15 @@
>   #include <linux/types.h>
>   #include <media/v4l2-device.h>
>   
> +#include "iris_hfi_common.h"
>   #include "iris_hfi_queue.h"
>   #include "iris_platform_common.h"
>   #include "iris_resources.h"
>   #include "iris_state.h"
>   
> +#define IRIS_FW_VERSION_LENGTH		128
> +#define IFACEQ_CORE_PKT_SIZE		(1024 * 4)
> +
>   /**
>    * struct iris_core - holds core parameters valid for all instances
>    *
> @@ -40,6 +44,14 @@
>    * @message_queue: shared interface queue to receive responses from firmware
>    * @debug_queue: shared interface queue to receive debug info from firmware
>    * @lock: a lock for this strucure
> + * @response_packet: a pointer to response packet from fw to driver
> + * @header_id: id of packet header
> + * @packet_id: id of packet
> + * @hfi_ops: iris hfi command ops
> + * @hfi_response_ops: iris hfi response ops
> + * @core_init_done: structure of signal completion for system response
> + * @intr_status: interrupt status
> + * @sys_error_handler: a delayed work for handling system fatal error
>    */
>   
>   struct iris_core {
> @@ -66,6 +78,14 @@ struct iris_core {
>   	struct iris_iface_q_info		message_queue;
>   	struct iris_iface_q_info		debug_queue;
>   	struct mutex				lock; /* lock for core related operations */
> +	u8					*response_packet;
> +	u32					header_id;
> +	u32					packet_id;
> +	const struct iris_hfi_command_ops	*hfi_ops;
> +	const struct iris_hfi_response_ops	*hfi_response_ops;
> +	struct completion			core_init_done;
> +	u32					intr_status;
> +	struct delayed_work			sys_error_handler;
>   };
>   
>   int iris_core_init(struct iris_core *core);
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.c b/drivers/media/platform/qcom/iris/iris_hfi_common.c
> new file mode 100644
> index 000000000000..a5a28029d8d1
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.c
> @@ -0,0 +1,56 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include "iris_core.h"
> +#include "iris_hfi_common.h"
> +#include "iris_vpu_common.h"
> +
> +int iris_hfi_core_init(struct iris_core *core)
> +{
> +	const struct iris_hfi_command_ops *hfi_ops = core->hfi_ops;
> +	int ret;
> +
> +	ret = hfi_ops->sys_init(core);
> +	if (ret)
> +		return ret;
> +
> +	ret = hfi_ops->sys_image_version(core);
> +	if (ret)
> +		return ret;
> +
> +	return hfi_ops->sys_interframe_powercollapse(core);
> +}
> +
> +irqreturn_t iris_hfi_isr(int irq, void *data)
> +{
> +	disable_irq_nosync(irq);
> +
> +	return IRQ_WAKE_THREAD;
> +}
> +
> +irqreturn_t iris_hfi_isr_handler(int irq, void *data)
> +{
> +	struct iris_core *core = data;
> +
> +	if (!core)
> +		return IRQ_NONE;
> +
> +	mutex_lock(&core->lock);
> +	if (core->state != IRIS_CORE_INIT) {
> +		mutex_unlock(&core->lock);
> +		goto exit;
> +	}
> +
> +	iris_vpu_clear_interrupt(core);
> +	mutex_unlock(&core->lock);
> +
> +	core->hfi_response_ops->hfi_response_handler(core);
> +
> +exit:
> +	if (!iris_vpu_watchdog(core, core->intr_status))
> +		enable_irq(irq);
> +
> +	return IRQ_HANDLED;
> +}
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h
> new file mode 100644
> index 000000000000..c3d5b899cf60
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h
> @@ -0,0 +1,60 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#ifndef _IRIS_HFI_COMMON_H_
> +#define _IRIS_HFI_COMMON_H_
> +
> +#include <linux/types.h>
> +#include <media/v4l2-device.h>
> +
> +struct iris_core;
> +
> +enum hfi_packet_port_type {
> +	HFI_PORT_NONE		= 0x00000000,
> +	HFI_PORT_BITSTREAM	= 0x00000001,
> +	HFI_PORT_RAW		= 0x00000002,
> +};
> +
> +enum hfi_packet_payload_info {
> +	HFI_PAYLOAD_NONE	= 0x00000000,
> +	HFI_PAYLOAD_U32		= 0x00000001,
> +	HFI_PAYLOAD_S32		= 0x00000002,
> +	HFI_PAYLOAD_U64		= 0x00000003,
> +	HFI_PAYLOAD_S64		= 0x00000004,
> +	HFI_PAYLOAD_STRUCTURE	= 0x00000005,
> +	HFI_PAYLOAD_BLOB	= 0x00000006,
> +	HFI_PAYLOAD_STRING	= 0x00000007,
> +	HFI_PAYLOAD_Q16		= 0x00000008,
> +	HFI_PAYLOAD_U32_ENUM	= 0x00000009,
> +	HFI_PAYLOAD_32_PACKED	= 0x0000000a,
> +	HFI_PAYLOAD_U32_ARRAY	= 0x0000000b,
> +	HFI_PAYLOAD_S32_ARRAY	= 0x0000000c,
> +	HFI_PAYLOAD_64_PACKED	= 0x0000000d,
> +};
> +
> +enum hfi_packet_host_flags {
> +	HFI_HOST_FLAGS_NONE			= 0x00000000,
> +	HFI_HOST_FLAGS_INTR_REQUIRED		= 0x00000001,
> +	HFI_HOST_FLAGS_RESPONSE_REQUIRED	= 0x00000002,
> +	HFI_HOST_FLAGS_NON_DISCARDABLE		= 0x00000004,
> +	HFI_HOST_FLAGS_GET_PROPERTY		= 0x00000008,
> +};
> +
> +struct iris_hfi_command_ops {
> +	int (*sys_init)(struct iris_core *core);
> +	int (*sys_image_version)(struct iris_core *core);
> +	int (*sys_interframe_powercollapse)(struct iris_core *core);
> +};
> +
> +struct iris_hfi_response_ops {
> +	void (*hfi_response_handler)(struct iris_core *core);
> +};
> +
> +int iris_hfi_core_init(struct iris_core *core);
> +
> +irqreturn_t iris_hfi_isr(int irq, void *data);
> +irqreturn_t iris_hfi_isr_handler(int irq, void *data);
> +
> +#endif
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1.h
> index b02f629a9cdc..15edbb359c71 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1.h
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1.h
> @@ -6,8 +6,11 @@
>   #ifndef _IRIS_HFI_GEN1_H_
>   #define _IRIS_HFI_GEN1_H_
>   
> +struct iris_core;
>   struct iris_inst;
>   
> +void iris_hfi_gen1_command_ops_init(struct iris_core *core);
> +void iris_hfi_gen1_response_ops_init(struct iris_core *core);
>   struct iris_inst *iris_hfi_gen1_get_instance(void);
>   
>   #endif
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> index 20c68f4ffb72..8f045ef56163 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> @@ -4,8 +4,69 @@
>    */
>   
>   #include "iris_hfi_gen1.h"
> +#include "iris_hfi_gen1_defines.h"
>   #include "iris_instance.h"
>   
> +static int iris_hfi_gen1_sys_init(struct iris_core *core)
> +{
> +	struct hfi_sys_init_pkt sys_init_pkt;
> +
> +	sys_init_pkt.hdr.size = sizeof(sys_init_pkt);
> +	sys_init_pkt.hdr.pkt_type = HFI_CMD_SYS_INIT;
> +	sys_init_pkt.arch_type = HFI_VIDEO_ARCH_OX;
> +
> +	return iris_hfi_queue_cmd_write_locked(core, &sys_init_pkt, sys_init_pkt.hdr.size);
> +}
> +
> +static int iris_hfi_gen1_sys_image_version(struct iris_core *core)
> +{
> +	struct hfi_sys_get_property_pkt packet;
> +
> +	packet.hdr.size = sizeof(packet);
> +	packet.hdr.pkt_type = HFI_CMD_SYS_GET_PROPERTY;
> +	packet.num_properties = 1;
> +	packet.data = HFI_PROPERTY_SYS_IMAGE_VERSION;
> +
> +	return iris_hfi_queue_cmd_write_locked(core, &packet, packet.hdr.size);
> +}
> +
> +static int iris_hfi_gen1_sys_interframe_powercollapse(struct iris_core *core)
> +{
> +	struct hfi_sys_set_property_pkt *pkt;
> +	struct hfi_enable *hfi;
> +	u32 packet_size;
> +	u32 ret;
> +
> +	packet_size = struct_size(pkt, data, 1) + sizeof(*hfi);
> +	pkt = kzalloc(packet_size, GFP_KERNEL);
> +	if (!pkt)
> +		return -ENOMEM;
> +
> +	hfi = (struct hfi_enable *)&pkt->data[1];
> +
> +	pkt->hdr.size = packet_size;
> +	pkt->hdr.pkt_type = HFI_CMD_SYS_SET_PROPERTY;
> +	pkt->num_properties = 1;
> +	pkt->data[0] = HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL;
> +	hfi->enable = true;
> +
> +	ret = iris_hfi_queue_cmd_write_locked(core, pkt, pkt->hdr.size);
> +	kfree(pkt);
> +
> +	return ret;
> +}
> +
> +static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = {
> +	.sys_init = iris_hfi_gen1_sys_init,
> +	.sys_image_version = iris_hfi_gen1_sys_image_version,
> +	.sys_interframe_powercollapse = iris_hfi_gen1_sys_interframe_powercollapse,
> +};
> +
> +void iris_hfi_gen1_command_ops_init(struct iris_core *core)
> +{
> +	core->hfi_ops = &iris_hfi_gen1_command_ops;
> +}
> +
>   struct iris_inst *iris_hfi_gen1_get_instance(void)
>   {
>   	return kzalloc(sizeof(struct iris_inst), GFP_KERNEL);
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
> new file mode 100644
> index 000000000000..5c07d6a29863
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
> @@ -0,0 +1,94 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#ifndef _IRIS_HFI_GEN1_DEFINES_H_
> +#define _IRIS_HFI_GEN1_DEFINES_H_
> +
> +#include <linux/types.h>
> +
> +#define HFI_VIDEO_ARCH_OX				0x1
> +#define HFI_ERR_NONE					0x0
> +
> +#define HFI_CMD_SYS_INIT				0x10001
> +#define HFI_CMD_SYS_SET_PROPERTY			0x10005
> +#define HFI_CMD_SYS_GET_PROPERTY			0x10006
> +
> +#define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL		0x5
> +#define HFI_PROPERTY_SYS_IMAGE_VERSION			0x6
> +
> +#define HFI_EVENT_SYS_ERROR				0x1
> +
> +#define HFI_MSG_SYS_INIT				0x20001
> +#define HFI_MSG_SYS_COV					0x20009
> +#define HFI_MSG_SYS_PROPERTY_INFO			0x2000a
> +
> +#define HFI_MSG_EVENT_NOTIFY				0x21001
> +
> +struct hfi_pkt_hdr {
> +	u32 size;
> +	u32 pkt_type;
> +};
> +
> +struct hfi_sys_init_pkt {
> +	struct hfi_pkt_hdr hdr;
> +	u32 arch_type;
> +};
> +
> +struct hfi_sys_set_property_pkt {
> +	struct hfi_pkt_hdr hdr;
> +	u32 num_properties;
> +	u32 data[];
> +};
> +
> +struct hfi_sys_get_property_pkt {
> +	struct hfi_pkt_hdr hdr;
> +	u32 num_properties;
> +	u32 data;
> +};
> +
> +struct hfi_msg_event_notify_pkt {
> +	struct hfi_pkt_hdr hdr;
> +	u32 event_id;
> +	u32 event_data1;
> +	u32 event_data2;
> +	u32 ext_event_data[];
> +};
> +
> +struct hfi_msg_sys_init_done_pkt {
> +	struct hfi_pkt_hdr hdr;
> +	u32 error_type;
> +	u32 num_properties;
> +	u32 data[];
> +};
> +
> +struct hfi_msg_sys_property_info_pkt {
> +	struct hfi_pkt_hdr hdr;
> +	u32 num_properties;
> +	u32 property;
> +	u8 data[];
> +};
> +
> +struct hfi_enable {
> +	u32 enable;
> +};
> +
> +struct hfi_msg_sys_debug_pkt {
> +	struct hfi_pkt_hdr hdr;
> +	u32 msg_type;
> +	u32 msg_size;
> +	u32 time_stamp_hi;
> +	u32 time_stamp_lo;
> +	u8 msg_data[];
> +};
> +
> +struct hfi_msg_sys_coverage_pkt {
> +	struct hfi_pkt_hdr hdr;
> +	u32 msg_size;
> +	u32 time_stamp_hi;
> +	u32 time_stamp_lo;
> +	u8 msg_data[];
> +};
> +
> +#endif
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> new file mode 100644
> index 000000000000..3eb2ce99c614
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> @@ -0,0 +1,174 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include "iris_hfi_gen1.h"
> +#include "iris_hfi_gen1_defines.h"
> +#include "iris_instance.h"
> +
> +static void
> +iris_hfi_gen1_sys_event_notify(struct iris_core *core, void *packet)
> +{
> +	struct hfi_msg_event_notify_pkt *pkt = packet;
> +
> +	if (pkt->event_id == HFI_EVENT_SYS_ERROR)
> +		dev_err(core->dev, "sys error (type: %x, data1:%x, data2:%x)\n",
> +			pkt->event_id, pkt->event_data1, pkt->event_data2);
> +
> +	iris_change_core_state(core, IRIS_CORE_ERROR);
> +	schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10));
> +}
> +
> +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) {
> +		iris_change_core_state(core, IRIS_CORE_ERROR);
> +		return;
> +	}
> +
> +	complete(&core->core_init_done);
> +}
> +
> +static void
> +iris_hfi_gen1_sys_get_prop_image_version(struct iris_core *core,
> +					 struct hfi_msg_sys_property_info_pkt *pkt)
> +{
> +	char fw_version[IRIS_FW_VERSION_LENGTH];
> +	u8 *str_image_version;
> +	int req_bytes;
> +	u32 i;
> +
> +	req_bytes = pkt->hdr.size - sizeof(*pkt);
> +
> +	if (req_bytes < IRIS_FW_VERSION_LENGTH - 1 || !pkt->data[0] || pkt->num_properties > 1)
> +		/* bad packet */
> +		return;
> +
> +	str_image_version = pkt->data;
> +	if (!str_image_version)
> +		return;
> +
> +	for (i = 0; i < IRIS_FW_VERSION_LENGTH - 1; i++) {
> +		if (str_image_version[i] != '\0')
> +			fw_version[i] = str_image_version[i];
> +		else
> +			fw_version[i] = ' ';
> +	}
> +	fw_version[i] = '\0';
> +
> +	dev_dbg(core->dev, "firmware version: %s\n", fw_version);
> +}

You silently fail here alot in this function i.e. it returns void if it 
works or it doesn't work.

Either make this an integer returning a pass/fail state or make the 
failure path visible with a jump to a dev_dbg or a dev_err or any other 
sort of printout that is either always an error or an error visible in 
debug mode so that such a failure can be found and fixed.

> +
> +static void iris_hfi_gen1_sys_property_info(struct iris_core *core, void *packet)
> +{
> +	struct hfi_msg_sys_property_info_pkt *pkt = packet;
> +
> +	if (!pkt->num_properties) {
> +		dev_dbg(core->dev, "no properties\n");
> +		return;
> +	}
> +
> +	switch (pkt->property) {
> +	case HFI_PROPERTY_SYS_IMAGE_VERSION:
> +		iris_hfi_gen1_sys_get_prop_image_version(core, pkt);
> +		break;
> +	default:
> +		dev_dbg(core->dev, "unknown property data\n");
> +		break;
> +	}
> +}
> +
> +struct iris_hfi_gen1_response_pkt_info {
> +	u32 pkt;
> +	u32 pkt_sz;
> +};
> +
> +static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = {
> +	{
> +	 .pkt = HFI_MSG_EVENT_NOTIFY,
> +	 .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt),
> +	},
> +	{
> +	 .pkt = HFI_MSG_SYS_INIT,
> +	 .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt),
> +	},
> +	{
> +	 .pkt = HFI_MSG_SYS_PROPERTY_INFO,
> +	 .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt),
> +	},
> +};
> +
> +static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response)
> +{
> +	const struct iris_hfi_gen1_response_pkt_info *pkt_info;
> +	struct device *dev = core->dev;
> +	struct hfi_pkt_hdr *hdr;
> +	bool found = false;
> +	unsigned int i;
> +
> +	hdr = (struct hfi_pkt_hdr *)response;
> +
> +	for (i = 0; i < ARRAY_SIZE(pkt_infos); i++) {
> +		pkt_info = &pkt_infos[i];
> +		if (pkt_info->pkt != hdr->pkt_type)
> +			continue;
> +		found = true;
> +		break;
> +	}
> +
> +	if (!found || hdr->size < pkt_info->pkt_sz) {
> +		dev_err(dev, "bad packet size (%d should be %d, pkt type:%x, found %d)\n",
> +			hdr->size, pkt_info->pkt_sz, hdr->pkt_type, found);
> +
> +		return;
> +	}
> +
> +	if (hdr->pkt_type == HFI_MSG_SYS_INIT)
> +		iris_hfi_gen1_sys_init_done(core, hdr);
> +	else if (hdr->pkt_type == HFI_MSG_SYS_PROPERTY_INFO)
> +		iris_hfi_gen1_sys_property_info(core, hdr);
> +	else if (hdr->pkt_type == HFI_MSG_EVENT_NOTIFY)
> +		iris_hfi_gen1_sys_event_notify(core, hdr);
> +}
> +
> +static void iris_hfi_gen1_flush_debug_queue(struct iris_core *core, u8 *packet)
> +{
> +	struct hfi_msg_sys_coverage_pkt *pkt;
> +
> +	while (!iris_hfi_queue_dbg_read(core, packet)) {
> +		pkt = (struct hfi_msg_sys_coverage_pkt *)packet;
> +
> +		if (pkt->hdr.pkt_type != HFI_MSG_SYS_COV) {
> +			struct hfi_msg_sys_debug_pkt *pkt =
> +				(struct hfi_msg_sys_debug_pkt *)packet;
> +
> +			dev_dbg(core->dev, "%s", pkt->msg_data);
> +		}
> +	}

This loop looks funny. What's the intention here, to execute this loop 
so long as iris_hfi_queue_read() is empty, basically ?

Loads of questions like how to you guarantee that happens ? Why return 
-ENODATA if the queue is not empty.

But mostly I'd like to know how you know this loop will break ?

Same question for the other usage of iris_hfi_queue_dbg_read().

> +}
> +
> +static 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);
> +		if (core->state != IRIS_CORE_INIT)
> +			break;
> +
> +		memset(core->response_packet, 0, sizeof(struct hfi_pkt_hdr));
> +	}
> +
> +	iris_hfi_gen1_flush_debug_queue(core, core->response_packet);
> +}
> +
> +static const struct iris_hfi_response_ops iris_hfi_gen1_response_ops = {
> +	.hfi_response_handler = iris_hfi_gen1_response_handler,
> +};
> +
> +void iris_hfi_gen1_response_ops_init(struct iris_core *core)
> +{
> +	core->hfi_response_ops = &iris_hfi_gen1_response_ops;
> +}
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h
> index 4f9748cbe0e3..6ec83984fda9 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h
> @@ -8,6 +8,8 @@
>   
>   #include "iris_instance.h"
>   
> +struct iris_core;
> +
>   /**
>    * struct iris_inst_hfi_gen2 - holds per video instance parameters for hfi_gen2
>    *
> @@ -17,6 +19,8 @@ struct iris_inst_hfi_gen2 {
>   	struct iris_inst		inst;
>   };
>   
> +void iris_hfi_gen2_command_ops_init(struct iris_core *core);
> +void iris_hfi_gen2_response_ops_init(struct iris_core *core);
>   struct iris_inst *iris_hfi_gen2_get_instance(void);
>   
>   #endif
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
> index 3ee33c8befae..807266858d93 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
> @@ -4,6 +4,78 @@
>    */
>   
>   #include "iris_hfi_gen2.h"
> +#include "iris_hfi_gen2_packet.h"
> +
> +#define NUM_SYS_INIT_PACKETS 8
> +
> +static int iris_hfi_gen2_sys_init(struct iris_core *core)
> +{
> +	struct iris_hfi_header *hdr;
> +	u32 packet_size;
> +	int ret;
> +
> +	packet_size = sizeof(*hdr) +
> +		NUM_SYS_INIT_PACKETS * (sizeof(struct iris_hfi_packet) + sizeof(u32));

You can just make that into a define

sizeof(*hdr) == sizeof (struct iris_hfi_header) - fixed
NUM_SYS_INIT_PACKETS = define already and is fixed
(sizeof(struct iris_hfi_packet) + sizeof(u32) also fixed

There's nothing to calculate here - you can just bung it into a define 
at the top of the file and use the resulting HFI_PACKET_SIZE directly.

> +	hdr = kzalloc(packet_size, GFP_KERNEL);
> +	if (!hdr)
> +		return -ENOMEM;
> +
> +	iris_hfi_gen2_packet_sys_init(core, hdr);
> +	ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);
> +
> +	kfree(hdr);
> +
> +	return ret;
> +}
> +
> +static int iris_hfi_gen2_sys_image_version(struct iris_core *core)
> +{
> +	struct iris_hfi_header *hdr;
> +	u32 packet_size;
> +	int ret;
> +
> +	packet_size = sizeof(*hdr) + sizeof(struct iris_hfi_packet);

ditto

> +	hdr = kzalloc(packet_size, GFP_KERNEL);
> +	if (!hdr)
> +		return -ENOMEM;
> +
> +	iris_hfi_gen2_packet_image_version(core, hdr);
> +	ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);
> +
> +	kfree(hdr);
> +
> +	return ret;
> +}
> +
> +static int iris_hfi_gen2_sys_interframe_powercollapse(struct iris_core *core)
> +{
> +	struct iris_hfi_header *hdr;
> +	u32 packet_size;
> +	int ret;
> +
> +	packet_size = sizeof(*hdr) + sizeof(struct iris_hfi_packet) + sizeof(u32);
> +	hdr = kzalloc(packet_size, GFP_KERNEL);
> +	if (!hdr)
> +		return -ENOMEM;
> +
> +	iris_hfi_gen2_packet_sys_interframe_powercollapse(core, hdr);
> +	ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);
> +
> +	kfree(hdr);
> +
> +	return ret;
> +}
> +
> +static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = {
> +	.sys_init = iris_hfi_gen2_sys_init,
> +	.sys_image_version = iris_hfi_gen2_sys_image_version,
> +	.sys_interframe_powercollapse = iris_hfi_gen2_sys_interframe_powercollapse,
> +};
> +
> +void iris_hfi_gen2_command_ops_init(struct iris_core *core)
> +{
> +	core->hfi_ops = &iris_hfi_gen2_command_ops;
> +}
>   
>   struct iris_inst *iris_hfi_gen2_get_instance(void)
>   {
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
> new file mode 100644
> index 000000000000..3e3e4ddfe21f
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
> @@ -0,0 +1,46 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#ifndef _IRIS_HFI_GEN2_DEFINES_H_
> +#define _IRIS_HFI_GEN2_DEFINES_H_
> +
> +#include <linux/types.h>
> +
> +#define HFI_VIDEO_ARCH_LX			0x1
> +
> +#define HFI_CMD_BEGIN				0x01000000
> +#define HFI_CMD_INIT				0x01000001
> +#define HFI_CMD_END				0x01FFFFFF
> +
> +#define HFI_PROP_BEGIN				0x03000000
> +#define HFI_PROP_IMAGE_VERSION			0x03000001
> +#define HFI_PROP_INTRA_FRAME_POWER_COLLAPSE	0x03000002
> +#define HFI_PROP_UBWC_MAX_CHANNELS		0x03000003
> +#define HFI_PROP_UBWC_MAL_LENGTH		0x03000004
> +#define HFI_PROP_UBWC_HBB			0x03000005
> +#define HFI_PROP_UBWC_BANK_SWZL_LEVEL1		0x03000006
> +#define HFI_PROP_UBWC_BANK_SWZL_LEVEL2		0x03000007
> +#define HFI_PROP_UBWC_BANK_SWZL_LEVEL3		0x03000008
> +#define HFI_PROP_UBWC_BANK_SPREADING		0x03000009
> +#define HFI_PROP_END				0x03FFFFFF
> +
> +#define HFI_SYSTEM_ERROR_BEGIN			0x05000000
> +#define HFI_SYS_ERROR_WD_TIMEOUT		0x05000001
> +#define HFI_SYSTEM_ERROR_END			0x05FFFFFF
> +
> +enum hfi_packet_firmware_flags {
> +	HFI_FW_FLAGS_SUCCESS			= 0x00000001,
> +	HFI_FW_FLAGS_INFORMATION		= 0x00000002,
> +	HFI_FW_FLAGS_SESSION_ERROR		= 0x00000004,
> +	HFI_FW_FLAGS_SYSTEM_ERROR		= 0x00000008,
> +};
> +
> +struct hfi_debug_header {
> +	u32 size;
> +	u32 debug_level;
> +	u32 reserved[2];
> +};
> +
> +#endif
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c
> new file mode 100644
> index 000000000000..8266eae5ff94
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c
> @@ -0,0 +1,164 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include "iris_hfi_common.h"
> +#include "iris_hfi_gen2.h"
> +#include "iris_hfi_gen2_packet.h"
> +
> +static void iris_hfi_gen2_create_header(struct iris_hfi_header *hdr,
> +					u32 session_id, u32 header_id)
> +{
> +	memset(hdr, 0, sizeof(*hdr));
> +
> +	hdr->size = sizeof(*hdr);
> +	hdr->session_id = session_id;
> +	hdr->header_id = header_id;
> +	hdr->num_packets = 0;
> +}
> +
> +static void iris_hfi_gen2_create_packet(struct iris_hfi_header *hdr, u32 pkt_type,
> +					u32 pkt_flags, u32 payload_type, u32 port,
> +					u32 packet_id, void *payload, u32 payload_size)
> +{
> +	struct iris_hfi_packet *pkt;
> +	u32 pkt_size;
> +
> +	pkt = (struct iris_hfi_packet *)((u8 *)hdr + hdr->size);
> +	pkt_size = sizeof(*pkt) + payload_size;
> +
> +	memset(pkt, 0, pkt_size);
> +	pkt->size = pkt_size;
> +	pkt->type = pkt_type;
> +	pkt->flags = pkt_flags;
> +	pkt->payload_info = payload_type;
> +	pkt->port = port;
> +	pkt->packet_id = packet_id;
> +	if (payload_size)
> +		memcpy(&pkt->payload[0], payload, payload_size);

Do you know that the bounds here are always correct => 
sizeof(pkt->payload) >= payload_size always ?

> +
> +	hdr->num_packets++;
> +	hdr->size += pkt->size;
> +}
> +
> +void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_header *hdr)
> +{
> +	u32 payload = 0;
> +
> +	iris_hfi_gen2_create_header(hdr, 0, core->header_id++);
> +
> +	payload = HFI_VIDEO_ARCH_LX;
> +	iris_hfi_gen2_create_packet(hdr,
> +				    HFI_CMD_INIT,
> +				    (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
> +				    HFI_HOST_FLAGS_INTR_REQUIRED |
> +				    HFI_HOST_FLAGS_NON_DISCARDABLE),
> +				    HFI_PAYLOAD_U32,
> +				    HFI_PORT_NONE,
> +				    core->packet_id++,
> +				    &payload,
> +				    sizeof(u32));
> +
> +	payload = core->iris_platform_data->ubwc_config->max_channels;
> +	iris_hfi_gen2_create_packet(hdr,
> +				    HFI_PROP_UBWC_MAX_CHANNELS,
> +				    HFI_HOST_FLAGS_NONE,
> +				    HFI_PAYLOAD_U32,
> +				    HFI_PORT_NONE,
> +				    core->packet_id++,
> +				    &payload,
> +				    sizeof(u32));
> +
> +	payload = core->iris_platform_data->ubwc_config->mal_length;
> +	iris_hfi_gen2_create_packet(hdr,
> +				    HFI_PROP_UBWC_MAL_LENGTH,
> +				    HFI_HOST_FLAGS_NONE,
> +				    HFI_PAYLOAD_U32,
> +				    HFI_PORT_NONE,
> +				    core->packet_id++,
> +				    &payload,
> +				    sizeof(u32));
> +
> +	payload = core->iris_platform_data->ubwc_config->highest_bank_bit;
> +	iris_hfi_gen2_create_packet(hdr,
> +				    HFI_PROP_UBWC_HBB,
> +				    HFI_HOST_FLAGS_NONE,
> +				    HFI_PAYLOAD_U32,
> +				    HFI_PORT_NONE,
> +				    core->packet_id++,
> +				    &payload,
> +				    sizeof(u32));
> +
> +	payload = core->iris_platform_data->ubwc_config->bank_swzl_level;
> +	iris_hfi_gen2_create_packet(hdr,
> +				    HFI_PROP_UBWC_BANK_SWZL_LEVEL1,
> +				    HFI_HOST_FLAGS_NONE,
> +				    HFI_PAYLOAD_U32,
> +				    HFI_PORT_NONE,
> +				    core->packet_id++,
> +				    &payload,
> +				    sizeof(u32));
> +
> +	payload = core->iris_platform_data->ubwc_config->bank_swz2_level;
> +	iris_hfi_gen2_create_packet(hdr,
> +				    HFI_PROP_UBWC_BANK_SWZL_LEVEL2,
> +				    HFI_HOST_FLAGS_NONE,
> +				    HFI_PAYLOAD_U32,
> +				    HFI_PORT_NONE,
> +				    core->packet_id++,
> +				    &payload,
> +				    sizeof(u32));
> +
> +	payload = core->iris_platform_data->ubwc_config->bank_swz3_level;
> +	iris_hfi_gen2_create_packet(hdr,
> +				    HFI_PROP_UBWC_BANK_SWZL_LEVEL3,
> +				    HFI_HOST_FLAGS_NONE,
> +				    HFI_PAYLOAD_U32,
> +				    HFI_PORT_NONE,
> +				    core->packet_id++,
> +				    &payload,
> +				    sizeof(u32));
> +
> +	payload = core->iris_platform_data->ubwc_config->bank_spreading;
> +	iris_hfi_gen2_create_packet(hdr,
> +				    HFI_PROP_UBWC_BANK_SPREADING,
> +				    HFI_HOST_FLAGS_NONE,
> +				    HFI_PAYLOAD_U32,
> +				    HFI_PORT_NONE,
> +				    core->packet_id++,
> +				    &payload,
> +				    sizeof(u32));
> +}
> +
> +void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_header *hdr)
> +{
> +	iris_hfi_gen2_create_header(hdr, 0, core->header_id++);
> +
> +	iris_hfi_gen2_create_packet(hdr,
> +				    HFI_PROP_IMAGE_VERSION,
> +				    (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
> +				    HFI_HOST_FLAGS_INTR_REQUIRED |
> +				    HFI_HOST_FLAGS_GET_PROPERTY),
> +				    HFI_PAYLOAD_NONE,
> +				    HFI_PORT_NONE,
> +				    core->packet_id++,
> +				    NULL, 0);
> +}
> +
> +void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core,
> +						       struct iris_hfi_header *hdr)
> +{
> +	u32 payload = 1; /* HFI_TRUE */
> +
> +	iris_hfi_gen2_create_header(hdr, 0 /*session_id*/, core->header_id++);
> +
> +	iris_hfi_gen2_create_packet(hdr,
> +				    HFI_PROP_INTRA_FRAME_POWER_COLLAPSE,
> +				    HFI_HOST_FLAGS_NONE,
> +				    HFI_PAYLOAD_U32,
> +				    HFI_PORT_NONE,
> +				    core->packet_id++,
> +				    &payload,
> +				    sizeof(u32));
> +}
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h
> new file mode 100644
> index 000000000000..eba109efeb76
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h
> @@ -0,0 +1,69 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#ifndef _IRIS_HFI_GEN2_PACKET_H_
> +#define _IRIS_HFI_GEN2_PACKET_H_
> +
> +#include "iris_hfi_gen2_defines.h"
> +
> +struct iris_core;
> +
> +/**
> + * struct iris_hfi_header
> + *
> + * @size: size of the total packet in bytes including hfi_header
> + * @session_id: For session level hfi_header session_id is non-zero.
> + *                For  system level hfi_header session_id is zero.
> + * @header_id: unique header id for each hfi_header
> + * @reserved: reserved for future use
> + * @num_packets: number of hfi_packet that are included with the hfi_header
> + */
> +struct iris_hfi_header {
> +	u32 size;
> +	u32 session_id;
> +	u32 header_id;
> +	u32 reserved[4];
> +	u32 num_packets;
> +};
> +
> +/**
> + * struct iris_hfi_packet
> + *
> + * @size: size of the hfi_packet in bytes including payload
> + * @type: one of the below hfi_packet types:
> + *        HFI_CMD_*,
> + *        HFI_PROP_*,
> + *        HFI_ERROR_*,
> + *        HFI_INFO_*,
> + *        HFI_SYS_ERROR_*
> + * @flags: hfi_packet flags. It is represented as bit masks.
> + *         host packet flags are "enum hfi_packet_host_flags"
> + *         firmware packet flags are "enum hfi_packet_firmware_flags"
> + * @payload_info: payload information indicated by "enum hfi_packet_payload_info"
> + * @port: hfi_packet port type indicated by "enum hfi_packet_port_type"
> + *        This is bitmask and may be applicable to multiple ports.
> + * @packet_id: host hfi_packet contains unique packet id.
> + *             firmware returns host packet id in response packet
> + *             wherever applicable. If not applicable firmware sets it to zero.
> + * @reserved: reserved for future use.
> + * @payload: flexible array of payload having additional packet information.
> + */
> +struct iris_hfi_packet {
> +	u32 size;
> +	u32 type;
> +	u32 flags;
> +	u32 payload_info;
> +	u32 port;
> +	u32 packet_id;
> +	u32 reserved[2];
> +	u32 payload[];
> +};
> +
> +void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_header *hdr);
> +void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_header *hdr);
> +void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core,
> +						       struct iris_hfi_header *hdr);
> +
> +#endif
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
> new file mode 100644
> index 000000000000..e208a5ae664a
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
> @@ -0,0 +1,229 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include "iris_hfi_gen2.h"
> +#include "iris_hfi_gen2_defines.h"
> +#include "iris_hfi_gen2_packet.h"
> +#include "iris_vpu_common.h"
> +
> +struct iris_hfi_gen2_core_hfi_range {
> +	u32 begin;
> +	u32 end;
> +	int (*handle)(struct iris_core *core, struct iris_hfi_packet *pkt);
> +};
> +
> +static int iris_hfi_gen2_validate_packet(u8 *response_pkt, u8 *core_resp_pkt)
> +{
> +	u32 response_pkt_size = 0;
> +	u8 *response_limit;
> +
> +	response_limit = core_resp_pkt + IFACEQ_CORE_PKT_SIZE;
> +
> +	response_pkt_size = *(u32 *)response_pkt;
> +	if (!response_pkt_size)
> +		return -EINVAL;
> +
> +	if (response_pkt_size < sizeof(struct iris_hfi_packet))
> +		return -EINVAL;
> +
> +	if (response_pkt + response_pkt_size > response_limit)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int iris_hfi_gen2_validate_hdr_packet(struct iris_core *core, struct iris_hfi_header *hdr)
> +{
> +	struct iris_hfi_packet *packet;
> +	int i, ret = 0;
> +	u8 *pkt;
> +
> +	if (hdr->size < sizeof(*hdr) + sizeof(*packet))
> +		return -EINVAL;
> +
> +	pkt = (u8 *)((u8 *)hdr + sizeof(*hdr));
> +
> +	for (i = 0; i < hdr->num_packets; i++) {
> +		packet = (struct iris_hfi_packet *)pkt;
> +		ret = iris_hfi_gen2_validate_packet(pkt, core->response_packet);
> +		if (ret)
> +			return ret;
> +
> +		pkt += packet->size;
> +	}
> +
> +	return ret;
> +}
> +
> +static int iris_hfi_gen2_handle_system_error(struct iris_core *core,
> +					     struct iris_hfi_packet *pkt)
> +{
> +	dev_err(core->dev, "received system error of type %#x\n", pkt->type);
> +
> +	iris_change_core_state(core, IRIS_CORE_ERROR);
> +	schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10));
> +
> +	return 0;
> +}
> +
> +static int iris_hfi_gen2_handle_system_init(struct iris_core *core,
> +					    struct iris_hfi_packet *pkt)
> +{
> +	if (!(pkt->flags & HFI_FW_FLAGS_SUCCESS)) {
> +		iris_change_core_state(core, IRIS_CORE_ERROR);
> +		return 0;
> +	}
> +
> +	complete(&core->core_init_done);
> +
> +	return 0;
> +}
> +
> +static int iris_hfi_gen2_handle_image_version_property(struct iris_core *core,
> +						       struct iris_hfi_packet *pkt)
> +{
> +	char fw_version[IRIS_FW_VERSION_LENGTH];
> +	u8 *str_image_version;
> +	u32 req_bytes;
> +	u32 i = 0;
> +
> +	req_bytes = pkt->size - sizeof(*pkt);
> +	if (req_bytes < IRIS_FW_VERSION_LENGTH - 1)
> +		return -EINVAL;
> +
> +	str_image_version = (u8 *)pkt + sizeof(*pkt);
> +
> +	for (i = 0; i < IRIS_FW_VERSION_LENGTH - 1; i++) {
> +		if (str_image_version[i] != '\0')
> +			fw_version[i] = str_image_version[i];
> +		else
> +			fw_version[i] = ' ';
> +	}
> +	fw_version[i] = '\0';
> +
> +	dev_dbg(core->dev, "firmware version: %s\n", fw_version);
> +
> +	return 0;
> +}
> +
> +static int iris_hfi_gen2_handle_system_property(struct iris_core *core,
> +						struct iris_hfi_packet *pkt)
> +{
> +	int ret = 0;
> +
> +	switch (pkt->type) {
> +	case HFI_PROP_IMAGE_VERSION:
> +		ret = iris_hfi_gen2_handle_image_version_property(core, pkt);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static int iris_hfi_gen2_handle_system_response(struct iris_core *core,
> +						struct iris_hfi_header *hdr)
> +{
> +	struct iris_hfi_packet *packet;
> +	u8 *pkt, *start_pkt;
> +	int ret = 0;
> +	int i, j;
> +	static const struct iris_hfi_gen2_core_hfi_range range[] = {
> +		{HFI_SYSTEM_ERROR_BEGIN, HFI_SYSTEM_ERROR_END, iris_hfi_gen2_handle_system_error },
> +		{HFI_PROP_BEGIN,         HFI_PROP_END, iris_hfi_gen2_handle_system_property },
> +		{HFI_CMD_BEGIN,          HFI_CMD_END, iris_hfi_gen2_handle_system_init },
> +	};
> +
> +	start_pkt = (u8 *)((u8 *)hdr + sizeof(*hdr));
> +	for (i = 0; i < ARRAY_SIZE(range); i++) {
> +		pkt = start_pkt;
> +		for (j = 0; j < hdr->num_packets; j++) {
> +			packet = (struct iris_hfi_packet *)pkt;
> +			if (packet->flags & HFI_FW_FLAGS_SYSTEM_ERROR) {
> +				ret = iris_hfi_gen2_handle_system_error(core, packet);
> +				return ret;
> +			}
> +
> +			if (packet->type > range[i].begin && packet->type < range[i].end) {
> +				ret = range[i].handle(core, packet);
> +				if (ret)
> +					return ret;
> +
> +				if (packet->type >  HFI_SYSTEM_ERROR_BEGIN &&
> +				    packet->type < HFI_SYSTEM_ERROR_END)
> +					return 0;
> +			}
> +			pkt += packet->size;
> +		}
> +	}

You step the pkt pointer on each iteration of the j loop but then 
reinitialise it to the original start_pkt inside of each i loop.

So you'll always process the same packet in the i loop no ?

Is that the intention ?

> +
> +	return ret;
> +}
> +
> +static int iris_hfi_gen2_handle_response(struct iris_core *core, void *response)
> +{
> +	struct iris_hfi_header *hdr;
> +	int ret;
> +
> +	hdr = (struct iris_hfi_header *)response;
> +	ret = iris_hfi_gen2_validate_hdr_packet(core, hdr);
> +	if (ret)
> +		return iris_hfi_gen2_handle_system_error(core, NULL);
> +
> +	return iris_hfi_gen2_handle_system_response(core, hdr);
> +}
> +
> +static void iris_hfi_gen2_flush_debug_queue(struct iris_core *core, u8 *packet)
> +{
> +	struct hfi_debug_header *pkt;
> +	u8 *log;
> +
> +	while (!iris_hfi_queue_dbg_read(core, packet)) {
> +		pkt = (struct hfi_debug_header *)packet;
> +
> +		if (pkt->size < sizeof(*pkt))
> +			continue;
> +
> +		if (pkt->size >= IFACEQ_CORE_PKT_SIZE)
> +			continue;
> +
> +		packet[pkt->size] = '\0';
> +		log = (u8 *)packet + sizeof(*pkt) + 1;
> +		dev_dbg(core->dev, "%s", log);
> +	}
> +}

This more of a busy/wait than a flush. I asked previously how you know 
the other usage of iris_hfi_queue_dbg_read() would break. Similar 
question here, also is the "popping" of the 
log/stack/whatever-you-call-it that iris_hfi_queue_dbg_read() consumes 
immediate or can it stall ?

Do you need to have some kind of delay between reads ?

I really asking how you know this loop terminates, if it needs to be 
error-checked to ensure it terminates and if we you need "inter-frame" 
delays - to stop the CPU spinning while the data is delivered up ?


> +
> +static void iris_hfi_gen2_response_handler(struct iris_core *core)
> +{
> +	if (iris_vpu_watchdog(core, core->intr_status)) {
> +		struct iris_hfi_packet pkt = {.type = HFI_SYS_ERROR_WD_TIMEOUT};
> +
> +		dev_err(core->dev, "cpu watchdog error received\n");
> +		iris_change_core_state(core, IRIS_CORE_ERROR);
> +		iris_hfi_gen2_handle_system_error(core, &pkt);
> +
> +		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);
> +		if (core->state != IRIS_CORE_INIT)
> +			break;
> +		memset(core->response_packet, 0, sizeof(struct iris_hfi_header));
> +	}
> +
> +	iris_hfi_gen2_flush_debug_queue(core, core->response_packet);
> +}
> +
> +static const struct iris_hfi_response_ops iris_hfi_gen2_response_ops = {
> +	.hfi_response_handler = iris_hfi_gen2_response_handler,
> +};
> +
> +void iris_hfi_gen2_response_ops_init(struct iris_core *core)
> +{
> +	core->hfi_response_ops = &iris_hfi_gen2_response_ops;
> +}
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c
> index 11938880b8cd..b24d4640fea9 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c
> @@ -5,6 +5,207 @@
>   
>   #include "iris_core.h"
>   #include "iris_hfi_queue.h"
> +#include "iris_vpu_common.h"
> +
> +static int iris_hfi_queue_write(struct iris_iface_q_info *qinfo, void *packet, u32 packet_size)
> +{
> +	u32 empty_space, read_idx, write_idx, new_write_idx;
> +	struct iris_hfi_queue_header *queue;
> +	u32 *write_ptr;
> +	u32 residue;
> +
> +	queue = qinfo->qhdr;
> +
> +	read_idx = queue->read_idx * sizeof(u32);
> +	write_idx = queue->write_idx * sizeof(u32);
> +
> +	if (write_idx < read_idx)
> +		empty_space = read_idx - write_idx;
> +	else
> +		empty_space = IFACEQ_QUEUE_SIZE - (write_idx -  read_idx);
> +	if (empty_space < packet_size)
> +		return -ENOSPC;
> +
> +	queue->tx_req =  0;
> +
> +	new_write_idx = write_idx + packet_size;
> +	write_ptr = (u32 *)((u8 *)qinfo->kernel_vaddr + write_idx);
> +
> +	if (write_ptr < (u32 *)qinfo->kernel_vaddr ||
> +	    write_ptr > (u32 *)(qinfo->kernel_vaddr +
> +	    IFACEQ_QUEUE_SIZE))
> +		return -EINVAL;
> +
> +	if (new_write_idx < IFACEQ_QUEUE_SIZE) {
> +		memcpy(write_ptr, packet, packet_size);
> +	} else {
> +		residue = new_write_idx - IFACEQ_QUEUE_SIZE;
> +		memcpy(write_ptr, packet, (packet_size - residue));
> +		memcpy(qinfo->kernel_vaddr,
> +		       packet + (packet_size - residue), residue);
> +		new_write_idx = residue;
> +	}
> +
> +	/* Make sure packet is written before updating the write index */
> +	mb();
> +	queue->write_idx = new_write_idx / sizeof(u32);
> +
> +	/* Make sure write index is updated before an interrupt is raised */
> +	mb();
> +
> +	return 0;
> +}
> +
> +static int iris_hfi_queue_read(struct iris_iface_q_info *qinfo, void *packet)
> +{
> +	u32 read_idx, write_idx, new_read_idx;
> +	struct iris_hfi_queue_header *queue;
> +	u32 packet_size, residue;
> +	u32 receive_request = 0;
> +	u32 *read_ptr;
> +	int ret = 0;
> +
> +	queue = qinfo->qhdr;
> +
> +	if (queue->queue_type == IFACEQ_MSGQ_ID)
> +		receive_request = 1;
> +
> +	read_idx = queue->read_idx * sizeof(u32);
> +	write_idx = queue->write_idx * sizeof(u32);
> +
> +	if (read_idx == write_idx) {
> +		queue->rx_req = receive_request;
> +		/* Ensure qhdr is updated in main memory */
> +		mb();
> +		return -ENODATA;
> +	}
> +
> +	read_ptr = qinfo->kernel_vaddr + read_idx;
> +	if (read_ptr < (u32 *)qinfo->kernel_vaddr ||
> +	    read_ptr > (u32 *)(qinfo->kernel_vaddr +
> +	    IFACEQ_QUEUE_SIZE - sizeof(*read_ptr)))
> +		return -ENODATA;
> +
> +	packet_size = *read_ptr;
> +	if (!packet_size)
> +		return -EINVAL;
> +
> +	new_read_idx = read_idx + packet_size;
> +	if (packet_size <= IFACEQ_CORE_PKT_SIZE) {
> +		if (new_read_idx < IFACEQ_QUEUE_SIZE) {
> +			memcpy(packet, read_ptr, packet_size);
> +		} else {
> +			residue = new_read_idx - IFACEQ_QUEUE_SIZE;
> +			memcpy(packet, read_ptr, (packet_size - residue));
> +			memcpy((packet + (packet_size - residue)),
> +			       qinfo->kernel_vaddr, residue);
> +			new_read_idx = residue;
> +		}
> +	} else {
> +		new_read_idx = write_idx;
> +		ret = -EBADMSG;
> +	}
> +
> +	queue->rx_req = receive_request;
> +
> +	queue->read_idx = new_read_idx / sizeof(u32);
> +	/* Ensure qhdr is updated in main memory */
> +	mb();
> +
> +	return ret;
> +}
> +
> +int iris_hfi_queue_cmd_write_locked(struct iris_core *core, void *pkt, u32 pkt_size)
> +{
> +	struct iris_iface_q_info *q_info;
> +
> +	if (!mutex_is_locked(&core->lock))
> +		return -EINVAL;

Can this function be called without the mutex being locked ?

If not then you should have some kind of dev_err() with this no ? 
Otherwise browsing the code here IDT this check is needed.

I'd suggest either drop or be more noisy about the bug you encountered.

> +
> +	if (core->state != IRIS_CORE_INIT)
> +		return -EINVAL;
> +
> +	q_info = &core->command_queue;
> +	if (!q_info || !q_info->kernel_vaddr || !pkt) {
> +		dev_err(core->dev, "cannot write to shared command queue\n");
> +		return -ENODATA;
> +	}
> +
> +	if (!iris_hfi_queue_write(q_info, pkt, pkt_size)) {
> +		iris_vpu_raise_interrupt(core);
> +	} else {
> +		dev_err(core->dev, "queue full\n");
> +		return -ENODATA;
> +	}
> +
> +	return 0;
> +}
> +
> +int iris_hfi_queue_cmd_write(struct iris_core *core, void *pkt, u32 pkt_size)
> +{
> +	int ret;
> +
> +	mutex_lock(&core->lock);
> +	ret = iris_hfi_queue_cmd_write_locked(core, pkt, pkt_size);
> +	if (ret)
> +		dev_err(core->dev, "iris_hfi_queue_cmd_write_locked failed with %d\n", ret);
> +
> +	mutex_unlock(&core->lock);
> +
> +	return ret;
> +}
> +
> +int iris_hfi_queue_msg_read(struct iris_core *core, void *pkt)
> +{
> +	struct iris_iface_q_info *q_info;
> +	int ret = 0;
> +
> +	mutex_lock(&core->lock);
> +	if (core->state != IRIS_CORE_INIT) {
> +		ret = -EINVAL;
> +		goto unlock;
> +	}
> +
> +	q_info = &core->message_queue;
> +	if (iris_hfi_queue_read(q_info, pkt)) {
> +		ret = -ENODATA;

Its a very curious response code to return "ENODATA" when you actually 
have data..

Why not return

< 0 err code
0 no data
 > 0 data

?

> +		goto unlock;
> +	}
> +
> +unlock:
> +	mutex_unlock(&core->lock);
> +
> +	return ret;
> +}
> +
> +int iris_hfi_queue_dbg_read(struct iris_core *core, void *pkt)
> +{
> +	struct iris_iface_q_info *q_info;
> +	int ret = 0;
> +
> +	mutex_lock(&core->lock);
> +	if (core->state != IRIS_CORE_INIT) {
> +		ret = -EINVAL;
> +		goto unlock;
> +	}

I'm going to challenge this logic here. Can this function be called 
except when state == IRIS_CORE_INIT ?

Surely you should get into the IRIS_CORE_INIT state before progressing 
this far into your code's runtime ?

In which case a plethora of runtime checks for the validatity of your 
state-machine are redundant.

Far better to make a concrete transition from one state to another than 
to have a bunch of defensive coding checks which are redundant.

A blanket statement for this driver.

Please consider.

> +
> +	q_info = &core->debug_queue;
> +	if (!q_info || !q_info->kernel_vaddr || !pkt) {
> +		dev_err(core->dev, "cannot read from shared debug queue\n");
> +		ret = -ENODATA;
> +		goto unlock;
> +	}
> +
> +	if (iris_hfi_queue_read(q_info, pkt)) {
Should this really be returning an error and shoiuld it be the same 
error as above ?

> +		ret = -ENODATA;
> +		goto unlock;
> +	}
> +
> +unlock:
> +	mutex_unlock(&core->lock);
> +
> +	return ret;
> +}

[1]
Am I reading this function right. It returs -ENODATA to indicate both an 
error state and to indicate termination to the calling function ?

---
bod
Vikash Garodia Sept. 6, 2024, 1:31 p.m. UTC | #3
Hi Bryan,

On 9/5/2024 6:40 PM, Bryan O'Donoghue wrote:
> On 27/08/2024 11:05, Dikshita Agarwal via B4 Relay wrote:
>> From: Dikshita Agarwal <quic_dikshita@quicinc.com>
>>
>> Host firmware interface (HFI) is well defined set of interfaces
>> for communication between host driver and firmware.
>> The command and responses are exchanged in form of packets.
>> One or multiple packets are grouped under packet header.
>> Each packet has packet type which describes the specific HFI
>> and payload which holds the corresponding value for that HFI.
>>
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> ---
>>   drivers/media/platform/qcom/iris/Makefile          |   5 +
>>   drivers/media/platform/qcom/iris/iris_core.c       |  26 ++-
>>   drivers/media/platform/qcom/iris/iris_core.h       |  20 ++
>>   drivers/media/platform/qcom/iris/iris_hfi_common.c |  56 +++++
>>   drivers/media/platform/qcom/iris/iris_hfi_common.h |  60 ++++++
>>   drivers/media/platform/qcom/iris/iris_hfi_gen1.h   |   3 +
>>   .../platform/qcom/iris/iris_hfi_gen1_command.c     |  61 ++++++
>>   .../platform/qcom/iris/iris_hfi_gen1_defines.h     |  94 +++++++++
>>   .../platform/qcom/iris/iris_hfi_gen1_response.c    | 174 ++++++++++++++++
>>   drivers/media/platform/qcom/iris/iris_hfi_gen2.h   |   4 +
>>   .../platform/qcom/iris/iris_hfi_gen2_command.c     |  72 +++++++
>>   .../platform/qcom/iris/iris_hfi_gen2_defines.h     |  46 +++++
>>   .../platform/qcom/iris/iris_hfi_gen2_packet.c      | 164 +++++++++++++++
>>   .../platform/qcom/iris/iris_hfi_gen2_packet.h      |  69 +++++++
>>   .../platform/qcom/iris/iris_hfi_gen2_response.c    | 229 +++++++++++++++++++++
>>   drivers/media/platform/qcom/iris/iris_hfi_queue.c  | 201 ++++++++++++++++++
>>   drivers/media/platform/qcom/iris/iris_hfi_queue.h  |   5 +
>>   .../platform/qcom/iris/iris_platform_common.h      |  15 ++
>>   .../platform/qcom/iris/iris_platform_sm8250.c      |   3 +
>>   .../platform/qcom/iris/iris_platform_sm8550.c      |  14 ++
>>   drivers/media/platform/qcom/iris/iris_probe.c      |  40 ++++
>>   drivers/media/platform/qcom/iris/iris_state.c      |  15 ++
>>   drivers/media/platform/qcom/iris/iris_state.h      |   4 +
>>   drivers/media/platform/qcom/iris/iris_vpu_common.c |  42 ++++
>>   drivers/media/platform/qcom/iris/iris_vpu_common.h |   3 +
>>   25 files changed, 1424 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/media/platform/qcom/iris/Makefile
>> b/drivers/media/platform/qcom/iris/Makefile
>> index 95f4e92fe085..d1f0b933df3d 100644
>> --- a/drivers/media/platform/qcom/iris/Makefile
>> +++ b/drivers/media/platform/qcom/iris/Makefile
>> @@ -1,12 +1,17 @@
>>   iris-objs += iris_core.o \
>>                iris_firmware.o \
>> +             iris_hfi_common.o \
>>                iris_hfi_gen1_command.o \
>> +             iris_hfi_gen1_response.o \
>>                iris_hfi_gen2_command.o \
>> +             iris_hfi_gen2_packet.o \
>> +             iris_hfi_gen2_response.o \
>>                iris_hfi_queue.o \
>>                iris_platform_sm8250.o \
>>                iris_platform_sm8550.o \
>>                iris_probe.o \
>>                iris_resources.o \
>> +             iris_state.o \
>>                iris_vidc.o \
>>                iris_vpu_common.o \
>>   diff --git a/drivers/media/platform/qcom/iris/iris_core.c
>> b/drivers/media/platform/qcom/iris/iris_core.c
>> index 5ad66ac113ae..92458d7f1e36 100644
>> --- a/drivers/media/platform/qcom/iris/iris_core.c
>> +++ b/drivers/media/platform/qcom/iris/iris_core.c
>> @@ -17,6 +17,26 @@ void iris_core_deinit(struct iris_core *core)
>>       mutex_unlock(&core->lock);
>>   }
>>   +static int iris_wait_for_system_response(struct iris_core *core)
>> +{
>> +    u32 hw_response_timeout_val;
>> +    int ret;
>> +
>> +    if (core->state == IRIS_CORE_ERROR)
>> +        return -EIO;
>> +
>> +    hw_response_timeout_val = core->iris_platform_data->hw_response_timeout;
>> +
>> +    ret = wait_for_completion_timeout(&core->core_init_done,
>> +                      msecs_to_jiffies(hw_response_timeout_val));
>> +    if (!ret) {
>> +        iris_change_core_state(core, IRIS_CORE_ERROR);
>> +        return -ETIMEDOUT;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>>   int iris_core_init(struct iris_core *core)
>>   {
>>       int ret;
>> @@ -44,9 +64,13 @@ int iris_core_init(struct iris_core *core)
>>       if (ret)
>>           goto error_unload_fw;
>>   +    ret = iris_hfi_core_init(core);
>> +    if (ret)
>> +        goto error_unload_fw;
>> +
>>       mutex_unlock(&core->lock);
>>   -    return 0;
>> +    return iris_wait_for_system_response(core);
>>     error_unload_fw:
>>       iris_fw_unload(core);
>> diff --git a/drivers/media/platform/qcom/iris/iris_core.h
>> b/drivers/media/platform/qcom/iris/iris_core.h
>> index 13c5932f9110..409f9822807d 100644
>> --- a/drivers/media/platform/qcom/iris/iris_core.h
>> +++ b/drivers/media/platform/qcom/iris/iris_core.h
>> @@ -9,11 +9,15 @@
>>   #include <linux/types.h>
>>   #include <media/v4l2-device.h>
>>   +#include "iris_hfi_common.h"
>>   #include "iris_hfi_queue.h"
>>   #include "iris_platform_common.h"
>>   #include "iris_resources.h"
>>   #include "iris_state.h"
>>   +#define IRIS_FW_VERSION_LENGTH        128
>> +#define IFACEQ_CORE_PKT_SIZE        (1024 * 4)
>> +
>>   /**
>>    * struct iris_core - holds core parameters valid for all instances
>>    *
>> @@ -40,6 +44,14 @@
>>    * @message_queue: shared interface queue to receive responses from firmware
>>    * @debug_queue: shared interface queue to receive debug info from firmware
>>    * @lock: a lock for this strucure
>> + * @response_packet: a pointer to response packet from fw to driver
>> + * @header_id: id of packet header
>> + * @packet_id: id of packet
>> + * @hfi_ops: iris hfi command ops
>> + * @hfi_response_ops: iris hfi response ops
>> + * @core_init_done: structure of signal completion for system response
>> + * @intr_status: interrupt status
>> + * @sys_error_handler: a delayed work for handling system fatal error
>>    */
>>     struct iris_core {
>> @@ -66,6 +78,14 @@ struct iris_core {
>>       struct iris_iface_q_info        message_queue;
>>       struct iris_iface_q_info        debug_queue;
>>       struct mutex                lock; /* lock for core related operations */
>> +    u8                    *response_packet;
>> +    u32                    header_id;
>> +    u32                    packet_id;
>> +    const struct iris_hfi_command_ops    *hfi_ops;
>> +    const struct iris_hfi_response_ops    *hfi_response_ops;
>> +    struct completion            core_init_done;
>> +    u32                    intr_status;
>> +    struct delayed_work            sys_error_handler;
>>   };
>>     int iris_core_init(struct iris_core *core);
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.c
>> b/drivers/media/platform/qcom/iris/iris_hfi_common.c
>> new file mode 100644
>> index 000000000000..a5a28029d8d1
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.c
>> @@ -0,0 +1,56 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#include "iris_core.h"
>> +#include "iris_hfi_common.h"
>> +#include "iris_vpu_common.h"
>> +
>> +int iris_hfi_core_init(struct iris_core *core)
>> +{
>> +    const struct iris_hfi_command_ops *hfi_ops = core->hfi_ops;
>> +    int ret;
>> +
>> +    ret = hfi_ops->sys_init(core);
>> +    if (ret)
>> +        return ret;
>> +
>> +    ret = hfi_ops->sys_image_version(core);
>> +    if (ret)
>> +        return ret;
>> +
>> +    return hfi_ops->sys_interframe_powercollapse(core);
>> +}
>> +
>> +irqreturn_t iris_hfi_isr(int irq, void *data)
>> +{
>> +    disable_irq_nosync(irq);
>> +
>> +    return IRQ_WAKE_THREAD;
>> +}
>> +
>> +irqreturn_t iris_hfi_isr_handler(int irq, void *data)
>> +{
>> +    struct iris_core *core = data;
>> +
>> +    if (!core)
>> +        return IRQ_NONE;
>> +
>> +    mutex_lock(&core->lock);
>> +    if (core->state != IRIS_CORE_INIT) {
>> +        mutex_unlock(&core->lock);
>> +        goto exit;
>> +    }
>> +
>> +    iris_vpu_clear_interrupt(core);
>> +    mutex_unlock(&core->lock);
>> +
>> +    core->hfi_response_ops->hfi_response_handler(core);
>> +
>> +exit:
>> +    if (!iris_vpu_watchdog(core, core->intr_status))
>> +        enable_irq(irq);
>> +
>> +    return IRQ_HANDLED;
>> +}
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h
>> b/drivers/media/platform/qcom/iris/iris_hfi_common.h
>> new file mode 100644
>> index 000000000000..c3d5b899cf60
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h
>> @@ -0,0 +1,60 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#ifndef _IRIS_HFI_COMMON_H_
>> +#define _IRIS_HFI_COMMON_H_
>> +
>> +#include <linux/types.h>
>> +#include <media/v4l2-device.h>
>> +
>> +struct iris_core;
>> +
>> +enum hfi_packet_port_type {
>> +    HFI_PORT_NONE        = 0x00000000,
>> +    HFI_PORT_BITSTREAM    = 0x00000001,
>> +    HFI_PORT_RAW        = 0x00000002,
>> +};
>> +
>> +enum hfi_packet_payload_info {
>> +    HFI_PAYLOAD_NONE    = 0x00000000,
>> +    HFI_PAYLOAD_U32        = 0x00000001,
>> +    HFI_PAYLOAD_S32        = 0x00000002,
>> +    HFI_PAYLOAD_U64        = 0x00000003,
>> +    HFI_PAYLOAD_S64        = 0x00000004,
>> +    HFI_PAYLOAD_STRUCTURE    = 0x00000005,
>> +    HFI_PAYLOAD_BLOB    = 0x00000006,
>> +    HFI_PAYLOAD_STRING    = 0x00000007,
>> +    HFI_PAYLOAD_Q16        = 0x00000008,
>> +    HFI_PAYLOAD_U32_ENUM    = 0x00000009,
>> +    HFI_PAYLOAD_32_PACKED    = 0x0000000a,
>> +    HFI_PAYLOAD_U32_ARRAY    = 0x0000000b,
>> +    HFI_PAYLOAD_S32_ARRAY    = 0x0000000c,
>> +    HFI_PAYLOAD_64_PACKED    = 0x0000000d,
>> +};
>> +
>> +enum hfi_packet_host_flags {
>> +    HFI_HOST_FLAGS_NONE            = 0x00000000,
>> +    HFI_HOST_FLAGS_INTR_REQUIRED        = 0x00000001,
>> +    HFI_HOST_FLAGS_RESPONSE_REQUIRED    = 0x00000002,
>> +    HFI_HOST_FLAGS_NON_DISCARDABLE        = 0x00000004,
>> +    HFI_HOST_FLAGS_GET_PROPERTY        = 0x00000008,
>> +};
>> +
>> +struct iris_hfi_command_ops {
>> +    int (*sys_init)(struct iris_core *core);
>> +    int (*sys_image_version)(struct iris_core *core);
>> +    int (*sys_interframe_powercollapse)(struct iris_core *core);
>> +};
>> +
>> +struct iris_hfi_response_ops {
>> +    void (*hfi_response_handler)(struct iris_core *core);
>> +};
>> +
>> +int iris_hfi_core_init(struct iris_core *core);
>> +
>> +irqreturn_t iris_hfi_isr(int irq, void *data);
>> +irqreturn_t iris_hfi_isr_handler(int irq, void *data);
>> +
>> +#endif
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1.h
>> b/drivers/media/platform/qcom/iris/iris_hfi_gen1.h
>> index b02f629a9cdc..15edbb359c71 100644
>> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1.h
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1.h
>> @@ -6,8 +6,11 @@
>>   #ifndef _IRIS_HFI_GEN1_H_
>>   #define _IRIS_HFI_GEN1_H_
>>   +struct iris_core;
>>   struct iris_inst;
>>   +void iris_hfi_gen1_command_ops_init(struct iris_core *core);
>> +void iris_hfi_gen1_response_ops_init(struct iris_core *core);
>>   struct iris_inst *iris_hfi_gen1_get_instance(void);
>>     #endif
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>> b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>> index 20c68f4ffb72..8f045ef56163 100644
>> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
>> @@ -4,8 +4,69 @@
>>    */
>>     #include "iris_hfi_gen1.h"
>> +#include "iris_hfi_gen1_defines.h"
>>   #include "iris_instance.h"
>>   +static int iris_hfi_gen1_sys_init(struct iris_core *core)
>> +{
>> +    struct hfi_sys_init_pkt sys_init_pkt;
>> +
>> +    sys_init_pkt.hdr.size = sizeof(sys_init_pkt);
>> +    sys_init_pkt.hdr.pkt_type = HFI_CMD_SYS_INIT;
>> +    sys_init_pkt.arch_type = HFI_VIDEO_ARCH_OX;
>> +
>> +    return iris_hfi_queue_cmd_write_locked(core, &sys_init_pkt,
>> sys_init_pkt.hdr.size);
>> +}
>> +
>> +static int iris_hfi_gen1_sys_image_version(struct iris_core *core)
>> +{
>> +    struct hfi_sys_get_property_pkt packet;
>> +
>> +    packet.hdr.size = sizeof(packet);
>> +    packet.hdr.pkt_type = HFI_CMD_SYS_GET_PROPERTY;
>> +    packet.num_properties = 1;
>> +    packet.data = HFI_PROPERTY_SYS_IMAGE_VERSION;
>> +
>> +    return iris_hfi_queue_cmd_write_locked(core, &packet, packet.hdr.size);
>> +}
>> +
>> +static int iris_hfi_gen1_sys_interframe_powercollapse(struct iris_core *core)
>> +{
>> +    struct hfi_sys_set_property_pkt *pkt;
>> +    struct hfi_enable *hfi;
>> +    u32 packet_size;
>> +    u32 ret;
>> +
>> +    packet_size = struct_size(pkt, data, 1) + sizeof(*hfi);
>> +    pkt = kzalloc(packet_size, GFP_KERNEL);
>> +    if (!pkt)
>> +        return -ENOMEM;
>> +
>> +    hfi = (struct hfi_enable *)&pkt->data[1];
>> +
>> +    pkt->hdr.size = packet_size;
>> +    pkt->hdr.pkt_type = HFI_CMD_SYS_SET_PROPERTY;
>> +    pkt->num_properties = 1;
>> +    pkt->data[0] = HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL;
>> +    hfi->enable = true;
>> +
>> +    ret = iris_hfi_queue_cmd_write_locked(core, pkt, pkt->hdr.size);
>> +    kfree(pkt);
>> +
>> +    return ret;
>> +}
>> +
>> +static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = {
>> +    .sys_init = iris_hfi_gen1_sys_init,
>> +    .sys_image_version = iris_hfi_gen1_sys_image_version,
>> +    .sys_interframe_powercollapse = iris_hfi_gen1_sys_interframe_powercollapse,
>> +};
>> +
>> +void iris_hfi_gen1_command_ops_init(struct iris_core *core)
>> +{
>> +    core->hfi_ops = &iris_hfi_gen1_command_ops;
>> +}
>> +
>>   struct iris_inst *iris_hfi_gen1_get_instance(void)
>>   {
>>       return kzalloc(sizeof(struct iris_inst), GFP_KERNEL);
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>> b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>> new file mode 100644
>> index 000000000000..5c07d6a29863
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
>> @@ -0,0 +1,94 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#ifndef _IRIS_HFI_GEN1_DEFINES_H_
>> +#define _IRIS_HFI_GEN1_DEFINES_H_
>> +
>> +#include <linux/types.h>
>> +
>> +#define HFI_VIDEO_ARCH_OX                0x1
>> +#define HFI_ERR_NONE                    0x0
>> +
>> +#define HFI_CMD_SYS_INIT                0x10001
>> +#define HFI_CMD_SYS_SET_PROPERTY            0x10005
>> +#define HFI_CMD_SYS_GET_PROPERTY            0x10006
>> +
>> +#define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL        0x5
>> +#define HFI_PROPERTY_SYS_IMAGE_VERSION            0x6
>> +
>> +#define HFI_EVENT_SYS_ERROR                0x1
>> +
>> +#define HFI_MSG_SYS_INIT                0x20001
>> +#define HFI_MSG_SYS_COV                    0x20009
>> +#define HFI_MSG_SYS_PROPERTY_INFO            0x2000a
>> +
>> +#define HFI_MSG_EVENT_NOTIFY                0x21001
>> +
>> +struct hfi_pkt_hdr {
>> +    u32 size;
>> +    u32 pkt_type;
>> +};
>> +
>> +struct hfi_sys_init_pkt {
>> +    struct hfi_pkt_hdr hdr;
>> +    u32 arch_type;
>> +};
>> +
>> +struct hfi_sys_set_property_pkt {
>> +    struct hfi_pkt_hdr hdr;
>> +    u32 num_properties;
>> +    u32 data[];
>> +};
>> +
>> +struct hfi_sys_get_property_pkt {
>> +    struct hfi_pkt_hdr hdr;
>> +    u32 num_properties;
>> +    u32 data;
>> +};
>> +
>> +struct hfi_msg_event_notify_pkt {
>> +    struct hfi_pkt_hdr hdr;
>> +    u32 event_id;
>> +    u32 event_data1;
>> +    u32 event_data2;
>> +    u32 ext_event_data[];
>> +};
>> +
>> +struct hfi_msg_sys_init_done_pkt {
>> +    struct hfi_pkt_hdr hdr;
>> +    u32 error_type;
>> +    u32 num_properties;
>> +    u32 data[];
>> +};
>> +
>> +struct hfi_msg_sys_property_info_pkt {
>> +    struct hfi_pkt_hdr hdr;
>> +    u32 num_properties;
>> +    u32 property;
>> +    u8 data[];
>> +};
>> +
>> +struct hfi_enable {
>> +    u32 enable;
>> +};
>> +
>> +struct hfi_msg_sys_debug_pkt {
>> +    struct hfi_pkt_hdr hdr;
>> +    u32 msg_type;
>> +    u32 msg_size;
>> +    u32 time_stamp_hi;
>> +    u32 time_stamp_lo;
>> +    u8 msg_data[];
>> +};
>> +
>> +struct hfi_msg_sys_coverage_pkt {
>> +    struct hfi_pkt_hdr hdr;
>> +    u32 msg_size;
>> +    u32 time_stamp_hi;
>> +    u32 time_stamp_lo;
>> +    u8 msg_data[];
>> +};
>> +
>> +#endif
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
>> b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
>> new file mode 100644
>> index 000000000000..3eb2ce99c614
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
>> @@ -0,0 +1,174 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#include "iris_hfi_gen1.h"
>> +#include "iris_hfi_gen1_defines.h"
>> +#include "iris_instance.h"
>> +
>> +static void
>> +iris_hfi_gen1_sys_event_notify(struct iris_core *core, void *packet)
>> +{
>> +    struct hfi_msg_event_notify_pkt *pkt = packet;
>> +
>> +    if (pkt->event_id == HFI_EVENT_SYS_ERROR)
>> +        dev_err(core->dev, "sys error (type: %x, data1:%x, data2:%x)\n",
>> +            pkt->event_id, pkt->event_data1, pkt->event_data2);
>> +
>> +    iris_change_core_state(core, IRIS_CORE_ERROR);
>> +    schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10));
>> +}
>> +
>> +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) {
>> +        iris_change_core_state(core, IRIS_CORE_ERROR);
>> +        return;
>> +    }
>> +
>> +    complete(&core->core_init_done);
>> +}
>> +
>> +static void
>> +iris_hfi_gen1_sys_get_prop_image_version(struct iris_core *core,
>> +                     struct hfi_msg_sys_property_info_pkt *pkt)
>> +{
>> +    char fw_version[IRIS_FW_VERSION_LENGTH];
>> +    u8 *str_image_version;
>> +    int req_bytes;
>> +    u32 i;
>> +
>> +    req_bytes = pkt->hdr.size - sizeof(*pkt);
>> +
>> +    if (req_bytes < IRIS_FW_VERSION_LENGTH - 1 || !pkt->data[0] ||
>> pkt->num_properties > 1)
>> +        /* bad packet */
>> +        return;
>> +
>> +    str_image_version = pkt->data;
>> +    if (!str_image_version)
>> +        return;
>> +
>> +    for (i = 0; i < IRIS_FW_VERSION_LENGTH - 1; i++) {
>> +        if (str_image_version[i] != '\0')
>> +            fw_version[i] = str_image_version[i];
>> +        else
>> +            fw_version[i] = ' ';
>> +    }
>> +    fw_version[i] = '\0';
>> +
>> +    dev_dbg(core->dev, "firmware version: %s\n", fw_version);
>> +}
> 
> You silently fail here alot in this function i.e. it returns void if it works or
> it doesn't work.
> 
> Either make this an integer returning a pass/fail state or make the failure path
> visible with a jump to a dev_dbg or a dev_err or any other sort of printout that
> is either always an error or an error visible in debug mode so that such a
> failure can be found and fixed.
Ok, sounds good.
> 
>> +
>> +static void iris_hfi_gen1_sys_property_info(struct iris_core *core, void
>> *packet)
>> +{
>> +    struct hfi_msg_sys_property_info_pkt *pkt = packet;
>> +
>> +    if (!pkt->num_properties) {
>> +        dev_dbg(core->dev, "no properties\n");
>> +        return;
>> +    }
>> +
>> +    switch (pkt->property) {
>> +    case HFI_PROPERTY_SYS_IMAGE_VERSION:
>> +        iris_hfi_gen1_sys_get_prop_image_version(core, pkt);
>> +        break;
>> +    default:
>> +        dev_dbg(core->dev, "unknown property data\n");
>> +        break;
>> +    }
>> +}
>> +
>> +struct iris_hfi_gen1_response_pkt_info {
>> +    u32 pkt;
>> +    u32 pkt_sz;
>> +};
>> +
>> +static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = {
>> +    {
>> +     .pkt = HFI_MSG_EVENT_NOTIFY,
>> +     .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt),
>> +    },
>> +    {
>> +     .pkt = HFI_MSG_SYS_INIT,
>> +     .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt),
>> +    },
>> +    {
>> +     .pkt = HFI_MSG_SYS_PROPERTY_INFO,
>> +     .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt),
>> +    },
>> +};
>> +
>> +static void iris_hfi_gen1_handle_response(struct iris_core *core, void
>> *response)
>> +{
>> +    const struct iris_hfi_gen1_response_pkt_info *pkt_info;
>> +    struct device *dev = core->dev;
>> +    struct hfi_pkt_hdr *hdr;
>> +    bool found = false;
>> +    unsigned int i;
>> +
>> +    hdr = (struct hfi_pkt_hdr *)response;
>> +
>> +    for (i = 0; i < ARRAY_SIZE(pkt_infos); i++) {
>> +        pkt_info = &pkt_infos[i];
>> +        if (pkt_info->pkt != hdr->pkt_type)
>> +            continue;
>> +        found = true;
>> +        break;
>> +    }
>> +
>> +    if (!found || hdr->size < pkt_info->pkt_sz) {
>> +        dev_err(dev, "bad packet size (%d should be %d, pkt type:%x, found
>> %d)\n",
>> +            hdr->size, pkt_info->pkt_sz, hdr->pkt_type, found);
>> +
>> +        return;
>> +    }
>> +
>> +    if (hdr->pkt_type == HFI_MSG_SYS_INIT)
>> +        iris_hfi_gen1_sys_init_done(core, hdr);
>> +    else if (hdr->pkt_type == HFI_MSG_SYS_PROPERTY_INFO)
>> +        iris_hfi_gen1_sys_property_info(core, hdr);
>> +    else if (hdr->pkt_type == HFI_MSG_EVENT_NOTIFY)
>> +        iris_hfi_gen1_sys_event_notify(core, hdr);
>> +}
>> +
>> +static void iris_hfi_gen1_flush_debug_queue(struct iris_core *core, u8 *packet)
>> +{
>> +    struct hfi_msg_sys_coverage_pkt *pkt;
>> +
>> +    while (!iris_hfi_queue_dbg_read(core, packet)) {
>> +        pkt = (struct hfi_msg_sys_coverage_pkt *)packet;
>> +
>> +        if (pkt->hdr.pkt_type != HFI_MSG_SYS_COV) {
>> +            struct hfi_msg_sys_debug_pkt *pkt =
>> +                (struct hfi_msg_sys_debug_pkt *)packet;
>> +
>> +            dev_dbg(core->dev, "%s", pkt->msg_data);
>> +        }
>> +    }
> 
> This loop looks funny. What's the intention here, to execute this loop so long
> as iris_hfi_queue_read() is empty, basically ?
Yes, thats correct.
> 
> Loads of questions like how to you guarantee that happens ? Why return -ENODATA
> if the queue is not empty.
For debug queue, video firmware would write the debug packets while driver would
read them. When the read and write indices are same, loop would break and
indicates no data to read.

> 
> But mostly I'd like to know how you know this loop will break ?
> 
> Same question for the other usage of iris_hfi_queue_dbg_read().
Same logic as explained above.
> 
>> +}
>> +
>> +static 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);
>> +        if (core->state != IRIS_CORE_INIT)
>> +            break;
>> +
>> +        memset(core->response_packet, 0, sizeof(struct hfi_pkt_hdr));
>> +    }
>> +
>> +    iris_hfi_gen1_flush_debug_queue(core, core->response_packet);
>> +}
>> +
>> +static const struct iris_hfi_response_ops iris_hfi_gen1_response_ops = {
>> +    .hfi_response_handler = iris_hfi_gen1_response_handler,
>> +};
>> +
>> +void iris_hfi_gen1_response_ops_init(struct iris_core *core)
>> +{
>> +    core->hfi_response_ops = &iris_hfi_gen1_response_ops;
>> +}
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h
>> b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h
>> index 4f9748cbe0e3..6ec83984fda9 100644
>> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h
>> @@ -8,6 +8,8 @@
>>     #include "iris_instance.h"
>>   +struct iris_core;
>> +
>>   /**
>>    * struct iris_inst_hfi_gen2 - holds per video instance parameters for hfi_gen2
>>    *
>> @@ -17,6 +19,8 @@ struct iris_inst_hfi_gen2 {
>>       struct iris_inst        inst;
>>   };
>>   +void iris_hfi_gen2_command_ops_init(struct iris_core *core);
>> +void iris_hfi_gen2_response_ops_init(struct iris_core *core);
>>   struct iris_inst *iris_hfi_gen2_get_instance(void);
>>     #endif
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
>> b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
>> index 3ee33c8befae..807266858d93 100644
>> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
>> @@ -4,6 +4,78 @@
>>    */
>>     #include "iris_hfi_gen2.h"
>> +#include "iris_hfi_gen2_packet.h"
>> +
>> +#define NUM_SYS_INIT_PACKETS 8
>> +
>> +static int iris_hfi_gen2_sys_init(struct iris_core *core)
>> +{
>> +    struct iris_hfi_header *hdr;
>> +    u32 packet_size;
>> +    int ret;
>> +
>> +    packet_size = sizeof(*hdr) +
>> +        NUM_SYS_INIT_PACKETS * (sizeof(struct iris_hfi_packet) + sizeof(u32));
> 
> You can just make that into a define
> 
> sizeof(*hdr) == sizeof (struct iris_hfi_header) - fixed
> NUM_SYS_INIT_PACKETS = define already and is fixed
> (sizeof(struct iris_hfi_packet) + sizeof(u32) also fixed
> 
> There's nothing to calculate here - you can just bung it into a define at the
> top of the file and use the resulting HFI_PACKET_SIZE directly.
Looks good.
> 
>> +    hdr = kzalloc(packet_size, GFP_KERNEL);
>> +    if (!hdr)
>> +        return -ENOMEM;
>> +
>> +    iris_hfi_gen2_packet_sys_init(core, hdr);
>> +    ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);
>> +
>> +    kfree(hdr);
>> +
>> +    return ret;
>> +}
>> +
>> +static int iris_hfi_gen2_sys_image_version(struct iris_core *core)
>> +{
>> +    struct iris_hfi_header *hdr;
>> +    u32 packet_size;
>> +    int ret;
>> +
>> +    packet_size = sizeof(*hdr) + sizeof(struct iris_hfi_packet);
> 
> ditto
> 
>> +    hdr = kzalloc(packet_size, GFP_KERNEL);
>> +    if (!hdr)
>> +        return -ENOMEM;
>> +
>> +    iris_hfi_gen2_packet_image_version(core, hdr);
>> +    ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);
>> +
>> +    kfree(hdr);
>> +
>> +    return ret;
>> +}
>> +
>> +static int iris_hfi_gen2_sys_interframe_powercollapse(struct iris_core *core)
>> +{
>> +    struct iris_hfi_header *hdr;
>> +    u32 packet_size;
>> +    int ret;
>> +
>> +    packet_size = sizeof(*hdr) + sizeof(struct iris_hfi_packet) + sizeof(u32);
>> +    hdr = kzalloc(packet_size, GFP_KERNEL);
>> +    if (!hdr)
>> +        return -ENOMEM;
>> +
>> +    iris_hfi_gen2_packet_sys_interframe_powercollapse(core, hdr);
>> +    ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);
>> +
>> +    kfree(hdr);
>> +
>> +    return ret;
>> +}
>> +
>> +static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = {
>> +    .sys_init = iris_hfi_gen2_sys_init,
>> +    .sys_image_version = iris_hfi_gen2_sys_image_version,
>> +    .sys_interframe_powercollapse = iris_hfi_gen2_sys_interframe_powercollapse,
>> +};
>> +
>> +void iris_hfi_gen2_command_ops_init(struct iris_core *core)
>> +{
>> +    core->hfi_ops = &iris_hfi_gen2_command_ops;
>> +}
>>     struct iris_inst *iris_hfi_gen2_get_instance(void)
>>   {
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
>> b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
>> new file mode 100644
>> index 000000000000..3e3e4ddfe21f
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
>> @@ -0,0 +1,46 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#ifndef _IRIS_HFI_GEN2_DEFINES_H_
>> +#define _IRIS_HFI_GEN2_DEFINES_H_
>> +
>> +#include <linux/types.h>
>> +
>> +#define HFI_VIDEO_ARCH_LX            0x1
>> +
>> +#define HFI_CMD_BEGIN                0x01000000
>> +#define HFI_CMD_INIT                0x01000001
>> +#define HFI_CMD_END                0x01FFFFFF
>> +
>> +#define HFI_PROP_BEGIN                0x03000000
>> +#define HFI_PROP_IMAGE_VERSION            0x03000001
>> +#define HFI_PROP_INTRA_FRAME_POWER_COLLAPSE    0x03000002
>> +#define HFI_PROP_UBWC_MAX_CHANNELS        0x03000003
>> +#define HFI_PROP_UBWC_MAL_LENGTH        0x03000004
>> +#define HFI_PROP_UBWC_HBB            0x03000005
>> +#define HFI_PROP_UBWC_BANK_SWZL_LEVEL1        0x03000006
>> +#define HFI_PROP_UBWC_BANK_SWZL_LEVEL2        0x03000007
>> +#define HFI_PROP_UBWC_BANK_SWZL_LEVEL3        0x03000008
>> +#define HFI_PROP_UBWC_BANK_SPREADING        0x03000009
>> +#define HFI_PROP_END                0x03FFFFFF
>> +
>> +#define HFI_SYSTEM_ERROR_BEGIN            0x05000000
>> +#define HFI_SYS_ERROR_WD_TIMEOUT        0x05000001
>> +#define HFI_SYSTEM_ERROR_END            0x05FFFFFF
>> +
>> +enum hfi_packet_firmware_flags {
>> +    HFI_FW_FLAGS_SUCCESS            = 0x00000001,
>> +    HFI_FW_FLAGS_INFORMATION        = 0x00000002,
>> +    HFI_FW_FLAGS_SESSION_ERROR        = 0x00000004,
>> +    HFI_FW_FLAGS_SYSTEM_ERROR        = 0x00000008,
>> +};
>> +
>> +struct hfi_debug_header {
>> +    u32 size;
>> +    u32 debug_level;
>> +    u32 reserved[2];
>> +};
>> +
>> +#endif
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c
>> b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c
>> new file mode 100644
>> index 000000000000..8266eae5ff94
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c
>> @@ -0,0 +1,164 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#include "iris_hfi_common.h"
>> +#include "iris_hfi_gen2.h"
>> +#include "iris_hfi_gen2_packet.h"
>> +
>> +static void iris_hfi_gen2_create_header(struct iris_hfi_header *hdr,
>> +                    u32 session_id, u32 header_id)
>> +{
>> +    memset(hdr, 0, sizeof(*hdr));
>> +
>> +    hdr->size = sizeof(*hdr);
>> +    hdr->session_id = session_id;
>> +    hdr->header_id = header_id;
>> +    hdr->num_packets = 0;
>> +}
>> +
>> +static void iris_hfi_gen2_create_packet(struct iris_hfi_header *hdr, u32
>> pkt_type,
>> +                    u32 pkt_flags, u32 payload_type, u32 port,
>> +                    u32 packet_id, void *payload, u32 payload_size)
>> +{
>> +    struct iris_hfi_packet *pkt;
>> +    u32 pkt_size;
>> +
>> +    pkt = (struct iris_hfi_packet *)((u8 *)hdr + hdr->size);
>> +    pkt_size = sizeof(*pkt) + payload_size;
>> +
>> +    memset(pkt, 0, pkt_size);
>> +    pkt->size = pkt_size;
>> +    pkt->type = pkt_type;
>> +    pkt->flags = pkt_flags;
>> +    pkt->payload_info = payload_type;
>> +    pkt->port = port;
>> +    pkt->packet_id = packet_id;
>> +    if (payload_size)
>> +        memcpy(&pkt->payload[0], payload, payload_size);
> 
> Do you know that the bounds here are always correct => sizeof(pkt->payload) >=
> payload_size always ?
payload_size would be either of sizeof(u32) or sizeof(iris_hfi_buffer). We can
safely consider it as less than size of pkt->payload.
> 
>> +
>> +    hdr->num_packets++;
>> +    hdr->size += pkt->size;
>> +}
>> +
>> +void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct
>> iris_hfi_header *hdr)
>> +{
>> +    u32 payload = 0;
>> +
>> +    iris_hfi_gen2_create_header(hdr, 0, core->header_id++);
>> +
>> +    payload = HFI_VIDEO_ARCH_LX;
>> +    iris_hfi_gen2_create_packet(hdr,
>> +                    HFI_CMD_INIT,
>> +                    (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
>> +                    HFI_HOST_FLAGS_INTR_REQUIRED |
>> +                    HFI_HOST_FLAGS_NON_DISCARDABLE),
>> +                    HFI_PAYLOAD_U32,
>> +                    HFI_PORT_NONE,
>> +                    core->packet_id++,
>> +                    &payload,
>> +                    sizeof(u32));
>> +
>> +    payload = core->iris_platform_data->ubwc_config->max_channels;
>> +    iris_hfi_gen2_create_packet(hdr,
>> +                    HFI_PROP_UBWC_MAX_CHANNELS,
>> +                    HFI_HOST_FLAGS_NONE,
>> +                    HFI_PAYLOAD_U32,
>> +                    HFI_PORT_NONE,
>> +                    core->packet_id++,
>> +                    &payload,
>> +                    sizeof(u32));
>> +
>> +    payload = core->iris_platform_data->ubwc_config->mal_length;
>> +    iris_hfi_gen2_create_packet(hdr,
>> +                    HFI_PROP_UBWC_MAL_LENGTH,
>> +                    HFI_HOST_FLAGS_NONE,
>> +                    HFI_PAYLOAD_U32,
>> +                    HFI_PORT_NONE,
>> +                    core->packet_id++,
>> +                    &payload,
>> +                    sizeof(u32));
>> +
>> +    payload = core->iris_platform_data->ubwc_config->highest_bank_bit;
>> +    iris_hfi_gen2_create_packet(hdr,
>> +                    HFI_PROP_UBWC_HBB,
>> +                    HFI_HOST_FLAGS_NONE,
>> +                    HFI_PAYLOAD_U32,
>> +                    HFI_PORT_NONE,
>> +                    core->packet_id++,
>> +                    &payload,
>> +                    sizeof(u32));
>> +
>> +    payload = core->iris_platform_data->ubwc_config->bank_swzl_level;
>> +    iris_hfi_gen2_create_packet(hdr,
>> +                    HFI_PROP_UBWC_BANK_SWZL_LEVEL1,
>> +                    HFI_HOST_FLAGS_NONE,
>> +                    HFI_PAYLOAD_U32,
>> +                    HFI_PORT_NONE,
>> +                    core->packet_id++,
>> +                    &payload,
>> +                    sizeof(u32));
>> +
>> +    payload = core->iris_platform_data->ubwc_config->bank_swz2_level;
>> +    iris_hfi_gen2_create_packet(hdr,
>> +                    HFI_PROP_UBWC_BANK_SWZL_LEVEL2,
>> +                    HFI_HOST_FLAGS_NONE,
>> +                    HFI_PAYLOAD_U32,
>> +                    HFI_PORT_NONE,
>> +                    core->packet_id++,
>> +                    &payload,
>> +                    sizeof(u32));
>> +
>> +    payload = core->iris_platform_data->ubwc_config->bank_swz3_level;
>> +    iris_hfi_gen2_create_packet(hdr,
>> +                    HFI_PROP_UBWC_BANK_SWZL_LEVEL3,
>> +                    HFI_HOST_FLAGS_NONE,
>> +                    HFI_PAYLOAD_U32,
>> +                    HFI_PORT_NONE,
>> +                    core->packet_id++,
>> +                    &payload,
>> +                    sizeof(u32));
>> +
>> +    payload = core->iris_platform_data->ubwc_config->bank_spreading;
>> +    iris_hfi_gen2_create_packet(hdr,
>> +                    HFI_PROP_UBWC_BANK_SPREADING,
>> +                    HFI_HOST_FLAGS_NONE,
>> +                    HFI_PAYLOAD_U32,
>> +                    HFI_PORT_NONE,
>> +                    core->packet_id++,
>> +                    &payload,
>> +                    sizeof(u32));
>> +}
>> +
>> +void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct
>> iris_hfi_header *hdr)
>> +{
>> +    iris_hfi_gen2_create_header(hdr, 0, core->header_id++);
>> +
>> +    iris_hfi_gen2_create_packet(hdr,
>> +                    HFI_PROP_IMAGE_VERSION,
>> +                    (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
>> +                    HFI_HOST_FLAGS_INTR_REQUIRED |
>> +                    HFI_HOST_FLAGS_GET_PROPERTY),
>> +                    HFI_PAYLOAD_NONE,
>> +                    HFI_PORT_NONE,
>> +                    core->packet_id++,
>> +                    NULL, 0);
>> +}
>> +
>> +void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core,
>> +                               struct iris_hfi_header *hdr)
>> +{
>> +    u32 payload = 1; /* HFI_TRUE */
>> +
>> +    iris_hfi_gen2_create_header(hdr, 0 /*session_id*/, core->header_id++);
>> +
>> +    iris_hfi_gen2_create_packet(hdr,
>> +                    HFI_PROP_INTRA_FRAME_POWER_COLLAPSE,
>> +                    HFI_HOST_FLAGS_NONE,
>> +                    HFI_PAYLOAD_U32,
>> +                    HFI_PORT_NONE,
>> +                    core->packet_id++,
>> +                    &payload,
>> +                    sizeof(u32));
>> +}
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h
>> b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h
>> new file mode 100644
>> index 000000000000..eba109efeb76
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h
>> @@ -0,0 +1,69 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#ifndef _IRIS_HFI_GEN2_PACKET_H_
>> +#define _IRIS_HFI_GEN2_PACKET_H_
>> +
>> +#include "iris_hfi_gen2_defines.h"
>> +
>> +struct iris_core;
>> +
>> +/**
>> + * struct iris_hfi_header
>> + *
>> + * @size: size of the total packet in bytes including hfi_header
>> + * @session_id: For session level hfi_header session_id is non-zero.
>> + *                For  system level hfi_header session_id is zero.
>> + * @header_id: unique header id for each hfi_header
>> + * @reserved: reserved for future use
>> + * @num_packets: number of hfi_packet that are included with the hfi_header
>> + */
>> +struct iris_hfi_header {
>> +    u32 size;
>> +    u32 session_id;
>> +    u32 header_id;
>> +    u32 reserved[4];
>> +    u32 num_packets;
>> +};
>> +
>> +/**
>> + * struct iris_hfi_packet
>> + *
>> + * @size: size of the hfi_packet in bytes including payload
>> + * @type: one of the below hfi_packet types:
>> + *        HFI_CMD_*,
>> + *        HFI_PROP_*,
>> + *        HFI_ERROR_*,
>> + *        HFI_INFO_*,
>> + *        HFI_SYS_ERROR_*
>> + * @flags: hfi_packet flags. It is represented as bit masks.
>> + *         host packet flags are "enum hfi_packet_host_flags"
>> + *         firmware packet flags are "enum hfi_packet_firmware_flags"
>> + * @payload_info: payload information indicated by "enum
>> hfi_packet_payload_info"
>> + * @port: hfi_packet port type indicated by "enum hfi_packet_port_type"
>> + *        This is bitmask and may be applicable to multiple ports.
>> + * @packet_id: host hfi_packet contains unique packet id.
>> + *             firmware returns host packet id in response packet
>> + *             wherever applicable. If not applicable firmware sets it to zero.
>> + * @reserved: reserved for future use.
>> + * @payload: flexible array of payload having additional packet information.
>> + */
>> +struct iris_hfi_packet {
>> +    u32 size;
>> +    u32 type;
>> +    u32 flags;
>> +    u32 payload_info;
>> +    u32 port;
>> +    u32 packet_id;
>> +    u32 reserved[2];
>> +    u32 payload[];
>> +};
>> +
>> +void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct
>> iris_hfi_header *hdr);
>> +void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct
>> iris_hfi_header *hdr);
>> +void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core,
>> +                               struct iris_hfi_header *hdr);
>> +
>> +#endif
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
>> b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
>> new file mode 100644
>> index 000000000000..e208a5ae664a
>> --- /dev/null
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
>> @@ -0,0 +1,229 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#include "iris_hfi_gen2.h"
>> +#include "iris_hfi_gen2_defines.h"
>> +#include "iris_hfi_gen2_packet.h"
>> +#include "iris_vpu_common.h"
>> +
>> +struct iris_hfi_gen2_core_hfi_range {
>> +    u32 begin;
>> +    u32 end;
>> +    int (*handle)(struct iris_core *core, struct iris_hfi_packet *pkt);
>> +};
>> +
>> +static int iris_hfi_gen2_validate_packet(u8 *response_pkt, u8 *core_resp_pkt)
>> +{
>> +    u32 response_pkt_size = 0;
>> +    u8 *response_limit;
>> +
>> +    response_limit = core_resp_pkt + IFACEQ_CORE_PKT_SIZE;
>> +
>> +    response_pkt_size = *(u32 *)response_pkt;
>> +    if (!response_pkt_size)
>> +        return -EINVAL;
>> +
>> +    if (response_pkt_size < sizeof(struct iris_hfi_packet))
>> +        return -EINVAL;
>> +
>> +    if (response_pkt + response_pkt_size > response_limit)
>> +        return -EINVAL;
>> +
>> +    return 0;
>> +}
>> +
>> +static int iris_hfi_gen2_validate_hdr_packet(struct iris_core *core, struct
>> iris_hfi_header *hdr)
>> +{
>> +    struct iris_hfi_packet *packet;
>> +    int i, ret = 0;
>> +    u8 *pkt;
>> +
>> +    if (hdr->size < sizeof(*hdr) + sizeof(*packet))
>> +        return -EINVAL;
>> +
>> +    pkt = (u8 *)((u8 *)hdr + sizeof(*hdr));
>> +
>> +    for (i = 0; i < hdr->num_packets; i++) {
>> +        packet = (struct iris_hfi_packet *)pkt;
>> +        ret = iris_hfi_gen2_validate_packet(pkt, core->response_packet);
>> +        if (ret)
>> +            return ret;
>> +
>> +        pkt += packet->size;
>> +    }
>> +
>> +    return ret;
>> +}
>> +
>> +static int iris_hfi_gen2_handle_system_error(struct iris_core *core,
>> +                         struct iris_hfi_packet *pkt)
>> +{
>> +    dev_err(core->dev, "received system error of type %#x\n", pkt->type);
>> +
>> +    iris_change_core_state(core, IRIS_CORE_ERROR);
>> +    schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10));
>> +
>> +    return 0;
>> +}
>> +
>> +static int iris_hfi_gen2_handle_system_init(struct iris_core *core,
>> +                        struct iris_hfi_packet *pkt)
>> +{
>> +    if (!(pkt->flags & HFI_FW_FLAGS_SUCCESS)) {
>> +        iris_change_core_state(core, IRIS_CORE_ERROR);
>> +        return 0;
>> +    }
>> +
>> +    complete(&core->core_init_done);
>> +
>> +    return 0;
>> +}
>> +
>> +static int iris_hfi_gen2_handle_image_version_property(struct iris_core *core,
>> +                               struct iris_hfi_packet *pkt)
>> +{
>> +    char fw_version[IRIS_FW_VERSION_LENGTH];
>> +    u8 *str_image_version;
>> +    u32 req_bytes;
>> +    u32 i = 0;
>> +
>> +    req_bytes = pkt->size - sizeof(*pkt);
>> +    if (req_bytes < IRIS_FW_VERSION_LENGTH - 1)
>> +        return -EINVAL;
>> +
>> +    str_image_version = (u8 *)pkt + sizeof(*pkt);
>> +
>> +    for (i = 0; i < IRIS_FW_VERSION_LENGTH - 1; i++) {
>> +        if (str_image_version[i] != '\0')
>> +            fw_version[i] = str_image_version[i];
>> +        else
>> +            fw_version[i] = ' ';
>> +    }
>> +    fw_version[i] = '\0';
>> +
>> +    dev_dbg(core->dev, "firmware version: %s\n", fw_version);
>> +
>> +    return 0;
>> +}
>> +
>> +static int iris_hfi_gen2_handle_system_property(struct iris_core *core,
>> +                        struct iris_hfi_packet *pkt)
>> +{
>> +    int ret = 0;
>> +
>> +    switch (pkt->type) {
>> +    case HFI_PROP_IMAGE_VERSION:
>> +        ret = iris_hfi_gen2_handle_image_version_property(core, pkt);
>> +        break;
>> +    default:
>> +        break;
>> +    }
>> +
>> +    return ret;
>> +}
>> +
>> +static int iris_hfi_gen2_handle_system_response(struct iris_core *core,
>> +                        struct iris_hfi_header *hdr)
>> +{
>> +    struct iris_hfi_packet *packet;
>> +    u8 *pkt, *start_pkt;
>> +    int ret = 0;
>> +    int i, j;
>> +    static const struct iris_hfi_gen2_core_hfi_range range[] = {
>> +        {HFI_SYSTEM_ERROR_BEGIN, HFI_SYSTEM_ERROR_END,
>> iris_hfi_gen2_handle_system_error },
>> +        {HFI_PROP_BEGIN,         HFI_PROP_END,
>> iris_hfi_gen2_handle_system_property },
>> +        {HFI_CMD_BEGIN,          HFI_CMD_END,
>> iris_hfi_gen2_handle_system_init },
>> +    };
>> +
>> +    start_pkt = (u8 *)((u8 *)hdr + sizeof(*hdr));
>> +    for (i = 0; i < ARRAY_SIZE(range); i++) {
>> +        pkt = start_pkt;
>> +        for (j = 0; j < hdr->num_packets; j++) {
>> +            packet = (struct iris_hfi_packet *)pkt;
>> +            if (packet->flags & HFI_FW_FLAGS_SYSTEM_ERROR) {
>> +                ret = iris_hfi_gen2_handle_system_error(core, packet);
>> +                return ret;
>> +            }
>> +
>> +            if (packet->type > range[i].begin && packet->type < range[i].end) {
>> +                ret = range[i].handle(core, packet);
>> +                if (ret)
>> +                    return ret;
>> +
>> +                if (packet->type >  HFI_SYSTEM_ERROR_BEGIN &&
>> +                    packet->type < HFI_SYSTEM_ERROR_END)
>> +                    return 0;
>> +            }
>> +            pkt += packet->size;
>> +        }
>> +    }
> 
> You step the pkt pointer on each iteration of the j loop but then reinitialise
> it to the original start_pkt inside of each i loop.
> 
> So you'll always process the same packet in the i loop no ?
> 
> Is that the intention ?
Yes, thats the idea. Driver should parse system error among all the packets,
followed by properties associated then the command.
>> +
>> +    return ret;
>> +}
>> +
>> +static int iris_hfi_gen2_handle_response(struct iris_core *core, void *response)
>> +{
>> +    struct iris_hfi_header *hdr;
>> +    int ret;
>> +
>> +    hdr = (struct iris_hfi_header *)response;
>> +    ret = iris_hfi_gen2_validate_hdr_packet(core, hdr);
>> +    if (ret)
>> +        return iris_hfi_gen2_handle_system_error(core, NULL);
>> +
>> +    return iris_hfi_gen2_handle_system_response(core, hdr);
>> +}
>> +
>> +static void iris_hfi_gen2_flush_debug_queue(struct iris_core *core, u8 *packet)
>> +{
>> +    struct hfi_debug_header *pkt;
>> +    u8 *log;
>> +
>> +    while (!iris_hfi_queue_dbg_read(core, packet)) {
>> +        pkt = (struct hfi_debug_header *)packet;
>> +
>> +        if (pkt->size < sizeof(*pkt))
>> +            continue;
>> +
>> +        if (pkt->size >= IFACEQ_CORE_PKT_SIZE)
>> +            continue;
>> +
>> +        packet[pkt->size] = '\0';
>> +        log = (u8 *)packet + sizeof(*pkt) + 1;
>> +        dev_dbg(core->dev, "%s", log);
>> +    }
>> +}
> 
> This more of a busy/wait than a flush. I asked previously how you know the other
> usage of iris_hfi_queue_dbg_read() would break. Similar question here, also is
> the "popping" of the log/stack/whatever-you-call-it that
> iris_hfi_queue_dbg_read() consumes immediate or can it stall ?
> 
> Do you need to have some kind of delay between reads ?
The idea is to read the debug packets while handling response from firmware.
Lets say driver read till read index equals write index, and there are more
debug packets written later, then the same would be popped in next response
handling.
> 
> I really asking how you know this loop terminates, if it needs to be
> error-checked to ensure it terminates and if we you need "inter-frame" delays -
> to stop the CPU spinning while the data is delivered up ?
> 
> 
>> +
>> +static void iris_hfi_gen2_response_handler(struct iris_core *core)
>> +{
>> +    if (iris_vpu_watchdog(core, core->intr_status)) {
>> +        struct iris_hfi_packet pkt = {.type = HFI_SYS_ERROR_WD_TIMEOUT};
>> +
>> +        dev_err(core->dev, "cpu watchdog error received\n");
>> +        iris_change_core_state(core, IRIS_CORE_ERROR);
>> +        iris_hfi_gen2_handle_system_error(core, &pkt);
>> +
>> +        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);
>> +        if (core->state != IRIS_CORE_INIT)
>> +            break;
>> +        memset(core->response_packet, 0, sizeof(struct iris_hfi_header));
>> +    }
>> +
>> +    iris_hfi_gen2_flush_debug_queue(core, core->response_packet);
>> +}
>> +
>> +static const struct iris_hfi_response_ops iris_hfi_gen2_response_ops = {
>> +    .hfi_response_handler = iris_hfi_gen2_response_handler,
>> +};
>> +
>> +void iris_hfi_gen2_response_ops_init(struct iris_core *core)
>> +{
>> +    core->hfi_response_ops = &iris_hfi_gen2_response_ops;
>> +}
>> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c
>> b/drivers/media/platform/qcom/iris/iris_hfi_queue.c
>> index 11938880b8cd..b24d4640fea9 100644
>> --- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c
>> +++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c
>> @@ -5,6 +5,207 @@
>>     #include "iris_core.h"
>>   #include "iris_hfi_queue.h"
>> +#include "iris_vpu_common.h"
>> +
>> +static int iris_hfi_queue_write(struct iris_iface_q_info *qinfo, void
>> *packet, u32 packet_size)
>> +{
>> +    u32 empty_space, read_idx, write_idx, new_write_idx;
>> +    struct iris_hfi_queue_header *queue;
>> +    u32 *write_ptr;
>> +    u32 residue;
>> +
>> +    queue = qinfo->qhdr;
>> +
>> +    read_idx = queue->read_idx * sizeof(u32);
>> +    write_idx = queue->write_idx * sizeof(u32);
>> +
>> +    if (write_idx < read_idx)
>> +        empty_space = read_idx - write_idx;
>> +    else
>> +        empty_space = IFACEQ_QUEUE_SIZE - (write_idx -  read_idx);
>> +    if (empty_space < packet_size)
>> +        return -ENOSPC;
>> +
>> +    queue->tx_req =  0;
>> +
>> +    new_write_idx = write_idx + packet_size;
>> +    write_ptr = (u32 *)((u8 *)qinfo->kernel_vaddr + write_idx);
>> +
>> +    if (write_ptr < (u32 *)qinfo->kernel_vaddr ||
>> +        write_ptr > (u32 *)(qinfo->kernel_vaddr +
>> +        IFACEQ_QUEUE_SIZE))
>> +        return -EINVAL;
>> +
>> +    if (new_write_idx < IFACEQ_QUEUE_SIZE) {
>> +        memcpy(write_ptr, packet, packet_size);
>> +    } else {
>> +        residue = new_write_idx - IFACEQ_QUEUE_SIZE;
>> +        memcpy(write_ptr, packet, (packet_size - residue));
>> +        memcpy(qinfo->kernel_vaddr,
>> +               packet + (packet_size - residue), residue);
>> +        new_write_idx = residue;
>> +    }
>> +
>> +    /* Make sure packet is written before updating the write index */
>> +    mb();
>> +    queue->write_idx = new_write_idx / sizeof(u32);
>> +
>> +    /* Make sure write index is updated before an interrupt is raised */
>> +    mb();
>> +
>> +    return 0;
>> +}
>> +
>> +static int iris_hfi_queue_read(struct iris_iface_q_info *qinfo, void *packet)
>> +{
>> +    u32 read_idx, write_idx, new_read_idx;
>> +    struct iris_hfi_queue_header *queue;
>> +    u32 packet_size, residue;
>> +    u32 receive_request = 0;
>> +    u32 *read_ptr;
>> +    int ret = 0;
>> +
>> +    queue = qinfo->qhdr;
>> +
>> +    if (queue->queue_type == IFACEQ_MSGQ_ID)
>> +        receive_request = 1;
>> +
>> +    read_idx = queue->read_idx * sizeof(u32);
>> +    write_idx = queue->write_idx * sizeof(u32);
>> +
>> +    if (read_idx == write_idx) {
>> +        queue->rx_req = receive_request;
>> +        /* Ensure qhdr is updated in main memory */
>> +        mb();
>> +        return -ENODATA;
>> +    }
>> +
>> +    read_ptr = qinfo->kernel_vaddr + read_idx;
>> +    if (read_ptr < (u32 *)qinfo->kernel_vaddr ||
>> +        read_ptr > (u32 *)(qinfo->kernel_vaddr +
>> +        IFACEQ_QUEUE_SIZE - sizeof(*read_ptr)))
>> +        return -ENODATA;
>> +
>> +    packet_size = *read_ptr;
>> +    if (!packet_size)
>> +        return -EINVAL;
>> +
>> +    new_read_idx = read_idx + packet_size;
>> +    if (packet_size <= IFACEQ_CORE_PKT_SIZE) {
>> +        if (new_read_idx < IFACEQ_QUEUE_SIZE) {
>> +            memcpy(packet, read_ptr, packet_size);
>> +        } else {
>> +            residue = new_read_idx - IFACEQ_QUEUE_SIZE;
>> +            memcpy(packet, read_ptr, (packet_size - residue));
>> +            memcpy((packet + (packet_size - residue)),
>> +                   qinfo->kernel_vaddr, residue);
>> +            new_read_idx = residue;
>> +        }
>> +    } else {
>> +        new_read_idx = write_idx;
>> +        ret = -EBADMSG;
>> +    }
>> +
>> +    queue->rx_req = receive_request;
>> +
>> +    queue->read_idx = new_read_idx / sizeof(u32);
>> +    /* Ensure qhdr is updated in main memory */
>> +    mb();
>> +
>> +    return ret;
>> +}
>> +
>> +int iris_hfi_queue_cmd_write_locked(struct iris_core *core, void *pkt, u32
>> pkt_size)
>> +{
>> +    struct iris_iface_q_info *q_info;
>> +
>> +    if (!mutex_is_locked(&core->lock))
>> +        return -EINVAL;
> 
> Can this function be called without the mutex being locked ?
> 
> If not then you should have some kind of dev_err() with this no ? Otherwise
> browsing the code here IDT this check is needed.
This being driver implicit calls, and as the api suggest to be invoked from
locked context, the check can be dropped.

> 
> I'd suggest either drop or be more noisy about the bug you encountered.
> 
>> +
>> +    if (core->state != IRIS_CORE_INIT)
>> +        return -EINVAL;
>> +
>> +    q_info = &core->command_queue;
>> +    if (!q_info || !q_info->kernel_vaddr || !pkt) {
>> +        dev_err(core->dev, "cannot write to shared command queue\n");
>> +        return -ENODATA;
>> +    }
>> +
>> +    if (!iris_hfi_queue_write(q_info, pkt, pkt_size)) {
>> +        iris_vpu_raise_interrupt(core);
>> +    } else {
>> +        dev_err(core->dev, "queue full\n");
>> +        return -ENODATA;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +int iris_hfi_queue_cmd_write(struct iris_core *core, void *pkt, u32 pkt_size)
>> +{
>> +    int ret;
>> +
>> +    mutex_lock(&core->lock);
>> +    ret = iris_hfi_queue_cmd_write_locked(core, pkt, pkt_size);
>> +    if (ret)
>> +        dev_err(core->dev, "iris_hfi_queue_cmd_write_locked failed with
>> %d\n", ret);
>> +
>> +    mutex_unlock(&core->lock);
>> +
>> +    return ret;
>> +}
>> +
>> +int iris_hfi_queue_msg_read(struct iris_core *core, void *pkt)
>> +{
>> +    struct iris_iface_q_info *q_info;
>> +    int ret = 0;
>> +
>> +    mutex_lock(&core->lock);
>> +    if (core->state != IRIS_CORE_INIT) {
>> +        ret = -EINVAL;
>> +        goto unlock;
>> +    }
>> +
>> +    q_info = &core->message_queue;
>> +    if (iris_hfi_queue_read(q_info, pkt)) {
>> +        ret = -ENODATA;
> 
> Its a very curious response code to return "ENODATA" when you actually have data..
On a good working scenario, NODATA would indicate when all packets are read.
> 
> Why not return
> 
> < 0 err code
> 0 no data
>> 0 data
> 
> ?I do not see that info be useful to caller to make any informative decision. It
just cares for data (then continue) or exit.
> 
>> +        goto unlock;
>> +    }
>> +
>> +unlock:
>> +    mutex_unlock(&core->lock);
>> +
>> +    return ret;
>> +}
>> +
>> +int iris_hfi_queue_dbg_read(struct iris_core *core, void *pkt)
>> +{
>> +    struct iris_iface_q_info *q_info;
>> +    int ret = 0;
>> +
>> +    mutex_lock(&core->lock);
>> +    if (core->state != IRIS_CORE_INIT) {
>> +        ret = -EINVAL;
>> +        goto unlock;
>> +    }
> 
> I'm going to challenge this logic here. Can this function be called except when
> state == IRIS_CORE_INIT ?
> 
> Surely you should get into the IRIS_CORE_INIT state before progressing this far
> into your code's runtime ?
> 
> In which case a plethora of runtime checks for the validatity of your
> state-machine are redundant.
> 
> Far better to make a concrete transition from one state to another than to have
> a bunch of defensive coding checks which are redundant.
> 
> A blanket statement for this driver.
> 
> Please consider.
Certainly. As you know, during the offline reviews, there were few more such
checks and we have dropped them wherever not required. I do not see a possible
case for response thread processing with core in non-init state. Let me revisit
this part and update.
> 
>> +
>> +    q_info = &core->debug_queue;
>> +    if (!q_info || !q_info->kernel_vaddr || !pkt) {
>> +        dev_err(core->dev, "cannot read from shared debug queue\n");
>> +        ret = -ENODATA;
>> +        goto unlock;
>> +    }
>> +
>> +    if (iris_hfi_queue_read(q_info, pkt)) {
> Should this really be returning an error and shoiuld it be the same error as
> above ?
This is explained earlier in this discussion. Same applies here about returning
ENODATA.
> 
>> +        ret = -ENODATA;
>> +        goto unlock;
>> +    }
>> +
>> +unlock:
>> +    mutex_unlock(&core->lock);
>> +
>> +    return ret;
>> +}
> 
> [1]
> Am I reading this function right. It returs -ENODATA to indicate both an error
> state and to indicate termination to the calling function ?
Yes, in both case, the caller would process the packets read so far and continue.
> 
> ---
> bod

Regards,
Vikash
Dikshita Agarwal Sept. 24, 2024, 9:13 a.m. UTC | #4
On 9/5/2024 6:06 PM, Bryan O'Donoghue wrote:
> On 27/08/2024 11:05, Dikshita Agarwal via B4 Relay wrote:
>> +enum hfi_packet_port_type {
>> +    HFI_PORT_NONE        = 0x00000000,
>> +    HFI_PORT_BITSTREAM    = 0x00000001,
>> +    HFI_PORT_RAW        = 0x00000002,
>> +};
>> +
>> +enum hfi_packet_payload_info {
>> +    HFI_PAYLOAD_NONE    = 0x00000000,
>> +    HFI_PAYLOAD_U32        = 0x00000001,
>> +    HFI_PAYLOAD_S32        = 0x00000002,
>> +    HFI_PAYLOAD_U64        = 0x00000003,
>> +    HFI_PAYLOAD_S64        = 0x00000004,
>> +    HFI_PAYLOAD_STRUCTURE    = 0x00000005,
>> +    HFI_PAYLOAD_BLOB    = 0x00000006,
>> +    HFI_PAYLOAD_STRING    = 0x00000007,
>> +    HFI_PAYLOAD_Q16        = 0x00000008,
>> +    HFI_PAYLOAD_U32_ENUM    = 0x00000009,
>> +    HFI_PAYLOAD_32_PACKED    = 0x0000000a,
>> +    HFI_PAYLOAD_U32_ARRAY    = 0x0000000b,
>> +    HFI_PAYLOAD_S32_ARRAY    = 0x0000000c,
>> +    HFI_PAYLOAD_64_PACKED    = 0x0000000d,
>> +};
>> +
>> +enum hfi_packet_host_flags {
>> +    HFI_HOST_FLAGS_NONE            = 0x00000000,
> 
> Are these NONE flags used/necessary ?
> 
> If they are dead enum values, please drop in the next version.
Sure, will check and remove if not needed.
> 
> ---
> bod
diff mbox series

Patch

diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile
index 95f4e92fe085..d1f0b933df3d 100644
--- a/drivers/media/platform/qcom/iris/Makefile
+++ b/drivers/media/platform/qcom/iris/Makefile
@@ -1,12 +1,17 @@ 
 iris-objs += iris_core.o \
              iris_firmware.o \
+             iris_hfi_common.o \
              iris_hfi_gen1_command.o \
+             iris_hfi_gen1_response.o \
              iris_hfi_gen2_command.o \
+             iris_hfi_gen2_packet.o \
+             iris_hfi_gen2_response.o \
              iris_hfi_queue.o \
              iris_platform_sm8250.o \
              iris_platform_sm8550.o \
              iris_probe.o \
              iris_resources.o \
+             iris_state.o \
              iris_vidc.o \
              iris_vpu_common.o \
 
diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c
index 5ad66ac113ae..92458d7f1e36 100644
--- a/drivers/media/platform/qcom/iris/iris_core.c
+++ b/drivers/media/platform/qcom/iris/iris_core.c
@@ -17,6 +17,26 @@  void iris_core_deinit(struct iris_core *core)
 	mutex_unlock(&core->lock);
 }
 
+static int iris_wait_for_system_response(struct iris_core *core)
+{
+	u32 hw_response_timeout_val;
+	int ret;
+
+	if (core->state == IRIS_CORE_ERROR)
+		return -EIO;
+
+	hw_response_timeout_val = core->iris_platform_data->hw_response_timeout;
+
+	ret = wait_for_completion_timeout(&core->core_init_done,
+					  msecs_to_jiffies(hw_response_timeout_val));
+	if (!ret) {
+		iris_change_core_state(core, IRIS_CORE_ERROR);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
 int iris_core_init(struct iris_core *core)
 {
 	int ret;
@@ -44,9 +64,13 @@  int iris_core_init(struct iris_core *core)
 	if (ret)
 		goto error_unload_fw;
 
+	ret = iris_hfi_core_init(core);
+	if (ret)
+		goto error_unload_fw;
+
 	mutex_unlock(&core->lock);
 
-	return 0;
+	return iris_wait_for_system_response(core);
 
 error_unload_fw:
 	iris_fw_unload(core);
diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h
index 13c5932f9110..409f9822807d 100644
--- a/drivers/media/platform/qcom/iris/iris_core.h
+++ b/drivers/media/platform/qcom/iris/iris_core.h
@@ -9,11 +9,15 @@ 
 #include <linux/types.h>
 #include <media/v4l2-device.h>
 
+#include "iris_hfi_common.h"
 #include "iris_hfi_queue.h"
 #include "iris_platform_common.h"
 #include "iris_resources.h"
 #include "iris_state.h"
 
+#define IRIS_FW_VERSION_LENGTH		128
+#define IFACEQ_CORE_PKT_SIZE		(1024 * 4)
+
 /**
  * struct iris_core - holds core parameters valid for all instances
  *
@@ -40,6 +44,14 @@ 
  * @message_queue: shared interface queue to receive responses from firmware
  * @debug_queue: shared interface queue to receive debug info from firmware
  * @lock: a lock for this strucure
+ * @response_packet: a pointer to response packet from fw to driver
+ * @header_id: id of packet header
+ * @packet_id: id of packet
+ * @hfi_ops: iris hfi command ops
+ * @hfi_response_ops: iris hfi response ops
+ * @core_init_done: structure of signal completion for system response
+ * @intr_status: interrupt status
+ * @sys_error_handler: a delayed work for handling system fatal error
  */
 
 struct iris_core {
@@ -66,6 +78,14 @@  struct iris_core {
 	struct iris_iface_q_info		message_queue;
 	struct iris_iface_q_info		debug_queue;
 	struct mutex				lock; /* lock for core related operations */
+	u8					*response_packet;
+	u32					header_id;
+	u32					packet_id;
+	const struct iris_hfi_command_ops	*hfi_ops;
+	const struct iris_hfi_response_ops	*hfi_response_ops;
+	struct completion			core_init_done;
+	u32					intr_status;
+	struct delayed_work			sys_error_handler;
 };
 
 int iris_core_init(struct iris_core *core);
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.c b/drivers/media/platform/qcom/iris/iris_hfi_common.c
new file mode 100644
index 000000000000..a5a28029d8d1
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_hfi_common.c
@@ -0,0 +1,56 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "iris_core.h"
+#include "iris_hfi_common.h"
+#include "iris_vpu_common.h"
+
+int iris_hfi_core_init(struct iris_core *core)
+{
+	const struct iris_hfi_command_ops *hfi_ops = core->hfi_ops;
+	int ret;
+
+	ret = hfi_ops->sys_init(core);
+	if (ret)
+		return ret;
+
+	ret = hfi_ops->sys_image_version(core);
+	if (ret)
+		return ret;
+
+	return hfi_ops->sys_interframe_powercollapse(core);
+}
+
+irqreturn_t iris_hfi_isr(int irq, void *data)
+{
+	disable_irq_nosync(irq);
+
+	return IRQ_WAKE_THREAD;
+}
+
+irqreturn_t iris_hfi_isr_handler(int irq, void *data)
+{
+	struct iris_core *core = data;
+
+	if (!core)
+		return IRQ_NONE;
+
+	mutex_lock(&core->lock);
+	if (core->state != IRIS_CORE_INIT) {
+		mutex_unlock(&core->lock);
+		goto exit;
+	}
+
+	iris_vpu_clear_interrupt(core);
+	mutex_unlock(&core->lock);
+
+	core->hfi_response_ops->hfi_response_handler(core);
+
+exit:
+	if (!iris_vpu_watchdog(core, core->intr_status))
+		enable_irq(irq);
+
+	return IRQ_HANDLED;
+}
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h
new file mode 100644
index 000000000000..c3d5b899cf60
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h
@@ -0,0 +1,60 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _IRIS_HFI_COMMON_H_
+#define _IRIS_HFI_COMMON_H_
+
+#include <linux/types.h>
+#include <media/v4l2-device.h>
+
+struct iris_core;
+
+enum hfi_packet_port_type {
+	HFI_PORT_NONE		= 0x00000000,
+	HFI_PORT_BITSTREAM	= 0x00000001,
+	HFI_PORT_RAW		= 0x00000002,
+};
+
+enum hfi_packet_payload_info {
+	HFI_PAYLOAD_NONE	= 0x00000000,
+	HFI_PAYLOAD_U32		= 0x00000001,
+	HFI_PAYLOAD_S32		= 0x00000002,
+	HFI_PAYLOAD_U64		= 0x00000003,
+	HFI_PAYLOAD_S64		= 0x00000004,
+	HFI_PAYLOAD_STRUCTURE	= 0x00000005,
+	HFI_PAYLOAD_BLOB	= 0x00000006,
+	HFI_PAYLOAD_STRING	= 0x00000007,
+	HFI_PAYLOAD_Q16		= 0x00000008,
+	HFI_PAYLOAD_U32_ENUM	= 0x00000009,
+	HFI_PAYLOAD_32_PACKED	= 0x0000000a,
+	HFI_PAYLOAD_U32_ARRAY	= 0x0000000b,
+	HFI_PAYLOAD_S32_ARRAY	= 0x0000000c,
+	HFI_PAYLOAD_64_PACKED	= 0x0000000d,
+};
+
+enum hfi_packet_host_flags {
+	HFI_HOST_FLAGS_NONE			= 0x00000000,
+	HFI_HOST_FLAGS_INTR_REQUIRED		= 0x00000001,
+	HFI_HOST_FLAGS_RESPONSE_REQUIRED	= 0x00000002,
+	HFI_HOST_FLAGS_NON_DISCARDABLE		= 0x00000004,
+	HFI_HOST_FLAGS_GET_PROPERTY		= 0x00000008,
+};
+
+struct iris_hfi_command_ops {
+	int (*sys_init)(struct iris_core *core);
+	int (*sys_image_version)(struct iris_core *core);
+	int (*sys_interframe_powercollapse)(struct iris_core *core);
+};
+
+struct iris_hfi_response_ops {
+	void (*hfi_response_handler)(struct iris_core *core);
+};
+
+int iris_hfi_core_init(struct iris_core *core);
+
+irqreturn_t iris_hfi_isr(int irq, void *data);
+irqreturn_t iris_hfi_isr_handler(int irq, void *data);
+
+#endif
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1.h
index b02f629a9cdc..15edbb359c71 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1.h
@@ -6,8 +6,11 @@ 
 #ifndef _IRIS_HFI_GEN1_H_
 #define _IRIS_HFI_GEN1_H_
 
+struct iris_core;
 struct iris_inst;
 
+void iris_hfi_gen1_command_ops_init(struct iris_core *core);
+void iris_hfi_gen1_response_ops_init(struct iris_core *core);
 struct iris_inst *iris_hfi_gen1_get_instance(void);
 
 #endif
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
index 20c68f4ffb72..8f045ef56163 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
@@ -4,8 +4,69 @@ 
  */
 
 #include "iris_hfi_gen1.h"
+#include "iris_hfi_gen1_defines.h"
 #include "iris_instance.h"
 
+static int iris_hfi_gen1_sys_init(struct iris_core *core)
+{
+	struct hfi_sys_init_pkt sys_init_pkt;
+
+	sys_init_pkt.hdr.size = sizeof(sys_init_pkt);
+	sys_init_pkt.hdr.pkt_type = HFI_CMD_SYS_INIT;
+	sys_init_pkt.arch_type = HFI_VIDEO_ARCH_OX;
+
+	return iris_hfi_queue_cmd_write_locked(core, &sys_init_pkt, sys_init_pkt.hdr.size);
+}
+
+static int iris_hfi_gen1_sys_image_version(struct iris_core *core)
+{
+	struct hfi_sys_get_property_pkt packet;
+
+	packet.hdr.size = sizeof(packet);
+	packet.hdr.pkt_type = HFI_CMD_SYS_GET_PROPERTY;
+	packet.num_properties = 1;
+	packet.data = HFI_PROPERTY_SYS_IMAGE_VERSION;
+
+	return iris_hfi_queue_cmd_write_locked(core, &packet, packet.hdr.size);
+}
+
+static int iris_hfi_gen1_sys_interframe_powercollapse(struct iris_core *core)
+{
+	struct hfi_sys_set_property_pkt *pkt;
+	struct hfi_enable *hfi;
+	u32 packet_size;
+	u32 ret;
+
+	packet_size = struct_size(pkt, data, 1) + sizeof(*hfi);
+	pkt = kzalloc(packet_size, GFP_KERNEL);
+	if (!pkt)
+		return -ENOMEM;
+
+	hfi = (struct hfi_enable *)&pkt->data[1];
+
+	pkt->hdr.size = packet_size;
+	pkt->hdr.pkt_type = HFI_CMD_SYS_SET_PROPERTY;
+	pkt->num_properties = 1;
+	pkt->data[0] = HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL;
+	hfi->enable = true;
+
+	ret = iris_hfi_queue_cmd_write_locked(core, pkt, pkt->hdr.size);
+	kfree(pkt);
+
+	return ret;
+}
+
+static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = {
+	.sys_init = iris_hfi_gen1_sys_init,
+	.sys_image_version = iris_hfi_gen1_sys_image_version,
+	.sys_interframe_powercollapse = iris_hfi_gen1_sys_interframe_powercollapse,
+};
+
+void iris_hfi_gen1_command_ops_init(struct iris_core *core)
+{
+	core->hfi_ops = &iris_hfi_gen1_command_ops;
+}
+
 struct iris_inst *iris_hfi_gen1_get_instance(void)
 {
 	return kzalloc(sizeof(struct iris_inst), GFP_KERNEL);
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
new file mode 100644
index 000000000000..5c07d6a29863
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
@@ -0,0 +1,94 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _IRIS_HFI_GEN1_DEFINES_H_
+#define _IRIS_HFI_GEN1_DEFINES_H_
+
+#include <linux/types.h>
+
+#define HFI_VIDEO_ARCH_OX				0x1
+#define HFI_ERR_NONE					0x0
+
+#define HFI_CMD_SYS_INIT				0x10001
+#define HFI_CMD_SYS_SET_PROPERTY			0x10005
+#define HFI_CMD_SYS_GET_PROPERTY			0x10006
+
+#define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL		0x5
+#define HFI_PROPERTY_SYS_IMAGE_VERSION			0x6
+
+#define HFI_EVENT_SYS_ERROR				0x1
+
+#define HFI_MSG_SYS_INIT				0x20001
+#define HFI_MSG_SYS_COV					0x20009
+#define HFI_MSG_SYS_PROPERTY_INFO			0x2000a
+
+#define HFI_MSG_EVENT_NOTIFY				0x21001
+
+struct hfi_pkt_hdr {
+	u32 size;
+	u32 pkt_type;
+};
+
+struct hfi_sys_init_pkt {
+	struct hfi_pkt_hdr hdr;
+	u32 arch_type;
+};
+
+struct hfi_sys_set_property_pkt {
+	struct hfi_pkt_hdr hdr;
+	u32 num_properties;
+	u32 data[];
+};
+
+struct hfi_sys_get_property_pkt {
+	struct hfi_pkt_hdr hdr;
+	u32 num_properties;
+	u32 data;
+};
+
+struct hfi_msg_event_notify_pkt {
+	struct hfi_pkt_hdr hdr;
+	u32 event_id;
+	u32 event_data1;
+	u32 event_data2;
+	u32 ext_event_data[];
+};
+
+struct hfi_msg_sys_init_done_pkt {
+	struct hfi_pkt_hdr hdr;
+	u32 error_type;
+	u32 num_properties;
+	u32 data[];
+};
+
+struct hfi_msg_sys_property_info_pkt {
+	struct hfi_pkt_hdr hdr;
+	u32 num_properties;
+	u32 property;
+	u8 data[];
+};
+
+struct hfi_enable {
+	u32 enable;
+};
+
+struct hfi_msg_sys_debug_pkt {
+	struct hfi_pkt_hdr hdr;
+	u32 msg_type;
+	u32 msg_size;
+	u32 time_stamp_hi;
+	u32 time_stamp_lo;
+	u8 msg_data[];
+};
+
+struct hfi_msg_sys_coverage_pkt {
+	struct hfi_pkt_hdr hdr;
+	u32 msg_size;
+	u32 time_stamp_hi;
+	u32 time_stamp_lo;
+	u8 msg_data[];
+};
+
+#endif
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
new file mode 100644
index 000000000000..3eb2ce99c614
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
@@ -0,0 +1,174 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "iris_hfi_gen1.h"
+#include "iris_hfi_gen1_defines.h"
+#include "iris_instance.h"
+
+static void
+iris_hfi_gen1_sys_event_notify(struct iris_core *core, void *packet)
+{
+	struct hfi_msg_event_notify_pkt *pkt = packet;
+
+	if (pkt->event_id == HFI_EVENT_SYS_ERROR)
+		dev_err(core->dev, "sys error (type: %x, data1:%x, data2:%x)\n",
+			pkt->event_id, pkt->event_data1, pkt->event_data2);
+
+	iris_change_core_state(core, IRIS_CORE_ERROR);
+	schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10));
+}
+
+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) {
+		iris_change_core_state(core, IRIS_CORE_ERROR);
+		return;
+	}
+
+	complete(&core->core_init_done);
+}
+
+static void
+iris_hfi_gen1_sys_get_prop_image_version(struct iris_core *core,
+					 struct hfi_msg_sys_property_info_pkt *pkt)
+{
+	char fw_version[IRIS_FW_VERSION_LENGTH];
+	u8 *str_image_version;
+	int req_bytes;
+	u32 i;
+
+	req_bytes = pkt->hdr.size - sizeof(*pkt);
+
+	if (req_bytes < IRIS_FW_VERSION_LENGTH - 1 || !pkt->data[0] || pkt->num_properties > 1)
+		/* bad packet */
+		return;
+
+	str_image_version = pkt->data;
+	if (!str_image_version)
+		return;
+
+	for (i = 0; i < IRIS_FW_VERSION_LENGTH - 1; i++) {
+		if (str_image_version[i] != '\0')
+			fw_version[i] = str_image_version[i];
+		else
+			fw_version[i] = ' ';
+	}
+	fw_version[i] = '\0';
+
+	dev_dbg(core->dev, "firmware version: %s\n", fw_version);
+}
+
+static void iris_hfi_gen1_sys_property_info(struct iris_core *core, void *packet)
+{
+	struct hfi_msg_sys_property_info_pkt *pkt = packet;
+
+	if (!pkt->num_properties) {
+		dev_dbg(core->dev, "no properties\n");
+		return;
+	}
+
+	switch (pkt->property) {
+	case HFI_PROPERTY_SYS_IMAGE_VERSION:
+		iris_hfi_gen1_sys_get_prop_image_version(core, pkt);
+		break;
+	default:
+		dev_dbg(core->dev, "unknown property data\n");
+		break;
+	}
+}
+
+struct iris_hfi_gen1_response_pkt_info {
+	u32 pkt;
+	u32 pkt_sz;
+};
+
+static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = {
+	{
+	 .pkt = HFI_MSG_EVENT_NOTIFY,
+	 .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt),
+	},
+	{
+	 .pkt = HFI_MSG_SYS_INIT,
+	 .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt),
+	},
+	{
+	 .pkt = HFI_MSG_SYS_PROPERTY_INFO,
+	 .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt),
+	},
+};
+
+static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response)
+{
+	const struct iris_hfi_gen1_response_pkt_info *pkt_info;
+	struct device *dev = core->dev;
+	struct hfi_pkt_hdr *hdr;
+	bool found = false;
+	unsigned int i;
+
+	hdr = (struct hfi_pkt_hdr *)response;
+
+	for (i = 0; i < ARRAY_SIZE(pkt_infos); i++) {
+		pkt_info = &pkt_infos[i];
+		if (pkt_info->pkt != hdr->pkt_type)
+			continue;
+		found = true;
+		break;
+	}
+
+	if (!found || hdr->size < pkt_info->pkt_sz) {
+		dev_err(dev, "bad packet size (%d should be %d, pkt type:%x, found %d)\n",
+			hdr->size, pkt_info->pkt_sz, hdr->pkt_type, found);
+
+		return;
+	}
+
+	if (hdr->pkt_type == HFI_MSG_SYS_INIT)
+		iris_hfi_gen1_sys_init_done(core, hdr);
+	else if (hdr->pkt_type == HFI_MSG_SYS_PROPERTY_INFO)
+		iris_hfi_gen1_sys_property_info(core, hdr);
+	else if (hdr->pkt_type == HFI_MSG_EVENT_NOTIFY)
+		iris_hfi_gen1_sys_event_notify(core, hdr);
+}
+
+static void iris_hfi_gen1_flush_debug_queue(struct iris_core *core, u8 *packet)
+{
+	struct hfi_msg_sys_coverage_pkt *pkt;
+
+	while (!iris_hfi_queue_dbg_read(core, packet)) {
+		pkt = (struct hfi_msg_sys_coverage_pkt *)packet;
+
+		if (pkt->hdr.pkt_type != HFI_MSG_SYS_COV) {
+			struct hfi_msg_sys_debug_pkt *pkt =
+				(struct hfi_msg_sys_debug_pkt *)packet;
+
+			dev_dbg(core->dev, "%s", pkt->msg_data);
+		}
+	}
+}
+
+static 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);
+		if (core->state != IRIS_CORE_INIT)
+			break;
+
+		memset(core->response_packet, 0, sizeof(struct hfi_pkt_hdr));
+	}
+
+	iris_hfi_gen1_flush_debug_queue(core, core->response_packet);
+}
+
+static const struct iris_hfi_response_ops iris_hfi_gen1_response_ops = {
+	.hfi_response_handler = iris_hfi_gen1_response_handler,
+};
+
+void iris_hfi_gen1_response_ops_init(struct iris_core *core)
+{
+	core->hfi_response_ops = &iris_hfi_gen1_response_ops;
+}
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h
index 4f9748cbe0e3..6ec83984fda9 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.h
@@ -8,6 +8,8 @@ 
 
 #include "iris_instance.h"
 
+struct iris_core;
+
 /**
  * struct iris_inst_hfi_gen2 - holds per video instance parameters for hfi_gen2
  *
@@ -17,6 +19,8 @@  struct iris_inst_hfi_gen2 {
 	struct iris_inst		inst;
 };
 
+void iris_hfi_gen2_command_ops_init(struct iris_core *core);
+void iris_hfi_gen2_response_ops_init(struct iris_core *core);
 struct iris_inst *iris_hfi_gen2_get_instance(void);
 
 #endif
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
index 3ee33c8befae..807266858d93 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
@@ -4,6 +4,78 @@ 
  */
 
 #include "iris_hfi_gen2.h"
+#include "iris_hfi_gen2_packet.h"
+
+#define NUM_SYS_INIT_PACKETS 8
+
+static int iris_hfi_gen2_sys_init(struct iris_core *core)
+{
+	struct iris_hfi_header *hdr;
+	u32 packet_size;
+	int ret;
+
+	packet_size = sizeof(*hdr) +
+		NUM_SYS_INIT_PACKETS * (sizeof(struct iris_hfi_packet) + sizeof(u32));
+	hdr = kzalloc(packet_size, GFP_KERNEL);
+	if (!hdr)
+		return -ENOMEM;
+
+	iris_hfi_gen2_packet_sys_init(core, hdr);
+	ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);
+
+	kfree(hdr);
+
+	return ret;
+}
+
+static int iris_hfi_gen2_sys_image_version(struct iris_core *core)
+{
+	struct iris_hfi_header *hdr;
+	u32 packet_size;
+	int ret;
+
+	packet_size = sizeof(*hdr) + sizeof(struct iris_hfi_packet);
+	hdr = kzalloc(packet_size, GFP_KERNEL);
+	if (!hdr)
+		return -ENOMEM;
+
+	iris_hfi_gen2_packet_image_version(core, hdr);
+	ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);
+
+	kfree(hdr);
+
+	return ret;
+}
+
+static int iris_hfi_gen2_sys_interframe_powercollapse(struct iris_core *core)
+{
+	struct iris_hfi_header *hdr;
+	u32 packet_size;
+	int ret;
+
+	packet_size = sizeof(*hdr) + sizeof(struct iris_hfi_packet) + sizeof(u32);
+	hdr = kzalloc(packet_size, GFP_KERNEL);
+	if (!hdr)
+		return -ENOMEM;
+
+	iris_hfi_gen2_packet_sys_interframe_powercollapse(core, hdr);
+	ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size);
+
+	kfree(hdr);
+
+	return ret;
+}
+
+static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = {
+	.sys_init = iris_hfi_gen2_sys_init,
+	.sys_image_version = iris_hfi_gen2_sys_image_version,
+	.sys_interframe_powercollapse = iris_hfi_gen2_sys_interframe_powercollapse,
+};
+
+void iris_hfi_gen2_command_ops_init(struct iris_core *core)
+{
+	core->hfi_ops = &iris_hfi_gen2_command_ops;
+}
 
 struct iris_inst *iris_hfi_gen2_get_instance(void)
 {
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
new file mode 100644
index 000000000000..3e3e4ddfe21f
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
@@ -0,0 +1,46 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _IRIS_HFI_GEN2_DEFINES_H_
+#define _IRIS_HFI_GEN2_DEFINES_H_
+
+#include <linux/types.h>
+
+#define HFI_VIDEO_ARCH_LX			0x1
+
+#define HFI_CMD_BEGIN				0x01000000
+#define HFI_CMD_INIT				0x01000001
+#define HFI_CMD_END				0x01FFFFFF
+
+#define HFI_PROP_BEGIN				0x03000000
+#define HFI_PROP_IMAGE_VERSION			0x03000001
+#define HFI_PROP_INTRA_FRAME_POWER_COLLAPSE	0x03000002
+#define HFI_PROP_UBWC_MAX_CHANNELS		0x03000003
+#define HFI_PROP_UBWC_MAL_LENGTH		0x03000004
+#define HFI_PROP_UBWC_HBB			0x03000005
+#define HFI_PROP_UBWC_BANK_SWZL_LEVEL1		0x03000006
+#define HFI_PROP_UBWC_BANK_SWZL_LEVEL2		0x03000007
+#define HFI_PROP_UBWC_BANK_SWZL_LEVEL3		0x03000008
+#define HFI_PROP_UBWC_BANK_SPREADING		0x03000009
+#define HFI_PROP_END				0x03FFFFFF
+
+#define HFI_SYSTEM_ERROR_BEGIN			0x05000000
+#define HFI_SYS_ERROR_WD_TIMEOUT		0x05000001
+#define HFI_SYSTEM_ERROR_END			0x05FFFFFF
+
+enum hfi_packet_firmware_flags {
+	HFI_FW_FLAGS_SUCCESS			= 0x00000001,
+	HFI_FW_FLAGS_INFORMATION		= 0x00000002,
+	HFI_FW_FLAGS_SESSION_ERROR		= 0x00000004,
+	HFI_FW_FLAGS_SYSTEM_ERROR		= 0x00000008,
+};
+
+struct hfi_debug_header {
+	u32 size;
+	u32 debug_level;
+	u32 reserved[2];
+};
+
+#endif
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c
new file mode 100644
index 000000000000..8266eae5ff94
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c
@@ -0,0 +1,164 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "iris_hfi_common.h"
+#include "iris_hfi_gen2.h"
+#include "iris_hfi_gen2_packet.h"
+
+static void iris_hfi_gen2_create_header(struct iris_hfi_header *hdr,
+					u32 session_id, u32 header_id)
+{
+	memset(hdr, 0, sizeof(*hdr));
+
+	hdr->size = sizeof(*hdr);
+	hdr->session_id = session_id;
+	hdr->header_id = header_id;
+	hdr->num_packets = 0;
+}
+
+static void iris_hfi_gen2_create_packet(struct iris_hfi_header *hdr, u32 pkt_type,
+					u32 pkt_flags, u32 payload_type, u32 port,
+					u32 packet_id, void *payload, u32 payload_size)
+{
+	struct iris_hfi_packet *pkt;
+	u32 pkt_size;
+
+	pkt = (struct iris_hfi_packet *)((u8 *)hdr + hdr->size);
+	pkt_size = sizeof(*pkt) + payload_size;
+
+	memset(pkt, 0, pkt_size);
+	pkt->size = pkt_size;
+	pkt->type = pkt_type;
+	pkt->flags = pkt_flags;
+	pkt->payload_info = payload_type;
+	pkt->port = port;
+	pkt->packet_id = packet_id;
+	if (payload_size)
+		memcpy(&pkt->payload[0], payload, payload_size);
+
+	hdr->num_packets++;
+	hdr->size += pkt->size;
+}
+
+void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_header *hdr)
+{
+	u32 payload = 0;
+
+	iris_hfi_gen2_create_header(hdr, 0, core->header_id++);
+
+	payload = HFI_VIDEO_ARCH_LX;
+	iris_hfi_gen2_create_packet(hdr,
+				    HFI_CMD_INIT,
+				    (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
+				    HFI_HOST_FLAGS_INTR_REQUIRED |
+				    HFI_HOST_FLAGS_NON_DISCARDABLE),
+				    HFI_PAYLOAD_U32,
+				    HFI_PORT_NONE,
+				    core->packet_id++,
+				    &payload,
+				    sizeof(u32));
+
+	payload = core->iris_platform_data->ubwc_config->max_channels;
+	iris_hfi_gen2_create_packet(hdr,
+				    HFI_PROP_UBWC_MAX_CHANNELS,
+				    HFI_HOST_FLAGS_NONE,
+				    HFI_PAYLOAD_U32,
+				    HFI_PORT_NONE,
+				    core->packet_id++,
+				    &payload,
+				    sizeof(u32));
+
+	payload = core->iris_platform_data->ubwc_config->mal_length;
+	iris_hfi_gen2_create_packet(hdr,
+				    HFI_PROP_UBWC_MAL_LENGTH,
+				    HFI_HOST_FLAGS_NONE,
+				    HFI_PAYLOAD_U32,
+				    HFI_PORT_NONE,
+				    core->packet_id++,
+				    &payload,
+				    sizeof(u32));
+
+	payload = core->iris_platform_data->ubwc_config->highest_bank_bit;
+	iris_hfi_gen2_create_packet(hdr,
+				    HFI_PROP_UBWC_HBB,
+				    HFI_HOST_FLAGS_NONE,
+				    HFI_PAYLOAD_U32,
+				    HFI_PORT_NONE,
+				    core->packet_id++,
+				    &payload,
+				    sizeof(u32));
+
+	payload = core->iris_platform_data->ubwc_config->bank_swzl_level;
+	iris_hfi_gen2_create_packet(hdr,
+				    HFI_PROP_UBWC_BANK_SWZL_LEVEL1,
+				    HFI_HOST_FLAGS_NONE,
+				    HFI_PAYLOAD_U32,
+				    HFI_PORT_NONE,
+				    core->packet_id++,
+				    &payload,
+				    sizeof(u32));
+
+	payload = core->iris_platform_data->ubwc_config->bank_swz2_level;
+	iris_hfi_gen2_create_packet(hdr,
+				    HFI_PROP_UBWC_BANK_SWZL_LEVEL2,
+				    HFI_HOST_FLAGS_NONE,
+				    HFI_PAYLOAD_U32,
+				    HFI_PORT_NONE,
+				    core->packet_id++,
+				    &payload,
+				    sizeof(u32));
+
+	payload = core->iris_platform_data->ubwc_config->bank_swz3_level;
+	iris_hfi_gen2_create_packet(hdr,
+				    HFI_PROP_UBWC_BANK_SWZL_LEVEL3,
+				    HFI_HOST_FLAGS_NONE,
+				    HFI_PAYLOAD_U32,
+				    HFI_PORT_NONE,
+				    core->packet_id++,
+				    &payload,
+				    sizeof(u32));
+
+	payload = core->iris_platform_data->ubwc_config->bank_spreading;
+	iris_hfi_gen2_create_packet(hdr,
+				    HFI_PROP_UBWC_BANK_SPREADING,
+				    HFI_HOST_FLAGS_NONE,
+				    HFI_PAYLOAD_U32,
+				    HFI_PORT_NONE,
+				    core->packet_id++,
+				    &payload,
+				    sizeof(u32));
+}
+
+void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_header *hdr)
+{
+	iris_hfi_gen2_create_header(hdr, 0, core->header_id++);
+
+	iris_hfi_gen2_create_packet(hdr,
+				    HFI_PROP_IMAGE_VERSION,
+				    (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
+				    HFI_HOST_FLAGS_INTR_REQUIRED |
+				    HFI_HOST_FLAGS_GET_PROPERTY),
+				    HFI_PAYLOAD_NONE,
+				    HFI_PORT_NONE,
+				    core->packet_id++,
+				    NULL, 0);
+}
+
+void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core,
+						       struct iris_hfi_header *hdr)
+{
+	u32 payload = 1; /* HFI_TRUE */
+
+	iris_hfi_gen2_create_header(hdr, 0 /*session_id*/, core->header_id++);
+
+	iris_hfi_gen2_create_packet(hdr,
+				    HFI_PROP_INTRA_FRAME_POWER_COLLAPSE,
+				    HFI_HOST_FLAGS_NONE,
+				    HFI_PAYLOAD_U32,
+				    HFI_PORT_NONE,
+				    core->packet_id++,
+				    &payload,
+				    sizeof(u32));
+}
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h
new file mode 100644
index 000000000000..eba109efeb76
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h
@@ -0,0 +1,69 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _IRIS_HFI_GEN2_PACKET_H_
+#define _IRIS_HFI_GEN2_PACKET_H_
+
+#include "iris_hfi_gen2_defines.h"
+
+struct iris_core;
+
+/**
+ * struct iris_hfi_header
+ *
+ * @size: size of the total packet in bytes including hfi_header
+ * @session_id: For session level hfi_header session_id is non-zero.
+ *                For  system level hfi_header session_id is zero.
+ * @header_id: unique header id for each hfi_header
+ * @reserved: reserved for future use
+ * @num_packets: number of hfi_packet that are included with the hfi_header
+ */
+struct iris_hfi_header {
+	u32 size;
+	u32 session_id;
+	u32 header_id;
+	u32 reserved[4];
+	u32 num_packets;
+};
+
+/**
+ * struct iris_hfi_packet
+ *
+ * @size: size of the hfi_packet in bytes including payload
+ * @type: one of the below hfi_packet types:
+ *        HFI_CMD_*,
+ *        HFI_PROP_*,
+ *        HFI_ERROR_*,
+ *        HFI_INFO_*,
+ *        HFI_SYS_ERROR_*
+ * @flags: hfi_packet flags. It is represented as bit masks.
+ *         host packet flags are "enum hfi_packet_host_flags"
+ *         firmware packet flags are "enum hfi_packet_firmware_flags"
+ * @payload_info: payload information indicated by "enum hfi_packet_payload_info"
+ * @port: hfi_packet port type indicated by "enum hfi_packet_port_type"
+ *        This is bitmask and may be applicable to multiple ports.
+ * @packet_id: host hfi_packet contains unique packet id.
+ *             firmware returns host packet id in response packet
+ *             wherever applicable. If not applicable firmware sets it to zero.
+ * @reserved: reserved for future use.
+ * @payload: flexible array of payload having additional packet information.
+ */
+struct iris_hfi_packet {
+	u32 size;
+	u32 type;
+	u32 flags;
+	u32 payload_info;
+	u32 port;
+	u32 packet_id;
+	u32 reserved[2];
+	u32 payload[];
+};
+
+void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_header *hdr);
+void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_header *hdr);
+void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core,
+						       struct iris_hfi_header *hdr);
+
+#endif
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
new file mode 100644
index 000000000000..e208a5ae664a
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
@@ -0,0 +1,229 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "iris_hfi_gen2.h"
+#include "iris_hfi_gen2_defines.h"
+#include "iris_hfi_gen2_packet.h"
+#include "iris_vpu_common.h"
+
+struct iris_hfi_gen2_core_hfi_range {
+	u32 begin;
+	u32 end;
+	int (*handle)(struct iris_core *core, struct iris_hfi_packet *pkt);
+};
+
+static int iris_hfi_gen2_validate_packet(u8 *response_pkt, u8 *core_resp_pkt)
+{
+	u32 response_pkt_size = 0;
+	u8 *response_limit;
+
+	response_limit = core_resp_pkt + IFACEQ_CORE_PKT_SIZE;
+
+	response_pkt_size = *(u32 *)response_pkt;
+	if (!response_pkt_size)
+		return -EINVAL;
+
+	if (response_pkt_size < sizeof(struct iris_hfi_packet))
+		return -EINVAL;
+
+	if (response_pkt + response_pkt_size > response_limit)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int iris_hfi_gen2_validate_hdr_packet(struct iris_core *core, struct iris_hfi_header *hdr)
+{
+	struct iris_hfi_packet *packet;
+	int i, ret = 0;
+	u8 *pkt;
+
+	if (hdr->size < sizeof(*hdr) + sizeof(*packet))
+		return -EINVAL;
+
+	pkt = (u8 *)((u8 *)hdr + sizeof(*hdr));
+
+	for (i = 0; i < hdr->num_packets; i++) {
+		packet = (struct iris_hfi_packet *)pkt;
+		ret = iris_hfi_gen2_validate_packet(pkt, core->response_packet);
+		if (ret)
+			return ret;
+
+		pkt += packet->size;
+	}
+
+	return ret;
+}
+
+static int iris_hfi_gen2_handle_system_error(struct iris_core *core,
+					     struct iris_hfi_packet *pkt)
+{
+	dev_err(core->dev, "received system error of type %#x\n", pkt->type);
+
+	iris_change_core_state(core, IRIS_CORE_ERROR);
+	schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10));
+
+	return 0;
+}
+
+static int iris_hfi_gen2_handle_system_init(struct iris_core *core,
+					    struct iris_hfi_packet *pkt)
+{
+	if (!(pkt->flags & HFI_FW_FLAGS_SUCCESS)) {
+		iris_change_core_state(core, IRIS_CORE_ERROR);
+		return 0;
+	}
+
+	complete(&core->core_init_done);
+
+	return 0;
+}
+
+static int iris_hfi_gen2_handle_image_version_property(struct iris_core *core,
+						       struct iris_hfi_packet *pkt)
+{
+	char fw_version[IRIS_FW_VERSION_LENGTH];
+	u8 *str_image_version;
+	u32 req_bytes;
+	u32 i = 0;
+
+	req_bytes = pkt->size - sizeof(*pkt);
+	if (req_bytes < IRIS_FW_VERSION_LENGTH - 1)
+		return -EINVAL;
+
+	str_image_version = (u8 *)pkt + sizeof(*pkt);
+
+	for (i = 0; i < IRIS_FW_VERSION_LENGTH - 1; i++) {
+		if (str_image_version[i] != '\0')
+			fw_version[i] = str_image_version[i];
+		else
+			fw_version[i] = ' ';
+	}
+	fw_version[i] = '\0';
+
+	dev_dbg(core->dev, "firmware version: %s\n", fw_version);
+
+	return 0;
+}
+
+static int iris_hfi_gen2_handle_system_property(struct iris_core *core,
+						struct iris_hfi_packet *pkt)
+{
+	int ret = 0;
+
+	switch (pkt->type) {
+	case HFI_PROP_IMAGE_VERSION:
+		ret = iris_hfi_gen2_handle_image_version_property(core, pkt);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static int iris_hfi_gen2_handle_system_response(struct iris_core *core,
+						struct iris_hfi_header *hdr)
+{
+	struct iris_hfi_packet *packet;
+	u8 *pkt, *start_pkt;
+	int ret = 0;
+	int i, j;
+	static const struct iris_hfi_gen2_core_hfi_range range[] = {
+		{HFI_SYSTEM_ERROR_BEGIN, HFI_SYSTEM_ERROR_END, iris_hfi_gen2_handle_system_error },
+		{HFI_PROP_BEGIN,         HFI_PROP_END, iris_hfi_gen2_handle_system_property },
+		{HFI_CMD_BEGIN,          HFI_CMD_END, iris_hfi_gen2_handle_system_init },
+	};
+
+	start_pkt = (u8 *)((u8 *)hdr + sizeof(*hdr));
+	for (i = 0; i < ARRAY_SIZE(range); i++) {
+		pkt = start_pkt;
+		for (j = 0; j < hdr->num_packets; j++) {
+			packet = (struct iris_hfi_packet *)pkt;
+			if (packet->flags & HFI_FW_FLAGS_SYSTEM_ERROR) {
+				ret = iris_hfi_gen2_handle_system_error(core, packet);
+				return ret;
+			}
+
+			if (packet->type > range[i].begin && packet->type < range[i].end) {
+				ret = range[i].handle(core, packet);
+				if (ret)
+					return ret;
+
+				if (packet->type >  HFI_SYSTEM_ERROR_BEGIN &&
+				    packet->type < HFI_SYSTEM_ERROR_END)
+					return 0;
+			}
+			pkt += packet->size;
+		}
+	}
+
+	return ret;
+}
+
+static int iris_hfi_gen2_handle_response(struct iris_core *core, void *response)
+{
+	struct iris_hfi_header *hdr;
+	int ret;
+
+	hdr = (struct iris_hfi_header *)response;
+	ret = iris_hfi_gen2_validate_hdr_packet(core, hdr);
+	if (ret)
+		return iris_hfi_gen2_handle_system_error(core, NULL);
+
+	return iris_hfi_gen2_handle_system_response(core, hdr);
+}
+
+static void iris_hfi_gen2_flush_debug_queue(struct iris_core *core, u8 *packet)
+{
+	struct hfi_debug_header *pkt;
+	u8 *log;
+
+	while (!iris_hfi_queue_dbg_read(core, packet)) {
+		pkt = (struct hfi_debug_header *)packet;
+
+		if (pkt->size < sizeof(*pkt))
+			continue;
+
+		if (pkt->size >= IFACEQ_CORE_PKT_SIZE)
+			continue;
+
+		packet[pkt->size] = '\0';
+		log = (u8 *)packet + sizeof(*pkt) + 1;
+		dev_dbg(core->dev, "%s", log);
+	}
+}
+
+static void iris_hfi_gen2_response_handler(struct iris_core *core)
+{
+	if (iris_vpu_watchdog(core, core->intr_status)) {
+		struct iris_hfi_packet pkt = {.type = HFI_SYS_ERROR_WD_TIMEOUT};
+
+		dev_err(core->dev, "cpu watchdog error received\n");
+		iris_change_core_state(core, IRIS_CORE_ERROR);
+		iris_hfi_gen2_handle_system_error(core, &pkt);
+
+		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);
+		if (core->state != IRIS_CORE_INIT)
+			break;
+		memset(core->response_packet, 0, sizeof(struct iris_hfi_header));
+	}
+
+	iris_hfi_gen2_flush_debug_queue(core, core->response_packet);
+}
+
+static const struct iris_hfi_response_ops iris_hfi_gen2_response_ops = {
+	.hfi_response_handler = iris_hfi_gen2_response_handler,
+};
+
+void iris_hfi_gen2_response_ops_init(struct iris_core *core)
+{
+	core->hfi_response_ops = &iris_hfi_gen2_response_ops;
+}
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c
index 11938880b8cd..b24d4640fea9 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c
@@ -5,6 +5,207 @@ 
 
 #include "iris_core.h"
 #include "iris_hfi_queue.h"
+#include "iris_vpu_common.h"
+
+static int iris_hfi_queue_write(struct iris_iface_q_info *qinfo, void *packet, u32 packet_size)
+{
+	u32 empty_space, read_idx, write_idx, new_write_idx;
+	struct iris_hfi_queue_header *queue;
+	u32 *write_ptr;
+	u32 residue;
+
+	queue = qinfo->qhdr;
+
+	read_idx = queue->read_idx * sizeof(u32);
+	write_idx = queue->write_idx * sizeof(u32);
+
+	if (write_idx < read_idx)
+		empty_space = read_idx - write_idx;
+	else
+		empty_space = IFACEQ_QUEUE_SIZE - (write_idx -  read_idx);
+	if (empty_space < packet_size)
+		return -ENOSPC;
+
+	queue->tx_req =  0;
+
+	new_write_idx = write_idx + packet_size;
+	write_ptr = (u32 *)((u8 *)qinfo->kernel_vaddr + write_idx);
+
+	if (write_ptr < (u32 *)qinfo->kernel_vaddr ||
+	    write_ptr > (u32 *)(qinfo->kernel_vaddr +
+	    IFACEQ_QUEUE_SIZE))
+		return -EINVAL;
+
+	if (new_write_idx < IFACEQ_QUEUE_SIZE) {
+		memcpy(write_ptr, packet, packet_size);
+	} else {
+		residue = new_write_idx - IFACEQ_QUEUE_SIZE;
+		memcpy(write_ptr, packet, (packet_size - residue));
+		memcpy(qinfo->kernel_vaddr,
+		       packet + (packet_size - residue), residue);
+		new_write_idx = residue;
+	}
+
+	/* Make sure packet is written before updating the write index */
+	mb();
+	queue->write_idx = new_write_idx / sizeof(u32);
+
+	/* Make sure write index is updated before an interrupt is raised */
+	mb();
+
+	return 0;
+}
+
+static int iris_hfi_queue_read(struct iris_iface_q_info *qinfo, void *packet)
+{
+	u32 read_idx, write_idx, new_read_idx;
+	struct iris_hfi_queue_header *queue;
+	u32 packet_size, residue;
+	u32 receive_request = 0;
+	u32 *read_ptr;
+	int ret = 0;
+
+	queue = qinfo->qhdr;
+
+	if (queue->queue_type == IFACEQ_MSGQ_ID)
+		receive_request = 1;
+
+	read_idx = queue->read_idx * sizeof(u32);
+	write_idx = queue->write_idx * sizeof(u32);
+
+	if (read_idx == write_idx) {
+		queue->rx_req = receive_request;
+		/* Ensure qhdr is updated in main memory */
+		mb();
+		return -ENODATA;
+	}
+
+	read_ptr = qinfo->kernel_vaddr + read_idx;
+	if (read_ptr < (u32 *)qinfo->kernel_vaddr ||
+	    read_ptr > (u32 *)(qinfo->kernel_vaddr +
+	    IFACEQ_QUEUE_SIZE - sizeof(*read_ptr)))
+		return -ENODATA;
+
+	packet_size = *read_ptr;
+	if (!packet_size)
+		return -EINVAL;
+
+	new_read_idx = read_idx + packet_size;
+	if (packet_size <= IFACEQ_CORE_PKT_SIZE) {
+		if (new_read_idx < IFACEQ_QUEUE_SIZE) {
+			memcpy(packet, read_ptr, packet_size);
+		} else {
+			residue = new_read_idx - IFACEQ_QUEUE_SIZE;
+			memcpy(packet, read_ptr, (packet_size - residue));
+			memcpy((packet + (packet_size - residue)),
+			       qinfo->kernel_vaddr, residue);
+			new_read_idx = residue;
+		}
+	} else {
+		new_read_idx = write_idx;
+		ret = -EBADMSG;
+	}
+
+	queue->rx_req = receive_request;
+
+	queue->read_idx = new_read_idx / sizeof(u32);
+	/* Ensure qhdr is updated in main memory */
+	mb();
+
+	return ret;
+}
+
+int iris_hfi_queue_cmd_write_locked(struct iris_core *core, void *pkt, u32 pkt_size)
+{
+	struct iris_iface_q_info *q_info;
+
+	if (!mutex_is_locked(&core->lock))
+		return -EINVAL;
+
+	if (core->state != IRIS_CORE_INIT)
+		return -EINVAL;
+
+	q_info = &core->command_queue;
+	if (!q_info || !q_info->kernel_vaddr || !pkt) {
+		dev_err(core->dev, "cannot write to shared command queue\n");
+		return -ENODATA;
+	}
+
+	if (!iris_hfi_queue_write(q_info, pkt, pkt_size)) {
+		iris_vpu_raise_interrupt(core);
+	} else {
+		dev_err(core->dev, "queue full\n");
+		return -ENODATA;
+	}
+
+	return 0;
+}
+
+int iris_hfi_queue_cmd_write(struct iris_core *core, void *pkt, u32 pkt_size)
+{
+	int ret;
+
+	mutex_lock(&core->lock);
+	ret = iris_hfi_queue_cmd_write_locked(core, pkt, pkt_size);
+	if (ret)
+		dev_err(core->dev, "iris_hfi_queue_cmd_write_locked failed with %d\n", ret);
+
+	mutex_unlock(&core->lock);
+
+	return ret;
+}
+
+int iris_hfi_queue_msg_read(struct iris_core *core, void *pkt)
+{
+	struct iris_iface_q_info *q_info;
+	int ret = 0;
+
+	mutex_lock(&core->lock);
+	if (core->state != IRIS_CORE_INIT) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	q_info = &core->message_queue;
+	if (iris_hfi_queue_read(q_info, pkt)) {
+		ret = -ENODATA;
+		goto unlock;
+	}
+
+unlock:
+	mutex_unlock(&core->lock);
+
+	return ret;
+}
+
+int iris_hfi_queue_dbg_read(struct iris_core *core, void *pkt)
+{
+	struct iris_iface_q_info *q_info;
+	int ret = 0;
+
+	mutex_lock(&core->lock);
+	if (core->state != IRIS_CORE_INIT) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	q_info = &core->debug_queue;
+	if (!q_info || !q_info->kernel_vaddr || !pkt) {
+		dev_err(core->dev, "cannot read from shared debug queue\n");
+		ret = -ENODATA;
+		goto unlock;
+	}
+
+	if (iris_hfi_queue_read(q_info, pkt)) {
+		ret = -ENODATA;
+		goto unlock;
+	}
+
+unlock:
+	mutex_unlock(&core->lock);
+
+	return ret;
+}
 
 static void iris_hfi_queue_set_header(struct iris_core *core, u32 queue_id,
 				      struct iris_iface_q_info *iface_q)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.h b/drivers/media/platform/qcom/iris/iris_hfi_queue.h
index 54994bb776f1..1b728ebddd1d 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_queue.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.h
@@ -172,4 +172,9 @@  struct iris_iface_q_info {
 int iris_hfi_queues_init(struct iris_core *core);
 void iris_hfi_queues_deinit(struct iris_core *core);
 
+int iris_hfi_queue_cmd_write_locked(struct iris_core *core, void *pkt, u32 pkt_size);
+int iris_hfi_queue_cmd_write(struct iris_core *core, void *pkt, u32 pkt_size);
+int iris_hfi_queue_msg_read(struct iris_core *core, void *pkt);
+int iris_hfi_queue_dbg_read(struct iris_core *core, void *pkt);
+
 #endif
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
index 47fdebd8135c..4577977f9f8c 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
@@ -7,6 +7,7 @@ 
 #define _IRIS_PLATFORM_COMMON_H_
 
 #define IRIS_PAS_ID				9
+#define HW_RESPONSE_TIMEOUT_VALUE               (1000) /* milliseconds */
 
 extern struct iris_platform_data sm8550_data;
 extern struct iris_platform_data sm8250_data;
@@ -29,7 +30,19 @@  struct tz_cp_config {
 	u32 cp_nonpixel_size;
 };
 
+struct ubwc_config_data {
+	u32	max_channels;
+	u32	mal_length;
+	u32	highest_bank_bit;
+	u32	bank_swzl_level;
+	u32	bank_swz2_level;
+	u32	bank_swz3_level;
+	u32	bank_spreading;
+};
+
 struct iris_platform_data {
+	void (*init_hfi_command_ops)(struct iris_core *core);
+	void (*init_hfi_response_ops)(struct iris_core *core);
 	struct iris_inst *(*get_instance)(void);
 	const struct icc_info *icc_tbl;
 	unsigned int icc_tbl_size;
@@ -46,6 +59,8 @@  struct iris_platform_data {
 	u32 pas_id;
 	struct tz_cp_config *tz_cp_config_data;
 	u32 core_arch;
+	u32 hw_response_timeout;
+	struct ubwc_config_data *ubwc_config;
 };
 
 #endif
diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
index 36bcb1b851ed..b83665a9c5a2 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c
@@ -34,6 +34,8 @@  static struct tz_cp_config tz_cp_config_sm8250 = {
 
 struct iris_platform_data sm8250_data = {
 	.get_instance = iris_hfi_gen1_get_instance,
+	.init_hfi_command_ops = &iris_hfi_gen1_command_ops_init,
+	.init_hfi_response_ops = iris_hfi_gen1_response_ops_init,
 	.icc_tbl = sm8250_icc_table,
 	.icc_tbl_size = ARRAY_SIZE(sm8250_icc_table),
 	.clk_rst_tbl = sm8250_clk_reset_table,
@@ -48,4 +50,5 @@  struct iris_platform_data sm8250_data = {
 	.fwname = "qcom/vpu/vpu20_p4.mbn",
 	.pas_id = IRIS_PAS_ID,
 	.tz_cp_config_data = &tz_cp_config_sm8250,
+	.hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE,
 };
diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c
index a559e095fefc..91bfc0fa0989 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c
@@ -27,6 +27,16 @@  static const struct platform_clk_data sm8550_clk_table[] = {
 	{IRIS_HW_CLK,   "vcodec0_core" },
 };
 
+static struct ubwc_config_data ubwc_config_sm8550 = {
+	.max_channels = 8,
+	.mal_length = 32,
+	.highest_bank_bit = 16,
+	.bank_swzl_level = 0,
+	.bank_swz2_level = 1,
+	.bank_swz3_level = 1,
+	.bank_spreading = 1,
+};
+
 static struct tz_cp_config tz_cp_config_sm8550 = {
 	.cp_start = 0,
 	.cp_size = 0x25800000,
@@ -36,6 +46,8 @@  static struct tz_cp_config tz_cp_config_sm8550 = {
 
 struct iris_platform_data sm8550_data = {
 	.get_instance = iris_hfi_gen2_get_instance,
+	.init_hfi_command_ops = iris_hfi_gen2_command_ops_init,
+	.init_hfi_response_ops = iris_hfi_gen2_response_ops_init,
 	.icc_tbl = sm8550_icc_table,
 	.icc_tbl_size = ARRAY_SIZE(sm8550_icc_table),
 	.clk_rst_tbl = sm8550_clk_reset_table,
@@ -51,4 +63,6 @@  struct iris_platform_data sm8550_data = {
 	.pas_id = IRIS_PAS_ID,
 	.tz_cp_config_data = &tz_cp_config_sm8550,
 	.core_arch = VIDEO_ARCH_LX,
+	.hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE,
+	.ubwc_config = &ubwc_config_sm8550,
 };
diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
index 64bac287d3a8..ecf1a50be63b 100644
--- a/drivers/media/platform/qcom/iris/iris_probe.c
+++ b/drivers/media/platform/qcom/iris/iris_probe.c
@@ -8,6 +8,21 @@ 
 #include "iris_core.h"
 #include "iris_vidc.h"
 
+static inline int iris_init_isr(struct iris_core *core)
+{
+	int ret;
+
+	ret = devm_request_threaded_irq(core->dev, core->irq, iris_hfi_isr,
+					iris_hfi_isr_handler, IRQF_TRIGGER_HIGH, "iris", core);
+	if (ret) {
+		dev_err(core->dev, "failed to allocate irq\n");
+		return ret;
+	}
+	disable_irq_nosync(core->irq);
+
+	return ret;
+}
+
 static int iris_register_video_device(struct iris_core *core)
 {
 	struct video_device *vdev;
@@ -57,6 +72,15 @@  static void iris_remove(struct platform_device *pdev)
 	core->state = IRIS_CORE_DEINIT;
 }
 
+static void iris_sys_error_handler(struct work_struct *work)
+{
+	struct iris_core *core =
+			container_of(work, struct iris_core, sys_error_handler.work);
+
+	iris_core_deinit(core);
+	iris_core_init(core);
+}
+
 static int iris_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -71,6 +95,13 @@  static int iris_probe(struct platform_device *pdev)
 
 	core->state = IRIS_CORE_DEINIT;
 	mutex_init(&core->lock);
+	init_completion(&core->core_init_done);
+
+	core->response_packet = devm_kzalloc(core->dev, IFACEQ_CORE_PKT_SIZE, GFP_KERNEL);
+	if (!core->response_packet)
+		return -ENOMEM;
+
+	INIT_DELAYED_WORK(&core->sys_error_handler, iris_sys_error_handler);
 
 	core->reg_base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(core->reg_base))
@@ -80,6 +111,12 @@  static int iris_probe(struct platform_device *pdev)
 	if (core->irq < 0)
 		return core->irq;
 
+	ret = iris_init_isr(core);
+	if (ret) {
+		dev_err_probe(core->dev, ret, "Failed to init isr\n");
+		return ret;
+	}
+
 	core->iris_platform_data = of_device_get_match_data(core->dev);
 	if (!core->iris_platform_data) {
 		ret = -ENODEV;
@@ -88,6 +125,9 @@  static int iris_probe(struct platform_device *pdev)
 	}
 
 	iris_init_ops(core);
+	core->iris_platform_data->init_hfi_command_ops(core);
+	core->iris_platform_data->init_hfi_response_ops(core);
+
 	ret = iris_init_resources(core);
 	if (ret) {
 		dev_err_probe(core->dev, ret, "init resource failed\n");
diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c
new file mode 100644
index 000000000000..043aa0ee80b6
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_state.c
@@ -0,0 +1,15 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "iris_core.h"
+#include "iris_state.h"
+
+void iris_change_core_state(struct iris_core *core,
+			    enum iris_core_state request_state)
+{
+	mutex_lock(&core->lock);
+	core->state = request_state;
+	mutex_unlock(&core->lock);
+}
diff --git a/drivers/media/platform/qcom/iris/iris_state.h b/drivers/media/platform/qcom/iris/iris_state.h
index a0bfee98578a..8bf22f839311 100644
--- a/drivers/media/platform/qcom/iris/iris_state.h
+++ b/drivers/media/platform/qcom/iris/iris_state.h
@@ -6,6 +6,8 @@ 
 #ifndef _IRIS_STATE_H_
 #define _IRIS_STATE_H_
 
+struct iris_core;
+
 /**
  * enum iris_core_state
  *
@@ -38,4 +40,6 @@  enum iris_core_state {
 	IRIS_CORE_ERROR,
 };
 
+void iris_change_core_state(struct iris_core *core,
+			    enum iris_core_state request_state);
 #endif
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c
index df87b1b719a9..5930cf105a87 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_common.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c
@@ -11,6 +11,9 @@ 
 #define CPU_BASE_OFFS				0x000A0000
 
 #define CPU_CS_BASE_OFFS			(CPU_BASE_OFFS)
+#define CPU_IC_BASE_OFFS			(CPU_BASE_OFFS)
+
+#define CPU_CS_A2HSOFTINTCLR			(CPU_CS_BASE_OFFS + 0x1C)
 
 #define CTRL_INIT				(CPU_CS_BASE_OFFS + 0x48)
 #define CTRL_STATUS				(CPU_CS_BASE_OFFS + 0x4C)
@@ -27,6 +30,15 @@ 
 #define CPU_CS_H2XSOFTINTEN			(CPU_CS_BASE_OFFS + 0x148)
 #define CPU_CS_X2RPMH				(CPU_CS_BASE_OFFS + 0x168)
 
+#define CPU_IC_SOFTINT				(CPU_IC_BASE_OFFS + 0x150)
+#define CPU_IC_SOFTINT_H2A_SHFT			0x0
+
+#define WRAPPER_BASE_OFFS			0x000B0000
+#define WRAPPER_INTR_STATUS			(WRAPPER_BASE_OFFS + 0x0C)
+#define WRAPPER_INTR_STATUS_A2HWD_BMSK		0x8
+#define WRAPPER_INTR_STATUS_A2H_BMSK		0x4
+#define CTRL_INIT_IDLE_MSG_BMSK			0x40000000
+
 static void iris_vpu_setup_ucregion_memory_map(struct iris_core *core)
 {
 	u32 queue_size, value;
@@ -85,3 +97,33 @@  int iris_vpu_boot_firmware(struct iris_core *core)
 
 	return 0;
 }
+
+void iris_vpu_raise_interrupt(struct iris_core *core)
+{
+	writel(1 << CPU_IC_SOFTINT_H2A_SHFT, core->reg_base + CPU_IC_SOFTINT);
+}
+
+void iris_vpu_clear_interrupt(struct iris_core *core)
+{
+	u32 intr_status = 0, mask = 0;
+
+	intr_status = readl(core->reg_base + WRAPPER_INTR_STATUS);
+	mask = (WRAPPER_INTR_STATUS_A2H_BMSK |
+		WRAPPER_INTR_STATUS_A2HWD_BMSK |
+		CTRL_INIT_IDLE_MSG_BMSK);
+
+	if (intr_status & mask)
+		core->intr_status |= intr_status;
+
+	writel(1, core->reg_base + CPU_CS_A2HSOFTINTCLR);
+}
+
+int iris_vpu_watchdog(struct iris_core *core, u32 intr_status)
+{
+	if (intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK) {
+		dev_err(core->dev, "received interrupt\n");
+		return -ETIME;
+	}
+
+	return 0;
+}
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h
index d9b8df6e3f80..706b207bc295 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_common.h
+++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h
@@ -9,5 +9,8 @@ 
 struct iris_core;
 
 int iris_vpu_boot_firmware(struct iris_core *core);
+void iris_vpu_raise_interrupt(struct iris_core *core);
+void iris_vpu_clear_interrupt(struct iris_core *core);
+int iris_vpu_watchdog(struct iris_core *core, u32 intr_status);
 
 #endif