[PATCH v2 22/34] media: iris: introduce instance states

From: Dikshita Agarwal
Date: Mon Dec 18 2023 - 06:45:43 EST


Introduce different states for instances. State transitions
are defined, based on which they would be allowed/rejected/ignored.

IRIS_INST_OPEN - video instance is opened.
IRIS_INST_INPUT_STREAMING - stream on is completed on output plane.
IRIS_INST_OUTPUT_STREAMING - stream on is completed on capture
plane.
IRIS_INST_STREAMING - stream on is completed on both output and
capture planes.
IRIS_INST_CLOSE - video instance is closed.
IRIS_INST_ERROR - error state.

|
v
-------------
+---------| OPEN |--------- +
| ------------- |
| ^ ^ |
| / \ |
| / \ |
| v v |
| ----------- ----------- |
| | INPUT OUTPUT | |
|---| STREAMING STREAMING |---|
| ----------- ----------- |
| ^ ^ |
| \ / |
| \ / |
| v v |
| ------------- |
|--------| STREAMING |-----------|
| ------------- |
| | |
| | |
| v |
| ----------- |
+-------->| CLOSE |<----------+
| ----------- |
| | |
| | |
| v |
| ---------- |
+-------->| ERROR |<-----------+
----------

Signed-off-by: Dikshita Agarwal <quic_dikshita@xxxxxxxxxxx>
---
.../platform/qcom/vcodec/iris/iris_instance.h | 2 +
.../media/platform/qcom/vcodec/iris/iris_state.c | 86 ++++++++++++++++++++++
.../media/platform/qcom/vcodec/iris/iris_state.h | 22 ++++++
drivers/media/platform/qcom/vcodec/iris/iris_vb2.c | 3 +
.../media/platform/qcom/vcodec/iris/iris_vidc.c | 5 ++
5 files changed, 118 insertions(+)

diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_instance.h b/drivers/media/platform/qcom/vcodec/iris/iris_instance.h
index 5d4c856..275efa8 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_instance.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_instance.h
@@ -37,6 +37,7 @@
* @codec: codec type
* @buffers: structure of buffer info
* @fw_min_count: minimnum count of buffers needed by fw
+ * @state: instance state
*/

