All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sakari Ailus <sakari.ailus@linux.intel.com>
To: linux-media@vger.kernel.org
Cc: laurent.pinchart@ideasonboard.com,
	Dave Stevenson <dave.stevenson@raspberrypi.com>,
	Jacopo Mondi <jacopo.mondi@ideasonboard.com>,
	Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>,
	Jai Luthra <jai.luthra@ideasonboard.com>,
	Mehdi Djait <mehdi.djait@linux.intel.com>,
	Mattijs Korpershoek <mkorpershoek@kernel.org>
Subject: [PATCH v3 05/29] media: v4l2-subdev: Allow allocating frame descriptors based on the need
Date: Mon, 24 Aug 2026 15:14:27 +0300	[thread overview]
Message-ID: <20260824121451.3348583-6-sakari.ailus@linux.intel.com> (raw)
In-Reply-To: <20260824121451.3348583-1-sakari.ailus@linux.intel.com>

Frame descriptors entries require a small amount of memory per entry (20
bytes), but if the number of entries in a frame descriptor is large, an
unreasonably large amount of memory would need to be allocated in the
stack. Therefore the number of entries has been limited to 8.

Support larger frame descriptors by making the entry field a pointer that
by default points to a pre-allocated array while the get_frame_desc() pad
o may allocate as much memory as required, up to V4L2_FRAME_DESC_ENTRY_MAX
which is changed to 64.

The caller is also responsible for releasing the allocated memory by
calling v4l2_subdev_free_frame_desc().

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/v4l2-core/v4l2-subdev.c | 45 ++++++++++++++++++++-------
 include/media/v4l2-subdev.h           | 42 ++++++++++++++++++-------
 2 files changed, 63 insertions(+), 24 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index a5c53dc8c396..e15d3f63e004 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -63,10 +63,6 @@ static bool v4l2_subdev_enable_streams_api;
 /*
  * Maximum stream ID is 63 for now, as we use u64 bitmask to represent a set
  * of streams.
- *
- * Note that V4L2_FRAME_DESC_ENTRY_MAX is related: V4L2_FRAME_DESC_ENTRY_MAX
- * restricts the total number of streams in a pad, although the stream ID is
- * not restricted.
  */
 #define V4L2_SUBDEV_MAX_STREAM_ID 63
 
