Re: [PATCH v2] staging: media: meson: vdec: fix advanced concurrency and UAF bugs
Ferass El Hafidi <[email protected]> Mon, 13 Jul 2026 19:37:21 +0000
| Newsgroups | org.infradead.lists.linux-amlogic,dev.linux.lists.linux-staging,org.kernel.vger.linux-kernel,org.kernel.vger.linux-media |
|---|---|
| Message-ID | <[email protected]> |
On Mon, 13 Jul 2026 18:16, Alfie Varghese <[email protected]> wrote: >This commit fixes several deep concurrency and race condition issues identified >in the Amlogic video decoder driver: > >1. Fix a Use-After-Free window in vdec_close() by moving > cancel_work_sync(&sess->esparser_queue_work) to execute after the hardware > is stopped via v4l2_m2m_ctx_release(), preventing interrupts from re-arming it. >2. Fix a Use-After-Free relating to v4l2_m2m_release(). The driver incorrectly > allocated the m2m_dev per-session rather than per-device. Moved the > m2m_dev allocation to vdec_probe() and cleanup to vdec_remove() to fix > the structural UAF when background m2m jobs were pending. >3. Fix a TOCTOU race condition in vdec_isr() by adding synchronize_irq() > in vdec_stop_streaming() after clearing core->cur_sess, ensuring that > running interrupt handlers finish before freeing session data. >4. Fix a potential NULL/ERR pointer dereference in vdec_start_streaming() > by checking the return value of kthread_run() and handling errors gracefully. >5. Fix a memory leak in vdec_close() by freeing the session control > handler via v4l2_ctrl_handler_free(). >6. Prevent a potential NULL pointer dereference in vdec_probe() by adding > a NULL check for of_match_node(). > >Signed-off-by: Alfie Varghese <[email protected]> >--- > drivers/staging/media/meson/vdec/vdec.c | 52 ++- > drivers/staging/media/meson/vdec/vdec.h | 586 ++++++++++++------------ > 2 files changed, 331 insertions(+), 307 deletions(-) > >diff --git a/drivers/staging/media/meson/vdec/vdec.c b/drivers/staging/media/meson/vdec/vdec.c >index a039d925c0fe..f57c473da5e1 100644 >--- a/drivers/staging/media/meson/vdec/vdec.c >+++ b/drivers/staging/media/meson/vdec/vdec.c >@@ -337,9 +337,16 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) > > sess->sequence_cap = 0; > sess->sequence_out = 0; >- if (vdec_codec_needs_recycle(sess)) >+ if (vdec_codec_needs_recycle(sess)) { > sess->recycle_thread = kthread_run(vdec_recycle_thread, sess, > "vdec_recycle"); >+ if (IS_ERR(sess->recycle_thread)) { >+ ret = PTR_ERR(sess->recycle_thread); >+ sess->recycle_thread = NULL; >+ vdec_poweroff(sess); >+ goto vififo_free; >+ } >+ } > > sess->status = STATUS_INIT; > core->cur_sess = sess; >@@ -404,7 +411,7 @@ static void vdec_stop_streaming(struct vb2_queue *q) > sess->status == STATUS_INIT || > (sess->status == STATUS_NEEDS_RESUME && > (!sess->streamon_out || !sess->streamon_cap))) { >- if (vdec_codec_needs_recycle(sess)) >+ if (vdec_codec_needs_recycle(sess) && sess->recycle_thread) > kthread_stop(sess->recycle_thread); > > vdec_poweroff(sess); >@@ -416,6 +423,7 @@ static void vdec_stop_streaming(struct vb2_queue *q) > kfree(sess->priv); > sess->priv = NULL; > core->cur_sess = NULL; >+ synchronize_irq(core->irq); > sess->status = STATUS_STOPPED; > } > >@@ -873,18 +881,11 @@ static int vdec_open(struct file *file) > > sess->core = core; > >- sess->m2m_dev = v4l2_m2m_init(&vdec_m2m_ops); >- if (IS_ERR(sess->m2m_dev)) { >- dev_err(dev, "Fail to v4l2_m2m_init\n"); >- ret = PTR_ERR(sess->m2m_dev); >- goto err_free_sess; >- } >- >- sess->m2m_ctx = v4l2_m2m_ctx_init(sess->m2m_dev, sess, m2m_queue_init); >+ sess->m2m_ctx = v4l2_m2m_ctx_init(core->m2m_dev, sess, m2m_queue_init); > if (IS_ERR(sess->m2m_ctx)) { > dev_err(dev, "Fail to v4l2_m2m_ctx_init\n"); > ret = PTR_ERR(sess->m2m_ctx); >- goto err_m2m_release; >+ goto err_free_sess; > } > > ret = vdec_init_ctrls(sess); >@@ -915,8 +916,6 @@ static int vdec_open(struct file *file) > > err_m2m_ctx_release: > v4l2_m2m_ctx_release(sess->m2m_ctx); >-err_m2m_release: >- v4l2_m2m_release(sess->m2m_dev); > err_free_sess: > kfree(sess); > return ret; >@@ -927,10 +926,12 @@ static int vdec_close(struct file *file) > struct amvdec_session *sess = file_to_amvdec_session(file); > > v4l2_m2m_ctx_release(sess->m2m_ctx); >- v4l2_m2m_release(sess->m2m_dev); >+ cancel_work_sync(&sess->esparser_queue_work); > v4l2_fh_del(&sess->fh, file); > v4l2_fh_exit(&sess->fh); > >+ v4l2_ctrl_handler_free(&sess->ctrl_handler); >+ > mutex_destroy(&sess->lock); > mutex_destroy(&sess->bufs_recycle_lock); > >@@ -953,6 +954,9 @@ static irqreturn_t vdec_isr(int irq, void *data) > struct amvdec_core *core = data; > struct amvdec_session *sess = core->cur_sess; > >+ if (!sess) >+ return IRQ_NONE; >+ > sess->last_irq_jiffies = get_jiffies_64(); > > return sess->fmt_out->codec_ops->isr(sess); >@@ -963,6 +967,9 @@ static irqreturn_t vdec_threaded_isr(int irq, void *data) > struct amvdec_core *core = data; > struct amvdec_session *sess = core->cur_sess; > >+ if (!sess) >+ return IRQ_NONE; >+ > return sess->fmt_out->codec_ops->threaded_isr(sess); > } > >@@ -1020,6 +1027,8 @@ static int vdec_probe(struct platform_device *pdev) > return PTR_ERR(core->canvas); > > of_id = of_match_node(vdec_dt_match, dev->of_node); >+ if (!of_id) >+ return -ENODEV; > core->platform = of_id->data; > > if (core->platform->revision == VDEC_REVISION_G12A || >@@ -1049,6 +1058,8 @@ static int vdec_probe(struct platform_device *pdev) > if (irq < 0) > return irq; > >+ core->irq = irq; >+ > ret = devm_request_threaded_irq(core->dev, irq, vdec_isr, > vdec_threaded_isr, IRQF_ONESHOT, > "vdec", core); >@@ -1065,10 +1076,17 @@ static int vdec_probe(struct platform_device *pdev) > return -ENOMEM; > } > >+ core->m2m_dev = v4l2_m2m_init(&vdec_m2m_ops); >+ if (IS_ERR(core->m2m_dev)) { >+ dev_err(dev, "Failed to init v4l2 m2m dev\n"); >+ ret = PTR_ERR(core->m2m_dev); >+ goto err_v4l2_unreg; >+ } >+ > vdev = video_device_alloc(); > if (!vdev) { > ret = -ENOMEM; >- goto err_vdev_release; >+ goto err_m2m_release; > } > > core->vdev_dec = vdev; >@@ -1096,6 +1114,9 @@ static int vdec_probe(struct platform_device *pdev) > > err_vdev_release: > video_device_release(vdev); >+err_m2m_release: >+ v4l2_m2m_release(core->m2m_dev); >+err_v4l2_unreg: > v4l2_device_unregister(&core->v4l2_dev); > return ret; > } >@@ -1105,6 +1126,7 @@ static void vdec_remove(struct platform_device *pdev) > struct amvdec_core *core = platform_get_drvdata(pdev); > > video_unregister_device(core->vdev_dec); >+ v4l2_m2m_release(core->m2m_dev); > v4l2_device_unregister(&core->v4l2_dev); > } > It probably would be better to split into multiple commits to make it easier for maintainers to review your patch. >diff --git a/drivers/staging/media/meson/vdec/vdec.h b/drivers/staging/media/meson/vdec/vdec.h >index 7a5d8e871d70..b2a606e965b4 100644 >--- a/drivers/staging/media/meson/vdec/vdec.h >+++ b/drivers/staging/media/meson/vdec/vdec.h >@@ -1,292 +1,294 @@ >-/* SPDX-License-Identifier: GPL-2.0+ */ >-/* >- * Copyright (C) 2018 BayLibre, SAS >- * Author: Maxime Jourdan <[email protected]> >- */ >- >-#ifndef __MESON_VDEC_CORE_H_ >-#define __MESON_VDEC_CORE_H_ >- >-#include <linux/irqreturn.h> >-#include <linux/regmap.h> >-#include <linux/list.h> >-#include <media/videobuf2-v4l2.h> >-#include <media/v4l2-ctrls.h> >-#include <media/v4l2-device.h> >-#include <linux/soc/amlogic/meson-canvas.h> >- >-#include "vdec_platform.h" >- >-/* 32 buffers in 3-plane YUV420 */ >-#define MAX_CANVAS (32 * 3) >- >-struct amvdec_buffer { >- struct list_head list; >- struct vb2_buffer *vb; >-}; >- >-/** >- * struct amvdec_timestamp - stores a src timestamp along with a VIFIFO offset >- * >- * @list: used to make lists out of this struct >- * @tc: timecode from the v4l2 buffer >- * @ts: timestamp from the VB2 buffer >- * @offset: offset in the VIFIFO where the associated packet was written >- * @flags: flags from the v4l2 buffer >- * @used_count: times this timestamp was checked for a match with a dst buffer >- */ >-struct amvdec_timestamp { >- struct list_head list; >- struct v4l2_timecode tc; >- u64 ts; >- u32 offset; >- u32 flags; >- u32 used_count; >-}; >- >-struct amvdec_session; >- >-/** >- * struct amvdec_core - device parameters, singleton >- * >- * @dos_base: DOS memory base address >- * @esparser_base: PARSER memory base address >- * @regmap_ao: regmap for the AO bus >- * @dev: core device >- * @dev_dec: decoder device >- * @platform: platform-specific data >- * @canvas: canvas provider reference >- * @dos_parser_clk: DOS_PARSER clock >- * @dos_clk: DOS clock >- * @vdec_1_clk: VDEC_1 clock >- * @vdec_hevc_clk: VDEC_HEVC clock >- * @vdec_hevcf_clk: VDEC_HEVCF clock >- * @esparser_reset: RESET for the PARSER >- * @vdev_dec: video device for the decoder >- * @v4l2_dev: v4l2 device >- * @cur_sess: current decoding session >- * @lock: video device lock >- */ >-struct amvdec_core { >- void __iomem *dos_base; >- void __iomem *esparser_base; >- struct regmap *regmap_ao; >- >- struct device *dev; >- struct device *dev_dec; >- const struct vdec_platform *platform; >- >- struct meson_canvas *canvas; >- >- struct clk *dos_parser_clk; >- struct clk *dos_clk; >- struct clk *vdec_1_clk; >- struct clk *vdec_hevc_clk; >- struct clk *vdec_hevcf_clk; >- >- struct reset_control *esparser_reset; >- >- struct video_device *vdev_dec; >- struct v4l2_device v4l2_dev; >- >- struct amvdec_session *cur_sess; >- struct mutex lock; >-}; >- >-/** >- * struct amvdec_ops - vdec operations >- * >- * @start: mandatory call when the vdec needs to initialize >- * @stop: mandatory call when the vdec needs to stop >- * @conf_esparser: mandatory call to let the vdec configure the ESPARSER >- * @vififo_level: mandatory call to get the current amount of data >- * in the VIFIFO >- */ >-struct amvdec_ops { >- int (*start)(struct amvdec_session *sess); >- int (*stop)(struct amvdec_session *sess); >- void (*conf_esparser)(struct amvdec_session *sess); >- u32 (*vififo_level)(struct amvdec_session *sess); >-}; >- >-/** >- * struct amvdec_codec_ops - codec operations >- * >- * @start: mandatory call when the codec needs to initialize >- * @stop: mandatory call when the codec needs to stop >- * @load_extended_firmware: optional call to load additional firmware bits >- * @num_pending_bufs: optional call to get the number of dst buffers on hold >- * @can_recycle: optional call to know if the codec is ready to recycle >- * a dst buffer >- * @recycle: optional call to tell the codec to recycle a dst buffer. Must go >- * in pair with @can_recycle >- * @drain: optional call if the codec has a custom way of draining >- * @resume: optional call to resume after a resolution change >- * @eos_sequence: optional call to get an end sequence to send to esparser >- * for flush. Mutually exclusive with @drain. >- * @isr: mandatory call when the ISR triggers >- * @threaded_isr: mandatory call for the threaded ISR >- */ >-struct amvdec_codec_ops { >- int (*start)(struct amvdec_session *sess); >- int (*stop)(struct amvdec_session *sess); >- int (*load_extended_firmware)(struct amvdec_session *sess, >- const u8 *data, u32 len); >- u32 (*num_pending_bufs)(struct amvdec_session *sess); >- int (*can_recycle)(struct amvdec_core *core); >- void (*recycle)(struct amvdec_core *core, u32 buf_idx); >- void (*drain)(struct amvdec_session *sess); >- void (*resume)(struct amvdec_session *sess); >- const u8 * (*eos_sequence)(u32 *len); >- irqreturn_t (*isr)(struct amvdec_session *sess); >- irqreturn_t (*threaded_isr)(struct amvdec_session *sess); >-}; >- >-/** >- * struct amvdec_format - describes one of the OUTPUT (src) format supported >- * >- * @pixfmt: V4L2 pixel format >- * @min_buffers: minimum amount of CAPTURE (dst) buffers >- * @max_buffers: maximum amount of CAPTURE (dst) buffers >- * @max_width: maximum picture width supported >- * @max_height: maximum picture height supported >- * @flags: enum flags associated with this pixfmt >- * @vdec_ops: the VDEC operations that support this format >- * @codec_ops: the codec operations that support this format >- * @firmware_path: Path to the firmware that supports this format >- * @pixfmts_cap: list of CAPTURE pixel formats available with pixfmt >- */ >-struct amvdec_format { >- u32 pixfmt; >- u32 min_buffers; >- u32 max_buffers; >- u32 max_width; >- u32 max_height; >- u32 flags; >- >- struct amvdec_ops *vdec_ops; >- struct amvdec_codec_ops *codec_ops; >- >- char *firmware_path; >- u32 pixfmts_cap[4]; >-}; >- >-enum amvdec_status { >- STATUS_STOPPED, >- STATUS_INIT, >- STATUS_RUNNING, >- STATUS_NEEDS_RESUME, >-}; >- >-/** >- * struct amvdec_session - decoding session parameters >- * >- * @core: reference to the vdec core struct >- * @fh: v4l2 file handle >- * @m2m_dev: v4l2 m2m device >- * @m2m_ctx: v4l2 m2m context >- * @ctrl_handler: V4L2 control handler >- * @ctrl_min_buf_capture: V4L2 control V4L2_CID_MIN_BUFFERS_FOR_CAPTURE >- * @lock: cap & out queues lock >- * @fmt_out: vdec pixel format for the OUTPUT queue >- * @pixfmt_cap: V4L2 pixel format for the CAPTURE queue >- * @src_buffer_size: size in bytes of the OUTPUT buffers' only plane >- * @width: current picture width >- * @height: current picture height >- * @colorspace: current colorspace >- * @ycbcr_enc: current ycbcr_enc >- * @quantization: current quantization >- * @xfer_func: current transfer function >- * @pixelaspect: Pixel Aspect Ratio reported by the decoder >- * @esparser_queued_bufs: number of buffers currently queued into ESPARSER >- * @esparser_queue_work: work struct for the ESPARSER to process src buffers >- * @streamon_cap: stream on flag for capture queue >- * @streamon_out: stream on flag for output queue >- * @sequence_cap: capture sequence counter >- * @sequence_out: output sequence counter >- * @should_stop: flag set if userspace signaled EOS via command >- * or empty buffer >- * @keyframe_found: flag set once a keyframe has been parsed >- * @num_dst_bufs: number of destination buffers >- * @changed_format: the format changed >- * @canvas_alloc: array of all the canvas IDs allocated >- * @canvas_num: number of canvas IDs allocated >- * @vififo_vaddr: virtual address for the VIFIFO >- * @vififo_paddr: physical address for the VIFIFO >- * @vififo_size: size of the VIFIFO dma alloc >- * @bufs_recycle: list of buffers that need to be recycled >- * @bufs_recycle_lock: lock for the bufs_recycle list >- * @recycle_thread: task struct for the recycling thread >- * @timestamps: chronological list of src timestamps >- * @ts_spinlock: spinlock for the timestamps list >- * @last_irq_jiffies: tracks last time the vdec triggered an IRQ >- * @last_offset: tracks last offset of vififo >- * @wrap_count: number of times the vififo wrapped around >- * @fw_idx_to_vb2_idx: firmware buffer index to vb2 buffer index >- * @status: current decoding status >- * @priv: codec private data >- */ >-struct amvdec_session { >- struct amvdec_core *core; >- >- struct v4l2_fh fh; >- struct v4l2_m2m_dev *m2m_dev; >- struct v4l2_m2m_ctx *m2m_ctx; >- struct v4l2_ctrl_handler ctrl_handler; >- struct v4l2_ctrl *ctrl_min_buf_capture; >- struct mutex lock; >- >- const struct amvdec_format *fmt_out; >- u32 pixfmt_cap; >- u32 src_buffer_size; >- >- u32 width; >- u32 height; >- u32 colorspace; >- u8 ycbcr_enc; >- u8 quantization; >- u8 xfer_func; >- >- struct v4l2_fract pixelaspect; >- >- atomic_t esparser_queued_bufs; >- struct work_struct esparser_queue_work; >- >- unsigned int streamon_cap, streamon_out; >- unsigned int sequence_cap, sequence_out; >- unsigned int should_stop; >- unsigned int keyframe_found; >- unsigned int num_dst_bufs; >- unsigned int changed_format; >- >- u8 canvas_alloc[MAX_CANVAS]; >- u32 canvas_num; >- >- void *vififo_vaddr; >- dma_addr_t vififo_paddr; >- u32 vififo_size; >- >- struct list_head bufs_recycle; >- struct mutex bufs_recycle_lock; /* bufs_recycle list lock */ >- struct task_struct *recycle_thread; >- >- struct list_head timestamps; >- spinlock_t ts_spinlock; /* timestamp list lock */ >- >- u64 last_irq_jiffies; >- u32 last_offset; >- u32 wrap_count; >- u32 fw_idx_to_vb2_idx[32]; >- >- enum amvdec_status status; >- void *priv; >-}; >- >-static inline struct amvdec_session *file_to_amvdec_session(struct file *filp) >-{ >- return container_of(file_to_v4l2_fh(filp), struct amvdec_session, fh); >-} >- >-u32 amvdec_get_output_size(struct amvdec_session *sess); >- >-#endif >+/* SPDX-License-Identifier: GPL-2.0+ */ >+/* >+ * Copyright (C) 2018 BayLibre, SAS >+ * Author: Maxime Jourdan <[email protected]> >+ */ >+ >+#ifndef __MESON_VDEC_CORE_H_ >+#define __MESON_VDEC_CORE_H_ >+ >+#include <linux/irqreturn.h> >+#include <linux/regmap.h> >+#include <linux/list.h> >+#include <media/videobuf2-v4l2.h> >+#include <media/v4l2-ctrls.h> >+#include <media/v4l2-device.h> >+#include <linux/soc/amlogic/meson-canvas.h> >+ >+#include "vdec_platform.h" >+ >+/* 32 buffers in 3-plane YUV420 */ >+#define MAX_CANVAS (32 * 3) >+ >+struct amvdec_buffer { >+ struct list_head list; >+ struct vb2_buffer *vb; >+}; >+ >+/** >+ * struct amvdec_timestamp - stores a src timestamp along with a VIFIFO offset >+ * >+ * @list: used to make lists out of this struct >+ * @tc: timecode from the v4l2 buffer >+ * @ts: timestamp from the VB2 buffer >+ * @offset: offset in the VIFIFO where the associated packet was written >+ * @flags: flags from the v4l2 buffer >+ * @used_count: times this timestamp was checked for a match with a dst buffer >+ */ >+struct amvdec_timestamp { >+ struct list_head list; >+ struct v4l2_timecode tc; >+ u64 ts; >+ u32 offset; >+ u32 flags; >+ u32 used_count; >+}; >+ >+struct amvdec_session; >+ >+/** >+ * struct amvdec_core - device parameters, singleton >+ * >+ * @dos_base: DOS memory base address >+ * @esparser_base: PARSER memory base address >+ * @regmap_ao: regmap for the AO bus >+ * @dev: core device >+ * @dev_dec: decoder device >+ * @platform: platform-specific data >+ * @canvas: canvas provider reference >+ * @dos_parser_clk: DOS_PARSER clock >+ * @dos_clk: DOS clock >+ * @vdec_1_clk: VDEC_1 clock >+ * @vdec_hevc_clk: VDEC_HEVC clock >+ * @vdec_hevcf_clk: VDEC_HEVCF clock >+ * @esparser_reset: RESET for the PARSER >+ * @vdev_dec: video device for the decoder >+ * @v4l2_dev: v4l2 device >+ * @m2m_dev: v4l2 m2m device >+ * @cur_sess: current decoding session >+ * @lock: video device lock >+ * @irq: decoder irq >+ */ >+struct amvdec_core { >+ void __iomem *dos_base; >+ void __iomem *esparser_base; >+ struct regmap *regmap_ao; >+ >+ struct device *dev; >+ struct device *dev_dec; >+ const struct vdec_platform *platform; >+ >+ struct meson_canvas *canvas; >+ >+ struct clk *dos_parser_clk; >+ struct clk *dos_clk; >+ struct clk *vdec_1_clk; >+ struct clk *vdec_hevc_clk; >+ struct clk *vdec_hevcf_clk; >+ >+ struct reset_control *esparser_reset; >+ >+ struct video_device *vdev_dec; >+ struct v4l2_device v4l2_dev; >+ struct v4l2_m2m_dev *m2m_dev; >+ >+ struct amvdec_session *cur_sess; >+ struct mutex lock; >+ int irq; >+}; >+ >+/** >+ * struct amvdec_ops - vdec operations >+ * >+ * @start: mandatory call when the vdec needs to initialize >+ * @stop: mandatory call when the vdec needs to stop >+ * @conf_esparser: mandatory call to let the vdec configure the ESPARSER >+ * @vififo_level: mandatory call to get the current amount of data >+ * in the VIFIFO >+ */ >+struct amvdec_ops { >+ int (*start)(struct amvdec_session *sess); >+ int (*stop)(struct amvdec_session *sess); >+ void (*conf_esparser)(struct amvdec_session *sess); >+ u32 (*vififo_level)(struct amvdec_session *sess); >+}; >+ >+/** >+ * struct amvdec_codec_ops - codec operations >+ * >+ * @start: mandatory call when the codec needs to initialize >+ * @stop: mandatory call when the codec needs to stop >+ * @load_extended_firmware: optional call to load additional firmware bits >+ * @num_pending_bufs: optional call to get the number of dst buffers on hold >+ * @can_recycle: optional call to know if the codec is ready to recycle >+ * a dst buffer >+ * @recycle: optional call to tell the codec to recycle a dst buffer. Must go >+ * in pair with @can_recycle >+ * @drain: optional call if the codec has a custom way of draining >+ * @resume: optional call to resume after a resolution change >+ * @eos_sequence: optional call to get an end sequence to send to esparser >+ * for flush. Mutually exclusive with @drain. >+ * @isr: mandatory call when the ISR triggers >+ * @threaded_isr: mandatory call for the threaded ISR >+ */ >+struct amvdec_codec_ops { >+ int (*start)(struct amvdec_session *sess); >+ int (*stop)(struct amvdec_session *sess); >+ int (*load_extended_firmware)(struct amvdec_session *sess, >+ const u8 *data, u32 len); >+ u32 (*num_pending_bufs)(struct amvdec_session *sess); >+ int (*can_recycle)(struct amvdec_core *core); >+ void (*recycle)(struct amvdec_core *core, u32 buf_idx); >+ void (*drain)(struct amvdec_session *sess); >+ void (*resume)(struct amvdec_session *sess); >+ const u8 * (*eos_sequence)(u32 *len); >+ irqreturn_t (*isr)(struct amvdec_session *sess); >+ irqreturn_t (*threaded_isr)(struct amvdec_session *sess); >+}; >+ >+/** >+ * struct amvdec_format - describes one of the OUTPUT (src) format supported >+ * >+ * @pixfmt: V4L2 pixel format >+ * @min_buffers: minimum amount of CAPTURE (dst) buffers >+ * @max_buffers: maximum amount of CAPTURE (dst) buffers >+ * @max_width: maximum picture width supported >+ * @max_height: maximum picture height supported >+ * @flags: enum flags associated with this pixfmt >+ * @vdec_ops: the VDEC operations that support this format >+ * @codec_ops: the codec operations that support this format >+ * @firmware_path: Path to the firmware that supports this format >+ * @pixfmts_cap: list of CAPTURE pixel formats available with pixfmt >+ */ >+struct amvdec_format { >+ u32 pixfmt; >+ u32 min_buffers; >+ u32 max_buffers; >+ u32 max_width; >+ u32 max_height; >+ u32 flags; >+ >+ struct amvdec_ops *vdec_ops; >+ struct amvdec_codec_ops *codec_ops; >+ >+ char *firmware_path; >+ u32 pixfmts_cap[4]; >+}; >+ >+enum amvdec_status { >+ STATUS_STOPPED, >+ STATUS_INIT, >+ STATUS_RUNNING, >+ STATUS_NEEDS_RESUME, >+}; >+ >+/** >+ * struct amvdec_session - decoding session parameters >+ * >+ * @core: reference to the vdec core struct >+ * @fh: v4l2 file handle >+ * @m2m_ctx: v4l2 m2m context >+ * @ctrl_handler: V4L2 control handler >+ * @ctrl_min_buf_capture: V4L2 control V4L2_CID_MIN_BUFFERS_FOR_CAPTURE >+ * @lock: cap & out queues lock >+ * @fmt_out: vdec pixel format for the OUTPUT queue >+ * @pixfmt_cap: V4L2 pixel format for the CAPTURE queue >+ * @src_buffer_size: size in bytes of the OUTPUT buffers' only plane >+ * @width: current picture width >+ * @height: current picture height >+ * @colorspace: current colorspace >+ * @ycbcr_enc: current ycbcr_enc >+ * @quantization: current quantization >+ * @xfer_func: current transfer function >+ * @pixelaspect: Pixel Aspect Ratio reported by the decoder >+ * @esparser_queued_bufs: number of buffers currently queued into ESPARSER >+ * @esparser_queue_work: work struct for the ESPARSER to process src buffers >+ * @streamon_cap: stream on flag for capture queue >+ * @streamon_out: stream on flag for output queue >+ * @sequence_cap: capture sequence counter >+ * @sequence_out: output sequence counter >+ * @should_stop: flag set if userspace signaled EOS via command >+ * or empty buffer >+ * @keyframe_found: flag set once a keyframe has been parsed >+ * @num_dst_bufs: number of destination buffers >+ * @changed_format: the format changed >+ * @canvas_alloc: array of all the canvas IDs allocated >+ * @canvas_num: number of canvas IDs allocated >+ * @vififo_vaddr: virtual address for the VIFIFO >+ * @vififo_paddr: physical address for the VIFIFO >+ * @vififo_size: size of the VIFIFO dma alloc >+ * @bufs_recycle: list of buffers that need to be recycled >+ * @bufs_recycle_lock: lock for the bufs_recycle list >+ * @recycle_thread: task struct for the recycling thread >+ * @timestamps: chronological list of src timestamps >+ * @ts_spinlock: spinlock for the timestamps list >+ * @last_irq_jiffies: tracks last time the vdec triggered an IRQ >+ * @last_offset: tracks last offset of vififo >+ * @wrap_count: number of times the vififo wrapped around >+ * @fw_idx_to_vb2_idx: firmware buffer index to vb2 buffer index >+ * @status: current decoding status >+ * @priv: codec private data >+ */ >+struct amvdec_session { >+ struct amvdec_core *core; >+ >+ struct v4l2_fh fh; >+ struct v4l2_m2m_ctx *m2m_ctx; >+ struct v4l2_ctrl_handler ctrl_handler; >+ struct v4l2_ctrl *ctrl_min_buf_capture; >+ struct mutex lock; >+ >+ const struct amvdec_format *fmt_out; >+ u32 pixfmt_cap; >+ u32 src_buffer_size; >+ >+ u32 width; >+ u32 height; >+ u32 colorspace; >+ u8 ycbcr_enc; >+ u8 quantization; >+ u8 xfer_func; >+ >+ struct v4l2_fract pixelaspect; >+ >+ atomic_t esparser_queued_bufs; >+ struct work_struct esparser_queue_work; >+ >+ unsigned int streamon_cap, streamon_out; >+ unsigned int sequence_cap, sequence_out; >+ unsigned int should_stop; >+ unsigned int keyframe_found; >+ unsigned int num_dst_bufs; >+ unsigned int changed_format; >+ >+ u8 canvas_alloc[MAX_CANVAS]; >+ u32 canvas_num; >+ >+ void *vififo_vaddr; >+ dma_addr_t vififo_paddr; >+ u32 vififo_size; >+ >+ struct list_head bufs_recycle; >+ struct mutex bufs_recycle_lock; /* bufs_recycle list lock */ >+ struct task_struct *recycle_thread; >+ >+ struct list_head timestamps; >+ spinlock_t ts_spinlock; /* timestamp list lock */ >+ >+ u64 last_irq_jiffies; >+ u32 last_offset; >+ u32 wrap_count; >+ u32 fw_idx_to_vb2_idx[32]; >+ >+ enum amvdec_status status; >+ void *priv; >+}; >+ >+static inline struct amvdec_session *file_to_amvdec_session(struct file *filp) >+{ >+ return container_of(file_to_v4l2_fh(filp), struct amvdec_session, fh); >+} >+ >+u32 amvdec_get_output_size(struct amvdec_session *sess); >+ >+#endif What is this huge diff? >-- >2.54.0.windows.1 > > >_______________________________________________ >linux-amlogic mailing list >[email protected] >http://lists.infradead.org/mailman/listinfo/linux-amlogic Best regards, Ferass _______________________________________________ linux-amlogic mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-amlogic