struct iris_inst {
@@ -60,6 +61,7 @@ struct iris_inst {
enum codec_type codec;
struct iris_buffers_info buffers;
u32 fw_min_count;
+ enum iris_inst_state state;
};

#endif
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_state.c b/drivers/media/platform/qcom/vcodec/iris/iris_state.c
index 83bbc6b..9bf79a0 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_state.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_state.c
@@ -69,3 +69,89 @@ int iris_change_core_state(struct iris_core *core,

return ret;
}
+
+struct iris_inst_state_change_allow {
+ enum iris_inst_state from;
+ enum iris_inst_state to;
+ enum state_change allow;
+};
+
+static enum state_change iris_allow_inst_state_change(struct iris_inst *inst,
+ enum iris_inst_state req_state)
+{
+ enum state_change allow = STATE_CHANGE_ALLOW;
+ int cnt;
+ static struct iris_inst_state_change_allow state[] = {
+ /* from, to, allow */
+ {IRIS_INST_OPEN, IRIS_INST_OPEN, STATE_CHANGE_IGNORE },
+ {IRIS_INST_OPEN, IRIS_INST_INPUT_STREAMING, STATE_CHANGE_ALLOW },
+ {IRIS_INST_OPEN, IRIS_INST_OUTPUT_STREAMING, STATE_CHANGE_ALLOW },
+ {IRIS_INST_OPEN, IRIS_INST_STREAMING, STATE_CHANGE_DISALLOW },
+ {IRIS_INST_OPEN, IRIS_INST_CLOSE, STATE_CHANGE_ALLOW },
+ {IRIS_INST_OPEN, IRIS_INST_ERROR, STATE_CHANGE_ALLOW },
+
+ {IRIS_INST_INPUT_STREAMING, IRIS_INST_OPEN, STATE_CHANGE_ALLOW },
+ {IRIS_INST_INPUT_STREAMING, IRIS_INST_INPUT_STREAMING, STATE_CHANGE_IGNORE },
+ {IRIS_INST_INPUT_STREAMING, IRIS_INST_OUTPUT_STREAMING, STATE_CHANGE_DISALLOW },
+ {IRIS_INST_INPUT_STREAMING, IRIS_INST_STREAMING, STATE_CHANGE_ALLOW },
+ {IRIS_INST_INPUT_STREAMING, IRIS_INST_CLOSE, STATE_CHANGE_ALLOW },
+ {IRIS_INST_INPUT_STREAMING, IRIS_INST_ERROR, STATE_CHANGE_ALLOW },
+
+ {IRIS_INST_OUTPUT_STREAMING, IRIS_INST_OPEN, STATE_CHANGE_ALLOW },
+ {IRIS_INST_OUTPUT_STREAMING, IRIS_INST_INPUT_STREAMING, STATE_CHANGE_DISALLOW },
+ {IRIS_INST_OUTPUT_STREAMING, IRIS_INST_OUTPUT_STREAMING, STATE_CHANGE_IGNORE },
+ {IRIS_INST_OUTPUT_STREAMING, IRIS_INST_STREAMING, STATE_CHANGE_ALLOW },
+ {IRIS_INST_OUTPUT_STREAMING, IRIS_INST_CLOSE, STATE_CHANGE_ALLOW },
+ {IRIS_INST_OUTPUT_STREAMING, IRIS_INST_ERROR, STATE_CHANGE_ALLOW },
+
+ {IRIS_INST_STREAMING, IRIS_INST_OPEN, STATE_CHANGE_DISALLOW },
+ {IRIS_INST_STREAMING, IRIS_INST_INPUT_STREAMING, STATE_CHANGE_ALLOW },
+ {IRIS_INST_STREAMING, IRIS_INST_OUTPUT_STREAMING, STATE_CHANGE_ALLOW },
+ {IRIS_INST_STREAMING, IRIS_INST_STREAMING, STATE_CHANGE_IGNORE },
+ {IRIS_INST_STREAMING, IRIS_INST_CLOSE, STATE_CHANGE_ALLOW },
+ {IRIS_INST_STREAMING, IRIS_INST_ERROR, STATE_CHANGE_ALLOW },
+
+ {IRIS_INST_CLOSE, IRIS_INST_OPEN, STATE_CHANGE_DISALLOW },
+ {IRIS_INST_CLOSE, IRIS_INST_INPUT_STREAMING, STATE_CHANGE_DISALLOW },
+ {IRIS_INST_CLOSE, IRIS_INST_OUTPUT_STREAMING, STATE_CHANGE_DISALLOW },
+ {IRIS_INST_CLOSE, IRIS_INST_STREAMING, STATE_CHANGE_DISALLOW },
+ {IRIS_INST_CLOSE, IRIS_INST_CLOSE, STATE_CHANGE_IGNORE },
+ {IRIS_INST_CLOSE, IRIS_INST_ERROR, STATE_CHANGE_IGNORE },
+
+ {IRIS_INST_ERROR, IRIS_INST_OPEN, STATE_CHANGE_IGNORE },
+ {IRIS_INST_ERROR, IRIS_INST_INPUT_STREAMING, STATE_CHANGE_IGNORE },
+ {IRIS_INST_ERROR, IRIS_INST_OUTPUT_STREAMING, STATE_CHANGE_IGNORE },
+ {IRIS_INST_ERROR, IRIS_INST_STREAMING, STATE_CHANGE_IGNORE },
+ {IRIS_INST_ERROR, IRIS_INST_CLOSE, STATE_CHANGE_IGNORE },
+ {IRIS_INST_ERROR, IRIS_INST_ERROR, STATE_CHANGE_IGNORE },
+ };
+
+ for (cnt = 0; cnt < ARRAY_SIZE(state); cnt++) {
+ if (state[cnt].from == inst->state && state[cnt].to == req_state) {
+ allow = state[cnt].allow;
+ break;
+ }
+ }
+
+ return allow;
+}
+
+int iris_inst_change_state(struct iris_inst *inst,
+ enum iris_inst_state request_state)
+{
+ enum state_change allow;
+
+ if (IS_SESSION_ERROR(inst))
+ return 0;
+
+ if (inst->state == request_state)
+ return 0;
+
+ allow = iris_allow_inst_state_change(inst, request_state);
+ if (allow != STATE_CHANGE_ALLOW)
+ return (allow == STATE_CHANGE_DISALLOW ? -EINVAL : 0);
+
+ inst->state = request_state;
+
+ return 0;
+}
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_state.h b/drivers/media/platform/qcom/vcodec/iris/iris_state.h
index ee20842..6db95a1 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_state.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_state.h
@@ -7,6 +7,7 @@
#define _IRIS_STATE_H_

struct iris_core;
+struct iris_inst;

enum iris_core_state {
IRIS_CORE_DEINIT,
@@ -15,8 +16,29 @@ enum iris_core_state {
IRIS_CORE_ERROR,
};

+enum iris_inst_state {
+ IRIS_INST_OPEN,
+ IRIS_INST_INPUT_STREAMING,
+ IRIS_INST_OUTPUT_STREAMING,
+ IRIS_INST_STREAMING,
+ IRIS_INST_CLOSE,
+ IRIS_INST_ERROR,
+};
+
+enum state_change {
+ STATE_CHANGE_ALLOW,
+ STATE_CHANGE_DISALLOW,
+ STATE_CHANGE_IGNORE,
+};
+
+#define IS_SESSION_ERROR(inst) \
+((inst)->state == IRIS_INST_ERROR)
+
bool core_in_valid_state(struct iris_core *core);
int iris_change_core_state(struct iris_core *core,
enum iris_core_state request_state);

+int iris_inst_change_state(struct iris_inst *inst,
+ enum iris_inst_state request_state);
+
#endif
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_vb2.c b/drivers/media/platform/qcom/vcodec/iris/iris_vb2.c
index a57b5fb..8f499a9 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_vb2.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_vb2.c
@@ -34,6 +34,9 @@ int iris_vb2_queue_setup(struct vb2_queue *q,
else
f = inst->fmt_dst;

+ if (inst->state == IRIS_INST_STREAMING)
+ return -EINVAL;
+
if (*num_planes) {
if (*num_planes != f->fmt.pix_mp.num_planes ||
sizes[0] < f->fmt.pix_mp.plane_fmt[0].sizeimage)
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_vidc.c b/drivers/media/platform/qcom/vcodec/iris/iris_vidc.c
index 124333a..68ba75f 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_vidc.c
@@ -168,6 +168,7 @@ int vidc_open(struct file *filp)

inst->core = core;
inst->session_id = hash32_ptr(inst);
+ iris_inst_change_state(inst, IRIS_INST_OPEN);
mutex_init(&inst->ctx_q_lock);

ret = vidc_add_session(inst);
@@ -244,6 +245,7 @@ int vidc_close(struct file *filp)
v4l2_ctrl_handler_free(&inst->ctrl_handler);
vdec_inst_deinit(inst);
close_session(inst);
+ iris_inst_change_state(inst, IRIS_INST_CLOSE);
vidc_vb2_queue_deinit(inst);
vidc_v4l2_fh_deinit(inst);
vidc_remove_session(inst);
@@ -295,6 +297,9 @@ static __poll_t vidc_poll(struct file *filp, struct poll_table_struct *pt)
if (!inst)
return EPOLLERR;

+ if (IS_SESSION_ERROR(inst))
+ return EPOLLERR;
+
poll_wait(filp, &inst->fh.wait, pt);
poll_wait(filp, &inst->vb2q_src->done_wq, pt);
poll_wait(filp, &inst->vb2q_dst->done_wq, pt);
--
2.7.4