lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <bdd09198-d15e-4212-942c-92b19208d7cc@linaro.org>
Date: Thu, 5 Sep 2024 14:10:35 +0100
From: Bryan O'Donoghue <bryan.odonoghue@...aro.org>
To: quic_dikshita@...cinc.com, Vikash Garodia <quic_vgarodia@...cinc.com>,
 Abhinav Kumar <quic_abhinavk@...cinc.com>,
 Mauro Carvalho Chehab <mchehab@...nel.org>, Rob Herring <robh@...nel.org>,
 Krzysztof Kozlowski <krzk+dt@...nel.org>, Conor Dooley
 <conor+dt@...nel.org>, Philipp Zabel <p.zabel@...gutronix.de>
Cc: linux-media@...r.kernel.org, linux-arm-msm@...r.kernel.org,
 devicetree@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH v3 09/29] media: iris: introduce Host firmware interface
 with necessary hooks

On 27/08/2024 11:05, Dikshita Agarwal via B4 Relay wrote:
> From: Dikshita Agarwal <quic_dikshita@...cinc.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@...cinc.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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