@@ -354,6 +350,7 @@ static int call_set_frame_interval(struct v4l2_subdev *sd,
 static int call_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 			       struct v4l2_mbus_frame_desc *fd)
 {
+	unsigned int type;
 	unsigned int i;
 	int ret;
 
@@ -362,16 +359,26 @@ static int call_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 		return -EOPNOTSUPP;
 #endif
 
-	memset(fd, 0, sizeof(*fd));
+	type = fd->type;
+	memset_after(fd, 0, type);
+	fd->entry = fd->entry_mem;
+	fd->len_entries = ARRAY_SIZE(fd->entry_mem);
 
 	ret = sd->ops->pad->get_frame_desc(sd, pad, fd);
 	if (ret)
 		return ret;
 
+	if (type == V4L2_MBUS_FRAME_DESC_TYPE_UNDEFINED) {
+		type = fd->type;
+	} else if (type != fd->type) {
+		dev_dbg(sd->dev, "Expected frame descriptor type %u, got %u\n",
+			type, fd->type);
+		return -EINVAL;
+	}
+
 	dev_dbg(sd->dev, "Frame descriptor on pad %u, type %s\n", pad,
-		fd->type == V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL ? "parallel" :
-		fd->type == V4L2_MBUS_FRAME_DESC_TYPE_CSI2 ? "CSI-2" :
-		"unknown");
+		type == V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL ? "parallel" :
+		type == V4L2_MBUS_FRAME_DESC_TYPE_CSI2 ? "CSI-2" : "unknown");
 
 	for (i = 0; i < fd->num_entries; i++) {
 		struct v4l2_mbus_frame_desc_entry *entry = &fd->entry[i];
@@ -1086,9 +1093,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
 		 * descriptor accordingly, with up to one entry per route. Until
 		 * the frame descriptors entries get allocated dynamically,
 		 * limit the number of active routes to
-		 * V4L2_FRAME_DESC_ENTRY_MAX.
+		 * V4L2_FRAME_DESC_ENTRY_PREALLOC.
 		 */
-		if (num_active_routes > V4L2_FRAME_DESC_ENTRY_MAX)
+		if (num_active_routes > V4L2_FRAME_DESC_ENTRY_PREALLOC)
 			return -E2BIG;
 
 		/*
@@ -2638,7 +2645,7 @@ int __v4l2_subdev_get_frame_desc_passthrough(struct v4l2_subdev *sd,
 				return -EPIPE;
 			}
 
-			if (fd->num_entries >= V4L2_FRAME_DESC_ENTRY_MAX) {
+			if (fd->num_entries >= V4L2_FRAME_DESC_ENTRY_PREALLOC) {
 				dev_dbg(dev, "Frame desc entry limit reached\n");
 				return -E2BIG;
 			}
@@ -2703,6 +2710,14 @@ v4l2_subdev_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 			goto err_free;
 		}
 
+		if (desc->num_entries > desc->len_entries) {
+			dev_dbg(sd->dev,
+				"too many frame descriptors; got %u, expected at most %u\n",
+				desc->num_entries, desc->len_entries);
+			ret = -EINVAL;
+			goto err_free;
+		}
+
 		return desc;
 	}
 
@@ -2717,7 +2732,10 @@ v4l2_subdev_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 	if (ret < 0)
 		goto err_free;
 
-	struct v4l2_mbus_frame_desc_entry *entry = &desc->entry[0];
+	desc->entry = desc->entry_mem;
+	desc->len_entries = ARRAY_SIZE(desc->entry_mem);
+
+	struct v4l2_mbus_frame_desc_entry *entry = desc->entry;
 
 	entry->pixelcode = subdev_fmt.format.code;
 
@@ -2742,6 +2760,9 @@ EXPORT_SYMBOL_GPL(v4l2_subdev_get_frame_desc);
 
 void v4l2_subdev_free_frame_desc(struct v4l2_mbus_frame_desc *desc)
 {
+	if (desc->entry != desc->entry_mem)
+		kfree(desc->entry);
+
 	kfree(desc);
 }
 EXPORT_SYMBOL_GPL(v4l2_subdev_free_frame_desc);
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index c10ca3f5d979..daebf8982c43 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -366,11 +366,13 @@ struct v4l2_mbus_frame_desc_entry {
 	} bus;
 };
 
- /*
-  * If this number is too small, it should be dropped altogether and the
-  * API switched to a dynamic number of frame descriptor entries.
-  */
-#define V4L2_FRAME_DESC_ENTRY_MAX	8
+/* Size of the statically allocated frame descriptor array. */
+#define V4L2_FRAME_DESC_ENTRY_PREALLOC	8
+/*
+ * Maximum number of dynamically allocated frame descriptors. Note that
+ * V4L2_SUBDEV_MAX_STREAM_ID is related to this limit as well.
+ */
+#define V4L2_FRAME_DESC_ENTRY_MAX	64
 
 /**
  * enum v4l2_mbus_frame_desc_type - media bus frame description type
@@ -393,13 +395,17 @@ enum v4l2_mbus_frame_desc_type {
 /**
  * struct v4l2_mbus_frame_desc - media bus data frame description
  * @type: type of the bus (enum v4l2_mbus_frame_desc_type)
- * @entry: frame descriptors array
- * @num_entries: number of entries in @entry array
+ * @entry_mem: memory for the frame descriptors (@entry)
+ * @entry: pointer to the frame descriptors
+ * @num_entries: number of entries in @entry
+ * @len_entries: number of entries allocated for @entry
  */
 struct v4l2_mbus_frame_desc {
 	enum v4l2_mbus_frame_desc_type type;
-	struct v4l2_mbus_frame_desc_entry entry[V4L2_FRAME_DESC_ENTRY_MAX];
+	struct v4l2_mbus_frame_desc_entry entry_mem[V4L2_FRAME_DESC_ENTRY_PREALLOC];
+	struct v4l2_mbus_frame_desc_entry *entry;
 	unsigned short num_entries;
+	unsigned short len_entries;
 };
 
 /**
@@ -781,7 +787,17 @@ struct v4l2_subdev_state {
  * @link_validate: used by the media controller code to check if the links
  *		   that belongs to a pipeline can be used for stream.
  *
- * @get_frame_desc: get the current low level media bus frame parameters.
+ * @get_frame_desc: get the current low level media bus frame parameters. The
+ *		    callback is required to update the num_entries field to the
+ *		    total number of entries in the frame descriptor. The
+ *		    callback shall fill the first entries array up to
+ *		    len_entries, which signifies the number of entries
+ *		    allocated. If the number of entries needed exceeds
+ *		    len_entries, allocate enough memory using kzalloc_objs() or
+ *		    a similar function returning kmalloc() memory. Never call
+ *		    this directly in drivers, use v4l2_subdev_get_frame_desc()
+ *		    instead. The maximum number of num_entries is
+ *		    V4L2_FRAME_DESC_ENTRY_MAX.
  *
  * @set_frame_desc: set the low level media bus frame parameters, @fd array
  *                  may be adjusted by the subdev driver to device capabilities.
@@ -1794,8 +1810,9 @@ int v4l2_subdev_get_frame_desc_passthrough(struct v4l2_subdev *sd,
  *
  * The caller is required to set @desc->type to the expected bus type.
  *
- * The caller is required to release the memory of the frame descriptor entries
- * for each frame descriptor obtained by calling this function using
+ * The entries in the frame descriptor are allocated based on the need. The
+ * caller is required to release the memory of the frame descriptor entries for
+ * each frame descriptor obtained by calling this function using
  * v4l2_subdev_free_frame_desc().
  *
  * Use __free() to release the frame descriptor automatically::
@@ -1813,7 +1830,8 @@ v4l2_subdev_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
  * v4l2_subdev_free_frame_desc() - Release the memory of a frame descriptor
  * @desc: A pointer to a frame descriptor
  *
- * Release the frame descriptor.
+ * Release the frame descriptor entries in a frame descriptor as well as the
+ * frame descriptor itself.
  */
 void v4l2_subdev_free_frame_desc(struct v4l2_mbus_frame_desc *desc);
 
-- 
2.47.3


  parent reply	other threads:[~2026-08-24 12:14 UTC|newest]

Thread overview: 119+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-24 12:14 [PATCH v3 00/29] Rework frame descriptors Sakari Ailus
2026-08-24 12:14 ` [PATCH v3 01/29] media: v4l2-common: Add helper function media_bus_fmt_to_csi2_(bpp|dt)() Sakari Ailus
2026-08-26 13:18   ` Linus Walleij
2026-08-27  7:45     ` Linus Walleij
2026-08-27  8:50     ` Sakari Ailus
2026-08-27  9:34       ` Sakari Ailus
2026-08-27 22:29   ` Linus Walleij
2026-09-23 11:27     ` Sakari Ailus
2026-08-24 12:14 ` [PATCH v3 02/29] media: v4l2-subdev: Align frame descriptor error codes with routing Sakari Ailus
2026-08-27  7:46   ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 03/29] media: v4l2-subdev: Prepare for changes in getting frame descriptors Sakari Ailus
2026-08-31 12:43   ` Linus Walleij
2026-09-02 11:55     ` Sakari Ailus
2026-08-31 12:44   ` Linus Walleij
2026-09-02 12:00     ` Sakari Ailus
2026-08-24 12:14 ` [PATCH v3 04/29] media: v4l2-subdev: Allow releasing frame descriptors on return Sakari Ailus
2026-08-24 20:34   ` Frank Li
2026-08-31 12:54   ` Linus Walleij
2026-09-02 11:23     ` Sakari Ailus
2026-08-24 12:14 ` Sakari Ailus [this message]
2026-08-31 13:18   ` [PATCH v3 05/29] media: v4l2-subdev: Allow allocating frame descriptors based on the need Linus Walleij
2026-09-01 12:30     ` Linus Walleij
2026-09-23 12:11     ` Sakari Ailus
2026-08-24 12:14 ` [PATCH v3 06/29] media: v4l2-subdev: Change the maximum number of routes Sakari Ailus
2026-09-01 12:31   ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 07/29] media: v4l2-subdev: Add frame descriptor passthrough for CSI-2 and DVP Sakari Ailus
2026-08-24 20:43   ` Frank Li
2026-09-01 13:01   ` Linus Walleij
2026-09-02 12:02     ` Sakari Ailus
2026-09-02 13:04       ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 08/29] media: ds90ub913: Use v4l2_subdev_get_frame_desc_passthrough_csi2() Sakari Ailus
2026-08-24 20:44   ` Frank Li
2026-09-01 13:12   ` Linus Walleij
2026-09-02 12:05     ` Sakari Ailus
2026-08-24 12:14 ` [PATCH v3 09/29] media: ds90ub953: " Sakari Ailus
2026-08-24 20:44   ` Frank Li
2026-09-01 13:17   ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 10/29] media: nxp: imx8-isi: " Sakari Ailus
2026-08-24 20:44   ` Frank Li
2026-09-01 13:30   ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 11/29] media: rzg2l-cru: " Sakari Ailus
2026-08-24 20:45   ` Frank Li
2026-09-01 21:18   ` Linus Walleij
2026-09-02 12:22     ` Sakari Ailus
2026-08-24 12:14 ` [PATCH v3 12/29] media: dw-mipi-csi2rx: " Sakari Ailus
2026-08-24 20:46   ` Frank Li
2026-09-01 21:22   ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 13/29] media: cdn-csi2rc: media: " Sakari Ailus
2026-08-24 20:47   ` Frank Li
2026-08-26  6:41   ` Jai Luthra
2026-09-01 21:43   ` Linus Walleij
2026-09-09  8:39     ` Sakari Ailus
2026-08-24 12:14 ` [PATCH v3 14/29] media: v4l2-subdev: Make v4l2_subdev_get_frame_desc_passthrough() static Sakari Ailus
2026-08-24 20:48   ` Frank Li
2026-09-01 22:16   ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 15/29] media: v4l2-subdev: Return dynamically allocated pass-through routes Sakari Ailus
2026-08-24 21:00   ` Frank Li
2026-08-25  7:36     ` Sakari Ailus
2026-09-02  5:44   ` Linus Walleij
2026-09-02  9:34     ` Linus Walleij
2026-09-09  9:12       ` Sakari Ailus
2026-09-09  9:10     ` Sakari Ailus
2026-08-24 12:14 ` [PATCH v3 16/29] media: v4l2-subdev: Always return at least one frame descriptor Sakari Ailus
2026-09-04 10:27   ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 17/29] media: bcm2835-unicam: Use v4l2_subdev_get_frame_desc() Sakari Ailus
2026-08-24 21:07   ` Frank Li
2026-08-25  7:40     ` Sakari Ailus
2026-09-04 10:32   ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 18/29] media: bcm2835-unicam: Remove frame descriptor workaround Sakari Ailus
2026-08-24 21:10   ` Frank Li
2026-08-26 12:09     ` Sakari Ailus
2026-09-04 10:43   ` Linus Walleij
2026-09-09  9:26     ` Sakari Ailus
2026-08-24 12:14 ` [PATCH v3 19/29] media: nxp: imx8-isi: Use v4l2_subdev_get_frame_desc() Sakari Ailus
2026-09-04 12:44   ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 20/29] media: raspberrypi: cfe: " Sakari Ailus
2026-08-24 21:11   ` Frank Li
2026-09-04 12:51   ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 21/29] media: rzg2l-cru: " Sakari Ailus
2026-08-24 21:13   ` Frank Li
2026-09-04 12:57   ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 22/29] media: rkisp1: " Sakari Ailus
2026-08-24 21:13   ` Frank Li
2026-09-04 13:12   ` Linus Walleij
2026-09-09 10:06     ` Sakari Ailus
2026-08-24 12:14 ` [PATCH v3 23/29] media: exynos4-is: " Sakari Ailus
2026-08-24 21:22   ` Frank Li
2026-09-04 13:35   ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 24/29] media: ti: cal: " Sakari Ailus
2026-08-24 21:26   ` Frank Li
2026-08-25  8:05     ` Sakari Ailus
2026-09-04 13:38   ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 25/29] media: ipu6: " Sakari Ailus
2026-08-24 21:26   ` Frank Li
2026-09-04 20:21   ` Linus Walleij
2026-09-16  8:09     ` Sakari Ailus
2026-08-24 12:14 ` [PATCH v3 26/29] staging: media: ipu7: " Sakari Ailus
2026-08-24 21:27   ` Frank Li
2026-09-04 20:25   ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 27/29] media: cdns-csi2rc: " Sakari Ailus
2026-08-24 21:29   ` Frank Li
2026-08-26  6:39   ` Jai Luthra
2026-09-04 20:27   ` Linus Walleij
2026-09-16  8:12     ` Sakari Ailus
2026-08-24 12:14 ` [PATCH v3 28/29] media: v4l2-subdev: Use v4l2_subdev_get_frame_desc() for passthrough Sakari Ailus
2026-08-24 21:37   ` Frank Li
2026-08-25  7:34     ` Sakari Ailus
2026-09-04 20:38   ` Linus Walleij
2026-09-16  8:22     ` Sakari Ailus
2026-09-04 20:45   ` Linus Walleij
2026-08-24 12:14 ` [PATCH v3 29/29] media: j721e-csi2rx: Use v4l2_subdev_get_frame_desc() Sakari Ailus
2026-08-24 21:38   ` Frank Li
2026-08-26  6:36   ` Jai Luthra
2026-09-04 20:54   ` Linus Walleij
2026-09-16  8:32     ` Sakari Ailus
2026-09-16 12:48       ` Jai Luthra
2026-08-26  9:58 ` [PATCH v3 00/29] Rework frame descriptors Mattijs Korpershoek
2026-09-17  8:04   ` Tomi Valkeinen
2026-09-21  8:22     ` Mattijs Korpershoek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260824121451.3348583-6-sakari.ailus@linux.intel.com \
    --to=sakari.ailus@linux.intel.com \
    --cc=dave.stevenson@raspberrypi.com \
    --cc=jacopo.mondi@ideasonboard.com \
    --cc=jai.luthra@ideasonboard.com \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-media@vger.kernel.org \
    --cc=mehdi.djait@linux.intel.com \
    --cc=mkorpershoek@kernel.org \
    --cc=tomi.valkeinen@ideasonboard.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.