Re: [PATCH v2 5/7] media: iris: add helper to select context bank device

From: Dmitry Baryshkov

Date: Fri Feb 27 2026 - 15:32:07 EST


On Fri, Feb 27, 2026 at 07:41:21PM +0530, Vikash Garodia wrote:
> Depending on the buffer type (input, output, internal and interface
> queues), associated context bank is selected, if available. Fallback to
> parent device for backward compatibility.
>
> Co-developed-by: Vishnu Reddy <busanna.reddy@xxxxxxxxxxxxxxxx>
> Signed-off-by: Vishnu Reddy <busanna.reddy@xxxxxxxxxxxxxxxx>
> Signed-off-by: Vikash Garodia <vikash.garodia@xxxxxxxxxxxxxxxx>
> ---
> drivers/media/platform/qcom/iris/iris_buffer.c | 7 +--
> drivers/media/platform/qcom/iris/iris_buffer.h | 2 +
> drivers/media/platform/qcom/iris/iris_hfi_queue.c | 16 +++---
> drivers/media/platform/qcom/iris/iris_resources.c | 60 +++++++++++++++++++++++
> drivers/media/platform/qcom/iris/iris_resources.h | 2 +
> drivers/media/platform/qcom/iris/iris_vidc.c | 4 +-
> 6 files changed, 79 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c
> index 9151f43bc6b9c2c34c803de4231d1e6de0bec6c4..95962c19c334f08a74c5b7e8ba978ab631a65e9c 100644
> --- a/drivers/media/platform/qcom/iris/iris_buffer.c
> +++ b/drivers/media/platform/qcom/iris/iris_buffer.c
> @@ -335,8 +335,8 @@ void iris_get_internal_buffers(struct iris_inst *inst, u32 plane)
> static int iris_create_internal_buffer(struct iris_inst *inst,
> enum iris_buffer_type buffer_type, u32 index)
> {
> + struct device *dev = iris_get_cb_dev(inst->core, inst, buffer_type);
> struct iris_buffers *buffers = &inst->buffers[buffer_type];
> - struct iris_core *core = inst->core;
> struct iris_buffer *buffer;
>
> if (!buffers->size)
> @@ -352,7 +352,7 @@ static int iris_create_internal_buffer(struct iris_inst *inst,
> buffer->buffer_size = buffers->size;
> buffer->dma_attrs = DMA_ATTR_WRITE_COMBINE | DMA_ATTR_NO_KERNEL_MAPPING;
>
> - buffer->kvaddr = dma_alloc_attrs(core->dev, buffer->buffer_size,
> + buffer->kvaddr = dma_alloc_attrs(dev, buffer->buffer_size,
> &buffer->device_addr, GFP_KERNEL, buffer->dma_attrs);
> if (!buffer->kvaddr) {
> kfree(buffer);
> @@ -490,9 +490,10 @@ int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane)
> int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer)
> {
> struct iris_core *core = inst->core;
> + struct device *dev = iris_get_cb_dev(core, inst, buffer->type);
>
> list_del(&buffer->list);
> - dma_free_attrs(core->dev, buffer->buffer_size, buffer->kvaddr,
> + dma_free_attrs(dev, buffer->buffer_size, buffer->kvaddr,
> buffer->device_addr, buffer->dma_attrs);
> kfree(buffer);
>
> diff --git a/drivers/media/platform/qcom/iris/iris_buffer.h b/drivers/media/platform/qcom/iris/iris_buffer.h
> index 75bb767761824c4c02e0df9b765896cc093be333..9520aa290b44f06ed2004ad89940c19d1c08a3d2 100644
> --- a/drivers/media/platform/qcom/iris/iris_buffer.h
> +++ b/drivers/media/platform/qcom/iris/iris_buffer.h
> @@ -28,6 +28,7 @@ struct iris_inst;
> * @BUF_SCRATCH_2: buffer to store encoding context data for HW
> * @BUF_VPSS: buffer to store VPSS context data for HW
> * @BUF_PARTIAL: buffer for AV1 IBC data
> + * @BUF_HFI_QUEUE: buffer for hardware firmware interface queue

Separate commit?

> * @BUF_TYPE_MAX: max buffer types
> */
> enum iris_buffer_type {
> @@ -44,6 +45,7 @@ enum iris_buffer_type {
> BUF_SCRATCH_2,
> BUF_VPSS,
> BUF_PARTIAL,
> + BUF_HFI_QUEUE,
> BUF_TYPE_MAX,
> };
>
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c
> index b3ed06297953b902d5ea6c452385a88d5431ac66..c1241fb8dc6519020a063cbba87aed665701d7ae 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c
> @@ -245,25 +245,26 @@ static void iris_hfi_queue_deinit(struct iris_iface_q_info *iface_q)
>
> int iris_hfi_queues_init(struct iris_core *core)
> {
> + struct device *dev = iris_get_cb_dev(core, NULL, BUF_HFI_QUEUE);
> struct iris_hfi_queue_table_header *q_tbl_hdr;
> u32 queue_size;
>
> /* Iris hardware requires 4K queue alignment */
> queue_size = ALIGN((sizeof(*q_tbl_hdr) + (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ)), SZ_4K);
> - core->iface_q_table_vaddr = dma_alloc_attrs(core->dev, queue_size,
> + core->iface_q_table_vaddr = dma_alloc_attrs(dev, queue_size,
> &core->iface_q_table_daddr,
> GFP_KERNEL, DMA_ATTR_WRITE_COMBINE);
> if (!core->iface_q_table_vaddr) {
> - dev_err(core->dev, "queues alloc and map failed\n");
> + dev_err(dev, "queues alloc and map failed\n");
> return -ENOMEM;
> }
>
> - core->sfr_vaddr = dma_alloc_attrs(core->dev, SFR_SIZE,
> + core->sfr_vaddr = dma_alloc_attrs(dev, SFR_SIZE,
> &core->sfr_daddr,
> GFP_KERNEL, DMA_ATTR_WRITE_COMBINE);
> if (!core->sfr_vaddr) {
> - dev_err(core->dev, "sfr alloc and map failed\n");
> - dma_free_attrs(core->dev, sizeof(*q_tbl_hdr), core->iface_q_table_vaddr,
> + dev_err(dev, "sfr alloc and map failed\n");
> + dma_free_attrs(dev, sizeof(*q_tbl_hdr), core->iface_q_table_vaddr,
> core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE);
> return -ENOMEM;
> }
> @@ -291,6 +292,7 @@ int iris_hfi_queues_init(struct iris_core *core)
>
> void iris_hfi_queues_deinit(struct iris_core *core)
> {
> + struct device *dev = iris_get_cb_dev(core, NULL, BUF_HFI_QUEUE);
> u32 queue_size;
>
> if (!core->iface_q_table_vaddr)
> @@ -300,7 +302,7 @@ void iris_hfi_queues_deinit(struct iris_core *core)
> iris_hfi_queue_deinit(&core->message_queue);
> iris_hfi_queue_deinit(&core->command_queue);
>
> - dma_free_attrs(core->dev, SFR_SIZE, core->sfr_vaddr,
> + dma_free_attrs(dev, SFR_SIZE, core->sfr_vaddr,
> core->sfr_daddr, DMA_ATTR_WRITE_COMBINE);
>
> core->sfr_vaddr = NULL;
> @@ -309,7 +311,7 @@ void iris_hfi_queues_deinit(struct iris_core *core)
> queue_size = ALIGN(sizeof(struct iris_hfi_queue_table_header) +
> (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ), SZ_4K);
>
> - dma_free_attrs(core->dev, queue_size, core->iface_q_table_vaddr,
> + dma_free_attrs(dev, queue_size, core->iface_q_table_vaddr,
> core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE);
>
> core->iface_q_table_vaddr = NULL;
> diff --git a/drivers/media/platform/qcom/iris/iris_resources.c b/drivers/media/platform/qcom/iris/iris_resources.c
> index be58e8620086d0f82c2c2bda29247483f5c56d79..65544cb0fa8fc4b250b0a0be1bb900d74b999d35 100644
> --- a/drivers/media/platform/qcom/iris/iris_resources.c
> +++ b/drivers/media/platform/qcom/iris/iris_resources.c
> @@ -13,6 +13,7 @@
> #include <linux/reset.h>
>
> #include "iris_core.h"
> +#include "iris_instance.h"
> #include "iris_resources.h"
>
> #define BW_THRESHOLD 50000
> @@ -177,3 +178,62 @@ int iris_create_child_device_and_map(struct iris_core *core, struct iris_context
>
> return 0;
> }
> +
> +static enum iris_buffer_region iris_get_region(struct iris_inst *inst,
> + enum iris_buffer_type buffer_type)
> +{
> + switch (buffer_type) {
> + case BUF_INPUT:
> + if (inst && inst->domain == ENCODER)

Can inst be NULL here?

> + return IRIS_PIXEL_REGION;
> + else if (inst && inst->domain == DECODER)
> + return IRIS_BITSTREAM_REGION;

Are there any other possibilities than encoder and decoder?

> + break;
> + case BUF_OUTPUT:
> + if (inst && inst->domain == ENCODER)
> + return IRIS_BITSTREAM_REGION;
> + else if (inst && inst->domain == DECODER)
> + return IRIS_PIXEL_REGION;
> + break;
> + case BUF_BIN:
> + return IRIS_BITSTREAM_REGION;
> + case BUF_DPB:
> + case BUF_PARTIAL:
> + case BUF_SCRATCH_2:
> + case BUF_VPSS:
> + return IRIS_PIXEL_REGION;
> + case BUF_ARP:
> + case BUF_COMV:
> + case BUF_HFI_QUEUE:
> + case BUF_LINE:
> + case BUF_NON_COMV:
> + case BUF_PERSIST:
> + return IRIS_NON_PIXEL_REGION;
> + default:
> + return 0;

dev_err(dev, "unsupported buffer type %x\n", buffer_type)
return -EINVAL;

> + }
> +
> + return 0;

Drop

> +}
> +
> +struct device *iris_get_cb_dev(struct iris_core *core, struct iris_inst *inst,
> + enum iris_buffer_type buffer_type)
> +{
> + enum iris_buffer_region region;
> + struct device *dev = NULL;
> + int i;
> +
> + region = iris_get_region(inst, buffer_type);
> +
> + for (i = 0; i < core->iris_platform_data->cb_data_size; i++) {
> + if (core->iris_platform_data->cb_data[i].region & region) {
> + dev = core->iris_platform_data->cb_data[i].dev;
> + break;
> + }

You really seem to overcomplicate things. Replace array search with the
indexed array access. Much easier and much better.

enum iris_buffer_region {
IRIS_PIXEL_REGION,
IRIS_BITSTREAM_REGION,
IRIS_NON_PIXEL_REGION,
// add more when necessary
IRIS_NUM_REGIONS,
};

struct iris_core {
struct iris_cb_device cb_devices[IRIS_NUM_REGIONS];
};

region = iris_get_region(inst, buffer_type);
dev = core->cb_devices[region];
if (!dev)
dev = core->dev;


> + }
> +
> + if (!dev)
> + dev = core->dev;
> +
> + return dev;
> +}
> diff --git a/drivers/media/platform/qcom/iris/iris_resources.h b/drivers/media/platform/qcom/iris/iris_resources.h
> index b7efe15facb203eea9ae13d5f0abdcc2ea718b4d..ea31726f1789130fccf6b24540a62b86cb3c36ac 100644
> --- a/drivers/media/platform/qcom/iris/iris_resources.h
> +++ b/drivers/media/platform/qcom/iris/iris_resources.h
> @@ -16,5 +16,7 @@ int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw);
> int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type clk_type);
> int iris_prepare_enable_clock(struct iris_core *core, enum platform_clk_type clk_type);
> int iris_create_child_device_and_map(struct iris_core *core, struct iris_context_bank *cb);
> +struct device *iris_get_cb_dev(struct iris_core *core, struct iris_inst *inst,
> + enum iris_buffer_type buffer_type);
>
> #endif
> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
> index bd38d84c9cc79d15585ed5dd5f905a37521cb6dc..b61d7941d88662f34a9d2ab3b6c5bd9acf4b5df5 100644
> --- a/drivers/media/platform/qcom/iris/iris_vidc.c
> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c
> @@ -107,7 +107,7 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_
> src_vq->drv_priv = inst;
> src_vq->buf_struct_size = sizeof(struct iris_buffer);
> src_vq->min_reqbufs_allocation = MIN_BUFFERS;
> - src_vq->dev = inst->core->dev;
> + src_vq->dev = iris_get_cb_dev(inst->core, inst, BUF_INPUT);
> src_vq->lock = &inst->ctx_q_lock;
> ret = vb2_queue_init(src_vq);
> if (ret)
> @@ -121,7 +121,7 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_
> dst_vq->drv_priv = inst;
> dst_vq->buf_struct_size = sizeof(struct iris_buffer);
> dst_vq->min_reqbufs_allocation = MIN_BUFFERS;
> - dst_vq->dev = inst->core->dev;
> + dst_vq->dev = iris_get_cb_dev(inst->core, inst, BUF_OUTPUT);
> dst_vq->lock = &inst->ctx_q_lock;
>
> return vb2_queue_init(dst_vq);
>
> --
> 2.34.1
>

--
With best wishes
Dmitry